@vellumai/assistant 0.7.3 → 0.8.1

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 (778) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +29 -28
  3. package/Dockerfile +6 -4
  4. package/README.md +2 -2
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  6. package/bun.lock +3 -0
  7. package/docker-entrypoint.sh +16 -0
  8. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  9. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  10. package/eslint.config.mjs +12 -0
  11. package/knip.json +3 -1
  12. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  13. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  14. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  15. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  16. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  17. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/openapi.yaml +4126 -959
  20. package/package.json +5 -1
  21. package/scripts/generate-openapi.ts +52 -4
  22. package/scripts/sync-llm-catalog.ts +165 -0
  23. package/scripts/sync-web-search-catalog.ts +107 -0
  24. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  25. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  26. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  27. package/src/__tests__/anthropic-provider.test.ts +92 -2
  28. package/src/__tests__/app-control-flow.test.ts +7 -0
  29. package/src/__tests__/approval-cascade.test.ts +8 -16
  30. package/src/__tests__/approval-routes-http.test.ts +6 -0
  31. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  32. package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
  33. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  34. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  35. package/src/__tests__/btw-routes.test.ts +1 -0
  36. package/src/__tests__/call-constants.test.ts +10 -1
  37. package/src/__tests__/call-controller.test.ts +127 -0
  38. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  39. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  40. package/src/__tests__/channel-policy.test.ts +12 -0
  41. package/src/__tests__/checker.test.ts +89 -0
  42. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
  43. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  44. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  45. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  46. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
  48. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  49. package/src/__tests__/config-schema.test.ts +14 -3
  50. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  51. package/src/__tests__/config-set-route.test.ts +198 -0
  52. package/src/__tests__/config-watcher.test.ts +6 -0
  53. package/src/__tests__/contacts-tools.test.ts +51 -199
  54. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  55. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  56. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  57. package/src/__tests__/context-search-fanout.test.ts +20 -157
  58. package/src/__tests__/context-search-memory-source.test.ts +3 -26
  59. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  60. package/src/__tests__/context-search-types.test.ts +7 -2
  61. package/src/__tests__/context-window-manager.test.ts +389 -1
  62. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
  63. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  64. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  65. package/src/__tests__/conversation-agent-loop.test.ts +3 -3
  66. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  67. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  68. package/src/__tests__/conversation-error.test.ts +38 -0
  69. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  70. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  71. package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
  72. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  74. package/src/__tests__/conversation-process-callsite.test.ts +22 -7
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
  76. package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
  77. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  78. package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
  79. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  81. package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
  82. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
  83. package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
  84. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
  85. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  86. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  87. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  88. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  89. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  90. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  91. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  92. package/src/__tests__/filing-service.test.ts +25 -22
  93. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  94. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  95. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  96. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
  97. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  98. package/src/__tests__/heartbeat-service.test.ts +50 -233
  99. package/src/__tests__/history-repair.test.ts +89 -0
  100. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  101. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  102. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  103. package/src/__tests__/host-browser-routes.test.ts +325 -33
  104. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  105. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  106. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  107. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  108. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  109. package/src/__tests__/injector-chain.test.ts +24 -16
  110. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  111. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  112. package/src/__tests__/install-skill-routing.test.ts +2 -2
  113. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
  114. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  115. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  116. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  117. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  118. package/src/__tests__/llm-resolver.test.ts +46 -0
  119. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  120. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  121. package/src/__tests__/mcp-cli.test.ts +182 -220
  122. package/src/__tests__/mcp-health-check.test.ts +56 -27
  123. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  124. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  125. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  126. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  127. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  128. package/src/__tests__/oauth-cli.test.ts +38 -1888
  129. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  130. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  131. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  132. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  133. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  134. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  135. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  136. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  137. package/src/__tests__/plugin-types.test.ts +13 -11
  138. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  139. package/src/__tests__/profile-entry-status.test.ts +43 -0
  140. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  141. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  142. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  143. package/src/__tests__/relay-server.test.ts +164 -2
  144. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  145. package/src/__tests__/schedule-retry.test.ts +56 -4
  146. package/src/__tests__/schedule-routes.test.ts +104 -0
  147. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  148. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  149. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  150. package/src/__tests__/scheduler-wake.test.ts +0 -63
  151. package/src/__tests__/secret-allowlist.test.ts +1 -0
  152. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  153. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  154. package/src/__tests__/secret-response-routing.test.ts +7 -5
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  156. package/src/__tests__/server-history-render.test.ts +82 -0
  157. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  158. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  159. package/src/__tests__/skill-include-graph.test.ts +31 -0
  160. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  161. package/src/__tests__/skill-load-tool.test.ts +42 -16
  162. package/src/__tests__/skills.test.ts +39 -0
  163. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  164. package/src/__tests__/suggestion-routes.test.ts +3 -3
  165. package/src/__tests__/sync-message-contract.test.ts +63 -0
  166. package/src/__tests__/task-scheduler.test.ts +88 -23
  167. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  168. package/src/__tests__/tool-executor.test.ts +155 -0
  169. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  170. package/src/__tests__/usage-cli.test.ts +11 -73
  171. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  172. package/src/__tests__/vercel-config.test.ts +168 -0
  173. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  174. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  175. package/src/__tests__/web-search.test.ts +303 -2
  176. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  177. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  178. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
  179. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  180. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  181. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  182. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  183. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  184. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  185. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  186. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  187. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
  188. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  189. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  190. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  191. package/src/acp/resolve-agent.test.ts +25 -0
  192. package/src/acp/resolve-agent.ts +13 -2
  193. package/src/acp/session-manager.ts +14 -0
  194. package/src/agent/loop.ts +11 -0
  195. package/src/approvals/guardian-decision-primitive.ts +0 -13
  196. package/src/approvals/guardian-request-resolvers.ts +19 -102
  197. package/src/calls/call-constants.ts +5 -8
  198. package/src/calls/call-controller.ts +130 -67
  199. package/src/calls/relay-server.ts +42 -1
  200. package/src/calls/relay-setup-router.ts +36 -0
  201. package/src/calls/types.ts +1 -0
  202. package/src/calls/voice-session-bridge.ts +24 -5
  203. package/src/channels/config.ts +14 -1
  204. package/src/channels/types.ts +1 -0
  205. package/src/cli/AGENTS.md +164 -4
  206. package/src/cli/__tests__/notifications.test.ts +54 -0
  207. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  208. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  209. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  210. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  211. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  212. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  213. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  214. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  215. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  216. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  217. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  218. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  219. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  220. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  221. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  222. package/src/cli/commands/__tests__/status.test.ts +249 -0
  223. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  224. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  225. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  226. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  227. package/src/cli/commands/attachment.ts +8 -3
  228. package/src/cli/commands/audit.ts +95 -64
  229. package/src/cli/commands/auth.ts +61 -58
  230. package/src/cli/commands/avatar.ts +276 -390
  231. package/src/cli/commands/backup.ts +409 -505
  232. package/src/cli/commands/bash.ts +9 -5
  233. package/src/cli/commands/browser.ts +28 -9
  234. package/src/cli/commands/cache.ts +9 -4
  235. package/src/cli/commands/changelog.ts +414 -0
  236. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  237. package/src/cli/commands/clients.ts +8 -3
  238. package/src/cli/commands/completions.ts +9 -9
  239. package/src/cli/commands/config.ts +102 -72
  240. package/src/cli/commands/contacts.ts +575 -696
  241. package/src/cli/commands/conversations-defer.ts +17 -69
  242. package/src/cli/commands/conversations-import.ts +90 -253
  243. package/src/cli/commands/conversations.ts +346 -436
  244. package/src/cli/commands/credential-execution.ts +9 -6
  245. package/src/cli/commands/credentials.ts +456 -736
  246. package/src/cli/commands/domain.ts +128 -206
  247. package/src/cli/commands/email.ts +606 -794
  248. package/src/cli/commands/gateway.ts +8 -1
  249. package/src/cli/commands/image-generation.ts +157 -205
  250. package/src/cli/commands/inference-providers.ts +352 -0
  251. package/src/cli/commands/inference-session.ts +415 -0
  252. package/src/cli/commands/inference.ts +87 -65
  253. package/src/cli/commands/keys.ts +8 -3
  254. package/src/cli/commands/mcp.ts +103 -287
  255. package/src/cli/commands/memory-v2.ts +163 -517
  256. package/src/cli/commands/notifications.ts +33 -7
  257. package/src/cli/commands/oauth/apps.ts +292 -261
  258. package/src/cli/commands/oauth/connect.ts +182 -345
  259. package/src/cli/commands/oauth/disconnect.ts +16 -215
  260. package/src/cli/commands/oauth/index.ts +49 -45
  261. package/src/cli/commands/oauth/mode.ts +43 -199
  262. package/src/cli/commands/oauth/ping.ts +17 -125
  263. package/src/cli/commands/oauth/providers.ts +732 -921
  264. package/src/cli/commands/oauth/request.ts +60 -350
  265. package/src/cli/commands/oauth/shared.ts +11 -121
  266. package/src/cli/commands/oauth/status.ts +31 -121
  267. package/src/cli/commands/oauth/token.ts +13 -55
  268. package/src/cli/commands/pending.ts +19 -10
  269. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  270. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  271. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  272. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  273. package/src/cli/commands/platform/connect.ts +16 -80
  274. package/src/cli/commands/platform/disconnect.ts +14 -112
  275. package/src/cli/commands/platform/index.ts +177 -246
  276. package/src/cli/commands/routes.ts +153 -336
  277. package/src/cli/commands/sequence.ts +316 -360
  278. package/src/cli/commands/skills.ts +449 -671
  279. package/src/cli/commands/status.ts +58 -37
  280. package/src/cli/commands/stt.ts +94 -262
  281. package/src/cli/commands/task.ts +14 -40
  282. package/src/cli/commands/trust.ts +8 -3
  283. package/src/cli/commands/tts.ts +162 -167
  284. package/src/cli/commands/ui.ts +35 -42
  285. package/src/cli/commands/usage.ts +188 -126
  286. package/src/cli/commands/watchers.ts +8 -3
  287. package/src/cli/commands/webhooks.ts +99 -193
  288. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  289. package/src/cli/lib/daemon-credential-client.ts +4 -5
  290. package/src/cli/lib/nested-value.ts +44 -0
  291. package/src/cli/lib/open-browser.ts +36 -0
  292. package/src/cli/lib/register-command.ts +19 -0
  293. package/src/cli/lib/time-ago.ts +34 -0
  294. package/src/cli/program.ts +2 -4
  295. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  296. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  297. package/src/cli/utils/conversation-id.ts +30 -0
  298. package/src/cli/utils/parse-duration.ts +41 -0
  299. package/src/config/acp-defaults.test.ts +5 -1
  300. package/src/config/acp-defaults.ts +11 -4
  301. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  302. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  303. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  304. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  305. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  306. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  307. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  308. package/src/config/bundled-tool-registry.ts +0 -2
  309. package/src/config/feature-flag-registry.json +17 -17
  310. package/src/config/llm-resolver.ts +16 -1
  311. package/src/config/loader.ts +148 -33
  312. package/src/config/raw-config-utils.ts +2 -30
  313. package/src/config/schema.ts +4 -0
  314. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  315. package/src/config/schemas/call-site-catalog.ts +29 -7
  316. package/src/config/schemas/llm-request-logs.ts +57 -0
  317. package/src/config/schemas/llm.ts +52 -2
  318. package/src/config/schemas/memory-retrospective.ts +48 -0
  319. package/src/config/schemas/memory-v2.ts +33 -2
  320. package/src/config/schemas/memory.ts +4 -0
  321. package/src/config/schemas/services.ts +15 -12
  322. package/src/config/seed-inference-profiles.ts +195 -134
  323. package/src/contacts/contact-store.ts +0 -61
  324. package/src/context/window-manager.ts +191 -5
  325. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
  326. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  327. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  328. package/src/daemon/approval-generators.ts +23 -29
  329. package/src/daemon/config-watcher.ts +2 -0
  330. package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
  331. package/src/daemon/conversation-agent-loop.ts +140 -107
  332. package/src/daemon/conversation-error.ts +21 -0
  333. package/src/daemon/conversation-lifecycle.ts +68 -13
  334. package/src/daemon/conversation-process.ts +36 -19
  335. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  336. package/src/daemon/conversation-slash.ts +175 -23
  337. package/src/daemon/conversation-store.ts +17 -10
  338. package/src/daemon/conversation-surfaces.ts +92 -26
  339. package/src/daemon/conversation-tool-setup.ts +33 -19
  340. package/src/daemon/conversation.ts +49 -10
  341. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  342. package/src/daemon/guardian-action-generators.ts +7 -22
  343. package/src/daemon/handlers/config-model.ts +8 -126
  344. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  345. package/src/daemon/handlers/config-vercel.ts +3 -1
  346. package/src/daemon/handlers/shared.ts +26 -0
  347. package/src/daemon/handlers/skills.ts +84 -5
  348. package/src/daemon/history-repair.ts +33 -6
  349. package/src/daemon/host-app-control-proxy.ts +44 -19
  350. package/src/daemon/host-bash-proxy.ts +85 -158
  351. package/src/daemon/host-browser-proxy.ts +97 -36
  352. package/src/daemon/host-cu-proxy.ts +1 -1
  353. package/src/daemon/host-file-proxy.ts +1 -1
  354. package/src/daemon/host-proxy-base.ts +13 -1
  355. package/src/daemon/host-proxy-preactivation.ts +25 -1
  356. package/src/daemon/host-transfer-proxy.ts +2 -2
  357. package/src/daemon/identity-helpers.ts +19 -0
  358. package/src/daemon/lifecycle.ts +128 -114
  359. package/src/daemon/meet-host-supervisor.ts +15 -15
  360. package/src/daemon/memory-v2-startup.ts +62 -14
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/bookmarks.ts +18 -0
  363. package/src/daemon/message-types/conversations.ts +12 -9
  364. package/src/daemon/message-types/messages.ts +28 -2
  365. package/src/daemon/message-types/sync.ts +60 -0
  366. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  367. package/src/daemon/pkb-reminder-builder.ts +21 -7
  368. package/src/daemon/process-message.ts +56 -23
  369. package/src/daemon/server.ts +23 -18
  370. package/src/daemon/shutdown-handlers.ts +0 -2
  371. package/src/daemon/tool-setup-types.ts +9 -0
  372. package/src/daemon/tool-side-effects.ts +6 -4
  373. package/src/daemon/wake-target-adapter.ts +11 -0
  374. package/src/documents/document-store.ts +35 -1
  375. package/src/export/transcript-formatter.ts +61 -2
  376. package/src/filing/filing-service.ts +42 -56
  377. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  378. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  379. package/src/heartbeat/heartbeat-service.ts +149 -128
  380. package/src/home/__tests__/feed-types.test.ts +63 -131
  381. package/src/home/__tests__/feed-writer.test.ts +77 -278
  382. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  383. package/src/home/feed-types.ts +19 -73
  384. package/src/home/feed-writer.ts +25 -156
  385. package/src/home/post-connect-feed.ts +1 -3
  386. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  387. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  388. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  389. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  390. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  391. package/src/ipc/assistant-server.ts +148 -42
  392. package/src/ipc/cli-client.ts +370 -50
  393. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  394. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  395. package/src/ipc/skill-routes/events.ts +30 -3
  396. package/src/ipc/skill-server.ts +99 -42
  397. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  398. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  399. package/src/live-voice/live-voice-session-manager.ts +11 -4
  400. package/src/live-voice/live-voice-session.ts +14 -6
  401. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  402. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  403. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  404. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  405. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
  406. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  407. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  408. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  409. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  412. package/src/memory/bookmark-crud.ts +179 -0
  413. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  414. package/src/memory/context-search/agent-protocol.ts +5 -1
  415. package/src/memory/context-search/agent-runner.ts +60 -85
  416. package/src/memory/context-search/limits.ts +1 -4
  417. package/src/memory/context-search/search.ts +23 -113
  418. package/src/memory/context-search/sources/conversations.ts +18 -6
  419. package/src/memory/context-search/sources/memory-v2.ts +40 -31
  420. package/src/memory/context-search/sources/memory.ts +9 -2
  421. package/src/memory/context-search/sources/workspace.ts +13 -10
  422. package/src/memory/context-search/types.ts +1 -1
  423. package/src/memory/conversation-bootstrap.ts +11 -0
  424. package/src/memory/conversation-crud.ts +312 -10
  425. package/src/memory/conversation-queries.ts +9 -5
  426. package/src/memory/conversation-title-service.ts +1 -0
  427. package/src/memory/conversation-types.ts +16 -0
  428. package/src/memory/db-init.ts +14 -0
  429. package/src/memory/embedding-backend.ts +2 -1
  430. package/src/memory/embedding-runtime-manager.ts +1 -2
  431. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
  432. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  433. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  434. package/src/memory/graph/conversation-graph-memory.ts +108 -14
  435. package/src/memory/graph/extraction.ts +4 -0
  436. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  437. package/src/memory/graph/graph-search.test.ts +6 -5
  438. package/src/memory/graph/graph-search.ts +3 -4
  439. package/src/memory/graph/retriever.test.ts +12 -7
  440. package/src/memory/graph/retriever.ts +4 -5
  441. package/src/memory/graph/tool-handlers.ts +20 -11
  442. package/src/memory/graph/tools.ts +48 -9
  443. package/src/memory/indexer.ts +18 -2
  444. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
  445. package/src/memory/jobs/embed-concept-page.ts +261 -89
  446. package/src/memory/jobs-store.ts +51 -1
  447. package/src/memory/jobs-worker.ts +60 -7
  448. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  449. package/src/memory/llm-request-log-source-local.ts +26 -0
  450. package/src/memory/llm-request-log-source.ts +97 -0
  451. package/src/memory/llm-request-log-store.ts +1 -1
  452. package/src/memory/memory-retrospective-constants.ts +13 -0
  453. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  454. package/src/memory/memory-retrospective-job.ts +351 -0
  455. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  456. package/src/memory/memory-retrospective-state.ts +162 -0
  457. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  458. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  459. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  460. package/src/memory/message-content.ts +38 -1
  461. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  462. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  463. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  464. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  465. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  466. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  467. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  468. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  469. package/src/memory/migrations/243-provider-connections.ts +68 -0
  470. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  471. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  472. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  473. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  474. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  475. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  476. package/src/memory/migrations/index.ts +7 -0
  477. package/src/memory/pkb/pkb-search.test.ts +6 -5
  478. package/src/memory/pkb/pkb-search.ts +4 -5
  479. package/src/memory/published-pages-store.ts +16 -0
  480. package/src/memory/qdrant-client.ts +3 -0
  481. package/src/memory/schema/bookmarks.ts +38 -0
  482. package/src/memory/schema/conversations.ts +2 -0
  483. package/src/memory/schema/index.ts +2 -0
  484. package/src/memory/schema/inference.ts +29 -0
  485. package/src/memory/schema/memory-core.ts +9 -0
  486. package/src/memory/search/semantic.ts +5 -9
  487. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  488. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  489. package/src/memory/v2/__tests__/activation.test.ts +46 -9
  490. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  491. package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
  492. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  493. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  494. package/src/memory/v2/__tests__/injection.test.ts +768 -33
  495. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  496. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  497. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  498. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  499. package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
  500. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  501. package/src/memory/v2/__tests__/router.test.ts +516 -0
  502. package/src/memory/v2/__tests__/sim.test.ts +163 -8
  503. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  504. package/src/memory/v2/__tests__/static-context.test.ts +8 -35
  505. package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
  506. package/src/memory/v2/activation-store.ts +34 -5
  507. package/src/memory/v2/activation.ts +40 -27
  508. package/src/memory/v2/backfill-jobs.ts +17 -84
  509. package/src/memory/v2/consolidation-job.ts +92 -86
  510. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  511. package/src/memory/v2/injection.ts +466 -115
  512. package/src/memory/v2/migration.ts +117 -20
  513. package/src/memory/v2/page-index.ts +191 -0
  514. package/src/memory/v2/page-store.ts +42 -0
  515. package/src/memory/v2/prompts/consolidation.ts +14 -7
  516. package/src/memory/v2/prompts/router.ts +192 -0
  517. package/src/memory/v2/qdrant.ts +307 -133
  518. package/src/memory/v2/reranker.ts +14 -7
  519. package/src/memory/v2/router.ts +322 -0
  520. package/src/memory/v2/sim.ts +88 -34
  521. package/src/memory/v2/skill-store.ts +118 -29
  522. package/src/memory/v2/static-context.ts +20 -17
  523. package/src/memory/v2/sweep-job.ts +127 -102
  524. package/src/memory/v2/types.ts +16 -5
  525. package/src/memory/validation.ts +13 -0
  526. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  527. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  528. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  529. package/src/notifications/adapters/platform.ts +171 -0
  530. package/src/notifications/conversation-pairing.ts +2 -2
  531. package/src/notifications/copy-composer.ts +61 -12
  532. package/src/notifications/decision-engine.ts +46 -0
  533. package/src/notifications/destination-resolver.ts +21 -0
  534. package/src/notifications/emit-signal.ts +28 -1
  535. package/src/notifications/home-feed-side-effect.ts +111 -0
  536. package/src/notifications/signal.ts +5 -0
  537. package/src/permissions/checker.ts +12 -0
  538. package/src/permissions/gateway-threshold-reader.ts +116 -8
  539. package/src/permissions/ipc-risk-types.ts +2 -0
  540. package/src/permissions/prompter.ts +86 -96
  541. package/src/permissions/secret-prompter.ts +31 -31
  542. package/src/plugin-api/index.ts +13 -0
  543. package/src/plugin-api/package.json +12 -0
  544. package/src/plugin-api/types.ts +62 -0
  545. package/src/plugins/defaults/injectors.ts +20 -5
  546. package/src/plugins/external-plugin-loader.ts +294 -0
  547. package/src/plugins/types.ts +46 -30
  548. package/src/plugins/user-loader.ts +64 -41
  549. package/src/proactive-artifact/job.test.ts +63 -8
  550. package/src/proactive-artifact/job.ts +20 -2
  551. package/src/proactive-artifact/message-copy.ts +18 -1
  552. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  553. package/src/proactive-artifact/trigger-state.ts +4 -0
  554. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  555. package/src/prompts/system-prompt.ts +22 -1
  556. package/src/prompts/templates/SOUL.md +13 -28
  557. package/src/prompts/update-bulletin-job.ts +61 -73
  558. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  559. package/src/providers/__tests__/inference.test.ts +288 -0
  560. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  561. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  562. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  563. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  564. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  565. package/src/providers/anthropic/client.ts +95 -26
  566. package/src/providers/call-site-routing.ts +94 -16
  567. package/src/providers/connection-resolution.ts +163 -0
  568. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  569. package/src/providers/inference/adapter-factory.ts +173 -0
  570. package/src/providers/inference/auth.ts +112 -0
  571. package/src/providers/inference/backfill.ts +196 -0
  572. package/src/providers/inference/connections.ts +356 -0
  573. package/src/providers/inference/resolve-auth.ts +65 -0
  574. package/src/providers/model-catalog.ts +104 -6
  575. package/src/providers/openai/responses-provider.ts +4 -2
  576. package/src/providers/provider-env-vars.ts +17 -7
  577. package/src/providers/provider-secret-catalog.ts +49 -30
  578. package/src/providers/provider-send-message.ts +41 -20
  579. package/src/providers/registry.ts +143 -159
  580. package/src/providers/retry.ts +18 -10
  581. package/src/providers/search-provider-catalog.ts +121 -0
  582. package/src/runtime/AGENTS.md +18 -5
  583. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  584. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  585. package/src/runtime/actor-trust-resolver.ts +32 -10
  586. package/src/runtime/agent-wake.ts +35 -6
  587. package/src/runtime/assistant-event-hub.ts +3 -85
  588. package/src/runtime/auth/route-policy.ts +304 -8
  589. package/src/runtime/auth/same-actor.ts +2 -0
  590. package/src/runtime/background-job-runner.ts +339 -0
  591. package/src/runtime/btw-sidechain.ts +1 -0
  592. package/src/runtime/channel-approvals.ts +3 -2
  593. package/src/runtime/guardian-reply-router.ts +0 -10
  594. package/src/runtime/http-router.ts +36 -1
  595. package/src/runtime/http-server.ts +31 -5
  596. package/src/runtime/http-types.ts +2 -0
  597. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  598. package/src/runtime/middleware/request-logger.ts +62 -1
  599. package/src/runtime/pending-interactions.ts +19 -15
  600. package/src/runtime/pre-first-message-gate.ts +83 -0
  601. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  602. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  603. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  604. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  605. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  606. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  607. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  608. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  609. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  610. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  611. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  612. package/src/runtime/routes/acp-routes.ts +10 -8
  613. package/src/runtime/routes/app-management-routes.ts +228 -3
  614. package/src/runtime/routes/approval-routes.ts +7 -21
  615. package/src/runtime/routes/audit-routes.ts +43 -0
  616. package/src/runtime/routes/auth-routes.ts +72 -0
  617. package/src/runtime/routes/avatar-routes.ts +273 -20
  618. package/src/runtime/routes/backup-routes.ts +406 -2
  619. package/src/runtime/routes/bookmark-routes.ts +154 -0
  620. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  621. package/src/runtime/routes/consolidation-routes.ts +8 -9
  622. package/src/runtime/routes/contact-routes.ts +0 -160
  623. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  624. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  625. package/src/runtime/routes/conversation-query-routes.ts +373 -82
  626. package/src/runtime/routes/conversation-routes.ts +31 -10
  627. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  628. package/src/runtime/routes/credential-routes.ts +540 -0
  629. package/src/runtime/routes/debug-bash-routes.ts +2 -0
  630. package/src/runtime/routes/debug-routes.ts +2 -2
  631. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  632. package/src/runtime/routes/domain-routes.ts +167 -0
  633. package/src/runtime/routes/email-routes.ts +603 -0
  634. package/src/runtime/routes/errors.ts +2 -2
  635. package/src/runtime/routes/events-routes.ts +192 -0
  636. package/src/runtime/routes/filing-routes.ts +2 -3
  637. package/src/runtime/routes/home-feed-routes.ts +6 -78
  638. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  639. package/src/runtime/routes/host-browser-routes.ts +103 -22
  640. package/src/runtime/routes/http-adapter.ts +2 -0
  641. package/src/runtime/routes/identity-routes.ts +5 -0
  642. package/src/runtime/routes/image-generation-routes.ts +99 -0
  643. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  644. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  645. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  646. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
  647. package/src/runtime/routes/index.ts +36 -0
  648. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  649. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  650. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  651. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  652. package/src/runtime/routes/inference-send-routes.ts +115 -0
  653. package/src/runtime/routes/integrations/twilio.ts +1 -0
  654. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  655. package/src/runtime/routes/memory-item-routes.test.ts +3 -9
  656. package/src/runtime/routes/memory-item-routes.ts +5 -6
  657. package/src/runtime/routes/memory-v2-routes.ts +105 -404
  658. package/src/runtime/routes/notification-routes.ts +2 -0
  659. package/src/runtime/routes/oauth-apps.ts +112 -7
  660. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  661. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  662. package/src/runtime/routes/oauth-providers.ts +298 -8
  663. package/src/runtime/routes/platform-routes.ts +336 -0
  664. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  665. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  666. package/src/runtime/routes/playground/state.ts +2 -1
  667. package/src/runtime/routes/publish-routes.ts +221 -0
  668. package/src/runtime/routes/schedule-routes.ts +82 -0
  669. package/src/runtime/routes/sequence-routes.ts +291 -0
  670. package/src/runtime/routes/settings-routes.ts +2 -10
  671. package/src/runtime/routes/skills-routes.ts +31 -1
  672. package/src/runtime/routes/stt-routes.ts +240 -3
  673. package/src/runtime/routes/surface-action-routes.ts +43 -7
  674. package/src/runtime/routes/tts-routes.ts +67 -0
  675. package/src/runtime/routes/types.ts +32 -0
  676. package/src/runtime/routes/user-routes-cli.ts +243 -0
  677. package/src/runtime/routes/webhook-routes.ts +165 -0
  678. package/src/runtime/sync/resource-sync-events.ts +25 -0
  679. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  680. package/src/runtime/sync/sync-publisher.ts +21 -0
  681. package/src/schedule/scheduler.ts +200 -123
  682. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  683. package/src/security/secret-patterns.ts +3 -0
  684. package/src/sequence/engine.ts +38 -40
  685. package/src/skills/include-graph.ts +35 -13
  686. package/src/subagent/manager.ts +20 -15
  687. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  688. package/src/tools/browser/browser-execution.ts +15 -4
  689. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  690. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  691. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  692. package/src/tools/browser/cdp-client/factory.ts +66 -5
  693. package/src/tools/browser/runtime-check.ts +77 -0
  694. package/src/tools/document/document-tool.ts +20 -0
  695. package/src/tools/executor.ts +18 -2
  696. package/src/tools/memory/register.test.ts +10 -8
  697. package/src/tools/memory/register.ts +9 -1
  698. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  699. package/src/tools/network/web-search.ts +280 -37
  700. package/src/tools/permission-checker.ts +28 -5
  701. package/src/tools/skills/load.ts +24 -20
  702. package/src/tools/subagent/spawn.ts +3 -3
  703. package/src/tools/terminal/shell.ts +44 -0
  704. package/src/tools/tool-name-aliases.ts +19 -0
  705. package/src/tools/types.ts +19 -1
  706. package/src/usage/attribution.ts +3 -2
  707. package/src/util/pricing.ts +86 -160
  708. package/src/watcher/__tests__/engine.test.ts +301 -0
  709. package/src/watcher/constants.ts +7 -0
  710. package/src/watcher/engine.ts +90 -90
  711. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  712. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  713. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  714. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
  715. package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
  716. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  717. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  718. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  719. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  720. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  721. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  722. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  723. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  724. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  725. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  726. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  727. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  728. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  729. package/src/workspace/migrations/registry.ts +28 -0
  730. package/src/workspace/migrations/runner.ts +13 -2
  731. package/src/workspace/migrations/types.ts +13 -3
  732. package/src/workspace/provider-commit-message-generator.ts +3 -2
  733. package/src/__tests__/context-search-pkb-source.test.ts +0 -492
  734. package/src/__tests__/credentials-cli.test.ts +0 -1225
  735. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  736. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  737. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  738. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  739. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  740. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  741. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  742. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  743. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  744. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  745. package/src/cli/commands/autonomy.ts +0 -365
  746. package/src/cli/commands/memory.ts +0 -424
  747. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
  748. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  749. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  750. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  751. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  752. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  753. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  754. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  755. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  756. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  757. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  758. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  759. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  760. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  761. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  762. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  763. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  764. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  765. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  766. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  767. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  768. package/src/home/assistant-feed-authoring.ts +0 -135
  769. package/src/home/emit-feed-event.ts +0 -169
  770. package/src/home/feed-scheduler.ts +0 -281
  771. package/src/home/platform-gmail-digest.ts +0 -163
  772. package/src/home/rewrite-command-preview.ts +0 -66
  773. package/src/home/rewrite-feed-title.ts +0 -58
  774. package/src/home/rollup-producer.ts +0 -426
  775. package/src/memory/admin.ts +0 -326
  776. package/src/memory/context-search/sources/pkb.ts +0 -477
  777. package/src/memory/graph/compaction.ts +0 -299
  778. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -1,57 +1,45 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
-
4
1
  import type { Command } from "commander";
5
2
 
6
- import { getConfig } from "../../config/loader.js";
7
- import { resolveSkillStates } from "../../config/skill-state.js";
8
- import { loadSkillCatalog } from "../../config/skills.js";
9
- import type { CatalogSkill } from "../../skills/catalog-install.js";
10
- import {
11
- fetchCatalog,
12
- getRepoSkillsDir,
13
- installSkillLocally,
14
- readLocalCatalog,
15
- uninstallSkillLocally,
16
- } from "../../skills/catalog-install.js";
17
- import { filterByQuery } from "../../skills/catalog-search.js";
18
- import { clawhubSearch } from "../../skills/clawhub.js";
19
- import { readInstallMeta } from "../../skills/install-meta.js";
20
- import type {
21
- AuditResponse,
22
- SkillsShSearchResult,
23
- } from "../../skills/skillssh-registry.js";
24
- import {
25
- fetchSkillAudits,
26
- formatAuditBadges,
27
- installExternalSkill,
28
- resolveSkillSource,
29
- searchSkillsRegistry,
30
- } from "../../skills/skillssh-registry.js";
31
- import { getWorkspaceSkillsDir } from "../../util/platform.js";
3
+ import { cliIpcCall, exitFromIpcResult } from "../../ipc/cli-client.js";
4
+ import { registerCommand } from "../lib/register-command.js";
32
5
  import { log } from "../logger.js";
33
6
 
34
7
  // ---------------------------------------------------------------------------
35
- // Helpers
8
+ // Internal helpers
36
9
  // ---------------------------------------------------------------------------
37
10
 
38
- function formatDate(iso: string): string {
39
- try {
40
- const d = new Date(iso);
41
- const date = d.toLocaleDateString("en-US", {
42
- year: "numeric",
43
- month: "short",
44
- day: "numeric",
45
- });
46
- const time = d.toLocaleTimeString("en-US", {
47
- hour: "numeric",
48
- minute: "2-digit",
49
- hour12: true,
50
- });
51
- return `${date} ${time}`;
52
- } catch {
53
- return iso;
11
+ /**
12
+ * Map an IPC failure to a CLI exit code, mirroring `exitFromIpcResult`'s
13
+ * status→exit table without calling `process.exit` (so callers can flush
14
+ * stdout before the process tears down).
15
+ */
16
+ function exitCodeFromStatus(statusCode: number | undefined): number {
17
+ if (statusCode === undefined) return 10;
18
+ if (statusCode >= 500) return 3;
19
+ if (statusCode >= 400) return 2;
20
+ return 1;
21
+ }
22
+
23
+ /**
24
+ * Surface an IPC failure on a CLI command that supports `--json`. When `json`
25
+ * is true, emit a `{ok:false,error}` document to stdout and set `exitCode`
26
+ * without writing to stderr — so machine readers can parse output uniformly
27
+ * across success and failure paths. When `json` is false, fall back to
28
+ * `exitFromIpcResult` for the existing stderr-write + `process.exit`
29
+ * behaviour, preserving the human-mode UX.
30
+ */
31
+ function exitFromCliResult(
32
+ r: { ok: false; error?: string; statusCode?: number },
33
+ json: boolean,
34
+ ): void {
35
+ if (json) {
36
+ console.log(
37
+ JSON.stringify({ ok: false, error: r.error ?? "Unknown error" }),
38
+ );
39
+ process.exitCode = exitCodeFromStatus(r.statusCode);
40
+ return;
54
41
  }
42
+ exitFromIpcResult(r);
55
43
  }
56
44
 
57
45
  // ---------------------------------------------------------------------------
@@ -59,13 +47,14 @@ function formatDate(iso: string): string {
59
47
  // ---------------------------------------------------------------------------
60
48
 
61
49
  export function registerSkillsCommand(program: Command): void {
62
- const skills = program
63
- .command("skills")
64
- .description("Browse and install skills from the Vellum catalog");
65
-
66
- skills.addHelpText(
67
- "after",
68
- `
50
+ registerCommand(program, {
51
+ name: "skills",
52
+ transport: "ipc",
53
+ description: "Browse and install skills from the Vellum catalog",
54
+ build: (skills) => {
55
+ skills.addHelpText(
56
+ "after",
57
+ `
69
58
  Manage skills from the Vellum catalog. Skills extend the assistant's
70
59
  capabilities with pre-built workflows and tools.
71
60
 
@@ -81,15 +70,15 @@ Examples:
81
70
  $ assistant skills uninstall weather
82
71
  $ assistant skills add vercel-labs/skills@find-skills
83
72
  $ assistant skills add vercel-labs/skills/find-skills --overwrite`,
84
- );
85
-
86
- skills
87
- .command("list")
88
- .description("List bundled and installed skills")
89
- .option("--json", "Machine-readable JSON output")
90
- .addHelpText(
91
- "after",
92
- `
73
+ );
74
+
75
+ skills
76
+ .command("list")
77
+ .description("List bundled and installed skills")
78
+ .option("--json", "Machine-readable JSON output")
79
+ .addHelpText(
80
+ "after",
81
+ `
93
82
  Lists all bundled and installed skills with their source, state, and
94
83
  description. Use 'assistant skills inspect <id>' for detailed metadata
95
84
  or 'assistant skills search' to discover catalog skills.
@@ -97,70 +86,61 @@ or 'assistant skills search' to discover catalog skills.
97
86
  Examples:
98
87
  $ assistant skills list
99
88
  $ assistant skills list --json`,
100
- )
101
- .action(async (opts: { json?: boolean }) => {
102
- try {
103
- const localCatalog = loadSkillCatalog();
104
- const config = getConfig();
105
- const resolved = resolveSkillStates(localCatalog, config);
106
-
107
- // Flat alphabetical list — source is a property, not a section
108
- const allSkills = resolved
109
- .map((r) => {
110
- const s = r.summary;
111
- const source =
112
- s.source === "bundled" || s.source === "plugin"
113
- ? "bundled"
114
- : s.source; // managed, workspace, extra
115
- return {
89
+ )
90
+ .action(async (opts: { json?: boolean }, _cmd) => {
91
+ const r = await cliIpcCall<{
92
+ skills: Array<{
93
+ id: string;
94
+ name: string;
95
+ description: string;
96
+ emoji?: string;
97
+ origin: string;
98
+ kind: string;
99
+ status: string;
100
+ }>;
101
+ }>("listSkills", { queryParams: {} });
102
+ if (!r.ok)
103
+ return exitFromCliResult(
104
+ { ok: false, error: r.error, statusCode: r.statusCode },
105
+ opts.json ?? false,
106
+ );
107
+ const allSkills = r
108
+ .result!.skills.map((s) => ({
116
109
  id: s.id,
117
- name: s.displayName,
110
+ name: s.name,
118
111
  description: s.description,
119
112
  emoji: s.emoji,
120
- source,
121
- state: r.state,
122
- };
123
- })
124
- .sort((a, b) => a.id.localeCompare(b.id));
125
-
126
- if (opts.json) {
127
- console.log(JSON.stringify({ ok: true, skills: allSkills }));
128
- return;
129
- }
130
-
131
- if (allSkills.length === 0) {
132
- log.info("No skills available.");
133
- return;
134
- }
135
-
136
- log.info(`Skills (${allSkills.length}):\n`);
137
- for (const s of allSkills) {
138
- const emoji = s.emoji ? `${s.emoji} ` : "";
139
- const tags = [
140
- s.source,
141
- ...(s.state === "disabled" ? ["disabled"] : []),
142
- ];
143
- log.info(` ${emoji}${s.id} [${tags.join(", ")}]`);
144
- log.info(` ${s.name} — ${s.description}`);
145
- }
146
- } catch (err) {
147
- const msg = err instanceof Error ? err.message : String(err);
148
- if (opts.json) {
149
- console.log(JSON.stringify({ ok: false, error: msg }));
150
- } else {
151
- log.error(`Error: ${msg}`);
152
- }
153
- process.exitCode = 1;
154
- }
155
- });
156
-
157
- skills
158
- .command("inspect <skill-id>")
159
- .description("Show detailed information about a skill")
160
- .option("--json", "Machine-readable JSON output")
161
- .addHelpText(
162
- "after",
163
- `
113
+ source:
114
+ s.origin === "vellum" && s.kind === "bundled"
115
+ ? "bundled"
116
+ : s.origin,
117
+ state: s.status,
118
+ }))
119
+ .sort((a, b) => a.id.localeCompare(b.id));
120
+ if (opts.json) {
121
+ console.log(JSON.stringify({ ok: true, skills: allSkills }));
122
+ return;
123
+ }
124
+ if (allSkills.length === 0) {
125
+ log.info("No skills available.");
126
+ return;
127
+ }
128
+ log.info(`Skills (${allSkills.length}):\n`);
129
+ for (const s of allSkills) {
130
+ const emoji = s.emoji ? `${s.emoji} ` : "";
131
+ const tags = [s.source, ...(s.state === "disabled" ? ["disabled"] : [])];
132
+ log.info(` ${emoji}${s.id} [${tags.join(", ")}]`);
133
+ log.info(` ${s.name} — ${s.description}`);
134
+ }
135
+ });
136
+
137
+ skills
138
+ .command("inspect <skill-id>")
139
+ .description("Show detailed information about a skill")
140
+ .option("--json", "Machine-readable JSON output")
141
+ .addHelpText(
142
+ "after",
143
+ `
164
144
  Arguments:
165
145
  skill-id Skill identifier. Run 'assistant skills list' to see available IDs.
166
146
 
@@ -171,154 +151,103 @@ entries, tool manifest, activation hints, and feature flags.
171
151
  Examples:
172
152
  $ assistant skills inspect slack
173
153
  $ assistant skills inspect resend-setup --json`,
174
- )
175
- .action(async (skillId: string, opts: { json?: boolean }) => {
176
- try {
177
- const localCatalog = loadSkillCatalog();
178
- const config = getConfig();
179
- const resolved = resolveSkillStates(localCatalog, config);
180
-
181
- const match = resolved.find((r) => r.summary.id === skillId);
182
- if (!match) {
183
- throw new Error(
184
- `Skill "${skillId}" not found. Run 'assistant skills list' to see available skills.`,
185
- );
186
- }
187
-
188
- const { summary, state, configEntry } = match;
189
- const installMeta = readInstallMeta(summary.directoryPath);
190
-
191
- const detail: Record<string, unknown> = {
192
- id: summary.id,
193
- name: summary.displayName,
194
- description: summary.description,
195
- emoji: summary.emoji ?? null,
196
- source: summary.source,
197
- state,
198
- directoryPath: summary.directoryPath,
199
- featureFlag: summary.featureFlag ?? null,
200
- activationHints: summary.activationHints ?? null,
201
- avoidWhen: summary.avoidWhen ?? null,
202
- includes: summary.includes ?? null,
203
- toolManifest: summary.toolManifest
204
- ? {
205
- valid: summary.toolManifest.valid,
206
- toolCount: summary.toolManifest.toolCount,
207
- toolNames: summary.toolManifest.toolNames,
208
- }
209
- : null,
210
- installMeta: installMeta ?? null,
211
- config: configEntry
212
- ? {
213
- enabled: configEntry.enabled !== false,
214
- envKeys: configEntry.env
215
- ? Object.keys(configEntry.env)
216
- : [],
217
- configKeys: configEntry.config
218
- ? Object.keys(configEntry.config)
219
- : [],
220
- }
221
- : null,
222
- };
223
-
224
- if (opts.json) {
225
- console.log(JSON.stringify({ ok: true, skill: detail }));
226
- return;
227
- }
228
-
229
- const emoji = summary.emoji ? `${summary.emoji} ` : "";
230
- log.info(`${emoji}${summary.displayName} (${summary.id})`);
231
- log.info(` ${summary.description}\n`);
232
- log.info(` Source: ${summary.source}`);
233
- log.info(` State: ${state}`);
234
- log.info(` Path: ${summary.directoryPath}`);
235
- if (summary.featureFlag) {
236
- log.info(` Flag: ${summary.featureFlag}`);
237
- }
238
- if (summary.includes?.length) {
239
- log.info(` Includes: ${summary.includes.join(", ")}`);
240
- }
241
- if (summary.activationHints?.length) {
242
- log.info(` Hints: ${summary.activationHints.join("; ")}`);
243
- }
244
- if (summary.avoidWhen?.length) {
245
- log.info(` Avoid: ${summary.avoidWhen.join("; ")}`);
246
- }
247
-
248
- if (summary.toolManifest) {
249
- const tm = summary.toolManifest;
250
- log.info(
251
- `\n Tools: ${tm.valid ? `${tm.toolCount} tool(s)` : "invalid manifest"}`,
252
- );
253
- if (tm.toolNames.length > 0) {
254
- for (const name of tm.toolNames) {
255
- log.info(` - ${name}`);
256
- }
257
- }
258
- }
259
-
260
- if (installMeta) {
261
- log.info(`\n Install metadata:`);
262
- log.info(` Origin: ${installMeta.origin}`);
263
- log.info(` Installed: ${installMeta.installedAt}`);
264
- if (installMeta.installedBy) {
265
- log.info(` Installed by: ${installMeta.installedBy}`);
266
- }
267
- if (installMeta.version) {
268
- log.info(` Version: ${installMeta.version}`);
269
- }
270
- if (installMeta.slug) {
271
- log.info(` Slug: ${installMeta.slug}`);
272
- }
273
- if (installMeta.sourceRepo) {
274
- log.info(` Source repo: ${installMeta.sourceRepo}`);
275
- }
276
- if (installMeta.contentHash) {
277
- log.info(` Hash: ${installMeta.contentHash}`);
278
- }
279
- if (installMeta.backfilledBy) {
280
- log.info(` Backfilled: ${installMeta.backfilledBy}`);
281
- }
282
- }
283
-
284
- if (configEntry) {
285
- log.info(`\n Config:`);
286
- log.info(
287
- ` Enabled: ${configEntry.enabled !== false ? "yes" : "no"}`,
288
- );
289
- if (configEntry.env && Object.keys(configEntry.env).length > 0) {
290
- log.info(` Env vars: ${Object.keys(configEntry.env).join(", ")}`);
154
+ )
155
+ .action(async (skillId: string, opts: { json?: boolean }, _cmd) => {
156
+ const r = await cliIpcCall<{
157
+ id: string;
158
+ name: string;
159
+ description: string;
160
+ emoji: string | null;
161
+ source: string;
162
+ state: string;
163
+ directoryPath: string;
164
+ featureFlag: string | null;
165
+ includes: string[] | null;
166
+ activationHints: string[] | null;
167
+ avoidWhen: string[] | null;
168
+ toolManifest: {
169
+ valid: boolean;
170
+ toolCount: number;
171
+ toolNames: string[];
172
+ } | null;
173
+ installMeta: Record<string, unknown> | null;
174
+ config: {
175
+ enabled: boolean;
176
+ envKeys: string[];
177
+ configKeys: string[];
178
+ } | null;
179
+ }>("skillsLocalInspect", { pathParams: { id: skillId } });
180
+ if (!r.ok)
181
+ return exitFromCliResult(
182
+ { ok: false, error: r.error, statusCode: r.statusCode },
183
+ opts.json ?? false,
184
+ );
185
+ const detail = r.result!;
186
+ if (opts.json) {
187
+ console.log(JSON.stringify({ ok: true, skill: detail }));
188
+ return;
291
189
  }
292
- if (
293
- configEntry.config &&
294
- Object.keys(configEntry.config).length > 0
295
- ) {
190
+ const emoji = detail.emoji ? `${detail.emoji} ` : "";
191
+ log.info(`${emoji}${detail.name} (${detail.id})`);
192
+ log.info(` ${detail.description}\n`);
193
+ log.info(` Source: ${detail.source}`);
194
+ log.info(` State: ${detail.state}`);
195
+ log.info(` Path: ${detail.directoryPath}`);
196
+ if (detail.featureFlag) log.info(` Flag: ${detail.featureFlag}`);
197
+ if (detail.includes?.length)
198
+ log.info(` Includes: ${detail.includes.join(", ")}`);
199
+ if (detail.activationHints?.length)
200
+ log.info(` Hints: ${detail.activationHints.join("; ")}`);
201
+ if (detail.avoidWhen?.length)
202
+ log.info(` Avoid: ${detail.avoidWhen.join("; ")}`);
203
+ if (detail.toolManifest) {
204
+ const tm = detail.toolManifest;
296
205
  log.info(
297
- ` Config keys: ${Object.keys(configEntry.config).join(", ")}`,
206
+ `\n Tools: ${tm.valid ? `${tm.toolCount} tool(s)` : "invalid manifest"}`,
298
207
  );
208
+ for (const name of tm.toolNames) log.info(` - ${name}`);
209
+ }
210
+ if (detail.installMeta) {
211
+ log.info(`\n Install metadata:`);
212
+ if (detail.installMeta.origin)
213
+ log.info(` Origin: ${detail.installMeta.origin}`);
214
+ if (detail.installMeta.installedAt)
215
+ log.info(` Installed: ${detail.installMeta.installedAt}`);
216
+ if (detail.installMeta.installedBy)
217
+ log.info(` Installed by: ${detail.installMeta.installedBy}`);
218
+ if (detail.installMeta.version)
219
+ log.info(` Version: ${detail.installMeta.version}`);
220
+ if (detail.installMeta.slug)
221
+ log.info(` Slug: ${detail.installMeta.slug}`);
222
+ if (detail.installMeta.sourceRepo)
223
+ log.info(` Source repo: ${detail.installMeta.sourceRepo}`);
224
+ if (detail.installMeta.contentHash)
225
+ log.info(` Hash: ${detail.installMeta.contentHash}`);
226
+ if (detail.installMeta.backfilledBy)
227
+ log.info(` Backfilled: ${detail.installMeta.backfilledBy}`);
228
+ }
229
+ if (detail.config) {
230
+ log.info(`\n Config:`);
231
+ log.info(` Enabled: ${detail.config.enabled ? "yes" : "no"}`);
232
+ if (detail.config.envKeys.length)
233
+ log.info(` Env vars: ${detail.config.envKeys.join(", ")}`);
234
+ if (detail.config.configKeys.length)
235
+ log.info(
236
+ ` Config keys: ${detail.config.configKeys.join(", ")}`,
237
+ );
299
238
  }
300
- }
301
- } catch (err) {
302
- const msg = err instanceof Error ? err.message : String(err);
303
- if (opts.json) {
304
- console.log(JSON.stringify({ ok: false, error: msg }));
305
- } else {
306
- log.error(`Error: ${msg}`);
307
- }
308
- process.exitCode = 1;
309
- }
310
- });
311
-
312
- skills
313
- .command("search <query>")
314
- .description(
315
- "Search the Vellum catalog, skills.sh, and clawhub community registries",
316
- )
317
- .option("--limit <n>", "Maximum number of community results", "10")
318
- .option("--json", "Machine-readable JSON output")
319
- .addHelpText(
320
- "after",
321
- `
239
+ });
240
+
241
+ skills
242
+ .command("search <query>")
243
+ .description(
244
+ "Search the Vellum catalog, skills.sh, and clawhub community registries",
245
+ )
246
+ .option("--limit <n>", "Maximum number of community results", "10")
247
+ .option("--json", "Machine-readable JSON output")
248
+ .addHelpText(
249
+ "after",
250
+ `
322
251
  Arguments:
323
252
  query Free-text search term matched against skill names, descriptions,
324
253
  and tags. Searches the Vellum catalog, the skills.sh community
@@ -332,302 +261,157 @@ Examples:
332
261
  $ assistant skills search react
333
262
  $ assistant skills search "file management" --limit 3
334
263
  $ assistant skills search deploy --json`,
335
- )
336
- .action(async (query: string, opts: { limit: string; json?: boolean }) => {
337
- const json = opts.json ?? false;
338
- const limit = parseInt(opts.limit, 10) || 10;
339
-
340
- try {
341
- // ── Bundled + installed skill search ─────────────────────────
342
- const localCatalog = loadSkillCatalog();
343
- const bundledMatches = filterByQuery(localCatalog, query, [
344
- (s) => s.id,
345
- (s) => s.displayName,
346
- (s) => s.description,
347
- ]);
348
-
349
- // ── Vellum catalog search ────────────────────────────────────
350
- const repoSkillsDir = getRepoSkillsDir();
351
- let catalog: CatalogSkill[];
352
- if (repoSkillsDir) {
353
- catalog = readLocalCatalog(repoSkillsDir);
354
- } else {
355
- try {
356
- catalog = await fetchCatalog();
357
- } catch {
358
- catalog = [];
359
- }
360
- }
361
- const localIds = new Set(localCatalog.map((s) => s.id));
362
-
363
- const catalogMatches = filterByQuery(catalog, query, [
364
- (s) => s.id,
365
- (s) => s.name,
366
- (s) => s.description,
367
- ]);
368
-
369
- // ── Community registry searches (non-fatal on failure) ────────
370
- // Run skills.sh and clawhub searches in parallel.
371
- let registryResults: SkillsShSearchResult[] = [];
372
- let registryError: string | undefined;
373
- let clawhubResults: Awaited<
374
- ReturnType<typeof clawhubSearch>
375
- >["skills"] = [];
376
- let clawhubError: string | undefined;
377
-
378
- const [skillsShResult, clawhubResult] = await Promise.allSettled([
379
- searchSkillsRegistry(query, limit),
380
- clawhubSearch(query, { limit }),
381
- ]);
382
-
383
- if (skillsShResult.status === "fulfilled") {
384
- registryResults = skillsShResult.value;
385
- } else {
386
- registryError =
387
- skillsShResult.reason instanceof Error
388
- ? skillsShResult.reason.message
389
- : String(skillsShResult.reason);
390
- }
391
-
392
- if (clawhubResult.status === "fulfilled") {
393
- clawhubResults = clawhubResult.value.skills;
394
- } else {
395
- clawhubError =
396
- clawhubResult.reason instanceof Error
397
- ? clawhubResult.reason.message
398
- : String(clawhubResult.reason);
399
- }
400
-
401
- if (
402
- bundledMatches.length === 0 &&
403
- catalogMatches.length === 0 &&
404
- registryResults.length === 0 &&
405
- clawhubResults.length === 0
406
- ) {
264
+ )
265
+ .action(async (query: string, opts: { limit: string; json?: boolean }) => {
266
+ const json = opts.json ?? false;
267
+ const limit = parseInt(opts.limit, 10) || 10;
268
+
269
+ // Step 1: Vellum catalog (installed + remote available)
270
+ const catalogR = await cliIpcCall<{
271
+ skills: Array<{
272
+ id: string;
273
+ name: string;
274
+ description: string;
275
+ emoji?: string;
276
+ origin: string;
277
+ kind: string;
278
+ status: string;
279
+ updatedAt?: string;
280
+ }>;
281
+ }>("listSkills", { queryParams: { include: "catalog", q: query } });
282
+ const vellumSkills = catalogR.ok
283
+ ? catalogR.result!.skills.filter((s) => s.origin === "vellum")
284
+ : [];
285
+
286
+ // Step 2: community (skills.sh with audits + clawhub) + local bundled/installed
287
+ const communityR = await cliIpcCall<{
288
+ skills: Array<{
289
+ id: string;
290
+ name: string;
291
+ description: string;
292
+ emoji?: string;
293
+ origin: string;
294
+ kind: string;
295
+ status: string;
296
+ slug?: string;
297
+ author?: string;
298
+ stars?: number;
299
+ installs?: number;
300
+ publishedAt?: string;
301
+ version?: string;
302
+ sourceRepo?: string;
303
+ }>;
304
+ }>("searchSkills", { queryParams: { q: query, limit: String(limit) } });
305
+ const communitySkills = communityR.ok
306
+ ? communityR.result!.skills.filter((s) => s.origin !== "vellum")
307
+ : [];
308
+
309
+ // Deduplicate by id — vellum wins
310
+ const seen = new Set(vellumSkills.map((s) => s.id));
311
+ const dedupedCommunity = communitySkills.filter((s) => {
312
+ if (seen.has(s.id)) return false;
313
+ seen.add(s.id);
314
+ return true;
315
+ });
316
+ const clawhubResults = dedupedCommunity
317
+ .filter((s) => s.origin === "clawhub")
318
+ .slice(0, limit);
319
+ const skillsshResults = dedupedCommunity
320
+ .filter((s) => s.origin === "skillssh")
321
+ .slice(0, limit);
322
+
323
+ const hasResults =
324
+ vellumSkills.length > 0 ||
325
+ clawhubResults.length > 0 ||
326
+ skillsshResults.length > 0;
327
+
407
328
  if (json) {
408
329
  console.log(
409
330
  JSON.stringify({
410
331
  ok: true,
411
- bundled: [],
412
- catalog: [],
413
- community: [],
414
- clawhub: [],
415
- audits: {},
416
- ...(registryError ? { registryError } : {}),
417
- ...(clawhubError ? { clawhubError } : {}),
332
+ catalog: vellumSkills,
333
+ community: skillsshResults,
334
+ clawhub: clawhubResults,
335
+ ...(catalogR.ok ? {} : { catalogError: catalogR.error }),
336
+ ...(communityR.ok ? {} : { communityError: communityR.error }),
418
337
  }),
419
338
  );
420
- } else {
421
- log.info(`No skills found for "${query}".`);
422
- if (registryError) {
423
- log.warn(`(skills.sh registry unavailable: ${registryError})`);
424
- }
425
- if (clawhubError) {
426
- log.warn(`(clawhub registry unavailable: ${clawhubError})`);
427
- }
428
- }
429
- return;
430
- }
431
-
432
- // ── Fetch audits for community results ───────────────────────
433
- const allAudits: AuditResponse = {};
434
- if (registryResults.length > 0) {
435
- const sourceToSlugs = new Map<string, string[]>();
436
- for (const r of registryResults) {
437
- const slugs = sourceToSlugs.get(r.source) ?? [];
438
- slugs.push(r.skillId);
439
- sourceToSlugs.set(r.source, slugs);
339
+ return;
440
340
  }
441
- for (const [source, slugs] of sourceToSlugs) {
442
- try {
443
- const audits = await fetchSkillAudits(source, slugs);
444
- for (const [skillId, auditData] of Object.entries(audits)) {
445
- allAudits[`${source}/${skillId}`] = auditData;
446
- }
447
- } catch {
448
- // Audit fetch failures are non-fatal
449
- }
341
+
342
+ if (!hasResults) {
343
+ log.info(`No skills found for "${query}".`);
344
+ if (!catalogR.ok)
345
+ log.warn(`(Vellum catalog unavailable: ${catalogR.error})`);
346
+ if (!communityR.ok)
347
+ log.warn(`(Community registry unavailable: ${communityR.error})`);
348
+ return;
450
349
  }
451
- }
452
-
453
- if (json) {
454
- console.log(
455
- JSON.stringify({
456
- ok: true,
457
- bundled: bundledMatches.map((s) => ({
458
- id: s.id,
459
- name: s.displayName,
460
- description: s.description,
461
- emoji: s.emoji,
462
- source: s.source,
463
- })),
464
- catalog: catalogMatches,
465
- community: registryResults,
466
- clawhub: clawhubResults,
467
- audits: allAudits,
468
- ...(registryError ? { registryError } : {}),
469
- ...(clawhubError ? { clawhubError } : {}),
470
- }),
471
- );
472
- return;
473
- }
474
-
475
- // ── Installed-state detection ─────────────────────────────────
476
- const skillsDir = getWorkspaceSkillsDir();
477
- const isInstalled = (id: string) =>
478
- existsSync(join(skillsDir, id, "SKILL.md"));
479
- const getInstalledDate = (id: string): string | undefined => {
480
- const meta = readInstallMeta(join(skillsDir, id));
481
- return meta?.installedAt;
482
- };
483
-
484
- // ── Display installed results ─────────────────────────────────
485
- if (bundledMatches.length > 0) {
486
- log.info(`Installed skills (${bundledMatches.length}):\n`);
487
- for (const s of bundledMatches) {
488
- const emoji = s.emoji ? `${s.emoji} ` : "";
489
- const tag =
490
- s.source === "bundled" || s.source === "plugin"
491
- ? " [bundled]"
492
- : "";
493
- log.info(` ${emoji}${s.displayName}${tag}`);
494
- if (s.displayName !== s.id) {
495
- log.info(` ID: ${s.id}`);
496
- }
497
- log.info(` ${s.description}`);
498
- if (s.source !== "bundled" && s.source !== "plugin") {
499
- const meta = readInstallMeta(s.directoryPath);
500
- if (meta?.installedAt) {
501
- log.info(` Installed: ${formatDate(meta.installedAt)}`);
502
- }
350
+
351
+ if (vellumSkills.length > 0) {
352
+ log.info(`Vellum catalog (${vellumSkills.length}):\n`);
353
+ for (const s of vellumSkills) {
354
+ const emoji = s.emoji ? `${s.emoji} ` : "";
355
+ const badge = s.kind === "installed" ? " [installed]" : "";
356
+ log.info(` ${emoji}${s.name}${badge}`);
357
+ if (s.name !== s.id) log.info(` ID: ${s.id}`);
358
+ log.info(` ${s.description}`);
359
+ if (s.updatedAt) log.info(` Updated: ${s.updatedAt}`);
360
+ if (s.kind !== "installed")
361
+ log.info(` Install: assistant skills install ${s.id}`);
362
+ log.info("");
503
363
  }
504
- log.info("");
505
364
  }
506
- }
507
365
 
508
- // ── Display catalog results ──────────────────────────────────
509
- if (catalogMatches.length > 0) {
510
- log.info(`Vellum catalog (${catalogMatches.length}):\n`);
511
- for (const s of catalogMatches) {
512
- const emoji = s.emoji ? `${s.emoji} ` : "";
513
- const installed = isInstalled(s.id);
514
- const badge = installed ? " [installed]" : "";
515
- log.info(` ${emoji}${s.name}${badge}`);
516
- if (s.name !== s.id) {
517
- log.info(` ID: ${s.id}`);
366
+ if (skillsshResults.length > 0) {
367
+ log.info(`Community — skills.sh (${skillsshResults.length}):\n`);
368
+ for (const r of skillsshResults) {
369
+ const badge = r.kind === "installed" ? " [installed]" : "";
370
+ log.info(` ${r.name}${badge}`);
371
+ if (r.name !== r.id) log.info(` ID: ${r.id}`);
372
+ if (r.sourceRepo) log.info(` Source: ${r.sourceRepo}`);
373
+ if (r.installs !== undefined)
374
+ log.info(` Installs: ${r.installs}`);
375
+ if (r.kind !== "installed")
376
+ // Use the fully-qualified 3-segment id (owner/repo/skill) — this
377
+ // matches the `owner/repo/skill-name` form accepted by
378
+ // `resolveSkillSource()`. Building `sourceRepo@slug` fails for
379
+ // skills.sh because the registry returns `slug` as the full id,
380
+ // producing `owner/repo@owner/repo/skill` which the parser rejects.
381
+ log.info(` Install: assistant skills add ${r.id}`);
382
+ log.info("");
518
383
  }
519
- log.info(` ${s.description}`);
520
- if (s.updatedAt) {
521
- log.info(` Updated: ${formatDate(s.updatedAt)}`);
522
- }
523
- if (installed) {
524
- const installedDate = getInstalledDate(s.id);
525
- if (installedDate) {
526
- log.info(` Installed: ${formatDate(installedDate)}`);
527
- }
528
- } else {
529
- log.info(` Install: assistant skills install ${s.id}`);
530
- }
531
-
532
- log.info("");
384
+ } else if (!communityR.ok) {
385
+ log.warn(
386
+ `\n(skills.sh registry unavailable: ${communityR.error})`,
387
+ );
533
388
  }
534
- }
535
-
536
- // ── Display community results ────────────────────────────────
537
- if (registryResults.length > 0) {
538
- log.info(`Community — skills.sh (${registryResults.length}):\n`);
539
- for (const r of registryResults) {
540
- const installed = isInstalled(r.skillId);
541
- const installedFromVellum = localIds.has(r.skillId);
542
- const badge = installedFromVellum
543
- ? " [installed from catalog]"
544
- : installed
545
- ? " [installed]"
546
- : "";
547
- log.info(` ${r.name}${badge}`);
548
- if (r.name !== r.skillId) {
549
- log.info(` ID: ${r.skillId}`);
550
- }
551
- log.info(` Source: ${r.source}`);
552
- log.info(` Installs: ${r.installs}`);
553
- const auditData = allAudits[`${r.source}/${r.skillId}`];
554
- if (auditData) {
555
- log.info(` ${formatAuditBadges(auditData)}`);
556
- } else {
557
- log.info(" Security: no audit data");
558
- }
559
- if (!installed) {
560
- log.info(
561
- ` Install: assistant skills add ${r.source}@${r.skillId}`,
562
- );
563
- }
564
389
 
565
- log.info("");
566
- }
567
- } else if (registryError) {
568
- log.warn(`\n(skills.sh registry unavailable: ${registryError})`);
569
- }
570
-
571
- // ── Display clawhub results ─────────────────────────────────
572
- if (clawhubResults.length > 0) {
573
- log.info(`Community — Clawhub (${clawhubResults.length}):\n`);
574
- for (const r of clawhubResults) {
575
- const installed = isInstalled(r.slug);
576
- const installedFromVellum = localIds.has(r.slug);
577
- const badge = installedFromVellum
578
- ? " [installed from catalog]"
579
- : installed
580
- ? " [installed]"
581
- : "";
582
- log.info(` ${r.name}${badge}`);
583
- if (r.name !== r.slug) {
584
- log.info(` ID: ${r.slug}`);
585
- }
586
- if (r.author) {
587
- log.info(` Author: ${r.author}`);
588
- }
589
- if (r.description) {
590
- log.info(` ${r.description}`);
591
- }
592
- if (r.createdAt > 0) {
593
- log.info(
594
- ` Updated: ${formatDate(new Date(r.createdAt).toISOString())}`,
595
- );
390
+ if (clawhubResults.length > 0) {
391
+ log.info(`Community — Clawhub (${clawhubResults.length}):\n`);
392
+ for (const r of clawhubResults) {
393
+ const badge = r.kind === "installed" ? " [installed]" : "";
394
+ log.info(` ${r.name}${badge}`);
395
+ if (r.name !== r.id) log.info(` ID: ${r.id}`);
396
+ if (r.author) log.info(` Author: ${r.author}`);
397
+ if (r.description) log.info(` ${r.description}`);
398
+ if (r.stars) log.info(` Stars: ${r.stars}`);
399
+ if (r.installs) log.info(` Installs: ${r.installs}`);
400
+ if (r.kind !== "installed")
401
+ log.info(` Install: npx clawhub install ${r.slug ?? r.id}`);
402
+ log.info("");
596
403
  }
597
- if (r.stars > 0) {
598
- log.info(` Stars: ${r.stars}`);
599
- }
600
- if (r.installs > 0) {
601
- log.info(` Installs: ${r.installs}`);
602
- }
603
- if (!installed) {
604
- log.info(` Install: npx clawhub install ${r.slug}`);
605
- }
606
-
607
- log.info("");
608
404
  }
609
- } else if (clawhubError) {
610
- log.warn(`\n(clawhub registry unavailable: ${clawhubError})`);
611
- }
612
- } catch (err) {
613
- const msg = err instanceof Error ? err.message : String(err);
614
- if (json) {
615
- console.log(JSON.stringify({ ok: false, error: msg }));
616
- } else {
617
- log.error(`Error: ${msg}`);
618
- }
619
- process.exitCode = 1;
620
- }
621
- });
622
-
623
- skills
624
- .command("install <skill-id>")
625
- .description("Install a skill from the catalog")
626
- .option("--overwrite", "Replace an already installed skill")
627
- .option("--json", "Machine-readable JSON output")
628
- .addHelpText(
629
- "after",
630
- `
405
+ });
406
+
407
+ skills
408
+ .command("install <skill-id>")
409
+ .description("Install a skill from the catalog")
410
+ .option("--overwrite", "Replace an already installed skill")
411
+ .option("--json", "Machine-readable JSON output")
412
+ .addHelpText(
413
+ "after",
414
+ `
631
415
  Arguments:
632
416
  skill-id Skill identifier from the Vellum catalog. Run 'assistant skills list'
633
417
  to see available IDs. For community skills, use 'assistant skills add'.
@@ -639,62 +423,54 @@ Examples:
639
423
  $ assistant skills install weather
640
424
  $ assistant skills install weather --overwrite
641
425
  $ assistant skills install weather --json`,
642
- )
643
- .action(
644
- async (
645
- skillId: string,
646
- opts: { overwrite?: boolean; json?: boolean },
647
- ) => {
648
- const json = opts.json ?? false;
649
-
650
- try {
651
- // In dev mode, also check the repo-local skills/ directory
652
- const repoSkillsDir = getRepoSkillsDir();
653
- let localSkills: CatalogSkill[] = [];
654
- if (repoSkillsDir) {
655
- localSkills = readLocalCatalog(repoSkillsDir);
656
- }
657
-
658
- // Check local catalog first, then fall back to remote
659
- let entry = localSkills.find((s) => s.id === skillId);
660
- if (!entry) {
661
- const catalog = await fetchCatalog();
662
- entry = catalog.find((s) => s.id === skillId);
663
- }
664
-
665
- if (!entry) {
666
- throw new Error(
667
- `Skill "${skillId}" not found in the Vellum catalog`,
426
+ )
427
+ .action(
428
+ async (
429
+ skillId: string,
430
+ opts: { overwrite?: boolean; json?: boolean },
431
+ _cmd,
432
+ ) => {
433
+ const json = opts.json ?? false;
434
+
435
+ // Restrict to catalog-only; community installs use `skills add`.
436
+ const installR = await cliIpcCall<{ ok: boolean; skillId?: string }>(
437
+ "installSkill",
438
+ { body: { slug: skillId, overwrite: opts.overwrite ?? false, catalogOnly: true } },
668
439
  );
669
- }
670
-
671
- // Fetch, extract, and install
672
- await installSkillLocally(skillId, entry, opts.overwrite ?? false);
673
-
674
- if (json) {
675
- console.log(JSON.stringify({ ok: true, skillId }));
676
- } else {
677
- log.info(`Installed skill "${skillId}".`);
678
- }
679
- } catch (err) {
680
- const msg = err instanceof Error ? err.message : String(err);
681
- if (json) {
682
- console.log(JSON.stringify({ ok: false, error: msg }));
683
- } else {
684
- log.error(`Error: ${msg}`);
685
- }
686
- process.exitCode = 1;
687
- }
688
- },
689
- );
440
+ if (!installR.ok) {
441
+ if (json) {
442
+ console.log(
443
+ JSON.stringify({
444
+ ok: false,
445
+ error: installR.error,
446
+ }),
447
+ );
448
+ process.exitCode = 1;
449
+ return;
450
+ }
451
+ log.error(installR.error);
452
+ log.error(
453
+ `Run 'assistant skills search ${skillId}' to check available skills.`,
454
+ );
455
+ process.exitCode = 1;
456
+ return;
457
+ }
690
458
 
691
- skills
692
- .command("uninstall <skill-id>")
693
- .description("Uninstall a previously installed skill")
694
- .option("--json", "Machine-readable JSON output")
695
- .addHelpText(
696
- "after",
697
- `
459
+ if (json) {
460
+ console.log(JSON.stringify({ ok: true, skillId }));
461
+ } else {
462
+ log.info(`Installed skill "${skillId}".`);
463
+ }
464
+ },
465
+ );
466
+
467
+ skills
468
+ .command("uninstall <skill-id>")
469
+ .description("Uninstall a previously installed skill")
470
+ .option("--json", "Machine-readable JSON output")
471
+ .addHelpText(
472
+ "after",
473
+ `
698
474
  Arguments:
699
475
  skill-id Skill identifier to remove. Run 'assistant skills list' to see
700
476
  installed skills.
@@ -704,39 +480,33 @@ Removes the skill directory from the workspace. This action cannot be undone.
704
480
  Examples:
705
481
  $ assistant skills uninstall weather
706
482
  $ assistant skills uninstall weather --json`,
707
- )
708
- .action(async (skillId: string, opts: { json?: boolean }) => {
709
- const json = opts.json ?? false;
710
-
711
- try {
712
- uninstallSkillLocally(skillId);
713
-
714
- if (json) {
715
- console.log(JSON.stringify({ ok: true, skillId }));
716
- } else {
717
- log.info(`Uninstalled skill "${skillId}".`);
718
- }
719
- } catch (err) {
720
- const msg = err instanceof Error ? err.message : String(err);
721
- if (json) {
722
- console.log(JSON.stringify({ ok: false, error: msg }));
723
- } else {
724
- log.error(`Error: ${msg}`);
725
- }
726
- process.exitCode = 1;
727
- }
728
- });
729
-
730
- skills
731
- .command("add <source>")
732
- .description(
733
- "Install a community skill from the skills.sh registry (GitHub)",
734
- )
735
- .option("--overwrite", "Replace an already installed skill")
736
- .option("--json", "Machine-readable JSON output")
737
- .addHelpText(
738
- "after",
739
- `
483
+ )
484
+ .action(async (skillId: string, opts: { json?: boolean }, _cmd) => {
485
+ const r = await cliIpcCall<null>("deleteSkill", {
486
+ pathParams: { id: skillId },
487
+ });
488
+ if (!r.ok)
489
+ return exitFromCliResult(
490
+ { ok: false, error: r.error, statusCode: r.statusCode },
491
+ opts.json ?? false,
492
+ );
493
+ if (opts.json) {
494
+ console.log(JSON.stringify({ ok: true, skillId }));
495
+ } else {
496
+ log.info(`Uninstalled skill "${skillId}".`);
497
+ }
498
+ });
499
+
500
+ skills
501
+ .command("add <source>")
502
+ .description(
503
+ "Install a community skill from the skills.sh registry (GitHub)",
504
+ )
505
+ .option("--overwrite", "Replace an already installed skill")
506
+ .option("--json", "Machine-readable JSON output")
507
+ .addHelpText(
508
+ "after",
509
+ `
740
510
  Arguments:
741
511
  source Skill source in one of these formats:
742
512
  owner/repo@skill-name
@@ -752,42 +522,50 @@ Examples:
752
522
  $ assistant skills add vercel-labs/skills@find-skills
753
523
  $ assistant skills add vercel-labs/skills/find-skills
754
524
  $ assistant skills add vercel-labs/skills@find-skills --overwrite`,
755
- )
756
- .action(
757
- async (source: string, opts: { overwrite?: boolean; json?: boolean }) => {
758
- const json = opts.json ?? false;
759
-
760
- try {
761
- const { owner, repo, skillSlug, ref } = resolveSkillSource(source);
762
-
763
- await installExternalSkill(
764
- owner,
765
- repo,
766
- skillSlug,
767
- opts.overwrite ?? false,
768
- ref,
769
- );
770
-
771
- if (json) {
772
- console.log(
773
- JSON.stringify({
774
- ok: true,
775
- skillSlug,
776
- source: `${owner}/${repo}`,
777
- }),
525
+ )
526
+ .action(
527
+ async (
528
+ source: string,
529
+ opts: { overwrite?: boolean; json?: boolean },
530
+ _cmd,
531
+ ) => {
532
+ const json = opts.json ?? false;
533
+
534
+ // `add` is the community-install entry point (skills.sh-flavoured
535
+ // sources: `owner/repo@skill`, `owner/repo/skill`, or full GitHub
536
+ // URL). Pass `origin: "skillssh"` so the daemon routes via
537
+ // `resolveSkillSource()` + `installExternalSkill()` regardless of
538
+ // slug shape — the auto-detect (`looksLikeSkillsShSlug`) only
539
+ // recognises 3-segment `/`-delimited slugs, so the `@`-format
540
+ // documented in the help text otherwise misroutes to clawhub.
541
+ const r = await cliIpcCall<{ ok: boolean; skillId?: string }>(
542
+ "installSkill",
543
+ {
544
+ body: {
545
+ slug: source,
546
+ origin: "skillssh",
547
+ overwrite: opts.overwrite ?? false,
548
+ },
549
+ },
778
550
  );
779
- } else {
780
- log.info(`Installed skill "${skillSlug}" from ${owner}/${repo}.`);
781
- }
782
- } catch (err) {
783
- const msg = err instanceof Error ? err.message : String(err);
784
- if (json) {
785
- console.log(JSON.stringify({ ok: false, error: msg }));
786
- } else {
787
- log.error(`Error: ${msg}`);
788
- }
789
- process.exitCode = 1;
790
- }
791
- },
792
- );
551
+ if (!r.ok)
552
+ return exitFromCliResult(
553
+ { ok: false, error: r.error, statusCode: r.statusCode },
554
+ json,
555
+ );
556
+
557
+ if (json) {
558
+ console.log(
559
+ JSON.stringify({
560
+ ok: true,
561
+ skillId: r.result?.skillId ?? source,
562
+ }),
563
+ );
564
+ } else {
565
+ log.info(`Installed skill from ${source}.`);
566
+ }
567
+ },
568
+ );
569
+ },
570
+ });
793
571
  }