@hasna/skills 0.1.59 → 0.1.61
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/README.md +189 -60
- package/agent-skills/README.md +41 -0
- package/agent-skills/fleet-package-rollout/SKILL.md +169 -0
- package/agent-skills/inbox/SKILL.md +25 -0
- package/agent-skills/inbox/scripts/inbox +109 -0
- package/agent-skills/inbox/tests/test_registered_sender_id.sh +92 -0
- package/agent-skills/inbox-monitor/SKILL.md +41 -0
- package/agent-skills/inbox-monitor/scripts/inbox_monitor.sh +91 -0
- package/agent-skills/inbox-monitor/scripts/test_inbox_monitor.sh +71 -0
- package/agent-skills/merge-pr/SKILL.md +85 -0
- package/agent-skills/merge-pr/references/merge-safety.md +82 -0
- package/agent-skills/merge-pr/scripts/merge_pr_guard.py +694 -0
- package/agent-skills/merge-pr/scripts/test_merge_pr_guard.py +647 -0
- package/agent-skills/merge-pr/tests/fixtures/multi-commit-synthesized.json +28 -0
- package/agent-skills/merge-pr/tests/fixtures/trailer-free-provider.json +28 -0
- package/agent-skills/skill-goal-execute/SKILL.md +115 -0
- package/agent-skills/skill-login/SKILL.md +109 -0
- package/agent-skills/skill-project-create/SKILL.md +91 -0
- package/agent-skills/skill-publish/SKILL.md +207 -0
- package/bin/index.js +2457 -3344
- package/bin/mcp.js +1127 -2641
- package/bin/migrate.js +955 -33
- package/bin/server.js +2367 -1989
- package/bin/worker.js +2089 -151
- package/dist/cli/cli.test-utils.d.ts +13 -2
- package/dist/cli/commands/publish.d.ts +30 -0
- package/dist/cli/commands/registry.d.ts +8 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.js +1734 -2720
- package/dist/lib/agent-sync.d.ts +123 -0
- package/dist/lib/api-url.d.ts +34 -0
- package/dist/lib/auth-store.d.ts +21 -5
- package/dist/lib/blog-article.d.ts +37 -0
- package/dist/lib/config.d.ts +56 -2
- package/dist/lib/content-scan.d.ts +62 -9
- package/dist/lib/discovery.d.ts +10 -10
- package/dist/lib/doc-derived-counts.d.ts +56 -0
- package/dist/lib/feedback.d.ts +7 -0
- package/dist/lib/file-bytes.d.ts +43 -0
- package/dist/lib/hosted-skill-set.d.ts +69 -0
- package/dist/lib/infra-identifiers.d.ts +144 -0
- package/dist/lib/installer.d.ts +20 -6
- package/dist/lib/native-storage.d.ts +14 -11
- package/dist/lib/packlist.d.ts +13 -0
- package/dist/lib/portable-skills-files.d.ts +25 -0
- package/dist/lib/portable-skills-types.d.ts +105 -0
- package/dist/lib/portable-skills.d.ts +52 -103
- package/dist/lib/pull.d.ts +41 -0
- package/dist/lib/registry-merge.d.ts +57 -0
- package/dist/lib/registry-types.d.ts +1 -14
- package/dist/lib/registry.d.ts +6 -3
- package/dist/lib/remote-client.d.ts +15 -1
- package/dist/lib/remote-registry.d.ts +1 -1
- package/dist/lib/remote-run-contract.d.ts +0 -7
- package/dist/lib/retired-settings.d.ts +100 -0
- package/dist/lib/run-state.d.ts +14 -0
- package/dist/lib/skill-aliases.d.ts +0 -12
- package/dist/lib/skill-bundle.d.ts +37 -0
- package/dist/lib/vendor-host-code-scan.d.ts +66 -0
- package/dist/lib/vendor-host-folding.d.ts +40 -0
- package/dist/lib/vendor-host-guard.d.ts +47 -0
- package/dist/lib/vendor-host-package.d.ts +42 -0
- package/dist/lib/vendor-host-policy.d.ts +96 -0
- package/dist/lib/vendor-host-url.d.ts +81 -0
- package/dist/mcp/mcp-test-client.d.ts +18 -0
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +104 -51
- package/docs/skill-standard.md +1 -1
- package/migrations/postgres/0002_org_scoped_skill_registry.sql +72 -0
- package/migrations/sqlite/0001_open_skills_self_hosted.sql +150 -0
- package/migrations/sqlite/0002_org_scoped_skill_registry.sql +47 -0
- package/package.json +4 -4
- package/skills/_common/http-client.ts +17 -2
- package/skills/_common/install.sh +2 -2
- package/skills/_common/installer.ts +4 -5
- package/skills/_common/skill-install.ts +3 -3
- package/skills/ad-creative-pack/SKILL.md +28 -18
- package/skills/ad-creative-pack/package.json +1 -2
- package/skills/analyze-data/SKILL.md +1 -1
- package/skills/analyze-data/src/formatters.ts +2 -2
- package/skills/api-docs-portal/SKILL.md +62 -24
- package/skills/api-docs-portal/package.json +28 -4
- package/skills/api-docs-portal/src/index.ts +919 -0
- package/skills/audio-extract/SKILL.md +1 -1
- package/skills/blog-article/SKILL.md +32 -22
- package/skills/blog-article/package.json +1 -2
- package/skills/brand-assets/SKILL.md +94 -33
- package/skills/brand-assets/package.json +28 -4
- package/skills/brand-assets/src/cli.ts +155 -0
- package/skills/brand-assets/src/constants.ts +8 -0
- package/skills/brand-assets/src/extract.ts +236 -0
- package/skills/brand-assets/src/index.ts +668 -0
- package/skills/brand-assets/src/types.ts +59 -0
- package/skills/brand-kit/SKILL.md +27 -18
- package/skills/brand-kit/package.json +1 -2
- package/skills/compress-video/SKILL.md +1 -1
- package/skills/contract-review-report/SKILL.md +27 -18
- package/skills/contract-review-report/package.json +1 -2
- package/skills/customer-feedback-report/SKILL.md +27 -19
- package/skills/customer-feedback-report/package.json +1 -2
- package/skills/email-sequence/SKILL.md +26 -17
- package/skills/email-sequence/package.json +1 -2
- package/skills/generate-sitemap/src/index.ts +1 -1
- package/skills/invoice-reconciliation/SKILL.md +75 -19
- package/skills/invoice-reconciliation/package.json +29 -4
- package/skills/invoice-reconciliation/src/index.ts +743 -0
- package/skills/{convert → invoice-reconciliation}/tsconfig.json +3 -1
- package/skills/landing-page-pack/SKILL.md +27 -19
- package/skills/landing-page-pack/package.json +1 -2
- package/skills/logo-design/SKILL.md +69 -26
- package/skills/logo-design/package.json +28 -4
- package/skills/logo-design/src/cli.ts +132 -0
- package/skills/logo-design/src/constants.ts +5 -0
- package/skills/logo-design/src/docs.ts +102 -0
- package/skills/logo-design/src/geometry.ts +324 -0
- package/skills/logo-design/src/index.ts +212 -0
- package/skills/logo-design/src/palette.ts +258 -0
- package/skills/logo-design/src/types.ts +50 -0
- package/skills/logo-design/tsconfig.json +11 -2
- package/skills/market-research-report/SKILL.md +28 -18
- package/skills/market-research-report/package.json +2 -3
- package/skills/meeting-pack/SKILL.md +26 -17
- package/skills/meeting-pack/package.json +1 -2
- package/skills/merge-pdfs/src/index.ts +1 -1
- package/skills/migration-plan-pack/SKILL.md +30 -19
- package/skills/migration-plan-pack/package.json +1 -2
- package/skills/one-page-website/SKILL.md +105 -23
- package/skills/one-page-website/package.json +27 -4
- package/skills/one-page-website/src/design.ts +336 -0
- package/skills/one-page-website/src/docs.ts +159 -0
- package/skills/one-page-website/src/index.ts +357 -0
- package/skills/one-page-website/src/page.ts +340 -0
- package/skills/one-page-website/src/styles.ts +508 -0
- package/skills/one-page-website/src/types.ts +78 -0
- package/skills/one-page-website/tsconfig.json +11 -2
- package/skills/pdf-generate/SKILL.md +1 -1
- package/skills/pdf-to-dataset/SKILL.md +64 -21
- package/skills/pdf-to-dataset/package.json +30 -4
- package/skills/pdf-to-dataset/src/index.ts +790 -0
- package/skills/{emoji → pdf-to-dataset}/tsconfig.json +3 -4
- package/skills/pdf-to-markdown/SKILL.md +55 -23
- package/skills/pdf-to-markdown/package.json +28 -4
- package/skills/pdf-to-markdown/src/index.ts +694 -0
- package/skills/pdf-to-markdown/tsconfig.json +11 -4
- package/skills/performance-audit-report/SKILL.md +24 -17
- package/skills/performance-audit-report/package.json +1 -2
- package/skills/pitch-deck/SKILL.md +27 -19
- package/skills/pitch-deck/package.json +1 -2
- package/skills/product-mockup/SKILL.md +85 -23
- package/skills/product-mockup/package.json +25 -4
- package/skills/product-mockup/src/cli.ts +150 -0
- package/skills/product-mockup/src/design.ts +151 -0
- package/skills/product-mockup/src/docs.ts +134 -0
- package/skills/product-mockup/src/index.ts +182 -0
- package/skills/product-mockup/src/render.ts +407 -0
- package/skills/product-mockup/src/types.ts +66 -0
- package/skills/product-mockup/tsconfig.json +11 -2
- package/skills/proposal-pack/SKILL.md +27 -19
- package/skills/proposal-pack/package.json +2 -3
- package/skills/repo-onboarding-report/SKILL.md +26 -16
- package/skills/repo-onboarding-report/package.json +1 -2
- package/skills/security-audit/src/index.ts +1 -1
- package/skills/security-audit-report/SKILL.md +28 -16
- package/skills/security-audit-report/package.json +2 -3
- package/skills/seo-content-pack/SKILL.md +27 -17
- package/skills/seo-content-pack/package.json +1 -2
- package/skills/slide-deck-generator/SKILL.md +70 -21
- package/skills/slide-deck-generator/package.json +31 -4
- package/skills/slide-deck-generator/src/cli.ts +133 -0
- package/skills/slide-deck-generator/src/index.ts +148 -0
- package/skills/slide-deck-generator/src/model.ts +307 -0
- package/skills/slide-deck-generator/src/pptx.ts +143 -0
- package/skills/slide-deck-generator/src/render.ts +248 -0
- package/skills/slide-deck-generator/src/types.ts +114 -0
- package/skills/slide-deck-generator/src/utils.ts +53 -0
- package/skills/slide-deck-generator/tsconfig.json +17 -0
- package/skills/social-content-calendar/SKILL.md +27 -18
- package/skills/social-content-calendar/package.json +1 -2
- package/skills/split-pdf/src/index.ts +1 -1
- package/skills/test-suite-generator/SKILL.md +26 -16
- package/skills/test-suite-generator/package.json +2 -3
- package/skills/todos-plan/SKILL.md +339 -170
- package/skills/video-highlight-pack/SKILL.md +27 -17
- package/skills/video-highlight-pack/package.json +1 -2
- package/dist/cli/onboarding.d.ts +0 -13
- package/dist/lib/hosted-availability.d.ts +0 -13
- package/dist/lib/pricing.d.ts +0 -89
- package/skills/academic-journal-matcher/CLAUDE.md +0 -19
- package/skills/academic-journal-matcher/package.json +0 -27
- package/skills/academic-journal-matcher/src/index.ts +0 -86
- package/skills/academic-journal-matcher/tsconfig.json +0 -10
- package/skills/action-item-router/CLAUDE.md +0 -19
- package/skills/action-item-router/package.json +0 -27
- package/skills/action-item-router/src/index.ts +0 -304
- package/skills/action-item-router/tsconfig.json +0 -10
- package/skills/ad-creative-generator/CLAUDE.md +0 -19
- package/skills/ad-creative-generator/package.json +0 -27
- package/skills/ad-creative-generator/src/index.ts +0 -419
- package/skills/ad-creative-generator/tsconfig.json +0 -10
- package/skills/advanced-math/CLAUDE.md +0 -19
- package/skills/advanced-math/package.json +0 -29
- package/skills/advanced-math/src/calculators.ts +0 -118
- package/skills/advanced-math/src/cli.ts +0 -130
- package/skills/advanced-math/src/conversion.ts +0 -90
- package/skills/advanced-math/src/finance.ts +0 -75
- package/skills/advanced-math/src/formatting.ts +0 -95
- package/skills/advanced-math/src/index.ts +0 -133
- package/skills/advanced-math/src/runtime.ts +0 -49
- package/skills/advanced-math/src/symbolic.ts +0 -110
- package/skills/advanced-math/src/types.ts +0 -36
- package/skills/advanced-math/tsconfig.json +0 -10
- package/skills/anomaly-investigator/CLAUDE.md +0 -19
- package/skills/anomaly-investigator/package.json +0 -27
- package/skills/anomaly-investigator/src/index.ts +0 -311
- package/skills/anomaly-investigator/tsconfig.json +0 -10
- package/skills/apidocs/.env.example +0 -8
- package/skills/apidocs/CLAUDE.md +0 -278
- package/skills/apidocs/LICENSE +0 -192
- package/skills/apidocs/README.md +0 -196
- package/skills/apidocs/api-docs-list.json +0 -186
- package/skills/apidocs/package.json +0 -53
- package/skills/apidocs/scripts/crawl-all.ts +0 -157
- package/skills/apidocs/scripts/publish.ts +0 -210
- package/skills/apidocs/src/commands/add.ts +0 -279
- package/skills/apidocs/src/commands/endpoints.ts +0 -157
- package/skills/apidocs/src/commands/list.ts +0 -51
- package/skills/apidocs/src/commands/query.ts +0 -63
- package/skills/apidocs/src/commands/remove.ts +0 -39
- package/skills/apidocs/src/commands/sync.ts +0 -227
- package/skills/apidocs/src/index.ts +0 -3
- package/skills/apidocs/src/lib/crawler.ts +0 -427
- package/skills/apidocs/src/lib/discovery.ts +0 -244
- package/skills/apidocs/src/lib/embeddings.ts +0 -136
- package/skills/apidocs/src/lib/endpoint-extractor.ts +0 -359
- package/skills/apidocs/src/lib/html-to-md.ts +0 -163
- package/skills/apidocs/src/lib/parser.ts +0 -288
- package/skills/apidocs/src/lib/search.ts +0 -189
- package/skills/apidocs/src/lib/storage.ts +0 -242
- package/skills/apidocs/src/lib/vectors-local.ts +0 -220
- package/skills/apidocs/src/lib/vectors-s3.ts +0 -255
- package/skills/apidocs/src/lib/vectors.ts +0 -97
- package/skills/apidocs/src/types/index.ts +0 -297
- package/skills/apidocs/src/utils/output.ts +0 -132
- package/skills/apidocs/src/utils/paths.ts +0 -126
- package/skills/apidocs/tsconfig.json +0 -24
- package/skills/audio/SKILL.md +0 -35
- package/skills/audio/package.json +0 -11
- package/skills/audio-cleanup-lab/CLAUDE.md +0 -3
- package/skills/audio-cleanup-lab/SKILL.md +0 -81
- package/skills/audio-cleanup-lab/package.json +0 -23
- package/skills/audio-cleanup-lab/src/index.ts +0 -274
- package/skills/audio-cleanup-lab/tsconfig.json +0 -14
- package/skills/audio-transcript-pack/SKILL.md +0 -43
- package/skills/audio-transcript-pack/package.json +0 -11
- package/skills/banner-ad-suite/CLAUDE.md +0 -19
- package/skills/banner-ad-suite/package.json +0 -27
- package/skills/banner-ad-suite/src/index.ts +0 -331
- package/skills/banner-ad-suite/tsconfig.json +0 -10
- package/skills/benchmark-finder/CLAUDE.md +0 -19
- package/skills/benchmark-finder/package.json +0 -27
- package/skills/benchmark-finder/src/index.ts +0 -294
- package/skills/benchmark-finder/tsconfig.json +0 -10
- package/skills/blog-topic-cluster/CLAUDE.md +0 -19
- package/skills/blog-topic-cluster/package.json +0 -27
- package/skills/blog-topic-cluster/src/index.ts +0 -274
- package/skills/blog-topic-cluster/tsconfig.json +0 -10
- package/skills/brand-photo-shoot/SKILL.md +0 -28
- package/skills/brand-photo-shoot/package.json +0 -11
- package/skills/brand-style-guide/CLAUDE.md +0 -20
- package/skills/brand-style-guide/SKILL.md +0 -13
- package/skills/brand-style-guide/package.json +0 -26
- package/skills/brand-style-guide/src/index.ts +0 -288
- package/skills/brand-style-guide/tsconfig.json +0 -22
- package/skills/brand-voice-audit/CLAUDE.md +0 -19
- package/skills/brand-voice-audit/package.json +0 -27
- package/skills/brand-voice-audit/src/index.ts +0 -302
- package/skills/brand-voice-audit/tsconfig.json +0 -10
- package/skills/browse/LICENSE +0 -192
- package/skills/browse/README.md +0 -25
- package/skills/browse/SKILL.md +0 -35
- package/skills/browse/package.json +0 -11
- package/skills/browse/tsconfig.json +0 -22
- package/skills/budget-variance-analyzer/CLAUDE.md +0 -16
- package/skills/budget-variance-analyzer/SKILL.md +0 -83
- package/skills/budget-variance-analyzer/package.json +0 -24
- package/skills/budget-variance-analyzer/src/index.ts +0 -298
- package/skills/budget-variance-analyzer/tsconfig.json +0 -21
- package/skills/calendar-events/CLAUDE.md +0 -19
- package/skills/calendar-events/package.json +0 -27
- package/skills/calendar-events/src/ai-parser.ts +0 -103
- package/skills/calendar-events/src/api.ts +0 -157
- package/skills/calendar-events/src/auth.ts +0 -22
- package/skills/calendar-events/src/config.ts +0 -6
- package/skills/calendar-events/src/format.ts +0 -96
- package/skills/calendar-events/src/help.ts +0 -54
- package/skills/calendar-events/src/index.ts +0 -415
- package/skills/calendar-events/src/logger.ts +0 -34
- package/skills/calendar-events/src/types.ts +0 -67
- package/skills/calendar-events/tsconfig.json +0 -10
- package/skills/campaign-metric-brief/CLAUDE.md +0 -19
- package/skills/campaign-metric-brief/package.json +0 -27
- package/skills/campaign-metric-brief/src/index.ts +0 -307
- package/skills/campaign-metric-brief/tsconfig.json +0 -10
- package/skills/campaign-moodboard/CLAUDE.md +0 -19
- package/skills/campaign-moodboard/package.json +0 -27
- package/skills/campaign-moodboard/src/index.ts +0 -288
- package/skills/campaign-moodboard/tsconfig.json +0 -10
- package/skills/caption-style-stylist/CLAUDE.md +0 -19
- package/skills/caption-style-stylist/package.json +0 -27
- package/skills/caption-style-stylist/src/index.ts +0 -275
- package/skills/caption-style-stylist/tsconfig.json +0 -10
- package/skills/chemistry-calculator/CLAUDE.md +0 -19
- package/skills/chemistry-calculator/package.json +0 -27
- package/skills/chemistry-calculator/src/index.ts +0 -110
- package/skills/chemistry-calculator/tsconfig.json +0 -10
- package/skills/churn-risk-notifier/CLAUDE.md +0 -19
- package/skills/churn-risk-notifier/package.json +0 -27
- package/skills/churn-risk-notifier/src/index.ts +0 -308
- package/skills/churn-risk-notifier/tsconfig.json +0 -10
- package/skills/citation-formatter/CLAUDE.md +0 -19
- package/skills/citation-formatter/package.json +0 -27
- package/skills/citation-formatter/src/index.ts +0 -83
- package/skills/citation-formatter/tsconfig.json +0 -10
- package/skills/classroom-newsletter-kit/CLAUDE.md +0 -19
- package/skills/classroom-newsletter-kit/package.json +0 -27
- package/skills/classroom-newsletter-kit/src/index.ts +0 -293
- package/skills/classroom-newsletter-kit/tsconfig.json +0 -10
- package/skills/color-palette-harmonizer/CLAUDE.md +0 -19
- package/skills/color-palette-harmonizer/package.json +0 -27
- package/skills/color-palette-harmonizer/src/index.ts +0 -278
- package/skills/color-palette-harmonizer/tsconfig.json +0 -10
- package/skills/colorextract/SKILL.md +0 -35
- package/skills/colorextract/bun.lock +0 -102
- package/skills/colorextract/package.json +0 -25
- package/skills/colorextract/src/index.ts +0 -405
- package/skills/competitor-ad-analyzer/CLAUDE.md +0 -19
- package/skills/competitor-ad-analyzer/package.json +0 -27
- package/skills/competitor-ad-analyzer/src/index.ts +0 -350
- package/skills/competitor-ad-analyzer/tsconfig.json +0 -10
- package/skills/compliance-copy-check/CLAUDE.md +0 -19
- package/skills/compliance-copy-check/package.json +0 -27
- package/skills/compliance-copy-check/src/index.ts +0 -289
- package/skills/compliance-copy-check/tsconfig.json +0 -10
- package/skills/compliance-report-pack/CLAUDE.md +0 -19
- package/skills/compliance-report-pack/package.json +0 -27
- package/skills/compliance-report-pack/src/index.ts +0 -301
- package/skills/compliance-report-pack/tsconfig.json +0 -10
- package/skills/consolelog/.env.example +0 -19
- package/skills/consolelog/CLAUDE.md +0 -157
- package/skills/consolelog/LICENSE +0 -192
- package/skills/consolelog/README.md +0 -239
- package/skills/consolelog/data/.gitkeep +0 -0
- package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.csv +0 -16
- package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.json +0 -227
- package/skills/consolelog/package.json +0 -40
- package/skills/consolelog/scripts/migrate.ts +0 -26
- package/skills/consolelog/scripts/seed.ts +0 -48
- package/skills/consolelog/src/db/index.ts +0 -44
- package/skills/consolelog/src/db/queries.ts +0 -348
- package/skills/consolelog/src/db/schema.ts +0 -93
- package/skills/consolelog/src/index.ts +0 -3
- package/skills/consolelog/src/lib/config.ts +0 -110
- package/skills/consolelog/src/lib/installer.ts +0 -294
- package/skills/consolelog/src/lib/monitor.ts +0 -194
- package/skills/consolelog/src/lib/types.ts +0 -189
- package/skills/consolelog/src/lib/watcher.ts +0 -207
- package/skills/consolelog/tests/api.test.ts +0 -154
- package/skills/consolelog/tests/config.test.ts +0 -192
- package/skills/consolelog/tests/db.test.ts +0 -447
- package/skills/consolelog/tests/installer.test.ts +0 -155
- package/skills/consolelog/tsconfig.json +0 -24
- package/skills/contract-plainlanguage/CLAUDE.md +0 -19
- package/skills/contract-plainlanguage/package.json +0 -27
- package/skills/contract-plainlanguage/src/index.ts +0 -294
- package/skills/contract-plainlanguage/tsconfig.json +0 -10
- package/skills/convert/.env.example +0 -7
- package/skills/convert/LICENSE +0 -192
- package/skills/convert/README.md +0 -250
- package/skills/convert/SKILL.md +0 -106
- package/skills/convert/package.json +0 -37
- package/skills/convert/src/converters/ai.ts +0 -375
- package/skills/convert/src/converters/data.ts +0 -339
- package/skills/convert/src/converters/document.ts +0 -189
- package/skills/convert/src/converters/image.ts +0 -227
- package/skills/convert/src/converters/index.ts +0 -9
- package/skills/convert/src/converters/pdf.ts +0 -255
- package/skills/convert/src/index-local.ts +0 -568
- package/skills/convert/src/index.ts +0 -4
- package/skills/convert/src/types.ts +0 -192
- package/skills/copytone-translator/CLAUDE.md +0 -19
- package/skills/copytone-translator/package.json +0 -27
- package/skills/copytone-translator/src/index.ts +0 -295
- package/skills/copytone-translator/tsconfig.json +0 -10
- package/skills/create-ebook/CLAUDE.md +0 -19
- package/skills/create-ebook/package.json +0 -27
- package/skills/create-ebook/src/index.ts +0 -637
- package/skills/create-ebook/tsconfig.json +0 -10
- package/skills/crm-note-enhancer/CLAUDE.md +0 -19
- package/skills/crm-note-enhancer/package.json +0 -27
- package/skills/crm-note-enhancer/src/index.ts +0 -317
- package/skills/crm-note-enhancer/tsconfig.json +0 -10
- package/skills/customer-journey-mapper/CLAUDE.md +0 -19
- package/skills/customer-journey-mapper/package.json +0 -27
- package/skills/customer-journey-mapper/src/index.ts +0 -312
- package/skills/customer-journey-mapper/tsconfig.json +0 -10
- package/skills/dashboard-narrator/CLAUDE.md +0 -19
- package/skills/dashboard-narrator/package.json +0 -27
- package/skills/dashboard-narrator/src/index.ts +0 -307
- package/skills/dashboard-narrator/tsconfig.json +0 -10
- package/skills/dataset-health-check/CLAUDE.md +0 -19
- package/skills/dataset-health-check/package.json +0 -27
- package/skills/dataset-health-check/src/index.ts +0 -323
- package/skills/dataset-health-check/tsconfig.json +0 -10
- package/skills/decision-journal/CLAUDE.md +0 -19
- package/skills/decision-journal/package.json +0 -27
- package/skills/decision-journal/src/index.ts +0 -313
- package/skills/decision-journal/tsconfig.json +0 -10
- package/skills/deepresearch/CLAUDE.md +0 -11
- package/skills/deepresearch/README.md +0 -26
- package/skills/deepresearch/SKILL.md +0 -41
- package/skills/deepresearch/package.json +0 -11
- package/skills/deepresearch/tsconfig.json +0 -29
- package/skills/delegation-brief-writer/CLAUDE.md +0 -19
- package/skills/delegation-brief-writer/package.json +0 -27
- package/skills/delegation-brief-writer/src/index.ts +0 -314
- package/skills/delegation-brief-writer/tsconfig.json +0 -10
- package/skills/deploy/LICENSE +0 -192
- package/skills/deploy/README.md +0 -382
- package/skills/deploy/SKILL.md +0 -138
- package/skills/deploy/package.json +0 -18
- package/skills/deploy/src/deployer.ts +0 -256
- package/skills/deploy/src/health.ts +0 -103
- package/skills/deploy/src/hosts.ts +0 -45
- package/skills/deploy/src/http-client.ts +0 -128
- package/skills/deploy/src/index-local.ts +0 -366
- package/skills/deploy/src/index.ts +0 -4
- package/skills/deploy/src/types.ts +0 -56
- package/skills/deploy/tsconfig.json +0 -18
- package/skills/destination-briefing/CLAUDE.md +0 -19
- package/skills/destination-briefing/package.json +0 -27
- package/skills/destination-briefing/src/index.ts +0 -291
- package/skills/destination-briefing/tsconfig.json +0 -10
- package/skills/doc-generate/CLAUDE.md +0 -19
- package/skills/doc-generate/SKILL.md +0 -295
- package/skills/doc-generate/package.json +0 -23
- package/skills/doc-generate/src/ai.ts +0 -50
- package/skills/doc-generate/src/cli.ts +0 -203
- package/skills/doc-generate/src/dependencies.ts +0 -44
- package/skills/doc-generate/src/document-builder.ts +0 -299
- package/skills/doc-generate/src/index.ts +0 -90
- package/skills/doc-generate/src/markdown-parser.ts +0 -125
- package/skills/doc-generate/src/types.ts +0 -68
- package/skills/doc-generate/tsconfig.json +0 -16
- package/skills/domainsearch/.env.example +0 -7
- package/skills/domainsearch/LICENSE +0 -192
- package/skills/domainsearch/SKILL.md +0 -41
- package/skills/domainsearch/package.json +0 -33
- package/skills/domainsearch/src/index.ts +0 -3
- package/skills/domainsearch/src/lib/api-client.ts +0 -181
- package/skills/domainsearch/src/lib/config.ts +0 -72
- package/skills/domainsearch/src/lib/installer.ts +0 -164
- package/skills/domainsearch/tsconfig.json +0 -22
- package/skills/educational-resource-finder/CLAUDE.md +0 -19
- package/skills/educational-resource-finder/package.json +0 -27
- package/skills/educational-resource-finder/src/index.ts +0 -289
- package/skills/educational-resource-finder/tsconfig.json +0 -10
- package/skills/email-campaign/CLAUDE.md +0 -19
- package/skills/email-campaign/package.json +0 -27
- package/skills/email-campaign/src/index.ts +0 -339
- package/skills/email-campaign/tsconfig.json +0 -10
- package/skills/emoji/.env.example +0 -7
- package/skills/emoji/QUICKSTART.md +0 -52
- package/skills/emoji/README.md +0 -175
- package/skills/emoji/SKILL.md +0 -63
- package/skills/emoji/package.json +0 -31
- package/skills/emoji/src/image-processor.ts +0 -143
- package/skills/emoji/src/index.ts +0 -282
- package/skills/emoji/src/prompt-generator.ts +0 -181
- package/skills/emoji/src/providers/gemini.ts +0 -58
- package/skills/emoji/src/providers/openai.ts +0 -55
- package/skills/emoji/src/types.ts +0 -72
- package/skills/exam-readiness-check/CLAUDE.md +0 -19
- package/skills/exam-readiness-check/package.json +0 -27
- package/skills/exam-readiness-check/src/index.ts +0 -289
- package/skills/exam-readiness-check/tsconfig.json +0 -10
- package/skills/excel/CLAUDE.md +0 -19
- package/skills/excel/SKILL.md +0 -38
- package/skills/excel/package.json +0 -30
- package/skills/excel/src/index.ts +0 -644
- package/skills/excel/tsconfig.json +0 -10
- package/skills/extract/.env.example +0 -3
- package/skills/extract/LICENSE +0 -192
- package/skills/extract/README.md +0 -61
- package/skills/extract/SKILL.md +0 -91
- package/skills/extract/package.json +0 -35
- package/skills/extract/src/extractors/image.ts +0 -42
- package/skills/extract/src/extractors/pdf.ts +0 -96
- package/skills/extract/src/index-local.ts +0 -258
- package/skills/extract/src/index.ts +0 -4
- package/skills/extract/src/providers/openai.ts +0 -222
- package/skills/extract/src/types.ts +0 -61
- package/skills/extract/tsconfig.json +0 -19
- package/skills/extract-invoice/CLAUDE.md +0 -19
- package/skills/extract-invoice/package.json +0 -27
- package/skills/extract-invoice/src/cli.ts +0 -97
- package/skills/extract-invoice/src/extractor.ts +0 -170
- package/skills/extract-invoice/src/file-utils.ts +0 -46
- package/skills/extract-invoice/src/formatters.ts +0 -144
- package/skills/extract-invoice/src/index.ts +0 -129
- package/skills/extract-invoice/src/runtime.ts +0 -46
- package/skills/extract-invoice/src/types.ts +0 -88
- package/skills/extract-invoice/tsconfig.json +0 -10
- package/skills/family-activity-curator/CLAUDE.md +0 -19
- package/skills/family-activity-curator/package.json +0 -27
- package/skills/family-activity-curator/src/index.ts +0 -293
- package/skills/family-activity-curator/tsconfig.json +0 -10
- package/skills/faq-packager/CLAUDE.md +0 -19
- package/skills/faq-packager/package.json +0 -27
- package/skills/faq-packager/src/index.ts +0 -292
- package/skills/faq-packager/tsconfig.json +0 -10
- package/skills/feedback-survey-designer/CLAUDE.md +0 -19
- package/skills/feedback-survey-designer/package.json +0 -27
- package/skills/feedback-survey-designer/src/index.ts +0 -299
- package/skills/feedback-survey-designer/tsconfig.json +0 -10
- package/skills/field-trip-planner/CLAUDE.md +0 -19
- package/skills/field-trip-planner/package.json +0 -27
- package/skills/field-trip-planner/src/index.ts +0 -289
- package/skills/field-trip-planner/tsconfig.json +0 -10
- package/skills/forecast-scenario-lab/CLAUDE.md +0 -19
- package/skills/forecast-scenario-lab/package.json +0 -27
- package/skills/forecast-scenario-lab/src/index.ts +0 -314
- package/skills/forecast-scenario-lab/tsconfig.json +0 -10
- package/skills/generate-book-cover/CLAUDE.md +0 -19
- package/skills/generate-book-cover/package.json +0 -11
- package/skills/generate-book-cover/tsconfig.json +0 -10
- package/skills/generate-diagram/CLAUDE.md +0 -19
- package/skills/generate-diagram/package.json +0 -27
- package/skills/generate-diagram/src/index.ts +0 -514
- package/skills/generate-diagram/tsconfig.json +0 -10
- package/skills/generate-documentation/CLAUDE.md +0 -19
- package/skills/generate-documentation/package.json +0 -27
- package/skills/generate-documentation/src/ai.ts +0 -131
- package/skills/generate-documentation/src/cli.ts +0 -71
- package/skills/generate-documentation/src/code-parser.ts +0 -300
- package/skills/generate-documentation/src/file-processing.ts +0 -182
- package/skills/generate-documentation/src/index.ts +0 -65
- package/skills/generate-documentation/src/runtime.ts +0 -35
- package/skills/generate-documentation/src/types.ts +0 -30
- package/skills/generate-documentation/tsconfig.json +0 -10
- package/skills/generate-mock-data/CLAUDE.md +0 -19
- package/skills/generate-mock-data/package.json +0 -29
- package/skills/generate-mock-data/src/ai.ts +0 -102
- package/skills/generate-mock-data/src/formatters.ts +0 -84
- package/skills/generate-mock-data/src/generator.ts +0 -377
- package/skills/generate-mock-data/src/index.ts +0 -201
- package/skills/generate-mock-data/src/logger.ts +0 -37
- package/skills/generate-mock-data/src/presets.ts +0 -110
- package/skills/generate-mock-data/src/types.ts +0 -21
- package/skills/generate-mock-data/tsconfig.json +0 -10
- package/skills/generate-pr-description/CLAUDE.md +0 -19
- package/skills/generate-pr-description/package.json +0 -27
- package/skills/generate-pr-description/src/ai.ts +0 -144
- package/skills/generate-pr-description/src/cli.ts +0 -80
- package/skills/generate-pr-description/src/clipboard.ts +0 -30
- package/skills/generate-pr-description/src/formatters.ts +0 -231
- package/skills/generate-pr-description/src/git.ts +0 -153
- package/skills/generate-pr-description/src/index.ts +0 -114
- package/skills/generate-pr-description/src/types.ts +0 -49
- package/skills/generate-pr-description/tsconfig.json +0 -10
- package/skills/generate-presentation/CLAUDE.md +0 -19
- package/skills/generate-presentation/package.json +0 -27
- package/skills/generate-presentation/src/ai-clients.ts +0 -61
- package/skills/generate-presentation/src/cli.ts +0 -126
- package/skills/generate-presentation/src/index.ts +0 -44
- package/skills/generate-presentation/src/logger.ts +0 -67
- package/skills/generate-presentation/src/presentation-generator.ts +0 -425
- package/skills/generate-presentation/src/runtime.ts +0 -6
- package/skills/generate-presentation/src/security.ts +0 -12
- package/skills/generate-presentation/src/types.ts +0 -28
- package/skills/generate-presentation/tsconfig.json +0 -10
- package/skills/generate-regex/CLAUDE.md +0 -19
- package/skills/generate-regex/package.json +0 -29
- package/skills/generate-regex/src/index.ts +0 -669
- package/skills/generate-regex/tsconfig.json +0 -10
- package/skills/generate-social-posts/CLAUDE.md +0 -19
- package/skills/generate-social-posts/package.json +0 -27
- package/skills/generate-social-posts/src/ai.ts +0 -88
- package/skills/generate-social-posts/src/cli.ts +0 -118
- package/skills/generate-social-posts/src/exporters.ts +0 -126
- package/skills/generate-social-posts/src/generator.ts +0 -130
- package/skills/generate-social-posts/src/index.ts +0 -78
- package/skills/generate-social-posts/src/platforms.ts +0 -39
- package/skills/generate-social-posts/src/runtime.ts +0 -34
- package/skills/generate-social-posts/src/source.ts +0 -116
- package/skills/generate-social-posts/src/types.ts +0 -58
- package/skills/generate-social-posts/tsconfig.json +0 -10
- package/skills/generate-sql/CLAUDE.md +0 -19
- package/skills/generate-sql/package.json +0 -27
- package/skills/generate-sql/src/index.ts +0 -636
- package/skills/generate-sql/tsconfig.json +0 -10
- package/skills/github-manager/CLAUDE.md +0 -19
- package/skills/github-manager/package.json +0 -29
- package/skills/github-manager/src/index.ts +0 -101
- package/skills/github-manager/tsconfig.json +0 -10
- package/skills/gmail/CLAUDE.md +0 -19
- package/skills/gmail/package.json +0 -27
- package/skills/gmail/src/index.ts +0 -410
- package/skills/gmail/tsconfig.json +0 -10
- package/skills/goal-quarterly-roadmap/CLAUDE.md +0 -19
- package/skills/goal-quarterly-roadmap/package.json +0 -27
- package/skills/goal-quarterly-roadmap/src/index.ts +0 -305
- package/skills/goal-quarterly-roadmap/tsconfig.json +0 -10
- package/skills/grant-application-drafter/CLAUDE.md +0 -19
- package/skills/grant-application-drafter/package.json +0 -27
- package/skills/grant-application-drafter/src/index.ts +0 -309
- package/skills/grant-application-drafter/tsconfig.json +0 -10
- package/skills/grocery-basket-optimizer/CLAUDE.md +0 -19
- package/skills/grocery-basket-optimizer/package.json +0 -27
- package/skills/grocery-basket-optimizer/src/index.ts +0 -304
- package/skills/grocery-basket-optimizer/tsconfig.json +0 -10
- package/skills/guest-communication-suite/CLAUDE.md +0 -19
- package/skills/guest-communication-suite/package.json +0 -27
- package/skills/guest-communication-suite/src/index.ts +0 -312
- package/skills/guest-communication-suite/tsconfig.json +0 -10
- package/skills/habit-reflection-digest/CLAUDE.md +0 -19
- package/skills/habit-reflection-digest/package.json +0 -27
- package/skills/habit-reflection-digest/src/index.ts +0 -308
- package/skills/habit-reflection-digest/tsconfig.json +0 -10
- package/skills/highlight-reel-generator/CLAUDE.md +0 -19
- package/skills/highlight-reel-generator/package.json +0 -27
- package/skills/highlight-reel-generator/src/index.ts +0 -286
- package/skills/highlight-reel-generator/tsconfig.json +0 -10
- package/skills/homework-feedback-coach/CLAUDE.md +0 -19
- package/skills/homework-feedback-coach/package.json +0 -27
- package/skills/homework-feedback-coach/src/index.ts +0 -316
- package/skills/homework-feedback-coach/tsconfig.json +0 -10
- package/skills/household-maintenance-mgr/CLAUDE.md +0 -19
- package/skills/household-maintenance-mgr/package.json +0 -27
- package/skills/household-maintenance-mgr/src/index.ts +0 -293
- package/skills/household-maintenance-mgr/tsconfig.json +0 -10
- package/skills/icon-pack/README.md +0 -28
- package/skills/icon-pack/SKILL.md +0 -23
- package/skills/icon-pack/package.json +0 -11
- package/skills/icon-pack/tsconfig.json +0 -20
- package/skills/image/LICENSE +0 -192
- package/skills/image/README.md +0 -25
- package/skills/image/SKILL.md +0 -49
- package/skills/image/examples/aurora-examples.sh +0 -33
- package/skills/image/examples/google-examples.sh +0 -37
- package/skills/image/examples/openai-examples.sh +0 -35
- package/skills/image/package.json +0 -11
- package/skills/image/tsconfig.json +0 -19
- package/skills/implementation-agent/CLAUDE.md +0 -19
- package/skills/implementation-agent/package.json +0 -29
- package/skills/implementation-agent/src/ai-generation.ts +0 -225
- package/skills/implementation-agent/src/index.ts +0 -608
- package/skills/implementation-agent/src/minimist.d.ts +0 -15
- package/skills/implementation-agent/src/templates.ts +0 -686
- package/skills/implementation-agent/src/types.ts +0 -53
- package/skills/implementation-agent/tsconfig.json +0 -10
- package/skills/inbox-priority-planner/CLAUDE.md +0 -19
- package/skills/inbox-priority-planner/package.json +0 -27
- package/skills/inbox-priority-planner/src/index.ts +0 -309
- package/skills/inbox-priority-planner/tsconfig.json +0 -10
- package/skills/invoice-dispute-helper/CLAUDE.md +0 -19
- package/skills/invoice-dispute-helper/package.json +0 -27
- package/skills/invoice-dispute-helper/src/index.ts +0 -304
- package/skills/invoice-dispute-helper/tsconfig.json +0 -10
- package/skills/itinerary-architect/CLAUDE.md +0 -19
- package/skills/itinerary-architect/package.json +0 -27
- package/skills/itinerary-architect/src/index.ts +0 -313
- package/skills/itinerary-architect/tsconfig.json +0 -10
- package/skills/kpi-digest-generator/CLAUDE.md +0 -19
- package/skills/kpi-digest-generator/package.json +0 -27
- package/skills/kpi-digest-generator/src/index.ts +0 -318
- package/skills/kpi-digest-generator/tsconfig.json +0 -10
- package/skills/lab-notebook-formatter/CLAUDE.md +0 -19
- package/skills/lab-notebook-formatter/package.json +0 -27
- package/skills/lab-notebook-formatter/src/index.ts +0 -88
- package/skills/lab-notebook-formatter/tsconfig.json +0 -10
- package/skills/landing-page-copy/CLAUDE.md +0 -19
- package/skills/landing-page-copy/package.json +0 -27
- package/skills/landing-page-copy/src/index.ts +0 -400
- package/skills/landing-page-copy/tsconfig.json +0 -10
- package/skills/learning-style-profiler/CLAUDE.md +0 -19
- package/skills/learning-style-profiler/package.json +0 -27
- package/skills/learning-style-profiler/src/index.ts +0 -291
- package/skills/learning-style-profiler/tsconfig.json +0 -10
- package/skills/lesson-plan-customizer/CLAUDE.md +0 -19
- package/skills/lesson-plan-customizer/package.json +0 -27
- package/skills/lesson-plan-customizer/src/index.ts +0 -303
- package/skills/lesson-plan-customizer/tsconfig.json +0 -10
- package/skills/livestream-runofshow/CLAUDE.md +0 -19
- package/skills/livestream-runofshow/package.json +0 -27
- package/skills/livestream-runofshow/src/index.ts +0 -299
- package/skills/livestream-runofshow/tsconfig.json +0 -10
- package/skills/longform-structurer/CLAUDE.md +0 -19
- package/skills/longform-structurer/package.json +0 -27
- package/skills/longform-structurer/src/index.ts +0 -293
- package/skills/longform-structurer/tsconfig.json +0 -10
- package/skills/managehook/.env.example +0 -16
- package/skills/managehook/CLAUDE.md +0 -48
- package/skills/managehook/README.md +0 -210
- package/skills/managehook/package.json +0 -24
- package/skills/managehook/scripts/migrate.ts +0 -57
- package/skills/managehook/scripts/seed.ts +0 -58
- package/skills/managehook/src/db/index.ts +0 -37
- package/skills/managehook/src/index.ts +0 -3
- package/skills/managehook/src/lib/api-client.ts +0 -108
- package/skills/managehook/src/lib/config.ts +0 -34
- package/skills/managehook/src/lib/installer.ts +0 -140
- package/skills/managehook/src/lib/service-dir.ts +0 -119
- package/skills/managehook/tsconfig.json +0 -29
- package/skills/manageskill/.env.example +0 -16
- package/skills/manageskill/CLAUDE.md +0 -48
- package/skills/manageskill/README.md +0 -210
- package/skills/manageskill/package.json +0 -24
- package/skills/manageskill/scripts/migrate.ts +0 -57
- package/skills/manageskill/scripts/seed.ts +0 -58
- package/skills/manageskill/src/db/index.ts +0 -37
- package/skills/manageskill/src/index.ts +0 -3
- package/skills/manageskill/src/lib/api-client.ts +0 -108
- package/skills/manageskill/src/lib/config.ts +0 -34
- package/skills/manageskill/src/lib/installer.ts +0 -140
- package/skills/manageskill/src/lib/service-dir.ts +0 -119
- package/skills/manageskill/tsconfig.json +0 -29
- package/skills/mcp-builder/CLAUDE.md +0 -19
- package/skills/mcp-builder/package.json +0 -30
- package/skills/mcp-builder/src/ai-descriptions.ts +0 -37
- package/skills/mcp-builder/src/generators.ts +0 -513
- package/skills/mcp-builder/src/index.ts +0 -62
- package/skills/mcp-builder/src/minimist.d.ts +0 -15
- package/skills/mcp-builder/src/naming.ts +0 -12
- package/skills/mcp-builder/src/options.ts +0 -170
- package/skills/mcp-builder/src/templates.ts +0 -149
- package/skills/mcp-builder/src/types.ts +0 -42
- package/skills/mcp-builder/tsconfig.json +0 -10
- package/skills/meal-plan-designer/CLAUDE.md +0 -19
- package/skills/meal-plan-designer/package.json +0 -27
- package/skills/meal-plan-designer/src/index.ts +0 -301
- package/skills/meal-plan-designer/tsconfig.json +0 -10
- package/skills/meeting-insight-summarizer/CLAUDE.md +0 -19
- package/skills/meeting-insight-summarizer/package.json +0 -27
- package/skills/meeting-insight-summarizer/src/index.ts +0 -316
- package/skills/meeting-insight-summarizer/tsconfig.json +0 -10
- package/skills/microcopy-generator/CLAUDE.md +0 -19
- package/skills/microcopy-generator/package.json +0 -27
- package/skills/microcopy-generator/src/index.ts +0 -303
- package/skills/microcopy-generator/tsconfig.json +0 -10
- package/skills/mindfulness-prompt-cache/CLAUDE.md +0 -19
- package/skills/mindfulness-prompt-cache/package.json +0 -27
- package/skills/mindfulness-prompt-cache/src/index.ts +0 -290
- package/skills/mindfulness-prompt-cache/tsconfig.json +0 -10
- package/skills/music/SKILL.md +0 -33
- package/skills/music/package.json +0 -11
- package/skills/music-album/SKILL.md +0 -37
- package/skills/music-album/package.json +0 -11
- package/skills/notion-manager/CLAUDE.md +0 -19
- package/skills/notion-manager/package.json +0 -29
- package/skills/notion-manager/src/index.ts +0 -105
- package/skills/notion-manager/tsconfig.json +0 -10
- package/skills/npmpublish/CLAUDE.md +0 -30
- package/skills/npmpublish/README.md +0 -83
- package/skills/npmpublish/SKILL.md +0 -70
- package/skills/npmpublish/package.json +0 -41
- package/skills/npmpublish/src/index.ts +0 -192
- package/skills/npmpublish/tsconfig.json +0 -18
- package/skills/onboarding-sequence-builder/CLAUDE.md +0 -19
- package/skills/onboarding-sequence-builder/package.json +0 -27
- package/skills/onboarding-sequence-builder/src/index.ts +0 -321
- package/skills/onboarding-sequence-builder/tsconfig.json +0 -10
- package/skills/onsite-ops-checklist/CLAUDE.md +0 -19
- package/skills/onsite-ops-checklist/package.json +0 -27
- package/skills/onsite-ops-checklist/src/index.ts +0 -307
- package/skills/onsite-ops-checklist/tsconfig.json +0 -10
- package/skills/outreach-cadence-designer/CLAUDE.md +0 -19
- package/skills/outreach-cadence-designer/package.json +0 -27
- package/skills/outreach-cadence-designer/src/index.ts +0 -330
- package/skills/outreach-cadence-designer/tsconfig.json +0 -10
- package/skills/packaging-concept-studio/CLAUDE.md +0 -19
- package/skills/packaging-concept-studio/package.json +0 -27
- package/skills/packaging-concept-studio/src/index.ts +0 -296
- package/skills/packaging-concept-studio/tsconfig.json +0 -10
- package/skills/packing-plan-pro/CLAUDE.md +0 -19
- package/skills/packing-plan-pro/package.json +0 -27
- package/skills/packing-plan-pro/src/index.ts +0 -306
- package/skills/packing-plan-pro/tsconfig.json +0 -10
- package/skills/parent-teacher-brief/CLAUDE.md +0 -19
- package/skills/parent-teacher-brief/package.json +0 -27
- package/skills/parent-teacher-brief/src/index.ts +0 -290
- package/skills/parent-teacher-brief/tsconfig.json +0 -10
- package/skills/partner-kit-assembler/CLAUDE.md +0 -19
- package/skills/partner-kit-assembler/package.json +0 -27
- package/skills/partner-kit-assembler/src/index.ts +0 -313
- package/skills/partner-kit-assembler/tsconfig.json +0 -10
- package/skills/payroll-change-prepper/CLAUDE.md +0 -19
- package/skills/payroll-change-prepper/package.json +0 -27
- package/skills/payroll-change-prepper/src/index.ts +0 -304
- package/skills/payroll-change-prepper/tsconfig.json +0 -10
- package/skills/pdf-read/SKILL.md +0 -56
- package/skills/pdf-read/package.json +0 -11
- package/skills/pdf-read/tsconfig.json +0 -8
- package/skills/persona-based-adwriter/CLAUDE.md +0 -19
- package/skills/persona-based-adwriter/package.json +0 -27
- package/skills/persona-based-adwriter/src/index.ts +0 -285
- package/skills/persona-based-adwriter/tsconfig.json +0 -10
- package/skills/persona-generator/CLAUDE.md +0 -19
- package/skills/persona-generator/package.json +0 -27
- package/skills/persona-generator/src/index.ts +0 -443
- package/skills/persona-generator/tsconfig.json +0 -10
- package/skills/personal-daily-ops/CLAUDE.md +0 -19
- package/skills/personal-daily-ops/package.json +0 -27
- package/skills/personal-daily-ops/src/index.ts +0 -324
- package/skills/personal-daily-ops/tsconfig.json +0 -10
- package/skills/pet-care-scheduler/CLAUDE.md +0 -19
- package/skills/pet-care-scheduler/package.json +0 -27
- package/skills/pet-care-scheduler/src/index.ts +0 -298
- package/skills/pet-care-scheduler/tsconfig.json +0 -10
- package/skills/photo-album/SKILL.md +0 -29
- package/skills/photo-album/package.json +0 -11
- package/skills/photo-album/tsconfig.json +0 -4
- package/skills/playlist-maker/SKILL.md +0 -33
- package/skills/playlist-maker/package.json +0 -11
- package/skills/playlist-maker/tsconfig.json +0 -4
- package/skills/podcast-show-notes/CLAUDE.md +0 -19
- package/skills/podcast-show-notes/package.json +0 -27
- package/skills/podcast-show-notes/src/index.ts +0 -302
- package/skills/podcast-show-notes/tsconfig.json +0 -10
- package/skills/presentation-theme-maker/CLAUDE.md +0 -19
- package/skills/presentation-theme-maker/package.json +0 -27
- package/skills/presentation-theme-maker/src/index.ts +0 -292
- package/skills/presentation-theme-maker/tsconfig.json +0 -10
- package/skills/press-release-drafter/CLAUDE.md +0 -19
- package/skills/press-release-drafter/package.json +0 -27
- package/skills/press-release-drafter/src/index.ts +0 -291
- package/skills/press-release-drafter/tsconfig.json +0 -10
- package/skills/print-collateral-designer/CLAUDE.md +0 -19
- package/skills/print-collateral-designer/package.json +0 -27
- package/skills/print-collateral-designer/src/index.ts +0 -298
- package/skills/print-collateral-designer/tsconfig.json +0 -10
- package/skills/procurement-scorecard/CLAUDE.md +0 -19
- package/skills/procurement-scorecard/package.json +0 -27
- package/skills/procurement-scorecard/src/index.ts +0 -338
- package/skills/procurement-scorecard/tsconfig.json +0 -10
- package/skills/product-demo-script/CLAUDE.md +0 -19
- package/skills/product-demo-script/package.json +0 -27
- package/skills/product-demo-script/src/index.ts +0 -326
- package/skills/product-demo-script/tsconfig.json +0 -10
- package/skills/project-dashboard-reports/SKILL.md +0 -78
- package/skills/project-dashboard-reports/package.json +0 -25
- package/skills/project-dashboard-reports/src/index.ts +0 -67
- package/skills/project-retro-companion/CLAUDE.md +0 -19
- package/skills/project-retro-companion/package.json +0 -27
- package/skills/project-retro-companion/src/index.ts +0 -298
- package/skills/project-retro-companion/tsconfig.json +0 -10
- package/skills/proposal-redline-advisor/CLAUDE.md +0 -19
- package/skills/proposal-redline-advisor/package.json +0 -27
- package/skills/proposal-redline-advisor/src/index.ts +0 -320
- package/skills/proposal-redline-advisor/tsconfig.json +0 -10
- package/skills/read-image/SKILL.md +0 -47
- package/skills/read-image/package.json +0 -33
- package/skills/read-image/src/index.ts +0 -264
- package/skills/read-pdf/SKILL.md +0 -53
- package/skills/read-pdf/package.json +0 -11
- package/skills/remove-background/CLAUDE.md +0 -19
- package/skills/remove-background/package.json +0 -11
- package/skills/remove-background/tsconfig.json +0 -10
- package/skills/risk-disclosure-kit/CLAUDE.md +0 -19
- package/skills/risk-disclosure-kit/package.json +0 -27
- package/skills/risk-disclosure-kit/src/index.ts +0 -307
- package/skills/risk-disclosure-kit/tsconfig.json +0 -10
- package/skills/roi-comparison-tool/CLAUDE.md +0 -19
- package/skills/roi-comparison-tool/package.json +0 -27
- package/skills/roi-comparison-tool/src/index.ts +0 -322
- package/skills/roi-comparison-tool/tsconfig.json +0 -10
- package/skills/sales-call-recapper/CLAUDE.md +0 -19
- package/skills/sales-call-recapper/package.json +0 -27
- package/skills/sales-call-recapper/src/index.ts +0 -300
- package/skills/sales-call-recapper/tsconfig.json +0 -10
- package/skills/salescopy/.env.example +0 -2
- package/skills/salescopy/CLAUDE.md +0 -23
- package/skills/salescopy/LICENSE +0 -192
- package/skills/salescopy/README.md +0 -72
- package/skills/salescopy/package.json +0 -27
- package/skills/salescopy/src/commands/config.ts +0 -115
- package/skills/salescopy/src/commands/generate.ts +0 -179
- package/skills/salescopy/src/commands/sessions.ts +0 -169
- package/skills/salescopy/src/commands/templates.ts +0 -99
- package/skills/salescopy/src/index.ts +0 -3
- package/skills/salescopy/src/lib/generator.ts +0 -197
- package/skills/salescopy/src/lib/storage.ts +0 -191
- package/skills/salescopy/src/types/index.ts +0 -74
- package/skills/salescopy/src/utils/logger.ts +0 -33
- package/skills/salescopy/src/utils/paths.ts +0 -25
- package/skills/salescopy/tsconfig.json +0 -23
- package/skills/scaffold-project/CLAUDE.md +0 -19
- package/skills/scaffold-project/package.json +0 -29
- package/skills/scaffold-project/src/ai-detect.ts +0 -136
- package/skills/scaffold-project/src/file-generators.ts +0 -292
- package/skills/scaffold-project/src/index.ts +0 -240
- package/skills/scaffold-project/src/project-config.ts +0 -338
- package/skills/scaffold-project/src/templates.ts +0 -173
- package/skills/scaffold-project/src/types.ts +0 -58
- package/skills/scaffold-project/tsconfig.json +0 -10
- package/skills/scholarship-tracker/CLAUDE.md +0 -19
- package/skills/scholarship-tracker/package.json +0 -27
- package/skills/scholarship-tracker/src/index.ts +0 -298
- package/skills/scholarship-tracker/tsconfig.json +0 -10
- package/skills/sdk-generator/SKILL.md +0 -45
- package/skills/sdk-generator/package.json +0 -11
- package/skills/sdk-generator/tsconfig.json +0 -8
- package/skills/seating-chart-maker/CLAUDE.md +0 -19
- package/skills/seating-chart-maker/package.json +0 -27
- package/skills/seating-chart-maker/src/index.ts +0 -312
- package/skills/seating-chart-maker/tsconfig.json +0 -10
- package/skills/seo-brief-builder/CLAUDE.md +0 -19
- package/skills/seo-brief-builder/package.json +0 -27
- package/skills/seo-brief-builder/src/index.ts +0 -288
- package/skills/seo-brief-builder/tsconfig.json +0 -10
- package/skills/short-video-pack/SKILL.md +0 -30
- package/skills/short-video-pack/package.json +0 -11
- package/skills/slack-assistant/CLAUDE.md +0 -19
- package/skills/slack-assistant/package.json +0 -29
- package/skills/slack-assistant/src/index.ts +0 -79
- package/skills/slack-assistant/tsconfig.json +0 -10
- package/skills/sleep-routine-analyzer/CLAUDE.md +0 -19
- package/skills/sleep-routine-analyzer/package.json +0 -27
- package/skills/sleep-routine-analyzer/src/index.ts +0 -293
- package/skills/sleep-routine-analyzer/tsconfig.json +0 -10
- package/skills/sms/README.md +0 -33
- package/skills/sms/package.json +0 -35
- package/skills/sms/src/index.ts +0 -335
- package/skills/sms/tsconfig.json +0 -21
- package/skills/social-media-kit/CLAUDE.md +0 -19
- package/skills/social-media-kit/package.json +0 -27
- package/skills/social-media-kit/src/index.ts +0 -281
- package/skills/social-media-kit/tsconfig.json +0 -10
- package/skills/sponsorship-proposal-lab/CLAUDE.md +0 -19
- package/skills/sponsorship-proposal-lab/package.json +0 -27
- package/skills/sponsorship-proposal-lab/src/index.ts +0 -300
- package/skills/sponsorship-proposal-lab/tsconfig.json +0 -10
- package/skills/spreadsheet-cleanroom/CLAUDE.md +0 -19
- package/skills/spreadsheet-cleanroom/package.json +0 -27
- package/skills/spreadsheet-cleanroom/src/index.ts +0 -331
- package/skills/spreadsheet-cleanroom/tsconfig.json +0 -10
- package/skills/stress-relief-playbook/CLAUDE.md +0 -19
- package/skills/stress-relief-playbook/package.json +0 -27
- package/skills/stress-relief-playbook/src/index.ts +0 -298
- package/skills/stress-relief-playbook/tsconfig.json +0 -10
- package/skills/study-guide-builder/CLAUDE.md +0 -19
- package/skills/study-guide-builder/package.json +0 -27
- package/skills/study-guide-builder/src/index.ts +0 -298
- package/skills/study-guide-builder/tsconfig.json +0 -10
- package/skills/subscription-spend-watcher/CLAUDE.md +0 -19
- package/skills/subscription-spend-watcher/package.json +0 -27
- package/skills/subscription-spend-watcher/src/index.ts +0 -312
- package/skills/subscription-spend-watcher/tsconfig.json +0 -10
- package/skills/subtitle/.env.example +0 -2
- package/skills/subtitle/CLAUDE.md +0 -37
- package/skills/subtitle/LICENSE +0 -192
- package/skills/subtitle/README.md +0 -63
- package/skills/subtitle/package.json +0 -43
- package/skills/subtitle/src/commands/config.ts +0 -53
- package/skills/subtitle/src/commands/generate.ts +0 -61
- package/skills/subtitle/src/index.ts +0 -3
- package/skills/subtitle/src/lib/generator.ts +0 -216
- package/skills/subtitle/src/lib/storage.ts +0 -62
- package/skills/subtitle/src/types/index.ts +0 -68
- package/skills/subtitle/src/utils/logger.ts +0 -34
- package/skills/subtitle/src/utils/paths.ts +0 -51
- package/skills/subtitle/tsconfig.json +0 -21
- package/skills/survey-insight-extractor/CLAUDE.md +0 -19
- package/skills/survey-insight-extractor/package.json +0 -27
- package/skills/survey-insight-extractor/src/index.ts +0 -317
- package/skills/survey-insight-extractor/tsconfig.json +0 -10
- package/skills/terraform-generator/CLAUDE.md +0 -19
- package/skills/terraform-generator/package.json +0 -29
- package/skills/terraform-generator/src/index.ts +0 -99
- package/skills/terraform-generator/tsconfig.json +0 -10
- package/skills/testimonial-graphics/CLAUDE.md +0 -19
- package/skills/testimonial-graphics/package.json +0 -27
- package/skills/testimonial-graphics/src/index.ts +0 -303
- package/skills/testimonial-graphics/tsconfig.json +0 -10
- package/skills/timesheet/.env.example +0 -25
- package/skills/timesheet/README.md +0 -235
- package/skills/timesheet/package.json +0 -47
- package/skills/timesheet/scripts/publish.ts +0 -210
- package/skills/timesheet/src/commands/employee.ts +0 -96
- package/skills/timesheet/src/commands/export.ts +0 -29
- package/skills/timesheet/src/commands/generate.ts +0 -102
- package/skills/timesheet/src/commands/holiday.ts +0 -74
- package/skills/timesheet/src/commands/profile.ts +0 -133
- package/skills/timesheet/src/commands/setup.ts +0 -21
- package/skills/timesheet/src/commands/vacation.ts +0 -93
- package/skills/timesheet/src/index.ts +0 -3
- package/skills/timesheet/src/lib/employees.ts +0 -56
- package/skills/timesheet/src/lib/export.ts +0 -123
- package/skills/timesheet/src/lib/holidays.ts +0 -79
- package/skills/timesheet/src/lib/paths.ts +0 -59
- package/skills/timesheet/src/lib/profiles.ts +0 -168
- package/skills/timesheet/src/lib/storage.ts +0 -83
- package/skills/timesheet/src/lib/timesheet.ts +0 -130
- package/skills/timesheet/src/lib/vacations.ts +0 -70
- package/skills/timesheet/src/types/index.ts +0 -96
- package/skills/timesheet/tsconfig.json +0 -29
- package/skills/transcript/LICENSE +0 -192
- package/skills/transcript/README.md +0 -17
- package/skills/transcript/SKILL.md +0 -80
- package/skills/transcript/package.json +0 -11
- package/skills/transcript/tsconfig.json +0 -18
- package/skills/travel-budget-balancer/CLAUDE.md +0 -19
- package/skills/travel-budget-balancer/package.json +0 -27
- package/skills/travel-budget-balancer/src/index.ts +0 -297
- package/skills/travel-budget-balancer/tsconfig.json +0 -10
- package/skills/video/SKILL.md +0 -37
- package/skills/video/package.json +0 -11
- package/skills/video-cut-suggester/CLAUDE.md +0 -19
- package/skills/video-cut-suggester/package.json +0 -27
- package/skills/video-cut-suggester/src/index.ts +0 -304
- package/skills/video-cut-suggester/tsconfig.json +0 -10
- package/skills/video-thumbnail/CLAUDE.md +0 -19
- package/skills/video-thumbnail/package.json +0 -27
- package/skills/video-thumbnail/src/index.ts +0 -356
- package/skills/video-thumbnail/tsconfig.json +0 -10
- package/skills/voiceover-jingle-pack/SKILL.md +0 -28
- package/skills/voiceover-jingle-pack/package.json +0 -11
- package/skills/webcrawling/CLAUDE.md +0 -11
- package/skills/webcrawling/LICENSE +0 -192
- package/skills/webcrawling/README.md +0 -24
- package/skills/webcrawling/package.json +0 -11
- package/skills/webcrawling/tsconfig.json +0 -22
- package/skills/webinar-script-coach/CLAUDE.md +0 -19
- package/skills/webinar-script-coach/package.json +0 -27
- package/skills/webinar-script-coach/src/index.ts +0 -296
- package/skills/webinar-script-coach/tsconfig.json +0 -10
- package/skills/wellness-progress-reporter/CLAUDE.md +0 -19
- package/skills/wellness-progress-reporter/package.json +0 -27
- package/skills/wellness-progress-reporter/src/index.ts +0 -298
- package/skills/wellness-progress-reporter/tsconfig.json +0 -10
- package/skills/workout-cycle-planner/CLAUDE.md +0 -19
- package/skills/workout-cycle-planner/package.json +0 -27
- package/skills/workout-cycle-planner/src/index.ts +0 -299
- package/skills/workout-cycle-planner/tsconfig.json +0 -10
- package/skills/write/.env.example +0 -9
- package/skills/write/LICENSE +0 -192
- package/skills/write/README.md +0 -17
- package/skills/write/SKILL.md +0 -90
- package/skills/write/package.json +0 -32
- package/skills/write/src/agents/image-generator.ts +0 -186
- package/skills/write/src/agents/researcher.ts +0 -61
- package/skills/write/src/agents/writer.ts +0 -99
- package/skills/write/src/index-local.ts +0 -248
- package/skills/write/src/index.ts +0 -4
- package/skills/write/src/orchestrator.ts +0 -171
- package/skills/write/src/types.ts +0 -65
- package/skills/write/tsconfig.json +0 -18
- /package/migrations/{0001_open_skills_self_hosted.sql → postgres/0001_open_skills_self_hosted.sql} +0 -0
- /package/skills/{read-image → api-docs-portal}/tsconfig.json +0 -0
- /package/skills/{read-pdf → brand-assets}/tsconfig.json +0 -0
package/bin/worker.js
CHANGED
|
@@ -9724,7 +9724,7 @@ var require_es5 = __commonJS((exports, module) => {
|
|
|
9724
9724
|
|
|
9725
9725
|
// node_modules/@aws-sdk/core/dist-cjs/submodules/client/index.js
|
|
9726
9726
|
var require_client2 = __commonJS((exports) => {
|
|
9727
|
-
var __dirname = "/
|
|
9727
|
+
var __dirname = "/tmp/cossus-skills-release-85552597/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
|
|
9728
9728
|
var { Retry, RETRY_MODES } = require_retry();
|
|
9729
9729
|
var { HttpRequest, parseUrl } = require_protocols();
|
|
9730
9730
|
var { InvokeStore } = require_invoke_store();
|
|
@@ -20671,7 +20671,7 @@ var init_dist_es9 = __esm(() => {
|
|
|
20671
20671
|
});
|
|
20672
20672
|
|
|
20673
20673
|
// src/server/worker.ts
|
|
20674
|
-
import { randomUUID as
|
|
20674
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
20675
20675
|
|
|
20676
20676
|
// node_modules/@aws-sdk/checksums/dist-cjs/submodules/flexible-checksums/index.js
|
|
20677
20677
|
var { setFeature } = require_client2();
|
|
@@ -30259,6 +30259,10 @@ class S3Client extends import_client24.Client {
|
|
|
30259
30259
|
}
|
|
30260
30260
|
}
|
|
30261
30261
|
|
|
30262
|
+
// node_modules/@aws-sdk/client-s3/dist-es/commands/DeleteObjectCommand.js
|
|
30263
|
+
class DeleteObjectCommand extends command(_ep0, _mw0, "DeleteObject", DeleteObject$) {
|
|
30264
|
+
}
|
|
30265
|
+
|
|
30262
30266
|
// node_modules/@aws-sdk/client-s3/dist-es/commands/GetObjectCommand.js
|
|
30263
30267
|
class GetObjectCommand extends command(_ep0, _mw7, "GetObject", GetObject$) {
|
|
30264
30268
|
}
|
|
@@ -30267,7 +30271,137 @@ class GetObjectCommand extends command(_ep0, _mw7, "GetObject", GetObject$) {
|
|
|
30267
30271
|
class PutObjectCommand extends command(_ep0, _mw11, "PutObject", PutObject$) {
|
|
30268
30272
|
}
|
|
30269
30273
|
|
|
30274
|
+
// src/lib/skill-bundle.ts
|
|
30275
|
+
var ANY_SEGMENT_EXCLUDES = new Set([
|
|
30276
|
+
".git",
|
|
30277
|
+
".ds_store",
|
|
30278
|
+
".system",
|
|
30279
|
+
"node_modules",
|
|
30280
|
+
".aws",
|
|
30281
|
+
".ssh",
|
|
30282
|
+
".gnupg",
|
|
30283
|
+
".docker"
|
|
30284
|
+
]);
|
|
30285
|
+
var ROOT_EXCLUDES = new Set(["dist", "build", ".turbo"]);
|
|
30286
|
+
var CREDENTIAL_FILENAMES = new Set([
|
|
30287
|
+
".npmrc",
|
|
30288
|
+
".pypirc",
|
|
30289
|
+
".netrc",
|
|
30290
|
+
".envrc",
|
|
30291
|
+
".pgpass",
|
|
30292
|
+
".git-credentials",
|
|
30293
|
+
"credentials",
|
|
30294
|
+
"id_rsa",
|
|
30295
|
+
"id_dsa",
|
|
30296
|
+
"id_ecdsa",
|
|
30297
|
+
"id_ed25519"
|
|
30298
|
+
]);
|
|
30299
|
+
var ENV_TEMPLATE_NAMES = new Set([".env.example", ".env.sample", ".env.template", ".env.dist"]);
|
|
30300
|
+
var NON_DOTENV_EXTENSIONS = new Set([
|
|
30301
|
+
"ts",
|
|
30302
|
+
"tsx",
|
|
30303
|
+
"mts",
|
|
30304
|
+
"cts",
|
|
30305
|
+
"js",
|
|
30306
|
+
"jsx",
|
|
30307
|
+
"mjs",
|
|
30308
|
+
"cjs",
|
|
30309
|
+
"json",
|
|
30310
|
+
"jsonc",
|
|
30311
|
+
"json5",
|
|
30312
|
+
"py",
|
|
30313
|
+
"rb",
|
|
30314
|
+
"go",
|
|
30315
|
+
"rs",
|
|
30316
|
+
"java",
|
|
30317
|
+
"kt",
|
|
30318
|
+
"kts",
|
|
30319
|
+
"swift",
|
|
30320
|
+
"c",
|
|
30321
|
+
"h",
|
|
30322
|
+
"cc",
|
|
30323
|
+
"cpp",
|
|
30324
|
+
"hpp",
|
|
30325
|
+
"cs",
|
|
30326
|
+
"php",
|
|
30327
|
+
"sh",
|
|
30328
|
+
"bash",
|
|
30329
|
+
"zsh",
|
|
30330
|
+
"fish",
|
|
30331
|
+
"ps1",
|
|
30332
|
+
"bat",
|
|
30333
|
+
"cmd",
|
|
30334
|
+
"lua",
|
|
30335
|
+
"pl",
|
|
30336
|
+
"pm",
|
|
30337
|
+
"r",
|
|
30338
|
+
"jl",
|
|
30339
|
+
"dart",
|
|
30340
|
+
"ex",
|
|
30341
|
+
"exs",
|
|
30342
|
+
"scala",
|
|
30343
|
+
"clj",
|
|
30344
|
+
"cljs",
|
|
30345
|
+
"groovy",
|
|
30346
|
+
"gradle",
|
|
30347
|
+
"vb",
|
|
30348
|
+
"fs",
|
|
30349
|
+
"yaml",
|
|
30350
|
+
"yml",
|
|
30351
|
+
"toml",
|
|
30352
|
+
"ini",
|
|
30353
|
+
"xml",
|
|
30354
|
+
"csv",
|
|
30355
|
+
"tsv",
|
|
30356
|
+
"html",
|
|
30357
|
+
"htm",
|
|
30358
|
+
"css",
|
|
30359
|
+
"scss",
|
|
30360
|
+
"sass",
|
|
30361
|
+
"less",
|
|
30362
|
+
"md",
|
|
30363
|
+
"mdx",
|
|
30364
|
+
"txt",
|
|
30365
|
+
"rst",
|
|
30366
|
+
"adoc",
|
|
30367
|
+
"sql",
|
|
30368
|
+
"graphql",
|
|
30369
|
+
"gql",
|
|
30370
|
+
"proto",
|
|
30371
|
+
"d",
|
|
30372
|
+
"png",
|
|
30373
|
+
"jpg",
|
|
30374
|
+
"jpeg",
|
|
30375
|
+
"gif",
|
|
30376
|
+
"svg",
|
|
30377
|
+
"webp",
|
|
30378
|
+
"ico",
|
|
30379
|
+
"bmp",
|
|
30380
|
+
"pdf",
|
|
30381
|
+
"woff",
|
|
30382
|
+
"woff2",
|
|
30383
|
+
"ttf",
|
|
30384
|
+
"otf",
|
|
30385
|
+
"eot",
|
|
30386
|
+
"mp3",
|
|
30387
|
+
"mp4",
|
|
30388
|
+
"wav",
|
|
30389
|
+
"webm",
|
|
30390
|
+
"zip",
|
|
30391
|
+
"gz",
|
|
30392
|
+
"tar",
|
|
30393
|
+
"wasm"
|
|
30394
|
+
]);
|
|
30395
|
+
function ownBytes(view) {
|
|
30396
|
+
const source = view instanceof ArrayBuffer ? new Uint8Array(view) : view;
|
|
30397
|
+
const out = new Uint8Array(new ArrayBuffer(source.byteLength));
|
|
30398
|
+
out.set(source);
|
|
30399
|
+
return out;
|
|
30400
|
+
}
|
|
30401
|
+
|
|
30270
30402
|
// src/server/artifact-storage.ts
|
|
30403
|
+
var SHA256_HEX = /^[0-9a-f]{64}$/;
|
|
30404
|
+
|
|
30271
30405
|
class ArtifactStorage {
|
|
30272
30406
|
bucket;
|
|
30273
30407
|
prefix;
|
|
@@ -30312,10 +30446,74 @@ class ArtifactStorage {
|
|
|
30312
30446
|
}));
|
|
30313
30447
|
return await bodyToText(response.Body);
|
|
30314
30448
|
}
|
|
30449
|
+
async putBundle(orgId, sha256, bytes, contentType = "application/gzip") {
|
|
30450
|
+
assertSha256(sha256);
|
|
30451
|
+
if (!this.bucket)
|
|
30452
|
+
return { storageKind: "db", bytes };
|
|
30453
|
+
const key = this.bundleKeyFor(orgId, sha256);
|
|
30454
|
+
await this.s3.send(new PutObjectCommand({
|
|
30455
|
+
Bucket: this.bucket,
|
|
30456
|
+
Key: key,
|
|
30457
|
+
Body: bytes,
|
|
30458
|
+
ContentType: contentType
|
|
30459
|
+
}));
|
|
30460
|
+
return { storageKind: "s3", storageKey: key };
|
|
30461
|
+
}
|
|
30462
|
+
async readBundle(bundle) {
|
|
30463
|
+
if (bundle.storageKind === "db")
|
|
30464
|
+
return bundle.bytes ?? null;
|
|
30465
|
+
if (!this.bucket || !this.s3 || !bundle.storageKey)
|
|
30466
|
+
return null;
|
|
30467
|
+
const response = await this.s3.send(new GetObjectCommand({
|
|
30468
|
+
Bucket: this.bucket,
|
|
30469
|
+
Key: bundle.storageKey
|
|
30470
|
+
}));
|
|
30471
|
+
return await bodyToBytes(response.Body);
|
|
30472
|
+
}
|
|
30473
|
+
async deleteBundle(orgId, sha256) {
|
|
30474
|
+
if (!this.bucket || !this.s3)
|
|
30475
|
+
return;
|
|
30476
|
+
assertSha256(sha256);
|
|
30477
|
+
await this.s3.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: this.bundleKeyFor(orgId, sha256) }));
|
|
30478
|
+
}
|
|
30315
30479
|
keyFor(run, relativePath) {
|
|
30316
30480
|
const safeRelativePath = relativePath.replace(/^\/+/, "").replace(/\.\.(?:\/|$)/g, "");
|
|
30317
30481
|
return `${this.prefix}/${run.orgId}/${run.id}/${safeRelativePath}`;
|
|
30318
30482
|
}
|
|
30483
|
+
bundleKeyFor(orgId, sha256) {
|
|
30484
|
+
return `${this.prefix}/bundles/${encodeURIComponent(orgId)}/${sha256}.tar.gz`;
|
|
30485
|
+
}
|
|
30486
|
+
}
|
|
30487
|
+
function assertSha256(value) {
|
|
30488
|
+
if (!SHA256_HEX.test(value)) {
|
|
30489
|
+
throw new Error("bundle digest must be a lowercase hex sha-256; refusing to build a storage key from it");
|
|
30490
|
+
}
|
|
30491
|
+
}
|
|
30492
|
+
async function bodyToBytes(body) {
|
|
30493
|
+
if (!body)
|
|
30494
|
+
return ownBytes(new Uint8Array(0));
|
|
30495
|
+
if (body instanceof Uint8Array)
|
|
30496
|
+
return ownBytes(body);
|
|
30497
|
+
if (typeof body.transformToByteArray === "function") {
|
|
30498
|
+
return ownBytes(await body.transformToByteArray());
|
|
30499
|
+
}
|
|
30500
|
+
if (typeof body.getReader === "function") {
|
|
30501
|
+
const reader = body.getReader();
|
|
30502
|
+
const chunks2 = [];
|
|
30503
|
+
while (true) {
|
|
30504
|
+
const { value, done } = await reader.read();
|
|
30505
|
+
if (done)
|
|
30506
|
+
break;
|
|
30507
|
+
if (value)
|
|
30508
|
+
chunks2.push(value);
|
|
30509
|
+
}
|
|
30510
|
+
return concat(chunks2);
|
|
30511
|
+
}
|
|
30512
|
+
const chunks = [];
|
|
30513
|
+
for await (const chunk of body) {
|
|
30514
|
+
chunks.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
|
|
30515
|
+
}
|
|
30516
|
+
return concat(chunks);
|
|
30319
30517
|
}
|
|
30320
30518
|
async function bodyToText(body) {
|
|
30321
30519
|
if (!body)
|
|
@@ -30347,7 +30545,7 @@ async function bodyToText(body) {
|
|
|
30347
30545
|
}
|
|
30348
30546
|
function concat(chunks) {
|
|
30349
30547
|
const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
|
|
30350
|
-
const merged = new Uint8Array(total);
|
|
30548
|
+
const merged = new Uint8Array(new ArrayBuffer(total));
|
|
30351
30549
|
let offset = 0;
|
|
30352
30550
|
for (const chunk of chunks) {
|
|
30353
30551
|
merged.set(chunk, offset);
|
|
@@ -30356,23 +30554,89 @@ function concat(chunks) {
|
|
|
30356
30554
|
return merged;
|
|
30357
30555
|
}
|
|
30358
30556
|
|
|
30557
|
+
// src/server/auth.ts
|
|
30558
|
+
import { createHash as createHash3 } from "crypto";
|
|
30559
|
+
function hashApiKey(token) {
|
|
30560
|
+
return createHash3("sha256").update(token).digest("hex");
|
|
30561
|
+
}
|
|
30562
|
+
function publicPrincipal(partial = {}) {
|
|
30563
|
+
return {
|
|
30564
|
+
apiKeyId: partial.apiKeyId || "key_dev",
|
|
30565
|
+
orgId: partial.orgId || "org_dev",
|
|
30566
|
+
orgSlug: partial.orgSlug || "dev",
|
|
30567
|
+
orgName: partial.orgName || "Development",
|
|
30568
|
+
userId: partial.userId || "user_dev",
|
|
30569
|
+
email: partial.email || "dev@example.com",
|
|
30570
|
+
role: partial.role || "owner",
|
|
30571
|
+
scopes: partial.scopes || ["skills:read", "runs:write"]
|
|
30572
|
+
};
|
|
30573
|
+
}
|
|
30574
|
+
|
|
30575
|
+
// src/lib/retired-settings.ts
|
|
30576
|
+
var RETIRED_ENV_SUFFIXES = ["_STORAGE_MODE", "_DEPLOYMENT_MODE", "_CLOUD_MODE"];
|
|
30577
|
+
class RetiredSettingError extends Error {
|
|
30578
|
+
code = "RETIRED_SETTING";
|
|
30579
|
+
setting;
|
|
30580
|
+
constructor(setting, message) {
|
|
30581
|
+
super(message);
|
|
30582
|
+
this.name = "RetiredSettingError";
|
|
30583
|
+
this.setting = setting;
|
|
30584
|
+
}
|
|
30585
|
+
}
|
|
30586
|
+
function isRetiredModeEnvVar(name, app) {
|
|
30587
|
+
const upper = name.toUpperCase();
|
|
30588
|
+
if (!upper.includes(app.toUpperCase()))
|
|
30589
|
+
return false;
|
|
30590
|
+
return RETIRED_ENV_SUFFIXES.some((suffix) => upper.endsWith(suffix));
|
|
30591
|
+
}
|
|
30592
|
+
function findRetiredModeEnvVars(env, app) {
|
|
30593
|
+
const found = [];
|
|
30594
|
+
for (const [name, value] of Object.entries(env)) {
|
|
30595
|
+
if (value === undefined || value === "")
|
|
30596
|
+
continue;
|
|
30597
|
+
if (isRetiredModeEnvVar(name, app))
|
|
30598
|
+
found.push({ name, value });
|
|
30599
|
+
}
|
|
30600
|
+
return found.sort((a3, b3) => a3.name.localeCompare(b3.name));
|
|
30601
|
+
}
|
|
30602
|
+
function assertNoRetiredModeEnvVars(env, options) {
|
|
30603
|
+
const found = findRetiredModeEnvVars(env, options.app);
|
|
30604
|
+
if (found.length === 0)
|
|
30605
|
+
return;
|
|
30606
|
+
const names = found.map((entry) => entry.name);
|
|
30607
|
+
throw new RetiredSettingError(names[0], `${names.join(", ")} ${names.length === 1 ? "is" : "are"} no longer read. ` + "Deployment modes were removed: where a server keeps its data is decided by the " + `database it is given, not by a declared label. Set ${options.replacement} to a ` + "postgres:// URL to use PostgreSQL, or leave it unset for the on-box SQLite database. " + `Then unset ${names.join(" and ")}. ` + "Refused rather than ignored, because a discarded setting looks exactly like a " + "working one until something needs the data.");
|
|
30608
|
+
}
|
|
30609
|
+
|
|
30359
30610
|
// src/server/config.ts
|
|
30360
|
-
var
|
|
30611
|
+
var DATABASE_URL_ENV = "HASNA_SKILLS_DATABASE_URL";
|
|
30612
|
+
var SKILLS_ENV_NAMESPACE = "SKILLS";
|
|
30361
30613
|
function resolveServerConfig(env = process.env) {
|
|
30614
|
+
assertNoRetiredModeEnvVars(env, {
|
|
30615
|
+
app: SKILLS_ENV_NAMESPACE,
|
|
30616
|
+
replacement: DATABASE_URL_ENV
|
|
30617
|
+
});
|
|
30362
30618
|
const nodeEnv = env.NODE_ENV || "development";
|
|
30619
|
+
const host = env.HOST || env.SKILLS_HOST || "0.0.0.0";
|
|
30620
|
+
const port = parsePositiveInt(env.PORT || env.SKILLS_PORT, 8787);
|
|
30363
30621
|
return {
|
|
30364
|
-
host
|
|
30365
|
-
port
|
|
30366
|
-
databaseUrl: env
|
|
30622
|
+
host,
|
|
30623
|
+
port,
|
|
30624
|
+
databaseUrl: env[DATABASE_URL_ENV] || env.DATABASE_URL || undefined,
|
|
30367
30625
|
bootstrapApiKey: env.HASNA_SKILLS_BOOTSTRAP_API_KEY || undefined,
|
|
30368
30626
|
artifactBucket: env.HASNA_SKILLS_S3_BUCKET || env.SKILLS_S3_BUCKET || undefined,
|
|
30369
30627
|
artifactPrefix: normalizePrefix(env.HASNA_SKILLS_S3_PREFIX || env.SKILLS_S3_PREFIX || "skills/artifacts"),
|
|
30370
30628
|
inlineWorker: env.HASNA_SKILLS_INLINE_WORKER === "1",
|
|
30371
30629
|
requestBodyLimitBytes: parsePositiveInt(env.HASNA_SKILLS_REQUEST_BODY_LIMIT_BYTES, 1e6),
|
|
30372
|
-
|
|
30373
|
-
|
|
30630
|
+
skillBundleLimitBytes: parsePositiveInt(env.HASNA_SKILLS_BUNDLE_LIMIT_BYTES, 25000000),
|
|
30631
|
+
publicBaseUrl: (env.SKILLS_PUBLIC_BASE_URL || localOrigin(host, port)).replace(/\/+$/, ""),
|
|
30632
|
+
nodeEnv,
|
|
30633
|
+
allowEphemeralStore: env.HASNA_SKILLS_ALLOW_EPHEMERAL_STORE === "1"
|
|
30374
30634
|
};
|
|
30375
30635
|
}
|
|
30636
|
+
function localOrigin(host, port) {
|
|
30637
|
+
const hostname = host === "0.0.0.0" || host === "::" ? "localhost" : host;
|
|
30638
|
+
return `http://${hostname.includes(":") ? `[${hostname}]` : hostname}:${port}`;
|
|
30639
|
+
}
|
|
30376
30640
|
function parsePositiveInt(value, fallback) {
|
|
30377
30641
|
const parsed = Number.parseInt(value ?? "", 10);
|
|
30378
30642
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
@@ -30381,78 +30645,772 @@ function normalizePrefix(value) {
|
|
|
30381
30645
|
return value.replace(/^\/+|\/+$/g, "") || "skills/artifacts";
|
|
30382
30646
|
}
|
|
30383
30647
|
|
|
30384
|
-
// src/server/
|
|
30385
|
-
import {
|
|
30648
|
+
// src/server/database-url.ts
|
|
30649
|
+
import { isAbsolute, join as join3 } from "path";
|
|
30650
|
+
import { fileURLToPath } from "url";
|
|
30386
30651
|
|
|
30387
|
-
// src/
|
|
30388
|
-
import {
|
|
30652
|
+
// src/lib/config.ts
|
|
30653
|
+
import { existsSync, readFileSync as readFileSync2, writeFileSync, mkdirSync, copyFileSync, readdirSync, statSync } from "fs";
|
|
30654
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
30655
|
+
import { homedir as homedir2 } from "os";
|
|
30656
|
+
function mergeDirectoryContents(sourceDir, targetDir) {
|
|
30657
|
+
if (!existsSync(sourceDir))
|
|
30658
|
+
return;
|
|
30659
|
+
mkdirSync(targetDir, { recursive: true });
|
|
30660
|
+
for (const entry of readdirSync(sourceDir)) {
|
|
30661
|
+
const sourcePath = join2(sourceDir, entry);
|
|
30662
|
+
const targetPath = join2(targetDir, entry);
|
|
30663
|
+
try {
|
|
30664
|
+
const sourceStat = statSync(sourcePath);
|
|
30665
|
+
if (sourceStat.isDirectory()) {
|
|
30666
|
+
mergeDirectoryContents(sourcePath, targetPath);
|
|
30667
|
+
continue;
|
|
30668
|
+
}
|
|
30669
|
+
if (!existsSync(targetPath))
|
|
30670
|
+
copyFileSync(sourcePath, targetPath);
|
|
30671
|
+
} catch {}
|
|
30672
|
+
}
|
|
30673
|
+
}
|
|
30674
|
+
var DATA_DIR_ENV = "HASNA_SKILLS_DIR";
|
|
30675
|
+
function getDataDir() {
|
|
30676
|
+
const override = process.env[DATA_DIR_ENV];
|
|
30677
|
+
if (override) {
|
|
30678
|
+
try {
|
|
30679
|
+
mkdirSync(override, { recursive: true });
|
|
30680
|
+
} catch {}
|
|
30681
|
+
return override;
|
|
30682
|
+
}
|
|
30683
|
+
const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
|
|
30684
|
+
const newDir = join2(home, ".hasna", "skills");
|
|
30685
|
+
const oldDir = join2(home, ".skills");
|
|
30686
|
+
const oldConfigFile = join2(home, ".skillsrc");
|
|
30687
|
+
mkdirSync(newDir, { recursive: true });
|
|
30688
|
+
try {
|
|
30689
|
+
mergeDirectoryContents(oldDir, newDir);
|
|
30690
|
+
} catch {}
|
|
30691
|
+
if (existsSync(oldConfigFile) && !existsSync(join2(newDir, "config.json"))) {
|
|
30692
|
+
try {
|
|
30693
|
+
copyFileSync(oldConfigFile, join2(newDir, "config.json"));
|
|
30694
|
+
} catch {}
|
|
30695
|
+
}
|
|
30696
|
+
return newDir;
|
|
30697
|
+
}
|
|
30389
30698
|
|
|
30390
|
-
// src/server/
|
|
30391
|
-
|
|
30392
|
-
|
|
30393
|
-
|
|
30699
|
+
// src/server/database-url.ts
|
|
30700
|
+
var DEFAULT_SQLITE_FILENAME = "server.db";
|
|
30701
|
+
var SQLITE_MEMORY_PATH = ":memory:";
|
|
30702
|
+
var POSTGRES_SCHEMES = new Set(["postgres", "postgresql"]);
|
|
30703
|
+
var SQLITE_SCHEMES = new Set(["sqlite", "sqlite3", "file"]);
|
|
30704
|
+
var MEMORY_SCHEMES = new Set(["memory"]);
|
|
30705
|
+
var SQLITE_EXTENSIONS = [".db", ".sqlite", ".sqlite3", ".db3"];
|
|
30706
|
+
function defaultSqlitePath() {
|
|
30707
|
+
return join3(getDataDir(), DEFAULT_SQLITE_FILENAME);
|
|
30394
30708
|
}
|
|
30395
|
-
function
|
|
30396
|
-
|
|
30397
|
-
|
|
30398
|
-
|
|
30399
|
-
|
|
30400
|
-
|
|
30401
|
-
|
|
30402
|
-
|
|
30403
|
-
|
|
30404
|
-
|
|
30405
|
-
|
|
30709
|
+
function resolveDatabaseTarget(raw) {
|
|
30710
|
+
const value = raw?.trim();
|
|
30711
|
+
if (!value) {
|
|
30712
|
+
const path = defaultSqlitePath();
|
|
30713
|
+
return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
|
|
30714
|
+
}
|
|
30715
|
+
if (value === SQLITE_MEMORY_PATH) {
|
|
30716
|
+
return { kind: "sqlite", path: SQLITE_MEMORY_PATH, durable: false, label: "sqlite (in-memory)" };
|
|
30717
|
+
}
|
|
30718
|
+
const schemeMatch = value.match(/^([a-z][a-z0-9+.-]+):/i);
|
|
30719
|
+
const scheme = schemeMatch?.[1]?.toLowerCase();
|
|
30720
|
+
if (scheme && POSTGRES_SCHEMES.has(scheme)) {
|
|
30721
|
+
return { kind: "postgres", url: value, durable: true, label: "postgres" };
|
|
30722
|
+
}
|
|
30723
|
+
if (scheme && MEMORY_SCHEMES.has(scheme)) {
|
|
30724
|
+
return { kind: "memory", durable: false, label: "memory (non-durable)" };
|
|
30725
|
+
}
|
|
30726
|
+
if (scheme && SQLITE_SCHEMES.has(scheme)) {
|
|
30727
|
+
const path = sqlitePathFromUrl(value, scheme);
|
|
30728
|
+
return path === SQLITE_MEMORY_PATH ? { kind: "sqlite", path, durable: false, label: "sqlite (in-memory)" } : { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
|
|
30729
|
+
}
|
|
30730
|
+
if (scheme) {
|
|
30731
|
+
throw new Error(`unsupported database scheme "${scheme}:". Supported: postgres://, postgresql://, sqlite:, file:, ` + `an absolute or relative path to a .db/.sqlite file, ":memory:", or "memory:" (non-durable, tests only). ` + `Leave the setting empty to use the default SQLite database at ${defaultSqlitePath()}.`);
|
|
30732
|
+
}
|
|
30733
|
+
if (looksLikeSqlitePath(value)) {
|
|
30734
|
+
const path = isAbsolute(value) ? value : join3(process.cwd(), value);
|
|
30735
|
+
return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
|
|
30736
|
+
}
|
|
30737
|
+
throw new Error(`could not resolve a database backend from "${value}". Use postgres://\u2026, sqlite:\u2026, an absolute or ` + `relative path ending in ${SQLITE_EXTENSIONS.join("/")}, ":memory:", or leave it empty for the ` + `default SQLite database at ${defaultSqlitePath()}.`);
|
|
30406
30738
|
}
|
|
30739
|
+
function sqlitePathFromUrl(value, scheme) {
|
|
30740
|
+
const rest = value.slice(scheme.length + 1).replace(/[?#].*$/, "");
|
|
30741
|
+
if (rest.startsWith(SQLITE_MEMORY_PATH))
|
|
30742
|
+
return SQLITE_MEMORY_PATH;
|
|
30743
|
+
if (rest === "" || rest === "//") {
|
|
30744
|
+
throw new Error(`"${value}" names no database file. Give a path (${scheme}:///var/lib/skills/server.db), ` + `or ":memory:" if a non-durable database is genuinely what you want. ` + "An empty path here usually means an unset variable in a templated URL.");
|
|
30745
|
+
}
|
|
30746
|
+
if (rest.startsWith("//")) {
|
|
30747
|
+
if (!rest.startsWith("///")) {
|
|
30748
|
+
const authority = rest.slice(2).split("/")[0];
|
|
30749
|
+
throw new Error(`"${value}" has a host ("${authority}") where a path was expected. Remote SQLite files are not a thing; ` + `for an absolute path use ${scheme}:///${rest.slice(2)}, and for a relative one use ${scheme}:${rest.slice(2)}.`);
|
|
30750
|
+
}
|
|
30751
|
+
if (scheme === "file") {
|
|
30752
|
+
try {
|
|
30753
|
+
return fileURLToPath(new URL(value));
|
|
30754
|
+
} catch {}
|
|
30755
|
+
}
|
|
30756
|
+
return rest.slice(2).replace(/^\/\/+/, "/");
|
|
30757
|
+
}
|
|
30758
|
+
return isAbsolute(rest) ? rest : join3(process.cwd(), rest);
|
|
30759
|
+
}
|
|
30760
|
+
function looksLikeSqlitePath(value) {
|
|
30761
|
+
if (value.includes("/"))
|
|
30762
|
+
return true;
|
|
30763
|
+
return SQLITE_EXTENSIONS.some((extension) => value.toLowerCase().endsWith(extension));
|
|
30764
|
+
}
|
|
30765
|
+
|
|
30766
|
+
// src/server/handlers.ts
|
|
30767
|
+
import { createHash as createHash4 } from "crypto";
|
|
30407
30768
|
|
|
30408
30769
|
// src/server/store.ts
|
|
30409
|
-
|
|
30410
|
-
|
|
30411
|
-
|
|
30412
|
-
}
|
|
30770
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
30771
|
+
|
|
30772
|
+
// src/server/rows.ts
|
|
30773
|
+
import { randomUUID } from "crypto";
|
|
30413
30774
|
function nowIso() {
|
|
30414
30775
|
return new Date().toISOString();
|
|
30415
30776
|
}
|
|
30777
|
+
function normalizeLimit(limit) {
|
|
30778
|
+
return Number.isFinite(limit) ? Math.max(0, Math.trunc(limit)) : 0;
|
|
30779
|
+
}
|
|
30416
30780
|
function runId() {
|
|
30417
30781
|
return `run_${Date.now().toString(36)}_${randomUUID().slice(0, 8)}`;
|
|
30418
30782
|
}
|
|
30419
30783
|
function artifactId() {
|
|
30420
30784
|
return `art_${randomUUID().replace(/-/g, "").slice(0, 20)}`;
|
|
30421
30785
|
}
|
|
30422
|
-
function
|
|
30423
|
-
return
|
|
30786
|
+
function rowToRun(row) {
|
|
30787
|
+
return {
|
|
30788
|
+
id: String(row.id),
|
|
30789
|
+
orgId: String(row.org_id),
|
|
30790
|
+
userId: String(row.user_id),
|
|
30791
|
+
skill: String(row.skill_slug),
|
|
30792
|
+
requestedSlug: String(row.requested_slug),
|
|
30793
|
+
status: String(row.status),
|
|
30794
|
+
input: parseJsonObject(row.input_json),
|
|
30795
|
+
args: parseJsonArray(row.args_json),
|
|
30796
|
+
...typeof row.idempotency_key === "string" ? { idempotencyKey: row.idempotency_key } : {},
|
|
30797
|
+
correlationId: String(row.correlation_id),
|
|
30798
|
+
costCents: Number(row.cost_cents ?? 0),
|
|
30799
|
+
...typeof row.output_type === "string" ? { outputType: row.output_type } : {},
|
|
30800
|
+
...typeof row.output_preview === "string" ? { outputPreview: row.output_preview } : {},
|
|
30801
|
+
...typeof row.error_code === "string" ? { errorCode: row.error_code } : {},
|
|
30802
|
+
...typeof row.error_message === "string" ? { errorMessage: row.error_message } : {},
|
|
30803
|
+
createdAt: dateString(row.created_at),
|
|
30804
|
+
...row.started_at ? { startedAt: dateString(row.started_at) } : {},
|
|
30805
|
+
...row.completed_at ? { completedAt: dateString(row.completed_at) } : {}
|
|
30806
|
+
};
|
|
30424
30807
|
}
|
|
30425
|
-
|
|
30426
|
-
|
|
30427
|
-
|
|
30428
|
-
|
|
30808
|
+
function rowToLog(row) {
|
|
30809
|
+
return {
|
|
30810
|
+
runId: String(row.run_id),
|
|
30811
|
+
sequence: Number(row.sequence),
|
|
30812
|
+
level: String(row.level),
|
|
30813
|
+
message: String(row.message),
|
|
30814
|
+
createdAt: dateString(row.created_at)
|
|
30815
|
+
};
|
|
30816
|
+
}
|
|
30817
|
+
function rowToArtifact(row) {
|
|
30818
|
+
return {
|
|
30819
|
+
id: String(row.id),
|
|
30820
|
+
runId: String(row.run_id),
|
|
30821
|
+
orgId: String(row.org_id),
|
|
30822
|
+
fileName: String(row.file_name),
|
|
30823
|
+
relativePath: String(row.relative_path),
|
|
30824
|
+
contentType: String(row.content_type),
|
|
30825
|
+
byteSize: Number(row.byte_size),
|
|
30826
|
+
sha256: String(row.sha256),
|
|
30827
|
+
storageKind: String(row.storage_kind),
|
|
30828
|
+
...typeof row.storage_key === "string" ? { storageKey: row.storage_key } : {},
|
|
30829
|
+
...typeof row.body_text === "string" ? { bodyText: row.body_text } : {},
|
|
30830
|
+
createdAt: dateString(row.created_at)
|
|
30831
|
+
};
|
|
30832
|
+
}
|
|
30833
|
+
function rowToSkill(row) {
|
|
30834
|
+
return {
|
|
30835
|
+
orgId: String(row.org_id),
|
|
30836
|
+
slug: String(row.slug),
|
|
30837
|
+
displayName: String(row.display_name),
|
|
30838
|
+
description: String(row.description ?? ""),
|
|
30839
|
+
category: String(row.category),
|
|
30840
|
+
tags: parseJsonArray(row.tags_json),
|
|
30841
|
+
source: String(row.source),
|
|
30842
|
+
kind: String(row.kind) === "instruction" ? "instruction" : "executable",
|
|
30843
|
+
...typeof row.version === "string" ? { version: row.version } : {},
|
|
30844
|
+
...typeof row.skill_md === "string" ? { skillMd: row.skill_md } : {},
|
|
30845
|
+
...typeof row.bundle_sha256 === "string" ? { bundleSha256: row.bundle_sha256 } : {},
|
|
30846
|
+
...row.bundle_byte_size === null || row.bundle_byte_size === undefined ? {} : { bundleByteSize: Number(row.bundle_byte_size) },
|
|
30847
|
+
...typeof row.published_by_user_id === "string" ? { publishedByUserId: row.published_by_user_id } : {},
|
|
30848
|
+
createdAt: dateString(row.created_at),
|
|
30849
|
+
updatedAt: dateString(row.updated_at)
|
|
30850
|
+
};
|
|
30851
|
+
}
|
|
30852
|
+
function rowToSkillBundle(row) {
|
|
30853
|
+
return {
|
|
30854
|
+
orgId: String(row.org_id),
|
|
30855
|
+
sha256: String(row.sha256),
|
|
30856
|
+
byteSize: Number(row.byte_size),
|
|
30857
|
+
contentType: String(row.content_type),
|
|
30858
|
+
storageKind: String(row.storage_kind),
|
|
30859
|
+
...typeof row.storage_key === "string" ? { storageKey: row.storage_key } : {},
|
|
30860
|
+
...toBytes(row.body_blob) ? { bytes: toBytes(row.body_blob) } : {},
|
|
30861
|
+
createdAt: dateString(row.created_at)
|
|
30862
|
+
};
|
|
30863
|
+
}
|
|
30864
|
+
function toBytes(value) {
|
|
30865
|
+
if (value == null)
|
|
30866
|
+
return null;
|
|
30867
|
+
if (value instanceof Uint8Array)
|
|
30868
|
+
return ownBytes(value);
|
|
30869
|
+
if (value instanceof ArrayBuffer)
|
|
30870
|
+
return ownBytes(value);
|
|
30871
|
+
return null;
|
|
30872
|
+
}
|
|
30873
|
+
function parseJsonObject(value) {
|
|
30874
|
+
if (value && typeof value === "object" && !Array.isArray(value))
|
|
30875
|
+
return value;
|
|
30876
|
+
if (typeof value === "string") {
|
|
30877
|
+
try {
|
|
30878
|
+
const parsed = JSON.parse(value);
|
|
30879
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
30880
|
+
} catch {}
|
|
30429
30881
|
}
|
|
30430
|
-
return
|
|
30882
|
+
return {};
|
|
30883
|
+
}
|
|
30884
|
+
function parseJsonArray(value) {
|
|
30885
|
+
const parsed = typeof value === "string" ? safeParse(value) : value;
|
|
30886
|
+
return Array.isArray(parsed) ? parsed.map(String) : [];
|
|
30887
|
+
}
|
|
30888
|
+
function safeParse(value) {
|
|
30889
|
+
try {
|
|
30890
|
+
return JSON.parse(value);
|
|
30891
|
+
} catch {
|
|
30892
|
+
return;
|
|
30893
|
+
}
|
|
30894
|
+
}
|
|
30895
|
+
function dateString(value) {
|
|
30896
|
+
if (value instanceof Date)
|
|
30897
|
+
return value.toISOString();
|
|
30898
|
+
return String(value);
|
|
30431
30899
|
}
|
|
30432
30900
|
|
|
30433
|
-
|
|
30434
|
-
|
|
30435
|
-
|
|
30436
|
-
|
|
30437
|
-
|
|
30438
|
-
|
|
30439
|
-
|
|
30440
|
-
|
|
30441
|
-
|
|
30901
|
+
// src/server/sqlite-store.ts
|
|
30902
|
+
import { Database } from "bun:sqlite";
|
|
30903
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
30904
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
30905
|
+
import { dirname as dirname4, join as join5 } from "path";
|
|
30906
|
+
|
|
30907
|
+
// src/server/migrations-dir.ts
|
|
30908
|
+
import { existsSync as existsSync2 } from "fs";
|
|
30909
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
30910
|
+
var MIGRATION_DIALECTS = ["postgres", "sqlite"];
|
|
30911
|
+
var MAX_WALK_UP = 6;
|
|
30912
|
+
function findMigrationsRoot(startDirs = defaultStartDirs()) {
|
|
30913
|
+
for (const start of startDirs) {
|
|
30914
|
+
let dir = start;
|
|
30915
|
+
for (let level = 0;level < MAX_WALK_UP; level += 1) {
|
|
30916
|
+
const candidate = join4(dir, "migrations");
|
|
30917
|
+
if (MIGRATION_DIALECTS.some((dialect) => existsSync2(join4(candidate, dialect))))
|
|
30918
|
+
return candidate;
|
|
30919
|
+
const parent = dirname3(dir);
|
|
30920
|
+
if (parent === dir)
|
|
30921
|
+
break;
|
|
30922
|
+
dir = parent;
|
|
30923
|
+
}
|
|
30442
30924
|
}
|
|
30443
|
-
|
|
30444
|
-
|
|
30445
|
-
|
|
30446
|
-
|
|
30925
|
+
return null;
|
|
30926
|
+
}
|
|
30927
|
+
function resolveMigrationsDir(dialect, root3 = findMigrationsRoot()) {
|
|
30928
|
+
if (!root3) {
|
|
30929
|
+
throw new Error(`could not locate the migrations directory for dialect "${dialect}". ` + `Expected a migrations/${dialect}/ folder alongside the package root.`);
|
|
30930
|
+
}
|
|
30931
|
+
const dir = join4(root3, dialect);
|
|
30932
|
+
if (!existsSync2(dir)) {
|
|
30933
|
+
throw new Error(`migrations directory not found: ${dir}`);
|
|
30934
|
+
}
|
|
30935
|
+
return dir;
|
|
30936
|
+
}
|
|
30937
|
+
function defaultStartDirs() {
|
|
30938
|
+
const dirs = [import.meta.dir];
|
|
30939
|
+
const cwd = process.cwd();
|
|
30940
|
+
if (cwd && cwd !== import.meta.dir)
|
|
30941
|
+
dirs.push(cwd);
|
|
30942
|
+
return dirs;
|
|
30943
|
+
}
|
|
30944
|
+
|
|
30945
|
+
// src/server/sqlite-store.ts
|
|
30946
|
+
var CLAIM_ATTEMPTS = 8;
|
|
30947
|
+
var CLAIMABLE_STATUSES = ["queued", "retrying"];
|
|
30948
|
+
var LAST_USED_RESOLUTION_MS = 60000;
|
|
30949
|
+
|
|
30950
|
+
class SqliteSkillsStore {
|
|
30951
|
+
backend;
|
|
30952
|
+
db;
|
|
30953
|
+
closed = false;
|
|
30954
|
+
constructor(path = SQLITE_MEMORY_PATH, options = {}) {
|
|
30955
|
+
const inMemory = path === SQLITE_MEMORY_PATH;
|
|
30956
|
+
if (!inMemory)
|
|
30957
|
+
mkdirSync2(dirname4(path), { recursive: true });
|
|
30958
|
+
this.db = openDatabase(path);
|
|
30959
|
+
this.db.exec(`PRAGMA busy_timeout = ${Math.max(0, options.busyTimeoutMs ?? 5000)}`);
|
|
30960
|
+
if (!inMemory)
|
|
30961
|
+
enableWalMode(this.db);
|
|
30962
|
+
this.db.exec("PRAGMA foreign_keys = ON");
|
|
30963
|
+
this.db.exec("PRAGMA synchronous = NORMAL");
|
|
30964
|
+
if (options.migrate !== false) {
|
|
30965
|
+
applySqliteMigrations(this.db, options.migrationsDir);
|
|
30966
|
+
}
|
|
30967
|
+
this.backend = {
|
|
30968
|
+
kind: "sqlite",
|
|
30969
|
+
durable: !inMemory,
|
|
30970
|
+
label: inMemory ? "sqlite (in-memory)" : `sqlite (${path})`
|
|
30971
|
+
};
|
|
30972
|
+
}
|
|
30973
|
+
get database() {
|
|
30974
|
+
return this.db;
|
|
30975
|
+
}
|
|
30976
|
+
async close() {
|
|
30977
|
+
if (this.closed)
|
|
30978
|
+
return;
|
|
30979
|
+
this.closed = true;
|
|
30980
|
+
this.db.close(false);
|
|
30447
30981
|
}
|
|
30448
30982
|
async ensureBootstrapApiKey(token, principal) {
|
|
30449
|
-
|
|
30983
|
+
const resolved = publicPrincipal(principal);
|
|
30984
|
+
this.db.transaction(() => {
|
|
30985
|
+
this.db.run(`INSERT INTO organizations (id, slug, name) VALUES (?, ?, ?)
|
|
30986
|
+
ON CONFLICT (id) DO UPDATE SET slug = excluded.slug, name = excluded.name`, [resolved.orgId, resolved.orgSlug, resolved.orgName]);
|
|
30987
|
+
this.db.run(`INSERT INTO users (id, email, name) VALUES (?, ?, ?)
|
|
30988
|
+
ON CONFLICT (id) DO UPDATE SET email = excluded.email`, [resolved.userId, resolved.email, resolved.email]);
|
|
30989
|
+
this.db.run(`INSERT INTO organization_members (org_id, user_id, role) VALUES (?, ?, ?)
|
|
30990
|
+
ON CONFLICT (org_id, user_id) DO UPDATE SET role = excluded.role`, [resolved.orgId, resolved.userId, resolved.role]);
|
|
30991
|
+
this.db.run(`INSERT INTO api_keys (id, org_id, user_id, name, key_hash, scopes_json)
|
|
30992
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
30993
|
+
ON CONFLICT (key_hash) DO NOTHING`, [resolved.apiKeyId, resolved.orgId, resolved.userId, "bootstrap", hashApiKey(token), JSON.stringify(resolved.scopes)]);
|
|
30994
|
+
})();
|
|
30450
30995
|
}
|
|
30451
30996
|
async authenticateApiKeyHash(hash) {
|
|
30452
|
-
|
|
30453
|
-
|
|
30454
|
-
|
|
30455
|
-
|
|
30997
|
+
const row = this.get(`SELECT k.id AS api_key_id, k.scopes_json, k.last_used_at, o.id AS org_id, o.slug AS org_slug, o.name AS org_name,
|
|
30998
|
+
u.id AS user_id, u.email, m.role
|
|
30999
|
+
FROM api_keys k
|
|
31000
|
+
JOIN organizations o ON o.id = k.org_id
|
|
31001
|
+
JOIN users u ON u.id = k.user_id
|
|
31002
|
+
LEFT JOIN organization_members m ON m.org_id = k.org_id AND m.user_id = k.user_id
|
|
31003
|
+
WHERE k.key_hash = ? AND k.revoked_at IS NULL
|
|
31004
|
+
LIMIT 1`, [hash]);
|
|
31005
|
+
if (!row)
|
|
31006
|
+
return null;
|
|
31007
|
+
const lastUsed = typeof row.last_used_at === "string" ? Date.parse(row.last_used_at) : Number.NaN;
|
|
31008
|
+
if (!Number.isFinite(lastUsed) || Date.now() - lastUsed >= LAST_USED_RESOLUTION_MS) {
|
|
31009
|
+
this.db.run("UPDATE api_keys SET last_used_at = ? WHERE id = ?", [nowIso(), String(row.api_key_id)]);
|
|
31010
|
+
}
|
|
31011
|
+
return {
|
|
31012
|
+
apiKeyId: String(row.api_key_id),
|
|
31013
|
+
orgId: String(row.org_id),
|
|
31014
|
+
orgSlug: String(row.org_slug),
|
|
31015
|
+
orgName: String(row.org_name),
|
|
31016
|
+
userId: String(row.user_id),
|
|
31017
|
+
email: String(row.email),
|
|
31018
|
+
role: typeof row.role === "string" ? row.role : "member",
|
|
31019
|
+
scopes: parseScopes(row.scopes_json)
|
|
31020
|
+
};
|
|
31021
|
+
}
|
|
31022
|
+
async createRun(input) {
|
|
31023
|
+
if (input.idempotencyKey) {
|
|
31024
|
+
const existing = this.get("SELECT * FROM skills_runs WHERE org_id = ? AND idempotency_key = ? LIMIT 1", [input.principal.orgId, input.idempotencyKey]);
|
|
31025
|
+
if (existing)
|
|
31026
|
+
return rowToRun(existing);
|
|
31027
|
+
}
|
|
31028
|
+
const row = this.get(`INSERT INTO skills_runs (id, org_id, user_id, skill_slug, requested_slug, status, input_json, args_json, idempotency_key, correlation_id, created_at)
|
|
31029
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
31030
|
+
RETURNING *`, [
|
|
31031
|
+
runId(),
|
|
31032
|
+
input.principal.orgId,
|
|
31033
|
+
input.principal.userId,
|
|
31034
|
+
input.slug,
|
|
31035
|
+
input.slug,
|
|
31036
|
+
"queued",
|
|
31037
|
+
JSON.stringify(input.input),
|
|
31038
|
+
JSON.stringify(input.args),
|
|
31039
|
+
input.idempotencyKey ?? null,
|
|
31040
|
+
randomUUID2(),
|
|
31041
|
+
nowIso()
|
|
31042
|
+
]);
|
|
31043
|
+
return rowToRun(row);
|
|
31044
|
+
}
|
|
31045
|
+
async listRuns(principal, limit) {
|
|
31046
|
+
return this.all("SELECT * FROM skills_runs WHERE org_id = ? ORDER BY created_at DESC, rowid DESC LIMIT ?", [principal.orgId, normalizeLimit(limit)]).map(rowToRun);
|
|
31047
|
+
}
|
|
31048
|
+
async getRun(principal, id) {
|
|
31049
|
+
const row = this.get("SELECT * FROM skills_runs WHERE id = ? AND org_id = ? LIMIT 1", [id, principal.orgId]);
|
|
31050
|
+
return row ? rowToRun(row) : null;
|
|
31051
|
+
}
|
|
31052
|
+
async claimNextRun(input) {
|
|
31053
|
+
const lost = new Set;
|
|
31054
|
+
for (let attempt = 0;attempt < CLAIM_ATTEMPTS; attempt += 1) {
|
|
31055
|
+
const claimed = this.claimOnce(input.workerId, lost);
|
|
31056
|
+
if (claimed === "empty")
|
|
31057
|
+
return null;
|
|
31058
|
+
if (claimed)
|
|
31059
|
+
return claimed;
|
|
31060
|
+
}
|
|
31061
|
+
return null;
|
|
31062
|
+
}
|
|
31063
|
+
claimOnce(workerId, lost) {
|
|
31064
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
31065
|
+
try {
|
|
31066
|
+
const excluded = [...lost];
|
|
31067
|
+
const candidate = this.get(`SELECT id FROM skills_runs
|
|
31068
|
+
WHERE status IN (${CLAIMABLE_STATUSES.map(() => "?").join(", ")})
|
|
31069
|
+
${excluded.length ? `AND id NOT IN (${excluded.map(() => "?").join(", ")})` : ""}
|
|
31070
|
+
ORDER BY created_at ASC, rowid ASC
|
|
31071
|
+
LIMIT 1`, [...CLAIMABLE_STATUSES, ...excluded]);
|
|
31072
|
+
if (!candidate) {
|
|
31073
|
+
this.db.exec("COMMIT");
|
|
31074
|
+
return "empty";
|
|
31075
|
+
}
|
|
31076
|
+
const id = String(candidate.id);
|
|
31077
|
+
const now = nowIso();
|
|
31078
|
+
const result = this.db.run(`UPDATE skills_runs
|
|
31079
|
+
SET status = 'running', started_at = COALESCE(started_at, ?), locked_by = ?, locked_at = ?
|
|
31080
|
+
WHERE id = ? AND status IN (${CLAIMABLE_STATUSES.map(() => "?").join(", ")})`, [now, workerId, now, id, ...CLAIMABLE_STATUSES]);
|
|
31081
|
+
if (result.changes !== 1) {
|
|
31082
|
+
this.db.exec("ROLLBACK");
|
|
31083
|
+
lost.add(id);
|
|
31084
|
+
return null;
|
|
31085
|
+
}
|
|
31086
|
+
const row = this.get("SELECT * FROM skills_runs WHERE id = ? LIMIT 1", [id]);
|
|
31087
|
+
if (!row) {
|
|
31088
|
+
this.db.exec("ROLLBACK");
|
|
31089
|
+
throw new Error(`claimed run ${id} vanished within its own transaction; refusing to report a lost claim as an empty queue`);
|
|
31090
|
+
}
|
|
31091
|
+
this.db.exec("COMMIT");
|
|
31092
|
+
return rowToRun(row);
|
|
31093
|
+
} catch (error) {
|
|
31094
|
+
this.rollbackQuietly();
|
|
31095
|
+
throw error;
|
|
31096
|
+
}
|
|
31097
|
+
}
|
|
31098
|
+
async updateRun(id, patch) {
|
|
31099
|
+
const current = this.get("SELECT * FROM skills_runs WHERE id = ? LIMIT 1", [id]);
|
|
31100
|
+
if (!current)
|
|
31101
|
+
return null;
|
|
31102
|
+
const run = { ...rowToRun(current), ...patch };
|
|
31103
|
+
const row = this.get(`UPDATE skills_runs
|
|
31104
|
+
SET status = ?, output_type = ?, output_preview = ?, error_code = ?, error_message = ?, started_at = ?, completed_at = ?
|
|
31105
|
+
WHERE id = ?
|
|
31106
|
+
RETURNING *`, [
|
|
31107
|
+
run.status,
|
|
31108
|
+
run.outputType ?? null,
|
|
31109
|
+
run.outputPreview ?? null,
|
|
31110
|
+
run.errorCode ?? null,
|
|
31111
|
+
run.errorMessage ?? null,
|
|
31112
|
+
run.startedAt ?? null,
|
|
31113
|
+
run.completedAt ?? null,
|
|
31114
|
+
id
|
|
31115
|
+
]);
|
|
31116
|
+
return row ? rowToRun(row) : null;
|
|
31117
|
+
}
|
|
31118
|
+
async appendLog(id, orgId, level, message) {
|
|
31119
|
+
const row = this.get(`INSERT INTO skills_run_logs (run_id, org_id, sequence, level, message, created_at)
|
|
31120
|
+
VALUES (?, ?, (SELECT COALESCE(MAX(sequence), 0) + 1 FROM skills_run_logs WHERE run_id = ?), ?, ?, ?)
|
|
31121
|
+
RETURNING *`, [id, orgId, id, level, message, nowIso()]);
|
|
31122
|
+
return rowToLog(row);
|
|
31123
|
+
}
|
|
31124
|
+
async listLogs(principal, id) {
|
|
31125
|
+
return this.all(`SELECT l.* FROM skills_run_logs l
|
|
31126
|
+
JOIN skills_runs r ON r.id = l.run_id AND r.org_id = ?
|
|
31127
|
+
WHERE l.run_id = ?
|
|
31128
|
+
ORDER BY l.sequence ASC`, [principal.orgId, id]).map(rowToLog);
|
|
31129
|
+
}
|
|
31130
|
+
async addArtifact(artifact) {
|
|
31131
|
+
const row = this.get(`INSERT INTO skills_artifacts (id, run_id, org_id, file_name, relative_path, content_type, byte_size, sha256, storage_kind, storage_key, body_text, created_at)
|
|
31132
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
31133
|
+
RETURNING *`, [
|
|
31134
|
+
artifact.id,
|
|
31135
|
+
artifact.runId,
|
|
31136
|
+
artifact.orgId,
|
|
31137
|
+
artifact.fileName,
|
|
31138
|
+
artifact.relativePath,
|
|
31139
|
+
artifact.contentType,
|
|
31140
|
+
artifact.byteSize,
|
|
31141
|
+
artifact.sha256,
|
|
31142
|
+
artifact.storageKind,
|
|
31143
|
+
artifact.storageKey ?? null,
|
|
31144
|
+
artifact.bodyText ?? null,
|
|
31145
|
+
nowIso()
|
|
31146
|
+
]);
|
|
31147
|
+
return rowToArtifact(row);
|
|
31148
|
+
}
|
|
31149
|
+
async listArtifacts(principal, id) {
|
|
31150
|
+
return this.all(`SELECT a.* FROM skills_artifacts a
|
|
31151
|
+
JOIN skills_runs r ON r.id = a.run_id AND r.org_id = ?
|
|
31152
|
+
WHERE a.run_id = ?
|
|
31153
|
+
ORDER BY a.created_at ASC, a.rowid ASC`, [principal.orgId, id]).map(rowToArtifact);
|
|
31154
|
+
}
|
|
31155
|
+
async getArtifact(principal, id, artifact) {
|
|
31156
|
+
const row = this.get(`SELECT a.* FROM skills_artifacts a
|
|
31157
|
+
JOIN skills_runs r ON r.id = a.run_id AND r.org_id = ?
|
|
31158
|
+
WHERE a.run_id = ? AND a.id = ?
|
|
31159
|
+
LIMIT 1`, [principal.orgId, id, artifact]);
|
|
31160
|
+
return row ? rowToArtifact(row) : null;
|
|
31161
|
+
}
|
|
31162
|
+
async publishSkill(input) {
|
|
31163
|
+
const orgId = input.principal.orgId;
|
|
31164
|
+
const now = nowIso();
|
|
31165
|
+
return this.db.transaction(() => {
|
|
31166
|
+
const previous = this.get("SELECT bundle_sha256 FROM skills_registry WHERE org_id = ? AND slug = ?", [orgId, input.slug]);
|
|
31167
|
+
const previousSha = typeof previous?.bundle_sha256 === "string" ? previous.bundle_sha256 : null;
|
|
31168
|
+
if (input.bundle) {
|
|
31169
|
+
this.db.run(`INSERT INTO skills_bundles (org_id, sha256, byte_size, content_type, storage_kind, storage_key, body_blob, created_at)
|
|
31170
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
31171
|
+
ON CONFLICT (org_id, sha256) DO UPDATE SET
|
|
31172
|
+
byte_size = excluded.byte_size,
|
|
31173
|
+
content_type = excluded.content_type,
|
|
31174
|
+
storage_kind = excluded.storage_kind,
|
|
31175
|
+
storage_key = excluded.storage_key,
|
|
31176
|
+
body_blob = excluded.body_blob`, [
|
|
31177
|
+
orgId,
|
|
31178
|
+
input.bundle.sha256,
|
|
31179
|
+
input.bundle.byteSize,
|
|
31180
|
+
input.bundle.contentType,
|
|
31181
|
+
input.bundle.storageKind,
|
|
31182
|
+
input.bundle.storageKey ?? null,
|
|
31183
|
+
input.bundle.bytes ?? null,
|
|
31184
|
+
now
|
|
31185
|
+
]);
|
|
31186
|
+
}
|
|
31187
|
+
const row = this.get(`INSERT INTO skills_registry (org_id, slug, display_name, description, category, tags_json, source, kind, version, skill_md,
|
|
31188
|
+
bundle_sha256, bundle_byte_size, published_by_user_id, created_at, updated_at)
|
|
31189
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
31190
|
+
ON CONFLICT (org_id, slug) DO UPDATE SET
|
|
31191
|
+
display_name = excluded.display_name,
|
|
31192
|
+
description = excluded.description,
|
|
31193
|
+
category = excluded.category,
|
|
31194
|
+
tags_json = excluded.tags_json,
|
|
31195
|
+
source = excluded.source,
|
|
31196
|
+
kind = excluded.kind,
|
|
31197
|
+
version = excluded.version,
|
|
31198
|
+
skill_md = excluded.skill_md,
|
|
31199
|
+
-- COALESCE, not a straight assignment. A publish that carries no bundle is a
|
|
31200
|
+
-- metadata update, not an instruction to discard the stored one: the plain
|
|
31201
|
+
-- assignment nulled bundle_sha256 and then handed the old digest to orphan
|
|
31202
|
+
-- collection, so re-publishing metadata over an existing skill deleted its
|
|
31203
|
+
-- tarball and left every client with a 404.
|
|
31204
|
+
bundle_sha256 = COALESCE(excluded.bundle_sha256, skills_registry.bundle_sha256),
|
|
31205
|
+
bundle_byte_size = COALESCE(excluded.bundle_byte_size, skills_registry.bundle_byte_size),
|
|
31206
|
+
published_by_user_id = excluded.published_by_user_id,
|
|
31207
|
+
updated_at = excluded.updated_at
|
|
31208
|
+
RETURNING *`, [
|
|
31209
|
+
orgId,
|
|
31210
|
+
input.slug,
|
|
31211
|
+
input.displayName,
|
|
31212
|
+
input.description,
|
|
31213
|
+
input.category,
|
|
31214
|
+
JSON.stringify(input.tags),
|
|
31215
|
+
input.source,
|
|
31216
|
+
input.kind,
|
|
31217
|
+
input.version ?? null,
|
|
31218
|
+
input.skillMd ?? null,
|
|
31219
|
+
input.bundle?.sha256 ?? null,
|
|
31220
|
+
input.bundle?.byteSize ?? null,
|
|
31221
|
+
input.principal.userId,
|
|
31222
|
+
now,
|
|
31223
|
+
now
|
|
31224
|
+
]);
|
|
31225
|
+
if (previousSha && input.bundle && previousSha !== input.bundle.sha256)
|
|
31226
|
+
this.collectOrphanBundle(orgId, previousSha);
|
|
31227
|
+
return rowToSkill(row);
|
|
31228
|
+
})();
|
|
31229
|
+
}
|
|
31230
|
+
async listSkills(principal) {
|
|
31231
|
+
return this.all("SELECT * FROM skills_registry WHERE org_id = ? ORDER BY slug ASC", [principal.orgId]).map(rowToSkill);
|
|
31232
|
+
}
|
|
31233
|
+
async getSkill(principal, slug) {
|
|
31234
|
+
const row = this.get("SELECT * FROM skills_registry WHERE org_id = ? AND slug = ? LIMIT 1", [principal.orgId, slug]);
|
|
31235
|
+
return row ? rowToSkill(row) : null;
|
|
31236
|
+
}
|
|
31237
|
+
async updateSkill(principal, slug, patch) {
|
|
31238
|
+
const current = await this.getSkill(principal, slug);
|
|
31239
|
+
if (!current)
|
|
31240
|
+
return null;
|
|
31241
|
+
const next = { ...current, ...patch };
|
|
31242
|
+
const row = this.get(`UPDATE skills_registry
|
|
31243
|
+
SET display_name = ?, description = ?, category = ?, tags_json = ?, kind = ?, version = ?, skill_md = ?, updated_at = ?
|
|
31244
|
+
WHERE org_id = ? AND slug = ?
|
|
31245
|
+
RETURNING *`, [
|
|
31246
|
+
next.displayName,
|
|
31247
|
+
next.description,
|
|
31248
|
+
next.category,
|
|
31249
|
+
JSON.stringify(next.tags),
|
|
31250
|
+
next.kind,
|
|
31251
|
+
next.version ?? null,
|
|
31252
|
+
next.skillMd ?? null,
|
|
31253
|
+
nowIso(),
|
|
31254
|
+
principal.orgId,
|
|
31255
|
+
slug
|
|
31256
|
+
]);
|
|
31257
|
+
return row ? rowToSkill(row) : null;
|
|
31258
|
+
}
|
|
31259
|
+
async deleteSkill(principal, slug) {
|
|
31260
|
+
return this.db.transaction(() => {
|
|
31261
|
+
const existing = this.get("SELECT bundle_sha256 FROM skills_registry WHERE org_id = ? AND slug = ?", [principal.orgId, slug]);
|
|
31262
|
+
if (!existing)
|
|
31263
|
+
return false;
|
|
31264
|
+
this.db.run("DELETE FROM skills_registry WHERE org_id = ? AND slug = ?", [principal.orgId, slug]);
|
|
31265
|
+
if (typeof existing.bundle_sha256 === "string")
|
|
31266
|
+
this.collectOrphanBundle(principal.orgId, existing.bundle_sha256);
|
|
31267
|
+
return true;
|
|
31268
|
+
})();
|
|
31269
|
+
}
|
|
31270
|
+
async getSkillBundle(principal, sha256) {
|
|
31271
|
+
const row = this.get("SELECT * FROM skills_bundles WHERE org_id = ? AND sha256 = ? LIMIT 1", [principal.orgId, sha256]);
|
|
31272
|
+
return row ? rowToSkillBundle(row) : null;
|
|
31273
|
+
}
|
|
31274
|
+
collectOrphanBundle(orgId, sha256) {
|
|
31275
|
+
const referenced = this.get("SELECT 1 AS present FROM skills_registry WHERE org_id = ? AND bundle_sha256 = ? LIMIT 1", [orgId, sha256]);
|
|
31276
|
+
if (referenced)
|
|
31277
|
+
return;
|
|
31278
|
+
this.db.run("DELETE FROM skills_bundles WHERE org_id = ? AND sha256 = ?", [orgId, sha256]);
|
|
31279
|
+
}
|
|
31280
|
+
get(sql, params) {
|
|
31281
|
+
return this.db.query(sql).get(...params) ?? null;
|
|
31282
|
+
}
|
|
31283
|
+
all(sql, params) {
|
|
31284
|
+
return this.db.query(sql).all(...params);
|
|
31285
|
+
}
|
|
31286
|
+
rollbackQuietly() {
|
|
31287
|
+
try {
|
|
31288
|
+
this.db.exec("ROLLBACK");
|
|
31289
|
+
} catch {}
|
|
31290
|
+
}
|
|
31291
|
+
}
|
|
31292
|
+
function applySqliteMigrations(db, migrationsDir = resolveMigrationsDir("sqlite")) {
|
|
31293
|
+
db.exec(`CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
31294
|
+
version text PRIMARY KEY,
|
|
31295
|
+
applied_at text NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
31296
|
+
)`);
|
|
31297
|
+
const files = readdirSync2(migrationsDir).filter((name) => name.endsWith(".sql")).sort();
|
|
31298
|
+
if (files.length === 0) {
|
|
31299
|
+
throw new Error(`no .sql migrations found in ${migrationsDir}`);
|
|
31300
|
+
}
|
|
31301
|
+
const appliedNow = [];
|
|
31302
|
+
for (const file of files) {
|
|
31303
|
+
const version2 = file.replace(/\.sql$/, "");
|
|
31304
|
+
const text = readFileSync3(join5(migrationsDir, file), "utf8");
|
|
31305
|
+
const apply = db.transaction(() => {
|
|
31306
|
+
const already = db.query("SELECT 1 AS present FROM schema_migrations WHERE version = ? LIMIT 1").get(version2);
|
|
31307
|
+
if (already)
|
|
31308
|
+
return false;
|
|
31309
|
+
db.exec(text);
|
|
31310
|
+
db.run("INSERT INTO schema_migrations (version) VALUES (?)", [version2]);
|
|
31311
|
+
return true;
|
|
31312
|
+
});
|
|
31313
|
+
if (apply.immediate())
|
|
31314
|
+
appliedNow.push(version2);
|
|
31315
|
+
}
|
|
31316
|
+
return appliedNow;
|
|
31317
|
+
}
|
|
31318
|
+
function enableWalMode(db, attempts = 50, pauseMs = 10) {
|
|
31319
|
+
for (let attempt = 0;attempt < attempts; attempt += 1) {
|
|
31320
|
+
if (journalMode(db) === "wal")
|
|
31321
|
+
return true;
|
|
31322
|
+
try {
|
|
31323
|
+
if (String(db.query("PRAGMA journal_mode = WAL").get()?.journal_mode).toLowerCase() === "wal") {
|
|
31324
|
+
return true;
|
|
31325
|
+
}
|
|
31326
|
+
} catch {}
|
|
31327
|
+
Bun.sleepSync(pauseMs);
|
|
31328
|
+
}
|
|
31329
|
+
return false;
|
|
31330
|
+
}
|
|
31331
|
+
function journalMode(db) {
|
|
31332
|
+
try {
|
|
31333
|
+
return String(db.query("PRAGMA journal_mode").get()?.journal_mode ?? "").toLowerCase();
|
|
31334
|
+
} catch {
|
|
31335
|
+
return "";
|
|
31336
|
+
}
|
|
31337
|
+
}
|
|
31338
|
+
function openDatabase(path) {
|
|
31339
|
+
try {
|
|
31340
|
+
return new Database(path, { create: true, readwrite: true });
|
|
31341
|
+
} catch (error) {
|
|
31342
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
31343
|
+
throw new Error(`cannot open the skills database at ${path}: ${reason}. ` + "Check that the directory exists and is writable. Set HASNA_SKILLS_DATABASE_URL to choose a " + "different path or a postgres:// URL, or HASNA_SKILLS_DIR to relocate the whole data directory.", { cause: error });
|
|
31344
|
+
}
|
|
31345
|
+
}
|
|
31346
|
+
function parseScopes(value) {
|
|
31347
|
+
if (Array.isArray(value))
|
|
31348
|
+
return value.map(String);
|
|
31349
|
+
if (typeof value !== "string")
|
|
31350
|
+
return [];
|
|
31351
|
+
try {
|
|
31352
|
+
const parsed = JSON.parse(value);
|
|
31353
|
+
return Array.isArray(parsed) ? parsed.map(String) : [];
|
|
31354
|
+
} catch {
|
|
31355
|
+
return [];
|
|
31356
|
+
}
|
|
31357
|
+
}
|
|
31358
|
+
|
|
31359
|
+
// src/server/store.ts
|
|
31360
|
+
function resolvePoolMax(env = process.env) {
|
|
31361
|
+
const parsed = Number.parseInt(env.HASNA_SKILLS_DATABASE_POOL_MAX || env.SKILLS_DATABASE_POOL_MAX || "", 10);
|
|
31362
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 4;
|
|
31363
|
+
}
|
|
31364
|
+
var LOG_SEQUENCE_ATTEMPTS = 12;
|
|
31365
|
+
function createArtifactId() {
|
|
31366
|
+
return artifactId();
|
|
31367
|
+
}
|
|
31368
|
+
async function createStore(options = {}) {
|
|
31369
|
+
const target = resolveDatabaseTarget(options.databaseUrl);
|
|
31370
|
+
const store = instantiateStore(target, options.sqlite);
|
|
31371
|
+
await store.verifyConnectivity?.();
|
|
31372
|
+
if (options.bootstrapApiKey && store.ensureBootstrapApiKey) {
|
|
31373
|
+
await store.ensureBootstrapApiKey(options.bootstrapApiKey);
|
|
31374
|
+
}
|
|
31375
|
+
return store;
|
|
31376
|
+
}
|
|
31377
|
+
function instantiateStore(target, sqliteOptions) {
|
|
31378
|
+
switch (target.kind) {
|
|
31379
|
+
case "postgres":
|
|
31380
|
+
return new PostgresSkillsStore(target.url);
|
|
31381
|
+
case "sqlite":
|
|
31382
|
+
return new SqliteSkillsStore(target.path, sqliteOptions);
|
|
31383
|
+
case "memory":
|
|
31384
|
+
return new MemorySkillsStore;
|
|
31385
|
+
}
|
|
31386
|
+
}
|
|
31387
|
+
|
|
31388
|
+
class MemorySkillsStore {
|
|
31389
|
+
backend = { kind: "memory", durable: false, label: "memory (non-durable)" };
|
|
31390
|
+
apiKeys = new Map;
|
|
31391
|
+
runs = new Map;
|
|
31392
|
+
logs = new Map;
|
|
31393
|
+
artifacts = new Map;
|
|
31394
|
+
idempotency = new Map;
|
|
31395
|
+
skills = new Map;
|
|
31396
|
+
bundles = new Map;
|
|
31397
|
+
constructor(apiKeys = []) {
|
|
31398
|
+
for (const key of apiKeys)
|
|
31399
|
+
this.addApiKey(key.token, key.principal);
|
|
31400
|
+
}
|
|
31401
|
+
addApiKey(token, principal) {
|
|
31402
|
+
const resolved = publicPrincipal(principal);
|
|
31403
|
+
this.apiKeys.set(hashApiKey(token), resolved);
|
|
31404
|
+
return resolved;
|
|
31405
|
+
}
|
|
31406
|
+
async ensureBootstrapApiKey(token, principal) {
|
|
31407
|
+
this.addApiKey(token, principal);
|
|
31408
|
+
}
|
|
31409
|
+
async authenticateApiKeyHash(hash) {
|
|
31410
|
+
return this.apiKeys.get(hash) ?? null;
|
|
31411
|
+
}
|
|
31412
|
+
async createRun(input) {
|
|
31413
|
+
const idemKey = input.idempotencyKey?.trim();
|
|
30456
31414
|
const idemMapKey = idemKey ? `${input.principal.orgId}:${idemKey}` : undefined;
|
|
30457
31415
|
if (idemMapKey) {
|
|
30458
31416
|
const existing = this.idempotency.get(idemMapKey);
|
|
@@ -30470,7 +31428,7 @@ class MemorySkillsStore {
|
|
|
30470
31428
|
input: input.input,
|
|
30471
31429
|
args: input.args,
|
|
30472
31430
|
...idemKey ? { idempotencyKey: idemKey } : {},
|
|
30473
|
-
correlationId:
|
|
31431
|
+
correlationId: randomUUID3(),
|
|
30474
31432
|
costCents: 0,
|
|
30475
31433
|
createdAt: now
|
|
30476
31434
|
};
|
|
@@ -30482,17 +31440,17 @@ class MemorySkillsStore {
|
|
|
30482
31440
|
return run;
|
|
30483
31441
|
}
|
|
30484
31442
|
async listRuns(principal, limit) {
|
|
30485
|
-
return Array.from(this.runs.values()).filter((run) => run.orgId === principal.orgId).sort((a3, b3) => b3.createdAt.localeCompare(a3.createdAt)).slice(0, limit);
|
|
31443
|
+
return Array.from(this.runs.values()).filter((run) => run.orgId === principal.orgId).sort((a3, b3) => b3.createdAt.localeCompare(a3.createdAt)).slice(0, normalizeLimit(limit));
|
|
30486
31444
|
}
|
|
30487
31445
|
async getRun(principal, runId2) {
|
|
30488
31446
|
const run = this.runs.get(runId2);
|
|
30489
31447
|
return run && run.orgId === principal.orgId ? run : null;
|
|
30490
31448
|
}
|
|
30491
|
-
async claimNextRun(
|
|
31449
|
+
async claimNextRun(_input) {
|
|
30492
31450
|
const run = Array.from(this.runs.values()).filter((candidate) => candidate.status === "queued" || candidate.status === "retrying").sort((a3, b3) => a3.createdAt.localeCompare(b3.createdAt))[0];
|
|
30493
31451
|
if (!run)
|
|
30494
31452
|
return null;
|
|
30495
|
-
return this.patchRun(run.id, { status: "running", startedAt: nowIso() });
|
|
31453
|
+
return this.patchRun(run.id, { status: "running", startedAt: run.startedAt ?? nowIso() });
|
|
30496
31454
|
}
|
|
30497
31455
|
async updateRun(runId2, patch) {
|
|
30498
31456
|
return this.patchRun(runId2, patch);
|
|
@@ -30523,6 +31481,74 @@ class MemorySkillsStore {
|
|
|
30523
31481
|
const artifacts = await this.listArtifacts(principal, runId2);
|
|
30524
31482
|
return artifacts.find((artifact) => artifact.id === id) ?? null;
|
|
30525
31483
|
}
|
|
31484
|
+
async publishSkill(input) {
|
|
31485
|
+
const key = skillKey(input.principal.orgId, input.slug);
|
|
31486
|
+
const now = nowIso();
|
|
31487
|
+
const previous = this.skills.get(key);
|
|
31488
|
+
if (input.bundle) {
|
|
31489
|
+
const bundleMapKey = skillKey(input.principal.orgId, input.bundle.sha256);
|
|
31490
|
+
this.bundles.set(bundleMapKey, {
|
|
31491
|
+
...this.bundles.get(bundleMapKey),
|
|
31492
|
+
...input.bundle,
|
|
31493
|
+
orgId: input.principal.orgId,
|
|
31494
|
+
createdAt: this.bundles.get(bundleMapKey)?.createdAt ?? now
|
|
31495
|
+
});
|
|
31496
|
+
}
|
|
31497
|
+
const record = {
|
|
31498
|
+
orgId: input.principal.orgId,
|
|
31499
|
+
slug: input.slug,
|
|
31500
|
+
displayName: input.displayName,
|
|
31501
|
+
description: input.description,
|
|
31502
|
+
category: input.category,
|
|
31503
|
+
tags: [...input.tags],
|
|
31504
|
+
source: input.source,
|
|
31505
|
+
kind: input.kind,
|
|
31506
|
+
...input.version ? { version: input.version } : {},
|
|
31507
|
+
...input.skillMd ? { skillMd: input.skillMd } : {},
|
|
31508
|
+
...input.bundle ? { bundleSha256: input.bundle.sha256, bundleByteSize: input.bundle.byteSize } : previous?.bundleSha256 ? { bundleSha256: previous.bundleSha256, ...previous.bundleByteSize === undefined ? {} : { bundleByteSize: previous.bundleByteSize } } : {},
|
|
31509
|
+
publishedByUserId: input.principal.userId,
|
|
31510
|
+
createdAt: previous?.createdAt ?? now,
|
|
31511
|
+
updatedAt: now
|
|
31512
|
+
};
|
|
31513
|
+
this.skills.set(key, record);
|
|
31514
|
+
if (previous?.bundleSha256 && input.bundle && previous.bundleSha256 !== input.bundle.sha256) {
|
|
31515
|
+
this.collectOrphanBundle(input.principal.orgId, previous.bundleSha256);
|
|
31516
|
+
}
|
|
31517
|
+
return record;
|
|
31518
|
+
}
|
|
31519
|
+
async listSkills(principal) {
|
|
31520
|
+
return Array.from(this.skills.values()).filter((skill) => skill.orgId === principal.orgId).sort((a3, b3) => a3.slug.localeCompare(b3.slug));
|
|
31521
|
+
}
|
|
31522
|
+
async getSkill(principal, slug) {
|
|
31523
|
+
const skill = this.skills.get(skillKey(principal.orgId, slug));
|
|
31524
|
+
return skill && skill.orgId === principal.orgId ? skill : null;
|
|
31525
|
+
}
|
|
31526
|
+
async updateSkill(principal, slug, patch) {
|
|
31527
|
+
const current = await this.getSkill(principal, slug);
|
|
31528
|
+
if (!current)
|
|
31529
|
+
return null;
|
|
31530
|
+
const next = { ...current, ...patch, updatedAt: nowIso() };
|
|
31531
|
+
this.skills.set(skillKey(principal.orgId, slug), next);
|
|
31532
|
+
return next;
|
|
31533
|
+
}
|
|
31534
|
+
async deleteSkill(principal, slug) {
|
|
31535
|
+
const current = await this.getSkill(principal, slug);
|
|
31536
|
+
if (!current)
|
|
31537
|
+
return false;
|
|
31538
|
+
this.skills.delete(skillKey(principal.orgId, slug));
|
|
31539
|
+
if (current.bundleSha256)
|
|
31540
|
+
this.collectOrphanBundle(principal.orgId, current.bundleSha256);
|
|
31541
|
+
return true;
|
|
31542
|
+
}
|
|
31543
|
+
async getSkillBundle(principal, sha256) {
|
|
31544
|
+
const bundle = this.bundles.get(skillKey(principal.orgId, sha256));
|
|
31545
|
+
return bundle && bundle.orgId === principal.orgId ? bundle : null;
|
|
31546
|
+
}
|
|
31547
|
+
collectOrphanBundle(orgId, sha256) {
|
|
31548
|
+
const referenced = Array.from(this.skills.values()).some((skill) => skill.orgId === orgId && skill.bundleSha256 === sha256);
|
|
31549
|
+
if (!referenced)
|
|
31550
|
+
this.bundles.delete(skillKey(orgId, sha256));
|
|
31551
|
+
}
|
|
30526
31552
|
patchRun(runId2, patch) {
|
|
30527
31553
|
const run = this.runs.get(runId2);
|
|
30528
31554
|
if (!run)
|
|
@@ -30532,13 +31558,32 @@ class MemorySkillsStore {
|
|
|
30532
31558
|
return next;
|
|
30533
31559
|
}
|
|
30534
31560
|
}
|
|
31561
|
+
function skillKey(orgId, slug) {
|
|
31562
|
+
return `${orgId.length}:${orgId}:${slug}`;
|
|
31563
|
+
}
|
|
30535
31564
|
|
|
30536
31565
|
class PostgresSkillsStore {
|
|
31566
|
+
backend = { kind: "postgres", durable: true, label: "postgres" };
|
|
30537
31567
|
sql;
|
|
30538
31568
|
constructor(databaseUrl) {
|
|
30539
31569
|
const bunWithSql = Bun;
|
|
30540
31570
|
this.sql = new bunWithSql.SQL(databaseUrl, { max: resolvePoolMax() });
|
|
30541
31571
|
}
|
|
31572
|
+
async verifyConnectivity() {
|
|
31573
|
+
try {
|
|
31574
|
+
await this.sql`SELECT 1`;
|
|
31575
|
+
} catch (error) {
|
|
31576
|
+
throw new Error("cannot reach the configured Postgres database. The server will not start with an unreachable " + "database rather than fall back to another backend and silently split your data across two stores. " + `Check HASNA_SKILLS_DATABASE_URL and that the instance is accepting connections. Driver reported: ${connectionFailureSummary(error)}`);
|
|
31577
|
+
}
|
|
31578
|
+
try {
|
|
31579
|
+
await this.sql`SELECT 1 FROM api_keys LIMIT 0`;
|
|
31580
|
+
} catch (error) {
|
|
31581
|
+
throw new Error("the configured Postgres database is reachable but has no skills schema. Run `skills-migrate` against it " + "before starting the server - unlike SQLite, Postgres is not migrated automatically, so that several " + `replicas cannot race to migrate a shared database. Driver reported: ${connectionFailureSummary(error)}`);
|
|
31582
|
+
}
|
|
31583
|
+
}
|
|
31584
|
+
async close() {
|
|
31585
|
+
await this.sql.close?.();
|
|
31586
|
+
}
|
|
30542
31587
|
async ensureBootstrapApiKey(token, principal) {
|
|
30543
31588
|
const resolved = publicPrincipal(principal);
|
|
30544
31589
|
await this.sql`
|
|
@@ -30601,7 +31646,7 @@ class PostgresSkillsStore {
|
|
|
30601
31646
|
const id = runId();
|
|
30602
31647
|
const rows = await this.sql`
|
|
30603
31648
|
INSERT INTO skills_runs (id, org_id, user_id, skill_slug, requested_slug, status, input_json, args_json, idempotency_key, correlation_id)
|
|
30604
|
-
VALUES (${id}, ${input.principal.orgId}, ${input.principal.userId}, ${input.slug}, ${input.slug}, ${"queued"}, ${JSON.stringify(input.input)}::jsonb, ${JSON.stringify(input.args)}::jsonb, ${input.idempotencyKey ?? null}, ${
|
|
31649
|
+
VALUES (${id}, ${input.principal.orgId}, ${input.principal.userId}, ${input.slug}, ${input.slug}, ${"queued"}, ${JSON.stringify(input.input)}::jsonb, ${JSON.stringify(input.args)}::jsonb, ${input.idempotencyKey ?? null}, ${randomUUID3()})
|
|
30605
31650
|
RETURNING *
|
|
30606
31651
|
`;
|
|
30607
31652
|
return rowToRun(rows[0]);
|
|
@@ -30609,7 +31654,7 @@ class PostgresSkillsStore {
|
|
|
30609
31654
|
async listRuns(principal, limit) {
|
|
30610
31655
|
const rows = await this.sql`
|
|
30611
31656
|
SELECT * FROM skills_runs WHERE org_id = ${principal.orgId}
|
|
30612
|
-
ORDER BY created_at DESC LIMIT ${limit}
|
|
31657
|
+
ORDER BY created_at DESC LIMIT ${normalizeLimit(limit)}
|
|
30613
31658
|
`;
|
|
30614
31659
|
return rows.map(rowToRun);
|
|
30615
31660
|
}
|
|
@@ -30654,14 +31699,28 @@ class PostgresSkillsStore {
|
|
|
30654
31699
|
return rows[0] ? rowToRun(rows[0]) : null;
|
|
30655
31700
|
}
|
|
30656
31701
|
async appendLog(runId2, orgId, level, message) {
|
|
30657
|
-
|
|
30658
|
-
|
|
30659
|
-
|
|
30660
|
-
|
|
30661
|
-
|
|
30662
|
-
|
|
30663
|
-
|
|
30664
|
-
|
|
31702
|
+
let lastError;
|
|
31703
|
+
for (let attempt = 0;attempt < LOG_SEQUENCE_ATTEMPTS; attempt += 1) {
|
|
31704
|
+
try {
|
|
31705
|
+
const rows = await this.sql`
|
|
31706
|
+
INSERT INTO skills_run_logs (run_id, org_id, sequence, level, message)
|
|
31707
|
+
VALUES (
|
|
31708
|
+
${runId2},
|
|
31709
|
+
${orgId},
|
|
31710
|
+
(SELECT COALESCE(MAX(sequence), 0) + 1 FROM skills_run_logs WHERE run_id = ${runId2}),
|
|
31711
|
+
${level},
|
|
31712
|
+
${message}
|
|
31713
|
+
)
|
|
31714
|
+
RETURNING *
|
|
31715
|
+
`;
|
|
31716
|
+
return rowToLog(rows[0]);
|
|
31717
|
+
} catch (error) {
|
|
31718
|
+
if (!isUniqueViolation(error))
|
|
31719
|
+
throw error;
|
|
31720
|
+
lastError = error;
|
|
31721
|
+
}
|
|
31722
|
+
}
|
|
31723
|
+
throw lastError;
|
|
30665
31724
|
}
|
|
30666
31725
|
async listLogs(principal, runId2) {
|
|
30667
31726
|
const rows = await this.sql`
|
|
@@ -30698,80 +31757,121 @@ class PostgresSkillsStore {
|
|
|
30698
31757
|
`;
|
|
30699
31758
|
return rows[0] ? rowToArtifact(rows[0]) : null;
|
|
30700
31759
|
}
|
|
30701
|
-
|
|
30702
|
-
|
|
30703
|
-
|
|
30704
|
-
|
|
30705
|
-
|
|
30706
|
-
|
|
30707
|
-
|
|
30708
|
-
|
|
30709
|
-
|
|
30710
|
-
|
|
30711
|
-
|
|
30712
|
-
|
|
30713
|
-
|
|
30714
|
-
|
|
30715
|
-
|
|
30716
|
-
|
|
30717
|
-
|
|
30718
|
-
|
|
30719
|
-
|
|
30720
|
-
|
|
30721
|
-
|
|
30722
|
-
|
|
30723
|
-
}
|
|
30724
|
-
|
|
30725
|
-
|
|
30726
|
-
|
|
30727
|
-
|
|
30728
|
-
|
|
30729
|
-
|
|
30730
|
-
|
|
30731
|
-
|
|
30732
|
-
|
|
30733
|
-
|
|
30734
|
-
|
|
30735
|
-
|
|
30736
|
-
|
|
30737
|
-
|
|
30738
|
-
|
|
30739
|
-
|
|
30740
|
-
|
|
30741
|
-
|
|
30742
|
-
|
|
30743
|
-
|
|
30744
|
-
|
|
30745
|
-
|
|
30746
|
-
|
|
30747
|
-
|
|
30748
|
-
|
|
30749
|
-
|
|
30750
|
-
if (value && typeof value === "object" && !Array.isArray(value))
|
|
30751
|
-
return value;
|
|
30752
|
-
if (typeof value === "string") {
|
|
30753
|
-
try {
|
|
30754
|
-
const parsed = JSON.parse(value);
|
|
30755
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
30756
|
-
} catch {}
|
|
31760
|
+
async publishSkill(input) {
|
|
31761
|
+
const orgId = input.principal.orgId;
|
|
31762
|
+
return await this.sql.begin(async (tx) => {
|
|
31763
|
+
const previousRows = await tx`SELECT bundle_sha256 FROM skills_registry WHERE org_id = ${orgId} AND slug = ${input.slug} LIMIT 1`;
|
|
31764
|
+
const previousSha = typeof previousRows[0]?.bundle_sha256 === "string" ? String(previousRows[0].bundle_sha256) : null;
|
|
31765
|
+
if (input.bundle) {
|
|
31766
|
+
await tx`
|
|
31767
|
+
INSERT INTO skills_bundles (org_id, sha256, byte_size, content_type, storage_kind, storage_key, body_blob)
|
|
31768
|
+
VALUES (${orgId}, ${input.bundle.sha256}, ${input.bundle.byteSize}, ${input.bundle.contentType}, ${input.bundle.storageKind}, ${input.bundle.storageKey ?? null}, ${input.bundle.bytes ?? null})
|
|
31769
|
+
ON CONFLICT (org_id, sha256) DO UPDATE SET
|
|
31770
|
+
byte_size = EXCLUDED.byte_size,
|
|
31771
|
+
content_type = EXCLUDED.content_type,
|
|
31772
|
+
storage_kind = EXCLUDED.storage_kind,
|
|
31773
|
+
storage_key = EXCLUDED.storage_key,
|
|
31774
|
+
body_blob = EXCLUDED.body_blob
|
|
31775
|
+
`;
|
|
31776
|
+
}
|
|
31777
|
+
const rows = await tx`
|
|
31778
|
+
INSERT INTO skills_registry (org_id, slug, display_name, description, category, tags_json, source, kind, version, skill_md,
|
|
31779
|
+
bundle_sha256, bundle_byte_size, published_by_user_id, updated_at)
|
|
31780
|
+
VALUES (${orgId}, ${input.slug}, ${input.displayName}, ${input.description}, ${input.category}, ${JSON.stringify(input.tags)}::jsonb,
|
|
31781
|
+
${input.source}, ${input.kind}, ${input.version ?? null}, ${input.skillMd ?? null},
|
|
31782
|
+
${input.bundle?.sha256 ?? null}, ${input.bundle?.byteSize ?? null}, ${input.principal.userId}, now())
|
|
31783
|
+
ON CONFLICT (org_id, slug) DO UPDATE SET
|
|
31784
|
+
display_name = EXCLUDED.display_name,
|
|
31785
|
+
description = EXCLUDED.description,
|
|
31786
|
+
category = EXCLUDED.category,
|
|
31787
|
+
tags_json = EXCLUDED.tags_json,
|
|
31788
|
+
source = EXCLUDED.source,
|
|
31789
|
+
kind = EXCLUDED.kind,
|
|
31790
|
+
version = EXCLUDED.version,
|
|
31791
|
+
skill_md = EXCLUDED.skill_md,
|
|
31792
|
+
-- COALESCE: see the SQLite twin. A bundle-less publish is a metadata update,
|
|
31793
|
+
-- not an instruction to discard the stored tarball.
|
|
31794
|
+
bundle_sha256 = COALESCE(EXCLUDED.bundle_sha256, skills_registry.bundle_sha256),
|
|
31795
|
+
bundle_byte_size = COALESCE(EXCLUDED.bundle_byte_size, skills_registry.bundle_byte_size),
|
|
31796
|
+
published_by_user_id = EXCLUDED.published_by_user_id,
|
|
31797
|
+
updated_at = EXCLUDED.updated_at
|
|
31798
|
+
RETURNING *
|
|
31799
|
+
`;
|
|
31800
|
+
if (previousSha && input.bundle && previousSha !== input.bundle.sha256) {
|
|
31801
|
+
await tx`
|
|
31802
|
+
DELETE FROM skills_bundles
|
|
31803
|
+
WHERE org_id = ${orgId} AND sha256 = ${previousSha}
|
|
31804
|
+
AND NOT EXISTS (SELECT 1 FROM skills_registry WHERE org_id = ${orgId} AND bundle_sha256 = ${previousSha})
|
|
31805
|
+
`;
|
|
31806
|
+
}
|
|
31807
|
+
return rowToSkill(rows[0]);
|
|
31808
|
+
});
|
|
30757
31809
|
}
|
|
30758
|
-
|
|
30759
|
-
}
|
|
30760
|
-
|
|
30761
|
-
|
|
30762
|
-
|
|
30763
|
-
}
|
|
30764
|
-
|
|
30765
|
-
|
|
30766
|
-
|
|
30767
|
-
|
|
30768
|
-
|
|
31810
|
+
async listSkills(principal) {
|
|
31811
|
+
const rows = await this.sql`SELECT * FROM skills_registry WHERE org_id = ${principal.orgId} ORDER BY slug ASC`;
|
|
31812
|
+
return rows.map(rowToSkill);
|
|
31813
|
+
}
|
|
31814
|
+
async getSkill(principal, slug) {
|
|
31815
|
+
const rows = await this.sql`SELECT * FROM skills_registry WHERE org_id = ${principal.orgId} AND slug = ${slug} LIMIT 1`;
|
|
31816
|
+
return rows[0] ? rowToSkill(rows[0]) : null;
|
|
31817
|
+
}
|
|
31818
|
+
async updateSkill(principal, slug, patch) {
|
|
31819
|
+
const current = await this.getSkill(principal, slug);
|
|
31820
|
+
if (!current)
|
|
31821
|
+
return null;
|
|
31822
|
+
const next = { ...current, ...patch };
|
|
31823
|
+
const rows = await this.sql`
|
|
31824
|
+
UPDATE skills_registry
|
|
31825
|
+
SET display_name = ${next.displayName}, description = ${next.description}, category = ${next.category},
|
|
31826
|
+
tags_json = ${JSON.stringify(next.tags)}::jsonb, kind = ${next.kind}, version = ${next.version ?? null},
|
|
31827
|
+
skill_md = ${next.skillMd ?? null}, updated_at = now()
|
|
31828
|
+
WHERE org_id = ${principal.orgId} AND slug = ${slug}
|
|
31829
|
+
RETURNING *
|
|
31830
|
+
`;
|
|
31831
|
+
return rows[0] ? rowToSkill(rows[0]) : null;
|
|
31832
|
+
}
|
|
31833
|
+
async deleteSkill(principal, slug) {
|
|
31834
|
+
return await this.sql.begin(async (tx) => {
|
|
31835
|
+
const rows = await tx`
|
|
31836
|
+
DELETE FROM skills_registry WHERE org_id = ${principal.orgId} AND slug = ${slug}
|
|
31837
|
+
RETURNING bundle_sha256
|
|
31838
|
+
`;
|
|
31839
|
+
if (!rows[0])
|
|
31840
|
+
return false;
|
|
31841
|
+
const sha = rows[0].bundle_sha256;
|
|
31842
|
+
if (typeof sha === "string") {
|
|
31843
|
+
await tx`
|
|
31844
|
+
DELETE FROM skills_bundles
|
|
31845
|
+
WHERE org_id = ${principal.orgId} AND sha256 = ${sha}
|
|
31846
|
+
AND NOT EXISTS (SELECT 1 FROM skills_registry WHERE org_id = ${principal.orgId} AND bundle_sha256 = ${sha})
|
|
31847
|
+
`;
|
|
31848
|
+
}
|
|
31849
|
+
return true;
|
|
31850
|
+
});
|
|
31851
|
+
}
|
|
31852
|
+
async getSkillBundle(principal, sha256) {
|
|
31853
|
+
const rows = await this.sql`SELECT * FROM skills_bundles WHERE org_id = ${principal.orgId} AND sha256 = ${sha256} LIMIT 1`;
|
|
31854
|
+
return rows[0] ? rowToSkillBundle(rows[0]) : null;
|
|
31855
|
+
}
|
|
31856
|
+
async collectOrphanBundle(orgId, sha256) {
|
|
31857
|
+
await this.sql`
|
|
31858
|
+
DELETE FROM skills_bundles
|
|
31859
|
+
WHERE org_id = ${orgId} AND sha256 = ${sha256}
|
|
31860
|
+
AND NOT EXISTS (SELECT 1 FROM skills_registry WHERE org_id = ${orgId} AND bundle_sha256 = ${sha256})
|
|
31861
|
+
`;
|
|
30769
31862
|
}
|
|
30770
31863
|
}
|
|
30771
|
-
function
|
|
30772
|
-
|
|
30773
|
-
|
|
30774
|
-
|
|
31864
|
+
function isUniqueViolation(error) {
|
|
31865
|
+
const code = error?.code;
|
|
31866
|
+
if (code === "23505" || code === 23505)
|
|
31867
|
+
return true;
|
|
31868
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
31869
|
+
return /duplicate key value violates unique constraint/i.test(message);
|
|
31870
|
+
}
|
|
31871
|
+
function connectionFailureSummary(error) {
|
|
31872
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
31873
|
+
return message.replace(/[a-z][a-z0-9+.-]*:\/\/\S*/gi, "<redacted-url>").split(`
|
|
31874
|
+
`)[0].slice(0, 200);
|
|
30775
31875
|
}
|
|
30776
31876
|
|
|
30777
31877
|
// src/server/redaction.ts
|
|
@@ -30799,16 +31899,16 @@ var DETERMINISTIC_TEXT_HANDLERS = new Set([
|
|
|
30799
31899
|
]);
|
|
30800
31900
|
async function executeRun(store, run, storage = new ArtifactStorage) {
|
|
30801
31901
|
try {
|
|
30802
|
-
await store.appendLog(run.id, run.orgId, "info", redactForClient(`starting
|
|
31902
|
+
await store.appendLog(run.id, run.orgId, "info", redactForClient(`starting run ${run.skill}`));
|
|
30803
31903
|
if (!DETERMINISTIC_TEXT_HANDLERS.has(run.skill)) {
|
|
30804
|
-
await store.appendLog(run.id, run.orgId, "warn", `${run.skill} has no
|
|
30805
|
-
return await failRun(store, run, "HANDLER_UNAVAILABLE", "This
|
|
31904
|
+
await store.appendLog(run.id, run.orgId, "warn", `${run.skill} has no provider-free handler yet`);
|
|
31905
|
+
return await failRun(store, run, "HANDLER_UNAVAILABLE", "This deployment has no safe provider-free handler for that skill yet.");
|
|
30806
31906
|
}
|
|
30807
31907
|
const text = extractText(run);
|
|
30808
31908
|
if (!text.trim()) {
|
|
30809
31909
|
return await failRun(store, run, "INVALID_INPUT", "Provide transcript text with input.transcript, input.text, --text, --source, or positional text.");
|
|
30810
31910
|
}
|
|
30811
|
-
const title = extractOption(run.args, "--title") || stringInput(run.input, "title") || "
|
|
31911
|
+
const title = extractOption(run.args, "--title") || stringInput(run.input, "title") || "Skills run";
|
|
30812
31912
|
const summary = summarize(text);
|
|
30813
31913
|
const artifacts = [
|
|
30814
31914
|
textArtifact(run, "transcript.md", `# ${title}
|
|
@@ -30822,7 +31922,7 @@ ${summary}
|
|
|
30822
31922
|
textArtifact(run, "show-notes.md", `# Show Notes
|
|
30823
31923
|
|
|
30824
31924
|
- ${summary}
|
|
30825
|
-
- Generated by open-skills
|
|
31925
|
+
- Generated by the open-skills deterministic worker.
|
|
30826
31926
|
`),
|
|
30827
31927
|
textArtifact(run, "clips.csv", `start,end,title,summary
|
|
30828
31928
|
00:00,00:30,"Opening","${csv(summary)}"
|
|
@@ -30907,8 +32007,831 @@ function csv(value) {
|
|
|
30907
32007
|
return value.replace(/"/g, '""');
|
|
30908
32008
|
}
|
|
30909
32009
|
|
|
32010
|
+
// src/lib/registry-data/development-tools.ts
|
|
32011
|
+
var DEVELOPMENT_TOOLS_SKILLS = [
|
|
32012
|
+
{
|
|
32013
|
+
name: "repo-onboarding-report",
|
|
32014
|
+
displayName: "Repo Onboarding Report",
|
|
32015
|
+
description: "Generate repository onboarding packages with architecture maps, setup guides, risk registers, and first-week plans",
|
|
32016
|
+
category: "Development Tools",
|
|
32017
|
+
kind: "instruction",
|
|
32018
|
+
tags: ["repository", "onboarding", "architecture", "developer-tools"]
|
|
32019
|
+
},
|
|
32020
|
+
{
|
|
32021
|
+
name: "security-audit-report",
|
|
32022
|
+
displayName: "Security Audit Report",
|
|
32023
|
+
description: "Generate application security hardening reports covering auth, secrets, headers, webhooks, RLS, permissions, dependencies, and prioritized fixes",
|
|
32024
|
+
category: "Development Tools",
|
|
32025
|
+
kind: "instruction",
|
|
32026
|
+
tags: ["security", "audit", "hardening", "rls", "webhooks"]
|
|
32027
|
+
},
|
|
32028
|
+
{
|
|
32029
|
+
name: "performance-audit-report",
|
|
32030
|
+
displayName: "Performance Audit Report",
|
|
32031
|
+
description: "Generate performance audit reports with metrics, findings, budgets, remediation plans, and manifest artifacts",
|
|
32032
|
+
category: "Development Tools",
|
|
32033
|
+
kind: "instruction",
|
|
32034
|
+
tags: ["performance", "audit", "latency", "budget", "web"]
|
|
32035
|
+
},
|
|
32036
|
+
{
|
|
32037
|
+
name: "migration-plan-pack",
|
|
32038
|
+
displayName: "Migration Plan Pack",
|
|
32039
|
+
description: "Generate migration plans for frameworks, libraries, databases, infrastructure, and architecture upgrades with risk matrix, checklist, rollout, and test strategy artifacts",
|
|
32040
|
+
category: "Development Tools",
|
|
32041
|
+
kind: "instruction",
|
|
32042
|
+
tags: ["migration", "upgrade", "planning", "frameworks", "databases"]
|
|
32043
|
+
},
|
|
32044
|
+
{
|
|
32045
|
+
name: "test-suite-generator",
|
|
32046
|
+
displayName: "Test Suite Generator",
|
|
32047
|
+
description: "Generate runnable API, unit, and browser test suite packages with coverage notes",
|
|
32048
|
+
category: "Development Tools",
|
|
32049
|
+
kind: "instruction",
|
|
32050
|
+
tags: ["testing", "qa", "api-tests", "browser-tests", "coverage"]
|
|
32051
|
+
},
|
|
32052
|
+
{
|
|
32053
|
+
name: "api-test-suite",
|
|
32054
|
+
displayName: "API Test Suite",
|
|
32055
|
+
description: "Generate and run API test suites with comprehensive endpoint coverage",
|
|
32056
|
+
category: "Development Tools",
|
|
32057
|
+
tags: ["api", "testing", "automation", "qa"]
|
|
32058
|
+
},
|
|
32059
|
+
{
|
|
32060
|
+
name: "api-docs-portal",
|
|
32061
|
+
displayName: "API Docs Portal",
|
|
32062
|
+
description: "Generate static API documentation portals from OpenAPI specs, route lists, and endpoint examples",
|
|
32063
|
+
category: "Development Tools",
|
|
32064
|
+
tags: ["api", "documentation", "openapi", "portal"]
|
|
32065
|
+
},
|
|
32066
|
+
{
|
|
32067
|
+
name: "codefix",
|
|
32068
|
+
displayName: "Code Fix",
|
|
32069
|
+
description: "Code quality CLI for auto-linting, formatting, fixing, and style enforcement",
|
|
32070
|
+
category: "Development Tools",
|
|
32071
|
+
tags: ["code", "linting", "formatting", "quality"]
|
|
32072
|
+
},
|
|
32073
|
+
{
|
|
32074
|
+
name: "commitpush",
|
|
32075
|
+
displayName: "Commit Push",
|
|
32076
|
+
description: "Create logical commits from repo changes and push directly to the main branch",
|
|
32077
|
+
category: "Development Tools",
|
|
32078
|
+
tags: ["git", "commit", "push", "automation"]
|
|
32079
|
+
},
|
|
32080
|
+
{
|
|
32081
|
+
name: "commitpushpr",
|
|
32082
|
+
displayName: "Commit Push PR",
|
|
32083
|
+
description: "Create logical commits, push a feature branch, and open a GitHub pull request",
|
|
32084
|
+
category: "Development Tools",
|
|
32085
|
+
dependencies: ["commitpush"],
|
|
32086
|
+
tags: ["git", "commit", "pull-request", "github", "automation"]
|
|
32087
|
+
},
|
|
32088
|
+
{
|
|
32089
|
+
name: "database-explorer",
|
|
32090
|
+
displayName: "Database Explorer",
|
|
32091
|
+
description: "Explore and query databases with an interactive interface",
|
|
32092
|
+
category: "Development Tools",
|
|
32093
|
+
tags: ["database", "explorer", "sql", "query"]
|
|
32094
|
+
},
|
|
32095
|
+
{
|
|
32096
|
+
name: "diff-viewer",
|
|
32097
|
+
displayName: "Diff Viewer",
|
|
32098
|
+
description: "View and analyze file differences with visual diff representation",
|
|
32099
|
+
category: "Development Tools",
|
|
32100
|
+
tags: ["diff", "comparison", "files", "code-review"]
|
|
32101
|
+
},
|
|
32102
|
+
{
|
|
32103
|
+
name: "generate-api-client",
|
|
32104
|
+
displayName: "Generate API Client",
|
|
32105
|
+
description: "Generate API client libraries from OpenAPI specs and documentation",
|
|
32106
|
+
category: "Development Tools",
|
|
32107
|
+
tags: ["api", "client", "code-generation", "openapi"]
|
|
32108
|
+
},
|
|
32109
|
+
{
|
|
32110
|
+
name: "generate-dockerfile",
|
|
32111
|
+
displayName: "Generate Dockerfile",
|
|
32112
|
+
description: "Generate optimized Dockerfiles for containerized applications",
|
|
32113
|
+
category: "Development Tools",
|
|
32114
|
+
tags: ["docker", "dockerfile", "containers", "devops"]
|
|
32115
|
+
},
|
|
32116
|
+
{
|
|
32117
|
+
name: "generate-env",
|
|
32118
|
+
displayName: "Generate Env",
|
|
32119
|
+
description: "Generate environment variable files from templates and configurations",
|
|
32120
|
+
category: "Development Tools",
|
|
32121
|
+
tags: ["env", "environment", "configuration", "dotenv"]
|
|
32122
|
+
},
|
|
32123
|
+
{
|
|
32124
|
+
name: "generate-sitemap",
|
|
32125
|
+
displayName: "Generate Sitemap",
|
|
32126
|
+
description: "Generate XML sitemaps for websites and web applications",
|
|
32127
|
+
category: "Development Tools",
|
|
32128
|
+
tags: ["sitemap", "seo", "xml", "web"]
|
|
32129
|
+
},
|
|
32130
|
+
{
|
|
32131
|
+
name: "hook",
|
|
32132
|
+
displayName: "Hook",
|
|
32133
|
+
description: "Claude Code hook creation skill - generates standardized hook scaffolds",
|
|
32134
|
+
category: "Development Tools",
|
|
32135
|
+
tags: ["hooks", "scaffold", "claude-code", "automation"]
|
|
32136
|
+
},
|
|
32137
|
+
{
|
|
32138
|
+
name: "http-server",
|
|
32139
|
+
displayName: "HTTP Server",
|
|
32140
|
+
description: "Spin up local HTTP servers for development and testing",
|
|
32141
|
+
category: "Development Tools",
|
|
32142
|
+
tags: ["http", "server", "development", "local"]
|
|
32143
|
+
},
|
|
32144
|
+
{
|
|
32145
|
+
name: "lorem-generator",
|
|
32146
|
+
displayName: "Lorem Generator",
|
|
32147
|
+
description: "Generate placeholder text in various styles and lengths",
|
|
32148
|
+
category: "Development Tools",
|
|
32149
|
+
tags: ["lorem", "placeholder", "text", "mockup"]
|
|
32150
|
+
},
|
|
32151
|
+
{
|
|
32152
|
+
name: "managemcp",
|
|
32153
|
+
displayName: "Manage MCP",
|
|
32154
|
+
description: "Manage MCP servers with install, configure, and lifecycle operations",
|
|
32155
|
+
category: "Development Tools",
|
|
32156
|
+
tags: ["mcp", "management", "servers", "configuration"]
|
|
32157
|
+
},
|
|
32158
|
+
{
|
|
32159
|
+
name: "markdown-validator",
|
|
32160
|
+
displayName: "Markdown Validator",
|
|
32161
|
+
description: "Validate markdown files for syntax, links, and formatting issues",
|
|
32162
|
+
category: "Development Tools",
|
|
32163
|
+
tags: ["markdown", "validation", "linting", "formatting"]
|
|
32164
|
+
},
|
|
32165
|
+
{
|
|
32166
|
+
name: "monitor",
|
|
32167
|
+
displayName: "Monitor",
|
|
32168
|
+
description: "Operate the open-monitor MCP for machine health, processes, cron jobs, and cleanup workflows",
|
|
32169
|
+
category: "Development Tools",
|
|
32170
|
+
tags: ["monitoring", "mcp", "processes", "operations"]
|
|
32171
|
+
},
|
|
32172
|
+
{
|
|
32173
|
+
name: "regex-tester",
|
|
32174
|
+
displayName: "Regex Tester",
|
|
32175
|
+
description: "Test and validate regular expressions with sample inputs",
|
|
32176
|
+
category: "Development Tools",
|
|
32177
|
+
tags: ["regex", "testing", "validation", "patterns"]
|
|
32178
|
+
},
|
|
32179
|
+
{
|
|
32180
|
+
name: "scancommitpr",
|
|
32181
|
+
displayName: "Scan Commit PR",
|
|
32182
|
+
description: "Scan repo changes, group into logical commits, push, and optionally create a PR",
|
|
32183
|
+
category: "Development Tools",
|
|
32184
|
+
dependencies: ["scancommitpush"],
|
|
32185
|
+
tags: ["git", "commit", "push", "pull-request", "automation"]
|
|
32186
|
+
},
|
|
32187
|
+
{
|
|
32188
|
+
name: "scancommitpush",
|
|
32189
|
+
displayName: "Scan Commit Push",
|
|
32190
|
+
description: "Scan repo changes, group into logical commits with conventional messages, and push to GitHub",
|
|
32191
|
+
category: "Development Tools",
|
|
32192
|
+
tags: ["git", "commit", "push", "automation"]
|
|
32193
|
+
},
|
|
32194
|
+
{
|
|
32195
|
+
name: "security-audit",
|
|
32196
|
+
displayName: "Security Audit",
|
|
32197
|
+
description: "Perform security audits on codebases and infrastructure configurations",
|
|
32198
|
+
category: "Development Tools",
|
|
32199
|
+
tags: ["security", "audit", "vulnerabilities", "scanning"]
|
|
32200
|
+
},
|
|
32201
|
+
{
|
|
32202
|
+
name: "tmux-session",
|
|
32203
|
+
displayName: "Tmux Session",
|
|
32204
|
+
description: "Create and manage grouped tmux sessions with workspace-aware naming and window layout guidance",
|
|
32205
|
+
category: "Development Tools",
|
|
32206
|
+
tags: ["tmux", "terminal", "sessions", "workspace"]
|
|
32207
|
+
},
|
|
32208
|
+
{
|
|
32209
|
+
name: "validate-config",
|
|
32210
|
+
displayName: "Validate Config",
|
|
32211
|
+
description: "Validate configuration files for syntax and schema compliance",
|
|
32212
|
+
category: "Development Tools",
|
|
32213
|
+
tags: ["config", "validation", "schema", "linting"]
|
|
32214
|
+
}
|
|
32215
|
+
];
|
|
32216
|
+
|
|
32217
|
+
// src/lib/registry-data/business-marketing.ts
|
|
32218
|
+
var BUSINESS_MARKETING_SKILLS = [
|
|
32219
|
+
{
|
|
32220
|
+
name: "customer-feedback-report",
|
|
32221
|
+
displayName: "Customer Feedback Report",
|
|
32222
|
+
description: "Generate customer feedback reports with clusters, sentiment, root causes, roadmap recommendations, evidence, and PDF/Markdown artifacts",
|
|
32223
|
+
category: "Business & Marketing",
|
|
32224
|
+
kind: "instruction",
|
|
32225
|
+
tags: ["feedback", "customer", "sentiment", "roadmap", "report"]
|
|
32226
|
+
},
|
|
32227
|
+
{
|
|
32228
|
+
name: "pitch-deck",
|
|
32229
|
+
displayName: "Pitch Deck",
|
|
32230
|
+
description: "Generate investor and sales deck packages with slides, speaker notes, design direction, PDF, and PPTX artifacts",
|
|
32231
|
+
category: "Business & Marketing",
|
|
32232
|
+
kind: "instruction",
|
|
32233
|
+
dependencies: ["market-research-report"],
|
|
32234
|
+
tags: ["deck", "presentation", "investor", "sales", "pptx"]
|
|
32235
|
+
},
|
|
32236
|
+
{
|
|
32237
|
+
name: "proposal-pack",
|
|
32238
|
+
displayName: "Proposal Pack",
|
|
32239
|
+
description: "Generate client proposal packages with proposal, statement of work, pricing, timeline, assumptions, cover email, and PDF/Markdown artifacts",
|
|
32240
|
+
category: "Business & Marketing",
|
|
32241
|
+
kind: "instruction",
|
|
32242
|
+
tags: ["proposal", "sow", "sales", "pricing", "timeline"]
|
|
32243
|
+
},
|
|
32244
|
+
{
|
|
32245
|
+
name: "seo-content-pack",
|
|
32246
|
+
displayName: "SEO Content Pack",
|
|
32247
|
+
description: "Generate SEO content packages with topic clusters, articles, metadata, internal links, FAQs, and publishing cadence",
|
|
32248
|
+
category: "Business & Marketing",
|
|
32249
|
+
kind: "instruction",
|
|
32250
|
+
tags: ["seo", "content", "articles", "metadata"]
|
|
32251
|
+
},
|
|
32252
|
+
{
|
|
32253
|
+
name: "landing-page-pack",
|
|
32254
|
+
displayName: "Landing Page Pack",
|
|
32255
|
+
description: "Generate landing page packages with conversion copy, wireframes, CTA maps, experiments, preview HTML, and implementation notes",
|
|
32256
|
+
category: "Business & Marketing",
|
|
32257
|
+
kind: "instruction",
|
|
32258
|
+
tags: ["landing-page", "sales", "copywriting", "conversion"]
|
|
32259
|
+
},
|
|
32260
|
+
{
|
|
32261
|
+
name: "ad-creative-pack",
|
|
32262
|
+
displayName: "Ad Creative Pack",
|
|
32263
|
+
description: "Generate paid ad packages with platform copy, creative concepts, image prompts, audience angles, and test matrices",
|
|
32264
|
+
category: "Business & Marketing",
|
|
32265
|
+
kind: "instruction",
|
|
32266
|
+
tags: ["ads", "creative", "marketing", "copywriting"]
|
|
32267
|
+
},
|
|
32268
|
+
{
|
|
32269
|
+
name: "email-sequence",
|
|
32270
|
+
displayName: "Email Sequence",
|
|
32271
|
+
description: "Generate email campaign packages with subject lines, preview text, body copy, segmentation notes, CTA variants, HTML emails, and send plans",
|
|
32272
|
+
category: "Business & Marketing",
|
|
32273
|
+
kind: "instruction",
|
|
32274
|
+
tags: ["email", "marketing", "campaign", "copywriting"]
|
|
32275
|
+
},
|
|
32276
|
+
{
|
|
32277
|
+
name: "social-content-calendar",
|
|
32278
|
+
displayName: "Social Content Calendar",
|
|
32279
|
+
description: "Generate social content calendars with daily posts, channel strategy, asset briefs, hooks, publishing schedules, and repurposing maps",
|
|
32280
|
+
category: "Business & Marketing",
|
|
32281
|
+
kind: "instruction",
|
|
32282
|
+
tags: ["social", "content", "calendar", "marketing"]
|
|
32283
|
+
},
|
|
32284
|
+
{
|
|
32285
|
+
name: "one-page-website",
|
|
32286
|
+
displayName: "One Page Website",
|
|
32287
|
+
description: "Generate static one-page website bundles with HTML, CSS, JavaScript, copy, section maps, deploy notes, and manifest",
|
|
32288
|
+
category: "Business & Marketing",
|
|
32289
|
+
tags: ["website", "landing-page", "static-site", "html"]
|
|
32290
|
+
}
|
|
32291
|
+
];
|
|
32292
|
+
|
|
32293
|
+
// src/lib/registry-data/productivity-organization.ts
|
|
32294
|
+
var PRODUCTIVITY_ORGANIZATION_SKILLS = [
|
|
32295
|
+
{
|
|
32296
|
+
name: "meeting-pack",
|
|
32297
|
+
displayName: "Meeting Pack",
|
|
32298
|
+
description: "Generate meeting artifact packages with summaries, decisions, action items, follow-up email, timeline, project export, and manifest",
|
|
32299
|
+
category: "Productivity & Organization",
|
|
32300
|
+
kind: "instruction",
|
|
32301
|
+
tags: ["meeting", "summary", "action-items", "decisions"]
|
|
32302
|
+
},
|
|
32303
|
+
{
|
|
32304
|
+
name: "file-organizer",
|
|
32305
|
+
displayName: "File Organizer",
|
|
32306
|
+
description: "Organize files into structured directories based on type, date, or content",
|
|
32307
|
+
category: "Productivity & Organization",
|
|
32308
|
+
tags: ["files", "organization", "sorting", "cleanup"]
|
|
32309
|
+
},
|
|
32310
|
+
{
|
|
32311
|
+
name: "folder-tree",
|
|
32312
|
+
displayName: "Folder Tree",
|
|
32313
|
+
description: "Generate and display folder tree structures for documentation",
|
|
32314
|
+
category: "Productivity & Organization",
|
|
32315
|
+
tags: ["folder", "tree", "structure", "visualization"]
|
|
32316
|
+
},
|
|
32317
|
+
{
|
|
32318
|
+
name: "form-filler",
|
|
32319
|
+
displayName: "Form Filler",
|
|
32320
|
+
description: "Automatically fill out web forms and document templates",
|
|
32321
|
+
category: "Productivity & Organization",
|
|
32322
|
+
tags: ["forms", "automation", "filling", "data-entry"]
|
|
32323
|
+
},
|
|
32324
|
+
{
|
|
32325
|
+
name: "merge-pdfs",
|
|
32326
|
+
displayName: "Merge PDFs",
|
|
32327
|
+
description: "Merge multiple PDF files into a single document",
|
|
32328
|
+
category: "Productivity & Organization",
|
|
32329
|
+
tags: ["pdf", "merge", "documents", "combining"]
|
|
32330
|
+
},
|
|
32331
|
+
{
|
|
32332
|
+
name: "split-pdf",
|
|
32333
|
+
displayName: "Split PDF",
|
|
32334
|
+
description: "Split PDF documents into separate pages or sections",
|
|
32335
|
+
category: "Productivity & Organization",
|
|
32336
|
+
tags: ["pdf", "split", "documents", "pages"]
|
|
32337
|
+
}
|
|
32338
|
+
];
|
|
32339
|
+
|
|
32340
|
+
// src/lib/registry-data/project-management.ts
|
|
32341
|
+
var PROJECT_MANAGEMENT_SKILLS = [
|
|
32342
|
+
{
|
|
32343
|
+
name: "businessactivity",
|
|
32344
|
+
displayName: "Business Activity",
|
|
32345
|
+
description: "Business activity, workflow, and ownership management service",
|
|
32346
|
+
category: "Project Management",
|
|
32347
|
+
tags: ["business", "workflow", "activities", "management"]
|
|
32348
|
+
},
|
|
32349
|
+
{
|
|
32350
|
+
name: "implementation",
|
|
32351
|
+
displayName: "Implementation",
|
|
32352
|
+
description: "Create .implementation scaffold for project development tracking",
|
|
32353
|
+
category: "Project Management",
|
|
32354
|
+
tags: ["implementation", "tracking", "scaffold", "project"]
|
|
32355
|
+
},
|
|
32356
|
+
{
|
|
32357
|
+
name: "implementation-plan",
|
|
32358
|
+
displayName: "Implementation Plan",
|
|
32359
|
+
description: "Generate detailed implementation plans with phases and milestones",
|
|
32360
|
+
category: "Project Management",
|
|
32361
|
+
tags: ["implementation", "planning", "milestones", "phases"]
|
|
32362
|
+
},
|
|
32363
|
+
{
|
|
32364
|
+
name: "implementation-todo",
|
|
32365
|
+
displayName: "Implementation Todo",
|
|
32366
|
+
description: "Manage implementation task lists and todo items",
|
|
32367
|
+
category: "Project Management",
|
|
32368
|
+
tags: ["implementation", "todo", "tasks", "tracking"]
|
|
32369
|
+
},
|
|
32370
|
+
{
|
|
32371
|
+
name: "todos-plan",
|
|
32372
|
+
displayName: "Todos Plan",
|
|
32373
|
+
description: "Author, sync, route, and verify Todos plans using Todos CLI plan IDs as source of truth",
|
|
32374
|
+
category: "Project Management",
|
|
32375
|
+
tags: ["todos", "plans", "tasks", "verification", "workflow"]
|
|
32376
|
+
}
|
|
32377
|
+
];
|
|
32378
|
+
|
|
32379
|
+
// src/lib/registry-data/content-generation.ts
|
|
32380
|
+
var CONTENT_GENERATION_SKILLS = [
|
|
32381
|
+
{
|
|
32382
|
+
name: "pdf-generate",
|
|
32383
|
+
displayName: "PDF Generate",
|
|
32384
|
+
description: "Generate PDF documents with rich formatting and layouts",
|
|
32385
|
+
category: "Content Generation",
|
|
32386
|
+
tags: ["pdf", "document", "generation", "formatting"]
|
|
32387
|
+
},
|
|
32388
|
+
{
|
|
32389
|
+
name: "slide-deck-generator",
|
|
32390
|
+
displayName: "Slide Deck Generator",
|
|
32391
|
+
description: "Generate slide decks from briefs, docs, or outlines with PDF, PPTX, speaker notes, and structured slide metadata",
|
|
32392
|
+
category: "Content Generation",
|
|
32393
|
+
tags: ["presentation", "slides", "deck", "documents"]
|
|
32394
|
+
},
|
|
32395
|
+
{
|
|
32396
|
+
name: "generate-qrcode",
|
|
32397
|
+
displayName: "Generate QR Code",
|
|
32398
|
+
description: "Generate QR codes with custom styling and embedded data",
|
|
32399
|
+
category: "Content Generation",
|
|
32400
|
+
tags: ["qrcode", "generation", "encoding", "visual"]
|
|
32401
|
+
},
|
|
32402
|
+
{
|
|
32403
|
+
name: "generate-resume",
|
|
32404
|
+
displayName: "Generate Resume",
|
|
32405
|
+
description: "Generate professional resumes with formatting and content optimization",
|
|
32406
|
+
category: "Content Generation",
|
|
32407
|
+
tags: ["resume", "cv", "career", "generation"]
|
|
32408
|
+
}
|
|
32409
|
+
];
|
|
32410
|
+
|
|
32411
|
+
// src/lib/registry-data/finance-compliance.ts
|
|
32412
|
+
var FINANCE_COMPLIANCE_SKILLS = [
|
|
32413
|
+
{
|
|
32414
|
+
name: "contract-review-report",
|
|
32415
|
+
displayName: "Contract Review Report",
|
|
32416
|
+
description: "Generate contract review reports with risk register, clause summary, redline suggestions, negotiation email, and manifest artifacts",
|
|
32417
|
+
category: "Finance & Compliance",
|
|
32418
|
+
kind: "instruction",
|
|
32419
|
+
tags: ["contract", "legal", "review", "risk"]
|
|
32420
|
+
},
|
|
32421
|
+
{
|
|
32422
|
+
name: "invoice",
|
|
32423
|
+
displayName: "Invoice",
|
|
32424
|
+
description: "Generate professional invoices with company management and PDF export",
|
|
32425
|
+
category: "Finance & Compliance",
|
|
32426
|
+
tags: ["invoice", "billing", "pdf", "finance"]
|
|
32427
|
+
},
|
|
32428
|
+
{
|
|
32429
|
+
name: "invoice-reconciliation",
|
|
32430
|
+
displayName: "Invoice Reconciliation",
|
|
32431
|
+
description: "Generate invoice reconciliation reports with matched payments, discrepancies, anomaly notes, summaries, and manifest artifacts",
|
|
32432
|
+
category: "Finance & Compliance",
|
|
32433
|
+
tags: ["invoice", "payments", "reconciliation", "finance"]
|
|
32434
|
+
}
|
|
32435
|
+
];
|
|
32436
|
+
|
|
32437
|
+
// src/lib/registry-data/data-analysis.ts
|
|
32438
|
+
var DATA_ANALYSIS_SKILLS = [
|
|
32439
|
+
{
|
|
32440
|
+
name: "analyze-data",
|
|
32441
|
+
displayName: "Analyze Data",
|
|
32442
|
+
description: "Data science insights for CSV and JSON datasets with statistical analysis",
|
|
32443
|
+
category: "Data & Analysis",
|
|
32444
|
+
tags: ["data", "analysis", "csv", "json", "statistics"]
|
|
32445
|
+
},
|
|
32446
|
+
{
|
|
32447
|
+
name: "dashboard-builder",
|
|
32448
|
+
displayName: "Dashboard Builder",
|
|
32449
|
+
description: "Build data dashboards with charts, metrics, and visualizations",
|
|
32450
|
+
category: "Data & Analysis",
|
|
32451
|
+
tags: ["dashboard", "visualization", "charts", "metrics"]
|
|
32452
|
+
},
|
|
32453
|
+
{
|
|
32454
|
+
name: "data-anonymizer",
|
|
32455
|
+
displayName: "Data Anonymizer",
|
|
32456
|
+
description: "Anonymize sensitive data in datasets for privacy compliance",
|
|
32457
|
+
category: "Data & Analysis",
|
|
32458
|
+
tags: ["anonymization", "privacy", "data", "compliance"]
|
|
32459
|
+
},
|
|
32460
|
+
{
|
|
32461
|
+
name: "generate-chart",
|
|
32462
|
+
displayName: "Generate Chart",
|
|
32463
|
+
description: "Generate data charts and visualizations from datasets",
|
|
32464
|
+
category: "Data & Analysis",
|
|
32465
|
+
tags: ["charts", "visualization", "data", "graphs"]
|
|
32466
|
+
},
|
|
32467
|
+
{
|
|
32468
|
+
name: "read-csv",
|
|
32469
|
+
displayName: "Read CSV",
|
|
32470
|
+
description: "Parse CSV files into structured JSON with delimiter and encoding detection",
|
|
32471
|
+
category: "Data & Analysis",
|
|
32472
|
+
tags: ["csv", "parsing", "tabular", "data"]
|
|
32473
|
+
},
|
|
32474
|
+
{
|
|
32475
|
+
name: "read-excel",
|
|
32476
|
+
displayName: "Read Excel",
|
|
32477
|
+
description: "Parse XLS and XLSX workbooks into structured JSON with sheet and formatted cell metadata",
|
|
32478
|
+
category: "Data & Analysis",
|
|
32479
|
+
tags: ["excel", "spreadsheet", "xlsx", "data"]
|
|
32480
|
+
},
|
|
32481
|
+
{
|
|
32482
|
+
name: "pdf-to-markdown",
|
|
32483
|
+
displayName: "PDF to Markdown",
|
|
32484
|
+
description: "Convert PDFs into clean markdown with remote extraction and structure cleanup",
|
|
32485
|
+
category: "Data & Analysis",
|
|
32486
|
+
tags: ["pdf", "markdown", "conversion"]
|
|
32487
|
+
},
|
|
32488
|
+
{
|
|
32489
|
+
name: "pdf-to-dataset",
|
|
32490
|
+
displayName: "PDF to Dataset",
|
|
32491
|
+
description: "Extract PDF tables, forms, invoices, and semi-structured content into CSV and JSON datasets",
|
|
32492
|
+
category: "Data & Analysis",
|
|
32493
|
+
tags: ["pdf", "dataset", "csv", "json", "extraction"]
|
|
32494
|
+
},
|
|
32495
|
+
{
|
|
32496
|
+
name: "doc-read",
|
|
32497
|
+
displayName: "Doc Read",
|
|
32498
|
+
description: "Read and extract text from DOCX files with section parsing and metadata extraction",
|
|
32499
|
+
category: "Data & Analysis",
|
|
32500
|
+
tags: ["docx", "reader", "extraction", "word"]
|
|
32501
|
+
}
|
|
32502
|
+
];
|
|
32503
|
+
|
|
32504
|
+
// src/lib/registry-data/media-processing.ts
|
|
32505
|
+
var MEDIA_PROCESSING_SKILLS = [
|
|
32506
|
+
{
|
|
32507
|
+
name: "video-highlight-pack",
|
|
32508
|
+
displayName: "Video Highlight Pack",
|
|
32509
|
+
description: "Generate video highlight packages with clip plans, captions, thumbnail briefs, chapter markers, social posts, and edit decisions",
|
|
32510
|
+
category: "Media Processing",
|
|
32511
|
+
kind: "instruction",
|
|
32512
|
+
tags: ["video", "highlights", "clips", "captions"]
|
|
32513
|
+
},
|
|
32514
|
+
{
|
|
32515
|
+
name: "compress-video",
|
|
32516
|
+
displayName: "Compress Video",
|
|
32517
|
+
description: "Compress video files while preserving visual quality using ffmpeg",
|
|
32518
|
+
category: "Media Processing",
|
|
32519
|
+
tags: ["video", "compression", "ffmpeg", "optimization"]
|
|
32520
|
+
},
|
|
32521
|
+
{
|
|
32522
|
+
name: "audio-extract",
|
|
32523
|
+
displayName: "Audio Extract",
|
|
32524
|
+
description: "Extract audio tracks from video files with multiple format support",
|
|
32525
|
+
category: "Media Processing",
|
|
32526
|
+
tags: ["audio", "extraction", "video", "conversion"]
|
|
32527
|
+
},
|
|
32528
|
+
{
|
|
32529
|
+
name: "extract-frames",
|
|
32530
|
+
displayName: "Extract Frames",
|
|
32531
|
+
description: "Extract frames from video files at specified intervals or timestamps",
|
|
32532
|
+
category: "Media Processing",
|
|
32533
|
+
tags: ["frames", "video", "extraction", "images"]
|
|
32534
|
+
},
|
|
32535
|
+
{
|
|
32536
|
+
name: "gif-maker",
|
|
32537
|
+
displayName: "GIF Maker",
|
|
32538
|
+
description: "Create animated GIFs from images, videos, or screen recordings",
|
|
32539
|
+
category: "Media Processing",
|
|
32540
|
+
tags: ["gif", "animation", "images", "video"]
|
|
32541
|
+
},
|
|
32542
|
+
{
|
|
32543
|
+
name: "video-downloader",
|
|
32544
|
+
displayName: "Video Downloader",
|
|
32545
|
+
description: "Download videos from various online platforms and services",
|
|
32546
|
+
category: "Media Processing",
|
|
32547
|
+
tags: ["video", "download", "platforms", "media"]
|
|
32548
|
+
},
|
|
32549
|
+
{
|
|
32550
|
+
name: "watermark",
|
|
32551
|
+
displayName: "Watermark",
|
|
32552
|
+
description: "Add watermarks to images and documents for copyright protection",
|
|
32553
|
+
category: "Media Processing",
|
|
32554
|
+
tags: ["watermark", "protection", "copyright", "images"]
|
|
32555
|
+
}
|
|
32556
|
+
];
|
|
32557
|
+
|
|
32558
|
+
// src/lib/registry-data/design-branding.ts
|
|
32559
|
+
var DESIGN_BRANDING_SKILLS = [
|
|
32560
|
+
{
|
|
32561
|
+
name: "brand-kit",
|
|
32562
|
+
displayName: "Brand Kit",
|
|
32563
|
+
description: "Generate brand kits with logo usage, palette, typography, brand voice, sample applications, Markdown guide, PDF guide, and SVG assets",
|
|
32564
|
+
category: "Design & Branding",
|
|
32565
|
+
kind: "instruction",
|
|
32566
|
+
tags: ["brand", "design", "palette", "typography"]
|
|
32567
|
+
},
|
|
32568
|
+
{
|
|
32569
|
+
name: "brand-assets",
|
|
32570
|
+
displayName: "Brand Assets",
|
|
32571
|
+
description: "Fetch official brand assets from a website or brand name with logos, PNG sizes, palette, typography, source metadata, and manifests",
|
|
32572
|
+
category: "Design & Branding",
|
|
32573
|
+
tags: ["brand", "logo", "assets", "palette", "typography"]
|
|
32574
|
+
},
|
|
32575
|
+
{
|
|
32576
|
+
name: "logo-design",
|
|
32577
|
+
displayName: "Logo Design",
|
|
32578
|
+
description: "Generate multi-variant logo packages with transparent PNGs, vector-style SVGs, usage notes, and manifests",
|
|
32579
|
+
category: "Design & Branding",
|
|
32580
|
+
tags: ["logo", "design", "branding", "identity"]
|
|
32581
|
+
},
|
|
32582
|
+
{
|
|
32583
|
+
name: "generate-favicon",
|
|
32584
|
+
displayName: "Generate Favicon",
|
|
32585
|
+
description: "Generate favicons in multiple sizes and formats for websites",
|
|
32586
|
+
category: "Design & Branding",
|
|
32587
|
+
tags: ["favicon", "icon", "design", "web"]
|
|
32588
|
+
},
|
|
32589
|
+
{
|
|
32590
|
+
name: "product-mockup",
|
|
32591
|
+
displayName: "Product Mockup",
|
|
32592
|
+
description: "Generate product mockup packages with visual variants, prompts, usage notes, and asset metadata",
|
|
32593
|
+
category: "Design & Branding",
|
|
32594
|
+
tags: ["product", "mockup", "visualization", "marketing"]
|
|
32595
|
+
},
|
|
32596
|
+
{
|
|
32597
|
+
name: "siteanalyze",
|
|
32598
|
+
displayName: "Site Analyze",
|
|
32599
|
+
description: "Analyze any website's design system \u2014 detects shadcn/ui, Tailwind, extracts colors, typography, and components via Playwright + Claude Vision.",
|
|
32600
|
+
category: "Design & Branding",
|
|
32601
|
+
tags: ["design", "shadcn", "tailwind", "colors", "typography", "playwright", "analysis", "open-styles"]
|
|
32602
|
+
}
|
|
32603
|
+
];
|
|
32604
|
+
|
|
32605
|
+
// src/lib/registry-data/web-browser.ts
|
|
32606
|
+
var WEB_BROWSER_SKILLS = [
|
|
32607
|
+
{
|
|
32608
|
+
name: "domainpurchase",
|
|
32609
|
+
displayName: "Domain Purchase",
|
|
32610
|
+
description: "Purchase and manage domains via registrar connectors",
|
|
32611
|
+
category: "Web & Browser",
|
|
32612
|
+
tags: ["domain", "purchase", "registrar", "management"]
|
|
32613
|
+
}
|
|
32614
|
+
];
|
|
32615
|
+
|
|
32616
|
+
// src/lib/registry-data/research-writing.ts
|
|
32617
|
+
var RESEARCH_WRITING_SKILLS = [
|
|
32618
|
+
{
|
|
32619
|
+
name: "blog-article",
|
|
32620
|
+
displayName: "Blog Article",
|
|
32621
|
+
description: "Create SEO-optimized blog article artifact packages",
|
|
32622
|
+
category: "Research & Writing",
|
|
32623
|
+
kind: "instruction",
|
|
32624
|
+
tags: ["blog", "article", "writing", "seo"]
|
|
32625
|
+
},
|
|
32626
|
+
{
|
|
32627
|
+
name: "market-research-report",
|
|
32628
|
+
displayName: "Market Research Report",
|
|
32629
|
+
description: "Generate market research packages with competitor tables, positioning, pricing notes, source notes, and PDF/Markdown artifacts",
|
|
32630
|
+
category: "Research & Writing",
|
|
32631
|
+
kind: "instruction",
|
|
32632
|
+
tags: ["market-research", "competitors", "positioning", "pricing", "report"]
|
|
32633
|
+
}
|
|
32634
|
+
];
|
|
32635
|
+
|
|
32636
|
+
// src/lib/registry-data/science-academic.ts
|
|
32637
|
+
var SCIENCE_ACADEMIC_SKILLS = [
|
|
32638
|
+
{
|
|
32639
|
+
name: "bio-sequence-tool",
|
|
32640
|
+
displayName: "Bio Sequence Tool",
|
|
32641
|
+
description: "Analyze and manipulate biological sequences including DNA, RNA, and protein data",
|
|
32642
|
+
category: "Science & Academic",
|
|
32643
|
+
tags: ["biology", "dna", "sequence", "bioinformatics"]
|
|
32644
|
+
},
|
|
32645
|
+
{
|
|
32646
|
+
name: "experiment-power-calculator",
|
|
32647
|
+
displayName: "Experiment Power Calculator",
|
|
32648
|
+
description: "Calculate statistical power and sample size for experiments",
|
|
32649
|
+
category: "Science & Academic",
|
|
32650
|
+
tags: ["experiment", "statistics", "power-analysis", "sample-size"]
|
|
32651
|
+
},
|
|
32652
|
+
{
|
|
32653
|
+
name: "latex-table-generator",
|
|
32654
|
+
displayName: "LaTeX Table Generator",
|
|
32655
|
+
description: "Generate formatted LaTeX tables from data for academic papers",
|
|
32656
|
+
category: "Science & Academic",
|
|
32657
|
+
tags: ["latex", "tables", "academic", "formatting"]
|
|
32658
|
+
},
|
|
32659
|
+
{
|
|
32660
|
+
name: "scientific-figure-check",
|
|
32661
|
+
displayName: "Scientific Figure Check",
|
|
32662
|
+
description: "Validate scientific figures for accuracy, formatting, and publication standards",
|
|
32663
|
+
category: "Science & Academic",
|
|
32664
|
+
tags: ["scientific", "figures", "validation", "publishing"]
|
|
32665
|
+
},
|
|
32666
|
+
{
|
|
32667
|
+
name: "statistical-test-selector",
|
|
32668
|
+
displayName: "Statistical Test Selector",
|
|
32669
|
+
description: "Recommend appropriate statistical tests based on data and research questions",
|
|
32670
|
+
category: "Science & Academic",
|
|
32671
|
+
tags: ["statistics", "test-selection", "research", "analysis"]
|
|
32672
|
+
}
|
|
32673
|
+
];
|
|
32674
|
+
|
|
32675
|
+
// src/lib/registry-data/education-learning.ts
|
|
32676
|
+
var EDUCATION_LEARNING_SKILLS = [];
|
|
32677
|
+
|
|
32678
|
+
// src/lib/registry-data/communication.ts
|
|
32679
|
+
var COMMUNICATION_SKILLS = [];
|
|
32680
|
+
|
|
32681
|
+
// src/lib/registry-data/health-wellness.ts
|
|
32682
|
+
var HEALTH_WELLNESS_SKILLS = [];
|
|
32683
|
+
|
|
32684
|
+
// src/lib/registry-data/travel-lifestyle.ts
|
|
32685
|
+
var TRAVEL_LIFESTYLE_SKILLS = [];
|
|
32686
|
+
|
|
32687
|
+
// src/lib/registry-data/event-management.ts
|
|
32688
|
+
var EVENT_MANAGEMENT_SKILLS = [];
|
|
32689
|
+
|
|
32690
|
+
// src/lib/registry-data/index.ts
|
|
32691
|
+
var SKILLS = [
|
|
32692
|
+
...DEVELOPMENT_TOOLS_SKILLS,
|
|
32693
|
+
...BUSINESS_MARKETING_SKILLS,
|
|
32694
|
+
...PRODUCTIVITY_ORGANIZATION_SKILLS,
|
|
32695
|
+
...PROJECT_MANAGEMENT_SKILLS,
|
|
32696
|
+
...CONTENT_GENERATION_SKILLS,
|
|
32697
|
+
...FINANCE_COMPLIANCE_SKILLS,
|
|
32698
|
+
...DATA_ANALYSIS_SKILLS,
|
|
32699
|
+
...MEDIA_PROCESSING_SKILLS,
|
|
32700
|
+
...DESIGN_BRANDING_SKILLS,
|
|
32701
|
+
...WEB_BROWSER_SKILLS,
|
|
32702
|
+
...RESEARCH_WRITING_SKILLS,
|
|
32703
|
+
...SCIENCE_ACADEMIC_SKILLS,
|
|
32704
|
+
...EDUCATION_LEARNING_SKILLS,
|
|
32705
|
+
...COMMUNICATION_SKILLS,
|
|
32706
|
+
...HEALTH_WELLNESS_SKILLS,
|
|
32707
|
+
...TRAVEL_LIFESTYLE_SKILLS,
|
|
32708
|
+
...EVENT_MANAGEMENT_SKILLS
|
|
32709
|
+
];
|
|
32710
|
+
|
|
32711
|
+
// src/lib/hosted-skill-set.ts
|
|
32712
|
+
var HOSTED_RUNTIMES = new Set(["hosted"]);
|
|
32713
|
+
var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
|
|
32714
|
+
var HOSTED_METADATA_SET_EMPTY_ERROR = [
|
|
32715
|
+
"The hosted metadata skill set is empty, but the packaging guards that depend on it",
|
|
32716
|
+
"only mean anything while it is non-empty: an empty set makes every one of them pass",
|
|
32717
|
+
"vacuously and silently removes the protection that keeps hosted implementation source",
|
|
32718
|
+
"out of the published package.",
|
|
32719
|
+
"",
|
|
32720
|
+
"If emptying the set is intentional (every hosted skill was deleted or converted to a",
|
|
32721
|
+
"runnable in-repo skill), retire the derived guards in the SAME change \u2014 do not let them",
|
|
32722
|
+
"stay green and empty."
|
|
32723
|
+
].join(`
|
|
32724
|
+
`);
|
|
32725
|
+
var SLUG = "[^,{}/]+";
|
|
32726
|
+
var BRACE_SOURCE_EXCLUSION = new RegExp(`^!skills/\\{(${SLUG}(?:,${SLUG})+)\\}/src$`);
|
|
32727
|
+
var SINGLE_SOURCE_EXCLUSION = new RegExp(`^!skills/(${SLUG})/src$`);
|
|
32728
|
+
|
|
32729
|
+
// src/lib/skill-validation.ts
|
|
32730
|
+
var RESERVED_SKILL_ENTRIES = new Set([
|
|
32731
|
+
".env",
|
|
32732
|
+
".npmrc",
|
|
32733
|
+
".pypirc",
|
|
32734
|
+
".netrc",
|
|
32735
|
+
"id_rsa",
|
|
32736
|
+
"id_ed25519"
|
|
32737
|
+
]);
|
|
32738
|
+
var KNOWN_TOP_LEVEL_ENTRIES = new Set([
|
|
32739
|
+
".claude",
|
|
32740
|
+
".env.example",
|
|
32741
|
+
".gitignore",
|
|
32742
|
+
".skills",
|
|
32743
|
+
"CLAUDE.md",
|
|
32744
|
+
"AGENTS.md",
|
|
32745
|
+
"LICENSE",
|
|
32746
|
+
"PROJECT_OVERVIEW.md",
|
|
32747
|
+
"QUICKSTART.md",
|
|
32748
|
+
"README.md",
|
|
32749
|
+
"SKILL.md",
|
|
32750
|
+
"api-docs-list.json",
|
|
32751
|
+
"auth.ts",
|
|
32752
|
+
"bun.lock",
|
|
32753
|
+
"bunfig.toml",
|
|
32754
|
+
"data",
|
|
32755
|
+
"dist",
|
|
32756
|
+
"examples",
|
|
32757
|
+
"exports",
|
|
32758
|
+
"http-client.ts",
|
|
32759
|
+
"index.ts",
|
|
32760
|
+
"install.sh",
|
|
32761
|
+
"installer.ts",
|
|
32762
|
+
"logs",
|
|
32763
|
+
"node_modules",
|
|
32764
|
+
"package.json",
|
|
32765
|
+
"scripts",
|
|
32766
|
+
"skill-install.ts",
|
|
32767
|
+
"skill.json",
|
|
32768
|
+
"src",
|
|
32769
|
+
"tests",
|
|
32770
|
+
"references",
|
|
32771
|
+
"assets",
|
|
32772
|
+
"tsconfig.json",
|
|
32773
|
+
"vision.ts"
|
|
32774
|
+
]);
|
|
32775
|
+
var VALID_PROVENANCE_SOURCES = new Set(["official", "custom", "remote", "private", "private-hosted", "upstream", "extension"]);
|
|
32776
|
+
|
|
32777
|
+
// src/lib/portable-skills-files.ts
|
|
32778
|
+
var ANY_SEGMENT_COPY_EXCLUDES = new Set([
|
|
32779
|
+
".git",
|
|
32780
|
+
".DS_Store",
|
|
32781
|
+
".system",
|
|
32782
|
+
"node_modules"
|
|
32783
|
+
]);
|
|
32784
|
+
var FIRST_SEGMENT_COPY_EXCLUDES = new Set([
|
|
32785
|
+
"dist",
|
|
32786
|
+
"build",
|
|
32787
|
+
".turbo"
|
|
32788
|
+
]);
|
|
32789
|
+
// src/lib/portable-skills.ts
|
|
32790
|
+
var OFFICIAL_SKILL_NAMES = new Set(SKILLS.map((skill) => skill.name));
|
|
32791
|
+
// src/lib/installer.ts
|
|
32792
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4, rmSync } from "fs";
|
|
32793
|
+
import { dirname as dirname6, join as join7 } from "path";
|
|
32794
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
32795
|
+
|
|
32796
|
+
// src/lib/agent-sync.ts
|
|
32797
|
+
import { basename, dirname as dirname5, join as join6 } from "path";
|
|
32798
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
32799
|
+
var __dirname2 = dirname5(fileURLToPath2(import.meta.url));
|
|
32800
|
+
|
|
32801
|
+
// src/lib/installer.ts
|
|
32802
|
+
var __dirname3 = dirname6(fileURLToPath3(import.meta.url));
|
|
32803
|
+
function findSkillsDir() {
|
|
32804
|
+
let dir = __dirname3;
|
|
32805
|
+
for (let i3 = 0;i3 < 5; i3++) {
|
|
32806
|
+
const candidate = join7(dir, "skills");
|
|
32807
|
+
if (existsSync3(candidate) && !dir.includes(".skills"))
|
|
32808
|
+
return candidate;
|
|
32809
|
+
dir = dirname6(dir);
|
|
32810
|
+
}
|
|
32811
|
+
return join7(__dirname3, "..", "skills");
|
|
32812
|
+
}
|
|
32813
|
+
var SKILLS_DIR = findSkillsDir();
|
|
32814
|
+
|
|
32815
|
+
// src/server/skills-api.ts
|
|
32816
|
+
var MAX_SKILL_MD_BYTES = 512000;
|
|
32817
|
+
var MAX_MANIFEST_BYTES = MAX_SKILL_MD_BYTES + 64000;
|
|
32818
|
+
var ALLOWED_PUBLISH_PARTS = new Set(["manifest", "bundle"]);
|
|
32819
|
+
|
|
32820
|
+
// src/server/app.ts
|
|
32821
|
+
function assertDurableStore(store, config) {
|
|
32822
|
+
const backend = store.backend;
|
|
32823
|
+
if (!backend || backend.durable)
|
|
32824
|
+
return;
|
|
32825
|
+
assertDurableTarget(backend, config);
|
|
32826
|
+
}
|
|
32827
|
+
function assertDurableTarget(target, config) {
|
|
32828
|
+
if (target.durable || config.allowEphemeralStore)
|
|
32829
|
+
return;
|
|
32830
|
+
throw new Error(`refusing to start: the configured store is ${target.label} and does not survive a restart. ` + "Leave HASNA_SKILLS_DATABASE_URL unset to use the durable SQLite database in the skills data " + "directory, or point it at a postgres:// URL. Set HASNA_SKILLS_ALLOW_EPHEMERAL_STORE=1 only if " + "losing every run on restart is genuinely what you want.");
|
|
32831
|
+
}
|
|
32832
|
+
|
|
30910
32833
|
// src/server/worker.ts
|
|
30911
|
-
async function runWorkerOnce(store, workerId = `worker_${
|
|
32834
|
+
async function runWorkerOnce(store, workerId = `worker_${randomUUID4().slice(0, 8)}`, storage = new ArtifactStorage) {
|
|
30912
32835
|
const run = await store.claimNextRun({ workerId });
|
|
30913
32836
|
if (!run)
|
|
30914
32837
|
return false;
|
|
@@ -30922,16 +32845,31 @@ async function runWorkerOnce(store, workerId = `worker_${randomUUID2().slice(0,
|
|
|
30922
32845
|
if (import.meta.main) {
|
|
30923
32846
|
const config = resolveServerConfig();
|
|
30924
32847
|
const store = await createStore({ databaseUrl: config.databaseUrl, bootstrapApiKey: config.bootstrapApiKey });
|
|
32848
|
+
assertDurableStore(store, config);
|
|
30925
32849
|
const storage = new ArtifactStorage({ bucket: config.artifactBucket, prefix: config.artifactPrefix });
|
|
30926
|
-
|
|
32850
|
+
console.log(`skills worker ${process.env.HASNA_SKILLS_WORKER_ID || ""} storage: ${resolveDatabaseTarget(config.databaseUrl).label}`);
|
|
32851
|
+
const workerId = process.env.HASNA_SKILLS_WORKER_ID || `worker_${randomUUID4().slice(0, 8)}`;
|
|
30927
32852
|
const once = process.argv.includes("--once");
|
|
30928
32853
|
const idleMs = Number.parseInt(process.env.HASNA_SKILLS_WORKER_IDLE_MS || "1000", 10);
|
|
32854
|
+
const pause = Number.isFinite(idleMs) ? idleMs : 1000;
|
|
32855
|
+
let consecutiveErrors = 0;
|
|
30929
32856
|
do {
|
|
30930
|
-
|
|
32857
|
+
let processed = false;
|
|
32858
|
+
try {
|
|
32859
|
+
processed = await runWorkerOnce(store, workerId, storage);
|
|
32860
|
+
consecutiveErrors = 0;
|
|
32861
|
+
} catch (error) {
|
|
32862
|
+
consecutiveErrors += 1;
|
|
32863
|
+
console.error(`worker ${workerId}: claim/execute failed (${consecutiveErrors} in a row):`, error.message);
|
|
32864
|
+
if (once)
|
|
32865
|
+
process.exit(1);
|
|
32866
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(pause * consecutiveErrors, 30000)));
|
|
32867
|
+
continue;
|
|
32868
|
+
}
|
|
30931
32869
|
if (once)
|
|
30932
32870
|
process.exit(processed ? 0 : 2);
|
|
30933
32871
|
if (!processed)
|
|
30934
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
32872
|
+
await new Promise((resolve) => setTimeout(resolve, pause));
|
|
30935
32873
|
} while (true);
|
|
30936
32874
|
}
|
|
30937
32875
|
export {
|