@hasna/skills 0.1.27 → 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 (488) hide show
  1. package/LICENSE +1 -10
  2. package/README.md +141 -39
  3. package/bin/index.js +30121 -27576
  4. package/bin/mcp.js +22073 -18556
  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 +11606 -598
  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 +22 -11
  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/exports/products-2025-12-14T13-50-53-041Z.csv +16 -0
  108. package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.json +227 -0
  109. package/skills/consolelog/package.json +1 -1
  110. package/skills/consolelog/src/index.ts +3 -0
  111. package/skills/contract-review-report/SKILL.md +43 -0
  112. package/skills/contract-review-report/package.json +10 -0
  113. package/skills/convert/SKILL.md +2 -3
  114. package/skills/customer-feedback-report/SKILL.md +44 -0
  115. package/skills/customer-feedback-report/package.json +10 -0
  116. package/skills/dashboard-builder/package.json +3 -1
  117. package/skills/database-explorer/package.json +3 -1
  118. package/skills/deepresearch/README.md +4 -13
  119. package/skills/deploy/src/http-client.ts +1 -1
  120. package/skills/diff-viewer/package.json +4 -1
  121. package/skills/doc-generate/package.json +0 -1
  122. package/skills/doc-generate/src/ai.ts +50 -0
  123. package/skills/doc-generate/src/cli.ts +203 -0
  124. package/skills/doc-generate/src/dependencies.ts +44 -0
  125. package/skills/doc-generate/src/document-builder.ts +299 -0
  126. package/skills/doc-generate/src/index.ts +40 -764
  127. package/skills/doc-generate/src/markdown-parser.ts +125 -0
  128. package/skills/doc-generate/src/types.ts +68 -0
  129. package/skills/domainpurchase/SKILL.md +1 -1
  130. package/skills/domainpurchase/package.json +1 -1
  131. package/skills/domainpurchase/src/index.ts +3 -0
  132. package/skills/domainsearch/SKILL.md +1 -1
  133. package/skills/domainsearch/package.json +1 -1
  134. package/skills/domainsearch/src/index.ts +3 -0
  135. package/skills/email-sequence/SKILL.md +44 -0
  136. package/skills/email-sequence/package.json +14 -0
  137. package/skills/excel/CLAUDE.md +2 -2
  138. package/skills/experiment-power-calculator/package.json +3 -1
  139. package/skills/extract-invoice/src/cli.ts +97 -0
  140. package/skills/extract-invoice/src/extractor.ts +170 -0
  141. package/skills/extract-invoice/src/file-utils.ts +46 -0
  142. package/skills/extract-invoice/src/formatters.ts +144 -0
  143. package/skills/extract-invoice/src/index.ts +44 -629
  144. package/skills/extract-invoice/src/runtime.ts +46 -0
  145. package/skills/extract-invoice/src/types.ts +88 -0
  146. package/skills/folder-tree/package.json +3 -1
  147. package/skills/form-filler/package.json +3 -1
  148. package/skills/generate-api-client/package.json +3 -1
  149. package/skills/generate-api-client/src/generator.ts +47 -0
  150. package/skills/generate-api-client/src/index.ts +3 -777
  151. package/skills/generate-api-client/src/logger.ts +34 -0
  152. package/skills/generate-api-client/src/python-generator.ts +245 -0
  153. package/skills/generate-api-client/src/spec-loader.ts +48 -0
  154. package/skills/generate-api-client/src/type-mappers.ts +79 -0
  155. package/skills/generate-api-client/src/types.ts +76 -0
  156. package/skills/generate-api-client/src/typescript-generator.ts +247 -0
  157. package/skills/generate-book-cover/package.json +3 -1
  158. package/skills/generate-dockerfile/src/cli.ts +78 -0
  159. package/skills/generate-dockerfile/src/dockerfile-templates.ts +392 -0
  160. package/skills/generate-dockerfile/src/index.ts +12 -790
  161. package/skills/generate-dockerfile/src/logger.ts +30 -0
  162. package/skills/generate-dockerfile/src/project-detection.ts +68 -0
  163. package/skills/generate-dockerfile/src/support-files.ts +171 -0
  164. package/skills/generate-dockerfile/src/types.ts +29 -0
  165. package/skills/generate-documentation/src/ai.ts +131 -0
  166. package/skills/generate-documentation/src/cli.ts +71 -0
  167. package/skills/generate-documentation/src/code-parser.ts +300 -0
  168. package/skills/generate-documentation/src/file-processing.ts +182 -0
  169. package/skills/generate-documentation/src/index.ts +13 -753
  170. package/skills/generate-documentation/src/runtime.ts +35 -0
  171. package/skills/generate-documentation/src/types.ts +30 -0
  172. package/skills/generate-env/package.json +3 -1
  173. package/skills/generate-env/src/cli.ts +85 -0
  174. package/skills/generate-env/src/detection.ts +161 -0
  175. package/skills/generate-env/src/env-data.ts +66 -0
  176. package/skills/generate-env/src/generators.ts +240 -0
  177. package/skills/generate-env/src/index.ts +76 -676
  178. package/skills/generate-env/src/runtime.ts +30 -0
  179. package/skills/generate-env/src/types.ts +32 -0
  180. package/skills/generate-favicon/package.json +3 -1
  181. package/skills/generate-mock-data/package.json +3 -1
  182. package/skills/generate-mock-data/src/ai.ts +102 -0
  183. package/skills/generate-mock-data/src/formatters.ts +84 -0
  184. package/skills/generate-mock-data/src/generator.ts +377 -0
  185. package/skills/generate-mock-data/src/index.ts +15 -716
  186. package/skills/generate-mock-data/src/logger.ts +37 -0
  187. package/skills/generate-mock-data/src/presets.ts +110 -0
  188. package/skills/generate-mock-data/src/types.ts +21 -0
  189. package/skills/generate-pr-description/src/ai.ts +144 -0
  190. package/skills/generate-pr-description/src/cli.ts +80 -0
  191. package/skills/generate-pr-description/src/clipboard.ts +30 -0
  192. package/skills/generate-pr-description/src/formatters.ts +231 -0
  193. package/skills/generate-pr-description/src/git.ts +153 -0
  194. package/skills/generate-pr-description/src/index.ts +21 -714
  195. package/skills/generate-pr-description/src/types.ts +49 -0
  196. package/skills/generate-presentation/src/ai-clients.ts +61 -0
  197. package/skills/generate-presentation/src/cli.ts +126 -0
  198. package/skills/generate-presentation/src/index.ts +3 -751
  199. package/skills/generate-presentation/src/logger.ts +67 -0
  200. package/skills/generate-presentation/src/presentation-generator.ts +425 -0
  201. package/skills/generate-presentation/src/runtime.ts +6 -0
  202. package/skills/generate-presentation/src/security.ts +12 -0
  203. package/skills/generate-presentation/src/types.ts +28 -0
  204. package/skills/generate-qrcode/package.json +4 -1
  205. package/skills/generate-regex/package.json +3 -1
  206. package/skills/generate-resume/src/cli.ts +157 -0
  207. package/skills/generate-resume/src/index.ts +13 -917
  208. package/skills/generate-resume/src/parsers.ts +95 -0
  209. package/skills/generate-resume/src/renderers.ts +538 -0
  210. package/skills/generate-resume/src/security.ts +39 -0
  211. package/skills/generate-resume/src/types.ts +86 -0
  212. package/skills/generate-social-posts/src/ai.ts +88 -0
  213. package/skills/generate-social-posts/src/cli.ts +118 -0
  214. package/skills/generate-social-posts/src/exporters.ts +126 -0
  215. package/skills/generate-social-posts/src/generator.ts +130 -0
  216. package/skills/generate-social-posts/src/index.ts +19 -709
  217. package/skills/generate-social-posts/src/platforms.ts +39 -0
  218. package/skills/generate-social-posts/src/runtime.ts +34 -0
  219. package/skills/generate-social-posts/src/source.ts +116 -0
  220. package/skills/generate-social-posts/src/types.ts +58 -0
  221. package/skills/gif-maker/package.json +4 -1
  222. package/skills/github-manager/package.json +3 -1
  223. package/skills/gmail/CLAUDE.md +1 -1
  224. package/skills/highlight-reel-generator/src/index.ts +19 -0
  225. package/skills/hook/src/commands/create.ts +20 -845
  226. package/skills/hook/src/templates/root.ts +196 -0
  227. package/skills/hook/src/templates/source.ts +647 -0
  228. package/skills/http-server/package.json +3 -1
  229. package/skills/icon-pack/README.md +28 -0
  230. package/skills/icon-pack/SKILL.md +23 -0
  231. package/skills/icon-pack/package.json +29 -0
  232. package/skills/{audio → icon-pack}/tsconfig.json +10 -12
  233. package/skills/image/package.json +1 -2
  234. package/skills/implementation-agent/package.json +3 -1
  235. package/skills/implementation-agent/src/ai-generation.ts +225 -0
  236. package/skills/implementation-agent/src/index.ts +3 -960
  237. package/skills/implementation-agent/src/minimist.d.ts +15 -0
  238. package/skills/implementation-agent/src/templates.ts +686 -0
  239. package/skills/implementation-agent/src/types.ts +53 -0
  240. package/skills/implementation-plan/package.json +3 -1
  241. package/skills/implementation-todo/package.json +3 -1
  242. package/skills/invoice/package.json +1 -1
  243. package/skills/invoice/src/index.ts +3 -0
  244. package/skills/invoice-reconciliation/SKILL.md +42 -0
  245. package/skills/invoice-reconciliation/package.json +10 -0
  246. package/skills/landing-page-pack/SKILL.md +47 -0
  247. package/skills/landing-page-pack/package.json +14 -0
  248. package/skills/latex-table-generator/package.json +3 -1
  249. package/skills/logo-design/SKILL.md +25 -44
  250. package/skills/logo-design/package.json +3 -15
  251. package/skills/lorem-generator/package.json +3 -1
  252. package/skills/lorem-generator/src/index.ts +13 -0
  253. package/skills/managehook/package.json +1 -1
  254. package/skills/managehook/src/index.ts +3 -0
  255. package/skills/managemcp/package.json +1 -1
  256. package/skills/managemcp/src/index.ts +3 -0
  257. package/skills/manageskill/package.json +1 -1
  258. package/skills/manageskill/src/index.ts +3 -0
  259. package/skills/markdown-validator/package.json +3 -1
  260. package/skills/markdown-validator/src/index.ts +1 -4
  261. package/skills/market-research-report/SKILL.md +41 -0
  262. package/skills/market-research-report/package.json +10 -0
  263. package/skills/mcp-builder/package.json +4 -1
  264. package/skills/mcp-builder/src/ai-descriptions.ts +37 -0
  265. package/skills/mcp-builder/src/generators.ts +513 -0
  266. package/skills/mcp-builder/src/index.ts +7 -908
  267. package/skills/mcp-builder/src/minimist.d.ts +15 -0
  268. package/skills/mcp-builder/src/naming.ts +12 -0
  269. package/skills/mcp-builder/src/options.ts +170 -0
  270. package/skills/mcp-builder/src/templates.ts +149 -0
  271. package/skills/mcp-builder/src/types.ts +42 -0
  272. package/skills/meeting-pack/SKILL.md +43 -0
  273. package/skills/meeting-pack/package.json +10 -0
  274. package/skills/merge-pdfs/package.json +5 -1
  275. package/skills/migration-plan-pack/SKILL.md +45 -0
  276. package/skills/migration-plan-pack/package.json +10 -0
  277. package/skills/music/package.json +2 -3
  278. package/skills/music-album/SKILL.md +37 -0
  279. package/skills/music-album/package.json +10 -0
  280. package/skills/notion-manager/package.json +3 -1
  281. package/skills/npmpublish/CLAUDE.md +5 -8
  282. package/skills/npmpublish/README.md +5 -26
  283. package/skills/npmpublish/src/index.ts +9 -147
  284. package/skills/one-page-website/SKILL.md +46 -0
  285. package/skills/one-page-website/package.json +10 -0
  286. package/skills/one-page-website/tsconfig.json +8 -0
  287. package/skills/pdf-generate/src/cli.ts +162 -0
  288. package/skills/pdf-generate/src/html.ts +84 -0
  289. package/skills/pdf-generate/src/index.ts +11 -800
  290. package/skills/pdf-generate/src/markdown.ts +27 -0
  291. package/skills/pdf-generate/src/pdf-writer.ts +78 -0
  292. package/skills/pdf-generate/src/runtime.ts +34 -0
  293. package/skills/pdf-generate/src/security.ts +37 -0
  294. package/skills/pdf-generate/src/templates.ts +311 -0
  295. package/skills/pdf-generate/src/types.ts +28 -0
  296. package/skills/pdf-read/SKILL.md +10 -10
  297. package/skills/pdf-to-dataset/SKILL.md +45 -0
  298. package/skills/pdf-to-dataset/package.json +10 -0
  299. package/skills/pdf-to-markdown/SKILL.md +49 -0
  300. package/skills/pdf-to-markdown/package.json +10 -0
  301. package/skills/pdf-to-markdown/tsconfig.json +10 -0
  302. package/skills/performance-audit-report/SKILL.md +42 -0
  303. package/skills/performance-audit-report/package.json +10 -0
  304. package/skills/persona-based-adwriter/src/index.ts +19 -0
  305. package/skills/photo-album/SKILL.md +29 -0
  306. package/skills/photo-album/package.json +9 -0
  307. package/skills/photo-album/tsconfig.json +4 -0
  308. package/skills/pitch-deck/SKILL.md +43 -0
  309. package/skills/pitch-deck/package.json +9 -0
  310. package/skills/playlist-maker/SKILL.md +33 -0
  311. package/skills/playlist-maker/package.json +9 -0
  312. package/skills/playlist-maker/tsconfig.json +4 -0
  313. package/skills/product-mockup/SKILL.md +45 -0
  314. package/skills/product-mockup/package.json +3 -20
  315. package/skills/product-mockup/tsconfig.json +3 -5
  316. package/skills/project-retro-companion/src/index.ts +19 -0
  317. package/skills/proposal-pack/SKILL.md +45 -0
  318. package/skills/proposal-pack/package.json +10 -0
  319. package/skills/read-pdf/SKILL.md +5 -4
  320. package/skills/repo-onboarding-report/SKILL.md +42 -0
  321. package/skills/repo-onboarding-report/package.json +10 -0
  322. package/skills/sales-call-recapper/src/index.ts +20 -0
  323. package/skills/salescopy/package.json +1 -1
  324. package/skills/salescopy/src/index.ts +3 -0
  325. package/skills/scaffold-project/src/ai-detect.ts +136 -0
  326. package/skills/scaffold-project/src/file-generators.ts +292 -0
  327. package/skills/scaffold-project/src/index.ts +8 -991
  328. package/skills/scaffold-project/src/project-config.ts +338 -0
  329. package/skills/scaffold-project/src/templates.ts +173 -0
  330. package/skills/scaffold-project/src/types.ts +58 -0
  331. package/skills/scientific-figure-check/package.json +3 -1
  332. package/skills/sdk-generator/SKILL.md +45 -0
  333. package/skills/sdk-generator/package.json +10 -0
  334. package/skills/sdk-generator/tsconfig.json +8 -0
  335. package/skills/security-audit/src/index.ts +25 -6
  336. package/skills/security-audit-report/SKILL.md +40 -0
  337. package/skills/security-audit-report/package.json +10 -0
  338. package/skills/seo-content-pack/SKILL.md +44 -0
  339. package/skills/seo-content-pack/package.json +9 -0
  340. package/skills/short-video-pack/SKILL.md +30 -0
  341. package/skills/short-video-pack/package.json +10 -0
  342. package/skills/slack-assistant/package.json +3 -1
  343. package/skills/slide-deck-generator/SKILL.md +44 -0
  344. package/skills/slide-deck-generator/package.json +10 -0
  345. package/skills/sms/package.json +1 -1
  346. package/skills/sms/src/index.ts +15 -0
  347. package/skills/social-content-calendar/SKILL.md +45 -0
  348. package/skills/social-content-calendar/package.json +14 -0
  349. package/skills/split-pdf/package.json +4 -1
  350. package/skills/subtitle/package.json +2 -1
  351. package/skills/subtitle/src/index.ts +3 -0
  352. package/skills/terraform-generator/package.json +3 -1
  353. package/skills/test-suite-generator/SKILL.md +41 -0
  354. package/skills/test-suite-generator/package.json +10 -0
  355. package/skills/timesheet/package.json +1 -1
  356. package/skills/timesheet/src/index.ts +3 -0
  357. package/skills/transcript/SKILL.md +1 -8
  358. package/skills/validate-config/package.json +3 -1
  359. package/skills/video/package.json +6 -4
  360. package/skills/video-downloader/package.json +3 -1
  361. package/skills/video-highlight-pack/SKILL.md +44 -0
  362. package/skills/video-highlight-pack/package.json +10 -0
  363. package/skills/voiceover-jingle-pack/SKILL.md +28 -0
  364. package/skills/voiceover-jingle-pack/package.json +10 -0
  365. package/skills/watermark/package.json +6 -1
  366. package/skills/webcrawling/package.json +2 -1
  367. package/skills/write/SKILL.md +6 -6
  368. package/dist/server/serve.d.ts +0 -11
  369. package/skills/apidocs/.claude/settings.json +0 -5
  370. package/skills/audio/.env.example +0 -14
  371. package/skills/audio/QUICKSTART.md +0 -158
  372. package/skills/audio/README.md +0 -256
  373. package/skills/audio/src/index-local.ts +0 -206
  374. package/skills/audio/src/index.ts +0 -95
  375. package/skills/audio/src/providers/elevenlabs.ts +0 -115
  376. package/skills/audio/src/providers/google.ts +0 -116
  377. package/skills/audio/src/providers/minimax.ts +0 -83
  378. package/skills/audio/src/providers/openai.ts +0 -115
  379. package/skills/audio/src/types.ts +0 -79
  380. package/skills/audiobook-chapter-proofer/CLAUDE.md +0 -19
  381. package/skills/audiobook-chapter-proofer/package.json +0 -27
  382. package/skills/audiobook-chapter-proofer/src/index.ts +0 -285
  383. package/skills/browse/src/client.ts +0 -373
  384. package/skills/browse/src/index-local.ts +0 -430
  385. package/skills/browse/src/index.ts +0 -110
  386. package/skills/browse/src/sse-server.ts +0 -919
  387. package/skills/browse/src/types.ts +0 -104
  388. package/skills/consolelog/src/server/index.ts +0 -508
  389. package/skills/create-blog-article/CLAUDE.md +0 -19
  390. package/skills/create-blog-article/src/index.ts +0 -745
  391. package/skills/create-blog-article/tsconfig.json +0 -10
  392. package/skills/deepresearch/src/agents/query-generator.ts +0 -91
  393. package/skills/deepresearch/src/agents/synthesizer.ts +0 -111
  394. package/skills/deepresearch/src/index.ts +0 -224
  395. package/skills/deepresearch/src/research.ts +0 -166
  396. package/skills/deepresearch/src/services/anthropic.ts +0 -69
  397. package/skills/deepresearch/src/services/exa.ts +0 -108
  398. package/skills/deepresearch/src/services/firecrawl.ts +0 -88
  399. package/skills/deepresearch/src/services/openai.ts +0 -81
  400. package/skills/deepresearch/src/types.ts +0 -76
  401. package/skills/deepresearch/src/utils/file.ts +0 -111
  402. package/skills/deepresearch/src/utils/logger.ts +0 -84
  403. package/skills/domainpurchase/src/server/index.ts +0 -332
  404. package/skills/domainsearch/src/server/index.ts +0 -229
  405. package/skills/e2bswarm/README.md +0 -135
  406. package/skills/e2bswarm/SKILL.md +0 -118
  407. package/skills/e2bswarm/examples/tasks-example.json +0 -38
  408. package/skills/e2bswarm/package.json +0 -59
  409. package/skills/e2bswarm/src/commands/collect.ts +0 -135
  410. package/skills/e2bswarm/src/commands/install.ts +0 -164
  411. package/skills/e2bswarm/src/commands/kill.ts +0 -62
  412. package/skills/e2bswarm/src/commands/spawn.ts +0 -134
  413. package/skills/e2bswarm/src/commands/status.ts +0 -90
  414. package/skills/e2bswarm/src/commands/sync.ts +0 -208
  415. package/skills/e2bswarm/src/index.ts +0 -121
  416. package/skills/e2bswarm/src/lib/config.ts +0 -75
  417. package/skills/e2bswarm/src/lib/e2b.ts +0 -490
  418. package/skills/e2bswarm/src/lib/github.ts +0 -253
  419. package/skills/e2bswarm/src/lib/logger.ts +0 -41
  420. package/skills/e2bswarm/src/lib/paths.ts +0 -75
  421. package/skills/e2bswarm/src/lib/tasks.ts +0 -320
  422. package/skills/e2bswarm/src/types/index.ts +0 -107
  423. package/skills/e2bswarm/templates/codebox/e2b.Dockerfile +0 -38
  424. package/skills/e2bswarm/templates/codebox/e2b.toml +0 -3
  425. package/skills/e2bswarm/templates/setup.sh +0 -21
  426. package/skills/e2bswarm/tsconfig.json +0 -19
  427. package/skills/generate-book-cover/src/index.ts +0 -694
  428. package/skills/image/src/index-local.ts +0 -206
  429. package/skills/image/src/index.ts +0 -96
  430. package/skills/image/src/providers/google.ts +0 -79
  431. package/skills/image/src/providers/minimax.ts +0 -94
  432. package/skills/image/src/providers/openai.ts +0 -80
  433. package/skills/image/src/providers/xai.ts +0 -73
  434. package/skills/image/src/types.ts +0 -37
  435. package/skills/logo-design/CLAUDE.md +0 -30
  436. package/skills/logo-design/src/index.ts +0 -322
  437. package/skills/managehook/src/server/index.ts +0 -108
  438. package/skills/managemcp/src/server/index.ts +0 -108
  439. package/skills/manageskill/src/server/index.ts +0 -108
  440. package/skills/music/CLAUDE.md +0 -9
  441. package/skills/music/src/index.ts +0 -94
  442. package/skills/music/tsconfig.json +0 -10
  443. package/skills/pdf-read/src/index.ts +0 -320
  444. package/skills/product-mockup/CLAUDE.md +0 -19
  445. package/skills/product-mockup/src/index.ts +0 -290
  446. package/skills/read-pdf/src/index.ts +0 -388
  447. package/skills/remove-background/src/index.ts +0 -405
  448. package/skills/sound-effects/SKILL.md +0 -34
  449. package/skills/sound-effects/package.json +0 -21
  450. package/skills/sound-effects/src/index.ts +0 -172
  451. package/skills/sound-effects/tsconfig.json +0 -8
  452. package/skills/transcript/src/chunker.ts +0 -215
  453. package/skills/transcript/src/formatter.ts +0 -134
  454. package/skills/transcript/src/index-local.ts +0 -226
  455. package/skills/transcript/src/index.ts +0 -110
  456. package/skills/transcript/src/providers/elevenlabs.ts +0 -133
  457. package/skills/transcript/src/providers/gemini.ts +0 -192
  458. package/skills/transcript/src/providers/index.ts +0 -54
  459. package/skills/transcript/src/providers/openai.ts +0 -203
  460. package/skills/transcript/src/types.ts +0 -106
  461. package/skills/video/.env.example +0 -14
  462. package/skills/video/EXAMPLES.md +0 -266
  463. package/skills/video/LICENSE +0 -192
  464. package/skills/video/README.md +0 -174
  465. package/skills/video/src/cli.ts +0 -155
  466. package/skills/video/src/index-local.ts +0 -148
  467. package/skills/video/src/index.ts +0 -96
  468. package/skills/video/src/providers/google-veo.ts +0 -126
  469. package/skills/video/src/providers/index.ts +0 -22
  470. package/skills/video/src/providers/minimax.ts +0 -100
  471. package/skills/video/src/providers/openai-sora.ts +0 -164
  472. package/skills/video/src/providers/runway.ts +0 -159
  473. package/skills/video/src/types.ts +0 -35
  474. package/skills/video/tsconfig.json +0 -22
  475. package/skills/voiceover-casting-assistant/CLAUDE.md +0 -19
  476. package/skills/voiceover-casting-assistant/package.json +0 -27
  477. package/skills/voiceover-casting-assistant/src/index.ts +0 -255
  478. package/skills/voiceover-casting-assistant/tsconfig.json +0 -10
  479. package/skills/webcrawling/src/commands/config.ts +0 -34
  480. package/skills/webcrawling/src/commands/crawl.ts +0 -33
  481. package/skills/webcrawling/src/commands/scrape.ts +0 -32
  482. package/skills/webcrawling/src/commands/sessions.ts +0 -42
  483. package/skills/webcrawling/src/lib/crawler.ts +0 -174
  484. package/skills/webcrawling/src/lib/storage.ts +0 -130
  485. package/skills/webcrawling/src/types/index.ts +0 -45
  486. package/skills/webcrawling/src/utils/logger.ts +0 -30
  487. package/skills/webcrawling/src/utils/paths.ts +0 -28
  488. /package/skills/{audiobook-chapter-proofer → blog-article}/tsconfig.json +0 -0
@@ -1,745 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * Create Blog Article Skill
4
- * Generates complete blog articles with AI-generated images
5
- */
6
-
7
- import { parseArgs } from "util";
8
- import { mkdirSync, writeFileSync, appendFileSync, existsSync } from "fs";
9
- import { join, dirname } from "path";
10
- import { randomUUID } from "crypto";
11
-
12
- // Types
13
- interface ArticleOptions {
14
- topic: string;
15
- tone: "professional" | "casual" | "technical" | "friendly";
16
- length: "short" | "medium" | "long";
17
- images: number;
18
- style: "photorealistic" | "illustration" | "minimalist";
19
- seo: boolean;
20
- outlineOnly: boolean;
21
- output?: string;
22
- }
23
-
24
- interface ArticleOutline {
25
- title: string;
26
- metaDescription: string;
27
- introduction: string;
28
- sections: Array<{
29
- heading: string;
30
- subheadings?: string[];
31
- imagePrompt?: string;
32
- }>;
33
- conclusion: string;
34
- keywords: string[];
35
- }
36
-
37
- interface ArticleContent {
38
- title: string;
39
- metaDescription: string;
40
- featuredImageUrl?: string;
41
- introduction: string;
42
- sections: Array<{
43
- heading: string;
44
- content: string;
45
- imageUrl?: string;
46
- }>;
47
- conclusion: string;
48
- keywords: string[];
49
- tags: string[];
50
- wordCount: number;
51
- readingTime: number;
52
- }
53
-
54
- interface OpenAIChatResponse {
55
- choices: Array<{
56
- message: {
57
- content: string;
58
- };
59
- }>;
60
- usage?: {
61
- total_tokens: number;
62
- };
63
- }
64
-
65
- interface OpenAIImageResponse {
66
- data: Array<{
67
- url?: string;
68
- revised_prompt?: string;
69
- }>;
70
- }
71
-
72
- // =============================================================================
73
- // Security: HTML Escaping to prevent XSS
74
- // =============================================================================
75
-
76
- /**
77
- * Escape HTML special characters to prevent XSS attacks
78
- */
79
- function escapeHtml(str: string | undefined | null): string {
80
- if (str === undefined || str === null) return "";
81
- return String(str)
82
- .replace(/&/g, "&amp;")
83
- .replace(/</g, "&lt;")
84
- .replace(/>/g, "&gt;")
85
- .replace(/"/g, "&quot;")
86
- .replace(/'/g, "&#x27;");
87
- }
88
-
89
- // Constants
90
- const SKILL_NAME = "create-blog-article";
91
- const SESSION_ID = randomUUID().slice(0, 8);
92
-
93
- // Use SKILLS_OUTPUT_DIR from CLI if available, otherwise fall back to cwd
94
- const SKILLS_OUTPUT_DIR = process.env.SKILLS_OUTPUT_DIR || join(process.cwd(), ".skills");
95
- const EXPORTS_DIR = join(SKILLS_OUTPUT_DIR, "exports", SKILL_NAME);
96
- const LOGS_DIR = join(SKILLS_OUTPUT_DIR, "logs", SKILL_NAME);
97
-
98
- // Ensure directories exist
99
- function ensureDir(dir: string) {
100
- if (!existsSync(dir)) {
101
- mkdirSync(dir, { recursive: true });
102
- }
103
- }
104
-
105
- // Session timestamp for log filename
106
- const SESSION_TIMESTAMP = new Date().toISOString().replace(/[:.]/g, "_").replace(/-/g, "_").slice(0, 19).toLowerCase();
107
-
108
- // Logger
109
- function log(message: string, level: "info" | "error" | "success" = "info") {
110
- const timestamp = new Date().toISOString();
111
- const logFile = join(LOGS_DIR, `log_${SESSION_TIMESTAMP}_${SESSION_ID}.log`);
112
-
113
- ensureDir(LOGS_DIR);
114
-
115
- const logEntry = `[${timestamp}] [${level.toUpperCase()}] ${message}\n`;
116
- appendFileSync(logFile, logEntry);
117
-
118
- const prefix = level === "error" ? "āŒ" : level === "success" ? "āœ…" : "ā„¹ļø";
119
- if (level === "error") {
120
- console.error(`${prefix} ${message}`);
121
- } else {
122
- console.log(`${prefix} ${message}`);
123
- }
124
- }
125
-
126
- // Generate slug from text
127
- function slugify(text: string): string {
128
- return text
129
- .toLowerCase()
130
- .replace(/[^a-z0-9]+/g, "-")
131
- .replace(/^-|-$/g, "")
132
- .slice(0, 60);
133
- }
134
-
135
- // Calculate reading time (assuming 200 words per minute)
136
- function calculateReadingTime(wordCount: number): number {
137
- return Math.ceil(wordCount / 200);
138
- }
139
-
140
- // Count words in text
141
- function countWords(text: string): number {
142
- return text.split(/\s+/).filter(word => word.length > 0).length;
143
- }
144
-
145
- // Call OpenAI Chat API
146
- async function callOpenAI(prompt: string, systemPrompt: string): Promise<string> {
147
- const apiKey = process.env.OPENAI_API_KEY;
148
-
149
- if (!apiKey) {
150
- throw new Error("OPENAI_API_KEY environment variable is not set");
151
- }
152
-
153
- const response = await fetch("https://api.openai.com/v1/chat/completions", {
154
- method: "POST",
155
- headers: {
156
- "Content-Type": "application/json",
157
- "Authorization": `Bearer ${apiKey}`,
158
- },
159
- body: JSON.stringify({
160
- model: "gpt-4o-mini",
161
- messages: [
162
- { role: "system", content: systemPrompt },
163
- { role: "user", content: prompt },
164
- ],
165
- temperature: 0.7,
166
- max_tokens: 4000,
167
- }),
168
- });
169
-
170
- if (!response.ok) {
171
- const error = await response.json();
172
- throw new Error(`OpenAI API error: ${error.error?.message || response.statusText}`);
173
- }
174
-
175
- const data: OpenAIChatResponse = await response.json();
176
-
177
- if (!data.choices?.[0]?.message?.content) {
178
- throw new Error("No content returned from OpenAI");
179
- }
180
-
181
- return data.choices[0].message.content;
182
- }
183
-
184
- // Generate article outline
185
- async function generateOutline(options: ArticleOptions): Promise<ArticleOutline> {
186
- log(`Generating article outline for: "${options.topic}"`);
187
-
188
- const lengthGuide = {
189
- short: "3-4 sections, ~500 words total",
190
- medium: "5-6 sections, ~1000 words total",
191
- long: "7-9 sections, ~2000 words total",
192
- };
193
-
194
- const systemPrompt = `You are an expert content writer and SEO specialist. Generate a detailed article outline in JSON format. The outline should be engaging, well-structured, and optimized for readability.`;
195
-
196
- const userPrompt = `Create a detailed outline for a blog article with the following requirements:
197
-
198
- Topic: ${options.topic}
199
- Tone: ${options.tone}
200
- Length: ${options.length} (${lengthGuide[options.length]})
201
- Images: ${options.images} images will be generated
202
- ${options.seo ? "SEO: Include keywords and meta description optimized for search engines" : ""}
203
-
204
- Return a JSON object with this exact structure:
205
- {
206
- "title": "Compelling article title",
207
- "metaDescription": "SEO-optimized meta description (150-160 characters)",
208
- "introduction": "Brief outline of introduction paragraph",
209
- "sections": [
210
- {
211
- "heading": "Section heading",
212
- "subheadings": ["Optional subheading 1", "Optional subheading 2"],
213
- "imagePrompt": "Optional DALL-E prompt for section image"
214
- }
215
- ],
216
- "conclusion": "Brief outline of conclusion",
217
- "keywords": ["keyword1", "keyword2", "keyword3"]
218
- }
219
-
220
- Make the outline engaging and informative. ${options.images > 1 ? `Include imagePrompt for ${options.images - 1} sections (featured image will be generated separately).` : "No section images needed."}`;
221
-
222
- const response = await callOpenAI(userPrompt, systemPrompt);
223
-
224
- // Parse JSON response
225
- const jsonMatch = response.match(/\{[\s\S]*\}/);
226
- if (!jsonMatch) {
227
- throw new Error("Could not parse outline JSON from response");
228
- }
229
-
230
- const outline = JSON.parse(jsonMatch[0]);
231
- log(`Outline generated with ${outline.sections.length} sections`, "success");
232
-
233
- return outline;
234
- }
235
-
236
- // Generate full article content from outline
237
- async function generateArticleContent(outline: ArticleOutline, options: ArticleOptions): Promise<ArticleContent> {
238
- log(`Generating full article content`);
239
-
240
- const lengthGuide = {
241
- short: "500 words",
242
- medium: "1000 words",
243
- long: "2000 words",
244
- };
245
-
246
- const systemPrompt = `You are an expert content writer. Write engaging, informative blog articles with a ${options.tone} tone. Focus on providing value to readers with clear, well-structured content.`;
247
-
248
- const userPrompt = `Write a complete blog article based on this outline:
249
-
250
- Title: ${outline.title}
251
- Topic: ${options.topic}
252
- Tone: ${options.tone}
253
- Target Length: ${lengthGuide[options.length]}
254
-
255
- Introduction: ${outline.introduction}
256
-
257
- Sections:
258
- ${outline.sections.map((s, i) => `${i + 1}. ${s.heading}${s.subheadings ? "\n - " + s.subheadings.join("\n - ") : ""}`).join("\n")}
259
-
260
- Conclusion: ${outline.conclusion}
261
-
262
- Return a JSON object with this structure:
263
- {
264
- "introduction": "Full introduction paragraph(s)",
265
- "sections": [
266
- {
267
- "heading": "Section heading",
268
- "content": "Full section content with multiple paragraphs"
269
- }
270
- ],
271
- "conclusion": "Full conclusion paragraph(s)",
272
- "tags": ["tag1", "tag2", "tag3"]
273
- }
274
-
275
- Write naturally and engagingly. Each section should be substantial and informative.`;
276
-
277
- const response = await callOpenAI(userPrompt, systemPrompt);
278
-
279
- // Parse JSON response
280
- const jsonMatch = response.match(/\{[\s\S]*\}/);
281
- if (!jsonMatch) {
282
- throw new Error("Could not parse article JSON from response");
283
- }
284
-
285
- const content = JSON.parse(jsonMatch[0]);
286
-
287
- // Calculate word count
288
- const allText = [
289
- content.introduction,
290
- ...content.sections.map((s: { content: string }) => s.content),
291
- content.conclusion,
292
- ].join(" ");
293
-
294
- const wordCount = countWords(allText);
295
- const readingTime = calculateReadingTime(wordCount);
296
-
297
- log(`Article generated: ${wordCount} words, ${readingTime} min read`, "success");
298
-
299
- return {
300
- title: outline.title,
301
- metaDescription: outline.metaDescription,
302
- introduction: content.introduction,
303
- sections: content.sections.map((s: { heading: string; content: string }, i: number) => ({
304
- heading: s.heading,
305
- content: s.content,
306
- imageUrl: outline.sections[i]?.imagePrompt ? undefined : undefined, // Will be filled later
307
- })),
308
- conclusion: content.conclusion,
309
- keywords: outline.keywords,
310
- tags: content.tags || [],
311
- wordCount,
312
- readingTime,
313
- };
314
- }
315
-
316
- // Generate image using DALL-E
317
- async function generateImage(prompt: string, style: string): Promise<string> {
318
- const apiKey = process.env.OPENAI_API_KEY;
319
-
320
- if (!apiKey) {
321
- throw new Error("OPENAI_API_KEY environment variable is not set");
322
- }
323
-
324
- log(`Generating image: "${prompt.slice(0, 50)}..."`);
325
-
326
- const styleMap: Record<string, string> = {
327
- photorealistic: "photorealistic, professional photography, high quality",
328
- illustration: "digital illustration, clean lines, artistic",
329
- minimalist: "minimalist design, simple, clean, modern",
330
- };
331
-
332
- const enhancedPrompt = `${prompt}, ${styleMap[style] || styleMap.photorealistic}`;
333
-
334
- const response = await fetch("https://api.openai.com/v1/images/generations", {
335
- method: "POST",
336
- headers: {
337
- "Content-Type": "application/json",
338
- "Authorization": `Bearer ${apiKey}`,
339
- },
340
- body: JSON.stringify({
341
- model: "dall-e-3",
342
- prompt: enhancedPrompt,
343
- n: 1,
344
- size: "1792x1024",
345
- quality: "standard",
346
- response_format: "url",
347
- }),
348
- });
349
-
350
- if (!response.ok) {
351
- const error = await response.json();
352
- throw new Error(`OpenAI API error: ${error.error?.message || response.statusText}`);
353
- }
354
-
355
- const data: OpenAIImageResponse = await response.json();
356
-
357
- if (!data.data?.[0]?.url) {
358
- throw new Error("No image URL returned from OpenAI");
359
- }
360
-
361
- log(`Image generated successfully`, "success");
362
-
363
- return data.data[0].url;
364
- }
365
-
366
- // Download image from URL
367
- async function downloadImage(url: string, outputPath: string): Promise<void> {
368
- const response = await fetch(url);
369
-
370
- if (!response.ok) {
371
- throw new Error(`Failed to download image: ${response.statusText}`);
372
- }
373
-
374
- const buffer = await response.arrayBuffer();
375
- const dir = dirname(outputPath);
376
-
377
- ensureDir(dir);
378
- writeFileSync(outputPath, Buffer.from(buffer));
379
-
380
- log(`Image saved to: ${outputPath}`);
381
- }
382
-
383
- // Generate all images for article
384
- async function generateArticleImages(
385
- outline: ArticleOutline,
386
- content: ArticleContent,
387
- options: ArticleOptions,
388
- outputDir: string
389
- ): Promise<ArticleContent> {
390
- if (options.images === 0) {
391
- log("Skipping image generation (--images 0)");
392
- return content;
393
- }
394
-
395
- const imagesDir = join(outputDir, "images");
396
- ensureDir(imagesDir);
397
-
398
- // Generate featured image
399
- log("Generating featured image...");
400
- const featuredPrompt = `Blog article featured image for: ${content.title}`;
401
- const featuredUrl = await generateImage(featuredPrompt, options.style);
402
- const featuredPath = join(imagesDir, "featured.png");
403
- await downloadImage(featuredUrl, featuredPath);
404
- content.featuredImageUrl = featuredPath;
405
-
406
- // Generate section images if requested
407
- if (options.images > 1) {
408
- log(`Generating ${options.images - 1} section images...`);
409
-
410
- let imageCount = 0;
411
- for (let i = 0; i < outline.sections.length && imageCount < options.images - 1; i++) {
412
- const section = outline.sections[i];
413
- if (section.imagePrompt) {
414
- try {
415
- const imageUrl = await generateImage(section.imagePrompt, options.style);
416
- const imagePath = join(imagesDir, `section-${i + 1}.png`);
417
- await downloadImage(imageUrl, imagePath);
418
- content.sections[i].imageUrl = imagePath;
419
- imageCount++;
420
- } catch (error) {
421
- log(`Failed to generate image for section ${i + 1}: ${error}`, "error");
422
- }
423
- }
424
- }
425
- }
426
-
427
- log(`Generated ${options.images} image(s) successfully`, "success");
428
- return content;
429
- }
430
-
431
- // Export article as Markdown
432
- function exportMarkdown(content: ArticleContent, outputPath: string): void {
433
- let markdown = `---
434
- title: ${content.title}
435
- description: ${content.metaDescription}
436
- keywords: ${content.keywords.join(", ")}
437
- tags: ${content.tags.join(", ")}
438
- readingTime: ${content.readingTime} min
439
- wordCount: ${content.wordCount}
440
- ---
441
-
442
- # ${content.title}
443
-
444
- `;
445
-
446
- if (content.featuredImageUrl) {
447
- markdown += `![Featured Image](./images/featured.png)\n\n`;
448
- }
449
-
450
- markdown += `${content.introduction}\n\n`;
451
-
452
- for (const section of content.sections) {
453
- markdown += `## ${section.heading}\n\n`;
454
- markdown += `${section.content}\n\n`;
455
- if (section.imageUrl) {
456
- const imageName = section.imageUrl.split("/").pop();
457
- markdown += `![${section.heading}](./images/${imageName})\n\n`;
458
- }
459
- }
460
-
461
- markdown += `## Conclusion\n\n${content.conclusion}\n\n`;
462
-
463
- markdown += `---\n\n`;
464
- markdown += `**Keywords:** ${content.keywords.join(", ")}\n\n`;
465
- markdown += `**Tags:** ${content.tags.join(", ")}\n`;
466
-
467
- writeFileSync(outputPath, markdown);
468
- log(`Markdown exported to: ${outputPath}`);
469
- }
470
-
471
- // Export article as HTML
472
- function exportHTML(content: ArticleContent, outputPath: string): void {
473
- let html = `<!DOCTYPE html>
474
- <html lang="en">
475
- <head>
476
- <meta charset="UTF-8">
477
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
478
- <meta name="description" content="${escapeHtml(content.metaDescription)}">
479
- <meta name="keywords" content="${escapeHtml(content.keywords.join(", "))}">
480
- <title>${escapeHtml(content.title)}</title>
481
- <style>
482
- body {
483
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
484
- line-height: 1.6;
485
- max-width: 800px;
486
- margin: 0 auto;
487
- padding: 2rem;
488
- color: #333;
489
- }
490
- img {
491
- max-width: 100%;
492
- height: auto;
493
- border-radius: 8px;
494
- margin: 2rem 0;
495
- }
496
- h1 {
497
- font-size: 2.5rem;
498
- margin-bottom: 1rem;
499
- }
500
- h2 {
501
- font-size: 1.75rem;
502
- margin-top: 2rem;
503
- margin-bottom: 1rem;
504
- }
505
- .meta {
506
- color: #666;
507
- font-size: 0.9rem;
508
- margin-bottom: 2rem;
509
- }
510
- .tags {
511
- margin-top: 3rem;
512
- padding-top: 2rem;
513
- border-top: 1px solid #eee;
514
- }
515
- .tags span {
516
- display: inline-block;
517
- background: #f0f0f0;
518
- padding: 0.25rem 0.75rem;
519
- margin: 0.25rem;
520
- border-radius: 4px;
521
- font-size: 0.9rem;
522
- }
523
- </style>
524
- </head>
525
- <body>
526
- <article>
527
- <header>
528
- <h1>${escapeHtml(content.title)}</h1>
529
- <div class="meta">
530
- ${content.readingTime} min read • ${content.wordCount} words
531
- </div>
532
- </header>
533
-
534
- `;
535
-
536
- if (content.featuredImageUrl) {
537
- html += ` <img src="./images/featured.png" alt="Featured Image">\n\n`;
538
- }
539
-
540
- html += ` <p>${escapeHtml(content.introduction).replace(/\n/g, "</p>\n <p>")}</p>\n\n`;
541
-
542
- for (const section of content.sections) {
543
- html += ` <section>
544
- <h2>${escapeHtml(section.heading)}</h2>
545
- <p>${escapeHtml(section.content).replace(/\n/g, "</p>\n <p>")}</p>
546
- `;
547
- if (section.imageUrl) {
548
- const imageName = section.imageUrl.split("/").pop();
549
- html += ` <img src="./images/${imageName}" alt="${escapeHtml(section.heading)}">\n`;
550
- }
551
- html += ` </section>\n\n`;
552
- }
553
-
554
- html += ` <section>
555
- <h2>Conclusion</h2>
556
- <p>${escapeHtml(content.conclusion).replace(/\n/g, "</p>\n <p>")}</p>
557
- </section>
558
-
559
- <div class="tags">
560
- <strong>Tags:</strong>
561
- `;
562
-
563
- for (const tag of content.tags) {
564
- html += ` <span>${escapeHtml(tag)}</span>\n`;
565
- }
566
-
567
- html += ` </div>
568
- </article>
569
- </body>
570
- </html>`;
571
-
572
- writeFileSync(outputPath, html);
573
- log(`HTML exported to: ${outputPath}`);
574
- }
575
-
576
- // Export article as JSON
577
- function exportJSON(content: ArticleContent, outputPath: string): void {
578
- const json = JSON.stringify(content, null, 2);
579
- writeFileSync(outputPath, json);
580
- log(`JSON exported to: ${outputPath}`);
581
- }
582
-
583
- // Main function
584
- async function main() {
585
- const { values, positionals } = parseArgs({
586
- args: Bun.argv.slice(2),
587
- options: {
588
- tone: { type: "string", default: "professional" },
589
- length: { type: "string", default: "medium" },
590
- images: { type: "string", default: "1" },
591
- style: { type: "string", default: "photorealistic" },
592
- seo: { type: "boolean", default: false },
593
- "outline-only": { type: "boolean", default: false },
594
- output: { type: "string", short: "o" },
595
- help: { type: "boolean", short: "h" },
596
- },
597
- allowPositionals: true,
598
- });
599
-
600
- // Show help
601
- if (values.help || positionals.length === 0) {
602
- console.log(`
603
- Create Blog Article - Generate complete blog articles with AI-generated images
604
-
605
- Usage:
606
- bun run src/index.ts <topic> [options]
607
-
608
- Options:
609
- --tone <tone> Writing tone (professional, casual, technical, friendly) [default: professional]
610
- --length <length> Article length (short ~500w, medium ~1000w, long ~2000w) [default: medium]
611
- --images <number> Number of images (0, 1, 3, 5) [default: 1]
612
- --style <style> Image style (photorealistic, illustration, minimalist) [default: photorealistic]
613
- --seo Include SEO metadata and keywords [default: false]
614
- --outline-only Generate outline only, no full article [default: false]
615
- --output, -o <path> Custom output path
616
- --help, -h Show this help
617
-
618
- Examples:
619
- bun run src/index.ts "The Future of AI Development"
620
- bun run src/index.ts "How to Build REST APIs" --tone technical --length long
621
- bun run src/index.ts "Travel Tips" --seo --images 3 --style photorealistic
622
- bun run src/index.ts "Code Reviews" --outline-only
623
- `);
624
- process.exit(0);
625
- }
626
-
627
- const topic = positionals.join(" ");
628
-
629
- if (!topic) {
630
- log("Please provide a topic/title for the article", "error");
631
- process.exit(1);
632
- }
633
-
634
- // Validate options
635
- const validTones = ["professional", "casual", "technical", "friendly"];
636
- const validLengths = ["short", "medium", "long"];
637
- const validStyles = ["photorealistic", "illustration", "minimalist"];
638
- const validImageCounts = [0, 1, 3, 5];
639
-
640
- const tone = values.tone as string;
641
- const length = values.length as string;
642
- const style = values.style as string;
643
- const images = parseInt(values.images as string);
644
-
645
- if (!validTones.includes(tone)) {
646
- log(`Invalid tone: ${tone}. Must be one of: ${validTones.join(", ")}`, "error");
647
- process.exit(1);
648
- }
649
-
650
- if (!validLengths.includes(length)) {
651
- log(`Invalid length: ${length}. Must be one of: ${validLengths.join(", ")}`, "error");
652
- process.exit(1);
653
- }
654
-
655
- if (!validStyles.includes(style)) {
656
- log(`Invalid style: ${style}. Must be one of: ${validStyles.join(", ")}`, "error");
657
- process.exit(1);
658
- }
659
-
660
- if (!validImageCounts.includes(images)) {
661
- log(`Invalid images count: ${images}. Must be one of: ${validImageCounts.join(", ")}`, "error");
662
- process.exit(1);
663
- }
664
-
665
- const options: ArticleOptions = {
666
- topic,
667
- tone: tone as ArticleOptions["tone"],
668
- length: length as ArticleOptions["length"],
669
- images,
670
- style: style as ArticleOptions["style"],
671
- seo: values.seo as boolean,
672
- outlineOnly: values["outline-only"] as boolean,
673
- output: values.output as string | undefined,
674
- };
675
-
676
- try {
677
- log(`Session ID: ${SESSION_ID}`);
678
- log(`Topic: "${topic}"`);
679
- log(`Options: ${tone} tone, ${length} length, ${images} images, ${style} style`);
680
-
681
- // Determine output directory
682
- const timestamp = new Date().toISOString().replace(/[:.]/g, "_").replace(/-/g, "_").slice(0, 19).toLowerCase();
683
- const titleSlug = slugify(topic);
684
- const outputDir = options.output || join(EXPORTS_DIR, `export_${timestamp}_${titleSlug}`);
685
- ensureDir(outputDir);
686
-
687
- log(`Output directory: ${outputDir}`);
688
-
689
- // Step 1: Generate outline
690
- const outline = await generateOutline(options);
691
-
692
- if (options.outlineOnly) {
693
- // Export outline only
694
- const outlineJson = JSON.stringify(outline, null, 2);
695
- const outlinePath = join(outputDir, "outline.json");
696
- writeFileSync(outlinePath, outlineJson);
697
-
698
- console.log(`\n✨ Outline generated successfully!`);
699
- console.log(` šŸ“ Output: ${outlinePath}`);
700
- console.log(` šŸ“‹ Log: ${join(LOGS_DIR, `log_${SESSION_TIMESTAMP}_${SESSION_ID}.log`)}`);
701
- console.log(`\nšŸ“ Outline:`);
702
- console.log(` Title: ${outline.title}`);
703
- console.log(` Sections: ${outline.sections.length}`);
704
- console.log(` Keywords: ${outline.keywords.join(", ")}`);
705
-
706
- return;
707
- }
708
-
709
- // Step 2: Generate full article content
710
- let content = await generateArticleContent(outline, options);
711
-
712
- // Step 3: Generate images
713
- content = await generateArticleImages(outline, content, options, outputDir);
714
-
715
- // Step 4: Export in all formats
716
- log("Exporting article in multiple formats...");
717
-
718
- exportMarkdown(content, join(outputDir, "article.md"));
719
- exportHTML(content, join(outputDir, "article.html"));
720
- exportJSON(content, join(outputDir, "article.json"));
721
-
722
- console.log(`\n✨ Blog article generated successfully!`);
723
- console.log(` šŸ“ Output: ${outputDir}`);
724
- console.log(` šŸ“„ Formats: article.md, article.html, article.json`);
725
- if (options.images > 0) {
726
- console.log(` šŸ–¼ļø Images: ${options.images} image(s) in images/`);
727
- }
728
- console.log(` šŸ“‹ Log: ${join(LOGS_DIR, `log_${SESSION_TIMESTAMP}_${SESSION_ID}.log`)}`);
729
- console.log(`\nšŸ“Š Article Stats:`);
730
- console.log(` Title: ${content.title}`);
731
- console.log(` Words: ${content.wordCount}`);
732
- console.log(` Reading Time: ${content.readingTime} min`);
733
- console.log(` Sections: ${content.sections.length}`);
734
- console.log(` Tags: ${content.tags.join(", ")}`);
735
-
736
- } catch (error) {
737
- log(`Error: ${error instanceof Error ? error.message : "Unknown error"}`, "error");
738
- if (error instanceof Error && error.stack) {
739
- log(`Stack trace: ${error.stack}`, "error");
740
- }
741
- process.exit(1);
742
- }
743
- }
744
-
745
- main();