@vellumai/assistant 0.6.2 → 0.6.3

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 (396) hide show
  1. package/bun.lock +40 -40
  2. package/bunfig.toml +3 -0
  3. package/docs/architecture/memory.md +1 -1
  4. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
  5. package/openapi.yaml +184 -69
  6. package/package.json +41 -41
  7. package/scripts/generate-openapi.ts +1 -2
  8. package/src/__tests__/acp-session.test.ts +43 -0
  9. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
  10. package/src/__tests__/app-executors.test.ts +1 -0
  11. package/src/__tests__/app-source-watcher.test.ts +37 -11
  12. package/src/__tests__/approval-routes-http.test.ts +178 -1
  13. package/src/__tests__/browser-fill-credential.test.ts +229 -94
  14. package/src/__tests__/browser-manager.test.ts +40 -27
  15. package/src/__tests__/catalog-files.test.ts +862 -0
  16. package/src/__tests__/channel-approvals.test.ts +53 -0
  17. package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
  18. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  19. package/src/__tests__/config-schema.test.ts +125 -48
  20. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
  21. package/src/__tests__/context-overflow-approval.test.ts +16 -1
  22. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
  23. package/src/__tests__/conversation-agent-loop.test.ts +1 -1
  24. package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
  25. package/src/__tests__/conversation-attachments.test.ts +80 -4
  26. package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
  27. package/src/__tests__/conversation-fork-crud.test.ts +17 -0
  28. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  29. package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
  30. package/src/__tests__/conversation-inject-context.test.ts +103 -0
  31. package/src/__tests__/conversation-queue.test.ts +45 -2
  32. package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
  33. package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
  34. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  35. package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
  36. package/src/__tests__/conversation-starter-routes.test.ts +126 -0
  37. package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
  38. package/src/__tests__/conversation-store.test.ts +195 -0
  39. package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
  40. package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
  41. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  42. package/src/__tests__/credential-vault-unit.test.ts +4 -4
  43. package/src/__tests__/credential-vault.test.ts +152 -13
  44. package/src/__tests__/credentials-cli.test.ts +2 -2
  45. package/src/__tests__/date-context.test.ts +4 -4
  46. package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
  47. package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
  48. package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
  49. package/src/__tests__/gateway-only-guard.test.ts +3 -0
  50. package/src/__tests__/gemini-provider.test.ts +2 -2
  51. package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
  52. package/src/__tests__/headless-browser-interactions.test.ts +707 -371
  53. package/src/__tests__/headless-browser-navigate.test.ts +389 -47
  54. package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
  55. package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
  56. package/src/__tests__/host-bash-proxy.test.ts +150 -1
  57. package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
  58. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
  59. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
  60. package/src/__tests__/host-browser-event-routes.test.ts +350 -0
  61. package/src/__tests__/host-browser-proxy.test.ts +444 -0
  62. package/src/__tests__/host-browser-routes.test.ts +198 -0
  63. package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
  64. package/src/__tests__/host-cu-proxy.test.ts +171 -1
  65. package/src/__tests__/host-file-proxy.test.ts +185 -1
  66. package/src/__tests__/host-file-read-tool.test.ts +52 -0
  67. package/src/__tests__/host-proxy-interface.test.ts +165 -0
  68. package/src/__tests__/host-shell-tool.test.ts +1 -11
  69. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  70. package/src/__tests__/integration-status.test.ts +6 -7
  71. package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
  72. package/src/__tests__/mcp-client-auth.test.ts +40 -4
  73. package/src/__tests__/mcp-health-check.test.ts +10 -3
  74. package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
  75. package/src/__tests__/migration-export-http.test.ts +61 -2
  76. package/src/__tests__/migration-export-streaming.test.ts +66 -0
  77. package/src/__tests__/migration-import-commit-http.test.ts +101 -1
  78. package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
  79. package/src/__tests__/oauth-apps-routes.test.ts +17 -12
  80. package/src/__tests__/oauth-cli.test.ts +707 -60
  81. package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
  82. package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
  83. package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
  84. package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
  85. package/src/__tests__/oauth-providers-routes.test.ts +50 -14
  86. package/src/__tests__/oauth-store.test.ts +1386 -182
  87. package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
  88. package/src/__tests__/onboarding-template-contract.test.ts +75 -57
  89. package/src/__tests__/openai-provider.test.ts +2 -2
  90. package/src/__tests__/outlook-categories.test.ts +1 -1
  91. package/src/__tests__/outlook-client-automation.test.ts +1 -1
  92. package/src/__tests__/outlook-compose-tools.test.ts +1 -1
  93. package/src/__tests__/outlook-email-watcher.test.ts +1 -1
  94. package/src/__tests__/outlook-follow-up.test.ts +1 -1
  95. package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
  96. package/src/__tests__/outlook-trash.test.ts +1 -1
  97. package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
  98. package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
  99. package/src/__tests__/permission-mode.test.ts +28 -56
  100. package/src/__tests__/platform-callback-registration.test.ts +19 -0
  101. package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
  102. package/src/__tests__/proxy-approval-callback.test.ts +18 -0
  103. package/src/__tests__/require-fresh-approval.test.ts +40 -1
  104. package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
  105. package/src/__tests__/schedule-routes.test.ts +162 -0
  106. package/src/__tests__/secret-detection-handler.test.ts +84 -0
  107. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  108. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  109. package/src/__tests__/set-permission-mode.test.ts +13 -250
  110. package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
  111. package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
  112. package/src/__tests__/slack-channel-config.test.ts +12 -15
  113. package/src/__tests__/subagent-detail.test.ts +44 -2
  114. package/src/__tests__/subagent-disposal.test.ts +1 -0
  115. package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
  116. package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
  117. package/src/__tests__/subagent-manager-notify.test.ts +1 -0
  118. package/src/__tests__/subagent-notify-parent.test.ts +1 -0
  119. package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
  120. package/src/__tests__/subagent-tools.test.ts +1 -0
  121. package/src/__tests__/subagent-types.test.ts +1 -0
  122. package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
  123. package/src/__tests__/system-prompt.test.ts +72 -1
  124. package/src/__tests__/task-scheduler.test.ts +32 -6
  125. package/src/__tests__/telegram-config.test.ts +10 -13
  126. package/src/__tests__/terminal-tools.test.ts +9 -0
  127. package/src/__tests__/tool-approval-handler.test.ts +73 -0
  128. package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
  129. package/src/__tests__/top-level-renderer.test.ts +73 -1
  130. package/src/__tests__/transport-hints-queue.test.ts +14 -29
  131. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
  132. package/src/__tests__/v2-consent-policy.test.ts +103 -0
  133. package/src/acp/client-handler.ts +30 -4
  134. package/src/agent/loop.ts +12 -6
  135. package/src/approvals/guardian-request-resolvers.ts +21 -15
  136. package/src/browser-session/__tests__/manager.test.ts +297 -0
  137. package/src/browser-session/backends/cdp-inspect.ts +30 -0
  138. package/src/browser-session/backends/extension.ts +26 -0
  139. package/src/browser-session/backends/local.ts +24 -0
  140. package/src/browser-session/events.ts +164 -0
  141. package/src/browser-session/index.ts +27 -0
  142. package/src/browser-session/manager.ts +159 -0
  143. package/src/browser-session/types.ts +28 -0
  144. package/src/channels/__tests__/types.test.ts +134 -0
  145. package/src/channels/types.ts +53 -3
  146. package/src/cli/commands/browser-relay.ts +339 -409
  147. package/src/cli/commands/credentials.ts +3 -3
  148. package/src/cli/commands/email.ts +18 -13
  149. package/src/cli/commands/mcp.ts +16 -4
  150. package/src/cli/commands/oauth/__tests__/connect.test.ts +44 -44
  151. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
  152. package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
  153. package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
  154. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
  155. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
  156. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
  157. package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
  158. package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
  159. package/src/cli/commands/oauth/apps.ts +7 -4
  160. package/src/cli/commands/oauth/connect.ts +6 -3
  161. package/src/cli/commands/oauth/disconnect.ts +1 -1
  162. package/src/cli/commands/oauth/providers.ts +200 -36
  163. package/src/cli/commands/oauth/shared.ts +5 -5
  164. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
  165. package/src/cli/commands/platform/index.ts +107 -10
  166. package/src/cli/commands/usage.ts +10 -9
  167. package/src/cli/lib/daemon-credential-client.ts +4 -0
  168. package/src/cli/program.ts +1 -1
  169. package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
  170. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
  171. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
  172. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
  173. package/src/config/bundled-skills/contacts/SKILL.md +3 -0
  174. package/src/config/bundled-skills/document/SKILL.md +4 -0
  175. package/src/config/bundled-skills/gmail/SKILL.md +1 -1
  176. package/src/config/bundled-skills/outlook/SKILL.md +7 -0
  177. package/src/config/bundled-skills/subagent/SKILL.md +21 -0
  178. package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
  179. package/src/config/bundled-skills/tasks/SKILL.md +5 -0
  180. package/src/config/env-registry.ts +14 -0
  181. package/src/config/env.ts +21 -0
  182. package/src/config/feature-flag-registry.json +44 -5
  183. package/src/config/loader.ts +56 -1
  184. package/src/config/sanitize-for-transfer.ts +47 -0
  185. package/src/config/schema.ts +46 -5
  186. package/src/config/schemas/host-browser.ts +66 -0
  187. package/src/config/schemas/memory-lifecycle.ts +1 -1
  188. package/src/config/schemas/memory-retrieval.ts +103 -0
  189. package/src/config/schemas/security.ts +0 -6
  190. package/src/config/schemas/services.ts +8 -0
  191. package/src/config/types.ts +0 -1
  192. package/src/context/post-turn-tool-result-truncation.ts +176 -0
  193. package/src/context/window-manager.ts +19 -1
  194. package/src/credential-execution/approval-bridge.ts +49 -15
  195. package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
  196. package/src/daemon/app-source-watcher.ts +35 -0
  197. package/src/daemon/context-overflow-approval.ts +5 -0
  198. package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
  199. package/src/daemon/conversation-agent-loop.ts +58 -24
  200. package/src/daemon/conversation-attachments.ts +40 -0
  201. package/src/daemon/conversation-process.ts +48 -1
  202. package/src/daemon/conversation-runtime-assembly.ts +118 -36
  203. package/src/daemon/conversation-surfaces.ts +37 -36
  204. package/src/daemon/conversation-tool-setup.ts +74 -8
  205. package/src/daemon/conversation-workspace.ts +12 -0
  206. package/src/daemon/conversation.ts +226 -8
  207. package/src/daemon/date-context.ts +10 -10
  208. package/src/daemon/first-greeting.ts +3 -2
  209. package/src/daemon/handlers/conversations.ts +9 -140
  210. package/src/daemon/handlers/shared.ts +58 -0
  211. package/src/daemon/handlers/skills.ts +232 -37
  212. package/src/daemon/host-bash-proxy.ts +48 -13
  213. package/src/daemon/host-browser-proxy.ts +191 -0
  214. package/src/daemon/host-cu-proxy.ts +36 -11
  215. package/src/daemon/host-file-proxy.ts +57 -9
  216. package/src/daemon/lifecycle.ts +65 -11
  217. package/src/daemon/message-protocol.ts +7 -0
  218. package/src/daemon/message-types/conversations.ts +55 -13
  219. package/src/daemon/message-types/host-browser.ts +100 -0
  220. package/src/daemon/message-types/messages.ts +5 -5
  221. package/src/daemon/message-types/skills.ts +10 -0
  222. package/src/daemon/message-types/subagents.ts +2 -0
  223. package/src/daemon/server.ts +92 -12
  224. package/src/daemon/tool-side-effects.ts +6 -0
  225. package/src/daemon/transport-hints.ts +5 -24
  226. package/src/inbound/platform-callback-registration.ts +18 -17
  227. package/src/mcp/client.ts +59 -24
  228. package/src/memory/app-store.ts +31 -1
  229. package/src/memory/conversation-crud.ts +23 -0
  230. package/src/memory/conversation-starters-cadence.ts +76 -0
  231. package/src/memory/conversation-title-service.ts +5 -2
  232. package/src/memory/db-init.ts +12 -0
  233. package/src/memory/embedding-backend.test.ts +75 -0
  234. package/src/memory/embedding-backend.ts +131 -5
  235. package/src/memory/embedding-gemini.test.ts +54 -0
  236. package/src/memory/embedding-gemini.ts +20 -9
  237. package/src/memory/embedding-local.ts +176 -17
  238. package/src/memory/graph/consolidation.ts +10 -23
  239. package/src/memory/graph/extraction-job.ts +15 -0
  240. package/src/memory/graph/retriever.ts +40 -22
  241. package/src/memory/graph/store.test.ts +7 -3
  242. package/src/memory/graph/store.ts +47 -12
  243. package/src/memory/llm-usage-store.ts +45 -4
  244. package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
  245. package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
  246. package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
  247. package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
  248. package/src/memory/migrations/217-conversation-host-access.ts +40 -0
  249. package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
  250. package/src/memory/migrations/index.ts +6 -0
  251. package/src/memory/migrations/registry.ts +8 -0
  252. package/src/memory/schema/conversations.ts +1 -0
  253. package/src/memory/schema/oauth.ts +18 -13
  254. package/src/oauth/AGENTS.md +76 -0
  255. package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
  256. package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
  257. package/src/oauth/byo-connection.test.ts +8 -8
  258. package/src/oauth/byo-connection.ts +7 -7
  259. package/src/oauth/connect-orchestrator.ts +23 -21
  260. package/src/oauth/connect-types.ts +3 -3
  261. package/src/oauth/connection-resolver.test.ts +17 -4
  262. package/src/oauth/connection-resolver.ts +16 -16
  263. package/src/oauth/connection.ts +1 -1
  264. package/src/oauth/manual-token-connection.ts +13 -13
  265. package/src/oauth/oauth-store.ts +214 -100
  266. package/src/oauth/platform-connection.test.ts +3 -3
  267. package/src/oauth/platform-connection.ts +4 -4
  268. package/src/oauth/provider-serializer.ts +31 -5
  269. package/src/oauth/revoke.ts +76 -0
  270. package/src/oauth/seed-providers.ts +126 -87
  271. package/src/oauth/token-persistence.ts +1 -1
  272. package/src/permissions/permission-mode.ts +4 -11
  273. package/src/permissions/prompter.ts +13 -1
  274. package/src/permissions/v2-consent-policy.ts +87 -0
  275. package/src/prompts/system-prompt.ts +18 -21
  276. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
  277. package/src/prompts/templates/BOOTSTRAP.md +59 -105
  278. package/src/providers/anthropic/client.ts +1 -0
  279. package/src/providers/types.ts +1 -1
  280. package/src/runtime/AGENTS.md +23 -0
  281. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
  282. package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
  283. package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
  284. package/src/runtime/assistant-event-hub.ts +2 -2
  285. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  286. package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
  287. package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
  288. package/src/runtime/auth/middleware.ts +98 -0
  289. package/src/runtime/auth/route-policy.ts +6 -7
  290. package/src/runtime/capability-tokens.ts +414 -0
  291. package/src/runtime/channel-approvals.ts +18 -5
  292. package/src/runtime/chrome-extension-registry.ts +332 -0
  293. package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
  294. package/src/runtime/guardian-decision-types.ts +7 -0
  295. package/src/runtime/http-server.ts +425 -70
  296. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
  297. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
  298. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
  299. package/src/runtime/migrations/migration-transport.ts +6 -0
  300. package/src/runtime/migrations/migration-wizard.ts +22 -2
  301. package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
  302. package/src/runtime/migrations/vbundle-builder.ts +145 -38
  303. package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
  304. package/src/runtime/migrations/vbundle-importer.ts +55 -5
  305. package/src/runtime/pending-interactions.ts +29 -13
  306. package/src/runtime/routes/approval-routes.ts +90 -16
  307. package/src/runtime/routes/browser-cdp-routes.ts +229 -0
  308. package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
  309. package/src/runtime/routes/conversation-analysis-routes.ts +2 -1
  310. package/src/runtime/routes/conversation-management-routes.ts +108 -0
  311. package/src/runtime/routes/conversation-routes.ts +301 -27
  312. package/src/runtime/routes/conversation-starter-routes.ts +78 -16
  313. package/src/runtime/routes/guardian-action-routes.ts +24 -13
  314. package/src/runtime/routes/host-browser-routes.ts +279 -0
  315. package/src/runtime/routes/host-file-routes.ts +9 -1
  316. package/src/runtime/routes/identity-routes.ts +259 -16
  317. package/src/runtime/routes/log-export-routes.ts +42 -22
  318. package/src/runtime/routes/memory-item-routes.ts +1 -7
  319. package/src/runtime/routes/migration-routes.ts +87 -2
  320. package/src/runtime/routes/oauth-apps.ts +15 -17
  321. package/src/runtime/routes/oauth-providers.ts +4 -0
  322. package/src/runtime/routes/schedule-routes.ts +24 -11
  323. package/src/runtime/routes/settings-routes.ts +9 -97
  324. package/src/runtime/routes/skills-routes.ts +52 -2
  325. package/src/runtime/routes/subagents-routes.ts +14 -10
  326. package/src/runtime/routes/usage-routes.ts +8 -7
  327. package/src/runtime/routes/workspace-routes.test.ts +22 -0
  328. package/src/runtime/routes/workspace-routes.ts +8 -1
  329. package/src/runtime/routes/workspace-utils.ts +2 -0
  330. package/src/schedule/scheduler.ts +7 -5
  331. package/src/security/ces-credential-client.ts +20 -0
  332. package/src/security/ces-rpc-credential-backend.ts +17 -0
  333. package/src/security/credential-backend.ts +5 -0
  334. package/src/security/oauth2.ts +42 -25
  335. package/src/security/secure-keys.ts +118 -25
  336. package/src/security/token-manager.ts +23 -10
  337. package/src/skills/catalog-files.ts +492 -0
  338. package/src/subagent/manager.ts +131 -26
  339. package/src/subagent/types.ts +19 -0
  340. package/src/tools/apps/executors.ts +11 -2
  341. package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
  342. package/src/tools/browser/auth-detector.ts +43 -12
  343. package/src/tools/browser/browser-execution.ts +645 -340
  344. package/src/tools/browser/browser-manager.ts +36 -12
  345. package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
  346. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
  347. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
  348. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
  349. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
  350. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
  351. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
  352. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
  353. package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
  354. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
  355. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
  356. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
  357. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
  358. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
  359. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
  360. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
  361. package/src/tools/browser/cdp-client/errors.ts +34 -0
  362. package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
  363. package/src/tools/browser/cdp-client/factory.ts +204 -0
  364. package/src/tools/browser/cdp-client/index.ts +14 -0
  365. package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
  366. package/src/tools/browser/cdp-client/types.ts +52 -0
  367. package/src/tools/filesystem/edit.ts +1 -1
  368. package/src/tools/filesystem/list.ts +1 -1
  369. package/src/tools/filesystem/read.ts +1 -1
  370. package/src/tools/filesystem/write.ts +2 -1
  371. package/src/tools/host-filesystem/edit.ts +1 -1
  372. package/src/tools/host-filesystem/read.ts +12 -15
  373. package/src/tools/host-filesystem/write.ts +1 -1
  374. package/src/tools/host-terminal/host-shell.ts +21 -16
  375. package/src/tools/permission-checker.ts +77 -82
  376. package/src/tools/registry.ts +0 -2
  377. package/src/tools/secret-detection-handler.ts +34 -0
  378. package/src/tools/shared/filesystem/image-read.ts +61 -40
  379. package/src/tools/subagent/spawn.ts +47 -3
  380. package/src/tools/subagent/status.ts +2 -0
  381. package/src/tools/system/register.ts +2 -16
  382. package/src/tools/terminal/safe-env.ts +7 -0
  383. package/src/tools/terminal/shell.ts +21 -16
  384. package/src/tools/tool-approval-handler.ts +48 -2
  385. package/src/tools/types.ts +2 -0
  386. package/src/util/platform.ts +14 -19
  387. package/src/workspace/top-level-renderer.ts +19 -1
  388. package/src/__tests__/chrome-cdp.test.ts +0 -419
  389. package/src/__tests__/permission-mode-sse.test.ts +0 -418
  390. package/src/__tests__/permission-mode-store.test.ts +0 -277
  391. package/src/browser-extension-relay/protocol.ts +0 -63
  392. package/src/browser-extension-relay/server.ts +0 -203
  393. package/src/config/schemas/sandbox.ts +0 -14
  394. package/src/permissions/permission-mode-store.ts +0 -180
  395. package/src/tools/browser/chrome-cdp.ts +0 -239
  396. package/src/tools/system/set-permission-mode.ts +0 -103
@@ -19,6 +19,7 @@ import {
19
19
  draftSkill,
20
20
  enableSkill,
21
21
  getSkill,
22
+ getSkillFileContent,
22
23
  getSkillFiles,
23
24
  inspectSkill,
24
25
  installSkill,
@@ -151,6 +152,55 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
151
152
  },
152
153
  },
153
154
 
155
+ // The router uses strict anchored-regex matching, so this route is never
156
+ // ambiguous with skills/:id/files.
157
+ {
158
+ endpoint: "skills/:id/files/content",
159
+ method: "GET",
160
+ policyKey: "skills",
161
+ summary: "Get skill file content",
162
+ description:
163
+ "Return the content of a single file belonging to an installed or catalog skill.",
164
+ tags: ["skills"],
165
+ queryParams: [
166
+ {
167
+ name: "path",
168
+ schema: { type: "string" },
169
+ required: true,
170
+ description: "Relative path of the file within the skill directory",
171
+ },
172
+ ],
173
+ responseBody: z.object({
174
+ path: z.string(),
175
+ name: z.string(),
176
+ size: z.number().int(),
177
+ mimeType: z.string(),
178
+ isBinary: z.boolean(),
179
+ content: z.string().nullable(),
180
+ }),
181
+ handler: async ({ params, url }) => {
182
+ const path = url.searchParams.get("path");
183
+ if (!path) {
184
+ return httpError(
185
+ "BAD_REQUEST",
186
+ "path query parameter is required",
187
+ 400,
188
+ );
189
+ }
190
+ const result = await getSkillFileContent(params.id, path, ctx());
191
+ if ("error" in result) {
192
+ if (result.status === 400) {
193
+ return httpError("BAD_REQUEST", result.error, 400);
194
+ }
195
+ if (result.status === 404) {
196
+ return httpError("NOT_FOUND", result.error, 404);
197
+ }
198
+ return httpError("INTERNAL_ERROR", result.error, 500);
199
+ }
200
+ return Response.json(result);
201
+ },
202
+ },
203
+
154
204
  {
155
205
  endpoint: "skills/:id/files",
156
206
  method: "GET",
@@ -158,8 +208,8 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
158
208
  summary: "Get skill files",
159
209
  description: "Return skill metadata and directory contents.",
160
210
  tags: ["skills"],
161
- handler: ({ params }) => {
162
- const result = getSkillFiles(params.id, ctx());
211
+ handler: async ({ params }) => {
212
+ const result = await getSkillFiles(params.id, ctx());
163
213
  if ("error" in result) {
164
214
  if (result.status === 404) {
165
215
  return httpError("NOT_FOUND", result.error, 404);
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { z } from "zod";
9
9
 
10
- import { getMessages } from "../../memory/conversation-crud.js";
10
+ import { getMessages, type MessageRow } from "../../memory/conversation-crud.js";
11
11
  import { getSubagentManager } from "../../subagent/index.js";
12
12
  import { getLogger } from "../../util/logger.js";
13
13
  import { httpError } from "../http-errors.js";
@@ -31,16 +31,25 @@ export interface SubagentDetailResult {
31
31
  content: string;
32
32
  toolName?: string;
33
33
  isError?: boolean;
34
+ messageId?: string;
34
35
  }>;
35
36
  }
36
37
 
38
+ const FORK_DIRECTIVE_RE =
39
+ /^⎯⎯⎯ FORK TASK ⎯⎯⎯\n[\s\S]*?Complete this task directly and return only your findings:\n\n([\s\S]*?)\n⎯⎯⎯+$/;
40
+
41
+ function stripForkDirectiveFraming(text: string): string {
42
+ const match = FORK_DIRECTIVE_RE.exec(text);
43
+ return match ? match[1] : text;
44
+ }
45
+
37
46
  /**
38
47
  * Parse raw message rows into subagent detail events. Extracted as a pure
39
48
  * function so it can be unit-tested without a database.
40
49
  */
41
50
  export function parseSubagentMessages(
42
51
  subagentId: string,
43
- messages: Array<{ role: string; content: string }>,
52
+ messages: MessageRow[],
44
53
  ): SubagentDetailResult {
45
54
  // Extract objective from the first user message
46
55
  let objective: string | undefined;
@@ -53,7 +62,7 @@ export function parseSubagentMessages(
53
62
  (b: Record<string, unknown>) => isRecord(b) && b.type === "text",
54
63
  );
55
64
  if (textBlock && typeof textBlock.text === "string") {
56
- objective = textBlock.text;
65
+ objective = stripForkDirectiveFraming(textBlock.text);
57
66
  }
58
67
  }
59
68
  } catch {
@@ -62,12 +71,7 @@ export function parseSubagentMessages(
62
71
  }
63
72
 
64
73
  // Extract events from both assistant and user messages.
65
- const events: Array<{
66
- type: string;
67
- content: string;
68
- toolName?: string;
69
- isError?: boolean;
70
- }> = [];
74
+ const events: SubagentDetailResult["events"] = [];
71
75
  const pendingTools = new Map<string, string>();
72
76
  for (const m of messages) {
73
77
  if (m.role !== "assistant" && m.role !== "user") continue;
@@ -86,7 +90,7 @@ export function parseSubagentMessages(
86
90
  block.type === "text" &&
87
91
  typeof block.text === "string"
88
92
  ) {
89
- events.push({ type: "text", content: block.text });
93
+ events.push({ type: "text", content: block.text, messageId: m.id });
90
94
  } else if (block.type === "tool_use") {
91
95
  const name = typeof block.name === "string" ? block.name : "unknown";
92
96
  const input = isRecord(block.input)
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * GET /v1/usage/totals?from=&to= — aggregate totals for a time range
5
5
  * GET /v1/usage/daily?from=&to= — per-day buckets for a time range
6
- * GET /v1/usage/breakdown?from=&to=&groupBy= — grouped breakdown (actor, provider, model)
6
+ * GET /v1/usage/breakdown?from=&to=&groupBy= — grouped breakdown (actor, provider, model, or conversation)
7
7
  */
8
8
 
9
9
  import { z } from "zod";
@@ -17,7 +17,7 @@ import {
17
17
  import { httpError } from "../http-errors.js";
18
18
  import type { RouteDefinition } from "../http-router.js";
19
19
 
20
- const VALID_GROUP_BY = new Set(["actor", "provider", "model"]);
20
+ const VALID_GROUP_BY = new Set(["actor", "provider", "model", "conversation"]);
21
21
 
22
22
  /**
23
23
  * Parse and validate the `from` and `to` epoch-millis query parameters.
@@ -137,7 +137,7 @@ export function usageRouteDefinitions(): RouteDefinition[] {
137
137
  method: "GET",
138
138
  summary: "Get usage breakdown",
139
139
  description:
140
- "Return grouped usage breakdown (by actor, provider, or model).",
140
+ "Return grouped usage breakdown (by actor, provider, model, or conversation).",
141
141
  tags: ["usage"],
142
142
  queryParams: [
143
143
  {
@@ -153,7 +153,8 @@ export function usageRouteDefinitions(): RouteDefinition[] {
153
153
  {
154
154
  name: "groupBy",
155
155
  schema: { type: "string" },
156
- description: "Group by: actor, provider, or model (required)",
156
+ description:
157
+ "Group by: actor, provider, model, or conversation (required)",
157
158
  },
158
159
  ],
159
160
  responseBody: z.object({
@@ -167,21 +168,21 @@ export function usageRouteDefinitions(): RouteDefinition[] {
167
168
  if (!groupBy) {
168
169
  return httpError(
169
170
  "BAD_REQUEST",
170
- 'Missing required query parameter: "groupBy" (one of: actor, provider, model)',
171
+ 'Missing required query parameter: "groupBy" (one of: actor, provider, model, conversation)',
171
172
  400,
172
173
  );
173
174
  }
174
175
  if (!VALID_GROUP_BY.has(groupBy)) {
175
176
  return httpError(
176
177
  "BAD_REQUEST",
177
- `Invalid "groupBy" value: "${groupBy}". Must be one of: actor, provider, model`,
178
+ `Invalid "groupBy" value: "${groupBy}". Must be one of: actor, provider, model, conversation`,
178
179
  400,
179
180
  );
180
181
  }
181
182
 
182
183
  const breakdown = getUsageGroupBreakdown(
183
184
  range,
184
- groupBy as "actor" | "provider" | "model",
185
+ groupBy as "actor" | "provider" | "model" | "conversation",
185
186
  );
186
187
  return Response.json({ breakdown });
187
188
  },
@@ -190,6 +190,28 @@ describe("isTextMimeType", () => {
190
190
  // A binary plist has a specific MIME type — extension should not override it
191
191
  expect(isTextMimeType("application/x-plist", "Info.plist")).toBe(false);
192
192
  });
193
+
194
+ test("application/octet-stream with .jsonl filename is text", () => {
195
+ expect(isTextMimeType("application/octet-stream", "messages.jsonl")).toBe(
196
+ true,
197
+ );
198
+ });
199
+
200
+ test("application/octet-stream with .ndjson filename is text", () => {
201
+ expect(isTextMimeType("application/octet-stream", "events.ndjson")).toBe(
202
+ true,
203
+ );
204
+ });
205
+
206
+ test("application/octet-stream with .JSONL uppercase is text", () => {
207
+ expect(isTextMimeType("application/octet-stream", "DATA.JSONL")).toBe(true);
208
+ });
209
+
210
+ test("application/octet-stream with .NDJSON uppercase is text", () => {
211
+ expect(isTextMimeType("application/octet-stream", "DATA.NDJSON")).toBe(
212
+ true,
213
+ );
214
+ });
193
215
  });
194
216
 
195
217
  // ===========================================================================
@@ -120,7 +120,14 @@ function handleWorkspaceFile(ctx: RouteContext): Response {
120
120
  }
121
121
 
122
122
  const mimeType = Bun.file(resolved).type;
123
- const isText = isTextMimeType(mimeType, basename(resolved));
123
+ // Empty files with unknown MIME type default to text — there is no binary
124
+ // content to protect, and files created via the UI "New File" action are
125
+ // always 0 bytes. Without this override, extensionless files (e.g. "Test")
126
+ // would be classified as binary and rendered in a non-editable fallback view.
127
+ const isText =
128
+ stat.size === 0 && mimeType === "application/octet-stream"
129
+ ? true
130
+ : isTextMimeType(mimeType, basename(resolved));
124
131
  const isBinary = !isText;
125
132
 
126
133
  let content: string | undefined = undefined;
@@ -159,6 +159,8 @@ const TEXT_FILE_EXTENSIONS = new Set([
159
159
  "patch",
160
160
  "log",
161
161
  "lock",
162
+ "jsonl",
163
+ "ndjson",
162
164
  ]);
163
165
 
164
166
  export function isTextMimeType(mimeType: string, fileName?: string): boolean {
@@ -23,6 +23,7 @@ const log = getLogger("scheduler");
23
23
 
24
24
  export interface ScheduleMessageOptions {
25
25
  trustClass?: "guardian" | "trusted_contact" | "unknown";
26
+ taskRunId?: string;
26
27
  }
27
28
 
28
29
  export type ScheduleMessageProcessor = (
@@ -196,11 +197,12 @@ async function runScheduleOnce(
196
197
  source: "schedule",
197
198
  scheduleJobId: job.id,
198
199
  },
199
- processMessage as (
200
- conversationId: string,
201
- message: string,
202
- taskRunId: string,
203
- ) => Promise<void>,
200
+ async (conversationId, message, taskRunId) => {
201
+ await processMessage(conversationId, message, {
202
+ trustClass: "guardian",
203
+ taskRunId,
204
+ });
205
+ },
204
206
  );
205
207
 
206
208
  onScheduleConversationCreated?.({
@@ -190,6 +190,26 @@ export class CesCredentialBackend implements CredentialBackend {
190
190
  }
191
191
  }
192
192
 
193
+ async bulkSet(
194
+ credentials: Array<{ account: string; value: string }>,
195
+ ): Promise<Array<{ account: string; ok: boolean }>> {
196
+ try {
197
+ const res = await cesRequest("POST", "/v1/credentials/bulk", {
198
+ credentials,
199
+ });
200
+ if (!res?.ok) {
201
+ return credentials.map((c) => ({ account: c.account, ok: false }));
202
+ }
203
+ const data = (await res.json()) as {
204
+ results: Array<{ account: string; ok: boolean }>;
205
+ };
206
+ return data.results;
207
+ } catch (err) {
208
+ log.warn({ err }, "CES credential bulk set threw unexpectedly");
209
+ return credentials.map((c) => ({ account: c.account, ok: false }));
210
+ }
211
+ }
212
+
193
213
  async list(): Promise<CredentialListResult> {
194
214
  try {
195
215
  const res = await cesRequest("GET", "/v1/credentials");
@@ -86,4 +86,21 @@ export class CesRpcCredentialBackend implements CredentialBackend {
86
86
  return { accounts: [], unreachable: true };
87
87
  }
88
88
  }
89
+
90
+ async bulkSet(
91
+ credentials: Array<{ account: string; value: string }>,
92
+ ): Promise<Array<{ account: string; ok: boolean }>> {
93
+ if (!this.isAvailable()) {
94
+ return credentials.map((c) => ({ account: c.account, ok: false }));
95
+ }
96
+ try {
97
+ const result = await this.client.call(CesRpcMethod.BulkSetCredentials, {
98
+ credentials,
99
+ });
100
+ return result.results;
101
+ } catch (err) {
102
+ log.warn({ err }, "CES RPC bulk credential set failed");
103
+ return credentials.map((c) => ({ account: c.account, ok: false }));
104
+ }
105
+ }
89
106
  }
@@ -47,6 +47,11 @@ export interface CredentialBackend {
47
47
 
48
48
  /** List all account names. */
49
49
  list(): Promise<CredentialListResult>;
50
+
51
+ /** Bulk-set multiple credentials. Optional — backends without native bulk support omit this. */
52
+ bulkSet?(
53
+ credentials: Array<{ account: string; value: string }>,
54
+ ): Promise<Array<{ account: string; ok: boolean }>>;
50
55
  }
51
56
 
52
57
  // ---------------------------------------------------------------------------
@@ -33,13 +33,13 @@ export type TokenEndpointAuthMethod =
33
33
  | "client_secret_post";
34
34
 
35
35
  export interface OAuth2Config {
36
- authUrl: string;
37
- tokenUrl: string;
36
+ authorizeUrl: string;
37
+ tokenExchangeUrl: string;
38
38
  scopes: string[];
39
39
  clientId: string;
40
40
  /** Client secret for providers that require it (e.g. Slack). PKCE is always used regardless. */
41
41
  clientSecret?: string;
42
- extraParams?: Record<string, string>;
42
+ authorizeParams?: Record<string, string>;
43
43
  /** URL to fetch user identity info after OAuth. If omitted, account info is not fetched. */
44
44
  userinfoUrl?: string;
45
45
  /**
@@ -49,6 +49,13 @@ export interface OAuth2Config {
49
49
  * Defaults to `client_secret_post`.
50
50
  */
51
51
  tokenEndpointAuthMethod?: TokenEndpointAuthMethod;
52
+ /**
53
+ * Separator used to join scopes in the authorize URL and split the
54
+ * granted-scope string returned by the token endpoint. Defaults to
55
+ * `" "` (space) per the OAuth 2.0 spec, but providers like Linear
56
+ * use `","` (comma).
57
+ */
58
+ scopeSeparator: string;
52
59
  }
53
60
 
54
61
  export interface OAuth2TokenResult {
@@ -130,7 +137,7 @@ async function exchangeCodeForTokens(
130
137
  }
131
138
  }
132
139
 
133
- const tokenResp = await fetch(config.tokenUrl, {
140
+ const tokenResp = await fetch(config.tokenExchangeUrl, {
134
141
  method: "POST",
135
142
  headers,
136
143
  body: new URLSearchParams(tokenBody),
@@ -187,9 +194,19 @@ async function exchangeCodeForTokens(
187
194
  (tokenData.token_type as string | undefined),
188
195
  };
189
196
 
197
+ // Defensive split: providers (e.g. GitHub, Slack) may return comma-separated
198
+ // scopes in token responses regardless of the scope_separator used to join
199
+ // outbound authorize URLs, so we tolerate both spaces and commas here. When
200
+ // a provider explicitly configures a non-default separator (e.g. Linear uses
201
+ // ","), we honor that to keep symmetric round-tripping of configured scopes.
202
+ const splitPattern =
203
+ config.scopeSeparator === " " ? /[ ,]/ : config.scopeSeparator;
190
204
  const grantedScopes =
191
205
  typeof tokens.scope === "string"
192
- ? tokens.scope.split(/[ ,]/).filter(Boolean)
206
+ ? tokens.scope
207
+ .split(splitPattern)
208
+ .map((s) => s.trim())
209
+ .filter(Boolean)
193
210
  : [...config.scopes];
194
211
 
195
212
  return { tokens, grantedScopes, rawTokenResponse: tokenData };
@@ -228,18 +245,18 @@ async function runGatewayFlow(
228
245
  });
229
246
 
230
247
  const authParams = new URLSearchParams({
231
- ...config.extraParams,
248
+ ...config.authorizeParams,
232
249
  client_id: config.clientId,
233
250
  redirect_uri: redirectUri,
234
251
  response_type: "code",
235
- scope: config.scopes.join(" "),
252
+ scope: config.scopes.join(config.scopeSeparator),
236
253
  state,
237
254
  code_challenge: codeChallenge,
238
255
  code_challenge_method: "S256",
239
256
  });
240
257
 
241
- const authUrl = `${config.authUrl}?${authParams}`;
242
- callbacks.openUrl(authUrl);
258
+ const authorizeUrl = `${config.authorizeUrl}?${authParams}`;
259
+ callbacks.openUrl(authorizeUrl);
243
260
 
244
261
  const code = await codePromise;
245
262
 
@@ -401,22 +418,22 @@ function startLoopbackServerAndWaitForCode(
401
418
  );
402
419
 
403
420
  const authParams = new URLSearchParams({
404
- ...config.extraParams,
421
+ ...config.authorizeParams,
405
422
  client_id: config.clientId,
406
423
  redirect_uri: boundRedirectUri,
407
424
  response_type: "code",
408
- scope: config.scopes.join(" "),
425
+ scope: config.scopes.join(config.scopeSeparator),
409
426
  state,
410
427
  code_challenge: codeChallenge,
411
428
  code_challenge_method: "S256",
412
429
  });
413
430
 
414
- const authUrl = `${config.authUrl}?${authParams}`;
431
+ const authorizeUrl = `${config.authorizeUrl}?${authParams}`;
415
432
  log.info(
416
- { authUrlLength: authUrl.length, state },
433
+ { authorizeUrlLength: authorizeUrl.length, state },
417
434
  "oauth2 loopback: built auth URL, calling openUrl callback",
418
435
  );
419
- callbacks.openUrl(authUrl);
436
+ callbacks.openUrl(authorizeUrl);
420
437
  log.info("oauth2 loopback: openUrl callback returned");
421
438
  });
422
439
 
@@ -439,7 +456,7 @@ function startLoopbackServerAndWaitForCode(
439
456
  // ---------------------------------------------------------------------------
440
457
 
441
458
  export interface OAuth2PreparedFlow {
442
- authUrl: string;
459
+ authorizeUrl: string;
443
460
  state: string;
444
461
  /** Resolves when the user completes authorization and tokens are exchanged. */
445
462
  completion: Promise<OAuth2FlowResult>;
@@ -493,17 +510,17 @@ export async function prepareOAuth2Flow(
493
510
  });
494
511
 
495
512
  const authParams = new URLSearchParams({
496
- ...config.extraParams,
513
+ ...config.authorizeParams,
497
514
  client_id: config.clientId,
498
515
  redirect_uri: redirectUri,
499
516
  response_type: "code",
500
- scope: config.scopes.join(" "),
517
+ scope: config.scopes.join(config.scopeSeparator),
501
518
  state,
502
519
  code_challenge: codeChallenge,
503
520
  code_challenge_method: "S256",
504
521
  });
505
522
 
506
- const authUrl = `${config.authUrl}?${authParams}`;
523
+ const authorizeUrl = `${config.authorizeUrl}?${authParams}`;
507
524
 
508
525
  const completion = codePromise.then(async (code) => {
509
526
  return await exchangeCodeForTokens(config, code, redirectUri, codeVerifier);
@@ -511,7 +528,7 @@ export async function prepareOAuth2Flow(
511
528
 
512
529
  log.debug({ transport: "gateway", state }, "Prepared deferred OAuth2 flow");
513
530
 
514
- return { authUrl, state, completion };
531
+ return { authorizeUrl, state, completion };
515
532
  }
516
533
 
517
534
  /**
@@ -533,17 +550,17 @@ async function prepareLoopbackFlow(
533
550
  );
534
551
 
535
552
  const authParams = new URLSearchParams({
536
- ...config.extraParams,
553
+ ...config.authorizeParams,
537
554
  client_id: config.clientId,
538
555
  redirect_uri: redirectUri,
539
556
  response_type: "code",
540
- scope: config.scopes.join(" "),
557
+ scope: config.scopes.join(config.scopeSeparator),
541
558
  state,
542
559
  code_challenge: codeChallenge,
543
560
  code_challenge_method: "S256",
544
561
  });
545
562
 
546
- const authUrl = `${config.authUrl}?${authParams}`;
563
+ const authorizeUrl = `${config.authorizeUrl}?${authParams}`;
547
564
 
548
565
  const completion = codePromise.then(async (code) => {
549
566
  return await exchangeCodeForTokens(config, code, redirectUri, codeVerifier);
@@ -554,7 +571,7 @@ async function prepareLoopbackFlow(
554
571
  "Prepared deferred OAuth2 flow (loopback)",
555
572
  );
556
573
 
557
- return { authUrl, state, completion };
574
+ return { authorizeUrl, state, completion };
558
575
  }
559
576
 
560
577
  /**
@@ -763,7 +780,7 @@ export async function startOAuth2Flow(
763
780
  * Supports both PKCE (no secret) and client_secret flows.
764
781
  */
765
782
  export async function refreshOAuth2Token(
766
- tokenUrl: string,
783
+ tokenExchangeUrl: string,
767
784
  clientId: string,
768
785
  refreshToken: string,
769
786
  clientSecret?: string,
@@ -792,7 +809,7 @@ export async function refreshOAuth2Token(
792
809
  }
793
810
  }
794
811
 
795
- const resp = await fetch(tokenUrl, {
812
+ const resp = await fetch(tokenExchangeUrl, {
796
813
  method: "POST",
797
814
  headers,
798
815
  body: new URLSearchParams(body),