@vellumai/assistant 0.6.3 → 0.6.4

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 (667) hide show
  1. package/ARCHITECTURE.md +273 -10
  2. package/Dockerfile +2 -3
  3. package/bun.lock +5 -13
  4. package/docs/backup-troubleshooting.md +52 -0
  5. package/docs/browser-use-architecture-phase2.md +174 -0
  6. package/docs/stt-provider-onboarding.md +120 -0
  7. package/knip.json +12 -2
  8. package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
  9. package/node_modules/@vellumai/ces-contracts/package.json +3 -3
  10. package/openapi.yaml +982 -72
  11. package/package.json +4 -6
  12. package/scripts/generate-openapi.ts +0 -1
  13. package/scripts/test.sh +73 -18
  14. package/src/__tests__/agent-image-optimize.test.ts +28 -0
  15. package/src/__tests__/agent-loop.test.ts +123 -0
  16. package/src/__tests__/anthropic-provider.test.ts +263 -10
  17. package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
  18. package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
  19. package/src/__tests__/browser-fill-credential.test.ts +11 -0
  20. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  21. package/src/__tests__/browser-skill-endstate.test.ts +31 -7
  22. package/src/__tests__/btw-routes.test.ts +7 -0
  23. package/src/__tests__/call-controller.test.ts +581 -20
  24. package/src/__tests__/catalog-files.test.ts +138 -0
  25. package/src/__tests__/channel-invite-transport.test.ts +2 -2
  26. package/src/__tests__/channel-readiness-routes.test.ts +16 -20
  27. package/src/__tests__/channel-readiness-service.test.ts +12 -7
  28. package/src/__tests__/checker.test.ts +157 -10
  29. package/src/__tests__/clawhub-files.test.ts +347 -0
  30. package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
  31. package/src/__tests__/config-analysis.test.ts +100 -0
  32. package/src/__tests__/config-schema.test.ts +1013 -66
  33. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
  34. package/src/__tests__/config-watcher.test.ts +43 -8
  35. package/src/__tests__/contact-store-user-file.test.ts +512 -0
  36. package/src/__tests__/contacts-write.test.ts +197 -0
  37. package/src/__tests__/context-window-manager.test.ts +88 -0
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  40. package/src/__tests__/conversation-agent-loop.test.ts +98 -2
  41. package/src/__tests__/conversation-confirmation-signals.test.ts +135 -0
  42. package/src/__tests__/conversation-error.test.ts +70 -0
  43. package/src/__tests__/conversation-history-web-search.test.ts +11 -4
  44. package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
  45. package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
  46. package/src/__tests__/conversation-list-source.test.ts +145 -0
  47. package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
  48. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  49. package/src/__tests__/conversation-queue.test.ts +901 -60
  50. package/src/__tests__/conversation-routes-disk-view.test.ts +270 -0
  51. package/src/__tests__/conversation-runtime-assembly.test.ts +55 -0
  52. package/src/__tests__/conversation-skill-tools.test.ts +7 -4
  53. package/src/__tests__/conversation-slash-commands.test.ts +33 -0
  54. package/src/__tests__/conversation-slash-queue.test.ts +89 -18
  55. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  56. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
  57. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  59. package/src/__tests__/credential-health-service.test.ts +352 -0
  60. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  61. package/src/__tests__/credential-vault-unit.test.ts +379 -3
  62. package/src/__tests__/credentials-cli.test.ts +40 -16
  63. package/src/__tests__/cross-provider-web-search.test.ts +146 -35
  64. package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
  65. package/src/__tests__/device-id.test.ts +112 -0
  66. package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
  67. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
  68. package/src/__tests__/email-html-renderer.test.ts +71 -0
  69. package/src/__tests__/email-invite-adapter.test.ts +36 -32
  70. package/src/__tests__/emit-event-signal.test.ts +71 -0
  71. package/src/__tests__/extension-id-sync-guard.test.ts +75 -8
  72. package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
  73. package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
  74. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  75. package/src/__tests__/gemini-provider.test.ts +64 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
  77. package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
  78. package/src/__tests__/gmail-archive-gate.test.ts +246 -0
  79. package/src/__tests__/gmail-preferences.test.ts +117 -0
  80. package/src/__tests__/headless-browser-interactions.test.ts +43 -0
  81. package/src/__tests__/headless-browser-mode.test.ts +614 -0
  82. package/src/__tests__/headless-browser-navigate.test.ts +142 -5
  83. package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
  84. package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
  85. package/src/__tests__/heartbeat-service.test.ts +70 -17
  86. package/src/__tests__/home-state-routes.test.ts +162 -0
  87. package/src/__tests__/host-bash-proxy.test.ts +0 -5
  88. package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
  89. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
  90. package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
  91. package/src/__tests__/host-cu-proxy.test.ts +0 -5
  92. package/src/__tests__/identity-intro-cache.test.ts +40 -10
  93. package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
  94. package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
  95. package/src/__tests__/llm-context-normalization.test.ts +488 -0
  96. package/src/__tests__/llm-context-route-provider.test.ts +86 -5
  97. package/src/__tests__/llm-usage-store.test.ts +363 -0
  98. package/src/__tests__/media-stream-output.test.ts +555 -0
  99. package/src/__tests__/media-stream-parser.test.ts +374 -0
  100. package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
  101. package/src/__tests__/media-stream-stt-session.test.ts +588 -0
  102. package/src/__tests__/media-turn-detector.test.ts +440 -0
  103. package/src/__tests__/message-queue.test.ts +125 -0
  104. package/src/__tests__/migration-export-http.test.ts +6 -6
  105. package/src/__tests__/migration-import-commit-http.test.ts +8 -6
  106. package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
  107. package/src/__tests__/migration-validate-http.test.ts +3 -3
  108. package/src/__tests__/mock-gateway-ipc.ts +151 -0
  109. package/src/__tests__/model-intents.test.ts +2 -2
  110. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  111. package/src/__tests__/oauth-cli.test.ts +2 -0
  112. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  113. package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
  114. package/src/__tests__/oauth-providers-routes.test.ts +2 -0
  115. package/src/__tests__/oauth-store.test.ts +85 -0
  116. package/src/__tests__/oauth2-gateway-transport.test.ts +249 -6
  117. package/src/__tests__/onboarding-template-contract.test.ts +6 -13
  118. package/src/__tests__/openai-provider.test.ts +176 -0
  119. package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
  120. package/src/__tests__/openai-responses-provider.test.ts +1105 -0
  121. package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
  122. package/src/__tests__/outlook-unsubscribe.test.ts +31 -2
  123. package/src/__tests__/persona-resolver.test.ts +251 -0
  124. package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
  125. package/src/__tests__/platform.test.ts +92 -1
  126. package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
  127. package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
  128. package/src/__tests__/pricing.test.ts +174 -0
  129. package/src/__tests__/qdrant-manager.test.ts +29 -8
  130. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
  131. package/src/__tests__/relationship-state-contract.test.ts +175 -0
  132. package/src/__tests__/relay-server.test.ts +423 -5
  133. package/src/__tests__/search-skills-unified.test.ts +118 -0
  134. package/src/__tests__/secret-scanner-executor.test.ts +4 -0
  135. package/src/__tests__/secure-keys.test.ts +107 -0
  136. package/src/__tests__/send-endpoint-busy.test.ts +5 -1
  137. package/src/__tests__/sequence-store.test.ts +1 -1
  138. package/src/__tests__/server-history-render.test.ts +49 -0
  139. package/src/__tests__/settings-routes.test.ts +201 -0
  140. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  141. package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
  142. package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
  143. package/src/__tests__/skills.test.ts +5 -2
  144. package/src/__tests__/skillssh-files.test.ts +446 -0
  145. package/src/__tests__/slack-block-formatting.test.ts +110 -0
  146. package/src/__tests__/slack-channel-config.test.ts +564 -1
  147. package/src/__tests__/stt-catalog-parity.test.ts +282 -0
  148. package/src/__tests__/stt-stream-session.test.ts +535 -0
  149. package/src/__tests__/system-prompt.test.ts +112 -26
  150. package/src/__tests__/telephony-stt-routing.test.ts +329 -0
  151. package/src/__tests__/terminal-tools.test.ts +18 -7
  152. package/src/__tests__/test-preload.ts +18 -0
  153. package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
  155. package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
  156. package/src/__tests__/tool-executor.test.ts +33 -24
  157. package/src/__tests__/tool-result-truncation.test.ts +36 -0
  158. package/src/__tests__/trust-store.test.ts +7 -1
  159. package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
  160. package/src/__tests__/tts-catalog-parity.test.ts +345 -0
  161. package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
  162. package/src/__tests__/twilio-routes.test.ts +376 -0
  163. package/src/__tests__/unicode.test.ts +293 -0
  164. package/src/__tests__/update-bulletin-format.test.ts +59 -0
  165. package/src/__tests__/update-bulletin.test.ts +206 -5
  166. package/src/__tests__/usage-routes.test.ts +25 -4
  167. package/src/__tests__/user-reference.test.ts +46 -61
  168. package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
  169. package/src/__tests__/voice-config-update.test.ts +403 -0
  170. package/src/__tests__/voice-quality.test.ts +434 -19
  171. package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
  172. package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
  173. package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
  174. package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
  175. package/src/__tests__/workspace-migration-meets.test.ts +244 -0
  176. package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
  177. package/src/__tests__/workspace-policy.test.ts +2 -0
  178. package/src/agent/image-optimize.ts +24 -12
  179. package/src/agent/loop.ts +43 -3
  180. package/src/backup/__tests__/backup-key.test.ts +152 -0
  181. package/src/backup/__tests__/backup-worker.test.ts +767 -0
  182. package/src/backup/__tests__/list-snapshots.test.ts +87 -0
  183. package/src/backup/__tests__/local-writer.test.ts +218 -0
  184. package/src/backup/__tests__/offsite-writer.test.ts +641 -0
  185. package/src/backup/__tests__/paths.test.ts +300 -0
  186. package/src/backup/__tests__/restore.test.ts +498 -0
  187. package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
  188. package/src/backup/__tests__/stream-crypt.test.ts +228 -0
  189. package/src/backup/backup-key.ts +137 -0
  190. package/src/backup/backup-worker.ts +459 -0
  191. package/src/backup/list-snapshots.ts +147 -0
  192. package/src/backup/local-writer.ts +133 -0
  193. package/src/backup/offsite-writer.ts +222 -0
  194. package/src/backup/paths.ts +226 -0
  195. package/src/backup/restore.ts +322 -0
  196. package/src/backup/snapshot-lock.ts +431 -0
  197. package/src/backup/stream-crypt.ts +263 -0
  198. package/src/bundler/package-resolver.ts +4 -0
  199. package/src/calls/audio-store.ts +11 -5
  200. package/src/calls/call-controller.ts +226 -71
  201. package/src/calls/call-domain.ts +9 -0
  202. package/src/calls/call-speech-output.ts +190 -0
  203. package/src/calls/call-transport.ts +77 -0
  204. package/src/calls/media-stream-audio-transcode.ts +173 -0
  205. package/src/calls/media-stream-output.ts +660 -0
  206. package/src/calls/media-stream-parser.ts +300 -0
  207. package/src/calls/media-stream-protocol.ts +166 -0
  208. package/src/calls/media-stream-server.ts +592 -0
  209. package/src/calls/media-stream-stt-session.ts +460 -0
  210. package/src/calls/media-turn-detector.ts +230 -0
  211. package/src/calls/relay-server.ts +90 -75
  212. package/src/calls/resolve-call-tts-provider.ts +136 -0
  213. package/src/calls/telephony-stt-routing.ts +145 -0
  214. package/src/calls/tts-call-strategy.ts +161 -0
  215. package/src/calls/tts-text-sanitizer.ts +32 -16
  216. package/src/calls/twilio-routes.ts +281 -17
  217. package/src/calls/voice-quality.ts +78 -35
  218. package/src/calls/voice-session-bridge.ts +8 -1
  219. package/src/channels/types.ts +16 -0
  220. package/src/cli/__tests__/run-assistant-command.ts +11 -1
  221. package/src/cli/commands/__tests__/backup.test.ts +1165 -0
  222. package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
  223. package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
  224. package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
  225. package/src/cli/commands/__tests__/email-download.test.ts +16 -1
  226. package/src/cli/commands/__tests__/email-list.test.ts +22 -4
  227. package/src/cli/commands/__tests__/email-register.test.ts +4 -4
  228. package/src/cli/commands/__tests__/email-send.test.ts +37 -4
  229. package/src/cli/commands/__tests__/email-status.test.ts +5 -1
  230. package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
  231. package/src/cli/commands/backup.ts +993 -0
  232. package/src/cli/commands/conversations.ts +77 -0
  233. package/src/cli/commands/credentials.ts +0 -1
  234. package/src/cli/commands/domain.ts +210 -0
  235. package/src/cli/commands/email.ts +255 -3
  236. package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
  237. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
  238. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
  239. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
  240. package/src/cli/commands/oauth/mode.ts +12 -3
  241. package/src/cli/commands/oauth/providers.ts +15 -0
  242. package/src/cli/commands/oauth/shared.ts +2 -1
  243. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -9
  244. package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
  245. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  246. package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
  247. package/src/cli/program.ts +30 -4
  248. package/src/config/__tests__/backup-schema.test.ts +134 -0
  249. package/src/config/assistant-feature-flags.ts +61 -62
  250. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +37 -1
  251. package/src/config/bundled-skills/browser/SKILL.md +30 -5
  252. package/src/config/bundled-skills/browser/TOOLS.json +123 -0
  253. package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
  254. package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
  255. package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
  256. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +2 -2
  258. package/src/config/bundled-skills/gmail/SKILL.md +53 -7
  259. package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
  260. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
  261. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
  262. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
  263. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
  264. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
  265. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
  266. package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
  267. package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
  268. package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
  269. package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
  270. package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
  271. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
  272. package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
  273. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
  274. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  275. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
  276. package/src/config/bundled-skills/outlook/SKILL.md +2 -2
  277. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
  278. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  279. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
  280. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  281. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  282. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
  283. package/src/config/bundled-skills/slack/SKILL.md +1 -0
  284. package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
  285. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
  286. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
  287. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
  288. package/src/config/bundled-tool-registry.ts +8 -0
  289. package/src/config/env-registry.ts +24 -0
  290. package/src/config/env.ts +34 -10
  291. package/src/config/feature-flag-registry.json +46 -14
  292. package/src/config/loader.ts +26 -12
  293. package/src/config/schema.ts +35 -10
  294. package/src/config/schemas/__tests__/stt.test.ts +43 -0
  295. package/src/config/schemas/analysis.ts +51 -0
  296. package/src/config/schemas/backup.ts +72 -0
  297. package/src/config/schemas/calls.ts +1 -26
  298. package/src/config/schemas/elevenlabs.ts +0 -59
  299. package/src/config/schemas/filing.ts +47 -7
  300. package/src/config/schemas/heartbeat.ts +27 -5
  301. package/src/config/schemas/host-browser.ts +47 -1
  302. package/src/config/schemas/inference.ts +1 -1
  303. package/src/config/schemas/memory-lifecycle.ts +14 -2
  304. package/src/config/schemas/services.ts +44 -0
  305. package/src/config/schemas/stt.ts +59 -0
  306. package/src/config/schemas/tts.ts +230 -0
  307. package/src/config/schemas/updates.ts +14 -0
  308. package/src/config/skills.ts +4 -0
  309. package/src/config/types.ts +4 -0
  310. package/src/contacts/contact-store.ts +56 -11
  311. package/src/contacts/contacts-write.ts +38 -1
  312. package/src/context/post-turn-tool-result-truncation.ts +3 -2
  313. package/src/context/tool-result-truncation.ts +2 -1
  314. package/src/context/window-manager.ts +45 -12
  315. package/src/credential-execution/executable-discovery.ts +12 -2
  316. package/src/credential-execution/process-manager.ts +33 -2
  317. package/src/credential-health/credential-health-service.ts +366 -0
  318. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
  319. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
  320. package/src/daemon/__tests__/conversation-tool-setup.test.ts +17 -8
  321. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
  322. package/src/daemon/config-watcher.ts +99 -5
  323. package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
  324. package/src/daemon/conversation-agent-loop.ts +101 -24
  325. package/src/daemon/conversation-error.ts +11 -0
  326. package/src/daemon/conversation-history.ts +40 -6
  327. package/src/daemon/conversation-launch.ts +220 -0
  328. package/src/daemon/conversation-lifecycle.ts +59 -9
  329. package/src/daemon/conversation-messaging.ts +37 -3
  330. package/src/daemon/conversation-notifiers.ts +5 -0
  331. package/src/daemon/conversation-process.ts +581 -19
  332. package/src/daemon/conversation-queue-manager.ts +24 -0
  333. package/src/daemon/conversation-runtime-assembly.ts +11 -1
  334. package/src/daemon/conversation-slash.ts +36 -0
  335. package/src/daemon/conversation-surfaces.ts +94 -4
  336. package/src/daemon/conversation-tool-setup.ts +25 -0
  337. package/src/daemon/conversation-usage.ts +7 -4
  338. package/src/daemon/conversation.ts +86 -28
  339. package/src/daemon/handlers/config-slack-channel.ts +269 -94
  340. package/src/daemon/handlers/conversations.ts +4 -1
  341. package/src/daemon/handlers/shared.ts +22 -0
  342. package/src/daemon/handlers/skills.ts +321 -77
  343. package/src/daemon/host-browser-proxy.ts +2 -1
  344. package/src/daemon/lifecycle.ts +122 -25
  345. package/src/daemon/message-protocol.ts +6 -0
  346. package/src/daemon/message-types/conversations.ts +34 -1
  347. package/src/daemon/message-types/home.ts +40 -0
  348. package/src/daemon/message-types/meet.ts +143 -0
  349. package/src/daemon/message-types/messages.ts +14 -0
  350. package/src/daemon/message-types/schedules.ts +34 -2
  351. package/src/daemon/message-types/skills.ts +16 -0
  352. package/src/daemon/message-types/surfaces.ts +2 -0
  353. package/src/daemon/server.ts +347 -2
  354. package/src/daemon/shutdown-handlers.ts +32 -4
  355. package/src/daemon/shutdown-registry.ts +40 -0
  356. package/src/daemon/tool-side-effects.ts +9 -0
  357. package/src/email/html-renderer.ts +76 -0
  358. package/src/heartbeat/heartbeat-service.ts +93 -7
  359. package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
  360. package/src/home/__tests__/emit-feed-event.test.ts +169 -0
  361. package/src/home/__tests__/feed-scheduler.test.ts +194 -0
  362. package/src/home/__tests__/feed-types.test.ts +275 -0
  363. package/src/home/__tests__/feed-writer.test.ts +688 -0
  364. package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
  365. package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
  366. package/src/home/__tests__/progress-formula.test.ts +213 -0
  367. package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
  368. package/src/home/__tests__/rollup-producer.test.ts +398 -0
  369. package/src/home/assistant-feed-authoring.ts +124 -0
  370. package/src/home/emit-feed-event.ts +158 -0
  371. package/src/home/feed-scheduler.ts +247 -0
  372. package/src/home/feed-types.ts +181 -0
  373. package/src/home/feed-writer.ts +469 -0
  374. package/src/home/platform-gmail-digest.ts +163 -0
  375. package/src/home/progress-formula.ts +86 -0
  376. package/src/home/relationship-state-writer.ts +824 -0
  377. package/src/home/relationship-state.ts +143 -0
  378. package/src/home/rollup-producer.ts +384 -0
  379. package/src/hooks/runner.ts +7 -0
  380. package/src/inbound/platform-callback-registration.ts +12 -3
  381. package/src/inbound/public-ingress-urls.ts +12 -0
  382. package/src/instrument.ts +1 -1
  383. package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
  384. package/src/ipc/cli-client.ts +151 -0
  385. package/src/ipc/cli-server.ts +234 -0
  386. package/src/ipc/gateway-client.ts +180 -0
  387. package/src/ipc/routes/index.ts +5 -0
  388. package/src/ipc/routes/wake-conversation.ts +19 -0
  389. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
  390. package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
  391. package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
  392. package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
  393. package/src/memory/app-store.ts +1 -1
  394. package/src/memory/attachments-store.ts +70 -0
  395. package/src/memory/auto-analysis-enqueue.ts +127 -0
  396. package/src/memory/auto-analysis-guard.ts +27 -0
  397. package/src/memory/cleanup-schedule-state.ts +37 -0
  398. package/src/memory/conversation-analyze-job.ts +73 -0
  399. package/src/memory/conversation-crud.ts +99 -0
  400. package/src/memory/conversation-disk-view.ts +7 -0
  401. package/src/memory/conversation-group-migration.ts +34 -2
  402. package/src/memory/conversation-queries.ts +6 -5
  403. package/src/memory/db-init.ts +6 -0
  404. package/src/memory/db-maintenance.ts +108 -0
  405. package/src/memory/db.ts +1 -0
  406. package/src/memory/graph/conversation-graph-memory.ts +15 -0
  407. package/src/memory/graph/extraction.test.ts +23 -0
  408. package/src/memory/graph/extraction.ts +8 -0
  409. package/src/memory/graph/retriever.ts +27 -18
  410. package/src/memory/graph/scoring.test.ts +186 -0
  411. package/src/memory/graph/scoring.ts +31 -1
  412. package/src/memory/graph/tools.ts +1 -1
  413. package/src/memory/group-crud.ts +6 -1
  414. package/src/memory/indexer.ts +95 -16
  415. package/src/memory/job-handlers/cleanup.ts +11 -8
  416. package/src/memory/job-handlers/conversation-starters.ts +16 -10
  417. package/src/memory/jobs-store.ts +64 -4
  418. package/src/memory/jobs-worker.ts +22 -9
  419. package/src/memory/llm-usage-store.ts +92 -56
  420. package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
  421. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
  422. package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
  423. package/src/memory/migrations/index.ts +6 -0
  424. package/src/memory/migrations/registry.ts +8 -0
  425. package/src/memory/qdrant-manager.ts +43 -16
  426. package/src/memory/schema/conversations.ts +2 -0
  427. package/src/memory/schema/oauth.ts +3 -0
  428. package/src/memory/usage-buckets.ts +396 -0
  429. package/src/messaging/providers/gmail/client.ts +57 -6
  430. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
  431. package/src/messaging/providers/slack/adapter.ts +143 -38
  432. package/src/messaging/providers/slack/client.ts +16 -0
  433. package/src/messaging/providers/slack/types.ts +4 -0
  434. package/src/notifications/decision-engine.ts +3 -3
  435. package/src/notifications/signal.ts +5 -0
  436. package/src/oauth/__tests__/identity-verifier.test.ts +1 -0
  437. package/src/oauth/byo-connection.test.ts +18 -1
  438. package/src/oauth/byo-connection.ts +3 -1
  439. package/src/oauth/connect-orchestrator.ts +2 -0
  440. package/src/oauth/connection-resolver.ts +6 -2
  441. package/src/oauth/connection.ts +2 -0
  442. package/src/oauth/oauth-store.ts +9 -0
  443. package/src/oauth/platform-connection.test.ts +98 -0
  444. package/src/oauth/platform-connection.ts +52 -31
  445. package/src/oauth/seed-providers.ts +7 -0
  446. package/src/permissions/checker.ts +16 -6
  447. package/src/permissions/defaults.ts +49 -1
  448. package/src/permissions/trust-store.ts +3 -3
  449. package/src/permissions/workspace-policy.ts +3 -0
  450. package/src/platform/client.test.ts +10 -0
  451. package/src/platform/sync-identity.ts +129 -0
  452. package/src/prompts/persona-resolver.ts +126 -2
  453. package/src/prompts/system-prompt.ts +59 -18
  454. package/src/prompts/templates/BOOTSTRAP.md +5 -5
  455. package/src/prompts/templates/SOUL.md +3 -1
  456. package/src/prompts/templates/UPDATES.md +12 -0
  457. package/src/prompts/templates/channels/slack.md +20 -0
  458. package/src/prompts/update-bulletin-format.ts +26 -9
  459. package/src/prompts/update-bulletin.ts +34 -23
  460. package/src/prompts/user-reference.ts +20 -17
  461. package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
  462. package/src/providers/anthropic/client.ts +157 -61
  463. package/src/providers/fireworks/client.ts +2 -2
  464. package/src/providers/gemini/client.ts +9 -1
  465. package/src/providers/model-catalog.ts +6 -0
  466. package/src/providers/model-intents.ts +4 -4
  467. package/src/providers/ollama/client.ts +2 -2
  468. package/src/providers/openai/chat-completions-provider.ts +474 -0
  469. package/src/providers/openai/client.ts +25 -440
  470. package/src/providers/openai/responses-provider.ts +502 -0
  471. package/src/providers/openrouter/client.ts +101 -4
  472. package/src/providers/provider-secret-catalog.ts +139 -0
  473. package/src/providers/registry.ts +2 -2
  474. package/src/providers/retry.ts +14 -3
  475. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
  476. package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
  477. package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
  478. package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
  479. package/src/providers/speech-to-text/deepgram.test.ts +332 -0
  480. package/src/providers/speech-to-text/deepgram.ts +115 -0
  481. package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
  482. package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
  483. package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
  484. package/src/providers/speech-to-text/google-gemini.ts +101 -0
  485. package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
  486. package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
  487. package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
  488. package/src/providers/speech-to-text/openai-whisper.ts +63 -33
  489. package/src/providers/speech-to-text/provider-catalog.ts +306 -0
  490. package/src/providers/speech-to-text/resolve.ts +386 -6
  491. package/src/providers/types.ts +9 -0
  492. package/src/runtime/AGENTS.md +43 -1
  493. package/src/runtime/__tests__/agent-wake.test.ts +831 -0
  494. package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
  495. package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
  496. package/src/runtime/agent-wake.ts +512 -0
  497. package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
  498. package/src/runtime/auth/route-policy.ts +30 -5
  499. package/src/runtime/auth/token-service.ts +56 -1
  500. package/src/runtime/btw-sidechain.ts +2 -0
  501. package/src/runtime/capability-tokens.ts +10 -10
  502. package/src/runtime/channel-invite-transport.ts +1 -1
  503. package/src/runtime/channel-invite-transports/email.ts +14 -6
  504. package/src/runtime/channel-readiness-service.ts +12 -22
  505. package/src/runtime/chrome-extension-registry.ts +38 -2
  506. package/src/runtime/http-server.ts +395 -10
  507. package/src/runtime/http-types.ts +6 -2
  508. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
  509. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
  510. package/src/runtime/migrations/migration-transport.ts +1 -0
  511. package/src/runtime/migrations/migration-wizard.ts +1 -0
  512. package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
  513. package/src/runtime/migrations/vbundle-importer.ts +34 -0
  514. package/src/runtime/pending-interactions.ts +0 -11
  515. package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
  516. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
  517. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
  518. package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
  519. package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
  520. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
  521. package/src/runtime/routes/app-management-routes.ts +12 -18
  522. package/src/runtime/routes/attachment-routes.test.ts +9 -3
  523. package/src/runtime/routes/attachment-routes.ts +216 -17
  524. package/src/runtime/routes/backup-routes.ts +519 -0
  525. package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
  526. package/src/runtime/routes/btw-routes.ts +8 -6
  527. package/src/runtime/routes/contact-routes.test.ts +298 -0
  528. package/src/runtime/routes/contact-routes.ts +132 -5
  529. package/src/runtime/routes/conversation-analysis-routes.ts +22 -142
  530. package/src/runtime/routes/conversation-management-routes.ts +115 -0
  531. package/src/runtime/routes/conversation-routes.ts +367 -146
  532. package/src/runtime/routes/filing-routes.ts +93 -0
  533. package/src/runtime/routes/home-feed-routes.ts +334 -0
  534. package/src/runtime/routes/home-state-routes.ts +138 -0
  535. package/src/runtime/routes/host-browser-routes.ts +3 -14
  536. package/src/runtime/routes/identity-intro-cache.ts +7 -3
  537. package/src/runtime/routes/identity-routes.ts +3 -17
  538. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
  539. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
  540. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
  541. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
  542. package/src/runtime/routes/integrations/slack/channel.ts +11 -3
  543. package/src/runtime/routes/integrations/slack/share.ts +45 -7
  544. package/src/runtime/routes/llm-context-normalization.ts +303 -0
  545. package/src/runtime/routes/memory-item-routes.test.ts +3 -2
  546. package/src/runtime/routes/migration-routes.ts +40 -5
  547. package/src/runtime/routes/settings-routes.ts +22 -5
  548. package/src/runtime/routes/skills-routes.ts +76 -7
  549. package/src/runtime/routes/stt-routes.ts +233 -0
  550. package/src/runtime/routes/surface-action-routes.ts +41 -2
  551. package/src/runtime/routes/tts-routes.ts +108 -24
  552. package/src/runtime/routes/usage-routes.ts +30 -2
  553. package/src/runtime/routes/user-route-dispatcher.ts +50 -5
  554. package/src/runtime/routes/user-routes.ts +13 -1
  555. package/src/runtime/routes/work-items-routes.ts +8 -1
  556. package/src/runtime/runtime-mode.ts +33 -0
  557. package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
  558. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
  559. package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
  560. package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
  561. package/src/runtime/services/analyze-conversation.ts +344 -0
  562. package/src/runtime/services/analyze-deps-singleton.ts +32 -0
  563. package/src/runtime/services/auto-analysis-prompt.ts +55 -0
  564. package/src/runtime/skill-route-registry.ts +49 -0
  565. package/src/runtime/slack-block-formatting.ts +437 -10
  566. package/src/schedule/scheduler.ts +50 -0
  567. package/src/security/oauth2.ts +26 -4
  568. package/src/security/secure-keys.ts +25 -2
  569. package/src/security/token-manager.ts +8 -0
  570. package/src/sequence/engine.ts +23 -0
  571. package/src/sequence/types.ts +1 -1
  572. package/src/skills/catalog-files.ts +64 -2
  573. package/src/skills/category-inference.ts +122 -0
  574. package/src/skills/clawhub-files.ts +213 -0
  575. package/src/skills/clawhub.ts +84 -23
  576. package/src/skills/skill-file-provider.ts +40 -0
  577. package/src/skills/skillssh-files.ts +395 -0
  578. package/src/skills/skillssh-registry.ts +4 -4
  579. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
  580. package/src/stt/__tests__/types.test.ts +89 -0
  581. package/src/stt/daemon-batch-transcriber.ts +195 -0
  582. package/src/stt/stt-stream-session.ts +499 -0
  583. package/src/stt/types.ts +330 -0
  584. package/src/stt/wav-encoder.test.ts +373 -0
  585. package/src/stt/wav-encoder.ts +175 -0
  586. package/src/subagent/manager.ts +38 -14
  587. package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
  588. package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
  589. package/src/tools/browser/browser-execution.ts +1163 -23
  590. package/src/tools/browser/browser-manager.ts +45 -0
  591. package/src/tools/browser/browser-mode-constants.ts +12 -0
  592. package/src/tools/browser/browser-mode.ts +92 -0
  593. package/src/tools/browser/browser-status-constants.ts +33 -0
  594. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +393 -0
  595. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
  596. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
  597. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
  598. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +183 -17
  599. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
  600. package/src/tools/browser/cdp-client/errors.ts +15 -0
  601. package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
  602. package/src/tools/browser/cdp-client/factory.ts +797 -87
  603. package/src/tools/browser/cdp-client/index.ts +16 -2
  604. package/src/tools/browser/cdp-client/types.ts +68 -0
  605. package/src/tools/credentials/vault.ts +35 -6
  606. package/src/tools/network/web-fetch.ts +5 -2
  607. package/src/tools/network/web-search.ts +5 -2
  608. package/src/tools/shared/shell-output.ts +3 -1
  609. package/src/tools/side-effects.ts +2 -0
  610. package/src/tools/skills/sandbox-runner.ts +3 -2
  611. package/src/tools/terminal/safe-env.ts +10 -2
  612. package/src/tools/terminal/shell.ts +15 -4
  613. package/src/tools/tool-manifest.ts +21 -0
  614. package/src/tools/types.ts +17 -0
  615. package/src/tools/ui-surface/definitions.ts +6 -1
  616. package/src/tts/__tests__/provider-adapters.test.ts +834 -0
  617. package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
  618. package/src/tts/__tests__/provider-catalog.test.ts +183 -0
  619. package/src/tts/__tests__/provider-registry.test.ts +90 -0
  620. package/src/tts/provider-catalog.ts +201 -0
  621. package/src/tts/provider-registry.ts +73 -0
  622. package/src/tts/providers/deepgram-provider.ts +219 -0
  623. package/src/tts/providers/elevenlabs-provider.ts +211 -0
  624. package/src/tts/providers/fish-audio-provider.ts +183 -0
  625. package/src/tts/providers/index.ts +42 -0
  626. package/src/tts/providers/register-builtins.ts +130 -0
  627. package/src/tts/synthesize-text.ts +110 -0
  628. package/src/tts/tts-config-resolver.ts +78 -0
  629. package/src/tts/types.ts +153 -0
  630. package/src/types/onboarding-context.ts +7 -0
  631. package/src/util/abort-reasons.ts +58 -0
  632. package/src/util/device-id.ts +32 -16
  633. package/src/util/errors.ts +9 -1
  634. package/src/util/platform.ts +54 -10
  635. package/src/util/pricing.ts +66 -3
  636. package/src/util/spawn.ts +1 -1
  637. package/src/util/truncate.ts +4 -2
  638. package/src/util/unicode.ts +201 -0
  639. package/src/version.ts +19 -24
  640. package/src/watcher/engine.ts +23 -0
  641. package/src/watcher/watcher-store.ts +31 -0
  642. package/src/workspace/migrations/003-seed-device-id.ts +9 -3
  643. package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
  644. package/src/workspace/migrations/029-seed-pkb.ts +1 -1
  645. package/src/workspace/migrations/031-drop-user-md.ts +317 -0
  646. package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
  647. package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
  648. package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
  649. package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
  650. package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
  651. package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
  652. package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
  653. package/src/workspace/migrations/registry.ts +16 -0
  654. package/src/workspace/top-level-renderer.ts +13 -1
  655. package/src/workspace/turn-commit.ts +31 -0
  656. package/src/__tests__/email-cli.test.ts +0 -297
  657. package/src/__tests__/email-service-config-fallback.test.ts +0 -102
  658. package/src/cli/commands/browser-relay.ts +0 -466
  659. package/src/email/guardrails.ts +0 -221
  660. package/src/email/provider.ts +0 -117
  661. package/src/email/providers/agentmail.ts +0 -361
  662. package/src/email/providers/index.ts +0 -65
  663. package/src/email/service.ts +0 -384
  664. package/src/email/types.ts +0 -126
  665. package/src/prompts/templates/USER.md +0 -13
  666. package/src/providers/speech-to-text/types.ts +0 -17
  667. package/src/runtime/routes/browser-cdp-routes.ts +0 -229
@@ -1,21 +1,24 @@
1
1
  /**
2
- * Tests for `getSkillFiles` catalog fallback.
2
+ * Tests for `getSkillFiles` provider chain fallback.
3
3
  *
4
4
  * When a skill id isn't resolvable via `findSkillById` (i.e. not installed
5
5
  * locally, not bundled, not a managed skill), `getSkillFiles` falls back to
6
- * the Vellum catalog via `readCatalogSkillFiles`. Catalog fallback entries
7
- * carry `content: null` because the catalog-files helper defers content
8
- * fetching to a follow-up per-file endpoint. When a skill IS resolved by
6
+ * the provider chain (vellum catalog skills.sh clawhub). Each provider
7
+ * is tried in order until one returns data. When a skill IS resolved by
9
8
  * `findSkillById` but its on-disk directory is missing, `getSkillFiles`
10
- * returns a 404 without falling through to the catalog so the listing and
11
- * detail responses agree on `isInstalled`.
9
+ * returns a 404 without falling through to the provider chain so the
10
+ * listing and detail responses agree on `isInstalled`.
12
11
  *
13
12
  * Coverage:
14
13
  * - Uninstalled catalog skill: returns `{ skill: catalog/vellum/available, files }` with `content: null` for every entry.
15
- * - Neither installed nor in catalog: returns 404.
14
+ * - Neither installed nor handled by any provider: returns 404.
16
15
  * - Installed skill: preserves the disk-read behavior with inline `content`.
17
- * - Installed skill with missing directory: returns 404 without consulting the catalog.
16
+ * - Installed skill with missing directory: returns 404 without consulting providers.
18
17
  * - `catalogSkillToSlim` mapping: `metadata.vellum["display-name"]` wins over `cs.name`.
18
+ * - skills.sh-shaped ID not in vellum catalog returns files from skills.sh provider.
19
+ * - clawhub-shaped ID not in vellum catalog returns files from clawhub provider.
20
+ * - ID that no provider handles returns 404.
21
+ * - Provider priority: vellum provider is tried before skills.sh/clawhub.
19
22
  */
20
23
 
21
24
  import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
@@ -24,8 +27,9 @@ import { join } from "node:path";
24
27
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
25
28
 
26
29
  import type { SkillSummary } from "../config/skills.js";
30
+ import type { SlimSkillResponse } from "../daemon/message-types/skills.js";
27
31
  import type { SkillFileEntry } from "../skills/catalog-files.js";
28
- import type { CatalogSkill } from "../skills/catalog-install.js";
32
+ import type { SkillFileProvider } from "../skills/skill-file-provider.js";
29
33
 
30
34
  // ---------------------------------------------------------------------------
31
35
  // Mock state — mutated by individual tests via reset helpers below
@@ -37,9 +41,45 @@ type ResolvedSkillEntry = {
37
41
  };
38
42
 
39
43
  let mockResolvedStates: ResolvedSkillEntry[] = [];
40
- let mockCatalog: CatalogSkill[] = [];
41
- let mockCatalogFiles: SkillFileEntry[] | null = null;
42
- const catalogFilesCalls: string[] = [];
44
+
45
+ // Per-provider mock state
46
+ let mockVellumProvider: SkillFileProvider;
47
+ let mockSkillsshProvider: SkillFileProvider;
48
+ let mockClawhubProvider: SkillFileProvider;
49
+
50
+ // Track which providers were consulted
51
+ const providerCalls: Array<{
52
+ provider: string;
53
+ method: string;
54
+ skillId: string;
55
+ }> = [];
56
+
57
+ function makeNoopProvider(name: string): SkillFileProvider {
58
+ return {
59
+ canHandle(_skillId: string): boolean {
60
+ return false;
61
+ },
62
+ async listFiles(skillId: string): Promise<SkillFileEntry[] | null> {
63
+ providerCalls.push({ provider: name, method: "listFiles", skillId });
64
+ return null;
65
+ },
66
+ async readFileContent(
67
+ skillId: string,
68
+ _path: string,
69
+ ): Promise<SkillFileEntry | null> {
70
+ providerCalls.push({
71
+ provider: name,
72
+ method: "readFileContent",
73
+ skillId,
74
+ });
75
+ return null;
76
+ },
77
+ async toSlimSkill(skillId: string): Promise<SlimSkillResponse | null> {
78
+ providerCalls.push({ provider: name, method: "toSlimSkill", skillId });
79
+ return null;
80
+ },
81
+ };
82
+ }
43
83
 
44
84
  // ---------------------------------------------------------------------------
45
85
  // Module mocks — must be declared before importing the module under test
@@ -77,16 +117,51 @@ mock.module("../skills/install-meta.js", () => ({
77
117
  }));
78
118
 
79
119
  mock.module("../skills/catalog-cache.js", () => ({
80
- getCatalog: async () => mockCatalog,
120
+ getCatalog: async () => [],
81
121
  }));
82
122
 
123
+ // The provider factory functions are called once at module init and the
124
+ // returned objects are captured in the `fileProviders` array. To allow
125
+ // per-test mock reassignment, return proxy objects that delegate every
126
+ // method call to the CURRENT value of the mutable mock variable.
83
127
  mock.module("../skills/catalog-files.js", () => ({
84
- readCatalogSkillFiles: async (skillId: string) => {
85
- catalogFilesCalls.push(skillId);
86
- return mockCatalogFiles;
87
- },
128
+ catalogSkillToSlim: () => ({}),
129
+ createVellumCatalogProvider: () => ({
130
+ canHandle: (id: string) => mockVellumProvider.canHandle(id),
131
+ listFiles: (id: string) => mockVellumProvider.listFiles(id),
132
+ readFileContent: (id: string, p: string) =>
133
+ mockVellumProvider.readFileContent(id, p),
134
+ toSlimSkill: (id: string) => mockVellumProvider.toSlimSkill(id),
135
+ }),
136
+ hasHiddenOrSkippedSegment: () => false,
137
+ readCatalogSkillFiles: async () => null,
138
+ readCatalogSkillFileContent: async () => null,
139
+ sanitizeRelativePath: (p: string) => p,
140
+ SKIP_DIRS: new Set(["node_modules", "__pycache__", ".git"]),
141
+ }));
142
+
143
+ mock.module("../skills/skillssh-files.js", () => ({
144
+ createSkillsShProvider: () => ({
145
+ canHandle: (id: string) => mockSkillsshProvider.canHandle(id),
146
+ listFiles: (id: string) => mockSkillsshProvider.listFiles(id),
147
+ readFileContent: (id: string, p: string) =>
148
+ mockSkillsshProvider.readFileContent(id, p),
149
+ toSlimSkill: (id: string) => mockSkillsshProvider.toSlimSkill(id),
150
+ }),
151
+ }));
152
+
153
+ mock.module("../skills/clawhub-files.js", () => ({
154
+ createClawhubProvider: () => ({
155
+ canHandle: (id: string) => mockClawhubProvider.canHandle(id),
156
+ listFiles: (id: string) => mockClawhubProvider.listFiles(id),
157
+ readFileContent: (id: string, p: string) =>
158
+ mockClawhubProvider.readFileContent(id, p),
159
+ toSlimSkill: (id: string) => mockClawhubProvider.toSlimSkill(id),
160
+ }),
88
161
  }));
89
162
 
163
+ mock.module("../skills/skill-file-provider.js", () => ({}));
164
+
90
165
  mock.module("../skills/catalog-install.js", () => ({
91
166
  installSkillLocally: async () => {},
92
167
  upsertSkillsIndex: () => {},
@@ -154,7 +229,10 @@ mock.module("../daemon/handlers/shared.js", () => ({
154
229
  // Import after mocks
155
230
  // ---------------------------------------------------------------------------
156
231
 
157
- import { getSkillFiles } from "../daemon/handlers/skills.js";
232
+ import {
233
+ _resetFileProvidersForTest,
234
+ getSkillFiles,
235
+ } from "../daemon/handlers/skills.js";
158
236
 
159
237
  // ---------------------------------------------------------------------------
160
238
  // Helpers
@@ -194,25 +272,19 @@ function makeSummary(overrides: Partial<SkillSummary>): SkillSummary {
194
272
  // Tests
195
273
  // ---------------------------------------------------------------------------
196
274
 
197
- describe("getSkillFiles — catalog fallback", () => {
275
+ describe("getSkillFiles — provider chain fallback", () => {
198
276
  beforeEach(() => {
199
277
  mockResolvedStates = [];
200
- mockCatalog = [];
201
- mockCatalogFiles = null;
202
- catalogFilesCalls.length = 0;
278
+ providerCalls.length = 0;
279
+ mockVellumProvider = makeNoopProvider("vellum");
280
+ mockSkillsshProvider = makeNoopProvider("skillssh");
281
+ mockClawhubProvider = makeNoopProvider("clawhub");
282
+ // Force provider chain re-creation from the (mocked) factory functions
283
+ _resetFileProvidersForTest();
203
284
  });
204
285
 
205
- test("returns catalog skill with files (content: null) when skill is uninstalled but present in catalog", async () => {
206
- mockCatalog = [
207
- {
208
- id: "acme-seo",
209
- name: "acme-seo",
210
- description: "SEO helper",
211
- emoji: "\u{1F50D}",
212
- metadata: { vellum: { "display-name": "Acme SEO" } },
213
- },
214
- ];
215
- mockCatalogFiles = [
286
+ test("returns catalog skill with files (content: null) when skill is uninstalled but present in vellum catalog", async () => {
287
+ const mockFiles: SkillFileEntry[] = [
216
288
  {
217
289
  path: "SKILL.md",
218
290
  name: "SKILL.md",
@@ -231,6 +303,21 @@ describe("getSkillFiles — catalog fallback", () => {
231
303
  },
232
304
  ];
233
305
 
306
+ mockVellumProvider = {
307
+ canHandle: () => true,
308
+ listFiles: async () => mockFiles,
309
+ readFileContent: async () => null,
310
+ toSlimSkill: async () => ({
311
+ id: "acme-seo",
312
+ name: "Acme SEO",
313
+ description: "SEO helper",
314
+ emoji: "\u{1F50D}",
315
+ kind: "catalog",
316
+ origin: "vellum",
317
+ status: "available",
318
+ }),
319
+ };
320
+
234
321
  const result = await getSkillFiles("acme-seo", dummyCtx);
235
322
 
236
323
  expect("error" in result).toBe(false);
@@ -249,20 +336,17 @@ describe("getSkillFiles — catalog fallback", () => {
249
336
  for (const entry of result.files) {
250
337
  expect(entry.content).toBeNull();
251
338
  }
252
- // Files should be sorted by path via localeCompare (not codepoint) —
253
- // so "assets/logo.png" sorts before "SKILL.md" under default collation.
339
+ // Files should be sorted by path via localeCompare
254
340
  expect(result.files.map((f) => f.path)).toEqual(
255
341
  [...result.files.map((f) => f.path)].sort((a, b) => a.localeCompare(b)),
256
342
  );
257
343
  expect(new Set(result.files.map((f) => f.path))).toEqual(
258
344
  new Set(["SKILL.md", "assets/logo.png"]),
259
345
  );
260
- expect(catalogFilesCalls).toEqual(["acme-seo"]);
261
346
  });
262
347
 
263
- test("returns 404 when skill is neither installed nor in the catalog", async () => {
348
+ test("returns 404 when skill is neither installed nor handled by any provider", async () => {
264
349
  mockResolvedStates = [];
265
- mockCatalog = [];
266
350
 
267
351
  const result = await getSkillFiles("ghost-skill", dummyCtx);
268
352
 
@@ -270,18 +354,15 @@ describe("getSkillFiles — catalog fallback", () => {
270
354
  if (!("error" in result)) return;
271
355
  expect(result.status).toBe(404);
272
356
  expect(result.error).toContain("ghost-skill");
273
- expect(catalogFilesCalls).toEqual([]);
274
357
  });
275
358
 
276
- test("returns 404 when skill is in catalog but readCatalogSkillFiles returns null", async () => {
277
- mockCatalog = [
278
- {
279
- id: "broken-skill",
280
- name: "broken-skill",
281
- description: "",
282
- },
283
- ];
284
- mockCatalogFiles = null;
359
+ test("returns 404 with 'files unavailable' when vellum provider canHandle returns true but listFiles returns null", async () => {
360
+ mockVellumProvider = {
361
+ canHandle: () => true,
362
+ listFiles: async () => null,
363
+ readFileContent: async () => null,
364
+ toSlimSkill: async () => null,
365
+ };
285
366
 
286
367
  const result = await getSkillFiles("broken-skill", dummyCtx);
287
368
 
@@ -289,9 +370,10 @@ describe("getSkillFiles — catalog fallback", () => {
289
370
  if (!("error" in result)) return;
290
371
  expect(result.status).toBe(404);
291
372
  expect(result.error).toContain("broken-skill");
373
+ expect(result.error).toContain("unavailable");
292
374
  });
293
375
 
294
- test("installed skill returns inline disk content (no catalog call)", async () => {
376
+ test("installed skill returns inline disk content (no provider fallback)", async () => {
295
377
  // Create a real temp directory for the installed-skill path to read.
296
378
  const workspaceRoot = mkdtempSync(
297
379
  join(tmpdir(), "vellum-skill-files-test-"),
@@ -327,9 +409,6 @@ describe("getSkillFiles — catalog fallback", () => {
327
409
  expect("error" in result).toBe(false);
328
410
  if ("error" in result) return;
329
411
 
330
- // Catalog fallback should NOT have been consulted for an installed skill.
331
- expect(catalogFilesCalls).toEqual([]);
332
-
333
412
  expect(result.files).toHaveLength(2);
334
413
  const skillMd = result.files.find((f) => f.path === "SKILL.md");
335
414
  const notes = result.files.find((f) => f.path === "notes.txt");
@@ -349,14 +428,7 @@ describe("getSkillFiles — catalog fallback", () => {
349
428
  }
350
429
  });
351
430
 
352
- test("returns 404 without catalog fallback when installed skill directory is missing on disk", async () => {
353
- // `findSkillById` resolves the skill (resolver lists it as installed)
354
- // but the on-disk directoryPath does not exist — simulates a corrupted
355
- // install, mid-delete race, or external unmount. The handler must
356
- // return 404 so the listing response (`kind: "installed"`) and the
357
- // detail response stay consistent; falling through to the catalog
358
- // would flip the detail to `kind: "catalog"` and break the
359
- // client-side `isInstalled` contract.
431
+ test("returns 404 without provider fallback when installed skill directory is missing on disk", async () => {
360
432
  mockResolvedStates = [
361
433
  {
362
434
  summary: makeSummary({
@@ -370,26 +442,30 @@ describe("getSkillFiles — catalog fallback", () => {
370
442
  state: "enabled",
371
443
  },
372
444
  ];
373
- // Even if the same id is present in the catalog, the handler must NOT
374
- // fall through — return 404 instead to avoid masking the missing
375
- // install directory with a catalog response.
376
- mockCatalog = [
377
- {
445
+ // Even if a provider would handle this id, the handler must NOT
446
+ // fall through — return 404 instead.
447
+ mockVellumProvider = {
448
+ canHandle: () => true,
449
+ listFiles: async () => [
450
+ {
451
+ path: "SKILL.md",
452
+ name: "SKILL.md",
453
+ size: 10,
454
+ mimeType: "",
455
+ isBinary: false,
456
+ content: null,
457
+ },
458
+ ],
459
+ readFileContent: async () => null,
460
+ toSlimSkill: async () => ({
378
461
  id: "ghost-installed",
379
- name: "ghost-installed",
380
- description: "Also present in catalog",
381
- },
382
- ];
383
- mockCatalogFiles = [
384
- {
385
- path: "SKILL.md",
386
- name: "SKILL.md",
387
- size: 10,
388
- mimeType: "",
389
- isBinary: false,
390
- content: null,
391
- },
392
- ];
462
+ name: "Ghost",
463
+ description: "",
464
+ kind: "catalog",
465
+ origin: "vellum",
466
+ status: "available",
467
+ }),
468
+ };
393
469
 
394
470
  const result = await getSkillFiles("ghost-installed", dummyCtx);
395
471
 
@@ -398,19 +474,22 @@ describe("getSkillFiles — catalog fallback", () => {
398
474
  expect(result.status).toBe(404);
399
475
  expect(result.error).toContain("ghost-installed");
400
476
  expect(result.error).toContain("directory missing");
401
- // Catalog fallback must not have been consulted.
402
- expect(catalogFilesCalls).toEqual([]);
403
477
  });
404
478
 
405
479
  test("catalogSkillToSlim falls back to cs.name when metadata.vellum.display-name is absent", async () => {
406
- mockCatalog = [
407
- {
480
+ mockVellumProvider = {
481
+ canHandle: () => true,
482
+ listFiles: async () => [],
483
+ readFileContent: async () => null,
484
+ toSlimSkill: async () => ({
408
485
  id: "plain-skill",
409
486
  name: "plain-skill",
410
487
  description: "Minimal",
411
- },
412
- ];
413
- mockCatalogFiles = [];
488
+ kind: "catalog",
489
+ origin: "vellum",
490
+ status: "available",
491
+ }),
492
+ };
414
493
 
415
494
  const result = await getSkillFiles("plain-skill", dummyCtx);
416
495
 
@@ -423,15 +502,19 @@ describe("getSkillFiles — catalog fallback", () => {
423
502
  });
424
503
 
425
504
  test("catalogSkillToSlim prefers metadata.vellum.display-name over cs.name", async () => {
426
- mockCatalog = [
427
- {
505
+ mockVellumProvider = {
506
+ canHandle: () => true,
507
+ listFiles: async () => [],
508
+ readFileContent: async () => null,
509
+ toSlimSkill: async () => ({
428
510
  id: "fancy-skill",
429
- name: "raw-fancy-name",
511
+ name: "Pretty Fancy Name",
430
512
  description: "",
431
- metadata: { vellum: { "display-name": "Pretty Fancy Name" } },
432
- },
433
- ];
434
- mockCatalogFiles = [];
513
+ kind: "catalog",
514
+ origin: "vellum",
515
+ status: "available",
516
+ }),
517
+ };
435
518
 
436
519
  const result = await getSkillFiles("fancy-skill", dummyCtx);
437
520
 
@@ -439,6 +522,211 @@ describe("getSkillFiles — catalog fallback", () => {
439
522
  if ("error" in result) return;
440
523
  expect(result.skill.name).toBe("Pretty Fancy Name");
441
524
  });
525
+
526
+ test("skills.sh-shaped ID not in vellum catalog returns files from skills.sh provider", async () => {
527
+ // Vellum provider doesn't handle this ID
528
+ mockVellumProvider = {
529
+ canHandle: () => false,
530
+ listFiles: async () => null,
531
+ readFileContent: async () => null,
532
+ toSlimSkill: async () => null,
533
+ };
534
+
535
+ const skillsshFiles: SkillFileEntry[] = [
536
+ {
537
+ path: "SKILL.md",
538
+ name: "SKILL.md",
539
+ size: 100,
540
+ mimeType: "",
541
+ isBinary: false,
542
+ content: null,
543
+ },
544
+ ];
545
+ mockSkillsshProvider = {
546
+ canHandle: (id: string) => id.split("/").length >= 3,
547
+ listFiles: async () => skillsshFiles,
548
+ readFileContent: async () => null,
549
+ toSlimSkill: async (id: string) => ({
550
+ id,
551
+ name: "my-skill",
552
+ description: "",
553
+ kind: "catalog",
554
+ origin: "skillssh",
555
+ status: "available",
556
+ slug: id,
557
+ sourceRepo: "owner/repo",
558
+ installs: 0,
559
+ }),
560
+ };
561
+
562
+ const result = await getSkillFiles("owner/repo/my-skill", dummyCtx);
563
+
564
+ expect("error" in result).toBe(false);
565
+ if ("error" in result) return;
566
+ expect(result.skill.origin).toBe("skillssh");
567
+ expect(result.files).toHaveLength(1);
568
+ expect(result.files[0].path).toBe("SKILL.md");
569
+ });
570
+
571
+ test("clawhub-shaped ID not in vellum catalog returns files from clawhub provider", async () => {
572
+ // Vellum and skills.sh providers don't handle this ID
573
+ mockVellumProvider = {
574
+ canHandle: () => false,
575
+ listFiles: async () => null,
576
+ readFileContent: async () => null,
577
+ toSlimSkill: async () => null,
578
+ };
579
+ mockSkillsshProvider = {
580
+ canHandle: () => false,
581
+ listFiles: async () => null,
582
+ readFileContent: async () => null,
583
+ toSlimSkill: async () => null,
584
+ };
585
+
586
+ const clawhubFiles: SkillFileEntry[] = [
587
+ {
588
+ path: "SKILL.md",
589
+ name: "SKILL.md",
590
+ size: 200,
591
+ mimeType: "",
592
+ isBinary: false,
593
+ content: null,
594
+ },
595
+ {
596
+ path: "lib/utils.js",
597
+ name: "utils.js",
598
+ size: 500,
599
+ mimeType: "",
600
+ isBinary: false,
601
+ content: null,
602
+ },
603
+ ];
604
+ mockClawhubProvider = {
605
+ canHandle: () => true,
606
+ listFiles: async () => clawhubFiles,
607
+ readFileContent: async () => null,
608
+ toSlimSkill: async () => ({
609
+ id: "cool-tool",
610
+ name: "Cool Tool",
611
+ description: "A clawhub skill",
612
+ kind: "catalog",
613
+ origin: "clawhub",
614
+ status: "available",
615
+ slug: "cool-tool",
616
+ author: "someone",
617
+ stars: 5,
618
+ installs: 10,
619
+ reports: 0,
620
+ version: "",
621
+ }),
622
+ };
623
+
624
+ const result = await getSkillFiles("cool-tool", dummyCtx);
625
+
626
+ expect("error" in result).toBe(false);
627
+ if ("error" in result) return;
628
+ expect(result.skill.origin).toBe("clawhub");
629
+ expect(result.files).toHaveLength(2);
630
+ });
631
+
632
+ test("ID that no provider handles returns 404", async () => {
633
+ // All providers return canHandle=false
634
+ mockVellumProvider = makeNoopProvider("vellum");
635
+ mockSkillsshProvider = makeNoopProvider("skillssh");
636
+ mockClawhubProvider = makeNoopProvider("clawhub");
637
+
638
+ const result = await getSkillFiles("unknown-origin-skill", dummyCtx);
639
+
640
+ expect("error" in result).toBe(true);
641
+ if (!("error" in result)) return;
642
+ expect(result.status).toBe(404);
643
+ });
644
+
645
+ test("provider priority — vellum provider is tried before skills.sh and clawhub", async () => {
646
+ // All three providers claim to handle this ID, but vellum should win
647
+ const vellumListFilesCalls: string[] = [];
648
+ const skillsshListFilesCalls: string[] = [];
649
+ const clawhubListFilesCalls: string[] = [];
650
+
651
+ mockVellumProvider = {
652
+ canHandle: () => true,
653
+ listFiles: async (skillId: string) => {
654
+ vellumListFilesCalls.push(skillId);
655
+ return [
656
+ {
657
+ path: "SKILL.md",
658
+ name: "SKILL.md",
659
+ size: 10,
660
+ mimeType: "",
661
+ isBinary: false,
662
+ content: null,
663
+ },
664
+ ];
665
+ },
666
+ readFileContent: async () => null,
667
+ toSlimSkill: async () => ({
668
+ id: "contested-skill",
669
+ name: "Vellum Contested",
670
+ description: "",
671
+ kind: "catalog",
672
+ origin: "vellum",
673
+ status: "available",
674
+ }),
675
+ };
676
+ mockSkillsshProvider = {
677
+ canHandle: () => true,
678
+ listFiles: async (skillId: string) => {
679
+ skillsshListFilesCalls.push(skillId);
680
+ return [];
681
+ },
682
+ readFileContent: async () => null,
683
+ toSlimSkill: async () => ({
684
+ id: "contested-skill",
685
+ name: "Skillssh Contested",
686
+ description: "",
687
+ kind: "catalog",
688
+ origin: "skillssh",
689
+ status: "available",
690
+ slug: "contested-skill",
691
+ sourceRepo: "",
692
+ installs: 0,
693
+ }),
694
+ };
695
+ mockClawhubProvider = {
696
+ canHandle: () => true,
697
+ listFiles: async (skillId: string) => {
698
+ clawhubListFilesCalls.push(skillId);
699
+ return [];
700
+ },
701
+ readFileContent: async () => null,
702
+ toSlimSkill: async () => ({
703
+ id: "contested-skill",
704
+ name: "Clawhub Contested",
705
+ description: "",
706
+ kind: "catalog",
707
+ origin: "clawhub",
708
+ status: "available",
709
+ slug: "contested-skill",
710
+ author: "",
711
+ stars: 0,
712
+ installs: 0,
713
+ reports: 0,
714
+ version: "",
715
+ }),
716
+ };
717
+
718
+ const result = await getSkillFiles("contested-skill", dummyCtx);
719
+
720
+ expect("error" in result).toBe(false);
721
+ if ("error" in result) return;
722
+ // Vellum provider should have been used
723
+ expect(result.skill.origin).toBe("vellum");
724
+ expect(result.skill.name).toBe("Vellum Contested");
725
+ // Vellum was called, but skills.sh and clawhub were NOT called
726
+ expect(vellumListFilesCalls).toEqual(["contested-skill"]);
727
+ expect(skillsshListFilesCalls).toEqual([]);
728
+ expect(clawhubListFilesCalls).toEqual([]);
729
+ });
442
730
  });
443
731
 
444
732
  // ---------------------------------------------------------------------------
@@ -549,19 +549,21 @@ describe("bundled browser skill", () => {
549
549
  );
550
550
  });
551
551
 
552
- test("browser skill has a valid tool manifest with 14 tools", () => {
552
+ test("browser skill has a valid tool manifest with all browser tools", () => {
553
553
  const catalog = loadSkillCatalog();
554
554
  const browserSkill = catalog.find((s) => s.id === "browser");
555
555
  expect(browserSkill).toBeDefined();
556
556
  expect(browserSkill!.toolManifest).toBeDefined();
557
557
  expect(browserSkill!.toolManifest!.present).toBe(true);
558
558
  expect(browserSkill!.toolManifest!.valid).toBe(true);
559
- expect(browserSkill!.toolManifest!.toolCount).toBe(14);
559
+ expect(browserSkill!.toolManifest!.toolCount).toBe(17);
560
560
  expect(browserSkill!.toolManifest!.toolNames).toEqual([
561
561
  "browser_navigate",
562
562
  "browser_snapshot",
563
563
  "browser_screenshot",
564
564
  "browser_close",
565
+ "browser_attach",
566
+ "browser_detach",
565
567
  "browser_click",
566
568
  "browser_type",
567
569
  "browser_press_key",
@@ -572,6 +574,7 @@ describe("bundled browser skill", () => {
572
574
  "browser_extract",
573
575
  "browser_wait_for_download",
574
576
  "browser_fill_credential",
577
+ "browser_status",
575
578
  ]);
576
579
  });
577
580
  });