@vellumai/assistant 0.8.12 → 0.9.0-staging.2

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 (442) hide show
  1. package/AGENTS.md +0 -14
  2. package/ARCHITECTURE.md +45 -45
  3. package/README.md +1 -1
  4. package/bun.lock +200 -154
  5. package/docs/architecture/integrations.md +3 -3
  6. package/docs/architecture/memory.md +2 -2
  7. package/docs/architecture/security.md +10 -10
  8. package/docs/runbook-trusted-contacts.md +12 -12
  9. package/docs/skills.md +6 -6
  10. package/docs/workflows-testing.md +221 -0
  11. package/docs/workflows.md +510 -0
  12. package/examples/plugins/echo/README.md +5 -5
  13. package/knip.json +2 -0
  14. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +105 -0
  15. package/node_modules/@vellumai/gateway-client/src/index.ts +12 -0
  16. package/openapi.yaml +7197 -5708
  17. package/package.json +8 -4
  18. package/scripts/generate-openapi.ts +66 -114
  19. package/src/__tests__/access-request-seed-content-blocks.test.ts +213 -0
  20. package/src/__tests__/adaptive-thinking-repair.test.ts +32 -3
  21. package/src/__tests__/agent-loop-output-hooks.test.ts +183 -0
  22. package/src/__tests__/agent-loop-regrowth-guard.test.ts +506 -0
  23. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  24. package/src/__tests__/agent-wake-override-profile.test.ts +77 -0
  25. package/src/__tests__/app-compiler.test.ts +7 -1
  26. package/src/__tests__/app-dir-path-guard.test.ts +27 -3
  27. package/src/__tests__/app-executors.test.ts +43 -0
  28. package/src/__tests__/approval-cascade.test.ts +0 -5
  29. package/src/__tests__/approval-routes-http.test.ts +91 -0
  30. package/src/__tests__/assistant-stream-state.test.ts +107 -0
  31. package/src/__tests__/browser-fill-credential.test.ts +3 -3
  32. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +1 -1
  33. package/src/__tests__/compaction-events.test.ts +63 -7
  34. package/src/__tests__/compaction-trail-store.test.ts +74 -1
  35. package/src/__tests__/compaction.benchmark.test.ts +63 -41
  36. package/src/__tests__/compactor-low-watermark-cut.test.ts +349 -0
  37. package/src/__tests__/context-window-manager-compact-retry.test.ts +64 -0
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -5
  39. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -5
  40. package/src/__tests__/conversation-history-web-search.test.ts +7 -0
  41. package/src/__tests__/conversation-process-callsite.test.ts +0 -5
  42. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -5
  43. package/src/__tests__/conversation-queue.test.ts +0 -5
  44. package/src/__tests__/conversation-slash-queue.test.ts +0 -5
  45. package/src/__tests__/conversation-slash-unknown.test.ts +0 -5
  46. package/src/__tests__/conversation-speed-override.test.ts +0 -5
  47. package/src/__tests__/conversation-surfaces-data-persist.test.ts +97 -0
  48. package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
  49. package/src/__tests__/conversation-usage.test.ts +2 -0
  50. package/src/__tests__/conversation-workspace-injection.test.ts +0 -5
  51. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -5
  52. package/src/__tests__/credential-broker-browser-fill.test.ts +2 -2
  53. package/src/__tests__/credential-broker-server-use.test.ts +2 -2
  54. package/src/__tests__/credential-broker.test.ts +1 -1
  55. package/src/__tests__/credential-prompt-route.test.ts +417 -0
  56. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  57. package/src/__tests__/credential-vault.test.ts +37 -0
  58. package/src/__tests__/db-schedule-syntax-migration.test.ts +24 -0
  59. package/src/__tests__/dynamic-page-surface.test.ts +219 -0
  60. package/src/__tests__/empty-state-greeting-cache.test.ts +94 -0
  61. package/src/__tests__/gateway-flag-listener.test.ts +24 -7
  62. package/src/__tests__/guardian-action-sweep.test.ts +56 -219
  63. package/src/__tests__/guardian-routing-invariants.test.ts +138 -0
  64. package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
  65. package/src/__tests__/list-messages-hidden-metadata.test.ts +99 -0
  66. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +87 -1
  67. package/src/__tests__/llm-resolver.test.ts +115 -0
  68. package/src/__tests__/managed-profile-guard.test.ts +6 -5
  69. package/src/__tests__/max-tokens-continue-hook.test.ts +184 -0
  70. package/src/__tests__/media-generate-image.test.ts +20 -9
  71. package/src/__tests__/mock-gateway-ipc.ts +23 -0
  72. package/src/__tests__/model-intents.test.ts +1 -1
  73. package/src/__tests__/normalize-onboarding.test.ts +26 -0
  74. package/src/__tests__/notification-decision-strategy.test.ts +4 -2
  75. package/src/__tests__/notification-telegram-adapter.test.ts +21 -3
  76. package/src/__tests__/pending-interactions-resolved-event.test.ts +62 -0
  77. package/src/__tests__/post-turn-tool-result-truncation.test.ts +72 -18
  78. package/src/__tests__/require-fresh-approval.test.ts +425 -1
  79. package/src/__tests__/resolve-app-id.test.ts +56 -0
  80. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -0
  81. package/src/__tests__/schedule-routes-workflow-validation.test.ts +408 -0
  82. package/src/__tests__/schedule-routes.test.ts +257 -4
  83. package/src/__tests__/schedule-store.test.ts +60 -0
  84. package/src/__tests__/schedule-tools.test.ts +247 -2
  85. package/src/__tests__/skill-execute-input.test.ts +85 -0
  86. package/src/__tests__/skill-secret-handling-guard.test.ts +21 -20
  87. package/src/__tests__/skills.test.ts +3 -3
  88. package/src/__tests__/slack-app-setup-skill-regression.test.ts +1 -1
  89. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  90. package/src/__tests__/subagent-tool-gate-mode.test.ts +547 -0
  91. package/src/__tests__/system-prompt.test.ts +1 -1
  92. package/src/__tests__/task-progress-nudge-hook.test.ts +372 -0
  93. package/src/__tests__/task-scheduler.test.ts +299 -0
  94. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +209 -0
  95. package/src/__tests__/tool-result-spool.test.ts +3 -1
  96. package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +181 -0
  97. package/src/__tests__/workspace-migration-103-upgrade-quality-profile-to-opus-4-8.test.ts +174 -0
  98. package/src/agent/compaction-circuit.ts +11 -0
  99. package/src/agent/loop.ts +181 -12
  100. package/src/api/constants/call-sites.ts +12 -0
  101. package/src/api/events/assistant-thinking-delta.ts +10 -0
  102. package/src/api/events/usage-update.ts +7 -0
  103. package/src/api/index.ts +4 -1
  104. package/src/api/responses/memory-v3-selection-log.ts +18 -11
  105. package/src/approvals/approval-primitive.ts +2 -2
  106. package/src/background-wake/background-wake-routes.test.ts +5 -2
  107. package/src/bundler/compiler-tools.ts +1 -1
  108. package/src/bundler/package-resolver.ts +0 -1
  109. package/src/calls/call-domain.ts +1 -1
  110. package/src/calls/guardian-action-sweep.ts +16 -93
  111. package/src/cli/AGENTS.md +4 -0
  112. package/src/cli/commands/__tests__/schedules.test.ts +430 -1
  113. package/src/cli/commands/credentials.ts +28 -24
  114. package/src/cli/commands/image-generation.ts +23 -9
  115. package/src/cli/commands/notifications.ts +1 -1
  116. package/src/cli/commands/plugins.ts +89 -46
  117. package/src/cli/commands/schedules.ts +384 -11
  118. package/src/cli/lib/__tests__/inspect-plugin.test.ts +69 -5
  119. package/src/cli/lib/__tests__/install-from-github.test.ts +15 -0
  120. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +81 -4
  121. package/src/cli/lib/inspect-plugin.ts +62 -1
  122. package/src/cli/lib/install-from-github.ts +52 -5
  123. package/src/cli/lib/upgrade-plugin.ts +18 -0
  124. package/src/config/__tests__/workflows-schema.test.ts +60 -0
  125. package/src/config/bundled-skills/acp/SKILL.md +2 -2
  126. package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
  127. package/src/config/bundled-skills/app-builder/tools/app-create.ts +6 -1
  128. package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +7 -1
  129. package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +7 -1
  130. package/src/config/bundled-skills/app-builder/tools/app-update.ts +10 -1
  131. package/src/config/bundled-skills/image-studio/SKILL.md +66 -19
  132. package/src/config/bundled-skills/image-studio/TOOLS.json +1 -6
  133. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +22 -3
  134. package/src/config/bundled-skills/personal-page/SKILL.md +57 -0
  135. package/src/config/bundled-skills/personal-page/TOOLS.json +27 -0
  136. package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +17 -0
  137. package/src/config/bundled-skills/schedule/SKILL.md +7 -2
  138. package/src/config/bundled-skills/schedule/TOOLS.json +48 -4
  139. package/src/config/bundled-skills/workflows/SKILL.md +214 -0
  140. package/src/config/bundled-skills/workflows/TOOLS.json +84 -0
  141. package/src/config/bundled-skills/workflows/tools/manage-workflows.ts +12 -0
  142. package/src/config/bundled-skills/workflows/tools/run-workflow.ts +12 -0
  143. package/src/config/bundled-tool-registry.ts +14 -2
  144. package/src/config/call-site-defaults.ts +5 -0
  145. package/src/config/feature-flag-registry.json +12 -4
  146. package/src/config/llm-context-resolution.ts +8 -0
  147. package/src/config/llm-resolver.ts +30 -0
  148. package/src/config/preloaded-apps/personal-page/src/components/About.tsx +22 -0
  149. package/src/config/preloaded-apps/personal-page/src/components/App.tsx +16 -0
  150. package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +77 -0
  151. package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +57 -0
  152. package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +28 -0
  153. package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +234 -0
  154. package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +48 -0
  155. package/src/config/preloaded-apps/personal-page/src/components/media.ts +16 -0
  156. package/src/config/preloaded-apps/personal-page/src/index.html +20 -0
  157. package/src/config/preloaded-apps/personal-page/src/main.tsx +7 -0
  158. package/src/config/preloaded-apps/personal-page/src/profile-data.ts +82 -0
  159. package/src/config/preloaded-apps/personal-page/src/styles.css +759 -0
  160. package/src/config/schema.ts +2 -0
  161. package/src/config/schemas/call-site-catalog.ts +7 -0
  162. package/src/config/schemas/heartbeat.ts +4 -1
  163. package/src/config/schemas/llm.ts +33 -26
  164. package/src/config/schemas/memory-retrospective.ts +19 -0
  165. package/src/config/schemas/platform.ts +8 -0
  166. package/src/config/schemas/services.ts +5 -2
  167. package/src/config/schemas/workflows.ts +42 -0
  168. package/src/config/skills.ts +3 -3
  169. package/src/context/compactor.ts +273 -39
  170. package/src/context/post-turn-tool-result-truncation.ts +23 -6
  171. package/src/context/tool-result-spool.ts +12 -17
  172. package/src/credential-execution/executable-discovery.ts +1 -1
  173. package/src/credential-execution/process-manager.ts +37 -3
  174. package/src/credential-execution/prompted-credential.ts +205 -0
  175. package/src/daemon/conversation-agent-loop-handlers.ts +14 -0
  176. package/src/daemon/conversation-process.ts +11 -2
  177. package/src/daemon/conversation-surfaces.ts +167 -3
  178. package/src/daemon/conversation-tool-setup.ts +103 -26
  179. package/src/daemon/conversation-usage.ts +2 -0
  180. package/src/daemon/conversation.ts +115 -11
  181. package/src/daemon/handlers/shared.ts +26 -14
  182. package/src/daemon/host-cu-proxy.ts +15 -12
  183. package/src/daemon/host-file-proxy.ts +15 -12
  184. package/src/daemon/host-transfer-proxy.ts +30 -24
  185. package/src/daemon/lifecycle.ts +40 -3
  186. package/src/daemon/message-protocol.ts +3 -0
  187. package/src/daemon/message-types/messages.ts +2 -10
  188. package/src/daemon/message-types/workflows.ts +49 -0
  189. package/src/daemon/parse-actual-tokens-from-error.test.ts +62 -1
  190. package/src/daemon/parse-actual-tokens-from-error.ts +43 -4
  191. package/src/daemon/process-message.ts +6 -0
  192. package/src/daemon/tool-setup-types.ts +57 -0
  193. package/src/daemon/wake-conversation-ops.ts +18 -0
  194. package/src/heartbeat/heartbeat-run-store.ts +8 -2
  195. package/src/home/feed-types.ts +1 -1
  196. package/src/ipc/gateway-flag-listener.ts +28 -6
  197. package/src/mcp/mcp-auth-state.ts +8 -20
  198. package/src/media/__tests__/image-models.test.ts +57 -0
  199. package/src/media/image-models.ts +66 -0
  200. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +38 -0
  201. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +12 -2
  202. package/src/memory/__tests__/memory-retrospective-job.test.ts +911 -34
  203. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +227 -5
  204. package/src/memory/__tests__/memory-retrospective-state.test.ts +195 -0
  205. package/src/memory/__tests__/preloaded-apps.test.ts +85 -0
  206. package/src/memory/auto-analysis-enqueue.ts +14 -1
  207. package/src/memory/compaction-log-store-clickhouse.ts +6 -4
  208. package/src/memory/conversation-crud.ts +9 -2
  209. package/src/memory/conversation-disk-view.ts +1 -1
  210. package/src/memory/conversation-queries.ts +22 -7
  211. package/src/memory/db-init.ts +20 -0
  212. package/src/memory/db-maintenance.ts +16 -0
  213. package/src/memory/embedding-runtime-manager.ts +1 -1
  214. package/src/memory/llm-request-log-source-clickhouse.ts +112 -14
  215. package/src/memory/llm-request-log-source-local.ts +19 -1
  216. package/src/memory/llm-request-log-source.ts +35 -6
  217. package/src/memory/llm-request-log-store.ts +90 -2
  218. package/src/memory/memory-retrospective-constants.ts +9 -0
  219. package/src/memory/memory-retrospective-enqueue.ts +3 -6
  220. package/src/memory/memory-retrospective-fork-boundary.ts +94 -0
  221. package/src/memory/memory-retrospective-job.ts +500 -208
  222. package/src/memory/memory-retrospective-startup-cleanup.ts +97 -19
  223. package/src/memory/memory-retrospective-state.ts +85 -2
  224. package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +40 -0
  225. package/src/memory/migrations/282-schedule-inference-profile.test.ts +77 -0
  226. package/src/memory/migrations/282-schedule-inference-profile.ts +26 -0
  227. package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.test.ts +102 -0
  228. package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.ts +53 -0
  229. package/src/memory/migrations/284-workflow-runs.ts +51 -0
  230. package/src/memory/migrations/285-schedule-workflow-mode.ts +26 -0
  231. package/src/memory/migrations/286-workflow-run-trust.ts +27 -0
  232. package/src/memory/migrations/287-conversation-origin-channel-index.ts +15 -0
  233. package/src/memory/migrations/288-backfill-origin-channel-from-bindings.ts +43 -0
  234. package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +115 -0
  235. package/src/memory/migrations/290-schedule-capabilities.test.ts +77 -0
  236. package/src/memory/migrations/290-schedule-capabilities.ts +25 -0
  237. package/src/memory/migrations/__tests__/281-memory-retrospective-remembered-log.test.ts +96 -0
  238. package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +571 -0
  239. package/src/memory/migrations/index.ts +10 -0
  240. package/src/memory/preloaded-apps.ts +116 -0
  241. package/src/memory/schema/infrastructure.ts +4 -0
  242. package/src/memory/schema/memory-core.ts +4 -0
  243. package/src/memory/v2/__tests__/concept-page-frontmatter-schema.test.ts +45 -0
  244. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +11 -7
  245. package/src/memory/v2/__tests__/page-store.test.ts +13 -2
  246. package/src/memory/v2/__tests__/qdrant.test.ts +24 -0
  247. package/src/memory/v2/frontmatter-sweep.ts +7 -6
  248. package/src/memory/v2/page-store.ts +4 -3
  249. package/src/memory/v2/qdrant.ts +42 -3
  250. package/src/memory/v2/types.ts +16 -10
  251. package/src/messaging/draft-store.ts +1 -1
  252. package/src/notifications/access-request-copy.ts +200 -113
  253. package/src/notifications/adapters/slack.ts +250 -111
  254. package/src/notifications/adapters/telegram.ts +7 -44
  255. package/src/notifications/approval-card-builder.ts +93 -0
  256. package/src/notifications/broadcaster.ts +74 -0
  257. package/src/notifications/conversation-pairing.ts +8 -6
  258. package/src/notifications/copy-composer.ts +32 -26
  259. package/src/notifications/decision-engine.ts +59 -7
  260. package/src/notifications/guardian-question-mode.ts +145 -155
  261. package/src/notifications/home-feed-side-effect.ts +28 -11
  262. package/src/notifications/notification-utils.ts +66 -0
  263. package/src/notifications/signal.ts +6 -0
  264. package/src/notifications/tool-approval-copy.ts +142 -0
  265. package/src/notifications/types.ts +19 -0
  266. package/src/permissions/threshold.ts +11 -0
  267. package/src/plugin-api/types.ts +16 -4
  268. package/src/plugins/defaults/compaction/window-manager.ts +44 -0
  269. package/src/plugins/defaults/index.ts +46 -0
  270. package/src/plugins/defaults/max-tokens-continue/continue-state-store.ts +53 -0
  271. package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +80 -0
  272. package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +20 -0
  273. package/src/plugins/defaults/max-tokens-continue/package.json +14 -0
  274. package/src/plugins/defaults/memory-retrieval/hooks/__tests__/user-prompt-submit.test.ts +37 -0
  275. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +29 -1
  276. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +8 -3
  277. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +4 -2
  278. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +28 -18
  279. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +67 -0
  280. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +122 -22
  281. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +2 -0
  282. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +63 -1
  283. package/src/plugins/defaults/memory-v3-shadow/injector.ts +61 -18
  284. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +1 -1
  285. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +39 -10
  286. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +34 -1
  287. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +112 -47
  288. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +78 -15
  289. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +206 -0
  290. package/src/plugins/defaults/task-progress-nudge/package.json +15 -0
  291. package/src/prompts/__tests__/system-prompt.test.ts +100 -1
  292. package/src/prompts/__tests__/task-progress-hint-section.test.ts +5 -7
  293. package/src/prompts/normalize-onboarding.ts +2 -0
  294. package/src/prompts/persona-resolver.ts +3 -0
  295. package/src/prompts/system-prompt.ts +51 -2
  296. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +3 -1
  297. package/src/prompts/templates/system-sections.ts +8 -3
  298. package/src/providers/call-site-routing.ts +6 -3
  299. package/src/providers/fireworks/client.ts +3 -0
  300. package/src/providers/inference/auth.ts +52 -46
  301. package/src/providers/model-intents.ts +2 -2
  302. package/src/providers/openai/__tests__/coerce-object-args.test.ts +105 -0
  303. package/src/providers/openai/chat-completions-provider.ts +47 -9
  304. package/src/providers/openai/coerce-object-args.ts +104 -0
  305. package/src/providers/retry.ts +8 -5
  306. package/src/providers/types.ts +10 -0
  307. package/src/runtime/__tests__/agent-wake.test.ts +629 -7
  308. package/src/runtime/access-request-helper.ts +16 -9
  309. package/src/runtime/agent-wake.ts +302 -51
  310. package/src/runtime/assistant-stream-state.ts +141 -8
  311. package/src/runtime/background-job-runner.ts +9 -0
  312. package/src/runtime/channel-approval-types.ts +1 -0
  313. package/src/runtime/channel-invite-transports/telegram.ts +6 -5
  314. package/src/runtime/channel-invite-transports/voice.ts +2 -2
  315. package/src/runtime/channel-invite-types.ts +4 -2
  316. package/src/runtime/channel-retry-sweep.ts +19 -41
  317. package/src/runtime/finalize-event-delivery.ts +72 -0
  318. package/src/runtime/guardian-action-message-composer.ts +0 -54
  319. package/src/runtime/http-server.ts +6 -14
  320. package/src/runtime/http-types.ts +0 -1
  321. package/src/runtime/message-composer-types.ts +0 -9
  322. package/src/runtime/middleware/__tests__/rate-limiter.test.ts +63 -0
  323. package/src/runtime/middleware/auth.ts +27 -3
  324. package/src/runtime/middleware/rate-limiter.ts +28 -1
  325. package/src/runtime/migrations/vbundle-builder.ts +6 -5
  326. package/src/runtime/pending-interactions.ts +20 -1
  327. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +232 -173
  328. package/src/runtime/routes/__tests__/plugins-routes.test.ts +18 -0
  329. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +436 -0
  330. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +11 -0
  331. package/src/runtime/routes/approval-routes.ts +35 -8
  332. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -1
  333. package/src/runtime/routes/btw-routes.ts +37 -1
  334. package/src/runtime/routes/channel-delivery-routes.ts +11 -7
  335. package/src/runtime/routes/channel-route-definitions.ts +3 -0
  336. package/src/runtime/routes/channel-route-shared.ts +3 -1
  337. package/src/runtime/routes/consolidation-routes.ts +17 -13
  338. package/src/runtime/routes/conversation-compaction-routes.ts +159 -119
  339. package/src/runtime/routes/conversation-list-routes.ts +41 -4
  340. package/src/runtime/routes/conversation-query-routes.ts +196 -11
  341. package/src/runtime/routes/conversation-routes.ts +15 -1
  342. package/src/runtime/routes/credential-prompt-routes.ts +39 -17
  343. package/src/runtime/routes/empty-state-greeting-cache.ts +65 -0
  344. package/src/runtime/routes/heartbeat-routes.ts +18 -13
  345. package/src/runtime/routes/image-generation-routes.ts +20 -2
  346. package/src/runtime/routes/inbound-message-handler.ts +13 -12
  347. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +32 -31
  348. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +7 -5
  349. package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -21
  350. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
  351. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +6 -15
  352. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +1 -1
  353. package/src/runtime/routes/index.ts +6 -0
  354. package/src/runtime/routes/log-export/AGENTS.md +1 -1
  355. package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
  356. package/src/runtime/routes/migration-routes.ts +5 -9
  357. package/src/runtime/routes/plugins-routes.ts +26 -0
  358. package/src/runtime/routes/ps-routes.ts +10 -8
  359. package/src/runtime/routes/retrospective-routes.ts +235 -0
  360. package/src/runtime/routes/runs-pagination.ts +75 -0
  361. package/src/runtime/routes/schedule-routes.ts +367 -59
  362. package/src/runtime/routes/sounds-config-routes.ts +239 -0
  363. package/src/runtime/routes/surface-action-routes.ts +84 -4
  364. package/src/runtime/routes/workflow-routes.test.ts +372 -0
  365. package/src/runtime/routes/workflow-routes.ts +363 -0
  366. package/src/runtime/routes/workspace-routes.test.ts +61 -1
  367. package/src/runtime/routes/workspace-routes.ts +26 -1
  368. package/src/runtime/services/__tests__/analyze-conversation.test.ts +38 -0
  369. package/src/runtime/services/analyze-conversation.ts +26 -13
  370. package/src/schedule/inference-profile.ts +28 -0
  371. package/src/schedule/schedule-store.ts +152 -4
  372. package/src/schedule/scheduler-types.ts +6 -0
  373. package/src/schedule/scheduler.ts +96 -0
  374. package/src/security/secret-allowlist.ts +1 -1
  375. package/src/skills/path-classifier.ts +1 -1
  376. package/src/tools/apps/executors.ts +23 -0
  377. package/src/tools/apps/resolve-app-id.ts +42 -0
  378. package/src/tools/browser/browser-execution.ts +9 -11
  379. package/src/tools/credentials/broker.ts +4 -4
  380. package/src/tools/credentials/vault.ts +26 -137
  381. package/src/tools/executor.ts +69 -0
  382. package/src/tools/flag-gated-tools.test.ts +76 -0
  383. package/src/tools/permission-checker.ts +8 -1
  384. package/src/tools/registry.ts +51 -0
  385. package/src/tools/schedule/create.ts +77 -1
  386. package/src/tools/schedule/list.ts +1 -0
  387. package/src/tools/schedule/update.ts +73 -1
  388. package/src/tools/skills/execute.ts +56 -0
  389. package/src/tools/terminal/shell.ts +1 -1
  390. package/src/tools/ui-surface/definitions.ts +91 -2
  391. package/src/tools/workflows/manage-workflows.ts +183 -0
  392. package/src/tools/workflows/run-workflow.test.ts +442 -0
  393. package/src/tools/workflows/run-workflow.ts +88 -0
  394. package/src/types/onboarding-context.ts +2 -0
  395. package/src/usage/attribution.ts +24 -0
  396. package/src/util/canonicalize-identity.ts +12 -3
  397. package/src/util/platform.ts +17 -17
  398. package/src/watcher/__tests__/engine.test.ts +24 -0
  399. package/src/watcher/__tests__/telemetry.test.ts +135 -0
  400. package/src/watcher/engine.ts +7 -0
  401. package/src/watcher/telemetry.ts +74 -0
  402. package/src/workflows/capabilities.test.ts +365 -0
  403. package/src/workflows/capabilities.ts +359 -0
  404. package/src/workflows/deterministic-stringify.ts +27 -0
  405. package/src/workflows/engine-integration.test.ts +656 -0
  406. package/src/workflows/engine.test.ts +1144 -0
  407. package/src/workflows/engine.ts +1078 -0
  408. package/src/workflows/fanout-load.test.ts +168 -0
  409. package/src/workflows/journal-store.test.ts +369 -0
  410. package/src/workflows/journal-store.ts +470 -0
  411. package/src/workflows/leaf-runner.test.ts +704 -0
  412. package/src/workflows/leaf-runner.ts +589 -0
  413. package/src/workflows/library.test.ts +134 -0
  414. package/src/workflows/library.ts +124 -0
  415. package/src/workflows/run-manager.test.ts +711 -0
  416. package/src/workflows/run-manager.ts +593 -0
  417. package/src/workflows/sandbox-escape.test.ts +339 -0
  418. package/src/workflows/sandbox.test.ts +251 -0
  419. package/src/workflows/sandbox.ts +447 -0
  420. package/src/workspace/adaptive-thinking-repair.ts +33 -11
  421. package/src/workspace/migrations/021-move-signals-to-workspace.ts +1 -1
  422. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +1 -1
  423. package/src/workspace/migrations/026-backfill-install-meta.ts +1 -1
  424. package/src/workspace/migrations/030-seed-pkb-autoinject.ts +2 -1
  425. package/src/workspace/migrations/031-drop-user-md.ts +1 -4
  426. package/src/workspace/migrations/048-remove-workspace-hooks.ts +1 -1
  427. package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +5 -2
  428. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +1 -1
  429. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +8 -2
  430. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +41 -14
  431. package/src/workspace/migrations/102-preserve-heartbeat-enabled-for-existing-workspaces.ts +69 -0
  432. package/src/workspace/migrations/103-upgrade-quality-profile-to-opus-4-8.ts +83 -0
  433. package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +133 -0
  434. package/src/workspace/migrations/registry.ts +6 -0
  435. package/src/workspace/migrations/runner.ts +1 -1
  436. package/tsconfig.json +1 -1
  437. package/src/__tests__/guardian-action-copy-generator.test.ts +0 -200
  438. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -579
  439. package/src/__tests__/guardian-action-store.test.ts +0 -106
  440. package/src/daemon/guardian-action-generators.ts +0 -71
  441. package/src/memory/guardian-action-store.ts +0 -484
  442. package/src/runtime/guardian-action-grant-minter.ts +0 -150
@@ -1,71 +0,0 @@
1
- import { loadConfig } from "../config/loader.js";
2
- import { wrapWithCallSiteRouting } from "../providers/call-site-routing.js";
3
- import { getConfiguredProvider } from "../providers/provider-send-message.js";
4
- import {
5
- buildGuardianActionGenerationPrompt,
6
- getGuardianActionFallbackMessage,
7
- GUARDIAN_ACTION_COPY_MAX_TOKENS,
8
- GUARDIAN_ACTION_COPY_SYSTEM_PROMPT,
9
- GUARDIAN_ACTION_COPY_TIMEOUT_MS,
10
- includesRequiredKeywords,
11
- } from "../runtime/guardian-action-message-composer.js";
12
- import type { GuardianActionCopyGenerator } from "../runtime/http-types.js";
13
-
14
- /**
15
- * Create the daemon-owned guardian action copy generator that resolves
16
- * providers and calls `provider.sendMessage` to generate guardian action
17
- * copy text. Uses the `guardianQuestionCopy` call site so model selection
18
- * tracks the unified `llm.callSites` configuration.
19
- *
20
- * This keeps all provider awareness in the daemon lifecycle, away from
21
- * the runtime composer.
22
- */
23
- export function createGuardianActionCopyGenerator(): GuardianActionCopyGenerator {
24
- return async (context, options = {}) => {
25
- const baseProvider = await getConfiguredProvider("guardianQuestionCopy");
26
- if (!baseProvider) return null;
27
- // Wrap so the per-call `callSite` can route to a different provider
28
- // transport when `llm.callSites.guardianQuestionCopy.provider` overrides
29
- // the default. Connection-aware: when the resolved profile names a
30
- // `provider_connection`, that connection's auth wins over the legacy
31
- // registry lookup. See `wrapWithCallSiteRouting`.
32
- const provider = wrapWithCallSiteRouting(baseProvider, loadConfig());
33
-
34
- const fallbackText =
35
- options.fallbackText?.trim() || getGuardianActionFallbackMessage(context);
36
- const requiredKeywords = options.requiredKeywords
37
- ?.map((kw) => kw.trim())
38
- .filter((kw) => kw.length > 0);
39
- const prompt = buildGuardianActionGenerationPrompt(
40
- context,
41
- fallbackText,
42
- requiredKeywords,
43
- );
44
-
45
- const response = await provider.sendMessage(
46
- [{ role: "user", content: [{ type: "text", text: prompt }] }],
47
- {
48
- tools: [],
49
- systemPrompt: GUARDIAN_ACTION_COPY_SYSTEM_PROMPT,
50
- config: {
51
- max_tokens: options.maxTokens ?? GUARDIAN_ACTION_COPY_MAX_TOKENS,
52
- callSite: "guardianQuestionCopy",
53
- },
54
- signal: AbortSignal.timeout(
55
- options.timeoutMs ?? GUARDIAN_ACTION_COPY_TIMEOUT_MS,
56
- ),
57
- },
58
- );
59
-
60
- const block = response.content.find((entry) => entry.type === "text");
61
- const text = block && "text" in block ? block.text.trim() : "";
62
- if (!text) return null;
63
- const cleaned = text
64
- .replace(/^["'`]+/, "")
65
- .replace(/["'`]+$/, "")
66
- .trim();
67
- if (!cleaned) return null;
68
- if (!includesRequiredKeywords(cleaned, requiredKeywords)) return null;
69
- return cleaned;
70
- };
71
- }
@@ -1,484 +0,0 @@
1
- /**
2
- * Store for cross-channel guardian action requests and deliveries.
3
- *
4
- * Guardian action requests are created when a voice call's ASK_GUARDIAN
5
- * marker fires, and deliveries track per-channel dispatch (telegram, mac).
6
- * Resolution uses first-response-wins semantics: the first channel to
7
- * answer resolves the request and all other deliveries are marked answered.
8
- */
9
-
10
- import { and, desc, eq, inArray, lt } from "drizzle-orm";
11
- import { v4 as uuid } from "uuid";
12
-
13
- import { getDb } from "./db-connection.js";
14
- import { rawChanges } from "./raw-query.js";
15
- import { guardianActionDeliveries, guardianActionRequests } from "./schema.js";
16
-
17
- // ---------------------------------------------------------------------------
18
- // Types
19
- // ---------------------------------------------------------------------------
20
-
21
- export type GuardianActionRequestStatus =
22
- | "pending"
23
- | "answered"
24
- | "expired"
25
- | "cancelled";
26
- export type GuardianActionDeliveryStatus =
27
- | "pending"
28
- | "sent"
29
- | "failed"
30
- | "answered"
31
- | "expired"
32
- | "cancelled";
33
- export type ExpiredReason =
34
- | "call_timeout"
35
- | "sweep_timeout"
36
- | "cancelled"
37
- | "superseded";
38
- export type FollowupState =
39
- | "none"
40
- | "awaiting_guardian_choice"
41
- | "dispatching"
42
- | "completed"
43
- | "declined"
44
- | "failed";
45
- /** Follow-up action recorded on a request row (column retained). */
46
- export type FollowupAction = "call_back" | "decline";
47
-
48
- export interface GuardianActionRequest {
49
- id: string;
50
- kind: string;
51
- sourceChannel: string;
52
- sourceConversationId: string;
53
- callSessionId: string;
54
- pendingQuestionId: string;
55
- questionText: string;
56
- requestCode: string;
57
- status: GuardianActionRequestStatus;
58
- answerText: string | null;
59
- answeredByChannel: string | null;
60
- answeredByExternalUserId: string | null;
61
- answeredAt: number | null;
62
- expiresAt: number;
63
- expiredReason: ExpiredReason | null;
64
- followupState: FollowupState;
65
- lateAnswerText: string | null;
66
- lateAnsweredAt: number | null;
67
- followupAction: FollowupAction | null;
68
- followupCompletedAt: number | null;
69
- toolName: string | null;
70
- inputDigest: string | null;
71
- supersededByRequestId: string | null;
72
- supersededAt: number | null;
73
- createdAt: number;
74
- updatedAt: number;
75
- }
76
-
77
- export interface GuardianActionDelivery {
78
- id: string;
79
- requestId: string;
80
- destinationChannel: string;
81
- destinationConversationId: string | null;
82
- destinationChatId: string | null;
83
- destinationExternalUserId: string | null;
84
- status: GuardianActionDeliveryStatus;
85
- sentAt: number | null;
86
- respondedAt: number | null;
87
- lastError: string | null;
88
- createdAt: number;
89
- updatedAt: number;
90
- }
91
-
92
- // ---------------------------------------------------------------------------
93
- // Helpers
94
- // ---------------------------------------------------------------------------
95
-
96
- function rowToRequest(
97
- row: typeof guardianActionRequests.$inferSelect,
98
- ): GuardianActionRequest {
99
- return {
100
- id: row.id,
101
- kind: row.kind,
102
- sourceChannel: row.sourceChannel,
103
- sourceConversationId: row.sourceConversationId,
104
- callSessionId: row.callSessionId,
105
- pendingQuestionId: row.pendingQuestionId,
106
- questionText: row.questionText,
107
- requestCode: row.requestCode,
108
- status: row.status as GuardianActionRequestStatus,
109
- answerText: row.answerText,
110
- answeredByChannel: row.answeredByChannel,
111
- answeredByExternalUserId: row.answeredByExternalUserId,
112
- answeredAt: row.answeredAt,
113
- expiresAt: row.expiresAt,
114
- expiredReason: (row.expiredReason as ExpiredReason) ?? null,
115
- followupState: (row.followupState as FollowupState) ?? "none",
116
- lateAnswerText: row.lateAnswerText ?? null,
117
- lateAnsweredAt: row.lateAnsweredAt ?? null,
118
- followupAction: (row.followupAction as FollowupAction) ?? null,
119
- followupCompletedAt: row.followupCompletedAt ?? null,
120
- toolName: row.toolName ?? null,
121
- inputDigest: row.inputDigest ?? null,
122
- supersededByRequestId: row.supersededByRequestId ?? null,
123
- supersededAt: row.supersededAt ?? null,
124
- createdAt: row.createdAt,
125
- updatedAt: row.updatedAt,
126
- };
127
- }
128
-
129
- function rowToDelivery(
130
- row: typeof guardianActionDeliveries.$inferSelect,
131
- ): GuardianActionDelivery {
132
- return {
133
- id: row.id,
134
- requestId: row.requestId,
135
- destinationChannel: row.destinationChannel,
136
- destinationConversationId: row.destinationConversationId,
137
- destinationChatId: row.destinationChatId,
138
- destinationExternalUserId: row.destinationExternalUserId,
139
- status: row.status as GuardianActionDeliveryStatus,
140
- sentAt: row.sentAt,
141
- respondedAt: row.respondedAt,
142
- lastError: row.lastError,
143
- createdAt: row.createdAt,
144
- updatedAt: row.updatedAt,
145
- };
146
- }
147
-
148
- /** Generate a short human-readable request code (6 hex chars). */
149
- function generateRequestCode(): string {
150
- return uuid().replace(/-/g, "").slice(0, 6).toUpperCase();
151
- }
152
-
153
- // ---------------------------------------------------------------------------
154
- // Guardian Action Requests
155
- // ---------------------------------------------------------------------------
156
-
157
- /**
158
- * @internal Test-only helper. Production code should create guardian requests
159
- * via `createCanonicalGuardianRequest` in canonical-guardian-store.ts.
160
- * This function is retained solely so that existing test fixtures that seed
161
- * legacy guardian action rows continue to compile.
162
- */
163
- export function createGuardianActionRequest(params: {
164
- kind: string;
165
- sourceChannel: string;
166
- sourceConversationId: string;
167
- callSessionId: string;
168
- pendingQuestionId: string;
169
- questionText: string;
170
- expiresAt: number;
171
- toolName?: string;
172
- inputDigest?: string;
173
- }): GuardianActionRequest {
174
- const db = getDb();
175
- const now = Date.now();
176
- const id = uuid();
177
-
178
- const row = {
179
- id,
180
- kind: params.kind,
181
- sourceChannel: params.sourceChannel,
182
- sourceConversationId: params.sourceConversationId,
183
- callSessionId: params.callSessionId,
184
- pendingQuestionId: params.pendingQuestionId,
185
- questionText: params.questionText,
186
- requestCode: generateRequestCode(),
187
- status: "pending" as const,
188
- answerText: null,
189
- answeredByChannel: null,
190
- answeredByExternalUserId: null,
191
- answeredAt: null,
192
- expiresAt: params.expiresAt,
193
- expiredReason: null,
194
- followupState: "none" as const,
195
- lateAnswerText: null,
196
- lateAnsweredAt: null,
197
- followupAction: null,
198
- followupCompletedAt: null,
199
- toolName: params.toolName ?? null,
200
- inputDigest: params.inputDigest ?? null,
201
- supersededByRequestId: null,
202
- supersededAt: null,
203
- createdAt: now,
204
- updatedAt: now,
205
- };
206
-
207
- db.insert(guardianActionRequests).values(row).run();
208
- return rowToRequest(row);
209
- }
210
-
211
- export function getGuardianActionRequest(
212
- id: string,
213
- ): GuardianActionRequest | null {
214
- const db = getDb();
215
- const row = db
216
- .select()
217
- .from(guardianActionRequests)
218
- .where(eq(guardianActionRequests.id, id))
219
- .get();
220
- return row ? rowToRequest(row) : null;
221
- }
222
-
223
- /**
224
- * Find the most recent pending guardian action request for a given call session.
225
- * Used by the consultation timeout handler to mark the linked request as timed out.
226
- */
227
- export function getPendingRequestByCallSessionId(
228
- callSessionId: string,
229
- ): GuardianActionRequest | null {
230
- const db = getDb();
231
- const row = db
232
- .select()
233
- .from(guardianActionRequests)
234
- .where(
235
- and(
236
- eq(guardianActionRequests.callSessionId, callSessionId),
237
- eq(guardianActionRequests.status, "pending"),
238
- ),
239
- )
240
- .orderBy(desc(guardianActionRequests.createdAt))
241
- .get();
242
- return row ? rowToRequest(row) : null;
243
- }
244
-
245
- /**
246
- * First-response-wins resolution. Checks that the request is still
247
- * 'pending' before updating; returns the updated request on success
248
- * or null if the request was already resolved.
249
- */
250
- export function resolveGuardianActionRequest(
251
- id: string,
252
- answerText: string,
253
- answeredByChannel: string,
254
- answeredByExternalUserId?: string,
255
- ): GuardianActionRequest | null {
256
- const db = getDb();
257
- const now = Date.now();
258
-
259
- // Atomically check-and-update: only update if status is still 'pending'
260
- db.update(guardianActionRequests)
261
- .set({
262
- status: "answered",
263
- answerText,
264
- answeredByChannel,
265
- answeredByExternalUserId: answeredByExternalUserId ?? null,
266
- answeredAt: now,
267
- updatedAt: now,
268
- })
269
- .where(
270
- and(
271
- eq(guardianActionRequests.id, id),
272
- eq(guardianActionRequests.status, "pending"),
273
- ),
274
- )
275
- .run();
276
-
277
- // Check if the update took effect
278
- if (rawChanges() === 0) return null;
279
-
280
- // Mark all deliveries as 'answered'
281
- db.update(guardianActionDeliveries)
282
- .set({ status: "answered", respondedAt: now, updatedAt: now })
283
- .where(eq(guardianActionDeliveries.requestId, id))
284
- .run();
285
-
286
- return getGuardianActionRequest(id);
287
- }
288
-
289
- /**
290
- * Expire a guardian action request and all its deliveries.
291
- */
292
- export function expireGuardianActionRequest(
293
- id: string,
294
- reason: ExpiredReason,
295
- ): void {
296
- const db = getDb();
297
- const now = Date.now();
298
-
299
- db.update(guardianActionRequests)
300
- .set({
301
- status: "expired",
302
- expiredReason: reason,
303
- updatedAt: now,
304
- })
305
- .where(
306
- and(
307
- eq(guardianActionRequests.id, id),
308
- eq(guardianActionRequests.status, "pending"),
309
- ),
310
- )
311
- .run();
312
-
313
- db.update(guardianActionDeliveries)
314
- .set({ status: "expired", updatedAt: now })
315
- .where(
316
- and(
317
- eq(guardianActionDeliveries.requestId, id),
318
- inArray(guardianActionDeliveries.status, ["pending", "sent"]),
319
- ),
320
- )
321
- .run();
322
- }
323
-
324
- /**
325
- * Supersede a pending guardian action request: mark it expired with
326
- * reason='superseded', record the replacement request ID and timestamp,
327
- * and expire its active deliveries.
328
- *
329
- * Returns the updated request on success, or null if the request was
330
- * not in 'pending' status (first-writer-wins).
331
- */
332
- export function supersedeGuardianActionRequest(
333
- id: string,
334
- supersededByRequestId: string,
335
- ): GuardianActionRequest | null {
336
- const db = getDb();
337
- const now = Date.now();
338
-
339
- db.update(guardianActionRequests)
340
- .set({
341
- status: "expired",
342
- expiredReason: "superseded",
343
- supersededByRequestId,
344
- supersededAt: now,
345
- updatedAt: now,
346
- })
347
- .where(
348
- and(
349
- eq(guardianActionRequests.id, id),
350
- eq(guardianActionRequests.status, "pending"),
351
- ),
352
- )
353
- .run();
354
-
355
- if (rawChanges() === 0) return null;
356
-
357
- // Also expire active deliveries
358
- db.update(guardianActionDeliveries)
359
- .set({ status: "expired", updatedAt: now })
360
- .where(
361
- and(
362
- eq(guardianActionDeliveries.requestId, id),
363
- inArray(guardianActionDeliveries.status, ["pending", "sent"]),
364
- ),
365
- )
366
- .run();
367
-
368
- return getGuardianActionRequest(id);
369
- }
370
-
371
- /**
372
- * Get all pending guardian action requests that have expired.
373
- */
374
- export function getExpiredGuardianActionRequests(): GuardianActionRequest[] {
375
- const db = getDb();
376
- const now = Date.now();
377
- return db
378
- .select()
379
- .from(guardianActionRequests)
380
- .where(
381
- and(
382
- eq(guardianActionRequests.status, "pending"),
383
- lt(guardianActionRequests.expiresAt, now),
384
- ),
385
- )
386
- .all()
387
- .map(rowToRequest);
388
- }
389
-
390
- /**
391
- * Get all deliveries for a specific request.
392
- */
393
- export function getDeliveriesByRequestId(
394
- requestId: string,
395
- ): GuardianActionDelivery[] {
396
- const db = getDb();
397
- return db
398
- .select()
399
- .from(guardianActionDeliveries)
400
- .where(eq(guardianActionDeliveries.requestId, requestId))
401
- .all()
402
- .map(rowToDelivery);
403
- }
404
-
405
- /**
406
- * Cancel a guardian action request and all its deliveries.
407
- */
408
- export function cancelGuardianActionRequest(id: string): void {
409
- const db = getDb();
410
- const now = Date.now();
411
-
412
- db.update(guardianActionRequests)
413
- .set({ status: "cancelled", updatedAt: now })
414
- .where(
415
- and(
416
- eq(guardianActionRequests.id, id),
417
- eq(guardianActionRequests.status, "pending"),
418
- ),
419
- )
420
- .run();
421
-
422
- db.update(guardianActionDeliveries)
423
- .set({ status: "cancelled", updatedAt: now })
424
- .where(
425
- and(
426
- eq(guardianActionDeliveries.requestId, id),
427
- inArray(guardianActionDeliveries.status, ["pending", "sent"]),
428
- ),
429
- )
430
- .run();
431
- }
432
-
433
- // ---------------------------------------------------------------------------
434
- // Guardian Action Deliveries
435
- // ---------------------------------------------------------------------------
436
-
437
- export function createGuardianActionDelivery(params: {
438
- requestId: string;
439
- destinationChannel: string;
440
- destinationConversationId?: string;
441
- destinationChatId?: string;
442
- destinationExternalUserId?: string;
443
- }): GuardianActionDelivery {
444
- const db = getDb();
445
- const now = Date.now();
446
- const id = uuid();
447
-
448
- const row = {
449
- id,
450
- requestId: params.requestId,
451
- destinationChannel: params.destinationChannel,
452
- destinationConversationId: params.destinationConversationId ?? null,
453
- destinationChatId: params.destinationChatId ?? null,
454
- destinationExternalUserId: params.destinationExternalUserId ?? null,
455
- status: "pending" as const,
456
- sentAt: null,
457
- respondedAt: null,
458
- lastError: null,
459
- createdAt: now,
460
- updatedAt: now,
461
- };
462
-
463
- db.insert(guardianActionDeliveries).values(row).run();
464
- return rowToDelivery(row);
465
- }
466
-
467
- export function updateDeliveryStatus(
468
- deliveryId: string,
469
- status: GuardianActionDeliveryStatus,
470
- error?: string,
471
- ): void {
472
- const db = getDb();
473
- const now = Date.now();
474
-
475
- const updates: Record<string, unknown> = { status, updatedAt: now };
476
- if (status === "sent") updates.sentAt = now;
477
- if (status === "answered") updates.respondedAt = now;
478
- if (error !== undefined) updates.lastError = error;
479
-
480
- db.update(guardianActionDeliveries)
481
- .set(updates)
482
- .where(eq(guardianActionDeliveries.id, deliveryId))
483
- .run();
484
- }
@@ -1,150 +0,0 @@
1
- /**
2
- * Shared helper for minting scoped approval grants when a guardian-action
3
- * request is resolved with tool metadata.
4
- *
5
- * Used by both the channel inbound path (inbound-message-handler.ts) and
6
- * the desktop path (conversation-process.ts) to ensure grants are minted
7
- * consistently regardless of which channel the guardian answers on.
8
- */
9
-
10
- import { mintGrantFromDecision } from "../approvals/approval-primitive.js";
11
- import type { GuardianActionRequest } from "../memory/guardian-action-store.js";
12
- import { getLogger } from "../util/logger.js";
13
- import { runApprovalConversationTurn } from "./approval-conversation-turn.js";
14
- import type { ApprovalConversationGenerator } from "./http-types.js";
15
-
16
- const log = getLogger("guardian-action-grant-minter");
17
-
18
- /** TTL for scoped approval grants minted on guardian-action answer resolution. */
19
- const GUARDIAN_ACTION_GRANT_TTL_MS = 5 * 60 * 1000;
20
-
21
- /**
22
- * Mint a `tool_signature` scoped grant when a guardian-action request is
23
- * resolved and the request carries tool metadata (toolName + inputDigest).
24
- *
25
- * Classifies the guardian's answer via the conversational approval engine
26
- * (`runApprovalConversationTurn`). Only `approve_once` produces a grant —
27
- * guardian-action grants are always single-use `tool_signature` scoped.
28
- *
29
- * Skips silently when:
30
- * - The resolved request has no toolName/inputDigest (informational consult).
31
- * - The guardian's answer is not classified as approval (fail-closed).
32
- *
33
- * Fails silently on error -- grant minting is best-effort and must never
34
- * block the guardian-action answer flow.
35
- */
36
- export async function tryMintGuardianActionGrant(params: {
37
- request: GuardianActionRequest;
38
- answerText: string;
39
- decisionChannel: string;
40
- guardianExternalUserId?: string;
41
- approvalConversationGenerator: ApprovalConversationGenerator;
42
- }): Promise<void> {
43
- const {
44
- request,
45
- answerText,
46
- decisionChannel,
47
- guardianExternalUserId,
48
- approvalConversationGenerator,
49
- } = params;
50
-
51
- // Only mint for requests that carry tool metadata -- informational
52
- // ASK_GUARDIAN consults without tool context do not produce grants.
53
- if (!request.toolName || !request.inputDigest) {
54
- return;
55
- }
56
-
57
- // Classify the guardian's answer via the conversational approval engine.
58
- // Guardian-action grants are always single-use (approve_once only).
59
- let isApproval = false;
60
- try {
61
- const llmResult = await runApprovalConversationTurn(
62
- {
63
- toolName: request.toolName,
64
- allowedActions: ["approve_once", "reject"],
65
- role: "guardian",
66
- pendingApprovals: [
67
- { requestId: request.id, toolName: request.toolName },
68
- ],
69
- userMessage: answerText,
70
- },
71
- approvalConversationGenerator,
72
- );
73
-
74
- isApproval = llmResult.disposition === "approve_once";
75
-
76
- log.info(
77
- {
78
- event: "guardian_action_grant_classification",
79
- toolName: request.toolName,
80
- requestId: request.id,
81
- answerText,
82
- llmDisposition: llmResult.disposition,
83
- matched: isApproval,
84
- decisionChannel,
85
- },
86
- `Approval classifier returned disposition: ${llmResult.disposition}`,
87
- );
88
- } catch (err) {
89
- // Fail-closed: generator errors must not produce grants.
90
- log.warn(
91
- {
92
- event: "guardian_action_grant_classification_error",
93
- toolName: request.toolName,
94
- requestId: request.id,
95
- err,
96
- decisionChannel,
97
- },
98
- "Approval classifier threw an error; treating as non-approval (fail-closed)",
99
- );
100
- }
101
-
102
- if (!isApproval) {
103
- log.info(
104
- {
105
- event: "guardian_action_grant_skipped_no_approval",
106
- toolName: request.toolName,
107
- requestId: request.id,
108
- answerText,
109
- decisionChannel,
110
- },
111
- "Skipped grant minting: guardian answer not classified as approval",
112
- );
113
- return;
114
- }
115
-
116
- const result = mintGrantFromDecision({
117
- scopeMode: "tool_signature",
118
- toolName: request.toolName,
119
- inputDigest: request.inputDigest,
120
- requestChannel: request.sourceChannel,
121
- decisionChannel,
122
- executionChannel: null,
123
- conversationId: request.sourceConversationId,
124
- callSessionId: request.callSessionId,
125
- guardianExternalUserId: guardianExternalUserId ?? null,
126
- expiresAt: Date.now() + GUARDIAN_ACTION_GRANT_TTL_MS,
127
- });
128
-
129
- if (result.ok) {
130
- log.info(
131
- {
132
- event: "guardian_action_grant_minted",
133
- toolName: request.toolName,
134
- requestId: request.id,
135
- callSessionId: request.callSessionId,
136
- decisionChannel,
137
- },
138
- "Minted scoped approval grant for guardian-action answer resolution",
139
- );
140
- } else {
141
- log.error(
142
- {
143
- reason: result.reason,
144
- toolName: request.toolName,
145
- requestId: request.id,
146
- },
147
- "Failed to mint scoped approval grant for guardian-action (non-fatal)",
148
- );
149
- }
150
- }