@vellumai/assistant 0.11.6 → 0.11.7-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 (478) hide show
  1. package/ARCHITECTURE.md +31 -19
  2. package/Dockerfile +1 -0
  3. package/docs/architecture/security.md +3 -3
  4. package/docs/flux-turn-detection-spike.md +8 -7
  5. package/docs/runbook-trusted-contacts.md +14 -0
  6. package/docs/stt-provider-onboarding.md +8 -4
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/avatar-manifest/package.json +18 -0
  9. package/node_modules/@vellumai/avatar-manifest/src/__tests__/manifest.test.ts +173 -0
  10. package/node_modules/@vellumai/avatar-manifest/src/__tests__/read.test.ts +114 -0
  11. package/node_modules/@vellumai/avatar-manifest/src/index.ts +29 -0
  12. package/node_modules/@vellumai/avatar-manifest/src/layout.ts +18 -0
  13. package/node_modules/@vellumai/avatar-manifest/src/manifest.ts +156 -0
  14. package/node_modules/@vellumai/avatar-manifest/src/read.ts +109 -0
  15. package/node_modules/@vellumai/avatar-manifest/tsconfig.json +20 -0
  16. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
  17. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
  18. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
  19. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
  20. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
  21. package/node_modules/@vellumai/ces-client/src/http-credentials.ts +161 -0
  22. package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
  23. package/node_modules/@vellumai/environments/package.json +2 -1
  24. package/node_modules/@vellumai/environments/src/shell.test.ts +56 -0
  25. package/node_modules/@vellumai/environments/src/shell.ts +65 -0
  26. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
  27. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
  28. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
  29. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
  30. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
  31. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +32 -0
  32. package/node_modules/@vellumai/gateway-client/src/__tests__/gateway-client.test.ts +1 -0
  33. package/node_modules/@vellumai/gateway-client/src/__tests__/inbound-event-kind.test.ts +82 -0
  34. package/node_modules/@vellumai/gateway-client/src/__tests__/plugin-admission-denied-contract.test.ts +56 -0
  35. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +18 -0
  36. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +5 -11
  37. package/node_modules/@vellumai/gateway-client/src/channel-permission-contract.ts +3 -1
  38. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +9 -0
  39. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +4 -0
  40. package/node_modules/@vellumai/gateway-client/src/inbound-event-kind.ts +75 -0
  41. package/node_modules/@vellumai/gateway-client/src/index.ts +17 -0
  42. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +8 -0
  43. package/node_modules/@vellumai/gateway-client/src/plugin-admission-denied-contract.ts +47 -0
  44. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +11 -0
  45. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
  46. package/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
  47. package/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
  48. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
  49. package/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
  50. package/openapi.yaml +419 -55
  51. package/package.json +4 -1
  52. package/scripts/sync-llm-catalog.ts +6 -0
  53. package/src/__tests__/approval-card-edit-inbound-handoff.test.ts +199 -0
  54. package/src/__tests__/approval-card-edit.test.ts +153 -0
  55. package/src/__tests__/attachments-store-heic-normalize.test.ts +1 -1
  56. package/src/__tests__/available-skills.test.ts +54 -0
  57. package/src/__tests__/avatar-identity-sync.test.ts +5 -1
  58. package/src/__tests__/catalog-install-normalize.test.ts +9 -1
  59. package/src/__tests__/channel-policy.test.ts +1 -3
  60. package/src/__tests__/channel-readiness-discord.test.ts +9 -70
  61. package/src/__tests__/compactor-call-site-logging.test.ts +61 -0
  62. package/src/__tests__/config-loader-backfill.test.ts +69 -0
  63. package/src/__tests__/config-schema.test.ts +2 -3
  64. package/src/__tests__/conversation-agent-loop.test.ts +238 -0
  65. package/src/__tests__/conversation-attachments.test.ts +0 -1
  66. package/src/__tests__/conversation-error.test.ts +44 -0
  67. package/src/__tests__/conversation-evictor.test.ts +19 -0
  68. package/src/__tests__/conversation-fork-referential.test.ts +73 -63
  69. package/src/__tests__/conversation-fork-retrospective.test.ts +99 -74
  70. package/src/__tests__/conversation-runtime-assembly.test.ts +23 -0
  71. package/src/__tests__/conversation-slash.test.ts +9 -0
  72. package/src/__tests__/conversation-title-service.test.ts +97 -0
  73. package/src/__tests__/conversation-tool-setup-attribution.test.ts +16 -0
  74. package/src/__tests__/credential-broker-server-use.test.ts +0 -218
  75. package/src/__tests__/credential-broker.test.ts +43 -420
  76. package/src/__tests__/credential-record-write-through.test.ts +78 -0
  77. package/src/__tests__/credential-routes.test.ts +17 -1
  78. package/src/__tests__/credential-security-invariants.test.ts +8 -9
  79. package/src/__tests__/default-profile-catalog-fallback.test.ts +289 -0
  80. package/src/__tests__/delete-propagation.test.ts +92 -2
  81. package/src/__tests__/discord-callback-round-trip.test.ts +93 -0
  82. package/src/__tests__/discord-channel-config.test.ts +237 -0
  83. package/src/__tests__/edit-propagation.test.ts +42 -2
  84. package/src/__tests__/evict-conversations-for-reload.test.ts +51 -1
  85. package/src/__tests__/fallback-breaker.test.ts +1335 -0
  86. package/src/__tests__/gateway-threshold-reader-mock.ts +6 -0
  87. package/src/__tests__/guardian-card-withdrawal.test.ts +30 -0
  88. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -2
  89. package/src/__tests__/image-conversion.test.ts +38 -4
  90. package/src/__tests__/install-skill-routing.test.ts +25 -0
  91. package/src/__tests__/llm-catalog-parity.test.ts +4 -0
  92. package/src/__tests__/llm-resolver.test.ts +74 -0
  93. package/src/__tests__/llm-schema-fallback-profile.test.ts +359 -0
  94. package/src/__tests__/managed-fallback-dispatch.test.ts +430 -0
  95. package/src/__tests__/managed-profile-guard.test.ts +28 -0
  96. package/src/__tests__/managed-speech-defaults.test.ts +196 -1
  97. package/src/__tests__/mcp-cli.test.ts +23 -1
  98. package/src/__tests__/mcp-tool-annotations-risk.test.ts +43 -34
  99. package/src/__tests__/media-stream-stt-session.test.ts +2 -0
  100. package/src/__tests__/notification-decision-fallback.test.ts +106 -0
  101. package/src/__tests__/notification-discord-adapter.test.ts +162 -0
  102. package/src/__tests__/oauth-connect-orchestrator.test.ts +95 -0
  103. package/src/__tests__/persist-unsendable-image-downscale.test.ts +6 -8
  104. package/src/__tests__/persist-unsendable-image.test.ts +3 -3
  105. package/src/__tests__/platform.test.ts +19 -1
  106. package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
  107. package/src/__tests__/provider-catalog-visibility.test.ts +17 -0
  108. package/src/__tests__/provider-platform-proxy-integration.test.ts +8 -1
  109. package/src/__tests__/provider-usage-tracking.test.ts +56 -0
  110. package/src/__tests__/require-fresh-approval.test.ts +5 -2
  111. package/src/__tests__/retry-fallback-escalation.test.ts +1093 -0
  112. package/src/__tests__/schedule-retry.test.ts +183 -4
  113. package/src/__tests__/scheduler-reuse-conversation.test.ts +6 -6
  114. package/src/__tests__/secret-routes-platform-proxy.test.ts +55 -0
  115. package/src/__tests__/skill-load-tool.test.ts +34 -0
  116. package/src/__tests__/skill-tool-factory.test.ts +6 -1
  117. package/src/__tests__/skill-tool-manifest.test.ts +20 -0
  118. package/src/__tests__/skills.test.ts +25 -0
  119. package/src/__tests__/subagent-manager-notify.test.ts +38 -0
  120. package/src/__tests__/terminal-tools.test.ts +2 -0
  121. package/src/__tests__/tool-approval-handler.test.ts +146 -2
  122. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +108 -2
  123. package/src/__tests__/tool-audit.test.ts +111 -40
  124. package/src/__tests__/tool-executor-lifecycle-events.test.ts +228 -18
  125. package/src/__tests__/ui-shape-teaching.test.ts +1 -1
  126. package/src/__tests__/verification-control-plane-policy.test.ts +6 -2
  127. package/src/__tests__/voice-config-update.test.ts +43 -0
  128. package/src/__tests__/workspace-migration-147-rename-colliding-backup-profile-names.test.ts +480 -0
  129. package/src/__tests__/workspace-migration-148-strip-unsupported-fallback-profiles.test.ts +167 -0
  130. package/src/__tests__/workspace-migration-149-repoint-backup-profile-selections.test.ts +144 -0
  131. package/src/agent/loop.ts +31 -2
  132. package/src/approvals/guardian-card-withdrawal.ts +22 -0
  133. package/src/avatar/__tests__/ensure-raster.test.ts +291 -0
  134. package/src/avatar/avatar-manifest.ts +48 -100
  135. package/src/avatar/avatar-store.ts +7 -7
  136. package/src/avatar/ensure-raster.ts +146 -0
  137. package/src/avatar/resvg-lazy.test.ts +0 -1
  138. package/src/avatar/traits-png-sync.ts +9 -10
  139. package/src/background-wake/wake-intent-hooks.test.ts +0 -1
  140. package/src/backup/__tests__/paths.test.ts +6 -2
  141. package/src/backup/paths.ts +6 -4
  142. package/src/bundler/app-compiler.ts +2 -2
  143. package/src/bundler/compiler-tools.test.ts +36 -0
  144. package/src/bundler/compiler-tools.ts +54 -18
  145. package/src/calls/__tests__/telephony-synthesis-language.test.ts +81 -0
  146. package/src/calls/__tests__/voice-session-bridge.test.ts +57 -0
  147. package/src/calls/media-stream-stt-session.ts +2 -1
  148. package/src/calls/telephony-synthesis-language.ts +13 -5
  149. package/src/calls/voice-session-bridge.ts +19 -4
  150. package/src/channels/config.ts +23 -12
  151. package/src/cli/AGENTS.md +3 -1
  152. package/src/cli/commands/backup.help.ts +10 -13
  153. package/src/cli/commands/contacts.help.ts +16 -4
  154. package/src/cli/commands/contacts.ts +5 -1
  155. package/src/cli/commands/credentials.help.ts +1 -1
  156. package/src/cli/commands/inference-providers.ts +18 -53
  157. package/src/cli/commands/mcp.help.ts +6 -5
  158. package/src/cli/commands/mcp.ts +1 -1
  159. package/src/cli/commands/memory/memory-retrospective.ts +1 -0
  160. package/src/cli/commands/stt.help.ts +2 -2
  161. package/src/config/__tests__/backup-schema.test.ts +1 -1
  162. package/src/config/__tests__/default-profile-catalog.test.ts +83 -2
  163. package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +1 -1
  164. package/src/config/__tests__/memory-retrospective-schema.test.ts +12 -15
  165. package/src/config/bundled-skills/computer-use/SKILL.md +6 -6
  166. package/src/config/bundled-skills/computer-use/TOOLS.json +9 -6
  167. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +3 -1
  168. package/src/config/bundled-skills/media-processing/services/preprocess.ts +1 -1
  169. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  170. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +16 -15
  171. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +2 -1
  172. package/src/config/bundled-skills/settings/TOOLS.json +11 -5
  173. package/src/config/bundled-skills/settings/tools/open-system-settings.test.ts +85 -0
  174. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +33 -8
  175. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +54 -3
  176. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +1 -1
  177. package/src/config/default-profile-catalog.ts +195 -10
  178. package/src/config/default-profile-names.ts +41 -0
  179. package/src/config/feature-flag-registry.json +34 -2
  180. package/src/config/inference-profile-validation.ts +11 -2
  181. package/src/config/llm-resolver.ts +25 -0
  182. package/src/config/loader.ts +3 -0
  183. package/src/config/managed-speech-defaults.ts +160 -10
  184. package/src/config/schema.ts +2 -0
  185. package/src/config/schemas/__tests__/live-voice.test.ts +7 -6
  186. package/src/config/schemas/__tests__/stt.test.ts +94 -0
  187. package/src/config/schemas/backup.ts +1 -1
  188. package/src/config/schemas/channels.ts +32 -0
  189. package/src/config/schemas/live-voice.ts +13 -4
  190. package/src/config/schemas/llm.ts +263 -15
  191. package/src/config/schemas/mcp.ts +10 -2
  192. package/src/config/schemas/memory-retrospective.ts +1 -19
  193. package/src/config/schemas/services.ts +24 -0
  194. package/src/config/schemas/stt.ts +128 -5
  195. package/src/config/seed-inference-profiles.ts +32 -3
  196. package/src/config/skill-state.ts +5 -0
  197. package/src/config/skills.ts +21 -0
  198. package/src/contacts/notify-contacts-changed.ts +5 -2
  199. package/src/context/compactor.ts +74 -1
  200. package/src/daemon/__tests__/conversation-tool-setup.test.ts +138 -1
  201. package/src/daemon/config-watcher.ts +2 -1
  202. package/src/daemon/conversation-agent-loop-handlers.ts +27 -0
  203. package/src/daemon/conversation-agent-loop.ts +86 -10
  204. package/src/daemon/conversation-error.ts +25 -0
  205. package/src/daemon/conversation-evictor.ts +2 -4
  206. package/src/daemon/conversation-runtime-assembly.ts +19 -7
  207. package/src/daemon/conversation-skill-tools.ts +5 -1
  208. package/src/daemon/conversation-slash.ts +2 -2
  209. package/src/daemon/conversation-store.ts +8 -1
  210. package/src/daemon/conversation-tool-setup.ts +37 -0
  211. package/src/daemon/conversation.ts +0 -4
  212. package/src/daemon/handlers/channel-config-result.ts +30 -0
  213. package/src/daemon/handlers/config-discord-channel.ts +301 -0
  214. package/src/daemon/handlers/config-ingress.ts +9 -0
  215. package/src/daemon/handlers/config-slack-channel.ts +13 -15
  216. package/src/daemon/handlers/config-telegram.ts +2 -5
  217. package/src/daemon/handlers/conversations.ts +0 -2
  218. package/src/daemon/handlers/skills.ts +25 -7
  219. package/src/daemon/lifecycle.ts +3 -1
  220. package/src/daemon/message-types/messages.ts +0 -2
  221. package/src/daemon/tool-setup-types.ts +5 -3
  222. package/src/daemon/trust-context-types.test.ts +33 -0
  223. package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
  224. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +58 -4
  225. package/src/live-voice/__tests__/live-voice-managed-speech-fallback.test.ts +8 -3
  226. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +73 -11
  227. package/src/live-voice/__tests__/live-voice-session-preflight.test.ts +148 -2
  228. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +64 -0
  229. package/src/live-voice/__tests__/live-voice-stt.test.ts +3 -0
  230. package/src/live-voice/__tests__/live-voice-text-turn.test.ts +391 -0
  231. package/src/live-voice/__tests__/protocol.test.ts +224 -0
  232. package/src/live-voice/live-voice-credential-preflight.ts +5 -1
  233. package/src/live-voice/live-voice-session-manager.ts +39 -2
  234. package/src/live-voice/live-voice-session.ts +224 -9
  235. package/src/live-voice/protocol.ts +187 -1
  236. package/src/messaging/providers/discord/api.ts +2 -1
  237. package/src/messaging/providers/discord/withdraw.ts +62 -0
  238. package/src/messaging/read-provider-metadata.ts +32 -0
  239. package/src/monitoring/__tests__/file-descriptors.test.ts +32 -0
  240. package/src/monitoring/__tests__/process-memory.test.ts +34 -1
  241. package/src/monitoring/db-integrity-sample.ts +1 -0
  242. package/src/monitoring/file-descriptors.ts +39 -6
  243. package/src/monitoring/process-memory.ts +37 -5
  244. package/src/monitoring/resource-sampler.ts +25 -8
  245. package/src/notifications/__tests__/activity-failed-dedupe.test.ts +161 -0
  246. package/src/notifications/__tests__/background-failure-signal.test.ts +107 -0
  247. package/src/notifications/__tests__/connected-channels.test.ts +12 -0
  248. package/src/notifications/__tests__/copy-composer.test.ts +83 -0
  249. package/src/notifications/__tests__/destination-resolver.test.ts +38 -0
  250. package/src/notifications/activity-failed-dedupe.ts +95 -0
  251. package/src/notifications/adapters/discord.ts +132 -0
  252. package/src/notifications/adapters/shared.ts +16 -0
  253. package/src/notifications/adapters/slack.ts +6 -1
  254. package/src/notifications/adapters/telegram.ts +5 -8
  255. package/src/notifications/approval-card-data.ts +94 -1
  256. package/src/notifications/background-failure-signal.ts +116 -0
  257. package/src/notifications/broadcaster.ts +3 -9
  258. package/src/notifications/copy-composer.ts +41 -8
  259. package/src/notifications/decision-engine.ts +55 -0
  260. package/src/notifications/destination-resolver.ts +45 -5
  261. package/src/notifications/emit-signal.ts +19 -5
  262. package/src/notifications/guardian-question-mode.ts +57 -0
  263. package/src/notifications/types.ts +2 -8
  264. package/src/oauth/__tests__/seed-providers-managed.test.ts +18 -0
  265. package/src/oauth/connect-orchestrator.ts +16 -0
  266. package/src/oauth/seed-providers.ts +262 -0
  267. package/src/permissions/checker.test.ts +21 -0
  268. package/src/permissions/checker.ts +6 -0
  269. package/src/permissions/gateway-threshold-reader.test.ts +184 -0
  270. package/src/permissions/gateway-threshold-reader.ts +144 -10
  271. package/src/permissions/prompter.ts +0 -6
  272. package/src/permissions/types.ts +5 -4
  273. package/src/persistence/__tests__/bulk-write-gate.test.ts +0 -38
  274. package/src/persistence/bulk-write-gate.ts +9 -10
  275. package/src/persistence/conversation-crud.ts +88 -134
  276. package/src/persistence/conversation-title-service.ts +43 -29
  277. package/src/persistence/embeddings/embedding-local.ts +14 -85
  278. package/src/persistence/embeddings/embedding-runtime-manager.ts +1 -0
  279. package/src/persistence/lifecycle-events-store.test.ts +50 -0
  280. package/src/persistence/lifecycle-events-store.ts +75 -5
  281. package/src/platform/platform-patch-queue.test.ts +368 -0
  282. package/src/platform/platform-patch-queue.ts +190 -0
  283. package/src/platform/sync-avatar.test.ts +527 -0
  284. package/src/platform/sync-avatar.ts +209 -0
  285. package/src/platform/sync-identity.test.ts +75 -0
  286. package/src/platform/sync-identity.ts +17 -110
  287. package/src/plugin-api/model-profiles.test.ts +2 -2
  288. package/src/plugin-api/model-profiles.ts +7 -7
  289. package/src/plugin-api/transcription-session.ts +1 -1
  290. package/src/plugins/defaults/compaction/window-manager.ts +4 -0
  291. package/src/plugins/defaults/image-recovery/recover.ts +2 -2
  292. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +133 -34
  293. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +21 -31
  294. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +13 -9
  295. package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +31 -4
  296. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +0 -11
  297. package/src/plugins/defaults/memory/memory-retrospective-fork-boundary.ts +27 -13
  298. package/src/plugins/defaults/memory/memory-retrospective-job.ts +183 -113
  299. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +13 -13
  300. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +2 -2
  301. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +1 -1
  302. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +4 -2
  303. package/src/plugins/defaults/memory/substrate/sweep-job.ts +9 -42
  304. package/src/plugins/defaults/memory/v2/rerank-local.ts +1 -0
  305. package/src/plugins/defaults/memory/worker.ts +7 -0
  306. package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
  307. package/src/providers/__tests__/retry-callsite.test.ts +55 -0
  308. package/src/providers/__tests__/vellum-connection-routing.test.ts +21 -3
  309. package/src/providers/connection-resolution.ts +2 -17
  310. package/src/providers/fallback-breaker.ts +389 -0
  311. package/src/providers/inference/__tests__/adapter-factory-opencode.test.ts +92 -0
  312. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +16 -0
  313. package/src/providers/inference/__tests__/base-url-security.test.ts +12 -0
  314. package/src/providers/inference/adapter-factory.ts +246 -3
  315. package/src/providers/inference/auth.ts +15 -14
  316. package/src/providers/inference/chatgpt-subscription-auth.ts +70 -0
  317. package/src/providers/inference/chatgpt-subscription-credentials.ts +84 -0
  318. package/src/providers/inference/resolve-auth.ts +1 -1
  319. package/src/providers/media-resolve.ts +2 -3
  320. package/src/providers/model-catalog.ts +100 -0
  321. package/src/providers/openai/__tests__/api-error-normalization.test.ts +22 -0
  322. package/src/providers/openai/__tests__/chat-template-flatten.test.ts +198 -0
  323. package/src/providers/openai/api-error-normalization.ts +13 -0
  324. package/src/providers/openai/chat-completions-provider.ts +84 -0
  325. package/src/providers/opencode/client.test.ts +150 -0
  326. package/src/providers/opencode/client.ts +61 -0
  327. package/src/providers/platform-proxy/constants.ts +5 -0
  328. package/src/providers/provider-resolvability.ts +20 -0
  329. package/src/providers/provider-secret-catalog.ts +3 -2
  330. package/src/providers/retry.ts +956 -68
  331. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +42 -0
  332. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +136 -0
  333. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +120 -0
  334. package/src/providers/speech-to-text/__tests__/resolve.test.ts +316 -12
  335. package/src/providers/speech-to-text/deepgram-flux-frames.ts +83 -3
  336. package/src/providers/speech-to-text/deepgram-flux-realtime.ts +132 -4
  337. package/src/providers/speech-to-text/provider-catalog.ts +191 -3
  338. package/src/providers/speech-to-text/resolve.ts +132 -24
  339. package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +296 -0
  340. package/src/providers/types.ts +39 -0
  341. package/src/providers/usage-tracking.ts +12 -1
  342. package/src/providers/vellum/client.ts +29 -0
  343. package/src/providers/vellum-model-routing.test.ts +2 -0
  344. package/src/providers/vellum-model-routing.ts +3 -3
  345. package/src/runtime/AGENTS.md +1 -2
  346. package/src/runtime/__tests__/agent-wake.test.ts +105 -3
  347. package/src/runtime/__tests__/background-job-runner.test.ts +89 -3
  348. package/src/runtime/agent-wake.ts +44 -5
  349. package/src/runtime/background-job-runner.ts +68 -50
  350. package/src/runtime/channel-readiness-service.ts +0 -39
  351. package/src/runtime/http-server.ts +12 -4
  352. package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +18 -18
  353. package/src/runtime/routes/__tests__/backup-routes.test.ts +9 -5
  354. package/src/runtime/routes/__tests__/chatgpt-subscription-auth-routes.test.ts +372 -0
  355. package/src/runtime/routes/__tests__/contact-routes.test.ts +7 -0
  356. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +96 -0
  357. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +37 -0
  358. package/src/runtime/routes/__tests__/ingress-status-routes.test.ts +2 -1
  359. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +87 -0
  360. package/src/runtime/routes/acp-claude-auth-routes.ts +25 -54
  361. package/src/runtime/routes/approval-routes.ts +0 -12
  362. package/src/runtime/routes/avatar-routes.ts +17 -30
  363. package/src/runtime/routes/backup-routes.ts +2 -2
  364. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +296 -113
  365. package/src/runtime/routes/contact-prompt-routes.ts +65 -6
  366. package/src/runtime/routes/contact-routes.ts +20 -15
  367. package/src/runtime/routes/conversation-query-routes.ts +98 -10
  368. package/src/runtime/routes/conversation-routes.ts +2 -2
  369. package/src/runtime/routes/credential-routes.ts +2 -1
  370. package/src/runtime/routes/guardian-approval-interception.ts +12 -9
  371. package/src/runtime/routes/inbound-message-handler.ts +47 -48
  372. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +18 -13
  373. package/src/runtime/routes/inbound-stages/admission-policy.ts +2 -2
  374. package/src/runtime/routes/inbound-stages/edit-intercept.ts +20 -2
  375. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +9 -8
  376. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +1 -1
  377. package/src/runtime/routes/index.ts +2 -0
  378. package/src/runtime/routes/inference-profile-session-handler.ts +2 -2
  379. package/src/runtime/routes/inference-profiles-routes.ts +12 -7
  380. package/src/runtime/routes/inference-provider-connection-routes.ts +2 -2
  381. package/src/runtime/routes/inference-send-routes.ts +2 -2
  382. package/src/runtime/routes/ingress-status-routes.ts +2 -2
  383. package/src/runtime/routes/integrations/discord.ts +119 -0
  384. package/src/runtime/routes/llm-call-sites-routes.ts +2 -2
  385. package/src/runtime/routes/mcp-auth-routes.ts +12 -6
  386. package/src/runtime/routes/migration-routes.ts +3 -1
  387. package/src/runtime/routes/oauth-pending-flows.ts +136 -0
  388. package/src/runtime/routes/secret-routes.ts +7 -0
  389. package/src/runtime/routes/stt-routes.ts +38 -6
  390. package/src/runtime/routes/wake-conversation-routes.ts +8 -1
  391. package/src/runtime/routes/watch-routes.ts +9 -5
  392. package/src/runtime/sync/resource-sync-events.ts +2 -0
  393. package/src/runtime/trust-verdict-consumer.ts +3 -3
  394. package/src/schedule/__tests__/worker-feature-flags.test.ts +58 -0
  395. package/src/schedule/retry-policy.ts +8 -8
  396. package/src/schedule/run-script.ts +14 -23
  397. package/src/schedule/schedule-recovery.ts +0 -1
  398. package/src/schedule/scheduler.ts +89 -51
  399. package/src/schedule/worker.ts +57 -0
  400. package/src/security/__tests__/openai-device-auth.test.ts +355 -0
  401. package/src/security/ces-rpc-record-backend.ts +123 -0
  402. package/src/security/oauth2.ts +7 -0
  403. package/src/security/openai-device-auth.ts +364 -0
  404. package/src/security/secure-keys.ts +15 -0
  405. package/src/skills/available-skills.ts +10 -1
  406. package/src/skills/catalog-install.ts +19 -1
  407. package/src/skills/inline-command-runner.ts +6 -2
  408. package/src/skills/platform-compatibility.test.ts +49 -0
  409. package/src/skills/platform-compatibility.ts +65 -0
  410. package/src/skills/tool-manifest.ts +20 -0
  411. package/src/stt/__tests__/roles.test.ts +152 -0
  412. package/src/stt/daemon-batch-transcriber.ts +4 -1
  413. package/src/stt/roles.ts +180 -0
  414. package/src/stt/stt-stream-session.ts +3 -2
  415. package/src/stt/types.ts +33 -3
  416. package/src/subagent/manager.ts +12 -0
  417. package/src/telemetry/__tests__/live-voice-funnel.test.ts +34 -0
  418. package/src/telemetry/live-voice-funnel.ts +12 -2
  419. package/src/telemetry/telemetry-wire.generated.ts +6 -0
  420. package/src/telemetry/tool-audit.ts +83 -30
  421. package/src/telemetry/tool-executed-events-store.test.ts +0 -1
  422. package/src/telemetry/turn-outcome.ts +75 -4
  423. package/src/tools/client-os.ts +115 -0
  424. package/src/tools/computer-use/definitions.ts +11 -7
  425. package/src/tools/computer-use/skill-proxy-bridge.ts +2 -2
  426. package/src/tools/credentials/broker-types.ts +0 -71
  427. package/src/tools/credentials/broker.ts +6 -201
  428. package/src/tools/credentials/metadata-store.ts +65 -16
  429. package/src/tools/credentials/store.ts +2 -0
  430. package/src/tools/executor.ts +2 -8
  431. package/src/tools/host-shell.test.ts +75 -0
  432. package/src/tools/host-shell.ts +24 -0
  433. package/src/tools/host-terminal/host-shell.ts +15 -44
  434. package/src/tools/mcp/mcp-tool-factory.ts +44 -9
  435. package/src/tools/permission-checker.ts +73 -21
  436. package/src/tools/policy-context.ts +1 -0
  437. package/src/tools/shared/filesystem/image-read.ts +1 -1
  438. package/src/tools/skills/find-similar-skills.ts +10 -2
  439. package/src/tools/skills/load.ts +41 -6
  440. package/src/tools/skills/sandbox-runner.ts +8 -16
  441. package/src/tools/skills/skill-tool-factory.ts +1 -0
  442. package/src/tools/terminal/__tests__/safe-env.test.ts +64 -1
  443. package/src/tools/terminal/safe-env.ts +39 -9
  444. package/src/tools/terminal/shell.ts +12 -31
  445. package/src/tools/tool-approval-handler.ts +64 -10
  446. package/src/tools/tool-types.ts +10 -0
  447. package/src/tools/types.ts +19 -3
  448. package/src/tools/ui-surface/surface-shape-docs.ts +4 -3
  449. package/src/tools/workflows/manage-workflows.ts +2 -2
  450. package/src/tools/workflows/run-workflow.test.ts +2 -1
  451. package/src/util/__tests__/file-use.test.ts +61 -0
  452. package/src/util/__tests__/process-table.test.ts +66 -0
  453. package/src/util/__tests__/process-tree.test.ts +46 -0
  454. package/src/util/errors.ts +1 -0
  455. package/src/util/file-use.ts +91 -0
  456. package/src/util/host-process.test.ts +17 -0
  457. package/src/util/host-process.ts +75 -0
  458. package/src/util/image-conversion.ts +39 -7
  459. package/src/util/platform.ts +32 -13
  460. package/src/util/process-table.ts +249 -0
  461. package/src/util/process-tree.ts +85 -129
  462. package/src/util/provider-error-patterns.ts +20 -0
  463. package/src/util/spawn.ts +9 -2
  464. package/src/watch/__tests__/watch-retro.test.ts +48 -1
  465. package/src/watch/watch-retro.ts +46 -4
  466. package/src/workspace/git-service.ts +4 -14
  467. package/src/workspace/migrations/147-rename-colliding-backup-profile-names.ts +360 -0
  468. package/src/workspace/migrations/148-strip-unsupported-fallback-profiles.ts +117 -0
  469. package/src/workspace/migrations/149-repoint-backup-profile-selections.ts +204 -0
  470. package/src/workspace/migrations/150-stt-flux-provider-to-model-family.ts +139 -0
  471. package/src/workspace/migrations/__tests__/150-stt-flux-provider-to-model-family.test.ts +160 -0
  472. package/src/workspace/migrations/registry.ts +8 -0
  473. package/src/__tests__/permission-types.test.ts +0 -17
  474. package/src/channels/gateway-discord-admission.ts +0 -32
  475. package/src/persistence/fork-message-copy.ts +0 -239
  476. package/src/plugins/defaults/memory/__tests__/fork-message-copy.test.ts +0 -221
  477. package/src/security/__tests__/oauth2-device-code.test.ts +0 -431
  478. package/src/security/oauth2-device-code.ts +0 -312
@@ -1,5 +1,5 @@
1
1
  import { randomBytes } from "node:crypto";
2
- import { existsSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
2
+ import { existsSync, mkdirSync, rmSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
@@ -20,231 +20,6 @@ const TEST_DIR = join(
20
20
  );
21
21
  const STORE_PATH = join(TEST_DIR, "keys.enc");
22
22
 
23
- describe("CredentialBroker", () => {
24
- let broker: CredentialBroker;
25
- let tmpDir: string;
26
-
27
- beforeEach(() => {
28
- tmpDir = mkdtempSync(join(tmpdir(), "broker-test-"));
29
- _setMetadataPath(join(tmpDir, "metadata.json"));
30
- broker = new CredentialBroker();
31
- });
32
-
33
- afterEach(() => {
34
- _setMetadataPath(null);
35
- rmSync(tmpDir, { recursive: true, force: true });
36
- });
37
-
38
- describe("authorize", () => {
39
- test("denies when no credential metadata exists", () => {
40
- const result = broker.authorize({
41
- service: "github",
42
- field: "token",
43
- toolName: "browser_fill_credential",
44
- });
45
- expect(result.authorized).toBe(false);
46
- if (!result.authorized) {
47
- expect(result.reason).toContain("No credential found");
48
- }
49
- });
50
-
51
- test("authorizes when tool is in allowedTools", () => {
52
- upsertCredentialMetadata("github", "token", {
53
- allowedTools: ["browser_fill_credential"],
54
- });
55
- const result = broker.authorize({
56
- service: "github",
57
- field: "token",
58
- toolName: "browser_fill_credential",
59
- });
60
- expect(result.authorized).toBe(true);
61
- if (result.authorized) {
62
- expect(result.token.service).toBe("github");
63
- expect(result.token.field).toBe("token");
64
- expect(result.token.toolName).toBe("browser_fill_credential");
65
- expect(result.token.consumed).toBe(false);
66
- expect(result.token.tokenId).toBeTruthy();
67
- }
68
- });
69
-
70
- test("denies when tool is not in allowedTools", () => {
71
- upsertCredentialMetadata("github", "token", {
72
- allowedTools: ["other_tool"],
73
- });
74
- const result = broker.authorize({
75
- service: "github",
76
- field: "token",
77
- toolName: "browser_fill_credential",
78
- });
79
- expect(result.authorized).toBe(false);
80
- if (!result.authorized) {
81
- expect(result.reason).toContain("not allowed");
82
- expect(result.reason).toContain("browser_fill_credential");
83
- expect(result.reason).toContain("Allowed tools: other_tool");
84
- }
85
- });
86
-
87
- test("denies when allowedTools is empty (fail-closed)", () => {
88
- upsertCredentialMetadata("github", "token");
89
- const result = broker.authorize({
90
- service: "github",
91
- field: "token",
92
- toolName: "browser_fill_credential",
93
- });
94
- expect(result.authorized).toBe(false);
95
- if (!result.authorized) {
96
- expect(result.reason).toContain("not allowed");
97
- expect(result.reason).toContain("No tools are currently allowed");
98
- expect(result.reason).toContain("assistant credentials prompt");
99
- }
100
- });
101
-
102
- test("issues unique token IDs", () => {
103
- upsertCredentialMetadata("github", "token", {
104
- allowedTools: ["tool1", "tool2"],
105
- });
106
- const r1 = broker.authorize({
107
- service: "github",
108
- field: "token",
109
- toolName: "tool1",
110
- });
111
- const r2 = broker.authorize({
112
- service: "github",
113
- field: "token",
114
- toolName: "tool2",
115
- });
116
- expect(r1.authorized).toBe(true);
117
- expect(r2.authorized).toBe(true);
118
- if (r1.authorized && r2.authorized) {
119
- expect(r1.token.tokenId).not.toBe(r2.token.tokenId);
120
- }
121
- });
122
- });
123
-
124
- describe("consume", () => {
125
- test("returns storage key on first consumption", () => {
126
- upsertCredentialMetadata("github", "token", {
127
- allowedTools: ["browser_fill_credential"],
128
- });
129
- const auth = broker.authorize({
130
- service: "github",
131
- field: "token",
132
- toolName: "browser_fill_credential",
133
- });
134
- expect(auth.authorized).toBe(true);
135
- if (!auth.authorized) {
136
- return;
137
- }
138
-
139
- const result = broker.consume(auth.token.tokenId);
140
- expect(result.success).toBe(true);
141
- expect(result.storageKey).toBe(credentialKey("github", "token"));
142
- });
143
-
144
- test("rejects double consumption", () => {
145
- upsertCredentialMetadata("github", "token", {
146
- allowedTools: ["browser_fill_credential"],
147
- });
148
- const auth = broker.authorize({
149
- service: "github",
150
- field: "token",
151
- toolName: "browser_fill_credential",
152
- });
153
- if (!auth.authorized) {
154
- return;
155
- }
156
-
157
- broker.consume(auth.token.tokenId);
158
- const result = broker.consume(auth.token.tokenId);
159
- expect(result.success).toBe(false);
160
- expect(result.reason).toContain("already consumed");
161
- });
162
-
163
- test("rejects unknown token ID", () => {
164
- const result = broker.consume("nonexistent-token");
165
- expect(result.success).toBe(false);
166
- expect(result.reason).toContain("not found");
167
- });
168
- });
169
-
170
- describe("revoke", () => {
171
- test("revokes existing token", () => {
172
- upsertCredentialMetadata("github", "token", {
173
- allowedTools: ["browser_fill_credential"],
174
- });
175
- const auth = broker.authorize({
176
- service: "github",
177
- field: "token",
178
- toolName: "browser_fill_credential",
179
- });
180
- if (!auth.authorized) {
181
- return;
182
- }
183
-
184
- expect(broker.revoke(auth.token.tokenId)).toBe(true);
185
- // After revocation, consume should fail
186
- const result = broker.consume(auth.token.tokenId);
187
- expect(result.success).toBe(false);
188
- });
189
-
190
- test("returns false for unknown token", () => {
191
- expect(broker.revoke("nonexistent")).toBe(false);
192
- });
193
- });
194
-
195
- describe("revokeAll", () => {
196
- test("clears all active tokens", () => {
197
- upsertCredentialMetadata("github", "token", {
198
- allowedTools: ["tool1", "tool2"],
199
- });
200
- broker.authorize({
201
- service: "github",
202
- field: "token",
203
- toolName: "tool1",
204
- });
205
- broker.authorize({
206
- service: "github",
207
- field: "token",
208
- toolName: "tool2",
209
- });
210
- expect(broker.activeTokenCount).toBe(2);
211
-
212
- broker.revokeAll();
213
- expect(broker.activeTokenCount).toBe(0);
214
- });
215
- });
216
-
217
- describe("activeTokenCount", () => {
218
- test("counts only unconsumed tokens", () => {
219
- upsertCredentialMetadata("github", "token", {
220
- allowedTools: ["tool1", "tool2"],
221
- });
222
- const auth1 = broker.authorize({
223
- service: "github",
224
- field: "token",
225
- toolName: "tool1",
226
- });
227
- broker.authorize({
228
- service: "github",
229
- field: "token",
230
- toolName: "tool2",
231
- });
232
- expect(broker.activeTokenCount).toBe(2);
233
-
234
- if (auth1.authorized) {
235
- broker.consume(auth1.token.tokenId);
236
- }
237
- expect(broker.activeTokenCount).toBe(1);
238
- });
239
- });
240
- });
241
-
242
- // ---------------------------------------------------------------------------
243
- // Behavior that reads stored secret values, exercised against the encrypted
244
- // store backend (transient injection, multi-template serverUseById, revokeAll,
245
- // and canonical/legacy capability-key resolution).
246
- // ---------------------------------------------------------------------------
247
-
248
23
  describe("CredentialBroker (encrypted store backend)", () => {
249
24
  let broker: CredentialBroker;
250
25
 
@@ -267,51 +42,12 @@ describe("CredentialBroker (encrypted store backend)", () => {
267
42
  });
268
43
 
269
44
  describe("transient credentials", () => {
270
- test("consume returns transient value and deletes it", () => {
271
- // GIVEN a credential with metadata and an injected one-time transient value
272
- upsertCredentialMetadata("svc", "key", { allowedTools: ["tool1"] });
273
- broker.injectTransient("svc", "key", "one-time-secret");
274
-
275
- // WHEN the credential is authorized and consumed
276
- const auth = broker.authorize({
277
- service: "svc",
278
- field: "key",
279
- toolName: "tool1",
280
- });
281
- expect(auth.authorized).toBe(true);
282
- if (!auth.authorized) {
283
- return;
284
- }
285
- const result = broker.consume(auth.token.tokenId);
286
-
287
- // THEN the transient value is returned alongside the storage key
288
- expect(result.success).toBe(true);
289
- expect(result.value).toBe("one-time-secret");
290
- expect(result.storageKey).toBe(credentialKey("svc", "key"));
291
-
292
- // AND a subsequent authorize+consume no longer has the transient value
293
- const auth2 = broker.authorize({
294
- service: "svc",
295
- field: "key",
296
- toolName: "tool1",
297
- });
298
- expect(auth2.authorized).toBe(true);
299
- if (!auth2.authorized) {
300
- return;
301
- }
302
- const result2 = broker.consume(auth2.token.tokenId);
303
- expect(result2.success).toBe(true);
304
- expect(result2.value).toBeUndefined();
305
- });
306
-
307
45
  test("browserFill uses transient value when available", async () => {
308
- // GIVEN a credential with a transient value and no stored value
309
46
  upsertCredentialMetadata("github", "token", {
310
47
  allowedTools: ["browser_fill_credential"],
311
48
  });
312
49
  broker.injectTransient("github", "token", "transient-ghp-123");
313
50
 
314
- // WHEN browserFill runs
315
51
  let filledValue: string | undefined;
316
52
  const result = await broker.browserFill({
317
53
  service: "github",
@@ -322,20 +58,17 @@ describe("CredentialBroker (encrypted store backend)", () => {
322
58
  },
323
59
  });
324
60
 
325
- // THEN the transient value is filled
326
61
  expect(result.success).toBe(true);
327
62
  expect(filledValue).toBe("transient-ghp-123");
328
63
  });
329
64
 
330
65
  test("browserFill consumes transient value — second fill falls back to stored", async () => {
331
- // GIVEN a credential with both a stored value and a transient value
332
66
  upsertCredentialMetadata("github", "token", {
333
67
  allowedTools: ["browser_fill_credential"],
334
68
  });
335
69
  await setSecureKeyAsync(credentialKey("github", "token"), "stored-value");
336
70
  broker.injectTransient("github", "token", "transient-value");
337
71
 
338
- // WHEN browserFill runs twice
339
72
  let filled1: string | undefined;
340
73
  await broker.browserFill({
341
74
  service: "github",
@@ -355,19 +88,16 @@ describe("CredentialBroker (encrypted store backend)", () => {
355
88
  },
356
89
  });
357
90
 
358
- // THEN the first fill uses the transient and the second falls back to stored
359
91
  expect(filled1).toBe("transient-value");
360
92
  expect(filled2).toBe("stored-value");
361
93
  });
362
94
 
363
95
  test("browserFill preserves transient value on fill failure", async () => {
364
- // GIVEN a credential with a transient value
365
96
  upsertCredentialMetadata("github", "token", {
366
97
  allowedTools: ["browser_fill_credential"],
367
98
  });
368
99
  broker.injectTransient("github", "token", "transient-preserved");
369
100
 
370
- // WHEN the first fill throws
371
101
  const result1 = await broker.browserFill({
372
102
  service: "github",
373
103
  field: "token",
@@ -387,19 +117,16 @@ describe("CredentialBroker (encrypted store backend)", () => {
387
117
  },
388
118
  });
389
119
 
390
- // THEN the transient value survives for the second fill
391
120
  expect(result2.success).toBe(true);
392
121
  expect(filled).toBe("transient-preserved");
393
122
  });
394
123
 
395
124
  test("serverUse uses transient value when available", async () => {
396
- // GIVEN a credential with a transient value
397
125
  upsertCredentialMetadata("vercel", "api_token", {
398
126
  allowedTools: ["deploy"],
399
127
  });
400
128
  broker.injectTransient("vercel", "api_token", "transient-vercel-tok");
401
129
 
402
- // WHEN serverUse runs
403
130
  const result = await broker.serverUse({
404
131
  service: "vercel",
405
132
  field: "api_token",
@@ -410,19 +137,16 @@ describe("CredentialBroker (encrypted store backend)", () => {
410
137
  },
411
138
  });
412
139
 
413
- // THEN the transient value is used for execution
414
140
  expect(result.success).toBe(true);
415
141
  expect(result.result).toBe("deployed");
416
142
  });
417
143
 
418
144
  test("serverUse consumes transient — subsequent call has no value without stored key", async () => {
419
- // GIVEN a credential with only a transient value (no stored value)
420
145
  upsertCredentialMetadata("vercel", "api_token", {
421
146
  allowedTools: ["deploy"],
422
147
  });
423
148
  broker.injectTransient("vercel", "api_token", "transient-only");
424
149
 
425
- // WHEN serverUse runs twice
426
150
  await broker.serverUse({
427
151
  service: "vercel",
428
152
  field: "api_token",
@@ -438,202 +162,102 @@ describe("CredentialBroker (encrypted store backend)", () => {
438
162
  },
439
163
  });
440
164
 
441
- // THEN the second call fails because no stored value remains
442
165
  expect(result.success).toBe(false);
443
166
  expect(result.reason).toContain("no stored value");
444
167
  });
445
168
 
446
- test("injectTransient replaces previous transient for same key", () => {
447
- // GIVEN two transient values injected for the same credential
169
+ test("injectTransient replaces previous transient for same key", async () => {
448
170
  upsertCredentialMetadata("svc", "key", { allowedTools: ["t"] });
449
171
  broker.injectTransient("svc", "key", "first");
450
172
  broker.injectTransient("svc", "key", "second");
451
173
 
452
- // WHEN the credential is authorized and consumed
453
- const auth = broker.authorize({
174
+ const result = await broker.serverUse({
454
175
  service: "svc",
455
176
  field: "key",
456
177
  toolName: "t",
178
+ execute: async (v) => v,
457
179
  });
458
- if (!auth.authorized) {
459
- return;
460
- }
461
- const result = broker.consume(auth.token.tokenId);
462
180
 
463
- // THEN the most recent transient value wins
464
- expect(result.value).toBe("second");
181
+ expect(result.success).toBe(true);
182
+ expect(result.result).toBe("second");
465
183
  });
466
184
 
467
- test("transient value for one credential does not affect another", () => {
468
- // GIVEN a transient value injected for svcA only
185
+ test("transient value for one credential does not affect another", async () => {
469
186
  upsertCredentialMetadata("svcA", "key", { allowedTools: ["t"] });
470
187
  upsertCredentialMetadata("svcB", "key", { allowedTools: ["t"] });
188
+ await setSecureKeyAsync(credentialKey("svcB", "key"), "stored-b");
471
189
  broker.injectTransient("svcA", "key", "val-a");
472
190
 
473
- // WHEN both credentials are authorized and consumed
474
- const authB = broker.authorize({
191
+ const resultB = await broker.serverUse({
475
192
  service: "svcB",
476
193
  field: "key",
477
194
  toolName: "t",
195
+ execute: async (v) => v,
478
196
  });
479
- if (!authB.authorized) {
480
- return;
481
- }
482
- const resultB = broker.consume(authB.token.tokenId);
483
- const authA = broker.authorize({
197
+ const resultA = await broker.serverUse({
484
198
  service: "svcA",
485
199
  field: "key",
486
200
  toolName: "t",
201
+ execute: async (v) => v,
487
202
  });
488
- if (!authA.authorized) {
489
- return;
490
- }
491
- const resultA = broker.consume(authA.token.tokenId);
492
203
 
493
- // THEN only svcA carries the transient value
494
204
  expect(resultB.success).toBe(true);
495
- expect(resultB.value).toBeUndefined();
496
- expect(resultA.value).toBe("val-a");
497
- });
498
- });
499
-
500
- describe("serverUseById edge cases", () => {
501
- test("serverUseById with multiple injection templates returns all", async () => {
502
- // GIVEN a credential with two injection templates and a stored value
503
- const meta = upsertCredentialMetadata("multi", "api_key", {
504
- allowedTools: ["proxy"],
505
- injectionTemplates: [
506
- {
507
- hostPattern: "*.fal.ai",
508
- injectionType: "header",
509
- headerName: "Authorization",
510
- valuePrefix: "Key ",
511
- },
512
- {
513
- hostPattern: "gateway.fal.ai",
514
- injectionType: "header",
515
- headerName: "X-Fal-Key",
516
- },
517
- ],
518
- });
519
- await setSecureKeyAsync(
520
- credentialKey("multi", "api_key"),
521
- "multi-secret",
522
- );
523
-
524
- // WHEN serverUseById resolves the credential by id
525
- const result = await broker.serverUseById({
526
- credentialId: meta.credentialId,
527
- requestingTool: "proxy",
528
- });
529
-
530
- // THEN both injection templates are returned without leaking the secret
531
- expect(result.success).toBe(true);
532
- if (!result.success) {
533
- return;
534
- }
535
- expect(result.injectionTemplates).toHaveLength(2);
536
- expect(result.injectionTemplates[0].hostPattern).toBe("*.fal.ai");
537
- expect(result.injectionTemplates[1].hostPattern).toBe("gateway.fal.ai");
538
- expect(JSON.stringify(result)).not.toContain("multi-secret");
539
- });
540
- });
541
-
542
- describe("revokeAll", () => {
543
- test("revokeAll clears all tokens and subsequent consume fails", () => {
544
- // GIVEN two active tokens for a credential
545
- upsertCredentialMetadata("svc", "key", { allowedTools: ["t1", "t2"] });
546
- const a1 = broker.authorize({
547
- service: "svc",
548
- field: "key",
549
- toolName: "t1",
550
- });
551
- const a2 = broker.authorize({
552
- service: "svc",
553
- field: "key",
554
- toolName: "t2",
555
- });
556
- expect(broker.activeTokenCount).toBe(2);
557
-
558
- // WHEN revokeAll is called
559
- broker.revokeAll();
560
-
561
- // THEN the token count is zero and consuming either token fails
562
- expect(broker.activeTokenCount).toBe(0);
563
- if (a1.authorized) {
564
- expect(broker.consume(a1.token.tokenId).success).toBe(false);
565
- }
566
- if (a2.authorized) {
567
- expect(broker.consume(a2.token.tokenId).success).toBe(false);
568
- }
569
- });
570
-
571
- test("revokeAll on empty broker is a no-op", () => {
572
- // GIVEN a broker with no active tokens
573
- expect(broker.activeTokenCount).toBe(0);
574
-
575
- // WHEN revokeAll is called
576
- broker.revokeAll();
577
-
578
- // THEN the token count remains zero
579
- expect(broker.activeTokenCount).toBe(0);
205
+ expect(resultB.result).toBe("stored-b");
206
+ expect(resultA.success).toBe(true);
207
+ expect(resultA.result).toBe("val-a");
580
208
  });
581
209
  });
582
210
 
583
211
  describe("canonical capability key", () => {
584
- test("authorize succeeds with canonical key when metadata has canonical key", () => {
585
- // GIVEN metadata allowing the canonical browser-fill capability key
212
+ test("browserFill succeeds with canonical key when metadata has canonical key", async () => {
586
213
  upsertCredentialMetadata("github", "token", {
587
214
  allowedTools: [BROWSER_FILL_CAPABILITY],
588
215
  });
216
+ await setSecureKeyAsync(credentialKey("github", "token"), "ghp_secret");
589
217
 
590
- // WHEN authorizing with the canonical key
591
- const result = broker.authorize({
218
+ const result = await broker.browserFill({
592
219
  service: "github",
593
220
  field: "token",
594
221
  toolName: BROWSER_FILL_CAPABILITY,
222
+ fill: async () => {},
595
223
  });
596
224
 
597
- // THEN authorization succeeds
598
- expect(result.authorized).toBe(true);
225
+ expect(result.success).toBe(true);
599
226
  });
600
227
 
601
- test("authorize succeeds with canonical key when metadata has legacy alias", () => {
602
- // GIVEN metadata stored under the legacy browser_fill_credential alias
228
+ test("browserFill succeeds with canonical key when metadata has legacy alias", async () => {
603
229
  upsertCredentialMetadata("github", "token", {
604
230
  allowedTools: ["browser_fill_credential"],
605
231
  });
232
+ await setSecureKeyAsync(credentialKey("github", "token"), "ghp_secret");
606
233
 
607
- // WHEN authorizing with the canonical key
608
- const result = broker.authorize({
234
+ const result = await broker.browserFill({
609
235
  service: "github",
610
236
  field: "token",
611
237
  toolName: BROWSER_FILL_CAPABILITY,
238
+ fill: async () => {},
612
239
  });
613
240
 
614
- // THEN authorization succeeds
615
- expect(result.authorized).toBe(true);
241
+ expect(result.success).toBe(true);
616
242
  });
617
243
 
618
- test("authorize succeeds with legacy alias when metadata has canonical key", () => {
619
- // GIVEN metadata allowing the canonical capability key
244
+ test("browserFill succeeds with legacy alias when metadata has canonical key", async () => {
620
245
  upsertCredentialMetadata("github", "token", {
621
246
  allowedTools: [BROWSER_FILL_CAPABILITY],
622
247
  });
248
+ await setSecureKeyAsync(credentialKey("github", "token"), "ghp_secret");
623
249
 
624
- // WHEN authorizing with the legacy alias
625
- const result = broker.authorize({
250
+ const result = await broker.browserFill({
626
251
  service: "github",
627
252
  field: "token",
628
253
  toolName: "browser_fill_credential",
254
+ fill: async () => {},
629
255
  });
630
256
 
631
- // THEN authorization succeeds
632
- expect(result.authorized).toBe(true);
257
+ expect(result.success).toBe(true);
633
258
  });
634
259
 
635
260
  test("serverUse with canonical key works when metadata has legacy alias", async () => {
636
- // GIVEN metadata stored under the legacy alias with a stored value
637
261
  upsertCredentialMetadata("vercel", "api_token", {
638
262
  allowedTools: ["browser_fill_credential"],
639
263
  });
@@ -642,7 +266,6 @@ describe("CredentialBroker (encrypted store backend)", () => {
642
266
  "vercel-tok",
643
267
  );
644
268
 
645
- // WHEN serverUse runs with the canonical key
646
269
  const result = await broker.serverUse({
647
270
  service: "vercel",
648
271
  field: "api_token",
@@ -650,43 +273,43 @@ describe("CredentialBroker (encrypted store backend)", () => {
650
273
  execute: async (v) => v,
651
274
  });
652
275
 
653
- // THEN execution succeeds with the stored value
654
276
  expect(result.success).toBe(true);
655
277
  expect(result.result).toBe("vercel-tok");
656
278
  });
657
279
 
658
- test("non-aliased tool names are unaffected by alias resolution", () => {
659
- // GIVEN metadata allowing a non-aliased custom tool
280
+ test("non-aliased tool names are unaffected by alias resolution", async () => {
660
281
  upsertCredentialMetadata("svc", "key", {
661
282
  allowedTools: ["custom_tool"],
662
283
  });
284
+ await setSecureKeyAsync(credentialKey("svc", "key"), "secret");
663
285
 
664
- // WHEN authorizing with that custom tool
665
- const result = broker.authorize({
286
+ const result = await broker.serverUse({
666
287
  service: "svc",
667
288
  field: "key",
668
289
  toolName: "custom_tool",
290
+ execute: async (v) => v,
669
291
  });
670
292
 
671
- // THEN authorization succeeds
672
- expect(result.authorized).toBe(true);
293
+ expect(result.success).toBe(true);
294
+ expect(result.result).toBe("secret");
673
295
  });
674
296
 
675
- test("non-aliased tool denied when only canonical key is allowed", () => {
676
- // GIVEN metadata allowing only the canonical capability key
297
+ test("non-aliased tool denied when only canonical key is allowed", async () => {
677
298
  upsertCredentialMetadata("svc", "key", {
678
299
  allowedTools: [BROWSER_FILL_CAPABILITY],
679
300
  });
301
+ await setSecureKeyAsync(credentialKey("svc", "key"), "secret");
680
302
 
681
- // WHEN authorizing with an unrelated tool
682
- const result = broker.authorize({
303
+ const result = await broker.serverUse({
683
304
  service: "svc",
684
305
  field: "key",
685
306
  toolName: "unrelated_tool",
307
+ execute: async () => {
308
+ throw new Error("should not be called");
309
+ },
686
310
  });
687
311
 
688
- // THEN authorization is denied
689
- expect(result.authorized).toBe(false);
312
+ expect(result.success).toBe(false);
690
313
  });
691
314
  });
692
315
  });