@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,253 +0,0 @@
|
|
|
1
|
-
import { Sandbox } from 'e2b';
|
|
2
|
-
import { mkdir } from 'node:fs/promises';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import type { SwarmInstance } from '../types';
|
|
5
|
-
import { logger } from './logger';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Setup GitHub authentication in sandbox
|
|
9
|
-
*/
|
|
10
|
-
export async function setupGitHubAuth(sandbox: Sandbox): Promise<void> {
|
|
11
|
-
// Check for GitHub token in environment
|
|
12
|
-
const ghToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
13
|
-
|
|
14
|
-
if (ghToken) {
|
|
15
|
-
// Use token-based auth
|
|
16
|
-
await sandbox.commands.run(`
|
|
17
|
-
git config --global credential.helper store
|
|
18
|
-
echo "https://oauth2:${ghToken}@github.com" > ~/.git-credentials
|
|
19
|
-
git config --global user.email "swarm@e2b.dev"
|
|
20
|
-
git config --global user.name "E2B Swarm"
|
|
21
|
-
`);
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Try to copy SSH key from local machine
|
|
26
|
-
const sshKeyPath = `${process.env.HOME}/.ssh/id_ed25519`;
|
|
27
|
-
try {
|
|
28
|
-
const privateKey = await Bun.file(sshKeyPath).text();
|
|
29
|
-
const publicKey = await Bun.file(`${sshKeyPath}.pub`).text();
|
|
30
|
-
|
|
31
|
-
await sandbox.commands.run('mkdir -p ~/.ssh && chmod 700 ~/.ssh');
|
|
32
|
-
await sandbox.files.write('/home/user/.ssh/id_ed25519', privateKey);
|
|
33
|
-
await sandbox.files.write('/home/user/.ssh/id_ed25519.pub', publicKey);
|
|
34
|
-
await sandbox.commands.run(`
|
|
35
|
-
chmod 600 ~/.ssh/id_ed25519
|
|
36
|
-
chmod 644 ~/.ssh/id_ed25519.pub
|
|
37
|
-
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
|
|
38
|
-
git config --global user.email "swarm@e2b.dev"
|
|
39
|
-
git config --global user.name "E2B Swarm"
|
|
40
|
-
`);
|
|
41
|
-
return;
|
|
42
|
-
} catch {
|
|
43
|
-
// SSH key not found, try id_rsa
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const rsaKeyPath = `${process.env.HOME}/.ssh/id_rsa`;
|
|
47
|
-
try {
|
|
48
|
-
const privateKey = await Bun.file(rsaKeyPath).text();
|
|
49
|
-
const publicKey = await Bun.file(`${rsaKeyPath}.pub`).text();
|
|
50
|
-
|
|
51
|
-
await sandbox.commands.run('mkdir -p ~/.ssh && chmod 700 ~/.ssh');
|
|
52
|
-
await sandbox.files.write('/home/user/.ssh/id_rsa', privateKey);
|
|
53
|
-
await sandbox.files.write('/home/user/.ssh/id_rsa.pub', publicKey);
|
|
54
|
-
await sandbox.commands.run(`
|
|
55
|
-
chmod 600 ~/.ssh/id_rsa
|
|
56
|
-
chmod 644 ~/.ssh/id_rsa.pub
|
|
57
|
-
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
|
|
58
|
-
git config --global user.email "swarm@e2b.dev"
|
|
59
|
-
git config --global user.name "E2B Swarm"
|
|
60
|
-
`);
|
|
61
|
-
return;
|
|
62
|
-
} catch {
|
|
63
|
-
// No SSH key found
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
logger.warn('No GitHub authentication found. Set GITHUB_TOKEN or ensure SSH keys exist.');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Commit changes in the sandbox
|
|
71
|
-
*/
|
|
72
|
-
export async function commitChanges(
|
|
73
|
-
sandbox: Sandbox,
|
|
74
|
-
message: string
|
|
75
|
-
): Promise<{ success: boolean; error?: string }> {
|
|
76
|
-
// Stage all changes
|
|
77
|
-
const addResult = await sandbox.commands.run('cd /home/user/workspace && git add -A');
|
|
78
|
-
if (addResult.exitCode !== 0) {
|
|
79
|
-
return { success: false, error: `Failed to stage changes: ${addResult.stderr}` };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Check if there are changes to commit
|
|
83
|
-
const statusResult = await sandbox.commands.run('cd /home/user/workspace && git status --porcelain');
|
|
84
|
-
if (!statusResult.stdout.trim()) {
|
|
85
|
-
return { success: true }; // No changes to commit
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Commit
|
|
89
|
-
const commitResult = await sandbox.commands.run(
|
|
90
|
-
`cd /home/user/workspace && git commit -m "${message.replace(/"/g, '\\"')}"`
|
|
91
|
-
);
|
|
92
|
-
if (commitResult.exitCode !== 0) {
|
|
93
|
-
return { success: false, error: `Failed to commit: ${commitResult.stderr}` };
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return { success: true };
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Push changes to remote
|
|
101
|
-
*/
|
|
102
|
-
export async function pushChanges(
|
|
103
|
-
sandbox: Sandbox,
|
|
104
|
-
branch?: string
|
|
105
|
-
): Promise<{ success: boolean; error?: string }> {
|
|
106
|
-
const pushCmd = branch
|
|
107
|
-
? `cd /home/user/workspace && git push -u origin ${branch}`
|
|
108
|
-
: 'cd /home/user/workspace && git push';
|
|
109
|
-
|
|
110
|
-
const result = await sandbox.commands.run(pushCmd, { timeoutMs: 60000 });
|
|
111
|
-
if (result.exitCode !== 0) {
|
|
112
|
-
return { success: false, error: `Failed to push: ${result.stderr}` };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return { success: true };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Create a new branch
|
|
120
|
-
*/
|
|
121
|
-
export async function createBranch(
|
|
122
|
-
sandbox: Sandbox,
|
|
123
|
-
branchName: string
|
|
124
|
-
): Promise<{ success: boolean; error?: string }> {
|
|
125
|
-
const result = await sandbox.commands.run(
|
|
126
|
-
`cd /home/user/workspace && git checkout -b ${branchName}`
|
|
127
|
-
);
|
|
128
|
-
if (result.exitCode !== 0) {
|
|
129
|
-
return { success: false, error: `Failed to create branch: ${result.stderr}` };
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return { success: true };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Create a pull request using gh CLI
|
|
137
|
-
*/
|
|
138
|
-
export async function createPullRequest(
|
|
139
|
-
sandbox: Sandbox,
|
|
140
|
-
options: {
|
|
141
|
-
title: string;
|
|
142
|
-
body: string;
|
|
143
|
-
base?: string;
|
|
144
|
-
draft?: boolean;
|
|
145
|
-
}
|
|
146
|
-
): Promise<{ success: boolean; prUrl?: string; error?: string }> {
|
|
147
|
-
// Install gh CLI if not present
|
|
148
|
-
await sandbox.commands.run(`
|
|
149
|
-
which gh || (curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
|
|
150
|
-
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
|
|
151
|
-
sudo apt update && sudo apt install gh -y) 2>/dev/null || true
|
|
152
|
-
`, { timeoutMs: 120000 });
|
|
153
|
-
|
|
154
|
-
// Check for GitHub token
|
|
155
|
-
const ghToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
156
|
-
if (!ghToken) {
|
|
157
|
-
return { success: false, error: 'GITHUB_TOKEN not set. Cannot create PR.' };
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Authenticate gh CLI
|
|
161
|
-
await sandbox.commands.run(`echo "${ghToken}" | gh auth login --with-token`);
|
|
162
|
-
|
|
163
|
-
// Build PR command
|
|
164
|
-
const baseFlag = options.base ? `--base ${options.base}` : '';
|
|
165
|
-
const draftFlag = options.draft ? '--draft' : '';
|
|
166
|
-
|
|
167
|
-
const prCmd = `cd /home/user/workspace && gh pr create --title "${options.title.replace(/"/g, '\\"')}" --body "${options.body.replace(/"/g, '\\"')}" ${baseFlag} ${draftFlag}`;
|
|
168
|
-
|
|
169
|
-
const result = await sandbox.commands.run(prCmd, { timeoutMs: 60000 });
|
|
170
|
-
if (result.exitCode !== 0) {
|
|
171
|
-
return { success: false, error: `Failed to create PR: ${result.stderr}` };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Extract PR URL from output
|
|
175
|
-
const prUrl = result.stdout.trim().split('\n').pop();
|
|
176
|
-
|
|
177
|
-
return { success: true, prUrl };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Download changed files from sandbox to local export directory
|
|
182
|
-
*/
|
|
183
|
-
export async function downloadChangedFiles(
|
|
184
|
-
sandbox: Sandbox,
|
|
185
|
-
instance: SwarmInstance
|
|
186
|
-
): Promise<string[]> {
|
|
187
|
-
const exportDir = instance.exportDir;
|
|
188
|
-
if (!exportDir) return [];
|
|
189
|
-
|
|
190
|
-
// Get list of changed files
|
|
191
|
-
const diffResult = await sandbox.commands.run(
|
|
192
|
-
'cd /home/user/workspace && git diff --name-only HEAD~1 2>/dev/null || git diff --name-only'
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
const changedFiles = diffResult.stdout.trim().split('\n').filter(Boolean);
|
|
196
|
-
const downloadedFiles: string[] = [];
|
|
197
|
-
|
|
198
|
-
// Create changes directory
|
|
199
|
-
const changesDir = join(exportDir, 'changes');
|
|
200
|
-
await mkdir(changesDir, { recursive: true });
|
|
201
|
-
|
|
202
|
-
for (const file of changedFiles) {
|
|
203
|
-
try {
|
|
204
|
-
const content = await sandbox.files.read(`/home/user/workspace/${file}`);
|
|
205
|
-
const localPath = join(changesDir, file);
|
|
206
|
-
await mkdir(join(changesDir, file.split('/').slice(0, -1).join('/')), { recursive: true });
|
|
207
|
-
await Bun.write(localPath, content);
|
|
208
|
-
downloadedFiles.push(file);
|
|
209
|
-
} catch {
|
|
210
|
-
// File might have been deleted
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return downloadedFiles;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Get git status from sandbox
|
|
219
|
-
*/
|
|
220
|
-
export async function getGitStatus(sandbox: Sandbox): Promise<{
|
|
221
|
-
branch: string;
|
|
222
|
-
ahead: number;
|
|
223
|
-
behind: number;
|
|
224
|
-
modified: string[];
|
|
225
|
-
added: string[];
|
|
226
|
-
deleted: string[];
|
|
227
|
-
}> {
|
|
228
|
-
const branchResult = await sandbox.commands.run('cd /home/user/workspace && git branch --show-current');
|
|
229
|
-
const statusResult = await sandbox.commands.run('cd /home/user/workspace && git status --porcelain');
|
|
230
|
-
|
|
231
|
-
const modified: string[] = [];
|
|
232
|
-
const added: string[] = [];
|
|
233
|
-
const deleted: string[] = [];
|
|
234
|
-
|
|
235
|
-
for (const line of statusResult.stdout.split('\n')) {
|
|
236
|
-
if (!line.trim()) continue;
|
|
237
|
-
const status = line.slice(0, 2);
|
|
238
|
-
const file = line.slice(3);
|
|
239
|
-
|
|
240
|
-
if (status.includes('M')) modified.push(file);
|
|
241
|
-
if (status.includes('A') || status === '??') added.push(file);
|
|
242
|
-
if (status.includes('D')) deleted.push(file);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return {
|
|
246
|
-
branch: branchResult.stdout.trim(),
|
|
247
|
-
ahead: 0,
|
|
248
|
-
behind: 0,
|
|
249
|
-
modified,
|
|
250
|
-
added,
|
|
251
|
-
deleted,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
|
|
3
|
-
export const logger = {
|
|
4
|
-
info: (msg: string) => console.log(chalk.blue('ℹ'), msg),
|
|
5
|
-
success: (msg: string) => console.log(chalk.green('✓'), msg),
|
|
6
|
-
warn: (msg: string) => console.log(chalk.yellow('⚠'), msg),
|
|
7
|
-
error: (msg: string) => console.log(chalk.red('✗'), msg),
|
|
8
|
-
debug: (msg: string) => {
|
|
9
|
-
if (process.env.DEBUG) console.log(chalk.gray('⋯'), msg);
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
instance: (id: string, status: string, msg?: string) => {
|
|
13
|
-
const statusColors: Record<string, (s: string) => string> = {
|
|
14
|
-
starting: chalk.yellow,
|
|
15
|
-
cloning: chalk.blue,
|
|
16
|
-
'setting-up': chalk.blue,
|
|
17
|
-
running: chalk.cyan,
|
|
18
|
-
completed: chalk.green,
|
|
19
|
-
failed: chalk.red,
|
|
20
|
-
};
|
|
21
|
-
const colorFn = statusColors[status] || chalk.white;
|
|
22
|
-
const shortId = id.slice(0, 8);
|
|
23
|
-
console.log(` ${chalk.gray(`[${shortId}]`)} ${colorFn(status.padEnd(10))} ${msg || ''}`);
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
table: (data: Array<Record<string, unknown>>) => {
|
|
27
|
-
if (data.length === 0) {
|
|
28
|
-
console.log(chalk.gray(' No data'));
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
console.table(data);
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
divider: () => console.log(chalk.gray('─'.repeat(60))),
|
|
35
|
-
|
|
36
|
-
header: (title: string) => {
|
|
37
|
-
console.log();
|
|
38
|
-
console.log(chalk.bold.white(title));
|
|
39
|
-
logger.divider();
|
|
40
|
-
},
|
|
41
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { mkdir } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Standard skill data directory structure
|
|
6
|
-
*
|
|
7
|
-
* ~/.skills/
|
|
8
|
-
* └── [name]/
|
|
9
|
-
* ├── exports/ # Output data, results, artifacts
|
|
10
|
-
* ├── logs/ # Execution logs, debug info
|
|
11
|
-
* ├── cache/ # Temporary cached data
|
|
12
|
-
* └── config/ # Skill-specific configuration
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const SKILL_NAME = 'e2bswarm';
|
|
16
|
-
const SKILLS_ROOT = join(process.env.HOME!, '.skills');
|
|
17
|
-
const SKILL_DATA_DIR = join(SKILLS_ROOT, SKILL_NAME);
|
|
18
|
-
|
|
19
|
-
export const paths = {
|
|
20
|
-
// Root directories
|
|
21
|
-
skillsRoot: SKILLS_ROOT,
|
|
22
|
-
skillData: SKILL_DATA_DIR,
|
|
23
|
-
|
|
24
|
-
// Standard subdirectories
|
|
25
|
-
exports: join(SKILL_DATA_DIR, 'exports'),
|
|
26
|
-
logs: join(SKILL_DATA_DIR, 'logs'),
|
|
27
|
-
cache: join(SKILL_DATA_DIR, 'cache'),
|
|
28
|
-
config: join(SKILL_DATA_DIR, 'config'),
|
|
29
|
-
|
|
30
|
-
// State file (moved from ~/.claude/)
|
|
31
|
-
state: join(SKILL_DATA_DIR, 'state.json'),
|
|
32
|
-
|
|
33
|
-
// Helper to get timestamped export directory
|
|
34
|
-
getExportDir: (prefix?: string) => {
|
|
35
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
36
|
-
const dirName = prefix ? `${prefix}-${timestamp}` : timestamp;
|
|
37
|
-
return join(SKILL_DATA_DIR, 'exports', dirName);
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
// Helper to get log file path
|
|
41
|
-
getLogFile: (name: string) => {
|
|
42
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
43
|
-
return join(SKILL_DATA_DIR, 'logs', `${name}-${timestamp}.log`);
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
// Helper to get instance-specific paths
|
|
47
|
-
getInstance: (instanceId: string) => ({
|
|
48
|
-
exports: join(SKILL_DATA_DIR, 'exports', instanceId),
|
|
49
|
-
logs: join(SKILL_DATA_DIR, 'logs', instanceId),
|
|
50
|
-
}),
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Ensure all skill directories exist
|
|
55
|
-
*/
|
|
56
|
-
export async function ensureSkillDirs(): Promise<void> {
|
|
57
|
-
await mkdir(paths.exports, { recursive: true });
|
|
58
|
-
await mkdir(paths.logs, { recursive: true });
|
|
59
|
-
await mkdir(paths.cache, { recursive: true });
|
|
60
|
-
await mkdir(paths.config, { recursive: true });
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Get skill data path for any skill (reusable utility)
|
|
65
|
-
*/
|
|
66
|
-
export function getSkillPaths(skillName: string) {
|
|
67
|
-
const skillDir = join(SKILLS_ROOT, skillName);
|
|
68
|
-
return {
|
|
69
|
-
root: skillDir,
|
|
70
|
-
exports: join(skillDir, 'exports'),
|
|
71
|
-
logs: join(skillDir, 'logs'),
|
|
72
|
-
cache: join(skillDir, 'cache'),
|
|
73
|
-
config: join(skillDir, 'config'),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import { readdir } from 'node:fs/promises';
|
|
2
|
-
import { join, resolve } from 'node:path';
|
|
3
|
-
import type { Task, TaskSource, SpawnOptions } from '../types';
|
|
4
|
-
import { logger } from './logger';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Determine the task source from spawn options
|
|
8
|
-
*/
|
|
9
|
-
export function determineTaskSource(options: SpawnOptions): TaskSource {
|
|
10
|
-
if (options.tasksJson) {
|
|
11
|
-
return { type: 'json', value: options.tasksJson };
|
|
12
|
-
}
|
|
13
|
-
if (options.tasksFile) {
|
|
14
|
-
return { type: 'file', value: resolve(options.tasksFile) };
|
|
15
|
-
}
|
|
16
|
-
if (options.tasksDir) {
|
|
17
|
-
return { type: 'directory', value: resolve(options.tasksDir) };
|
|
18
|
-
}
|
|
19
|
-
if (options.tasks) {
|
|
20
|
-
// Check if it's a path or a task list ID
|
|
21
|
-
if (options.tasks.includes('/') || options.tasks.endsWith('.json')) {
|
|
22
|
-
return { type: 'file', value: resolve(options.tasks) };
|
|
23
|
-
}
|
|
24
|
-
return { type: 'task-list-id', value: options.tasks };
|
|
25
|
-
}
|
|
26
|
-
throw new Error(
|
|
27
|
-
'No task source provided. Use one of:\n' +
|
|
28
|
-
' --tasks <task-list-id> Load from ~/.claude/tasks/<id>/\n' +
|
|
29
|
-
' --tasks-dir <directory> Load from a local directory\n' +
|
|
30
|
-
' --tasks-file <file.json> Load from a JSON file\n' +
|
|
31
|
-
' --tasks-json \'[...]\''+ ' Inline JSON array'
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Load tasks from various sources
|
|
37
|
-
*/
|
|
38
|
-
export async function loadTasks(source: TaskSource): Promise<Task[]> {
|
|
39
|
-
switch (source.type) {
|
|
40
|
-
case 'json':
|
|
41
|
-
return parseTasksJson(source.value);
|
|
42
|
-
|
|
43
|
-
case 'file':
|
|
44
|
-
return loadTasksFromFile(source.value);
|
|
45
|
-
|
|
46
|
-
case 'directory':
|
|
47
|
-
return loadTasksFromDirectory(source.value);
|
|
48
|
-
|
|
49
|
-
case 'task-list-id':
|
|
50
|
-
return loadTasksFromTaskList(source.value);
|
|
51
|
-
|
|
52
|
-
default:
|
|
53
|
-
throw new Error(`Unknown task source type`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Parse inline JSON tasks
|
|
59
|
-
*/
|
|
60
|
-
function parseTasksJson(json: string): Task[] {
|
|
61
|
-
try {
|
|
62
|
-
const parsed = JSON.parse(json);
|
|
63
|
-
const tasks = Array.isArray(parsed) ? parsed : [parsed];
|
|
64
|
-
return validateTasks(tasks);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
throw new Error(`Failed to parse tasks JSON: ${error}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Load tasks from a JSON file
|
|
72
|
-
*/
|
|
73
|
-
async function loadTasksFromFile(filePath: string): Promise<Task[]> {
|
|
74
|
-
try {
|
|
75
|
-
const content = await Bun.file(filePath).text();
|
|
76
|
-
const parsed = JSON.parse(content);
|
|
77
|
-
const tasks = Array.isArray(parsed) ? parsed : [parsed];
|
|
78
|
-
logger.debug(`Loaded ${tasks.length} tasks from file: ${filePath}`);
|
|
79
|
-
return validateTasks(tasks);
|
|
80
|
-
} catch (error) {
|
|
81
|
-
throw new Error(`Failed to load tasks from file ${filePath}: ${error}`);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Load tasks from a directory containing JSON files
|
|
87
|
-
*/
|
|
88
|
-
async function loadTasksFromDirectory(dirPath: string): Promise<Task[]> {
|
|
89
|
-
try {
|
|
90
|
-
const files = await readdir(dirPath);
|
|
91
|
-
const jsonFiles = files.filter(f => f.endsWith('.json'));
|
|
92
|
-
|
|
93
|
-
if (jsonFiles.length === 0) {
|
|
94
|
-
throw new Error(`No JSON files found in directory: ${dirPath}`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const tasks: Task[] = [];
|
|
98
|
-
for (const file of jsonFiles) {
|
|
99
|
-
const content = await Bun.file(join(dirPath, file)).text();
|
|
100
|
-
const task = JSON.parse(content);
|
|
101
|
-
tasks.push(task);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
logger.debug(`Loaded ${tasks.length} tasks from directory: ${dirPath}`);
|
|
105
|
-
return validateTasks(tasks);
|
|
106
|
-
} catch (error) {
|
|
107
|
-
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
108
|
-
throw new Error(`Directory not found: ${dirPath}`);
|
|
109
|
-
}
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Load tasks from Claude Code task list (~/.claude/tasks/<id>/)
|
|
116
|
-
*/
|
|
117
|
-
async function loadTasksFromTaskList(taskListId: string): Promise<Task[]> {
|
|
118
|
-
const tasksDir = join(process.env.HOME!, '.claude', 'tasks', taskListId);
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
const files = await readdir(tasksDir);
|
|
122
|
-
const jsonFiles = files.filter(f => f.endsWith('.json'));
|
|
123
|
-
|
|
124
|
-
if (jsonFiles.length === 0) {
|
|
125
|
-
throw new Error(`No tasks found in task list: ${taskListId}`);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const tasks: Task[] = [];
|
|
129
|
-
for (const file of jsonFiles) {
|
|
130
|
-
const content = await Bun.file(join(tasksDir, file)).text();
|
|
131
|
-
const task = JSON.parse(content);
|
|
132
|
-
tasks.push(task);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
logger.debug(`Loaded ${tasks.length} tasks from task list: ${taskListId}`);
|
|
136
|
-
return validateTasks(tasks);
|
|
137
|
-
} catch (error) {
|
|
138
|
-
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
139
|
-
throw new Error(
|
|
140
|
-
`Task list not found: ${taskListId}\n` +
|
|
141
|
-
`Expected location: ${tasksDir}\n\n` +
|
|
142
|
-
'Available task lists can be found in ~/.claude/tasks/'
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
throw error;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Validate and normalize task objects
|
|
151
|
-
*/
|
|
152
|
-
function validateTasks(tasks: unknown[]): Task[] {
|
|
153
|
-
return tasks.map((task, index) => {
|
|
154
|
-
if (!task || typeof task !== 'object') {
|
|
155
|
-
throw new Error(`Task at index ${index} is not an object`);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const t = task as Record<string, unknown>;
|
|
159
|
-
|
|
160
|
-
if (!t.id) {
|
|
161
|
-
t.id = String(index + 1);
|
|
162
|
-
}
|
|
163
|
-
if (!t.subject && !t.description) {
|
|
164
|
-
throw new Error(`Task ${t.id} must have a subject or description`);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return {
|
|
168
|
-
id: String(t.id),
|
|
169
|
-
subject: String(t.subject || t.description || ''),
|
|
170
|
-
description: String(t.description || t.subject || ''),
|
|
171
|
-
activeForm: t.activeForm ? String(t.activeForm) : undefined,
|
|
172
|
-
status: (t.status as Task['status']) || 'pending',
|
|
173
|
-
blocks: Array.isArray(t.blocks) ? t.blocks.map(String) : [],
|
|
174
|
-
blockedBy: Array.isArray(t.blockedBy) ? t.blockedBy.map(String) : [],
|
|
175
|
-
metadata: t.metadata as Record<string, unknown> | undefined,
|
|
176
|
-
};
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Filter tasks to only pending/in_progress
|
|
182
|
-
*/
|
|
183
|
-
export function filterPendingTasks(tasks: Task[]): Task[] {
|
|
184
|
-
return tasks.filter(t => t.status !== 'completed');
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Distribute tasks across instances based on mode
|
|
189
|
-
*/
|
|
190
|
-
export function distributeTasks(
|
|
191
|
-
tasks: Task[],
|
|
192
|
-
instanceCount: number,
|
|
193
|
-
mode: 'all' | 'round-robin' | 'by-dependency' = 'all'
|
|
194
|
-
): Task[][] {
|
|
195
|
-
// Filter to pending tasks only
|
|
196
|
-
const pendingTasks = filterPendingTasks(tasks);
|
|
197
|
-
|
|
198
|
-
if (pendingTasks.length === 0) {
|
|
199
|
-
logger.warn('No pending tasks to distribute');
|
|
200
|
-
return Array(instanceCount).fill([]);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
switch (mode) {
|
|
204
|
-
case 'all':
|
|
205
|
-
// Each instance gets all tasks
|
|
206
|
-
return Array(instanceCount).fill(null).map(() => [...pendingTasks]);
|
|
207
|
-
|
|
208
|
-
case 'round-robin':
|
|
209
|
-
// Distribute tasks evenly across instances
|
|
210
|
-
return distributeRoundRobin(pendingTasks, instanceCount);
|
|
211
|
-
|
|
212
|
-
case 'by-dependency':
|
|
213
|
-
// Group tasks by their dependency chains
|
|
214
|
-
return distributeByDependency(pendingTasks, instanceCount);
|
|
215
|
-
|
|
216
|
-
default:
|
|
217
|
-
return [pendingTasks];
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function distributeRoundRobin(tasks: Task[], instanceCount: number): Task[][] {
|
|
222
|
-
const distribution: Task[][] = Array.from({ length: instanceCount }, () => []);
|
|
223
|
-
|
|
224
|
-
tasks.forEach((task, i) => {
|
|
225
|
-
distribution[i % instanceCount]!.push(task);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
return distribution;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function distributeByDependency(tasks: Task[], maxGroups: number): Task[][] {
|
|
232
|
-
const chains: Task[][] = [];
|
|
233
|
-
const assigned = new Set<string>();
|
|
234
|
-
|
|
235
|
-
// Find all tasks that have no blockers (roots)
|
|
236
|
-
const roots = tasks.filter(t => t.blockedBy.length === 0);
|
|
237
|
-
|
|
238
|
-
for (const root of roots) {
|
|
239
|
-
if (assigned.has(root.id)) continue;
|
|
240
|
-
const chain = collectDependencyChain(root, tasks, assigned);
|
|
241
|
-
if (chain.length > 0) {
|
|
242
|
-
chains.push(chain);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Add any orphaned tasks
|
|
247
|
-
for (const task of tasks) {
|
|
248
|
-
if (!assigned.has(task.id)) {
|
|
249
|
-
chains.push([task]);
|
|
250
|
-
assigned.add(task.id);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Merge chains if we have more than maxGroups
|
|
255
|
-
while (chains.length > maxGroups && chains.length > 1) {
|
|
256
|
-
// Find the smallest chain
|
|
257
|
-
let smallestIdx = 0;
|
|
258
|
-
for (let i = 1; i < chains.length; i++) {
|
|
259
|
-
if (chains[i]!.length < chains[smallestIdx]!.length) {
|
|
260
|
-
smallestIdx = i;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Merge with the next smallest
|
|
265
|
-
const smallest = chains.splice(smallestIdx, 1)[0]!;
|
|
266
|
-
let targetIdx = 0;
|
|
267
|
-
for (let i = 1; i < chains.length; i++) {
|
|
268
|
-
if (chains[i]!.length < chains[targetIdx]!.length) {
|
|
269
|
-
targetIdx = i;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
chains[targetIdx]!.push(...smallest);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// Pad with empty arrays if we have fewer chains than instances
|
|
276
|
-
while (chains.length < maxGroups) {
|
|
277
|
-
chains.push([]);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return chains;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
function collectDependencyChain(
|
|
284
|
-
task: Task,
|
|
285
|
-
allTasks: Task[],
|
|
286
|
-
assigned: Set<string>
|
|
287
|
-
): Task[] {
|
|
288
|
-
if (assigned.has(task.id)) return [];
|
|
289
|
-
|
|
290
|
-
assigned.add(task.id);
|
|
291
|
-
const chain: Task[] = [task];
|
|
292
|
-
|
|
293
|
-
// Find tasks that this one blocks (dependents)
|
|
294
|
-
for (const t of allTasks) {
|
|
295
|
-
if (t.blockedBy.includes(task.id)) {
|
|
296
|
-
chain.push(...collectDependencyChain(t, allTasks, assigned));
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return chain;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Serialize tasks for writing to sandbox
|
|
305
|
-
*/
|
|
306
|
-
export function serializeTasks(tasks: Task[]): string {
|
|
307
|
-
return JSON.stringify(tasks, null, 2);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Create a summary of task distribution
|
|
312
|
-
*/
|
|
313
|
-
export function summarizeDistribution(distribution: Task[][]): string {
|
|
314
|
-
const lines = distribution.map((tasks, i) => {
|
|
315
|
-
const subjects = tasks.slice(0, 3).map(t => t.subject.slice(0, 40));
|
|
316
|
-
const more = tasks.length > 3 ? ` (+${tasks.length - 3} more)` : '';
|
|
317
|
-
return ` Instance ${i + 1}: ${tasks.length} tasks${more}\n ${subjects.join('\n ')}`;
|
|
318
|
-
});
|
|
319
|
-
return lines.join('\n');
|
|
320
|
-
}
|