@vellumai/assistant 0.9.0 → 0.10.0-dev.202606192226.8ed8a6a

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 (624) hide show
  1. package/ARCHITECTURE.md +19 -35
  2. package/bun.lock +7 -8
  3. package/docs/activation-funnel-telemetry.md +28 -22
  4. package/docs/architecture/security.md +29 -28
  5. package/docs/stt-provider-onboarding.md +3 -5
  6. package/docs/workflows-testing.md +13 -44
  7. package/docs/workflows.md +3 -5
  8. package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
  9. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
  10. package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
  11. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
  12. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  13. package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
  14. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
  15. package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
  16. package/openapi.yaml +1128 -119
  17. package/package.json +2 -1
  18. package/scripts/sync-llm-catalog.ts +6 -15
  19. package/scripts/sync-web-search-catalog.ts +3 -11
  20. package/src/__tests__/access-request-card-view.test.ts +98 -0
  21. package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
  22. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
  23. package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
  24. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
  25. package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
  26. package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
  27. package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
  28. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
  29. package/src/__tests__/app-compiler.test.ts +15 -1
  30. package/src/__tests__/app-dir-path-guard.test.ts +0 -1
  31. package/src/__tests__/approval-cascade.test.ts +6 -0
  32. package/src/__tests__/approval-routes-http.test.ts +128 -0
  33. package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
  34. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  35. package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
  36. package/src/__tests__/avatar-identity-sync.test.ts +2 -27
  37. package/src/__tests__/btw-routes.test.ts +6 -8
  38. package/src/__tests__/call-pointer-messages.test.ts +28 -0
  39. package/src/__tests__/cancel-clears-processing.test.ts +89 -0
  40. package/src/__tests__/channel-approval-routes.test.ts +0 -4
  41. package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
  42. package/src/__tests__/checker.test.ts +0 -3
  43. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
  44. package/src/__tests__/compaction-events.test.ts +6 -0
  45. package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
  46. package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
  47. package/src/__tests__/config-loader-backfill.test.ts +268 -27
  48. package/src/__tests__/config-schema.test.ts +35 -0
  49. package/src/__tests__/config-watcher.test.ts +0 -18
  50. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
  51. package/src/__tests__/contact-store-user-file.test.ts +0 -6
  52. package/src/__tests__/contacts-tools.test.ts +29 -0
  53. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  54. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
  55. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  56. package/src/__tests__/conversation-agent-loop.test.ts +58 -0
  57. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  58. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
  59. package/src/__tests__/conversation-lifecycle.test.ts +7 -9
  60. package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
  61. package/src/__tests__/conversation-process-callsite.test.ts +6 -0
  62. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  63. package/src/__tests__/conversation-queue.test.ts +6 -0
  64. package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
  65. package/src/__tests__/conversation-slash-queue.test.ts +6 -0
  66. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +6 -0
  68. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
  69. package/src/__tests__/conversation-title-service.test.ts +62 -0
  70. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
  71. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  72. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  73. package/src/__tests__/credential-broker.test.ts +449 -1
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
  75. package/src/__tests__/credential-execution-tools.test.ts +0 -1
  76. package/src/__tests__/credential-prompt-route.test.ts +4 -4
  77. package/src/__tests__/credential-routes.test.ts +360 -0
  78. package/src/__tests__/credential-security-invariants.test.ts +4 -13
  79. package/src/__tests__/disk-pressure-policy.test.ts +12 -0
  80. package/src/__tests__/disk-pressure-tools.test.ts +41 -1
  81. package/src/__tests__/disk-usage.test.ts +65 -0
  82. package/src/__tests__/document-tool-security.test.ts +9 -6
  83. package/src/__tests__/document-update-default-surface.test.ts +202 -0
  84. package/src/__tests__/dynamic-page-surface.test.ts +152 -1
  85. package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
  86. package/src/__tests__/gateway-flag-listener.test.ts +110 -1
  87. package/src/__tests__/gateway-only-guard.test.ts +3 -7
  88. package/src/__tests__/gemini-count-tokens.test.ts +70 -0
  89. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  90. package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
  91. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
  92. package/src/__tests__/guardian-grant-minting.test.ts +3 -35
  93. package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
  94. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  95. package/src/__tests__/headless-browser-mode.test.ts +10 -0
  96. package/src/__tests__/headless-browser-navigate.test.ts +8 -3
  97. package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
  98. package/src/__tests__/host-browser-proxy.test.ts +87 -0
  99. package/src/__tests__/identity-routes.test.ts +0 -189
  100. package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
  101. package/src/__tests__/injector-disk-pressure.test.ts +10 -5
  102. package/src/__tests__/injector-v3-suppression.test.ts +27 -20
  103. package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
  104. package/src/__tests__/invite-redemption-service.test.ts +4 -7
  105. package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
  106. package/src/__tests__/llm-catalog-parity.test.ts +30 -23
  107. package/src/__tests__/llm-resolver.test.ts +70 -24
  108. package/src/__tests__/llm-schema.test.ts +1 -0
  109. package/src/__tests__/managed-profile-guard.test.ts +163 -4
  110. package/src/__tests__/mcp-health-check.test.ts +6 -7
  111. package/src/__tests__/media-stream-server-integration.test.ts +317 -13
  112. package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
  113. package/src/__tests__/onboarding-persona-write.test.ts +1 -1
  114. package/src/__tests__/path-policy.test.ts +34 -0
  115. package/src/__tests__/persona-resolver.test.ts +49 -14
  116. package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
  117. package/src/__tests__/plugin-api-provider.test.ts +24 -0
  118. package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
  119. package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
  120. package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
  121. package/src/__tests__/reaction-persistence.test.ts +150 -29
  122. package/src/__tests__/registry.test.ts +2 -7
  123. package/src/__tests__/relay-server.test.ts +285 -0
  124. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  125. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
  126. package/src/__tests__/schedule-routes.test.ts +0 -30
  127. package/src/__tests__/schedule-tools.test.ts +2 -18
  128. package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
  129. package/src/__tests__/secret-response-routing.test.ts +35 -0
  130. package/src/__tests__/secret-routes-platform-proxy.test.ts +16 -2
  131. package/src/__tests__/skill-execute-input.test.ts +177 -1
  132. package/src/__tests__/skill-load-tool.test.ts +72 -0
  133. package/src/__tests__/skill-runtime-path.test.ts +2 -3
  134. package/src/__tests__/skills.test.ts +51 -0
  135. package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
  136. package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
  137. package/src/__tests__/subagent-tools.test.ts +266 -0
  138. package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
  139. package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
  140. package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
  141. package/src/__tests__/title-generate-hook.test.ts +100 -3
  142. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
  143. package/src/__tests__/token-manager.test.ts +519 -0
  144. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
  145. package/src/__tests__/tool-audit-listener.test.ts +7 -7
  146. package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
  147. package/src/__tests__/tool-executor.test.ts +0 -79
  148. package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
  149. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
  150. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
  151. package/src/__tests__/trusted-contact-verification.test.ts +8 -10
  152. package/src/__tests__/twilio-routes.test.ts +81 -1
  153. package/src/__tests__/voice-invite-redemption.test.ts +2 -3
  154. package/src/__tests__/weak-open-model.test.ts +30 -0
  155. package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
  156. package/src/__tests__/workspace-greetings.test.ts +152 -0
  157. package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
  158. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
  159. package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
  160. package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
  161. package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
  162. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
  163. package/src/agent/loop.ts +75 -29
  164. package/src/api/README.md +6 -6
  165. package/src/api/events/tool-result.ts +6 -0
  166. package/src/api/events/workflow-completed.ts +53 -0
  167. package/src/api/events/workflow-leaf-finished.ts +38 -0
  168. package/src/api/events/workflow-leaf-started.ts +35 -0
  169. package/src/api/events/workflow-progress.ts +32 -0
  170. package/src/api/events/workflow-started.ts +31 -0
  171. package/src/api/index.ts +40 -0
  172. package/src/api/responses/conversation-message.ts +28 -4
  173. package/src/api/responses/home.ts +26 -4
  174. package/src/api/responses/workflow-journal.ts +53 -0
  175. package/src/approvals/guardian-card-withdrawal.ts +145 -0
  176. package/src/approvals/guardian-decision-primitive.ts +26 -3
  177. package/src/approvals/guardian-request-resolvers.ts +183 -80
  178. package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
  179. package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
  180. package/src/calls/call-pointer-messages.ts +10 -4
  181. package/src/calls/channel-admission-reader.ts +104 -0
  182. package/src/calls/guardian-dispatch.ts +17 -45
  183. package/src/calls/media-stream-server.ts +84 -2
  184. package/src/calls/relay-access-wait.ts +1 -1
  185. package/src/calls/relay-server.ts +66 -0
  186. package/src/calls/relay-setup-router.ts +82 -1
  187. package/src/calls/twilio-routes.ts +17 -8
  188. package/src/calls/voice-session-bridge.ts +2 -2
  189. package/src/cli/commands/clients.ts +3 -0
  190. package/src/cli/commands/db/status.ts +37 -3
  191. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
  192. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
  193. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
  194. package/src/cli/commands/memory/index.ts +30 -0
  195. package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
  196. package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
  197. package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
  198. package/src/cli/commands/oauth/status.test.ts +36 -0
  199. package/src/cli/commands/oauth/status.ts +23 -3
  200. package/src/cli/commands/plugins.ts +400 -14
  201. package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
  202. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  203. package/src/cli/lib/__tests__/install-from-github.test.ts +31 -0
  204. package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
  205. package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
  206. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
  207. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
  208. package/src/cli/lib/diff-plugin.ts +346 -0
  209. package/src/cli/lib/inspect-plugin.ts +12 -1
  210. package/src/cli/lib/install-from-github.ts +128 -19
  211. package/src/cli/lib/merge-plugin-tree.ts +328 -0
  212. package/src/cli/lib/plugin-fingerprint.ts +14 -0
  213. package/src/cli/lib/plugin-marketplace.ts +11 -0
  214. package/src/cli/lib/plugin-pin-history.ts +257 -0
  215. package/src/cli/lib/plugin-surfaces.ts +104 -0
  216. package/src/cli/lib/upgrade-plugin.ts +298 -10
  217. package/src/cli/program.ts +2 -6
  218. package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
  219. package/src/config/assistant-feature-flags.ts +22 -7
  220. package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
  221. package/src/config/bundled-skills/document-editor/SKILL.md +3 -3
  222. package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
  223. package/src/config/bundled-skills/messaging/SKILL.md +6 -4
  224. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
  225. package/src/config/bundled-skills/subagent/SKILL.md +4 -0
  226. package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
  227. package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
  228. package/src/config/bundled-skills/workflows/SKILL.md +14 -8
  229. package/src/config/bundled-tool-registry.ts +2 -7
  230. package/src/config/call-site-defaults.ts +15 -2
  231. package/src/config/feature-flag-registry.json +46 -31
  232. package/src/config/inference-profile-validation.ts +26 -0
  233. package/src/config/llm-resolver.ts +3 -0
  234. package/src/config/loader.ts +4 -0
  235. package/src/config/memory-v3-gate.ts +11 -0
  236. package/src/config/profile-order.ts +28 -0
  237. package/src/config/schema.ts +8 -6
  238. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  239. package/src/config/schemas/call-site-catalog.ts +7 -0
  240. package/src/config/schemas/channels.ts +11 -0
  241. package/src/config/schemas/elevenlabs.ts +0 -1
  242. package/src/config/schemas/llm.ts +31 -0
  243. package/src/config/schemas/memory-lifecycle.ts +3 -7
  244. package/src/config/schemas/memory-v3.ts +6 -0
  245. package/src/config/schemas/platform.ts +0 -8
  246. package/src/config/schemas/services.ts +18 -0
  247. package/src/config/seed-inference-profiles.ts +109 -44
  248. package/src/config/skills.ts +21 -0
  249. package/src/config/sync-gated-profiles.ts +220 -0
  250. package/src/contacts/contact-store.ts +89 -106
  251. package/src/contacts/contacts-write.ts +5 -22
  252. package/src/contacts/types.ts +0 -1
  253. package/src/context/compactor.ts +88 -54
  254. package/src/context/strip-injections.ts +58 -10
  255. package/src/context/token-estimator.ts +1 -1
  256. package/src/credential-execution/process-manager.ts +55 -14
  257. package/src/credential-execution/prompted-credential.ts +2 -3
  258. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
  259. package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
  260. package/src/daemon/config-watcher.ts +0 -4
  261. package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
  262. package/src/daemon/conversation-agent-loop.ts +114 -22
  263. package/src/daemon/conversation-history.ts +1 -1
  264. package/src/daemon/conversation-lifecycle.ts +3 -5
  265. package/src/daemon/conversation-process.ts +13 -5
  266. package/src/daemon/conversation-runtime-assembly.ts +13 -15
  267. package/src/daemon/conversation-slash.ts +2 -23
  268. package/src/daemon/conversation-surfaces.ts +26 -0
  269. package/src/daemon/conversation-tool-setup.ts +53 -19
  270. package/src/daemon/conversation.ts +131 -20
  271. package/src/daemon/disk-pressure-policy.ts +5 -3
  272. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
  273. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
  274. package/src/daemon/handlers/config-a2a.ts +0 -2
  275. package/src/daemon/handlers/config-channels.ts +15 -16
  276. package/src/daemon/handlers/config-slack-channel.ts +22 -3
  277. package/src/daemon/handlers/conversations.ts +107 -0
  278. package/src/daemon/host-browser-proxy.ts +41 -0
  279. package/src/daemon/lifecycle.ts +55 -27
  280. package/src/daemon/memory-v2-startup.test.ts +131 -0
  281. package/src/daemon/memory-v2-startup.ts +100 -1
  282. package/src/daemon/message-provenance.ts +2 -0
  283. package/src/daemon/message-types/contacts.ts +0 -1
  284. package/src/daemon/message-types/conversations.ts +3 -3
  285. package/src/daemon/message-types/sync.ts +0 -1
  286. package/src/daemon/message-types/web-activity.ts +7 -1
  287. package/src/daemon/message-types/workflows.ts +83 -1
  288. package/src/daemon/orphan-reaper.test.ts +0 -19
  289. package/src/daemon/orphan-reaper.ts +2 -24
  290. package/src/daemon/server.ts +0 -10
  291. package/src/daemon/tool-setup-types.ts +4 -0
  292. package/src/daemon/trust-context.ts +1 -1
  293. package/src/daemon/wake-conversation-ops.ts +1 -0
  294. package/src/events/tool-audit-listener.ts +2 -2
  295. package/src/home/feed-source-enrichment.test.ts +151 -0
  296. package/src/home/feed-source-enrichment.ts +176 -0
  297. package/src/home/relationship-state.ts +2 -4
  298. package/src/instrument.ts +18 -6
  299. package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
  300. package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
  301. package/src/ipc/assistant-server.ts +37 -4
  302. package/src/ipc/gateway-flag-listener.ts +18 -2
  303. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
  304. package/src/memory/__tests__/db-logs-attach.test.ts +122 -0
  305. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
  306. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
  307. package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
  308. package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
  309. package/src/memory/auth-fallback-events-store.ts +2 -2
  310. package/src/memory/auto-analysis-enqueue.ts +3 -5
  311. package/src/memory/bookmark-crud.ts +1 -2
  312. package/src/memory/canonical-guardian-store.ts +39 -1
  313. package/src/memory/conversation-crud.ts +9 -4
  314. package/src/memory/conversation-key-store.ts +17 -2
  315. package/src/memory/conversation-title-service.ts +64 -7
  316. package/src/memory/db-async-query.ts +20 -2
  317. package/src/memory/db-connection.ts +49 -5
  318. package/src/memory/db-init.ts +17 -17
  319. package/src/memory/embedding-backend.ts +38 -1
  320. package/src/memory/embedding-billing-breaker.ts +96 -0
  321. package/src/memory/jobs-store.ts +25 -13
  322. package/src/memory/jobs-worker.ts +54 -1
  323. package/src/memory/lifecycle-events-store.ts +2 -2
  324. package/src/memory/memory-retrospective-constants.ts +4 -4
  325. package/src/memory/memory-retrospective-enqueue.ts +31 -6
  326. package/src/memory/memory-retrospective-job.ts +28 -227
  327. package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
  328. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
  329. package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
  330. package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
  331. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
  332. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
  333. package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
  334. package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
  335. package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
  336. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
  337. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
  338. package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
  339. package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
  340. package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
  341. package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
  342. package/src/memory/migrations/index.ts +6 -0
  343. package/src/memory/migrations/run-migrations.ts +41 -0
  344. package/src/memory/migrations/validate-migration-state.ts +1 -1
  345. package/src/memory/onboarding-events-store.ts +3 -3
  346. package/src/memory/schema/contacts.ts +0 -5
  347. package/src/memory/skill-loaded-events-store.test.ts +7 -15
  348. package/src/memory/skill-loaded-events-store.ts +2 -2
  349. package/src/memory/tool-executed-events-store.test.ts +7 -7
  350. package/src/memory/turn-trace-store.test.ts +736 -0
  351. package/src/memory/turn-trace-store.ts +364 -0
  352. package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
  353. package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
  354. package/src/memory/v2/consolidation-job.ts +2 -2
  355. package/src/memory/v2/skill-content.ts +25 -7
  356. package/src/memory/v2/skill-store.ts +7 -1
  357. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
  358. package/src/memory/v3-eval/eval-packets.ts +546 -0
  359. package/src/messaging/providers/slack/adapter.ts +1 -1
  360. package/src/messaging/providers/slack/api.ts +31 -0
  361. package/src/messaging/providers/slack/send.test.ts +114 -2
  362. package/src/messaging/providers/slack/send.ts +30 -7
  363. package/src/messaging/providers/slack/withdraw.test.ts +200 -0
  364. package/src/messaging/providers/slack/withdraw.ts +161 -0
  365. package/src/notifications/AGENTS.md +2 -0
  366. package/src/notifications/access-request-copy.ts +72 -59
  367. package/src/notifications/adapters/shared.ts +29 -0
  368. package/src/notifications/adapters/slack.ts +58 -103
  369. package/src/notifications/adapters/telegram.ts +2 -20
  370. package/src/notifications/approval-card-data.ts +333 -0
  371. package/src/notifications/broadcaster.ts +16 -3
  372. package/src/notifications/canonical-delivery-recorder.ts +139 -0
  373. package/src/notifications/copy-composer.ts +3 -3
  374. package/src/notifications/decision-engine.ts +4 -2
  375. package/src/notifications/destination-resolver.ts +4 -6
  376. package/src/notifications/guardian-question-mode.ts +10 -0
  377. package/src/notifications/home-feed-side-effect.ts +7 -16
  378. package/src/notifications/notification-utils.ts +19 -20
  379. package/src/notifications/signal.ts +79 -43
  380. package/src/notifications/types.ts +98 -121
  381. package/src/oauth/AGENTS.md +5 -24
  382. package/src/permissions/checker.test.ts +51 -0
  383. package/src/permissions/checker.ts +185 -26
  384. package/src/permissions/ipc-risk-types.ts +24 -0
  385. package/src/permissions/question-prompter.test.ts +27 -0
  386. package/src/permissions/question-prompter.ts +4 -0
  387. package/src/permissions/secret-prompter.ts +15 -1
  388. package/src/platform/client.test.ts +119 -0
  389. package/src/platform/client.ts +66 -0
  390. package/src/platform/consent-cache.test.ts +267 -0
  391. package/src/platform/consent-cache.ts +174 -0
  392. package/src/plugin-api/constants.ts +1 -1
  393. package/src/plugin-api/index.ts +33 -1
  394. package/src/plugin-api/model-profiles.ts +33 -0
  395. package/src/plugin-api/types.ts +50 -2
  396. package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
  397. package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
  398. package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
  399. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
  400. package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
  401. package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
  402. package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
  403. package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
  404. package/src/plugins/defaults/advisor/config.ts +21 -0
  405. package/src/plugins/defaults/advisor/consult.ts +93 -0
  406. package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
  407. package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
  408. package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
  409. package/src/plugins/defaults/advisor/package.json +14 -0
  410. package/src/plugins/defaults/advisor/steering.ts +67 -0
  411. package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
  412. package/src/plugins/defaults/advisor/transcript.ts +76 -0
  413. package/src/plugins/defaults/compaction/window-manager.ts +18 -0
  414. package/src/plugins/defaults/index.ts +60 -0
  415. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
  416. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
  417. package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
  418. package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
  419. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
  420. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
  421. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
  422. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
  423. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
  424. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
  425. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
  426. package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
  427. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
  428. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
  429. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
  430. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
  431. package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
  432. package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
  433. package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
  434. package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
  435. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
  436. package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
  437. package/src/prompts/persona-resolver.ts +14 -4
  438. package/src/prompts/templates/system-sections.ts +7 -2
  439. package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
  440. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  441. package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
  442. package/src/providers/__tests__/retry-callsite.test.ts +176 -0
  443. package/src/providers/anthropic/client.ts +230 -175
  444. package/src/providers/atlascloud/client.ts +85 -0
  445. package/src/providers/call-site-routing.ts +10 -0
  446. package/src/providers/fetch-provider-catalog.ts +85 -0
  447. package/src/providers/gemini/client.ts +43 -0
  448. package/src/providers/inference/adapter-factory.ts +3 -0
  449. package/src/providers/model-catalog.ts +58 -0
  450. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
  451. package/src/providers/openai/chat-completions-provider.ts +7 -0
  452. package/src/providers/openai/responses-provider.ts +10 -0
  453. package/src/providers/provider-send-message.ts +11 -3
  454. package/src/providers/ratelimit.ts +9 -0
  455. package/src/providers/retry.ts +62 -12
  456. package/src/providers/search-provider-catalog.ts +10 -0
  457. package/src/providers/types.ts +16 -0
  458. package/src/providers/usage-tracking.ts +7 -0
  459. package/src/providers/weak-open-model.ts +22 -0
  460. package/src/runtime/AGENTS.md +0 -1
  461. package/src/runtime/__tests__/agent-wake.test.ts +227 -0
  462. package/src/runtime/__tests__/client-health.test.ts +44 -0
  463. package/src/runtime/access-request-helper.ts +21 -53
  464. package/src/runtime/actor-trust-resolver.ts +59 -63
  465. package/src/runtime/agent-wake.ts +71 -0
  466. package/src/runtime/assistant-event-hub.ts +18 -4
  467. package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
  468. package/src/runtime/auth/require-bound-guardian.ts +1 -4
  469. package/src/runtime/btw-sidechain.ts +3 -6
  470. package/src/runtime/capabilities.test.ts +120 -0
  471. package/src/runtime/capabilities.ts +197 -0
  472. package/src/runtime/channel-approval-types.ts +22 -45
  473. package/src/runtime/channel-invite-transports/telegram.ts +4 -4
  474. package/src/runtime/channel-retry-sweep.ts +1 -0
  475. package/src/runtime/channel-verification-service.ts +3 -3
  476. package/src/runtime/client-health.ts +26 -0
  477. package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
  478. package/src/runtime/effective-capabilities.test.ts +128 -0
  479. package/src/runtime/effective-capabilities.ts +84 -0
  480. package/src/runtime/guardian-reply-router.ts +106 -21
  481. package/src/runtime/invite-redemption-service.ts +9 -25
  482. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +126 -0
  483. package/src/runtime/migrations/vbundle-builder.ts +49 -20
  484. package/src/runtime/pending-interactions.ts +35 -0
  485. package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
  486. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
  487. package/src/runtime/routes/__tests__/plugins-routes.test.ts +383 -1
  488. package/src/runtime/routes/app-routes.ts +1 -1
  489. package/src/runtime/routes/approval-routes.ts +40 -9
  490. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
  491. package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
  492. package/src/runtime/routes/browser-tabs-routes.ts +9 -0
  493. package/src/runtime/routes/btw-routes.ts +1 -27
  494. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
  495. package/src/runtime/routes/client-routes.ts +10 -0
  496. package/src/runtime/routes/contact-routes.ts +31 -8
  497. package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
  498. package/src/runtime/routes/conversation-management-routes.ts +80 -1
  499. package/src/runtime/routes/conversation-query-routes.ts +68 -22
  500. package/src/runtime/routes/conversation-routes.ts +39 -14
  501. package/src/runtime/routes/credential-routes.ts +40 -16
  502. package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
  503. package/src/runtime/routes/events-routes.ts +1 -3
  504. package/src/runtime/routes/guardian-approval-interception.ts +14 -73
  505. package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
  506. package/src/runtime/routes/home-feed-routes.ts +8 -3
  507. package/src/runtime/routes/identity-routes.ts +1 -296
  508. package/src/runtime/routes/inbound-message-handler.ts +214 -228
  509. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
  510. package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
  511. package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
  512. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
  513. package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
  514. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
  515. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
  516. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
  517. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
  518. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
  519. package/src/runtime/routes/index.ts +2 -0
  520. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
  521. package/src/runtime/routes/integrations/slack/channel.ts +36 -0
  522. package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
  523. package/src/runtime/routes/mcp-auth-routes.ts +233 -41
  524. package/src/runtime/routes/memory-eval-routes.ts +87 -0
  525. package/src/runtime/routes/notification-routes.ts +122 -133
  526. package/src/runtime/routes/platform-routes.ts +2 -2
  527. package/src/runtime/routes/plugins-routes.ts +366 -11
  528. package/src/runtime/routes/schedule-routes.ts +0 -22
  529. package/src/runtime/routes/secret-routes.ts +15 -0
  530. package/src/runtime/routes/surface-action-routes.ts +2 -1
  531. package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
  532. package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
  533. package/src/runtime/routes/workflow-routes.test.ts +229 -44
  534. package/src/runtime/routes/workflow-routes.ts +131 -29
  535. package/src/runtime/routes/workspace-greetings.ts +55 -0
  536. package/src/runtime/sync/resource-sync-events.ts +1 -11
  537. package/src/runtime/tool-grant-request-helper.ts +18 -16
  538. package/src/runtime/trust-context-resolver.ts +8 -5
  539. package/src/schedule/inference-profile.ts +2 -14
  540. package/src/schedule/schedule-store.ts +1 -1
  541. package/src/schedule/scheduler-types.ts +5 -1
  542. package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
  543. package/src/security/secret-patterns.ts +3 -0
  544. package/src/subagent/manager.ts +17 -4
  545. package/src/subagent/types.ts +6 -0
  546. package/src/telemetry/trace-collection-policy.test.ts +28 -0
  547. package/src/telemetry/trace-collection-policy.ts +30 -0
  548. package/src/telemetry/types.ts +89 -0
  549. package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
  550. package/src/telemetry/usage-telemetry-reporter.ts +148 -41
  551. package/src/tools/AGENTS.md +3 -3
  552. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
  553. package/src/tools/browser/browser-execution.ts +30 -19
  554. package/src/tools/document/document-tool.ts +30 -6
  555. package/src/tools/executor.ts +5 -3
  556. package/src/tools/host-terminal/host-shell.ts +5 -4
  557. package/src/tools/memory/register.ts +2 -2
  558. package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
  559. package/src/tools/network/__tests__/web-search.test.ts +143 -0
  560. package/src/tools/network/web-fetch.ts +372 -1
  561. package/src/tools/network/web-search-error.ts +1 -1
  562. package/src/tools/network/web-search.ts +213 -10
  563. package/src/tools/permission-checker.ts +4 -3
  564. package/src/tools/registry.ts +20 -0
  565. package/src/tools/schedule/create.ts +7 -12
  566. package/src/tools/schedule/update.ts +4 -11
  567. package/src/tools/shared/filesystem/path-policy.ts +39 -13
  568. package/src/tools/side-effects.ts +2 -17
  569. package/src/tools/skills/execute.ts +99 -2
  570. package/src/tools/skills/load.ts +43 -2
  571. package/src/tools/subagent/spawn.ts +64 -15
  572. package/src/tools/terminal/shell.ts +10 -4
  573. package/src/tools/tool-approval-handler.ts +18 -13
  574. package/src/tools/tool-manifest.ts +0 -2
  575. package/src/tools/types.ts +10 -0
  576. package/src/tools/ui-surface/definitions.ts +64 -3
  577. package/src/tools/verification-control-plane-policy.ts +3 -1
  578. package/src/tools/workflows/run-workflow.test.ts +8 -18
  579. package/src/tools/workflows/run-workflow.ts +1 -0
  580. package/src/util/disk-usage.ts +78 -23
  581. package/src/util/logs-db-path.ts +22 -0
  582. package/src/util/platform.ts +10 -3
  583. package/src/watcher/telemetry.ts +2 -2
  584. package/src/workflows/capabilities.ts +2 -3
  585. package/src/workflows/engine.test.ts +175 -1
  586. package/src/workflows/engine.ts +82 -0
  587. package/src/workflows/journal-store.test.ts +70 -0
  588. package/src/workflows/journal-store.ts +18 -3
  589. package/src/workflows/run-manager.test.ts +171 -28
  590. package/src/workflows/run-manager.ts +66 -24
  591. package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
  592. package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
  593. package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
  594. package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
  595. package/src/workspace/migrations/registry.ts +8 -0
  596. package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
  597. package/src/__tests__/credential-security-e2e.test.ts +0 -362
  598. package/src/__tests__/credential-vault-unit.test.ts +0 -1528
  599. package/src/__tests__/credential-vault.test.ts +0 -1706
  600. package/src/__tests__/identity-intro-cache.test.ts +0 -315
  601. package/src/__tests__/secret-onetime-send.test.ts +0 -182
  602. package/src/cli/commands/__tests__/task.test.ts +0 -914
  603. package/src/cli/commands/task.ts +0 -771
  604. package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
  605. package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
  606. package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
  607. package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
  608. package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
  609. package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
  610. package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
  611. package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
  612. package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
  613. package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
  614. package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
  615. package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
  616. package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
  617. package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
  618. package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
  619. package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
  620. package/src/memory/preloaded-apps.ts +0 -116
  621. package/src/notifications/tool-approval-copy.ts +0 -142
  622. package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
  623. package/src/runtime/routes/identity-intro-cache.ts +0 -172
  624. package/src/tools/credentials/vault.ts +0 -712
@@ -58,6 +58,7 @@ import { resolveEffectiveContextWindow } from "../config/llm-context-resolution.
58
58
  import { getConfig } from "../config/loader.js";
59
59
  import type { LLMCallSite } from "../config/schemas/llm.js";
60
60
  import type { Conversation } from "../daemon/conversation.js";
61
+ import { recordUsage } from "../daemon/conversation-usage.js";
61
62
  import { getDiskPressureStatus } from "../daemon/disk-pressure-guard.js";
62
63
  import {
63
64
  classifyDiskPressureTurnPolicy,
@@ -195,6 +196,14 @@ export interface WakeOptions {
195
196
  * retrospectives whose conversation title already says "(Retrospective)").
196
197
  */
197
198
  suppressWakeSurface?: boolean;
199
+ /**
200
+ * Run the wake's turn as non-interactive (no client present). Threads to the
201
+ * agent loop's `isNonInteractive`, which gates the `<non_interactive_context>`
202
+ * and `<background_turn>` injectors. Fork-based memory retrospectives set this
203
+ * to the source conversation's background-turn state so the fork reproduces
204
+ * the source's injected turn block (prompt-cache prefix parity). Default false.
205
+ */
206
+ isNonInteractive?: boolean;
198
207
  /**
199
208
  * Optional exact tool allowlist for this wake. Used by internal maintenance
200
209
  * jobs that need the assistant's judgment but must not execute arbitrary
@@ -587,6 +596,7 @@ export async function wakeAgentForOpportunity(
587
596
  opts.forceOverrideProfile ??
588
597
  getConversationOverrideProfile(conversationId);
589
598
  const callSite = opts.callSite ?? "mainAgent";
599
+ const isNonInteractive = opts.isNonInteractive ?? false;
590
600
  const config = getConfig();
591
601
  const effectiveContextWindow = resolveEffectiveContextWindow({
592
602
  llm: config.llm,
@@ -784,6 +794,47 @@ export async function wakeAgentForOpportunity(
784
794
  if (event.type === "compaction_completed") {
785
795
  recordCompactionEndBestEffort(conversationId, event);
786
796
  }
797
+ // Normal user turns record usage via the `dispatchAgentEvent` event handler)
798
+ // Wakes run their own onEvent and bypass it, so record here.
799
+ if (event.type === "usage") {
800
+ try {
801
+ recordUsage(
802
+ {
803
+ conversationId,
804
+ providerName: event.actualProvider ?? conversation.provider.name,
805
+ usageStats: conversation.usageStats,
806
+ },
807
+ event.inputTokens,
808
+ event.outputTokens,
809
+ event.model,
810
+ () => {},
811
+ "main_agent",
812
+ `wake:${source}`,
813
+ event.cacheCreationInputTokens ?? 0,
814
+ event.cacheReadInputTokens ?? 0,
815
+ event.rawResponse,
816
+ 1,
817
+ undefined,
818
+ // Mirror the profile state the request actually ran under:
819
+ // `forceOverrideProfile` floats the override above the call-site
820
+ // profile (fork retrospectives with matchConversationProfile), and
821
+ // the conversation-id seed resolves the same mix arm the dispatch
822
+ // path chose. Without these, attribution credits the call-site
823
+ // profile/arm instead of the one that ran.
824
+ {
825
+ callSite,
826
+ overrideProfile: overrideProfile ?? null,
827
+ forceOverrideProfile,
828
+ selectionSeed: conversationId,
829
+ },
830
+ );
831
+ } catch (err) {
832
+ log.warn(
833
+ { conversationId, source, err },
834
+ "agent-wake: usage recording failed (non-fatal)",
835
+ );
836
+ }
837
+ }
787
838
  // Replicates the recordRequestLog side-effect in `handleUsage` because
788
839
  // wakes own their own onEvent and never reach `dispatchAgentEvent`.
789
840
  // Defer persistence while buffering — see `pendingLogs` above.
@@ -1063,6 +1114,19 @@ export async function wakeAgentForOpportunity(
1063
1114
  };
1064
1115
  }
1065
1116
 
1117
+ // Wakes bypass `runAgentLoopImpl`, which is what stamps the live turn's
1118
+ // call site and override profile onto the conversation for the tool
1119
+ // executor to read. Without stamping them here, `subagent_spawn` (and
1120
+ // usage attribution) see an unstamped context and resolve children under
1121
+ // workspace defaults instead of the profile this wake actually runs
1122
+ // under — so a wake on a conversation pinned to another profile spawns
1123
+ // children under the wrong one. Restored in the `finally` so a queued
1124
+ // user turn or a later background read never inherits the wake's stamps.
1125
+ const priorCallSite = conversation.currentCallSite;
1126
+ const priorTurnOverrideProfile = conversation.currentTurnOverrideProfile;
1127
+ conversation.currentCallSite = callSite;
1128
+ conversation.currentTurnOverrideProfile = overrideProfile;
1129
+
1066
1130
  let updatedHistory: Message[];
1067
1131
  try {
1068
1132
  ({ history: updatedHistory } = await conversation.agentLoop.run({
@@ -1080,6 +1144,7 @@ export async function wakeAgentForOpportunity(
1080
1144
  trust: wakeTrust,
1081
1145
  overrideProfile,
1082
1146
  forceOverrideProfile,
1147
+ isNonInteractive,
1083
1148
  // The wake's compaction lives in the pre-run gate above
1084
1149
  // (`conversation.maybeCompact()`), never in the loop: the in-loop
1085
1150
  // budget gate and overflow-recovery ladder stay disabled because
@@ -1112,6 +1177,12 @@ export async function wakeAgentForOpportunity(
1112
1177
  // `processing` and drain the queue.
1113
1178
  runError = err instanceof Error ? err : new Error(String(err));
1114
1179
  return { invoked: true, producedToolCalls: false };
1180
+ } finally {
1181
+ // Restore the pre-wake values so a queued user turn or background read
1182
+ // never observes the wake's stamps. (`runAgentLoopImpl` re-stamps both
1183
+ // at the start of the next normal turn regardless.)
1184
+ conversation.currentCallSite = priorCallSite;
1185
+ conversation.currentTurnOverrideProfile = priorTurnOverrideProfile;
1115
1186
  }
1116
1187
 
1117
1188
  // The loop swallows provider rejections into a graceful no-output
@@ -40,6 +40,7 @@ export function capabilityForMessageType(
40
40
  return HOST_PREFIX_TO_CAPABILITY[stem];
41
41
  }
42
42
  import { appendEventToStream } from "../signals/event-stream.js";
43
+ import { IntegrityError } from "../util/errors.js";
43
44
  import { getLogger } from "../util/logger.js";
44
45
  import type { AssistantEvent } from "./assistant-event.js";
45
46
  import { buildAssistantEvent } from "./assistant-event.js";
@@ -757,9 +758,22 @@ async function createCanonicalRequestForConfirmation(
757
758
  });
758
759
  }
759
760
  } catch (err) {
760
- log.debug(
761
- { err, conversationId },
762
- "Failed to create canonical request from broadcast",
763
- );
761
+ if (err instanceof IntegrityError) {
762
+ // The confirmation could not be promoted to a canonical guardian request
763
+ // (e.g. its trust context resolved no guardianPrincipalId). Channel
764
+ // guardian decisions — reactions, buttons, and text — all route through
765
+ // the canonical pipeline, so without this record none of them can resolve
766
+ // the confirmation. Surface it rather than swallowing: for a guardian's
767
+ // own confirmation a bound principal should always be present.
768
+ log.warn(
769
+ { err, conversationId, requestId: msg.requestId },
770
+ "Could not create canonical guardian request for confirmation; channel guardian decisions will not work for it",
771
+ );
772
+ } else {
773
+ log.debug(
774
+ { err, conversationId },
775
+ "Failed to create canonical request from broadcast",
776
+ );
777
+ }
764
778
  }
765
779
  }
@@ -210,6 +210,18 @@ describe("ROUTES policy declarations", () => {
210
210
  expect(route!.policy!.requiredScopes).toContain("chat.write");
211
211
  });
212
212
 
213
+ test("platform/status is readable by browser actors", async () => {
214
+ const { ROUTES } = await import("../../routes/index.js");
215
+ const route = ROUTES.find(
216
+ (r) => r.endpoint === "platform/status" && r.method === "GET",
217
+ );
218
+ expect(route).toBeDefined();
219
+ expect(route!.policy).not.toBeNull();
220
+ expect(route!.policy!.allowedPrincipalTypes).toContain("actor");
221
+ expect(route!.policy!.allowedPrincipalTypes).toContain("local");
222
+ expect(route!.policy!.requiredScopes).toContain("settings.read");
223
+ });
224
+
213
225
  test("confirm declares an approval-write policy", async () => {
214
226
  const { ROUTES } = await import("../../routes/index.js");
215
227
  const route = ROUTES.find((r) => r.endpoint === "confirm");
@@ -27,10 +27,7 @@ export function requireBoundGuardian(
27
27
  // No guardian yet — in pre-bootstrap state, allow through
28
28
  return null;
29
29
  }
30
- if (
31
- (guardianResult.channel.externalUserId ??
32
- guardianResult.contact.principalId) !== authContext.actorPrincipalId
33
- ) {
30
+ if (guardianResult.channel.address !== authContext.actorPrincipalId) {
34
31
  return httpError(
35
32
  "FORBIDDEN",
36
33
  "Actor is not the bound guardian for this channel",
@@ -31,10 +31,9 @@ export interface RunBtwSidechainParams {
31
31
  /**
32
32
  * Unified call-site identifier. The provider layer resolves
33
33
  * provider/model/maxTokens/effort/speed/temperature/thinking/contextWindow
34
- * via `resolveCallSiteConfig(callSite, config.llm)`. Defaults to
35
- * `'identityIntro'` since this side-chain runner was originally introduced
36
- * for the identity intro generation path; callers (greeting, title, etc.)
37
- * override it with their own call-site ID.
34
+ * via `resolveCallSiteConfig(callSite, config.llm)`. Generic BTW traffic
35
+ * uses `identityIntro`; callers with a narrower purpose override it with
36
+ * their own call-site ID.
38
37
  */
39
38
  callSite?: LLMCallSite;
40
39
  signal?: AbortSignal;
@@ -95,8 +94,6 @@ export async function runBtwSidechain(
95
94
  config: {
96
95
  max_tokens: params.maxTokens ?? 1024,
97
96
  tool_choice: { type: "none" },
98
- // Default call site is "identityIntro" — the original purpose of
99
- // this side-chain runner. Callers may override per invocation.
100
97
  callSite: params.callSite ?? ("identityIntro" as LLMCallSite),
101
98
  },
102
99
  onEvent: (event) => {
@@ -0,0 +1,120 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import type { TrustClass } from "./actor-trust-resolver.js";
4
+ import { type CapabilitySet, resolveCapabilities } from "./capabilities.js";
5
+
6
+ /**
7
+ * The capability matrix — the single source of truth for what each trust class
8
+ * may do. If a call site's behavior changes during migration, it changes here
9
+ * (reviewed in one diff) instead of across the ~40 inline conditionals.
10
+ */
11
+ const MATRIX: Record<TrustClass, CapabilitySet> = {
12
+ guardian: {
13
+ canSelfApproveTools: true,
14
+ sensitiveToolApproval: "self",
15
+ canManageSchedules: true,
16
+ canUseVerificationControlPlane: true,
17
+ canSelfAuthorizeArchiveBySender: true,
18
+ canAccessMemory: true,
19
+ canAccessPrivilegedDocuments: true,
20
+ canRunUnsandboxedShell: true,
21
+ mayBeInteractive: true,
22
+ canActUnderDiskPressureCleanup: true,
23
+ promptTrustGuidance: "none",
24
+ },
25
+ trusted_contact: {
26
+ canSelfApproveTools: false,
27
+ sensitiveToolApproval: "escalate-and-wait",
28
+ canManageSchedules: false,
29
+ canUseVerificationControlPlane: false,
30
+ canSelfAuthorizeArchiveBySender: false,
31
+ canAccessMemory: false,
32
+ canAccessPrivilegedDocuments: false,
33
+ canRunUnsandboxedShell: false,
34
+ mayBeInteractive: true,
35
+ canActUnderDiskPressureCleanup: false,
36
+ promptTrustGuidance: "social-engineering-defense",
37
+ },
38
+ unverified_contact: {
39
+ canSelfApproveTools: false,
40
+ sensitiveToolApproval: "escalate-and-wait",
41
+ canManageSchedules: false,
42
+ canUseVerificationControlPlane: false,
43
+ canSelfAuthorizeArchiveBySender: false,
44
+ canAccessMemory: false,
45
+ canAccessPrivilegedDocuments: false,
46
+ canRunUnsandboxedShell: false,
47
+ mayBeInteractive: true,
48
+ canActUnderDiskPressureCleanup: false,
49
+ promptTrustGuidance: "social-engineering-defense",
50
+ },
51
+ unknown: {
52
+ canSelfApproveTools: false,
53
+ sensitiveToolApproval: "deny",
54
+ canManageSchedules: false,
55
+ canUseVerificationControlPlane: false,
56
+ canSelfAuthorizeArchiveBySender: false,
57
+ canAccessMemory: false,
58
+ canAccessPrivilegedDocuments: false,
59
+ canRunUnsandboxedShell: false,
60
+ mayBeInteractive: false,
61
+ canActUnderDiskPressureCleanup: false,
62
+ promptTrustGuidance: "stranger-warning",
63
+ },
64
+ };
65
+
66
+ describe("resolveCapabilities", () => {
67
+ for (const trustClass of Object.keys(MATRIX) as TrustClass[]) {
68
+ test(`resolves the full capability set for "${trustClass}"`, () => {
69
+ expect(resolveCapabilities(trustClass)).toEqual(MATRIX[trustClass]);
70
+ });
71
+ }
72
+
73
+ test("undefined fail-closes to the `unknown` capability set", () => {
74
+ expect(resolveCapabilities(undefined)).toEqual(MATRIX.unknown);
75
+ });
76
+
77
+ test("an unrecognized/legacy string fail-closes to the `unknown` capability set", () => {
78
+ expect(resolveCapabilities("non_guardian")).toEqual(MATRIX.unknown);
79
+ expect(resolveCapabilities("some_future_role")).toEqual(MATRIX.unknown);
80
+ });
81
+
82
+ test("inherited Object.prototype keys fail-closed (no prototype read)", () => {
83
+ for (const key of [
84
+ "__proto__",
85
+ "constructor",
86
+ "toString",
87
+ "hasOwnProperty",
88
+ ]) {
89
+ expect(resolveCapabilities(key)).toEqual(MATRIX.unknown);
90
+ }
91
+ });
92
+
93
+ test("unverified_contact is byte-for-byte identical to trusted_contact (admission-only distinction)", () => {
94
+ expect(resolveCapabilities("unverified_contact")).toEqual(
95
+ resolveCapabilities("trusted_contact"),
96
+ );
97
+ });
98
+
99
+ test("only guardian self-approves; only guardian/contacts may be interactive", () => {
100
+ expect(resolveCapabilities("guardian").canSelfApproveTools).toBe(true);
101
+ expect(resolveCapabilities("trusted_contact").canSelfApproveTools).toBe(
102
+ false,
103
+ );
104
+
105
+ expect(resolveCapabilities("guardian").mayBeInteractive).toBe(true);
106
+ expect(resolveCapabilities("trusted_contact").mayBeInteractive).toBe(true);
107
+ expect(resolveCapabilities("unverified_contact").mayBeInteractive).toBe(
108
+ true,
109
+ );
110
+ expect(resolveCapabilities("unknown").mayBeInteractive).toBe(false);
111
+ });
112
+
113
+ test("sensitive tool approval is graded across the three tiers", () => {
114
+ expect(resolveCapabilities("guardian").sensitiveToolApproval).toBe("self");
115
+ expect(resolveCapabilities("trusted_contact").sensitiveToolApproval).toBe(
116
+ "escalate-and-wait",
117
+ );
118
+ expect(resolveCapabilities("unknown").sensitiveToolApproval).toBe("deny");
119
+ });
120
+ });
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Trust capabilities — what an actor may do once admitted.
3
+ *
4
+ * Separates *what an actor can do* (capabilities/permissions) from *who the
5
+ * actor is* (`TrustClass`, their role/level). The ~40+ decision sites
6
+ * read a named capability instead of re-deriving permissions inline from the
7
+ * This resolves the class to a named capability set in one place so call sites
8
+ * read a capability instead of re-deriving it.
9
+ *
10
+ * Stateless / derive-on-read: capabilities are derived from the already-resolved
11
+ * (and already-persisted) `trustClass` at point of use. Nothing here is stored;
12
+ * `trustClass` remains the persisted field in retry payloads, the journal store,
13
+ * and conversation CRUD.
14
+ *
15
+ * Admission is a SEPARATE axis: `TRUST_CLASS_RANK` vs `ADMISSION_FLOOR`
16
+ * ("who gets in the door") is intentionally not modeled here. `CapabilitySet`
17
+ * is the "what they may do once inside" axis.
18
+ *
19
+ * Context-dependent decisions (interactivity routing, self-approval races,
20
+ * channel-specific overrides) COMPOSE these primitives with runtime context.
21
+ * They are not encoded in the table; named composition helpers live in
22
+ * `effective-capabilities.ts` (and `resolveRoutingState` in
23
+ * `trust-context-resolver.ts`).
24
+ */
25
+
26
+ import type { TrustClass } from "./actor-trust-resolver.js";
27
+
28
+ /**
29
+ * Outcome when an actor invokes a tool that requires guardian approval.
30
+ * - `self`: the actor self-approves (guardian).
31
+ * - `escalate-and-wait`: route to the guardian and wait inline for a grant.
32
+ * - `deny`: fail-closed, no escalation or wait.
33
+ */
34
+ export type SensitiveToolApproval = "self" | "escalate-and-wait" | "deny";
35
+
36
+ /**
37
+ * Which trust-guidance block to inject into the model prompt. The capability
38
+ * layer owns the *selector*; the prompt layer owns the copy for each value.
39
+ */
40
+ export type PromptTrustGuidance =
41
+ | "none"
42
+ | "social-engineering-defense"
43
+ | "stranger-warning";
44
+
45
+ /**
46
+ * What an actor may do once admitted, derived purely from their trust class.
47
+ */
48
+ export interface CapabilitySet {
49
+ // --- Tool approval mechanism ---
50
+ /**
51
+ * Auto-approves *ordinary* tool calls (e.g. background/platform-hosted bash)
52
+ * and honors the actor's own pending-confirmation callback. The
53
+ * sensitive/guardian-required tool path is governed separately by
54
+ * `sensitiveToolApproval`; the two are independent levers.
55
+ */
56
+ canSelfApproveTools: boolean;
57
+ /** Outcome when a guardian-approval-required (sensitive) tool is invoked. */
58
+ sensitiveToolApproval: SensitiveToolApproval;
59
+
60
+ // --- Privileged tool gates ---
61
+ /** May create/update schedules. */
62
+ canManageSchedules: boolean;
63
+ /** May use verification control-plane tools. */
64
+ canUseVerificationControlPlane: boolean;
65
+ /**
66
+ * May treat its own `user_approved` flag as sufficient authorization to
67
+ * archive-by-sender. Non-guardians can still archive by sender, but must be
68
+ * authorized via surface action, task, or explicit prompt approval instead.
69
+ */
70
+ canSelfAuthorizeArchiveBySender: boolean;
71
+
72
+ // --- Data & memory ---
73
+ /**
74
+ * May access long-term / cross-conversation memory — both the memory *tools*
75
+ * (recall, auto-analysis, retrospection, graph extraction) and *visibility*
76
+ * of cross-conversation history in assembled context. Untrusted actors are
77
+ * walled off from both.
78
+ */
79
+ canAccessMemory: boolean;
80
+ /**
81
+ * May perform privileged (non-conversation-scoped) document operations from
82
+ * trust class alone. The effective decision also honors privileged channels —
83
+ * see `canActOnPrivilegedDocuments` in `effective-capabilities.ts`.
84
+ */
85
+ canAccessPrivilegedDocuments: boolean;
86
+
87
+ // --- Execution environment ---
88
+ /**
89
+ * May run the shell WITHOUT the untrusted sandbox / CES lockdown (no
90
+ * `VELLUM_UNTRUSTED_SHELL`, no credential-secrecy confinement).
91
+ */
92
+ canRunUnsandboxedShell: boolean;
93
+
94
+ // --- Interactivity & resource ---
95
+ /**
96
+ * Trust class alone permits interactive guardian-approval waits. Composed
97
+ * downstream with `guardianRouteResolvable` to derive `promptWaitingAllowed`
98
+ * (see `resolveRoutingState`).
99
+ */
100
+ mayBeInteractive: boolean;
101
+ /** May trigger cleanup-mode operations under disk pressure. */
102
+ canActUnderDiskPressureCleanup: boolean;
103
+
104
+ // --- Prompt shaping ---
105
+ /** Which trust-guidance block to inject into the model prompt. */
106
+ promptTrustGuidance: PromptTrustGuidance;
107
+ }
108
+
109
+ /**
110
+ * Guardian: full control-plane access, self-approves tools.
111
+ */
112
+ const GUARDIAN_CAPABILITIES: CapabilitySet = {
113
+ canSelfApproveTools: true,
114
+ sensitiveToolApproval: "self",
115
+ canManageSchedules: true,
116
+ canUseVerificationControlPlane: true,
117
+ canSelfAuthorizeArchiveBySender: true,
118
+ canAccessMemory: true,
119
+ canAccessPrivilegedDocuments: true,
120
+ canRunUnsandboxedShell: true,
121
+ mayBeInteractive: true,
122
+ canActUnderDiskPressureCleanup: true,
123
+ promptTrustGuidance: "none",
124
+ };
125
+
126
+ /**
127
+ * Trusted / unverified contacts: may invoke tools but escalate sensitive ones
128
+ * to the guardian; no privileged data access; sandboxed execution.
129
+ *
130
+ * `trusted_contact` and `unverified_contact` are deliberately identical here —
131
+ * the distinction is admission-only (see `actor-trust-resolver.ts`). The matrix
132
+ * test pins this invariant.
133
+ */
134
+ const CONTACT_CAPABILITIES: CapabilitySet = {
135
+ canSelfApproveTools: false,
136
+ sensitiveToolApproval: "escalate-and-wait",
137
+ canManageSchedules: false,
138
+ canUseVerificationControlPlane: false,
139
+ canSelfAuthorizeArchiveBySender: false,
140
+ canAccessMemory: false,
141
+ canAccessPrivilegedDocuments: false,
142
+ canRunUnsandboxedShell: false,
143
+ mayBeInteractive: true,
144
+ canActUnderDiskPressureCleanup: false,
145
+ promptTrustGuidance: "social-engineering-defense",
146
+ };
147
+
148
+ /**
149
+ * Unknown actors: fail-closed. No escalation, no interactivity, treated as a
150
+ * potential stranger in the prompt.
151
+ */
152
+ const UNKNOWN_CAPABILITIES: CapabilitySet = {
153
+ canSelfApproveTools: false,
154
+ sensitiveToolApproval: "deny",
155
+ canManageSchedules: false,
156
+ canUseVerificationControlPlane: false,
157
+ canSelfAuthorizeArchiveBySender: false,
158
+ canAccessMemory: false,
159
+ canAccessPrivilegedDocuments: false,
160
+ canRunUnsandboxedShell: false,
161
+ mayBeInteractive: false,
162
+ canActUnderDiskPressureCleanup: false,
163
+ promptTrustGuidance: "stranger-warning",
164
+ };
165
+
166
+ const CAPABILITIES_BY_CLASS: Record<TrustClass, CapabilitySet> = {
167
+ guardian: GUARDIAN_CAPABILITIES,
168
+ trusted_contact: CONTACT_CAPABILITIES,
169
+ unverified_contact: CONTACT_CAPABILITIES,
170
+ unknown: UNKNOWN_CAPABILITIES,
171
+ };
172
+
173
+ /**
174
+ * Resolve the capability set for a trust class. Pure and stateless.
175
+ *
176
+ * This is the single fail-closed trust boundary: any value that is not a
177
+ * recognized `TrustClass` — including `undefined` and legacy/persisted strings
178
+ * (e.g. `"non_guardian"`) — resolves to the `unknown` capability set. Callers
179
+ * pass their raw trust value directly; they never re-derive "is this a known
180
+ * class?" at the call site. The `(string & {})` member keeps autocomplete for
181
+ * the known classes while still accepting an arbitrary string.
182
+ *
183
+ * The lookup uses an own-property check so raw values that name inherited
184
+ * members (`"__proto__"`, `"constructor"`, `"toString"`) fail closed to the
185
+ * `unknown` set rather than reading off `Object.prototype`.
186
+ */
187
+ export function resolveCapabilities(
188
+ trustClass: TrustClass | (string & {}) | undefined,
189
+ ): CapabilitySet {
190
+ if (
191
+ trustClass != null &&
192
+ Object.prototype.hasOwnProperty.call(CAPABILITIES_BY_CLASS, trustClass)
193
+ ) {
194
+ return CAPABILITIES_BY_CLASS[trustClass as TrustClass];
195
+ }
196
+ return UNKNOWN_CAPABILITIES;
197
+ }
@@ -1,27 +1,35 @@
1
1
  /**
2
2
  * Channel-agnostic approval flow types.
3
3
  *
4
- * These types model the approval prompt/decision lifecycle for tool-use
5
- * confirmations surfaced through external channels (Telegram, Slack, etc.).
6
- * They are intentionally decoupled from any specific channel so that the
7
- * same approval flow can be reused across transports.
4
+ * Wire-format types (`ApprovalUIMetadata`, `PermissionRequestDetails`,
5
+ * `ApprovalActionOption`) are defined as Zod schemas in
6
+ * `@vellumai/gateway-client/outbound-contract` and re-exported here for
7
+ * convenience. Daemon-internal types that do not cross a wire boundary
8
+ * are defined locally.
8
9
  */
9
10
 
11
+ import type { ApprovalActionOption } from "@vellumai/gateway-client";
12
+
10
13
  import type { GuardianDecisionAction } from "./guardian-decision-types.js";
11
14
 
15
+ export type {
16
+ ApprovalActionOption,
17
+ ApprovalUIMetadata,
18
+ PermissionRequestDetails,
19
+ } from "@vellumai/gateway-client";
20
+ // Re-export shared wire types + schemas so existing daemon imports keep working.
21
+ export {
22
+ ApprovalUIMetadataSchema,
23
+ PermissionRequestDetailsSchema,
24
+ } from "@vellumai/gateway-client";
25
+
12
26
  // ---------------------------------------------------------------------------
13
- // Approval actions
27
+ // Approval actions (daemon-internal)
14
28
  // ---------------------------------------------------------------------------
15
29
 
16
30
  /** The set of actions a user can take on an approval prompt. */
17
31
  export type ApprovalAction = "approve_once" | "reject";
18
32
 
19
- /** An action presented to the user as a tappable button or text option. */
20
- export interface ApprovalActionOption {
21
- id: ApprovalAction;
22
- label: string;
23
- }
24
-
25
33
  /**
26
34
  * Map `GuardianDecisionAction[]` to `ApprovalActionOption[]` so channel
27
35
  * prompt payloads can be derived from the unified decision action set.
@@ -32,13 +40,13 @@ export function toApprovalActionOptions(
32
40
  actions: GuardianDecisionAction[],
33
41
  ): ApprovalActionOption[] {
34
42
  return actions.map((a) => ({
35
- id: a.action as ApprovalAction,
43
+ id: a.action,
36
44
  label: a.label,
37
45
  }));
38
46
  }
39
47
 
40
48
  // ---------------------------------------------------------------------------
41
- // Approval prompt
49
+ // Approval prompt (daemon-internal)
42
50
  // ---------------------------------------------------------------------------
43
51
 
44
52
  /** The approval prompt model sent to users via a channel. */
@@ -52,38 +60,7 @@ export interface ChannelApprovalPrompt {
52
60
  }
53
61
 
54
62
  // ---------------------------------------------------------------------------
55
- // Approval UI metadata (gateway callback payload)
56
- // ---------------------------------------------------------------------------
57
-
58
- /**
59
- * Tool-permission-specific details carried alongside the approval payload.
60
- * Channels that support rich UI (e.g. Slack Block Kit) use these fields
61
- * to render a detailed permission request card with risk indicators,
62
- * tool arguments, and requester identity.
63
- */
64
- export interface PermissionRequestDetails {
65
- toolName: string;
66
- riskLevel: string;
67
- toolInput: Record<string, unknown>;
68
- /** Present for guardian-escalated requests to identify who is asking. */
69
- requesterIdentifier?: string;
70
- }
71
-
72
- /**
73
- * Metadata attached to gateway callback payloads so the channel adapter
74
- * can render approval UI and route the user's decision back to the
75
- * correct pending interaction.
76
- */
77
- export interface ApprovalUIMetadata {
78
- requestId: string;
79
- actions: ApprovalActionOption[];
80
- plainTextFallback: string;
81
- /** When present, the approval is a tool permission request with extra context. */
82
- permissionDetails?: PermissionRequestDetails;
83
- }
84
-
85
- // ---------------------------------------------------------------------------
86
- // Decision result
63
+ // Decision result (daemon-internal)
87
64
  // ---------------------------------------------------------------------------
88
65
 
89
66
  /** How the user communicated their decision. */
@@ -36,10 +36,10 @@ import type {
36
36
 
37
37
  /**
38
38
  * Ensure the Telegram bot username is resolved and cached in config.
39
- * When the bot token was configured via CLI `credential set`,
40
- * `credential_store` tool, or ingress secret redirect, the `getMe` API
41
- * call that populates the config is skipped — this function fills that
42
- * gap so that invite share links can be generated.
39
+ * When the bot token was configured via the `assistant credentials set` CLI
40
+ * or ingress secret redirect, the `getMe` API call that populates the config
41
+ * is skipped — this function fills that gap so that invite share links can be
42
+ * generated.
43
43
  */
44
44
  export async function ensureTelegramBotUsernameResolved(): Promise<void> {
45
45
  if (getTelegramBotUsername() && getTelegramBotId()) {
@@ -52,6 +52,7 @@ function parseTrustRuntimeContext(value: unknown): TrustContext | undefined {
52
52
  if (
53
53
  trustClass !== "guardian" &&
54
54
  trustClass !== "trusted_contact" &&
55
+ trustClass !== "unverified_contact" &&
55
56
  trustClass !== "unknown"
56
57
  ) {
57
58
  return undefined;
@@ -333,7 +333,7 @@ export function getGuardianBinding(
333
333
  id: result.channel.id,
334
334
  assistantId,
335
335
  channel,
336
- guardianExternalUserId: result.channel.externalUserId ?? "",
336
+ guardianExternalUserId: result.channel.address,
337
337
  guardianDeliveryChatId: result.channel.externalChatId ?? "",
338
338
  guardianPrincipalId: result.contact.principalId ?? "",
339
339
  status: "active" as const,
@@ -355,11 +355,11 @@ export function getGuardianBinding(
355
355
  export function isGuardian(
356
356
  assistantId: string,
357
357
  channel: string,
358
- externalUserId: string,
358
+ address: string,
359
359
  ): boolean {
360
360
  const result = findGuardianForChannel(channel);
361
361
  if (result) {
362
- return result.channel.externalUserId === externalUserId;
362
+ return result.channel.address.toLowerCase() === address.toLowerCase();
363
363
  }
364
364
 
365
365
  return false;