@vellumai/assistant 0.5.10 → 0.5.12

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 (395) hide show
  1. package/AGENTS.md +8 -0
  2. package/ARCHITECTURE.md +43 -43
  3. package/Dockerfile +3 -0
  4. package/docs/architecture/integrations.md +37 -42
  5. package/docs/architecture/memory.md +7 -12
  6. package/docs/credential-execution-service.md +9 -9
  7. package/docs/skills.md +1 -1
  8. package/node_modules/@vellumai/ces-contracts/src/__tests__/grants.test.ts +7 -7
  9. package/node_modules/@vellumai/ces-contracts/src/handles.ts +5 -4
  10. package/node_modules/@vellumai/credential-storage/src/index.ts +3 -3
  11. package/node_modules/@vellumai/credential-storage/src/static-credentials.ts +1 -1
  12. package/openapi.yaml +7208 -0
  13. package/package.json +2 -1
  14. package/scripts/generate-openapi.ts +562 -0
  15. package/src/__tests__/acp-session.test.ts +239 -44
  16. package/src/__tests__/assistant-feature-flag-guard.test.ts +8 -8
  17. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +5 -86
  18. package/src/__tests__/assistant-feature-flags-integration.test.ts +7 -14
  19. package/src/__tests__/browser-skill-endstate.test.ts +1 -1
  20. package/src/__tests__/btw-routes.test.ts +8 -0
  21. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +10 -10
  22. package/src/__tests__/catalog-cache.test.ts +164 -0
  23. package/src/__tests__/catalog-search.test.ts +61 -0
  24. package/src/__tests__/channel-approvals.test.ts +7 -7
  25. package/src/__tests__/channel-readiness-service.test.ts +41 -0
  26. package/src/__tests__/cli-command-risk-guard.test.ts +181 -6
  27. package/src/__tests__/config-schema.test.ts +10 -2
  28. package/src/__tests__/context-memory-e2e.test.ts +2 -6
  29. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +396 -0
  30. package/src/__tests__/conversation-error.test.ts +3 -2
  31. package/src/__tests__/conversation-skill-tools.test.ts +1 -3
  32. package/src/__tests__/conversation-title-service.test.ts +2 -15
  33. package/src/__tests__/credential-execution-feature-gates.test.ts +4 -8
  34. package/src/__tests__/credential-execution-managed-contract.test.ts +8 -8
  35. package/src/__tests__/credential-security-e2e.test.ts +4 -4
  36. package/src/__tests__/credential-security-invariants.test.ts +12 -18
  37. package/src/__tests__/credential-vault-unit.test.ts +32 -34
  38. package/src/__tests__/credential-vault.test.ts +25 -33
  39. package/src/__tests__/credentials-cli.test.ts +3 -3
  40. package/src/__tests__/daemon-credential-client.test.ts +2 -2
  41. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -1
  42. package/src/__tests__/gateway-only-guard.test.ts +3 -0
  43. package/src/__tests__/heartbeat-service.test.ts +35 -0
  44. package/src/__tests__/host-bash-proxy.test.ts +79 -0
  45. package/src/__tests__/host-cu-proxy.test.ts +90 -0
  46. package/src/__tests__/host-file-proxy.test.ts +89 -0
  47. package/src/__tests__/host-shell-tool.test.ts +1 -1
  48. package/src/__tests__/inline-skill-load-permissions.test.ts +3 -3
  49. package/src/__tests__/integration-status.test.ts +5 -5
  50. package/src/__tests__/list-messages-attachments.test.ts +171 -0
  51. package/src/__tests__/llm-request-log-turn-query.test.ts +64 -0
  52. package/src/__tests__/log-export-workspace.test.ts +1 -1
  53. package/src/__tests__/mcp-abort-signal.test.ts +205 -0
  54. package/src/__tests__/mcp-client-auth.test.ts +1 -1
  55. package/src/__tests__/memory-lifecycle-e2e.test.ts +2 -2
  56. package/src/__tests__/memory-recall-log-store.test.ts +182 -0
  57. package/src/__tests__/memory-recall-quality.test.ts +6 -8
  58. package/src/__tests__/memory-regressions.test.ts +53 -42
  59. package/src/__tests__/memory-retrieval.benchmark.test.ts +5 -9
  60. package/src/__tests__/messaging-send-tool.test.ts +5 -5
  61. package/src/__tests__/messaging-skill-split.test.ts +2 -17
  62. package/src/__tests__/notification-telegram-adapter.test.ts +125 -0
  63. package/src/__tests__/oauth-cli.test.ts +203 -649
  64. package/src/__tests__/oauth-provider-profiles.test.ts +55 -20
  65. package/src/__tests__/oauth-scope-policy.test.ts +4 -6
  66. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  67. package/src/__tests__/platform-callback-registration.test.ts +119 -0
  68. package/src/__tests__/secret-ingress-channel.test.ts +261 -0
  69. package/src/__tests__/secret-ingress-cli.test.ts +201 -0
  70. package/src/__tests__/secret-ingress-http.test.ts +312 -0
  71. package/src/__tests__/secret-ingress.test.ts +283 -0
  72. package/src/__tests__/secret-onetime-send.test.ts +4 -4
  73. package/src/__tests__/secret-routes-managed-proxy.test.ts +78 -0
  74. package/src/__tests__/secure-keys-managed-failover.test.ts +73 -0
  75. package/src/__tests__/skill-feature-flags-integration.test.ts +4 -4
  76. package/src/__tests__/skill-feature-flags.test.ts +11 -19
  77. package/src/__tests__/skill-load-feature-flag.test.ts +1 -1
  78. package/src/__tests__/skill-load-inline-command.test.ts +3 -3
  79. package/src/__tests__/skill-load-inline-includes.test.ts +2 -2
  80. package/src/__tests__/skill-memory.test.ts +2 -4
  81. package/src/__tests__/skill-projection-feature-flag.test.ts +2 -4
  82. package/src/__tests__/skill-projection.benchmark.test.ts +1 -3
  83. package/src/__tests__/skills-uninstall.test.ts +2 -2
  84. package/src/__tests__/skills.test.ts +16 -2
  85. package/src/__tests__/slack-channel-config.test.ts +1 -1
  86. package/src/__tests__/slack-messaging-token-resolution.test.ts +22 -24
  87. package/src/__tests__/slack-share-routes.test.ts +5 -5
  88. package/src/__tests__/slack-skill.test.ts +5 -69
  89. package/src/__tests__/system-prompt.test.ts +39 -0
  90. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -1
  91. package/src/__tests__/workspace-migration-018-rekey-compound-credential-keys.test.ts +181 -0
  92. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +5 -4
  93. package/src/acp/client-handler.ts +113 -31
  94. package/src/acp/session-manager.ts +29 -27
  95. package/src/approvals/guardian-request-resolvers.ts +1 -1
  96. package/src/cli/AGENTS.md +113 -0
  97. package/src/cli/commands/autonomy.ts +3 -5
  98. package/src/cli/commands/browser-relay.ts +2 -17
  99. package/src/cli/commands/contacts.ts +6 -4
  100. package/src/cli/commands/conversations.ts +13 -1
  101. package/src/cli/commands/credential-execution.ts +17 -3
  102. package/src/cli/commands/credentials.ts +2 -8
  103. package/src/cli/commands/memory.ts +2 -3
  104. package/src/cli/commands/oauth/__tests__/connect.test.ts +706 -0
  105. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +686 -0
  106. package/src/cli/commands/oauth/__tests__/mode.test.ts +625 -0
  107. package/src/cli/commands/oauth/__tests__/ping.test.ts +631 -0
  108. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +574 -0
  109. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +416 -0
  110. package/src/cli/commands/oauth/__tests__/status.test.ts +551 -0
  111. package/src/cli/commands/oauth/__tests__/token.test.ts +420 -0
  112. package/src/cli/commands/oauth/apps.ts +87 -50
  113. package/src/cli/commands/oauth/connect.ts +405 -0
  114. package/src/cli/commands/oauth/disconnect.ts +285 -0
  115. package/src/cli/commands/oauth/index.ts +62 -20
  116. package/src/cli/commands/oauth/mode.ts +251 -0
  117. package/src/cli/commands/oauth/ping.ts +196 -0
  118. package/src/cli/commands/oauth/providers.ts +589 -55
  119. package/src/cli/commands/oauth/request.ts +564 -0
  120. package/src/cli/commands/oauth/shared.ts +114 -0
  121. package/src/cli/commands/oauth/status.ts +191 -0
  122. package/src/cli/commands/oauth/token.ts +150 -0
  123. package/src/cli/commands/platform/connect.ts +104 -0
  124. package/src/cli/commands/platform/disconnect.ts +118 -0
  125. package/src/cli/commands/platform/index.ts +252 -0
  126. package/src/cli/commands/sequence.ts +5 -4
  127. package/src/cli/commands/shotgun.ts +16 -0
  128. package/src/cli/commands/skills.ts +173 -41
  129. package/src/cli/commands/usage.ts +5 -11
  130. package/src/cli/lib/daemon-credential-client.ts +22 -38
  131. package/src/cli/program.ts +1 -1
  132. package/src/cli.ts +82 -17
  133. package/src/config/assistant-feature-flags.ts +77 -18
  134. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
  135. package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -1
  136. package/src/config/bundled-skills/contacts/tools/google-contacts.ts +1 -1
  137. package/src/config/bundled-skills/conversations/SKILL.md +20 -0
  138. package/src/config/bundled-skills/conversations/TOOLS.json +23 -0
  139. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +66 -0
  140. package/src/config/bundled-skills/gmail/SKILL.md +13 -13
  141. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +3 -3
  142. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +2 -2
  143. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +1 -1
  144. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +1 -1
  145. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +1 -1
  146. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +1 -1
  147. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +2 -2
  148. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +1 -1
  149. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +1 -1
  150. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
  151. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +1 -1
  152. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +1 -1
  153. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +1 -1
  154. package/src/config/bundled-skills/google-calendar/SKILL.md +10 -4
  155. package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
  156. package/src/config/bundled-skills/messaging/SKILL.md +19 -42
  157. package/src/config/bundled-skills/messaging/TOOLS.json +9 -9
  158. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
  159. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -2
  160. package/src/config/bundled-skills/messaging/tools/shared.ts +5 -6
  161. package/src/config/bundled-skills/notifications/SKILL.md +1 -1
  162. package/src/config/bundled-skills/schedule/SKILL.md +2 -2
  163. package/src/config/bundled-skills/settings/SKILL.md +5 -3
  164. package/src/config/bundled-skills/settings/TOOLS.json +17 -0
  165. package/src/config/bundled-skills/settings/tools/avatar-get.ts +50 -0
  166. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +7 -0
  167. package/src/config/bundled-skills/settings/tools/avatar-update.ts +6 -1
  168. package/src/config/bundled-skills/settings/tools/identity-avatar.ts +55 -0
  169. package/src/config/bundled-skills/skills-catalog/SKILL.md +3 -3
  170. package/src/config/bundled-skills/slack/SKILL.md +58 -44
  171. package/src/config/bundled-tool-registry.ts +7 -19
  172. package/src/config/env.ts +5 -1
  173. package/src/config/feature-flag-registry.json +58 -42
  174. package/src/config/loader.ts +4 -0
  175. package/src/config/schemas/platform.ts +0 -8
  176. package/src/config/schemas/security.ts +9 -1
  177. package/src/config/schemas/services.ts +1 -1
  178. package/src/config/skill-state.ts +1 -3
  179. package/src/config/skills.ts +2 -4
  180. package/src/credential-execution/client.ts +1 -1
  181. package/src/credential-execution/feature-gates.ts +9 -16
  182. package/src/credential-execution/process-manager.ts +12 -0
  183. package/src/daemon/config-watcher.ts +4 -0
  184. package/src/daemon/conversation-agent-loop-handlers.ts +10 -0
  185. package/src/daemon/conversation-agent-loop.ts +51 -2
  186. package/src/daemon/conversation-error.ts +36 -6
  187. package/src/daemon/conversation-memory.ts +0 -1
  188. package/src/daemon/conversation-messaging.ts +9 -0
  189. package/src/daemon/conversation-runtime-assembly.ts +33 -0
  190. package/src/daemon/conversation-surfaces.ts +120 -14
  191. package/src/daemon/conversation.ts +5 -0
  192. package/src/daemon/handlers/config-slack-channel.ts +43 -1
  193. package/src/daemon/handlers/conversations.ts +41 -33
  194. package/src/daemon/handlers/skills.ts +148 -3
  195. package/src/daemon/host-bash-proxy.ts +16 -0
  196. package/src/daemon/host-cu-proxy.ts +16 -0
  197. package/src/daemon/host-file-proxy.ts +16 -0
  198. package/src/daemon/lifecycle.ts +73 -3
  199. package/src/daemon/message-types/acp.ts +0 -15
  200. package/src/daemon/message-types/conversations.ts +1 -0
  201. package/src/daemon/message-types/guardian-actions.ts +2 -0
  202. package/src/daemon/message-types/host-bash.ts +6 -1
  203. package/src/daemon/message-types/host-cu.ts +6 -1
  204. package/src/daemon/message-types/host-file.ts +6 -1
  205. package/src/daemon/message-types/integrations.ts +0 -1
  206. package/src/daemon/message-types/memory.ts +0 -1
  207. package/src/daemon/message-types/messages.ts +9 -1
  208. package/src/daemon/message-types/schedules.ts +9 -0
  209. package/src/daemon/server.ts +48 -9
  210. package/src/email/feature-gate.ts +3 -3
  211. package/src/heartbeat/heartbeat-service.ts +48 -0
  212. package/src/hooks/cli.ts +74 -0
  213. package/src/inbound/platform-callback-registration.ts +68 -19
  214. package/src/mcp/client.ts +6 -1
  215. package/src/mcp/manager.ts +2 -1
  216. package/src/mcp/mcp-oauth-provider.ts +3 -3
  217. package/src/memory/app-store.ts +3 -3
  218. package/src/memory/conversation-crud.ts +213 -0
  219. package/src/memory/conversation-key-store.ts +26 -0
  220. package/src/memory/conversation-title-service.ts +7 -17
  221. package/src/memory/db-init.ts +24 -0
  222. package/src/memory/embedding-local.ts +47 -2
  223. package/src/memory/indexer.ts +13 -10
  224. package/src/memory/items-extractor.ts +12 -4
  225. package/src/memory/job-utils.ts +5 -0
  226. package/src/memory/jobs-store.ts +10 -2
  227. package/src/memory/journal-memory.ts +6 -2
  228. package/src/memory/llm-request-log-store.ts +88 -21
  229. package/src/memory/memory-recall-log-store.ts +128 -0
  230. package/src/memory/migrations/194-memory-recall-logs.ts +50 -0
  231. package/src/memory/migrations/195-oauth-providers-ping-config.ts +23 -0
  232. package/src/memory/migrations/196-messages-conversation-created-at-index.ts +9 -0
  233. package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +186 -0
  234. package/src/memory/migrations/197-oauth-providers-behavior-columns.ts +29 -0
  235. package/src/memory/migrations/198-drop-setup-skill-id-column.ts +11 -0
  236. package/src/memory/migrations/index.ts +6 -0
  237. package/src/memory/migrations/registry.ts +8 -0
  238. package/src/memory/retriever.test.ts +4 -5
  239. package/src/memory/schema/infrastructure.ts +31 -0
  240. package/src/memory/schema/oauth.ts +14 -0
  241. package/src/messaging/provider.ts +13 -12
  242. package/src/messaging/providers/gmail/adapter.ts +44 -35
  243. package/src/messaging/providers/slack/adapter.ts +63 -33
  244. package/src/messaging/providers/telegram-bot/adapter.ts +7 -9
  245. package/src/messaging/providers/whatsapp/adapter.ts +6 -8
  246. package/src/notifications/adapters/telegram.ts +78 -2
  247. package/src/oauth/__tests__/identity-verifier.test.ts +464 -0
  248. package/src/oauth/byo-connection.test.ts +22 -24
  249. package/src/oauth/connect-orchestrator.ts +79 -64
  250. package/src/oauth/connect-types.ts +7 -65
  251. package/src/oauth/connection-resolver.test.ts +13 -13
  252. package/src/oauth/connection-resolver.ts +3 -4
  253. package/src/oauth/identity-verifier.ts +177 -0
  254. package/src/oauth/manual-token-connection.ts +5 -5
  255. package/src/oauth/oauth-store.ts +251 -5
  256. package/src/oauth/platform-connection.test.ts +56 -6
  257. package/src/oauth/platform-connection.ts +8 -1
  258. package/src/oauth/seed-providers.ts +256 -34
  259. package/src/permissions/checker.ts +129 -3
  260. package/src/permissions/trust-client.ts +2 -2
  261. package/src/platform/client.ts +2 -2
  262. package/src/prompts/journal-context.ts +6 -1
  263. package/src/prompts/system-prompt.ts +43 -9
  264. package/src/prompts/templates/BOOTSTRAP.md +16 -5
  265. package/src/providers/anthropic/client.ts +139 -28
  266. package/src/runtime/auth/__tests__/middleware.test.ts +19 -0
  267. package/src/runtime/auth/route-policy.ts +0 -1
  268. package/src/runtime/btw-sidechain.ts +7 -1
  269. package/src/runtime/channel-approvals.ts +2 -2
  270. package/src/runtime/channel-readiness-service.ts +30 -7
  271. package/src/runtime/guardian-action-service.ts +7 -2
  272. package/src/runtime/http-router.ts +31 -0
  273. package/src/runtime/http-server.ts +26 -7
  274. package/src/runtime/http-types.ts +9 -0
  275. package/src/runtime/pending-interactions.ts +21 -3
  276. package/src/runtime/routes/acp-routes.ts +46 -28
  277. package/src/runtime/routes/app-management-routes.ts +123 -0
  278. package/src/runtime/routes/app-routes.ts +31 -0
  279. package/src/runtime/routes/approval-routes.ts +108 -3
  280. package/src/runtime/routes/attachment-routes.ts +45 -0
  281. package/src/runtime/routes/avatar-routes.ts +16 -0
  282. package/src/runtime/routes/brain-graph-routes.ts +18 -0
  283. package/src/runtime/routes/btw-routes.ts +20 -0
  284. package/src/runtime/routes/call-routes.ts +81 -0
  285. package/src/runtime/routes/channel-readiness-routes.ts +48 -7
  286. package/src/runtime/routes/channel-routes.ts +18 -0
  287. package/src/runtime/routes/channel-verification-routes.ts +49 -1
  288. package/src/runtime/routes/contact-routes.ts +77 -0
  289. package/src/runtime/routes/conversation-attention-routes.ts +37 -0
  290. package/src/runtime/routes/conversation-management-routes.ts +125 -0
  291. package/src/runtime/routes/conversation-query-routes.ts +78 -0
  292. package/src/runtime/routes/conversation-routes.ts +191 -39
  293. package/src/runtime/routes/conversation-starter-routes.ts +29 -0
  294. package/src/runtime/routes/debug-routes.ts +23 -0
  295. package/src/runtime/routes/diagnostics-routes.ts +30 -0
  296. package/src/runtime/routes/documents-routes.ts +42 -0
  297. package/src/runtime/routes/events-routes.ts +10 -0
  298. package/src/runtime/routes/global-search-routes.ts +35 -0
  299. package/src/runtime/routes/guardian-action-routes.ts +61 -3
  300. package/src/runtime/routes/guardian-approval-prompt.ts +77 -2
  301. package/src/runtime/routes/heartbeat-routes.ts +278 -0
  302. package/src/runtime/routes/host-bash-routes.ts +16 -1
  303. package/src/runtime/routes/host-cu-routes.ts +23 -1
  304. package/src/runtime/routes/host-file-routes.ts +18 -1
  305. package/src/runtime/routes/identity-routes.ts +35 -0
  306. package/src/runtime/routes/inbound-message-handler.ts +46 -25
  307. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -8
  308. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +30 -2
  309. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +1 -2
  310. package/src/runtime/routes/integrations/slack/share.ts +1 -1
  311. package/src/runtime/routes/integrations/twilio.ts +32 -22
  312. package/src/runtime/routes/invite-routes.ts +83 -0
  313. package/src/runtime/routes/log-export-routes.ts +14 -0
  314. package/src/runtime/routes/memory-item-routes.ts +99 -1
  315. package/src/runtime/routes/migration-rollback-routes.ts +25 -0
  316. package/src/runtime/routes/migration-routes.ts +40 -0
  317. package/src/runtime/routes/notification-routes.ts +20 -0
  318. package/src/runtime/routes/oauth-apps.ts +13 -4
  319. package/src/runtime/routes/pairing-routes.ts +15 -0
  320. package/src/runtime/routes/recording-routes.ts +72 -0
  321. package/src/runtime/routes/schedule-routes.ts +77 -5
  322. package/src/runtime/routes/secret-routes.ts +99 -14
  323. package/src/runtime/routes/settings-routes.ts +102 -19
  324. package/src/runtime/routes/skills-routes.ts +141 -18
  325. package/src/runtime/routes/subagents-routes.ts +38 -3
  326. package/src/runtime/routes/surface-action-routes.ts +66 -24
  327. package/src/runtime/routes/surface-content-routes.ts +20 -0
  328. package/src/runtime/routes/telemetry-routes.ts +12 -0
  329. package/src/runtime/routes/trace-event-routes.ts +25 -0
  330. package/src/runtime/routes/trust-rules-routes.ts +46 -0
  331. package/src/runtime/routes/tts-routes.ts +15 -4
  332. package/src/runtime/routes/upgrade-broadcast-routes.ts +38 -0
  333. package/src/runtime/routes/usage-routes.ts +59 -0
  334. package/src/runtime/routes/watch-routes.ts +28 -0
  335. package/src/runtime/routes/work-items-routes.ts +59 -0
  336. package/src/runtime/routes/workspace-commit-routes.ts +12 -0
  337. package/src/runtime/routes/workspace-routes.ts +102 -0
  338. package/src/schedule/integration-status.ts +2 -2
  339. package/src/schedule/scheduler.ts +7 -1
  340. package/src/security/AGENTS.md +7 -0
  341. package/src/security/ces-rpc-credential-backend.ts +19 -16
  342. package/src/security/credential-backend.ts +1 -1
  343. package/src/security/encrypted-store.ts +3 -3
  344. package/src/security/oauth-completion-page.ts +153 -0
  345. package/src/security/oauth2.ts +58 -17
  346. package/src/security/secret-ingress.ts +174 -0
  347. package/src/security/secret-patterns.ts +133 -0
  348. package/src/security/secret-scanner.ts +28 -117
  349. package/src/security/secure-keys.ts +207 -7
  350. package/src/security/token-manager.ts +3 -6
  351. package/src/signals/bash.ts +6 -1
  352. package/src/signals/confirm.ts +12 -8
  353. package/src/signals/user-message.ts +18 -3
  354. package/src/skills/catalog-cache.ts +44 -0
  355. package/src/skills/catalog-search.ts +18 -0
  356. package/src/skills/skill-memory.ts +1 -2
  357. package/src/tasks/task-runner.ts +7 -1
  358. package/src/tools/credentials/broker.ts +1 -1
  359. package/src/tools/credentials/metadata-store.ts +1 -1
  360. package/src/tools/credentials/post-connect-hooks.ts +1 -1
  361. package/src/tools/credentials/vault.ts +36 -48
  362. package/src/tools/host-terminal/host-shell.ts +16 -3
  363. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  364. package/src/tools/memory/definitions.ts +1 -1
  365. package/src/tools/memory/handlers.test.ts +2 -4
  366. package/src/tools/skills/load.ts +1 -1
  367. package/src/tools/skills/sandbox-runner.ts +16 -3
  368. package/src/tools/terminal/safe-env.ts +7 -0
  369. package/src/tools/terminal/shell.ts +16 -3
  370. package/src/tools/tool-manifest.ts +1 -1
  371. package/src/util/log-redact.ts +9 -34
  372. package/src/util/logger.ts +11 -1
  373. package/src/util/sentry-log-stream.ts +51 -0
  374. package/src/watcher/providers/github.ts +2 -2
  375. package/src/watcher/providers/gmail.ts +1 -1
  376. package/src/watcher/providers/google-calendar.ts +1 -1
  377. package/src/watcher/providers/linear.ts +2 -2
  378. package/src/workspace/migrations/011-backfill-installation-id.ts +5 -3
  379. package/src/workspace/migrations/020-rename-oauth-skill-dirs.ts +119 -0
  380. package/src/workspace/migrations/registry.ts +2 -0
  381. package/docs/architecture/keychain-broker.md +0 -68
  382. package/src/cli/commands/oauth/connections.ts +0 -734
  383. package/src/cli/commands/oauth/platform.ts +0 -525
  384. package/src/cli/commands/platform.ts +0 -176
  385. package/src/config/bundled-skills/slack/TOOLS.json +0 -272
  386. package/src/config/bundled-skills/slack/tools/shared.ts +0 -34
  387. package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +0 -27
  388. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +0 -38
  389. package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +0 -146
  390. package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +0 -105
  391. package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +0 -26
  392. package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +0 -27
  393. package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +0 -25
  394. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +0 -372
  395. package/src/oauth/provider-behaviors.ts +0 -634
@@ -8,6 +8,8 @@
8
8
  * header. Guardian decisions additionally verify that the actor is the
9
9
  * bound guardian.
10
10
  */
11
+ import { z } from "zod";
12
+
11
13
  import { getConversationByKey } from "../../memory/conversation-key-store.js";
12
14
  import { addRule } from "../../permissions/trust-store.js";
13
15
  import type { UserDecision } from "../../permissions/types.js";
@@ -69,6 +71,10 @@ export async function handleConfirm(
69
71
  // pending interaction — the client can retry with corrected values.
70
72
  const peeked = pendingInteractions.get(requestId);
71
73
  if (!peeked) {
74
+ log.warn(
75
+ { requestId, decision },
76
+ "Confirmation POST for unknown requestId (already consumed or never registered)",
77
+ );
72
78
  return httpError(
73
79
  "NOT_FOUND",
74
80
  "No pending interaction found for this requestId",
@@ -129,7 +135,23 @@ export async function handleConfirm(
129
135
  // Validation passed — consume the pending interaction.
130
136
  const interaction = pendingInteractions.resolve(requestId)!;
131
137
 
132
- interaction.conversation.handleConfirmationResponse(
138
+ log.info(
139
+ {
140
+ requestId,
141
+ decision,
142
+ toolName: interaction.confirmationDetails?.toolName,
143
+ conversationId: interaction.conversationId,
144
+ },
145
+ "Confirmation resolved via HTTP",
146
+ );
147
+
148
+ // ACP permissions: resolve directly without a Conversation object.
149
+ if (interaction.directResolve) {
150
+ interaction.directResolve(decision as UserDecision);
151
+ return Response.json({ accepted: true });
152
+ }
153
+
154
+ interaction.conversation!.handleConfirmationResponse(
133
155
  requestId,
134
156
  decision as UserDecision,
135
157
  selectedPattern,
@@ -187,7 +209,7 @@ export async function handleSecret(
187
209
  );
188
210
  }
189
211
 
190
- interaction.conversation.handleSecretResponse(
212
+ interaction.conversation!.handleSecretResponse(
191
213
  requestId,
192
214
  value,
193
215
  delivery as "store" | "transient_send" | undefined,
@@ -355,7 +377,9 @@ export function handleListPendingInteractions(
355
377
  resolvedConversationId,
356
378
  );
357
379
 
358
- const confirmation = interactions.find((i) => i.kind === "confirmation");
380
+ const confirmation = interactions.find(
381
+ (i) => i.kind === "confirmation" || i.kind === "acp_confirmation",
382
+ );
359
383
  const secret = interactions.find((i) => i.kind === "secret");
360
384
 
361
385
  return Response.json({
@@ -377,6 +401,8 @@ export function handleListPendingInteractions(
377
401
  confirmation.confirmationDetails?.persistentDecisionsAllowed,
378
402
  temporaryOptionsAvailable:
379
403
  confirmation.confirmationDetails?.temporaryOptionsAvailable,
404
+ acpToolKind: confirmation.confirmationDetails?.acpToolKind,
405
+ acpOptions: confirmation.confirmationDetails?.acpOptions,
380
406
  }
381
407
  : null,
382
408
  pendingSecret: secret
@@ -396,22 +422,101 @@ export function approvalRouteDefinitions(): RouteDefinition[] {
396
422
  {
397
423
  endpoint: "confirm",
398
424
  method: "POST",
425
+ summary: "Resolve a pending confirmation",
426
+ description: "Approve or deny a pending tool confirmation by requestId.",
427
+ tags: ["approvals"],
428
+ requestBody: z.object({
429
+ requestId: z.string().describe("Pending interaction request ID"),
430
+ decision: z
431
+ .string()
432
+ .describe(
433
+ "One of: allow, allow_10m, allow_conversation, deny, always_allow, always_deny, always_allow_high_risk",
434
+ ),
435
+ selectedPattern: z
436
+ .string()
437
+ .describe("Allowlist pattern for persistent decisions")
438
+ .optional(),
439
+ selectedScope: z
440
+ .string()
441
+ .describe("Scope for persistent decisions")
442
+ .optional(),
443
+ }),
444
+ responseBody: z.object({
445
+ accepted: z.boolean(),
446
+ }),
399
447
  handler: async ({ req, authContext }) => handleConfirm(req, authContext),
400
448
  },
401
449
  {
402
450
  endpoint: "secret",
403
451
  method: "POST",
452
+ summary: "Resolve a pending secret request",
453
+ description: "Provide a secret value for a pending secret request.",
454
+ tags: ["approvals"],
455
+ requestBody: z.object({
456
+ requestId: z.string().describe("Pending interaction request ID"),
457
+ value: z.string().describe("Secret value").optional(),
458
+ delivery: z
459
+ .string()
460
+ .describe("Delivery mode: store or transient_send")
461
+ .optional(),
462
+ }),
463
+ responseBody: z.object({
464
+ accepted: z.boolean(),
465
+ }),
404
466
  handler: async ({ req, authContext }) => handleSecret(req, authContext),
405
467
  },
406
468
  {
407
469
  endpoint: "trust-rules",
408
470
  method: "POST",
471
+ summary: "Add a trust rule for a pending confirmation",
472
+ description:
473
+ "Add a trust rule bound to a pending confirmation without resolving it.",
474
+ tags: ["approvals"],
475
+ requestBody: z.object({
476
+ requestId: z.string().describe("Pending confirmation request ID"),
477
+ pattern: z.string().describe("Allowlist pattern"),
478
+ scope: z.string().describe("Scope for the rule"),
479
+ decision: z.string().describe("allow or deny"),
480
+ allowHighRisk: z
481
+ .boolean()
482
+ .describe("Allow high-risk invocations")
483
+ .optional(),
484
+ }),
485
+ responseBody: z.object({
486
+ accepted: z.boolean(),
487
+ }),
409
488
  handler: async ({ req, authContext }) =>
410
489
  handleTrustRule(req, authContext),
411
490
  },
412
491
  {
413
492
  endpoint: "pending-interactions",
414
493
  method: "GET",
494
+ summary: "List pending interactions",
495
+ description:
496
+ "Return pending confirmations and secrets for a conversation.",
497
+ tags: ["approvals"],
498
+ queryParams: [
499
+ {
500
+ name: "conversationKey",
501
+ schema: { type: "string" },
502
+ description: "Conversation key",
503
+ },
504
+ {
505
+ name: "conversationId",
506
+ schema: { type: "string" },
507
+ description: "Conversation ID",
508
+ },
509
+ ],
510
+ responseBody: z.object({
511
+ pendingConfirmation: z
512
+ .object({})
513
+ .passthrough()
514
+ .describe("Pending confirmation details or null"),
515
+ pendingSecret: z
516
+ .object({})
517
+ .passthrough()
518
+ .describe("Pending secret request or null"),
519
+ }),
415
520
  handler: ({ url, authContext }) =>
416
521
  handleListPendingInteractions(url, authContext),
417
522
  },
@@ -3,6 +3,8 @@
3
3
  */
4
4
  import { existsSync, statSync } from "node:fs";
5
5
 
6
+ import { z } from "zod";
7
+
6
8
  import * as attachmentsStore from "../../memory/attachments-store.js";
7
9
  import {
8
10
  AttachmentUploadError,
@@ -261,23 +263,66 @@ export function attachmentRouteDefinitions(): RouteDefinition[] {
261
263
  {
262
264
  endpoint: "attachments",
263
265
  method: "POST",
266
+ summary: "Upload attachment",
267
+ description:
268
+ "Upload an attachment as base64 data or file path reference.",
269
+ tags: ["attachments"],
270
+ requestBody: z.object({
271
+ filename: z.string(),
272
+ mimeType: z.string(),
273
+ data: z.string().describe("Base64-encoded file data").optional(),
274
+ filePath: z
275
+ .string()
276
+ .describe("On-disk file path (file-backed upload)")
277
+ .optional(),
278
+ }),
279
+ responseBody: z.object({
280
+ id: z.string(),
281
+ original_filename: z.string(),
282
+ mime_type: z.string(),
283
+ size_bytes: z.number(),
284
+ kind: z.string(),
285
+ }),
264
286
  handler: async ({ req }) => handleUploadAttachment(req),
265
287
  },
266
288
  {
267
289
  endpoint: "attachments",
268
290
  method: "DELETE",
291
+ summary: "Delete attachment",
292
+ description: "Delete an attachment by ID.",
293
+ tags: ["attachments"],
294
+ requestBody: z.object({
295
+ attachmentId: z.string(),
296
+ }),
269
297
  handler: async ({ req }) => handleDeleteAttachment(req),
270
298
  },
271
299
  {
272
300
  endpoint: "attachments/:id/content",
273
301
  method: "GET",
274
302
  policyKey: "attachments/content",
303
+ summary: "Get attachment content",
304
+ description:
305
+ "Serve raw file bytes for an attachment. Supports Range headers.",
306
+ tags: ["attachments"],
275
307
  handler: ({ req, params }) => handleGetAttachmentContent(params.id, req),
276
308
  },
277
309
  {
278
310
  endpoint: "attachments/:id",
279
311
  method: "GET",
280
312
  policyKey: "attachments",
313
+ summary: "Get attachment metadata",
314
+ description:
315
+ "Return metadata and optional base64 data for an attachment.",
316
+ tags: ["attachments"],
317
+ responseBody: z.object({
318
+ id: z.string(),
319
+ filename: z.string(),
320
+ mimeType: z.string(),
321
+ sizeBytes: z.number(),
322
+ kind: z.string(),
323
+ data: z.string().describe("Base64-encoded content"),
324
+ fileBacked: z.boolean(),
325
+ }),
281
326
  handler: ({ params }) => handleGetAttachment(params.id),
282
327
  },
283
328
  ];
@@ -1,5 +1,7 @@
1
1
  import { join } from "node:path";
2
2
 
3
+ import { z } from "zod";
4
+
3
5
  import { getCharacterComponents } from "../../avatar/character-components.js";
4
6
  import {
5
7
  type CharacterTraits,
@@ -39,11 +41,25 @@ export function avatarRouteDefinitions(): RouteDefinition[] {
39
41
  {
40
42
  endpoint: "avatar/character-components",
41
43
  method: "GET",
44
+ summary: "Get character components",
45
+ description: "Return available avatar character components.",
46
+ tags: ["avatar"],
42
47
  handler: () => Response.json(getCharacterComponents()),
43
48
  },
44
49
  {
45
50
  endpoint: "avatar/render-from-traits",
46
51
  method: "POST",
52
+ summary: "Render avatar from traits",
53
+ description: "Write character traits and render an avatar PNG.",
54
+ tags: ["avatar"],
55
+ requestBody: z.object({
56
+ bodyShape: z.string(),
57
+ eyeStyle: z.string(),
58
+ color: z.string(),
59
+ }),
60
+ responseBody: z.object({
61
+ ok: z.boolean(),
62
+ }),
47
63
  handler: async ({ req }) => {
48
64
  let body: CharacterTraits;
49
65
  try {
@@ -9,6 +9,7 @@ import { readFileSync } from "node:fs";
9
9
  import { join } from "node:path";
10
10
 
11
11
  import { count } from "drizzle-orm";
12
+ import { z } from "zod";
12
13
 
13
14
  import { getDb } from "../../memory/db.js";
14
15
  import { memoryItems } from "../../memory/schema.js";
@@ -136,11 +137,28 @@ export function brainGraphRouteDefinitions(deps: {
136
137
  {
137
138
  endpoint: "brain-graph",
138
139
  method: "GET",
140
+ summary: "Get brain graph data",
141
+ description:
142
+ "Return a knowledge-graph shaped for brain-lobe visualization, with memory items mapped to brain regions.",
143
+ tags: ["brain-graph"],
144
+ responseBody: z.object({
145
+ entities: z.array(z.unknown()).describe("Graph entity nodes"),
146
+ relations: z.array(z.unknown()).describe("Graph relation edges"),
147
+ memorySummary: z
148
+ .array(z.unknown())
149
+ .describe("Memory kind counts and colors"),
150
+ totalKnowledgeCount: z.number().int(),
151
+ generatedAt: z.string().describe("ISO 8601 timestamp"),
152
+ }),
139
153
  handler: () => handleGetBrainGraph(),
140
154
  },
141
155
  {
142
156
  endpoint: "brain-graph-ui",
143
157
  method: "GET",
158
+ summary: "Serve brain graph UI",
159
+ description:
160
+ "Return the brain-graph HTML visualization page with an embedded auth token.",
161
+ tags: ["brain-graph"],
144
162
  handler: () => handleServeBrainGraphUI(deps.mintUiPageToken()),
145
163
  },
146
164
  ];
@@ -14,7 +14,13 @@
14
14
 
15
15
  import { existsSync, readFileSync } from "node:fs";
16
16
 
17
+ import { z } from "zod";
18
+
17
19
  import { getConversationByKey } from "../../memory/conversation-key-store.js";
20
+ import {
21
+ resolveChannelPersona,
22
+ resolveGuardianPersona,
23
+ } from "../../prompts/persona-resolver.js";
18
24
  import { getLogger } from "../../util/logger.js";
19
25
  import { getWorkspacePromptPath } from "../../util/platform.js";
20
26
  import type { AuthContext } from "../auth/types.js";
@@ -144,10 +150,14 @@ async function handleBtw(
144
150
  (async () => {
145
151
  try {
146
152
  const isIntroRequest = conversationKey === IDENTITY_INTRO_KEY;
153
+ const userPersona = resolveGuardianPersona();
154
+ const channelPersona = resolveChannelPersona(undefined);
147
155
  const result = await runBtwSidechain({
148
156
  content: trimmedContent,
149
157
  conversation,
150
158
  signal: req.signal,
159
+ userPersona,
160
+ channelPersona,
151
161
  onEvent: (event) => {
152
162
  if (event.type === "text_delta") {
153
163
  controller.enqueue(
@@ -222,6 +232,16 @@ export function btwRouteDefinitions(deps: {
222
232
  endpoint: "btw",
223
233
  method: "POST",
224
234
  policyKey: "btw",
235
+ summary: "Run ephemeral LLM side-chain",
236
+ description:
237
+ "Stream an ephemeral LLM call reusing the conversation's provider and message history. Response is SSE (btw_text_delta, btw_complete, btw_error).",
238
+ tags: ["btw"],
239
+ requestBody: z.object({
240
+ conversationKey: z
241
+ .string()
242
+ .describe("Conversation key to scope the call"),
243
+ content: z.string().describe("User prompt content"),
244
+ }),
225
245
  handler: async ({ req, authContext }) =>
226
246
  handleBtw(req, deps, authContext),
227
247
  },
@@ -8,6 +8,8 @@
8
8
  * POST /v1/calls/:callSessionId/instruction — relay an instruction to an active call
9
9
  */
10
10
 
11
+ import { z } from "zod";
12
+
11
13
  import {
12
14
  answerCall,
13
15
  cancelCall,
@@ -288,31 +290,110 @@ export function callRouteDefinitions(deps: {
288
290
  {
289
291
  endpoint: "calls/start",
290
292
  method: "POST",
293
+ summary: "Start a call",
294
+ description:
295
+ "Initiate a new outbound phone call. Supports idempotency keys to prevent duplicate calls.",
296
+ tags: ["calls"],
291
297
  handler: async ({ req }) => handleStartCall(req, deps.assistantId),
298
+ requestBody: z.object({
299
+ phoneNumber: z.string().describe("Phone number to call").optional(),
300
+ task: z.string().describe("Task description for the call").optional(),
301
+ context: z
302
+ .string()
303
+ .describe("Additional context for the call")
304
+ .optional(),
305
+ conversationId: z.string().describe("Conversation to associate with"),
306
+ callerIdentityMode: z
307
+ .string()
308
+ .describe("Caller identity: 'assistant_number' or 'user_number'")
309
+ .optional(),
310
+ idempotencyKey: z
311
+ .string()
312
+ .describe("Idempotency key to prevent duplicate calls")
313
+ .optional(),
314
+ }),
315
+ responseBody: z.object({
316
+ callSessionId: z.string(),
317
+ callSid: z.string(),
318
+ status: z.string(),
319
+ toNumber: z.string(),
320
+ fromNumber: z.string(),
321
+ callerIdentityMode: z.string(),
322
+ }),
292
323
  },
293
324
  {
294
325
  endpoint: "calls/:id/cancel",
295
326
  method: "POST",
296
327
  policyKey: "calls/cancel",
328
+ summary: "Cancel a call",
329
+ description: "Cancel an active or pending call.",
330
+ tags: ["calls"],
297
331
  handler: async ({ req, params }) => handleCancelCall(req, params.id),
332
+ requestBody: z.object({
333
+ reason: z.string().describe("Cancellation reason"),
334
+ }),
335
+ responseBody: z.object({
336
+ callSessionId: z.string(),
337
+ status: z.string(),
338
+ }),
298
339
  },
299
340
  {
300
341
  endpoint: "calls/:id/answer",
301
342
  method: "POST",
302
343
  policyKey: "calls/answer",
344
+ summary: "Answer a pending call question",
345
+ description:
346
+ "Provide an answer to a pending question during an active call.",
347
+ tags: ["calls"],
303
348
  handler: async ({ req, params }) => handleAnswerCall(req, params.id),
349
+ requestBody: z.object({
350
+ answer: z.string().describe("Answer text"),
351
+ pendingQuestionId: z.string().describe("ID of the pending question"),
352
+ }),
353
+ responseBody: z.object({
354
+ ok: z.boolean(),
355
+ questionId: z.string(),
356
+ }),
304
357
  },
305
358
  {
306
359
  endpoint: "calls/:id/instruction",
307
360
  method: "POST",
308
361
  policyKey: "calls/instruction",
362
+ summary: "Relay instruction to active call",
363
+ description: "Send a real-time instruction to an active call.",
364
+ tags: ["calls"],
309
365
  handler: async ({ req, params }) => handleInstructionCall(req, params.id),
366
+ requestBody: z.object({
367
+ instruction: z.string().describe("Instruction text to relay"),
368
+ }),
369
+ responseBody: z.object({
370
+ ok: z.boolean(),
371
+ }),
310
372
  },
311
373
  {
312
374
  endpoint: "calls/:id",
313
375
  method: "GET",
314
376
  policyKey: "calls",
377
+ summary: "Get call status",
378
+ description: "Return the current status and details of a call session.",
379
+ tags: ["calls"],
315
380
  handler: ({ params }) => handleGetCallStatus(params.id),
381
+ responseBody: z.object({
382
+ callSessionId: z.string(),
383
+ conversationId: z.string(),
384
+ status: z.string(),
385
+ toNumber: z.string(),
386
+ fromNumber: z.string(),
387
+ provider: z.string(),
388
+ providerCallSid: z.string(),
389
+ task: z.string(),
390
+ startedAt: z.string(),
391
+ endedAt: z.string(),
392
+ lastError: z.string(),
393
+ pendingQuestion: z.object({}).passthrough(),
394
+ createdAt: z.string(),
395
+ updatedAt: z.string(),
396
+ }),
316
397
  },
317
398
  ];
318
399
  }
@@ -5,6 +5,8 @@
5
5
  * POST /v1/channels/readiness/refresh — invalidate cache and refresh readiness
6
6
  */
7
7
 
8
+ import { z } from "zod";
9
+
8
10
  import type { ChannelId } from "../../channels/types.js";
9
11
  import { getReadinessService } from "../../daemon/handlers/config-channels.js";
10
12
  import {
@@ -64,13 +66,18 @@ export async function handleRefreshChannelReadiness(
64
66
  req: Request,
65
67
  ): Promise<Response> {
66
68
  let body: { channel?: ChannelId; includeRemote?: boolean };
67
- try {
68
- body = (await req.json()) as typeof body;
69
- } catch {
70
- return Response.json(
71
- { success: false, error: "Invalid JSON in request body" },
72
- { status: 400 },
73
- );
69
+ const text = await req.text();
70
+ if (!text.trim()) {
71
+ body = {};
72
+ } else {
73
+ try {
74
+ body = JSON.parse(text) as typeof body;
75
+ } catch {
76
+ return Response.json(
77
+ { success: false, error: "Invalid JSON in request body" },
78
+ { status: 400 },
79
+ );
80
+ }
74
81
  }
75
82
 
76
83
  const service = getReadinessService();
@@ -123,12 +130,46 @@ export function channelReadinessRouteDefinitions(): RouteDefinition[] {
123
130
  {
124
131
  endpoint: "channels/readiness",
125
132
  method: "GET",
133
+ summary: "Get channel readiness",
134
+ description: "Return readiness snapshots for one or all channels.",
135
+ tags: ["channels"],
126
136
  handler: async ({ url }) => handleGetChannelReadiness(url),
137
+ queryParams: [
138
+ {
139
+ name: "channel",
140
+ schema: { type: "string" },
141
+ description: "Optional channel ID filter",
142
+ },
143
+ {
144
+ name: "includeRemote",
145
+ schema: { type: "string" },
146
+ description: "Include remote checks (default true)",
147
+ },
148
+ ],
149
+ responseBody: z.object({
150
+ success: z.boolean(),
151
+ snapshots: z.array(z.unknown()).describe("Channel readiness snapshots"),
152
+ }),
127
153
  },
128
154
  {
129
155
  endpoint: "channels/readiness/refresh",
130
156
  method: "POST",
157
+ summary: "Refresh channel readiness",
158
+ description: "Invalidate cache and re-evaluate channel readiness.",
159
+ tags: ["channels"],
131
160
  handler: async ({ req }) => handleRefreshChannelReadiness(req),
161
+ requestBody: z.object({
162
+ channel: z.string().describe("Optional channel ID to refresh"),
163
+ includeRemote: z
164
+ .boolean()
165
+ .describe("Include remote checks (default true)"),
166
+ }),
167
+ responseBody: z.object({
168
+ success: z.boolean(),
169
+ snapshots: z
170
+ .array(z.unknown())
171
+ .describe("Refreshed readiness snapshots"),
172
+ }),
132
173
  },
133
174
  ];
134
175
  }
@@ -8,6 +8,7 @@
8
8
  * - channel-guardian-routes.ts — guardian approval interception, expiry sweep
9
9
  */
10
10
 
11
+ import type { HeartbeatService } from "../../heartbeat/heartbeat-service.js";
11
12
  import type { RouteDefinition } from "../http-router.js";
12
13
  import type {
13
14
  ApprovalConversationGenerator,
@@ -53,17 +54,24 @@ export function channelRouteDefinitions(deps: {
53
54
  approvalConversationGenerator?: ApprovalConversationGenerator;
54
55
  guardianActionCopyGenerator?: GuardianActionCopyGenerator;
55
56
  guardianFollowUpConversationGenerator?: GuardianFollowUpConversationGenerator;
57
+ getHeartbeatService?: () => HeartbeatService | undefined;
56
58
  }): RouteDefinition[] {
57
59
  return [
58
60
  {
59
61
  endpoint: "channels/conversation",
60
62
  method: "DELETE",
63
+ summary: "Delete channel conversation",
64
+ description: "Delete a conversation by channel source.",
65
+ tags: ["channels"],
61
66
  handler: async ({ req }) =>
62
67
  _handleDeleteConversation(req, deps.assistantId),
63
68
  },
64
69
  {
65
70
  endpoint: "channels/inbound",
66
71
  method: "POST",
72
+ summary: "Process inbound channel message",
73
+ description: "Receive an inbound message from a channel integration.",
74
+ tags: ["channels"],
67
75
  handler: async ({ req }) =>
68
76
  _handleChannelInbound(
69
77
  req,
@@ -73,21 +81,31 @@ export function channelRouteDefinitions(deps: {
73
81
  deps.approvalConversationGenerator,
74
82
  deps.guardianActionCopyGenerator,
75
83
  deps.guardianFollowUpConversationGenerator,
84
+ deps.getHeartbeatService?.(),
76
85
  ),
77
86
  },
78
87
  {
79
88
  endpoint: "channels/delivery-ack",
80
89
  method: "POST",
90
+ summary: "Acknowledge channel delivery",
91
+ description: "Acknowledge delivery of a channel message.",
92
+ tags: ["channels"],
81
93
  handler: async ({ req }) => _handleChannelDeliveryAck(req),
82
94
  },
83
95
  {
84
96
  endpoint: "channels/dead-letters",
85
97
  method: "GET",
98
+ summary: "List dead letters",
99
+ description: "Return undeliverable channel messages.",
100
+ tags: ["channels"],
86
101
  handler: () => _handleListDeadLetters(),
87
102
  },
88
103
  {
89
104
  endpoint: "channels/replay",
90
105
  method: "POST",
106
+ summary: "Replay dead letters",
107
+ description: "Retry delivery of dead-letter messages.",
108
+ tags: ["channels"],
91
109
  handler: async ({ req }) => _handleReplayDeadLetters(req),
92
110
  },
93
111
  ];