@vellumai/assistant 0.4.56 → 0.5.0

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 (457) hide show
  1. package/ARCHITECTURE.md +10 -10
  2. package/Dockerfile +3 -0
  3. package/README.md +11 -11
  4. package/docs/architecture/integrations.md +2 -2
  5. package/docs/architecture/memory.md +3 -4
  6. package/docs/credential-execution-service.md +13 -20
  7. package/node_modules/@vellumai/ces-contracts/src/error.ts +5 -4
  8. package/package.json +1 -1
  9. package/src/__tests__/actor-token-service.test.ts +7 -7
  10. package/src/__tests__/anthropic-provider.test.ts +172 -0
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +15 -1
  12. package/src/__tests__/approval-cascade.test.ts +2 -2
  13. package/src/__tests__/approval-routes-http.test.ts +3 -4
  14. package/src/__tests__/asset-materialize-tool.test.ts +5 -5
  15. package/src/__tests__/asset-search-tool.test.ts +1 -1
  16. package/src/__tests__/assistant-attachments.test.ts +5 -5
  17. package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
  18. package/src/__tests__/assistant-feature-flags-integration.test.ts +50 -38
  19. package/src/__tests__/attachments-store.test.ts +2 -2
  20. package/src/__tests__/avatar-e2e.test.ts +5 -3
  21. package/src/__tests__/browser-skill-endstate.test.ts +0 -1
  22. package/src/__tests__/call-routes-http.test.ts +2 -2
  23. package/src/__tests__/callback-handoff-copy.test.ts +1 -1
  24. package/src/__tests__/cancel-resolves-conversation-key.test.ts +158 -0
  25. package/src/__tests__/channel-readiness-routes.test.ts +0 -1
  26. package/src/__tests__/channel-readiness-service.test.ts +0 -1
  27. package/src/__tests__/checker.test.ts +31 -32
  28. package/src/__tests__/chrome-cdp.test.ts +47 -18
  29. package/src/__tests__/claude-code-skill-regression.test.ts +2 -2
  30. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  31. package/src/__tests__/config-schema.test.ts +9 -18
  32. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -4
  34. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -2
  35. package/src/__tests__/conversation-agent-loop.test.ts +11 -4
  36. package/src/__tests__/conversation-attachments.test.ts +1 -1
  37. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -2
  38. package/src/__tests__/conversation-error.test.ts +33 -0
  39. package/src/__tests__/conversation-init.benchmark.test.ts +0 -1
  40. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  41. package/src/__tests__/conversation-pairing.test.ts +1 -1
  42. package/src/__tests__/conversation-pre-run-repair.test.ts +4 -4
  43. package/src/__tests__/conversation-provider-retry-repair.test.ts +4 -4
  44. package/src/__tests__/conversation-queue.test.ts +23 -14
  45. package/src/__tests__/conversation-routes-slash-commands.test.ts +3 -3
  46. package/src/__tests__/conversation-runtime-assembly.test.ts +204 -185
  47. package/src/__tests__/conversation-seed-composer.test.ts +1 -1
  48. package/src/__tests__/conversation-slash-queue.test.ts +4 -4
  49. package/src/__tests__/conversation-slash-unknown.test.ts +4 -4
  50. package/src/__tests__/conversation-starter-routes.test.ts +291 -0
  51. package/src/__tests__/conversation-wipe.test.ts +438 -0
  52. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -3
  53. package/src/__tests__/conversation-workspace-injection.test.ts +4 -5
  54. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -5
  55. package/src/__tests__/credential-security-e2e.test.ts +20 -0
  56. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  57. package/src/__tests__/credential-vault-unit.test.ts +227 -0
  58. package/src/__tests__/credentials-cli.test.ts +3 -0
  59. package/src/__tests__/date-context.test.ts +59 -377
  60. package/src/__tests__/drop-capability-card-state-migration.test.ts +169 -0
  61. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +11 -45
  62. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
  63. package/src/__tests__/encrypted-store.test.ts +249 -15
  64. package/src/__tests__/ephemeral-permissions.test.ts +4 -5
  65. package/src/__tests__/event-bus.test.ts +3 -3
  66. package/src/__tests__/file-read-tool.test.ts +40 -0
  67. package/src/__tests__/gateway-only-enforcement.test.ts +2 -2
  68. package/src/__tests__/gateway-only-guard.test.ts +1 -0
  69. package/src/__tests__/gemini-image-service.test.ts +4 -4
  70. package/src/__tests__/gemini-provider.test.ts +6 -9
  71. package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
  72. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  73. package/src/__tests__/host-file-read-tool.test.ts +87 -0
  74. package/src/__tests__/host-shell-tool.test.ts +6 -6
  75. package/src/__tests__/http-user-message-parity.test.ts +2 -2
  76. package/src/__tests__/identity-intro-cache.test.ts +209 -0
  77. package/src/__tests__/intent-routing.test.ts +51 -99
  78. package/src/__tests__/invite-routes-http.test.ts +5 -0
  79. package/src/__tests__/list-messages-attachments.test.ts +1 -1
  80. package/src/__tests__/managed-proxy-context.test.ts +2 -5
  81. package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
  82. package/src/__tests__/media-generate-image.test.ts +32 -15
  83. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
  84. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
  85. package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
  86. package/src/__tests__/memory-recall-quality.test.ts +4 -3
  87. package/src/__tests__/memory-regressions.test.ts +86 -90
  88. package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
  89. package/src/__tests__/migration-export-http.test.ts +26 -27
  90. package/src/__tests__/migration-import-commit-http.test.ts +165 -37
  91. package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
  92. package/src/__tests__/migration-validate-http.test.ts +16 -16
  93. package/src/__tests__/model-intents.test.ts +2 -2
  94. package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
  95. package/src/__tests__/non-member-access-request.test.ts +3 -3
  96. package/src/__tests__/notification-broadcaster.test.ts +1 -1
  97. package/src/__tests__/notification-decision-fallback.test.ts +2 -2
  98. package/src/__tests__/notification-decision-identity.test.ts +8 -9
  99. package/src/__tests__/notification-decision-strategy.test.ts +1 -1
  100. package/src/__tests__/notification-deep-link.test.ts +1 -1
  101. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  102. package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
  103. package/src/__tests__/oauth-store.test.ts +1 -3
  104. package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
  105. package/src/__tests__/onboarding-template-contract.test.ts +23 -59
  106. package/src/__tests__/provider-error-scenarios.test.ts +154 -0
  107. package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
  108. package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
  109. package/src/__tests__/provider-registry-ollama.test.ts +5 -2
  110. package/src/__tests__/qdrant-manager.test.ts +7 -7
  111. package/src/__tests__/ratelimit.test.ts +0 -74
  112. package/src/__tests__/recording-handler.test.ts +0 -1
  113. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  114. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  115. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  116. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  117. package/src/__tests__/scheduler-recurrence.test.ts +46 -2
  118. package/src/__tests__/schema-transforms.test.ts +114 -54
  119. package/src/__tests__/secret-onetime-send.test.ts +20 -0
  120. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
  121. package/src/__tests__/secret-scanner-executor.test.ts +1 -2
  122. package/src/__tests__/send-endpoint-busy.test.ts +63 -4
  123. package/src/__tests__/send-notification-tool.test.ts +2 -2
  124. package/src/__tests__/shell-credential-ref.test.ts +0 -1
  125. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
  126. package/src/__tests__/skill-memory.test.ts +549 -0
  127. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
  128. package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
  129. package/src/__tests__/slack-channel-config.test.ts +109 -94
  130. package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
  131. package/src/__tests__/swarm-recursion.test.ts +2 -2
  132. package/src/__tests__/swarm-tool.test.ts +2 -2
  133. package/src/__tests__/system-prompt.test.ts +19 -66
  134. package/src/__tests__/telegram-config.test.ts +121 -0
  135. package/src/__tests__/terminal-tools.test.ts +1 -1
  136. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  138. package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
  139. package/src/__tests__/tool-executor.test.ts +1 -1
  140. package/src/__tests__/trace-emitter.test.ts +8 -1
  141. package/src/__tests__/trust-store.test.ts +7 -8
  142. package/src/__tests__/twilio-routes.test.ts +1 -18
  143. package/src/__tests__/user-reference.test.ts +82 -2
  144. package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
  145. package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
  146. package/src/approvals/guardian-request-resolvers.ts +3 -3
  147. package/src/avatar/ascii-renderer.ts +2 -2
  148. package/src/avatar/png-renderer.ts +2 -2
  149. package/src/avatar/resvg-lazy.ts +21 -0
  150. package/src/calls/guardian-dispatch.ts +1 -1
  151. package/src/calls/relay-access-wait.ts +2 -2
  152. package/src/calls/twilio-rest.ts +0 -248
  153. package/src/cli/AGENTS.md +5 -8
  154. package/src/cli/__tests__/notifications.test.ts +5 -5
  155. package/src/cli/commands/avatar.ts +64 -2
  156. package/src/cli/commands/conversations.ts +131 -1
  157. package/src/cli/commands/credentials.ts +2 -0
  158. package/src/cli/commands/notifications.ts +3 -3
  159. package/src/cli.ts +10 -0
  160. package/src/config/bundled-skills/acp/SKILL.md +5 -5
  161. package/src/config/bundled-skills/acp/TOOLS.json +6 -6
  162. package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
  163. package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
  164. package/src/config/bundled-skills/browser/SKILL.md +15 -15
  165. package/src/config/bundled-skills/browser/TOOLS.json +14 -14
  166. package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
  167. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
  168. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
  169. package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
  170. package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
  171. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
  172. package/src/config/bundled-skills/contacts/SKILL.md +3 -3
  173. package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
  174. package/src/config/bundled-skills/document/SKILL.md +4 -4
  175. package/src/config/bundled-skills/document/TOOLS.json +2 -2
  176. package/src/config/bundled-skills/followups/TOOLS.json +3 -3
  177. package/src/config/bundled-skills/gmail/SKILL.md +32 -32
  178. package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
  179. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
  180. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
  181. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
  182. package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
  183. package/src/config/bundled-skills/google-calendar/types.ts +1 -1
  184. package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
  185. package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
  186. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
  187. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
  188. package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
  189. package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
  190. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
  191. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
  192. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
  193. package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
  194. package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
  195. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
  196. package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
  197. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
  198. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
  199. package/src/config/bundled-skills/messaging/SKILL.md +29 -25
  200. package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
  201. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
  202. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
  203. package/src/config/bundled-skills/notifications/SKILL.md +3 -3
  204. package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
  205. package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
  206. package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
  207. package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
  208. package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
  209. package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
  210. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
  211. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
  212. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
  213. package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
  214. package/src/config/bundled-skills/schedule/SKILL.md +26 -26
  215. package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
  216. package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
  217. package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
  218. package/src/config/bundled-skills/sequences/SKILL.md +2 -2
  219. package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
  220. package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
  221. package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
  222. package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
  223. package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
  224. package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
  225. package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
  226. package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
  227. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  228. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
  229. package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
  230. package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
  231. package/src/config/bundled-skills/slack/SKILL.md +2 -2
  232. package/src/config/bundled-skills/slack/TOOLS.json +8 -8
  233. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
  234. package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
  235. package/src/config/bundled-skills/tasks/SKILL.md +1 -1
  236. package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
  237. package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
  238. package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
  239. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
  240. package/src/config/bundled-skills/watcher/SKILL.md +4 -4
  241. package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
  242. package/src/config/feature-flag-registry.json +33 -17
  243. package/src/config/schemas/sandbox.ts +1 -1
  244. package/src/config/schemas/services.ts +13 -3
  245. package/src/config/schemas/timeouts.ts +0 -10
  246. package/src/contacts/contact-store.ts +63 -0
  247. package/src/contacts/contacts-write.ts +1 -1
  248. package/src/daemon/assistant-attachments.ts +2 -2
  249. package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
  250. package/src/daemon/conversation-agent-loop.ts +7 -30
  251. package/src/daemon/conversation-error.ts +24 -0
  252. package/src/daemon/conversation-memory.ts +8 -7
  253. package/src/daemon/conversation-runtime-assembly.ts +141 -275
  254. package/src/daemon/conversation-slash.ts +7 -26
  255. package/src/daemon/conversation-surfaces.ts +14 -0
  256. package/src/daemon/conversation-tool-setup.ts +9 -8
  257. package/src/daemon/conversation.ts +2 -0
  258. package/src/daemon/daemon-control.ts +1 -1
  259. package/src/daemon/date-context.ts +10 -83
  260. package/src/daemon/handlers/config-channels.ts +12 -2
  261. package/src/daemon/handlers/config-slack-channel.ts +7 -1
  262. package/src/daemon/handlers/config-telegram.ts +6 -1
  263. package/src/daemon/handlers/conversations.ts +2 -2
  264. package/src/daemon/handlers/skills.ts +4 -0
  265. package/src/daemon/lifecycle.ts +28 -4
  266. package/src/daemon/providers-setup.ts +1 -1
  267. package/src/daemon/server.ts +1 -5
  268. package/src/daemon/shutdown-handlers.ts +9 -3
  269. package/src/daemon/tool-side-effects.ts +40 -0
  270. package/src/daemon/trace-emitter.ts +26 -2
  271. package/src/events/domain-events.ts +1 -1
  272. package/src/events/tool-permission-telemetry-listener.ts +46 -0
  273. package/src/inbound/platform-callback-registration.ts +0 -18
  274. package/src/media/app-icon-generator.ts +15 -8
  275. package/src/media/avatar-router.ts +15 -8
  276. package/src/media/gemini-image-service.ts +125 -21
  277. package/src/memory/attachments-store.ts +3 -3
  278. package/src/memory/channel-verification-sessions.ts +6 -6
  279. package/src/memory/conversation-crud.ts +196 -1
  280. package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
  281. package/src/memory/conversation-title-service.ts +2 -3
  282. package/src/memory/db-init.ts +25 -1
  283. package/src/memory/invite-store.ts +4 -4
  284. package/src/memory/items-extractor.ts +4 -4
  285. package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
  286. package/src/memory/jobs-store.ts +3 -2
  287. package/src/memory/jobs-worker.ts +7 -5
  288. package/src/memory/lifecycle-events-store.ts +63 -0
  289. package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
  290. package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
  291. package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
  292. package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
  293. package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
  294. package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
  295. package/src/memory/migrations/index.ts +6 -0
  296. package/src/memory/migrations/registry.ts +13 -0
  297. package/src/memory/retriever.test.ts +223 -96
  298. package/src/memory/retriever.ts +115 -138
  299. package/src/memory/schema/calls.ts +1 -1
  300. package/src/memory/schema/contacts.ts +1 -1
  301. package/src/memory/schema/infrastructure.ts +29 -0
  302. package/src/memory/schema/memory-core.ts +7 -17
  303. package/src/memory/schema/notifications.ts +1 -1
  304. package/src/memory/search/formatting.ts +23 -6
  305. package/src/memory/search/lexical.ts +2 -0
  306. package/src/memory/search/semantic.ts +2 -0
  307. package/src/memory/search/staleness.ts +5 -1
  308. package/src/memory/search/types.ts +4 -0
  309. package/src/memory/task-memory-cleanup.ts +96 -6
  310. package/src/memory/trace-event-store.ts +148 -0
  311. package/src/notifications/README.md +1 -1
  312. package/src/notifications/decision-engine.ts +45 -4
  313. package/src/notifications/emit-signal.ts +5 -4
  314. package/src/notifications/events-store.ts +4 -4
  315. package/src/notifications/signal.ts +1 -1
  316. package/src/oauth/manual-token-connection.ts +49 -25
  317. package/src/permissions/checker.ts +6 -5
  318. package/src/permissions/defaults.ts +4 -4
  319. package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
  320. package/src/prompts/cache-boundary.ts +8 -0
  321. package/src/prompts/system-prompt.ts +105 -634
  322. package/src/prompts/templates/BOOTSTRAP.md +172 -33
  323. package/src/prompts/templates/IDENTITY.md +8 -24
  324. package/src/prompts/templates/SOUL.md +20 -41
  325. package/src/prompts/templates/USER.md +3 -19
  326. package/src/prompts/user-reference.ts +14 -16
  327. package/src/providers/anthropic/client.ts +51 -19
  328. package/src/providers/gemini/client.ts +6 -9
  329. package/src/providers/managed-proxy/constants.ts +1 -7
  330. package/src/providers/managed-proxy/context.ts +0 -1
  331. package/src/providers/model-intents.ts +5 -5
  332. package/src/providers/openai/client.ts +10 -1
  333. package/src/providers/openrouter/client.ts +1 -0
  334. package/src/providers/ratelimit.ts +0 -35
  335. package/src/providers/registry.ts +3 -5
  336. package/src/providers/retry.ts +18 -1
  337. package/src/runtime/access-request-helper.ts +16 -2
  338. package/src/runtime/auth/route-policy.ts +7 -0
  339. package/src/runtime/channel-verification-service.ts +1 -1
  340. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  341. package/src/runtime/guardian-vellum-migration.ts +61 -1
  342. package/src/runtime/http-server.ts +8 -4
  343. package/src/runtime/migrations/vbundle-builder.ts +212 -32
  344. package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
  345. package/src/runtime/migrations/vbundle-importer.ts +66 -1
  346. package/src/runtime/migrations/vbundle-validator.ts +17 -3
  347. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
  348. package/src/runtime/routes/attachment-routes.ts +2 -2
  349. package/src/runtime/routes/btw-routes.ts +93 -0
  350. package/src/runtime/routes/channel-verification-routes.ts +19 -2
  351. package/src/runtime/routes/conversation-management-routes.ts +55 -1
  352. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  353. package/src/runtime/routes/conversation-routes.ts +49 -5
  354. package/src/runtime/routes/conversation-starter-routes.ts +207 -0
  355. package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
  356. package/src/runtime/routes/identity-intro-cache.ts +105 -0
  357. package/src/runtime/routes/identity-routes.ts +51 -0
  358. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
  359. package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
  360. package/src/runtime/routes/migration-routes.ts +25 -13
  361. package/src/runtime/routes/secret-routes.ts +18 -0
  362. package/src/runtime/routes/settings-routes.ts +9 -9
  363. package/src/runtime/routes/telemetry-routes.ts +53 -0
  364. package/src/runtime/routes/trace-event-routes.ts +62 -0
  365. package/src/runtime/tool-grant-request-helper.ts +1 -1
  366. package/src/runtime/verification-outbound-actions.ts +47 -31
  367. package/src/security/encrypted-store.ts +262 -78
  368. package/src/skills/catalog-install.ts +10 -0
  369. package/src/skills/managed-store.ts +2 -0
  370. package/src/skills/skill-memory.ts +222 -0
  371. package/src/subagent/manager.ts +1 -4
  372. package/src/telemetry/types.ts +10 -1
  373. package/src/telemetry/usage-telemetry-reporter.test.ts +7 -2
  374. package/src/telemetry/usage-telemetry-reporter.ts +53 -4
  375. package/src/tools/AGENTS.md +11 -11
  376. package/src/tools/acp/spawn.ts +1 -1
  377. package/src/tools/apps/executors.ts +8 -8
  378. package/src/tools/apps/registry.ts +1 -1
  379. package/src/tools/assets/materialize.ts +6 -6
  380. package/src/tools/assets/search.ts +10 -10
  381. package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
  382. package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
  383. package/src/tools/browser/auth-detector.ts +6 -6
  384. package/src/tools/browser/browser-execution.ts +13 -13
  385. package/src/tools/browser/browser-manager.ts +3 -3
  386. package/src/tools/browser/chrome-cdp.ts +5 -5
  387. package/src/tools/browser/jit-auth.ts +2 -2
  388. package/src/tools/browser/network-recorder.test.ts +2 -2
  389. package/src/tools/browser/network-recorder.ts +3 -3
  390. package/src/tools/browser/runtime-check.ts +3 -3
  391. package/src/tools/claude-code/claude-code.ts +2 -2
  392. package/src/tools/computer-use/definitions.ts +18 -18
  393. package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
  394. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
  395. package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
  396. package/src/tools/credentials/broker-types.ts +5 -5
  397. package/src/tools/credentials/broker.ts +15 -15
  398. package/src/tools/credentials/metadata-store.ts +2 -2
  399. package/src/tools/credentials/resolve.ts +1 -1
  400. package/src/tools/credentials/selection.ts +1 -1
  401. package/src/tools/credentials/tool-policy.ts +1 -1
  402. package/src/tools/credentials/vault.ts +115 -25
  403. package/src/tools/execution-target.ts +2 -2
  404. package/src/tools/executor.ts +7 -7
  405. package/src/tools/filesystem/edit.ts +2 -2
  406. package/src/tools/filesystem/read.ts +15 -4
  407. package/src/tools/filesystem/write.ts +1 -1
  408. package/src/tools/host-filesystem/edit.ts +2 -1
  409. package/src/tools/host-filesystem/read.ts +18 -1
  410. package/src/tools/host-filesystem/write.ts +1 -1
  411. package/src/tools/host-terminal/host-shell.ts +9 -8
  412. package/src/tools/mcp/mcp-tool-factory.ts +7 -6
  413. package/src/tools/memory/definitions.ts +6 -5
  414. package/src/tools/memory/handlers.test.ts +1 -1
  415. package/src/tools/network/__tests__/web-search.test.ts +3 -3
  416. package/src/tools/network/domain-normalize.ts +2 -2
  417. package/src/tools/network/script-proxy/session-manager.ts +10 -10
  418. package/src/tools/network/web-fetch.ts +1 -1
  419. package/src/tools/network/web-search.ts +3 -3
  420. package/src/tools/permission-checker.ts +8 -8
  421. package/src/tools/registry.ts +7 -7
  422. package/src/tools/schedule/list.ts +2 -2
  423. package/src/tools/schema-transforms.ts +31 -21
  424. package/src/tools/secret-detection-handler.ts +1 -1
  425. package/src/tools/sensitive-output-placeholders.ts +1 -1
  426. package/src/tools/shared/filesystem/edit-engine.ts +1 -1
  427. package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
  428. package/src/tools/shared/filesystem/image-read.ts +25 -5
  429. package/src/tools/shared/filesystem/path-policy.ts +2 -2
  430. package/src/tools/shared/shell-output.ts +1 -1
  431. package/src/tools/side-effects.ts +1 -1
  432. package/src/tools/skills/execute.ts +1 -1
  433. package/src/tools/skills/load.ts +3 -3
  434. package/src/tools/skills/sandbox-runner.ts +3 -3
  435. package/src/tools/subagent/read.ts +1 -1
  436. package/src/tools/subagent/spawn.ts +2 -2
  437. package/src/tools/swarm/delegate.ts +3 -3
  438. package/src/tools/system/request-permission.ts +5 -4
  439. package/src/tools/terminal/backends/native.ts +4 -4
  440. package/src/tools/terminal/parser.ts +6 -6
  441. package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
  442. package/src/tools/terminal/shell.ts +16 -16
  443. package/src/tools/tool-approval-handler.ts +21 -12
  444. package/src/tools/tool-manifest.ts +4 -4
  445. package/src/tools/types.ts +3 -3
  446. package/src/tools/ui-surface/definitions.ts +9 -37
  447. package/src/tools/watcher/list.ts +1 -1
  448. package/src/util/logger.ts +7 -2
  449. package/src/util/pricing.ts +4 -0
  450. package/src/util/retry.ts +29 -1
  451. package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
  452. package/src/workspace/migrations/registry.ts +2 -0
  453. package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
  454. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
  455. package/src/cli/reference.ts +0 -38
  456. package/src/memory/job-handlers/capability-cards.ts +0 -420
  457. package/src/runtime/routes/thread-starter-routes.ts +0 -294
@@ -0,0 +1,222 @@
1
+ import { and, eq } from "drizzle-orm";
2
+ import { v4 as uuid } from "uuid";
3
+
4
+ import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
5
+ import { getConfig } from "../config/loader.js";
6
+ import { getDb } from "../memory/db.js";
7
+ import { computeMemoryFingerprint } from "../memory/fingerprint.js";
8
+ import { enqueueMemoryJob } from "../memory/jobs-store.js";
9
+ import { memoryItems } from "../memory/schema.js";
10
+ import { getLogger } from "../util/logger.js";
11
+ import { type CatalogSkill, resolveCatalog } from "./catalog-install.js";
12
+
13
+ const log = getLogger("skill-memory");
14
+
15
+ /**
16
+ * Build a semantically rich capability statement from a catalog skill entry.
17
+ * Truncated to 500 chars max (matching the limit used by memory item extraction).
18
+ */
19
+ export function buildCapabilityStatement(entry: CatalogSkill): string {
20
+ const displayName = entry.metadata?.vellum?.["display-name"] ?? entry.name;
21
+ const activationHints = entry.metadata?.vellum?.["activation-hints"];
22
+
23
+ let statement = `The "${displayName}" skill (${entry.id}) is available. ${entry.description}.`;
24
+ if (activationHints && activationHints.length > 0) {
25
+ statement += ` Use when: ${activationHints.join("; ")}.`;
26
+ }
27
+
28
+ // Truncate to 500 chars max
29
+ if (statement.length > 500) {
30
+ statement = statement.slice(0, 500);
31
+ }
32
+
33
+ return statement;
34
+ }
35
+
36
+ /**
37
+ * Upsert a capability memory item for a catalog skill.
38
+ * Best-effort: errors are logged but never thrown.
39
+ */
40
+ export function upsertSkillCapabilityMemory(
41
+ skillId: string,
42
+ entry: CatalogSkill,
43
+ ): void {
44
+ try {
45
+ const db = getDb();
46
+ const subject = `skill:${skillId}`;
47
+ const statement = buildCapabilityStatement(entry);
48
+ const kind = "capability";
49
+ const scopeId = "default";
50
+ const confidence = 1.0;
51
+ const importance = 0.7;
52
+ const fingerprint = computeMemoryFingerprint(
53
+ scopeId,
54
+ kind,
55
+ subject,
56
+ statement,
57
+ );
58
+ const now = Date.now();
59
+
60
+ const existing = db
61
+ .select()
62
+ .from(memoryItems)
63
+ .where(
64
+ and(
65
+ eq(memoryItems.kind, kind),
66
+ eq(memoryItems.subject, subject),
67
+ eq(memoryItems.scopeId, scopeId),
68
+ ),
69
+ )
70
+ .get();
71
+
72
+ if (existing) {
73
+ if (
74
+ existing.status === "active" &&
75
+ existing.fingerprint === fingerprint
76
+ ) {
77
+ // Same content — just touch lastSeenAt
78
+ db.update(memoryItems)
79
+ .set({ lastSeenAt: now })
80
+ .where(eq(memoryItems.id, existing.id))
81
+ .run();
82
+ return;
83
+ }
84
+
85
+ if (existing.status === "active") {
86
+ // Content changed — update statement and fingerprint
87
+ db.update(memoryItems)
88
+ .set({
89
+ statement,
90
+ fingerprint,
91
+ lastSeenAt: now,
92
+ })
93
+ .where(eq(memoryItems.id, existing.id))
94
+ .run();
95
+ enqueueMemoryJob("embed_item", { itemId: existing.id });
96
+ return;
97
+ }
98
+
99
+ // status === "deleted" or other — reactivate
100
+ db.update(memoryItems)
101
+ .set({
102
+ status: "active",
103
+ statement,
104
+ fingerprint,
105
+ lastSeenAt: now,
106
+ firstSeenAt: now,
107
+ })
108
+ .where(eq(memoryItems.id, existing.id))
109
+ .run();
110
+ enqueueMemoryJob("embed_item", { itemId: existing.id });
111
+ return;
112
+ }
113
+
114
+ // No existing — insert new row
115
+ const id = uuid();
116
+ db.insert(memoryItems)
117
+ .values({
118
+ id,
119
+ kind,
120
+ subject,
121
+ statement,
122
+ status: "active",
123
+ confidence,
124
+ importance,
125
+ fingerprint,
126
+ scopeId,
127
+ firstSeenAt: now,
128
+ lastSeenAt: now,
129
+ })
130
+ .run();
131
+ enqueueMemoryJob("embed_item", { itemId: id });
132
+ } catch (err) {
133
+ log.warn({ err, skillId }, "Failed to upsert skill capability memory");
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Soft-delete the capability memory item for a skill.
139
+ * Best-effort: errors are logged but never thrown.
140
+ */
141
+ export function deleteSkillCapabilityMemory(skillId: string): void {
142
+ try {
143
+ const db = getDb();
144
+ const subject = `skill:${skillId}`;
145
+ const now = Date.now();
146
+
147
+ const existing = db
148
+ .select()
149
+ .from(memoryItems)
150
+ .where(
151
+ and(
152
+ eq(memoryItems.kind, "capability"),
153
+ eq(memoryItems.subject, subject),
154
+ eq(memoryItems.scopeId, "default"),
155
+ ),
156
+ )
157
+ .get();
158
+
159
+ if (existing && existing.status !== "deleted") {
160
+ db.update(memoryItems)
161
+ .set({ status: "deleted", lastSeenAt: now })
162
+ .where(eq(memoryItems.id, existing.id))
163
+ .run();
164
+ }
165
+ } catch (err) {
166
+ log.warn({ err, skillId }, "Failed to delete skill capability memory");
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Seed capability memory items for all catalog skills.
172
+ * Prunes stale entries whose skills are no longer in the catalog.
173
+ * Best-effort: errors are logged but never thrown.
174
+ */
175
+ export async function seedCatalogSkillMemories(): Promise<void> {
176
+ try {
177
+ const catalog = await resolveCatalog();
178
+ const config = getConfig();
179
+ const catalogIds = new Set<string>();
180
+
181
+ for (const entry of catalog) {
182
+ // Skip skills whose feature flag is disabled
183
+ const flagId = entry.metadata?.vellum?.["feature-flag"];
184
+ if (flagId) {
185
+ const flagKey = `feature_flags.${flagId}.enabled`;
186
+ if (!isAssistantFeatureFlagEnabled(flagKey, config)) {
187
+ continue;
188
+ }
189
+ }
190
+
191
+ catalogIds.add(entry.id);
192
+ upsertSkillCapabilityMemory(entry.id, entry);
193
+ }
194
+
195
+ // Prune stale capability memories for skills no longer in catalog
196
+ const db = getDb();
197
+ const allCapabilities = db
198
+ .select()
199
+ .from(memoryItems)
200
+ .where(
201
+ and(
202
+ eq(memoryItems.kind, "capability"),
203
+ eq(memoryItems.scopeId, "default"),
204
+ eq(memoryItems.status, "active"),
205
+ ),
206
+ )
207
+ .all();
208
+
209
+ const now = Date.now();
210
+ for (const item of allCapabilities) {
211
+ const itemSkillId = item.subject.replace("skill:", "");
212
+ if (!catalogIds.has(itemSkillId)) {
213
+ db.update(memoryItems)
214
+ .set({ status: "deleted", lastSeenAt: now })
215
+ .where(eq(memoryItems.id, item.id))
216
+ .run();
217
+ }
218
+ }
219
+ } catch (err) {
220
+ log.warn({ err }, "Failed to seed catalog skill memories");
221
+ }
222
+ }
@@ -134,10 +134,7 @@ export class SubagentManager {
134
134
  appConfig.providerOrder,
135
135
  );
136
136
  const { rateLimit } = appConfig;
137
- if (
138
- rateLimit.maxRequestsPerMinute > 0 ||
139
- rateLimit.maxTokensPerSession > 0
140
- ) {
137
+ if (rateLimit.maxRequestsPerMinute > 0) {
141
138
  provider = new RateLimitProvider(
142
139
  provider,
143
140
  rateLimit,
@@ -22,5 +22,14 @@ export interface TurnTelemetryEvent extends TelemetryEventBase {
22
22
  type: "turn";
23
23
  }
24
24
 
25
+ /** Lifecycle event — app_open, hatch, etc. */
26
+ export interface LifecycleTelemetryEvent extends TelemetryEventBase {
27
+ type: "lifecycle";
28
+ event_name: string;
29
+ }
30
+
25
31
  /** Discriminated union of all telemetry event types. */
26
- export type TelemetryEvent = LlmUsageTelemetryEvent | TurnTelemetryEvent;
32
+ export type TelemetryEvent =
33
+ | LlmUsageTelemetryEvent
34
+ | TurnTelemetryEvent
35
+ | LifecycleTelemetryEvent;
@@ -89,6 +89,10 @@ mock.module("../util/logger.js", () => ({
89
89
  }),
90
90
  }));
91
91
 
92
+ mock.module("../version.js", () => ({
93
+ APP_VERSION: "1.2.3-test",
94
+ }));
95
+
92
96
  // ---------------------------------------------------------------------------
93
97
  // Production import (after mocks)
94
98
  // ---------------------------------------------------------------------------
@@ -193,7 +197,7 @@ describe("UsageTelemetryReporter", () => {
193
197
 
194
198
  expect(mockFetch).toHaveBeenCalledTimes(1);
195
199
  const [url, opts] = mockFetch.mock.calls[0] as [string, RequestInit];
196
- expect(url).toBe("https://test.vellum.ai/v1/assistants/telemetry/ingest/");
200
+ expect(url).toBe("https://test.vellum.ai/v1/telemetry/ingest/");
197
201
  expect((opts.headers as Record<string, string>)["Authorization"]).toBe(
198
202
  "Api-Key test-key",
199
203
  );
@@ -370,8 +374,9 @@ describe("UsageTelemetryReporter", () => {
370
374
  (mockFetch.mock.calls[0] as [string, RequestInit])[1].body as string,
371
375
  );
372
376
 
373
- // Top-level: installation_id and events array (no turn_events key)
377
+ // Top-level: installation_id, app_version, and events array (no turn_events key)
374
378
  expect(body.installation_id).toBe("test-device-id");
379
+ expect(body.app_version).toBe("1.2.3-test");
375
380
  expect(Array.isArray(body.events)).toBe(true);
376
381
  expect(body.events.length).toBe(1);
377
382
  expect(body.turn_events).toBeUndefined();
@@ -19,12 +19,14 @@ import {
19
19
  getMemoryCheckpoint,
20
20
  setMemoryCheckpoint,
21
21
  } from "../memory/checkpoints.js";
22
+ import { queryUnreportedLifecycleEvents } from "../memory/lifecycle-events-store.js";
22
23
  import { queryUnreportedUsageEvents } from "../memory/llm-usage-store.js";
23
24
  import { queryUnreportedTurnEvents } from "../memory/turn-events-store.js";
24
25
  import { resolveManagedProxyContext } from "../providers/managed-proxy/context.js";
25
26
  import { getExternalAssistantId } from "../runtime/auth/external-assistant-id.js";
26
27
  import { getDeviceId } from "../util/device-id.js";
27
28
  import { getLogger } from "../util/logger.js";
29
+ import { APP_VERSION } from "../version.js";
28
30
  import type { TelemetryEvent } from "./types.js";
29
31
 
30
32
  const log = getLogger("usage-telemetry");
@@ -37,10 +39,14 @@ const CHECKPOINT_KEY_WATERMARK = "telemetry:usage:last_reported_at";
37
39
  const CHECKPOINT_KEY_WATERMARK_ID = "telemetry:usage:last_reported_id";
38
40
  const CHECKPOINT_KEY_TURN_WATERMARK = "telemetry:turns:last_reported_at";
39
41
  const CHECKPOINT_KEY_TURN_WATERMARK_ID = "telemetry:turns:last_reported_id";
42
+ const CHECKPOINT_KEY_LIFECYCLE_WATERMARK =
43
+ "telemetry:lifecycle:last_reported_at";
44
+ const CHECKPOINT_KEY_LIFECYCLE_WATERMARK_ID =
45
+ "telemetry:lifecycle:last_reported_id";
40
46
  const REPORT_INTERVAL_MS = 5 * 60 * 1000;
41
47
  const BATCH_SIZE = 500;
42
48
  const MAX_CONSECUTIVE_BATCHES = 10;
43
- const TELEMETRY_PATH = "/v1/assistants/telemetry/ingest/";
49
+ const TELEMETRY_PATH = "/v1/telemetry/ingest/";
44
50
 
45
51
  // ---------------------------------------------------------------------------
46
52
  // Reporter
@@ -100,6 +106,13 @@ export class UsageTelemetryReporter {
100
106
  const turnWatermarkId =
101
107
  getMemoryCheckpoint(CHECKPOINT_KEY_TURN_WATERMARK_ID) ?? undefined;
102
108
 
109
+ // Read lifecycle watermark (compound cursor: createdAt + id)
110
+ const lifecycleWatermark = Number(
111
+ getMemoryCheckpoint(CHECKPOINT_KEY_LIFECYCLE_WATERMARK) ?? "0",
112
+ );
113
+ const lifecycleWatermarkId =
114
+ getMemoryCheckpoint(CHECKPOINT_KEY_LIFECYCLE_WATERMARK_ID) ?? undefined;
115
+
103
116
  // Query unreported events
104
117
  const events = queryUnreportedUsageEvents(
105
118
  watermark,
@@ -111,8 +124,18 @@ export class UsageTelemetryReporter {
111
124
  turnWatermarkId,
112
125
  BATCH_SIZE,
113
126
  );
127
+ const lifecycleEvents = queryUnreportedLifecycleEvents(
128
+ lifecycleWatermark,
129
+ lifecycleWatermarkId,
130
+ BATCH_SIZE,
131
+ );
114
132
 
115
- if (events.length === 0 && turnEvents.length === 0) return;
133
+ if (
134
+ events.length === 0 &&
135
+ turnEvents.length === 0 &&
136
+ lifecycleEvents.length === 0
137
+ )
138
+ return;
116
139
 
117
140
  // Resolve auth context — skip flush when neither auth mode is viable
118
141
  const proxyCtx = await resolveManagedProxyContext();
@@ -154,6 +177,14 @@ export class UsageTelemetryReporter {
154
177
  recorded_at: e.createdAt,
155
178
  }),
156
179
  ),
180
+ ...lifecycleEvents.map(
181
+ (e): TelemetryEvent => ({
182
+ type: "lifecycle",
183
+ daemon_event_id: e.id,
184
+ event_name: e.eventName,
185
+ recorded_at: e.createdAt,
186
+ }),
187
+ ),
157
188
  ];
158
189
 
159
190
  const assistantId = getExternalAssistantId() ?? "self";
@@ -162,6 +193,7 @@ export class UsageTelemetryReporter {
162
193
  const payload = {
163
194
  installation_id: getDeviceId(),
164
195
  assistant_id: assistantId,
196
+ app_version: APP_VERSION,
165
197
  ...(organizationId ? { organization_id: organizationId } : {}),
166
198
  ...(userId ? { user_id: userId } : {}),
167
199
  events: typedEvents,
@@ -207,8 +239,25 @@ export class UsageTelemetryReporter {
207
239
  setMemoryCheckpoint(CHECKPOINT_KEY_TURN_WATERMARK_ID, lastTurn.id);
208
240
  }
209
241
 
210
- // If we got a full batch of either type, there may be more — recurse
211
- if (events.length === BATCH_SIZE || turnEvents.length === BATCH_SIZE) {
242
+ // Advance lifecycle watermark (compound cursor)
243
+ if (lifecycleEvents.length > 0) {
244
+ const lastLifecycle = lifecycleEvents[lifecycleEvents.length - 1];
245
+ setMemoryCheckpoint(
246
+ CHECKPOINT_KEY_LIFECYCLE_WATERMARK,
247
+ String(lastLifecycle.createdAt),
248
+ );
249
+ setMemoryCheckpoint(
250
+ CHECKPOINT_KEY_LIFECYCLE_WATERMARK_ID,
251
+ lastLifecycle.id,
252
+ );
253
+ }
254
+
255
+ // If we got a full batch of any type, there may be more — recurse
256
+ if (
257
+ events.length === BATCH_SIZE ||
258
+ turnEvents.length === BATCH_SIZE ||
259
+ lifecycleEvents.length === BATCH_SIZE
260
+ ) {
212
261
  await this._doFlush(batchCount + 1);
213
262
  }
214
263
  } catch (err) {
@@ -1,4 +1,4 @@
1
- # Tools Agent Instructions
1
+ # Tools - Agent Instructions
2
2
 
3
3
  ## No New Tools Policy
4
4
 
@@ -8,11 +8,11 @@ The tool registration system (`class ... implements Tool` + `registerTool()`) is
8
8
 
9
9
  ## Why This Policy Exists
10
10
 
11
- 1. **Skills are preferred** The project direction is to teach the assistant CLI tools via skills rather than hardcoding tool implementations. Skills are progressively disclosed into context, are more portable, and are often self-contained.
11
+ 1. **Skills are preferred** - The project direction is to teach the assistant CLI tools via skills rather than hardcoding tool implementations. Skills are progressively disclosed into context, are more portable, and are often self-contained.
12
12
 
13
- 2. **Context overhead** Each registered tool adds to the system prompt and increases token usage for every conversation.
13
+ 2. **Context overhead** - Each registered tool adds to the system prompt and increases token usage for every conversation.
14
14
 
15
- 3. **Maintenance burden** Tools require ongoing maintenance, testing, and security review. Skills can be iterated on independently.
15
+ 3. **Maintenance burden** - Tools require ongoing maintenance, testing, and security review. Skills can be iterated on independently.
16
16
 
17
17
  ## What To Do Instead
18
18
 
@@ -20,9 +20,9 @@ Instead of creating a new tool, consider:
20
20
 
21
21
  1. **Create a skill**
22
22
 
23
- 2. **Use existing tools** Many capabilities can be achieved by combining existing tools (bash, file operations, network tools) with skill instructions.
23
+ 2. **Use existing tools** - Many capabilities can be achieved by combining existing tools (bash, file operations, network tools) with skill instructions.
24
24
 
25
- 3. **External CLI tools** If you need new functionality, consider whether it can be exposed as a CLI tool that the assistant can invoke via bash.
25
+ 3. **External CLI tools** - If you need new functionality, consider whether it can be exposed as a CLI tool that the assistant can invoke via bash.
26
26
 
27
27
  ## Approved Exception: Credential Execution Service (CES) Tools
28
28
 
@@ -36,16 +36,16 @@ The following three CES tools are the only approved exception to the no-new-tool
36
36
 
37
37
  These tools exist as `class ... implements Tool` registrations because:
38
38
 
39
- - They enforce hard process-boundary isolation credential values are materialized only inside the CES process (`credential-executor/` package), never in the assistant process
39
+ - They enforce hard process-boundary isolation - credential values are materialized only inside the CES process (`credential-executor/` package), never in the assistant process
40
40
  - Skills run inside the assistant process and cannot provide this isolation guarantee
41
41
  - The tools are thin RPC stubs; actual credential materialization and execution logic lives in the separate `credential-executor/` package
42
42
 
43
43
  **Key constraints**:
44
44
 
45
- - CES is a **separate package and image** no direct source imports from `assistant/` to `credential-executor/` or vice versa
46
- - **Grants and audit logs are CES-owned** durable state the assistant never reads or writes CES grant or audit tables directly
47
- - `host_bash` is **outside the strong CES secrecy guarantee** it does not enforce credential isolation
48
- - Secure generic authenticated HTTP **must not** run through `run_authenticated_command` use `make_authenticated_request` instead, which enforces domain validation and produces structured audit logs
45
+ - CES is a **separate package and image** - no direct source imports from `assistant/` to `credential-executor/` or vice versa
46
+ - **Grants and audit logs are CES-owned** durable state - the assistant never reads or writes CES grant or audit tables directly
47
+ - `host_bash` is **outside the strong CES secrecy guarantee** - it does not enforce credential isolation
48
+ - Secure generic authenticated HTTP **must not** run through `run_authenticated_command` - use `make_authenticated_request` instead, which enforces domain validation and produces structured audit logs
49
49
  - Managed rollout requires a **third runtime image** (alongside assistant and gateway) and `vembda` pod-template changes
50
50
 
51
51
  See [`assistant/docs/credential-execution-service.md`](../../docs/credential-execution-service.md) for the full ADR.
@@ -32,7 +32,7 @@ export async function executeAcpSpawn(
32
32
  | undefined;
33
33
  if (!sendToClient) {
34
34
  return {
35
- content: "No client connected cannot spawn ACP agent.",
35
+ content: "No client connected - cannot spawn ACP agent.",
36
36
  isError: true,
37
37
  };
38
38
  }
@@ -28,7 +28,7 @@ export interface ExecutorResult {
28
28
  }
29
29
 
30
30
  // ---------------------------------------------------------------------------
31
- // Dependency interfaces callers inject these rather than importing the
31
+ // Dependency interfaces - callers inject these rather than importing the
32
32
  // app-store module directly, which makes the executors testable with mocks.
33
33
  // ---------------------------------------------------------------------------
34
34
 
@@ -82,7 +82,7 @@ export type ProxyResolver = (
82
82
  ) => Promise<ExecutorResult>;
83
83
 
84
84
  // ---------------------------------------------------------------------------
85
- // Path resolution multifile apps default to src/ for file operations
85
+ // Path resolution - multifile apps default to src/ for file operations
86
86
  // ---------------------------------------------------------------------------
87
87
 
88
88
  /**
@@ -146,7 +146,7 @@ export async function executeAppCreate(
146
146
  const autoOpen = input.auto_open !== false; // default true
147
147
  const preview = input.preview;
148
148
 
149
- // Validate required fields LLM input is not type-checked at runtime
149
+ // Validate required fields - LLM input is not type-checked at runtime
150
150
  if (typeof name !== "string" || name.trim() === "") {
151
151
  return {
152
152
  content: JSON.stringify({
@@ -168,7 +168,7 @@ export async function executeAppCreate(
168
168
  }
169
169
  }
170
170
 
171
- // Extract icon from preview if provided only persist emoji-like values,
171
+ // Extract icon from preview if provided - only persist emoji-like values,
172
172
  // not URLs which would render as raw strings in UI and bundle manifests.
173
173
  const rawIcon = preview?.icon as string | undefined;
174
174
  const icon = rawIcon && !rawIcon.startsWith("http") ? rawIcon : undefined;
@@ -270,7 +270,7 @@ render(<App />, document.getElementById('app')!);
270
270
  isError: false,
271
271
  };
272
272
  } catch {
273
- // Preview emission failure is non-fatal the app was created successfully.
273
+ // Preview emission failure is non-fatal - the app was created successfully.
274
274
  return {
275
275
  content: JSON.stringify({
276
276
  ...app,
@@ -388,7 +388,7 @@ export function executeAppFileList(
388
388
 
389
389
  if (app && isMultifileApp(app)) {
390
390
  // Separate build output paths from source paths without mutating the
391
- // file path strings consumers need clean paths for subsequent tool calls.
391
+ // file path strings - consumers need clean paths for subsequent tool calls.
392
392
  const buildOutputPaths = files.filter((f) =>
393
393
  f.replace(/\\/g, "/").startsWith("dist/"),
394
394
  );
@@ -557,7 +557,7 @@ export async function executeAppGenerateIcon(
557
557
  );
558
558
 
559
559
  if (existsSync(iconPath)) {
560
- // Success clean up the old icon backup
560
+ // Success - clean up the old icon backup
561
561
  if (existsSync(tempPath)) {
562
562
  unlinkSync(tempPath);
563
563
  }
@@ -567,7 +567,7 @@ export async function executeAppGenerateIcon(
567
567
  };
568
568
  }
569
569
 
570
- // Generation failed restore the previous icon if we had one
570
+ // Generation failed - restore the previous icon if we had one
571
571
  if (existsSync(tempPath)) {
572
572
  renameSync(tempPath, iconPath);
573
573
  }
@@ -2,7 +2,7 @@
2
2
  * Registers app proxy tools with the daemon's tool registry.
3
3
  *
4
4
  * Called once at daemon startup via initializeTools(). Only proxy tools
5
- * (e.g. app_open) are registered here non-proxy data tools are now
5
+ * (e.g. app_open) are registered here - non-proxy data tools are now
6
6
  * provided by the app-builder skill via its TOOLS.json manifest.
7
7
  */
8
8
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * asset_materialize write a stored attachment to a sandbox file path.
2
+ * asset_materialize - write a stored attachment to a sandbox file path.
3
3
  *
4
4
  * Accepts an attachment ID (from asset_search) and a destination path
5
5
  * within the sandbox working directory. Decodes the base64 content and
@@ -31,11 +31,11 @@ import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
31
31
  import { getAttachmentSourceConversations } from "./search.js";
32
32
 
33
33
  // ---------------------------------------------------------------------------
34
- // Size limit prevent materializing excessively large attachments
34
+ // Size limit - prevent materializing excessively large attachments
35
35
  // ---------------------------------------------------------------------------
36
36
 
37
- /** 50 MB ceiling for materialized files. */
38
- export const MAX_MATERIALIZE_BYTES = 50 * 1024 * 1024;
37
+ /** 100 MB ceiling for materialized files. */
38
+ export const MAX_MATERIALIZE_BYTES = 100 * 1024 * 1024;
39
39
 
40
40
  // ---------------------------------------------------------------------------
41
41
  // Helpers
@@ -110,7 +110,7 @@ class AssetMaterializeTool implements Tool {
110
110
  name = "asset_materialize";
111
111
  description = definition.description;
112
112
  category = "assets";
113
- defaultRiskLevel = RiskLevel.Medium;
113
+ defaultRiskLevel = RiskLevel.Low;
114
114
 
115
115
  getDefinition(): ToolDefinition {
116
116
  return definition;
@@ -177,7 +177,7 @@ class AssetMaterializeTool implements Tool {
177
177
  if (sources.length > 0) {
178
178
  const hasStandard = sources.some((s) => s.conversationType !== "private");
179
179
  if (!hasStandard) {
180
- // All sources are private check if the caller is in any of those conversations
180
+ // All sources are private - check if the caller is in any of those conversations
181
181
  const callerInSourceConversation = sources.some((s) =>
182
182
  isAttachmentVisible(
183
183
  { conversationId: s.conversationId, isPrivate: true },
@@ -1,9 +1,9 @@
1
1
  /**
2
- * asset_search cross-conversation attachment metadata search.
2
+ * asset_search - cross-conversation attachment metadata search.
3
3
  *
4
4
  * Queries the attachments store for matching assets by MIME type,
5
5
  * filename, recency, or conversation scope. Returns metadata and
6
- * attachment IDs only never base64 payloads. The IDs can be
6
+ * attachment IDs only - never base64 payloads. The IDs can be
7
7
  * passed to asset_materialize (PR 35) to retrieve actual content.
8
8
  */
9
9
 
@@ -33,7 +33,7 @@ import { registerTool } from "../registry.js";
33
33
  import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
34
34
 
35
35
  // ---------------------------------------------------------------------------
36
- // Recency presets map human-readable labels to epoch-ms cutoff offsets
36
+ // Recency presets - map human-readable labels to epoch-ms cutoff offsets
37
37
  // ---------------------------------------------------------------------------
38
38
 
39
39
  const RECENCY_MS: Record<string, number> = {
@@ -113,7 +113,7 @@ function isAttachmentVisibleFromContext(
113
113
  return true;
114
114
  }
115
115
 
116
- // All sources are private visible only if the caller is in one of those conversations
116
+ // All sources are private - visible only if the caller is in one of those conversations
117
117
  return sources.some((s) =>
118
118
  isAttachmentVisible(
119
119
  { conversationId: s.conversationId, isPrivate: true },
@@ -143,13 +143,13 @@ export function searchAttachments(
143
143
  const db = getDb();
144
144
  const conditions = [];
145
145
 
146
- // MIME type filter supports wildcards like 'image/*' via LIKE
146
+ // MIME type filter - supports wildcards like 'image/*' via LIKE
147
147
  if (params.mime_type) {
148
148
  const mimePattern = params.mime_type.replace(/\*/g, "%");
149
149
  conditions.push(like(attachments.mimeType, mimePattern));
150
150
  }
151
151
 
152
- // Filename filter case-insensitive substring match (escape LIKE wildcards)
152
+ // Filename filter - case-insensitive substring match (escape LIKE wildcards)
153
153
  if (params.filename) {
154
154
  conditions.push(
155
155
  like(
@@ -159,7 +159,7 @@ export function searchAttachments(
159
159
  );
160
160
  }
161
161
 
162
- // Recency filter computed cutoff timestamp
162
+ // Recency filter - computed cutoff timestamp
163
163
  if (params.recency) {
164
164
  const offsetMs = RECENCY_MS[params.recency];
165
165
  if (offsetMs) {
@@ -168,7 +168,7 @@ export function searchAttachments(
168
168
  }
169
169
  }
170
170
 
171
- // Conversation scope join through message_attachments + messages
171
+ // Conversation scope - join through message_attachments + messages
172
172
  if (params.conversation_id) {
173
173
  const linkedIds = db
174
174
  .select({ attachmentId: messageAttachments.attachmentId })
@@ -239,7 +239,7 @@ export function searchAttachments(
239
239
  }));
240
240
  }
241
241
 
242
- // No conversation constraint query attachments table directly
242
+ // No conversation constraint - query attachments table directly
243
243
  const limit = Math.min(params.limit ?? DEFAULT_LIMIT, MAX_RESULTS);
244
244
  const where = conditions.length > 0 ? and(...conditions) : undefined;
245
245
 
@@ -271,7 +271,7 @@ const definition: ToolDefinition = {
271
271
  name: "asset_search",
272
272
  description:
273
273
  "Search for previously uploaded media assets (images, documents, etc.) by metadata. " +
274
- "Returns attachment IDs and metadata not file content. Use the returned IDs with " +
274
+ "Returns attachment IDs and metadata - not file content. Use the returned IDs with " +
275
275
  "asset_materialize to retrieve actual file data.",
276
276
  input_schema: {
277
277
  type: "object",