@vellumai/assistant 0.8.10 → 0.8.11-dev.202606112057.e4bc22e

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 (417) hide show
  1. package/bun.lock +63 -118
  2. package/docs/workspace-tools.md +196 -0
  3. package/examples/plugins/echo/README.md +3 -3
  4. package/knip.json +1 -0
  5. package/openapi.yaml +578 -128
  6. package/package.json +2 -3
  7. package/scripts/build-plugin-api.ts +299 -0
  8. package/src/__tests__/agent-loop-callsite-precedence.test.ts +7 -0
  9. package/src/__tests__/agent-loop-compaction-events.test.ts +197 -0
  10. package/src/__tests__/agent-loop-exit-reason.test.ts +93 -96
  11. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +2 -0
  12. package/src/__tests__/agent-loop-output-hooks.test.ts +274 -1
  13. package/src/__tests__/agent-loop-override-profile.test.ts +3 -0
  14. package/src/__tests__/agent-loop-provider-error-recording.test.ts +4 -0
  15. package/src/__tests__/agent-loop-thinking.test.ts +4 -0
  16. package/src/__tests__/agent-loop.test.ts +578 -5
  17. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -1
  18. package/src/__tests__/approval-cascade.test.ts +1 -0
  19. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  20. package/src/__tests__/btw-routes.test.ts +7 -35
  21. package/src/__tests__/build-persisted-content.test.ts +75 -1
  22. package/src/__tests__/catalog-install-normalize.test.ts +141 -0
  23. package/src/__tests__/ces-startup-timeout.test.ts +60 -0
  24. package/src/__tests__/compaction-events.test.ts +1 -0
  25. package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
  26. package/src/__tests__/context-overflow-reducer.test.ts +264 -124
  27. package/src/__tests__/context-window-manager-overflow-rung.test.ts +351 -0
  28. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  29. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -5
  30. package/src/__tests__/conversation-agent-loop-overflow.test.ts +284 -455
  31. package/src/__tests__/conversation-agent-loop.test.ts +131 -551
  32. package/src/__tests__/conversation-app-control-instantiation.test.ts +13 -0
  33. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  34. package/src/__tests__/conversation-error.test.ts +2 -6
  35. package/src/__tests__/conversation-fork-crud.test.ts +259 -0
  36. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  37. package/src/__tests__/conversation-lifecycle.test.ts +257 -1
  38. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  39. package/src/__tests__/conversation-provider-retry-repair.test.ts +38 -377
  40. package/src/__tests__/conversation-queue.test.ts +1 -39
  41. package/src/__tests__/conversation-runtime-assembly.test.ts +119 -8
  42. package/src/__tests__/conversation-skill-tools.test.ts +491 -5
  43. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  44. package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
  45. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  46. package/src/__tests__/conversation-store.test.ts +74 -0
  47. package/src/__tests__/conversation-surfaces-app-control.test.ts +4 -1
  48. package/src/__tests__/conversation-tool-setup-attribution.test.ts +323 -0
  49. package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +34 -0
  50. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  51. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  52. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -0
  53. package/src/__tests__/corrected-target.test.ts +93 -0
  54. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -5
  55. package/src/__tests__/credential-execution-tools.test.ts +23 -11
  56. package/src/__tests__/credential-security-invariants.test.ts +6 -1
  57. package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
  58. package/src/__tests__/device-id.test.ts +70 -1
  59. package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
  60. package/src/__tests__/empty-response-hook.test.ts +242 -66
  61. package/src/__tests__/external-plugin-loader.test.ts +0 -31
  62. package/src/__tests__/get-skill-detail-audit.test.ts +43 -1
  63. package/src/__tests__/guardian-routing-invariants.test.ts +91 -0
  64. package/src/__tests__/history-repair-hook.test.ts +228 -3
  65. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  66. package/src/__tests__/host-browser-proxy.test.ts +254 -9
  67. package/src/__tests__/identity-intro-cache.test.ts +12 -5
  68. package/src/__tests__/identity-routes.test.ts +17 -57
  69. package/src/__tests__/image-recovery-hook.test.ts +387 -0
  70. package/src/__tests__/injector-chain.test.ts +5 -4
  71. package/src/__tests__/injector-v3-suppression.test.ts +373 -47
  72. package/src/__tests__/intent-routing.test.ts +7 -0
  73. package/src/__tests__/memory-retrieval-hook.test.ts +117 -15
  74. package/src/__tests__/model-intents.test.ts +1 -1
  75. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  76. package/src/__tests__/oauth-store.test.ts +0 -85
  77. package/src/__tests__/{context-overflow-policy.test.ts → overflow-policy.test.ts} +1 -1
  78. package/src/__tests__/parallel-tool.benchmark.test.ts +4 -0
  79. package/src/__tests__/persist-unsendable-image-downscale.test.ts +29 -9
  80. package/src/__tests__/persist-unsendable-image.test.ts +4 -4
  81. package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
  82. package/src/__tests__/plugin-bootstrap.test.ts +82 -73
  83. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  84. package/src/__tests__/plugin-types.test.ts +0 -8
  85. package/src/__tests__/provider-catalog-visibility.test.ts +1 -9
  86. package/src/__tests__/prune-old-conversations-job.test.ts +99 -0
  87. package/src/__tests__/registry.test.ts +240 -1
  88. package/src/__tests__/require-fresh-approval.test.ts +3 -0
  89. package/src/__tests__/schedule-routes.test.ts +116 -1
  90. package/src/__tests__/schedule-store.test.ts +28 -0
  91. package/src/__tests__/schedule-tools.test.ts +94 -1
  92. package/src/__tests__/server-history-render.test.ts +39 -0
  93. package/src/__tests__/skill-projection-feature-flag.test.ts +13 -0
  94. package/src/__tests__/skill-projection.benchmark.test.ts +25 -7
  95. package/src/__tests__/skills.test.ts +202 -0
  96. package/src/__tests__/slim-skill-category.test.ts +195 -0
  97. package/src/__tests__/strip-memory-injections.test.ts +33 -39
  98. package/src/__tests__/test-support/tool-invocation-seed.ts +79 -0
  99. package/src/__tests__/title-generate-hook.test.ts +9 -7
  100. package/src/__tests__/tool-audit-listener.test.ts +264 -1
  101. package/src/__tests__/tool-error-hook.test.ts +4 -3
  102. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
  103. package/src/__tests__/tool-executor-lifecycle-events.test.ts +273 -0
  104. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
  105. package/src/__tests__/tool-start-timestamp.test.ts +218 -0
  106. package/src/__tests__/tools-get-route.test.ts +202 -0
  107. package/src/__tests__/workspace-tool-loader.test.ts +319 -0
  108. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  109. package/src/agent/loop.ts +569 -319
  110. package/src/api/events/tool-result.ts +9 -0
  111. package/src/api/events/tool-use-start.ts +7 -0
  112. package/src/api/events/usage-progress.ts +28 -0
  113. package/src/api/index.ts +16 -0
  114. package/src/api/responses/conversation-message.ts +135 -27
  115. package/src/api/responses/memory-v3-selection-log.ts +4 -4
  116. package/src/approvals/guardian-request-resolvers.ts +26 -0
  117. package/src/browser-session/backends/host-bridge.ts +29 -0
  118. package/src/browser-session/index.ts +1 -0
  119. package/src/browser-session/types.ts +5 -1
  120. package/src/bundler/app-bundler.ts +25 -42
  121. package/src/cli/commands/__tests__/schedules.test.ts +62 -4
  122. package/src/cli/commands/__tests__/skills.test.ts +53 -0
  123. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  124. package/src/cli/commands/inference-providers.ts +0 -8
  125. package/src/cli/commands/plugins.ts +2 -2
  126. package/src/cli/commands/schedules.ts +27 -4
  127. package/src/cli/commands/skills.ts +187 -146
  128. package/src/cli/commands/tools.ts +106 -0
  129. package/src/cli/lib/__tests__/install-from-github.test.ts +256 -328
  130. package/src/cli/lib/__tests__/plugin-artifact.test.ts +116 -0
  131. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +6 -2
  132. package/src/cli/lib/__tests__/plugin-details.test.ts +166 -16
  133. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +2 -2
  134. package/src/cli/lib/__tests__/search-plugins.test.ts +145 -240
  135. package/src/cli/lib/install-from-github.ts +187 -117
  136. package/src/cli/lib/plugin-artifact.ts +84 -0
  137. package/src/cli/lib/plugin-catalog-cache.ts +9 -9
  138. package/src/cli/lib/plugin-details.ts +56 -69
  139. package/src/cli/lib/plugin-marketplace.ts +42 -14
  140. package/src/cli/lib/search-plugins.ts +29 -129
  141. package/src/cli/program.ts +2 -0
  142. package/src/config/bundled-skills/acp/SKILL.md +1 -0
  143. package/src/config/bundled-skills/app-builder/SKILL.md +1 -0
  144. package/src/config/bundled-skills/app-control/SKILL.md +1 -0
  145. package/src/config/bundled-skills/computer-use/SKILL.md +1 -0
  146. package/src/config/bundled-skills/contacts/SKILL.md +1 -0
  147. package/src/config/bundled-skills/document-editor/SKILL.md +1 -0
  148. package/src/config/bundled-skills/followups/SKILL.md +1 -0
  149. package/src/config/bundled-skills/image-studio/SKILL.md +1 -0
  150. package/src/config/bundled-skills/media-processing/SKILL.md +1 -0
  151. package/src/config/bundled-skills/messaging/SKILL.md +1 -0
  152. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -0
  153. package/src/config/bundled-skills/playbooks/SKILL.md +1 -0
  154. package/src/config/bundled-skills/schedule/SKILL.md +1 -0
  155. package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
  156. package/src/config/bundled-skills/sequences/SKILL.md +1 -0
  157. package/src/config/bundled-skills/settings/SKILL.md +1 -0
  158. package/src/config/bundled-skills/skill-management/SKILL.md +101 -1
  159. package/src/config/bundled-skills/subagent/SKILL.md +1 -0
  160. package/src/config/bundled-skills/transcribe/SKILL.md +1 -0
  161. package/src/config/env-registry.ts +23 -0
  162. package/src/config/feature-flag-registry.json +17 -89
  163. package/src/config/loader.ts +5 -22
  164. package/src/config/schema.ts +2 -0
  165. package/src/config/schemas/__tests__/compaction-logs.test.ts +56 -0
  166. package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
  167. package/src/config/schemas/__tests__/memory-v3.test.ts +61 -1
  168. package/src/config/schemas/compaction-logs.ts +79 -0
  169. package/src/config/schemas/memory-v2.ts +0 -8
  170. package/src/config/schemas/memory-v3.ts +104 -33
  171. package/src/config/seed-inference-profiles.ts +1 -1
  172. package/src/config/skills.ts +117 -47
  173. package/src/context/compactor.ts +11 -0
  174. package/src/context/strip-injections.ts +38 -4
  175. package/src/credential-execution/feature-gates.ts +0 -21
  176. package/src/credential-execution/startup-timeout.ts +32 -4
  177. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
  178. package/src/daemon/conversation-agent-loop-handlers.ts +140 -91
  179. package/src/daemon/conversation-agent-loop.ts +123 -658
  180. package/src/daemon/conversation-error.ts +12 -48
  181. package/src/daemon/conversation-lifecycle.ts +1 -1
  182. package/src/daemon/conversation-runtime-assembly.ts +183 -22
  183. package/src/daemon/conversation-skill-tools.ts +137 -8
  184. package/src/daemon/conversation-slash.ts +0 -14
  185. package/src/daemon/conversation-store.ts +2 -19
  186. package/src/daemon/conversation-tool-setup.ts +87 -1
  187. package/src/daemon/conversation.ts +119 -50
  188. package/src/daemon/external-plugins-bootstrap.ts +36 -95
  189. package/src/daemon/handlers/config-channels.ts +11 -2
  190. package/src/daemon/handlers/shared.ts +9 -1
  191. package/src/daemon/handlers/skills.ts +10 -4
  192. package/src/daemon/host-app-control-proxy.ts +72 -57
  193. package/src/daemon/host-browser-proxy.ts +117 -22
  194. package/src/daemon/lifecycle.ts +34 -5
  195. package/src/daemon/message-protocol.ts +0 -7
  196. package/src/daemon/message-types/conversations.ts +2 -15
  197. package/src/daemon/message-types/schedules.ts +1 -0
  198. package/src/daemon/message-types/skills.ts +17 -0
  199. package/src/daemon/providers-setup.ts +3 -0
  200. package/src/daemon/server.ts +3 -3
  201. package/src/daemon/tool-setup-types.ts +9 -3
  202. package/src/daemon/trust-context.ts +23 -0
  203. package/src/daemon/workspace-tools-watcher.ts +324 -0
  204. package/src/events/tool-audit-listener.ts +78 -16
  205. package/src/events/tool-metrics-listener.ts +2 -5
  206. package/src/media/image-credentials.ts +2 -2
  207. package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +227 -0
  208. package/src/memory/__tests__/conversation-queries.test.ts +176 -0
  209. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
  210. package/src/memory/compaction-log-writer-clickhouse.ts +418 -0
  211. package/src/memory/conversation-attention-store.ts +1 -0
  212. package/src/memory/conversation-crud.ts +134 -3
  213. package/src/memory/conversation-queries.ts +64 -7
  214. package/src/memory/db-init.ts +14 -0
  215. package/src/memory/delivery-channels.ts +0 -69
  216. package/src/memory/embedding-backend.test.ts +130 -1
  217. package/src/memory/embedding-backend.ts +79 -106
  218. package/src/memory/embedding-gemini.ts +5 -0
  219. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +12 -0
  220. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
  221. package/src/memory/graph/conversation-graph-memory.ts +36 -25
  222. package/src/memory/graph/tool-handlers.ts +3 -0
  223. package/src/memory/job-handlers/cleanup.ts +3 -1
  224. package/src/memory/jobs-store.ts +0 -28
  225. package/src/memory/jobs-worker.ts +10 -22
  226. package/src/memory/memory-marker.ts +29 -0
  227. package/src/memory/memory-retrospective-startup-cleanup.ts +1 -1
  228. package/src/memory/migrations/268-add-memory-v3-selections.ts +6 -0
  229. package/src/memory/migrations/270-schedule-description.ts +36 -0
  230. package/src/memory/migrations/275-tool-invocations-add-skill-id.test.ts +81 -0
  231. package/src/memory/migrations/275-tool-invocations-add-skill-id.ts +20 -0
  232. package/src/memory/migrations/276-tool-invocations-created-at-id-index.test.ts +68 -0
  233. package/src/memory/migrations/276-tool-invocations-created-at-id-index.ts +20 -0
  234. package/src/memory/migrations/277-add-memory-v3-ever-injected.ts +29 -0
  235. package/src/memory/migrations/278-tool-invocations-telemetry-columns.test.ts +96 -0
  236. package/src/memory/migrations/278-tool-invocations-telemetry-columns.ts +39 -0
  237. package/src/memory/migrations/279-create-skill-loaded-events.test.ts +84 -0
  238. package/src/memory/migrations/279-create-skill-loaded-events.ts +26 -0
  239. package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
  240. package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
  241. package/src/memory/migrations/index.ts +10 -0
  242. package/src/memory/migrations/registry.ts +8 -0
  243. package/src/memory/schema/conversations.ts +16 -0
  244. package/src/memory/schema/infrastructure.ts +26 -0
  245. package/src/memory/skill-loaded-events-store.test.ts +160 -0
  246. package/src/memory/skill-loaded-events-store.ts +95 -0
  247. package/src/memory/tool-executed-events-store.test.ts +219 -0
  248. package/src/memory/tool-executed-events-store.ts +102 -0
  249. package/src/memory/tool-usage-store.ts +15 -3
  250. package/src/memory/v2/__tests__/consolidation-job.test.ts +117 -12
  251. package/src/memory/v2/__tests__/consolidation-prompt-flag-gating-guard.test.ts +189 -0
  252. package/src/memory/v2/__tests__/injected-block-slugs.test.ts +90 -0
  253. package/src/memory/v2/__tests__/page-store.test.ts +33 -0
  254. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +88 -15
  255. package/src/memory/v2/activation-store.ts +50 -1
  256. package/src/memory/v2/consolidation-job.ts +113 -29
  257. package/src/memory/v2/injected-block-slugs.ts +79 -0
  258. package/src/memory/v2/injection.ts +6 -1
  259. package/src/memory/v2/prompts/consolidation.ts +414 -13
  260. package/src/memory/v2/router.ts +2 -28
  261. package/src/memory/v2/static-context.ts +1 -1
  262. package/src/memory/v2/types.ts +16 -0
  263. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  264. package/src/notifications/access-request-copy.ts +298 -0
  265. package/src/notifications/adapters/slack.ts +3 -3
  266. package/src/notifications/adapters/telegram.ts +2 -1
  267. package/src/notifications/copy-composer.ts +49 -267
  268. package/src/notifications/decision-engine.ts +16 -35
  269. package/src/notifications/home-feed-side-effect.ts +1 -6
  270. package/src/oauth/oauth-store.ts +0 -9
  271. package/src/permissions/checker.test.ts +83 -1
  272. package/src/permissions/checker.ts +25 -2
  273. package/src/permissions/gateway-threshold-reader.test.ts +182 -0
  274. package/src/permissions/gateway-threshold-reader.ts +80 -0
  275. package/src/platform/client.ts +1 -3
  276. package/src/platform/feature-gate.ts +3 -12
  277. package/src/plugin-api/constants.ts +4 -2
  278. package/src/plugin-api/index.ts +63 -11
  279. package/src/plugin-api/types.ts +236 -71
  280. package/src/plugins/defaults/compaction/compact.ts +66 -2
  281. package/src/plugins/defaults/compaction/context-overflow-reducer.ts +240 -32
  282. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  283. package/src/{daemon/context-overflow-policy.ts → plugins/defaults/compaction/overflow-policy.ts} +1 -1
  284. package/src/plugins/defaults/compaction/window-manager.ts +303 -1
  285. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +173 -0
  286. package/src/plugins/defaults/empty-response/hooks/stop.ts +11 -115
  287. package/src/plugins/defaults/empty-response/nudge-state-store.ts +46 -0
  288. package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +50 -0
  289. package/src/plugins/defaults/history-repair/hooks/stop.ts +22 -0
  290. package/src/plugins/defaults/history-repair/repair-state-store.ts +51 -0
  291. package/src/plugins/defaults/history-repair/terminal.ts +39 -2
  292. package/src/plugins/defaults/image-recovery/detect.ts +25 -0
  293. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +73 -0
  294. package/src/plugins/defaults/image-recovery/hooks/stop.ts +22 -0
  295. package/src/plugins/defaults/image-recovery/image-recovery-state-store.ts +48 -0
  296. package/src/plugins/defaults/image-recovery/package.json +14 -0
  297. package/src/{daemon/persist-unsendable-image.ts → plugins/defaults/image-recovery/recover.ts} +67 -14
  298. package/src/plugins/defaults/index.ts +71 -5
  299. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +76 -112
  300. package/src/plugins/defaults/memory-retrieval/hooks/{user-prompt-submit-temp.ts → user-prompt-submit.ts} +83 -74
  301. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +14 -8
  302. package/src/plugins/defaults/memory-retrieval/injectors.ts +2 -18
  303. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  304. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1157 -0
  305. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +683 -0
  306. package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +161 -140
  307. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +160 -0
  308. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +335 -316
  309. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +145 -53
  310. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +38 -1
  311. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +18 -8
  312. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +112 -71
  313. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +192 -51
  314. package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +4 -16
  315. package/src/plugins/defaults/memory-v3-shadow/card.test.ts +173 -0
  316. package/src/plugins/defaults/memory-v3-shadow/card.ts +116 -0
  317. package/src/plugins/defaults/memory-v3-shadow/core-set.test.ts +104 -0
  318. package/src/plugins/defaults/memory-v3-shadow/core-set.ts +59 -0
  319. package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.test.ts +305 -0
  320. package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.ts +278 -0
  321. package/src/plugins/defaults/memory-v3-shadow/hot-set.test.ts +138 -0
  322. package/src/plugins/defaults/memory-v3-shadow/hot-set.ts +85 -0
  323. package/src/plugins/defaults/memory-v3-shadow/injector.ts +331 -24
  324. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +119 -13
  325. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +169 -114
  326. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +47 -16
  327. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +144 -66
  328. package/src/plugins/defaults/memory-v3-shadow/prune.test.ts +758 -0
  329. package/src/plugins/defaults/memory-v3-shadow/prune.ts +471 -0
  330. package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +68 -16
  331. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +19 -12
  332. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +96 -43
  333. package/src/plugins/defaults/memory-v3-shadow/types.ts +34 -17
  334. package/src/plugins/defaults/title-generate/hooks/stop.ts +9 -11
  335. package/src/plugins/pipeline.ts +8 -5
  336. package/src/plugins/types.ts +5 -51
  337. package/src/providers/cache-control.ts +26 -0
  338. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -2
  339. package/src/providers/model-catalog.ts +13 -1
  340. package/src/providers/model-intents.ts +2 -2
  341. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +147 -0
  342. package/src/providers/openai/chat-completions-provider.ts +46 -0
  343. package/src/providers/openai/responses-provider.ts +45 -0
  344. package/src/providers/registry.ts +0 -8
  345. package/src/runtime/AGENTS.md +2 -0
  346. package/src/runtime/__tests__/agent-wake.test.ts +0 -1
  347. package/src/runtime/agent-wake.ts +13 -0
  348. package/src/runtime/routes/__tests__/acp-routes.test.ts +151 -0
  349. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
  350. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
  351. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -62
  352. package/src/runtime/routes/__tests__/plugins-routes.test.ts +32 -11
  353. package/src/runtime/routes/acp-routes.test.ts +106 -0
  354. package/src/runtime/routes/acp-routes.ts +248 -2
  355. package/src/runtime/routes/browser-tabs-routes.ts +1 -1
  356. package/src/runtime/routes/btw-routes.ts +0 -14
  357. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  358. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +0 -14
  359. package/src/runtime/routes/consolidation-routes.ts +6 -82
  360. package/src/runtime/routes/conversation-list-routes.ts +83 -5
  361. package/src/runtime/routes/conversation-management-routes.ts +125 -0
  362. package/src/runtime/routes/identity-intro-cache.ts +1 -1
  363. package/src/runtime/routes/identity-routes.ts +84 -20
  364. package/src/runtime/routes/inbound-message-handler.ts +0 -36
  365. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  366. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -45
  367. package/src/runtime/routes/plugins-routes.ts +49 -45
  368. package/src/runtime/routes/schedule-routes.ts +43 -5
  369. package/src/runtime/routes/settings-routes.ts +140 -15
  370. package/src/runtime/routes/skills-routes.ts +18 -6
  371. package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
  372. package/src/runtime/services/conversation-serializer.ts +38 -1
  373. package/src/runtime/verification-outbound-actions.ts +147 -2
  374. package/src/runtime/verification-templates.ts +29 -3
  375. package/src/schedule/schedule-store.ts +19 -0
  376. package/src/skills/catalog-install.ts +77 -13
  377. package/src/tasks/task-scheduler.ts +1 -0
  378. package/src/telemetry/types.ts +66 -1
  379. package/src/telemetry/usage-telemetry-reporter.test.ts +542 -13
  380. package/src/telemetry/usage-telemetry-reporter.ts +213 -20
  381. package/src/tools/apps/executors.ts +1 -1
  382. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +49 -2
  383. package/src/tools/browser/__tests__/browser-status.test.ts +29 -5
  384. package/src/tools/browser/browser-execution.ts +27 -9
  385. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +380 -4
  386. package/src/tools/browser/cdp-client/__tests__/host-bridge-cdp-client.test.ts +107 -0
  387. package/src/tools/browser/cdp-client/__tests__/types.test.ts +6 -1
  388. package/src/tools/browser/cdp-client/factory.ts +217 -17
  389. package/src/tools/browser/cdp-client/host-bridge-cdp-client.ts +67 -0
  390. package/src/tools/browser/cdp-client/types.ts +22 -2
  391. package/src/tools/credential-execution/make-authenticated-request.ts +2 -1
  392. package/src/tools/credential-execution/manage-secure-command-tool.ts +169 -164
  393. package/src/tools/credential-execution/run-authenticated-command.ts +2 -1
  394. package/src/tools/executor.ts +39 -7
  395. package/src/tools/registry.ts +387 -5
  396. package/src/tools/schedule/create.ts +16 -0
  397. package/src/tools/schedule/list.ts +12 -4
  398. package/src/tools/schedule/update.ts +12 -0
  399. package/src/tools/skills/load.ts +11 -6
  400. package/src/tools/terminal/safe-env.ts +2 -0
  401. package/src/tools/types.ts +65 -9
  402. package/src/tools/workspace-tools/loader.ts +673 -0
  403. package/src/usage/attribution.ts +28 -0
  404. package/src/util/device-id.ts +17 -3
  405. package/src/util/platform.ts +16 -0
  406. package/tsconfig.plugin-api.json +13 -0
  407. package/src/__tests__/plugin-external-api.test.ts +0 -68
  408. package/src/__tests__/plugin-skill-contribution.test.ts +0 -355
  409. package/src/daemon/message-types/browser.ts +0 -10
  410. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  411. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +0 -36
  412. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +0 -37
  413. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +0 -106
  414. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +0 -44
  415. package/src/plugins/defaults/memory-v3-shadow/working-set.ts +0 -91
  416. package/src/plugins/external-api.ts +0 -114
  417. package/src/plugins/plugin-skill-contributions.ts +0 -292
@@ -146,6 +146,59 @@ describe("skills list", () => {
146
146
  ).toEqual({});
147
147
  });
148
148
 
149
+ test("--json derives source from owner for plugin-resident skills", async () => {
150
+ /**
151
+ * Plugin-resident skills are mapped to kind:bundled/origin:vellum, so
152
+ * their attribution lives on `owner`. The CLI must surface that as
153
+ * `plugin:<id>` instead of collapsing to "bundled".
154
+ */
155
+
156
+ // GIVEN a plugin-resident skill (owner set) and a plain bundled skill
157
+ mockIpcResults = [
158
+ {
159
+ ok: true,
160
+ result: {
161
+ skills: [
162
+ {
163
+ id: "caveman",
164
+ name: "Caveman",
165
+ description: "Ultra-compressed communication mode",
166
+ origin: "vellum",
167
+ kind: "bundled",
168
+ status: "enabled",
169
+ owner: { kind: "plugin", id: "caveman" },
170
+ },
171
+ {
172
+ id: "weather",
173
+ name: "Weather",
174
+ description: "Get weather",
175
+ origin: "vellum",
176
+ kind: "bundled",
177
+ status: "enabled",
178
+ },
179
+ ],
180
+ },
181
+ },
182
+ ];
183
+
184
+ // WHEN listing skills as JSON
185
+ const { stdout } = await runCommand(["skills", "list", "--json"]);
186
+
187
+ // THEN the plugin skill's source is `plugin:<id>` and owner is preserved
188
+ const parsed = JSON.parse(stdout) as {
189
+ ok: boolean;
190
+ skills: Array<{ id: string; source: string; owner?: unknown }>;
191
+ };
192
+ const caveman = parsed.skills.find((s) => s.id === "caveman");
193
+ const weather = parsed.skills.find((s) => s.id === "weather");
194
+ expect(caveman?.source).toBe("plugin:caveman");
195
+ expect(caveman?.owner).toEqual({ kind: "plugin", id: "caveman" });
196
+
197
+ // AND a bundled skill with no owner keeps the "bundled" source label
198
+ expect(weather?.source).toBe("bundled");
199
+ expect(weather?.owner).toBeUndefined();
200
+ });
201
+
149
202
  test("IPC failure sets exitCode 1", async () => {
150
203
  mockIpcResults = [{ ok: false, error: "Connection refused" }];
151
204
 
@@ -79,7 +79,7 @@ export function registerChannelVerificationSessionsCommand(
79
79
  "after",
80
80
  `
81
81
  Verification sessions are used to verify guardian bindings and trusted
82
- contacts across channels (telegram, phone, slack). Three flows exist:
82
+ contacts across channels (telegram, phone, slack, email). Three flows exist:
83
83
 
84
84
  1. Inbound challenge — the assistant generates a secret code and waits
85
85
  for the guardian to send it back on the channel. Used when the
@@ -107,10 +107,10 @@ Examples:
107
107
  cvs
108
108
  .command("create")
109
109
  .description("Create a new verification session")
110
- .option("--channel <channel>", "Channel type (telegram, phone, slack)")
110
+ .option("--channel <channel>", "Channel type (telegram, phone, slack, email)")
111
111
  .option(
112
112
  "--destination <destination>",
113
- "Destination address for outbound verification (handle, phone number, or user ID)",
113
+ "Destination address for outbound verification (handle, phone number, user ID, or email address)",
114
114
  )
115
115
  .option("--rebind", "Replace existing guardian binding")
116
116
  .option(
@@ -140,7 +140,7 @@ Routes between three creation modes based on the provided options:
140
140
 
141
141
  2. Outbound: --channel <ch> --destination <dest>
142
142
  Sends a verification code to the given destination. Supports telegram
143
- (handle or chat ID), phone (E.164 number), and slack (user ID).
143
+ (handle or chat ID), phone (E.164 number), slack (user ID), and email.
144
144
  Use --rebind to replace an existing guardian binding.
145
145
 
146
146
  3. Inbound: --channel <ch> (no --destination)
@@ -240,7 +240,7 @@ Examples:
240
240
  )
241
241
  .requiredOption(
242
242
  "--channel <channel>",
243
- "Channel type (telegram, phone, slack)",
243
+ "Channel type (telegram, phone, slack, email)",
244
244
  )
245
245
  .option(
246
246
  "--origin-conversation-id <id>",
@@ -290,7 +290,7 @@ Examples:
290
290
  .description("Cancel all active verification sessions for a channel")
291
291
  .requiredOption(
292
292
  "--channel <channel>",
293
- "Channel type (telegram, phone, slack)",
293
+ "Channel type (telegram, phone, slack, email)",
294
294
  )
295
295
  .addHelpText(
296
296
  "after",
@@ -16,8 +16,6 @@
16
16
 
17
17
  import type { Command } from "commander";
18
18
 
19
- import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
20
- import { getConfig } from "../../config/loader.js";
21
19
  import { cliIpcCall } from "../../ipc/cli-client.js";
22
20
  import type { OAuth2Config } from "../../security/oauth2.js";
23
21
  import { startOAuth2Flow } from "../../security/oauth2.js";
@@ -343,12 +341,6 @@ function attachLoginChatgptSubcommand(providers: Command): void {
343
341
  .description("Authenticate with ChatGPT via browser OAuth flow")
344
342
  .option("--json", "Output as JSON")
345
343
  .action(async (opts: { json?: boolean }) => {
346
- const config = getConfig();
347
- if (!isAssistantFeatureFlagEnabled("chatgpt-subscription-auth", config)) {
348
- writeCliError("This feature is not yet available", opts.json);
349
- return;
350
- }
351
-
352
344
  try {
353
345
  // Step 1: Run browser-based PKCE OAuth flow
354
346
  process.stdout.write("Opening browser for ChatGPT authentication...\n");
@@ -55,7 +55,7 @@ Examples:
55
55
  plugins
56
56
  .command("install <name>")
57
57
  .description(
58
- "Install a plugin from vellum-ai/vellum-assistant/experimental/plugins/<name>",
58
+ "Install a plugin from the curated plugins/marketplace.json catalog",
59
59
  )
60
60
  .option("--force", "Overwrite an existing install")
61
61
  .option(
@@ -150,7 +150,7 @@ Examples:
150
150
  plugins
151
151
  .command("search <query>")
152
152
  .description(
153
- "Search vellum-ai/vellum-assistant/experimental/plugins for plugin names matching <query> (case-insensitive regex)",
153
+ "Search the plugins/marketplace.json catalog for plugin names matching <query> (case-insensitive regex)",
154
154
  )
155
155
  .option("--json", "Emit machine-readable JSON instead of a table")
156
156
  .action(async (query: string, opts: { json?: boolean }) => {
@@ -23,6 +23,7 @@ interface ScheduleRecord {
23
23
  maxRetries: number;
24
24
  retryBackoffMs: number;
25
25
  description: string | null;
26
+ cadenceDescription: string | null;
26
27
  mode: string;
27
28
  status: string;
28
29
  routingIntent: string;
@@ -64,9 +65,9 @@ export function registerSchedulesCommand(program: Command): void {
64
65
  Schedules are recurring or one-shot jobs run by the assistant.
65
66
 
66
67
  This CLI namespace is intentionally landing incrementally. Today it supports
67
- listing schedules, viewing recent run history, enabling/disabling schedules,
68
- manually executing a schedule one time, and cancelling pending one-shot schedules;
69
- create, delete, and run inspection will follow as separate slices.
68
+ creating schedules, listing schedules, viewing recent run history,
69
+ enabling/disabling schedules, manually executing a schedule one time, cancelling
70
+ pending one-shot schedules, and deleting schedules.
70
71
 
71
72
  Examples:
72
73
  $ assistant schedules list
@@ -318,6 +319,10 @@ Examples:
318
319
  "-e, --expression <expr>",
319
320
  "Cron or RRULE expression that schedules the fire times",
320
321
  )
322
+ .requiredOption(
323
+ "-d, --description <text>",
324
+ "Authored description explaining what the schedule is for",
325
+ )
321
326
  .requiredOption(
322
327
  "-m, --message <text>",
323
328
  "Message body sent to the assistant on each fire",
@@ -333,6 +338,7 @@ Examples:
333
338
  `
334
339
  Options:
335
340
  -e, --expression <expr> Cron (e.g. '*/30 * * * *') or RRULE expression.
341
+ -d, --description <text> Authored description explaining what the schedule is for.
336
342
  -m, --message <text> Message body sent on each fire.
337
343
  -t, --timezone <tz> IANA timezone applied to the expression.
338
344
  --no-enabled Create the schedule disabled. Defaults to enabled.
@@ -349,13 +355,16 @@ Behavior:
349
355
  Examples:
350
356
  $ assistant schedules create "Heartbeat" \\
351
357
  --expression '*/30 * * * *' \\
358
+ --description 'Checks service heartbeat every 30 minutes' \\
352
359
  --message 'run heartbeat'
353
360
  $ assistant schedules create "Morning summary" \\
354
361
  --expression '0 9 * * MON-FRI' \\
362
+ --description 'Summarizes weekday activity' \\
355
363
  --timezone America/New_York \\
356
364
  --message 'write the morning summary'
357
365
  $ assistant schedules create "Drafted" \\
358
366
  --expression '0 0 * * *' \\
367
+ --description 'Placeholder daily schedule' \\
359
368
  --message 'placeholder' \\
360
369
  --no-enabled --json`,
361
370
  )
@@ -364,6 +373,7 @@ Examples:
364
373
  name: string,
365
374
  opts: {
366
375
  expression: string;
376
+ description: string;
367
377
  message: string;
368
378
  timezone?: string;
369
379
  enabled: boolean;
@@ -383,9 +393,22 @@ Examples:
383
393
  return;
384
394
  }
385
395
 
396
+ const description = opts.description.trim();
397
+ if (!description) {
398
+ const error = "description is required";
399
+ if (opts.json) {
400
+ writeOutput(cmd, { ok: false, error });
401
+ } else {
402
+ log.error(error);
403
+ }
404
+ process.exitCode = 1;
405
+ return;
406
+ }
407
+
386
408
  const body: Record<string, unknown> = {
387
409
  name: scheduleName,
388
410
  expression: opts.expression,
411
+ description,
389
412
  message: opts.message,
390
413
  enabled: opts.enabled,
391
414
  };
@@ -662,7 +685,7 @@ async function toggleScheduleEnabled(
662
685
 
663
686
  function describeSchedule(schedule: ScheduleRecord): string {
664
687
  if (schedule.isOneShot) return "one-shot";
665
- const expression = schedule.description ?? schedule.expression ?? "—";
688
+ const expression = schedule.cadenceDescription ?? schedule.expression ?? "—";
666
689
  return schedule.timezone
667
690
  ? `${expression} (${schedule.timezone})`
668
691
  : expression;
@@ -97,6 +97,7 @@ Examples:
97
97
  origin: string;
98
98
  kind: string;
99
99
  status: string;
100
+ owner?: { kind: string; id: string };
100
101
  }>;
101
102
  }>("listSkills", { queryParams: {} });
102
103
  if (!r.ok)
@@ -104,16 +105,27 @@ Examples:
104
105
  { ok: false, error: r.error, statusCode: r.statusCode },
105
106
  opts.json ?? false,
106
107
  );
108
+ // Source labels the extension a skill ships from. Plugin-resident
109
+ // skills are intentionally mapped to kind:bundled/origin:vellum for
110
+ // older clients, so their real attribution lives on `owner` —
111
+ // surface it as `plugin:<id>` instead of collapsing to "bundled".
112
+ const sourceLabel = (s: {
113
+ origin: string;
114
+ kind: string;
115
+ owner?: { kind: string; id: string };
116
+ }): string => {
117
+ if (s.owner) return `${s.owner.kind}:${s.owner.id}`;
118
+ if (s.origin === "vellum" && s.kind === "bundled") return "bundled";
119
+ return s.origin;
120
+ };
107
121
  const allSkills = r
108
122
  .result!.skills.map((s) => ({
109
123
  id: s.id,
110
124
  name: s.name,
111
125
  description: s.description,
112
126
  emoji: s.emoji,
113
- source:
114
- s.origin === "vellum" && s.kind === "bundled"
115
- ? "bundled"
116
- : s.origin,
127
+ source: sourceLabel(s),
128
+ owner: s.owner,
117
129
  state: s.status,
118
130
  }))
119
131
  .sort((a, b) => a.id.localeCompare(b.id));
@@ -125,12 +137,22 @@ Examples:
125
137
  log.info("No skills available.");
126
138
  return;
127
139
  }
140
+ // Align ID / SOURCE / STATE into columns so source is scannable.
141
+ const idWidth = Math.max(2, ...allSkills.map((s) => s.id.length));
142
+ const srcWidth = Math.max(
143
+ 6,
144
+ ...allSkills.map((s) => s.source.length),
145
+ );
128
146
  log.info(`Skills (${allSkills.length}):\n`);
147
+ log.info(
148
+ ` ${"ID".padEnd(idWidth)} ${"SOURCE".padEnd(srcWidth)} STATE`,
149
+ );
129
150
  for (const s of allSkills) {
130
151
  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}`);
152
+ log.info(
153
+ ` ${s.id.padEnd(idWidth)} ${s.source.padEnd(srcWidth)} ${s.state}`,
154
+ );
155
+ log.info(` ${emoji}${s.name} — ${s.description}`);
134
156
  }
135
157
  });
136
158
 
@@ -193,7 +215,8 @@ Examples:
193
215
  log.info(` Source: ${detail.source}`);
194
216
  log.info(` State: ${detail.state}`);
195
217
  log.info(` Path: ${detail.directoryPath}`);
196
- if (detail.featureFlag) log.info(` Flag: ${detail.featureFlag}`);
218
+ if (detail.featureFlag)
219
+ log.info(` Flag: ${detail.featureFlag}`);
197
220
  if (detail.includes?.length)
198
221
  log.info(` Includes: ${detail.includes.join(", ")}`);
199
222
  if (detail.activationHints?.length)
@@ -228,7 +251,9 @@ Examples:
228
251
  }
229
252
  if (detail.config) {
230
253
  log.info(`\n Config:`);
231
- log.info(` Enabled: ${detail.config.enabled ? "yes" : "no"}`);
254
+ log.info(
255
+ ` Enabled: ${detail.config.enabled ? "yes" : "no"}`,
256
+ );
232
257
  if (detail.config.envKeys.length)
233
258
  log.info(` Env vars: ${detail.config.envKeys.join(", ")}`);
234
259
  if (detail.config.configKeys.length)
@@ -262,147 +287,157 @@ Examples:
262
287
  $ assistant skills search "file management" --limit 3
263
288
  $ assistant skills search deploy --json`,
264
289
  )
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
- : [];
290
+ .action(
291
+ async (query: string, opts: { limit: string; json?: boolean }) => {
292
+ const json = opts.json ?? false;
293
+ const limit = parseInt(opts.limit, 10) || 10;
294
+
295
+ // Step 1: Vellum catalog (installed + remote available)
296
+ const catalogR = await cliIpcCall<{
297
+ skills: Array<{
298
+ id: string;
299
+ name: string;
300
+ description: string;
301
+ emoji?: string;
302
+ origin: string;
303
+ kind: string;
304
+ status: string;
305
+ updatedAt?: string;
306
+ }>;
307
+ }>("listSkills", { queryParams: { include: "catalog", q: query } });
308
+ const vellumSkills = catalogR.ok
309
+ ? catalogR.result!.skills.filter((s) => s.origin === "vellum")
310
+ : [];
311
+
312
+ // Step 2: community (skills.sh with audits + clawhub) + local bundled/installed
313
+ const communityR = await cliIpcCall<{
314
+ skills: Array<{
315
+ id: string;
316
+ name: string;
317
+ description: string;
318
+ emoji?: string;
319
+ origin: string;
320
+ kind: string;
321
+ status: string;
322
+ slug?: string;
323
+ author?: string;
324
+ stars?: number;
325
+ installs?: number;
326
+ publishedAt?: string;
327
+ version?: string;
328
+ sourceRepo?: string;
329
+ }>;
330
+ }>("searchSkills", {
331
+ queryParams: { q: query, limit: String(limit) },
332
+ });
333
+ const communitySkills = communityR.ok
334
+ ? communityR.result!.skills.filter((s) => s.origin !== "vellum")
335
+ : [];
336
+
337
+ // Deduplicate by id — vellum wins
338
+ const seen = new Set(vellumSkills.map((s) => s.id));
339
+ const dedupedCommunity = communitySkills.filter((s) => {
340
+ if (seen.has(s.id)) return false;
341
+ seen.add(s.id);
342
+ return true;
343
+ });
344
+ const clawhubResults = dedupedCommunity
345
+ .filter((s) => s.origin === "clawhub")
346
+ .slice(0, limit);
347
+ const skillsshResults = dedupedCommunity
348
+ .filter((s) => s.origin === "skillssh")
349
+ .slice(0, limit);
350
+
351
+ const hasResults =
352
+ vellumSkills.length > 0 ||
353
+ clawhubResults.length > 0 ||
354
+ skillsshResults.length > 0;
285
355
 
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
-
328
- if (json) {
329
- console.log(
330
- JSON.stringify({
331
- ok: true,
332
- catalog: vellumSkills,
333
- community: skillsshResults,
334
- clawhub: clawhubResults,
335
- ...(catalogR.ok ? {} : { catalogError: catalogR.error }),
336
- ...(communityR.ok ? {} : { communityError: communityR.error }),
337
- }),
338
- );
339
- return;
340
- }
356
+ if (json) {
357
+ console.log(
358
+ JSON.stringify({
359
+ ok: true,
360
+ catalog: vellumSkills,
361
+ community: skillsshResults,
362
+ clawhub: clawhubResults,
363
+ ...(catalogR.ok ? {} : { catalogError: catalogR.error }),
364
+ ...(communityR.ok
365
+ ? {}
366
+ : { communityError: communityR.error }),
367
+ }),
368
+ );
369
+ return;
370
+ }
341
371
 
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;
349
- }
372
+ if (!hasResults) {
373
+ log.info(`No skills found for "${query}".`);
374
+ if (!catalogR.ok)
375
+ log.warn(`(Vellum catalog unavailable: ${catalogR.error})`);
376
+ if (!communityR.ok)
377
+ log.warn(
378
+ `(Community registry unavailable: ${communityR.error})`,
379
+ );
380
+ return;
381
+ }
350
382
 
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("");
383
+ if (vellumSkills.length > 0) {
384
+ log.info(`Vellum catalog (${vellumSkills.length}):\n`);
385
+ for (const s of vellumSkills) {
386
+ const emoji = s.emoji ? `${s.emoji} ` : "";
387
+ const badge = s.kind === "installed" ? " [installed]" : "";
388
+ log.info(` ${emoji}${s.name}${badge}`);
389
+ if (s.name !== s.id) log.info(` ID: ${s.id}`);
390
+ log.info(` ${s.description}`);
391
+ if (s.updatedAt) log.info(` Updated: ${s.updatedAt}`);
392
+ if (s.kind !== "installed")
393
+ log.info(` Install: assistant skills install ${s.id}`);
394
+ log.info("");
395
+ }
363
396
  }
364
- }
365
397
 
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("");
398
+ if (skillsshResults.length > 0) {
399
+ log.info(`Community — skills.sh (${skillsshResults.length}):\n`);
400
+ for (const r of skillsshResults) {
401
+ const badge = r.kind === "installed" ? " [installed]" : "";
402
+ log.info(` ${r.name}${badge}`);
403
+ if (r.name !== r.id) log.info(` ID: ${r.id}`);
404
+ if (r.sourceRepo) log.info(` Source: ${r.sourceRepo}`);
405
+ if (r.installs !== undefined)
406
+ log.info(` Installs: ${r.installs}`);
407
+ if (r.kind !== "installed")
408
+ // Use the fully-qualified 3-segment id (owner/repo/skill) — this
409
+ // matches the `owner/repo/skill-name` form accepted by
410
+ // `resolveSkillSource()`. Building `sourceRepo@slug` fails for
411
+ // skills.sh because the registry returns `slug` as the full id,
412
+ // producing `owner/repo@owner/repo/skill` which the parser rejects.
413
+ log.info(` Install: assistant skills add ${r.id}`);
414
+ log.info("");
415
+ }
416
+ } else if (!communityR.ok) {
417
+ log.warn(
418
+ `\n(skills.sh registry unavailable: ${communityR.error})`,
419
+ );
383
420
  }
384
- } else if (!communityR.ok) {
385
- log.warn(
386
- `\n(skills.sh registry unavailable: ${communityR.error})`,
387
- );
388
- }
389
421
 
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("");
422
+ if (clawhubResults.length > 0) {
423
+ log.info(`Community — Clawhub (${clawhubResults.length}):\n`);
424
+ for (const r of clawhubResults) {
425
+ const badge = r.kind === "installed" ? " [installed]" : "";
426
+ log.info(` ${r.name}${badge}`);
427
+ if (r.name !== r.id) log.info(` ID: ${r.id}`);
428
+ if (r.author) log.info(` Author: ${r.author}`);
429
+ if (r.description) log.info(` ${r.description}`);
430
+ if (r.stars) log.info(` Stars: ${r.stars}`);
431
+ if (r.installs) log.info(` Installs: ${r.installs}`);
432
+ if (r.kind !== "installed")
433
+ log.info(
434
+ ` Install: npx clawhub install ${r.slug ?? r.id}`,
435
+ );
436
+ log.info("");
437
+ }
403
438
  }
404
- }
405
- });
439
+ },
440
+ );
406
441
 
407
442
  skills
408
443
  .command("install <skill-id>")
@@ -433,10 +468,16 @@ Examples:
433
468
  const json = opts.json ?? false;
434
469
 
435
470
  // 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 } },
439
- );
471
+ const installR = await cliIpcCall<{
472
+ ok: boolean;
473
+ skillId?: string;
474
+ }>("installSkill", {
475
+ body: {
476
+ slug: skillId,
477
+ overwrite: opts.overwrite ?? false,
478
+ catalogOnly: true,
479
+ },
480
+ });
440
481
  if (!installR.ok) {
441
482
  if (json) {
442
483
  console.log(