@vellumai/assistant 0.4.56 → 0.4.57

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 (450) 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 +185 -173
  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 +237 -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__/gateway-only-enforcement.test.ts +2 -2
  67. package/src/__tests__/gateway-only-guard.test.ts +1 -0
  68. package/src/__tests__/gemini-image-service.test.ts +4 -4
  69. package/src/__tests__/gemini-provider.test.ts +6 -9
  70. package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
  71. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  72. package/src/__tests__/host-shell-tool.test.ts +6 -6
  73. package/src/__tests__/http-user-message-parity.test.ts +2 -2
  74. package/src/__tests__/intent-routing.test.ts +51 -99
  75. package/src/__tests__/invite-routes-http.test.ts +5 -0
  76. package/src/__tests__/list-messages-attachments.test.ts +1 -1
  77. package/src/__tests__/managed-proxy-context.test.ts +2 -5
  78. package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
  79. package/src/__tests__/media-generate-image.test.ts +32 -15
  80. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
  81. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
  82. package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
  83. package/src/__tests__/memory-recall-quality.test.ts +4 -3
  84. package/src/__tests__/memory-regressions.test.ts +86 -90
  85. package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
  86. package/src/__tests__/migration-export-http.test.ts +26 -27
  87. package/src/__tests__/migration-import-commit-http.test.ts +165 -37
  88. package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
  89. package/src/__tests__/migration-validate-http.test.ts +16 -16
  90. package/src/__tests__/model-intents.test.ts +1 -1
  91. package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
  92. package/src/__tests__/notification-broadcaster.test.ts +1 -1
  93. package/src/__tests__/notification-decision-fallback.test.ts +2 -2
  94. package/src/__tests__/notification-decision-identity.test.ts +8 -9
  95. package/src/__tests__/notification-decision-strategy.test.ts +1 -1
  96. package/src/__tests__/notification-deep-link.test.ts +1 -1
  97. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  98. package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
  99. package/src/__tests__/oauth-store.test.ts +1 -3
  100. package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
  101. package/src/__tests__/onboarding-template-contract.test.ts +23 -59
  102. package/src/__tests__/provider-error-scenarios.test.ts +154 -0
  103. package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
  104. package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
  105. package/src/__tests__/provider-registry-ollama.test.ts +5 -2
  106. package/src/__tests__/qdrant-manager.test.ts +7 -7
  107. package/src/__tests__/ratelimit.test.ts +0 -74
  108. package/src/__tests__/recording-handler.test.ts +0 -1
  109. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  110. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  111. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  112. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  113. package/src/__tests__/scheduler-recurrence.test.ts +46 -2
  114. package/src/__tests__/schema-transforms.test.ts +114 -54
  115. package/src/__tests__/secret-onetime-send.test.ts +20 -0
  116. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
  117. package/src/__tests__/secret-scanner-executor.test.ts +1 -2
  118. package/src/__tests__/send-endpoint-busy.test.ts +63 -4
  119. package/src/__tests__/send-notification-tool.test.ts +2 -2
  120. package/src/__tests__/shell-credential-ref.test.ts +0 -1
  121. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
  122. package/src/__tests__/skill-memory.test.ts +547 -0
  123. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
  124. package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
  125. package/src/__tests__/slack-channel-config.test.ts +109 -94
  126. package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
  127. package/src/__tests__/swarm-recursion.test.ts +2 -2
  128. package/src/__tests__/swarm-tool.test.ts +2 -2
  129. package/src/__tests__/system-prompt.test.ts +19 -66
  130. package/src/__tests__/telegram-config.test.ts +121 -0
  131. package/src/__tests__/terminal-tools.test.ts +1 -1
  132. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
  133. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  134. package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
  135. package/src/__tests__/tool-executor.test.ts +1 -1
  136. package/src/__tests__/trace-emitter.test.ts +8 -1
  137. package/src/__tests__/trust-store.test.ts +7 -8
  138. package/src/__tests__/twilio-routes.test.ts +1 -18
  139. package/src/__tests__/user-reference.test.ts +82 -2
  140. package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
  141. package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
  142. package/src/approvals/guardian-request-resolvers.ts +3 -3
  143. package/src/avatar/ascii-renderer.ts +2 -2
  144. package/src/avatar/png-renderer.ts +2 -2
  145. package/src/avatar/resvg-lazy.ts +21 -0
  146. package/src/calls/guardian-dispatch.ts +1 -1
  147. package/src/calls/relay-access-wait.ts +2 -2
  148. package/src/calls/twilio-rest.ts +0 -248
  149. package/src/cli/AGENTS.md +5 -8
  150. package/src/cli/__tests__/notifications.test.ts +5 -5
  151. package/src/cli/commands/avatar.ts +64 -2
  152. package/src/cli/commands/conversations.ts +131 -1
  153. package/src/cli/commands/credentials.ts +2 -0
  154. package/src/cli/commands/notifications.ts +3 -3
  155. package/src/cli.ts +10 -0
  156. package/src/config/bundled-skills/acp/SKILL.md +5 -5
  157. package/src/config/bundled-skills/acp/TOOLS.json +6 -6
  158. package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
  159. package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
  160. package/src/config/bundled-skills/browser/SKILL.md +15 -15
  161. package/src/config/bundled-skills/browser/TOOLS.json +14 -14
  162. package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
  163. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
  164. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
  165. package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
  166. package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
  167. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
  168. package/src/config/bundled-skills/contacts/SKILL.md +3 -3
  169. package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
  170. package/src/config/bundled-skills/document/SKILL.md +4 -4
  171. package/src/config/bundled-skills/document/TOOLS.json +2 -2
  172. package/src/config/bundled-skills/followups/TOOLS.json +3 -3
  173. package/src/config/bundled-skills/gmail/SKILL.md +32 -32
  174. package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
  175. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
  176. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
  177. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
  178. package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
  179. package/src/config/bundled-skills/google-calendar/types.ts +1 -1
  180. package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
  181. package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
  182. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
  183. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
  184. package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
  185. package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
  186. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
  187. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
  188. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
  189. package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
  190. package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
  191. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
  192. package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
  193. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
  194. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
  195. package/src/config/bundled-skills/messaging/SKILL.md +29 -25
  196. package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
  197. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
  198. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
  199. package/src/config/bundled-skills/notifications/SKILL.md +3 -3
  200. package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
  201. package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
  202. package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
  203. package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
  204. package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
  205. package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
  206. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
  207. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
  208. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
  209. package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
  210. package/src/config/bundled-skills/schedule/SKILL.md +26 -26
  211. package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
  212. package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
  213. package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
  214. package/src/config/bundled-skills/sequences/SKILL.md +2 -2
  215. package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
  216. package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
  217. package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
  218. package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
  219. package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
  220. package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
  221. package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
  222. package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
  223. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  224. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
  225. package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
  226. package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
  227. package/src/config/bundled-skills/slack/SKILL.md +2 -2
  228. package/src/config/bundled-skills/slack/TOOLS.json +8 -8
  229. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
  230. package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
  231. package/src/config/bundled-skills/tasks/SKILL.md +1 -1
  232. package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
  233. package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
  234. package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
  235. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
  236. package/src/config/bundled-skills/watcher/SKILL.md +4 -4
  237. package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
  238. package/src/config/feature-flag-registry.json +33 -17
  239. package/src/config/schemas/sandbox.ts +1 -1
  240. package/src/config/schemas/services.ts +13 -3
  241. package/src/config/schemas/timeouts.ts +0 -10
  242. package/src/contacts/contact-store.ts +63 -0
  243. package/src/contacts/contacts-write.ts +1 -1
  244. package/src/daemon/assistant-attachments.ts +2 -2
  245. package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
  246. package/src/daemon/conversation-agent-loop.ts +7 -30
  247. package/src/daemon/conversation-error.ts +24 -0
  248. package/src/daemon/conversation-memory.ts +8 -7
  249. package/src/daemon/conversation-runtime-assembly.ts +139 -274
  250. package/src/daemon/conversation-slash.ts +7 -26
  251. package/src/daemon/conversation-surfaces.ts +14 -0
  252. package/src/daemon/conversation-tool-setup.ts +9 -8
  253. package/src/daemon/conversation.ts +2 -0
  254. package/src/daemon/daemon-control.ts +1 -1
  255. package/src/daemon/date-context.ts +10 -83
  256. package/src/daemon/handlers/config-channels.ts +12 -2
  257. package/src/daemon/handlers/config-slack-channel.ts +7 -1
  258. package/src/daemon/handlers/config-telegram.ts +6 -1
  259. package/src/daemon/handlers/conversations.ts +2 -2
  260. package/src/daemon/handlers/skills.ts +4 -0
  261. package/src/daemon/lifecycle.ts +28 -4
  262. package/src/daemon/providers-setup.ts +1 -1
  263. package/src/daemon/server.ts +1 -5
  264. package/src/daemon/shutdown-handlers.ts +9 -3
  265. package/src/daemon/tool-side-effects.ts +40 -0
  266. package/src/daemon/trace-emitter.ts +25 -2
  267. package/src/events/domain-events.ts +1 -1
  268. package/src/events/tool-permission-telemetry-listener.ts +46 -0
  269. package/src/inbound/platform-callback-registration.ts +0 -18
  270. package/src/media/app-icon-generator.ts +15 -8
  271. package/src/media/avatar-router.ts +15 -8
  272. package/src/media/gemini-image-service.ts +125 -21
  273. package/src/memory/attachments-store.ts +3 -3
  274. package/src/memory/channel-verification-sessions.ts +6 -6
  275. package/src/memory/conversation-crud.ts +196 -1
  276. package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
  277. package/src/memory/conversation-title-service.ts +2 -3
  278. package/src/memory/db-init.ts +25 -1
  279. package/src/memory/invite-store.ts +4 -4
  280. package/src/memory/items-extractor.ts +4 -4
  281. package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
  282. package/src/memory/jobs-store.ts +3 -2
  283. package/src/memory/jobs-worker.ts +7 -5
  284. package/src/memory/lifecycle-events-store.ts +63 -0
  285. package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
  286. package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
  287. package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
  288. package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
  289. package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
  290. package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
  291. package/src/memory/migrations/index.ts +6 -0
  292. package/src/memory/migrations/registry.ts +13 -0
  293. package/src/memory/retriever.test.ts +223 -96
  294. package/src/memory/retriever.ts +115 -138
  295. package/src/memory/schema/calls.ts +1 -1
  296. package/src/memory/schema/contacts.ts +1 -1
  297. package/src/memory/schema/infrastructure.ts +29 -0
  298. package/src/memory/schema/memory-core.ts +7 -17
  299. package/src/memory/schema/notifications.ts +1 -1
  300. package/src/memory/search/formatting.ts +23 -6
  301. package/src/memory/search/lexical.ts +2 -0
  302. package/src/memory/search/semantic.ts +2 -0
  303. package/src/memory/search/staleness.ts +1 -0
  304. package/src/memory/search/types.ts +4 -0
  305. package/src/memory/task-memory-cleanup.ts +96 -6
  306. package/src/memory/trace-event-store.ts +148 -0
  307. package/src/notifications/README.md +1 -1
  308. package/src/notifications/decision-engine.ts +2 -2
  309. package/src/notifications/emit-signal.ts +4 -4
  310. package/src/notifications/events-store.ts +4 -4
  311. package/src/notifications/signal.ts +1 -1
  312. package/src/oauth/manual-token-connection.ts +49 -25
  313. package/src/permissions/checker.ts +6 -5
  314. package/src/permissions/defaults.ts +4 -4
  315. package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
  316. package/src/prompts/cache-boundary.ts +8 -0
  317. package/src/prompts/system-prompt.ts +105 -634
  318. package/src/prompts/templates/BOOTSTRAP.md +166 -33
  319. package/src/prompts/templates/IDENTITY.md +8 -23
  320. package/src/prompts/templates/SOUL.md +20 -41
  321. package/src/prompts/templates/USER.md +3 -19
  322. package/src/prompts/user-reference.ts +14 -16
  323. package/src/providers/anthropic/client.ts +46 -2
  324. package/src/providers/gemini/client.ts +6 -9
  325. package/src/providers/managed-proxy/constants.ts +1 -7
  326. package/src/providers/managed-proxy/context.ts +0 -1
  327. package/src/providers/model-intents.ts +5 -5
  328. package/src/providers/openai/client.ts +10 -1
  329. package/src/providers/openrouter/client.ts +1 -0
  330. package/src/providers/ratelimit.ts +0 -35
  331. package/src/providers/registry.ts +3 -5
  332. package/src/providers/retry.ts +18 -1
  333. package/src/runtime/access-request-helper.ts +1 -1
  334. package/src/runtime/auth/route-policy.ts +7 -0
  335. package/src/runtime/channel-verification-service.ts +1 -1
  336. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  337. package/src/runtime/guardian-vellum-migration.ts +63 -1
  338. package/src/runtime/http-server.ts +8 -4
  339. package/src/runtime/migrations/vbundle-builder.ts +212 -32
  340. package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
  341. package/src/runtime/migrations/vbundle-importer.ts +66 -1
  342. package/src/runtime/migrations/vbundle-validator.ts +17 -3
  343. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
  344. package/src/runtime/routes/attachment-routes.ts +2 -2
  345. package/src/runtime/routes/btw-routes.ts +9 -0
  346. package/src/runtime/routes/channel-verification-routes.ts +19 -2
  347. package/src/runtime/routes/conversation-management-routes.ts +55 -1
  348. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  349. package/src/runtime/routes/conversation-routes.ts +49 -5
  350. package/src/runtime/routes/conversation-starter-routes.ts +207 -0
  351. package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
  352. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
  353. package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
  354. package/src/runtime/routes/migration-routes.ts +25 -13
  355. package/src/runtime/routes/secret-routes.ts +18 -0
  356. package/src/runtime/routes/settings-routes.ts +8 -8
  357. package/src/runtime/routes/telemetry-routes.ts +53 -0
  358. package/src/runtime/routes/trace-event-routes.ts +62 -0
  359. package/src/runtime/tool-grant-request-helper.ts +1 -1
  360. package/src/runtime/verification-outbound-actions.ts +47 -31
  361. package/src/security/encrypted-store.ts +263 -78
  362. package/src/skills/catalog-install.ts +10 -0
  363. package/src/skills/managed-store.ts +2 -0
  364. package/src/skills/skill-memory.ts +220 -0
  365. package/src/subagent/manager.ts +1 -4
  366. package/src/telemetry/types.ts +10 -1
  367. package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
  368. package/src/telemetry/usage-telemetry-reporter.ts +51 -4
  369. package/src/tools/AGENTS.md +11 -11
  370. package/src/tools/acp/spawn.ts +1 -1
  371. package/src/tools/apps/executors.ts +8 -8
  372. package/src/tools/apps/registry.ts +1 -1
  373. package/src/tools/assets/materialize.ts +6 -6
  374. package/src/tools/assets/search.ts +10 -10
  375. package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
  376. package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
  377. package/src/tools/browser/auth-detector.ts +6 -6
  378. package/src/tools/browser/browser-execution.ts +13 -13
  379. package/src/tools/browser/browser-manager.ts +3 -3
  380. package/src/tools/browser/chrome-cdp.ts +5 -5
  381. package/src/tools/browser/jit-auth.ts +2 -2
  382. package/src/tools/browser/network-recorder.test.ts +2 -2
  383. package/src/tools/browser/network-recorder.ts +3 -3
  384. package/src/tools/browser/runtime-check.ts +3 -3
  385. package/src/tools/claude-code/claude-code.ts +2 -2
  386. package/src/tools/computer-use/definitions.ts +18 -18
  387. package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
  388. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
  389. package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
  390. package/src/tools/credentials/broker-types.ts +5 -5
  391. package/src/tools/credentials/broker.ts +15 -15
  392. package/src/tools/credentials/metadata-store.ts +2 -2
  393. package/src/tools/credentials/resolve.ts +1 -1
  394. package/src/tools/credentials/selection.ts +1 -1
  395. package/src/tools/credentials/tool-policy.ts +1 -1
  396. package/src/tools/credentials/vault.ts +115 -25
  397. package/src/tools/execution-target.ts +2 -2
  398. package/src/tools/executor.ts +7 -7
  399. package/src/tools/filesystem/edit.ts +2 -2
  400. package/src/tools/filesystem/read.ts +1 -1
  401. package/src/tools/filesystem/write.ts +1 -1
  402. package/src/tools/host-filesystem/edit.ts +2 -1
  403. package/src/tools/host-filesystem/read.ts +2 -1
  404. package/src/tools/host-filesystem/write.ts +1 -1
  405. package/src/tools/host-terminal/host-shell.ts +9 -8
  406. package/src/tools/mcp/mcp-tool-factory.ts +7 -6
  407. package/src/tools/memory/definitions.ts +6 -5
  408. package/src/tools/memory/handlers.test.ts +1 -1
  409. package/src/tools/network/__tests__/web-search.test.ts +3 -3
  410. package/src/tools/network/domain-normalize.ts +2 -2
  411. package/src/tools/network/script-proxy/session-manager.ts +10 -10
  412. package/src/tools/network/web-fetch.ts +1 -1
  413. package/src/tools/network/web-search.ts +3 -3
  414. package/src/tools/permission-checker.ts +8 -8
  415. package/src/tools/registry.ts +7 -7
  416. package/src/tools/schedule/list.ts +2 -2
  417. package/src/tools/schema-transforms.ts +31 -21
  418. package/src/tools/secret-detection-handler.ts +1 -1
  419. package/src/tools/sensitive-output-placeholders.ts +1 -1
  420. package/src/tools/shared/filesystem/edit-engine.ts +1 -1
  421. package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
  422. package/src/tools/shared/filesystem/image-read.ts +25 -5
  423. package/src/tools/shared/filesystem/path-policy.ts +2 -2
  424. package/src/tools/shared/shell-output.ts +1 -1
  425. package/src/tools/side-effects.ts +1 -1
  426. package/src/tools/skills/execute.ts +1 -1
  427. package/src/tools/skills/load.ts +3 -3
  428. package/src/tools/skills/sandbox-runner.ts +3 -3
  429. package/src/tools/subagent/read.ts +1 -1
  430. package/src/tools/subagent/spawn.ts +2 -2
  431. package/src/tools/swarm/delegate.ts +3 -3
  432. package/src/tools/system/request-permission.ts +5 -4
  433. package/src/tools/terminal/backends/native.ts +4 -4
  434. package/src/tools/terminal/parser.ts +6 -6
  435. package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
  436. package/src/tools/terminal/shell.ts +16 -16
  437. package/src/tools/tool-approval-handler.ts +21 -12
  438. package/src/tools/tool-manifest.ts +4 -4
  439. package/src/tools/types.ts +3 -3
  440. package/src/tools/ui-surface/definitions.ts +9 -37
  441. package/src/tools/watcher/list.ts +1 -1
  442. package/src/util/logger.ts +7 -2
  443. package/src/util/retry.ts +29 -1
  444. package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
  445. package/src/workspace/migrations/registry.ts +2 -0
  446. package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
  447. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
  448. package/src/cli/reference.ts +0 -38
  449. package/src/memory/job-handlers/capability-cards.ts +0 -420
  450. package/src/runtime/routes/thread-starter-routes.ts +0 -294
@@ -34,7 +34,7 @@ const CONTAINER_WORKSPACE_EXACT = "/workspace";
34
34
  *
35
35
  * For existing paths, symlinks are resolved via realpathSync so a symlink
36
36
  * pointing outside the boundary is caught. For new paths (e.g. file_write),
37
- * pass `mustExist: false` the nearest existing ancestor directory is
37
+ * pass `mustExist: false` - the nearest existing ancestor directory is
38
38
  * resolved via realpathSync to catch symlinks in parent dirs.
39
39
  *
40
40
  * Paths starting with `/workspace/` are treated as container-scoped and
@@ -71,7 +71,7 @@ export function sandboxPolicy(
71
71
  try {
72
72
  realResolved = realpathSync(resolved);
73
73
  } catch {
74
- // File doesn't exist will be caught by the tool's own existence check
74
+ // File doesn't exist - will be caught by the tool's own existence check
75
75
  realResolved = resolved;
76
76
  }
77
77
  } else {
@@ -9,7 +9,7 @@ export interface ShellOutputResult {
9
9
  /**
10
10
  * Format the raw stdout/stderr/exit-code from a spawned shell command into the
11
11
  * final tool result. Both `shell.ts` (sandbox bash) and `host-shell.ts`
12
- * (host_bash) must produce identical output formatting this shared function
12
+ * (host_bash) must produce identical output formatting - this shared function
13
13
  * is the single source of truth for that logic.
14
14
  */
15
15
  export function formatShellOutput(
@@ -1,4 +1,4 @@
1
- // Side-effect tool classification single source of truth.
1
+ // Side-effect tool classification - single source of truth.
2
2
  // Tools that modify state outside the assistant (filesystem writes,
3
3
  // shell commands, network requests that trigger actions, etc.).
4
4
  // Used by private-conversation gating and permission simulation to decide
@@ -27,7 +27,7 @@ export class SkillExecuteTool implements Tool {
27
27
  description:
28
28
  "Tool-specific parameters as documented in the skill's instructions",
29
29
  },
30
- reason: {
30
+ activity: {
31
31
  type: "string",
32
32
  description:
33
33
  "Brief non-technical explanation of what you are doing and why, shown to the user as a status update.",
@@ -113,7 +113,7 @@ function formatToolSchemas(
113
113
  export class SkillLoadTool implements Tool {
114
114
  name = "skill_load";
115
115
  description =
116
- "Load full instructions for a configured skill from ~/.vellum/workspace/skills.";
116
+ "Load full instructions for a skill. Works for both bundled skills (listed in the catalog) and workspace skills in ~/.vellum/workspace/skills.";
117
117
  category = "skills";
118
118
  defaultRiskLevel = RiskLevel.Low;
119
119
 
@@ -249,7 +249,7 @@ export class SkillLoadTool implements Tool {
249
249
  catalogIndex = indexCatalogById(catalog);
250
250
  }
251
251
 
252
- // Validate (fail-closed catches genuinely missing deps + cycles)
252
+ // Validate (fail-closed - catches genuinely missing deps + cycles)
253
253
  const validation = validateIncludes(skill.id, catalogIndex);
254
254
  if (!validation.ok) {
255
255
  if (validation.error === "missing") {
@@ -307,7 +307,7 @@ export class SkillLoadTool implements Tool {
307
307
  continue;
308
308
 
309
309
  childLines.push(
310
- ` - ${child.id}: ${child.displayName} ${child.description} (${child.skillFilePath})`,
310
+ ` - ${child.id}: ${child.displayName} - ${child.description} (${child.skillFilePath})`,
311
311
  );
312
312
 
313
313
  // Load the included skill's body content
@@ -204,7 +204,7 @@ function spawnRunner(
204
204
  return;
205
205
  }
206
206
 
207
- // No structured result fall back to raw output
207
+ // No structured result - fall back to raw output
208
208
  if (code !== 0) {
209
209
  const truncatedStderr =
210
210
  stderr.length > MAX_OUTPUT_CHARS
@@ -261,7 +261,7 @@ function parseSkillResult(
261
261
  }
262
262
  }
263
263
  } catch {
264
- // malformed line keep scanning
264
+ // malformed line - keep scanning
265
265
  }
266
266
  searchFrom = lineStart;
267
267
  }
@@ -285,7 +285,7 @@ function parseSkillResult(
285
285
  };
286
286
  }
287
287
  } catch {
288
- // malformed line keep scanning
288
+ // malformed line - keep scanning
289
289
  }
290
290
  searchFrom = lineStart;
291
291
  }
@@ -44,7 +44,7 @@ export async function executeSubagentRead(
44
44
  };
45
45
  }
46
46
 
47
- // Extract assistant messages only that's the subagent's output.
47
+ // Extract assistant messages only - that's the subagent's output.
48
48
  const output: string[] = [];
49
49
  for (const msg of dbMessages) {
50
50
  if (msg.role !== "assistant") continue;
@@ -23,7 +23,7 @@ export async function executeSubagentSpawn(
23
23
  | undefined;
24
24
  if (!sendToClient) {
25
25
  return {
26
- content: "No client connected cannot spawn subagent.",
26
+ content: "No client connected - cannot spawn subagent.",
27
27
  isError: true,
28
28
  };
29
29
  }
@@ -45,7 +45,7 @@ export async function executeSubagentSpawn(
45
45
  subagentId,
46
46
  label,
47
47
  status: "pending",
48
- message: `Subagent "${label}" spawned. You will be notified automatically when it completes or fails do NOT poll subagent_status. Continue the conversation normally.`,
48
+ message: `Subagent "${label}" spawned. You will be notified automatically when it completes or fails - do NOT poll subagent_status. Continue the conversation normally.`,
49
49
  }),
50
50
  isError: false,
51
51
  };
@@ -73,7 +73,7 @@ export const swarmDelegateTool: Tool = {
73
73
  return { content: "Cancelled", isError: true };
74
74
  }
75
75
 
76
- // Recursion guard scoped to conversation so independent conversations are not blocked
76
+ // Recursion guard - scoped to conversation so independent conversations are not blocked
77
77
  const conversationKey = context.conversationId;
78
78
  if (activeConversations.has(conversationKey)) {
79
79
  return {
@@ -129,7 +129,7 @@ export const swarmDelegateTool: Tool = {
129
129
  config.providerOrder,
130
130
  );
131
131
  } catch {
132
- // No provider available for synthesis will use fallback
132
+ // No provider available for synthesis - will use fallback
133
133
  }
134
134
 
135
135
  const summary = await executeSwarm({
@@ -199,7 +199,7 @@ export const swarmDelegateTool: Tool = {
199
199
  },
200
200
  };
201
201
 
202
- /** Clear all active conversations only for testing. */
202
+ /** Clear all active conversations - only for testing. */
203
203
  export function _resetSwarmActive(): void {
204
204
  activeConversations.clear();
205
205
  }
@@ -53,8 +53,9 @@ const FRIENDLY_NAMES: Record<PermissionType, string> = {
53
53
  class RequestSystemPermissionTool implements Tool {
54
54
  name = "request_system_permission";
55
55
  description =
56
- "Ask the user to grant a macOS system permission (e.g. Full Disk Access) via System Settings. " +
57
- "Use this when a tool execution fails because of a TCC/permission error.";
56
+ "Ask the user to grant a macOS system permission via System Settings. " +
57
+ "Use when a tool fails with a permission/access error (e.g. 'Operation not permitted', 'EACCES', sandbox denial). " +
58
+ "Do not explain how to open System Settings manually - this tool handles it with a clickable button.";
58
59
  category = "system";
59
60
  defaultRiskLevel = RiskLevel.High;
60
61
 
@@ -70,13 +71,13 @@ class RequestSystemPermissionTool implements Tool {
70
71
  enum: [...PERMISSION_TYPES],
71
72
  description: "The macOS system permission to request",
72
73
  },
73
- reason: {
74
+ activity: {
74
75
  type: "string",
75
76
  description:
76
77
  "Short explanation of why this permission is needed (shown to the user)",
77
78
  },
78
79
  },
79
- required: ["permission_type", "reason"],
80
+ required: ["permission_type", "activity"],
80
81
  },
81
82
  };
82
83
  }
@@ -31,12 +31,12 @@ function buildSandboxProfile(
31
31
  denyReadPaths?: string[],
32
32
  ): string {
33
33
  const networkRule = allowNetwork
34
- ? ";; Allow network access (proxied mode needed to reach the credential proxy)\n(allow network*)"
34
+ ? ";; Allow network access (proxied mode - needed to reach the credential proxy)\n(allow network*)"
35
35
  : ";; Block network access\n(deny network*)";
36
36
 
37
37
  // Build deny-read rules for protected paths (CES shell lockdown).
38
38
  // These are placed AFTER the allow file-read* rule because SBPL uses
39
- // last-match-wins semantics the more specific deny overrides the
39
+ // last-match-wins semantics - the more specific deny overrides the
40
40
  // general allow.
41
41
  const denyReadRules =
42
42
  denyReadPaths && denyReadPaths.length > 0
@@ -149,13 +149,13 @@ let bwrapAvailable = false;
149
149
  /**
150
150
  * Check whether bwrap is installed AND functional (can create namespaces).
151
151
  *
152
- * Just testing `bwrap --version` is not enough the binary may exist but
152
+ * Just testing `bwrap --version` is not enough - the binary may exist but
153
153
  * namespace creation can be blocked by the kernel (e.g. inside containers
154
154
  * or when user namespaces are disabled). We run a minimal sandbox that
155
155
  * exercises all namespace types used by buildBwrapArgs() (mount, network,
156
156
  * PID) to verify end-to-end functionality.
157
157
  *
158
- * Only positive results are cached if bwrap is unavailable, we re-check
158
+ * Only positive results are cached - if bwrap is unavailable, we re-check
159
159
  * on every call so that a mid-session install is picked up immediately.
160
160
  */
161
161
  function isBwrapAvailable(): boolean {
@@ -38,7 +38,7 @@ export interface ParsedCommand {
38
38
  }
39
39
 
40
40
  const SHELL_PROGRAMS = new Set(["sh", "bash", "zsh", "dash", "ksh", "fish"]);
41
- // Script interpreters that can execute arbitrary code from stdin piping
41
+ // Script interpreters that can execute arbitrary code from stdin - piping
42
42
  // untrusted data into these is as dangerous as piping into a shell.
43
43
  const SCRIPT_INTERPRETERS = new Set([
44
44
  "python",
@@ -55,7 +55,7 @@ const STDIN_EXEC_FLAGS = new Set(["-c", "-e", "-"]);
55
55
  // Per-interpreter flags that consume the next argument as a value (not a filename).
56
56
  // Mapped by interpreter name since flags differ across interpreters
57
57
  // (e.g. -I is standalone in Python but takes a value in Ruby).
58
- // Note: `-m` is intentionally excluded it means "run module", so the next arg
58
+ // Note: `-m` is intentionally excluded - it means "run module", so the next arg
59
59
  // is a module name and the interpreter is NOT in stdin-exec mode.
60
60
  const INTERPRETER_VALUE_FLAGS: ReadonlyMap<
61
61
  string,
@@ -128,7 +128,7 @@ const initGuard = new PromiseGuard<void>();
128
128
  * In development / `bunx` the file lives under `node_modules/` relative
129
129
  * to the source tree. In compiled Bun binaries `import.meta.dirname`
130
130
  * points into the virtual `/$bunfs/` filesystem where binary assets
131
- * don't exist fall back to:
131
+ * don't exist - fall back to:
132
132
  * 1. `../Resources/<file>` (macOS .app bundle layout)
133
133
  * 2. Next to the compiled binary (process.execPath)
134
134
  * This matches the pattern used for compiled Bun binary asset resolution.
@@ -352,7 +352,7 @@ function extractSegments(node: TSNode): CommandSegment[] {
352
352
  }
353
353
 
354
354
  /**
355
- * Returns true when the interpreter args indicate stdin-exec mode i.e. the
355
+ * Returns true when the interpreter args indicate stdin-exec mode - i.e. the
356
356
  * interpreter will read code from stdin (or from an inline -c/-e argument)
357
357
  * rather than from a file. Concretely:
358
358
  * - Any STDIN_EXEC_FLAGS present → stdin-exec
@@ -367,7 +367,7 @@ function isStdinExecMode(interpreter: string, args: string[]): boolean {
367
367
  if (STDIN_EXEC_FLAGS.has(arg)) return true;
368
368
  // First non-flag argument is a filename/module → file mode
369
369
  if (!arg.startsWith("-")) return false;
370
- // Flags like -W, -X consume the next token as their value skip it
370
+ // Flags like -W, -X consume the next token as their value - skip it
371
371
  if (valueFlags.has(arg)) i++;
372
372
  }
373
373
  // No positional arguments at all → interpreter reads from stdin
@@ -581,7 +581,7 @@ export async function parse(command: string): Promise<ParsedCommand> {
581
581
  const parser = await ensureParser();
582
582
  const tree = parser.parse(command);
583
583
  if (!tree) {
584
- // Parser couldn't parse treat as opaque
584
+ // Parser couldn't parse - treat as opaque
585
585
  return { segments: [], dangerousPatterns: [], hasOpaqueConstructs: true };
586
586
  }
587
587
  const rootNode = tree.rootNode;
@@ -46,7 +46,7 @@ function checkNativeBackend(): SandboxCheckResult {
46
46
  return {
47
47
  label: "Native sandbox (Linux bwrap)",
48
48
  ok: false,
49
- detail: "bwrap not available install bubblewrap",
49
+ detail: "bwrap not available - install bubblewrap",
50
50
  };
51
51
  }
52
52
  }
@@ -39,13 +39,13 @@ function buildCredentialRefTrace(
39
39
  * inside the sandbox when CES shell lockdown is active.
40
40
  *
41
41
  * Protected paths include:
42
- * - ~/.vellum/protected/ credential store secrets (also covers local-mode
42
+ * - ~/.vellum/protected/ - credential store secrets (also covers local-mode
43
43
  * CES data root at ~/.vellum/protected/credential-executor/)
44
- * - ~/.vellum/workspace/data/db/ database files that may contain credential metadata
45
- * - CES bootstrap socket directory (/run/ces-bootstrap/ or CES_BOOTSTRAP_SOCKET_DIR)
44
+ * - ~/.vellum/workspace/data/db/ - database files that may contain credential metadata
45
+ * - CES bootstrap socket directory (/run/ces-bootstrap/ or CES_BOOTSTRAP_SOCKET_DIR) -
46
46
  * prevents untrusted shells from connecting to the CES sidecar directly
47
47
  * - CES managed-mode data root (CES_DATA_DIR, or /ces-data when
48
- * CES_MANAGED_MODE is set) prevents access to CES-private state in
48
+ * CES_MANAGED_MODE is set) - prevents access to CES-private state in
49
49
  * managed deployments (local-mode is already covered by the protected/
50
50
  * entry)
51
51
  */
@@ -53,7 +53,7 @@ function buildCesProtectedPaths(): string[] {
53
53
  const root = getRootDir();
54
54
  const paths = [`${root}/protected`, `${root}/workspace/data/db`];
55
55
 
56
- // CES bootstrap socket directory block access to the Unix socket that
56
+ // CES bootstrap socket directory - block access to the Unix socket that
57
57
  // accepts RPC commands from the assistant process.
58
58
  const bootstrapSocketDir =
59
59
  process.env["CES_BOOTSTRAP_SOCKET_DIR"] || "/run/ces-bootstrap";
@@ -68,7 +68,7 @@ function buildCesProtectedPaths(): string[] {
68
68
  paths.push(dirname(process.env["CES_BOOTSTRAP_SOCKET"]));
69
69
  }
70
70
 
71
- // CES managed-mode private data root in managed deployments the CES
71
+ // CES managed-mode private data root - in managed deployments the CES
72
72
  // data lives outside the Vellum root, so it isn't covered by the
73
73
  // `protected/` entry above.
74
74
  const cesDataDir = process.env["CES_DATA_DIR"];
@@ -100,7 +100,7 @@ class ShellTool implements Tool {
100
100
  type: "string",
101
101
  description: "The shell command to execute",
102
102
  },
103
- reason: {
103
+ activity: {
104
104
  type: "string",
105
105
  description:
106
106
  'Brief non-technical explanation of what this command does and why, shown to a non-technical user in the permission prompt. Avoid jargon and technical terms. Good: "to check if a required program is installed on your computer". Bad: "to check if gcloud CLI is installed". Good: "to download a helper program". Bad: "to run npm install".',
@@ -123,7 +123,7 @@ class ShellTool implements Tool {
123
123
  'Optional list of credential IDs to inject via the proxy when network_mode is "proxied".',
124
124
  },
125
125
  },
126
- required: ["command", "reason"],
126
+ required: ["command", "activity"],
127
127
  },
128
128
  };
129
129
  }
@@ -140,7 +140,7 @@ class ShellTool implements Tool {
140
140
  };
141
141
  }
142
142
 
143
- // Reject commands containing null bytes they cause truncation at the
143
+ // Reject commands containing null bytes - they cause truncation at the
144
144
  // OS level while the parser sees the full string, enabling bypass.
145
145
  if (command.includes("\0")) {
146
146
  return { content: "Error: command contains null bytes", isError: true };
@@ -155,7 +155,7 @@ class ShellTool implements Tool {
155
155
  input.network_mode === "proxied" ? "proxied" : "off";
156
156
 
157
157
  // -----------------------------------------------------------------------
158
- // CES shell lockdown reject proxied credential sessions for untrusted
158
+ // CES shell lockdown - reject proxied credential sessions for untrusted
159
159
  // actors when the lockdown flag is active. Proxied sessions grant the
160
160
  // subprocess access to credentials through the egress proxy, which
161
161
  // violates the secrecy guarantee.
@@ -183,7 +183,7 @@ class ShellTool implements Tool {
183
183
  }
184
184
 
185
185
  // -----------------------------------------------------------------------
186
- // CES shell lockdown reject non-empty credential-ref mode for untrusted
186
+ // CES shell lockdown - reject non-empty credential-ref mode for untrusted
187
187
  // actors. Even when network_mode is "off", passing credential_ids could
188
188
  // allow the model to probe stored credential metadata.
189
189
  // -----------------------------------------------------------------------
@@ -201,7 +201,7 @@ class ShellTool implements Tool {
201
201
  }
202
202
 
203
203
  // Resolve credential refs (UUID or service/field) to canonical UUIDs.
204
- // Fail fast if any ref is unresolvable partial execution with missing
204
+ // Fail fast if any ref is unresolvable - partial execution with missing
205
205
  // credentials is worse than a clear error.
206
206
  const credentialIds: string[] = [];
207
207
  if (networkMode === "proxied" && rawCredentialRefs.length > 0) {
@@ -264,7 +264,7 @@ class ShellTool implements Tool {
264
264
  "Executing shell command",
265
265
  );
266
266
 
267
- // Resolve sandbox config early needed both for proxy env and command wrapping.
267
+ // Resolve sandbox config early - needed both for proxy env and command wrapping.
268
268
  const sandboxConfig =
269
269
  context.sandboxOverride != null
270
270
  ? { ...config.sandbox, enabled: context.sandboxOverride }
@@ -273,7 +273,7 @@ class ShellTool implements Tool {
273
273
  // Acquire proxy session if proxied mode is requested.
274
274
  // `getOrStartSession` serializes per-conversation so concurrent proxied
275
275
  // commands share a single session instead of each creating one.
276
- // Sessions are NOT stopped here the session manager's idle timer handles
276
+ // Sessions are NOT stopped here - the session manager's idle timer handles
277
277
  // cleanup after all commands finish (see resetIdleTimer / stopAllSessions).
278
278
  let proxyEnv: ProxyEnvVars | null = null;
279
279
 
@@ -291,7 +291,7 @@ class ShellTool implements Tool {
291
291
  } catch (err) {
292
292
  log.error({ err }, "Failed to start proxy session");
293
293
  return {
294
- content: `Error: failed to start proxy session ${
294
+ content: `Error: failed to start proxy session - ${
295
295
  err instanceof Error ? err.message : String(err)
296
296
  }`,
297
297
  isError: true,
@@ -385,7 +385,7 @@ class ShellTool implements Tool {
385
385
  resolve({
386
386
  content: `Error spawning command: ${err.message}${
387
387
  (err as NodeJS.ErrnoException).code === "ENOENT"
388
- ? ". The command was not found check that it is installed and in PATH."
388
+ ? ". The command was not found - check that it is installed and in PATH."
389
389
  : ""
390
390
  }`,
391
391
  isError: true,
@@ -82,7 +82,7 @@ export async function waitForInlineGrant(
82
82
  return { outcome: "aborted" };
83
83
  }
84
84
 
85
- // Check if the canonical request was rejected exit early without
85
+ // Check if the canonical request was rejected - exit early without
86
86
  // waiting for the full timeout.
87
87
  const request = getCanonicalGuardianRequest(escalationRequestId);
88
88
  if (request && request.status === "denied") {
@@ -98,7 +98,7 @@ export async function waitForInlineGrant(
98
98
  return { outcome: "denied", requestId: escalationRequestId };
99
99
  }
100
100
 
101
- // Try to consume the grant if the guardian approved, the canonical
101
+ // Try to consume the grant - if the guardian approved, the canonical
102
102
  // decision primitive will have minted a scoped grant by now.
103
103
  const grantResult = await consumeGrantForInvocation(consumeParams, {
104
104
  maxWaitMs: 0,
@@ -112,7 +112,7 @@ export async function waitForInlineGrant(
112
112
  grantId: grantResult.grant.id,
113
113
  elapsedMs: maxWait - (deadline - Date.now()),
114
114
  },
115
- "Grant found during inline wait tool execution proceeding",
115
+ "Grant found during inline wait - tool execution proceeding",
116
116
  );
117
117
  return { outcome: "granted", grant: { id: grantResult.grant.id } };
118
118
  }
@@ -125,16 +125,25 @@ export async function waitForInlineGrant(
125
125
  toolName: consumeParams.toolName,
126
126
  maxWaitMs: maxWait,
127
127
  },
128
- "Inline grant wait timed out no guardian decision within budget",
128
+ "Inline grant wait timed out - no guardian decision within budget",
129
129
  );
130
130
  return { outcome: "timeout", requestId: escalationRequestId };
131
131
  }
132
132
 
133
+ const UI_SURFACE_TOOLS = new Set(["ui_show", "ui_update", "ui_dismiss"]);
134
+
133
135
  function requiresGuardianApprovalForActor(
134
136
  toolName: string,
135
137
  input: Record<string, unknown>,
136
138
  executionTarget: ExecutionTarget,
137
139
  ): boolean {
140
+ // UI surface tools are passive, user-visible operations (cards, forms,
141
+ // tables). User input is voluntary and user-controlled — skip the guardian
142
+ // gate so they work during fresh onboarding before trust is established.
143
+ if (UI_SURFACE_TOOLS.has(toolName)) {
144
+ return false;
145
+ }
146
+
138
147
  // Side-effect tools always require guardian approval for untrusted actors.
139
148
  // Read-only host execution is also blocked because it can leak sensitive
140
149
  // local information (e.g. shell/file reads).
@@ -425,13 +434,13 @@ export class ToolApprovalHandler {
425
434
  executionTarget,
426
435
  grantId: grantResult.grant.id,
427
436
  },
428
- "Scoped grant consumed allowing untrusted actor tool invocation",
437
+ "Scoped grant consumed - allowing untrusted actor tool invocation",
429
438
  );
430
439
 
431
440
  return { allowed: true, tool, grantConsumed: true };
432
441
  }
433
442
 
434
- // Treat abort as a cancellation not a grant denial. This matches
443
+ // Treat abort as a cancellation - not a grant denial. This matches
435
444
  // the abort check at the top of checkPreExecutionGates so the caller
436
445
  // sees a consistent "Cancelled" result instead of a spurious
437
446
  // guardian_approval_required denial during voice barge-in.
@@ -458,12 +467,12 @@ export class ToolApprovalHandler {
458
467
  };
459
468
  }
460
469
 
461
- // No matching grant or race condition deny or wait inline.
470
+ // No matching grant or race condition - deny or wait inline.
462
471
  //
463
472
  // For verified non-guardian actors (trusted_contact) with sufficient
464
473
  // context, escalate to the guardian by creating a canonical
465
474
  // tool_grant_request. Then wait bounded for the grant to become
466
- // available this lets the tool call succeed inline after guardian
475
+ // available - this lets the tool call succeed inline after guardian
467
476
  // approval without the requester having to retry manually.
468
477
  //
469
478
  // Unverified actors remain fail-closed with no escalation or wait.
@@ -524,7 +533,7 @@ export class ToolApprovalHandler {
524
533
  grantId: waitResult.grant.id,
525
534
  escalationRequestId: escalation.requestId,
526
535
  },
527
- "Inline grant wait succeeded allowing trusted contact tool invocation",
536
+ "Inline grant wait succeeded - allowing trusted contact tool invocation",
528
537
  );
529
538
  return { allowed: true, tool, grantConsumed: true };
530
539
  }
@@ -589,7 +598,7 @@ export class ToolApprovalHandler {
589
598
  waitOutcome: waitResult.outcome,
590
599
  escalationRequestId: escalation.requestId,
591
600
  },
592
- "Inline grant wait ended without approval denying trusted contact tool invocation",
601
+ "Inline grant wait ended without approval - denying trusted contact tool invocation",
593
602
  );
594
603
  const durationMs = Date.now() - startTime;
595
604
  emitLifecycleEvent({
@@ -610,10 +619,10 @@ export class ToolApprovalHandler {
610
619
  result: { content: escalationMessage, isError: true },
611
620
  };
612
621
  }
613
- // escalation.failed fall through to generic denial.
622
+ // escalation.failed - fall through to generic denial.
614
623
  }
615
624
 
616
- // Unknown/unverified actors or escalation failures generic denial.
625
+ // Unknown/unverified actors or escalation failures - generic denial.
617
626
  const reason = guardianApprovalDeniedMessage(context.trustClass, name);
618
627
  log.warn(
619
628
  {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Declarative tool manifest single place to inspect what gets registered.
2
+ * Declarative tool manifest - single place to inspect what gets registered.
3
3
  *
4
4
  * Each entry describes HOW a tool (or group of tools) gets loaded and
5
5
  * registered. `initializeTools()` in `registry.ts` iterates this list
@@ -73,7 +73,7 @@ export const eagerModuleToolNames: string[] = [
73
73
  // a test registry reset) and tools that have always been explicit.
74
74
 
75
75
  export const explicitTools: Tool[] = [
76
- // Previously-eager tools kept here so initializeTools() can re-register
76
+ // Previously-eager tools - kept here so initializeTools() can re-register
77
77
  // them after __resetRegistryForTesting() clears the registry (ESM caching
78
78
  // prevents their side-effect registrations from re-running).
79
79
  shellTool,
@@ -99,7 +99,7 @@ export const explicitTools: Tool[] = [
99
99
  // This list is intentionally separate from `explicitTools` so that
100
100
  // initializeTools() in registry.ts can conditionally include them.
101
101
 
102
- /** All CES tools stable references for the manifest snapshot. */
102
+ /** All CES tools - stable references for the manifest snapshot. */
103
103
  export const cesTools: Tool[] = [
104
104
  makeAuthenticatedRequestTool,
105
105
  runAuthenticatedCommandTool,
@@ -123,7 +123,7 @@ export function getCesToolsIfEnabled(): Tool[] {
123
123
  );
124
124
  }
125
125
  } catch {
126
- // Config not yet loaded (e.g. during test setup) CES tools stay off.
126
+ // Config not yet loaded (e.g. during test setup) - CES tools stay off.
127
127
  }
128
128
  return [];
129
129
  }
@@ -114,7 +114,7 @@ export interface ToolContext {
114
114
  sandboxOverride?: boolean;
115
115
  /** Optional callback for tool lifecycle events (start/prompt/deny/execute/error/secret_detected). */
116
116
  onToolLifecycleEvent?: ToolLifecycleEventHandler;
117
- /** Optional resolver for proxy tools delegates execution to an external client. */
117
+ /** Optional resolver for proxy tools - delegates execution to an external client. */
118
118
  proxyToolResolver?: ProxyToolResolver;
119
119
  /** When set, only tools in this set may execute. Tools outside the set are blocked with an error. */
120
120
  allowedToolNames?: Set<string>;
@@ -147,7 +147,7 @@ export interface ToolContext {
147
147
  forcePromptSideEffects?: boolean;
148
148
  /**
149
149
  * When true, the tool requires a fresh interactive approval for every
150
- * invocation no cached grants, temporary overrides, persistent
150
+ * invocation - no cached grants, temporary overrides, persistent
151
151
  * "Always Allow" rules, or non-interactive auto-approve shortcuts may
152
152
  * bypass the prompt. This flag is independently sufficient: it
153
153
  * promotes allow → prompt decisions on its own and suppresses
@@ -231,7 +231,7 @@ export interface ToolExecutionResult {
231
231
  }
232
232
 
233
233
  // ---------------------------------------------------------------------------
234
- // Proxy approval types local definitions for the outbound-proxy contract.
234
+ // Proxy approval types - local definitions for the outbound-proxy contract.
235
235
  // The proxy service owns the canonical shapes; these are the assistant's
236
236
  // minimal view of the approval callback interface.
237
237
  // ---------------------------------------------------------------------------
@@ -28,43 +28,15 @@ function proxyExecute(): Promise<ToolExecutionResult> {
28
28
  export const uiShowTool: Tool = {
29
29
  name: "ui_show",
30
30
  description:
31
- 'Show structured data or UI to the user. Use for displaying weather, flights, stock prices, quick tables, cards, lists, forms, or any temporary data visualization. Use display: "inline" (default) to embed in chat, or "panel" for a floating window. For long-form writing use the document skill instead; for interactive apps use the app-builder skill instead.\n\n' +
32
- "Supported surface types:\n" +
33
- "- card: Informational card with title, subtitle, body text, and optional metadata key-value pairs. " +
34
- "Cards support an optional template field for specialized native rendering. " +
35
- "data shape: { title: string, subtitle?: string, body: string, metadata?: Array<{ label: string, value: string }>, template?: string, templateData?: object }\n" +
36
- ' Template "weather_forecast": renders an Apple Weather-style forecast widget. ' +
37
- 'templateData shape: { location: string, currentTemp: number, feelsLike: number, unit: "F"|"C", condition: string, humidity: number, windSpeed: number, windDirection: string, ' +
38
- "hourly: Array<{ time: string, icon: string (SF Symbol name), temp: number }>, " +
39
- "forecast: Array<{ day: string, icon: string (SF Symbol name), low: number, high: number, precip: number|null, condition: string }> }\n" +
40
- ' Template "task_progress": renders a live-updating task progress widget showing structured step-by-step progress. ' +
41
- 'templateData shape: { title: string, status: "in_progress"|"completed"|"failed", ' +
42
- 'steps: Array<{ label: string, status: "pending"|"in_progress"|"completed"|"failed", detail?: string }> }\n' +
43
- "- table: Data table with columns, selectable rows, and action buttons. " +
44
- 'data shape: { columns: Array<{ id: string, label: string, width?: number }>, rows: Array<{ id: string, cells: Record<string, string | { text: string, icon?: string, iconColor?: "success"|"warning"|"error"|"muted" }>, selectable?: boolean, selected?: boolean }>, selectionMode?: "none"|"single"|"multiple", caption?: string }. ' +
45
- "Cell values can be plain strings or rich objects with icon (SF Symbol name) and iconColor. " +
46
- "Column width is in points — use it for narrow columns (e.g. counts, short labels) so flexible columns get more space. Omit width for columns that should expand.\n" +
47
- "- form: Input form with typed fields. " +
48
- 'data shape: { description?: string, fields: Array<{ id: string, type: "text"|"textarea"|"select"|"toggle"|"number"|"password", label: string, placeholder?: string, required?: boolean, defaultValue?: string|number|boolean, options?: Array<{ label: string, value: string }> }>, submitLabel?: string }. ' +
49
- "For multi-page forms, use pages array instead of top-level fields: { pages: [{ id: string, title: string, description?: string, fields: [...] }], pageLabels?: { next?: string, back?: string, submit?: string }, submitLabel?: string }\n" +
50
- "- list: Selectable list of items. " +
51
- 'data shape: { items: Array<{ id: string, title: string, subtitle?: string, icon?: string, selected?: boolean }>, selectionMode: "single"|"multiple"|"none" }\n' +
52
- "- confirmation: Yes/no confirmation dialog. " +
53
- "data shape: { message: string, detail?: string, confirmLabel?: string, confirmedLabel?: string, cancelLabel?: string, destructive?: boolean }\n" +
54
- "- dynamic_page: Custom HTML page rendered in a sandboxed container. " +
55
- "data shape: { html: string, width?: number, height?: number, preview?: { title: string, subtitle?: string, description?: string, icon?: string (emoji), metrics?: Array<{ label: string, value: string }> } }. " +
56
- 'When preview is provided, a compact preview card is shown inline in chat with the title, subtitle, description, metric pills, and a "View Output" button that opens the full page.\n' +
57
- "- file_upload: File upload dialog where the user can drag-and-drop or browse for files. " +
58
- "data shape: { prompt: string, acceptedTypes?: string[], maxFiles?: number }\n\n" +
59
- "Action payload conventions:\n" +
60
- "- Multi-select tables: use `window.vellum.sendAction(actionId, { selectedIds: [...] })` to send selected row IDs\n" +
61
- "- Bulk actions: include `selectedRows` array with full row data for context\n\n" +
62
- "Presenting choices: When the user needs to make a choice or provide structured input, prefer interactive surfaces over plain text. " +
63
- "Use list (2-8 options, single select), form (structured input with typed fields), confirmation (destructive/important actions), or table (data review with selectable rows).\n\n" +
64
- "Tool chaining: After gathering data via tools (web search, browser, APIs), synthesize results into a visual output.\n\n" +
65
- 'Task progress for multi-step workflows: Create a card with template "task_progress" and templateData containing steps. ' +
66
- "As each step completes, call ui_update to patch data.templateData (not top-level fields). " +
67
- 'Set templateData.status to "completed" or "failed" when done.',
31
+ "Show structured data or UI to the user. For long-form writing use the document skill; for interactive apps use the app-builder skill.\n\n" +
32
+ "Surface types (data shapes):\n" +
33
+ "- card: { title, subtitle?, body, metadata?: [{ label, value }], template?, templateData? }. Templates: \"weather_forecast\" (native weather widget), \"task_progress\" (live step tracker - update via ui_update on data.templateData; shape: { title, status: \"in_progress\"|\"completed\"|\"failed\", steps: [{ label, status: \"pending\"|\"in_progress\"|\"completed\"|\"failed\", detail? }] })\n" +
34
+ '- table: { columns: [{ id, label, width? }], rows: [{ id, cells: Record<id, string | { text, icon?, iconColor?: "success"|"warning"|"error"|"muted" }>, selectable?, selected? }], selectionMode?: "none"|"single"|"multiple", caption? }\n' +
35
+ '- form: { description?, fields: [{ id, type: "text"|"textarea"|"select"|"toggle"|"number"|"password", label, placeholder?, required?, defaultValue?, options?: [{ label, value }] }], submitLabel? }. Multi-page: { pages: [{ id, title, description?, fields }], pageLabels?: { next?, back?, submit? }, submitLabel? }\n' +
36
+ '- list: { items: [{ id, title, subtitle?, icon?, selected? }], selectionMode: "single"|"multiple"|"none" }\n' +
37
+ "- confirmation: { message, detail?, confirmLabel?, confirmedLabel?, cancelLabel?, destructive? }\n" +
38
+ "- dynamic_page: { html, width?, height?, preview?: { title, subtitle?, description?, icon?, metrics?: [{ label, value }] } }\n" +
39
+ "- file_upload: { prompt, acceptedTypes?, maxFiles? }",
68
40
  category: "ui-surface",
69
41
  defaultRiskLevel: RiskLevel.Low,
70
42
  executionMode: "proxy",