@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.
- package/LICENSE +1 -10
- package/README.md +141 -39
- package/bin/index.js +30122 -27575
- package/bin/mcp.js +22112 -18593
- package/dist/cli/cli.test-utils.d.ts +15 -0
- package/dist/cli/commands/auth.d.ts +2 -0
- package/dist/cli/commands/install.d.ts +1 -1
- package/dist/cli/commands/runtime-mcp.d.ts +4 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.js +11607 -597
- package/dist/lib/auth-store.d.ts +13 -0
- package/dist/lib/installer.d.ts +58 -55
- package/dist/lib/mcp-contracts.d.ts +86 -0
- package/dist/lib/project-state.d.ts +43 -0
- package/dist/lib/registry-data/business-marketing.d.ts +2 -0
- package/dist/lib/registry-data/communication.d.ts +2 -0
- package/dist/lib/registry-data/content-generation.d.ts +2 -0
- package/dist/lib/registry-data/data-analysis.d.ts +2 -0
- package/dist/lib/registry-data/design-branding.d.ts +2 -0
- package/dist/lib/registry-data/development-tools.d.ts +2 -0
- package/dist/lib/registry-data/education-learning.d.ts +2 -0
- package/dist/lib/registry-data/event-management.d.ts +2 -0
- package/dist/lib/registry-data/finance-compliance.d.ts +2 -0
- package/dist/lib/registry-data/health-wellness.d.ts +2 -0
- package/dist/lib/registry-data/index.d.ts +2 -0
- package/dist/lib/registry-data/media-processing.d.ts +2 -0
- package/dist/lib/registry-data/productivity-organization.d.ts +2 -0
- package/dist/lib/registry-data/project-management.d.ts +2 -0
- package/dist/lib/registry-data/research-writing.d.ts +2 -0
- package/dist/lib/registry-data/science-academic.d.ts +2 -0
- package/dist/lib/registry-data/travel-lifestyle.d.ts +2 -0
- package/dist/lib/registry-data/web-browser.d.ts +2 -0
- package/dist/lib/registry-types.d.ts +27 -0
- package/dist/lib/registry.d.ts +6 -18
- package/dist/lib/remote-registry.d.ts +3 -0
- package/dist/lib/run-state.d.ts +60 -0
- package/dist/lib/skill-aliases.d.ts +17 -0
- package/dist/lib/skillinfo.d.ts +5 -1
- package/dist/mcp/discovery-tools.d.ts +2 -0
- package/dist/mcp/helpers.d.ts +26 -0
- package/dist/mcp/http.d.ts +10 -0
- package/dist/mcp/index.d.ts +3 -2
- package/dist/mcp/operation-tools.d.ts +2 -0
- package/dist/mcp/resource-meta-tools.d.ts +2 -0
- package/dist/mcp/schedule-tools.d.ts +2 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/types/api.d.ts +7 -4
- package/package.json +23 -10
- package/skills/_common/http-client.ts +1 -1
- package/skills/_common/index.ts +2 -3
- package/skills/_common/install.sh +5 -110
- package/skills/_common/installer.ts +31 -282
- package/skills/_common/skill-install.ts +14 -181
- package/skills/ad-creative-pack/SKILL.md +45 -0
- package/skills/ad-creative-pack/package.json +14 -0
- package/skills/advanced-math/package.json +3 -1
- package/skills/advanced-math/src/calculators.ts +118 -0
- package/skills/advanced-math/src/cli.ts +130 -0
- package/skills/advanced-math/src/conversion.ts +90 -0
- package/skills/advanced-math/src/finance.ts +75 -0
- package/skills/advanced-math/src/formatting.ts +95 -0
- package/skills/advanced-math/src/index.ts +24 -702
- package/skills/advanced-math/src/runtime.ts +49 -0
- package/skills/advanced-math/src/symbolic.ts +110 -0
- package/skills/advanced-math/src/types.ts +36 -0
- package/skills/analyze-data/SKILL.md +2 -2
- package/skills/analyze-data/src/analysis.ts +401 -0
- package/skills/analyze-data/src/cli.ts +66 -0
- package/skills/analyze-data/src/formatters.ts +235 -0
- package/skills/analyze-data/src/index.ts +6 -1027
- package/skills/analyze-data/src/logger.ts +36 -0
- package/skills/analyze-data/src/parsers.ts +57 -0
- package/skills/analyze-data/src/stats.ts +151 -0
- package/skills/analyze-data/src/types.ts +85 -0
- package/skills/api-docs-portal/SKILL.md +46 -0
- package/skills/api-docs-portal/package.json +9 -0
- package/skills/api-test-suite/src/index.ts +13 -0
- package/skills/apidocs/package.json +1 -1
- package/skills/apidocs/src/index.ts +3 -0
- package/skills/audio/package.json +2 -3
- package/skills/audio-cleanup-lab/SKILL.md +2 -2
- package/skills/audio-extract/CLAUDE.md +1 -1
- package/skills/audio-transcript-pack/SKILL.md +43 -0
- package/skills/audio-transcript-pack/package.json +10 -0
- package/skills/blog-article/CLAUDE.md +12 -0
- package/skills/blog-article/SKILL.md +45 -0
- package/skills/{create-blog-article → blog-article}/package.json +3 -3
- package/skills/brand-kit/SKILL.md +45 -0
- package/skills/brand-kit/package.json +14 -0
- package/skills/brand-photo-shoot/SKILL.md +28 -0
- package/skills/brand-photo-shoot/package.json +10 -0
- package/skills/brand-style-guide/SKILL.md +2 -2
- package/skills/brand-style-guide/src/index.ts +0 -0
- package/skills/budget-variance-analyzer/SKILL.md +2 -2
- package/skills/businessactivity/package.json +1 -1
- package/skills/businessactivity/src/index.ts +3 -0
- package/skills/calendar-events/src/ai-parser.ts +103 -0
- package/skills/calendar-events/src/api.ts +157 -0
- package/skills/calendar-events/src/auth.ts +22 -0
- package/skills/calendar-events/src/config.ts +6 -0
- package/skills/calendar-events/src/format.ts +96 -0
- package/skills/calendar-events/src/help.ts +54 -0
- package/skills/calendar-events/src/index.ts +21 -524
- package/skills/calendar-events/src/logger.ts +34 -0
- package/skills/calendar-events/src/types.ts +67 -0
- package/skills/compress-video/SKILL.md +2 -2
- package/skills/consolelog/package.json +1 -1
- package/skills/consolelog/src/index.ts +3 -0
- package/skills/contract-review-report/SKILL.md +43 -0
- package/skills/contract-review-report/package.json +10 -0
- package/skills/convert/SKILL.md +2 -3
- package/skills/customer-feedback-report/SKILL.md +44 -0
- package/skills/customer-feedback-report/package.json +10 -0
- package/skills/dashboard-builder/package.json +3 -1
- package/skills/database-explorer/package.json +3 -1
- package/skills/deepresearch/README.md +4 -13
- package/skills/deploy/src/http-client.ts +1 -1
- package/skills/diff-viewer/package.json +4 -1
- package/skills/doc-generate/package.json +0 -1
- package/skills/doc-generate/src/ai.ts +50 -0
- package/skills/doc-generate/src/cli.ts +203 -0
- package/skills/doc-generate/src/dependencies.ts +44 -0
- package/skills/doc-generate/src/document-builder.ts +299 -0
- package/skills/doc-generate/src/index.ts +40 -764
- package/skills/doc-generate/src/markdown-parser.ts +125 -0
- package/skills/doc-generate/src/types.ts +68 -0
- package/skills/domainpurchase/SKILL.md +1 -1
- package/skills/domainpurchase/package.json +1 -1
- package/skills/domainpurchase/src/index.ts +3 -0
- package/skills/domainsearch/SKILL.md +1 -1
- package/skills/domainsearch/package.json +1 -1
- package/skills/domainsearch/src/index.ts +3 -0
- package/skills/email-sequence/SKILL.md +44 -0
- package/skills/email-sequence/package.json +14 -0
- package/skills/excel/CLAUDE.md +2 -2
- package/skills/experiment-power-calculator/package.json +3 -1
- package/skills/extract-invoice/src/cli.ts +97 -0
- package/skills/extract-invoice/src/extractor.ts +170 -0
- package/skills/extract-invoice/src/file-utils.ts +46 -0
- package/skills/extract-invoice/src/formatters.ts +144 -0
- package/skills/extract-invoice/src/index.ts +44 -629
- package/skills/extract-invoice/src/runtime.ts +46 -0
- package/skills/extract-invoice/src/types.ts +88 -0
- package/skills/folder-tree/package.json +3 -1
- package/skills/form-filler/package.json +3 -1
- package/skills/generate-api-client/package.json +3 -1
- package/skills/generate-api-client/src/generator.ts +47 -0
- package/skills/generate-api-client/src/index.ts +3 -777
- package/skills/generate-api-client/src/logger.ts +34 -0
- package/skills/generate-api-client/src/python-generator.ts +245 -0
- package/skills/generate-api-client/src/spec-loader.ts +48 -0
- package/skills/generate-api-client/src/type-mappers.ts +79 -0
- package/skills/generate-api-client/src/types.ts +76 -0
- package/skills/generate-api-client/src/typescript-generator.ts +247 -0
- package/skills/generate-book-cover/package.json +3 -1
- package/skills/generate-dockerfile/src/cli.ts +78 -0
- package/skills/generate-dockerfile/src/dockerfile-templates.ts +392 -0
- package/skills/generate-dockerfile/src/index.ts +12 -790
- package/skills/generate-dockerfile/src/logger.ts +30 -0
- package/skills/generate-dockerfile/src/project-detection.ts +68 -0
- package/skills/generate-dockerfile/src/support-files.ts +171 -0
- package/skills/generate-dockerfile/src/types.ts +29 -0
- package/skills/generate-documentation/src/ai.ts +131 -0
- package/skills/generate-documentation/src/cli.ts +71 -0
- package/skills/generate-documentation/src/code-parser.ts +300 -0
- package/skills/generate-documentation/src/file-processing.ts +182 -0
- package/skills/generate-documentation/src/index.ts +13 -753
- package/skills/generate-documentation/src/runtime.ts +35 -0
- package/skills/generate-documentation/src/types.ts +30 -0
- package/skills/generate-env/package.json +3 -1
- package/skills/generate-env/src/cli.ts +85 -0
- package/skills/generate-env/src/detection.ts +161 -0
- package/skills/generate-env/src/env-data.ts +66 -0
- package/skills/generate-env/src/generators.ts +240 -0
- package/skills/generate-env/src/index.ts +76 -676
- package/skills/generate-env/src/runtime.ts +30 -0
- package/skills/generate-env/src/types.ts +32 -0
- package/skills/generate-favicon/package.json +3 -1
- package/skills/generate-mock-data/package.json +3 -1
- package/skills/generate-mock-data/src/ai.ts +102 -0
- package/skills/generate-mock-data/src/formatters.ts +84 -0
- package/skills/generate-mock-data/src/generator.ts +377 -0
- package/skills/generate-mock-data/src/index.ts +15 -716
- package/skills/generate-mock-data/src/logger.ts +37 -0
- package/skills/generate-mock-data/src/presets.ts +110 -0
- package/skills/generate-mock-data/src/types.ts +21 -0
- package/skills/generate-pr-description/src/ai.ts +144 -0
- package/skills/generate-pr-description/src/cli.ts +80 -0
- package/skills/generate-pr-description/src/clipboard.ts +30 -0
- package/skills/generate-pr-description/src/formatters.ts +231 -0
- package/skills/generate-pr-description/src/git.ts +153 -0
- package/skills/generate-pr-description/src/index.ts +21 -714
- package/skills/generate-pr-description/src/types.ts +49 -0
- package/skills/generate-presentation/src/ai-clients.ts +61 -0
- package/skills/generate-presentation/src/cli.ts +126 -0
- package/skills/generate-presentation/src/index.ts +3 -751
- package/skills/generate-presentation/src/logger.ts +67 -0
- package/skills/generate-presentation/src/presentation-generator.ts +425 -0
- package/skills/generate-presentation/src/runtime.ts +6 -0
- package/skills/generate-presentation/src/security.ts +12 -0
- package/skills/generate-presentation/src/types.ts +28 -0
- package/skills/generate-qrcode/package.json +4 -1
- package/skills/generate-regex/package.json +3 -1
- package/skills/generate-resume/src/cli.ts +157 -0
- package/skills/generate-resume/src/index.ts +13 -917
- package/skills/generate-resume/src/parsers.ts +95 -0
- package/skills/generate-resume/src/renderers.ts +538 -0
- package/skills/generate-resume/src/security.ts +39 -0
- package/skills/generate-resume/src/types.ts +86 -0
- package/skills/generate-social-posts/src/ai.ts +88 -0
- package/skills/generate-social-posts/src/cli.ts +118 -0
- package/skills/generate-social-posts/src/exporters.ts +126 -0
- package/skills/generate-social-posts/src/generator.ts +130 -0
- package/skills/generate-social-posts/src/index.ts +19 -709
- package/skills/generate-social-posts/src/platforms.ts +39 -0
- package/skills/generate-social-posts/src/runtime.ts +34 -0
- package/skills/generate-social-posts/src/source.ts +116 -0
- package/skills/generate-social-posts/src/types.ts +58 -0
- package/skills/gif-maker/package.json +4 -1
- package/skills/github-manager/package.json +3 -1
- package/skills/gmail/CLAUDE.md +1 -1
- package/skills/highlight-reel-generator/src/index.ts +19 -0
- package/skills/hook/src/commands/create.ts +20 -845
- package/skills/hook/src/templates/root.ts +196 -0
- package/skills/hook/src/templates/source.ts +647 -0
- package/skills/http-server/package.json +3 -1
- package/skills/icon-pack/README.md +28 -0
- package/skills/icon-pack/SKILL.md +23 -0
- package/skills/icon-pack/package.json +29 -0
- package/skills/{audio → icon-pack}/tsconfig.json +10 -12
- package/skills/image/package.json +1 -2
- package/skills/implementation-agent/package.json +3 -1
- package/skills/implementation-agent/src/ai-generation.ts +225 -0
- package/skills/implementation-agent/src/index.ts +3 -960
- package/skills/implementation-agent/src/minimist.d.ts +15 -0
- package/skills/implementation-agent/src/templates.ts +686 -0
- package/skills/implementation-agent/src/types.ts +53 -0
- package/skills/implementation-plan/package.json +3 -1
- package/skills/implementation-todo/package.json +3 -1
- package/skills/invoice/package.json +1 -1
- package/skills/invoice/src/index.ts +3 -0
- package/skills/invoice-reconciliation/SKILL.md +42 -0
- package/skills/invoice-reconciliation/package.json +10 -0
- package/skills/landing-page-pack/SKILL.md +47 -0
- package/skills/landing-page-pack/package.json +14 -0
- package/skills/latex-table-generator/package.json +3 -1
- package/skills/logo-design/SKILL.md +25 -44
- package/skills/logo-design/package.json +3 -15
- package/skills/lorem-generator/package.json +3 -1
- package/skills/lorem-generator/src/index.ts +13 -0
- package/skills/managehook/package.json +1 -1
- package/skills/managehook/src/index.ts +3 -0
- package/skills/managemcp/package.json +1 -1
- package/skills/managemcp/src/index.ts +3 -0
- package/skills/manageskill/package.json +1 -1
- package/skills/manageskill/src/index.ts +3 -0
- package/skills/markdown-validator/package.json +3 -1
- package/skills/markdown-validator/src/index.ts +1 -4
- package/skills/market-research-report/SKILL.md +41 -0
- package/skills/market-research-report/package.json +10 -0
- package/skills/mcp-builder/package.json +4 -1
- package/skills/mcp-builder/src/ai-descriptions.ts +37 -0
- package/skills/mcp-builder/src/generators.ts +513 -0
- package/skills/mcp-builder/src/index.ts +7 -908
- package/skills/mcp-builder/src/minimist.d.ts +15 -0
- package/skills/mcp-builder/src/naming.ts +12 -0
- package/skills/mcp-builder/src/options.ts +170 -0
- package/skills/mcp-builder/src/templates.ts +149 -0
- package/skills/mcp-builder/src/types.ts +42 -0
- package/skills/meeting-pack/SKILL.md +43 -0
- package/skills/meeting-pack/package.json +10 -0
- package/skills/merge-pdfs/package.json +5 -1
- package/skills/migration-plan-pack/SKILL.md +45 -0
- package/skills/migration-plan-pack/package.json +10 -0
- package/skills/music/package.json +2 -3
- package/skills/music-album/SKILL.md +37 -0
- package/skills/music-album/package.json +10 -0
- package/skills/notion-manager/package.json +3 -1
- package/skills/npmpublish/CLAUDE.md +5 -8
- package/skills/npmpublish/README.md +5 -26
- package/skills/npmpublish/src/index.ts +9 -147
- package/skills/one-page-website/SKILL.md +46 -0
- package/skills/one-page-website/package.json +10 -0
- package/skills/one-page-website/tsconfig.json +8 -0
- package/skills/pdf-generate/src/cli.ts +162 -0
- package/skills/pdf-generate/src/html.ts +84 -0
- package/skills/pdf-generate/src/index.ts +11 -800
- package/skills/pdf-generate/src/markdown.ts +27 -0
- package/skills/pdf-generate/src/pdf-writer.ts +78 -0
- package/skills/pdf-generate/src/runtime.ts +34 -0
- package/skills/pdf-generate/src/security.ts +37 -0
- package/skills/pdf-generate/src/templates.ts +311 -0
- package/skills/pdf-generate/src/types.ts +28 -0
- package/skills/pdf-read/SKILL.md +10 -10
- package/skills/pdf-to-dataset/SKILL.md +45 -0
- package/skills/pdf-to-dataset/package.json +10 -0
- package/skills/pdf-to-markdown/SKILL.md +49 -0
- package/skills/pdf-to-markdown/package.json +10 -0
- package/skills/pdf-to-markdown/tsconfig.json +10 -0
- package/skills/performance-audit-report/SKILL.md +42 -0
- package/skills/performance-audit-report/package.json +10 -0
- package/skills/persona-based-adwriter/src/index.ts +19 -0
- package/skills/photo-album/SKILL.md +29 -0
- package/skills/photo-album/package.json +9 -0
- package/skills/photo-album/tsconfig.json +4 -0
- package/skills/pitch-deck/SKILL.md +43 -0
- package/skills/pitch-deck/package.json +9 -0
- package/skills/playlist-maker/SKILL.md +33 -0
- package/skills/playlist-maker/package.json +9 -0
- package/skills/playlist-maker/tsconfig.json +4 -0
- package/skills/product-mockup/SKILL.md +45 -0
- package/skills/product-mockup/package.json +3 -20
- package/skills/product-mockup/tsconfig.json +3 -5
- package/skills/project-retro-companion/src/index.ts +19 -0
- package/skills/proposal-pack/SKILL.md +45 -0
- package/skills/proposal-pack/package.json +10 -0
- package/skills/read-pdf/SKILL.md +5 -4
- package/skills/repo-onboarding-report/SKILL.md +42 -0
- package/skills/repo-onboarding-report/package.json +10 -0
- package/skills/sales-call-recapper/src/index.ts +20 -0
- package/skills/salescopy/package.json +1 -1
- package/skills/salescopy/src/index.ts +3 -0
- package/skills/scaffold-project/src/ai-detect.ts +136 -0
- package/skills/scaffold-project/src/file-generators.ts +292 -0
- package/skills/scaffold-project/src/index.ts +8 -991
- package/skills/scaffold-project/src/project-config.ts +338 -0
- package/skills/scaffold-project/src/templates.ts +173 -0
- package/skills/scaffold-project/src/types.ts +58 -0
- package/skills/scientific-figure-check/package.json +3 -1
- package/skills/sdk-generator/SKILL.md +45 -0
- package/skills/sdk-generator/package.json +10 -0
- package/skills/sdk-generator/tsconfig.json +8 -0
- package/skills/security-audit/src/index.ts +25 -6
- package/skills/security-audit-report/SKILL.md +40 -0
- package/skills/security-audit-report/package.json +10 -0
- package/skills/seo-content-pack/SKILL.md +44 -0
- package/skills/seo-content-pack/package.json +9 -0
- package/skills/short-video-pack/SKILL.md +30 -0
- package/skills/short-video-pack/package.json +10 -0
- package/skills/slack-assistant/package.json +3 -1
- package/skills/slide-deck-generator/SKILL.md +44 -0
- package/skills/slide-deck-generator/package.json +10 -0
- package/skills/sms/package.json +1 -1
- package/skills/sms/src/index.ts +15 -0
- package/skills/social-content-calendar/SKILL.md +45 -0
- package/skills/social-content-calendar/package.json +14 -0
- package/skills/split-pdf/package.json +4 -1
- package/skills/subtitle/package.json +2 -1
- package/skills/subtitle/src/index.ts +3 -0
- package/skills/terraform-generator/package.json +3 -1
- package/skills/test-suite-generator/SKILL.md +41 -0
- package/skills/test-suite-generator/package.json +10 -0
- package/skills/timesheet/package.json +1 -1
- package/skills/timesheet/src/index.ts +3 -0
- package/skills/transcript/SKILL.md +1 -8
- package/skills/validate-config/package.json +3 -1
- package/skills/video/package.json +6 -4
- package/skills/video-downloader/package.json +3 -1
- package/skills/video-highlight-pack/SKILL.md +44 -0
- package/skills/video-highlight-pack/package.json +10 -0
- package/skills/voiceover-jingle-pack/SKILL.md +28 -0
- package/skills/voiceover-jingle-pack/package.json +10 -0
- package/skills/watermark/package.json +6 -1
- package/skills/webcrawling/package.json +2 -1
- package/skills/write/SKILL.md +6 -6
- package/dist/server/serve.d.ts +0 -11
- package/skills/apidocs/.claude/settings.json +0 -5
- package/skills/audio/.env.example +0 -14
- package/skills/audio/QUICKSTART.md +0 -158
- package/skills/audio/README.md +0 -256
- package/skills/audio/src/index-local.ts +0 -206
- package/skills/audio/src/index.ts +0 -95
- package/skills/audio/src/providers/elevenlabs.ts +0 -115
- package/skills/audio/src/providers/google.ts +0 -116
- package/skills/audio/src/providers/minimax.ts +0 -83
- package/skills/audio/src/providers/openai.ts +0 -115
- package/skills/audio/src/types.ts +0 -79
- package/skills/audiobook-chapter-proofer/CLAUDE.md +0 -19
- package/skills/audiobook-chapter-proofer/package.json +0 -27
- package/skills/audiobook-chapter-proofer/src/index.ts +0 -285
- package/skills/browse/src/client.ts +0 -373
- package/skills/browse/src/index-local.ts +0 -430
- package/skills/browse/src/index.ts +0 -110
- package/skills/browse/src/sse-server.ts +0 -919
- package/skills/browse/src/types.ts +0 -104
- package/skills/consolelog/src/server/index.ts +0 -508
- package/skills/create-blog-article/CLAUDE.md +0 -19
- package/skills/create-blog-article/src/index.ts +0 -745
- package/skills/create-blog-article/tsconfig.json +0 -10
- package/skills/deepresearch/src/agents/query-generator.ts +0 -91
- package/skills/deepresearch/src/agents/synthesizer.ts +0 -111
- package/skills/deepresearch/src/index.ts +0 -224
- package/skills/deepresearch/src/research.ts +0 -166
- package/skills/deepresearch/src/services/anthropic.ts +0 -69
- package/skills/deepresearch/src/services/exa.ts +0 -108
- package/skills/deepresearch/src/services/firecrawl.ts +0 -88
- package/skills/deepresearch/src/services/openai.ts +0 -81
- package/skills/deepresearch/src/types.ts +0 -76
- package/skills/deepresearch/src/utils/file.ts +0 -111
- package/skills/deepresearch/src/utils/logger.ts +0 -84
- package/skills/domainpurchase/src/server/index.ts +0 -332
- package/skills/domainsearch/src/server/index.ts +0 -229
- package/skills/e2bswarm/README.md +0 -135
- package/skills/e2bswarm/SKILL.md +0 -118
- package/skills/e2bswarm/examples/tasks-example.json +0 -38
- package/skills/e2bswarm/package.json +0 -59
- package/skills/e2bswarm/src/commands/collect.ts +0 -135
- package/skills/e2bswarm/src/commands/install.ts +0 -164
- package/skills/e2bswarm/src/commands/kill.ts +0 -62
- package/skills/e2bswarm/src/commands/spawn.ts +0 -134
- package/skills/e2bswarm/src/commands/status.ts +0 -90
- package/skills/e2bswarm/src/commands/sync.ts +0 -208
- package/skills/e2bswarm/src/index.ts +0 -121
- package/skills/e2bswarm/src/lib/config.ts +0 -75
- package/skills/e2bswarm/src/lib/e2b.ts +0 -490
- package/skills/e2bswarm/src/lib/github.ts +0 -253
- package/skills/e2bswarm/src/lib/logger.ts +0 -41
- package/skills/e2bswarm/src/lib/paths.ts +0 -75
- package/skills/e2bswarm/src/lib/tasks.ts +0 -320
- package/skills/e2bswarm/src/types/index.ts +0 -107
- package/skills/e2bswarm/templates/codebox/e2b.Dockerfile +0 -38
- package/skills/e2bswarm/templates/codebox/e2b.toml +0 -3
- package/skills/e2bswarm/templates/setup.sh +0 -21
- package/skills/e2bswarm/tsconfig.json +0 -19
- package/skills/generate-book-cover/src/index.ts +0 -694
- package/skills/image/src/index-local.ts +0 -206
- package/skills/image/src/index.ts +0 -96
- package/skills/image/src/providers/google.ts +0 -79
- package/skills/image/src/providers/minimax.ts +0 -94
- package/skills/image/src/providers/openai.ts +0 -80
- package/skills/image/src/providers/xai.ts +0 -73
- package/skills/image/src/types.ts +0 -37
- package/skills/logo-design/CLAUDE.md +0 -30
- package/skills/logo-design/src/index.ts +0 -322
- package/skills/managehook/src/server/index.ts +0 -108
- package/skills/managemcp/src/server/index.ts +0 -108
- package/skills/manageskill/src/server/index.ts +0 -108
- package/skills/music/CLAUDE.md +0 -9
- package/skills/music/src/index.ts +0 -94
- package/skills/music/tsconfig.json +0 -10
- package/skills/pdf-read/src/index.ts +0 -320
- package/skills/product-mockup/CLAUDE.md +0 -19
- package/skills/product-mockup/src/index.ts +0 -290
- package/skills/read-pdf/src/index.ts +0 -388
- package/skills/remove-background/src/index.ts +0 -405
- package/skills/scaffold-project/my-app/.env.example +0 -2
- package/skills/scaffold-project/my-app/README.md +0 -72
- package/skills/scaffold-project/my-app/package.json +0 -29
- package/skills/scaffold-project/my-app/src/index.ts +0 -23
- package/skills/scaffold-project/my-app/tsconfig.json +0 -33
- package/skills/sound-effects/SKILL.md +0 -34
- package/skills/sound-effects/package.json +0 -21
- package/skills/sound-effects/src/index.ts +0 -172
- package/skills/sound-effects/tsconfig.json +0 -8
- package/skills/transcript/src/chunker.ts +0 -215
- package/skills/transcript/src/formatter.ts +0 -134
- package/skills/transcript/src/index-local.ts +0 -226
- package/skills/transcript/src/index.ts +0 -110
- package/skills/transcript/src/providers/elevenlabs.ts +0 -133
- package/skills/transcript/src/providers/gemini.ts +0 -192
- package/skills/transcript/src/providers/index.ts +0 -54
- package/skills/transcript/src/providers/openai.ts +0 -203
- package/skills/transcript/src/types.ts +0 -106
- package/skills/video/.env.example +0 -14
- package/skills/video/EXAMPLES.md +0 -266
- package/skills/video/LICENSE +0 -192
- package/skills/video/README.md +0 -174
- package/skills/video/src/cli.ts +0 -155
- package/skills/video/src/index-local.ts +0 -148
- package/skills/video/src/index.ts +0 -96
- package/skills/video/src/providers/google-veo.ts +0 -126
- package/skills/video/src/providers/index.ts +0 -22
- package/skills/video/src/providers/minimax.ts +0 -100
- package/skills/video/src/providers/openai-sora.ts +0 -164
- package/skills/video/src/providers/runway.ts +0 -159
- package/skills/video/src/types.ts +0 -35
- package/skills/video/tsconfig.json +0 -22
- package/skills/voiceover-casting-assistant/CLAUDE.md +0 -19
- package/skills/voiceover-casting-assistant/package.json +0 -27
- package/skills/voiceover-casting-assistant/src/index.ts +0 -255
- package/skills/voiceover-casting-assistant/tsconfig.json +0 -10
- package/skills/webcrawling/src/commands/config.ts +0 -34
- package/skills/webcrawling/src/commands/crawl.ts +0 -33
- package/skills/webcrawling/src/commands/scrape.ts +0 -32
- package/skills/webcrawling/src/commands/sessions.ts +0 -42
- package/skills/webcrawling/src/lib/crawler.ts +0 -174
- package/skills/webcrawling/src/lib/storage.ts +0 -130
- package/skills/webcrawling/src/types/index.ts +0 -45
- package/skills/webcrawling/src/utils/logger.ts +0 -30
- package/skills/webcrawling/src/utils/paths.ts +0 -28
- /package/skills/{audiobook-chapter-proofer → blog-article}/tsconfig.json +0 -0
|
@@ -1,762 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
/**
|
|
3
3
|
* Generate Documentation Skill
|
|
4
|
-
* Auto-generates JSDoc/TSDoc/Python docstrings from code using AI analysis
|
|
5
|
-
*
|
|
6
|
-
* Features:
|
|
7
|
-
* - Multi-language support (TypeScript, JavaScript, Python)
|
|
8
|
-
* - AI-powered analysis using Anthropic Claude or OpenAI
|
|
9
|
-
* - Inline insertion or separate markdown output
|
|
10
|
-
* - Batch processing of directories
|
|
11
|
-
* - Intelligent type inference and parameter analysis
|
|
4
|
+
* Auto-generates JSDoc/TSDoc/Python docstrings from code using AI analysis.
|
|
12
5
|
*/
|
|
13
6
|
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
import { parseGenerateOptions } from "./cli";
|
|
9
|
+
import {
|
|
10
|
+
collectFiles,
|
|
11
|
+
generateMarkdownDocs,
|
|
12
|
+
insertDocumentation,
|
|
13
|
+
processFile,
|
|
14
|
+
} from "./file-processing";
|
|
15
|
+
import { EXPORTS_DIR, LOGS_DIR, SESSION_ID, SESSION_TIMESTAMP, log } from "./runtime";
|
|
16
|
+
import type { DocumentationResult } from "./types";
|
|
18
17
|
|
|
19
|
-
// Types
|
|
20
|
-
type DocFormat = "jsdoc" | "tsdoc" | "python" | "auto";
|
|
21
|
-
type OutputMode = "inline" | string; // inline or file path
|
|
22
|
-
type ApiProvider = "anthropic" | "openai";
|
|
23
|
-
|
|
24
|
-
interface GenerateOptions {
|
|
25
|
-
path: string;
|
|
26
|
-
format: DocFormat;
|
|
27
|
-
output: OutputMode;
|
|
28
|
-
includeExamples: boolean;
|
|
29
|
-
update: boolean;
|
|
30
|
-
verbose: boolean;
|
|
31
|
-
apiProvider: ApiProvider;
|
|
32
|
-
model?: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
interface CodeElement {
|
|
36
|
-
type: "function" | "class" | "method" | "interface" | "type";
|
|
37
|
-
name: string;
|
|
38
|
-
code: string;
|
|
39
|
-
startLine: number;
|
|
40
|
-
endLine: number;
|
|
41
|
-
hasExistingDoc: boolean;
|
|
42
|
-
language: "typescript" | "javascript" | "python";
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
interface DocumentationResult {
|
|
46
|
-
element: CodeElement;
|
|
47
|
-
documentation: string;
|
|
48
|
-
updated: boolean;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Constants
|
|
52
|
-
const SKILL_NAME = "generate-documentation";
|
|
53
|
-
const SESSION_ID = randomUUID().slice(0, 8);
|
|
54
|
-
|
|
55
|
-
// Use SKILLS_OUTPUT_DIR from CLI if available
|
|
56
|
-
const SKILLS_OUTPUT_DIR = process.env.SKILLS_OUTPUT_DIR || join(process.cwd(), ".skills");
|
|
57
|
-
const EXPORTS_DIR = join(SKILLS_OUTPUT_DIR, "exports", SKILL_NAME);
|
|
58
|
-
const LOGS_DIR = join(SKILLS_OUTPUT_DIR, "logs", SKILL_NAME);
|
|
59
|
-
const BACKUPS_DIR = join(SKILLS_OUTPUT_DIR, "backups", SKILL_NAME);
|
|
60
|
-
|
|
61
|
-
const SESSION_TIMESTAMP = new Date().toISOString().replace(/[:.]/g, "_").replace(/-/g, "_").slice(0, 19).toLowerCase();
|
|
62
|
-
|
|
63
|
-
// Ensure directories exist
|
|
64
|
-
function ensureDir(dir: string) {
|
|
65
|
-
if (!existsSync(dir)) {
|
|
66
|
-
mkdirSync(dir, { recursive: true });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Logger
|
|
71
|
-
function log(message: string, level: "info" | "error" | "success" | "warn" = "info") {
|
|
72
|
-
const timestamp = new Date().toISOString();
|
|
73
|
-
const logFile = join(LOGS_DIR, `log_${SESSION_TIMESTAMP}_${SESSION_ID}.log`);
|
|
74
|
-
|
|
75
|
-
ensureDir(LOGS_DIR);
|
|
76
|
-
|
|
77
|
-
const logEntry = `[${timestamp}] [${level.toUpperCase()}] ${message}\n`;
|
|
78
|
-
appendFileSync(logFile, logEntry);
|
|
79
|
-
|
|
80
|
-
const prefix = level === "error" ? "Error" : level === "success" ? "Success" : level === "warn" ? "Warning" : "Info";
|
|
81
|
-
console.log(`[${prefix}] ${message}`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Detect language from file extension
|
|
85
|
-
function detectLanguage(filePath: string): "typescript" | "javascript" | "python" | null {
|
|
86
|
-
const ext = extname(filePath).toLowerCase();
|
|
87
|
-
switch (ext) {
|
|
88
|
-
case ".ts":
|
|
89
|
-
case ".tsx":
|
|
90
|
-
return "typescript";
|
|
91
|
-
case ".js":
|
|
92
|
-
case ".jsx":
|
|
93
|
-
case ".mjs":
|
|
94
|
-
case ".cjs":
|
|
95
|
-
return "javascript";
|
|
96
|
-
case ".py":
|
|
97
|
-
return "python";
|
|
98
|
-
default:
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Auto-detect format from language
|
|
104
|
-
function autoDetectFormat(language: "typescript" | "javascript" | "python"): DocFormat {
|
|
105
|
-
switch (language) {
|
|
106
|
-
case "typescript":
|
|
107
|
-
return "tsdoc";
|
|
108
|
-
case "javascript":
|
|
109
|
-
return "jsdoc";
|
|
110
|
-
case "python":
|
|
111
|
-
return "python";
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Parse TypeScript/JavaScript file to find code elements
|
|
116
|
-
function parseTypeScriptFile(content: string, filePath: string): CodeElement[] {
|
|
117
|
-
const elements: CodeElement[] = [];
|
|
118
|
-
const lines = content.split("\n");
|
|
119
|
-
const language = detectLanguage(filePath) as "typescript" | "javascript";
|
|
120
|
-
|
|
121
|
-
// Simple regex-based parsing (production version would use proper AST parsing)
|
|
122
|
-
const functionRegex = /^(?:export\s+)?(?:async\s+)?function\s+(\w+)/;
|
|
123
|
-
const arrowFunctionRegex = /^(?:export\s+)?const\s+(\w+)\s*=\s*(?:async\s+)?\([^)]*\)\s*(?::\s*[^=]+)?\s*=>/;
|
|
124
|
-
const classRegex = /^(?:export\s+)?(?:abstract\s+)?class\s+(\w+)/;
|
|
125
|
-
const interfaceRegex = /^(?:export\s+)?interface\s+(\w+)/;
|
|
126
|
-
const typeRegex = /^(?:export\s+)?type\s+(\w+)/;
|
|
127
|
-
const methodRegex = /^\s+(?:async\s+)?(\w+)\s*\(/;
|
|
128
|
-
|
|
129
|
-
let inClass = false;
|
|
130
|
-
let classDepth = 0;
|
|
131
|
-
let currentElement: Partial<CodeElement> | null = null;
|
|
132
|
-
|
|
133
|
-
for (let i = 0; i < lines.length; i++) {
|
|
134
|
-
const line = lines[i];
|
|
135
|
-
const trimmedLine = line.trim();
|
|
136
|
-
|
|
137
|
-
// Check for existing documentation
|
|
138
|
-
const hasExistingDoc = i > 0 && lines[i - 1].trim().startsWith("/**");
|
|
139
|
-
|
|
140
|
-
// Function
|
|
141
|
-
const funcMatch = functionRegex.exec(trimmedLine);
|
|
142
|
-
if (funcMatch) {
|
|
143
|
-
const startLine = i;
|
|
144
|
-
const endLine = findBlockEnd(lines, i);
|
|
145
|
-
elements.push({
|
|
146
|
-
type: "function",
|
|
147
|
-
name: funcMatch[1],
|
|
148
|
-
code: lines.slice(startLine, endLine + 1).join("\n"),
|
|
149
|
-
startLine,
|
|
150
|
-
endLine,
|
|
151
|
-
hasExistingDoc,
|
|
152
|
-
language,
|
|
153
|
-
});
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Arrow function
|
|
158
|
-
const arrowMatch = arrowFunctionRegex.exec(trimmedLine);
|
|
159
|
-
if (arrowMatch) {
|
|
160
|
-
const startLine = i;
|
|
161
|
-
const endLine = findBlockEnd(lines, i);
|
|
162
|
-
elements.push({
|
|
163
|
-
type: "function",
|
|
164
|
-
name: arrowMatch[1],
|
|
165
|
-
code: lines.slice(startLine, endLine + 1).join("\n"),
|
|
166
|
-
startLine,
|
|
167
|
-
endLine,
|
|
168
|
-
hasExistingDoc,
|
|
169
|
-
language,
|
|
170
|
-
});
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Class
|
|
175
|
-
const classMatch = classRegex.exec(trimmedLine);
|
|
176
|
-
if (classMatch) {
|
|
177
|
-
const startLine = i;
|
|
178
|
-
const endLine = findBlockEnd(lines, i);
|
|
179
|
-
elements.push({
|
|
180
|
-
type: "class",
|
|
181
|
-
name: classMatch[1],
|
|
182
|
-
code: lines.slice(startLine, endLine + 1).join("\n"),
|
|
183
|
-
startLine,
|
|
184
|
-
endLine,
|
|
185
|
-
hasExistingDoc,
|
|
186
|
-
language,
|
|
187
|
-
});
|
|
188
|
-
inClass = true;
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Interface
|
|
193
|
-
const interfaceMatch = interfaceRegex.exec(trimmedLine);
|
|
194
|
-
if (interfaceMatch) {
|
|
195
|
-
const startLine = i;
|
|
196
|
-
const endLine = findBlockEnd(lines, i);
|
|
197
|
-
elements.push({
|
|
198
|
-
type: "interface",
|
|
199
|
-
name: interfaceMatch[1],
|
|
200
|
-
code: lines.slice(startLine, endLine + 1).join("\n"),
|
|
201
|
-
startLine,
|
|
202
|
-
endLine,
|
|
203
|
-
hasExistingDoc,
|
|
204
|
-
language,
|
|
205
|
-
});
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Type
|
|
210
|
-
const typeMatch = typeRegex.exec(trimmedLine);
|
|
211
|
-
if (typeMatch) {
|
|
212
|
-
const startLine = i;
|
|
213
|
-
// Types can be multi-line
|
|
214
|
-
let endLine = i;
|
|
215
|
-
if (trimmedLine.includes("{")) {
|
|
216
|
-
endLine = findBlockEnd(lines, i);
|
|
217
|
-
} else {
|
|
218
|
-
while (endLine < lines.length - 1 && !lines[endLine].includes(";")) {
|
|
219
|
-
endLine++;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
elements.push({
|
|
223
|
-
type: "type",
|
|
224
|
-
name: typeMatch[1],
|
|
225
|
-
code: lines.slice(startLine, endLine + 1).join("\n"),
|
|
226
|
-
startLine,
|
|
227
|
-
endLine,
|
|
228
|
-
hasExistingDoc,
|
|
229
|
-
language,
|
|
230
|
-
});
|
|
231
|
-
continue;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Method (inside class)
|
|
235
|
-
if (inClass) {
|
|
236
|
-
const methodMatch = methodRegex.exec(line);
|
|
237
|
-
if (methodMatch && !trimmedLine.startsWith("//") && !trimmedLine.startsWith("*")) {
|
|
238
|
-
const startLine = i;
|
|
239
|
-
const endLine = findBlockEnd(lines, i);
|
|
240
|
-
elements.push({
|
|
241
|
-
type: "method",
|
|
242
|
-
name: methodMatch[1],
|
|
243
|
-
code: lines.slice(startLine, endLine + 1).join("\n"),
|
|
244
|
-
startLine,
|
|
245
|
-
endLine,
|
|
246
|
-
hasExistingDoc,
|
|
247
|
-
language,
|
|
248
|
-
});
|
|
249
|
-
continue;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Track class depth
|
|
254
|
-
if (inClass) {
|
|
255
|
-
if (trimmedLine.includes("{")) classDepth++;
|
|
256
|
-
if (trimmedLine.includes("}")) {
|
|
257
|
-
classDepth--;
|
|
258
|
-
if (classDepth === 0) inClass = false;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return elements;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Parse Python file to find code elements
|
|
267
|
-
function parsePythonFile(content: string): CodeElement[] {
|
|
268
|
-
const elements: CodeElement[] = [];
|
|
269
|
-
const lines = content.split("\n");
|
|
270
|
-
|
|
271
|
-
const functionRegex = /^(?:async\s+)?def\s+(\w+)\s*\(/;
|
|
272
|
-
const classRegex = /^class\s+(\w+)/;
|
|
273
|
-
|
|
274
|
-
let inClass = false;
|
|
275
|
-
let classIndent = 0;
|
|
276
|
-
|
|
277
|
-
for (let i = 0; i < lines.length; i++) {
|
|
278
|
-
const line = lines[i];
|
|
279
|
-
const trimmedLine = line.trim();
|
|
280
|
-
const indent = line.length - line.trimLeft().length;
|
|
281
|
-
|
|
282
|
-
// Check for existing docstring
|
|
283
|
-
const hasExistingDoc = i < lines.length - 1 && lines[i + 1].trim().startsWith('"""');
|
|
284
|
-
|
|
285
|
-
// Class
|
|
286
|
-
const classMatch = classRegex.exec(trimmedLine);
|
|
287
|
-
if (classMatch) {
|
|
288
|
-
const startLine = i;
|
|
289
|
-
const endLine = findPythonBlockEnd(lines, i);
|
|
290
|
-
elements.push({
|
|
291
|
-
type: "class",
|
|
292
|
-
name: classMatch[1],
|
|
293
|
-
code: lines.slice(startLine, endLine + 1).join("\n"),
|
|
294
|
-
startLine,
|
|
295
|
-
endLine,
|
|
296
|
-
hasExistingDoc,
|
|
297
|
-
language: "python",
|
|
298
|
-
});
|
|
299
|
-
inClass = true;
|
|
300
|
-
classIndent = indent;
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Function
|
|
305
|
-
const funcMatch = functionRegex.exec(trimmedLine);
|
|
306
|
-
if (funcMatch) {
|
|
307
|
-
const startLine = i;
|
|
308
|
-
const endLine = findPythonBlockEnd(lines, i);
|
|
309
|
-
const isMethod = inClass && indent > classIndent;
|
|
310
|
-
|
|
311
|
-
elements.push({
|
|
312
|
-
type: isMethod ? "method" : "function",
|
|
313
|
-
name: funcMatch[1],
|
|
314
|
-
code: lines.slice(startLine, endLine + 1).join("\n"),
|
|
315
|
-
startLine,
|
|
316
|
-
endLine,
|
|
317
|
-
hasExistingDoc,
|
|
318
|
-
language: "python",
|
|
319
|
-
});
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Check if we've left the class
|
|
324
|
-
if (inClass && indent <= classIndent && trimmedLine && !trimmedLine.startsWith("#")) {
|
|
325
|
-
inClass = false;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return elements;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// Find the end of a code block (TypeScript/JavaScript)
|
|
333
|
-
function findBlockEnd(lines: string[], startLine: number): number {
|
|
334
|
-
let braceCount = 0;
|
|
335
|
-
let inBlock = false;
|
|
336
|
-
|
|
337
|
-
for (let i = startLine; i < lines.length; i++) {
|
|
338
|
-
const line = lines[i];
|
|
339
|
-
for (const char of line) {
|
|
340
|
-
if (char === "{") {
|
|
341
|
-
braceCount++;
|
|
342
|
-
inBlock = true;
|
|
343
|
-
} else if (char === "}") {
|
|
344
|
-
braceCount--;
|
|
345
|
-
if (inBlock && braceCount === 0) {
|
|
346
|
-
return i;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Single-line arrow function without braces
|
|
352
|
-
if (i === startLine && line.includes("=>") && !line.includes("{")) {
|
|
353
|
-
return i;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
return startLine;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// Find the end of a Python block
|
|
361
|
-
function findPythonBlockEnd(lines: string[], startLine: number): number {
|
|
362
|
-
const startIndent = lines[startLine].length - lines[startLine].trimLeft().length;
|
|
363
|
-
|
|
364
|
-
for (let i = startLine + 1; i < lines.length; i++) {
|
|
365
|
-
const line = lines[i];
|
|
366
|
-
const trimmed = line.trim();
|
|
367
|
-
|
|
368
|
-
// Skip empty lines and comments
|
|
369
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
370
|
-
|
|
371
|
-
const indent = line.length - line.trimLeft().length;
|
|
372
|
-
|
|
373
|
-
// If we find a line at the same or lower indent level, we've reached the end
|
|
374
|
-
if (indent <= startIndent) {
|
|
375
|
-
return i - 1;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
return lines.length - 1;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Generate documentation using AI
|
|
383
|
-
async function generateDocumentation(
|
|
384
|
-
element: CodeElement,
|
|
385
|
-
options: GenerateOptions
|
|
386
|
-
): Promise<string> {
|
|
387
|
-
const apiKey = options.apiProvider === "anthropic"
|
|
388
|
-
? process.env.ANTHROPIC_API_KEY
|
|
389
|
-
: process.env.OPENAI_API_KEY;
|
|
390
|
-
|
|
391
|
-
if (!apiKey) {
|
|
392
|
-
throw new Error(`${options.apiProvider.toUpperCase()}_API_KEY environment variable is not set`);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// Build prompt based on format and language
|
|
396
|
-
const format = options.format === "auto" ? autoDetectFormat(element.language) : options.format;
|
|
397
|
-
|
|
398
|
-
const prompt = buildDocumentationPrompt(element, format, options.includeExamples);
|
|
399
|
-
|
|
400
|
-
if (options.verbose) {
|
|
401
|
-
log(`Analyzing ${element.type} "${element.name}" in ${element.language}...`);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// Call AI API
|
|
405
|
-
if (options.apiProvider === "anthropic") {
|
|
406
|
-
return await callAnthropicAPI(prompt, apiKey, options.model || "claude-3-5-sonnet-20241022");
|
|
407
|
-
} else {
|
|
408
|
-
return await callOpenAIAPI(prompt, apiKey, options.model || "gpt-4-turbo");
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// Build documentation prompt
|
|
413
|
-
function buildDocumentationPrompt(element: CodeElement, format: DocFormat, includeExamples: boolean): string {
|
|
414
|
-
let prompt = `You are a technical documentation expert. Generate ${format} documentation for the following ${element.language} ${element.type}.\n\n`;
|
|
415
|
-
|
|
416
|
-
prompt += `Code:\n\`\`\`${element.language}\n${element.code}\n\`\`\`\n\n`;
|
|
417
|
-
|
|
418
|
-
prompt += `Requirements:\n`;
|
|
419
|
-
|
|
420
|
-
if (format === "jsdoc" || format === "tsdoc") {
|
|
421
|
-
prompt += `- Use JSDoc/TSDoc format with /** */ comment block\n`;
|
|
422
|
-
prompt += `- Include a clear description of what the ${element.type} does\n`;
|
|
423
|
-
prompt += `- Document all @param tags with types and descriptions\n`;
|
|
424
|
-
prompt += `- Include @returns tag with return type and description\n`;
|
|
425
|
-
prompt += `- Add @throws tags for any errors that may be thrown\n`;
|
|
426
|
-
|
|
427
|
-
if (format === "tsdoc") {
|
|
428
|
-
prompt += `- Use TypeScript-specific features (generics, union types, etc.)\n`;
|
|
429
|
-
prompt += `- Leverage type information from signatures\n`;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if (includeExamples) {
|
|
433
|
-
prompt += `- Include an @example block with realistic usage example\n`;
|
|
434
|
-
prompt += `- Show expected input and output in the example\n`;
|
|
435
|
-
}
|
|
436
|
-
} else if (format === "python") {
|
|
437
|
-
prompt += `- Use Python docstring format (Google or NumPy style)\n`;
|
|
438
|
-
prompt += `- Include a clear description of what the ${element.type} does\n`;
|
|
439
|
-
prompt += `- Document all Args: with types and descriptions\n`;
|
|
440
|
-
prompt += `- Include Returns: section with return type and description\n`;
|
|
441
|
-
prompt += `- Add Raises: section for any exceptions\n`;
|
|
442
|
-
|
|
443
|
-
if (includeExamples) {
|
|
444
|
-
prompt += `- Include an Example: section with realistic usage\n`;
|
|
445
|
-
prompt += `- Use doctest-compatible format for examples\n`;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
prompt += `\nGenerate ONLY the documentation comment block without any additional explanation or the code itself.`;
|
|
450
|
-
|
|
451
|
-
return prompt;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
// Call Anthropic API
|
|
455
|
-
async function callAnthropicAPI(prompt: string, apiKey: string, model: string): Promise<string> {
|
|
456
|
-
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
|
457
|
-
method: "POST",
|
|
458
|
-
headers: {
|
|
459
|
-
"Content-Type": "application/json",
|
|
460
|
-
"x-api-key": apiKey,
|
|
461
|
-
"anthropic-version": "2023-06-01",
|
|
462
|
-
},
|
|
463
|
-
body: JSON.stringify({
|
|
464
|
-
model,
|
|
465
|
-
max_tokens: 2048,
|
|
466
|
-
messages: [{
|
|
467
|
-
role: "user",
|
|
468
|
-
content: prompt,
|
|
469
|
-
}],
|
|
470
|
-
}),
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
if (!response.ok) {
|
|
474
|
-
const error = await response.json();
|
|
475
|
-
throw new Error(`Anthropic API error: ${error.error?.message || response.statusText}`);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
const data = await response.json();
|
|
479
|
-
return data.content[0].text.trim();
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// Call OpenAI API
|
|
483
|
-
async function callOpenAIAPI(prompt: string, apiKey: string, model: string): Promise<string> {
|
|
484
|
-
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
485
|
-
method: "POST",
|
|
486
|
-
headers: {
|
|
487
|
-
"Content-Type": "application/json",
|
|
488
|
-
"Authorization": `Bearer ${apiKey}`,
|
|
489
|
-
},
|
|
490
|
-
body: JSON.stringify({
|
|
491
|
-
model,
|
|
492
|
-
messages: [{
|
|
493
|
-
role: "user",
|
|
494
|
-
content: prompt,
|
|
495
|
-
}],
|
|
496
|
-
max_tokens: 2048,
|
|
497
|
-
temperature: 0.3,
|
|
498
|
-
}),
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
if (!response.ok) {
|
|
502
|
-
const error = await response.json();
|
|
503
|
-
throw new Error(`OpenAI API error: ${error.error?.message || response.statusText}`);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
const data = await response.json();
|
|
507
|
-
return data.choices[0].message.content.trim();
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Process a single file
|
|
511
|
-
async function processFile(filePath: string, options: GenerateOptions): Promise<DocumentationResult[]> {
|
|
512
|
-
log(`Processing file: ${filePath}`);
|
|
513
|
-
|
|
514
|
-
const content = readFileSync(filePath, "utf-8");
|
|
515
|
-
const language = detectLanguage(filePath);
|
|
516
|
-
|
|
517
|
-
if (!language) {
|
|
518
|
-
log(`Skipping unsupported file: ${filePath}`, "warn");
|
|
519
|
-
return [];
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// Parse file to find code elements
|
|
523
|
-
const elements = language === "python"
|
|
524
|
-
? parsePythonFile(content)
|
|
525
|
-
: parseTypeScriptFile(content, filePath);
|
|
526
|
-
|
|
527
|
-
log(`Found ${elements.length} code element(s) in ${basename(filePath)}`);
|
|
528
|
-
|
|
529
|
-
const results: DocumentationResult[] = [];
|
|
530
|
-
|
|
531
|
-
// Generate documentation for each element
|
|
532
|
-
for (const element of elements) {
|
|
533
|
-
// Skip if already documented and not updating
|
|
534
|
-
if (element.hasExistingDoc && !options.update) {
|
|
535
|
-
if (options.verbose) {
|
|
536
|
-
log(`Skipping ${element.name} (already documented)`, "info");
|
|
537
|
-
}
|
|
538
|
-
continue;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
try {
|
|
542
|
-
const documentation = await generateDocumentation(element, options);
|
|
543
|
-
results.push({
|
|
544
|
-
element,
|
|
545
|
-
documentation,
|
|
546
|
-
updated: element.hasExistingDoc,
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
log(`Generated documentation for ${element.name}`, "success");
|
|
550
|
-
} catch (error) {
|
|
551
|
-
log(`Failed to generate docs for ${element.name}: ${error instanceof Error ? error.message : "Unknown error"}`, "error");
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
return results;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
// Insert documentation into file
|
|
559
|
-
function insertDocumentation(filePath: string, results: DocumentationResult[]): void {
|
|
560
|
-
const content = readFileSync(filePath, "utf-8");
|
|
561
|
-
const lines = content.split("\n");
|
|
562
|
-
|
|
563
|
-
// Create backup
|
|
564
|
-
const backupDir = join(BACKUPS_DIR, SESSION_TIMESTAMP);
|
|
565
|
-
ensureDir(backupDir);
|
|
566
|
-
const backupPath = join(backupDir, basename(filePath));
|
|
567
|
-
copyFileSync(filePath, backupPath);
|
|
568
|
-
log(`Backed up to: ${backupPath}`);
|
|
569
|
-
|
|
570
|
-
// Sort results by start line (descending) to avoid line number shifts
|
|
571
|
-
const sortedResults = [...results].sort((a, b) => b.element.startLine - a.element.startLine);
|
|
572
|
-
|
|
573
|
-
for (const result of sortedResults) {
|
|
574
|
-
const { element, documentation } = result;
|
|
575
|
-
|
|
576
|
-
// Find insertion point (before the code element)
|
|
577
|
-
const insertLine = element.startLine;
|
|
578
|
-
|
|
579
|
-
// Remove existing documentation if updating
|
|
580
|
-
let startRemove = insertLine;
|
|
581
|
-
if (element.hasExistingDoc) {
|
|
582
|
-
// Find the start of the existing doc comment
|
|
583
|
-
for (let i = insertLine - 1; i >= 0; i--) {
|
|
584
|
-
if (lines[i].trim().startsWith("/**") || lines[i].trim().startsWith('"""')) {
|
|
585
|
-
startRemove = i;
|
|
586
|
-
break;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
// Remove old documentation
|
|
590
|
-
const removeCount = insertLine - startRemove;
|
|
591
|
-
lines.splice(startRemove, removeCount);
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
// Get indentation from the code line
|
|
595
|
-
const codeLineIndent = element.code.split("\n")[0].match(/^\s*/)?.[0] || "";
|
|
596
|
-
|
|
597
|
-
// Format documentation with proper indentation
|
|
598
|
-
const docLines = documentation.split("\n").map(line => codeLineIndent + line);
|
|
599
|
-
|
|
600
|
-
// Insert new documentation
|
|
601
|
-
lines.splice(startRemove, 0, ...docLines);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// Write updated content
|
|
605
|
-
writeFileSync(filePath, lines.join("\n"), "utf-8");
|
|
606
|
-
log(`Updated file: ${filePath}`, "success");
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
// Generate markdown documentation
|
|
610
|
-
function generateMarkdownDocs(allResults: Map<string, DocumentationResult[]>, outputPath: string): void {
|
|
611
|
-
let markdown = `# API Documentation\n\n`;
|
|
612
|
-
markdown += `Generated on ${new Date().toLocaleString()}\n\n`;
|
|
613
|
-
|
|
614
|
-
for (const [filePath, results] of allResults.entries()) {
|
|
615
|
-
if (results.length === 0) continue;
|
|
616
|
-
|
|
617
|
-
markdown += `## ${filePath}\n\n`;
|
|
618
|
-
|
|
619
|
-
for (const result of results) {
|
|
620
|
-
const { element, documentation } = result;
|
|
621
|
-
|
|
622
|
-
markdown += `### ${element.name}\n\n`;
|
|
623
|
-
markdown += `**Type:** ${element.type}\n\n`;
|
|
624
|
-
|
|
625
|
-
// Extract description from documentation
|
|
626
|
-
const docLines = documentation.split("\n");
|
|
627
|
-
const description = docLines
|
|
628
|
-
.filter(line => !line.includes("@param") && !line.includes("@returns") && !line.includes("Args:") && !line.includes("Returns:"))
|
|
629
|
-
.join("\n")
|
|
630
|
-
.replace(/\/\*\*|\*\/|\*/g, "")
|
|
631
|
-
.trim();
|
|
632
|
-
|
|
633
|
-
if (description) {
|
|
634
|
-
markdown += `${description}\n\n`;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// Show code signature
|
|
638
|
-
const signature = element.code.split("\n")[0];
|
|
639
|
-
markdown += `**Signature:**\n\`\`\`${element.language}\n${signature}\n\`\`\`\n\n`;
|
|
640
|
-
|
|
641
|
-
markdown += `---\n\n`;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
ensureDir(dirname(outputPath));
|
|
646
|
-
writeFileSync(outputPath, markdown, "utf-8");
|
|
647
|
-
log(`Generated markdown documentation: ${outputPath}`, "success");
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
// Collect all files from path (file or directory)
|
|
651
|
-
function collectFiles(path: string): string[] {
|
|
652
|
-
const files: string[] = [];
|
|
653
|
-
|
|
654
|
-
if (!existsSync(path)) {
|
|
655
|
-
throw new Error(`Path not found: ${path}`);
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
const stat = statSync(path);
|
|
659
|
-
|
|
660
|
-
if (stat.isFile()) {
|
|
661
|
-
const language = detectLanguage(path);
|
|
662
|
-
if (language) {
|
|
663
|
-
files.push(path);
|
|
664
|
-
}
|
|
665
|
-
} else if (stat.isDirectory()) {
|
|
666
|
-
const entries = readdirSync(path);
|
|
667
|
-
for (const entry of entries) {
|
|
668
|
-
const fullPath = join(path, entry);
|
|
669
|
-
const entryStat = statSync(fullPath);
|
|
670
|
-
|
|
671
|
-
if (entryStat.isDirectory()) {
|
|
672
|
-
// Recurse into subdirectories
|
|
673
|
-
files.push(...collectFiles(fullPath));
|
|
674
|
-
} else if (entryStat.isFile()) {
|
|
675
|
-
const language = detectLanguage(fullPath);
|
|
676
|
-
if (language) {
|
|
677
|
-
files.push(fullPath);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
return files;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
// Main function
|
|
687
18
|
async function main() {
|
|
688
|
-
const { values, positionals } = parseArgs({
|
|
689
|
-
args: Bun.argv.slice(2),
|
|
690
|
-
options: {
|
|
691
|
-
format: { type: "string", default: "auto" },
|
|
692
|
-
output: { type: "string", default: "inline" },
|
|
693
|
-
"include-examples": { type: "boolean", default: false },
|
|
694
|
-
update: { type: "boolean", default: false },
|
|
695
|
-
verbose: { type: "boolean", default: false },
|
|
696
|
-
"api-provider": { type: "string", default: "anthropic" },
|
|
697
|
-
model: { type: "string" },
|
|
698
|
-
help: { type: "boolean", short: "h" },
|
|
699
|
-
},
|
|
700
|
-
allowPositionals: true,
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
// Show help
|
|
704
|
-
if (values.help || positionals.length === 0) {
|
|
705
|
-
console.log(`
|
|
706
|
-
Generate Documentation - AI-powered code documentation generator
|
|
707
|
-
|
|
708
|
-
Usage:
|
|
709
|
-
skills run generate-documentation -- <file-or-directory> [options]
|
|
710
|
-
|
|
711
|
-
Options:
|
|
712
|
-
--format <format> Documentation format (jsdoc, tsdoc, python, auto) [default: auto]
|
|
713
|
-
--output <mode> Output mode: "inline" or file path for markdown [default: inline]
|
|
714
|
-
--include-examples Generate usage examples [default: false]
|
|
715
|
-
--update Update existing documentation [default: false]
|
|
716
|
-
--verbose Show detailed analysis [default: false]
|
|
717
|
-
--api-provider <provider> AI provider (anthropic, openai) [default: anthropic]
|
|
718
|
-
--model <model> AI model to use [default: provider default]
|
|
719
|
-
--help, -h Show this help
|
|
720
|
-
|
|
721
|
-
Examples:
|
|
722
|
-
# Single file with inline documentation
|
|
723
|
-
skills run generate-documentation -- ./src/utils.ts
|
|
724
|
-
|
|
725
|
-
# Directory with examples
|
|
726
|
-
skills run generate-documentation -- ./src --include-examples
|
|
727
|
-
|
|
728
|
-
# Generate markdown output
|
|
729
|
-
skills run generate-documentation -- ./lib --output ./docs/api.md
|
|
730
|
-
|
|
731
|
-
# Python with specific provider
|
|
732
|
-
skills run generate-documentation -- ./app.py --format python --api-provider openai
|
|
733
|
-
`);
|
|
734
|
-
process.exit(0);
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
const path = positionals[0];
|
|
738
|
-
|
|
739
|
-
if (!path) {
|
|
740
|
-
log("Please provide a file or directory path", "error");
|
|
741
|
-
process.exit(1);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
19
|
try {
|
|
745
20
|
log(`Session ID: ${SESSION_ID}`);
|
|
746
21
|
|
|
747
|
-
const options
|
|
748
|
-
|
|
749
|
-
format: values.format as DocFormat,
|
|
750
|
-
output: values.output as OutputMode,
|
|
751
|
-
includeExamples: values["include-examples"] as boolean,
|
|
752
|
-
update: values.update as boolean,
|
|
753
|
-
verbose: values.verbose as boolean,
|
|
754
|
-
apiProvider: values["api-provider"] as ApiProvider,
|
|
755
|
-
model: values.model as string | undefined,
|
|
756
|
-
};
|
|
757
|
-
|
|
758
|
-
// Collect all files to process
|
|
759
|
-
const files = collectFiles(path);
|
|
22
|
+
const options = parseGenerateOptions();
|
|
23
|
+
const files = collectFiles(options.path);
|
|
760
24
|
log(`Found ${files.length} file(s) to process`);
|
|
761
25
|
|
|
762
26
|
if (files.length === 0) {
|
|
@@ -764,7 +28,6 @@ Examples:
|
|
|
764
28
|
process.exit(0);
|
|
765
29
|
}
|
|
766
30
|
|
|
767
|
-
// Process all files
|
|
768
31
|
const allResults = new Map<string, DocumentationResult[]>();
|
|
769
32
|
let totalGenerated = 0;
|
|
770
33
|
|
|
@@ -773,13 +36,11 @@ Examples:
|
|
|
773
36
|
allResults.set(file, results);
|
|
774
37
|
totalGenerated += results.length;
|
|
775
38
|
|
|
776
|
-
// Insert documentation inline
|
|
777
39
|
if (options.output === "inline" && results.length > 0) {
|
|
778
40
|
insertDocumentation(file, results);
|
|
779
41
|
}
|
|
780
42
|
}
|
|
781
43
|
|
|
782
|
-
// Generate markdown output if specified
|
|
783
44
|
if (options.output !== "inline") {
|
|
784
45
|
const outputPath = options.output.endsWith(".md")
|
|
785
46
|
? options.output
|
|
@@ -795,7 +56,6 @@ Documentation generation complete!
|
|
|
795
56
|
Output: ${options.output === "inline" ? "Inline (files updated)" : options.output}
|
|
796
57
|
Log: ${join(LOGS_DIR, `log_${SESSION_TIMESTAMP}_${SESSION_ID}.log`)}
|
|
797
58
|
`);
|
|
798
|
-
|
|
799
59
|
} catch (error) {
|
|
800
60
|
log(`Error: ${error instanceof Error ? error.message : "Unknown error"}`, "error");
|
|
801
61
|
process.exit(1);
|