@hasna/skills 0.1.26 → 0.1.29

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 (491) hide show
  1. package/LICENSE +1 -10
  2. package/README.md +141 -39
  3. package/bin/index.js +30122 -27575
  4. package/bin/mcp.js +22112 -18593
  5. package/dist/cli/cli.test-utils.d.ts +15 -0
  6. package/dist/cli/commands/auth.d.ts +2 -0
  7. package/dist/cli/commands/install.d.ts +1 -1
  8. package/dist/cli/commands/runtime-mcp.d.ts +4 -0
  9. package/dist/index.d.ts +9 -4
  10. package/dist/index.js +11607 -597
  11. package/dist/lib/auth-store.d.ts +13 -0
  12. package/dist/lib/installer.d.ts +58 -55
  13. package/dist/lib/mcp-contracts.d.ts +86 -0
  14. package/dist/lib/project-state.d.ts +43 -0
  15. package/dist/lib/registry-data/business-marketing.d.ts +2 -0
  16. package/dist/lib/registry-data/communication.d.ts +2 -0
  17. package/dist/lib/registry-data/content-generation.d.ts +2 -0
  18. package/dist/lib/registry-data/data-analysis.d.ts +2 -0
  19. package/dist/lib/registry-data/design-branding.d.ts +2 -0
  20. package/dist/lib/registry-data/development-tools.d.ts +2 -0
  21. package/dist/lib/registry-data/education-learning.d.ts +2 -0
  22. package/dist/lib/registry-data/event-management.d.ts +2 -0
  23. package/dist/lib/registry-data/finance-compliance.d.ts +2 -0
  24. package/dist/lib/registry-data/health-wellness.d.ts +2 -0
  25. package/dist/lib/registry-data/index.d.ts +2 -0
  26. package/dist/lib/registry-data/media-processing.d.ts +2 -0
  27. package/dist/lib/registry-data/productivity-organization.d.ts +2 -0
  28. package/dist/lib/registry-data/project-management.d.ts +2 -0
  29. package/dist/lib/registry-data/research-writing.d.ts +2 -0
  30. package/dist/lib/registry-data/science-academic.d.ts +2 -0
  31. package/dist/lib/registry-data/travel-lifestyle.d.ts +2 -0
  32. package/dist/lib/registry-data/web-browser.d.ts +2 -0
  33. package/dist/lib/registry-types.d.ts +27 -0
  34. package/dist/lib/registry.d.ts +6 -18
  35. package/dist/lib/remote-registry.d.ts +3 -0
  36. package/dist/lib/run-state.d.ts +60 -0
  37. package/dist/lib/skill-aliases.d.ts +17 -0
  38. package/dist/lib/skillinfo.d.ts +5 -1
  39. package/dist/mcp/discovery-tools.d.ts +2 -0
  40. package/dist/mcp/helpers.d.ts +26 -0
  41. package/dist/mcp/http.d.ts +10 -0
  42. package/dist/mcp/index.d.ts +3 -2
  43. package/dist/mcp/operation-tools.d.ts +2 -0
  44. package/dist/mcp/resource-meta-tools.d.ts +2 -0
  45. package/dist/mcp/schedule-tools.d.ts +2 -0
  46. package/dist/mcp/server.d.ts +4 -0
  47. package/dist/types/api.d.ts +7 -4
  48. package/package.json +23 -10
  49. package/skills/_common/http-client.ts +1 -1
  50. package/skills/_common/index.ts +2 -3
  51. package/skills/_common/install.sh +5 -110
  52. package/skills/_common/installer.ts +31 -282
  53. package/skills/_common/skill-install.ts +14 -181
  54. package/skills/ad-creative-pack/SKILL.md +45 -0
  55. package/skills/ad-creative-pack/package.json +14 -0
  56. package/skills/advanced-math/package.json +3 -1
  57. package/skills/advanced-math/src/calculators.ts +118 -0
  58. package/skills/advanced-math/src/cli.ts +130 -0
  59. package/skills/advanced-math/src/conversion.ts +90 -0
  60. package/skills/advanced-math/src/finance.ts +75 -0
  61. package/skills/advanced-math/src/formatting.ts +95 -0
  62. package/skills/advanced-math/src/index.ts +24 -702
  63. package/skills/advanced-math/src/runtime.ts +49 -0
  64. package/skills/advanced-math/src/symbolic.ts +110 -0
  65. package/skills/advanced-math/src/types.ts +36 -0
  66. package/skills/analyze-data/SKILL.md +2 -2
  67. package/skills/analyze-data/src/analysis.ts +401 -0
  68. package/skills/analyze-data/src/cli.ts +66 -0
  69. package/skills/analyze-data/src/formatters.ts +235 -0
  70. package/skills/analyze-data/src/index.ts +6 -1027
  71. package/skills/analyze-data/src/logger.ts +36 -0
  72. package/skills/analyze-data/src/parsers.ts +57 -0
  73. package/skills/analyze-data/src/stats.ts +151 -0
  74. package/skills/analyze-data/src/types.ts +85 -0
  75. package/skills/api-docs-portal/SKILL.md +46 -0
  76. package/skills/api-docs-portal/package.json +9 -0
  77. package/skills/api-test-suite/src/index.ts +13 -0
  78. package/skills/apidocs/package.json +1 -1
  79. package/skills/apidocs/src/index.ts +3 -0
  80. package/skills/audio/package.json +2 -3
  81. package/skills/audio-cleanup-lab/SKILL.md +2 -2
  82. package/skills/audio-extract/CLAUDE.md +1 -1
  83. package/skills/audio-transcript-pack/SKILL.md +43 -0
  84. package/skills/audio-transcript-pack/package.json +10 -0
  85. package/skills/blog-article/CLAUDE.md +12 -0
  86. package/skills/blog-article/SKILL.md +45 -0
  87. package/skills/{create-blog-article → blog-article}/package.json +3 -3
  88. package/skills/brand-kit/SKILL.md +45 -0
  89. package/skills/brand-kit/package.json +14 -0
  90. package/skills/brand-photo-shoot/SKILL.md +28 -0
  91. package/skills/brand-photo-shoot/package.json +10 -0
  92. package/skills/brand-style-guide/SKILL.md +2 -2
  93. package/skills/brand-style-guide/src/index.ts +0 -0
  94. package/skills/budget-variance-analyzer/SKILL.md +2 -2
  95. package/skills/businessactivity/package.json +1 -1
  96. package/skills/businessactivity/src/index.ts +3 -0
  97. package/skills/calendar-events/src/ai-parser.ts +103 -0
  98. package/skills/calendar-events/src/api.ts +157 -0
  99. package/skills/calendar-events/src/auth.ts +22 -0
  100. package/skills/calendar-events/src/config.ts +6 -0
  101. package/skills/calendar-events/src/format.ts +96 -0
  102. package/skills/calendar-events/src/help.ts +54 -0
  103. package/skills/calendar-events/src/index.ts +21 -524
  104. package/skills/calendar-events/src/logger.ts +34 -0
  105. package/skills/calendar-events/src/types.ts +67 -0
  106. package/skills/compress-video/SKILL.md +2 -2
  107. package/skills/consolelog/package.json +1 -1
  108. package/skills/consolelog/src/index.ts +3 -0
  109. package/skills/contract-review-report/SKILL.md +43 -0
  110. package/skills/contract-review-report/package.json +10 -0
  111. package/skills/convert/SKILL.md +2 -3
  112. package/skills/customer-feedback-report/SKILL.md +44 -0
  113. package/skills/customer-feedback-report/package.json +10 -0
  114. package/skills/dashboard-builder/package.json +3 -1
  115. package/skills/database-explorer/package.json +3 -1
  116. package/skills/deepresearch/README.md +4 -13
  117. package/skills/deploy/src/http-client.ts +1 -1
  118. package/skills/diff-viewer/package.json +4 -1
  119. package/skills/doc-generate/package.json +0 -1
  120. package/skills/doc-generate/src/ai.ts +50 -0
  121. package/skills/doc-generate/src/cli.ts +203 -0
  122. package/skills/doc-generate/src/dependencies.ts +44 -0
  123. package/skills/doc-generate/src/document-builder.ts +299 -0
  124. package/skills/doc-generate/src/index.ts +40 -764
  125. package/skills/doc-generate/src/markdown-parser.ts +125 -0
  126. package/skills/doc-generate/src/types.ts +68 -0
  127. package/skills/domainpurchase/SKILL.md +1 -1
  128. package/skills/domainpurchase/package.json +1 -1
  129. package/skills/domainpurchase/src/index.ts +3 -0
  130. package/skills/domainsearch/SKILL.md +1 -1
  131. package/skills/domainsearch/package.json +1 -1
  132. package/skills/domainsearch/src/index.ts +3 -0
  133. package/skills/email-sequence/SKILL.md +44 -0
  134. package/skills/email-sequence/package.json +14 -0
  135. package/skills/excel/CLAUDE.md +2 -2
  136. package/skills/experiment-power-calculator/package.json +3 -1
  137. package/skills/extract-invoice/src/cli.ts +97 -0
  138. package/skills/extract-invoice/src/extractor.ts +170 -0
  139. package/skills/extract-invoice/src/file-utils.ts +46 -0
  140. package/skills/extract-invoice/src/formatters.ts +144 -0
  141. package/skills/extract-invoice/src/index.ts +44 -629
  142. package/skills/extract-invoice/src/runtime.ts +46 -0
  143. package/skills/extract-invoice/src/types.ts +88 -0
  144. package/skills/folder-tree/package.json +3 -1
  145. package/skills/form-filler/package.json +3 -1
  146. package/skills/generate-api-client/package.json +3 -1
  147. package/skills/generate-api-client/src/generator.ts +47 -0
  148. package/skills/generate-api-client/src/index.ts +3 -777
  149. package/skills/generate-api-client/src/logger.ts +34 -0
  150. package/skills/generate-api-client/src/python-generator.ts +245 -0
  151. package/skills/generate-api-client/src/spec-loader.ts +48 -0
  152. package/skills/generate-api-client/src/type-mappers.ts +79 -0
  153. package/skills/generate-api-client/src/types.ts +76 -0
  154. package/skills/generate-api-client/src/typescript-generator.ts +247 -0
  155. package/skills/generate-book-cover/package.json +3 -1
  156. package/skills/generate-dockerfile/src/cli.ts +78 -0
  157. package/skills/generate-dockerfile/src/dockerfile-templates.ts +392 -0
  158. package/skills/generate-dockerfile/src/index.ts +12 -790
  159. package/skills/generate-dockerfile/src/logger.ts +30 -0
  160. package/skills/generate-dockerfile/src/project-detection.ts +68 -0
  161. package/skills/generate-dockerfile/src/support-files.ts +171 -0
  162. package/skills/generate-dockerfile/src/types.ts +29 -0
  163. package/skills/generate-documentation/src/ai.ts +131 -0
  164. package/skills/generate-documentation/src/cli.ts +71 -0
  165. package/skills/generate-documentation/src/code-parser.ts +300 -0
  166. package/skills/generate-documentation/src/file-processing.ts +182 -0
  167. package/skills/generate-documentation/src/index.ts +13 -753
  168. package/skills/generate-documentation/src/runtime.ts +35 -0
  169. package/skills/generate-documentation/src/types.ts +30 -0
  170. package/skills/generate-env/package.json +3 -1
  171. package/skills/generate-env/src/cli.ts +85 -0
  172. package/skills/generate-env/src/detection.ts +161 -0
  173. package/skills/generate-env/src/env-data.ts +66 -0
  174. package/skills/generate-env/src/generators.ts +240 -0
  175. package/skills/generate-env/src/index.ts +76 -676
  176. package/skills/generate-env/src/runtime.ts +30 -0
  177. package/skills/generate-env/src/types.ts +32 -0
  178. package/skills/generate-favicon/package.json +3 -1
  179. package/skills/generate-mock-data/package.json +3 -1
  180. package/skills/generate-mock-data/src/ai.ts +102 -0
  181. package/skills/generate-mock-data/src/formatters.ts +84 -0
  182. package/skills/generate-mock-data/src/generator.ts +377 -0
  183. package/skills/generate-mock-data/src/index.ts +15 -716
  184. package/skills/generate-mock-data/src/logger.ts +37 -0
  185. package/skills/generate-mock-data/src/presets.ts +110 -0
  186. package/skills/generate-mock-data/src/types.ts +21 -0
  187. package/skills/generate-pr-description/src/ai.ts +144 -0
  188. package/skills/generate-pr-description/src/cli.ts +80 -0
  189. package/skills/generate-pr-description/src/clipboard.ts +30 -0
  190. package/skills/generate-pr-description/src/formatters.ts +231 -0
  191. package/skills/generate-pr-description/src/git.ts +153 -0
  192. package/skills/generate-pr-description/src/index.ts +21 -714
  193. package/skills/generate-pr-description/src/types.ts +49 -0
  194. package/skills/generate-presentation/src/ai-clients.ts +61 -0
  195. package/skills/generate-presentation/src/cli.ts +126 -0
  196. package/skills/generate-presentation/src/index.ts +3 -751
  197. package/skills/generate-presentation/src/logger.ts +67 -0
  198. package/skills/generate-presentation/src/presentation-generator.ts +425 -0
  199. package/skills/generate-presentation/src/runtime.ts +6 -0
  200. package/skills/generate-presentation/src/security.ts +12 -0
  201. package/skills/generate-presentation/src/types.ts +28 -0
  202. package/skills/generate-qrcode/package.json +4 -1
  203. package/skills/generate-regex/package.json +3 -1
  204. package/skills/generate-resume/src/cli.ts +157 -0
  205. package/skills/generate-resume/src/index.ts +13 -917
  206. package/skills/generate-resume/src/parsers.ts +95 -0
  207. package/skills/generate-resume/src/renderers.ts +538 -0
  208. package/skills/generate-resume/src/security.ts +39 -0
  209. package/skills/generate-resume/src/types.ts +86 -0
  210. package/skills/generate-social-posts/src/ai.ts +88 -0
  211. package/skills/generate-social-posts/src/cli.ts +118 -0
  212. package/skills/generate-social-posts/src/exporters.ts +126 -0
  213. package/skills/generate-social-posts/src/generator.ts +130 -0
  214. package/skills/generate-social-posts/src/index.ts +19 -709
  215. package/skills/generate-social-posts/src/platforms.ts +39 -0
  216. package/skills/generate-social-posts/src/runtime.ts +34 -0
  217. package/skills/generate-social-posts/src/source.ts +116 -0
  218. package/skills/generate-social-posts/src/types.ts +58 -0
  219. package/skills/gif-maker/package.json +4 -1
  220. package/skills/github-manager/package.json +3 -1
  221. package/skills/gmail/CLAUDE.md +1 -1
  222. package/skills/highlight-reel-generator/src/index.ts +19 -0
  223. package/skills/hook/src/commands/create.ts +20 -845
  224. package/skills/hook/src/templates/root.ts +196 -0
  225. package/skills/hook/src/templates/source.ts +647 -0
  226. package/skills/http-server/package.json +3 -1
  227. package/skills/icon-pack/README.md +28 -0
  228. package/skills/icon-pack/SKILL.md +23 -0
  229. package/skills/icon-pack/package.json +29 -0
  230. package/skills/{audio → icon-pack}/tsconfig.json +10 -12
  231. package/skills/image/package.json +1 -2
  232. package/skills/implementation-agent/package.json +3 -1
  233. package/skills/implementation-agent/src/ai-generation.ts +225 -0
  234. package/skills/implementation-agent/src/index.ts +3 -960
  235. package/skills/implementation-agent/src/minimist.d.ts +15 -0
  236. package/skills/implementation-agent/src/templates.ts +686 -0
  237. package/skills/implementation-agent/src/types.ts +53 -0
  238. package/skills/implementation-plan/package.json +3 -1
  239. package/skills/implementation-todo/package.json +3 -1
  240. package/skills/invoice/package.json +1 -1
  241. package/skills/invoice/src/index.ts +3 -0
  242. package/skills/invoice-reconciliation/SKILL.md +42 -0
  243. package/skills/invoice-reconciliation/package.json +10 -0
  244. package/skills/landing-page-pack/SKILL.md +47 -0
  245. package/skills/landing-page-pack/package.json +14 -0
  246. package/skills/latex-table-generator/package.json +3 -1
  247. package/skills/logo-design/SKILL.md +25 -44
  248. package/skills/logo-design/package.json +3 -15
  249. package/skills/lorem-generator/package.json +3 -1
  250. package/skills/lorem-generator/src/index.ts +13 -0
  251. package/skills/managehook/package.json +1 -1
  252. package/skills/managehook/src/index.ts +3 -0
  253. package/skills/managemcp/package.json +1 -1
  254. package/skills/managemcp/src/index.ts +3 -0
  255. package/skills/manageskill/package.json +1 -1
  256. package/skills/manageskill/src/index.ts +3 -0
  257. package/skills/markdown-validator/package.json +3 -1
  258. package/skills/markdown-validator/src/index.ts +1 -4
  259. package/skills/market-research-report/SKILL.md +41 -0
  260. package/skills/market-research-report/package.json +10 -0
  261. package/skills/mcp-builder/package.json +4 -1
  262. package/skills/mcp-builder/src/ai-descriptions.ts +37 -0
  263. package/skills/mcp-builder/src/generators.ts +513 -0
  264. package/skills/mcp-builder/src/index.ts +7 -908
  265. package/skills/mcp-builder/src/minimist.d.ts +15 -0
  266. package/skills/mcp-builder/src/naming.ts +12 -0
  267. package/skills/mcp-builder/src/options.ts +170 -0
  268. package/skills/mcp-builder/src/templates.ts +149 -0
  269. package/skills/mcp-builder/src/types.ts +42 -0
  270. package/skills/meeting-pack/SKILL.md +43 -0
  271. package/skills/meeting-pack/package.json +10 -0
  272. package/skills/merge-pdfs/package.json +5 -1
  273. package/skills/migration-plan-pack/SKILL.md +45 -0
  274. package/skills/migration-plan-pack/package.json +10 -0
  275. package/skills/music/package.json +2 -3
  276. package/skills/music-album/SKILL.md +37 -0
  277. package/skills/music-album/package.json +10 -0
  278. package/skills/notion-manager/package.json +3 -1
  279. package/skills/npmpublish/CLAUDE.md +5 -8
  280. package/skills/npmpublish/README.md +5 -26
  281. package/skills/npmpublish/src/index.ts +9 -147
  282. package/skills/one-page-website/SKILL.md +46 -0
  283. package/skills/one-page-website/package.json +10 -0
  284. package/skills/one-page-website/tsconfig.json +8 -0
  285. package/skills/pdf-generate/src/cli.ts +162 -0
  286. package/skills/pdf-generate/src/html.ts +84 -0
  287. package/skills/pdf-generate/src/index.ts +11 -800
  288. package/skills/pdf-generate/src/markdown.ts +27 -0
  289. package/skills/pdf-generate/src/pdf-writer.ts +78 -0
  290. package/skills/pdf-generate/src/runtime.ts +34 -0
  291. package/skills/pdf-generate/src/security.ts +37 -0
  292. package/skills/pdf-generate/src/templates.ts +311 -0
  293. package/skills/pdf-generate/src/types.ts +28 -0
  294. package/skills/pdf-read/SKILL.md +10 -10
  295. package/skills/pdf-to-dataset/SKILL.md +45 -0
  296. package/skills/pdf-to-dataset/package.json +10 -0
  297. package/skills/pdf-to-markdown/SKILL.md +49 -0
  298. package/skills/pdf-to-markdown/package.json +10 -0
  299. package/skills/pdf-to-markdown/tsconfig.json +10 -0
  300. package/skills/performance-audit-report/SKILL.md +42 -0
  301. package/skills/performance-audit-report/package.json +10 -0
  302. package/skills/persona-based-adwriter/src/index.ts +19 -0
  303. package/skills/photo-album/SKILL.md +29 -0
  304. package/skills/photo-album/package.json +9 -0
  305. package/skills/photo-album/tsconfig.json +4 -0
  306. package/skills/pitch-deck/SKILL.md +43 -0
  307. package/skills/pitch-deck/package.json +9 -0
  308. package/skills/playlist-maker/SKILL.md +33 -0
  309. package/skills/playlist-maker/package.json +9 -0
  310. package/skills/playlist-maker/tsconfig.json +4 -0
  311. package/skills/product-mockup/SKILL.md +45 -0
  312. package/skills/product-mockup/package.json +3 -20
  313. package/skills/product-mockup/tsconfig.json +3 -5
  314. package/skills/project-retro-companion/src/index.ts +19 -0
  315. package/skills/proposal-pack/SKILL.md +45 -0
  316. package/skills/proposal-pack/package.json +10 -0
  317. package/skills/read-pdf/SKILL.md +5 -4
  318. package/skills/repo-onboarding-report/SKILL.md +42 -0
  319. package/skills/repo-onboarding-report/package.json +10 -0
  320. package/skills/sales-call-recapper/src/index.ts +20 -0
  321. package/skills/salescopy/package.json +1 -1
  322. package/skills/salescopy/src/index.ts +3 -0
  323. package/skills/scaffold-project/src/ai-detect.ts +136 -0
  324. package/skills/scaffold-project/src/file-generators.ts +292 -0
  325. package/skills/scaffold-project/src/index.ts +8 -991
  326. package/skills/scaffold-project/src/project-config.ts +338 -0
  327. package/skills/scaffold-project/src/templates.ts +173 -0
  328. package/skills/scaffold-project/src/types.ts +58 -0
  329. package/skills/scientific-figure-check/package.json +3 -1
  330. package/skills/sdk-generator/SKILL.md +45 -0
  331. package/skills/sdk-generator/package.json +10 -0
  332. package/skills/sdk-generator/tsconfig.json +8 -0
  333. package/skills/security-audit/src/index.ts +25 -6
  334. package/skills/security-audit-report/SKILL.md +40 -0
  335. package/skills/security-audit-report/package.json +10 -0
  336. package/skills/seo-content-pack/SKILL.md +44 -0
  337. package/skills/seo-content-pack/package.json +9 -0
  338. package/skills/short-video-pack/SKILL.md +30 -0
  339. package/skills/short-video-pack/package.json +10 -0
  340. package/skills/slack-assistant/package.json +3 -1
  341. package/skills/slide-deck-generator/SKILL.md +44 -0
  342. package/skills/slide-deck-generator/package.json +10 -0
  343. package/skills/sms/package.json +1 -1
  344. package/skills/sms/src/index.ts +15 -0
  345. package/skills/social-content-calendar/SKILL.md +45 -0
  346. package/skills/social-content-calendar/package.json +14 -0
  347. package/skills/split-pdf/package.json +4 -1
  348. package/skills/subtitle/package.json +2 -1
  349. package/skills/subtitle/src/index.ts +3 -0
  350. package/skills/terraform-generator/package.json +3 -1
  351. package/skills/test-suite-generator/SKILL.md +41 -0
  352. package/skills/test-suite-generator/package.json +10 -0
  353. package/skills/timesheet/package.json +1 -1
  354. package/skills/timesheet/src/index.ts +3 -0
  355. package/skills/transcript/SKILL.md +1 -8
  356. package/skills/validate-config/package.json +3 -1
  357. package/skills/video/package.json +6 -4
  358. package/skills/video-downloader/package.json +3 -1
  359. package/skills/video-highlight-pack/SKILL.md +44 -0
  360. package/skills/video-highlight-pack/package.json +10 -0
  361. package/skills/voiceover-jingle-pack/SKILL.md +28 -0
  362. package/skills/voiceover-jingle-pack/package.json +10 -0
  363. package/skills/watermark/package.json +6 -1
  364. package/skills/webcrawling/package.json +2 -1
  365. package/skills/write/SKILL.md +6 -6
  366. package/dist/server/serve.d.ts +0 -11
  367. package/skills/apidocs/.claude/settings.json +0 -5
  368. package/skills/audio/.env.example +0 -14
  369. package/skills/audio/QUICKSTART.md +0 -158
  370. package/skills/audio/README.md +0 -256
  371. package/skills/audio/src/index-local.ts +0 -206
  372. package/skills/audio/src/index.ts +0 -95
  373. package/skills/audio/src/providers/elevenlabs.ts +0 -115
  374. package/skills/audio/src/providers/google.ts +0 -116
  375. package/skills/audio/src/providers/minimax.ts +0 -83
  376. package/skills/audio/src/providers/openai.ts +0 -115
  377. package/skills/audio/src/types.ts +0 -79
  378. package/skills/audiobook-chapter-proofer/CLAUDE.md +0 -19
  379. package/skills/audiobook-chapter-proofer/package.json +0 -27
  380. package/skills/audiobook-chapter-proofer/src/index.ts +0 -285
  381. package/skills/browse/src/client.ts +0 -373
  382. package/skills/browse/src/index-local.ts +0 -430
  383. package/skills/browse/src/index.ts +0 -110
  384. package/skills/browse/src/sse-server.ts +0 -919
  385. package/skills/browse/src/types.ts +0 -104
  386. package/skills/consolelog/src/server/index.ts +0 -508
  387. package/skills/create-blog-article/CLAUDE.md +0 -19
  388. package/skills/create-blog-article/src/index.ts +0 -745
  389. package/skills/create-blog-article/tsconfig.json +0 -10
  390. package/skills/deepresearch/src/agents/query-generator.ts +0 -91
  391. package/skills/deepresearch/src/agents/synthesizer.ts +0 -111
  392. package/skills/deepresearch/src/index.ts +0 -224
  393. package/skills/deepresearch/src/research.ts +0 -166
  394. package/skills/deepresearch/src/services/anthropic.ts +0 -69
  395. package/skills/deepresearch/src/services/exa.ts +0 -108
  396. package/skills/deepresearch/src/services/firecrawl.ts +0 -88
  397. package/skills/deepresearch/src/services/openai.ts +0 -81
  398. package/skills/deepresearch/src/types.ts +0 -76
  399. package/skills/deepresearch/src/utils/file.ts +0 -111
  400. package/skills/deepresearch/src/utils/logger.ts +0 -84
  401. package/skills/domainpurchase/src/server/index.ts +0 -332
  402. package/skills/domainsearch/src/server/index.ts +0 -229
  403. package/skills/e2bswarm/README.md +0 -135
  404. package/skills/e2bswarm/SKILL.md +0 -118
  405. package/skills/e2bswarm/examples/tasks-example.json +0 -38
  406. package/skills/e2bswarm/package.json +0 -59
  407. package/skills/e2bswarm/src/commands/collect.ts +0 -135
  408. package/skills/e2bswarm/src/commands/install.ts +0 -164
  409. package/skills/e2bswarm/src/commands/kill.ts +0 -62
  410. package/skills/e2bswarm/src/commands/spawn.ts +0 -134
  411. package/skills/e2bswarm/src/commands/status.ts +0 -90
  412. package/skills/e2bswarm/src/commands/sync.ts +0 -208
  413. package/skills/e2bswarm/src/index.ts +0 -121
  414. package/skills/e2bswarm/src/lib/config.ts +0 -75
  415. package/skills/e2bswarm/src/lib/e2b.ts +0 -490
  416. package/skills/e2bswarm/src/lib/github.ts +0 -253
  417. package/skills/e2bswarm/src/lib/logger.ts +0 -41
  418. package/skills/e2bswarm/src/lib/paths.ts +0 -75
  419. package/skills/e2bswarm/src/lib/tasks.ts +0 -320
  420. package/skills/e2bswarm/src/types/index.ts +0 -107
  421. package/skills/e2bswarm/templates/codebox/e2b.Dockerfile +0 -38
  422. package/skills/e2bswarm/templates/codebox/e2b.toml +0 -3
  423. package/skills/e2bswarm/templates/setup.sh +0 -21
  424. package/skills/e2bswarm/tsconfig.json +0 -19
  425. package/skills/generate-book-cover/src/index.ts +0 -694
  426. package/skills/image/src/index-local.ts +0 -206
  427. package/skills/image/src/index.ts +0 -96
  428. package/skills/image/src/providers/google.ts +0 -79
  429. package/skills/image/src/providers/minimax.ts +0 -94
  430. package/skills/image/src/providers/openai.ts +0 -80
  431. package/skills/image/src/providers/xai.ts +0 -73
  432. package/skills/image/src/types.ts +0 -37
  433. package/skills/logo-design/CLAUDE.md +0 -30
  434. package/skills/logo-design/src/index.ts +0 -322
  435. package/skills/managehook/src/server/index.ts +0 -108
  436. package/skills/managemcp/src/server/index.ts +0 -108
  437. package/skills/manageskill/src/server/index.ts +0 -108
  438. package/skills/music/CLAUDE.md +0 -9
  439. package/skills/music/src/index.ts +0 -94
  440. package/skills/music/tsconfig.json +0 -10
  441. package/skills/pdf-read/src/index.ts +0 -320
  442. package/skills/product-mockup/CLAUDE.md +0 -19
  443. package/skills/product-mockup/src/index.ts +0 -290
  444. package/skills/read-pdf/src/index.ts +0 -388
  445. package/skills/remove-background/src/index.ts +0 -405
  446. package/skills/scaffold-project/my-app/.env.example +0 -2
  447. package/skills/scaffold-project/my-app/README.md +0 -72
  448. package/skills/scaffold-project/my-app/package.json +0 -29
  449. package/skills/scaffold-project/my-app/src/index.ts +0 -23
  450. package/skills/scaffold-project/my-app/tsconfig.json +0 -33
  451. package/skills/sound-effects/SKILL.md +0 -34
  452. package/skills/sound-effects/package.json +0 -21
  453. package/skills/sound-effects/src/index.ts +0 -172
  454. package/skills/sound-effects/tsconfig.json +0 -8
  455. package/skills/transcript/src/chunker.ts +0 -215
  456. package/skills/transcript/src/formatter.ts +0 -134
  457. package/skills/transcript/src/index-local.ts +0 -226
  458. package/skills/transcript/src/index.ts +0 -110
  459. package/skills/transcript/src/providers/elevenlabs.ts +0 -133
  460. package/skills/transcript/src/providers/gemini.ts +0 -192
  461. package/skills/transcript/src/providers/index.ts +0 -54
  462. package/skills/transcript/src/providers/openai.ts +0 -203
  463. package/skills/transcript/src/types.ts +0 -106
  464. package/skills/video/.env.example +0 -14
  465. package/skills/video/EXAMPLES.md +0 -266
  466. package/skills/video/LICENSE +0 -192
  467. package/skills/video/README.md +0 -174
  468. package/skills/video/src/cli.ts +0 -155
  469. package/skills/video/src/index-local.ts +0 -148
  470. package/skills/video/src/index.ts +0 -96
  471. package/skills/video/src/providers/google-veo.ts +0 -126
  472. package/skills/video/src/providers/index.ts +0 -22
  473. package/skills/video/src/providers/minimax.ts +0 -100
  474. package/skills/video/src/providers/openai-sora.ts +0 -164
  475. package/skills/video/src/providers/runway.ts +0 -159
  476. package/skills/video/src/types.ts +0 -35
  477. package/skills/video/tsconfig.json +0 -22
  478. package/skills/voiceover-casting-assistant/CLAUDE.md +0 -19
  479. package/skills/voiceover-casting-assistant/package.json +0 -27
  480. package/skills/voiceover-casting-assistant/src/index.ts +0 -255
  481. package/skills/voiceover-casting-assistant/tsconfig.json +0 -10
  482. package/skills/webcrawling/src/commands/config.ts +0 -34
  483. package/skills/webcrawling/src/commands/crawl.ts +0 -33
  484. package/skills/webcrawling/src/commands/scrape.ts +0 -32
  485. package/skills/webcrawling/src/commands/sessions.ts +0 -42
  486. package/skills/webcrawling/src/lib/crawler.ts +0 -174
  487. package/skills/webcrawling/src/lib/storage.ts +0 -130
  488. package/skills/webcrawling/src/types/index.ts +0 -45
  489. package/skills/webcrawling/src/utils/logger.ts +0 -30
  490. package/skills/webcrawling/src/utils/paths.ts +0 -28
  491. /package/skills/{audiobook-chapter-proofer → blog-article}/tsconfig.json +0 -0
@@ -1,253 +0,0 @@
1
- import { Sandbox } from 'e2b';
2
- import { mkdir } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- import type { SwarmInstance } from '../types';
5
- import { logger } from './logger';
6
-
7
- /**
8
- * Setup GitHub authentication in sandbox
9
- */
10
- export async function setupGitHubAuth(sandbox: Sandbox): Promise<void> {
11
- // Check for GitHub token in environment
12
- const ghToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
13
-
14
- if (ghToken) {
15
- // Use token-based auth
16
- await sandbox.commands.run(`
17
- git config --global credential.helper store
18
- echo "https://oauth2:${ghToken}@github.com" > ~/.git-credentials
19
- git config --global user.email "swarm@e2b.dev"
20
- git config --global user.name "E2B Swarm"
21
- `);
22
- return;
23
- }
24
-
25
- // Try to copy SSH key from local machine
26
- const sshKeyPath = `${process.env.HOME}/.ssh/id_ed25519`;
27
- try {
28
- const privateKey = await Bun.file(sshKeyPath).text();
29
- const publicKey = await Bun.file(`${sshKeyPath}.pub`).text();
30
-
31
- await sandbox.commands.run('mkdir -p ~/.ssh && chmod 700 ~/.ssh');
32
- await sandbox.files.write('/home/user/.ssh/id_ed25519', privateKey);
33
- await sandbox.files.write('/home/user/.ssh/id_ed25519.pub', publicKey);
34
- await sandbox.commands.run(`
35
- chmod 600 ~/.ssh/id_ed25519
36
- chmod 644 ~/.ssh/id_ed25519.pub
37
- ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
38
- git config --global user.email "swarm@e2b.dev"
39
- git config --global user.name "E2B Swarm"
40
- `);
41
- return;
42
- } catch {
43
- // SSH key not found, try id_rsa
44
- }
45
-
46
- const rsaKeyPath = `${process.env.HOME}/.ssh/id_rsa`;
47
- try {
48
- const privateKey = await Bun.file(rsaKeyPath).text();
49
- const publicKey = await Bun.file(`${rsaKeyPath}.pub`).text();
50
-
51
- await sandbox.commands.run('mkdir -p ~/.ssh && chmod 700 ~/.ssh');
52
- await sandbox.files.write('/home/user/.ssh/id_rsa', privateKey);
53
- await sandbox.files.write('/home/user/.ssh/id_rsa.pub', publicKey);
54
- await sandbox.commands.run(`
55
- chmod 600 ~/.ssh/id_rsa
56
- chmod 644 ~/.ssh/id_rsa.pub
57
- ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
58
- git config --global user.email "swarm@e2b.dev"
59
- git config --global user.name "E2B Swarm"
60
- `);
61
- return;
62
- } catch {
63
- // No SSH key found
64
- }
65
-
66
- logger.warn('No GitHub authentication found. Set GITHUB_TOKEN or ensure SSH keys exist.');
67
- }
68
-
69
- /**
70
- * Commit changes in the sandbox
71
- */
72
- export async function commitChanges(
73
- sandbox: Sandbox,
74
- message: string
75
- ): Promise<{ success: boolean; error?: string }> {
76
- // Stage all changes
77
- const addResult = await sandbox.commands.run('cd /home/user/workspace && git add -A');
78
- if (addResult.exitCode !== 0) {
79
- return { success: false, error: `Failed to stage changes: ${addResult.stderr}` };
80
- }
81
-
82
- // Check if there are changes to commit
83
- const statusResult = await sandbox.commands.run('cd /home/user/workspace && git status --porcelain');
84
- if (!statusResult.stdout.trim()) {
85
- return { success: true }; // No changes to commit
86
- }
87
-
88
- // Commit
89
- const commitResult = await sandbox.commands.run(
90
- `cd /home/user/workspace && git commit -m "${message.replace(/"/g, '\\"')}"`
91
- );
92
- if (commitResult.exitCode !== 0) {
93
- return { success: false, error: `Failed to commit: ${commitResult.stderr}` };
94
- }
95
-
96
- return { success: true };
97
- }
98
-
99
- /**
100
- * Push changes to remote
101
- */
102
- export async function pushChanges(
103
- sandbox: Sandbox,
104
- branch?: string
105
- ): Promise<{ success: boolean; error?: string }> {
106
- const pushCmd = branch
107
- ? `cd /home/user/workspace && git push -u origin ${branch}`
108
- : 'cd /home/user/workspace && git push';
109
-
110
- const result = await sandbox.commands.run(pushCmd, { timeoutMs: 60000 });
111
- if (result.exitCode !== 0) {
112
- return { success: false, error: `Failed to push: ${result.stderr}` };
113
- }
114
-
115
- return { success: true };
116
- }
117
-
118
- /**
119
- * Create a new branch
120
- */
121
- export async function createBranch(
122
- sandbox: Sandbox,
123
- branchName: string
124
- ): Promise<{ success: boolean; error?: string }> {
125
- const result = await sandbox.commands.run(
126
- `cd /home/user/workspace && git checkout -b ${branchName}`
127
- );
128
- if (result.exitCode !== 0) {
129
- return { success: false, error: `Failed to create branch: ${result.stderr}` };
130
- }
131
-
132
- return { success: true };
133
- }
134
-
135
- /**
136
- * Create a pull request using gh CLI
137
- */
138
- export async function createPullRequest(
139
- sandbox: Sandbox,
140
- options: {
141
- title: string;
142
- body: string;
143
- base?: string;
144
- draft?: boolean;
145
- }
146
- ): Promise<{ success: boolean; prUrl?: string; error?: string }> {
147
- // Install gh CLI if not present
148
- await sandbox.commands.run(`
149
- which gh || (curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
150
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
151
- sudo apt update && sudo apt install gh -y) 2>/dev/null || true
152
- `, { timeoutMs: 120000 });
153
-
154
- // Check for GitHub token
155
- const ghToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
156
- if (!ghToken) {
157
- return { success: false, error: 'GITHUB_TOKEN not set. Cannot create PR.' };
158
- }
159
-
160
- // Authenticate gh CLI
161
- await sandbox.commands.run(`echo "${ghToken}" | gh auth login --with-token`);
162
-
163
- // Build PR command
164
- const baseFlag = options.base ? `--base ${options.base}` : '';
165
- const draftFlag = options.draft ? '--draft' : '';
166
-
167
- const prCmd = `cd /home/user/workspace && gh pr create --title "${options.title.replace(/"/g, '\\"')}" --body "${options.body.replace(/"/g, '\\"')}" ${baseFlag} ${draftFlag}`;
168
-
169
- const result = await sandbox.commands.run(prCmd, { timeoutMs: 60000 });
170
- if (result.exitCode !== 0) {
171
- return { success: false, error: `Failed to create PR: ${result.stderr}` };
172
- }
173
-
174
- // Extract PR URL from output
175
- const prUrl = result.stdout.trim().split('\n').pop();
176
-
177
- return { success: true, prUrl };
178
- }
179
-
180
- /**
181
- * Download changed files from sandbox to local export directory
182
- */
183
- export async function downloadChangedFiles(
184
- sandbox: Sandbox,
185
- instance: SwarmInstance
186
- ): Promise<string[]> {
187
- const exportDir = instance.exportDir;
188
- if (!exportDir) return [];
189
-
190
- // Get list of changed files
191
- const diffResult = await sandbox.commands.run(
192
- 'cd /home/user/workspace && git diff --name-only HEAD~1 2>/dev/null || git diff --name-only'
193
- );
194
-
195
- const changedFiles = diffResult.stdout.trim().split('\n').filter(Boolean);
196
- const downloadedFiles: string[] = [];
197
-
198
- // Create changes directory
199
- const changesDir = join(exportDir, 'changes');
200
- await mkdir(changesDir, { recursive: true });
201
-
202
- for (const file of changedFiles) {
203
- try {
204
- const content = await sandbox.files.read(`/home/user/workspace/${file}`);
205
- const localPath = join(changesDir, file);
206
- await mkdir(join(changesDir, file.split('/').slice(0, -1).join('/')), { recursive: true });
207
- await Bun.write(localPath, content);
208
- downloadedFiles.push(file);
209
- } catch {
210
- // File might have been deleted
211
- }
212
- }
213
-
214
- return downloadedFiles;
215
- }
216
-
217
- /**
218
- * Get git status from sandbox
219
- */
220
- export async function getGitStatus(sandbox: Sandbox): Promise<{
221
- branch: string;
222
- ahead: number;
223
- behind: number;
224
- modified: string[];
225
- added: string[];
226
- deleted: string[];
227
- }> {
228
- const branchResult = await sandbox.commands.run('cd /home/user/workspace && git branch --show-current');
229
- const statusResult = await sandbox.commands.run('cd /home/user/workspace && git status --porcelain');
230
-
231
- const modified: string[] = [];
232
- const added: string[] = [];
233
- const deleted: string[] = [];
234
-
235
- for (const line of statusResult.stdout.split('\n')) {
236
- if (!line.trim()) continue;
237
- const status = line.slice(0, 2);
238
- const file = line.slice(3);
239
-
240
- if (status.includes('M')) modified.push(file);
241
- if (status.includes('A') || status === '??') added.push(file);
242
- if (status.includes('D')) deleted.push(file);
243
- }
244
-
245
- return {
246
- branch: branchResult.stdout.trim(),
247
- ahead: 0,
248
- behind: 0,
249
- modified,
250
- added,
251
- deleted,
252
- };
253
- }
@@ -1,41 +0,0 @@
1
- import chalk from 'chalk';
2
-
3
- export const logger = {
4
- info: (msg: string) => console.log(chalk.blue('ℹ'), msg),
5
- success: (msg: string) => console.log(chalk.green('✓'), msg),
6
- warn: (msg: string) => console.log(chalk.yellow('⚠'), msg),
7
- error: (msg: string) => console.log(chalk.red('✗'), msg),
8
- debug: (msg: string) => {
9
- if (process.env.DEBUG) console.log(chalk.gray('⋯'), msg);
10
- },
11
-
12
- instance: (id: string, status: string, msg?: string) => {
13
- const statusColors: Record<string, (s: string) => string> = {
14
- starting: chalk.yellow,
15
- cloning: chalk.blue,
16
- 'setting-up': chalk.blue,
17
- running: chalk.cyan,
18
- completed: chalk.green,
19
- failed: chalk.red,
20
- };
21
- const colorFn = statusColors[status] || chalk.white;
22
- const shortId = id.slice(0, 8);
23
- console.log(` ${chalk.gray(`[${shortId}]`)} ${colorFn(status.padEnd(10))} ${msg || ''}`);
24
- },
25
-
26
- table: (data: Array<Record<string, unknown>>) => {
27
- if (data.length === 0) {
28
- console.log(chalk.gray(' No data'));
29
- return;
30
- }
31
- console.table(data);
32
- },
33
-
34
- divider: () => console.log(chalk.gray('─'.repeat(60))),
35
-
36
- header: (title: string) => {
37
- console.log();
38
- console.log(chalk.bold.white(title));
39
- logger.divider();
40
- },
41
- };
@@ -1,75 +0,0 @@
1
- import { mkdir } from 'node:fs/promises';
2
- import { join } from 'node:path';
3
-
4
- /**
5
- * Standard skill data directory structure
6
- *
7
- * ~/.skills/
8
- * └── [name]/
9
- * ├── exports/ # Output data, results, artifacts
10
- * ├── logs/ # Execution logs, debug info
11
- * ├── cache/ # Temporary cached data
12
- * └── config/ # Skill-specific configuration
13
- */
14
-
15
- const SKILL_NAME = 'e2bswarm';
16
- const SKILLS_ROOT = join(process.env.HOME!, '.skills');
17
- const SKILL_DATA_DIR = join(SKILLS_ROOT, SKILL_NAME);
18
-
19
- export const paths = {
20
- // Root directories
21
- skillsRoot: SKILLS_ROOT,
22
- skillData: SKILL_DATA_DIR,
23
-
24
- // Standard subdirectories
25
- exports: join(SKILL_DATA_DIR, 'exports'),
26
- logs: join(SKILL_DATA_DIR, 'logs'),
27
- cache: join(SKILL_DATA_DIR, 'cache'),
28
- config: join(SKILL_DATA_DIR, 'config'),
29
-
30
- // State file (moved from ~/.claude/)
31
- state: join(SKILL_DATA_DIR, 'state.json'),
32
-
33
- // Helper to get timestamped export directory
34
- getExportDir: (prefix?: string) => {
35
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
36
- const dirName = prefix ? `${prefix}-${timestamp}` : timestamp;
37
- return join(SKILL_DATA_DIR, 'exports', dirName);
38
- },
39
-
40
- // Helper to get log file path
41
- getLogFile: (name: string) => {
42
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
43
- return join(SKILL_DATA_DIR, 'logs', `${name}-${timestamp}.log`);
44
- },
45
-
46
- // Helper to get instance-specific paths
47
- getInstance: (instanceId: string) => ({
48
- exports: join(SKILL_DATA_DIR, 'exports', instanceId),
49
- logs: join(SKILL_DATA_DIR, 'logs', instanceId),
50
- }),
51
- };
52
-
53
- /**
54
- * Ensure all skill directories exist
55
- */
56
- export async function ensureSkillDirs(): Promise<void> {
57
- await mkdir(paths.exports, { recursive: true });
58
- await mkdir(paths.logs, { recursive: true });
59
- await mkdir(paths.cache, { recursive: true });
60
- await mkdir(paths.config, { recursive: true });
61
- }
62
-
63
- /**
64
- * Get skill data path for any skill (reusable utility)
65
- */
66
- export function getSkillPaths(skillName: string) {
67
- const skillDir = join(SKILLS_ROOT, skillName);
68
- return {
69
- root: skillDir,
70
- exports: join(skillDir, 'exports'),
71
- logs: join(skillDir, 'logs'),
72
- cache: join(skillDir, 'cache'),
73
- config: join(skillDir, 'config'),
74
- };
75
- }
@@ -1,320 +0,0 @@
1
- import { readdir } from 'node:fs/promises';
2
- import { join, resolve } from 'node:path';
3
- import type { Task, TaskSource, SpawnOptions } from '../types';
4
- import { logger } from './logger';
5
-
6
- /**
7
- * Determine the task source from spawn options
8
- */
9
- export function determineTaskSource(options: SpawnOptions): TaskSource {
10
- if (options.tasksJson) {
11
- return { type: 'json', value: options.tasksJson };
12
- }
13
- if (options.tasksFile) {
14
- return { type: 'file', value: resolve(options.tasksFile) };
15
- }
16
- if (options.tasksDir) {
17
- return { type: 'directory', value: resolve(options.tasksDir) };
18
- }
19
- if (options.tasks) {
20
- // Check if it's a path or a task list ID
21
- if (options.tasks.includes('/') || options.tasks.endsWith('.json')) {
22
- return { type: 'file', value: resolve(options.tasks) };
23
- }
24
- return { type: 'task-list-id', value: options.tasks };
25
- }
26
- throw new Error(
27
- 'No task source provided. Use one of:\n' +
28
- ' --tasks <task-list-id> Load from ~/.claude/tasks/<id>/\n' +
29
- ' --tasks-dir <directory> Load from a local directory\n' +
30
- ' --tasks-file <file.json> Load from a JSON file\n' +
31
- ' --tasks-json \'[...]\''+ ' Inline JSON array'
32
- );
33
- }
34
-
35
- /**
36
- * Load tasks from various sources
37
- */
38
- export async function loadTasks(source: TaskSource): Promise<Task[]> {
39
- switch (source.type) {
40
- case 'json':
41
- return parseTasksJson(source.value);
42
-
43
- case 'file':
44
- return loadTasksFromFile(source.value);
45
-
46
- case 'directory':
47
- return loadTasksFromDirectory(source.value);
48
-
49
- case 'task-list-id':
50
- return loadTasksFromTaskList(source.value);
51
-
52
- default:
53
- throw new Error(`Unknown task source type`);
54
- }
55
- }
56
-
57
- /**
58
- * Parse inline JSON tasks
59
- */
60
- function parseTasksJson(json: string): Task[] {
61
- try {
62
- const parsed = JSON.parse(json);
63
- const tasks = Array.isArray(parsed) ? parsed : [parsed];
64
- return validateTasks(tasks);
65
- } catch (error) {
66
- throw new Error(`Failed to parse tasks JSON: ${error}`);
67
- }
68
- }
69
-
70
- /**
71
- * Load tasks from a JSON file
72
- */
73
- async function loadTasksFromFile(filePath: string): Promise<Task[]> {
74
- try {
75
- const content = await Bun.file(filePath).text();
76
- const parsed = JSON.parse(content);
77
- const tasks = Array.isArray(parsed) ? parsed : [parsed];
78
- logger.debug(`Loaded ${tasks.length} tasks from file: ${filePath}`);
79
- return validateTasks(tasks);
80
- } catch (error) {
81
- throw new Error(`Failed to load tasks from file ${filePath}: ${error}`);
82
- }
83
- }
84
-
85
- /**
86
- * Load tasks from a directory containing JSON files
87
- */
88
- async function loadTasksFromDirectory(dirPath: string): Promise<Task[]> {
89
- try {
90
- const files = await readdir(dirPath);
91
- const jsonFiles = files.filter(f => f.endsWith('.json'));
92
-
93
- if (jsonFiles.length === 0) {
94
- throw new Error(`No JSON files found in directory: ${dirPath}`);
95
- }
96
-
97
- const tasks: Task[] = [];
98
- for (const file of jsonFiles) {
99
- const content = await Bun.file(join(dirPath, file)).text();
100
- const task = JSON.parse(content);
101
- tasks.push(task);
102
- }
103
-
104
- logger.debug(`Loaded ${tasks.length} tasks from directory: ${dirPath}`);
105
- return validateTasks(tasks);
106
- } catch (error) {
107
- if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
108
- throw new Error(`Directory not found: ${dirPath}`);
109
- }
110
- throw error;
111
- }
112
- }
113
-
114
- /**
115
- * Load tasks from Claude Code task list (~/.claude/tasks/<id>/)
116
- */
117
- async function loadTasksFromTaskList(taskListId: string): Promise<Task[]> {
118
- const tasksDir = join(process.env.HOME!, '.claude', 'tasks', taskListId);
119
-
120
- try {
121
- const files = await readdir(tasksDir);
122
- const jsonFiles = files.filter(f => f.endsWith('.json'));
123
-
124
- if (jsonFiles.length === 0) {
125
- throw new Error(`No tasks found in task list: ${taskListId}`);
126
- }
127
-
128
- const tasks: Task[] = [];
129
- for (const file of jsonFiles) {
130
- const content = await Bun.file(join(tasksDir, file)).text();
131
- const task = JSON.parse(content);
132
- tasks.push(task);
133
- }
134
-
135
- logger.debug(`Loaded ${tasks.length} tasks from task list: ${taskListId}`);
136
- return validateTasks(tasks);
137
- } catch (error) {
138
- if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
139
- throw new Error(
140
- `Task list not found: ${taskListId}\n` +
141
- `Expected location: ${tasksDir}\n\n` +
142
- 'Available task lists can be found in ~/.claude/tasks/'
143
- );
144
- }
145
- throw error;
146
- }
147
- }
148
-
149
- /**
150
- * Validate and normalize task objects
151
- */
152
- function validateTasks(tasks: unknown[]): Task[] {
153
- return tasks.map((task, index) => {
154
- if (!task || typeof task !== 'object') {
155
- throw new Error(`Task at index ${index} is not an object`);
156
- }
157
-
158
- const t = task as Record<string, unknown>;
159
-
160
- if (!t.id) {
161
- t.id = String(index + 1);
162
- }
163
- if (!t.subject && !t.description) {
164
- throw new Error(`Task ${t.id} must have a subject or description`);
165
- }
166
-
167
- return {
168
- id: String(t.id),
169
- subject: String(t.subject || t.description || ''),
170
- description: String(t.description || t.subject || ''),
171
- activeForm: t.activeForm ? String(t.activeForm) : undefined,
172
- status: (t.status as Task['status']) || 'pending',
173
- blocks: Array.isArray(t.blocks) ? t.blocks.map(String) : [],
174
- blockedBy: Array.isArray(t.blockedBy) ? t.blockedBy.map(String) : [],
175
- metadata: t.metadata as Record<string, unknown> | undefined,
176
- };
177
- });
178
- }
179
-
180
- /**
181
- * Filter tasks to only pending/in_progress
182
- */
183
- export function filterPendingTasks(tasks: Task[]): Task[] {
184
- return tasks.filter(t => t.status !== 'completed');
185
- }
186
-
187
- /**
188
- * Distribute tasks across instances based on mode
189
- */
190
- export function distributeTasks(
191
- tasks: Task[],
192
- instanceCount: number,
193
- mode: 'all' | 'round-robin' | 'by-dependency' = 'all'
194
- ): Task[][] {
195
- // Filter to pending tasks only
196
- const pendingTasks = filterPendingTasks(tasks);
197
-
198
- if (pendingTasks.length === 0) {
199
- logger.warn('No pending tasks to distribute');
200
- return Array(instanceCount).fill([]);
201
- }
202
-
203
- switch (mode) {
204
- case 'all':
205
- // Each instance gets all tasks
206
- return Array(instanceCount).fill(null).map(() => [...pendingTasks]);
207
-
208
- case 'round-robin':
209
- // Distribute tasks evenly across instances
210
- return distributeRoundRobin(pendingTasks, instanceCount);
211
-
212
- case 'by-dependency':
213
- // Group tasks by their dependency chains
214
- return distributeByDependency(pendingTasks, instanceCount);
215
-
216
- default:
217
- return [pendingTasks];
218
- }
219
- }
220
-
221
- function distributeRoundRobin(tasks: Task[], instanceCount: number): Task[][] {
222
- const distribution: Task[][] = Array.from({ length: instanceCount }, () => []);
223
-
224
- tasks.forEach((task, i) => {
225
- distribution[i % instanceCount]!.push(task);
226
- });
227
-
228
- return distribution;
229
- }
230
-
231
- function distributeByDependency(tasks: Task[], maxGroups: number): Task[][] {
232
- const chains: Task[][] = [];
233
- const assigned = new Set<string>();
234
-
235
- // Find all tasks that have no blockers (roots)
236
- const roots = tasks.filter(t => t.blockedBy.length === 0);
237
-
238
- for (const root of roots) {
239
- if (assigned.has(root.id)) continue;
240
- const chain = collectDependencyChain(root, tasks, assigned);
241
- if (chain.length > 0) {
242
- chains.push(chain);
243
- }
244
- }
245
-
246
- // Add any orphaned tasks
247
- for (const task of tasks) {
248
- if (!assigned.has(task.id)) {
249
- chains.push([task]);
250
- assigned.add(task.id);
251
- }
252
- }
253
-
254
- // Merge chains if we have more than maxGroups
255
- while (chains.length > maxGroups && chains.length > 1) {
256
- // Find the smallest chain
257
- let smallestIdx = 0;
258
- for (let i = 1; i < chains.length; i++) {
259
- if (chains[i]!.length < chains[smallestIdx]!.length) {
260
- smallestIdx = i;
261
- }
262
- }
263
-
264
- // Merge with the next smallest
265
- const smallest = chains.splice(smallestIdx, 1)[0]!;
266
- let targetIdx = 0;
267
- for (let i = 1; i < chains.length; i++) {
268
- if (chains[i]!.length < chains[targetIdx]!.length) {
269
- targetIdx = i;
270
- }
271
- }
272
- chains[targetIdx]!.push(...smallest);
273
- }
274
-
275
- // Pad with empty arrays if we have fewer chains than instances
276
- while (chains.length < maxGroups) {
277
- chains.push([]);
278
- }
279
-
280
- return chains;
281
- }
282
-
283
- function collectDependencyChain(
284
- task: Task,
285
- allTasks: Task[],
286
- assigned: Set<string>
287
- ): Task[] {
288
- if (assigned.has(task.id)) return [];
289
-
290
- assigned.add(task.id);
291
- const chain: Task[] = [task];
292
-
293
- // Find tasks that this one blocks (dependents)
294
- for (const t of allTasks) {
295
- if (t.blockedBy.includes(task.id)) {
296
- chain.push(...collectDependencyChain(t, allTasks, assigned));
297
- }
298
- }
299
-
300
- return chain;
301
- }
302
-
303
- /**
304
- * Serialize tasks for writing to sandbox
305
- */
306
- export function serializeTasks(tasks: Task[]): string {
307
- return JSON.stringify(tasks, null, 2);
308
- }
309
-
310
- /**
311
- * Create a summary of task distribution
312
- */
313
- export function summarizeDistribution(distribution: Task[][]): string {
314
- const lines = distribution.map((tasks, i) => {
315
- const subjects = tasks.slice(0, 3).map(t => t.subject.slice(0, 40));
316
- const more = tasks.length > 3 ? ` (+${tasks.length - 3} more)` : '';
317
- return ` Instance ${i + 1}: ${tasks.length} tasks${more}\n ${subjects.join('\n ')}`;
318
- });
319
- return lines.join('\n');
320
- }