@shadowob/cloud 1.1.6-dev.311

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 (334) hide show
  1. package/README.md +509 -0
  2. package/dist/agent-browser-CERTMCDL.js +117 -0
  3. package/dist/agent-browser-CIRZRIY4.js +118 -0
  4. package/dist/agent-pack-LF3O5TR4.js +1236 -0
  5. package/dist/agent-pack-RQT27V7R.js +1235 -0
  6. package/dist/airtable-BG2Q75G2.js +82 -0
  7. package/dist/airtable-JCQXFM5D.js +83 -0
  8. package/dist/alipay-MZX2XCDB.js +52 -0
  9. package/dist/alipay-TZQI34RB.js +51 -0
  10. package/dist/amap-5RQB3VGC.js +45 -0
  11. package/dist/amap-KPCLZYYL.js +44 -0
  12. package/dist/atlassian-LGOEWYC7.js +54 -0
  13. package/dist/atlassian-TVS2A4IU.js +55 -0
  14. package/dist/baidu-appbuilder-6UMESXHW.js +41 -0
  15. package/dist/baidu-appbuilder-QRRL3ETM.js +42 -0
  16. package/dist/baidu-maps-HEPMVP5D.js +44 -0
  17. package/dist/baidu-maps-HXC4FBVP.js +45 -0
  18. package/dist/baidu-netdisk-G5Q6B5NH.js +45 -0
  19. package/dist/baidu-netdisk-RS2K5W2M.js +44 -0
  20. package/dist/baidu-smartprogram-EWTK5WKK.js +41 -0
  21. package/dist/baidu-smartprogram-JHD3XWF6.js +40 -0
  22. package/dist/browserbase-IUIYVYI7.js +67 -0
  23. package/dist/browserbase-JFO2PCIA.js +68 -0
  24. package/dist/canva-3YOFL7JS.js +62 -0
  25. package/dist/canva-FMYN65SM.js +61 -0
  26. package/dist/chunk-6P2K6QZR.js +529 -0
  27. package/dist/chunk-7VMRQ7MG.js +90 -0
  28. package/dist/chunk-AD3JTIU3.js +17 -0
  29. package/dist/chunk-BF6CV2Y4.js +64 -0
  30. package/dist/chunk-CTNUKOQE.js +439 -0
  31. package/dist/chunk-EEFMJYKB.js +97 -0
  32. package/dist/chunk-EJKFQ35I.js +739 -0
  33. package/dist/chunk-HUICDC56.js +62 -0
  34. package/dist/chunk-JUPAE5IA.js +527 -0
  35. package/dist/chunk-JY2HTT7Q.js +437 -0
  36. package/dist/chunk-KEPTCLUO.js +121 -0
  37. package/dist/chunk-KKK5H7YX.js +3622 -0
  38. package/dist/chunk-POSVEKIY.js +210 -0
  39. package/dist/chunk-QET4LT4J.js +5769 -0
  40. package/dist/chunk-QV4XWO3P.js +30 -0
  41. package/dist/chunk-R52J3PH2.js +120 -0
  42. package/dist/chunk-R5U7XKVJ.js +16 -0
  43. package/dist/chunk-RECNVWMT.js +212 -0
  44. package/dist/chunk-RTPBU5HF.js +92 -0
  45. package/dist/chunk-SUZ2ATT6.js +5774 -0
  46. package/dist/chunk-SVMXSIMG.js +98 -0
  47. package/dist/chunk-TV3CBM7R.js +28 -0
  48. package/dist/chunk-V2LU736V.js +3495 -0
  49. package/dist/chunk-ZUYL3W53.js +741 -0
  50. package/dist/claude-plugin-577TAQVS.js +1463 -0
  51. package/dist/claude-plugin-L3MXJJ6J.js +1464 -0
  52. package/dist/cli.js +7021 -0
  53. package/dist/cloudflare-HBBABPK6.js +114 -0
  54. package/dist/cloudflare-RDFPKMM5.js +115 -0
  55. package/dist/cnb-FLP3QX46.js +44 -0
  56. package/dist/cnb-YAVVEYFB.js +45 -0
  57. package/dist/console/index.html +12 -0
  58. package/dist/console/logo.png +0 -0
  59. package/dist/console/static/css/5079.f9e0918d.css +1 -0
  60. package/dist/console/static/css/index.7f91f806.css +1 -0
  61. package/dist/console/static/font/codicon.5b7d6fac.ttf +0 -0
  62. package/dist/console/static/js/5079.72a51ca2.js +699 -0
  63. package/dist/console/static/js/5079.72a51ca2.js.LICENSE.txt +35 -0
  64. package/dist/console/static/js/7426.f8d483ea.js +1 -0
  65. package/dist/console/static/js/async/1008.4df521b7.js +1 -0
  66. package/dist/console/static/js/async/102.1d473ec7.js +1 -0
  67. package/dist/console/static/js/async/1134.3f9fd9e7.js +1 -0
  68. package/dist/console/static/js/async/1318.4b8e48e7.js +1 -0
  69. package/dist/console/static/js/async/1360.5606da88.js +7 -0
  70. package/dist/console/static/js/async/1546.045f484f.js +1 -0
  71. package/dist/console/static/js/async/1562.187de2a8.js +1 -0
  72. package/dist/console/static/js/async/168.456d4813.js +1 -0
  73. package/dist/console/static/js/async/1750.e6dc2664.js +1 -0
  74. package/dist/console/static/js/async/1994.3fc86066.js +1 -0
  75. package/dist/console/static/js/async/2348.613ae3d9.js +1 -0
  76. package/dist/console/static/js/async/2390.1b890b9d.js +1 -0
  77. package/dist/console/static/js/async/2414.9d040212.js +1 -0
  78. package/dist/console/static/js/async/2454.4c1784ab.js +1 -0
  79. package/dist/console/static/js/async/2498.f5f92030.js +1 -0
  80. package/dist/console/static/js/async/2924.b823cd1a.js +1 -0
  81. package/dist/console/static/js/async/3062.63fddea6.js +1 -0
  82. package/dist/console/static/js/async/3078.dd712008.js +1 -0
  83. package/dist/console/static/js/async/3198.1f307065.js +1 -0
  84. package/dist/console/static/js/async/3246.3d5a899f.js +1 -0
  85. package/dist/console/static/js/async/3286.871676eb.js +1 -0
  86. package/dist/console/static/js/async/342.10bf3b90.js +1 -0
  87. package/dist/console/static/js/async/3446.9681a4d7.js +1 -0
  88. package/dist/console/static/js/async/3698.ccfaabec.js +1 -0
  89. package/dist/console/static/js/async/3790.2a1106a6.js +1 -0
  90. package/dist/console/static/js/async/4231.b29784d4.js +1 -0
  91. package/dist/console/static/js/async/4551.515bd41d.js +1 -0
  92. package/dist/console/static/js/async/4596.40f6e71b.js +1 -0
  93. package/dist/console/static/js/async/4600.4aaebe6d.js +1 -0
  94. package/dist/console/static/js/async/4718.1aae022f.js +1 -0
  95. package/dist/console/static/js/async/4846.a347c020.js +1 -0
  96. package/dist/console/static/js/async/4860.83dadf89.js +1 -0
  97. package/dist/console/static/js/async/500.fcfa37cb.js +1 -0
  98. package/dist/console/static/js/async/5096.b360203d.js +1 -0
  99. package/dist/console/static/js/async/5222.043274fe.js +1 -0
  100. package/dist/console/static/js/async/5362.f498001c.js +1 -0
  101. package/dist/console/static/js/async/54.c94f0755.js +1 -0
  102. package/dist/console/static/js/async/5478.50dd9ef0.js +2 -0
  103. package/dist/console/static/js/async/5478.50dd9ef0.js.LICENSE.txt +3 -0
  104. package/dist/console/static/js/async/5507.a6a1f793.js +1 -0
  105. package/dist/console/static/js/async/5638.bc6b102d.js +1 -0
  106. package/dist/console/static/js/async/5722.e0029049.js +1 -0
  107. package/dist/console/static/js/async/5942.74635c6b.js +1 -0
  108. package/dist/console/static/js/async/5994.1c5629c1.js +1 -0
  109. package/dist/console/static/js/async/6054.6bddf720.js +1 -0
  110. package/dist/console/static/js/async/6118.45e754e5.js +1 -0
  111. package/dist/console/static/js/async/6127.adcbcbb6.js +1 -0
  112. package/dist/console/static/js/async/614.3f434c20.js +1 -0
  113. package/dist/console/static/js/async/6234.ba3b002d.js +1 -0
  114. package/dist/console/static/js/async/6310.6546a9ba.js +1 -0
  115. package/dist/console/static/js/async/6378.9f805419.js +1 -0
  116. package/dist/console/static/js/async/6380.e4433c49.js +1 -0
  117. package/dist/console/static/js/async/6418.f23bcfda.js +1 -0
  118. package/dist/console/static/js/async/6428.77c86114.js +1 -0
  119. package/dist/console/static/js/async/6443.83318a6c.js +1 -0
  120. package/dist/console/static/js/async/6508.2b445d62.js +3 -0
  121. package/dist/console/static/js/async/6542.e82a26c8.js +1 -0
  122. package/dist/console/static/js/async/6544.62111ecb.js +1 -0
  123. package/dist/console/static/js/async/6612.a0c9fcf4.js +1 -0
  124. package/dist/console/static/js/async/6740.695aebf0.js +1 -0
  125. package/dist/console/static/js/async/6822.dbbb32bc.js +1 -0
  126. package/dist/console/static/js/async/6824.ad3540ab.js +1 -0
  127. package/dist/console/static/js/async/6930.585dab94.js +1 -0
  128. package/dist/console/static/js/async/6982.c81b95e6.js +1 -0
  129. package/dist/console/static/js/async/7046.ab2378c1.js +1 -0
  130. package/dist/console/static/js/async/7110.a603277f.js +1 -0
  131. package/dist/console/static/js/async/7142.4a21366f.js +1 -0
  132. package/dist/console/static/js/async/7348.15cc6148.js +1373 -0
  133. package/dist/console/static/js/async/7348.15cc6148.js.LICENSE.txt +14 -0
  134. package/dist/console/static/js/async/7374.b1ac5c44.js +1 -0
  135. package/dist/console/static/js/async/742.847f17ca.js +1 -0
  136. package/dist/console/static/js/async/7446.743954d8.js +1 -0
  137. package/dist/console/static/js/async/7673.59bbbaac.js +1 -0
  138. package/dist/console/static/js/async/7684.c5760c8c.js +1 -0
  139. package/dist/console/static/js/async/7714.c30d0f94.js +1 -0
  140. package/dist/console/static/js/async/8118.36d5a3bf.js +298 -0
  141. package/dist/console/static/js/async/8145.4bcf043a.js +1 -0
  142. package/dist/console/static/js/async/8246.408de938.js +1 -0
  143. package/dist/console/static/js/async/8390.bdae1f7d.js +1 -0
  144. package/dist/console/static/js/async/8422.fd94dbe1.js +1 -0
  145. package/dist/console/static/js/async/8434.94a0e2ae.js +1 -0
  146. package/dist/console/static/js/async/8518.3158de13.js +1 -0
  147. package/dist/console/static/js/async/8564.fc2eb841.js +1 -0
  148. package/dist/console/static/js/async/8678.73af4c9b.js +1 -0
  149. package/dist/console/static/js/async/8694.79747168.js +1 -0
  150. package/dist/console/static/js/async/8756.1de37b83.js +1 -0
  151. package/dist/console/static/js/async/8804.7fe6bdf9.js +3 -0
  152. package/dist/console/static/js/async/8883.e717ee94.js +1 -0
  153. package/dist/console/static/js/async/8886.fe6e876c.js +1 -0
  154. package/dist/console/static/js/async/9030.fc1ae402.js +1 -0
  155. package/dist/console/static/js/async/9094.5598d084.js +1 -0
  156. package/dist/console/static/js/async/9218.ee7b84b7.js +1 -0
  157. package/dist/console/static/js/async/94.9b80bc35.js +1 -0
  158. package/dist/console/static/js/async/9526.92aba34c.js +1 -0
  159. package/dist/console/static/js/async/9762.f83bc4f3.js +1 -0
  160. package/dist/console/static/js/async/984.e11c113a.js +1 -0
  161. package/dist/console/static/js/async/9846.246653cd.js +1 -0
  162. package/dist/console/static/js/index.4487e1ff.js +1 -0
  163. package/dist/console/static/js/lib-react.15d7ca9a.js +2 -0
  164. package/dist/console/static/js/lib-react.15d7ca9a.js.LICENSE.txt +49 -0
  165. package/dist/coze-C6PMDPBI.js +49 -0
  166. package/dist/coze-E6VGRNLV.js +48 -0
  167. package/dist/dashboard.command-J7XOZNXU.js +8 -0
  168. package/dist/dashboard.command-RV2NHDKW.js +7 -0
  169. package/dist/dingtalk-JNRNRN7E.js +77 -0
  170. package/dist/dingtalk-WZGGIAHJ.js +76 -0
  171. package/dist/douyin-miniprogram-AIJPPIZH.js +41 -0
  172. package/dist/douyin-miniprogram-HCYZ5NBW.js +42 -0
  173. package/dist/figma-2YYNSCDX.js +103 -0
  174. package/dist/figma-RYOBMENP.js +102 -0
  175. package/dist/firebase-2IJDDBXX.js +112 -0
  176. package/dist/firebase-OYSY6HPT.js +111 -0
  177. package/dist/firecrawl-2T3SBUW7.js +66 -0
  178. package/dist/firecrawl-IYYXLAZM.js +65 -0
  179. package/dist/flyai-7FJ4TRAG.js +81 -0
  180. package/dist/flyai-QS5Q6FJR.js +82 -0
  181. package/dist/gitagent-MWI75OIX.js +725 -0
  182. package/dist/gitagent-YBMWY7NZ.js +726 -0
  183. package/dist/gitee-3N7OFOM7.js +53 -0
  184. package/dist/gitee-KVNK6KLZ.js +54 -0
  185. package/dist/github-LUEC2LID.js +143 -0
  186. package/dist/github-XRO5Z3GC.js +142 -0
  187. package/dist/google-ads-A3QAJI4D.js +88 -0
  188. package/dist/google-ads-VPKWTX67.js +89 -0
  189. package/dist/google-analytics-C4UR5ZR2.js +50 -0
  190. package/dist/google-analytics-XDYZA2B7.js +49 -0
  191. package/dist/google-workspace-LL3EWVHH.js +320 -0
  192. package/dist/google-workspace-YX35SHHX.js +321 -0
  193. package/dist/huawei-xiaoyi-6BSMGJHR.js +40 -0
  194. package/dist/huawei-xiaoyi-KPWLTSHB.js +41 -0
  195. package/dist/hubspot-DIUHGEDI.js +45 -0
  196. package/dist/hubspot-FTIEMNZO.js +44 -0
  197. package/dist/huggingface-MJCOXA7E.js +116 -0
  198. package/dist/huggingface-UUXK2RHK.js +117 -0
  199. package/dist/index.d.ts +3013 -0
  200. package/dist/index.js +15649 -0
  201. package/dist/inference-ai-image-generation-CMI6R5T3.js +106 -0
  202. package/dist/inference-ai-image-generation-PXV6IG4U.js +107 -0
  203. package/dist/inference-sh-7AZOLEFI.js +94 -0
  204. package/dist/inference-sh-ABQOD3YF.js +95 -0
  205. package/dist/init.command-6E24K4H3.js +9 -0
  206. package/dist/init.command-O4HG4HKR.js +10 -0
  207. package/dist/klaviyo-6K5YEFNH.js +45 -0
  208. package/dist/klaviyo-LDPBWBSS.js +44 -0
  209. package/dist/kuaidi100-HGFM5VK2.js +42 -0
  210. package/dist/kuaidi100-UHPFCVXP.js +41 -0
  211. package/dist/lark-6LNA3LUQ.js +103 -0
  212. package/dist/lark-URVBZNS4.js +102 -0
  213. package/dist/linear-7QFSFPOD.js +57 -0
  214. package/dist/linear-T4ORUP7N.js +56 -0
  215. package/dist/lovart-PDUXRUHJ.js +99 -0
  216. package/dist/lovart-QO3SK55T.js +100 -0
  217. package/dist/meta-ads-SCNFI45S.js +42 -0
  218. package/dist/meta-ads-V6XPZWX3.js +41 -0
  219. package/dist/miclaw-5CNTW7VV.js +36 -0
  220. package/dist/miclaw-TPPPS2WN.js +35 -0
  221. package/dist/model-provider-AVSFJSZP.js +393 -0
  222. package/dist/model-provider-KFB76XV5.js +392 -0
  223. package/dist/notion-FZK76MN2.js +69 -0
  224. package/dist/notion-WFA7KGZZ.js +70 -0
  225. package/dist/oceanengine-3JZUS3PP.js +43 -0
  226. package/dist/oceanengine-5BRIJVJE.js +42 -0
  227. package/dist/opencli-PFXHGCS2.js +81 -0
  228. package/dist/opencli-VIGRJTGH.js +80 -0
  229. package/dist/paypal-33UADIPR.js +54 -0
  230. package/dist/paypal-Z5JYHIWD.js +55 -0
  231. package/dist/playwright-MG5WHK47.js +58 -0
  232. package/dist/playwright-SQAQ3DZG.js +59 -0
  233. package/dist/plugins-HZBWK3WQ.js +120 -0
  234. package/dist/plugins-I4GD5SZX.js +121 -0
  235. package/dist/posthog-MU5MAJOQ.js +79 -0
  236. package/dist/posthog-RJRRKDWB.js +80 -0
  237. package/dist/salesforce-34FVIJTG.js +82 -0
  238. package/dist/salesforce-3QZ6OFVO.js +83 -0
  239. package/dist/sentry-MCIRMACU.js +111 -0
  240. package/dist/sentry-PIWW46VA.js +110 -0
  241. package/dist/seo-suite-4SQ3I67Q.js +54 -0
  242. package/dist/seo-suite-WJXMA3S4.js +55 -0
  243. package/dist/serve.command-5FMIPQRY.js +10 -0
  244. package/dist/serve.command-DNE6GPMK.js +9 -0
  245. package/dist/shadowob-JELOWHWX.js +1068 -0
  246. package/dist/shadowob-PRSMI5MW.js +1069 -0
  247. package/dist/sherlock-2PKY2E2Y.js +66 -0
  248. package/dist/sherlock-C5ZWPPVT.js +67 -0
  249. package/dist/shopify-GL3NFVGE.js +94 -0
  250. package/dist/shopify-R4G3UXM6.js +93 -0
  251. package/dist/skill-discovery-7INAUP4D.js +77 -0
  252. package/dist/skill-discovery-YPXXV622.js +78 -0
  253. package/dist/state-7MCZBTR5.js +17 -0
  254. package/dist/state-FGOFLFBE.js +18 -0
  255. package/dist/stripe-C22RR4ZS.js +83 -0
  256. package/dist/stripe-LJNPQ3CQ.js +82 -0
  257. package/dist/supabase-IRNQ54FJ.js +98 -0
  258. package/dist/supabase-N4ONFJNQ.js +97 -0
  259. package/dist/taobao-aipaas-LRR4GMO3.js +45 -0
  260. package/dist/taobao-aipaas-RVKORSF4.js +46 -0
  261. package/dist/tapd-3JPVJ7XH.js +46 -0
  262. package/dist/tapd-TMQRSMFG.js +47 -0
  263. package/dist/tencent-ads-IGD33LO7.js +42 -0
  264. package/dist/tencent-ads-UHC6OPBV.js +43 -0
  265. package/dist/tencent-docs-C3A4J3CJ.js +47 -0
  266. package/dist/tencent-docs-O2SC4FHL.js +48 -0
  267. package/dist/tencent-maps-HMMWMNF4.js +37 -0
  268. package/dist/tencent-maps-OQOKHVW2.js +36 -0
  269. package/dist/vercel-KOXDDTHX.js +73 -0
  270. package/dist/vercel-OLNVDWMG.js +74 -0
  271. package/dist/webflow-FULU5Q2I.js +114 -0
  272. package/dist/webflow-OMJKZM54.js +115 -0
  273. package/dist/wechat-miniprogram-skyline-KYCDMQNW.js +74 -0
  274. package/dist/wechat-miniprogram-skyline-VR4FVIQL.js +75 -0
  275. package/dist/wechat-pay-BCMAJ6UW.js +50 -0
  276. package/dist/wechat-pay-YQQKXVUI.js +51 -0
  277. package/dist/wonda-NGWIORYN.js +81 -0
  278. package/dist/wonda-RBABXFNM.js +82 -0
  279. package/dist/wordpress-woocommerce-RDIUTHYT.js +57 -0
  280. package/dist/wordpress-woocommerce-RNA5HB3N.js +58 -0
  281. package/dist/wps-DAEFQHDE.js +47 -0
  282. package/dist/wps-LUWHMZQQ.js +48 -0
  283. package/dist/yuque-HCHTJWNI.js +72 -0
  284. package/dist/yuque-KRH5O74J.js +71 -0
  285. package/images/RUNNERS.md +270 -0
  286. package/images/cc-connect-runner/entrypoint.mjs +311 -0
  287. package/images/claude-runner/Dockerfile +88 -0
  288. package/images/claude-runner/RUNNER.md +222 -0
  289. package/images/claude-runner/entrypoint.mjs +2 -0
  290. package/images/codex-runner/Dockerfile +87 -0
  291. package/images/codex-runner/RUNNER.md +226 -0
  292. package/images/codex-runner/entrypoint.mjs +2 -0
  293. package/images/gemini-runner/Dockerfile +87 -0
  294. package/images/gemini-runner/RUNNER.md +218 -0
  295. package/images/gemini-runner/entrypoint.mjs +2 -0
  296. package/images/hermes-runner/Dockerfile +74 -0
  297. package/images/hermes-runner/RUNNER.md +243 -0
  298. package/images/hermes-runner/entrypoint.mjs +283 -0
  299. package/images/openclaw-runner/Dockerfile +212 -0
  300. package/images/openclaw-runner/RUNNER.md +170 -0
  301. package/images/openclaw-runner/entrypoint.mjs +1113 -0
  302. package/images/openclaw-runner/warm-runtime-deps.mjs +95 -0
  303. package/images/opencode-runner/Dockerfile +87 -0
  304. package/images/opencode-runner/RUNNER.md +202 -0
  305. package/images/opencode-runner/entrypoint.mjs +2 -0
  306. package/package.json +121 -0
  307. package/templates/agent-marketplace-buddy.template.json +131 -0
  308. package/templates/ai-werewolf.template.json +92 -0
  309. package/templates/bmad-method-buddy.template.json +123 -0
  310. package/templates/brain-fix.template.json +92 -0
  311. package/templates/claude-ads-buddy.template.json +123 -0
  312. package/templates/claude-financial-services-buddy.template.json +111 -0
  313. package/templates/claude-seo-buddy.template.json +123 -0
  314. package/templates/code-arena.template.json +92 -0
  315. package/templates/daily-brief.template.json +92 -0
  316. package/templates/e-wife.template.json +92 -0
  317. package/templates/everything-claude-code-buddy.template.json +125 -0
  318. package/templates/financial-freedom.template.json +92 -0
  319. package/templates/gitstory.template.json +92 -0
  320. package/templates/google-workspace-buddy.template.json +88 -0
  321. package/templates/gsd-buddy.template.json +119 -0
  322. package/templates/gstack-buddy.template.json +143 -0
  323. package/templates/gstack.template.json +92 -0
  324. package/templates/little-match-girl.template.json +114 -0
  325. package/templates/lovart-buddy.template.json +110 -0
  326. package/templates/marketingskills-buddy.template.json +102 -0
  327. package/templates/retire-buddy.template.json +92 -0
  328. package/templates/scientific-skills-buddy.template.json +119 -0
  329. package/templates/seomachine-buddy.template.json +113 -0
  330. package/templates/shadow-server-app-demo.template.json +105 -0
  331. package/templates/slavingia-skills-buddy.template.json +102 -0
  332. package/templates/superclaude-buddy.template.json +146 -0
  333. package/templates/superpowers-buddy.template.json +108 -0
  334. package/templates/world-pulse.template.json +92 -0
@@ -0,0 +1,741 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/plugins/agent-pack/indexer-script.ts
4
+ var AGENT_PACK_SLASH_INDEXER_SCRIPT = String.raw`
5
+ import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
6
+ import { basename, dirname, extname, join, relative } from 'node:path'
7
+
8
+ function readArg(name, fallback) {
9
+ const idx = process.argv.indexOf(name)
10
+ return idx >= 0 && process.argv[idx + 1] ? process.argv[idx + 1] : fallback
11
+ }
12
+
13
+ function listChildDirs(dir) {
14
+ try {
15
+ return readdirSync(dir, { withFileTypes: true })
16
+ .filter((d) => d.isDirectory())
17
+ .map((d) => join(dir, d.name))
18
+ } catch {
19
+ return []
20
+ }
21
+ }
22
+
23
+ function listFiles(dir, suffix) {
24
+ try {
25
+ return readdirSync(dir, { withFileTypes: true })
26
+ .filter((d) => d.isFile() && d.name.endsWith(suffix))
27
+ .map((d) => join(dir, d.name))
28
+ } catch {
29
+ return []
30
+ }
31
+ }
32
+
33
+ function listFilesRecursive(dir, maxDepth, depth = 0) {
34
+ if (depth > maxDepth) return []
35
+ try {
36
+ const entries = readdirSync(dir, { withFileTypes: true })
37
+ const out = []
38
+ for (const entry of entries) {
39
+ if (entry.name.startsWith('.')) continue
40
+ const path = join(dir, entry.name)
41
+ if (entry.isDirectory()) {
42
+ if (['node_modules', 'dist', 'build', 'vendor', 'coverage', '__pycache__'].includes(entry.name)) {
43
+ continue
44
+ }
45
+ out.push(...listFilesRecursive(path, maxDepth, depth + 1))
46
+ } else if (entry.isFile()) {
47
+ out.push(path)
48
+ }
49
+ }
50
+ return out
51
+ } catch {
52
+ return []
53
+ }
54
+ }
55
+
56
+ function readMaybe(path) {
57
+ try {
58
+ return readFileSync(path, 'utf-8')
59
+ } catch {
60
+ return ''
61
+ }
62
+ }
63
+
64
+ function normalizeSlashCommandName(value) {
65
+ if (typeof value !== 'string') return null
66
+ const name = value.trim().replace(/^\/+/, '')
67
+ return /^[a-zA-Z][a-zA-Z0-9._-]{0,63}$/.test(name) ? name : null
68
+ }
69
+
70
+ function parseFrontmatterList(value) {
71
+ if (typeof value !== 'string') return []
72
+ const trimmed = value.trim()
73
+ const unwrapped =
74
+ trimmed.startsWith('[') && trimmed.endsWith(']') ? trimmed.slice(1, -1) : trimmed
75
+ return unwrapped
76
+ .split(',')
77
+ .map((item) => item.trim().replace(/^['"]|['"]$/g, ''))
78
+ .filter(Boolean)
79
+ }
80
+
81
+ function parseFrontmatter(text) {
82
+ if (!text.startsWith('---')) return { data: {}, body: text }
83
+ const end = text.indexOf('\n---', 3)
84
+ if (end === -1) return { data: {}, body: text }
85
+
86
+ const raw = text.slice(3, end).trim()
87
+ const data = {}
88
+ const lines = raw.split('\n')
89
+ for (let i = 0; i < lines.length; i++) {
90
+ const line = lines[i]
91
+ const match = line.match(/^([a-zA-Z0-9_.-]+):\s*(.*)$/)
92
+ if (!match) continue
93
+ const key = match[1]
94
+ const value = match[2].trim().replace(/^['"]|['"]$/g, '')
95
+
96
+ if (value === '|') {
97
+ const block = []
98
+ while (i + 1 < lines.length) {
99
+ const next = lines[i + 1]
100
+ if (next && !/^\s/.test(next)) break
101
+ block.push(next.replace(/^\s{2}/, ''))
102
+ i++
103
+ }
104
+ data[key] = block.join('\n').trim()
105
+ continue
106
+ }
107
+
108
+ if (value) {
109
+ data[key] = value
110
+ continue
111
+ }
112
+
113
+ const items = []
114
+ while (i + 1 < lines.length) {
115
+ const itemMatch = lines[i + 1].match(/^\s*-\s*(.+)$/)
116
+ if (!itemMatch) break
117
+ items.push(itemMatch[1].trim().replace(/^['"]|['"]$/g, ''))
118
+ i++
119
+ }
120
+ data[key] = items.length > 0 ? items.join(',') : value
121
+ }
122
+
123
+ return { data, body: text.slice(end + 4).trimStart() }
124
+ }
125
+
126
+ function parseFrontmatterJson(value) {
127
+ if (typeof value !== 'string') return undefined
128
+ const trimmed = value.trim()
129
+ if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return undefined
130
+ try {
131
+ return JSON.parse(trimmed)
132
+ } catch {
133
+ return undefined
134
+ }
135
+ }
136
+
137
+ function normalizeInteractionItems(value, max) {
138
+ if (!Array.isArray(value)) return undefined
139
+ const items = value
140
+ .filter((item) => item && typeof item === 'object' && !Array.isArray(item))
141
+ .map((item, index) => {
142
+ const label =
143
+ typeof item.label === 'string' && item.label.trim()
144
+ ? item.label.trim()
145
+ : typeof item.value === 'string' && item.value.trim()
146
+ ? item.value.trim()
147
+ : 'Option ' + (index + 1)
148
+ const id =
149
+ typeof item.id === 'string' && item.id.trim()
150
+ ? item.id.trim()
151
+ : typeof item.value === 'string' && item.value.trim()
152
+ ? item.value.trim()
153
+ : label
154
+ return {
155
+ id,
156
+ label,
157
+ ...(typeof item.value === 'string' && item.value.trim()
158
+ ? { value: item.value.trim() }
159
+ : {}),
160
+ ...(item.style === 'primary' || item.style === 'secondary' || item.style === 'destructive'
161
+ ? { style: item.style }
162
+ : {}),
163
+ }
164
+ })
165
+ .filter((item) => item.id && item.label)
166
+ return items.length > 0 ? items.slice(0, max) : undefined
167
+ }
168
+
169
+ function normalizeSlashInteraction(value) {
170
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
171
+ const kind = typeof value.kind === 'string' ? value.kind.trim().toLowerCase() : ''
172
+ if (!['buttons', 'select', 'form', 'approval'].includes(kind)) return undefined
173
+
174
+ const out = { kind }
175
+ for (const key of ['id', 'prompt', 'submitLabel', 'responsePrompt', 'approvalCommentLabel']) {
176
+ if (typeof value[key] === 'string' && value[key].trim()) out[key] = value[key].trim()
177
+ }
178
+ if (typeof value.oneShot === 'boolean') out.oneShot = value.oneShot
179
+
180
+ const buttons = normalizeInteractionItems(value.buttons, 8)
181
+ const options = normalizeInteractionItems(value.options, 20)?.map((option) => ({
182
+ id: option.id,
183
+ label: option.label,
184
+ value: option.value ?? option.id,
185
+ }))
186
+ if (buttons) out.buttons = buttons
187
+ if (options) out.options = options
188
+
189
+ if (Array.isArray(value.fields)) {
190
+ out.fields = value.fields
191
+ .filter((field) => field && typeof field === 'object' && !Array.isArray(field))
192
+ .map((field, index) => ({
193
+ id:
194
+ typeof field.id === 'string' && field.id.trim() ? field.id.trim() : 'field_' + (index + 1),
195
+ kind:
196
+ typeof field.kind === 'string' &&
197
+ ['text', 'textarea', 'number', 'checkbox', 'select'].includes(field.kind)
198
+ ? field.kind
199
+ : 'text',
200
+ label:
201
+ typeof field.label === 'string' && field.label.trim()
202
+ ? field.label.trim()
203
+ : 'Field ' + (index + 1),
204
+ ...(typeof field.placeholder === 'string' && field.placeholder.trim()
205
+ ? { placeholder: field.placeholder.trim() }
206
+ : {}),
207
+ ...(typeof field.defaultValue === 'string' ? { defaultValue: field.defaultValue } : {}),
208
+ ...(typeof field.required === 'boolean' ? { required: field.required } : {}),
209
+ ...(typeof field.maxLength === 'number' ? { maxLength: field.maxLength } : {}),
210
+ ...(typeof field.min === 'number' ? { min: field.min } : {}),
211
+ ...(typeof field.max === 'number' ? { max: field.max } : {}),
212
+ }))
213
+ .slice(0, 12)
214
+ }
215
+
216
+ return out
217
+ }
218
+
219
+ function frontmatterInteraction(data) {
220
+ const direct = normalizeSlashInteraction(
221
+ parseFrontmatterJson(data.interaction) ?? parseFrontmatterJson(data.interactive),
222
+ )
223
+ if (direct) return direct
224
+
225
+ const kind = data['interaction.kind'] ?? data['interactive.kind']
226
+ if (!kind) return undefined
227
+ const oneShotRaw = data['interaction.oneShot'] ?? data['interactive.oneShot']
228
+ return normalizeSlashInteraction({
229
+ kind,
230
+ id: data['interaction.id'] ?? data['interactive.id'],
231
+ prompt: data['interaction.prompt'] ?? data['interactive.prompt'],
232
+ submitLabel: data['interaction.submitLabel'] ?? data['interactive.submitLabel'],
233
+ responsePrompt: data['interaction.responsePrompt'] ?? data['interactive.responsePrompt'],
234
+ approvalCommentLabel:
235
+ data['interaction.approvalCommentLabel'] ?? data['interactive.approvalCommentLabel'],
236
+ ...(oneShotRaw !== undefined ? { oneShot: oneShotRaw === 'true' } : {}),
237
+ buttons: parseFrontmatterJson(data['interaction.buttons'] ?? data['interactive.buttons']),
238
+ options: parseFrontmatterJson(data['interaction.options'] ?? data['interactive.options']),
239
+ fields: parseFrontmatterJson(data['interaction.fields'] ?? data['interactive.fields']),
240
+ })
241
+ }
242
+
243
+ function derivePackId(path, mountPath) {
244
+ const mountParts = mountPath.split('/').filter(Boolean)
245
+ const parts = path.split('/').filter(Boolean)
246
+ if (mountParts.length > 0) {
247
+ for (let i = 0; i <= parts.length - mountParts.length - 1; i++) {
248
+ let matches = true
249
+ for (let j = 0; j < mountParts.length; j++) {
250
+ if (parts[i + j] !== mountParts[j]) {
251
+ matches = false
252
+ break
253
+ }
254
+ }
255
+ if (matches && parts[i + mountParts.length]) return parts[i + mountParts.length]
256
+ }
257
+ }
258
+
259
+ const idx = parts.lastIndexOf('agent-packs')
260
+ if (idx >= 0 && parts[idx + 1]) return parts[idx + 1]
261
+ return undefined
262
+ }
263
+
264
+ function deriveSlashDescription(body, frontmatter) {
265
+ const fmDescription =
266
+ typeof frontmatter.description === 'string' ? frontmatter.description.trim() : ''
267
+ if (fmDescription) return fmDescription.slice(0, 240)
268
+
269
+ for (const line of body.split('\n')) {
270
+ const text = line.replace(/^#+\s*/, '').trim()
271
+ if (text) return text.slice(0, 240)
272
+ }
273
+ return undefined
274
+ }
275
+
276
+ function asStringArray(value) {
277
+ if (typeof value === 'string') return [value]
278
+ return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : []
279
+ }
280
+
281
+ function matchesSlashCommandRule(rule, command, context) {
282
+ const match = rule.match
283
+ if (!match || typeof match !== 'object') return true
284
+ if (typeof match.packId === 'string' && match.packId !== context.packId) return false
285
+
286
+ const names = [...asStringArray(match.name), ...asStringArray(match.names)]
287
+ if (
288
+ names.length > 0 &&
289
+ !names.some((name) => name.toLowerCase() === command.name.toLowerCase())
290
+ ) {
291
+ return false
292
+ }
293
+
294
+ if (typeof match.namePattern === 'string' && match.namePattern.trim()) {
295
+ try {
296
+ if (!new RegExp(match.namePattern).test(command.name)) return false
297
+ } catch (err) {
298
+ console.warn('[agent-pack] Ignoring invalid slash command rule pattern: ' + err.message)
299
+ return false
300
+ }
301
+ }
302
+
303
+ const pathIncludes = asStringArray(match.sourcePathIncludes)
304
+ return pathIncludes.length === 0 || pathIncludes.some((needle) => context.path.includes(needle))
305
+ }
306
+
307
+ function applySlashCommandRules(command, context, rules) {
308
+ for (const rule of rules) {
309
+ if (!matchesSlashCommandRule(rule, command, context)) continue
310
+
311
+ const aliases = asStringArray(rule.aliases)
312
+ .map(normalizeSlashCommandName)
313
+ .filter(Boolean)
314
+ .filter((alias) => alias.toLowerCase() !== command.name.toLowerCase())
315
+ if (aliases.length > 0) {
316
+ command.aliases = [...new Set([...(command.aliases ?? []), ...aliases])]
317
+ }
318
+
319
+ const interaction = normalizeSlashInteraction(rule.interaction)
320
+ if (interaction && !command.interaction) command.interaction = interaction
321
+ }
322
+
323
+ return command
324
+ }
325
+
326
+ function stripMarkdownInline(value) {
327
+ return value
328
+ .replace(new RegExp('[' + String.fromCharCode(96) + '*_~]', 'g'), '')
329
+ .replace(/\s+/g, ' ')
330
+ .trim()
331
+ }
332
+
333
+ function extractAskLine(block) {
334
+ const quoted = block.match(/\*\*Ask:\*\*\s*"([\s\S]*?)"/)
335
+ if (quoted?.[1]) return stripMarkdownInline(quoted[1])
336
+
337
+ const line = block.match(/\*\*Ask:\*\*\s*(.+)/)
338
+ if (line?.[1]) return stripMarkdownInline(line[1].replace(/^"|"$/g, ''))
339
+
340
+ return ''
341
+ }
342
+
343
+ function slugifyFieldId(value, fallback) {
344
+ const slug = value
345
+ .toLowerCase()
346
+ .replace(/[^a-z0-9]+/g, '_')
347
+ .replace(/^_+|_+$/g, '')
348
+ .slice(0, 64)
349
+ return slug || fallback
350
+ }
351
+
352
+ function deriveAskFieldsFromMarkdown(markdown) {
353
+ const questionHeadingRegex = /^#{2,6}\s+Q(\d+)\s*:\s*(.+?)\s*$/gm
354
+ const matches = [...markdown.matchAll(questionHeadingRegex)]
355
+ const fields = []
356
+
357
+ for (let i = 0; i < matches.length && fields.length < 12; i++) {
358
+ const current = matches[i]
359
+ const next = matches[i + 1]
360
+ const qNumber = current[1]
361
+ const title = stripMarkdownInline(current[2] ?? 'Question ' + (fields.length + 1))
362
+ const blockStart = (current.index ?? 0) + current[0].length
363
+ const blockEnd = next?.index ?? markdown.length
364
+ const ask = extractAskLine(markdown.slice(blockStart, blockEnd))
365
+ if (!ask) continue
366
+ fields.push({
367
+ id: slugifyFieldId('q' + qNumber + '_' + title, 'q' + (fields.length + 1)),
368
+ kind: 'textarea',
369
+ label: 'Q' + qNumber + ': ' + title,
370
+ placeholder: ask,
371
+ required: true,
372
+ maxLength: 2000,
373
+ })
374
+ }
375
+
376
+ if (fields.length > 0) return fields
377
+
378
+ const askLines = [...markdown.matchAll(/\*\*Ask:\*\*\s*"?(.+?)"?\s*$/gm)]
379
+ for (let i = 0; i < askLines.length && fields.length < 12; i++) {
380
+ const ask = stripMarkdownInline(askLines[i][1] ?? '')
381
+ if (!ask) continue
382
+ fields.push({
383
+ id: 'q' + (i + 1),
384
+ kind: 'textarea',
385
+ label: 'Q' + (i + 1),
386
+ placeholder: ask,
387
+ required: true,
388
+ maxLength: 2000,
389
+ })
390
+ }
391
+
392
+ return fields
393
+ }
394
+
395
+ function inferInteractionFromMarkdown(command, inferInteractions) {
396
+ if (!inferInteractions || !command.body) return undefined
397
+ const fields = deriveAskFieldsFromMarkdown(command.body)
398
+ if (fields.length < 2) return undefined
399
+
400
+ return {
401
+ id: 'slash:' + (command.packId ?? 'pack') + ':' + command.name + ':auto-form',
402
+ kind: 'form',
403
+ prompt:
404
+ command.description ?? '/' + command.name + ' needs a few answers before the Buddy can continue.',
405
+ oneShot: true,
406
+ responsePrompt:
407
+ 'Use the submitted values as answers to this slash command, then continue from the source command definition. Produce the requested artifact before asking for approval.',
408
+ fields,
409
+ }
410
+ }
411
+
412
+ function deriveAliasCandidates(name, packId) {
413
+ const candidates = new Set()
414
+ let base = name
415
+
416
+ if (packId && base.startsWith(packId + '-')) {
417
+ base = base.slice(packId.length + 1)
418
+ if (normalizeSlashCommandName(base)) candidates.add(base)
419
+ }
420
+
421
+ for (const prefix of ['openclaw-', 'claude-', 'claude-code-', 'codex-', 'cursor-']) {
422
+ if (base.startsWith(prefix)) {
423
+ const stripped = base.slice(prefix.length)
424
+ if (normalizeSlashCommandName(stripped)) candidates.add(stripped)
425
+ }
426
+ }
427
+
428
+ for (const candidate of [...candidates]) {
429
+ if (candidate.endsWith('-hours')) candidates.add(candidate.replace(/-hours$/, '-hour'))
430
+ }
431
+
432
+ return [...candidates].filter((alias) => alias.toLowerCase() !== name.toLowerCase())
433
+ }
434
+
435
+ function addInferredAliases(command, context) {
436
+ const aliases = new Set(command.aliases ?? [])
437
+ for (const alias of deriveAliasCandidates(command.name, context.packId)) aliases.add(alias)
438
+ if (aliases.size > 0) command.aliases = [...aliases]
439
+ return command
440
+ }
441
+
442
+ const SCRIPT_EXTENSIONS = new Set(['', '.sh', '.bash', '.js', '.mjs', '.cjs', '.py', '.rb', '.pl'])
443
+ const SCRIPT_EXCLUDED_EXTENSIONS = new Set([
444
+ '.ts',
445
+ '.tsx',
446
+ '.json',
447
+ '.md',
448
+ '.mdx',
449
+ '.txt',
450
+ '.png',
451
+ '.jpg',
452
+ '.jpeg',
453
+ '.gif',
454
+ '.svg',
455
+ '.icns',
456
+ '.map',
457
+ '.lock',
458
+ ])
459
+ const SCRIPT_EXCLUDED_NAMES = new Set([
460
+ 'package.json',
461
+ 'package-lock.json',
462
+ 'pnpm-lock.yaml',
463
+ 'yarn.lock',
464
+ 'bun.lockb',
465
+ ])
466
+
467
+ function readScriptHead(path) {
468
+ try {
469
+ return readFileSync(path, 'utf-8').slice(0, 12000)
470
+ } catch {
471
+ return ''
472
+ }
473
+ }
474
+
475
+ function isLikelyScript(path) {
476
+ const name = basename(path)
477
+ if (!name || name.startsWith('.') || SCRIPT_EXCLUDED_NAMES.has(name)) return false
478
+ const ext = extname(name).toLowerCase()
479
+ if (SCRIPT_EXCLUDED_EXTENSIONS.has(ext)) return false
480
+ if (!SCRIPT_EXTENSIONS.has(ext)) return false
481
+
482
+ try {
483
+ const stat = statSync(path)
484
+ if (!stat.isFile() || stat.size <= 0 || stat.size > 512 * 1024) return false
485
+ } catch {
486
+ return false
487
+ }
488
+
489
+ if (ext === '') return true
490
+ const head = readScriptHead(path)
491
+ return head.startsWith('#!') || /(^|\n)\s*(Usage:|USAGE:|export\s+default|if\s+\(__name__\s*==)/.test(head)
492
+ }
493
+
494
+ function commandNameFromScriptPath(path) {
495
+ const ext = extname(path)
496
+ const raw = ext ? basename(path, ext) : basename(path)
497
+ const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '')
498
+ return normalizeSlashCommandName(normalized)
499
+ }
500
+
501
+ function deriveScriptDescription(path, packId) {
502
+ const head = readScriptHead(path)
503
+ const lines = head.split('\n').slice(0, 60)
504
+ for (const rawLine of lines) {
505
+ const line = rawLine
506
+ .replace(/^#!.*$/, '')
507
+ .replace(/^\s*(#|\/\/)\s?/, '')
508
+ .trim()
509
+ if (!line) continue
510
+ if (/^(usage|env overrides?|set -|shellcheck|eslint|biome)/i.test(line)) continue
511
+ return stripMarkdownInline(line).slice(0, 180)
512
+ }
513
+ return 'Run a helper script from the ' + packId + ' agent pack.'
514
+ }
515
+
516
+ function scriptSkillMarkdown(params) {
517
+ const rel = params.relPath
518
+ const description = params.description
519
+ const path = params.path
520
+ return [
521
+ '---',
522
+ 'name: ' + JSON.stringify(params.name),
523
+ 'description: ' + JSON.stringify(description),
524
+ '---',
525
+ '',
526
+ '# ' + params.name,
527
+ '',
528
+ 'This capability is backed by a mounted helper script from the ' + params.packId + ' agent pack.',
529
+ '',
530
+ '- Script path: ' + path,
531
+ '- Pack script: ' + rel,
532
+ '',
533
+ 'When this skill is relevant:',
534
+ '',
535
+ '1. Inspect usage first by running the script with --help, or read the script if help is not supported.',
536
+ '2. Run the script with explicit user-provided arguments, using the absolute script path above.',
537
+ '3. Summarize stdout, stderr, exit status, and any files created or changed.',
538
+ '4. For destructive, credentialed, long-running, or network-heavy actions, explain the exact action before running it unless the user explicitly requested that action.',
539
+ ].join('\n')
540
+ }
541
+
542
+ function discoverPackDirs(mountPath) {
543
+ return listChildDirs(mountPath).filter((packDir) => !packDir.endsWith('/.shadow'))
544
+ }
545
+
546
+ function discoverPackScripts(packDir, maxPerPack) {
547
+ const scriptsDir = join(packDir, 'scripts')
548
+ if (!existsSync(scriptsDir)) return []
549
+ const seenNames = new Set()
550
+ const scripts = []
551
+ for (const path of listFilesRecursive(scriptsDir, 4)) {
552
+ if (!isLikelyScript(path)) continue
553
+ const name = commandNameFromScriptPath(path)
554
+ if (!name || seenNames.has(name.toLowerCase())) continue
555
+ seenNames.add(name.toLowerCase())
556
+ scripts.push({
557
+ name,
558
+ path,
559
+ relPath: relative(scriptsDir, path),
560
+ })
561
+ if (scripts.length >= maxPerPack) break
562
+ }
563
+ return scripts
564
+ }
565
+
566
+ function generateScriptSkillWrappers(mountPath, options) {
567
+ if (!options.includeScripts || !options.generateScriptSkills) return
568
+ for (const packDir of discoverPackDirs(mountPath)) {
569
+ const packId = basename(packDir)
570
+ const skillsDir = join(packDir, 'skills')
571
+ mkdirSync(skillsDir, { recursive: true })
572
+
573
+ for (const script of discoverPackScripts(packDir, options.maxScriptCommandsPerPack)) {
574
+ const skillDir = join(skillsDir, script.name)
575
+ const skillPath = join(skillDir, 'SKILL.md')
576
+ if (existsSync(skillPath)) continue
577
+ const description = deriveScriptDescription(script.path, packId)
578
+ mkdirSync(skillDir, { recursive: true })
579
+ writeFileSync(
580
+ skillPath,
581
+ scriptSkillMarkdown({
582
+ ...script,
583
+ packId,
584
+ description,
585
+ }),
586
+ 'utf-8',
587
+ )
588
+ }
589
+ }
590
+ }
591
+
592
+ function discoverScriptCommands(mountPath, options) {
593
+ if (!options.includeScripts) return []
594
+ const commands = []
595
+ for (const packDir of discoverPackDirs(mountPath)) {
596
+ const packId = basename(packDir)
597
+ for (const script of discoverPackScripts(packDir, options.maxScriptCommandsPerPack)) {
598
+ const description = deriveScriptDescription(script.path, packId)
599
+ commands.push({
600
+ name: script.name,
601
+ description,
602
+ packId,
603
+ sourcePath: script.path,
604
+ body: scriptSkillMarkdown({
605
+ ...script,
606
+ packId,
607
+ description,
608
+ }),
609
+ })
610
+ }
611
+ }
612
+ return commands
613
+ }
614
+
615
+ function readSlashCommand(path, fallbackName, options) {
616
+ const text = readMaybe(path).trim()
617
+ if (!text) return null
618
+ const { data, body } = parseFrontmatter(text)
619
+ const name = normalizeSlashCommandName(data.name ?? fallbackName)
620
+ if (!name) return null
621
+ const packId = derivePackId(path, options.mountPath)
622
+ const aliases = parseFrontmatterList(data.aliases)
623
+ .map(normalizeSlashCommandName)
624
+ .filter(Boolean)
625
+ .filter((alias) => alias.toLowerCase() !== name.toLowerCase())
626
+ const description = deriveSlashDescription(body, data)
627
+ const interaction = frontmatterInteraction(data)
628
+
629
+ let command = {
630
+ name,
631
+ ...(description ? { description } : {}),
632
+ ...(aliases.length > 0 ? { aliases: [...new Set(aliases)] } : {}),
633
+ ...(packId ? { packId } : {}),
634
+ ...(interaction ? { interaction } : {}),
635
+ sourcePath: path,
636
+ body: text.slice(0, 20000),
637
+ }
638
+
639
+ const context = { path, packId, body, frontmatter: data }
640
+ command = addInferredAliases(command, context)
641
+ command = applySlashCommandRules(command, context, options.rules)
642
+
643
+ if (!command.interaction) {
644
+ const inferred = inferInteractionFromMarkdown(command, options.inferInteractions)
645
+ if (inferred) command.interaction = inferred
646
+ }
647
+
648
+ return command
649
+ }
650
+
651
+ function discoverSlashCommands(commandsDirs, options) {
652
+ const commands = []
653
+ const seen = new Set()
654
+ for (const dir of commandsDirs) {
655
+ for (const file of listFiles(dir, '.md')) {
656
+ const fallbackName = file.split('/').pop().replace(/\.md$/, '')
657
+ const command = readSlashCommand(file, fallbackName, options)
658
+ if (!command) continue
659
+ const key = command.name.toLowerCase()
660
+ if (seen.has(key)) continue
661
+ seen.add(key)
662
+ commands.push(command)
663
+ }
664
+
665
+ for (const childDir of listChildDirs(dir)) {
666
+ const fallbackName = childDir.split('/').pop()
667
+ for (const candidate of ['SKILL.md', 'COMMAND.md', 'README.md']) {
668
+ const path = join(childDir, candidate)
669
+ if (!existsSync(path)) continue
670
+ const command = readSlashCommand(path, fallbackName, options)
671
+ if (!command) break
672
+ const key = command.name.toLowerCase()
673
+ if (!seen.has(key)) {
674
+ seen.add(key)
675
+ commands.push(command)
676
+ }
677
+ break
678
+ }
679
+ }
680
+ }
681
+ return commands.slice(0, 200)
682
+ }
683
+
684
+ function commandDirsFromMountRoot(mountPath) {
685
+ const dirs = []
686
+ for (const packDir of listChildDirs(mountPath)) {
687
+ if (packDir.endsWith('/.shadow')) continue
688
+ for (const kind of ['commands', 'skills']) {
689
+ const dir = join(packDir, kind)
690
+ if (existsSync(dir)) dirs.push(dir)
691
+ }
692
+ }
693
+ return [...new Set(dirs)]
694
+ }
695
+
696
+ const mountPath = readArg('--mount-path', '/agent-packs')
697
+ const output = readArg('--output', mountPath + '/.shadow/slash-commands.json')
698
+ const rulesRaw = readArg('--rules-json', '[]')
699
+ const inferInteractions = readArg('--infer-interactions', 'true') !== 'false'
700
+ const includeScripts = readArg('--include-scripts', 'true') !== 'false'
701
+ const generateScriptSkills = readArg('--generate-script-skills', 'true') !== 'false'
702
+ const maxScriptCommandsPerPack = Math.max(
703
+ 0,
704
+ Number.parseInt(readArg('--max-script-commands-per-pack', '80'), 10) || 80,
705
+ )
706
+ let rules = []
707
+ try {
708
+ const parsed = JSON.parse(rulesRaw)
709
+ if (Array.isArray(parsed)) rules = parsed
710
+ } catch (err) {
711
+ console.warn('[agent-pack] Ignoring invalid slash command rules JSON: ' + err.message)
712
+ }
713
+
714
+ const options = {
715
+ inferInteractions,
716
+ includeScripts,
717
+ generateScriptSkills,
718
+ maxScriptCommandsPerPack,
719
+ rules,
720
+ mountPath,
721
+ }
722
+ generateScriptSkillWrappers(mountPath, options)
723
+
724
+ const seenCommands = new Set()
725
+ const commands = [
726
+ ...discoverSlashCommands(commandDirsFromMountRoot(mountPath), options),
727
+ ...discoverScriptCommands(mountPath, options),
728
+ ].filter((command) => {
729
+ const key = command.name.toLowerCase()
730
+ if (seenCommands.has(key)) return false
731
+ seenCommands.add(key)
732
+ return true
733
+ }).slice(0, 200)
734
+ mkdirSync(dirname(output), { recursive: true })
735
+ writeFileSync(output, JSON.stringify(commands, null, 2), 'utf-8')
736
+ console.log('[agent-pack] Wrote ' + commands.length + ' slash command(s) to ' + output)
737
+ `;
738
+
739
+ export {
740
+ AGENT_PACK_SLASH_INDEXER_SCRIPT
741
+ };