@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,739 @@
1
+ // src/plugins/agent-pack/indexer-script.ts
2
+ var AGENT_PACK_SLASH_INDEXER_SCRIPT = String.raw`
3
+ import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
4
+ import { basename, dirname, extname, join, relative } from 'node:path'
5
+
6
+ function readArg(name, fallback) {
7
+ const idx = process.argv.indexOf(name)
8
+ return idx >= 0 && process.argv[idx + 1] ? process.argv[idx + 1] : fallback
9
+ }
10
+
11
+ function listChildDirs(dir) {
12
+ try {
13
+ return readdirSync(dir, { withFileTypes: true })
14
+ .filter((d) => d.isDirectory())
15
+ .map((d) => join(dir, d.name))
16
+ } catch {
17
+ return []
18
+ }
19
+ }
20
+
21
+ function listFiles(dir, suffix) {
22
+ try {
23
+ return readdirSync(dir, { withFileTypes: true })
24
+ .filter((d) => d.isFile() && d.name.endsWith(suffix))
25
+ .map((d) => join(dir, d.name))
26
+ } catch {
27
+ return []
28
+ }
29
+ }
30
+
31
+ function listFilesRecursive(dir, maxDepth, depth = 0) {
32
+ if (depth > maxDepth) return []
33
+ try {
34
+ const entries = readdirSync(dir, { withFileTypes: true })
35
+ const out = []
36
+ for (const entry of entries) {
37
+ if (entry.name.startsWith('.')) continue
38
+ const path = join(dir, entry.name)
39
+ if (entry.isDirectory()) {
40
+ if (['node_modules', 'dist', 'build', 'vendor', 'coverage', '__pycache__'].includes(entry.name)) {
41
+ continue
42
+ }
43
+ out.push(...listFilesRecursive(path, maxDepth, depth + 1))
44
+ } else if (entry.isFile()) {
45
+ out.push(path)
46
+ }
47
+ }
48
+ return out
49
+ } catch {
50
+ return []
51
+ }
52
+ }
53
+
54
+ function readMaybe(path) {
55
+ try {
56
+ return readFileSync(path, 'utf-8')
57
+ } catch {
58
+ return ''
59
+ }
60
+ }
61
+
62
+ function normalizeSlashCommandName(value) {
63
+ if (typeof value !== 'string') return null
64
+ const name = value.trim().replace(/^\/+/, '')
65
+ return /^[a-zA-Z][a-zA-Z0-9._-]{0,63}$/.test(name) ? name : null
66
+ }
67
+
68
+ function parseFrontmatterList(value) {
69
+ if (typeof value !== 'string') return []
70
+ const trimmed = value.trim()
71
+ const unwrapped =
72
+ trimmed.startsWith('[') && trimmed.endsWith(']') ? trimmed.slice(1, -1) : trimmed
73
+ return unwrapped
74
+ .split(',')
75
+ .map((item) => item.trim().replace(/^['"]|['"]$/g, ''))
76
+ .filter(Boolean)
77
+ }
78
+
79
+ function parseFrontmatter(text) {
80
+ if (!text.startsWith('---')) return { data: {}, body: text }
81
+ const end = text.indexOf('\n---', 3)
82
+ if (end === -1) return { data: {}, body: text }
83
+
84
+ const raw = text.slice(3, end).trim()
85
+ const data = {}
86
+ const lines = raw.split('\n')
87
+ for (let i = 0; i < lines.length; i++) {
88
+ const line = lines[i]
89
+ const match = line.match(/^([a-zA-Z0-9_.-]+):\s*(.*)$/)
90
+ if (!match) continue
91
+ const key = match[1]
92
+ const value = match[2].trim().replace(/^['"]|['"]$/g, '')
93
+
94
+ if (value === '|') {
95
+ const block = []
96
+ while (i + 1 < lines.length) {
97
+ const next = lines[i + 1]
98
+ if (next && !/^\s/.test(next)) break
99
+ block.push(next.replace(/^\s{2}/, ''))
100
+ i++
101
+ }
102
+ data[key] = block.join('\n').trim()
103
+ continue
104
+ }
105
+
106
+ if (value) {
107
+ data[key] = value
108
+ continue
109
+ }
110
+
111
+ const items = []
112
+ while (i + 1 < lines.length) {
113
+ const itemMatch = lines[i + 1].match(/^\s*-\s*(.+)$/)
114
+ if (!itemMatch) break
115
+ items.push(itemMatch[1].trim().replace(/^['"]|['"]$/g, ''))
116
+ i++
117
+ }
118
+ data[key] = items.length > 0 ? items.join(',') : value
119
+ }
120
+
121
+ return { data, body: text.slice(end + 4).trimStart() }
122
+ }
123
+
124
+ function parseFrontmatterJson(value) {
125
+ if (typeof value !== 'string') return undefined
126
+ const trimmed = value.trim()
127
+ if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return undefined
128
+ try {
129
+ return JSON.parse(trimmed)
130
+ } catch {
131
+ return undefined
132
+ }
133
+ }
134
+
135
+ function normalizeInteractionItems(value, max) {
136
+ if (!Array.isArray(value)) return undefined
137
+ const items = value
138
+ .filter((item) => item && typeof item === 'object' && !Array.isArray(item))
139
+ .map((item, index) => {
140
+ const label =
141
+ typeof item.label === 'string' && item.label.trim()
142
+ ? item.label.trim()
143
+ : typeof item.value === 'string' && item.value.trim()
144
+ ? item.value.trim()
145
+ : 'Option ' + (index + 1)
146
+ const id =
147
+ typeof item.id === 'string' && item.id.trim()
148
+ ? item.id.trim()
149
+ : typeof item.value === 'string' && item.value.trim()
150
+ ? item.value.trim()
151
+ : label
152
+ return {
153
+ id,
154
+ label,
155
+ ...(typeof item.value === 'string' && item.value.trim()
156
+ ? { value: item.value.trim() }
157
+ : {}),
158
+ ...(item.style === 'primary' || item.style === 'secondary' || item.style === 'destructive'
159
+ ? { style: item.style }
160
+ : {}),
161
+ }
162
+ })
163
+ .filter((item) => item.id && item.label)
164
+ return items.length > 0 ? items.slice(0, max) : undefined
165
+ }
166
+
167
+ function normalizeSlashInteraction(value) {
168
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
169
+ const kind = typeof value.kind === 'string' ? value.kind.trim().toLowerCase() : ''
170
+ if (!['buttons', 'select', 'form', 'approval'].includes(kind)) return undefined
171
+
172
+ const out = { kind }
173
+ for (const key of ['id', 'prompt', 'submitLabel', 'responsePrompt', 'approvalCommentLabel']) {
174
+ if (typeof value[key] === 'string' && value[key].trim()) out[key] = value[key].trim()
175
+ }
176
+ if (typeof value.oneShot === 'boolean') out.oneShot = value.oneShot
177
+
178
+ const buttons = normalizeInteractionItems(value.buttons, 8)
179
+ const options = normalizeInteractionItems(value.options, 20)?.map((option) => ({
180
+ id: option.id,
181
+ label: option.label,
182
+ value: option.value ?? option.id,
183
+ }))
184
+ if (buttons) out.buttons = buttons
185
+ if (options) out.options = options
186
+
187
+ if (Array.isArray(value.fields)) {
188
+ out.fields = value.fields
189
+ .filter((field) => field && typeof field === 'object' && !Array.isArray(field))
190
+ .map((field, index) => ({
191
+ id:
192
+ typeof field.id === 'string' && field.id.trim() ? field.id.trim() : 'field_' + (index + 1),
193
+ kind:
194
+ typeof field.kind === 'string' &&
195
+ ['text', 'textarea', 'number', 'checkbox', 'select'].includes(field.kind)
196
+ ? field.kind
197
+ : 'text',
198
+ label:
199
+ typeof field.label === 'string' && field.label.trim()
200
+ ? field.label.trim()
201
+ : 'Field ' + (index + 1),
202
+ ...(typeof field.placeholder === 'string' && field.placeholder.trim()
203
+ ? { placeholder: field.placeholder.trim() }
204
+ : {}),
205
+ ...(typeof field.defaultValue === 'string' ? { defaultValue: field.defaultValue } : {}),
206
+ ...(typeof field.required === 'boolean' ? { required: field.required } : {}),
207
+ ...(typeof field.maxLength === 'number' ? { maxLength: field.maxLength } : {}),
208
+ ...(typeof field.min === 'number' ? { min: field.min } : {}),
209
+ ...(typeof field.max === 'number' ? { max: field.max } : {}),
210
+ }))
211
+ .slice(0, 12)
212
+ }
213
+
214
+ return out
215
+ }
216
+
217
+ function frontmatterInteraction(data) {
218
+ const direct = normalizeSlashInteraction(
219
+ parseFrontmatterJson(data.interaction) ?? parseFrontmatterJson(data.interactive),
220
+ )
221
+ if (direct) return direct
222
+
223
+ const kind = data['interaction.kind'] ?? data['interactive.kind']
224
+ if (!kind) return undefined
225
+ const oneShotRaw = data['interaction.oneShot'] ?? data['interactive.oneShot']
226
+ return normalizeSlashInteraction({
227
+ kind,
228
+ id: data['interaction.id'] ?? data['interactive.id'],
229
+ prompt: data['interaction.prompt'] ?? data['interactive.prompt'],
230
+ submitLabel: data['interaction.submitLabel'] ?? data['interactive.submitLabel'],
231
+ responsePrompt: data['interaction.responsePrompt'] ?? data['interactive.responsePrompt'],
232
+ approvalCommentLabel:
233
+ data['interaction.approvalCommentLabel'] ?? data['interactive.approvalCommentLabel'],
234
+ ...(oneShotRaw !== undefined ? { oneShot: oneShotRaw === 'true' } : {}),
235
+ buttons: parseFrontmatterJson(data['interaction.buttons'] ?? data['interactive.buttons']),
236
+ options: parseFrontmatterJson(data['interaction.options'] ?? data['interactive.options']),
237
+ fields: parseFrontmatterJson(data['interaction.fields'] ?? data['interactive.fields']),
238
+ })
239
+ }
240
+
241
+ function derivePackId(path, mountPath) {
242
+ const mountParts = mountPath.split('/').filter(Boolean)
243
+ const parts = path.split('/').filter(Boolean)
244
+ if (mountParts.length > 0) {
245
+ for (let i = 0; i <= parts.length - mountParts.length - 1; i++) {
246
+ let matches = true
247
+ for (let j = 0; j < mountParts.length; j++) {
248
+ if (parts[i + j] !== mountParts[j]) {
249
+ matches = false
250
+ break
251
+ }
252
+ }
253
+ if (matches && parts[i + mountParts.length]) return parts[i + mountParts.length]
254
+ }
255
+ }
256
+
257
+ const idx = parts.lastIndexOf('agent-packs')
258
+ if (idx >= 0 && parts[idx + 1]) return parts[idx + 1]
259
+ return undefined
260
+ }
261
+
262
+ function deriveSlashDescription(body, frontmatter) {
263
+ const fmDescription =
264
+ typeof frontmatter.description === 'string' ? frontmatter.description.trim() : ''
265
+ if (fmDescription) return fmDescription.slice(0, 240)
266
+
267
+ for (const line of body.split('\n')) {
268
+ const text = line.replace(/^#+\s*/, '').trim()
269
+ if (text) return text.slice(0, 240)
270
+ }
271
+ return undefined
272
+ }
273
+
274
+ function asStringArray(value) {
275
+ if (typeof value === 'string') return [value]
276
+ return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : []
277
+ }
278
+
279
+ function matchesSlashCommandRule(rule, command, context) {
280
+ const match = rule.match
281
+ if (!match || typeof match !== 'object') return true
282
+ if (typeof match.packId === 'string' && match.packId !== context.packId) return false
283
+
284
+ const names = [...asStringArray(match.name), ...asStringArray(match.names)]
285
+ if (
286
+ names.length > 0 &&
287
+ !names.some((name) => name.toLowerCase() === command.name.toLowerCase())
288
+ ) {
289
+ return false
290
+ }
291
+
292
+ if (typeof match.namePattern === 'string' && match.namePattern.trim()) {
293
+ try {
294
+ if (!new RegExp(match.namePattern).test(command.name)) return false
295
+ } catch (err) {
296
+ console.warn('[agent-pack] Ignoring invalid slash command rule pattern: ' + err.message)
297
+ return false
298
+ }
299
+ }
300
+
301
+ const pathIncludes = asStringArray(match.sourcePathIncludes)
302
+ return pathIncludes.length === 0 || pathIncludes.some((needle) => context.path.includes(needle))
303
+ }
304
+
305
+ function applySlashCommandRules(command, context, rules) {
306
+ for (const rule of rules) {
307
+ if (!matchesSlashCommandRule(rule, command, context)) continue
308
+
309
+ const aliases = asStringArray(rule.aliases)
310
+ .map(normalizeSlashCommandName)
311
+ .filter(Boolean)
312
+ .filter((alias) => alias.toLowerCase() !== command.name.toLowerCase())
313
+ if (aliases.length > 0) {
314
+ command.aliases = [...new Set([...(command.aliases ?? []), ...aliases])]
315
+ }
316
+
317
+ const interaction = normalizeSlashInteraction(rule.interaction)
318
+ if (interaction && !command.interaction) command.interaction = interaction
319
+ }
320
+
321
+ return command
322
+ }
323
+
324
+ function stripMarkdownInline(value) {
325
+ return value
326
+ .replace(new RegExp('[' + String.fromCharCode(96) + '*_~]', 'g'), '')
327
+ .replace(/\s+/g, ' ')
328
+ .trim()
329
+ }
330
+
331
+ function extractAskLine(block) {
332
+ const quoted = block.match(/\*\*Ask:\*\*\s*"([\s\S]*?)"/)
333
+ if (quoted?.[1]) return stripMarkdownInline(quoted[1])
334
+
335
+ const line = block.match(/\*\*Ask:\*\*\s*(.+)/)
336
+ if (line?.[1]) return stripMarkdownInline(line[1].replace(/^"|"$/g, ''))
337
+
338
+ return ''
339
+ }
340
+
341
+ function slugifyFieldId(value, fallback) {
342
+ const slug = value
343
+ .toLowerCase()
344
+ .replace(/[^a-z0-9]+/g, '_')
345
+ .replace(/^_+|_+$/g, '')
346
+ .slice(0, 64)
347
+ return slug || fallback
348
+ }
349
+
350
+ function deriveAskFieldsFromMarkdown(markdown) {
351
+ const questionHeadingRegex = /^#{2,6}\s+Q(\d+)\s*:\s*(.+?)\s*$/gm
352
+ const matches = [...markdown.matchAll(questionHeadingRegex)]
353
+ const fields = []
354
+
355
+ for (let i = 0; i < matches.length && fields.length < 12; i++) {
356
+ const current = matches[i]
357
+ const next = matches[i + 1]
358
+ const qNumber = current[1]
359
+ const title = stripMarkdownInline(current[2] ?? 'Question ' + (fields.length + 1))
360
+ const blockStart = (current.index ?? 0) + current[0].length
361
+ const blockEnd = next?.index ?? markdown.length
362
+ const ask = extractAskLine(markdown.slice(blockStart, blockEnd))
363
+ if (!ask) continue
364
+ fields.push({
365
+ id: slugifyFieldId('q' + qNumber + '_' + title, 'q' + (fields.length + 1)),
366
+ kind: 'textarea',
367
+ label: 'Q' + qNumber + ': ' + title,
368
+ placeholder: ask,
369
+ required: true,
370
+ maxLength: 2000,
371
+ })
372
+ }
373
+
374
+ if (fields.length > 0) return fields
375
+
376
+ const askLines = [...markdown.matchAll(/\*\*Ask:\*\*\s*"?(.+?)"?\s*$/gm)]
377
+ for (let i = 0; i < askLines.length && fields.length < 12; i++) {
378
+ const ask = stripMarkdownInline(askLines[i][1] ?? '')
379
+ if (!ask) continue
380
+ fields.push({
381
+ id: 'q' + (i + 1),
382
+ kind: 'textarea',
383
+ label: 'Q' + (i + 1),
384
+ placeholder: ask,
385
+ required: true,
386
+ maxLength: 2000,
387
+ })
388
+ }
389
+
390
+ return fields
391
+ }
392
+
393
+ function inferInteractionFromMarkdown(command, inferInteractions) {
394
+ if (!inferInteractions || !command.body) return undefined
395
+ const fields = deriveAskFieldsFromMarkdown(command.body)
396
+ if (fields.length < 2) return undefined
397
+
398
+ return {
399
+ id: 'slash:' + (command.packId ?? 'pack') + ':' + command.name + ':auto-form',
400
+ kind: 'form',
401
+ prompt:
402
+ command.description ?? '/' + command.name + ' needs a few answers before the Buddy can continue.',
403
+ oneShot: true,
404
+ responsePrompt:
405
+ '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.',
406
+ fields,
407
+ }
408
+ }
409
+
410
+ function deriveAliasCandidates(name, packId) {
411
+ const candidates = new Set()
412
+ let base = name
413
+
414
+ if (packId && base.startsWith(packId + '-')) {
415
+ base = base.slice(packId.length + 1)
416
+ if (normalizeSlashCommandName(base)) candidates.add(base)
417
+ }
418
+
419
+ for (const prefix of ['openclaw-', 'claude-', 'claude-code-', 'codex-', 'cursor-']) {
420
+ if (base.startsWith(prefix)) {
421
+ const stripped = base.slice(prefix.length)
422
+ if (normalizeSlashCommandName(stripped)) candidates.add(stripped)
423
+ }
424
+ }
425
+
426
+ for (const candidate of [...candidates]) {
427
+ if (candidate.endsWith('-hours')) candidates.add(candidate.replace(/-hours$/, '-hour'))
428
+ }
429
+
430
+ return [...candidates].filter((alias) => alias.toLowerCase() !== name.toLowerCase())
431
+ }
432
+
433
+ function addInferredAliases(command, context) {
434
+ const aliases = new Set(command.aliases ?? [])
435
+ for (const alias of deriveAliasCandidates(command.name, context.packId)) aliases.add(alias)
436
+ if (aliases.size > 0) command.aliases = [...aliases]
437
+ return command
438
+ }
439
+
440
+ const SCRIPT_EXTENSIONS = new Set(['', '.sh', '.bash', '.js', '.mjs', '.cjs', '.py', '.rb', '.pl'])
441
+ const SCRIPT_EXCLUDED_EXTENSIONS = new Set([
442
+ '.ts',
443
+ '.tsx',
444
+ '.json',
445
+ '.md',
446
+ '.mdx',
447
+ '.txt',
448
+ '.png',
449
+ '.jpg',
450
+ '.jpeg',
451
+ '.gif',
452
+ '.svg',
453
+ '.icns',
454
+ '.map',
455
+ '.lock',
456
+ ])
457
+ const SCRIPT_EXCLUDED_NAMES = new Set([
458
+ 'package.json',
459
+ 'package-lock.json',
460
+ 'pnpm-lock.yaml',
461
+ 'yarn.lock',
462
+ 'bun.lockb',
463
+ ])
464
+
465
+ function readScriptHead(path) {
466
+ try {
467
+ return readFileSync(path, 'utf-8').slice(0, 12000)
468
+ } catch {
469
+ return ''
470
+ }
471
+ }
472
+
473
+ function isLikelyScript(path) {
474
+ const name = basename(path)
475
+ if (!name || name.startsWith('.') || SCRIPT_EXCLUDED_NAMES.has(name)) return false
476
+ const ext = extname(name).toLowerCase()
477
+ if (SCRIPT_EXCLUDED_EXTENSIONS.has(ext)) return false
478
+ if (!SCRIPT_EXTENSIONS.has(ext)) return false
479
+
480
+ try {
481
+ const stat = statSync(path)
482
+ if (!stat.isFile() || stat.size <= 0 || stat.size > 512 * 1024) return false
483
+ } catch {
484
+ return false
485
+ }
486
+
487
+ if (ext === '') return true
488
+ const head = readScriptHead(path)
489
+ return head.startsWith('#!') || /(^|\n)\s*(Usage:|USAGE:|export\s+default|if\s+\(__name__\s*==)/.test(head)
490
+ }
491
+
492
+ function commandNameFromScriptPath(path) {
493
+ const ext = extname(path)
494
+ const raw = ext ? basename(path, ext) : basename(path)
495
+ const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '')
496
+ return normalizeSlashCommandName(normalized)
497
+ }
498
+
499
+ function deriveScriptDescription(path, packId) {
500
+ const head = readScriptHead(path)
501
+ const lines = head.split('\n').slice(0, 60)
502
+ for (const rawLine of lines) {
503
+ const line = rawLine
504
+ .replace(/^#!.*$/, '')
505
+ .replace(/^\s*(#|\/\/)\s?/, '')
506
+ .trim()
507
+ if (!line) continue
508
+ if (/^(usage|env overrides?|set -|shellcheck|eslint|biome)/i.test(line)) continue
509
+ return stripMarkdownInline(line).slice(0, 180)
510
+ }
511
+ return 'Run a helper script from the ' + packId + ' agent pack.'
512
+ }
513
+
514
+ function scriptSkillMarkdown(params) {
515
+ const rel = params.relPath
516
+ const description = params.description
517
+ const path = params.path
518
+ return [
519
+ '---',
520
+ 'name: ' + JSON.stringify(params.name),
521
+ 'description: ' + JSON.stringify(description),
522
+ '---',
523
+ '',
524
+ '# ' + params.name,
525
+ '',
526
+ 'This capability is backed by a mounted helper script from the ' + params.packId + ' agent pack.',
527
+ '',
528
+ '- Script path: ' + path,
529
+ '- Pack script: ' + rel,
530
+ '',
531
+ 'When this skill is relevant:',
532
+ '',
533
+ '1. Inspect usage first by running the script with --help, or read the script if help is not supported.',
534
+ '2. Run the script with explicit user-provided arguments, using the absolute script path above.',
535
+ '3. Summarize stdout, stderr, exit status, and any files created or changed.',
536
+ '4. For destructive, credentialed, long-running, or network-heavy actions, explain the exact action before running it unless the user explicitly requested that action.',
537
+ ].join('\n')
538
+ }
539
+
540
+ function discoverPackDirs(mountPath) {
541
+ return listChildDirs(mountPath).filter((packDir) => !packDir.endsWith('/.shadow'))
542
+ }
543
+
544
+ function discoverPackScripts(packDir, maxPerPack) {
545
+ const scriptsDir = join(packDir, 'scripts')
546
+ if (!existsSync(scriptsDir)) return []
547
+ const seenNames = new Set()
548
+ const scripts = []
549
+ for (const path of listFilesRecursive(scriptsDir, 4)) {
550
+ if (!isLikelyScript(path)) continue
551
+ const name = commandNameFromScriptPath(path)
552
+ if (!name || seenNames.has(name.toLowerCase())) continue
553
+ seenNames.add(name.toLowerCase())
554
+ scripts.push({
555
+ name,
556
+ path,
557
+ relPath: relative(scriptsDir, path),
558
+ })
559
+ if (scripts.length >= maxPerPack) break
560
+ }
561
+ return scripts
562
+ }
563
+
564
+ function generateScriptSkillWrappers(mountPath, options) {
565
+ if (!options.includeScripts || !options.generateScriptSkills) return
566
+ for (const packDir of discoverPackDirs(mountPath)) {
567
+ const packId = basename(packDir)
568
+ const skillsDir = join(packDir, 'skills')
569
+ mkdirSync(skillsDir, { recursive: true })
570
+
571
+ for (const script of discoverPackScripts(packDir, options.maxScriptCommandsPerPack)) {
572
+ const skillDir = join(skillsDir, script.name)
573
+ const skillPath = join(skillDir, 'SKILL.md')
574
+ if (existsSync(skillPath)) continue
575
+ const description = deriveScriptDescription(script.path, packId)
576
+ mkdirSync(skillDir, { recursive: true })
577
+ writeFileSync(
578
+ skillPath,
579
+ scriptSkillMarkdown({
580
+ ...script,
581
+ packId,
582
+ description,
583
+ }),
584
+ 'utf-8',
585
+ )
586
+ }
587
+ }
588
+ }
589
+
590
+ function discoverScriptCommands(mountPath, options) {
591
+ if (!options.includeScripts) return []
592
+ const commands = []
593
+ for (const packDir of discoverPackDirs(mountPath)) {
594
+ const packId = basename(packDir)
595
+ for (const script of discoverPackScripts(packDir, options.maxScriptCommandsPerPack)) {
596
+ const description = deriveScriptDescription(script.path, packId)
597
+ commands.push({
598
+ name: script.name,
599
+ description,
600
+ packId,
601
+ sourcePath: script.path,
602
+ body: scriptSkillMarkdown({
603
+ ...script,
604
+ packId,
605
+ description,
606
+ }),
607
+ })
608
+ }
609
+ }
610
+ return commands
611
+ }
612
+
613
+ function readSlashCommand(path, fallbackName, options) {
614
+ const text = readMaybe(path).trim()
615
+ if (!text) return null
616
+ const { data, body } = parseFrontmatter(text)
617
+ const name = normalizeSlashCommandName(data.name ?? fallbackName)
618
+ if (!name) return null
619
+ const packId = derivePackId(path, options.mountPath)
620
+ const aliases = parseFrontmatterList(data.aliases)
621
+ .map(normalizeSlashCommandName)
622
+ .filter(Boolean)
623
+ .filter((alias) => alias.toLowerCase() !== name.toLowerCase())
624
+ const description = deriveSlashDescription(body, data)
625
+ const interaction = frontmatterInteraction(data)
626
+
627
+ let command = {
628
+ name,
629
+ ...(description ? { description } : {}),
630
+ ...(aliases.length > 0 ? { aliases: [...new Set(aliases)] } : {}),
631
+ ...(packId ? { packId } : {}),
632
+ ...(interaction ? { interaction } : {}),
633
+ sourcePath: path,
634
+ body: text.slice(0, 20000),
635
+ }
636
+
637
+ const context = { path, packId, body, frontmatter: data }
638
+ command = addInferredAliases(command, context)
639
+ command = applySlashCommandRules(command, context, options.rules)
640
+
641
+ if (!command.interaction) {
642
+ const inferred = inferInteractionFromMarkdown(command, options.inferInteractions)
643
+ if (inferred) command.interaction = inferred
644
+ }
645
+
646
+ return command
647
+ }
648
+
649
+ function discoverSlashCommands(commandsDirs, options) {
650
+ const commands = []
651
+ const seen = new Set()
652
+ for (const dir of commandsDirs) {
653
+ for (const file of listFiles(dir, '.md')) {
654
+ const fallbackName = file.split('/').pop().replace(/\.md$/, '')
655
+ const command = readSlashCommand(file, fallbackName, options)
656
+ if (!command) continue
657
+ const key = command.name.toLowerCase()
658
+ if (seen.has(key)) continue
659
+ seen.add(key)
660
+ commands.push(command)
661
+ }
662
+
663
+ for (const childDir of listChildDirs(dir)) {
664
+ const fallbackName = childDir.split('/').pop()
665
+ for (const candidate of ['SKILL.md', 'COMMAND.md', 'README.md']) {
666
+ const path = join(childDir, candidate)
667
+ if (!existsSync(path)) continue
668
+ const command = readSlashCommand(path, fallbackName, options)
669
+ if (!command) break
670
+ const key = command.name.toLowerCase()
671
+ if (!seen.has(key)) {
672
+ seen.add(key)
673
+ commands.push(command)
674
+ }
675
+ break
676
+ }
677
+ }
678
+ }
679
+ return commands.slice(0, 200)
680
+ }
681
+
682
+ function commandDirsFromMountRoot(mountPath) {
683
+ const dirs = []
684
+ for (const packDir of listChildDirs(mountPath)) {
685
+ if (packDir.endsWith('/.shadow')) continue
686
+ for (const kind of ['commands', 'skills']) {
687
+ const dir = join(packDir, kind)
688
+ if (existsSync(dir)) dirs.push(dir)
689
+ }
690
+ }
691
+ return [...new Set(dirs)]
692
+ }
693
+
694
+ const mountPath = readArg('--mount-path', '/agent-packs')
695
+ const output = readArg('--output', mountPath + '/.shadow/slash-commands.json')
696
+ const rulesRaw = readArg('--rules-json', '[]')
697
+ const inferInteractions = readArg('--infer-interactions', 'true') !== 'false'
698
+ const includeScripts = readArg('--include-scripts', 'true') !== 'false'
699
+ const generateScriptSkills = readArg('--generate-script-skills', 'true') !== 'false'
700
+ const maxScriptCommandsPerPack = Math.max(
701
+ 0,
702
+ Number.parseInt(readArg('--max-script-commands-per-pack', '80'), 10) || 80,
703
+ )
704
+ let rules = []
705
+ try {
706
+ const parsed = JSON.parse(rulesRaw)
707
+ if (Array.isArray(parsed)) rules = parsed
708
+ } catch (err) {
709
+ console.warn('[agent-pack] Ignoring invalid slash command rules JSON: ' + err.message)
710
+ }
711
+
712
+ const options = {
713
+ inferInteractions,
714
+ includeScripts,
715
+ generateScriptSkills,
716
+ maxScriptCommandsPerPack,
717
+ rules,
718
+ mountPath,
719
+ }
720
+ generateScriptSkillWrappers(mountPath, options)
721
+
722
+ const seenCommands = new Set()
723
+ const commands = [
724
+ ...discoverSlashCommands(commandDirsFromMountRoot(mountPath), options),
725
+ ...discoverScriptCommands(mountPath, options),
726
+ ].filter((command) => {
727
+ const key = command.name.toLowerCase()
728
+ if (seenCommands.has(key)) return false
729
+ seenCommands.add(key)
730
+ return true
731
+ }).slice(0, 200)
732
+ mkdirSync(dirname(output), { recursive: true })
733
+ writeFileSync(output, JSON.stringify(commands, null, 2), 'utf-8')
734
+ console.log('[agent-pack] Wrote ' + commands.length + ' slash command(s) to ' + output)
735
+ `;
736
+
737
+ export {
738
+ AGENT_PACK_SLASH_INDEXER_SCRIPT
739
+ };