@vellumai/assistant 0.6.1 → 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 (463) hide show
  1. package/bun.lock +40 -40
  2. package/bunfig.toml +3 -0
  3. package/docker-entrypoint.sh +12 -2
  4. package/docs/architecture/memory.md +1 -1
  5. package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
  6. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
  7. package/openapi.yaml +184 -69
  8. package/package.json +41 -41
  9. package/scripts/generate-openapi.ts +1 -2
  10. package/src/__tests__/acp-session.test.ts +43 -0
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
  12. package/src/__tests__/app-executors.test.ts +1 -0
  13. package/src/__tests__/app-source-watcher.test.ts +37 -11
  14. package/src/__tests__/approval-routes-http.test.ts +178 -1
  15. package/src/__tests__/assistant-event-hub.test.ts +30 -0
  16. package/src/__tests__/browser-fill-credential.test.ts +229 -94
  17. package/src/__tests__/browser-manager.test.ts +40 -27
  18. package/src/__tests__/catalog-files.test.ts +862 -0
  19. package/src/__tests__/channel-approvals.test.ts +53 -0
  20. package/src/__tests__/checker.test.ts +104 -170
  21. package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
  22. package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
  23. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  24. package/src/__tests__/config-schema.test.ts +125 -48
  25. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
  26. package/src/__tests__/context-overflow-approval.test.ts +21 -6
  27. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
  28. package/src/__tests__/conversation-agent-loop.test.ts +1 -1
  29. package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
  30. package/src/__tests__/conversation-attachments.test.ts +80 -4
  31. package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
  32. package/src/__tests__/conversation-directories-parse.test.ts +105 -0
  33. package/src/__tests__/conversation-fork-crud.test.ts +17 -0
  34. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  35. package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
  36. package/src/__tests__/conversation-inject-context.test.ts +103 -0
  37. package/src/__tests__/conversation-queue.test.ts +45 -2
  38. package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
  39. package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
  40. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  41. package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
  42. package/src/__tests__/conversation-starter-routes.test.ts +126 -0
  43. package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
  44. package/src/__tests__/conversation-store.test.ts +195 -0
  45. package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
  46. package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -3
  47. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  48. package/src/__tests__/credential-vault-unit.test.ts +4 -4
  49. package/src/__tests__/credential-vault.test.ts +152 -13
  50. package/src/__tests__/credentials-cli.test.ts +2 -2
  51. package/src/__tests__/date-context.test.ts +4 -4
  52. package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
  53. package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
  54. package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
  55. package/src/__tests__/gateway-only-guard.test.ts +3 -0
  56. package/src/__tests__/gemini-provider.test.ts +2 -2
  57. package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
  58. package/src/__tests__/headless-browser-interactions.test.ts +707 -371
  59. package/src/__tests__/headless-browser-navigate.test.ts +389 -47
  60. package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
  61. package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
  62. package/src/__tests__/host-bash-proxy.test.ts +150 -1
  63. package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
  64. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
  65. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
  66. package/src/__tests__/host-browser-event-routes.test.ts +350 -0
  67. package/src/__tests__/host-browser-proxy.test.ts +444 -0
  68. package/src/__tests__/host-browser-routes.test.ts +198 -0
  69. package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
  70. package/src/__tests__/host-cu-proxy.test.ts +171 -1
  71. package/src/__tests__/host-file-proxy.test.ts +185 -1
  72. package/src/__tests__/host-file-read-tool.test.ts +52 -0
  73. package/src/__tests__/host-proxy-interface.test.ts +165 -0
  74. package/src/__tests__/host-shell-tool.test.ts +1 -11
  75. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  76. package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
  77. package/src/__tests__/inline-command-runner.test.ts +7 -5
  78. package/src/__tests__/integration-status.test.ts +6 -7
  79. package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
  80. package/src/__tests__/log-export-workspace.test.ts +190 -0
  81. package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
  82. package/src/__tests__/mcp-client-auth.test.ts +40 -4
  83. package/src/__tests__/mcp-health-check.test.ts +10 -3
  84. package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
  85. package/src/__tests__/migration-export-http.test.ts +61 -2
  86. package/src/__tests__/migration-export-streaming.test.ts +66 -0
  87. package/src/__tests__/migration-import-commit-http.test.ts +101 -1
  88. package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
  89. package/src/__tests__/navigate-settings-tab.test.ts +14 -1
  90. package/src/__tests__/notification-broadcaster.test.ts +65 -0
  91. package/src/__tests__/oauth-apps-routes.test.ts +17 -12
  92. package/src/__tests__/oauth-cli.test.ts +707 -60
  93. package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
  94. package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
  95. package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
  96. package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
  97. package/src/__tests__/oauth-providers-routes.test.ts +50 -14
  98. package/src/__tests__/oauth-store.test.ts +1386 -182
  99. package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
  100. package/src/__tests__/onboarding-template-contract.test.ts +74 -55
  101. package/src/__tests__/openai-provider.test.ts +2 -2
  102. package/src/__tests__/outlook-categories.test.ts +1 -1
  103. package/src/__tests__/outlook-client-automation.test.ts +1 -1
  104. package/src/__tests__/outlook-compose-tools.test.ts +1 -1
  105. package/src/__tests__/outlook-email-watcher.test.ts +1 -1
  106. package/src/__tests__/outlook-follow-up.test.ts +1 -1
  107. package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
  108. package/src/__tests__/outlook-trash.test.ts +1 -1
  109. package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
  110. package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
  111. package/src/__tests__/permission-mode.test.ts +28 -56
  112. package/src/__tests__/pkb-autoinject.test.ts +96 -0
  113. package/src/__tests__/platform-callback-registration.test.ts +19 -0
  114. package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
  115. package/src/__tests__/proxy-approval-callback.test.ts +18 -0
  116. package/src/__tests__/require-fresh-approval.test.ts +40 -3
  117. package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
  118. package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
  119. package/src/__tests__/schedule-routes.test.ts +162 -0
  120. package/src/__tests__/secret-detection-handler.test.ts +84 -0
  121. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  122. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  123. package/src/__tests__/set-permission-mode.test.ts +13 -250
  124. package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
  125. package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
  126. package/src/__tests__/slack-channel-config.test.ts +12 -15
  127. package/src/__tests__/subagent-detail.test.ts +44 -2
  128. package/src/__tests__/subagent-disposal.test.ts +1 -0
  129. package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
  130. package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
  131. package/src/__tests__/subagent-manager-notify.test.ts +1 -0
  132. package/src/__tests__/subagent-notify-parent.test.ts +1 -0
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
  134. package/src/__tests__/subagent-tools.test.ts +1 -0
  135. package/src/__tests__/subagent-types.test.ts +1 -0
  136. package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
  137. package/src/__tests__/system-prompt.test.ts +72 -1
  138. package/src/__tests__/task-scheduler.test.ts +32 -6
  139. package/src/__tests__/telegram-config.test.ts +10 -13
  140. package/src/__tests__/terminal-sandbox.test.ts +1 -1
  141. package/src/__tests__/terminal-tools.test.ts +11 -5
  142. package/src/__tests__/test-preload.ts +14 -0
  143. package/src/__tests__/tool-approval-handler.test.ts +73 -0
  144. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
  145. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
  146. package/src/__tests__/tool-executor.test.ts +0 -1
  147. package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
  148. package/src/__tests__/top-level-renderer.test.ts +73 -1
  149. package/src/__tests__/transport-hints-queue.test.ts +62 -0
  150. package/src/__tests__/trust-store.test.ts +4 -4
  151. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
  152. package/src/__tests__/v2-consent-policy.test.ts +103 -0
  153. package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
  154. package/src/__tests__/workspace-policy.test.ts +2 -7
  155. package/src/acp/client-handler.ts +30 -4
  156. package/src/agent/loop.ts +12 -35
  157. package/src/approvals/guardian-request-resolvers.ts +21 -15
  158. package/src/browser-session/__tests__/manager.test.ts +297 -0
  159. package/src/browser-session/backends/cdp-inspect.ts +30 -0
  160. package/src/browser-session/backends/extension.ts +26 -0
  161. package/src/browser-session/backends/local.ts +24 -0
  162. package/src/browser-session/events.ts +164 -0
  163. package/src/browser-session/index.ts +27 -0
  164. package/src/browser-session/manager.ts +159 -0
  165. package/src/browser-session/types.ts +28 -0
  166. package/src/channels/__tests__/types.test.ts +134 -0
  167. package/src/channels/types.ts +55 -0
  168. package/src/cli/__tests__/run-assistant-command.ts +34 -7
  169. package/src/cli/__tests__/unknown-command.test.ts +33 -0
  170. package/src/cli/commands/browser-relay.ts +339 -409
  171. package/src/cli/commands/credentials.ts +3 -3
  172. package/src/cli/commands/default-action.ts +68 -1
  173. package/src/cli/commands/email.ts +18 -13
  174. package/src/cli/commands/mcp.ts +16 -4
  175. package/src/cli/commands/oauth/__tests__/connect.test.ts +68 -41
  176. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
  177. package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
  178. package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
  179. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
  180. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
  181. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
  182. package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
  183. package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
  184. package/src/cli/commands/oauth/apps.ts +7 -4
  185. package/src/cli/commands/oauth/connect.ts +16 -2
  186. package/src/cli/commands/oauth/disconnect.ts +1 -1
  187. package/src/cli/commands/oauth/providers.ts +200 -36
  188. package/src/cli/commands/oauth/shared.ts +5 -5
  189. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
  190. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  191. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  192. package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
  193. package/src/cli/commands/platform/index.ts +107 -10
  194. package/src/cli/commands/usage.ts +10 -9
  195. package/src/cli/lib/daemon-credential-client.ts +4 -0
  196. package/src/cli/program.ts +10 -3
  197. package/src/config/assistant-feature-flags.ts +59 -55
  198. package/src/config/bundled-skills/app-builder/SKILL.md +33 -173
  199. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
  200. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
  201. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
  202. package/src/config/bundled-skills/contacts/SKILL.md +3 -0
  203. package/src/config/bundled-skills/document/SKILL.md +4 -0
  204. package/src/config/bundled-skills/gmail/SKILL.md +12 -7
  205. package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
  206. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
  207. package/src/config/bundled-skills/outlook/SKILL.md +7 -0
  208. package/src/config/bundled-skills/settings/TOOLS.json +1 -1
  209. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
  210. package/src/config/bundled-skills/subagent/SKILL.md +21 -0
  211. package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
  212. package/src/config/bundled-skills/tasks/SKILL.md +5 -0
  213. package/src/config/env-registry.ts +14 -0
  214. package/src/config/env.ts +21 -0
  215. package/src/config/feature-flag-registry.json +46 -7
  216. package/src/config/loader.ts +56 -1
  217. package/src/config/sanitize-for-transfer.ts +47 -0
  218. package/src/config/schema.ts +46 -5
  219. package/src/config/schemas/host-browser.ts +66 -0
  220. package/src/config/schemas/memory-lifecycle.ts +1 -1
  221. package/src/config/schemas/memory-retrieval.ts +103 -0
  222. package/src/config/schemas/security.ts +0 -6
  223. package/src/config/schemas/services.ts +16 -0
  224. package/src/config/types.ts +0 -1
  225. package/src/context/post-turn-tool-result-truncation.ts +176 -0
  226. package/src/context/window-manager.ts +19 -1
  227. package/src/credential-execution/approval-bridge.ts +49 -16
  228. package/src/credential-execution/managed-catalog.ts +3 -7
  229. package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
  230. package/src/daemon/app-source-watcher.ts +35 -0
  231. package/src/daemon/config-watcher.ts +6 -2
  232. package/src/daemon/context-overflow-approval.ts +5 -1
  233. package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
  234. package/src/daemon/conversation-agent-loop.ts +74 -19
  235. package/src/daemon/conversation-attachments.ts +40 -1
  236. package/src/daemon/conversation-messaging.ts +3 -0
  237. package/src/daemon/conversation-process.ts +66 -3
  238. package/src/daemon/conversation-queue-manager.ts +8 -0
  239. package/src/daemon/conversation-runtime-assembly.ts +159 -20
  240. package/src/daemon/conversation-surfaces.ts +78 -12
  241. package/src/daemon/conversation-tool-setup.ts +74 -11
  242. package/src/daemon/conversation-workspace.ts +12 -0
  243. package/src/daemon/conversation.ts +227 -11
  244. package/src/daemon/date-context.ts +10 -10
  245. package/src/daemon/first-greeting.ts +3 -2
  246. package/src/daemon/handlers/conversations.ts +9 -139
  247. package/src/daemon/handlers/shared.ts +65 -0
  248. package/src/daemon/handlers/skills.ts +232 -37
  249. package/src/daemon/host-bash-proxy.ts +48 -13
  250. package/src/daemon/host-browser-proxy.ts +191 -0
  251. package/src/daemon/host-cu-proxy.ts +36 -11
  252. package/src/daemon/host-file-proxy.ts +57 -9
  253. package/src/daemon/lifecycle.ts +86 -12
  254. package/src/daemon/message-protocol.ts +7 -0
  255. package/src/daemon/message-types/conversations.ts +59 -13
  256. package/src/daemon/message-types/host-browser.ts +100 -0
  257. package/src/daemon/message-types/messages.ts +5 -6
  258. package/src/daemon/message-types/notifications.ts +12 -0
  259. package/src/daemon/message-types/settings.ts +12 -0
  260. package/src/daemon/message-types/skills.ts +10 -0
  261. package/src/daemon/message-types/subagents.ts +2 -0
  262. package/src/daemon/server.ts +112 -35
  263. package/src/daemon/tool-side-effects.ts +6 -0
  264. package/src/daemon/transport-hints.ts +14 -0
  265. package/src/inbound/platform-callback-registration.ts +18 -17
  266. package/src/index.ts +1 -1
  267. package/src/mcp/client.ts +59 -24
  268. package/src/memory/app-store.ts +31 -1
  269. package/src/memory/conversation-crud.ts +38 -10
  270. package/src/memory/conversation-directories.ts +39 -0
  271. package/src/memory/conversation-group-migration.ts +65 -5
  272. package/src/memory/conversation-starters-cadence.ts +76 -0
  273. package/src/memory/conversation-title-service.ts +5 -2
  274. package/src/memory/db-init.ts +12 -0
  275. package/src/memory/embedding-backend.test.ts +75 -0
  276. package/src/memory/embedding-backend.ts +131 -5
  277. package/src/memory/embedding-gemini.test.ts +54 -0
  278. package/src/memory/embedding-gemini.ts +20 -9
  279. package/src/memory/embedding-local.ts +177 -18
  280. package/src/memory/graph/capability-seed.ts +3 -5
  281. package/src/memory/graph/consolidation.ts +10 -23
  282. package/src/memory/graph/extraction-job.ts +15 -0
  283. package/src/memory/graph/retriever.ts +40 -22
  284. package/src/memory/graph/store.test.ts +7 -3
  285. package/src/memory/graph/store.ts +47 -12
  286. package/src/memory/group-crud.ts +25 -9
  287. package/src/memory/llm-usage-store.ts +45 -4
  288. package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
  289. package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
  290. package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
  291. package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
  292. package/src/memory/migrations/217-conversation-host-access.ts +40 -0
  293. package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
  294. package/src/memory/migrations/index.ts +6 -0
  295. package/src/memory/migrations/registry.ts +8 -0
  296. package/src/memory/schema/conversations.ts +1 -0
  297. package/src/memory/schema/oauth.ts +18 -13
  298. package/src/messaging/provider.ts +1 -1
  299. package/src/notifications/broadcaster.ts +6 -0
  300. package/src/notifications/conversation-pairing.ts +12 -4
  301. package/src/notifications/emit-signal.ts +14 -0
  302. package/src/notifications/signal.ts +11 -0
  303. package/src/oauth/AGENTS.md +76 -0
  304. package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
  305. package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
  306. package/src/oauth/byo-connection.test.ts +8 -8
  307. package/src/oauth/byo-connection.ts +7 -7
  308. package/src/oauth/connect-orchestrator.ts +23 -21
  309. package/src/oauth/connect-types.ts +3 -3
  310. package/src/oauth/connection-resolver.test.ts +17 -4
  311. package/src/oauth/connection-resolver.ts +16 -16
  312. package/src/oauth/connection.ts +1 -1
  313. package/src/oauth/manual-token-connection.ts +13 -13
  314. package/src/oauth/oauth-store.ts +214 -100
  315. package/src/oauth/platform-connection.test.ts +5 -5
  316. package/src/oauth/platform-connection.ts +4 -4
  317. package/src/oauth/provider-serializer.ts +31 -5
  318. package/src/oauth/revoke.ts +76 -0
  319. package/src/oauth/seed-providers.ts +127 -87
  320. package/src/oauth/token-persistence.ts +1 -1
  321. package/src/permissions/checker.ts +3 -3
  322. package/src/permissions/defaults.ts +7 -8
  323. package/src/permissions/permission-mode.ts +4 -11
  324. package/src/permissions/prompter.ts +13 -3
  325. package/src/permissions/v2-consent-policy.ts +87 -0
  326. package/src/platform/client.ts +1 -1
  327. package/src/prompts/system-prompt.ts +18 -21
  328. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
  329. package/src/prompts/templates/BOOTSTRAP.md +59 -96
  330. package/src/prompts/templates/SOUL.md +11 -11
  331. package/src/providers/anthropic/client.ts +1 -0
  332. package/src/providers/types.ts +1 -1
  333. package/src/runtime/AGENTS.md +23 -0
  334. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
  335. package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
  336. package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
  337. package/src/runtime/assistant-event-hub.ts +24 -2
  338. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  339. package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
  340. package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
  341. package/src/runtime/auth/middleware.ts +98 -0
  342. package/src/runtime/auth/route-policy.ts +6 -7
  343. package/src/runtime/auth/token-service.ts +8 -0
  344. package/src/runtime/capability-tokens.ts +414 -0
  345. package/src/runtime/channel-approvals.ts +18 -5
  346. package/src/runtime/chrome-extension-registry.ts +332 -0
  347. package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
  348. package/src/runtime/guardian-decision-types.ts +7 -0
  349. package/src/runtime/http-server.ts +425 -70
  350. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
  351. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
  352. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
  353. package/src/runtime/migrations/migration-transport.ts +6 -0
  354. package/src/runtime/migrations/migration-wizard.ts +22 -2
  355. package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
  356. package/src/runtime/migrations/vbundle-builder.ts +145 -38
  357. package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
  358. package/src/runtime/migrations/vbundle-importer.ts +55 -5
  359. package/src/runtime/pending-interactions.ts +29 -13
  360. package/src/runtime/routes/approval-routes.ts +90 -16
  361. package/src/runtime/routes/browser-cdp-routes.ts +229 -0
  362. package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
  363. package/src/runtime/routes/conversation-analysis-routes.ts +18 -5
  364. package/src/runtime/routes/conversation-management-routes.ts +108 -0
  365. package/src/runtime/routes/conversation-routes.ts +308 -28
  366. package/src/runtime/routes/conversation-starter-routes.ts +78 -16
  367. package/src/runtime/routes/group-routes.ts +22 -8
  368. package/src/runtime/routes/guardian-action-routes.ts +24 -13
  369. package/src/runtime/routes/host-browser-routes.ts +279 -0
  370. package/src/runtime/routes/host-file-routes.ts +9 -1
  371. package/src/runtime/routes/identity-routes.ts +259 -16
  372. package/src/runtime/routes/log-export/AGENTS.md +104 -0
  373. package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
  374. package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
  375. package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
  376. package/src/runtime/routes/log-export-routes.ts +60 -25
  377. package/src/runtime/routes/memory-item-routes.ts +1 -7
  378. package/src/runtime/routes/migration-routes.ts +87 -2
  379. package/src/runtime/routes/oauth-apps.ts +15 -17
  380. package/src/runtime/routes/oauth-providers.ts +4 -0
  381. package/src/runtime/routes/schedule-routes.ts +24 -11
  382. package/src/runtime/routes/settings-routes.ts +9 -97
  383. package/src/runtime/routes/skills-routes.ts +52 -2
  384. package/src/runtime/routes/subagents-routes.ts +14 -10
  385. package/src/runtime/routes/usage-routes.ts +8 -7
  386. package/src/runtime/routes/workspace-routes.test.ts +22 -0
  387. package/src/runtime/routes/workspace-routes.ts +8 -1
  388. package/src/runtime/routes/workspace-utils.ts +2 -0
  389. package/src/schedule/scheduler.ts +7 -5
  390. package/src/security/ces-credential-client.ts +20 -0
  391. package/src/security/ces-rpc-credential-backend.ts +17 -0
  392. package/src/security/credential-backend.ts +5 -0
  393. package/src/security/oauth2.ts +42 -25
  394. package/src/security/secure-keys.ts +118 -25
  395. package/src/security/token-manager.ts +23 -10
  396. package/src/skills/catalog-files.ts +492 -0
  397. package/src/skills/inline-command-runner.ts +12 -14
  398. package/src/subagent/manager.ts +131 -26
  399. package/src/subagent/types.ts +19 -0
  400. package/src/tools/apps/executors.ts +11 -2
  401. package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
  402. package/src/tools/browser/auth-detector.ts +43 -12
  403. package/src/tools/browser/browser-execution.ts +645 -340
  404. package/src/tools/browser/browser-manager.ts +36 -12
  405. package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
  406. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
  407. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
  408. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
  409. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
  410. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
  411. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
  412. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
  413. package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
  414. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
  415. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
  416. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
  417. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
  418. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
  419. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
  420. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
  421. package/src/tools/browser/cdp-client/errors.ts +34 -0
  422. package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
  423. package/src/tools/browser/cdp-client/factory.ts +204 -0
  424. package/src/tools/browser/cdp-client/index.ts +14 -0
  425. package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
  426. package/src/tools/browser/cdp-client/types.ts +52 -0
  427. package/src/tools/filesystem/edit.ts +1 -1
  428. package/src/tools/filesystem/list.ts +1 -1
  429. package/src/tools/filesystem/read.ts +1 -1
  430. package/src/tools/filesystem/write.ts +2 -1
  431. package/src/tools/host-filesystem/edit.ts +1 -1
  432. package/src/tools/host-filesystem/read.ts +12 -15
  433. package/src/tools/host-filesystem/write.ts +1 -1
  434. package/src/tools/host-terminal/host-shell.ts +21 -16
  435. package/src/tools/permission-checker.ts +77 -100
  436. package/src/tools/registry.ts +0 -2
  437. package/src/tools/secret-detection-handler.ts +34 -1
  438. package/src/tools/shared/filesystem/image-read.ts +61 -40
  439. package/src/tools/skills/sandbox-runner.ts +3 -6
  440. package/src/tools/subagent/spawn.ts +47 -3
  441. package/src/tools/subagent/status.ts +2 -0
  442. package/src/tools/system/register.ts +2 -16
  443. package/src/tools/terminal/safe-env.ts +7 -0
  444. package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
  445. package/src/tools/terminal/sandbox.ts +4 -1
  446. package/src/tools/terminal/shell.ts +24 -21
  447. package/src/tools/tool-approval-handler.ts +48 -2
  448. package/src/tools/types.ts +2 -3
  449. package/src/util/platform.ts +14 -19
  450. package/src/watcher/provider-types.ts +1 -1
  451. package/src/workspace/migrations/029-seed-pkb.ts +1 -0
  452. package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
  453. package/src/workspace/migrations/registry.ts +2 -0
  454. package/src/workspace/top-level-renderer.ts +19 -1
  455. package/src/__tests__/chrome-cdp.test.ts +0 -419
  456. package/src/__tests__/permission-mode-sse.test.ts +0 -418
  457. package/src/__tests__/permission-mode-store.test.ts +0 -277
  458. package/src/browser-extension-relay/protocol.ts +0 -63
  459. package/src/browser-extension-relay/server.ts +0 -203
  460. package/src/config/schemas/sandbox.ts +0 -14
  461. package/src/permissions/permission-mode-store.ts +0 -180
  462. package/src/tools/browser/chrome-cdp.ts +0 -239
  463. package/src/tools/system/set-permission-mode.ts +0 -103
@@ -138,10 +138,11 @@ globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
138
138
  import { type OAuth2Config, startOAuth2Flow } from "../security/oauth2.js";
139
139
 
140
140
  const BASE_OAUTH_CONFIG: OAuth2Config = {
141
- authUrl: "https://provider.example.com/authorize",
142
- tokenUrl: "https://provider.example.com/token",
141
+ authorizeUrl: "https://provider.example.com/authorize",
142
+ tokenExchangeUrl: "https://provider.example.com/token",
143
143
  scopes: ["read", "write"],
144
144
  clientId: "test-client-id",
145
+ scopeSeparator: " ",
145
146
  };
146
147
 
147
148
  beforeEach(() => {
@@ -219,9 +220,9 @@ describe("OAuth2 gateway transport", () => {
219
220
  expect(capturedAuthUrl).toContain(encodeURIComponent("/oauth/callback"));
220
221
 
221
222
  // Extract the redirect_uri and simulate the callback
222
- const authUrl = new URL(capturedAuthUrl);
223
- const redirectUri = authUrl.searchParams.get("redirect_uri")!;
224
- const state = authUrl.searchParams.get("state")!;
223
+ const authorizeUrl = new URL(capturedAuthUrl);
224
+ const redirectUri = authorizeUrl.searchParams.get("redirect_uri")!;
225
+ const state = authorizeUrl.searchParams.get("state")!;
225
226
 
226
227
  // Make a request to the loopback server with the auth code
227
228
  const callbackUrl = `${redirectUri}?code=loopback-auth-code&state=${state}`;
@@ -282,9 +283,9 @@ describe("OAuth2 gateway transport", () => {
282
283
  expect(capturedAuthUrl).not.toContain("gw.example.com");
283
284
 
284
285
  // Simulate callback to loopback server
285
- const authUrl = new URL(capturedAuthUrl);
286
- const redirectUri = authUrl.searchParams.get("redirect_uri")!;
287
- const state = authUrl.searchParams.get("state")!;
286
+ const authorizeUrl = new URL(capturedAuthUrl);
287
+ const redirectUri = authorizeUrl.searchParams.get("redirect_uri")!;
288
+ const state = authorizeUrl.searchParams.get("state")!;
288
289
  await fetch(`${redirectUri}?code=explicit-loopback-code&state=${state}`);
289
290
 
290
291
  const result = await flowPromise;
@@ -405,9 +406,9 @@ describe("OAuth2 gateway transport", () => {
405
406
  expect(capturedAuthUrl).toContain("code_challenge=");
406
407
  expect(capturedAuthUrl).toContain("code_challenge_method=S256");
407
408
 
408
- const authUrl = new URL(capturedAuthUrl);
409
- const redirectUri = authUrl.searchParams.get("redirect_uri")!;
410
- const state = authUrl.searchParams.get("state")!;
409
+ const authorizeUrl = new URL(capturedAuthUrl);
410
+ const redirectUri = authorizeUrl.searchParams.get("redirect_uri")!;
411
+ const state = authorizeUrl.searchParams.get("state")!;
411
412
 
412
413
  const resp = await fetch(
413
414
  `${redirectUri}?code=loopback-code&state=${state}`,
@@ -440,9 +441,9 @@ describe("OAuth2 gateway transport", () => {
440
441
 
441
442
  await urlReadyPromise;
442
443
 
443
- const authUrl = new URL(capturedAuthUrl);
444
- const redirectUri = authUrl.searchParams.get("redirect_uri")!;
445
- const state = authUrl.searchParams.get("state")!;
444
+ const authorizeUrl = new URL(capturedAuthUrl);
445
+ const redirectUri = authorizeUrl.searchParams.get("redirect_uri")!;
446
+ const state = authorizeUrl.searchParams.get("state")!;
446
447
 
447
448
  // Fire callback without awaiting — immediately check flowPromise rejection
448
449
  fetch(`${redirectUri}?error=access_denied&state=${state}`).catch(
@@ -473,8 +474,8 @@ describe("OAuth2 gateway transport", () => {
473
474
 
474
475
  await urlReadyPromise;
475
476
 
476
- const authUrl = new URL(capturedAuthUrl);
477
- const redirectUri = authUrl.searchParams.get("redirect_uri")!;
477
+ const authorizeUrl = new URL(capturedAuthUrl);
478
+ const redirectUri = authorizeUrl.searchParams.get("redirect_uri")!;
478
479
 
479
480
  // Send callback with wrong state
480
481
  const resp = await fetch(
@@ -484,7 +485,7 @@ describe("OAuth2 gateway transport", () => {
484
485
 
485
486
  // The flow should still be waiting (not resolved)
486
487
  // Send the correct callback to clean up
487
- const state = authUrl.searchParams.get("state")!;
488
+ const state = authorizeUrl.searchParams.get("state")!;
488
489
  await fetch(`${redirectUri}?code=correct-code&state=${state}`);
489
490
 
490
491
  const result = await flowPromise;
@@ -516,9 +517,9 @@ describe("OAuth2 gateway transport", () => {
516
517
 
517
518
  await urlReadyPromise;
518
519
 
519
- const authUrl = new URL(capturedAuthUrl);
520
- const redirectUri = authUrl.searchParams.get("redirect_uri")!;
521
- const state = authUrl.searchParams.get("state")!;
520
+ const authorizeUrl = new URL(capturedAuthUrl);
521
+ const redirectUri = authorizeUrl.searchParams.get("redirect_uri")!;
522
+ const state = authorizeUrl.searchParams.get("state")!;
522
523
 
523
524
  // Fire callback without awaiting — immediately check flowPromise rejection
524
525
  fetch(`${redirectUri}?code=code-that-fails&state=${state}`).catch(
@@ -653,4 +654,194 @@ describe("OAuth2 gateway transport", () => {
653
654
  expect(lastTokenRequestBody!.has("client_secret")).toBe(false);
654
655
  });
655
656
  });
657
+
658
+ describe("scope separator", () => {
659
+ test("authorize URL joins scopes with space when scopeSeparator is ' '", async () => {
660
+ mockPublicBaseUrl = "https://gw.example.com";
661
+
662
+ let capturedAuthUrl = "";
663
+ const flowPromise = startOAuth2Flow(
664
+ BASE_OAUTH_CONFIG,
665
+ {
666
+ openUrl: (url) => {
667
+ capturedAuthUrl = url;
668
+ },
669
+ },
670
+ { callbackTransport: "gateway" },
671
+ );
672
+
673
+ await new Promise((r) => setTimeout(r, 10));
674
+
675
+ // URLSearchParams encodes spaces as '+' in query strings (application/x-www-form-urlencoded)
676
+ expect(capturedAuthUrl).toContain("scope=read+write");
677
+
678
+ const entries = Array.from(pendingCallbacks.entries());
679
+ entries[0][1].resolve("space-separator-code");
680
+ await flowPromise;
681
+ });
682
+
683
+ test("authorize URL joins scopes with comma when scopeSeparator is ','", async () => {
684
+ mockPublicBaseUrl = "https://gw.example.com";
685
+
686
+ const commaConfig: OAuth2Config = {
687
+ ...BASE_OAUTH_CONFIG,
688
+ scopeSeparator: ",",
689
+ };
690
+
691
+ let capturedAuthUrl = "";
692
+ const flowPromise = startOAuth2Flow(
693
+ commaConfig,
694
+ {
695
+ openUrl: (url) => {
696
+ capturedAuthUrl = url;
697
+ },
698
+ },
699
+ { callbackTransport: "gateway" },
700
+ );
701
+
702
+ await new Promise((r) => setTimeout(r, 10));
703
+
704
+ // Comma-encoded scopes
705
+ expect(capturedAuthUrl).toContain("scope=read%2Cwrite");
706
+
707
+ const entries = Array.from(pendingCallbacks.entries());
708
+ entries[0][1].resolve("comma-separator-code");
709
+ await flowPromise;
710
+ });
711
+
712
+ test("token response with comma-separated scope splits into individual scopes when scopeSeparator is ','", async () => {
713
+ mockPublicBaseUrl = "https://gw.example.com";
714
+ mockTokenResponse = {
715
+ ok: true,
716
+ status: 200,
717
+ body: {
718
+ access_token: "test-access-token",
719
+ refresh_token: "test-refresh-token",
720
+ expires_in: 3600,
721
+ scope: "read,write,issues:create",
722
+ token_type: "Bearer",
723
+ },
724
+ };
725
+
726
+ const commaConfig: OAuth2Config = {
727
+ ...BASE_OAUTH_CONFIG,
728
+ scopeSeparator: ",",
729
+ };
730
+
731
+ const flowPromise = startOAuth2Flow(
732
+ commaConfig,
733
+ { openUrl: () => {} },
734
+ { callbackTransport: "gateway" },
735
+ );
736
+
737
+ await new Promise((r) => setTimeout(r, 10));
738
+
739
+ const entries = Array.from(pendingCallbacks.entries());
740
+ entries[0][1].resolve("comma-token-code");
741
+
742
+ const result = await flowPromise;
743
+ expect(result.grantedScopes).toEqual(["read", "write", "issues:create"]);
744
+ });
745
+
746
+ test("token response with whitespace around comma separators is trimmed", async () => {
747
+ mockPublicBaseUrl = "https://gw.example.com";
748
+ mockTokenResponse = {
749
+ ok: true,
750
+ status: 200,
751
+ body: {
752
+ access_token: "test-access-token",
753
+ refresh_token: "test-refresh-token",
754
+ expires_in: 3600,
755
+ scope: " read , write ",
756
+ token_type: "Bearer",
757
+ },
758
+ };
759
+
760
+ const commaConfig: OAuth2Config = {
761
+ ...BASE_OAUTH_CONFIG,
762
+ scopeSeparator: ",",
763
+ };
764
+
765
+ const flowPromise = startOAuth2Flow(
766
+ commaConfig,
767
+ { openUrl: () => {} },
768
+ { callbackTransport: "gateway" },
769
+ );
770
+
771
+ await new Promise((r) => setTimeout(r, 10));
772
+
773
+ const entries = Array.from(pendingCallbacks.entries());
774
+ entries[0][1].resolve("comma-whitespace-code");
775
+
776
+ const result = await flowPromise;
777
+ expect(result.grantedScopes).toEqual(["read", "write"]);
778
+ });
779
+
780
+ test("default-space provider still parses comma-separated token response scopes (GitHub/Slack compat)", async () => {
781
+ // Providers like GitHub and Slack use space as their authorize-URL
782
+ // separator but return comma-separated scopes in token responses.
783
+ // The defensive split MUST tolerate that without requiring providers
784
+ // to opt into scopeSeparator: ",".
785
+ mockPublicBaseUrl = "https://gw.example.com";
786
+ mockTokenResponse = {
787
+ ok: true,
788
+ status: 200,
789
+ body: {
790
+ access_token: "test-access-token",
791
+ refresh_token: "test-refresh-token",
792
+ expires_in: 3600,
793
+ scope: "repo,read:user,notifications",
794
+ token_type: "Bearer",
795
+ },
796
+ };
797
+
798
+ // BASE_OAUTH_CONFIG uses the default " " separator.
799
+ const flowPromise = startOAuth2Flow(
800
+ BASE_OAUTH_CONFIG,
801
+ { openUrl: () => {} },
802
+ { callbackTransport: "gateway" },
803
+ );
804
+
805
+ await new Promise((r) => setTimeout(r, 10));
806
+
807
+ const entries = Array.from(pendingCallbacks.entries());
808
+ entries[0][1].resolve("github-style-code");
809
+
810
+ const result = await flowPromise;
811
+ expect(result.grantedScopes).toEqual([
812
+ "repo",
813
+ "read:user",
814
+ "notifications",
815
+ ]);
816
+ });
817
+
818
+ test("default-space provider parses space-separated token response scopes", async () => {
819
+ mockPublicBaseUrl = "https://gw.example.com";
820
+ mockTokenResponse = {
821
+ ok: true,
822
+ status: 200,
823
+ body: {
824
+ access_token: "test-access-token",
825
+ refresh_token: "test-refresh-token",
826
+ expires_in: 3600,
827
+ scope: "read write admin",
828
+ token_type: "Bearer",
829
+ },
830
+ };
831
+
832
+ const flowPromise = startOAuth2Flow(
833
+ BASE_OAUTH_CONFIG,
834
+ { openUrl: () => {} },
835
+ { callbackTransport: "gateway" },
836
+ );
837
+
838
+ await new Promise((r) => setTimeout(r, 10));
839
+
840
+ const entries = Array.from(pendingCallbacks.entries());
841
+ entries[0][1].resolve("space-token-code");
842
+
843
+ const result = await flowPromise;
844
+ expect(result.grantedScopes).toEqual(["read", "write", "admin"]);
845
+ });
846
+ });
656
847
  });
@@ -19,48 +19,17 @@ describe("onboarding template contracts", () => {
19
19
 
20
20
  test("contains identity discovery prompts", () => {
21
21
  const lower = bootstrap.toLowerCase();
22
- expect(lower).toContain("your name");
23
- expect(lower).toContain("personality");
22
+ expect(lower).toContain("identity");
23
+ expect(lower).toContain("infer");
24
24
  });
25
25
 
26
- test("leads with personality-first emotional arc", () => {
27
- const lower = bootstrap.toLowerCase();
28
- expect(lower).toContain("personality");
29
- expect(lower).toContain("vibe");
30
- // Personality arc should come before usefulness arc
31
- const personalityIdx = lower.indexOf("oh, this has personality");
32
- const usefulIdx = lower.indexOf("oh, this is useful");
33
- expect(personalityIdx).toBeGreaterThan(-1);
34
- expect(usefulIdx).toBeGreaterThan(-1);
35
- expect(personalityIdx).toBeLessThan(usefulIdx);
36
- });
37
-
38
- test("contains name selection with change-later instruction", () => {
39
- const lower = bootstrap.toLowerCase();
40
- expect(lower).toContain("what they want to call you");
41
- expect(lower).toContain("change it later");
42
- });
43
-
44
- test("name exchange happens before personality quiz", () => {
45
- const nameIdx = bootstrap.indexOf("Step 1: Name Exchange");
46
- const quizIdx = bootstrap.indexOf("Step 2: Personality Quiz");
47
- expect(nameIdx).toBeGreaterThan(-1);
48
- expect(quizIdx).toBeGreaterThan(-1);
49
- expect(nameIdx).toBeLessThan(quizIdx);
50
- });
51
-
52
- test("gathers user context: work role, hobbies, daily tools", () => {
26
+ test("gathers user context", () => {
53
27
  const lower = bootstrap.toLowerCase();
54
28
  expect(lower).toContain("work role");
55
- expect(lower).toContain("hobbies");
29
+ expect(lower).toContain("goals");
56
30
  expect(lower).toContain("tools");
57
31
  });
58
32
 
59
- test("references ui_show payloads from BOOTSTRAP-REFERENCE.md", () => {
60
- expect(bootstrap).toContain("ui_show");
61
- expect(bootstrap).toContain("BOOTSTRAP-REFERENCE.md");
62
- });
63
-
64
33
  test("contains wrapping-up criteria with deletion instructions", () => {
65
34
  const lower = bootstrap.toLowerCase();
66
35
  expect(lower).toContain("wrapping up");
@@ -70,15 +39,12 @@ describe("onboarding template contracts", () => {
70
39
 
71
40
  test("contains refusal policy", () => {
72
41
  const lower = bootstrap.toLowerCase();
73
- expect(lower).toContain("hard-required");
74
- expect(lower).toContain("best-effort");
75
42
  expect(lower).toContain("declined");
76
- expect(lower).toContain("not interrogation");
43
+ expect(lower).toContain("constraints");
77
44
  });
78
45
 
79
- test("defines resolved as provided, inferred, or declined", () => {
46
+ test("defines field states as inferred or declined", () => {
80
47
  const lower = bootstrap.toLowerCase();
81
- expect(lower).toContain("resolved");
82
48
  expect(lower).toContain("inferred");
83
49
  expect(lower).toContain("declined");
84
50
  });
@@ -91,6 +57,7 @@ describe("onboarding template contracts", () => {
91
57
  });
92
58
 
93
59
  test("includes budget constraint", () => {
60
+ expect(bootstrap).toContain("$2");
94
61
  expect(bootstrap).toContain("$5");
95
62
  });
96
63
 
@@ -98,29 +65,73 @@ describe("onboarding template contracts", () => {
98
65
  expect(bootstrap).toContain("new colleague");
99
66
  });
100
67
 
101
- test("instructs checking Connected Services for email task variant", () => {
102
- expect(bootstrap).toContain("Connected Services");
103
- expect(bootstrap).toContain("Connect my email");
104
- expect(bootstrap).toContain("Check my email");
68
+ test("contains numbered goals", () => {
69
+ const lower = bootstrap.toLowerCase();
70
+ expect(lower).toContain("establish mutual identity");
71
+ expect(lower).toContain("prove value fast");
72
+ expect(lower).toContain("infer, don't interrogate");
73
+ expect(lower).toContain("surface what you learned");
74
+ expect(lower).toContain("offer the next level");
75
+ expect(lower).toContain("write everything immediately");
76
+ expect(lower).toContain("clean up");
77
+ });
78
+
79
+ test("contains constraints section", () => {
80
+ expect(bootstrap).toContain("## Constraints");
81
+ expect(bootstrap).toContain("$2");
82
+ expect(bootstrap).toContain("2 questions");
83
+ expect(bootstrap.toLowerCase()).toContain("don't block on setup");
84
+ expect(bootstrap).toContain("One-shot");
105
85
  });
106
86
 
107
- test("includes daily briefing and channel suggestions in getting set up", () => {
87
+ test("contains 'what you own' section", () => {
108
88
  const lower = bootstrap.toLowerCase();
109
- expect(lower).toContain("daily briefing");
89
+ expect(lower).toContain("sequencing");
90
+ expect(lower).toContain("pacing");
91
+ });
92
+
93
+ test("contains technical contract", () => {
94
+ expect(bootstrap).toContain("Technical Contract");
95
+ expect(bootstrap).toContain("prescribed");
96
+ });
97
+
98
+ test("contains capability unlock pattern", () => {
99
+ const lower = bootstrap.toLowerCase();
100
+ expect(lower).toContain("email");
101
+ expect(lower).toContain("voice");
110
102
  expect(lower).toContain("slack");
111
- expect(lower).toContain("telegram");
112
103
  });
113
- });
114
104
 
115
- describe("BOOTSTRAP-REFERENCE.md", () => {
116
- test("contains personality form with 4 dropdowns", () => {
117
- expect(bootstrapRef).toContain('surface_type: "form"');
118
- expect(bootstrapRef).toContain("communication_style");
119
- expect(bootstrapRef).toContain("task_style");
120
- expect(bootstrapRef).toContain("humor");
121
- expect(bootstrapRef).toContain("depth");
105
+ test("contains tone guidance", () => {
106
+ expect(bootstrap).toContain("Not servile");
107
+ expect(bootstrap.toLowerCase()).toContain("match");
108
+ expect(bootstrap.toLowerCase()).toContain("energy");
122
109
  });
123
110
 
111
+ test("contains pre-chat onboarding context section", () => {
112
+ const lower = bootstrap.toLowerCase();
113
+ expect(lower).toContain("onboarding");
114
+ expect(lower).toContain("json");
115
+ expect(lower).toContain("context");
116
+ });
117
+
118
+ test("does not contain personality quiz references", () => {
119
+ // BOOTSTRAP.md says "No personality quiz" as part of goal 3,
120
+ // but should NOT contain instructions TO USE or SHOW a personality quiz
121
+ expect(bootstrap).not.toMatch(/show.*personality quiz/i);
122
+ expect(bootstrap).not.toMatch(/present.*personality quiz/i);
123
+ // "dropdown" only appears in "No dropdown forms" — that's a prohibition, not an instruction
124
+ expect(bootstrap).not.toMatch(/show.*dropdown/i);
125
+ });
126
+
127
+ test("does not contain rigid step sequence", () => {
128
+ expect(bootstrap).not.toMatch(/Step 1:/);
129
+ expect(bootstrap).not.toMatch(/Step 2:/);
130
+ expect(bootstrap).not.toMatch(/Step 3:/);
131
+ });
132
+ });
133
+
134
+ describe("BOOTSTRAP-REFERENCE.md", () => {
124
135
  test("contains email-not-connected task card variant", () => {
125
136
  expect(bootstrapRef).toContain("Email Not Connected");
126
137
  expect(bootstrapRef).toContain("Connect my email");
@@ -131,6 +142,14 @@ describe("onboarding template contracts", () => {
131
142
  expect(bootstrapRef).toContain("Email Already Connected");
132
143
  expect(bootstrapRef).toContain("Check my email");
133
144
  });
145
+
146
+ test("does not contain personality form", () => {
147
+ expect(bootstrapRef).not.toContain('surface_type: "form"');
148
+ expect(bootstrapRef).not.toContain("communication_style");
149
+ expect(bootstrapRef).not.toContain("task_style");
150
+ expect(bootstrapRef).not.toContain("humor");
151
+ expect(bootstrapRef).not.toContain("depth");
152
+ });
134
153
  });
135
154
 
136
155
  describe("IDENTITY.md", () => {
@@ -653,10 +653,10 @@ describe("OpenAIProvider", () => {
653
653
  [{ role: "user", content: [{ type: "text", text: "Hi" }] }],
654
654
  undefined,
655
655
  undefined,
656
- { config: { max_tokens: 32000 } },
656
+ { config: { max_tokens: 64000 } },
657
657
  );
658
658
 
659
- expect(lastCreateParams!.max_completion_tokens).toBe(32000);
659
+ expect(lastCreateParams!.max_completion_tokens).toBe(64000);
660
660
  });
661
661
 
662
662
  // -----------------------------------------------------------------------
@@ -15,7 +15,7 @@ const mockListMasterCategories = mock(() =>
15
15
  }),
16
16
  );
17
17
  const mockResolveOAuthConnection = mock(() =>
18
- Promise.resolve({ id: "conn-1", providerKey: "outlook" }),
18
+ Promise.resolve({ id: "conn-1", provider: "outlook" }),
19
19
  );
20
20
 
21
21
  mock.module("../messaging/providers/outlook/client.js", () => ({
@@ -25,7 +25,7 @@ function createMockConnection(
25
25
  ): OAuthConnection {
26
26
  return {
27
27
  id: "outlook-conn-1",
28
- providerKey: "outlook",
28
+ provider: "outlook",
29
29
  accountInfo: "test@outlook.com",
30
30
  request: mock(() =>
31
31
  Promise.resolve({ status, headers: {}, body: responseBody }),
@@ -56,7 +56,7 @@ const createForwardDraftMock = mock(
56
56
 
57
57
  const fakeConnection = {
58
58
  id: "conn-1",
59
- providerKey: "microsoft",
59
+ provider: "microsoft",
60
60
  accountInfo: "user@outlook.com",
61
61
  } as unknown as OAuthConnection;
62
62
 
@@ -40,7 +40,7 @@ mock.module("../messaging/providers/outlook/client.js", () => ({
40
40
  }));
41
41
 
42
42
  const mockResolveOAuthConnection =
43
- mock<(providerKey: string) => Promise<unknown>>();
43
+ mock<(provider: string) => Promise<unknown>>();
44
44
 
45
45
  mock.module("../oauth/connection-resolver.js", () => ({
46
46
  resolveOAuthConnection: mockResolveOAuthConnection,
@@ -24,7 +24,7 @@ const mockListMessages = mock(() =>
24
24
  }),
25
25
  );
26
26
  const mockResolveOAuthConnection = mock(() =>
27
- Promise.resolve({ id: "conn-1", providerKey: "outlook" }),
27
+ Promise.resolve({ id: "conn-1", provider: "outlook" }),
28
28
  );
29
29
 
30
30
  mock.module("../messaging/providers/outlook/client.js", () => ({
@@ -164,7 +164,7 @@ import {
164
164
  function createMockConnection(): OAuthConnection {
165
165
  return {
166
166
  id: "outlook-conn-1",
167
- providerKey: "outlook",
167
+ provider: "outlook",
168
168
  accountInfo: "test@outlook.com",
169
169
  request: mock(() =>
170
170
  Promise.resolve({ status: 200, headers: {}, body: {} }),
@@ -884,7 +884,7 @@ describe("Outlook client functions", () => {
884
884
  ): OAuthConnection {
885
885
  return {
886
886
  id: "outlook-conn-1",
887
- providerKey: "outlook",
887
+ provider: "outlook",
888
888
  accountInfo: "test@outlook.com",
889
889
  request: mock(() =>
890
890
  Promise.resolve({ status, headers: {}, body: responseBody }),
@@ -4,7 +4,7 @@ import { describe, expect, mock, test } from "bun:test";
4
4
 
5
5
  const mockTrashMessage = mock(() => Promise.resolve({}));
6
6
  const mockResolveOAuthConnection = mock(() =>
7
- Promise.resolve({ id: "conn-1", providerKey: "outlook" }),
7
+ Promise.resolve({ id: "conn-1", provider: "outlook" }),
8
8
  );
9
9
 
10
10
  mock.module("../messaging/providers/outlook/client.js", () => ({
@@ -57,7 +57,7 @@ const { run } =
57
57
 
58
58
  // ── Helpers ──────────────────────────────────────────────────────────────────
59
59
 
60
- const fakeConnection = { id: "outlook-conn-1", providerKey: "outlook" };
60
+ const fakeConnection = { id: "outlook-conn-1", provider: "outlook" };
61
61
 
62
62
  function makeContext(overrides: Partial<ToolContext> = {}): ToolContext {
63
63
  return {