@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
@@ -37,9 +37,9 @@ import {
37
37
  } from "../../runtime/routes/workspace-utils.js";
38
38
  import { getCatalog } from "../../skills/catalog-cache.js";
39
39
  import {
40
+ catalogSkillToSlim,
41
+ createVellumCatalogProvider,
40
42
  hasHiddenOrSkippedSegment,
41
- readCatalogSkillFileContent,
42
- readCatalogSkillFiles,
43
43
  sanitizeRelativePath,
44
44
  type SkillFileEntry,
45
45
  SKIP_DIRS,
@@ -50,6 +50,8 @@ import {
50
50
  upsertSkillsIndex,
51
51
  } from "../../skills/catalog-install.js";
52
52
  import { filterByQuery } from "../../skills/catalog-search.js";
53
+ import type { SkillCategory } from "../../skills/category-inference.js";
54
+ import { inferCategory } from "../../skills/category-inference.js";
53
55
  import {
54
56
  clawhubCheckUpdates,
55
57
  clawhubInspect,
@@ -58,6 +60,7 @@ import {
58
60
  clawhubSearch,
59
61
  clawhubUpdate,
60
62
  } from "../../skills/clawhub.js";
63
+ import { createClawhubProvider } from "../../skills/clawhub-files.js";
61
64
  import {
62
65
  readInstallMeta,
63
66
  type SkillInstallMeta,
@@ -68,10 +71,14 @@ import {
68
71
  removeSkillsIndexEntry,
69
72
  validateManagedSkillId,
70
73
  } from "../../skills/managed-store.js";
74
+ import type { SkillFileProvider } from "../../skills/skill-file-provider.js";
75
+ import { createSkillsShProvider } from "../../skills/skillssh-files.js";
71
76
  import {
77
+ fetchSkillAudits,
72
78
  installExternalSkill,
73
79
  resolveSkillSource,
74
80
  searchSkillsRegistry,
81
+ type SkillAuditData,
75
82
  } from "../../skills/skillssh-registry.js";
76
83
  import { getWorkspaceSkillsDir } from "../../util/platform.js";
77
84
  import type {
@@ -79,6 +86,10 @@ import type {
79
86
  SkillFileContentResponse,
80
87
  SlimSkillResponse,
81
88
  } from "../message-types/skills.js";
89
+
90
+ // Re-export for use by route layer and future consumers.
91
+ export type { SkillCategory };
92
+ export { inferCategory };
82
93
  import {
83
94
  CONFIG_RELOAD_DEBOUNCE_MS,
84
95
  ensureSkillEntry,
@@ -100,6 +111,62 @@ export interface SkillOperationContext {
100
111
  broadcast: HandlerContext["broadcast"];
101
112
  }
102
113
 
114
+ // ─── Provider chain for uninstalled skill file preview ───────────────────────
115
+ // Ordered by priority: vellum first (most common and cheapest to check),
116
+ // then skills.sh, then clawhub.
117
+ //
118
+ // Lazy-initialized on first access so that mock modules (in tests) can
119
+ // replace the factory functions before providers are constructed.
120
+
121
+ let _fileProviders: SkillFileProvider[] | null = null;
122
+
123
+ function getFileProviders(): SkillFileProvider[] {
124
+ if (!_fileProviders) {
125
+ _fileProviders = [
126
+ createVellumCatalogProvider(),
127
+ createSkillsShProvider(),
128
+ createClawhubProvider(),
129
+ ];
130
+ }
131
+ return _fileProviders;
132
+ }
133
+
134
+ /** @internal Exported for test use only — forces re-creation of providers. */
135
+ export function _resetFileProvidersForTest(): void {
136
+ _fileProviders = null;
137
+ }
138
+
139
+ async function resolveSkillFiles(skillId: string): Promise<{
140
+ handled: boolean;
141
+ skill: SlimSkillResponse | null;
142
+ files: SkillFileEntry[] | null;
143
+ }> {
144
+ for (const provider of getFileProviders()) {
145
+ if (!provider.canHandle(skillId)) continue;
146
+ // Commit to this provider — don't fall through to subsequent providers.
147
+ const files = await provider.listFiles(skillId);
148
+ if (files === null) return { handled: true, skill: null, files: null };
149
+ const skill = await provider.toSlimSkill(skillId);
150
+ if (skill === null) return { handled: true, skill: null, files: null };
151
+ files.sort((a, b) => a.path.localeCompare(b.path));
152
+ return { handled: true, skill, files };
153
+ }
154
+ return { handled: false, skill: null, files: null };
155
+ }
156
+
157
+ async function resolveSkillFileContent(
158
+ skillId: string,
159
+ sanitizedPath: string,
160
+ ): Promise<{ handled: boolean; result: SkillFileEntry | null }> {
161
+ for (const provider of getFileProviders()) {
162
+ if (!provider.canHandle(skillId)) continue;
163
+ // Commit to this provider — don't fall through to subsequent providers.
164
+ const result = await provider.readFileContent(skillId, sanitizedPath);
165
+ return { handled: true, result };
166
+ }
167
+ return { handled: false, result: null };
168
+ }
169
+
103
170
  // ─── Frontmatter parsing ─────────────────────────────────────────────────────
104
171
 
105
172
  const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
@@ -326,6 +393,7 @@ function toSlimSkillResponse(
326
393
  stars: 0,
327
394
  installs: 0,
328
395
  reports: 0,
396
+ version: "",
329
397
  };
330
398
  }
331
399
  case "skillssh": {
@@ -399,6 +467,138 @@ export async function listSkillsWithCatalog(
399
467
  return merged;
400
468
  }
401
469
 
470
+ // ─── Filtered skill listing ──────────────────────────────────────────────────
471
+
472
+ export interface SkillListFilter {
473
+ origin?: string;
474
+ kind?: string;
475
+ q?: string;
476
+ category?: string;
477
+ includeCatalog?: boolean;
478
+ }
479
+
480
+ /** Human-readable labels matching Swift's `sourceLabel`. */
481
+ export function originDisplayLabel(origin: string): string {
482
+ switch (origin) {
483
+ case "vellum":
484
+ return "Vellum";
485
+ case "clawhub":
486
+ return "Clawhub";
487
+ case "skillssh":
488
+ return "skills.sh";
489
+ case "custom":
490
+ return "Custom";
491
+ default:
492
+ return origin;
493
+ }
494
+ }
495
+
496
+ /** Check if a skill's origin matches a text query (matching Swift logic). */
497
+ export function originMatchesQuery(origin: string, query: string): boolean {
498
+ const label = originDisplayLabel(origin).toLowerCase();
499
+ if (label.includes(query)) return true;
500
+ // "community" umbrella matches clawhub and skillssh
501
+ if (
502
+ (origin === "clawhub" || origin === "skillssh") &&
503
+ "community".includes(query)
504
+ ) {
505
+ return true;
506
+ }
507
+ return false;
508
+ }
509
+
510
+ /**
511
+ * List skills with filtering, category counts, and sorting.
512
+ * Calls listSkillsWithCatalog for the full merged list, then applies filters.
513
+ */
514
+ export async function listSkillsFiltered(
515
+ filter: SkillListFilter,
516
+ ctx: SkillOperationContext,
517
+ ): Promise<{
518
+ skills: SlimSkillResponse[];
519
+ categoryCounts: Record<string, number>;
520
+ totalCount: number;
521
+ }> {
522
+ let skills =
523
+ filter.includeCatalog !== false
524
+ ? await listSkillsWithCatalog(ctx)
525
+ : listSkills(ctx);
526
+
527
+ // Apply origin filter
528
+ if (filter.origin) {
529
+ skills = skills.filter((s) => s.origin === filter.origin);
530
+ }
531
+
532
+ // Apply kind/status filter
533
+ if (filter.kind) {
534
+ switch (filter.kind) {
535
+ case "installed":
536
+ skills = skills.filter(
537
+ (s) => s.kind === "installed" || s.kind === "bundled",
538
+ );
539
+ break;
540
+ case "available":
541
+ skills = skills.filter((s) => s.status === "available");
542
+ break;
543
+ default:
544
+ skills = skills.filter((s) => s.kind === filter.kind);
545
+ break;
546
+ }
547
+ }
548
+
549
+ // Apply text search
550
+ if (filter.q) {
551
+ const query = filter.q.trim().toLowerCase();
552
+ if (query) {
553
+ skills = skills.filter((s) => {
554
+ if (s.name.toLowerCase().includes(query)) return true;
555
+ if (s.description.toLowerCase().includes(query)) return true;
556
+ if (s.id.toLowerCase().includes(query)) return true;
557
+ if (originMatchesQuery(s.origin, query)) return true;
558
+ return false;
559
+ });
560
+ }
561
+ }
562
+
563
+ // Compute category counts BEFORE applying the category filter
564
+ const categoryCounts: Record<string, number> = {};
565
+ for (const s of skills) {
566
+ const cat = inferCategory(s.name, s.description);
567
+ categoryCounts[cat] = (categoryCounts[cat] ?? 0) + 1;
568
+ }
569
+ const totalCount = skills.length;
570
+
571
+ // Apply category filter
572
+ if (filter.category) {
573
+ skills = skills.filter(
574
+ (s) => inferCategory(s.name, s.description) === filter.category,
575
+ );
576
+ }
577
+
578
+ // Sort: installed first, community origins before core within installed,
579
+ // then alphabetical by name (matching Swift sorting logic)
580
+ skills.sort((a, b) => {
581
+ // Installed (bundled + installed) before catalog (available)
582
+ const aInstalled = a.kind === "installed" || a.kind === "bundled" ? 0 : 1;
583
+ const bInstalled = b.kind === "installed" || b.kind === "bundled" ? 0 : 1;
584
+ if (aInstalled !== bInstalled) return aInstalled - bInstalled;
585
+
586
+ // Within installed, community origins (clawhub, skillssh) before core (vellum)
587
+ if (aInstalled === 0 && bInstalled === 0) {
588
+ const aCommunity =
589
+ a.origin === "clawhub" || a.origin === "skillssh" ? 0 : 1;
590
+ const bCommunity =
591
+ b.origin === "clawhub" || b.origin === "skillssh" ? 0 : 1;
592
+ if (aCommunity !== bCommunity) return aCommunity - bCommunity;
593
+ }
594
+
595
+ // Alphabetical by name
596
+ return a.name.localeCompare(b.name);
597
+ });
598
+
599
+ return { skills, categoryCounts, totalCount };
600
+ }
601
+
402
602
  /** Look up a single skill by ID from the resolved catalog, returning its SlimSkillResponse. */
403
603
  function findSkillById(
404
604
  skillId: string,
@@ -420,6 +620,32 @@ export async function getSkill(
420
620
  ): Promise<{ skill: SkillDetailResponse } | { error: string; status: number }> {
421
621
  const found = findSkillById(skillId);
422
622
  if (!found) {
623
+ // Fallback: skill is not installed. Try all file providers.
624
+ for (const provider of getFileProviders()) {
625
+ if (!provider.canHandle(skillId)) continue;
626
+ // Commit to this provider — don't fall through to subsequent providers.
627
+ const slim = await provider.toSlimSkill(skillId);
628
+ if (slim) {
629
+ // Enrich uninstalled skills.sh skills with audit data (non-fatal)
630
+ if (slim.origin === "skillssh") {
631
+ try {
632
+ const sourceRepo = slim.sourceRepo;
633
+ const skillSlug = slim.slug.split("/").pop() ?? slim.slug;
634
+ const audits = await fetchSkillAudits(sourceRepo, [skillSlug]);
635
+ if (audits[skillSlug]) {
636
+ (slim as { audit?: SkillAuditData }).audit = audits[skillSlug];
637
+ }
638
+ } catch (err) {
639
+ log.warn(
640
+ { err, skillId },
641
+ "Failed to enrich uninstalled skillssh skill with audit data",
642
+ );
643
+ }
644
+ }
645
+ return { skill: slim as SkillDetailResponse };
646
+ }
647
+ return { error: `Skill "${skillId}" not found`, status: 404 };
648
+ }
423
649
  return { error: `Skill "${skillId}" not found`, status: 404 };
424
650
  }
425
651
 
@@ -443,6 +669,7 @@ export async function getSkill(
443
669
  installs: slim.installs,
444
670
  reports: slim.reports,
445
671
  publishedAt: slim.publishedAt,
672
+ version: slim.version,
446
673
  };
447
674
  try {
448
675
  const inspectResult = await clawhubInspect(slim.slug);
@@ -477,6 +704,20 @@ export async function getSkill(
477
704
  sourceRepo: slim.sourceRepo,
478
705
  installs: slim.installs,
479
706
  };
707
+ // Enrich with audit data (non-fatal on failure)
708
+ try {
709
+ const sourceRepo = slim.sourceRepo;
710
+ const skillSlug = slim.slug.split("/").pop() ?? slim.slug;
711
+ const audits = await fetchSkillAudits(sourceRepo, [skillSlug]);
712
+ if (audits[skillSlug]) {
713
+ (detail as { audit?: SkillAuditData }).audit = audits[skillSlug];
714
+ }
715
+ } catch (err) {
716
+ log.warn(
717
+ { err, skillId },
718
+ "Failed to enrich skillssh skill detail with audit data",
719
+ );
720
+ }
480
721
  return { skill: detail };
481
722
  }
482
723
 
@@ -566,35 +807,15 @@ function readDirRecursive(dir: string, rootDir: string): SkillFileEntry[] {
566
807
  }
567
808
 
568
809
  /**
569
- * Map a `CatalogSkill` (from the Vellum platform API) to a `SlimSkillResponse`
570
- * shaped for the "available catalog skill" case. Shared between
571
- * `listSkillsWithCatalog` (merging catalog entries into the installed list)
572
- * and `getSkillFiles` (catalog fallback for preview listings). Keeping the
573
- * mapping in one place avoids divergence between the list and detail paths.
574
- */
575
- function catalogSkillToSlim(cs: CatalogSkill): SlimSkillResponse {
576
- return {
577
- id: cs.id,
578
- name: cs.metadata?.vellum?.["display-name"] ?? cs.name,
579
- description: cs.description,
580
- emoji: cs.emoji,
581
- kind: "catalog",
582
- origin: "vellum",
583
- status: "available",
584
- };
585
- }
586
-
587
- /**
588
- * Read a single file's content from an installed or catalog skill.
810
+ * Read a single file's content from an installed or uninstalled skill.
589
811
  *
590
812
  * Installed-skill path (eager): reads the file directly from the skill's
591
813
  * on-disk directory. Applies lexical containment, symlink rejection, and
592
814
  * realpath containment checks for defense in depth.
593
815
  *
594
- * Catalog fallback: when the skill id is not backed by a local directory
595
- * (e.g. an uninstalled Vellum catalog skill), delegates to
596
- * `readCatalogSkillFileContent`, which handles both the dev-mode repo
597
- * checkout path and the platform preview API path internally.
816
+ * Provider chain fallback: when the skill id is not backed by a local
817
+ * directory, iterates the file-provider chain (vellum catalog,
818
+ * skills.sh, clawhub) until one returns content.
598
819
  */
599
820
  export async function getSkillFileContent(
600
821
  skillId: string,
@@ -701,32 +922,23 @@ export async function getSkillFileContent(
701
922
  };
702
923
  }
703
924
 
704
- // Catalog fallback: skill is not installed locally. Try the catalog
705
- // preview helper, which handles both dev-mode repo checkouts and the
706
- // platform preview API.
707
- let catalog: Awaited<ReturnType<typeof getCatalog>> = [];
708
- try {
709
- catalog = await getCatalog();
710
- } catch {
711
- catalog = [];
712
- }
713
- const inCatalog = catalog.some((s) => s.id === skillId);
714
- if (!inCatalog) {
715
- return { error: "Skill not found", status: 404 };
925
+ // Fallback: skill is not installed. Try all file providers.
926
+ const { handled, result } = await resolveSkillFileContent(skillId, sanitized);
927
+ if (handled && result) {
928
+ return {
929
+ path: result.path,
930
+ name: result.name,
931
+ size: result.size,
932
+ mimeType: result.mimeType,
933
+ isBinary: result.isBinary,
934
+ content: result.content,
935
+ };
716
936
  }
717
-
718
- const result = await readCatalogSkillFileContent(skillId, sanitized);
719
- if (!result) {
937
+ if (handled) {
938
+ // A provider claimed this skill but the specific file wasn't found.
720
939
  return { error: "File not found", status: 404 };
721
940
  }
722
- return {
723
- path: result.path,
724
- name: result.name,
725
- size: result.size,
726
- mimeType: result.mimeType,
727
- isBinary: result.isBinary,
728
- content: result.content,
729
- };
941
+ return { error: "Skill not found", status: 404 };
730
942
  }
731
943
 
732
944
  export async function getSkillFiles(
@@ -758,31 +970,16 @@ export async function getSkillFiles(
758
970
  };
759
971
  }
760
972
 
761
- // Fallback: skill is not installed. Try the Vellum catalog — this covers
762
- // previewing files for an uninstalled catalog skill without touching the
763
- // install flow.
764
- let catalog: CatalogSkill[];
765
- try {
766
- catalog = await getCatalog();
767
- } catch {
768
- return { error: `Skill "${skillId}" not found`, status: 404 };
769
- }
770
- const cs = catalog.find((c) => c.id === skillId);
771
- if (!cs) {
772
- return { error: `Skill "${skillId}" not found`, status: 404 };
973
+ // Fallback: skill is not installed. Try all file providers.
974
+ const resolved = await resolveSkillFiles(skillId);
975
+ if (resolved.handled && resolved.skill && resolved.files) {
976
+ return { skill: resolved.skill, files: resolved.files };
773
977
  }
774
-
775
- const files = await readCatalogSkillFiles(skillId);
776
- if (files === null) {
777
- return {
778
- error: `Skill files unavailable for "${skillId}"`,
779
- status: 404,
780
- };
978
+ if (resolved.handled) {
979
+ // A provider claimed this skill but couldn't produce files/metadata.
980
+ return { error: `Skill files unavailable for "${skillId}"`, status: 404 };
781
981
  }
782
-
783
- const skill = catalogSkillToSlim(cs);
784
- files.sort((a, b) => a.path.localeCompare(b.path));
785
- return { skill, files };
982
+ return { error: `Skill "${skillId}" not found`, status: 404 };
786
983
  }
787
984
 
788
985
  export function enableSkill(
@@ -871,7 +1068,9 @@ export async function installSkill(
871
1068
  contactId?: string;
872
1069
  },
873
1070
  ctx: SkillOperationContext,
874
- ): Promise<{ success: true } | { success: false; error: string }> {
1071
+ ): Promise<
1072
+ { success: true; skillId: string } | { success: false; error: string }
1073
+ > {
875
1074
  try {
876
1075
  // Bundled skills are already available — no install needed
877
1076
  const catalog = loadSkillCatalog();
@@ -916,7 +1115,7 @@ export async function installSkill(
916
1115
  }
917
1116
  seedSkillGraphNodes();
918
1117
  void seedUninstalledCatalogSkillMemories().catch(() => {});
919
- return { success: true };
1118
+ return { success: true, skillId: spec.slug };
920
1119
  }
921
1120
 
922
1121
  // Check the Vellum catalog (first-party skills hosted on the platform).
@@ -937,7 +1136,7 @@ export async function installSkill(
937
1136
 
938
1137
  const skillDir = join(getWorkspaceSkillsDir(), spec.slug);
939
1138
  postInstallSkill(spec.slug, skillDir, ctx);
940
- return { success: true };
1139
+ return { success: true, skillId: spec.slug };
941
1140
  }
942
1141
  } catch (err) {
943
1142
  // If catalog lookup/install fails, fall through to community registries
@@ -965,7 +1164,7 @@ export async function installSkill(
965
1164
 
966
1165
  const skillDir = join(getWorkspaceSkillsDir(), resolved.skillSlug);
967
1166
  postInstallSkill(resolved.skillSlug, skillDir, ctx);
968
- return { success: true };
1167
+ return { success: true, skillId: resolved.skillSlug };
969
1168
  }
970
1169
 
971
1170
  // Install from clawhub (community)
@@ -993,7 +1192,7 @@ export async function installSkill(
993
1192
  upsertSkillsIndex(skillId);
994
1193
 
995
1194
  postInstallSkill(skillId, skillDir, ctx);
996
- return { success: true };
1195
+ return { success: true, skillId };
997
1196
  } catch (err) {
998
1197
  const message = err instanceof Error ? err.message : String(err);
999
1198
  log.error({ err }, "Failed to install skill");
@@ -1166,6 +1365,7 @@ export async function searchSkills(
1166
1365
  publishedAt: s.createdAt
1167
1366
  ? new Date(s.createdAt * 1000).toISOString()
1168
1367
  : undefined,
1368
+ version: s.version,
1169
1369
  }));
1170
1370
  } else {
1171
1371
  log.warn(
@@ -1187,6 +1387,50 @@ export async function searchSkills(
1187
1387
  sourceRepo: r.source,
1188
1388
  installs: r.installs,
1189
1389
  }));
1390
+
1391
+ // Batch-fetch audit data for skills.sh results, grouped by source repo.
1392
+ try {
1393
+ if (skillsshResult.value.length > 0) {
1394
+ const sourceToSlugs = new Map<string, string[]>();
1395
+ for (const r of skillsshResult.value) {
1396
+ const slugs = sourceToSlugs.get(r.source) ?? [];
1397
+ slugs.push(r.skillId);
1398
+ sourceToSlugs.set(r.source, slugs);
1399
+ }
1400
+
1401
+ const auditResults = await Promise.allSettled(
1402
+ [...sourceToSlugs.entries()].map(([source, slugs]) =>
1403
+ fetchSkillAudits(source, slugs).then((audits) => ({
1404
+ source,
1405
+ audits,
1406
+ })),
1407
+ ),
1408
+ );
1409
+
1410
+ // Build a lookup map keyed by full skill ID (e.g. "owner/repo/skill-name")
1411
+ const auditMap = new Map<string, SkillAuditData>();
1412
+ for (const result of auditResults) {
1413
+ if (result.status !== "fulfilled") continue;
1414
+ const { source, audits } = result.value;
1415
+ for (const [skillSlug, auditData] of Object.entries(audits)) {
1416
+ auditMap.set(`${source}/${skillSlug}`, auditData);
1417
+ }
1418
+ }
1419
+
1420
+ // Enrich each skills.sh skill with audit data
1421
+ skillsshSkills = skillsshSkills.map((skill) => {
1422
+ if (skill.origin !== "skillssh") return skill;
1423
+ const audit = auditMap.get(skill.id);
1424
+ if (!audit) return skill;
1425
+ return { ...skill, audit };
1426
+ });
1427
+ }
1428
+ } catch (err) {
1429
+ log.warn(
1430
+ { err },
1431
+ "Audit fetch failed for skills.sh results, continuing without audit data",
1432
+ );
1433
+ }
1190
1434
  } else {
1191
1435
  log.warn(
1192
1436
  { err: skillsshResult.reason },
@@ -77,7 +77,8 @@ export class HostBrowserProxy {
77
77
  "Host browser proxy request timed out",
78
78
  );
79
79
  resolve({
80
- content: "Host browser proxy timed out waiting for client response",
80
+ content:
81
+ "Host browser proxy timed out waiting for extension response (check browser-relay connectivity and /v1/host-browser-result callback failures such as 404/401).",
81
82
  isError: true,
82
83
  });
83
84
  }, timeoutSec * 1000);