@xopcai/xopc 0.0.103 → 0.0.104

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 (930) hide show
  1. package/README.md +7 -4
  2. package/README.zh-CN.md +7 -4
  3. package/dist/_virtual/_rolldown/runtime.js +2 -3
  4. package/dist/browser-ext/manifest.json +1 -1
  5. package/dist/extensions/feishu/src/adapters/cli-login.d.ts +1 -1
  6. package/dist/extensions/feishu/src/adapters/cli-login.js +1 -1
  7. package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -1
  8. package/dist/extensions/feishu/src/adapters/gateway-setup.d.ts +2 -0
  9. package/dist/extensions/feishu/src/adapters/gateway-setup.js +225 -0
  10. package/dist/extensions/feishu/src/adapters/gateway-setup.js.map +1 -0
  11. package/dist/extensions/feishu/src/index.d.ts +8 -1
  12. package/dist/extensions/feishu/src/index.js +14 -1
  13. package/dist/extensions/feishu/src/index.js.map +1 -0
  14. package/dist/extensions/feishu/src/outbound/outbound-adapter.js +1 -1
  15. package/dist/extensions/feishu/src/plugin.d.ts +2 -1
  16. package/dist/extensions/feishu/src/plugin.js +2 -0
  17. package/dist/extensions/feishu/src/plugin.js.map +1 -1
  18. package/dist/extensions/feishu/src/streaming/streaming-adapter.js +1 -1
  19. package/dist/extensions/feishu/src/transport/webhook/monitor.js +1 -1
  20. package/dist/extensions/feishu/xopc.extension.json +66 -1
  21. package/dist/extensions/telegram/src/adapters/gateway-setup.d.ts +2 -0
  22. package/dist/extensions/telegram/src/adapters/gateway-setup.js +146 -0
  23. package/dist/extensions/telegram/src/adapters/gateway-setup.js.map +1 -0
  24. package/dist/extensions/telegram/src/adapters/security-adapter.js +1 -1
  25. package/dist/extensions/telegram/src/command-handler.js +1 -2
  26. package/dist/extensions/telegram/src/command-handler.js.map +1 -1
  27. package/dist/extensions/telegram/src/config-schema.js +2 -2
  28. package/dist/extensions/telegram/src/config-schema.js.map +1 -1
  29. package/dist/extensions/telegram/src/doctor.d.ts +1 -0
  30. package/dist/extensions/telegram/src/doctor.js +68 -0
  31. package/dist/extensions/telegram/src/doctor.js.map +1 -1
  32. package/dist/extensions/telegram/src/index.d.ts +8 -1
  33. package/dist/extensions/telegram/src/index.js +15 -2
  34. package/dist/extensions/telegram/src/index.js.map +1 -0
  35. package/dist/extensions/telegram/src/plugin.d.ts +13 -5
  36. package/dist/extensions/telegram/src/plugin.js +32 -12
  37. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  38. package/dist/extensions/telegram/src/proxy-fetch.js +22 -5
  39. package/dist/extensions/telegram/src/proxy-fetch.js.map +1 -1
  40. package/dist/extensions/telegram/xopc.extension.json +412 -5
  41. package/dist/extensions/weixin/src/adapters/onboard-cli.js +2 -2
  42. package/dist/extensions/weixin/src/adapters/onboard-cli.js.map +1 -1
  43. package/dist/extensions/weixin/src/api/api.js +1 -1
  44. package/dist/extensions/weixin/src/index.d.ts +8 -0
  45. package/dist/extensions/weixin/src/index.js +12 -1
  46. package/dist/extensions/weixin/src/index.js.map +1 -0
  47. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  48. package/dist/extensions/weixin/src/plugin.d.ts +2 -1
  49. package/dist/extensions/weixin/src/plugin.js +77 -2
  50. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  51. package/dist/extensions/weixin/xopc.extension.json +52 -0
  52. package/dist/gateway/static/root/assets/agents-CvsBrBfi.js +396 -0
  53. package/dist/gateway/static/root/assets/{apps-page-C5RmwmTT.js → apps-page-L-IwQTe0.js} +1 -1
  54. package/dist/gateway/static/root/assets/browser-BLJWD7WI.js +8 -0
  55. package/dist/gateway/static/root/assets/channels-settings-D95KuPeP.js +1 -0
  56. package/dist/gateway/static/root/assets/cron-page-CfkWXDAI.js +1 -0
  57. package/dist/gateway/static/root/assets/{dist-CWm8hTXZ.js → dist-C6vclgEL.js} +1 -1
  58. package/dist/gateway/static/root/assets/{extension-debug-page-BzYgTkS9.js → extension-debug-page-D4JYAbsX.js} +1 -1
  59. package/dist/gateway/static/root/assets/{extension-page-BmTZH6gL.js → extension-page-_T62gi6e.js} +1 -1
  60. package/dist/gateway/static/root/assets/extension-settings-page-CkJbjyM-.js +1 -0
  61. package/dist/gateway/static/root/assets/{fetch-CMoWY2Si.js → fetch-B5aiIguv.js} +1 -1
  62. package/dist/gateway/static/root/assets/gateway-startup-retry-DqmLXhs6.js +1 -0
  63. package/dist/gateway/static/root/assets/heartbeat-config-api-HwJV1K_Y.js +1 -0
  64. package/dist/gateway/static/root/assets/index-BPYKW7FB.css +1 -0
  65. package/dist/gateway/static/root/assets/index-DvTb6wNR.js +4845 -0
  66. package/dist/gateway/static/root/assets/{logs-page-BjdQjHwk.js → logs-page-DsjtTjBy.js} +2 -2
  67. package/dist/gateway/static/root/assets/{note-detail-page-8Er4197b.js → note-detail-page-B2V7RhgD.js} +43 -43
  68. package/dist/gateway/static/root/assets/{note-time-CF3vf1jm.js → note-time-BG8GCTr4.js} +1 -1
  69. package/dist/gateway/static/root/assets/notes-page-xrcVBQ6Z.js +1 -0
  70. package/dist/gateway/static/root/assets/schema-form-S-QUvhul.js +1 -0
  71. package/dist/gateway/static/root/assets/sessions-page-CrQer6Au.js +1 -0
  72. package/dist/gateway/static/root/assets/settings-advanced-gate-DujQl9c7.js +2 -0
  73. package/dist/gateway/static/root/assets/{settings-form-section-C7qA7y0J.js → settings-form-section-r1V7dRV6.js} +1 -1
  74. package/dist/gateway/static/root/assets/settings-page-C9nrONQ2.js +3 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-Tvr5Mtq5.js → share-preview-page-DOFy0FNt.js} +1 -1
  76. package/dist/gateway/static/root/assets/skills-page-DmTsrs_a.js +2 -0
  77. package/dist/gateway/static/root/assets/{theme-store-HTvJlFLL.js → theme-store-Bo3j5Ovv.js} +1 -1
  78. package/dist/gateway/static/root/assets/url-WgQIjFZu.js +3 -0
  79. package/dist/gateway/static/root/assets/voice-api-key-field-AjmUAlEQ.js +1 -0
  80. package/dist/gateway/static/root/assets/{workflow-page.utils-CeBkAjP7.js → workflow-page.utils-DLEJ92gK.js} +1 -1
  81. package/dist/gateway/static/root/assets/workflows-page-BnjjKrM1.js +27 -0
  82. package/dist/gateway/static/root/index.html +6 -5
  83. package/dist/package.js +1 -1
  84. package/dist/src/agent/agent-manager.d.ts +18 -6
  85. package/dist/src/agent/agent-manager.js +60 -35
  86. package/dist/src/agent/agent-manager.js.map +1 -1
  87. package/dist/src/agent/builtin-agent-ids.d.ts +2 -0
  88. package/dist/src/agent/builtin-agent-ids.js +17 -0
  89. package/dist/src/agent/builtin-agent-ids.js.map +1 -0
  90. package/dist/src/agent/child-agent-factory.d.ts +4 -0
  91. package/dist/src/agent/child-agent-factory.js +28 -8
  92. package/dist/src/agent/child-agent-factory.js.map +1 -1
  93. package/dist/src/agent/context/workspace-seed.js +1 -1
  94. package/dist/src/agent/context/workspace-templates/AGENTS.md +23 -184
  95. package/dist/src/agent/embedded/run-turn.js +8 -2
  96. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  97. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
  98. package/dist/src/agent/embedded/subscribe-session.js +33 -51
  99. package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
  100. package/dist/src/agent/embedded/types.d.ts +36 -35
  101. package/dist/src/agent/fallback/candidates.js +1 -1
  102. package/dist/src/agent/fallback/candidates.js.map +1 -1
  103. package/dist/src/agent/inbound/inbound-loop.js +1 -1
  104. package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
  105. package/dist/src/agent/inbound/turn-dispatcher.js +24 -5
  106. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  107. package/dist/src/agent/models/manager.d.ts +1 -1
  108. package/dist/src/agent/models/manager.js +1 -1
  109. package/dist/src/agent/models/manager.js.map +1 -1
  110. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +1 -1
  111. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +1 -1
  112. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +1 -1
  113. package/dist/src/agent/prompt/sections/tooling.js +4 -0
  114. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  115. package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -0
  116. package/dist/src/agent/service/direct-turn-helpers.js +1 -1
  117. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  118. package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
  119. package/dist/src/agent/service/process-direct-streaming.js +35 -18
  120. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  121. package/dist/src/agent/service-inbound-utils.d.ts +0 -1
  122. package/dist/src/agent/service-inbound-utils.js +1 -17
  123. package/dist/src/agent/service-inbound-utils.js.map +1 -1
  124. package/dist/src/agent/service.d.ts +4 -4
  125. package/dist/src/agent/service.js +27 -15
  126. package/dist/src/agent/service.js.map +1 -1
  127. package/dist/src/agent/session/session-config-service.d.ts +1 -0
  128. package/dist/src/agent/session/session-config-service.js +9 -1
  129. package/dist/src/agent/session/session-config-service.js.map +1 -1
  130. package/dist/src/agent/session/session-inspector.d.ts +2 -1
  131. package/dist/src/agent/session/session-inspector.js +4 -0
  132. package/dist/src/agent/session/session-inspector.js.map +1 -1
  133. package/dist/src/agent/skills/config.js +1 -3
  134. package/dist/src/agent/skills/config.js.map +1 -1
  135. package/dist/src/agent/skills/format-skills-prompt.d.ts +1 -0
  136. package/dist/src/agent/skills/format-skills-prompt.js +3 -2
  137. package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
  138. package/dist/src/agent/skills/hub-pull.js +1 -1
  139. package/dist/src/agent/skills/index.js +20 -5
  140. package/dist/src/agent/skills/index.js.map +1 -1
  141. package/dist/src/agent/skills/installer.js +14 -27
  142. package/dist/src/agent/skills/installer.js.map +1 -1
  143. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +11 -1
  144. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js.map +1 -1
  145. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +18 -4
  146. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
  147. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +11 -2
  148. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -1
  149. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +2 -2
  150. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
  151. package/dist/src/agent/skills/skill-manager.d.ts +4 -1
  152. package/dist/src/agent/skills/skill-manager.js +3 -3
  153. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  154. package/dist/src/agent/skills/skill-view-path.d.ts +1 -17
  155. package/dist/src/agent/skills/skill-view-path.js +3 -66
  156. package/dist/src/agent/skills/skill-view-path.js.map +1 -1
  157. package/dist/src/agent/skills/test-framework.js +2 -3
  158. package/dist/src/agent/skills/test-framework.js.map +1 -1
  159. package/dist/src/agent/streaming/reasoning-visibility-sse.js +1 -0
  160. package/dist/src/agent/streaming/reasoning-visibility-sse.js.map +1 -1
  161. package/dist/src/agent/tool-manuals/browser.d.ts +1 -0
  162. package/{skills/browser/SKILL.md → dist/src/agent/tool-manuals/browser.js} +51 -54
  163. package/dist/src/agent/tool-manuals/browser.js.map +1 -0
  164. package/dist/src/agent/tool-manuals/index.d.ts +10 -0
  165. package/dist/src/agent/tool-manuals/index.js +28 -0
  166. package/dist/src/agent/tool-manuals/index.js.map +1 -0
  167. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -1
  168. package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
  169. package/dist/src/agent/tools/factory.js +7 -5
  170. package/dist/src/agent/tools/factory.js.map +1 -1
  171. package/dist/src/agent/tools/index.d.ts +1 -0
  172. package/dist/src/agent/tools/index.js +5 -4
  173. package/dist/src/agent/tools/session-search-tool.js +1 -1
  174. package/dist/src/agent/tools/shell.js +1 -1
  175. package/dist/src/agent/tools/skills-tools.js +37 -8
  176. package/dist/src/agent/tools/skills-tools.js.map +1 -1
  177. package/dist/src/agent/tools/tool-manual-tool.d.ts +6 -0
  178. package/dist/src/agent/tools/tool-manual-tool.js +34 -0
  179. package/dist/src/agent/tools/tool-manual-tool.js.map +1 -0
  180. package/dist/src/agent/tools/web-extract.js +2 -2
  181. package/dist/src/agent/tools/web.js +1 -1
  182. package/dist/src/agent/workflow/catalog.d.ts +7 -2
  183. package/dist/src/agent/workflow/catalog.js +66 -25
  184. package/dist/src/agent/workflow/catalog.js.map +1 -1
  185. package/dist/src/agent/workflow/subagent-runner.d.ts +3 -0
  186. package/dist/src/agent/workflow/subagent-runner.js +50 -4
  187. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  188. package/dist/src/agent/workflow/types.d.ts +10 -0
  189. package/dist/src/auth/credentials.js +10 -5
  190. package/dist/src/auth/credentials.js.map +1 -1
  191. package/dist/src/browser/actions/extension-registry-bridge.js +1 -1
  192. package/dist/src/browser/actions/registry.js +2 -2
  193. package/dist/src/browser/cdp-local-launcher.js +1 -1
  194. package/dist/src/browser/index.js +3 -3
  195. package/dist/src/browser/providers/browser-ext-install.js +1 -1
  196. package/dist/src/browser/providers/cloakbrowser.js +1 -1
  197. package/dist/src/channels/catalog/channel-catalog-service.d.ts +11 -0
  198. package/dist/src/channels/catalog/channel-catalog-service.js +168 -0
  199. package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -0
  200. package/dist/src/channels/catalog/channel-catalog-types.d.ts +22 -0
  201. package/dist/src/channels/catalog/channel-catalog-types.js +1 -0
  202. package/dist/src/channels/dock.d.ts +0 -7
  203. package/dist/src/channels/dock.js +1 -21
  204. package/dist/src/channels/index.d.ts +1 -3
  205. package/dist/src/channels/index.js +1 -5
  206. package/dist/src/channels/lifecycle-supervisor.d.ts +1 -0
  207. package/dist/src/channels/lifecycle-supervisor.js +11 -0
  208. package/dist/src/channels/lifecycle-supervisor.js.map +1 -1
  209. package/dist/src/channels/manager.d.ts +1 -0
  210. package/dist/src/channels/manager.js +3 -0
  211. package/dist/src/channels/manager.js.map +1 -1
  212. package/dist/src/channels/pairing/pairing-channel.d.ts +2 -3
  213. package/dist/src/channels/pairing/pairing-messages.js +1 -1
  214. package/dist/src/channels/pairing/pairing-messages.js.map +1 -1
  215. package/dist/src/channels/pairing/pairing-service.d.ts +1 -1
  216. package/dist/src/channels/pairing/pairing-service.js +8 -27
  217. package/dist/src/channels/pairing/pairing-service.js.map +1 -1
  218. package/dist/src/channels/plugin-types.d.ts +3 -1
  219. package/dist/src/channels/plugins/types.adapters.d.ts +55 -2
  220. package/dist/src/channels/telegram/index.js +1 -1
  221. package/dist/src/chat-commands/builtins/config.js +4 -4
  222. package/dist/src/chat-commands/builtins/config.js.map +1 -1
  223. package/dist/src/chat-commands/config-paths.js +1 -1
  224. package/dist/src/chat-commands/config-paths.js.map +1 -1
  225. package/dist/src/chat-commands/context.js +1 -1
  226. package/dist/src/chat-commands/context.js.map +1 -1
  227. package/dist/src/cli/bin.js +1 -1
  228. package/dist/src/cli/command-manifest.js +1 -1
  229. package/dist/src/cli/command-manifest.js.map +1 -1
  230. package/dist/src/cli/commands/agent.js +2 -2
  231. package/dist/src/cli/commands/agent.js.map +1 -1
  232. package/dist/src/cli/commands/agents.js +2 -4
  233. package/dist/src/cli/commands/agents.js.map +1 -1
  234. package/dist/src/cli/commands/auth.js +1 -1
  235. package/dist/src/cli/commands/browser-cli-helpers.js +1 -1
  236. package/dist/src/cli/commands/channels.d.ts +1 -5
  237. package/dist/src/cli/commands/channels.js +115 -281
  238. package/dist/src/cli/commands/channels.js.map +1 -1
  239. package/dist/src/cli/commands/config.js +2 -2
  240. package/dist/src/cli/commands/config.js.map +1 -1
  241. package/dist/src/cli/commands/doctor/checks/channel-config.js +16 -69
  242. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
  243. package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js +6 -4
  244. package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js.map +1 -1
  245. package/dist/src/cli/commands/doctor/checks/channel-plugins.js +2 -2
  246. package/dist/src/cli/commands/doctor/checks/channel-plugins.js.map +1 -1
  247. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  248. package/dist/src/cli/commands/doctor/checks/provider-auth.js +13 -9
  249. package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
  250. package/dist/src/cli/commands/extension-dev.js +2 -1
  251. package/dist/src/cli/commands/extension-dev.js.map +1 -1
  252. package/dist/src/cli/commands/extension-marketplace.js +2 -1
  253. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  254. package/dist/src/cli/commands/extension-pack.js +2 -1
  255. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  256. package/dist/src/cli/commands/models.js +7 -4
  257. package/dist/src/cli/commands/models.js.map +1 -1
  258. package/dist/src/cli/commands/onboard/channels/index.js +1 -1
  259. package/dist/src/cli/commands/onboard/channels/index.js.map +1 -1
  260. package/dist/src/cli/commands/onboard/channels/registry.d.ts +2 -1
  261. package/dist/src/cli/commands/onboard/channels/registry.js +32 -8
  262. package/dist/src/cli/commands/onboard/channels/registry.js.map +1 -1
  263. package/dist/src/cli/commands/onboard/model.js +8 -5
  264. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  265. package/dist/src/cli/commands/onboard.js +4 -6
  266. package/dist/src/cli/commands/onboard.js.map +1 -1
  267. package/dist/src/cli/commands/setup-shared/runner.d.ts +1 -1
  268. package/dist/src/cli/commands/setup-shared/runner.js.map +1 -1
  269. package/dist/src/cli/commands/setup-shared/types.d.ts +1 -1
  270. package/dist/src/cli/commands/setup-shared/types.js.map +1 -1
  271. package/dist/src/cli/commands/tui.js +13 -5
  272. package/dist/src/cli/commands/tui.js.map +1 -1
  273. package/dist/src/cli/extension-cli-register.js +1 -1
  274. package/dist/src/commands/agents.config.d.ts +3 -3
  275. package/dist/src/commands/agents.config.js +7 -7
  276. package/dist/src/commands/agents.config.js.map +1 -1
  277. package/dist/src/config/agent-profile.d.ts +1 -1
  278. package/dist/src/config/agent-profile.js +6 -2
  279. package/dist/src/config/agent-profile.js.map +1 -1
  280. package/dist/src/config/agent-typed-models.d.ts +2 -2
  281. package/dist/src/config/agent-typed-models.js +13 -2
  282. package/dist/src/config/agent-typed-models.js.map +1 -1
  283. package/dist/src/config/index.js +3 -3
  284. package/dist/src/config/integration.d.ts +1 -1
  285. package/dist/src/config/loader.d.ts +0 -1
  286. package/dist/src/config/loader.js +4 -9
  287. package/dist/src/config/loader.js.map +1 -1
  288. package/dist/src/config/models-json.d.ts +6 -6
  289. package/dist/src/config/rules.js +2 -12
  290. package/dist/src/config/rules.js.map +1 -1
  291. package/dist/src/config/schema.d.ts +74 -47
  292. package/dist/src/config/schema.js +28 -66
  293. package/dist/src/config/schema.js.map +1 -1
  294. package/dist/src/config/validate-channel-configs.d.ts +0 -3
  295. package/dist/src/config/validate-channel-configs.js +29 -10
  296. package/dist/src/config/validate-channel-configs.js.map +1 -1
  297. package/dist/src/cron/executor.js +1 -4
  298. package/dist/src/cron/executor.js.map +1 -1
  299. package/dist/src/extensions/activation-context.js +3 -1
  300. package/dist/src/extensions/activation-context.js.map +1 -1
  301. package/dist/src/extensions/activation-planner.js +12 -0
  302. package/dist/src/extensions/activation-planner.js.map +1 -1
  303. package/dist/src/extensions/api.d.ts +5 -1
  304. package/dist/src/extensions/api.js +12 -0
  305. package/dist/src/extensions/api.js.map +1 -1
  306. package/dist/src/extensions/discover-extensions.js +17 -13
  307. package/dist/src/extensions/discover-extensions.js.map +1 -1
  308. package/dist/src/extensions/extension-metadata-snapshot.js +11 -5
  309. package/dist/src/extensions/extension-metadata-snapshot.js.map +1 -1
  310. package/dist/src/extensions/index.js +12 -4
  311. package/dist/src/extensions/index.js.map +1 -0
  312. package/dist/src/extensions/loader.d.ts +5 -1
  313. package/dist/src/extensions/loader.js +12 -11
  314. package/dist/src/extensions/loader.js.map +1 -1
  315. package/dist/src/extensions/manifest-registry.js +98 -93
  316. package/dist/src/extensions/manifest-registry.js.map +1 -1
  317. package/dist/src/extensions/normalize-manifest.js +91 -15
  318. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  319. package/dist/src/extensions/sdk/index.js +1 -1
  320. package/dist/src/extensions/sdk/testing.js +4 -0
  321. package/dist/src/extensions/sdk/testing.js.map +1 -1
  322. package/dist/src/extensions/types/core.d.ts +32 -1
  323. package/dist/src/extensions/types/manifest.d.ts +60 -0
  324. package/dist/src/extensions/types/tui.d.ts +414 -5
  325. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  326. package/dist/src/gateway/agent-builtin-tools.js +16 -0
  327. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  328. package/dist/src/gateway/agent-run-relay.d.ts +2 -3
  329. package/dist/src/gateway/agent-run-relay.js +10 -3
  330. package/dist/src/gateway/agent-run-relay.js.map +1 -1
  331. package/dist/src/gateway/agents-admin.d.ts +32 -19
  332. package/dist/src/gateway/agents-admin.js +113 -93
  333. package/dist/src/gateway/agents-admin.js.map +1 -1
  334. package/dist/src/gateway/chat-stream/mapper.d.ts +34 -0
  335. package/dist/src/gateway/chat-stream/mapper.js +244 -0
  336. package/dist/src/gateway/chat-stream/mapper.js.map +1 -0
  337. package/dist/src/gateway/chat-stream/protocol.d.ts +100 -0
  338. package/dist/src/gateway/chat-stream/protocol.js +1 -0
  339. package/dist/src/gateway/heartbeat/service.js +1 -1
  340. package/dist/src/gateway/hono/lib/agent-model.d.ts +4 -4
  341. package/dist/src/gateway/hono/lib/agent-model.js +13 -11
  342. package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
  343. package/dist/src/gateway/hono/lib/config-payload.d.ts +19 -7
  344. package/dist/src/gateway/hono/lib/config-payload.js +16 -15
  345. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  346. package/dist/src/gateway/hono/routes/agents.js +83 -48
  347. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  348. package/dist/src/gateway/hono/routes/channels.js +134 -214
  349. package/dist/src/gateway/hono/routes/channels.js.map +1 -1
  350. package/dist/src/gateway/hono/routes/commands-skills.js +10 -4
  351. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  352. package/dist/src/gateway/hono/routes/config-patch/agents.js +26 -13
  353. package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
  354. package/dist/src/gateway/hono/routes/config-patch/channels.d.ts +1 -11
  355. package/dist/src/gateway/hono/routes/config-patch/channels.js +18 -165
  356. package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
  357. package/dist/src/gateway/hono/routes/config.js +5 -2
  358. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  359. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  360. package/dist/src/gateway/hono/routes/lazy-bundles.js +13 -1
  361. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  362. package/dist/src/gateway/hono/routes/public-gateway.js +2 -4
  363. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  364. package/dist/src/gateway/hono/routes/sessions.js +179 -0
  365. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  366. package/dist/src/gateway/hono/routes/tui.d.ts +3 -0
  367. package/dist/src/gateway/hono/routes/tui.js +16 -0
  368. package/dist/src/gateway/hono/routes/tui.js.map +1 -0
  369. package/dist/src/gateway/hono/routes/workflows.js +25 -1
  370. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  371. package/dist/src/gateway/hono/sse.d.ts +5 -7
  372. package/dist/src/gateway/hono/sse.js +21 -38
  373. package/dist/src/gateway/hono/sse.js.map +1 -1
  374. package/dist/src/gateway/protocol.js.map +1 -1
  375. package/dist/src/gateway/service/agent-runner.d.ts +2 -4
  376. package/dist/src/gateway/service/agent-runner.js +1 -1
  377. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  378. package/dist/src/gateway/service/marketplace-service.d.ts +4 -3
  379. package/dist/src/gateway/service/marketplace-service.js +7 -4
  380. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  381. package/dist/src/gateway/service/run-gateway-agent.d.ts +2 -6
  382. package/dist/src/gateway/service/run-gateway-agent.js +63 -36
  383. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  384. package/dist/src/gateway/service/sessions-api.d.ts +19 -0
  385. package/dist/src/gateway/service/sessions-api.js +12 -0
  386. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  387. package/dist/src/gateway/service.d.ts +6 -0
  388. package/dist/src/gateway/service.js +73 -57
  389. package/dist/src/gateway/service.js.map +1 -1
  390. package/dist/src/heartbeat/index.js +1 -1
  391. package/dist/src/mcp/channel-bridge.js +1 -1
  392. package/dist/src/project-trust/trust-store.d.ts +30 -0
  393. package/dist/src/project-trust/trust-store.js +194 -0
  394. package/dist/src/project-trust/trust-store.js.map +1 -0
  395. package/dist/src/providers/index.d.ts +1 -1
  396. package/dist/src/providers/index.js +18 -7
  397. package/dist/src/providers/index.js.map +1 -1
  398. package/dist/src/routing/resolve-route.d.ts +0 -3
  399. package/dist/src/routing/resolve-route.js.map +1 -1
  400. package/dist/src/routing/resolve-tui-session-key.d.ts +2 -0
  401. package/dist/src/routing/resolve-tui-session-key.js +8 -3
  402. package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
  403. package/dist/src/session/client-history.d.ts +32 -0
  404. package/dist/src/session/client-history.js +232 -1
  405. package/dist/src/session/client-history.js.map +1 -1
  406. package/dist/src/session/manager.d.ts +37 -4
  407. package/dist/src/session/manager.js +39 -15
  408. package/dist/src/session/manager.js.map +1 -1
  409. package/dist/src/session/session-context-for-llm.d.ts +93 -1
  410. package/dist/src/session/session-context-for-llm.js +105 -2
  411. package/dist/src/session/session-context-for-llm.js.map +1 -1
  412. package/dist/src/session/store.d.ts +37 -0
  413. package/dist/src/session/store.js +127 -2
  414. package/dist/src/session/store.js.map +1 -1
  415. package/dist/src/session/stored-rows-to-file-entries.js +37 -1
  416. package/dist/src/session/stored-rows-to-file-entries.js.map +1 -1
  417. package/dist/src/session/types.d.ts +14 -1
  418. package/dist/src/session/types.js.map +1 -1
  419. package/dist/src/share/share-thumbnail.js +1 -1
  420. package/dist/src/storage/sqlite/migrations/004_add_session_type_metadata.sql +15 -0
  421. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  422. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  423. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  424. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  425. package/dist/src/storage/sqlite/row-mappers.d.ts +14 -1
  426. package/dist/src/storage/sqlite/row-mappers.js +14 -1
  427. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  428. package/dist/src/storage/sqlite/schema.js +1 -1
  429. package/dist/src/storage/sqlite/session-metadata.js +1 -0
  430. package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
  431. package/dist/src/storage/sqlite/session-repository.js +52 -25
  432. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  433. package/dist/src/tui/backends/embedded-backend.d.ts +53 -4
  434. package/dist/src/tui/backends/embedded-backend.js +227 -39
  435. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  436. package/dist/src/tui/backends/gateway-sse-backend.d.ts +59 -3
  437. package/dist/src/tui/backends/gateway-sse-backend.js +416 -26
  438. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  439. package/dist/src/tui/chat-history.d.ts +5 -1
  440. package/dist/src/tui/chat-history.js +78 -8
  441. package/dist/src/tui/chat-history.js.map +1 -1
  442. package/dist/src/tui/clipboard-text.d.ts +5 -0
  443. package/dist/src/tui/clipboard-text.js +46 -0
  444. package/dist/src/tui/clipboard-text.js.map +1 -0
  445. package/dist/src/tui/components/assistant-message.d.ts +19 -3
  446. package/dist/src/tui/components/assistant-message.js +115 -9
  447. package/dist/src/tui/components/assistant-message.js.map +1 -1
  448. package/dist/src/tui/components/bash-execution.d.ts +3 -2
  449. package/dist/src/tui/components/bash-execution.js +31 -3
  450. package/dist/src/tui/components/bash-execution.js.map +1 -1
  451. package/dist/src/tui/components/bash-summary.d.ts +23 -0
  452. package/dist/src/tui/components/bash-summary.js +87 -0
  453. package/dist/src/tui/components/bash-summary.js.map +1 -0
  454. package/dist/src/tui/components/branch-message-summary.d.ts +17 -0
  455. package/dist/src/tui/components/branch-message-summary.js +43 -0
  456. package/dist/src/tui/components/branch-message-summary.js.map +1 -0
  457. package/dist/src/tui/components/branch-summary.d.ts +13 -0
  458. package/dist/src/tui/components/branch-summary.js +51 -0
  459. package/dist/src/tui/components/branch-summary.js.map +1 -0
  460. package/dist/src/tui/components/chat-log.d.ts +46 -6
  461. package/dist/src/tui/components/chat-log.js +183 -21
  462. package/dist/src/tui/components/chat-log.js.map +1 -1
  463. package/dist/src/tui/components/compaction-summary.d.ts +13 -0
  464. package/dist/src/tui/components/compaction-summary.js +46 -0
  465. package/dist/src/tui/components/compaction-summary.js.map +1 -0
  466. package/dist/src/tui/components/custom-editor.d.ts +1 -0
  467. package/dist/src/tui/components/custom-editor.js +2 -0
  468. package/dist/src/tui/components/custom-editor.js.map +1 -1
  469. package/dist/src/tui/components/custom-message.d.ts +23 -0
  470. package/dist/src/tui/components/custom-message.js +65 -0
  471. package/dist/src/tui/components/custom-message.js.map +1 -0
  472. package/dist/src/tui/components/extension-dialog.d.ts +42 -0
  473. package/dist/src/tui/components/extension-dialog.js +127 -0
  474. package/dist/src/tui/components/extension-dialog.js.map +1 -0
  475. package/dist/src/tui/components/scoped-models-selector.d.ts +7 -2
  476. package/dist/src/tui/components/scoped-models-selector.js +89 -16
  477. package/dist/src/tui/components/scoped-models-selector.js.map +1 -1
  478. package/dist/src/tui/components/searchable-select-list.d.ts +30 -3
  479. package/dist/src/tui/components/searchable-select-list.js +82 -10
  480. package/dist/src/tui/components/searchable-select-list.js.map +1 -1
  481. package/dist/src/tui/components/session-selector.d.ts +18 -4
  482. package/dist/src/tui/components/session-selector.js +207 -40
  483. package/dist/src/tui/components/session-selector.js.map +1 -1
  484. package/dist/src/tui/components/settings-selector.d.ts +6 -2
  485. package/dist/src/tui/components/settings-selector.js +126 -7
  486. package/dist/src/tui/components/settings-selector.js.map +1 -1
  487. package/dist/src/tui/components/thinking-selector.d.ts +12 -0
  488. package/dist/src/tui/components/thinking-selector.js +48 -0
  489. package/dist/src/tui/components/thinking-selector.js.map +1 -0
  490. package/dist/src/tui/components/tool-execution.d.ts +57 -3
  491. package/dist/src/tui/components/tool-execution.js +378 -28
  492. package/dist/src/tui/components/tool-execution.js.map +1 -1
  493. package/dist/src/tui/components/tui-bottom-bar.d.ts +9 -1
  494. package/dist/src/tui/components/tui-bottom-bar.js +56 -11
  495. package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
  496. package/dist/src/tui/components/tui-header.d.ts +9 -2
  497. package/dist/src/tui/components/tui-header.js +25 -5
  498. package/dist/src/tui/components/tui-header.js.map +1 -1
  499. package/dist/src/tui/components/user-message.d.ts +4 -2
  500. package/dist/src/tui/components/user-message.js +42 -9
  501. package/dist/src/tui/components/user-message.js.map +1 -1
  502. package/dist/src/tui/components/visual-truncate.d.ts +11 -0
  503. package/dist/src/tui/components/visual-truncate.js +27 -0
  504. package/dist/src/tui/components/visual-truncate.js.map +1 -0
  505. package/dist/src/tui/extension-host/autocomplete.d.ts +43 -0
  506. package/dist/src/tui/extension-host/autocomplete.js +116 -0
  507. package/dist/src/tui/extension-host/autocomplete.js.map +1 -0
  508. package/dist/src/tui/extension-host/host.d.ts +31 -1
  509. package/dist/src/tui/extension-host/host.js +123 -6
  510. package/dist/src/tui/extension-host/host.js.map +1 -1
  511. package/dist/src/tui/extension-host/load-extensions.d.ts +6 -1
  512. package/dist/src/tui/extension-host/load-extensions.js +4 -3
  513. package/dist/src/tui/extension-host/load-extensions.js.map +1 -1
  514. package/dist/src/tui/extension-host/runtime-context.d.ts +21 -0
  515. package/dist/src/tui/extension-host/runtime-context.js +152 -0
  516. package/dist/src/tui/extension-host/runtime-context.js.map +1 -0
  517. package/dist/src/tui/extension-host/runtime.d.ts +52 -4
  518. package/dist/src/tui/extension-host/runtime.js +547 -85
  519. package/dist/src/tui/extension-host/runtime.js.map +1 -1
  520. package/dist/src/tui/extension-host/surface.d.ts +20 -0
  521. package/dist/src/tui/extension-host/surface.js +30 -6
  522. package/dist/src/tui/extension-host/surface.js.map +1 -1
  523. package/dist/src/tui/extension-host/tool-renderers.d.ts +6 -3
  524. package/dist/src/tui/extension-host/tool-renderers.js +43 -5
  525. package/dist/src/tui/extension-host/tool-renderers.js.map +1 -1
  526. package/dist/src/tui/format-tui-hotkeys.d.ts +12 -2
  527. package/dist/src/tui/format-tui-hotkeys.js +22 -5
  528. package/dist/src/tui/format-tui-hotkeys.js.map +1 -1
  529. package/dist/src/tui/tui-agent-events.d.ts +8 -6
  530. package/dist/src/tui/tui-agent-events.js +200 -59
  531. package/dist/src/tui/tui-agent-events.js.map +1 -1
  532. package/dist/src/tui/tui-backend.d.ts +169 -3
  533. package/dist/src/tui/tui-command-formatters.d.ts +76 -0
  534. package/dist/src/tui/tui-command-formatters.js +594 -0
  535. package/dist/src/tui/tui-command-formatters.js.map +1 -0
  536. package/dist/src/tui/tui-commands.d.ts +57 -7
  537. package/dist/src/tui/tui-commands.js +639 -43
  538. package/dist/src/tui/tui-commands.js.map +1 -1
  539. package/dist/src/tui/tui-context-usage.d.ts +1 -1
  540. package/dist/src/tui/tui-context-usage.js +9 -1
  541. package/dist/src/tui/tui-context-usage.js.map +1 -1
  542. package/dist/src/tui/tui-extension-user-message.d.ts +8 -0
  543. package/dist/src/tui/tui-extension-user-message.js +32 -0
  544. package/dist/src/tui/tui-extension-user-message.js.map +1 -0
  545. package/dist/src/tui/tui-follow-up-queue.d.ts +9 -0
  546. package/dist/src/tui/tui-follow-up-queue.js +18 -0
  547. package/dist/src/tui/tui-follow-up-queue.js.map +1 -0
  548. package/dist/src/tui/tui-local-shell.d.ts +11 -1
  549. package/dist/src/tui/tui-local-shell.js +50 -8
  550. package/dist/src/tui/tui-local-shell.js.map +1 -1
  551. package/dist/src/tui/tui-model-picker.d.ts +26 -0
  552. package/dist/src/tui/tui-model-picker.js +152 -0
  553. package/dist/src/tui/tui-model-picker.js.map +1 -0
  554. package/dist/src/tui/tui-oauth-login.d.ts +16 -0
  555. package/dist/src/tui/tui-oauth-login.js +189 -0
  556. package/dist/src/tui/tui-oauth-login.js.map +1 -0
  557. package/dist/src/tui/tui-overlays.d.ts +3 -3
  558. package/dist/src/tui/tui-overlays.js +6 -7
  559. package/dist/src/tui/tui-overlays.js.map +1 -1
  560. package/dist/src/tui/tui-picker-overlay.d.ts +27 -32
  561. package/dist/src/tui/tui-picker-overlay.js +340 -30
  562. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  563. package/dist/src/tui/tui-picker-services.d.ts +41 -0
  564. package/dist/src/tui/tui-picker-services.js +1 -0
  565. package/dist/src/tui/tui-run-state.d.ts +11 -0
  566. package/dist/src/tui/tui-run-state.js +114 -0
  567. package/dist/src/tui/tui-run-state.js.map +1 -0
  568. package/dist/src/tui/tui-runtime-hints.d.ts +4 -0
  569. package/dist/src/tui/tui-runtime-hints.js +18 -0
  570. package/dist/src/tui/tui-runtime-hints.js.map +1 -0
  571. package/dist/src/tui/tui-scoped-models.d.ts +1 -1
  572. package/dist/src/tui/tui-scoped-models.js +2 -2
  573. package/dist/src/tui/tui-scoped-models.js.map +1 -1
  574. package/dist/src/tui/tui-session-actions.d.ts +5 -3
  575. package/dist/src/tui/tui-session-actions.js +21 -9
  576. package/dist/src/tui/tui-session-actions.js.map +1 -1
  577. package/dist/src/tui/tui-session-format.d.ts +4 -1
  578. package/dist/src/tui/tui-session-format.js +17 -3
  579. package/dist/src/tui/tui-session-format.js.map +1 -1
  580. package/dist/src/tui/tui-session-snapshot.d.ts +82 -0
  581. package/dist/src/tui/tui-session-snapshot.js +184 -0
  582. package/dist/src/tui/tui-session-snapshot.js.map +1 -0
  583. package/dist/src/tui/tui-session-stats.d.ts +3 -0
  584. package/dist/src/tui/tui-session-stats.js +59 -0
  585. package/dist/src/tui/tui-session-stats.js.map +1 -0
  586. package/dist/src/tui/tui-settings.d.ts +21 -0
  587. package/dist/src/tui/tui-settings.js +28 -1
  588. package/dist/src/tui/tui-settings.js.map +1 -1
  589. package/dist/src/tui/tui-skills-autocomplete.js +1 -1
  590. package/dist/src/tui/tui-skills-autocomplete.js.map +1 -1
  591. package/dist/src/tui/tui-startup-resources.d.ts +3 -0
  592. package/dist/src/tui/tui-startup-resources.js +39 -0
  593. package/dist/src/tui/tui-startup-resources.js.map +1 -0
  594. package/dist/src/tui/tui-startup-text.d.ts +10 -0
  595. package/dist/src/tui/tui-startup-text.js +58 -0
  596. package/dist/src/tui/tui-startup-text.js.map +1 -0
  597. package/dist/src/tui/tui-stdio-filter.d.ts +1 -0
  598. package/dist/src/tui/tui-stdio-filter.js +11 -7
  599. package/dist/src/tui/tui-stdio-filter.js.map +1 -1
  600. package/dist/src/tui/tui-submit.d.ts +2 -0
  601. package/dist/src/tui/tui-submit.js +2 -1
  602. package/dist/src/tui/tui-submit.js.map +1 -1
  603. package/dist/src/tui/tui-tool-diff.js +61 -7
  604. package/dist/src/tui/tui-tool-diff.js.map +1 -1
  605. package/dist/src/tui/tui-tool-result.d.ts +17 -0
  606. package/dist/src/tui/tui-tool-result.js +74 -0
  607. package/dist/src/tui/tui-tool-result.js.map +1 -0
  608. package/dist/src/tui/tui-transcript-tree-picker.d.ts +57 -0
  609. package/dist/src/tui/tui-transcript-tree-picker.js +604 -0
  610. package/dist/src/tui/tui-transcript-tree-picker.js.map +1 -0
  611. package/dist/src/tui/tui-transcript-tree.d.ts +7 -0
  612. package/dist/src/tui/tui-transcript-tree.js +316 -0
  613. package/dist/src/tui/tui-transcript-tree.js.map +1 -0
  614. package/dist/src/tui/tui-types.d.ts +25 -34
  615. package/dist/src/tui/tui-types.js +12 -0
  616. package/dist/src/tui/tui-types.js.map +1 -1
  617. package/dist/src/tui/tui.js +1288 -112
  618. package/dist/src/tui/tui.js.map +1 -1
  619. package/dist/src/tui/xopc-tui-keybindings.d.ts +127 -2
  620. package/dist/src/tui/xopc-tui-keybindings.js +127 -2
  621. package/dist/src/tui/xopc-tui-keybindings.js.map +1 -1
  622. package/dist/src/workflows/domain/definition-utils.d.ts +2 -1
  623. package/dist/src/workflows/domain/definition-utils.js +18 -8
  624. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  625. package/dist/src/workflows/domain/definition.d.ts +25 -0
  626. package/dist/src/workflows/domain/event.d.ts +1 -0
  627. package/dist/src/workflows/domain/result.d.ts +15 -0
  628. package/dist/src/workflows/domain/run.d.ts +2 -0
  629. package/dist/src/workflows/domain/run.js.map +1 -1
  630. package/dist/src/workflows/engine/projector.js +4 -0
  631. package/dist/src/workflows/engine/projector.js.map +1 -1
  632. package/dist/src/workflows/engine/workflow-engine.d.ts +37 -1
  633. package/dist/src/workflows/engine/workflow-engine.js +75 -11
  634. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  635. package/dist/src/workflows/index.d.ts +1 -0
  636. package/dist/src/workflows/index.js +4 -1
  637. package/dist/src/workflows/registry/catalog-workflow-definition-registry.d.ts +9 -0
  638. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +40 -0
  639. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -0
  640. package/dist/src/workflows/registry/index.d.ts +2 -0
  641. package/dist/src/workflows/registry/index.js +2 -0
  642. package/dist/src/workflows/registry/workflow-definition-registry.d.ts +15 -0
  643. package/dist/src/workflows/registry/workflow-definition-registry.js +1 -0
  644. package/dist/src/workflows/runtime/index.d.ts +2 -0
  645. package/dist/src/workflows/runtime/index.js +2 -1
  646. package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +5 -0
  647. package/dist/src/workflows/runtime/script-workflow-runtime.js +15 -0
  648. package/dist/src/workflows/runtime/script-workflow-runtime.js.map +1 -0
  649. package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +16 -0
  650. package/dist/src/workflows/runtime/workflow-runtime-port.js +1 -0
  651. package/dist/src/workflows/service/run-view-to-snapshot.js +3 -0
  652. package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -1
  653. package/dist/src/workflows/service/workflow-run-service.d.ts +3 -0
  654. package/dist/src/workflows/service/workflow-run-service.js +10 -15
  655. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  656. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -1
  657. package/dist/src/workflows/service/workflow-session-bridge.js +4 -1
  658. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  659. package/package.json +21 -15
  660. package/skills/creative/frontend-design/SKILL.md +1 -1
  661. package/skills/creative/theme-factory/SKILL.md +1 -1
  662. package/skills/documents/xlsx/SKILL.md +1 -1
  663. package/skills/engineering/diagnose/SKILL.md +2 -2
  664. package/skills/engineering/tdd/SKILL.md +1 -1
  665. package/skills/tools/github/SKILL.md +6 -1
  666. package/skills/tools/webapp-testing/SKILL.md +4 -1
  667. package/dist/extensions/telegram/src/adapters/config-surface.d.ts +0 -2
  668. package/dist/extensions/telegram/src/adapters/config-surface.js +0 -26
  669. package/dist/extensions/telegram/src/adapters/config-surface.js.map +0 -1
  670. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +0 -158
  671. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +0 -1
  672. package/dist/gateway/static/root/assets/agents-BwXkia_W.js +0 -222
  673. package/dist/gateway/static/root/assets/channels-settings-tlOTdaXw.js +0 -1
  674. package/dist/gateway/static/root/assets/channels-status-swr-D4XjqwqC.js +0 -8
  675. package/dist/gateway/static/root/assets/cron-api-DcmfGuj0.js +0 -1
  676. package/dist/gateway/static/root/assets/cron-page-CijJ4G6F.js +0 -1
  677. package/dist/gateway/static/root/assets/extension-settings-page-CyJk_G64.js +0 -1
  678. package/dist/gateway/static/root/assets/field-primitives-C4GpxsDo.js +0 -1
  679. package/dist/gateway/static/root/assets/heartbeat-config-api-CLD0Gpi3.js +0 -1
  680. package/dist/gateway/static/root/assets/index-0HmunJW9.js +0 -4845
  681. package/dist/gateway/static/root/assets/index-Bk75Phrd.css +0 -1
  682. package/dist/gateway/static/root/assets/notes-page-BBnTh0uI.js +0 -1
  683. package/dist/gateway/static/root/assets/sessions-page-B0riYK7j.js +0 -1
  684. package/dist/gateway/static/root/assets/settings-advanced-gate-DiP_WHu_.js +0 -2
  685. package/dist/gateway/static/root/assets/settings-page-1ZPhcCZ9.js +0 -3
  686. package/dist/gateway/static/root/assets/skills-page-BQ1hllKD.js +0 -2
  687. package/dist/gateway/static/root/assets/url-F3_D_6zZ.js +0 -3
  688. package/dist/gateway/static/root/assets/utils-CPr3FBh2.js +0 -1
  689. package/dist/gateway/static/root/assets/voice-api-key-field-BkbDl6dH.js +0 -1
  690. package/dist/gateway/static/root/assets/workflows-page-D059ysoF.js +0 -27
  691. package/dist/src/agent/embedded/map-stream-events.d.ts +0 -9
  692. package/dist/src/agent/embedded/map-stream-events.js +0 -63
  693. package/dist/src/agent/embedded/map-stream-events.js.map +0 -1
  694. package/dist/src/channels/dock.js.map +0 -1
  695. package/dist/src/channels/plugins/bundled.d.ts +0 -11
  696. package/dist/src/channels/plugins/bundled.js +0 -10
  697. package/dist/src/channels/plugins/bundled.js.map +0 -1
  698. package/dist/src/channels/registry.d.ts +0 -25
  699. package/dist/src/channels/registry.js +0 -82
  700. package/dist/src/channels/registry.js.map +0 -1
  701. package/dist/src/config/localized-text.d.ts +0 -6
  702. package/dist/src/config/localized-text.js +0 -42
  703. package/dist/src/config/localized-text.js.map +0 -1
  704. package/dist/src/generated/bundled-channel-plugins.d.ts +0 -10
  705. package/dist/src/generated/bundled-channel-plugins.js +0 -16
  706. package/dist/src/generated/bundled-channel-plugins.js.map +0 -1
  707. package/dist/src/tui/stream-assembler.d.ts +0 -22
  708. package/dist/src/tui/stream-assembler.js +0 -63
  709. package/dist/src/tui/stream-assembler.js.map +0 -1
  710. package/skills/browser/SKILL-zh.md +0 -188
  711. package/skills/business/company-values/SKILL-zh.md +0 -80
  712. package/skills/business/company-values/SKILL.md +0 -80
  713. package/skills/business/find-community/SKILL-zh.md +0 -50
  714. package/skills/business/find-community/SKILL.md +0 -50
  715. package/skills/business/first-customers/SKILL-zh.md +0 -76
  716. package/skills/business/first-customers/SKILL.md +0 -76
  717. package/skills/business/grow-sustainably/SKILL-zh.md +0 -92
  718. package/skills/business/grow-sustainably/SKILL.md +0 -92
  719. package/skills/business/marketing-plan/SKILL-zh.md +0 -100
  720. package/skills/business/marketing-plan/SKILL.md +0 -100
  721. package/skills/business/minimalist-review/SKILL-zh.md +0 -82
  722. package/skills/business/minimalist-review/SKILL.md +0 -82
  723. package/skills/business/mvp/SKILL-zh.md +0 -81
  724. package/skills/business/mvp/SKILL.md +0 -81
  725. package/skills/business/pricing/SKILL-zh.md +0 -64
  726. package/skills/business/pricing/SKILL.md +0 -64
  727. package/skills/business/processize/SKILL-zh.md +0 -91
  728. package/skills/business/processize/SKILL.md +0 -91
  729. package/skills/business/validate-idea/SKILL-zh.md +0 -68
  730. package/skills/business/validate-idea/SKILL.md +0 -68
  731. package/skills/creative/algorithmic-art/LICENSE.txt +0 -202
  732. package/skills/creative/algorithmic-art/SKILL-zh.md +0 -405
  733. package/skills/creative/algorithmic-art/SKILL.md +0 -405
  734. package/skills/creative/algorithmic-art/templates/generator_template.js +0 -223
  735. package/skills/creative/algorithmic-art/templates/viewer.html +0 -599
  736. package/skills/creative/frontend-design/SKILL-zh.md +0 -42
  737. package/skills/creative/theme-factory/SKILL-zh.md +0 -59
  738. package/skills/creative/web-artifacts-builder/LICENSE.txt +0 -202
  739. package/skills/creative/web-artifacts-builder/SKILL-zh.md +0 -74
  740. package/skills/creative/web-artifacts-builder/SKILL.md +0 -74
  741. package/skills/creative/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  742. package/skills/creative/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  743. package/skills/creative/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  744. package/skills/documents/doc-coauthoring/SKILL-zh.md +0 -375
  745. package/skills/documents/doc-coauthoring/SKILL.md +0 -375
  746. package/skills/documents/docx/LICENSE.txt +0 -30
  747. package/skills/documents/docx/SKILL-zh.md +0 -590
  748. package/skills/documents/docx/SKILL.md +0 -590
  749. package/skills/documents/docx/scripts/__init__.py +0 -1
  750. package/skills/documents/docx/scripts/accept_changes.py +0 -135
  751. package/skills/documents/docx/scripts/comment.py +0 -318
  752. package/skills/documents/docx/scripts/office/helpers/__init__.py +0 -0
  753. package/skills/documents/docx/scripts/office/helpers/merge_runs.py +0 -199
  754. package/skills/documents/docx/scripts/office/helpers/simplify_redlines.py +0 -197
  755. package/skills/documents/docx/scripts/office/pack.py +0 -159
  756. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  757. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  758. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  759. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  760. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  761. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  762. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  763. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  764. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  765. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  766. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  767. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  768. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  769. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  770. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  771. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  772. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  773. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  774. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  775. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  776. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  777. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  778. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  779. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  780. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  781. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  782. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  783. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  784. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  785. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  786. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  787. package/skills/documents/docx/scripts/office/schemas/mce/mc.xsd +0 -75
  788. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  789. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  790. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  791. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  792. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  793. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  794. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  795. package/skills/documents/docx/scripts/office/soffice.py +0 -183
  796. package/skills/documents/docx/scripts/office/unpack.py +0 -132
  797. package/skills/documents/docx/scripts/office/validate.py +0 -111
  798. package/skills/documents/docx/scripts/office/validators/__init__.py +0 -15
  799. package/skills/documents/docx/scripts/office/validators/base.py +0 -847
  800. package/skills/documents/docx/scripts/office/validators/docx.py +0 -446
  801. package/skills/documents/docx/scripts/office/validators/pptx.py +0 -275
  802. package/skills/documents/docx/scripts/office/validators/redlining.py +0 -247
  803. package/skills/documents/docx/scripts/templates/comments.xml +0 -3
  804. package/skills/documents/docx/scripts/templates/commentsExtended.xml +0 -3
  805. package/skills/documents/docx/scripts/templates/commentsExtensible.xml +0 -3
  806. package/skills/documents/docx/scripts/templates/commentsIds.xml +0 -3
  807. package/skills/documents/docx/scripts/templates/people.xml +0 -3
  808. package/skills/documents/pdf/LICENSE.txt +0 -30
  809. package/skills/documents/pdf/SKILL-zh.md +0 -314
  810. package/skills/documents/pdf/SKILL.md +0 -314
  811. package/skills/documents/pdf/forms.md +0 -294
  812. package/skills/documents/pdf/reference.md +0 -612
  813. package/skills/documents/pdf/scripts/check_bounding_boxes.py +0 -65
  814. package/skills/documents/pdf/scripts/check_fillable_fields.py +0 -11
  815. package/skills/documents/pdf/scripts/convert_pdf_to_images.py +0 -33
  816. package/skills/documents/pdf/scripts/create_validation_image.py +0 -37
  817. package/skills/documents/pdf/scripts/extract_form_field_info.py +0 -122
  818. package/skills/documents/pdf/scripts/extract_form_structure.py +0 -115
  819. package/skills/documents/pdf/scripts/fill_fillable_fields.py +0 -98
  820. package/skills/documents/pdf/scripts/fill_pdf_form_with_annotations.py +0 -107
  821. package/skills/documents/pptx/LICENSE.txt +0 -30
  822. package/skills/documents/pptx/SKILL-zh.md +0 -232
  823. package/skills/documents/pptx/SKILL.md +0 -232
  824. package/skills/documents/pptx/editing.md +0 -205
  825. package/skills/documents/pptx/pptxgenjs.md +0 -420
  826. package/skills/documents/pptx/scripts/__init__.py +0 -0
  827. package/skills/documents/pptx/scripts/add_slide.py +0 -195
  828. package/skills/documents/pptx/scripts/clean.py +0 -286
  829. package/skills/documents/pptx/scripts/office/helpers/__init__.py +0 -0
  830. package/skills/documents/pptx/scripts/office/helpers/merge_runs.py +0 -199
  831. package/skills/documents/pptx/scripts/office/helpers/simplify_redlines.py +0 -197
  832. package/skills/documents/pptx/scripts/office/pack.py +0 -159
  833. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  834. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  835. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  836. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  837. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  838. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  839. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  840. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  841. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  842. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  843. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  844. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  845. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  846. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  847. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  848. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  849. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  850. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  851. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  852. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  853. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  854. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  855. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  856. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  857. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  858. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  859. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  860. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  861. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  862. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  863. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  864. package/skills/documents/pptx/scripts/office/schemas/mce/mc.xsd +0 -75
  865. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  866. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  867. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  868. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  869. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  870. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  871. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  872. package/skills/documents/pptx/scripts/office/soffice.py +0 -183
  873. package/skills/documents/pptx/scripts/office/unpack.py +0 -132
  874. package/skills/documents/pptx/scripts/office/validate.py +0 -111
  875. package/skills/documents/pptx/scripts/office/validators/__init__.py +0 -15
  876. package/skills/documents/pptx/scripts/office/validators/base.py +0 -847
  877. package/skills/documents/pptx/scripts/office/validators/docx.py +0 -446
  878. package/skills/documents/pptx/scripts/office/validators/pptx.py +0 -275
  879. package/skills/documents/pptx/scripts/office/validators/redlining.py +0 -247
  880. package/skills/documents/pptx/scripts/thumbnail.py +0 -289
  881. package/skills/documents/xlsx/SKILL-zh.md +0 -292
  882. package/skills/engineering/diagnose/SKILL-zh.md +0 -117
  883. package/skills/engineering/grill-with-docs/ADR-FORMAT.md +0 -47
  884. package/skills/engineering/grill-with-docs/CONTEXT-FORMAT.md +0 -77
  885. package/skills/engineering/grill-with-docs/SKILL-zh.md +0 -88
  886. package/skills/engineering/grill-with-docs/SKILL.md +0 -88
  887. package/skills/engineering/improve-codebase-architecture/DEEPENING.md +0 -37
  888. package/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
  889. package/skills/engineering/improve-codebase-architecture/LANGUAGE.md +0 -53
  890. package/skills/engineering/improve-codebase-architecture/SKILL-zh.md +0 -71
  891. package/skills/engineering/improve-codebase-architecture/SKILL.md +0 -71
  892. package/skills/engineering/tdd/SKILL-zh.md +0 -109
  893. package/skills/engineering/to-issues/SKILL-zh.md +0 -81
  894. package/skills/engineering/to-issues/SKILL.md +0 -81
  895. package/skills/engineering/to-prd/SKILL-zh.md +0 -76
  896. package/skills/engineering/to-prd/SKILL.md +0 -74
  897. package/skills/engineering/zoom-out/SKILL-zh.md +0 -7
  898. package/skills/engineering/zoom-out/SKILL.md +0 -7
  899. package/skills/tools/find-skills/SKILL-zh.md +0 -440
  900. package/skills/tools/github/SKILL-zh.md +0 -48
  901. package/skills/tools/internal-comms/LICENSE.txt +0 -202
  902. package/skills/tools/internal-comms/SKILL-zh.md +0 -32
  903. package/skills/tools/internal-comms/SKILL.md +0 -32
  904. package/skills/tools/internal-comms/examples/3p-updates.md +0 -47
  905. package/skills/tools/internal-comms/examples/company-newsletter.md +0 -65
  906. package/skills/tools/internal-comms/examples/faq-answers.md +0 -30
  907. package/skills/tools/internal-comms/examples/general-comms.md +0 -16
  908. package/skills/tools/skill-creator/LICENSE.txt +0 -202
  909. package/skills/tools/skill-creator/SKILL-zh.md +0 -483
  910. package/skills/tools/skill-creator/SKILL.md +0 -485
  911. package/skills/tools/skill-creator/agents/analyzer.md +0 -274
  912. package/skills/tools/skill-creator/agents/comparator.md +0 -202
  913. package/skills/tools/skill-creator/agents/grader.md +0 -223
  914. package/skills/tools/skill-creator/assets/eval_review.html +0 -146
  915. package/skills/tools/skill-creator/eval-viewer/generate_review.py +0 -471
  916. package/skills/tools/skill-creator/eval-viewer/viewer.html +0 -1325
  917. package/skills/tools/skill-creator/references/schemas.md +0 -430
  918. package/skills/tools/skill-creator/scripts/__init__.py +0 -0
  919. package/skills/tools/skill-creator/scripts/aggregate_benchmark.py +0 -401
  920. package/skills/tools/skill-creator/scripts/generate_report.py +0 -326
  921. package/skills/tools/skill-creator/scripts/improve_description.py +0 -247
  922. package/skills/tools/skill-creator/scripts/package_skill.py +0 -136
  923. package/skills/tools/skill-creator/scripts/quick_validate.py +0 -103
  924. package/skills/tools/skill-creator/scripts/run_eval.py +0 -310
  925. package/skills/tools/skill-creator/scripts/run_loop.py +0 -328
  926. package/skills/tools/skill-creator/scripts/utils.py +0 -47
  927. package/skills/tools/summarize/SKILL-zh.md +0 -47
  928. package/skills/tools/weather/SKILL-zh.md +0 -46
  929. package/skills/tools/weather/SKILL.md +0 -46
  930. package/skills/tools/webapp-testing/SKILL-zh.md +0 -96
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../../../src/agent/skills/config.ts"],"sourcesContent":["/**\n * Skill Configuration Manager\n * \n * Handles skill-specific configuration and environment variables.\n *\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport { writeTextAtomicSync } from '../../infra/write-file-atomic.js';\nimport type { SkillConfig, SkillsConfig, Skill } from './types.js';\n\nconst log = createLogger('SkillConfig');\n\n/**\n * Resolve skill configuration from multiple sources\n * \n * Priority (highest to lowest):\n * 1. Environment variable overrides (XOPC_SKILL_<NAME>_<KEY>)\n * 2. Config file entries\n * 3. Skill defaults\n */\nexport function resolveSkillConfig(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): SkillConfig {\n const config: SkillConfig = {};\n\n // Start with config file entries\n const entryConfig = skillsConfig?.entries?.[skill.name];\n if (entryConfig) {\n config.enabled = entryConfig.enabled;\n config.apiKey = entryConfig.apiKey;\n config.env = entryConfig.env ? { ...entryConfig.env } : undefined;\n config.config = entryConfig.config ? { ...entryConfig.config } : undefined;\n }\n\n // Apply environment variable overrides\n const envPrefix = `XOPC_SKILL_${skill.name.toUpperCase().replace(/-/g, '_')}`;\n \n // Check for enabled override\n const enabledEnv = process.env[`${envPrefix}_ENABLED`];\n if (enabledEnv !== undefined) {\n config.enabled = enabledEnv.toLowerCase() === 'true' || enabledEnv === '1';\n }\n\n // Check for API key override\n const apiKeyEnv = process.env[`${envPrefix}_API_KEY`];\n if (apiKeyEnv) {\n config.apiKey = apiKeyEnv;\n }\n\n // Check for environment variable overrides\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(`${envPrefix}_ENV_`)) {\n const envKey = key.slice(`${envPrefix}_ENV_`.length);\n if (!config.env) {\n config.env = {};\n }\n config.env[envKey] = value;\n }\n }\n\n return config;\n}\n\n/**\n * Apply environment variable overrides to a skill's environment\n */\nexport function applySkillEnvOverrides(\n skill: Skill,\n baseEnv: Record<string, string> = {},\n skillConfig?: SkillConfig\n): Record<string, string> {\n const env: Record<string, string> = { ...baseEnv };\n\n // Apply config env\n if (skillConfig?.env) {\n for (const [key, value] of Object.entries(skillConfig.env)) {\n env[key] = value;\n }\n }\n\n // Apply environment variable overrides\n const envPrefix = `XOPC_SKILL_${skill.name.toUpperCase().replace(/-/g, '_')}`;\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(`${envPrefix}_ENV_`)) {\n const envKey = key.slice(`${envPrefix}_ENV_`.length);\n env[envKey] = value;\n }\n }\n\n return env;\n}\n\n/**\n * Get the effective environment for a skill\n */\nexport function getSkillEnvironment(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): Record<string, string> {\n const config = resolveSkillConfig(skill, skillsConfig);\n return applySkillEnvOverrides(skill, process.env as Record<string, string>, config);\n}\n\n/**\n * Skill configuration file manager\n */\nexport interface SkillConfigFile {\n /** Path to the config file */\n configPath: string;\n /** Load configuration */\n load: () => SkillsConfig;\n /** Save configuration */\n save: (config: SkillsConfig) => void;\n /** Get skill-specific config */\n getSkillConfig: (skillName: string) => SkillConfig | undefined;\n /** Update skill configuration */\n updateSkillConfig: (skillName: string, config: Partial<SkillConfig>) => void;\n /** Enable/disable a skill */\n setSkillEnabled: (skillName: string, enabled: boolean) => void;\n /** Set skill API key */\n setSkillApiKey: (skillName: string, apiKey: string) => void;\n}\n\n/**\n * Create a skill configuration file manager\n */\nexport function createSkillConfigManager(configDir: string): SkillConfigFile {\n const configPath = join(configDir, 'skills.json');\n\n function loadConfig(): SkillsConfig {\n if (!existsSync(configPath)) {\n return {};\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n return JSON.parse(content);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ error: err, errorMessage: em, path: configPath }, `Skills config load failed, using defaults: ${em}`);\n return {};\n }\n }\n\n function saveConfig(config: SkillsConfig): void {\n try {\n writeTextAtomicSync(configPath, JSON.stringify(config, null, 2));\n log.info('Saved skills config');\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ error: err, errorMessage: em, path: configPath }, `Failed to save skills config: ${em}`);\n }\n }\n\n return {\n configPath,\n\n load: loadConfig,\n\n save: saveConfig,\n\n getSkillConfig: (skillName: string) => {\n const config = loadConfig();\n return config.entries?.[skillName];\n },\n\n updateSkillConfig: (skillName: string, updates: Partial<SkillConfig>) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n ...updates,\n };\n\n saveConfig(config);\n },\n\n setSkillEnabled: (skillName: string, enabled: boolean) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n enabled,\n };\n\n saveConfig(config);\n log.info({ skillName, enabled }, 'Updated skill enabled state');\n },\n\n setSkillApiKey: (skillName: string, apiKey: string) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n apiKey,\n };\n\n saveConfig(config);\n log.info({ skillName }, 'Updated skill API key');\n },\n };\n}\n\n/**\n * Check if a skill is enabled\n */\nexport function isSkillEnabled(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): boolean {\n const config = resolveSkillConfig(skill, skillsConfig);\n \n // Explicitly disabled\n if (config.enabled === false) {\n return false;\n }\n\n // Check if skill has requirements that are not met\n const requires = skill.metadata.xopc?.requires || skill.metadata.requires;\n if (requires?.bins) {\n const { hasBinary } = require('./installer.js');\n for (const bin of requires.bins) {\n if (!hasBinary(bin)) {\n log.debug({ skill: skill.name, bin }, 'Skill requirement not met');\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Validate skill configuration\n */\nexport function validateSkillConfig(config: SkillsConfig): {\n valid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n if (config.toolGating !== undefined && typeof config.toolGating !== 'boolean') {\n errors.push('toolGating must be a boolean');\n }\n\n if (\n config.agentWritePolicy !== undefined &&\n config.agentWritePolicy !== 'global' &&\n config.agentWritePolicy !== 'workspace' &&\n config.agentWritePolicy !== 'both'\n ) {\n errors.push('agentWritePolicy must be \"global\", \"workspace\", or \"both\"');\n }\n\n // Validate limits\n const limits = config.limits;\n if (limits) {\n if (limits.maxCandidatesPerRoot !== undefined && limits.maxCandidatesPerRoot < 1) {\n errors.push('limits.maxCandidatesPerRoot must be at least 1');\n }\n if (limits.maxSkillsLoadedPerSource !== undefined && limits.maxSkillsLoadedPerSource < 1) {\n errors.push('limits.maxSkillsLoadedPerSource must be at least 1');\n }\n if (limits.maxSkillsInPrompt !== undefined && limits.maxSkillsInPrompt < 1) {\n errors.push('limits.maxSkillsInPrompt must be at least 1');\n }\n }\n\n // Validate entries\n if (config.entries) {\n for (const [skillName, skillConfig] of Object.entries(config.entries)) {\n if (skillConfig.apiKey && typeof skillConfig.apiKey !== 'string') {\n errors.push(`entries.${skillName}.apiKey must be a string`);\n }\n if (skillConfig.env && typeof skillConfig.env !== 'object') {\n errors.push(`entries.${skillName}.env must be an object`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../../../src/agent/skills/config.ts"],"sourcesContent":["/**\n * Skill Configuration Manager\n * \n * Handles skill-specific configuration and environment variables.\n *\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport { writeTextAtomicSync } from '../../infra/write-file-atomic.js';\nimport { hasBinary } from './installer.js';\nimport type { SkillConfig, SkillsConfig, Skill } from './types.js';\n\nconst log = createLogger('SkillConfig');\n\n/**\n * Resolve skill configuration from multiple sources\n * \n * Priority (highest to lowest):\n * 1. Environment variable overrides (XOPC_SKILL_<NAME>_<KEY>)\n * 2. Config file entries\n * 3. Skill defaults\n */\nexport function resolveSkillConfig(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): SkillConfig {\n const config: SkillConfig = {};\n\n // Start with config file entries\n const entryConfig = skillsConfig?.entries?.[skill.name];\n if (entryConfig) {\n config.enabled = entryConfig.enabled;\n config.apiKey = entryConfig.apiKey;\n config.env = entryConfig.env ? { ...entryConfig.env } : undefined;\n config.config = entryConfig.config ? { ...entryConfig.config } : undefined;\n }\n\n // Apply environment variable overrides\n const envPrefix = `XOPC_SKILL_${skill.name.toUpperCase().replace(/-/g, '_')}`;\n \n // Check for enabled override\n const enabledEnv = process.env[`${envPrefix}_ENABLED`];\n if (enabledEnv !== undefined) {\n config.enabled = enabledEnv.toLowerCase() === 'true' || enabledEnv === '1';\n }\n\n // Check for API key override\n const apiKeyEnv = process.env[`${envPrefix}_API_KEY`];\n if (apiKeyEnv) {\n config.apiKey = apiKeyEnv;\n }\n\n // Check for environment variable overrides\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(`${envPrefix}_ENV_`)) {\n const envKey = key.slice(`${envPrefix}_ENV_`.length);\n if (!config.env) {\n config.env = {};\n }\n config.env[envKey] = value;\n }\n }\n\n return config;\n}\n\n/**\n * Apply environment variable overrides to a skill's environment\n */\nexport function applySkillEnvOverrides(\n skill: Skill,\n baseEnv: Record<string, string> = {},\n skillConfig?: SkillConfig\n): Record<string, string> {\n const env: Record<string, string> = { ...baseEnv };\n\n // Apply config env\n if (skillConfig?.env) {\n for (const [key, value] of Object.entries(skillConfig.env)) {\n env[key] = value;\n }\n }\n\n // Apply environment variable overrides\n const envPrefix = `XOPC_SKILL_${skill.name.toUpperCase().replace(/-/g, '_')}`;\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(`${envPrefix}_ENV_`)) {\n const envKey = key.slice(`${envPrefix}_ENV_`.length);\n env[envKey] = value;\n }\n }\n\n return env;\n}\n\n/**\n * Get the effective environment for a skill\n */\nexport function getSkillEnvironment(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): Record<string, string> {\n const config = resolveSkillConfig(skill, skillsConfig);\n return applySkillEnvOverrides(skill, process.env as Record<string, string>, config);\n}\n\n/**\n * Skill configuration file manager\n */\nexport interface SkillConfigFile {\n /** Path to the config file */\n configPath: string;\n /** Load configuration */\n load: () => SkillsConfig;\n /** Save configuration */\n save: (config: SkillsConfig) => void;\n /** Get skill-specific config */\n getSkillConfig: (skillName: string) => SkillConfig | undefined;\n /** Update skill configuration */\n updateSkillConfig: (skillName: string, config: Partial<SkillConfig>) => void;\n /** Enable/disable a skill */\n setSkillEnabled: (skillName: string, enabled: boolean) => void;\n /** Set skill API key */\n setSkillApiKey: (skillName: string, apiKey: string) => void;\n}\n\n/**\n * Create a skill configuration file manager\n */\nexport function createSkillConfigManager(configDir: string): SkillConfigFile {\n const configPath = join(configDir, 'skills.json');\n\n function loadConfig(): SkillsConfig {\n if (!existsSync(configPath)) {\n return {};\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n return JSON.parse(content);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ error: err, errorMessage: em, path: configPath }, `Skills config load failed, using defaults: ${em}`);\n return {};\n }\n }\n\n function saveConfig(config: SkillsConfig): void {\n try {\n writeTextAtomicSync(configPath, JSON.stringify(config, null, 2));\n log.info('Saved skills config');\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ error: err, errorMessage: em, path: configPath }, `Failed to save skills config: ${em}`);\n }\n }\n\n return {\n configPath,\n\n load: loadConfig,\n\n save: saveConfig,\n\n getSkillConfig: (skillName: string) => {\n const config = loadConfig();\n return config.entries?.[skillName];\n },\n\n updateSkillConfig: (skillName: string, updates: Partial<SkillConfig>) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n ...updates,\n };\n\n saveConfig(config);\n },\n\n setSkillEnabled: (skillName: string, enabled: boolean) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n enabled,\n };\n\n saveConfig(config);\n log.info({ skillName, enabled }, 'Updated skill enabled state');\n },\n\n setSkillApiKey: (skillName: string, apiKey: string) => {\n const config = loadConfig();\n \n if (!config.entries) {\n config.entries = {};\n }\n\n const existing = config.entries[skillName] || {};\n config.entries[skillName] = {\n ...existing,\n apiKey,\n };\n\n saveConfig(config);\n log.info({ skillName }, 'Updated skill API key');\n },\n };\n}\n\n/**\n * Check if a skill is enabled\n */\nexport function isSkillEnabled(\n skill: Skill,\n skillsConfig?: SkillsConfig\n): boolean {\n const config = resolveSkillConfig(skill, skillsConfig);\n \n // Explicitly disabled\n if (config.enabled === false) {\n return false;\n }\n\n // Check if skill has requirements that are not met\n const requires = skill.metadata.xopc?.requires || skill.metadata.requires;\n if (requires?.bins) {\n for (const bin of requires.bins) {\n if (!hasBinary(bin)) {\n log.debug({ skill: skill.name, bin }, 'Skill requirement not met');\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Validate skill configuration\n */\nexport function validateSkillConfig(config: SkillsConfig): {\n valid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n if (config.toolGating !== undefined && typeof config.toolGating !== 'boolean') {\n errors.push('toolGating must be a boolean');\n }\n\n if (\n config.agentWritePolicy !== undefined &&\n config.agentWritePolicy !== 'global' &&\n config.agentWritePolicy !== 'workspace' &&\n config.agentWritePolicy !== 'both'\n ) {\n errors.push('agentWritePolicy must be \"global\", \"workspace\", or \"both\"');\n }\n\n // Validate limits\n const limits = config.limits;\n if (limits) {\n if (limits.maxCandidatesPerRoot !== undefined && limits.maxCandidatesPerRoot < 1) {\n errors.push('limits.maxCandidatesPerRoot must be at least 1');\n }\n if (limits.maxSkillsLoadedPerSource !== undefined && limits.maxSkillsLoadedPerSource < 1) {\n errors.push('limits.maxSkillsLoadedPerSource must be at least 1');\n }\n if (limits.maxSkillsInPrompt !== undefined && limits.maxSkillsInPrompt < 1) {\n errors.push('limits.maxSkillsInPrompt must be at least 1');\n }\n }\n\n // Validate entries\n if (config.entries) {\n for (const [skillName, skillConfig] of Object.entries(config.entries)) {\n if (skillConfig.apiKey && typeof skillConfig.apiKey !== 'string') {\n errors.push(`entries.${skillName}.apiKey must be a string`);\n }\n if (skillConfig.env && typeof skillConfig.env !== 'object') {\n errors.push(`entries.${skillName}.env must be an object`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n"],"mappings":"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"}
@@ -4,6 +4,7 @@
4
4
  import type { Skill } from './types.js';
5
5
  import type { SkillsConfig } from './types.js';
6
6
  export interface FormatSkillsForPromptOptions {
7
+ /** Explicit skill names visible in this context. Omitted means all enabled skills; empty means no visible skills. */
7
8
  skillAllowlist?: string[];
8
9
  /** When set (including empty array), applies tool gating from skill frontmatter. */
9
10
  registeredToolNames?: string[];
@@ -6,10 +6,11 @@ import { skillVisibleForRegisteredTools } from "./skill-tool-gating.js";
6
6
  */
7
7
  function selectSkillsVisibleInPrompt(skills, skillsConfig, options) {
8
8
  let list = skills;
9
- if (options?.skillAllowlist?.length) {
9
+ if (options?.skillAllowlist !== void 0) {
10
+ if (options.skillAllowlist.length === 0) return [];
10
11
  const allow = new Set(options.skillAllowlist.map((s) => s.toLowerCase()));
11
12
  list = list.filter((s) => allow.has(s.name.toLowerCase()));
12
- } else if (options?.skillAllowlist?.length === 0) return [];
13
+ }
13
14
  list = list.filter((s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig));
14
15
  if (skillsConfig?.toolGating !== false && options?.registeredToolNames !== void 0) {
15
16
  const at = new Set(options.registeredToolNames);
@@ -1 +1 @@
1
- {"version":3,"file":"format-skills-prompt.js","names":[],"sources":["../../../../src/agent/skills/format-skills-prompt.ts"],"sourcesContent":["/**\n * Build `<available_skills>` XML block for the system prompt.\n */\n\nimport { isSkillEnabled } from './config.js';\nimport { skillVisibleForRegisteredTools } from './skill-tool-gating.js';\nimport type { Skill } from './types.js';\nimport type { SkillsConfig } from './types.js';\n\nexport interface FormatSkillsForPromptOptions {\n skillAllowlist?: string[];\n /** When set (including empty array), applies tool gating from skill frontmatter. */\n registeredToolNames?: string[];\n}\n\nexport function selectSkillsVisibleInPrompt(\n skills: Skill[],\n skillsConfig?: SkillsConfig,\n options?: FormatSkillsForPromptOptions,\n): Skill[] {\n let list = skills;\n\n if (options?.skillAllowlist?.length) {\n const allow = new Set(options.skillAllowlist.map((s) => s.toLowerCase()));\n list = list.filter((s) => allow.has(s.name.toLowerCase()));\n } else if (options?.skillAllowlist?.length === 0) {\n return [];\n }\n\n list = list.filter((s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig));\n\n if (skillsConfig?.toolGating !== false && options?.registeredToolNames !== undefined) {\n const at = new Set(options.registeredToolNames);\n list = list.filter((s) => skillVisibleForRegisteredTools(s, at));\n }\n\n return list;\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\nfunction formatSkillXmlMetadataOnly(skill: Skill): string {\n const emoji = skill.metadata.emoji || '';\n const emojiStr = emoji ? `${emoji} ` : '';\n\n return [\n ' <skill>',\n ` <name>${escapeXml(skill.name)}</name>`,\n ` <description>${emojiStr}${escapeXml(skill.description)}</description>`,\n ' </skill>',\n ].join('\\n');\n}\n\nexport function formatSkillsForPrompt(\n skills: Skill[],\n skillsConfig?: SkillsConfig,\n options?: FormatSkillsForPromptOptions,\n): string {\n const visibleSkills = selectSkillsVisibleInPrompt(skills, skillsConfig, options);\n if (visibleSkills.length === 0) return '';\n\n const lines = [\n '\\n\\n<available_skills>',\n 'Skills are folders of instructions, scripts, and resources.',\n 'Use skills_list to browse; use skill_view(name) for SKILL.md or skill_view(name, path) for references/, templates/, scripts/, or assets/.',\n '',\n ];\n\n for (const skill of visibleSkills) {\n lines.push(formatSkillXmlMetadataOnly(skill));\n }\n\n lines.push('</available_skills>');\n return lines.join('\\n');\n}\n"],"mappings":";;;;;;AAeA,SAAgB,4BACd,QACA,cACA,SACS;CACT,IAAI,OAAO;AAEX,KAAI,SAAS,gBAAgB,QAAQ;EACnC,MAAM,QAAQ,IAAI,IAAI,QAAQ,eAAe,KAAK,MAAM,EAAE,aAAa,CAAC,CAAC;AACzE,SAAO,KAAK,QAAQ,MAAM,MAAM,IAAI,EAAE,KAAK,aAAa,CAAC,CAAC;YACjD,SAAS,gBAAgB,WAAW,EAC7C,QAAO,EAAE;AAGX,QAAO,KAAK,QAAQ,MAAM,CAAC,EAAE,0BAA0B,eAAe,GAAG,aAAa,CAAC;AAEvF,KAAI,cAAc,eAAe,SAAS,SAAS,wBAAwB,KAAA,GAAW;EACpF,MAAM,KAAK,IAAI,IAAI,QAAQ,oBAAoB;AAC/C,SAAO,KAAK,QAAQ,MAAM,+BAA+B,GAAG,GAAG,CAAC;;AAGlE,QAAO;;AAGT,SAAS,UAAU,KAAqB;AACtC,QAAO,IACJ,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,SAAS,CACvB,QAAQ,MAAM,SAAS;;AAG5B,SAAS,2BAA2B,OAAsB;CACxD,MAAM,QAAQ,MAAM,SAAS,SAAS;CACtC,MAAM,WAAW,QAAQ,GAAG,MAAM,KAAK;AAEvC,QAAO;EACL;EACA,aAAa,UAAU,MAAM,KAAK,CAAC;EACnC,oBAAoB,WAAW,UAAU,MAAM,YAAY,CAAC;EAC5D;EACD,CAAC,KAAK,KAAK;;AAGd,SAAgB,sBACd,QACA,cACA,SACQ;CACR,MAAM,gBAAgB,4BAA4B,QAAQ,cAAc,QAAQ;AAChF,KAAI,cAAc,WAAW,EAAG,QAAO;CAEvC,MAAM,QAAQ;EACZ;EACA;EACA;EACA;EACD;AAED,MAAK,MAAM,SAAS,cAClB,OAAM,KAAK,2BAA2B,MAAM,CAAC;AAG/C,OAAM,KAAK,sBAAsB;AACjC,QAAO,MAAM,KAAK,KAAK"}
1
+ {"version":3,"file":"format-skills-prompt.js","names":[],"sources":["../../../../src/agent/skills/format-skills-prompt.ts"],"sourcesContent":["/**\n * Build `<available_skills>` XML block for the system prompt.\n */\n\nimport { isSkillEnabled } from './config.js';\nimport { skillVisibleForRegisteredTools } from './skill-tool-gating.js';\nimport type { Skill } from './types.js';\nimport type { SkillsConfig } from './types.js';\n\nexport interface FormatSkillsForPromptOptions {\n /** Explicit skill names visible in this context. Omitted means all enabled skills; empty means no visible skills. */\n skillAllowlist?: string[];\n /** When set (including empty array), applies tool gating from skill frontmatter. */\n registeredToolNames?: string[];\n}\n\nexport function selectSkillsVisibleInPrompt(\n skills: Skill[],\n skillsConfig?: SkillsConfig,\n options?: FormatSkillsForPromptOptions,\n): Skill[] {\n let list = skills;\n\n if (options?.skillAllowlist !== undefined) {\n if (options.skillAllowlist.length === 0) {\n return [];\n }\n const allow = new Set(options.skillAllowlist.map((s) => s.toLowerCase()));\n list = list.filter((s) => allow.has(s.name.toLowerCase()));\n }\n\n list = list.filter((s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig));\n\n if (skillsConfig?.toolGating !== false && options?.registeredToolNames !== undefined) {\n const at = new Set(options.registeredToolNames);\n list = list.filter((s) => skillVisibleForRegisteredTools(s, at));\n }\n\n return list;\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\nfunction formatSkillXmlMetadataOnly(skill: Skill): string {\n const emoji = skill.metadata.emoji || '';\n const emojiStr = emoji ? `${emoji} ` : '';\n\n return [\n ' <skill>',\n ` <name>${escapeXml(skill.name)}</name>`,\n ` <description>${emojiStr}${escapeXml(skill.description)}</description>`,\n ' </skill>',\n ].join('\\n');\n}\n\nexport function formatSkillsForPrompt(\n skills: Skill[],\n skillsConfig?: SkillsConfig,\n options?: FormatSkillsForPromptOptions,\n): string {\n const visibleSkills = selectSkillsVisibleInPrompt(skills, skillsConfig, options);\n if (visibleSkills.length === 0) return '';\n\n const lines = [\n '\\n\\n<available_skills>',\n 'Skills are folders of instructions, scripts, and resources.',\n 'Use skills_list to browse; use skill_view(name) for SKILL.md or skill_view(name, path) for references/, templates/, scripts/, or assets/.',\n '',\n ];\n\n for (const skill of visibleSkills) {\n lines.push(formatSkillXmlMetadataOnly(skill));\n }\n\n lines.push('</available_skills>');\n return lines.join('\\n');\n}\n"],"mappings":";;;;;;AAgBA,SAAgB,4BACd,QACA,cACA,SACS;CACT,IAAI,OAAO;AAEX,KAAI,SAAS,mBAAmB,KAAA,GAAW;AACzC,MAAI,QAAQ,eAAe,WAAW,EACpC,QAAO,EAAE;EAEX,MAAM,QAAQ,IAAI,IAAI,QAAQ,eAAe,KAAK,MAAM,EAAE,aAAa,CAAC,CAAC;AACzE,SAAO,KAAK,QAAQ,MAAM,MAAM,IAAI,EAAE,KAAK,aAAa,CAAC,CAAC;;AAG5D,QAAO,KAAK,QAAQ,MAAM,CAAC,EAAE,0BAA0B,eAAe,GAAG,aAAa,CAAC;AAEvF,KAAI,cAAc,eAAe,SAAS,SAAS,wBAAwB,KAAA,GAAW;EACpF,MAAM,KAAK,IAAI,IAAI,QAAQ,oBAAoB;AAC/C,SAAO,KAAK,QAAQ,MAAM,+BAA+B,GAAG,GAAG,CAAC;;AAGlE,QAAO;;AAGT,SAAS,UAAU,KAAqB;AACtC,QAAO,IACJ,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,SAAS,CACvB,QAAQ,MAAM,SAAS;;AAG5B,SAAS,2BAA2B,OAAsB;CACxD,MAAM,QAAQ,MAAM,SAAS,SAAS;CACtC,MAAM,WAAW,QAAQ,GAAG,MAAM,KAAK;AAEvC,QAAO;EACL;EACA,aAAa,UAAU,MAAM,KAAK,CAAC;EACnC,oBAAoB,WAAW,UAAU,MAAM,YAAY,CAAC;EAC5D;EACD,CAAC,KAAK,KAAK;;AAGd,SAAgB,sBACd,QACA,cACA,SACQ;CACR,MAAM,gBAAgB,4BAA4B,QAAQ,cAAc,QAAQ;AAChF,KAAI,cAAc,WAAW,EAAG,QAAO;CAEvC,MAAM,QAAQ;EACZ;EACA;EACA;EACA;EACD;AAED,MAAK,MAAM,SAAS,cAClB,OAAM,KAAK,2BAA2B,MAAM,CAAC;AAG/C,OAAM,KAAK,sBAAsB;AACjC,QAAO,MAAM,KAAK,KAAK"}
@@ -7,8 +7,8 @@ import { computeSkillTreeHashSync } from "./hub-hash.js";
7
7
  import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
8
8
  import { basename, join, normalize, resolve, sep } from "node:path";
9
9
  import { tmpdir } from "node:os";
10
- import { fileURLToPath } from "node:url";
11
10
  import { execFileSync } from "node:child_process";
11
+ import { fileURLToPath } from "node:url";
12
12
  import { fetch } from "undici";
13
13
  //#region src/agent/skills/hub-pull.ts
14
14
  /**
@@ -3,20 +3,19 @@ import { init_logger } from "../../utils/logger.js";
3
3
  import { resolveStateDir } from "../../config/paths-state.js";
4
4
  import { init_paths } from "../../config/paths.js";
5
5
  import { parseFrontmatter } from "../../markdown/frontmatter.js";
6
- import { findInstallSpec, getDefaultInstallerPreferences, hasBinary, init_installer, installSkill } from "./installer.js";
6
+ import { findInstallSpec, getDefaultInstallerPreferences, hasBinary, installSkill } from "./installer.js";
7
7
  import { applySkillEnvOverrides, createSkillConfigManager, getSkillEnvironment, isSkillEnabled, resolveSkillConfig, validateSkillConfig } from "./config.js";
8
+ import { collectSkillInstallWarnings, formatScanSummary, scanSkillDirectory } from "./scanner.js";
8
9
  import { parseSkillToolConditions } from "./skill-tool-gating.js";
9
10
  import { parseRequiredEnvVarNames } from "./required-env-vars.js";
10
- import { parseSkillMetadata } from "./parse-skill-metadata.js";
11
- import { collectSkillInstallWarnings, formatScanSummary, scanSkillDirectory } from "./scanner.js";
12
11
  import { formatSkillsForPrompt } from "./format-skills-prompt.js";
12
+ import { parseSkillMetadata } from "./parse-skill-metadata.js";
13
13
  import { SkillTestFramework, SkillTestRunner, formatTestResults, formatTestResultsJson, formatTestResultsTap } from "./test-framework.js";
14
14
  import { basename, dirname, join, relative, sep } from "path";
15
15
  import { existsSync, readFileSync, readdirSync } from "fs";
16
16
  //#region src/agent/skills/index.ts
17
17
  init_paths();
18
18
  init_logger();
19
- init_installer();
20
19
  const log = createLogger("SkillLoader");
21
20
  const IGNORE_FILES = [
22
21
  ".gitignore",
@@ -98,13 +97,27 @@ function discoverSkills(dir, source) {
98
97
  scan(dir, loadIgnoreRules(dir, dir));
99
98
  return skills;
100
99
  }
100
+ function deriveDescriptionFromMarkdown(content) {
101
+ let fallbackHeading = "";
102
+ for (const rawLine of content.split(/\r?\n/)) {
103
+ const line = rawLine.trim();
104
+ if (!line) continue;
105
+ const heading = line.match(/^#{1,6}\s+(.+)$/);
106
+ if (heading) {
107
+ fallbackHeading ||= heading[1]?.trim() ?? "";
108
+ continue;
109
+ }
110
+ return line.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/[*_`~]/g, "").trim() || void 0;
111
+ }
112
+ return fallbackHeading || void 0;
113
+ }
101
114
  function loadSkillFromFile(filePath, source, rootDir) {
102
115
  try {
103
116
  const { frontmatter, content } = parseFrontmatter(readFileSync(filePath, "utf-8"));
104
117
  const skillDir = dirname(filePath);
105
118
  const parentDirName = basename(skillDir);
106
119
  const name = frontmatter.name || parentDirName;
107
- const description = frontmatter.description;
120
+ const description = frontmatter.description?.trim() || deriveDescriptionFromMarkdown(content);
108
121
  if (!description?.trim()) return null;
109
122
  let category;
110
123
  if (rootDir) {
@@ -112,6 +125,8 @@ function loadSkillFromFile(filePath, source, rootDir) {
112
125
  if (segments.length > 1) category = segments[0];
113
126
  }
114
127
  const metadata = parseSkillMetadata(frontmatter);
128
+ metadata.name ||= name;
129
+ metadata.description ||= description.trim();
115
130
  const toolConditions = parseSkillToolConditions(frontmatter);
116
131
  const requiredEnvVarNames = parseRequiredEnvVarNames(frontmatter);
117
132
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/agent/skills/index.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync } from 'fs';\nimport { basename, dirname, join, relative, sep } from 'path';\nimport { parseFrontmatter } from '../../markdown/frontmatter.js';\nimport { resolveStateDir } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { createSkillConfigManager, isSkillEnabled } from './config.js';\nimport { formatSkillsForPrompt } from './format-skills-prompt.js';\nimport { parseRequiredEnvVarNames } from './required-env-vars.js';\nimport { parseSkillMetadata } from './parse-skill-metadata.js';\nimport { parseSkillToolConditions } from './skill-tool-gating.js';\nimport type { Skill, SkillDiagnostic, LoadSkillsResult, SkillConfig, SkillsConfig } from './types.js';\n\nconst log = createLogger('SkillLoader');\n\nconst IGNORE_FILES = ['.gitignore', '.ignore', '.fdignore'];\n\nfunction toPosixPath(p: string): string {\n return p.split(sep).join('/');\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n if (trimmed.startsWith('#') && !trimmed.startsWith('\\\\#')) return null;\n\n let pattern = line;\n let negated = false;\n\n if (pattern.startsWith('!')) {\n negated = true;\n pattern = pattern.slice(1);\n } else if (pattern.startsWith('\\\\!')) {\n pattern = pattern.slice(1);\n }\n\n if (pattern.startsWith('/')) {\n pattern = pattern.slice(1);\n }\n\n const prefixed = prefix ? `${prefix}${pattern}` : pattern;\n return negated ? `!${prefixed}` : prefixed;\n}\n\nfunction loadIgnoreRules(dir: string, rootDir: string): Set<string> {\n const ignoredPaths = new Set<string>();\n const relativeDir = relative(rootDir, dir);\n const prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : '';\n\n for (const filename of IGNORE_FILES) {\n const ignorePath = join(dir, filename);\n if (!existsSync(ignorePath)) continue;\n\n try {\n const content = readFileSync(ignorePath, 'utf-8');\n for (const line of content.split(/\\r?\\n/)) {\n const pattern = prefixIgnorePattern(line, prefix);\n if (pattern) {\n const fullPattern = pattern.startsWith('!')\n ? `!${prefix}${pattern.slice(1)}`\n : `${prefix}${pattern}`;\n ignoredPaths.add(fullPattern);\n }\n }\n } catch {}\n }\n\n return ignoredPaths;\n}\n\nfunction shouldIgnore(path: string, ignoredPaths: Set<string>): boolean {\n for (const pattern of ignoredPaths) {\n if (pattern.startsWith('!')) {\n const positive = pattern.slice(1);\n if (path === positive || path.startsWith(`${positive}/`)) {\n return false;\n }\n } else {\n if (path === pattern || path.startsWith(`${pattern}/`)) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction discoverSkills(dir: string, source: 'builtin' | 'workspace' | 'global'): Skill[] {\n const skills: Skill[] = [];\n if (!existsSync(dir)) return skills;\n\n function scan(currentDir: string, currentIgnoredPaths: Set<string>) {\n try {\n const entries = readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;\n\n const fullPath = join(currentDir, entry.name);\n const relPath = toPosixPath(relative(dir, fullPath));\n\n if (shouldIgnore(relPath, currentIgnoredPaths)) continue;\n\n if (entry.isDirectory()) {\n const skillMdPath = join(fullPath, 'SKILL.md');\n const skillRelPath = `${relPath}/`;\n\n const subIgnoredPaths = new Set(currentIgnoredPaths);\n const subIgnoreFile = join(fullPath, '.gitignore');\n if (existsSync(subIgnoreFile)) {\n const subRules = loadIgnoreRules(fullPath, dir);\n for (const rule of subRules) {\n subIgnoredPaths.add(`${skillRelPath}${rule}`);\n }\n }\n\n if (existsSync(skillMdPath) && !shouldIgnore(skillRelPath, currentIgnoredPaths)) {\n const skill = loadSkillFromFile(skillMdPath, source, dir);\n if (skill) skills.push(skill);\n }\n\n scan(fullPath, subIgnoredPaths);\n }\n }\n } catch {}\n }\n\n scan(dir, loadIgnoreRules(dir, dir));\n return skills;\n}\n\nfunction loadSkillFromFile(filePath: string, source: 'builtin' | 'workspace' | 'global', rootDir?: string): Skill | null {\n try {\n const rawContent = readFileSync(filePath, 'utf-8');\n const { frontmatter, content } = parseFrontmatter(rawContent);\n const skillDir = dirname(filePath);\n const parentDirName = basename(skillDir);\n\n const name = (frontmatter.name as string | undefined) || parentDirName;\n const description = frontmatter.description as string | undefined;\n if (!description?.trim()) return null;\n\n // Derive category from directory path: skills/creative/algorithmic-art → 'creative'\n // Only assign a category when the skill is nested at least two levels below rootDir.\n let category: string | undefined;\n if (rootDir) {\n const relDir = toPosixPath(relative(rootDir, skillDir));\n const segments = relDir.split('/');\n if (segments.length > 1) {\n category = segments[0];\n }\n }\n\n const metadata = parseSkillMetadata(frontmatter);\n const toolConditions = parseSkillToolConditions(frontmatter);\n const requiredEnvVarNames = parseRequiredEnvVarNames(frontmatter);\n\n return {\n name,\n description: description.trim(),\n category,\n filePath,\n baseDir: skillDir,\n source,\n disableModelInvocation: frontmatter['disable-model-invocation'] === true,\n metadata,\n toolConditions,\n requiredEnvVarNames: requiredEnvVarNames.length > 0 ? requiredEnvVarNames : undefined,\n content,\n };\n } catch {\n return null;\n }\n}\n\nexport function loadSkills(options: {\n workspaceDir?: string;\n globalDir?: string;\n builtinDir?: string;\n extraDirs?: string[];\n}): LoadSkillsResult {\n const { workspaceDir, builtinDir, extraDirs = [] } = options;\n\n const skillMap = new Map<string, Skill>();\n const diagnostics: SkillDiagnostic[] = [];\n\n if (builtinDir) {\n for (const skill of discoverSkills(builtinDir, 'builtin')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${existing.source} overrides ${skill.source}`,\n path: skill.filePath,\n });\n } else {\n skillMap.set(skill.name, skill);\n }\n }\n }\n\n const globalDirs = [\n options.globalDir,\n join(resolveStateDir(), 'skills'),\n ].filter((d): d is string => !!d && existsSync(d));\n\n for (const dir of globalDirs) {\n for (const skill of discoverSkills(dir, 'global')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${skill.source} overrides ${existing.source}`,\n path: skill.filePath,\n });\n }\n // Global must win over bundled when names match (Workspace > Global > Bundled).\n skillMap.set(skill.name, skill);\n }\n }\n\n if (workspaceDir) {\n const workspaceSkills = discoverSkills(join(workspaceDir, 'skills'), 'workspace');\n for (const skill of workspaceSkills) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${skill.source} overrides ${existing.source}`,\n path: skill.filePath,\n });\n }\n skillMap.set(skill.name, skill);\n }\n }\n\n // Scan extra directories\n for (const extraDir of extraDirs) {\n if (existsSync(extraDir)) {\n for (const skill of discoverSkills(extraDir, 'global')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${existing.source} overrides ${skill.source}`,\n path: skill.filePath,\n });\n } else {\n skillMap.set(skill.name, skill);\n }\n }\n }\n }\n\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n const merged = Array.from(skillMap.values());\n\n return {\n skills: merged,\n prompt: formatSkillsForPrompt(merged, skillsConfig),\n diagnostics,\n };\n}\n\nexport interface SkillLoader {\n init: (workspace: string, builtin: string | null) => LoadSkillsResult;\n load: () => LoadSkillsResult;\n reload: () => LoadSkillsResult;\n /** Recompute `<available_skills>` from disk-loaded skills and current ~/.xopc/skills.json (no filesystem rescan). */\n refreshPromptFromConfig: () => void;\n getSkills: () => Skill[];\n getPrompt: () => string;\n getDiagnostics: () => SkillDiagnostic[];\n getLastLoadTime: () => number;\n getSkillByName: (name: string) => Skill | undefined;\n getEnabledSkills: (config?: Record<string, SkillConfig>) => Skill[];\n}\n\nexport function createSkillLoader(): SkillLoader {\n let cachedSkills: Skill[] = [];\n let cachedPrompt: string = '';\n let cachedDiagnostics: SkillDiagnostic[] = [];\n let lastLoadTime = 0;\n let workspaceDir: string | undefined;\n let builtinDir: string | undefined;\n let extraDirs: string[] = [];\n\n function updateCache(result: LoadSkillsResult): LoadSkillsResult {\n cachedSkills = result.skills;\n cachedPrompt = result.prompt;\n cachedDiagnostics = result.diagnostics;\n lastLoadTime = Date.now();\n return result;\n }\n\n return {\n init: (workspace: string, builtin: string | null) => {\n workspaceDir = workspace;\n builtinDir = builtin || undefined;\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n \n load: () => {\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n \n reload: () => {\n log.info('Reloading skills');\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n\n refreshPromptFromConfig: () => {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n cachedPrompt = formatSkillsForPrompt(cachedSkills, skillsConfig);\n lastLoadTime = Date.now();\n },\n\n getSkills: () => cachedSkills,\n getPrompt: () => cachedPrompt,\n getDiagnostics: () => cachedDiagnostics,\n getLastLoadTime: () => lastLoadTime,\n \n getSkillByName: (name: string) => {\n return cachedSkills.find(s => s.name === name);\n },\n \n getEnabledSkills: (entries?: Record<string, SkillConfig>) => {\n const skillsConfig: SkillsConfig =\n entries !== undefined ? { entries } : createSkillConfigManager(resolveStateDir()).load();\n return cachedSkills.filter(\n (skill) => !skill.disableModelInvocation && isSkillEnabled(skill, skillsConfig),\n );\n },\n };\n}\n\n// `SkillManager` + sibling types removed from this barrel — `skill-manager.ts`\n// imports `createSkillLoader` from THIS file, so re-exporting it back here\n// formed a circular cycle. External callers should import directly from\n// `./skill-manager.js`.\n\n// Re-export types for convenience\nexport type { \n Skill, \n SkillMetadata, \n SkillConfig,\n SkillInstallSpec,\n SkillInstallResult,\n SkillInstallRequest,\n LoadSkillsResult,\n // Note: SkillDiagnostic is re-exported from skill-manager.ts above\n SkillSnapshot,\n} from './types.js';\n\n// Re-export installer\nexport { \n installSkill, \n findInstallSpec,\n hasBinary,\n getDefaultInstallerPreferences,\n type InstallerPreferences,\n type InstallContext,\n} from './installer.js';\n\n// Re-export scanner\nexport {\n scanSkillDirectory,\n formatScanSummary,\n collectSkillInstallWarnings,\n type ScanSummary,\n type SecurityFinding,\n type Severity,\n} from './scanner.js';\n\n// Re-export config manager\nexport {\n resolveSkillConfig,\n applySkillEnvOverrides,\n getSkillEnvironment,\n createSkillConfigManager,\n isSkillEnabled,\n validateSkillConfig,\n type SkillConfigFile,\n} from './config.js';\n\n// `watcher.ts` re-exports removed — it imports `SkillLoader` from THIS file, so\n// re-exporting back here formed a circular cycle. External callers should\n// import directly from `./watcher.js`.\n\n// Re-export test framework\nexport {\n SkillTestFramework,\n SkillTestRunner,\n formatTestResults,\n formatTestResultsJson,\n formatTestResultsTap,\n type TestResult,\n type TestStatus,\n type SkillTestReport,\n type TestOptions,\n type TestRunnerOptions,\n} from './test-framework.js';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/agent/skills/index.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync } from 'fs';\nimport { basename, dirname, join, relative, sep } from 'path';\nimport { parseFrontmatter } from '../../markdown/frontmatter.js';\nimport { resolveStateDir } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { createSkillConfigManager, isSkillEnabled } from './config.js';\nimport { formatSkillsForPrompt } from './format-skills-prompt.js';\nimport { parseRequiredEnvVarNames } from './required-env-vars.js';\nimport { parseSkillMetadata } from './parse-skill-metadata.js';\nimport { parseSkillToolConditions } from './skill-tool-gating.js';\nimport type { Skill, SkillDiagnostic, LoadSkillsResult, SkillConfig, SkillsConfig } from './types.js';\n\nconst log = createLogger('SkillLoader');\n\nconst IGNORE_FILES = ['.gitignore', '.ignore', '.fdignore'];\n\nfunction toPosixPath(p: string): string {\n return p.split(sep).join('/');\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n if (trimmed.startsWith('#') && !trimmed.startsWith('\\\\#')) return null;\n\n let pattern = line;\n let negated = false;\n\n if (pattern.startsWith('!')) {\n negated = true;\n pattern = pattern.slice(1);\n } else if (pattern.startsWith('\\\\!')) {\n pattern = pattern.slice(1);\n }\n\n if (pattern.startsWith('/')) {\n pattern = pattern.slice(1);\n }\n\n const prefixed = prefix ? `${prefix}${pattern}` : pattern;\n return negated ? `!${prefixed}` : prefixed;\n}\n\nfunction loadIgnoreRules(dir: string, rootDir: string): Set<string> {\n const ignoredPaths = new Set<string>();\n const relativeDir = relative(rootDir, dir);\n const prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : '';\n\n for (const filename of IGNORE_FILES) {\n const ignorePath = join(dir, filename);\n if (!existsSync(ignorePath)) continue;\n\n try {\n const content = readFileSync(ignorePath, 'utf-8');\n for (const line of content.split(/\\r?\\n/)) {\n const pattern = prefixIgnorePattern(line, prefix);\n if (pattern) {\n const fullPattern = pattern.startsWith('!')\n ? `!${prefix}${pattern.slice(1)}`\n : `${prefix}${pattern}`;\n ignoredPaths.add(fullPattern);\n }\n }\n } catch {}\n }\n\n return ignoredPaths;\n}\n\nfunction shouldIgnore(path: string, ignoredPaths: Set<string>): boolean {\n for (const pattern of ignoredPaths) {\n if (pattern.startsWith('!')) {\n const positive = pattern.slice(1);\n if (path === positive || path.startsWith(`${positive}/`)) {\n return false;\n }\n } else {\n if (path === pattern || path.startsWith(`${pattern}/`)) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction discoverSkills(dir: string, source: 'builtin' | 'workspace' | 'global'): Skill[] {\n const skills: Skill[] = [];\n if (!existsSync(dir)) return skills;\n\n function scan(currentDir: string, currentIgnoredPaths: Set<string>) {\n try {\n const entries = readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;\n\n const fullPath = join(currentDir, entry.name);\n const relPath = toPosixPath(relative(dir, fullPath));\n\n if (shouldIgnore(relPath, currentIgnoredPaths)) continue;\n\n if (entry.isDirectory()) {\n const skillMdPath = join(fullPath, 'SKILL.md');\n const skillRelPath = `${relPath}/`;\n\n const subIgnoredPaths = new Set(currentIgnoredPaths);\n const subIgnoreFile = join(fullPath, '.gitignore');\n if (existsSync(subIgnoreFile)) {\n const subRules = loadIgnoreRules(fullPath, dir);\n for (const rule of subRules) {\n subIgnoredPaths.add(`${skillRelPath}${rule}`);\n }\n }\n\n if (existsSync(skillMdPath) && !shouldIgnore(skillRelPath, currentIgnoredPaths)) {\n const skill = loadSkillFromFile(skillMdPath, source, dir);\n if (skill) skills.push(skill);\n }\n\n scan(fullPath, subIgnoredPaths);\n }\n }\n } catch {}\n }\n\n scan(dir, loadIgnoreRules(dir, dir));\n return skills;\n}\n\nfunction deriveDescriptionFromMarkdown(content: string): string | undefined {\n let fallbackHeading = '';\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line) continue;\n\n const heading = line.match(/^#{1,6}\\s+(.+)$/);\n if (heading) {\n fallbackHeading ||= heading[1]?.trim() ?? '';\n continue;\n }\n\n return line\n .replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1')\n .replace(/[*_`~]/g, '')\n .trim() || undefined;\n }\n\n return fallbackHeading || undefined;\n}\n\nfunction loadSkillFromFile(filePath: string, source: 'builtin' | 'workspace' | 'global', rootDir?: string): Skill | null {\n try {\n const rawContent = readFileSync(filePath, 'utf-8');\n const { frontmatter, content } = parseFrontmatter(rawContent);\n const skillDir = dirname(filePath);\n const parentDirName = basename(skillDir);\n\n const name = (frontmatter.name as string | undefined) || parentDirName;\n const description =\n (frontmatter.description as string | undefined)?.trim() || deriveDescriptionFromMarkdown(content);\n if (!description?.trim()) return null;\n\n // Derive category from directory path: skills/creative/algorithmic-art → 'creative'\n // Only assign a category when the skill is nested at least two levels below rootDir.\n let category: string | undefined;\n if (rootDir) {\n const relDir = toPosixPath(relative(rootDir, skillDir));\n const segments = relDir.split('/');\n if (segments.length > 1) {\n category = segments[0];\n }\n }\n\n const metadata = parseSkillMetadata(frontmatter);\n metadata.name ||= name;\n metadata.description ||= description.trim();\n const toolConditions = parseSkillToolConditions(frontmatter);\n const requiredEnvVarNames = parseRequiredEnvVarNames(frontmatter);\n\n return {\n name,\n description: description.trim(),\n category,\n filePath,\n baseDir: skillDir,\n source,\n disableModelInvocation: frontmatter['disable-model-invocation'] === true,\n metadata,\n toolConditions,\n requiredEnvVarNames: requiredEnvVarNames.length > 0 ? requiredEnvVarNames : undefined,\n content,\n };\n } catch {\n return null;\n }\n}\n\nexport function loadSkills(options: {\n workspaceDir?: string;\n globalDir?: string;\n builtinDir?: string;\n extraDirs?: string[];\n}): LoadSkillsResult {\n const { workspaceDir, builtinDir, extraDirs = [] } = options;\n\n const skillMap = new Map<string, Skill>();\n const diagnostics: SkillDiagnostic[] = [];\n\n if (builtinDir) {\n for (const skill of discoverSkills(builtinDir, 'builtin')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${existing.source} overrides ${skill.source}`,\n path: skill.filePath,\n });\n } else {\n skillMap.set(skill.name, skill);\n }\n }\n }\n\n const globalDirs = [\n options.globalDir,\n join(resolveStateDir(), 'skills'),\n ].filter((d): d is string => !!d && existsSync(d));\n\n for (const dir of globalDirs) {\n for (const skill of discoverSkills(dir, 'global')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${skill.source} overrides ${existing.source}`,\n path: skill.filePath,\n });\n }\n // Global must win over bundled when names match (Workspace > Global > Bundled).\n skillMap.set(skill.name, skill);\n }\n }\n\n if (workspaceDir) {\n const workspaceSkills = discoverSkills(join(workspaceDir, 'skills'), 'workspace');\n for (const skill of workspaceSkills) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${skill.source} overrides ${existing.source}`,\n path: skill.filePath,\n });\n }\n skillMap.set(skill.name, skill);\n }\n }\n\n // Scan extra directories\n for (const extraDir of extraDirs) {\n if (existsSync(extraDir)) {\n for (const skill of discoverSkills(extraDir, 'global')) {\n const existing = skillMap.get(skill.name);\n if (existing) {\n diagnostics.push({\n type: 'collision',\n skillName: skill.name,\n message: `Skill \"${skill.name}\" collision: ${existing.source} overrides ${skill.source}`,\n path: skill.filePath,\n });\n } else {\n skillMap.set(skill.name, skill);\n }\n }\n }\n }\n\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n const merged = Array.from(skillMap.values());\n\n return {\n skills: merged,\n prompt: formatSkillsForPrompt(merged, skillsConfig),\n diagnostics,\n };\n}\n\nexport interface SkillLoader {\n init: (workspace: string, builtin: string | null) => LoadSkillsResult;\n load: () => LoadSkillsResult;\n reload: () => LoadSkillsResult;\n /** Recompute `<available_skills>` from disk-loaded skills and current ~/.xopc/skills.json (no filesystem rescan). */\n refreshPromptFromConfig: () => void;\n getSkills: () => Skill[];\n getPrompt: () => string;\n getDiagnostics: () => SkillDiagnostic[];\n getLastLoadTime: () => number;\n getSkillByName: (name: string) => Skill | undefined;\n getEnabledSkills: (config?: Record<string, SkillConfig>) => Skill[];\n}\n\nexport function createSkillLoader(): SkillLoader {\n let cachedSkills: Skill[] = [];\n let cachedPrompt: string = '';\n let cachedDiagnostics: SkillDiagnostic[] = [];\n let lastLoadTime = 0;\n let workspaceDir: string | undefined;\n let builtinDir: string | undefined;\n let extraDirs: string[] = [];\n\n function updateCache(result: LoadSkillsResult): LoadSkillsResult {\n cachedSkills = result.skills;\n cachedPrompt = result.prompt;\n cachedDiagnostics = result.diagnostics;\n lastLoadTime = Date.now();\n return result;\n }\n\n return {\n init: (workspace: string, builtin: string | null) => {\n workspaceDir = workspace;\n builtinDir = builtin || undefined;\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n \n load: () => {\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n \n reload: () => {\n log.info('Reloading skills');\n return updateCache(loadSkills({ workspaceDir, builtinDir, extraDirs }));\n },\n\n refreshPromptFromConfig: () => {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n cachedPrompt = formatSkillsForPrompt(cachedSkills, skillsConfig);\n lastLoadTime = Date.now();\n },\n\n getSkills: () => cachedSkills,\n getPrompt: () => cachedPrompt,\n getDiagnostics: () => cachedDiagnostics,\n getLastLoadTime: () => lastLoadTime,\n \n getSkillByName: (name: string) => {\n return cachedSkills.find(s => s.name === name);\n },\n \n getEnabledSkills: (entries?: Record<string, SkillConfig>) => {\n const skillsConfig: SkillsConfig =\n entries !== undefined ? { entries } : createSkillConfigManager(resolveStateDir()).load();\n return cachedSkills.filter(\n (skill) => !skill.disableModelInvocation && isSkillEnabled(skill, skillsConfig),\n );\n },\n };\n}\n\n// `SkillManager` + sibling types removed from this barrel — `skill-manager.ts`\n// imports `createSkillLoader` from THIS file, so re-exporting it back here\n// formed a circular cycle. External callers should import directly from\n// `./skill-manager.js`.\n\n// Re-export types for convenience\nexport type { \n Skill, \n SkillMetadata, \n SkillConfig,\n SkillInstallSpec,\n SkillInstallResult,\n SkillInstallRequest,\n LoadSkillsResult,\n // Note: SkillDiagnostic is re-exported from skill-manager.ts above\n SkillSnapshot,\n} from './types.js';\n\n// Re-export installer\nexport { \n installSkill, \n findInstallSpec,\n hasBinary,\n getDefaultInstallerPreferences,\n type InstallerPreferences,\n type InstallContext,\n} from './installer.js';\n\n// Re-export scanner\nexport {\n scanSkillDirectory,\n formatScanSummary,\n collectSkillInstallWarnings,\n type ScanSummary,\n type SecurityFinding,\n type Severity,\n} from './scanner.js';\n\n// Re-export config manager\nexport {\n resolveSkillConfig,\n applySkillEnvOverrides,\n getSkillEnvironment,\n createSkillConfigManager,\n isSkillEnabled,\n validateSkillConfig,\n type SkillConfigFile,\n} from './config.js';\n\n// `watcher.ts` re-exports removed — it imports `SkillLoader` from THIS file, so\n// re-exporting back here formed a circular cycle. External callers should\n// import directly from `./watcher.js`.\n\n// Re-export test framework\nexport {\n SkillTestFramework,\n SkillTestRunner,\n formatTestResults,\n formatTestResultsJson,\n formatTestResultsTap,\n type TestResult,\n type TestStatus,\n type SkillTestReport,\n type TestOptions,\n type TestRunnerOptions,\n} from './test-framework.js';\n"],"mappings":"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"}
@@ -1,8 +1,7 @@
1
- import { __esmMin, __exportAll, __require } from "../../../_virtual/_rolldown/runtime.js";
2
1
  import { createLogger } from "../../utils/logger/index.js";
3
2
  import { init_logger } from "../../utils/logger.js";
4
- import { join } from "path";
5
- import { existsSync } from "fs";
3
+ import { delimiter, join } from "path";
4
+ import { accessSync, constants, existsSync } from "fs";
6
5
  import { promisify } from "util";
7
6
  import { exec } from "child_process";
8
7
  //#region src/agent/skills/installer.ts
@@ -12,29 +11,24 @@ import { exec } from "child_process";
12
11
  * Handles installation of skill dependencies via various package managers.
13
12
  *
14
13
  */
15
- var installer_exports = /* @__PURE__ */ __exportAll({
16
- findInstallSpec: () => findInstallSpec,
17
- getDefaultInstallerPreferences: () => getDefaultInstallerPreferences,
18
- hasBinary: () => hasBinary,
19
- installSkill: () => installSkill,
20
- resolveBrewExecutable: () => resolveBrewExecutable
21
- });
14
+ init_logger();
15
+ const execAsync = promisify(exec);
16
+ const log = createLogger("SkillInstaller");
22
17
  /**
23
18
  * Check if a binary exists
24
19
  */
25
20
  function hasBinary(name) {
26
- try {
27
- const { which } = __require("which");
28
- return !!which.sync(name, { nothrow: true });
29
- } catch {
21
+ if (!name || name.includes("/") || name.includes("\\")) return false;
22
+ const pathEntries = (process.env.PATH || "").split(delimiter).filter(Boolean);
23
+ const extensions = process.platform === "win32" ? (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean) : [""];
24
+ for (const dir of pathEntries) for (const ext of extensions) {
25
+ const candidate = join(dir, `${name}${ext}`);
30
26
  try {
31
- const { execSync } = __require("child_process");
32
- execSync(`which ${name}`, { stdio: "ignore" });
27
+ accessSync(candidate, constants.X_OK);
33
28
  return true;
34
- } catch {
35
- return false;
36
- }
29
+ } catch {}
37
30
  }
31
+ return false;
38
32
  }
39
33
  /**
40
34
  * Resolve brew executable path
@@ -347,14 +341,7 @@ function getDefaultInstallerPreferences() {
347
341
  nodeManager: "pnpm"
348
342
  };
349
343
  }
350
- var execAsync, log;
351
- var init_installer = __esmMin((() => {
352
- init_logger();
353
- execAsync = promisify(exec);
354
- log = createLogger("SkillInstaller");
355
- }));
356
344
  //#endregion
357
- init_installer();
358
- export { findInstallSpec, getDefaultInstallerPreferences, hasBinary, init_installer, installSkill, installer_exports, resolveBrewExecutable };
345
+ export { findInstallSpec, getDefaultInstallerPreferences, hasBinary, installSkill, resolveBrewExecutable };
359
346
 
360
347
  //# sourceMappingURL=installer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"installer.js","names":[],"sources":["../../../../src/agent/skills/installer.ts"],"sourcesContent":["/**\n * Skill Installer\n * \n * Handles installation of skill dependencies via various package managers.\n *\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillEntry, SkillInstallResult, SkillInstallSpec } from './types.js';\n\nconst execAsync = promisify(exec);\n\nconst log = createLogger('SkillInstaller');\n\nexport interface InstallerPreferences {\n preferBrew: boolean;\n nodeManager: 'pnpm' | 'npm' | 'yarn' | 'bun';\n}\n\nexport interface InstallContext {\n workspaceDir: string;\n skillEntry: SkillEntry;\n installSpec: SkillInstallSpec;\n timeoutMs: number;\n preferences: InstallerPreferences;\n}\n\n/**\n * Check if a binary exists\n */\nexport function hasBinary(name: string): boolean {\n try {\n const { which } = require('which');\n return !!which.sync(name, { nothrow: true });\n } catch {\n // Fallback: try to execute the command\n try {\n const { execSync } = require('child_process');\n execSync(`which ${name}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n }\n}\n\n/**\n * Resolve brew executable path\n */\nexport function resolveBrewExecutable(): string | undefined {\n const candidates = [\n '/opt/homebrew/bin/brew',\n '/usr/local/bin/brew',\n ];\n \n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n \n return undefined;\n}\n\n/**\n * Build install command for Node.js packages\n */\nfunction buildNodeInstallCommand(packageName: string, manager: InstallerPreferences['nodeManager']): string[] {\n switch (manager) {\n case 'pnpm':\n return ['pnpm', 'add', '-g', '--ignore-scripts', packageName];\n case 'yarn':\n return ['yarn', 'global', 'add', '--ignore-scripts', packageName];\n case 'bun':\n return ['bun', 'add', '-g', '--ignore-scripts', packageName];\n default:\n return ['npm', 'install', '-g', '--ignore-scripts', packageName];\n }\n}\n\n/**\n * Build install command from spec\n */\nfunction buildInstallCommand(spec: SkillInstallSpec, prefs: InstallerPreferences): {\n argv: string[] | null;\n error?: string;\n} {\n switch (spec.kind) {\n case 'brew': {\n if (!spec.formula) {\n return { argv: null, error: 'Missing brew formula' };\n }\n return { argv: ['brew', 'install', spec.formula] };\n }\n \n case 'pnpm':\n case 'npm':\n case 'yarn':\n case 'bun': {\n if (!spec.package) {\n return { argv: null, error: 'Missing package name' };\n }\n return {\n argv: buildNodeInstallCommand(spec.package, prefs.nodeManager),\n };\n }\n \n case 'go': {\n if (!spec.module) {\n return { argv: null, error: 'Missing go module' };\n }\n return { argv: ['go', 'install', spec.module] };\n }\n \n case 'uv': {\n if (!spec.package) {\n return { argv: null, error: 'Missing uv package' };\n }\n return { argv: ['uv', 'tool', 'install', spec.package] };\n }\n \n case 'download': {\n return { argv: null, error: 'Download install handled separately' };\n }\n \n default: {\n const _exhaustive: never = spec.kind;\n return { argv: null, error: `Unsupported installer: ${spec.kind}` };\n }\n }\n}\n\n/**\n * Run command with timeout\n */\nasync function runCommandWithTimeout(\n argv: string[],\n timeoutMs: number,\n env?: NodeJS.ProcessEnv\n): Promise<{ code: number | null; stdout: string; stderr: string }> {\n const [cmd, ...args] = argv;\n \n try {\n const { stdout, stderr } = await execAsync(`${cmd} ${args.join(' ')}`, {\n timeout: timeoutMs,\n env,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n });\n \n return {\n code: 0,\n stdout: stdout.toString(),\n stderr: stderr.toString(),\n };\n } catch (err: unknown) {\n if (err instanceof Error) {\n const execError = err as Error & { code?: number; stdout?: string; stderr?: string };\n return {\n code: execError.code ?? null,\n stdout: execError.stdout?.toString() ?? '',\n stderr: execError.stderr?.toString() ?? '',\n };\n }\n \n return {\n code: null,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/**\n * Ensure uv is installed\n */\nasync function ensureUvInstalled(timeoutMs: number): Promise<SkillInstallResult | undefined> {\n if (hasBinary('uv')) {\n return undefined;\n }\n \n // Try to install via brew\n const brewExe = resolveBrewExecutable();\n if (!brewExe) {\n return {\n ok: false,\n message: 'uv not installed — install manually: https://docs.astral.sh/uv/getting-started/installation/',\n stdout: '',\n stderr: '',\n code: null,\n };\n }\n \n const result = await runCommandWithTimeout([brewExe, 'install', 'uv'], timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'Failed to install uv (brew)',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n}\n\n/**\n * Ensure Go is installed\n */\nasync function ensureGoInstalled(timeoutMs: number): Promise<SkillInstallResult | undefined> {\n if (hasBinary('go')) {\n return undefined;\n }\n \n const brewExe = resolveBrewExecutable();\n if (brewExe) {\n const result = await runCommandWithTimeout([brewExe, 'install', 'go'], timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'Failed to install go (brew)',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n }\n \n // Try apt-get on Linux\n if (hasBinary('apt-get')) {\n const isRoot = process.getuid?.() === 0;\n const aptCmd = isRoot \n ? ['apt-get', 'install', '-y', 'golang-go']\n : ['sudo', 'apt-get', 'install', '-y', 'golang-go'];\n \n // Update package index first\n if (!isRoot) {\n await runCommandWithTimeout(['sudo', 'apt-get', 'update', '-qq'], Math.min(timeoutMs, 30000));\n }\n \n const result = await runCommandWithTimeout(aptCmd, timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'go not installed — automatic install via apt failed. Install manually: https://go.dev/doc/install',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n }\n \n return {\n ok: false,\n message: 'go not installed — install manually: https://go.dev/doc/install',\n stdout: '',\n stderr: '',\n code: null,\n };\n}\n\n/**\n * Create install failure result\n */\nfunction createInstallFailure(params: {\n message: string;\n stdout?: string;\n stderr?: string;\n code?: number | null;\n}): SkillInstallResult {\n return {\n ok: false,\n message: params.message,\n stdout: params.stdout?.trim() ?? '',\n stderr: params.stderr?.trim() ?? '',\n code: params.code ?? null,\n };\n}\n\n/**\n * Create install success result\n */\nfunction createInstallSuccess(result: { code: number | null; stdout: string; stderr: string }): SkillInstallResult {\n return {\n ok: true,\n message: 'Installed',\n stdout: result.stdout.trim(),\n stderr: result.stderr.trim(),\n code: result.code,\n };\n}\n\n/**\n * Find install spec by ID\n */\nexport function findInstallSpec(entry: SkillEntry, installId: string): SkillInstallSpec | undefined {\n const specs = entry.metadata.install ?? [];\n \n for (const [index, spec] of specs.entries()) {\n const id = spec.id ?? `${spec.kind}-${index}`;\n if (id === installId) {\n return spec;\n }\n }\n \n return undefined;\n}\n\n/**\n * Install a skill dependency\n */\nexport async function installSkill(ctx: InstallContext): Promise<SkillInstallResult> {\n const { installSpec, timeoutMs, preferences } = ctx;\n \n log.info({ skill: ctx.skillEntry.skill.name, kind: installSpec.kind }, 'Installing skill dependency');\n \n // Handle download installer separately\n if (installSpec.kind === 'download') {\n return createInstallFailure({\n message: 'Download installer not yet implemented',\n });\n }\n \n // Check and install prerequisites\n if (installSpec.kind === 'uv') {\n const uvFailure = await ensureUvInstalled(timeoutMs);\n if (uvFailure) {\n return uvFailure;\n }\n }\n \n if (installSpec.kind === 'go') {\n const goFailure = await ensureGoInstalled(timeoutMs);\n if (goFailure) {\n return goFailure;\n }\n }\n \n // Build install command\n const command = buildInstallCommand(installSpec, preferences);\n if (command.error) {\n return createInstallFailure({\n message: command.error,\n });\n }\n \n if (!command.argv) {\n return createInstallFailure({\n message: 'Invalid install command',\n });\n }\n \n // Resolve brew executable\n let argv = [...command.argv];\n if (installSpec.kind === 'brew') {\n const brewExe = resolveBrewExecutable();\n if (!brewExe) {\n const hint = process.platform === 'linux'\n ? 'Homebrew is not installed. Install it from https://brew.sh or use your system package manager.'\n : 'Homebrew is not installed. Install it from https://brew.sh';\n \n return createInstallFailure({\n message: `brew not installed — ${hint}`,\n });\n }\n argv[0] = brewExe;\n }\n \n // Set up environment for go installations\n let env: NodeJS.ProcessEnv | undefined;\n if (installSpec.kind === 'go') {\n const brewExe = resolveBrewExecutable();\n if (brewExe) {\n try {\n const { stdout } = await execAsync(`${brewExe} --prefix`);\n const prefix = stdout.trim();\n if (prefix) {\n env = { ...process.env, GOBIN: join(prefix, 'bin') };\n }\n } catch {\n // Use default GOBIN\n }\n }\n }\n \n // Execute install command\n const result = await runCommandWithTimeout(argv, timeoutMs, env);\n \n if (result.code === 0) {\n log.info({ skill: ctx.skillEntry.skill.name }, 'Skill dependency installed successfully');\n return createInstallSuccess(result);\n }\n \n log.warn({ \n skill: ctx.skillEntry.skill.name, \n stderr: result.stderr \n }, 'Skill dependency installation failed');\n \n return createInstallFailure({\n message: result.stderr || `Installation failed with exit code ${result.code}`,\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n });\n}\n\n/**\n * Get default installer preferences from config\n */\nexport function getDefaultInstallerPreferences(): InstallerPreferences {\n return {\n preferBrew: true,\n nodeManager: 'pnpm', // Default to pnpm as per project guidelines\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"installer.js","names":[],"sources":["../../../../src/agent/skills/installer.ts"],"sourcesContent":["/**\n * Skill Installer\n * \n * Handles installation of skill dependencies via various package managers.\n *\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { accessSync, constants, existsSync } from 'fs';\nimport { delimiter, join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillEntry, SkillInstallResult, SkillInstallSpec } from './types.js';\n\nconst execAsync = promisify(exec);\n\nconst log = createLogger('SkillInstaller');\n\nexport interface InstallerPreferences {\n preferBrew: boolean;\n nodeManager: 'pnpm' | 'npm' | 'yarn' | 'bun';\n}\n\nexport interface InstallContext {\n workspaceDir: string;\n skillEntry: SkillEntry;\n installSpec: SkillInstallSpec;\n timeoutMs: number;\n preferences: InstallerPreferences;\n}\n\n/**\n * Check if a binary exists\n */\nexport function hasBinary(name: string): boolean {\n if (!name || name.includes('/') || name.includes('\\\\')) {\n return false;\n }\n\n const pathEntries = (process.env.PATH || '').split(delimiter).filter(Boolean);\n const extensions = process.platform === 'win32'\n ? (process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM').split(';').filter(Boolean)\n : [''];\n\n for (const dir of pathEntries) {\n for (const ext of extensions) {\n const candidate = join(dir, `${name}${ext}`);\n try {\n accessSync(candidate, constants.X_OK);\n return true;\n } catch {\n // Continue searching PATH.\n }\n }\n }\n\n return false;\n}\n\n/**\n * Resolve brew executable path\n */\nexport function resolveBrewExecutable(): string | undefined {\n const candidates = [\n '/opt/homebrew/bin/brew',\n '/usr/local/bin/brew',\n ];\n \n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n \n return undefined;\n}\n\n/**\n * Build install command for Node.js packages\n */\nfunction buildNodeInstallCommand(packageName: string, manager: InstallerPreferences['nodeManager']): string[] {\n switch (manager) {\n case 'pnpm':\n return ['pnpm', 'add', '-g', '--ignore-scripts', packageName];\n case 'yarn':\n return ['yarn', 'global', 'add', '--ignore-scripts', packageName];\n case 'bun':\n return ['bun', 'add', '-g', '--ignore-scripts', packageName];\n default:\n return ['npm', 'install', '-g', '--ignore-scripts', packageName];\n }\n}\n\n/**\n * Build install command from spec\n */\nfunction buildInstallCommand(spec: SkillInstallSpec, prefs: InstallerPreferences): {\n argv: string[] | null;\n error?: string;\n} {\n switch (spec.kind) {\n case 'brew': {\n if (!spec.formula) {\n return { argv: null, error: 'Missing brew formula' };\n }\n return { argv: ['brew', 'install', spec.formula] };\n }\n \n case 'pnpm':\n case 'npm':\n case 'yarn':\n case 'bun': {\n if (!spec.package) {\n return { argv: null, error: 'Missing package name' };\n }\n return {\n argv: buildNodeInstallCommand(spec.package, prefs.nodeManager),\n };\n }\n \n case 'go': {\n if (!spec.module) {\n return { argv: null, error: 'Missing go module' };\n }\n return { argv: ['go', 'install', spec.module] };\n }\n \n case 'uv': {\n if (!spec.package) {\n return { argv: null, error: 'Missing uv package' };\n }\n return { argv: ['uv', 'tool', 'install', spec.package] };\n }\n \n case 'download': {\n return { argv: null, error: 'Download install handled separately' };\n }\n \n default: {\n const _exhaustive: never = spec.kind;\n return { argv: null, error: `Unsupported installer: ${spec.kind}` };\n }\n }\n}\n\n/**\n * Run command with timeout\n */\nasync function runCommandWithTimeout(\n argv: string[],\n timeoutMs: number,\n env?: NodeJS.ProcessEnv\n): Promise<{ code: number | null; stdout: string; stderr: string }> {\n const [cmd, ...args] = argv;\n \n try {\n const { stdout, stderr } = await execAsync(`${cmd} ${args.join(' ')}`, {\n timeout: timeoutMs,\n env,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n });\n \n return {\n code: 0,\n stdout: stdout.toString(),\n stderr: stderr.toString(),\n };\n } catch (err: unknown) {\n if (err instanceof Error) {\n const execError = err as Error & { code?: number; stdout?: string; stderr?: string };\n return {\n code: execError.code ?? null,\n stdout: execError.stdout?.toString() ?? '',\n stderr: execError.stderr?.toString() ?? '',\n };\n }\n \n return {\n code: null,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/**\n * Ensure uv is installed\n */\nasync function ensureUvInstalled(timeoutMs: number): Promise<SkillInstallResult | undefined> {\n if (hasBinary('uv')) {\n return undefined;\n }\n \n // Try to install via brew\n const brewExe = resolveBrewExecutable();\n if (!brewExe) {\n return {\n ok: false,\n message: 'uv not installed — install manually: https://docs.astral.sh/uv/getting-started/installation/',\n stdout: '',\n stderr: '',\n code: null,\n };\n }\n \n const result = await runCommandWithTimeout([brewExe, 'install', 'uv'], timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'Failed to install uv (brew)',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n}\n\n/**\n * Ensure Go is installed\n */\nasync function ensureGoInstalled(timeoutMs: number): Promise<SkillInstallResult | undefined> {\n if (hasBinary('go')) {\n return undefined;\n }\n \n const brewExe = resolveBrewExecutable();\n if (brewExe) {\n const result = await runCommandWithTimeout([brewExe, 'install', 'go'], timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'Failed to install go (brew)',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n }\n \n // Try apt-get on Linux\n if (hasBinary('apt-get')) {\n const isRoot = process.getuid?.() === 0;\n const aptCmd = isRoot \n ? ['apt-get', 'install', '-y', 'golang-go']\n : ['sudo', 'apt-get', 'install', '-y', 'golang-go'];\n \n // Update package index first\n if (!isRoot) {\n await runCommandWithTimeout(['sudo', 'apt-get', 'update', '-qq'], Math.min(timeoutMs, 30000));\n }\n \n const result = await runCommandWithTimeout(aptCmd, timeoutMs);\n if (result.code === 0) {\n return undefined;\n }\n \n return {\n ok: false,\n message: 'go not installed — automatic install via apt failed. Install manually: https://go.dev/doc/install',\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n };\n }\n \n return {\n ok: false,\n message: 'go not installed — install manually: https://go.dev/doc/install',\n stdout: '',\n stderr: '',\n code: null,\n };\n}\n\n/**\n * Create install failure result\n */\nfunction createInstallFailure(params: {\n message: string;\n stdout?: string;\n stderr?: string;\n code?: number | null;\n}): SkillInstallResult {\n return {\n ok: false,\n message: params.message,\n stdout: params.stdout?.trim() ?? '',\n stderr: params.stderr?.trim() ?? '',\n code: params.code ?? null,\n };\n}\n\n/**\n * Create install success result\n */\nfunction createInstallSuccess(result: { code: number | null; stdout: string; stderr: string }): SkillInstallResult {\n return {\n ok: true,\n message: 'Installed',\n stdout: result.stdout.trim(),\n stderr: result.stderr.trim(),\n code: result.code,\n };\n}\n\n/**\n * Find install spec by ID\n */\nexport function findInstallSpec(entry: SkillEntry, installId: string): SkillInstallSpec | undefined {\n const specs = entry.metadata.install ?? [];\n \n for (const [index, spec] of specs.entries()) {\n const id = spec.id ?? `${spec.kind}-${index}`;\n if (id === installId) {\n return spec;\n }\n }\n \n return undefined;\n}\n\n/**\n * Install a skill dependency\n */\nexport async function installSkill(ctx: InstallContext): Promise<SkillInstallResult> {\n const { installSpec, timeoutMs, preferences } = ctx;\n \n log.info({ skill: ctx.skillEntry.skill.name, kind: installSpec.kind }, 'Installing skill dependency');\n \n // Handle download installer separately\n if (installSpec.kind === 'download') {\n return createInstallFailure({\n message: 'Download installer not yet implemented',\n });\n }\n \n // Check and install prerequisites\n if (installSpec.kind === 'uv') {\n const uvFailure = await ensureUvInstalled(timeoutMs);\n if (uvFailure) {\n return uvFailure;\n }\n }\n \n if (installSpec.kind === 'go') {\n const goFailure = await ensureGoInstalled(timeoutMs);\n if (goFailure) {\n return goFailure;\n }\n }\n \n // Build install command\n const command = buildInstallCommand(installSpec, preferences);\n if (command.error) {\n return createInstallFailure({\n message: command.error,\n });\n }\n \n if (!command.argv) {\n return createInstallFailure({\n message: 'Invalid install command',\n });\n }\n \n // Resolve brew executable\n let argv = [...command.argv];\n if (installSpec.kind === 'brew') {\n const brewExe = resolveBrewExecutable();\n if (!brewExe) {\n const hint = process.platform === 'linux'\n ? 'Homebrew is not installed. Install it from https://brew.sh or use your system package manager.'\n : 'Homebrew is not installed. Install it from https://brew.sh';\n \n return createInstallFailure({\n message: `brew not installed — ${hint}`,\n });\n }\n argv[0] = brewExe;\n }\n \n // Set up environment for go installations\n let env: NodeJS.ProcessEnv | undefined;\n if (installSpec.kind === 'go') {\n const brewExe = resolveBrewExecutable();\n if (brewExe) {\n try {\n const { stdout } = await execAsync(`${brewExe} --prefix`);\n const prefix = stdout.trim();\n if (prefix) {\n env = { ...process.env, GOBIN: join(prefix, 'bin') };\n }\n } catch {\n // Use default GOBIN\n }\n }\n }\n \n // Execute install command\n const result = await runCommandWithTimeout(argv, timeoutMs, env);\n \n if (result.code === 0) {\n log.info({ skill: ctx.skillEntry.skill.name }, 'Skill dependency installed successfully');\n return createInstallSuccess(result);\n }\n \n log.warn({ \n skill: ctx.skillEntry.skill.name, \n stderr: result.stderr \n }, 'Skill dependency installation failed');\n \n return createInstallFailure({\n message: result.stderr || `Installation failed with exit code ${result.code}`,\n stdout: result.stdout,\n stderr: result.stderr,\n code: result.code,\n });\n}\n\n/**\n * Get default installer preferences from config\n */\nexport function getDefaultInstallerPreferences(): InstallerPreferences {\n return {\n preferBrew: true,\n nodeManager: 'pnpm', // Default to pnpm as per project guidelines\n };\n}\n"],"mappings":"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"}
@@ -1,5 +1,9 @@
1
1
  import { registerMarketplaceAdapter } from "../../registry.js";
2
+ import { buildSkillMarkdownPreviewFromRaw } from "../../../skill-markdown-preview-from-raw.js";
2
3
  //#region src/agent/skills/marketplace/adapters/clawhub/adapter.ts
4
+ /**
5
+ * ClawHub (clawhub.ai) skills marketplace adapter.
6
+ */
3
7
  const DEFAULT_CLAWHUB_BASE = "https://clawhub.ai";
4
8
  const MAX_CLAWHUB_FILE_BYTES = 512 * 1024;
5
9
  const MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;
@@ -274,12 +278,18 @@ const clawHubMarketplaceAdapter = {
274
278
  if (!readme) readme = fallbackReadmeMarkdown(detail);
275
279
  const changelog = detail.latestVersion.changelog?.trim();
276
280
  if (changelog) readme = `${readme}\n\n---\n\n## Changelog\n\n${changelog}`;
281
+ const description = detail.skill.summary || "";
282
+ const skillDocPreview = buildSkillMarkdownPreviewFromRaw(readme, {
283
+ name: slug,
284
+ description
285
+ });
277
286
  return {
278
287
  id: slug,
279
288
  name: slug,
280
289
  type: "skill",
281
- description: detail.skill.summary || "",
290
+ description,
282
291
  readme,
292
+ skillDocPreview,
283
293
  downloads: detail.skill.stats.downloads,
284
294
  author: {
285
295
  username: detail.owner.handle,
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","names":[],"sources":["../../../../../../../src/agent/skills/marketplace/adapters/clawhub/adapter.ts"],"sourcesContent":["/**\n * ClawHub (clawhub.ai) skills marketplace adapter.\n */\n\nimport type { SkillsMarketplaceAdapter } from '../../adapter.types.js';\nimport { registerMarketplaceAdapter } from '../../registry.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_CLAWHUB_BASE = 'https://clawhub.ai';\nconst MAX_CLAWHUB_FILE_BYTES = 512 * 1024;\nconst MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;\nconst SKILL_ID_RE = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62})$/;\nconst LIST_BATCH_SIZE = 200;\n\nconst DEFAULT_CACHE_MS = 5 * 60 * 1000;\nconst MAX_LIST_CACHE_KEYS = 24;\nconst MAX_DETAIL_CACHE_KEYS = 48;\n\n// ─── Inline helpers ──────────────────────────────────────────────────────────\n\nfunction isValidSkillId(id: string): boolean {\n return SKILL_ID_RE.test(id);\n}\n\nfunction resolveClawHubBaseUrl(): string {\n const env = process.env.CLAWHUB_REGISTRY?.trim();\n if (env) {\n try {\n return new URL(env).toString().replace(/\\/$/, '');\n } catch {\n // fall through\n }\n }\n return DEFAULT_CLAWHUB_BASE;\n}\n\n// ─── ClawHub API types ───────────────────────────────────────────────────────\n\ninterface ClawHubSkillListItem {\n slug: string;\n displayName: string;\n summary: string;\n tags: Record<string, string>;\n stats: {\n comments: number;\n downloads: number;\n installsAllTime: number;\n installsCurrent: number;\n stars: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n latestVersion: {\n version: string;\n createdAt: number;\n changelog: string | null;\n license: string | null;\n };\n metadata: { os: string[] | null; systems: string[] | null } | null;\n}\n\ninterface ClawHubSkillListResponse {\n items: ClawHubSkillListItem[];\n nextCursor: string | null;\n}\n\ninterface ClawHubSearchResultItem {\n score: number;\n slug: string;\n displayName: string;\n summary: string;\n version: string | null;\n updatedAt: number;\n ownerHandle: string;\n owner: {\n handle: string;\n displayName: string;\n image: string | null;\n };\n}\n\ninterface ClawHubSearchResponse {\n results: ClawHubSearchResultItem[];\n}\n\ninterface ClawHubSkillDetail {\n skill: {\n slug: string;\n displayName: string;\n summary: string;\n tags: Record<string, string>;\n stats: {\n comments: number;\n downloads: number;\n installsAllTime: number;\n installsCurrent: number;\n stars: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n };\n latestVersion: {\n version: string;\n createdAt: number;\n changelog: string | null;\n license: string | null;\n };\n metadata: { os: string[] | null; systems: string[] | null } | null;\n owner: {\n handle: string;\n userId: string;\n displayName: string;\n image: string | null;\n };\n moderation: {\n isSuspicious: boolean;\n isMalwareBlocked: boolean;\n verdict: string;\n } | null;\n}\n\ninterface ClawHubVersionFile {\n path: string;\n size: number;\n sha256: string;\n contentType: string;\n}\n\ninterface ClawHubVersionDetail {\n skill: { slug: string; displayName: string };\n version: {\n version: string;\n createdAt: number;\n changelog: string | null;\n changelogSource: string | null;\n license: string | null;\n files: ClawHubVersionFile[];\n security: {\n status: string;\n hasWarnings: boolean;\n hasScanResult: boolean;\n } | null;\n };\n}\n\ntype ClawHubListSort = 'updated' | 'newest' | 'downloads' | 'stars' | 'trending';\n\ninterface ClawHubListParams {\n limit?: number;\n cursor?: string;\n sort?: ClawHubListSort;\n}\n\n// ─── ClawHub HTTP helpers ────────────────────────────────────────────────────\n\nasync function clawHubFetch(path: string, init?: { signal?: AbortSignal }): Promise<Response> {\n const base = resolveClawHubBaseUrl();\n const url = `${base}${path}`;\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n signal: init?.signal,\n });\n return res as unknown as Response;\n}\n\nfunction assertOk(res: Response, context: string): void {\n if (!res.ok) {\n throw new Error(`ClawHub ${context} failed (${res.status})`);\n }\n}\n\nasync function listClawHubSkills(params?: ClawHubListParams): Promise<ClawHubSkillListResponse> {\n const sp = new URLSearchParams();\n if (params?.limit) sp.set('limit', String(params.limit));\n if (params?.cursor) sp.set('cursor', params.cursor);\n if (params?.sort) sp.set('sort', params.sort);\n sp.set('nonSuspiciousOnly', 'true');\n const qs = sp.toString();\n const res = await clawHubFetch(`/api/v1/skills${qs ? `?${qs}` : ''}`);\n assertOk(res, 'list skills');\n return (await res.json()) as ClawHubSkillListResponse;\n}\n\nasync function searchClawHubSkills(query: string, limit?: number): Promise<ClawHubSearchResponse> {\n const sp = new URLSearchParams({ q: query, nonSuspiciousOnly: 'true' });\n if (limit) sp.set('limit', String(limit));\n const res = await clawHubFetch(`/api/v1/search?${sp.toString()}`);\n assertOk(res, 'search');\n return (await res.json()) as ClawHubSearchResponse;\n}\n\nasync function getClawHubSkillDetail(slug: string): Promise<ClawHubSkillDetail> {\n const enc = encodeURIComponent(slug.trim());\n const res = await clawHubFetch(`/api/v1/skills/${enc}`);\n assertOk(res, `skill detail [${slug}]`);\n return (await res.json()) as ClawHubSkillDetail;\n}\n\nasync function getClawHubVersionDetail(slug: string, version: string): Promise<ClawHubVersionDetail> {\n const enc = encodeURIComponent(slug.trim());\n const ver = encodeURIComponent(version.trim());\n const res = await clawHubFetch(`/api/v1/skills/${enc}/versions/${ver}`);\n assertOk(res, `version detail [${slug}@${version}]`);\n return (await res.json()) as ClawHubVersionDetail;\n}\n\nasync function getClawHubSkillFileText(slug: string, filePath: string, version?: string): Promise<string> {\n const enc = encodeURIComponent(slug.trim());\n const sp = new URLSearchParams({ path: filePath });\n if (version?.trim()) sp.set('version', version.trim());\n const base = resolveClawHubBaseUrl();\n const url = `${base}/api/v1/skills/${enc}/file?${sp.toString()}`;\n const res = await fetch(url, { headers: { Accept: 'text/markdown,text/plain,*/*' } });\n if (!res.ok) {\n throw new Error(`ClawHub file fetch [${slug}/${filePath}] failed (${res.status})`);\n }\n const text = await res.text();\n return text.length > MAX_CLAWHUB_FILE_BYTES ? text.slice(0, MAX_CLAWHUB_FILE_BYTES) : text;\n}\n\nasync function downloadClawHubSkillZip(\n slug: string,\n version?: string,\n): Promise<{ buffer: Buffer; version: string }> {\n const enc = encodeURIComponent(slug.trim());\n const sp = version?.trim() ? `?version=${encodeURIComponent(version.trim())}` : '';\n const base = resolveClawHubBaseUrl();\n const url = `${base}/api/v1/packages/${enc}/download${sp}`;\n const res = await fetch(url, { redirect: 'follow' });\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`ClawHub download [${slug}] failed (${res.status}): ${body.slice(0, 200)}`);\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (!contentType.includes('zip') && !contentType.includes('octet-stream')) {\n throw new Error(`ClawHub download [${slug}] unexpected content-type: ${contentType}`);\n }\n const arrayBuf = await res.arrayBuffer();\n if (arrayBuf.byteLength > MAX_SKILL_ZIP_BYTES) {\n throw new Error(\n `ClawHub download [${slug}] exceeds size limit (${arrayBuf.byteLength} > ${MAX_SKILL_ZIP_BYTES})`,\n );\n }\n return { buffer: Buffer.from(arrayBuf), version: version?.trim() || 'latest' };\n}\n\nfunction pickClawHubDocFilePath(files: ClawHubVersionFile[]): string | null {\n const rows = files.map((f) => ({\n path: f.path.replace(/\\\\/g, '/'),\n base: f.path.replace(/\\\\/g, '/').split('/').pop()?.toLowerCase() ?? '',\n }));\n const find = (name: string) => rows.find((r) => r.base === name.toLowerCase());\n const skillMd = find('SKILL.md') ?? find('skill.md');\n if (skillMd) return skillMd.path;\n const readme = find('README.md') ?? find('readme.md');\n if (readme) return readme.path;\n return null;\n}\n\n// ─── In-memory TTL cache ─────────────────────────────────────────────────────\n\ntype CacheEntry<T> = { value: T; expiresAt: number };\n\nfunction cacheTtlMs(): number {\n const raw = process.env.XOPC_CLAWHUB_CACHE_MS?.trim();\n if (raw === '0' || raw === 'false') return 0;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_CACHE_MS;\n return parsed;\n}\n\nfunction getFresh<T>(entry: CacheEntry<T> | undefined): T | undefined {\n if (!entry || entry.expiresAt <= Date.now()) return undefined;\n return entry.value;\n}\n\nfunction evictOldest<T>(map: Map<string, CacheEntry<T>>): void {\n const first = map.keys().next().value;\n if (first !== undefined) map.delete(first);\n}\n\nconst listCache = new Map<string, CacheEntry<ClawHubSkillListResponse>>();\nconst searchCache = new Map<string, CacheEntry<ClawHubSearchResponse>>();\nconst detailCache = new Map<string, CacheEntry<ClawHubSkillDetail>>();\n\nasync function cachedListClawHubSkills(params?: ClawHubListParams): Promise<ClawHubSkillListResponse> {\n const ttl = cacheTtlMs();\n const key = JSON.stringify(params ?? {});\n if (ttl > 0) {\n const hit = getFresh(listCache.get(key));\n if (hit) return hit;\n }\n const value = await listClawHubSkills(params);\n if (ttl > 0) {\n while (listCache.size >= MAX_LIST_CACHE_KEYS) evictOldest(listCache);\n listCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedSearchClawHubSkills(query: string, limit?: number): Promise<ClawHubSearchResponse> {\n const ttl = cacheTtlMs();\n const key = `${query}::${limit ?? ''}`;\n if (ttl > 0) {\n const hit = getFresh(searchCache.get(key));\n if (hit) return hit;\n }\n const value = await searchClawHubSkills(query, limit);\n if (ttl > 0) {\n while (searchCache.size >= MAX_LIST_CACHE_KEYS) evictOldest(searchCache);\n searchCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedGetClawHubSkillDetail(slug: string): Promise<ClawHubSkillDetail> {\n const ttl = cacheTtlMs();\n const key = slug.trim();\n if (ttl > 0) {\n const hit = getFresh(detailCache.get(key));\n if (hit) return hit;\n }\n const value = await getClawHubSkillDetail(slug);\n if (ttl > 0) {\n while (detailCache.size >= MAX_DETAIL_CACHE_KEYS) evictOldest(detailCache);\n detailCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\n// ─── Adapter conversion helpers ──────────────────────────────────────────────\n\ninterface PackageListItem {\n id: string;\n name: string;\n type: string;\n description: string;\n downloads: number;\n author: { username: string; avatarUrl: string | null };\n latestVersion?: string;\n updatedAt: string;\n categories?: string[];\n stars?: number;\n sourceLabel?: string;\n}\n\nfunction convertListItemToPackageItem(item: ClawHubSkillListItem): PackageListItem {\n return {\n id: item.slug,\n name: item.displayName || item.slug,\n type: 'skill',\n description: item.summary || '',\n downloads: item.stats.downloads,\n author: { username: 'clawhub', avatarUrl: null },\n latestVersion: item.latestVersion?.version ?? item.tags.latest ?? '1.0.0',\n updatedAt: String(item.updatedAt),\n categories: item.metadata?.os ?? [],\n stars: item.stats.stars,\n sourceLabel: 'ClawHub',\n };\n}\n\nfunction convertSearchResultToPackageItem(\n item: ClawHubSearchResultItem,\n enrichment?: ClawHubSkillListItem,\n): PackageListItem {\n return {\n id: item.slug,\n name: item.displayName || item.slug,\n type: 'skill',\n description: item.summary || '',\n downloads: enrichment?.stats.downloads ?? 0,\n author: {\n username: item.owner?.handle ?? item.ownerHandle ?? 'clawhub',\n avatarUrl: item.owner?.image ?? null,\n },\n latestVersion: item.version ?? enrichment?.latestVersion?.version ?? '1.0.0',\n updatedAt: String(item.updatedAt),\n categories: enrichment?.metadata?.os ?? [],\n stars: enrichment?.stats.stars ?? 0,\n sourceLabel: 'ClawHub',\n };\n}\n\nfunction mapSortParam(sort?: string): ClawHubListSort | undefined {\n if (sort === 'downloads') return 'downloads';\n if (sort === 'newest') return 'newest';\n return undefined;\n}\n\nfunction fallbackReadmeMarkdown(detail: {\n skill: { slug: string; displayName: string; summary: string };\n latestVersion: { version: string };\n}): string {\n const title = detail.skill.displayName || detail.skill.slug;\n const body = detail.skill.summary || '_No description._';\n return `## ${title}\\n\\n**${detail.skill.slug}** · v${detail.latestVersion.version}\\n\\n${body}`;\n}\n\nexport const clawHubMarketplaceAdapter: SkillsMarketplaceAdapter = {\n id: 'clawhub',\n\n async listCategories() {\n return [];\n },\n\n async listPackages(_config, params) {\n const pageSize = params.pageSize ?? 20;\n const page = params.page ?? 1;\n\n if (params.q?.trim()) {\n // Search results from /search omit downloads/stars/metadata. We pull the cached list\n // snapshot in parallel and merge by slug — costs nothing when the list cache is hot\n // (which it is after any preceding browse), and adds at most one round-trip on a cold\n // cache. We still tolerate a list-fetch failure: enrichment becomes a no-op.\n const [searchResponse, listSettled] = await Promise.allSettled([\n cachedSearchClawHubSkills(params.q.trim(), LIST_BATCH_SIZE),\n cachedListClawHubSkills({ limit: LIST_BATCH_SIZE }),\n ]);\n if (searchResponse.status === 'rejected') throw searchResponse.reason;\n const enrichmentBySlug = new Map<string, ClawHubSkillListItem>();\n if (listSettled.status === 'fulfilled') {\n for (const it of listSettled.value.items) enrichmentBySlug.set(it.slug, it);\n }\n let rows = searchResponse.value.results.map((r) =>\n convertSearchResultToPackageItem(r, enrichmentBySlug.get(r.slug)),\n );\n if (params.sort === 'downloads') {\n rows = [...rows].sort((a, b) => b.downloads - a.downloads);\n } else if (params.sort === 'newest') {\n rows = [...rows].sort((a, b) => Number(b.updatedAt) - Number(a.updatedAt));\n }\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'clawhub' };\n }\n\n const sort = mapSortParam(params.sort);\n const listResponse = await cachedListClawHubSkills({ limit: LIST_BATCH_SIZE, sort });\n const rows = listResponse.items.map(convertListItemToPackageItem);\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'clawhub' };\n },\n\n async getPackageDetail(_config, packageName) {\n const detail = await cachedGetClawHubSkillDetail(packageName);\n const slug = detail.skill.slug;\n const version = detail.latestVersion.version;\n\n let readme: string | null = null;\n\n try {\n const versionDetail = await getClawHubVersionDetail(slug, version);\n const docPath = pickClawHubDocFilePath(versionDetail.version.files);\n if (docPath) {\n const rawText = await getClawHubSkillFileText(slug, docPath, version);\n const trimmed = rawText.trim();\n if (trimmed) readme = trimmed;\n }\n } catch {\n // version detail or file fetch failed — use fallback\n }\n\n if (!readme) {\n readme = fallbackReadmeMarkdown(detail);\n }\n\n const changelog = detail.latestVersion.changelog?.trim();\n if (changelog) {\n readme = `${readme}\\n\\n---\\n\\n## Changelog\\n\\n${changelog}`;\n }\n\n return {\n id: slug,\n name: slug,\n type: 'skill',\n description: detail.skill.summary || '',\n readme,\n downloads: detail.skill.stats.downloads,\n author: {\n username: detail.owner.handle,\n avatarUrl: detail.owner.image,\n },\n latestVersion: {\n version: detail.latestVersion.version,\n changelog: detail.latestVersion.changelog,\n publishedAt: String(detail.latestVersion.createdAt),\n },\n provider: 'clawhub',\n };\n },\n\n async downloadPackage(_config, packageName, version) {\n const slug = packageName.trim();\n const result = await downloadClawHubSkillZip(slug, version);\n return {\n buffer: result.buffer,\n skillId: isValidSkillId(slug) ? slug : 'unknown',\n version: result.version,\n };\n },\n};\n\nregisterMarketplaceAdapter({\n adapter: clawHubMarketplaceAdapter,\n displayName: 'ClawHub',\n});\n"],"mappings":";;AASA,MAAM,uBAAuB;AAC7B,MAAM,yBAAyB,MAAM;AACrC,MAAM,sBAAsB,KAAK,OAAO;AACxC,MAAM,cAAc;AACpB,MAAM,kBAAkB;AAExB,MAAM,mBAAmB,MAAS;AAClC,MAAM,sBAAsB;AAC5B,MAAM,wBAAwB;AAI9B,SAAS,eAAe,IAAqB;AAC3C,QAAO,YAAY,KAAK,GAAG;;AAG7B,SAAS,wBAAgC;CACvC,MAAM,MAAM,QAAQ,IAAI,kBAAkB,MAAM;AAChD,KAAI,IACF,KAAI;AACF,SAAO,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,OAAO,GAAG;SAC3C;AAIV,QAAO;;AA4HT,eAAe,aAAa,MAAc,MAAoD;CAE5F,MAAM,MAAM,GADC,uBACM,GAAG;AAKtB,QAAO,MAJW,MAAM,KAAK;EAC3B,SAAS,EAAE,QAAQ,oBAAoB;EACvC,QAAQ,MAAM;EACf,CAAC;;AAIJ,SAAS,SAAS,KAAe,SAAuB;AACtD,KAAI,CAAC,IAAI,GACP,OAAM,IAAI,MAAM,WAAW,QAAQ,WAAW,IAAI,OAAO,GAAG;;AAIhE,eAAe,kBAAkB,QAA+D;CAC9F,MAAM,KAAK,IAAI,iBAAiB;AAChC,KAAI,QAAQ,MAAO,IAAG,IAAI,SAAS,OAAO,OAAO,MAAM,CAAC;AACxD,KAAI,QAAQ,OAAQ,IAAG,IAAI,UAAU,OAAO,OAAO;AACnD,KAAI,QAAQ,KAAM,IAAG,IAAI,QAAQ,OAAO,KAAK;AAC7C,IAAG,IAAI,qBAAqB,OAAO;CACnC,MAAM,KAAK,GAAG,UAAU;CACxB,MAAM,MAAM,MAAM,aAAa,iBAAiB,KAAK,IAAI,OAAO,KAAK;AACrE,UAAS,KAAK,cAAc;AAC5B,QAAQ,MAAM,IAAI,MAAM;;AAG1B,eAAe,oBAAoB,OAAe,OAAgD;CAChG,MAAM,KAAK,IAAI,gBAAgB;EAAE,GAAG;EAAO,mBAAmB;EAAQ,CAAC;AACvE,KAAI,MAAO,IAAG,IAAI,SAAS,OAAO,MAAM,CAAC;CACzC,MAAM,MAAM,MAAM,aAAa,kBAAkB,GAAG,UAAU,GAAG;AACjE,UAAS,KAAK,SAAS;AACvB,QAAQ,MAAM,IAAI,MAAM;;AAG1B,eAAe,sBAAsB,MAA2C;CAE9E,MAAM,MAAM,MAAM,aAAa,kBADnB,mBAAmB,KAAK,MAAM,CACU,GAAG;AACvD,UAAS,KAAK,iBAAiB,KAAK,GAAG;AACvC,QAAQ,MAAM,IAAI,MAAM;;AAG1B,eAAe,wBAAwB,MAAc,SAAgD;CAGnG,MAAM,MAAM,MAAM,aAAa,kBAFnB,mBAAmB,KAAK,MAAM,CAEU,CAAC,YADzC,mBAAmB,QAAQ,MAAM,CACuB,GAAG;AACvE,UAAS,KAAK,mBAAmB,KAAK,GAAG,QAAQ,GAAG;AACpD,QAAQ,MAAM,IAAI,MAAM;;AAG1B,eAAe,wBAAwB,MAAc,UAAkB,SAAmC;CACxG,MAAM,MAAM,mBAAmB,KAAK,MAAM,CAAC;CAC3C,MAAM,KAAK,IAAI,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAClD,KAAI,SAAS,MAAM,CAAE,IAAG,IAAI,WAAW,QAAQ,MAAM,CAAC;CAEtD,MAAM,MAAM,GADC,uBACM,CAAC,iBAAiB,IAAI,QAAQ,GAAG,UAAU;CAC9D,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,gCAAgC,EAAE,CAAC;AACrF,KAAI,CAAC,IAAI,GACP,OAAM,IAAI,MAAM,uBAAuB,KAAK,GAAG,SAAS,YAAY,IAAI,OAAO,GAAG;CAEpF,MAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,QAAO,KAAK,SAAS,yBAAyB,KAAK,MAAM,GAAG,uBAAuB,GAAG;;AAGxF,eAAe,wBACb,MACA,SAC8C;CAC9C,MAAM,MAAM,mBAAmB,KAAK,MAAM,CAAC;CAC3C,MAAM,KAAK,SAAS,MAAM,GAAG,YAAY,mBAAmB,QAAQ,MAAM,CAAC,KAAK;CAEhF,MAAM,MAAM,GADC,uBACM,CAAC,mBAAmB,IAAI,WAAW;CACtD,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,UAAU,UAAU,CAAC;AACpD,KAAI,CAAC,IAAI,IAAI;EACX,MAAM,OAAO,MAAM,IAAI,MAAM,CAAC,YAAY,GAAG;AAC7C,QAAM,IAAI,MAAM,qBAAqB,KAAK,YAAY,IAAI,OAAO,KAAK,KAAK,MAAM,GAAG,IAAI,GAAG;;CAE7F,MAAM,cAAc,IAAI,QAAQ,IAAI,eAAe,IAAI;AACvD,KAAI,CAAC,YAAY,SAAS,MAAM,IAAI,CAAC,YAAY,SAAS,eAAe,CACvE,OAAM,IAAI,MAAM,qBAAqB,KAAK,6BAA6B,cAAc;CAEvF,MAAM,WAAW,MAAM,IAAI,aAAa;AACxC,KAAI,SAAS,aAAa,oBACxB,OAAM,IAAI,MACR,qBAAqB,KAAK,wBAAwB,SAAS,WAAW,KAAK,oBAAoB,GAChG;AAEH,QAAO;EAAE,QAAQ,OAAO,KAAK,SAAS;EAAE,SAAS,SAAS,MAAM,IAAI;EAAU;;AAGhF,SAAS,uBAAuB,OAA4C;CAC1E,MAAM,OAAO,MAAM,KAAK,OAAO;EAC7B,MAAM,EAAE,KAAK,QAAQ,OAAO,IAAI;EAChC,MAAM,EAAE,KAAK,QAAQ,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,aAAa,IAAI;EACrE,EAAE;CACH,MAAM,QAAQ,SAAiB,KAAK,MAAM,MAAM,EAAE,SAAS,KAAK,aAAa,CAAC;CAC9E,MAAM,UAAU,KAAK,WAAW,IAAI,KAAK,WAAW;AACpD,KAAI,QAAS,QAAO,QAAQ;CAC5B,MAAM,SAAS,KAAK,YAAY,IAAI,KAAK,YAAY;AACrD,KAAI,OAAQ,QAAO,OAAO;AAC1B,QAAO;;AAOT,SAAS,aAAqB;CAC5B,MAAM,MAAM,QAAQ,IAAI,uBAAuB,MAAM;AACrD,KAAI,QAAQ,OAAO,QAAQ,QAAS,QAAO;CAC3C,MAAM,SAAS,OAAO,IAAI;AAC1B,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,SAAS,EAAG,QAAO;AACnD,QAAO;;AAGT,SAAS,SAAY,OAAiD;AACpE,KAAI,CAAC,SAAS,MAAM,aAAa,KAAK,KAAK,CAAE,QAAO,KAAA;AACpD,QAAO,MAAM;;AAGf,SAAS,YAAe,KAAuC;CAC7D,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC;AAChC,KAAI,UAAU,KAAA,EAAW,KAAI,OAAO,MAAM;;AAG5C,MAAM,4BAAY,IAAI,KAAmD;AACzE,MAAM,8BAAc,IAAI,KAAgD;AACxE,MAAM,8BAAc,IAAI,KAA6C;AAErE,eAAe,wBAAwB,QAA+D;CACpG,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,KAAK,UAAU,UAAU,EAAE,CAAC;AACxC,KAAI,MAAM,GAAG;EACX,MAAM,MAAM,SAAS,UAAU,IAAI,IAAI,CAAC;AACxC,MAAI,IAAK,QAAO;;CAElB,MAAM,QAAQ,MAAM,kBAAkB,OAAO;AAC7C,KAAI,MAAM,GAAG;AACX,SAAO,UAAU,QAAQ,oBAAqB,aAAY,UAAU;AACpE,YAAU,IAAI,KAAK;GAAE;GAAO,WAAW,KAAK,KAAK,GAAG;GAAK,CAAC;;AAE5D,QAAO;;AAGT,eAAe,0BAA0B,OAAe,OAAgD;CACtG,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,GAAG,MAAM,IAAI,SAAS;AAClC,KAAI,MAAM,GAAG;EACX,MAAM,MAAM,SAAS,YAAY,IAAI,IAAI,CAAC;AAC1C,MAAI,IAAK,QAAO;;CAElB,MAAM,QAAQ,MAAM,oBAAoB,OAAO,MAAM;AACrD,KAAI,MAAM,GAAG;AACX,SAAO,YAAY,QAAQ,oBAAqB,aAAY,YAAY;AACxE,cAAY,IAAI,KAAK;GAAE;GAAO,WAAW,KAAK,KAAK,GAAG;GAAK,CAAC;;AAE9D,QAAO;;AAGT,eAAe,4BAA4B,MAA2C;CACpF,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,KAAK,MAAM;AACvB,KAAI,MAAM,GAAG;EACX,MAAM,MAAM,SAAS,YAAY,IAAI,IAAI,CAAC;AAC1C,MAAI,IAAK,QAAO;;CAElB,MAAM,QAAQ,MAAM,sBAAsB,KAAK;AAC/C,KAAI,MAAM,GAAG;AACX,SAAO,YAAY,QAAQ,sBAAuB,aAAY,YAAY;AAC1E,cAAY,IAAI,KAAK;GAAE;GAAO,WAAW,KAAK,KAAK,GAAG;GAAK,CAAC;;AAE9D,QAAO;;AAmBT,SAAS,6BAA6B,MAA6C;AACjF,QAAO;EACL,IAAI,KAAK;EACT,MAAM,KAAK,eAAe,KAAK;EAC/B,MAAM;EACN,aAAa,KAAK,WAAW;EAC7B,WAAW,KAAK,MAAM;EACtB,QAAQ;GAAE,UAAU;GAAW,WAAW;GAAM;EAChD,eAAe,KAAK,eAAe,WAAW,KAAK,KAAK,UAAU;EAClE,WAAW,OAAO,KAAK,UAAU;EACjC,YAAY,KAAK,UAAU,MAAM,EAAE;EACnC,OAAO,KAAK,MAAM;EAClB,aAAa;EACd;;AAGH,SAAS,iCACP,MACA,YACiB;AACjB,QAAO;EACL,IAAI,KAAK;EACT,MAAM,KAAK,eAAe,KAAK;EAC/B,MAAM;EACN,aAAa,KAAK,WAAW;EAC7B,WAAW,YAAY,MAAM,aAAa;EAC1C,QAAQ;GACN,UAAU,KAAK,OAAO,UAAU,KAAK,eAAe;GACpD,WAAW,KAAK,OAAO,SAAS;GACjC;EACD,eAAe,KAAK,WAAW,YAAY,eAAe,WAAW;EACrE,WAAW,OAAO,KAAK,UAAU;EACjC,YAAY,YAAY,UAAU,MAAM,EAAE;EAC1C,OAAO,YAAY,MAAM,SAAS;EAClC,aAAa;EACd;;AAGH,SAAS,aAAa,MAA4C;AAChE,KAAI,SAAS,YAAa,QAAO;AACjC,KAAI,SAAS,SAAU,QAAO;;AAIhC,SAAS,uBAAuB,QAGrB;CACT,MAAM,QAAQ,OAAO,MAAM,eAAe,OAAO,MAAM;CACvD,MAAM,OAAO,OAAO,MAAM,WAAW;AACrC,QAAO,MAAM,MAAM,QAAQ,OAAO,MAAM,KAAK,QAAQ,OAAO,cAAc,QAAQ,MAAM;;AAG1F,MAAa,4BAAsD;CACjE,IAAI;CAEJ,MAAM,iBAAiB;AACrB,SAAO,EAAE;;CAGX,MAAM,aAAa,SAAS,QAAQ;EAClC,MAAM,WAAW,OAAO,YAAY;EACpC,MAAM,OAAO,OAAO,QAAQ;AAE5B,MAAI,OAAO,GAAG,MAAM,EAAE;GAKpB,MAAM,CAAC,gBAAgB,eAAe,MAAM,QAAQ,WAAW,CAC7D,0BAA0B,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAC3D,wBAAwB,EAAE,OAAO,iBAAiB,CAAC,CACpD,CAAC;AACF,OAAI,eAAe,WAAW,WAAY,OAAM,eAAe;GAC/D,MAAM,mCAAmB,IAAI,KAAmC;AAChE,OAAI,YAAY,WAAW,YACzB,MAAK,MAAM,MAAM,YAAY,MAAM,MAAO,kBAAiB,IAAI,GAAG,MAAM,GAAG;GAE7E,IAAI,OAAO,eAAe,MAAM,QAAQ,KAAK,MAC3C,iCAAiC,GAAG,iBAAiB,IAAI,EAAE,KAAK,CAAC,CAClE;AACD,OAAI,OAAO,SAAS,YAClB,QAAO,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,UAAU;YACjD,OAAO,SAAS,SACzB,QAAO,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,OAAO,EAAE,UAAU,GAAG,OAAO,EAAE,UAAU,CAAC;GAE5E,MAAM,QAAQ,KAAK;GACnB,MAAM,SAAS,OAAO,KAAK;AAG3B,UAAO;IAAE,OAFK,KAAK,MAAM,OAAO,QAAQ,SAE1B;IAAE,MAAM;KAAE;KAAM;KAAU;KAAO,YAD5B,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,SAAS,CACD;KAAE;IAAE,UAAU;IAAW;;EAKpF,MAAM,QAAO,MADc,wBAAwB;GAAE,OAAO;GAAiB,MADhE,aAAa,OAAO,KACgD;GAAE,CAAC,EAC1D,MAAM,IAAI,6BAA6B;EACjE,MAAM,QAAQ,KAAK;EACnB,MAAM,SAAS,OAAO,KAAK;AAG3B,SAAO;GAAE,OAFK,KAAK,MAAM,OAAO,QAAQ,SAE1B;GAAE,MAAM;IAAE;IAAM;IAAU;IAAO,YAD5B,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,SAAS,CACD;IAAE;GAAE,UAAU;GAAW;;CAGpF,MAAM,iBAAiB,SAAS,aAAa;EAC3C,MAAM,SAAS,MAAM,4BAA4B,YAAY;EAC7D,MAAM,OAAO,OAAO,MAAM;EAC1B,MAAM,UAAU,OAAO,cAAc;EAErC,IAAI,SAAwB;AAE5B,MAAI;GAEF,MAAM,UAAU,wBAAuB,MADX,wBAAwB,MAAM,QAAQ,EACb,QAAQ,MAAM;AACnE,OAAI,SAAS;IAEX,MAAM,WAAU,MADM,wBAAwB,MAAM,SAAS,QAAQ,EAC7C,MAAM;AAC9B,QAAI,QAAS,UAAS;;UAElB;AAIR,MAAI,CAAC,OACH,UAAS,uBAAuB,OAAO;EAGzC,MAAM,YAAY,OAAO,cAAc,WAAW,MAAM;AACxD,MAAI,UACF,UAAS,GAAG,OAAO,6BAA6B;AAGlD,SAAO;GACL,IAAI;GACJ,MAAM;GACN,MAAM;GACN,aAAa,OAAO,MAAM,WAAW;GACrC;GACA,WAAW,OAAO,MAAM,MAAM;GAC9B,QAAQ;IACN,UAAU,OAAO,MAAM;IACvB,WAAW,OAAO,MAAM;IACzB;GACD,eAAe;IACb,SAAS,OAAO,cAAc;IAC9B,WAAW,OAAO,cAAc;IAChC,aAAa,OAAO,OAAO,cAAc,UAAU;IACpD;GACD,UAAU;GACX;;CAGH,MAAM,gBAAgB,SAAS,aAAa,SAAS;EACnD,MAAM,OAAO,YAAY,MAAM;EAC/B,MAAM,SAAS,MAAM,wBAAwB,MAAM,QAAQ;AAC3D,SAAO;GACL,QAAQ,OAAO;GACf,SAAS,eAAe,KAAK,GAAG,OAAO;GACvC,SAAS,OAAO;GACjB;;CAEJ;AAED,2BAA2B;CACzB,SAAS;CACT,aAAa;CACd,CAAC"}
1
+ {"version":3,"file":"adapter.js","names":[],"sources":["../../../../../../../src/agent/skills/marketplace/adapters/clawhub/adapter.ts"],"sourcesContent":["/**\n * ClawHub (clawhub.ai) skills marketplace adapter.\n */\n\nimport { buildSkillMarkdownPreviewFromRaw } from '../../../skill-markdown-preview-from-raw.js';\nimport type { SkillsMarketplaceAdapter } from '../../adapter.types.js';\nimport { registerMarketplaceAdapter } from '../../registry.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_CLAWHUB_BASE = 'https://clawhub.ai';\nconst MAX_CLAWHUB_FILE_BYTES = 512 * 1024;\nconst MAX_SKILL_ZIP_BYTES = 15 * 1024 * 1024;\nconst SKILL_ID_RE = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62})$/;\nconst LIST_BATCH_SIZE = 200;\n\nconst DEFAULT_CACHE_MS = 5 * 60 * 1000;\nconst MAX_LIST_CACHE_KEYS = 24;\nconst MAX_DETAIL_CACHE_KEYS = 48;\n\n// ─── Inline helpers ──────────────────────────────────────────────────────────\n\nfunction isValidSkillId(id: string): boolean {\n return SKILL_ID_RE.test(id);\n}\n\nfunction resolveClawHubBaseUrl(): string {\n const env = process.env.CLAWHUB_REGISTRY?.trim();\n if (env) {\n try {\n return new URL(env).toString().replace(/\\/$/, '');\n } catch {\n // fall through\n }\n }\n return DEFAULT_CLAWHUB_BASE;\n}\n\n// ─── ClawHub API types ───────────────────────────────────────────────────────\n\ninterface ClawHubSkillListItem {\n slug: string;\n displayName: string;\n summary: string;\n tags: Record<string, string>;\n stats: {\n comments: number;\n downloads: number;\n installsAllTime: number;\n installsCurrent: number;\n stars: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n latestVersion: {\n version: string;\n createdAt: number;\n changelog: string | null;\n license: string | null;\n };\n metadata: { os: string[] | null; systems: string[] | null } | null;\n}\n\ninterface ClawHubSkillListResponse {\n items: ClawHubSkillListItem[];\n nextCursor: string | null;\n}\n\ninterface ClawHubSearchResultItem {\n score: number;\n slug: string;\n displayName: string;\n summary: string;\n version: string | null;\n updatedAt: number;\n ownerHandle: string;\n owner: {\n handle: string;\n displayName: string;\n image: string | null;\n };\n}\n\ninterface ClawHubSearchResponse {\n results: ClawHubSearchResultItem[];\n}\n\ninterface ClawHubSkillDetail {\n skill: {\n slug: string;\n displayName: string;\n summary: string;\n tags: Record<string, string>;\n stats: {\n comments: number;\n downloads: number;\n installsAllTime: number;\n installsCurrent: number;\n stars: number;\n versions: number;\n };\n createdAt: number;\n updatedAt: number;\n };\n latestVersion: {\n version: string;\n createdAt: number;\n changelog: string | null;\n license: string | null;\n };\n metadata: { os: string[] | null; systems: string[] | null } | null;\n owner: {\n handle: string;\n userId: string;\n displayName: string;\n image: string | null;\n };\n moderation: {\n isSuspicious: boolean;\n isMalwareBlocked: boolean;\n verdict: string;\n } | null;\n}\n\ninterface ClawHubVersionFile {\n path: string;\n size: number;\n sha256: string;\n contentType: string;\n}\n\ninterface ClawHubVersionDetail {\n skill: { slug: string; displayName: string };\n version: {\n version: string;\n createdAt: number;\n changelog: string | null;\n changelogSource: string | null;\n license: string | null;\n files: ClawHubVersionFile[];\n security: {\n status: string;\n hasWarnings: boolean;\n hasScanResult: boolean;\n } | null;\n };\n}\n\ntype ClawHubListSort = 'updated' | 'newest' | 'downloads' | 'stars' | 'trending';\n\ninterface ClawHubListParams {\n limit?: number;\n cursor?: string;\n sort?: ClawHubListSort;\n}\n\n// ─── ClawHub HTTP helpers ────────────────────────────────────────────────────\n\nasync function clawHubFetch(path: string, init?: { signal?: AbortSignal }): Promise<Response> {\n const base = resolveClawHubBaseUrl();\n const url = `${base}${path}`;\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n signal: init?.signal,\n });\n return res as unknown as Response;\n}\n\nfunction assertOk(res: Response, context: string): void {\n if (!res.ok) {\n throw new Error(`ClawHub ${context} failed (${res.status})`);\n }\n}\n\nasync function listClawHubSkills(params?: ClawHubListParams): Promise<ClawHubSkillListResponse> {\n const sp = new URLSearchParams();\n if (params?.limit) sp.set('limit', String(params.limit));\n if (params?.cursor) sp.set('cursor', params.cursor);\n if (params?.sort) sp.set('sort', params.sort);\n sp.set('nonSuspiciousOnly', 'true');\n const qs = sp.toString();\n const res = await clawHubFetch(`/api/v1/skills${qs ? `?${qs}` : ''}`);\n assertOk(res, 'list skills');\n return (await res.json()) as ClawHubSkillListResponse;\n}\n\nasync function searchClawHubSkills(query: string, limit?: number): Promise<ClawHubSearchResponse> {\n const sp = new URLSearchParams({ q: query, nonSuspiciousOnly: 'true' });\n if (limit) sp.set('limit', String(limit));\n const res = await clawHubFetch(`/api/v1/search?${sp.toString()}`);\n assertOk(res, 'search');\n return (await res.json()) as ClawHubSearchResponse;\n}\n\nasync function getClawHubSkillDetail(slug: string): Promise<ClawHubSkillDetail> {\n const enc = encodeURIComponent(slug.trim());\n const res = await clawHubFetch(`/api/v1/skills/${enc}`);\n assertOk(res, `skill detail [${slug}]`);\n return (await res.json()) as ClawHubSkillDetail;\n}\n\nasync function getClawHubVersionDetail(slug: string, version: string): Promise<ClawHubVersionDetail> {\n const enc = encodeURIComponent(slug.trim());\n const ver = encodeURIComponent(version.trim());\n const res = await clawHubFetch(`/api/v1/skills/${enc}/versions/${ver}`);\n assertOk(res, `version detail [${slug}@${version}]`);\n return (await res.json()) as ClawHubVersionDetail;\n}\n\nasync function getClawHubSkillFileText(slug: string, filePath: string, version?: string): Promise<string> {\n const enc = encodeURIComponent(slug.trim());\n const sp = new URLSearchParams({ path: filePath });\n if (version?.trim()) sp.set('version', version.trim());\n const base = resolveClawHubBaseUrl();\n const url = `${base}/api/v1/skills/${enc}/file?${sp.toString()}`;\n const res = await fetch(url, { headers: { Accept: 'text/markdown,text/plain,*/*' } });\n if (!res.ok) {\n throw new Error(`ClawHub file fetch [${slug}/${filePath}] failed (${res.status})`);\n }\n const text = await res.text();\n return text.length > MAX_CLAWHUB_FILE_BYTES ? text.slice(0, MAX_CLAWHUB_FILE_BYTES) : text;\n}\n\nasync function downloadClawHubSkillZip(\n slug: string,\n version?: string,\n): Promise<{ buffer: Buffer; version: string }> {\n const enc = encodeURIComponent(slug.trim());\n const sp = version?.trim() ? `?version=${encodeURIComponent(version.trim())}` : '';\n const base = resolveClawHubBaseUrl();\n const url = `${base}/api/v1/packages/${enc}/download${sp}`;\n const res = await fetch(url, { redirect: 'follow' });\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`ClawHub download [${slug}] failed (${res.status}): ${body.slice(0, 200)}`);\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (!contentType.includes('zip') && !contentType.includes('octet-stream')) {\n throw new Error(`ClawHub download [${slug}] unexpected content-type: ${contentType}`);\n }\n const arrayBuf = await res.arrayBuffer();\n if (arrayBuf.byteLength > MAX_SKILL_ZIP_BYTES) {\n throw new Error(\n `ClawHub download [${slug}] exceeds size limit (${arrayBuf.byteLength} > ${MAX_SKILL_ZIP_BYTES})`,\n );\n }\n return { buffer: Buffer.from(arrayBuf), version: version?.trim() || 'latest' };\n}\n\nfunction pickClawHubDocFilePath(files: ClawHubVersionFile[]): string | null {\n const rows = files.map((f) => ({\n path: f.path.replace(/\\\\/g, '/'),\n base: f.path.replace(/\\\\/g, '/').split('/').pop()?.toLowerCase() ?? '',\n }));\n const find = (name: string) => rows.find((r) => r.base === name.toLowerCase());\n const skillMd = find('SKILL.md') ?? find('skill.md');\n if (skillMd) return skillMd.path;\n const readme = find('README.md') ?? find('readme.md');\n if (readme) return readme.path;\n return null;\n}\n\n// ─── In-memory TTL cache ─────────────────────────────────────────────────────\n\ntype CacheEntry<T> = { value: T; expiresAt: number };\n\nfunction cacheTtlMs(): number {\n const raw = process.env.XOPC_CLAWHUB_CACHE_MS?.trim();\n if (raw === '0' || raw === 'false') return 0;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_CACHE_MS;\n return parsed;\n}\n\nfunction getFresh<T>(entry: CacheEntry<T> | undefined): T | undefined {\n if (!entry || entry.expiresAt <= Date.now()) return undefined;\n return entry.value;\n}\n\nfunction evictOldest<T>(map: Map<string, CacheEntry<T>>): void {\n const first = map.keys().next().value;\n if (first !== undefined) map.delete(first);\n}\n\nconst listCache = new Map<string, CacheEntry<ClawHubSkillListResponse>>();\nconst searchCache = new Map<string, CacheEntry<ClawHubSearchResponse>>();\nconst detailCache = new Map<string, CacheEntry<ClawHubSkillDetail>>();\n\nasync function cachedListClawHubSkills(params?: ClawHubListParams): Promise<ClawHubSkillListResponse> {\n const ttl = cacheTtlMs();\n const key = JSON.stringify(params ?? {});\n if (ttl > 0) {\n const hit = getFresh(listCache.get(key));\n if (hit) return hit;\n }\n const value = await listClawHubSkills(params);\n if (ttl > 0) {\n while (listCache.size >= MAX_LIST_CACHE_KEYS) evictOldest(listCache);\n listCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedSearchClawHubSkills(query: string, limit?: number): Promise<ClawHubSearchResponse> {\n const ttl = cacheTtlMs();\n const key = `${query}::${limit ?? ''}`;\n if (ttl > 0) {\n const hit = getFresh(searchCache.get(key));\n if (hit) return hit;\n }\n const value = await searchClawHubSkills(query, limit);\n if (ttl > 0) {\n while (searchCache.size >= MAX_LIST_CACHE_KEYS) evictOldest(searchCache);\n searchCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\nasync function cachedGetClawHubSkillDetail(slug: string): Promise<ClawHubSkillDetail> {\n const ttl = cacheTtlMs();\n const key = slug.trim();\n if (ttl > 0) {\n const hit = getFresh(detailCache.get(key));\n if (hit) return hit;\n }\n const value = await getClawHubSkillDetail(slug);\n if (ttl > 0) {\n while (detailCache.size >= MAX_DETAIL_CACHE_KEYS) evictOldest(detailCache);\n detailCache.set(key, { value, expiresAt: Date.now() + ttl });\n }\n return value;\n}\n\n// ─── Adapter conversion helpers ──────────────────────────────────────────────\n\ninterface PackageListItem {\n id: string;\n name: string;\n type: string;\n description: string;\n downloads: number;\n author: { username: string; avatarUrl: string | null };\n latestVersion?: string;\n updatedAt: string;\n categories?: string[];\n stars?: number;\n sourceLabel?: string;\n}\n\nfunction convertListItemToPackageItem(item: ClawHubSkillListItem): PackageListItem {\n return {\n id: item.slug,\n name: item.displayName || item.slug,\n type: 'skill',\n description: item.summary || '',\n downloads: item.stats.downloads,\n author: { username: 'clawhub', avatarUrl: null },\n latestVersion: item.latestVersion?.version ?? item.tags.latest ?? '1.0.0',\n updatedAt: String(item.updatedAt),\n categories: item.metadata?.os ?? [],\n stars: item.stats.stars,\n sourceLabel: 'ClawHub',\n };\n}\n\nfunction convertSearchResultToPackageItem(\n item: ClawHubSearchResultItem,\n enrichment?: ClawHubSkillListItem,\n): PackageListItem {\n return {\n id: item.slug,\n name: item.displayName || item.slug,\n type: 'skill',\n description: item.summary || '',\n downloads: enrichment?.stats.downloads ?? 0,\n author: {\n username: item.owner?.handle ?? item.ownerHandle ?? 'clawhub',\n avatarUrl: item.owner?.image ?? null,\n },\n latestVersion: item.version ?? enrichment?.latestVersion?.version ?? '1.0.0',\n updatedAt: String(item.updatedAt),\n categories: enrichment?.metadata?.os ?? [],\n stars: enrichment?.stats.stars ?? 0,\n sourceLabel: 'ClawHub',\n };\n}\n\nfunction mapSortParam(sort?: string): ClawHubListSort | undefined {\n if (sort === 'downloads') return 'downloads';\n if (sort === 'newest') return 'newest';\n return undefined;\n}\n\nfunction fallbackReadmeMarkdown(detail: {\n skill: { slug: string; displayName: string; summary: string };\n latestVersion: { version: string };\n}): string {\n const title = detail.skill.displayName || detail.skill.slug;\n const body = detail.skill.summary || '_No description._';\n return `## ${title}\\n\\n**${detail.skill.slug}** · v${detail.latestVersion.version}\\n\\n${body}`;\n}\n\nexport const clawHubMarketplaceAdapter: SkillsMarketplaceAdapter = {\n id: 'clawhub',\n\n async listCategories() {\n return [];\n },\n\n async listPackages(_config, params) {\n const pageSize = params.pageSize ?? 20;\n const page = params.page ?? 1;\n\n if (params.q?.trim()) {\n // Search results from /search omit downloads/stars/metadata. We pull the cached list\n // snapshot in parallel and merge by slug — costs nothing when the list cache is hot\n // (which it is after any preceding browse), and adds at most one round-trip on a cold\n // cache. We still tolerate a list-fetch failure: enrichment becomes a no-op.\n const [searchResponse, listSettled] = await Promise.allSettled([\n cachedSearchClawHubSkills(params.q.trim(), LIST_BATCH_SIZE),\n cachedListClawHubSkills({ limit: LIST_BATCH_SIZE }),\n ]);\n if (searchResponse.status === 'rejected') throw searchResponse.reason;\n const enrichmentBySlug = new Map<string, ClawHubSkillListItem>();\n if (listSettled.status === 'fulfilled') {\n for (const it of listSettled.value.items) enrichmentBySlug.set(it.slug, it);\n }\n let rows = searchResponse.value.results.map((r) =>\n convertSearchResultToPackageItem(r, enrichmentBySlug.get(r.slug)),\n );\n if (params.sort === 'downloads') {\n rows = [...rows].sort((a, b) => b.downloads - a.downloads);\n } else if (params.sort === 'newest') {\n rows = [...rows].sort((a, b) => Number(b.updatedAt) - Number(a.updatedAt));\n }\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'clawhub' };\n }\n\n const sort = mapSortParam(params.sort);\n const listResponse = await cachedListClawHubSkills({ limit: LIST_BATCH_SIZE, sort });\n const rows = listResponse.items.map(convertListItemToPackageItem);\n const total = rows.length;\n const start = (page - 1) * pageSize;\n const items = rows.slice(start, start + pageSize);\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n return { items, meta: { page, pageSize, total, totalPages }, provider: 'clawhub' };\n },\n\n async getPackageDetail(_config, packageName) {\n const detail = await cachedGetClawHubSkillDetail(packageName);\n const slug = detail.skill.slug;\n const version = detail.latestVersion.version;\n\n let readme: string | null = null;\n\n try {\n const versionDetail = await getClawHubVersionDetail(slug, version);\n const docPath = pickClawHubDocFilePath(versionDetail.version.files);\n if (docPath) {\n const rawText = await getClawHubSkillFileText(slug, docPath, version);\n const trimmed = rawText.trim();\n if (trimmed) readme = trimmed;\n }\n } catch {\n // version detail or file fetch failed — use fallback\n }\n\n if (!readme) {\n readme = fallbackReadmeMarkdown(detail);\n }\n\n const changelog = detail.latestVersion.changelog?.trim();\n if (changelog) {\n readme = `${readme}\\n\\n---\\n\\n## Changelog\\n\\n${changelog}`;\n }\n\n const description = detail.skill.summary || '';\n const skillDocPreview = buildSkillMarkdownPreviewFromRaw(readme, {\n name: slug,\n description,\n });\n\n return {\n id: slug,\n name: slug,\n type: 'skill',\n description,\n readme,\n skillDocPreview,\n downloads: detail.skill.stats.downloads,\n author: {\n username: detail.owner.handle,\n avatarUrl: detail.owner.image,\n },\n latestVersion: {\n version: detail.latestVersion.version,\n changelog: detail.latestVersion.changelog,\n publishedAt: String(detail.latestVersion.createdAt),\n },\n provider: 'clawhub',\n };\n },\n\n async downloadPackage(_config, packageName, version) {\n const slug = packageName.trim();\n const result = await downloadClawHubSkillZip(slug, version);\n return {\n buffer: result.buffer,\n skillId: isValidSkillId(slug) ? slug : 'unknown',\n version: result.version,\n };\n },\n};\n\nregisterMarketplaceAdapter({\n adapter: clawHubMarketplaceAdapter,\n displayName: 'ClawHub',\n});\n"],"mappings":"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"}