@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
@@ -42,9 +42,13 @@ export function isConversationFailed(conversationId: string): boolean {
42
42
  export function invalidateAssistantInferredItemsForConversation(
43
43
  conversationId: string,
44
44
  ): number {
45
- // Cancel pending extract_items jobs for this conversation's messages
45
+ // Cancel pending extraction jobs for this conversation's messages
46
46
  // so the worker never processes them. Jobs already running will be
47
47
  // caught by the isConversationFailed check in the extraction handler.
48
+ // NOTE: Only extract_items jobs are cancelled here — not embed_item or
49
+ // other job types. Multi-sourced items may still be valid (corroborated
50
+ // by other conversations), and their embedding jobs must not be killed.
51
+ // The broader cancelPendingJobsForConversation is used by the wipe path.
48
52
  cancelPendingExtractionJobsForConversation(conversationId);
49
53
 
50
54
  const affected = rawRun(
@@ -94,9 +98,95 @@ export function invalidateAssistantInferredItemsForConversation(
94
98
  }
95
99
 
96
100
  /**
97
- * Cancel pending `extract_items` jobs whose messageId belongs to the given
98
- * conversation. This drains the queue so the worker never processes them,
99
- * complementing the runtime check in the extraction handler.
101
+ * Cancel all pending/running memory jobs referencing the given conversation.
102
+ * Covers every job type: `extract_items`, `embed_attachment` (keyed by messageId),
103
+ * `embed_segment` (keyed by segmentId via memory_segments),
104
+ * `build_conversation_summary` (keyed by conversationId),
105
+ * and `embed_item` (keyed by itemId sourced from the conversation's messages).
106
+ */
107
+ export function cancelPendingJobsForConversation(
108
+ conversationId: string,
109
+ reason: string = "conversation_wiped",
110
+ ): number {
111
+ const now = Date.now();
112
+ let total = 0;
113
+
114
+ // Jobs keyed by messageId: extract_items, embed_attachment
115
+ total += rawRun(
116
+ `UPDATE memory_jobs
117
+ SET status = 'failed',
118
+ last_error = ?,
119
+ updated_at = ?
120
+ WHERE status IN ('pending', 'running')
121
+ AND json_extract(payload, '$.messageId') IN (
122
+ SELECT id FROM messages WHERE conversation_id = ?
123
+ )`,
124
+ reason,
125
+ now,
126
+ conversationId,
127
+ );
128
+
129
+ // Jobs keyed by conversationId: build_conversation_summary
130
+ total += rawRun(
131
+ `UPDATE memory_jobs
132
+ SET status = 'failed',
133
+ last_error = ?,
134
+ updated_at = ?
135
+ WHERE status IN ('pending', 'running')
136
+ AND json_extract(payload, '$.conversationId') = ?`,
137
+ reason,
138
+ now,
139
+ conversationId,
140
+ );
141
+
142
+ // Jobs keyed by segmentId: embed_segment (segments belong to the conversation)
143
+ total += rawRun(
144
+ `UPDATE memory_jobs
145
+ SET status = 'failed',
146
+ last_error = ?,
147
+ updated_at = ?
148
+ WHERE status IN ('pending', 'running')
149
+ AND json_extract(payload, '$.segmentId') IN (
150
+ SELECT id FROM memory_segments WHERE conversation_id = ?
151
+ )`,
152
+ reason,
153
+ now,
154
+ conversationId,
155
+ );
156
+
157
+ // Jobs keyed by itemId: embed_item (items sourced from this conversation)
158
+ total += rawRun(
159
+ `UPDATE memory_jobs
160
+ SET status = 'failed',
161
+ last_error = ?,
162
+ updated_at = ?
163
+ WHERE status IN ('pending', 'running')
164
+ AND json_extract(payload, '$.itemId') IN (
165
+ SELECT mis.memory_item_id
166
+ FROM memory_item_sources mis
167
+ JOIN messages m ON m.id = mis.message_id
168
+ WHERE m.conversation_id = ?
169
+ )`,
170
+ reason,
171
+ now,
172
+ conversationId,
173
+ );
174
+
175
+ if (total > 0) {
176
+ log.info(
177
+ { conversationId, cancelled: total },
178
+ "Cancelled pending memory jobs for conversation",
179
+ );
180
+ }
181
+
182
+ return total;
183
+ }
184
+
185
+ /**
186
+ * Cancel only pending/running `extract_items` jobs for messages in the
187
+ * given conversation. Used by the task-failure path where we want to
188
+ * stop new extractions but must NOT cancel `embed_item` jobs — those
189
+ * items may be multi-sourced and still valid.
100
190
  */
101
191
  function cancelPendingExtractionJobsForConversation(
102
192
  conversationId: string,
@@ -107,8 +197,8 @@ function cancelPendingExtractionJobsForConversation(
107
197
  SET status = 'failed',
108
198
  last_error = 'conversation_failed',
109
199
  updated_at = ?
110
- WHERE type IN ('extract_items')
111
- AND status IN ('pending', 'running')
200
+ WHERE status IN ('pending', 'running')
201
+ AND type = 'extract_items'
112
202
  AND json_extract(payload, '$.messageId') IN (
113
203
  SELECT id FROM messages WHERE conversation_id = ?
114
204
  )`,
@@ -0,0 +1,148 @@
1
+ import { and, asc, eq, gt, lt, sql } from "drizzle-orm";
2
+
3
+ import type {
4
+ TraceEvent,
5
+ TraceEventKind,
6
+ } from "../daemon/message-types/messages.js";
7
+ import { getDb, rawChanges } from "./db.js";
8
+ import { traceEvents } from "./schema.js";
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Types
12
+ // ---------------------------------------------------------------------------
13
+
14
+ export interface TraceEventRow {
15
+ eventId: string;
16
+ conversationId: string;
17
+ requestId?: string;
18
+ timestampMs: number;
19
+ sequence: number;
20
+ kind: TraceEventKind;
21
+ status?: "info" | "success" | "warning" | "error";
22
+ summary: string;
23
+ attributes?: Record<string, string | number | boolean | null>;
24
+ }
25
+
26
+ // ---------------------------------------------------------------------------
27
+ // Write
28
+ // ---------------------------------------------------------------------------
29
+
30
+ /** Insert a single trace event row. Duplicate eventIds are silently ignored. */
31
+ export function persistTraceEvent(event: TraceEvent): void {
32
+ const db = getDb();
33
+ db.insert(traceEvents)
34
+ .values({
35
+ eventId: event.eventId,
36
+ conversationId: event.conversationId,
37
+ requestId: event.requestId ?? null,
38
+ timestampMs: event.timestampMs,
39
+ sequence: event.sequence,
40
+ kind: event.kind,
41
+ status: event.status ?? null,
42
+ summary: event.summary,
43
+ attributesJson: event.attributes
44
+ ? JSON.stringify(event.attributes)
45
+ : null,
46
+ createdAt: Date.now(),
47
+ })
48
+ .onConflictDoNothing()
49
+ .run();
50
+ }
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Read
54
+ // ---------------------------------------------------------------------------
55
+
56
+ /** Parse a raw DB row into a TraceEventRow with deserialized attributes. */
57
+ function rowToTraceEventRow(row: {
58
+ eventId: string;
59
+ conversationId: string;
60
+ requestId: string | null;
61
+ timestampMs: number;
62
+ sequence: number;
63
+ kind: string;
64
+ status: string | null;
65
+ summary: string;
66
+ attributesJson: string | null;
67
+ }): TraceEventRow {
68
+ return {
69
+ eventId: row.eventId,
70
+ conversationId: row.conversationId,
71
+ requestId: row.requestId ?? undefined,
72
+ timestampMs: row.timestampMs,
73
+ sequence: row.sequence,
74
+ kind: row.kind as TraceEventKind,
75
+ status: (row.status as TraceEventRow["status"]) ?? undefined,
76
+ summary: row.summary,
77
+ attributes: row.attributesJson
78
+ ? (JSON.parse(row.attributesJson) as Record<
79
+ string,
80
+ string | number | boolean | null
81
+ >)
82
+ : undefined,
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Query trace events for a conversation, ordered by sequence ASC, timestamp_ms ASC.
88
+ * Default limit of 5000 (matching the client's retention cap).
89
+ * Supports `afterSequence` for incremental fetching.
90
+ */
91
+ export function getTraceEvents(
92
+ conversationId: string,
93
+ opts?: { limit?: number; afterSequence?: number },
94
+ ): TraceEventRow[] {
95
+ const db = getDb();
96
+ const limit = opts?.limit ?? 5000;
97
+
98
+ const where =
99
+ opts?.afterSequence != null
100
+ ? and(
101
+ eq(traceEvents.conversationId, conversationId),
102
+ gt(traceEvents.sequence, opts.afterSequence),
103
+ )
104
+ : eq(traceEvents.conversationId, conversationId);
105
+
106
+ const rows = db
107
+ .select()
108
+ .from(traceEvents)
109
+ .where(where)
110
+ .orderBy(asc(traceEvents.sequence), asc(traceEvents.timestampMs))
111
+ .limit(limit)
112
+ .all();
113
+
114
+ return rows.map(rowToTraceEventRow);
115
+ }
116
+
117
+ // ---------------------------------------------------------------------------
118
+ // Cleanup
119
+ // ---------------------------------------------------------------------------
120
+
121
+ /**
122
+ * Delete trace events older than `maxAgeDays` based on `created_at`.
123
+ * Returns the count of deleted rows.
124
+ */
125
+ export function deleteOldTraceEvents(maxAgeDays: number): number {
126
+ const db = getDb();
127
+ const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;
128
+ db.delete(traceEvents).where(lt(traceEvents.createdAt, cutoff)).run();
129
+ return rawChanges();
130
+ }
131
+
132
+ // ---------------------------------------------------------------------------
133
+ // Sequence
134
+ // ---------------------------------------------------------------------------
135
+
136
+ /**
137
+ * Return the highest sequence number persisted for a conversation,
138
+ * or -1 if no events exist yet.
139
+ */
140
+ export function getMaxSequence(conversationId: string): number {
141
+ const db = getDb();
142
+ const row = db
143
+ .select({ maxSeq: sql<number>`MAX(${traceEvents.sequence})` })
144
+ .from(traceEvents)
145
+ .where(eq(traceEvents.conversationId, conversationId))
146
+ .get();
147
+ return row?.maxSeq ?? -1;
148
+ }
@@ -441,7 +441,7 @@ import { emitNotificationSignal } from "../notifications/emit-signal.js";
441
441
  await emitNotificationSignal({
442
442
  sourceEventName: "your_event_name",
443
443
  sourceChannel: "scheduler", // where the event originated
444
- sourceSessionId: conversationId,
444
+ sourceContextId: conversationId,
445
445
  attentionHints: {
446
446
  requiresAction: true,
447
447
  urgency: "high",
@@ -319,7 +319,7 @@ function buildFallbackDecision(
319
319
  selectedChannels: [],
320
320
  reasoningSummary: "Fallback: suppressed (vellum channel not available)",
321
321
  renderedCopy: {},
322
- dedupeKey: `fallback:${signal.sourceEventName}:${signal.sourceSessionId}:${signal.createdAt}`,
322
+ dedupeKey: `fallback:${signal.sourceEventName}:${signal.sourceContextId}:${signal.createdAt}`,
323
323
  confidence: 0.3,
324
324
  fallbackUsed: true,
325
325
  };
@@ -334,7 +334,7 @@ function buildFallbackDecision(
334
334
  ? "Fallback: high urgency + requires action — all channels"
335
335
  : "Fallback: vellum-only (local, always delivered)",
336
336
  renderedCopy: copy,
337
- dedupeKey: `fallback:${signal.sourceEventName}:${signal.sourceSessionId}:${signal.createdAt}`,
337
+ dedupeKey: `fallback:${signal.sourceEventName}:${signal.sourceContextId}:${signal.createdAt}`,
338
338
  confidence: 0.3,
339
339
  fallbackUsed: true,
340
340
  };
@@ -148,8 +148,8 @@ export interface EmitSignalParams<TEventName extends string = string> {
148
148
  sourceEventName: TEventName;
149
149
  /** Source channel that produced the event — must be a registered channel. */
150
150
  sourceChannel: NotificationSourceChannel;
151
- /** Conversation or conversation ID from the source context. */
152
- sourceSessionId: string;
151
+ /** Opaque identifier for the source context (conversation ID, schedule ID, call session ID, etc.). */
152
+ sourceContextId: string;
153
153
  /** Attention hints for the decision engine. */
154
154
  attentionHints: AttentionHints;
155
155
  /** Arbitrary context payload passed to the decision engine. */
@@ -202,7 +202,7 @@ export async function emitNotificationSignal<TEventName extends string>(
202
202
  signalId,
203
203
  createdAt: Date.now(),
204
204
  sourceChannel: params.sourceChannel,
205
- sourceSessionId: params.sourceSessionId,
205
+ sourceContextId: params.sourceContextId,
206
206
  sourceEventName: params.sourceEventName,
207
207
  contextPayload: (params.contextPayload ??
208
208
  {}) as NotificationContextPayload<TEventName>,
@@ -218,7 +218,7 @@ export async function emitNotificationSignal<TEventName extends string>(
218
218
  id: signalId,
219
219
  sourceEventName: params.sourceEventName,
220
220
  sourceChannel: params.sourceChannel,
221
- sourceSessionId: params.sourceSessionId,
221
+ sourceContextId: params.sourceContextId,
222
222
  attentionHints: params.attentionHints,
223
223
  payload: params.contextPayload ?? {},
224
224
  dedupeKey: params.dedupeKey,
@@ -16,7 +16,7 @@ export interface NotificationEventRow {
16
16
  id: string;
17
17
  sourceEventName: string;
18
18
  sourceChannel: string;
19
- sourceSessionId: string;
19
+ sourceContextId: string;
20
20
  attentionHintsJson: string;
21
21
  payloadJson: string;
22
22
  dedupeKey: string | null;
@@ -31,7 +31,7 @@ function rowToEvent(
31
31
  id: row.id,
32
32
  sourceEventName: row.sourceEventName,
33
33
  sourceChannel: row.sourceChannel,
34
- sourceSessionId: row.sourceSessionId,
34
+ sourceContextId: row.sourceContextId,
35
35
  attentionHintsJson: row.attentionHintsJson,
36
36
  payloadJson: row.payloadJson,
37
37
  dedupeKey: row.dedupeKey,
@@ -44,7 +44,7 @@ export interface CreateEventParams {
44
44
  id: string;
45
45
  sourceEventName: string;
46
46
  sourceChannel: string;
47
- sourceSessionId: string;
47
+ sourceContextId: string;
48
48
  attentionHints: AttentionHints;
49
49
  payload: Record<string, unknown>;
50
50
  dedupeKey?: string;
@@ -76,7 +76,7 @@ export function createEvent(
76
76
  id: params.id,
77
77
  sourceEventName: params.sourceEventName,
78
78
  sourceChannel: params.sourceChannel,
79
- sourceSessionId: params.sourceSessionId,
79
+ sourceContextId: params.sourceContextId,
80
80
  attentionHintsJson: JSON.stringify(params.attentionHints),
81
81
  payloadJson: JSON.stringify(params.payload),
82
82
  dedupeKey: normalizedDedupeKey,
@@ -131,7 +131,7 @@ export interface NotificationSignal<TEventName extends string = string> {
131
131
  signalId: string;
132
132
  createdAt: number; // epoch ms
133
133
  sourceChannel: NotificationSourceChannel; // see NOTIFICATION_SOURCE_CHANNELS registry
134
- sourceSessionId: string;
134
+ sourceContextId: string;
135
135
  sourceEventName: TEventName; // free-form: 'reminder_fired', 'schedule_complete', 'guardian_question', etc.
136
136
  contextPayload: NotificationContextPayload<TEventName>;
137
137
  attentionHints: AttentionHints;
@@ -65,6 +65,53 @@ export function removeManualTokenConnection(providerKey: string): void {
65
65
  deleteConnection(conn.id);
66
66
  }
67
67
 
68
+ /**
69
+ * Reconcile the synthetic oauth_connection row for a manual-token provider
70
+ * with whatever credentials are currently present in secure storage.
71
+ *
72
+ * This lets generic credential entry paths (chat setup, CLI, secure prompt)
73
+ * keep connection status in sync without duplicating per-provider rules.
74
+ */
75
+ export async function syncManualTokenConnection(
76
+ providerKey: string,
77
+ accountInfo?: string,
78
+ ): Promise<void> {
79
+ switch (providerKey) {
80
+ case "telegram": {
81
+ const hasBotToken = !!(await getSecureKeyAsync(
82
+ credentialKey("telegram", "bot_token"),
83
+ ));
84
+ const hasWebhookSecret = !!(await getSecureKeyAsync(
85
+ credentialKey("telegram", "webhook_secret"),
86
+ ));
87
+ if (hasBotToken && hasWebhookSecret) {
88
+ await ensureManualTokenConnection(providerKey, accountInfo);
89
+ } else {
90
+ removeManualTokenConnection(providerKey);
91
+ }
92
+ return;
93
+ }
94
+
95
+ case "slack_channel": {
96
+ const hasBotToken = !!(await getSecureKeyAsync(
97
+ credentialKey("slack_channel", "bot_token"),
98
+ ));
99
+ const hasAppToken = !!(await getSecureKeyAsync(
100
+ credentialKey("slack_channel", "app_token"),
101
+ ));
102
+ if (hasBotToken && hasAppToken) {
103
+ await ensureManualTokenConnection(providerKey, accountInfo);
104
+ } else {
105
+ removeManualTokenConnection(providerKey);
106
+ }
107
+ return;
108
+ }
109
+
110
+ default:
111
+ return;
112
+ }
113
+ }
114
+
68
115
  /**
69
116
  * Backfill oauth_connection rows for manual-token providers that already
70
117
  * have valid keychain credentials but are missing connection records.
@@ -78,29 +125,6 @@ export function removeManualTokenConnection(providerKey: string): void {
78
125
  * connection row.
79
126
  */
80
127
  export async function backfillManualTokenConnections(): Promise<void> {
81
- // Telegram: requires both bot_token and webhook_secret
82
- if (!getConnectionByProvider("telegram")) {
83
- const hasBotToken = !!(await getSecureKeyAsync(
84
- credentialKey("telegram", "bot_token"),
85
- ));
86
- const hasWebhookSecret = !!(await getSecureKeyAsync(
87
- credentialKey("telegram", "webhook_secret"),
88
- ));
89
- if (hasBotToken && hasWebhookSecret) {
90
- await ensureManualTokenConnection("telegram");
91
- }
92
- }
93
-
94
- // Slack channel: requires both bot_token and app_token
95
- if (!getConnectionByProvider("slack_channel")) {
96
- const hasBotToken = !!(await getSecureKeyAsync(
97
- credentialKey("slack_channel", "bot_token"),
98
- ));
99
- const hasAppToken = !!(await getSecureKeyAsync(
100
- credentialKey("slack_channel", "app_token"),
101
- ));
102
- if (hasBotToken && hasAppToken) {
103
- await ensureManualTokenConnection("slack_channel");
104
- }
105
- }
128
+ await syncManualTokenConnection("telegram");
129
+ await syncManualTokenConnection("slack_channel");
106
130
  }
@@ -48,10 +48,10 @@ function riskCacheKey(
48
48
  workingDir?: string,
49
49
  manifestOverride?: ManifestOverride,
50
50
  ): string {
51
- // Strip `reason` before computing the cache key — it is cosmetic and varies
52
- // per invocation even for identical tool operations, causing unnecessary
53
- // cache misses.
54
- const { reason: _reason, ...cacheableInput } = input;
51
+ // Strip `reason` and `activity` before computing the cache key — they are
52
+ // cosmetic status text that varies per invocation even for identical tool
53
+ // operations, causing unnecessary cache misses.
54
+ const { reason: _reason, activity: _activity, ...cacheableInput } = input;
55
55
  const inputJson = JSON.stringify(cacheableInput);
56
56
  const hash = createHash("sha256")
57
57
  .update(inputJson)
@@ -143,6 +143,7 @@ const LOW_RISK_PROGRAMS = new Set([
143
143
  "tree",
144
144
  "du",
145
145
  "df",
146
+ "assistant",
146
147
  ]);
147
148
 
148
149
  // High-risk shell programs / patterns
@@ -544,7 +545,7 @@ async function classifyRiskUncached(
544
545
  ) {
545
546
  return RiskLevel.High;
546
547
  }
547
- return RiskLevel.Medium;
548
+ return RiskLevel.Low;
548
549
  }
549
550
  if (toolName === "web_search") return RiskLevel.Low;
550
551
  if (toolName === "web_fetch") {
@@ -259,10 +259,10 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
259
259
  }),
260
260
  );
261
261
 
262
- // ui_update and ui_dismiss are purely passive operations (modify/remove existing
263
- // surfaces). ui_show is excluded because it can create forms that collect user
264
- // inputit goes through normal permission checking instead.
265
- const UI_SURFACE_TOOLS = ["ui_update", "ui_dismiss"] as const;
262
+ // All three UI surface tools are passive, user-visible operations. ui_show
263
+ // creates surfaces (cards, forms, tables) but user input is voluntary and
264
+ // user-controlledsafe to auto-approve like ui_update and ui_dismiss.
265
+ const UI_SURFACE_TOOLS = ["ui_show", "ui_update", "ui_dismiss"] as const;
266
266
  const uiSurfaceRules: DefaultRuleTemplate[] = UI_SURFACE_TOOLS.map(
267
267
  (tool) => ({
268
268
  id: `default:allow-${tool}-global`,
@@ -1,113 +1,32 @@
1
1
  /**
2
2
  * Tests for buildCliReferenceSection — verifies the CLI reference section
3
- * included in the system prompt has the expected structure, CES tool guidance,
4
- * and caching behaviour.
3
+ * included in the system prompt has the expected structure.
5
4
  */
6
5
 
7
- import { beforeEach, describe, expect, test } from "bun:test";
6
+ import { describe, expect, test } from "bun:test";
8
7
 
9
- import {
10
- _resetCliHelpCache,
11
- buildCliReferenceSection,
12
- } from "../system-prompt.js";
8
+ import { buildCliReferenceSection } from "../system-prompt.js";
13
9
 
14
10
  describe("buildCliReferenceSection", () => {
15
- beforeEach(() => {
16
- _resetCliHelpCache();
17
- });
18
-
19
11
  test("includes the Assistant CLI heading", () => {
20
12
  const result = buildCliReferenceSection();
21
13
  expect(result).toContain("## Assistant CLI");
22
14
  });
23
15
 
24
- test("includes CLI help text with command listings", () => {
25
- const result = buildCliReferenceSection();
26
- // The reference is a side-effect-free snapshot of the top-level CLI help.
27
- expect(result).toContain("Usage:");
28
- expect(result).toContain("Commands:");
29
- });
30
-
31
16
  test("mentions bash as the way to invoke the CLI", () => {
32
17
  const result = buildCliReferenceSection();
33
18
  expect(result).toContain("use the `bash` tool");
34
19
  });
35
20
 
36
- // -----------------------------------------------------------------------
37
- // CES tool guidance — new credential workflow
38
- // -----------------------------------------------------------------------
39
-
40
- test("teaches handle discovery via assistant credentials list", () => {
41
- const result = buildCliReferenceSection();
42
- expect(result).toContain("assistant credentials list");
43
- });
44
-
45
- test("teaches handle discovery via assistant oauth connections list", () => {
21
+ test("tells the model to run assistant --help for discovery", () => {
46
22
  const result = buildCliReferenceSection();
47
- expect(result).toContain("assistant oauth connections list");
23
+ expect(result).toContain("assistant --help");
48
24
  });
49
25
 
50
- test("teaches make_authenticated_request CES tool", () => {
26
+ test("does not embed the full CLI help output", () => {
51
27
  const result = buildCliReferenceSection();
52
- expect(result).toContain("make_authenticated_request");
53
- });
54
-
55
- test("teaches run_authenticated_command CES tool", () => {
56
- const result = buildCliReferenceSection();
57
- expect(result).toContain("run_authenticated_command");
58
- });
59
-
60
- test("teaches manage_secure_command_tool CES tool", () => {
61
- const result = buildCliReferenceSection();
62
- expect(result).toContain("manage_secure_command_tool");
63
- });
64
-
65
- test("warns against revealing raw secrets", () => {
66
- const result = buildCliReferenceSection();
67
- expect(result).toContain("Never reveal raw secrets");
68
- });
69
-
70
- test("warns that host_bash is outside CES secrecy boundary", () => {
71
- const result = buildCliReferenceSection();
72
- expect(result).toContain("outside the CES secrecy boundary");
73
- });
74
-
75
- // -----------------------------------------------------------------------
76
- // Deprecated patterns must NOT appear
77
- // -----------------------------------------------------------------------
78
-
79
- test("does not teach token-reveal via oauth connections token", () => {
80
- const result = buildCliReferenceSection();
81
- // The old pattern was: assistant oauth connections token <provider-key>
82
- // for fetching raw tokens. This must not appear in the guidance.
83
- expect(result).not.toContain(
84
- "assistant oauth connections token <provider-key>",
85
- );
86
- });
87
-
88
- test("does not recommend using credential_store for direct API calls", () => {
89
- const result = buildCliReferenceSection();
90
- // The old pattern was: "Direct API calls via host_bash — Use curl/httpie
91
- // with API tokens from credential_store". This is replaced by CES tools.
92
- expect(result).not.toContain("API tokens from credential_store");
93
- });
94
-
95
- // -----------------------------------------------------------------------
96
- // Caching
97
- // -----------------------------------------------------------------------
98
-
99
- test("result is cached — calling twice returns the same string", () => {
100
- const first = buildCliReferenceSection();
101
- const second = buildCliReferenceSection();
102
- expect(first).toBe(second);
103
- });
104
-
105
- test("cache is reset by _resetCliHelpCache", () => {
106
- const first = buildCliReferenceSection();
107
- _resetCliHelpCache();
108
- const second = buildCliReferenceSection();
109
- // Content should be identical even after reset (same CLI program),
110
- // but they should be independently computed strings.
111
- expect(first).toEqual(second);
28
+ // The full help text used to be embedded; now the model should
29
+ // discover commands by running the CLI itself.
30
+ expect(result).not.toContain("Commands:\n");
112
31
  });
113
32
  });
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The SYSTEM_PROMPT_CACHE_BOUNDARY marker is a lightweight constant kept in its
3
+ * own file so that providers (openai, gemini) can import it without pulling in
4
+ * the full system-prompt module and its heavy transitive dependencies, which
5
+ * would otherwise create a circular import cycle.
6
+ */
7
+ export const SYSTEM_PROMPT_CACHE_BOUNDARY =
8
+ "\n<!-- SYSTEM_PROMPT_CACHE_BOUNDARY -->\n";