@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
@@ -52,13 +52,13 @@ export interface BrowserFillRequest {
52
52
  toolName: string;
53
53
  domain?: string;
54
54
  /**
55
- * Opaque fill callback the broker calls this with the plaintext value internally.
55
+ * Opaque fill callback - the broker calls this with the plaintext value internally.
56
56
  * The caller provides the fill function but never receives the secret value.
57
57
  */
58
58
  fill: (value: string) => Promise<void>;
59
59
  }
60
60
 
61
- /** Result of a broker-mediated browser fill contains only metadata, never plaintext. */
61
+ /** Result of a broker-mediated browser fill - contains only metadata, never plaintext. */
62
62
  export interface BrowserFillResult {
63
63
  success: boolean;
64
64
  reason?: string;
@@ -70,13 +70,13 @@ export interface ServerUseRequest<T> {
70
70
  field: string;
71
71
  toolName: string;
72
72
  /**
73
- * Opaque callback the broker calls this with the plaintext value internally.
73
+ * Opaque callback - the broker calls this with the plaintext value internally.
74
74
  * The caller provides the function but never receives the secret value directly.
75
75
  */
76
76
  execute: (value: string) => Promise<T>;
77
77
  }
78
78
 
79
- /** Result of a broker-mediated server-side credential use contains the callback result, never plaintext. */
79
+ /** Result of a broker-mediated server-side credential use - contains the callback result, never plaintext. */
80
80
  export interface ServerUseResult<T> {
81
81
  success: boolean;
82
82
  result?: T;
@@ -89,7 +89,7 @@ export interface ServerUseByIdRequest {
89
89
  requestingTool: string;
90
90
  }
91
91
 
92
- /** Successful by-id lookup result metadata + injection templates, never plaintext. */
92
+ /** Successful by-id lookup result - metadata + injection templates, never plaintext. */
93
93
  export interface ServerUseByIdSuccess {
94
94
  success: true;
95
95
  credentialId: string;
@@ -68,7 +68,7 @@ export class CredentialBroker {
68
68
  };
69
69
  }
70
70
 
71
- // Tool policy enforcement deny if tool is not in the credential's allowed list
71
+ // Tool policy enforcement - deny if tool is not in the credential's allowed list
72
72
  if (!isToolAllowed(request.toolName, metadata.allowedTools)) {
73
73
  const tools = metadata.allowedTools ?? [];
74
74
  return {
@@ -76,7 +76,7 @@ export class CredentialBroker {
76
76
  reason:
77
77
  `Tool "${request.toolName}" is not allowed to use credential ${request.service}/${request.field}. ` +
78
78
  (tools.length === 0
79
- ? "No tools are currently allowed update the credential with allowed_tools via credential_store."
79
+ ? "No tools are currently allowed - update the credential with allowed_tools via credential_store."
80
80
  : `Allowed tools: ${tools.join(", ")}.`),
81
81
  };
82
82
  }
@@ -125,7 +125,7 @@ export class CredentialBroker {
125
125
 
126
126
  token.consumed = true;
127
127
  const storageKey = credentialKey(token.service, token.field);
128
- // Check for transient value first (one-time send) consume and return the value
128
+ // Check for transient value first (one-time send) - consume and return the value
129
129
  // directly since transient values are never persisted to secure storage.
130
130
  const transient = this.transientValues.get(storageKey);
131
131
  if (transient !== undefined) {
@@ -166,7 +166,7 @@ export class CredentialBroker {
166
166
  * Fill a browser field using a credential without exposing plaintext to the caller.
167
167
  *
168
168
  * The broker resolves the credential, reads the secret internally, and passes it
169
- * to the provided fill callback. The return value contains only metadata the
169
+ * to the provided fill callback. The return value contains only metadata - the
170
170
  * plaintext never leaves this method's scope.
171
171
  */
172
172
  async browserFill(request: BrowserFillRequest): Promise<BrowserFillResult> {
@@ -178,7 +178,7 @@ export class CredentialBroker {
178
178
  };
179
179
  }
180
180
 
181
- // Tool policy enforcement deny if tool is not in the credential's allowed list
181
+ // Tool policy enforcement - deny if tool is not in the credential's allowed list
182
182
  if (!isToolAllowed(request.toolName, metadata.allowedTools)) {
183
183
  const tools = metadata.allowedTools ?? [];
184
184
  return {
@@ -186,12 +186,12 @@ export class CredentialBroker {
186
186
  reason:
187
187
  `Tool "${request.toolName}" is not allowed to use credential ${request.service}/${request.field}. ` +
188
188
  (tools.length === 0
189
- ? "No tools are currently allowed update the credential with allowed_tools via credential_store."
189
+ ? "No tools are currently allowed - update the credential with allowed_tools via credential_store."
190
190
  : `Allowed tools: ${tools.join(", ")}.`),
191
191
  };
192
192
  }
193
193
 
194
- // Domain policy enforcement deny if the page domain is not in the credential's allowed list
194
+ // Domain policy enforcement - deny if the page domain is not in the credential's allowed list
195
195
  const browserDomains = metadata.allowedDomains ?? [];
196
196
  if (browserDomains.length > 0) {
197
197
  if (!request.domain) {
@@ -228,7 +228,7 @@ export class CredentialBroker {
228
228
  try {
229
229
  await request.fill(value);
230
230
  // Only discard the transient value after a successful fill, and only if
231
- // the map still holds the same reference a concurrent injectTransient()
231
+ // the map still holds the same reference - a concurrent injectTransient()
232
232
  // call during the async fill could have replaced it with a new value.
233
233
  if (
234
234
  transient !== undefined &&
@@ -246,7 +246,7 @@ export class CredentialBroker {
246
246
  );
247
247
  return { success: true };
248
248
  } catch (err) {
249
- // Log the raw error for debugging but never return it the callback
249
+ // Log the raw error for debugging but never return it - the callback
250
250
  // error text may embed the credential value, leaking plaintext outside
251
251
  // the broker's trust boundary.
252
252
  log.error(
@@ -262,7 +262,7 @@ export class CredentialBroker {
262
262
  *
263
263
  * Like browserFill, the broker reads the secret internally and passes it
264
264
  * to the provided callback. The return value contains only the callback's
265
- * result the plaintext never leaves this method's scope.
265
+ * result - the plaintext never leaves this method's scope.
266
266
  */
267
267
  async serverUse<T>(
268
268
  request: ServerUseRequest<T>,
@@ -282,12 +282,12 @@ export class CredentialBroker {
282
282
  reason:
283
283
  `Tool "${request.toolName}" is not allowed to use credential ${request.service}/${request.field}. ` +
284
284
  (tools.length === 0
285
- ? "No tools are currently allowed update the credential with allowed_tools via credential_store."
285
+ ? "No tools are currently allowed - update the credential with allowed_tools via credential_store."
286
286
  : `Allowed tools: ${tools.join(", ")}.`),
287
287
  };
288
288
  }
289
289
 
290
- // Domain policy enforcement credentials with domain restrictions are
290
+ // Domain policy enforcement - credentials with domain restrictions are
291
291
  // scoped to browser use on those domains and cannot be used server-side.
292
292
  const serverDomains = metadata.allowedDomains ?? [];
293
293
  if (serverDomains.length > 0) {
@@ -341,7 +341,7 @@ export class CredentialBroker {
341
341
  *
342
342
  * Returns metadata and injection templates so the proxy knows how to
343
343
  * inject the credential into outbound requests. The secret value is
344
- * never included in the result the proxy reads it separately via
344
+ * never included in the result - the proxy reads it separately via
345
345
  * the secure key backend at injection time.
346
346
  */
347
347
  async serverUseById(
@@ -365,12 +365,12 @@ export class CredentialBroker {
365
365
  reason:
366
366
  `Tool "${request.requestingTool}" is not allowed to use credential ${metadata.service}/${metadata.field}. ` +
367
367
  (tools.length === 0
368
- ? "No tools are currently allowed update the credential with allowed_tools via credential_store."
368
+ ? "No tools are currently allowed - update the credential with allowed_tools via credential_store."
369
369
  : `Allowed tools: ${tools.join(", ")}.`),
370
370
  };
371
371
  }
372
372
 
373
- // Domain policy enforcement credentials with domain restrictions are
373
+ // Domain policy enforcement - credentials with domain restrictions are
374
374
  // scoped to browser use on those domains and cannot be used server-side.
375
375
  const domains = metadata.allowedDomains ?? [];
376
376
  if (domains.length > 0) {
@@ -22,7 +22,7 @@ import type { CredentialInjectionTemplate } from "./policy-types.js";
22
22
  /**
23
23
  * CredentialMetadata extends the shared StaticCredentialRecord with
24
24
  * assistant-specific injection template fields (composeWith, valueTransform).
25
- * Structurally compatible the shared store persists all fields as-is.
25
+ * Structurally compatible - the shared store persists all fields as-is.
26
26
  */
27
27
  export interface CredentialMetadata {
28
28
  credentialId: string;
@@ -60,7 +60,7 @@ function getStore(): StaticCredentialMetadataStore {
60
60
  }
61
61
 
62
62
  // ---------------------------------------------------------------------------
63
- // Public API unchanged signatures, delegates to shared store
63
+ // Public API - unchanged signatures, delegates to shared store
64
64
  // ---------------------------------------------------------------------------
65
65
 
66
66
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Credential resolver maps between opaque IDs, service/field pairs,
2
+ * Credential resolver - maps between opaque IDs, service/field pairs,
3
3
  * and storage locators.
4
4
  *
5
5
  * This decouples external credential references from the underlying
@@ -27,7 +27,7 @@ export interface CredentialSelectionResult {
27
27
  }
28
28
 
29
29
  /**
30
- * Tier scores higher-priority criteria use larger values so they
30
+ * Tier scores - higher-priority criteria use larger values so they
31
31
  * dominate over lower-priority ones regardless of accumulation.
32
32
  */
33
33
  const SCORE_EXACT_HOST = 100;
@@ -13,7 +13,7 @@
13
13
  * @returns true if the tool is explicitly listed in allowedTools
14
14
  *
15
15
  * Semantics:
16
- * 1. Explicit allowlist tool must be listed by exact name
16
+ * 1. Explicit allowlist - tool must be listed by exact name
17
17
  * 2. No wildcard support in v1
18
18
  * 3. Fail-closed on empty or missing list
19
19
  */
@@ -1,5 +1,10 @@
1
1
  import { getConfig } from "../../config/loader.js";
2
+ import {
3
+ setSlackChannelConfig,
4
+ type SlackChannelConfigResult,
5
+ } from "../../daemon/handlers/config-slack-channel.js";
2
6
  import { orchestrateOAuthConnect } from "../../oauth/connect-orchestrator.js";
7
+ import { syncManualTokenConnection } from "../../oauth/manual-token-connection.js";
3
8
  import {
4
9
  disconnectOAuthProvider,
5
10
  getAppByProviderAndClientId,
@@ -42,6 +47,39 @@ import { toPolicyFromInput, validatePolicyInput } from "./policy-validate.js";
42
47
 
43
48
  const log = getLogger("credential-vault");
44
49
 
50
+ function isSlackChannelCredential(
51
+ service: string,
52
+ field: string,
53
+ ): field is "bot_token" | "app_token" {
54
+ return (
55
+ service === "slack_channel" &&
56
+ (field === "bot_token" || field === "app_token")
57
+ );
58
+ }
59
+
60
+ async function storeSlackChannelCredential(
61
+ field: "bot_token" | "app_token",
62
+ value: string,
63
+ ): Promise<SlackChannelConfigResult> {
64
+ return field === "bot_token"
65
+ ? setSlackChannelConfig(value, undefined)
66
+ : setSlackChannelConfig(undefined, value);
67
+ }
68
+
69
+ function formatSlackChannelStatus(
70
+ result: SlackChannelConfigResult,
71
+ ): string {
72
+ if (result.connected) {
73
+ const teamLabel = result.teamName ?? "Slack";
74
+ const botLabel = result.botUsername ? ` (@${result.botUsername})` : "";
75
+ return ` Slack channel connected to ${teamLabel}${botLabel}.`;
76
+ }
77
+ if (result.warning) {
78
+ return ` ${result.warning}`;
79
+ }
80
+ return "";
81
+ }
82
+
45
83
  class CredentialStoreTool implements Tool {
46
84
  name = "credential_store";
47
85
  description =
@@ -67,7 +105,7 @@ class CredentialStoreTool implements Tool {
67
105
  "describe",
68
106
  ],
69
107
  description:
70
- 'The operation to perform. Use "prompt" to ask the user for a secret via secure UI the value never enters the conversation. Use "oauth2_connect" to connect an OAuth2 service via browser authorization. Use "describe" to get setup metadata for a well-known OAuth service (dashboard URL, scopes, redirect URI, etc.). For well-known services (gmail, slack), only the service name is required endpoints, scopes, and stored client credentials are resolved automatically.',
108
+ 'The operation to perform. Use "prompt" to ask the user for a secret via secure UI - the value never enters the conversation. Use "oauth2_connect" to connect an OAuth2 service via browser authorization. Use "describe" to get setup metadata for a well-known OAuth service (dashboard URL, scopes, redirect URI, etc.). For well-known services (gmail, slack), only the service name is required - endpoints, scopes, and stored client credentials are resolved automatically.',
71
109
  },
72
110
  service: {
73
111
  type: "string",
@@ -322,13 +360,27 @@ class CredentialStoreTool implements Tool {
322
360
  };
323
361
  }
324
362
 
325
- const key = credentialKey(service, field);
326
- const ok = await setSecureKeyAsync(key, value);
327
- if (!ok) {
328
- return {
329
- content: "Error: failed to store credential",
330
- isError: true,
331
- };
363
+ let slackChannelResult: SlackChannelConfigResult | undefined;
364
+ if (isSlackChannelCredential(service, field)) {
365
+ slackChannelResult = await storeSlackChannelCredential(field, value);
366
+ if (!slackChannelResult.success) {
367
+ return {
368
+ content: `Error: ${
369
+ slackChannelResult.error ??
370
+ "failed to configure Slack channel"
371
+ }`,
372
+ isError: true,
373
+ };
374
+ }
375
+ } else {
376
+ const key = credentialKey(service, field);
377
+ const ok = await setSecureKeyAsync(key, value);
378
+ if (!ok) {
379
+ return {
380
+ content: "Error: failed to store credential",
381
+ isError: true,
382
+ };
383
+ }
332
384
  }
333
385
  try {
334
386
  upsertCredentialMetadata(service, field, {
@@ -344,12 +396,19 @@ class CredentialStoreTool implements Tool {
344
396
  "metadata write failed after storing credential",
345
397
  );
346
398
  }
399
+ if (!isSlackChannelCredential(service, field)) {
400
+ await syncManualTokenConnection(service);
401
+ }
347
402
  const metadata = getCredentialMetadata(service, field);
348
403
  const credIdSuffix = metadata
349
404
  ? ` (credential_id: ${metadata.credentialId})`
350
405
  : "";
351
406
  return {
352
- content: `Stored credential for ${service}/${field}.${credIdSuffix}`,
407
+ content: `Stored credential for ${service}/${field}.${credIdSuffix}${
408
+ slackChannelResult
409
+ ? formatSlackChannelStatus(slackChannelResult)
410
+ : ""
411
+ }`,
353
412
  isError: false,
354
413
  };
355
414
  }
@@ -477,7 +536,7 @@ class CredentialStoreTool implements Tool {
477
536
  if (oauthResult === "error") {
478
537
  log.warn(
479
538
  { service },
480
- "OAuth disconnect failed after removing credential secure key deletion error",
539
+ "OAuth disconnect failed after removing credential - secure key deletion error",
481
540
  );
482
541
  }
483
542
  } catch (err) {
@@ -653,6 +712,13 @@ class CredentialStoreTool implements Tool {
653
712
 
654
713
  // Handle one-time send delivery: inject into context without persisting
655
714
  if (result.delivery === "transient_send") {
715
+ if (isSlackChannelCredential(service, field)) {
716
+ return {
717
+ content:
718
+ "Error: Slack channel credentials must be saved to secure storage. Re-run the secure prompt and choose to store the token.",
719
+ isError: true,
720
+ };
721
+ }
656
722
  const config = getConfig();
657
723
  if (!config.secretDetection.allowOneTimeSend) {
658
724
  log.warn(
@@ -666,7 +732,7 @@ class CredentialStoreTool implements Tool {
666
732
  };
667
733
  }
668
734
  // Ensure metadata exists so broker policy checks work, but don't
669
- // overwrite an existing record a stored credential's policy should
735
+ // overwrite an existing record - a stored credential's policy should
670
736
  // not be silently replaced by the transient prompt's policy.
671
737
  // Metadata must be written before injecting the transient value so
672
738
  // we never leave a dangling value that fails policy checks.
@@ -703,14 +769,31 @@ class CredentialStoreTool implements Tool {
703
769
  };
704
770
  }
705
771
 
706
- // Default: persist to keychain
707
- const key = credentialKey(service, field);
708
- const ok = await setSecureKeyAsync(key, result.value);
709
- if (!ok) {
710
- return {
711
- content: "Error: failed to store credential",
712
- isError: true,
713
- };
772
+ let slackChannelResult: SlackChannelConfigResult | undefined;
773
+ if (isSlackChannelCredential(service, field)) {
774
+ slackChannelResult = await storeSlackChannelCredential(
775
+ field,
776
+ result.value,
777
+ );
778
+ if (!slackChannelResult.success) {
779
+ return {
780
+ content: `Error: ${
781
+ slackChannelResult.error ??
782
+ "failed to configure Slack channel"
783
+ }`,
784
+ isError: true,
785
+ };
786
+ }
787
+ } else {
788
+ // Default: persist to keychain
789
+ const key = credentialKey(service, field);
790
+ const ok = await setSecureKeyAsync(key, result.value);
791
+ if (!ok) {
792
+ return {
793
+ content: "Error: failed to store credential",
794
+ isError: true,
795
+ };
796
+ }
714
797
  }
715
798
  try {
716
799
  upsertCredentialMetadata(service, field, {
@@ -725,12 +808,19 @@ class CredentialStoreTool implements Tool {
725
808
  "metadata write failed after storing credential",
726
809
  );
727
810
  }
811
+ if (!isSlackChannelCredential(service, field)) {
812
+ await syncManualTokenConnection(service);
813
+ }
728
814
  const promptMeta = getCredentialMetadata(service, field);
729
815
  const promptCredIdSuffix = promptMeta
730
816
  ? ` (credential_id: ${promptMeta.credentialId})`
731
817
  : "";
732
818
  return {
733
- content: `Credential stored for ${service}/${field}.${promptCredIdSuffix}`,
819
+ content: `Credential stored for ${service}/${field}.${promptCredIdSuffix}${
820
+ slackChannelResult
821
+ ? formatSlackChannelStatus(slackChannelResult)
822
+ : ""
823
+ }`,
734
824
  isError: false,
735
825
  };
736
826
  }
@@ -754,7 +844,7 @@ class CredentialStoreTool implements Tool {
754
844
  // Resolve client_id and client_secret.
755
845
  // Priority:
756
846
  // 1. Explicit input from the caller
757
- // 2. oauth-store DB when clientId is already known, look up the
847
+ // 2. oauth-store DB - when clientId is already known, look up the
758
848
  // matching app so the secret comes from the same app. Only fall
759
849
  // back to the most-recent-app heuristic when clientId is unknown.
760
850
  let clientId = input.client_id as string | undefined;
@@ -791,7 +881,7 @@ class CredentialStoreTool implements Tool {
791
881
  isError: true,
792
882
  };
793
883
 
794
- // Fail early when client_secret is required but missing guide the
884
+ // Fail early when client_secret is required but missing - guide the
795
885
  // agent to collect it from the user rather than letting it improvise
796
886
  // browser-automation workarounds that inevitably fail.
797
887
  const requiresSecret =
@@ -808,7 +898,7 @@ class CredentialStoreTool implements Tool {
808
898
  };
809
899
  }
810
900
 
811
- // Delegate to the shared orchestrator it resolves authUrl, tokenUrl,
901
+ // Delegate to the shared orchestrator - it resolves authUrl, tokenUrl,
812
902
  // extraParams, userinfoUrl, and tokenEndpointAuthMethod from the DB.
813
903
  const result = await orchestrateOAuthConnect({
814
904
  service: rawService,
@@ -909,7 +999,7 @@ class CredentialStoreTool implements Tool {
909
999
  redirectUri = `http://localhost:${loopbackPort}/oauth/callback`;
910
1000
  } else if (transport === "loopback") {
911
1001
  redirectUri =
912
- "(automatic no redirect URI needed, uses random localhost port)";
1002
+ "(automatic - no redirect URI needed, uses random localhost port)";
913
1003
  } else {
914
1004
  // Try to compute the actual URL from config/env
915
1005
  try {
@@ -920,7 +1010,7 @@ class CredentialStoreTool implements Tool {
920
1010
  redirectUri = `${baseUrl}/webhooks/oauth/callback`;
921
1011
  } catch {
922
1012
  redirectUri =
923
- "(requires ingress.publicBaseUrl not currently configured)";
1013
+ "(requires ingress.publicBaseUrl - not currently configured)";
924
1014
  }
925
1015
  }
926
1016
 
@@ -11,12 +11,12 @@ export function resolveExecutionTarget(
11
11
  manifestOverride?: ManifestOverride,
12
12
  ): ExecutionTarget {
13
13
  const tool = getTool(toolName);
14
- // Manifest-declared execution target is authoritative check it first so
14
+ // Manifest-declared execution target is authoritative - check it first so
15
15
  // skill tools with host_/computer_use_ prefixes aren't mis-classified.
16
16
  if (tool?.executionTarget) {
17
17
  return tool.executionTarget;
18
18
  }
19
- // Check the tool's executionMode metadata proxy tools run on the connected
19
+ // Check the tool's executionMode metadata - proxy tools run on the connected
20
20
  // client (host), not inside the sandbox.
21
21
  if (tool?.executionMode === "proxy") {
22
22
  return "host";
@@ -88,7 +88,7 @@ export class ToolExecutor {
88
88
  // whether a scoped grant was consumed. Previously this was nested
89
89
  // inside the `!grantConsumed` block, meaning untrusted host_bash
90
90
  // calls that arrived with a consumed guardian-approval grant would
91
- // skip this assignment entirely defeating the lockdown.
91
+ // skip this assignment entirely - defeating the lockdown.
92
92
  if (
93
93
  name === "host_bash" &&
94
94
  isCesShellLockdownEnabled(getConfig()) &&
@@ -98,7 +98,7 @@ export class ToolExecutor {
98
98
  }
99
99
 
100
100
  // Secure command tool installation always requires fresh per-invocation
101
- // approval no persistent grants. This is unconditional (not gated on
101
+ // approval - no persistent grants. This is unconditional (not gated on
102
102
  // CES lockdown or trust class) because installing secure tools is
103
103
  // inherently high-impact.
104
104
  if (name === "manage_secure_command_tool") {
@@ -106,11 +106,11 @@ export class ToolExecutor {
106
106
  context.requireFreshApproval = true;
107
107
  }
108
108
 
109
- // A consumed scoped grant is a complete authorization skip the
109
+ // A consumed scoped grant is a complete authorization - skip the
110
110
  // interactive permission/prompt flow so non-interactive sessions
111
111
  // don't auto-deny prompt-gated tools and burn the one-time grant.
112
112
  // Exception: requireFreshApproval tools always go through the
113
- // permission check even when a grant was consumed the grant does
113
+ // permission check even when a grant was consumed - the grant does
114
114
  // not substitute for an interactive human review.
115
115
  if (!gateResult.grantConsumed || context.requireFreshApproval) {
116
116
  // Check permissions via the extracted PermissionChecker
@@ -164,7 +164,7 @@ export class ToolExecutor {
164
164
  return { content: msg, isError: true };
165
165
  }
166
166
 
167
- // Execute the tool proxy tools delegate to an external resolver
167
+ // Execute the tool - proxy tools delegate to an external resolver
168
168
  let execResult: ToolExecutionResult;
169
169
  let toolTimeoutMs: number;
170
170
  if (name === "bash" || name === "host_bash") {
@@ -276,7 +276,7 @@ export class ToolExecutor {
276
276
  grantId: bridgeResult.grantId,
277
277
  conversationId: context.conversationId,
278
278
  },
279
- "CES approval granted retrying tool invocation with grantId",
279
+ "CES approval granted - retrying tool invocation with grantId",
280
280
  );
281
281
 
282
282
  if (tool.executionMode === "proxy") {
@@ -579,7 +579,7 @@ function computePreviewDiff(
579
579
  };
580
580
  }
581
581
  } catch {
582
- // Preview is best-effort don't block the prompt on errors
582
+ // Preview is best-effort - don't block the prompt on errors
583
583
  }
584
584
  return undefined;
585
585
  }
@@ -9,9 +9,9 @@ import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
9
9
  class FileEditTool implements Tool {
10
10
  name = "file_edit";
11
11
  description =
12
- "Replace an exact string in a file with a new string. Use this for surgical edits instead of rewriting entire files.";
12
+ "Replace an exact string in a file with a new string. Use this for surgical edits instead of rewriting entire files. To delete a file, use bash with rm instead.";
13
13
  category = "filesystem";
14
- defaultRiskLevel = RiskLevel.Medium;
14
+ defaultRiskLevel = RiskLevel.Low;
15
15
 
16
16
  getDefinition(): ToolDefinition {
17
17
  return {
@@ -14,7 +14,7 @@ import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
14
14
  class FileReadTool implements Tool {
15
15
  name = "file_read";
16
16
  description =
17
- "Read the contents of a file. For image files (JPEG, PNG, GIF, WebP), returns the image for visual analysis.";
17
+ "Read the contents of a file. For image files (JPEG, PNG, GIF, WebP), returns the image for visual analysis. Always use this tool (not host_file_read) for workspace files under .vellum.";
18
18
  category = "filesystem";
19
19
  defaultRiskLevel = RiskLevel.Low;
20
20
 
@@ -10,7 +10,7 @@ class FileWriteTool implements Tool {
10
10
  name = "file_write";
11
11
  description = "Write content to a file, creating it if it does not exist";
12
12
  category = "filesystem";
13
- defaultRiskLevel = RiskLevel.Medium;
13
+ defaultRiskLevel = RiskLevel.Low;
14
14
 
15
15
  getDefinition(): ToolDefinition {
16
16
  return {
@@ -7,7 +7,8 @@ import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
7
7
 
8
8
  class HostFileEditTool implements Tool {
9
9
  name = "host_file_edit";
10
- description = "Replace exact text in a host filesystem file with new text";
10
+ description =
11
+ "Replace exact text in a host filesystem file with new text. Not for workspace files under .vellum (use file_edit instead).";
11
12
  category = "host-filesystem";
12
13
  defaultRiskLevel = RiskLevel.Medium;
13
14
 
@@ -6,7 +6,8 @@ import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
6
6
 
7
7
  class HostFileReadTool implements Tool {
8
8
  name = "host_file_read";
9
- description = "Read the contents of a file on the host filesystem";
9
+ description =
10
+ "Read the contents of a file on the host filesystem. Not for workspace files under .vellum (use file_read instead).";
10
11
  category = "host-filesystem";
11
12
  defaultRiskLevel = RiskLevel.Medium;
12
13
 
@@ -8,7 +8,7 @@ import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
8
8
  class HostFileWriteTool implements Tool {
9
9
  name = "host_file_write";
10
10
  description =
11
- "Write content to a file on the host filesystem, creating it if it does not exist";
11
+ "Write content to a file on the host filesystem, creating it if it does not exist. Not for workspace files under .vellum (use file_write instead).";
12
12
  category = "host-filesystem";
13
13
  defaultRiskLevel = RiskLevel.Medium;
14
14