@hasna/skills 0.1.62 → 0.1.64
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 +38 -12
- package/bin/index.js +15743 -21709
- package/bin/mcp.js +3866 -11522
- package/bin/migrate.js +281 -35
- package/bin/server.js +5805 -2682
- package/bin/worker.js +5280 -2388
- package/dist/cli/commands/publish.d.ts +2 -0
- package/dist/cli/commands/registry-reconcile.d.ts +2 -0
- package/dist/cli/components/App.d.ts +2 -1
- package/dist/cli/components/CategorySelect.d.ts +2 -1
- package/dist/cli/components/Header.d.ts +2 -1
- package/dist/cli/components/InstallProgress.d.ts +2 -1
- package/dist/cli/components/SearchView.d.ts +2 -1
- package/dist/cli/components/SkillSelect.d.ts +2 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5386 -13739
- package/dist/lib/agent-sync.d.ts +61 -6
- package/dist/lib/auth-store.d.ts +37 -0
- package/dist/lib/config.d.ts +51 -0
- package/dist/lib/home-adoption.d.ts +91 -0
- package/dist/lib/home-census.d.ts +26 -0
- package/dist/lib/home-migration.d.ts +60 -0
- package/dist/lib/native-storage.d.ts +1 -1
- package/dist/lib/portable-skills-files.d.ts +21 -1
- package/dist/lib/portable-skills-types.d.ts +46 -0
- package/dist/lib/portable-skills.d.ts +35 -6
- package/dist/lib/pull.d.ts +97 -0
- package/dist/lib/registry-reconcile.d.ts +114 -0
- package/dist/lib/registry.d.ts +7 -4
- package/dist/lib/remote-client.d.ts +124 -1
- package/dist/lib/remote-registry.d.ts +26 -0
- package/dist/lib/revision.d.ts +29 -0
- package/dist/lib/run-state.d.ts +5 -0
- package/dist/lib/skill-bundles.d.ts +54 -0
- package/dist/lib/skill-contract.d.ts +35 -0
- package/dist/lib/skill-hash.d.ts +77 -0
- package/dist/sdk/cancel.d.ts +30 -0
- package/dist/sdk/dispatcher.d.ts +40 -0
- package/dist/sdk/event-sink.d.ts +2 -0
- package/dist/sdk/events.d.ts +79 -0
- package/dist/sdk/execution/admission.d.ts +44 -0
- package/dist/sdk/execution/dispatchers/e2b.d.ts +17 -0
- package/dist/sdk/execution/dispatchers/ecs.d.ts +151 -0
- package/dist/sdk/execution/image-profile.d.ts +73 -0
- package/dist/sdk/execution/index.d.ts +15 -0
- package/dist/sdk/execution/receipts.d.ts +44 -0
- package/dist/sdk/execution/state-machine.d.ts +38 -0
- package/dist/sdk/execution/storage.d.ts +158 -0
- package/dist/sdk/execution/types.d.ts +130 -0
- package/dist/sdk/executor.d.ts +17 -0
- package/dist/sdk/governance-store.d.ts +156 -0
- package/dist/sdk/governance.d.ts +92 -0
- package/dist/sdk/index.d.ts +26 -0
- package/dist/sdk/index.js +49728 -0
- package/dist/sdk/offline.d.ts +16 -0
- package/dist/sdk/outputs.d.ts +71 -0
- package/dist/sdk/registry.d.ts +28 -0
- package/dist/sdk/runs.d.ts +229 -0
- package/dist/sdk/server.d.ts +35 -0
- package/dist/sdk/spend.d.ts +36 -0
- package/dist/sdk/storage.d.ts +25 -0
- package/dist/server/app.d.ts +42 -0
- package/dist/server/artifact-storage.d.ts +102 -0
- package/dist/server/auth.d.ts +5 -0
- package/dist/server/config.d.ts +50 -0
- package/dist/server/database-url.d.ts +42 -0
- package/dist/server/handlers.d.ts +3 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/migrate.d.ts +13 -0
- package/dist/server/migrations-dir.d.ts +18 -0
- package/dist/server/redaction.d.ts +1 -0
- package/dist/server/registry.d.ts +5 -0
- package/dist/server/rows.d.ts +24 -0
- package/dist/server/skills-api.d.ts +170 -0
- package/dist/server/sqlite-store.d.ts +131 -0
- package/dist/server/store-fixtures.d.ts +25 -0
- package/dist/server/store.d.ts +170 -0
- package/dist/server/types.d.ts +337 -0
- package/dist/server/worker.d.ts +4 -0
- package/dist/storage.js +39 -2
- package/docs/skill-standard.md +211 -39
- package/migrations/postgres/0003_run_outputs_governance.sql +83 -0
- package/migrations/postgres/0004_hosted_pins.sql +28 -0
- package/migrations/postgres/0005_revision_tombstone_registry.sql +37 -0
- package/migrations/postgres/0005_tag_projection.sql +36 -0
- package/migrations/sqlite/0003_run_outputs_governance.sql +58 -0
- package/migrations/sqlite/0004_hosted_pins.sql +21 -0
- package/migrations/sqlite/0005_revision_tombstone_registry.sql +18 -0
- package/migrations/sqlite/0005_tag_projection.sql +25 -0
- package/package.json +12 -8
- package/schemas/skill.schema.json +181 -0
- package/agent-skills/README.md +0 -41
- package/agent-skills/fleet-package-rollout/SKILL.md +0 -169
- package/agent-skills/inbox/SKILL.md +0 -25
- package/agent-skills/inbox/scripts/inbox +0 -109
- package/agent-skills/inbox/tests/test_registered_sender_id.sh +0 -92
- package/agent-skills/inbox-monitor/SKILL.md +0 -41
- package/agent-skills/inbox-monitor/scripts/inbox_monitor.sh +0 -91
- package/agent-skills/inbox-monitor/scripts/test_inbox_monitor.sh +0 -71
- package/agent-skills/merge-pr/SKILL.md +0 -85
- package/agent-skills/merge-pr/references/merge-safety.md +0 -82
- package/agent-skills/merge-pr/scripts/merge_pr_guard.py +0 -694
- package/agent-skills/merge-pr/scripts/test_merge_pr_guard.py +0 -647
- package/agent-skills/merge-pr/tests/fixtures/multi-commit-synthesized.json +0 -28
- package/agent-skills/merge-pr/tests/fixtures/trailer-free-provider.json +0 -28
- package/agent-skills/skill-goal-execute/SKILL.md +0 -115
- package/agent-skills/skill-login/SKILL.md +0 -109
- package/agent-skills/skill-project-create/SKILL.md +0 -91
- package/agent-skills/skill-publish/SKILL.md +0 -254
- package/agent-skills/skill-publish/scripts/capture_registry.js +0 -47
- package/agent-skills/skill-publish/scripts/publish_with_git_head.sh +0 -143
- package/agent-skills/skill-publish/scripts/test_publish_with_git_head.sh +0 -231
- package/skills/_common/auth.ts +0 -45
- package/skills/_common/http-client.ts +0 -143
- package/skills/_common/index.ts +0 -26
- package/skills/_common/install.sh +0 -7
- package/skills/_common/installer.ts +0 -72
- package/skills/_common/skill-install.ts +0 -37
- package/skills/_common/vision.ts +0 -374
- package/skills/ad-creative-pack/SKILL.md +0 -55
- package/skills/ad-creative-pack/package.json +0 -10
- package/skills/analyze-data/CLAUDE.md +0 -16
- package/skills/analyze-data/SKILL.md +0 -112
- package/skills/analyze-data/package.json +0 -23
- package/skills/analyze-data/src/analysis.ts +0 -401
- package/skills/analyze-data/src/cli.ts +0 -66
- package/skills/analyze-data/src/formatters.ts +0 -235
- package/skills/analyze-data/src/index.ts +0 -74
- package/skills/analyze-data/src/logger.ts +0 -36
- package/skills/analyze-data/src/parsers.ts +0 -57
- package/skills/analyze-data/src/stats.ts +0 -151
- package/skills/analyze-data/src/types.ts +0 -85
- package/skills/analyze-data/tsconfig.json +0 -19
- package/skills/api-docs-portal/SKILL.md +0 -84
- package/skills/api-docs-portal/package.json +0 -35
- package/skills/api-docs-portal/src/index.ts +0 -919
- package/skills/api-docs-portal/tsconfig.json +0 -17
- package/skills/api-test-suite/CLAUDE.md +0 -19
- package/skills/api-test-suite/package.json +0 -27
- package/skills/api-test-suite/src/index.ts +0 -381
- package/skills/api-test-suite/tsconfig.json +0 -10
- package/skills/audio-extract/CLAUDE.md +0 -9
- package/skills/audio-extract/SKILL.md +0 -73
- package/skills/audio-extract/package.json +0 -23
- package/skills/audio-extract/src/index.ts +0 -323
- package/skills/audio-extract/tsconfig.json +0 -11
- package/skills/bio-sequence-tool/CLAUDE.md +0 -19
- package/skills/bio-sequence-tool/package.json +0 -27
- package/skills/bio-sequence-tool/src/index.ts +0 -85
- package/skills/bio-sequence-tool/tsconfig.json +0 -10
- package/skills/blog-article/CLAUDE.md +0 -12
- package/skills/blog-article/SKILL.md +0 -55
- package/skills/blog-article/package.json +0 -10
- package/skills/blog-article/tsconfig.json +0 -10
- package/skills/brand-assets/SKILL.md +0 -118
- package/skills/brand-assets/package.json +0 -35
- package/skills/brand-assets/src/cli.ts +0 -155
- package/skills/brand-assets/src/constants.ts +0 -8
- package/skills/brand-assets/src/extract.ts +0 -236
- package/skills/brand-assets/src/index.ts +0 -668
- package/skills/brand-assets/src/types.ts +0 -59
- package/skills/brand-assets/tsconfig.json +0 -17
- package/skills/brand-kit/SKILL.md +0 -54
- package/skills/brand-kit/package.json +0 -10
- package/skills/businessactivity/CLAUDE.md +0 -176
- package/skills/businessactivity/LICENSE +0 -192
- package/skills/businessactivity/README.md +0 -287
- package/skills/businessactivity/package.json +0 -25
- package/skills/businessactivity/scripts/publish.ts +0 -210
- package/skills/businessactivity/src/commands/activity.ts +0 -211
- package/skills/businessactivity/src/commands/function.ts +0 -227
- package/skills/businessactivity/src/commands/owner.ts +0 -193
- package/skills/businessactivity/src/commands/profile.ts +0 -121
- package/skills/businessactivity/src/commands/responsibility.ts +0 -264
- package/skills/businessactivity/src/commands/team.ts +0 -244
- package/skills/businessactivity/src/commands/workflow.ts +0 -359
- package/skills/businessactivity/src/index.ts +0 -3
- package/skills/businessactivity/src/lib/config.ts +0 -167
- package/skills/businessactivity/src/lib/output.ts +0 -76
- package/skills/businessactivity/src/lib/paths.ts +0 -79
- package/skills/businessactivity/src/lib/storage.ts +0 -95
- package/skills/businessactivity/src/types/index.ts +0 -86
- package/skills/businessactivity/tsconfig.json +0 -29
- package/skills/codefix/LICENSE +0 -192
- package/skills/codefix/README.md +0 -232
- package/skills/codefix/SKILL.md +0 -94
- package/skills/codefix/package.json +0 -21
- package/skills/codefix/src/fixers/batch.ts +0 -213
- package/skills/codefix/src/fixers/detector.ts +0 -160
- package/skills/codefix/src/fixers/index.ts +0 -7
- package/skills/codefix/src/fixers/runner.ts +0 -522
- package/skills/codefix/src/index-local.ts +0 -431
- package/skills/codefix/src/index.ts +0 -4
- package/skills/codefix/src/types.ts +0 -211
- package/skills/codefix/tsconfig.json +0 -15
- package/skills/commitpush/SKILL.md +0 -57
- package/skills/commitpush/package.json +0 -33
- package/skills/commitpush/src/index.ts +0 -34
- package/skills/commitpush/tsconfig.json +0 -17
- package/skills/commitpushpr/SKILL.md +0 -55
- package/skills/commitpushpr/package.json +0 -33
- package/skills/commitpushpr/src/index.ts +0 -34
- package/skills/commitpushpr/tsconfig.json +0 -17
- package/skills/compress-video/CLAUDE.md +0 -9
- package/skills/compress-video/SKILL.md +0 -79
- package/skills/compress-video/package.json +0 -23
- package/skills/compress-video/src/index.ts +0 -473
- package/skills/compress-video/tsconfig.json +0 -11
- package/skills/contract-review-report/SKILL.md +0 -52
- package/skills/contract-review-report/package.json +0 -10
- package/skills/customer-feedback-report/SKILL.md +0 -52
- package/skills/customer-feedback-report/package.json +0 -10
- package/skills/dashboard-builder/CLAUDE.md +0 -19
- package/skills/dashboard-builder/package.json +0 -29
- package/skills/dashboard-builder/src/index.ts +0 -150
- package/skills/dashboard-builder/tsconfig.json +0 -10
- package/skills/data-anonymizer/CLAUDE.md +0 -19
- package/skills/data-anonymizer/package.json +0 -27
- package/skills/data-anonymizer/src/index.ts +0 -183
- package/skills/data-anonymizer/tsconfig.json +0 -10
- package/skills/database-explorer/CLAUDE.md +0 -19
- package/skills/database-explorer/package.json +0 -29
- package/skills/database-explorer/src/index.ts +0 -95
- package/skills/database-explorer/tsconfig.json +0 -10
- package/skills/diff-viewer/CLAUDE.md +0 -19
- package/skills/diff-viewer/package.json +0 -30
- package/skills/diff-viewer/src/index.ts +0 -164
- package/skills/diff-viewer/tsconfig.json +0 -10
- package/skills/doc-read/SKILL.md +0 -45
- package/skills/doc-read/package.json +0 -29
- package/skills/doc-read/src/index.ts +0 -324
- package/skills/doc-read/tsconfig.json +0 -8
- package/skills/domainpurchase/LICENSE +0 -192
- package/skills/domainpurchase/SKILL.md +0 -29
- package/skills/domainpurchase/package.json +0 -30
- package/skills/domainpurchase/src/index.ts +0 -3
- package/skills/domainpurchase/tsconfig.json +0 -21
- package/skills/email-sequence/SKILL.md +0 -53
- package/skills/email-sequence/package.json +0 -10
- package/skills/experiment-power-calculator/CLAUDE.md +0 -19
- package/skills/experiment-power-calculator/package.json +0 -29
- package/skills/experiment-power-calculator/src/index.ts +0 -86
- package/skills/experiment-power-calculator/tsconfig.json +0 -10
- package/skills/extract-frames/CLAUDE.md +0 -19
- package/skills/extract-frames/package.json +0 -27
- package/skills/extract-frames/src/index.ts +0 -616
- package/skills/extract-frames/tsconfig.json +0 -10
- package/skills/file-organizer/CLAUDE.md +0 -19
- package/skills/file-organizer/package.json +0 -27
- package/skills/file-organizer/src/index.ts +0 -91
- package/skills/file-organizer/tsconfig.json +0 -10
- package/skills/folder-tree/CLAUDE.md +0 -19
- package/skills/folder-tree/package.json +0 -29
- package/skills/folder-tree/src/index.ts +0 -568
- package/skills/folder-tree/tsconfig.json +0 -10
- package/skills/form-filler/CLAUDE.md +0 -19
- package/skills/form-filler/package.json +0 -29
- package/skills/form-filler/src/index.ts +0 -81
- package/skills/form-filler/tsconfig.json +0 -10
- package/skills/generate-api-client/CLAUDE.md +0 -19
- package/skills/generate-api-client/package.json +0 -29
- package/skills/generate-api-client/src/generator.ts +0 -47
- package/skills/generate-api-client/src/index.ts +0 -92
- package/skills/generate-api-client/src/logger.ts +0 -34
- package/skills/generate-api-client/src/python-generator.ts +0 -245
- package/skills/generate-api-client/src/spec-loader.ts +0 -48
- package/skills/generate-api-client/src/type-mappers.ts +0 -79
- package/skills/generate-api-client/src/types.ts +0 -76
- package/skills/generate-api-client/src/typescript-generator.ts +0 -247
- package/skills/generate-api-client/tsconfig.json +0 -10
- package/skills/generate-chart/CLAUDE.md +0 -19
- package/skills/generate-chart/package.json +0 -27
- package/skills/generate-chart/src/index.ts +0 -510
- package/skills/generate-chart/tsconfig.json +0 -10
- package/skills/generate-dockerfile/CLAUDE.md +0 -19
- package/skills/generate-dockerfile/package.json +0 -27
- package/skills/generate-dockerfile/src/cli.ts +0 -78
- package/skills/generate-dockerfile/src/dockerfile-templates.ts +0 -392
- package/skills/generate-dockerfile/src/index.ts +0 -81
- package/skills/generate-dockerfile/src/logger.ts +0 -30
- package/skills/generate-dockerfile/src/project-detection.ts +0 -68
- package/skills/generate-dockerfile/src/support-files.ts +0 -171
- package/skills/generate-dockerfile/src/types.ts +0 -29
- package/skills/generate-dockerfile/tsconfig.json +0 -10
- package/skills/generate-env/CLAUDE.md +0 -19
- package/skills/generate-env/package.json +0 -29
- package/skills/generate-env/src/cli.ts +0 -85
- package/skills/generate-env/src/detection.ts +0 -161
- package/skills/generate-env/src/env-data.ts +0 -66
- package/skills/generate-env/src/generators.ts +0 -240
- package/skills/generate-env/src/index.ts +0 -120
- package/skills/generate-env/src/runtime.ts +0 -30
- package/skills/generate-env/src/types.ts +0 -32
- package/skills/generate-env/tsconfig.json +0 -10
- package/skills/generate-favicon/CLAUDE.md +0 -19
- package/skills/generate-favicon/package.json +0 -29
- package/skills/generate-favicon/src/index.ts +0 -421
- package/skills/generate-favicon/tsconfig.json +0 -10
- package/skills/generate-qrcode/CLAUDE.md +0 -19
- package/skills/generate-qrcode/package.json +0 -30
- package/skills/generate-qrcode/src/index.ts +0 -584
- package/skills/generate-qrcode/tsconfig.json +0 -10
- package/skills/generate-resume/CLAUDE.md +0 -19
- package/skills/generate-resume/package.json +0 -27
- package/skills/generate-resume/src/cli.ts +0 -157
- package/skills/generate-resume/src/index.ts +0 -178
- package/skills/generate-resume/src/parsers.ts +0 -95
- package/skills/generate-resume/src/renderers.ts +0 -538
- package/skills/generate-resume/src/security.ts +0 -39
- package/skills/generate-resume/src/types.ts +0 -86
- package/skills/generate-resume/tsconfig.json +0 -10
- package/skills/generate-sitemap/CLAUDE.md +0 -19
- package/skills/generate-sitemap/package.json +0 -27
- package/skills/generate-sitemap/src/index.ts +0 -626
- package/skills/generate-sitemap/tsconfig.json +0 -10
- package/skills/gif-maker/CLAUDE.md +0 -19
- package/skills/gif-maker/package.json +0 -30
- package/skills/gif-maker/src/index.ts +0 -600
- package/skills/gif-maker/tsconfig.json +0 -10
- package/skills/hook/LICENSE +0 -192
- package/skills/hook/README.md +0 -74
- package/skills/hook/SKILL.md +0 -85
- package/skills/hook/bunfig.toml +0 -5
- package/skills/hook/package.json +0 -28
- package/skills/hook/src/commands/create.ts +0 -112
- package/skills/hook/src/commands/events.ts +0 -37
- package/skills/hook/src/commands/validate.ts +0 -117
- package/skills/hook/src/index.ts +0 -118
- package/skills/hook/src/templates/root.ts +0 -196
- package/skills/hook/src/templates/source.ts +0 -647
- package/skills/hook/tsconfig.json +0 -18
- package/skills/http-server/CLAUDE.md +0 -19
- package/skills/http-server/package.json +0 -29
- package/skills/http-server/src/index.ts +0 -51
- package/skills/http-server/tsconfig.json +0 -10
- package/skills/implementation/LICENSE +0 -192
- package/skills/implementation/README.md +0 -53
- package/skills/implementation/SKILL.md +0 -57
- package/skills/implementation/bunfig.toml +0 -5
- package/skills/implementation/package.json +0 -28
- package/skills/implementation/src/commands/create.ts +0 -187
- package/skills/implementation/src/index.ts +0 -62
- package/skills/implementation/tsconfig.json +0 -18
- package/skills/implementation-plan/CLAUDE.md +0 -19
- package/skills/implementation-plan/package.json +0 -29
- package/skills/implementation-plan/src/index.ts +0 -520
- package/skills/implementation-plan/tsconfig.json +0 -10
- package/skills/implementation-todo/CLAUDE.md +0 -19
- package/skills/implementation-todo/package.json +0 -29
- package/skills/implementation-todo/src/index.ts +0 -429
- package/skills/implementation-todo/tsconfig.json +0 -10
- package/skills/invoice/.env.example +0 -3
- package/skills/invoice/CLAUDE.md +0 -31
- package/skills/invoice/LICENSE +0 -192
- package/skills/invoice/README.md +0 -70
- package/skills/invoice/package.json +0 -26
- package/skills/invoice/src/commands/companies.ts +0 -202
- package/skills/invoice/src/commands/config.ts +0 -132
- package/skills/invoice/src/commands/generate.ts +0 -177
- package/skills/invoice/src/commands/invoices.ts +0 -218
- package/skills/invoice/src/index.ts +0 -3
- package/skills/invoice/src/lib/api.ts +0 -124
- package/skills/invoice/src/lib/storage.ts +0 -171
- package/skills/invoice/src/types/index.ts +0 -86
- package/skills/invoice/src/utils/logger.ts +0 -33
- package/skills/invoice/src/utils/paths.ts +0 -25
- package/skills/invoice/tsconfig.json +0 -23
- package/skills/invoice-reconciliation/SKILL.md +0 -98
- package/skills/invoice-reconciliation/package.json +0 -36
- package/skills/invoice-reconciliation/src/index.ts +0 -743
- package/skills/invoice-reconciliation/tsconfig.json +0 -17
- package/skills/landing-page-pack/SKILL.md +0 -55
- package/skills/landing-page-pack/package.json +0 -10
- package/skills/latex-table-generator/CLAUDE.md +0 -19
- package/skills/latex-table-generator/package.json +0 -29
- package/skills/latex-table-generator/src/index.ts +0 -113
- package/skills/latex-table-generator/tsconfig.json +0 -10
- package/skills/logo-design/SKILL.md +0 -94
- package/skills/logo-design/package.json +0 -35
- package/skills/logo-design/src/cli.ts +0 -132
- package/skills/logo-design/src/constants.ts +0 -5
- package/skills/logo-design/src/docs.ts +0 -102
- package/skills/logo-design/src/geometry.ts +0 -324
- package/skills/logo-design/src/index.ts +0 -212
- package/skills/logo-design/src/palette.ts +0 -258
- package/skills/logo-design/src/types.ts +0 -50
- package/skills/logo-design/tsconfig.json +0 -17
- package/skills/lorem-generator/CLAUDE.md +0 -19
- package/skills/lorem-generator/package.json +0 -29
- package/skills/lorem-generator/src/index.ts +0 -59
- package/skills/lorem-generator/tsconfig.json +0 -10
- package/skills/managemcp/CLAUDE.md +0 -14
- package/skills/managemcp/README.md +0 -24
- package/skills/managemcp/package.json +0 -16
- package/skills/managemcp/src/index.ts +0 -3
- package/skills/managemcp/tsconfig.json +0 -27
- package/skills/markdown-validator/CLAUDE.md +0 -19
- package/skills/markdown-validator/package.json +0 -29
- package/skills/markdown-validator/src/index.ts +0 -92
- package/skills/markdown-validator/tsconfig.json +0 -10
- package/skills/market-research-report/SKILL.md +0 -51
- package/skills/market-research-report/package.json +0 -10
- package/skills/meeting-pack/SKILL.md +0 -52
- package/skills/meeting-pack/package.json +0 -10
- package/skills/merge-pdfs/CLAUDE.md +0 -19
- package/skills/merge-pdfs/package.json +0 -31
- package/skills/merge-pdfs/src/index.ts +0 -427
- package/skills/merge-pdfs/tsconfig.json +0 -10
- package/skills/migration-plan-pack/SKILL.md +0 -56
- package/skills/migration-plan-pack/package.json +0 -10
- package/skills/monitor/SKILL.md +0 -69
- package/skills/monitor/package.json +0 -33
- package/skills/monitor/src/index.ts +0 -34
- package/skills/monitor/tsconfig.json +0 -17
- package/skills/one-page-website/SKILL.md +0 -128
- package/skills/one-page-website/package.json +0 -34
- package/skills/one-page-website/src/design.ts +0 -336
- package/skills/one-page-website/src/docs.ts +0 -159
- package/skills/one-page-website/src/index.ts +0 -357
- package/skills/one-page-website/src/page.ts +0 -340
- package/skills/one-page-website/src/styles.ts +0 -508
- package/skills/one-page-website/src/types.ts +0 -78
- package/skills/one-page-website/tsconfig.json +0 -17
- package/skills/pdf-generate/CLAUDE.md +0 -19
- package/skills/pdf-generate/SKILL.md +0 -86
- package/skills/pdf-generate/package.json +0 -21
- package/skills/pdf-generate/src/cli.ts +0 -162
- package/skills/pdf-generate/src/html.ts +0 -84
- package/skills/pdf-generate/src/index.ts +0 -62
- package/skills/pdf-generate/src/markdown.ts +0 -27
- package/skills/pdf-generate/src/pdf-writer.ts +0 -78
- package/skills/pdf-generate/src/runtime.ts +0 -34
- package/skills/pdf-generate/src/security.ts +0 -37
- package/skills/pdf-generate/src/templates.ts +0 -311
- package/skills/pdf-generate/src/types.ts +0 -28
- package/skills/pdf-generate/tsconfig.json +0 -16
- package/skills/pdf-to-dataset/SKILL.md +0 -88
- package/skills/pdf-to-dataset/package.json +0 -37
- package/skills/pdf-to-dataset/src/index.ts +0 -790
- package/skills/pdf-to-dataset/tsconfig.json +0 -17
- package/skills/pdf-to-markdown/SKILL.md +0 -81
- package/skills/pdf-to-markdown/package.json +0 -35
- package/skills/pdf-to-markdown/src/index.ts +0 -694
- package/skills/pdf-to-markdown/tsconfig.json +0 -17
- package/skills/performance-audit-report/SKILL.md +0 -49
- package/skills/performance-audit-report/package.json +0 -10
- package/skills/pitch-deck/SKILL.md +0 -51
- package/skills/pitch-deck/package.json +0 -10
- package/skills/product-mockup/SKILL.md +0 -107
- package/skills/product-mockup/package.json +0 -32
- package/skills/product-mockup/src/cli.ts +0 -150
- package/skills/product-mockup/src/design.ts +0 -151
- package/skills/product-mockup/src/docs.ts +0 -134
- package/skills/product-mockup/src/index.ts +0 -182
- package/skills/product-mockup/src/render.ts +0 -407
- package/skills/product-mockup/src/types.ts +0 -66
- package/skills/product-mockup/tsconfig.json +0 -17
- package/skills/proposal-pack/SKILL.md +0 -53
- package/skills/proposal-pack/package.json +0 -10
- package/skills/read-csv/SKILL.md +0 -62
- package/skills/read-csv/package.json +0 -37
- package/skills/read-csv/src/index.ts +0 -356
- package/skills/read-csv/tsconfig.json +0 -17
- package/skills/read-excel/SKILL.md +0 -64
- package/skills/read-excel/package.json +0 -36
- package/skills/read-excel/src/index.ts +0 -266
- package/skills/read-excel/tsconfig.json +0 -17
- package/skills/regex-tester/CLAUDE.md +0 -19
- package/skills/regex-tester/package.json +0 -27
- package/skills/regex-tester/src/index.ts +0 -183
- package/skills/regex-tester/tsconfig.json +0 -10
- package/skills/repo-onboarding-report/SKILL.md +0 -52
- package/skills/repo-onboarding-report/package.json +0 -10
- package/skills/scancommitpr/SKILL.md +0 -178
- package/skills/scancommitpr/package.json +0 -34
- package/skills/scancommitpr/src/index.ts +0 -44
- package/skills/scancommitpr/tsconfig.json +0 -13
- package/skills/scancommitpush/SKILL.md +0 -174
- package/skills/scancommitpush/package.json +0 -32
- package/skills/scancommitpush/src/index.ts +0 -44
- package/skills/scancommitpush/tsconfig.json +0 -13
- package/skills/scientific-figure-check/CLAUDE.md +0 -19
- package/skills/scientific-figure-check/package.json +0 -29
- package/skills/scientific-figure-check/src/index.ts +0 -83
- package/skills/scientific-figure-check/tsconfig.json +0 -10
- package/skills/security-audit/CLAUDE.md +0 -19
- package/skills/security-audit/package.json +0 -27
- package/skills/security-audit/src/index.ts +0 -145
- package/skills/security-audit/tsconfig.json +0 -10
- package/skills/security-audit-report/SKILL.md +0 -52
- package/skills/security-audit-report/package.json +0 -10
- package/skills/seo-content-pack/SKILL.md +0 -54
- package/skills/seo-content-pack/package.json +0 -10
- package/skills/siteanalyze/SKILL.md +0 -25
- package/skills/siteanalyze/package.json +0 -27
- package/skills/siteanalyze/src/index.ts +0 -592
- package/skills/slide-deck-generator/SKILL.md +0 -93
- package/skills/slide-deck-generator/package.json +0 -38
- package/skills/slide-deck-generator/src/cli.ts +0 -133
- package/skills/slide-deck-generator/src/index.ts +0 -148
- package/skills/slide-deck-generator/src/model.ts +0 -307
- package/skills/slide-deck-generator/src/pptx.ts +0 -143
- package/skills/slide-deck-generator/src/render.ts +0 -248
- package/skills/slide-deck-generator/src/types.ts +0 -114
- package/skills/slide-deck-generator/src/utils.ts +0 -53
- package/skills/slide-deck-generator/tsconfig.json +0 -17
- package/skills/social-content-calendar/SKILL.md +0 -54
- package/skills/social-content-calendar/package.json +0 -10
- package/skills/split-pdf/CLAUDE.md +0 -19
- package/skills/split-pdf/package.json +0 -30
- package/skills/split-pdf/src/index.ts +0 -301
- package/skills/split-pdf/tsconfig.json +0 -10
- package/skills/statistical-test-selector/CLAUDE.md +0 -19
- package/skills/statistical-test-selector/package.json +0 -27
- package/skills/statistical-test-selector/src/index.ts +0 -75
- package/skills/statistical-test-selector/tsconfig.json +0 -10
- package/skills/test-suite-generator/SKILL.md +0 -51
- package/skills/test-suite-generator/package.json +0 -10
- package/skills/tmux-session/SKILL.md +0 -109
- package/skills/tmux-session/package.json +0 -33
- package/skills/tmux-session/src/index.ts +0 -34
- package/skills/tmux-session/tsconfig.json +0 -17
- package/skills/todos-plan/SKILL.md +0 -363
- package/skills/todos-plan/agents/openai.yaml +0 -4
- package/skills/todos-plan/package.json +0 -9
- package/skills/todos-plan/src/index.ts +0 -68
- package/skills/tsconfig.base.json +0 -12
- package/skills/validate-config/CLAUDE.md +0 -19
- package/skills/validate-config/package.json +0 -29
- package/skills/validate-config/src/index.ts +0 -56
- package/skills/validate-config/tsconfig.json +0 -10
- package/skills/video-downloader/CLAUDE.md +0 -19
- package/skills/video-downloader/package.json +0 -29
- package/skills/video-downloader/src/index.ts +0 -561
- package/skills/video-downloader/tsconfig.json +0 -10
- package/skills/video-highlight-pack/SKILL.md +0 -54
- package/skills/video-highlight-pack/package.json +0 -10
- package/skills/watermark/CLAUDE.md +0 -19
- package/skills/watermark/package.json +0 -32
- package/skills/watermark/src/index.ts +0 -587
- package/skills/watermark/tsconfig.json +0 -10
package/bin/migrate.js
CHANGED
|
@@ -59,8 +59,10 @@ function resolveServerConfig(env = process.env) {
|
|
|
59
59
|
artifactBucket: env.HASNA_SKILLS_S3_BUCKET || env.SKILLS_S3_BUCKET || undefined,
|
|
60
60
|
artifactPrefix: normalizePrefix(env.HASNA_SKILLS_S3_PREFIX || env.SKILLS_S3_PREFIX || "skills/artifacts"),
|
|
61
61
|
inlineWorker: env.HASNA_SKILLS_INLINE_WORKER === "1",
|
|
62
|
+
bundleSigningKey: env.HASNA_SKILLS_API_SIGNING_KEY || env.HASNA_SKILLS_SIGNING_KEY || undefined,
|
|
62
63
|
requestBodyLimitBytes: parsePositiveInt(env.HASNA_SKILLS_REQUEST_BODY_LIMIT_BYTES, 1e6),
|
|
63
64
|
skillBundleLimitBytes: parsePositiveInt(env.HASNA_SKILLS_BUNDLE_LIMIT_BYTES, 25000000),
|
|
65
|
+
tombstoneWindowMs: parsePositiveInt(env.HASNA_SKILLS_TOMBSTONE_WINDOW_MS, 7 * 24 * 60 * 60 * 1000),
|
|
64
66
|
publicBaseUrl: (env.SKILLS_PUBLIC_BASE_URL || localOrigin(host, port)).replace(/\/+$/, ""),
|
|
65
67
|
nodeEnv,
|
|
66
68
|
allowEphemeralStore: env.HASNA_SKILLS_ALLOW_EPHEMERAL_STORE === "1"
|
|
@@ -273,6 +275,7 @@ var ANY_SEGMENT_EXCLUDES = new Set([
|
|
|
273
275
|
".docker"
|
|
274
276
|
]);
|
|
275
277
|
var ROOT_EXCLUDES = new Set(["dist", "build", ".turbo"]);
|
|
278
|
+
var TOOL_SIDECAR_FILENAMES = new Set([".hasna-skills.json"]);
|
|
276
279
|
var CREDENTIAL_FILENAMES = new Set([
|
|
277
280
|
".npmrc",
|
|
278
281
|
".pypirc",
|
|
@@ -412,6 +415,7 @@ function rowToRun(row) {
|
|
|
412
415
|
...typeof row.idempotency_key === "string" ? { idempotencyKey: row.idempotency_key } : {},
|
|
413
416
|
correlationId: String(row.correlation_id),
|
|
414
417
|
costCents: Number(row.cost_cents ?? 0),
|
|
418
|
+
leaseGeneration: Number(row.lease_generation ?? 0),
|
|
415
419
|
...typeof row.output_type === "string" ? { outputType: row.output_type } : {},
|
|
416
420
|
...typeof row.output_preview === "string" ? { outputPreview: row.output_preview } : {},
|
|
417
421
|
...typeof row.error_code === "string" ? { errorCode: row.error_code } : {},
|
|
@@ -443,6 +447,8 @@ function rowToArtifact(row) {
|
|
|
443
447
|
storageKind: String(row.storage_kind),
|
|
444
448
|
...typeof row.storage_key === "string" ? { storageKey: row.storage_key } : {},
|
|
445
449
|
...typeof row.body_text === "string" ? { bodyText: row.body_text } : {},
|
|
450
|
+
visibility: String(row.visibility ?? "private") === "public" ? "public" : "private",
|
|
451
|
+
...row.expires_at ? { expiresAt: dateString(row.expires_at) } : {},
|
|
446
452
|
createdAt: dateString(row.created_at)
|
|
447
453
|
};
|
|
448
454
|
}
|
|
@@ -462,7 +468,20 @@ function rowToSkill(row) {
|
|
|
462
468
|
...row.bundle_byte_size === null || row.bundle_byte_size === undefined ? {} : { bundleByteSize: Number(row.bundle_byte_size) },
|
|
463
469
|
...typeof row.published_by_user_id === "string" ? { publishedByUserId: row.published_by_user_id } : {},
|
|
464
470
|
createdAt: dateString(row.created_at),
|
|
465
|
-
updatedAt: dateString(row.updated_at)
|
|
471
|
+
updatedAt: dateString(row.updated_at),
|
|
472
|
+
revisionId: String(row.revision_id ?? ""),
|
|
473
|
+
revisionNumber: Number(row.revision_number ?? 0),
|
|
474
|
+
...row.tombstoned_at ? { tombstonedAt: dateString(row.tombstoned_at) } : {},
|
|
475
|
+
...row.tombstone_purge_after ? { tombstonePurgeAfter: dateString(row.tombstone_purge_after) } : {}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function rowToPin(row) {
|
|
479
|
+
return {
|
|
480
|
+
orgId: String(row.org_id),
|
|
481
|
+
principal: String(row.principal),
|
|
482
|
+
slug: String(row.slug),
|
|
483
|
+
pinnedAt: dateString(row.pinned_at),
|
|
484
|
+
metadata: parseJsonObject(row.metadata_json)
|
|
466
485
|
};
|
|
467
486
|
}
|
|
468
487
|
function rowToSkillBundle(row) {
|
|
@@ -514,9 +533,61 @@ function dateString(value) {
|
|
|
514
533
|
return String(value);
|
|
515
534
|
}
|
|
516
535
|
|
|
536
|
+
// src/server/types.ts
|
|
537
|
+
class StaleLeaseGenerationError extends Error {
|
|
538
|
+
runId;
|
|
539
|
+
expectedGeneration;
|
|
540
|
+
currentGeneration;
|
|
541
|
+
status;
|
|
542
|
+
constructor(runId2, expectedGeneration, currentGeneration, status) {
|
|
543
|
+
super(`late transition rejected for run ${runId2}: expected lease_generation ${expectedGeneration}, ` + `current ${currentGeneration} (status ${status})`);
|
|
544
|
+
this.name = "StaleLeaseGenerationError";
|
|
545
|
+
this.runId = runId2;
|
|
546
|
+
this.expectedGeneration = expectedGeneration;
|
|
547
|
+
this.currentGeneration = currentGeneration;
|
|
548
|
+
this.status = status;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
class SkillRevisionConflictError extends Error {
|
|
553
|
+
slug;
|
|
554
|
+
expectedRevisionId;
|
|
555
|
+
currentRevisionId;
|
|
556
|
+
constructor(slug, expectedRevisionId, currentRevisionId) {
|
|
557
|
+
super(`revision conflict for '${slug}': expected revision ${expectedRevisionId ?? "(none)"}, ` + `current is ${currentRevisionId ?? "(none)"}. Refused rather than silently overwriting a newer revision.`);
|
|
558
|
+
this.name = "SkillRevisionConflictError";
|
|
559
|
+
this.slug = slug;
|
|
560
|
+
this.expectedRevisionId = expectedRevisionId;
|
|
561
|
+
this.currentRevisionId = currentRevisionId;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// src/lib/revision.ts
|
|
566
|
+
import { createHash as createHash2 } from "crypto";
|
|
567
|
+
function revisionIdOf(content) {
|
|
568
|
+
const canonical = JSON.stringify({
|
|
569
|
+
slug: content.slug,
|
|
570
|
+
displayName: content.displayName,
|
|
571
|
+
description: content.description,
|
|
572
|
+
category: content.category,
|
|
573
|
+
tags: content.tags,
|
|
574
|
+
source: content.source,
|
|
575
|
+
kind: content.kind,
|
|
576
|
+
version: content.version ?? null,
|
|
577
|
+
skillMd: content.skillMd ?? null,
|
|
578
|
+
bundleSha256: content.bundleSha256 ?? null,
|
|
579
|
+
bundleByteSize: content.bundleByteSize ?? null
|
|
580
|
+
});
|
|
581
|
+
return createHash2("sha256").update(canonical).digest("hex");
|
|
582
|
+
}
|
|
583
|
+
function revisionIdOfRecord(record) {
|
|
584
|
+
return revisionIdOf(record);
|
|
585
|
+
}
|
|
586
|
+
|
|
517
587
|
// src/server/sqlite-store.ts
|
|
518
588
|
var CLAIM_ATTEMPTS = 8;
|
|
519
589
|
var CLAIMABLE_STATUSES = ["queued", "retrying"];
|
|
590
|
+
var NO_REVISION_SENTINEL = "0000000000000000000000000000000000000000000000000000000000000000";
|
|
520
591
|
var LAST_USED_RESOLUTION_MS = 60000;
|
|
521
592
|
|
|
522
593
|
class SqliteSkillsStore {
|
|
@@ -536,12 +607,24 @@ class SqliteSkillsStore {
|
|
|
536
607
|
if (options.migrate !== false) {
|
|
537
608
|
applySqliteMigrations(this.db, options.migrationsDir);
|
|
538
609
|
}
|
|
610
|
+
this.backfillLegacyRevisions();
|
|
539
611
|
this.backend = {
|
|
540
612
|
kind: "sqlite",
|
|
541
613
|
durable: !inMemory,
|
|
542
614
|
label: inMemory ? "sqlite (in-memory)" : `sqlite (${path})`
|
|
543
615
|
};
|
|
544
616
|
}
|
|
617
|
+
backfillLegacyRevisions() {
|
|
618
|
+
const rows = this.all("SELECT * FROM skills_registry WHERE revision_id = ''", []);
|
|
619
|
+
for (const row of rows) {
|
|
620
|
+
const record = rowToSkill(row);
|
|
621
|
+
this.db.run("UPDATE skills_registry SET revision_id = ? WHERE org_id = ? AND slug = ?", [
|
|
622
|
+
revisionIdOfRecord(record),
|
|
623
|
+
record.orgId,
|
|
624
|
+
record.slug
|
|
625
|
+
]);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
545
628
|
get database() {
|
|
546
629
|
return this.db;
|
|
547
630
|
}
|
|
@@ -648,7 +731,8 @@ class SqliteSkillsStore {
|
|
|
648
731
|
const id = String(candidate.id);
|
|
649
732
|
const now = nowIso();
|
|
650
733
|
const result = this.db.run(`UPDATE skills_runs
|
|
651
|
-
SET status = 'running', started_at = COALESCE(started_at, ?), locked_by = ?, locked_at =
|
|
734
|
+
SET status = 'running', started_at = COALESCE(started_at, ?), locked_by = ?, locked_at = ?,
|
|
735
|
+
lease_generation = lease_generation + 1
|
|
652
736
|
WHERE id = ? AND status IN (${CLAIMABLE_STATUSES.map(() => "?").join(", ")})`, [now, workerId, now, id, ...CLAIMABLE_STATUSES]);
|
|
653
737
|
if (result.changes !== 1) {
|
|
654
738
|
this.db.exec("ROLLBACK");
|
|
@@ -687,6 +771,33 @@ class SqliteSkillsStore {
|
|
|
687
771
|
]);
|
|
688
772
|
return row ? rowToRun(row) : null;
|
|
689
773
|
}
|
|
774
|
+
async transitionRun(id, patch, expectedGeneration) {
|
|
775
|
+
const current = this.get("SELECT * FROM skills_runs WHERE id = ? LIMIT 1", [id]);
|
|
776
|
+
if (!current)
|
|
777
|
+
return null;
|
|
778
|
+
const stored = rowToRun(current);
|
|
779
|
+
if (stored.leaseGeneration !== expectedGeneration) {
|
|
780
|
+
throw new StaleLeaseGenerationError(id, expectedGeneration, stored.leaseGeneration, stored.status);
|
|
781
|
+
}
|
|
782
|
+
const run = { ...stored, ...patch };
|
|
783
|
+
const row = this.get(`UPDATE skills_runs
|
|
784
|
+
SET status = ?, output_type = ?, output_preview = ?, error_code = ?, error_message = ?, started_at = ?, completed_at = ?,
|
|
785
|
+
lease_generation = ?
|
|
786
|
+
WHERE id = ? AND lease_generation = ?
|
|
787
|
+
RETURNING *`, [
|
|
788
|
+
run.status,
|
|
789
|
+
run.outputType ?? null,
|
|
790
|
+
run.outputPreview ?? null,
|
|
791
|
+
run.errorCode ?? null,
|
|
792
|
+
run.errorMessage ?? null,
|
|
793
|
+
run.startedAt ?? null,
|
|
794
|
+
run.completedAt ?? null,
|
|
795
|
+
run.leaseGeneration,
|
|
796
|
+
id,
|
|
797
|
+
expectedGeneration
|
|
798
|
+
]);
|
|
799
|
+
return row ? rowToRun(row) : null;
|
|
800
|
+
}
|
|
690
801
|
async appendLog(id, orgId, level, message) {
|
|
691
802
|
const row = this.get(`INSERT INTO skills_run_logs (run_id, org_id, sequence, level, message, created_at)
|
|
692
803
|
VALUES (?, ?, (SELECT COALESCE(MAX(sequence), 0) + 1 FROM skills_run_logs WHERE run_id = ?), ?, ?, ?)
|
|
@@ -700,8 +811,8 @@ class SqliteSkillsStore {
|
|
|
700
811
|
ORDER BY l.sequence ASC`, [principal.orgId, id]).map(rowToLog);
|
|
701
812
|
}
|
|
702
813
|
async addArtifact(artifact) {
|
|
703
|
-
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)
|
|
704
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
814
|
+
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, visibility, expires_at, created_at)
|
|
815
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
705
816
|
RETURNING *`, [
|
|
706
817
|
artifact.id,
|
|
707
818
|
artifact.runId,
|
|
@@ -714,6 +825,8 @@ class SqliteSkillsStore {
|
|
|
714
825
|
artifact.storageKind,
|
|
715
826
|
artifact.storageKey ?? null,
|
|
716
827
|
artifact.bodyText ?? null,
|
|
828
|
+
artifact.visibility,
|
|
829
|
+
artifact.expiresAt ?? null,
|
|
717
830
|
nowIso()
|
|
718
831
|
]);
|
|
719
832
|
return rowToArtifact(row);
|
|
@@ -735,8 +848,29 @@ class SqliteSkillsStore {
|
|
|
735
848
|
const orgId = input.principal.orgId;
|
|
736
849
|
const now = nowIso();
|
|
737
850
|
return this.db.transaction(() => {
|
|
738
|
-
const previous = this.get("SELECT bundle_sha256 FROM skills_registry WHERE org_id = ? AND slug = ?", [orgId, input.slug]);
|
|
851
|
+
const previous = this.get("SELECT revision_id, revision_number, bundle_sha256, bundle_byte_size, skill_md, tombstoned_at FROM skills_registry WHERE org_id = ? AND slug = ?", [orgId, input.slug]);
|
|
739
852
|
const previousSha = typeof previous?.bundle_sha256 === "string" ? previous.bundle_sha256 : null;
|
|
853
|
+
const previousRevisionId = typeof previous?.revision_id === "string" && previous.revision_id ? previous.revision_id : null;
|
|
854
|
+
const tombstoned = previous?.tombstoned_at != null;
|
|
855
|
+
const carriedSkillMd = typeof input.skillMd === "string" ? input.skillMd : typeof previous?.skill_md === "string" ? previous.skill_md : null;
|
|
856
|
+
if (previous && !tombstoned && input.expectedRevisionId !== previousRevisionId) {
|
|
857
|
+
throw new SkillRevisionConflictError(input.slug, input.expectedRevisionId, previousRevisionId);
|
|
858
|
+
}
|
|
859
|
+
const carriedSha = input.bundle?.sha256 ?? previousSha;
|
|
860
|
+
const carriedSize = input.bundle?.byteSize ?? (previous?.bundle_byte_size == null ? null : Number(previous.bundle_byte_size));
|
|
861
|
+
const revisionId = revisionIdOfRecord({
|
|
862
|
+
slug: input.slug,
|
|
863
|
+
displayName: input.displayName,
|
|
864
|
+
description: input.description,
|
|
865
|
+
category: input.category,
|
|
866
|
+
tags: input.tags,
|
|
867
|
+
source: input.source,
|
|
868
|
+
kind: input.kind,
|
|
869
|
+
...input.version ? { version: input.version } : {},
|
|
870
|
+
...carriedSkillMd ? { skillMd: carriedSkillMd } : {},
|
|
871
|
+
...carriedSha ? { bundleSha256: carriedSha } : {},
|
|
872
|
+
...carriedSize === null || carriedSize === undefined ? {} : { bundleByteSize: carriedSize }
|
|
873
|
+
});
|
|
740
874
|
if (input.bundle) {
|
|
741
875
|
this.db.run(`INSERT INTO skills_bundles (org_id, sha256, byte_size, content_type, storage_kind, storage_key, body_blob, created_at)
|
|
742
876
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
@@ -757,8 +891,8 @@ class SqliteSkillsStore {
|
|
|
757
891
|
]);
|
|
758
892
|
}
|
|
759
893
|
const row = this.get(`INSERT INTO skills_registry (org_id, slug, display_name, description, category, tags_json, source, kind, version, skill_md,
|
|
760
|
-
bundle_sha256, bundle_byte_size, published_by_user_id, created_at, updated_at)
|
|
761
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
894
|
+
bundle_sha256, bundle_byte_size, published_by_user_id, revision_id, revision_number, created_at, updated_at)
|
|
895
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)
|
|
762
896
|
ON CONFLICT (org_id, slug) DO UPDATE SET
|
|
763
897
|
display_name = excluded.display_name,
|
|
764
898
|
description = excluded.description,
|
|
@@ -776,7 +910,16 @@ class SqliteSkillsStore {
|
|
|
776
910
|
bundle_sha256 = COALESCE(excluded.bundle_sha256, skills_registry.bundle_sha256),
|
|
777
911
|
bundle_byte_size = COALESCE(excluded.bundle_byte_size, skills_registry.bundle_byte_size),
|
|
778
912
|
published_by_user_id = excluded.published_by_user_id,
|
|
913
|
+
revision_id = excluded.revision_id,
|
|
914
|
+
-- Current + 1, not the inserted 1: on the update path the ACTUAL row's
|
|
915
|
+
-- counter is the truth (it may have advanced since the pre-read, which is
|
|
916
|
+
-- exactly what the WHERE guard below detects).
|
|
917
|
+
revision_number = skills_registry.revision_number + 1,
|
|
918
|
+
tombstoned_at = NULL,
|
|
919
|
+
tombstone_purge_after = NULL,
|
|
779
920
|
updated_at = excluded.updated_at
|
|
921
|
+
WHERE skills_registry.tombstoned_at IS NOT NULL
|
|
922
|
+
OR skills_registry.revision_id = ?
|
|
780
923
|
RETURNING *`, [
|
|
781
924
|
orgId,
|
|
782
925
|
input.slug,
|
|
@@ -787,62 +930,165 @@ class SqliteSkillsStore {
|
|
|
787
930
|
input.source,
|
|
788
931
|
input.kind,
|
|
789
932
|
input.version ?? null,
|
|
790
|
-
|
|
933
|
+
carriedSkillMd,
|
|
791
934
|
input.bundle?.sha256 ?? null,
|
|
792
935
|
input.bundle?.byteSize ?? null,
|
|
793
936
|
input.principal.userId,
|
|
937
|
+
revisionId,
|
|
938
|
+
now,
|
|
794
939
|
now,
|
|
795
|
-
|
|
940
|
+
input.expectedRevisionId ?? NO_REVISION_SENTINEL
|
|
796
941
|
]);
|
|
942
|
+
if (!row) {
|
|
943
|
+
const current = this.get("SELECT revision_id FROM skills_registry WHERE org_id = ? AND slug = ?", [orgId, input.slug]);
|
|
944
|
+
const currentId = typeof current?.revision_id === "string" ? current.revision_id : null;
|
|
945
|
+
throw new SkillRevisionConflictError(input.slug, input.expectedRevisionId, currentId);
|
|
946
|
+
}
|
|
797
947
|
if (previousSha && input.bundle && previousSha !== input.bundle.sha256)
|
|
798
948
|
this.collectOrphanBundle(orgId, previousSha);
|
|
949
|
+
this.db.run("DELETE FROM skills_tags WHERE org_id = ? AND slug = ?", [orgId, input.slug]);
|
|
950
|
+
const insertTag = this.db.prepare("INSERT OR IGNORE INTO skills_tags (org_id, slug, tag) VALUES (?, ?, ?)");
|
|
951
|
+
for (const tag of input.tags) {
|
|
952
|
+
if (!tag.trim())
|
|
953
|
+
continue;
|
|
954
|
+
insertTag.run(orgId, input.slug, tag);
|
|
955
|
+
}
|
|
799
956
|
return rowToSkill(row);
|
|
800
957
|
})();
|
|
801
958
|
}
|
|
802
959
|
async listSkills(principal) {
|
|
803
|
-
|
|
960
|
+
await this.purgeExpiredTombstones(principal);
|
|
961
|
+
return this.all("SELECT * FROM skills_registry WHERE org_id = ? AND tombstoned_at IS NULL ORDER BY slug ASC", [principal.orgId]).map(rowToSkill);
|
|
804
962
|
}
|
|
805
963
|
async getSkill(principal, slug) {
|
|
806
964
|
const row = this.get("SELECT * FROM skills_registry WHERE org_id = ? AND slug = ? LIMIT 1", [principal.orgId, slug]);
|
|
807
965
|
return row ? rowToSkill(row) : null;
|
|
808
966
|
}
|
|
809
|
-
async updateSkill(principal, slug, patch) {
|
|
967
|
+
async updateSkill(principal, slug, patch, expectedRevisionId) {
|
|
810
968
|
const current = await this.getSkill(principal, slug);
|
|
811
|
-
if (!current)
|
|
969
|
+
if (!current || current.tombstonedAt)
|
|
812
970
|
return null;
|
|
971
|
+
if (expectedRevisionId !== current.revisionId) {
|
|
972
|
+
throw new SkillRevisionConflictError(slug, expectedRevisionId, current.revisionId);
|
|
973
|
+
}
|
|
813
974
|
const next = { ...current, ...patch };
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
975
|
+
return this.db.transaction(() => {
|
|
976
|
+
const revisionId = revisionIdOfRecord(next);
|
|
977
|
+
const row = this.get(`UPDATE skills_registry
|
|
978
|
+
SET display_name = ?, description = ?, category = ?, tags_json = ?, kind = ?, version = ?, skill_md = ?,
|
|
979
|
+
revision_id = ?, revision_number = revision_number + 1, updated_at = ?
|
|
980
|
+
WHERE org_id = ? AND slug = ? AND tombstoned_at IS NULL AND revision_id = ?
|
|
981
|
+
RETURNING *`, [
|
|
982
|
+
next.displayName,
|
|
983
|
+
next.description,
|
|
984
|
+
next.category,
|
|
985
|
+
JSON.stringify(next.tags),
|
|
986
|
+
next.kind,
|
|
987
|
+
next.version ?? null,
|
|
988
|
+
next.skillMd ?? null,
|
|
989
|
+
revisionId,
|
|
990
|
+
nowIso(),
|
|
991
|
+
principal.orgId,
|
|
992
|
+
slug,
|
|
993
|
+
current.revisionId
|
|
994
|
+
]);
|
|
995
|
+
if (!row) {
|
|
996
|
+
const nowRow = this.get("SELECT revision_id, tombstoned_at FROM skills_registry WHERE org_id = ? AND slug = ? LIMIT 1", [
|
|
997
|
+
principal.orgId,
|
|
998
|
+
slug
|
|
999
|
+
]);
|
|
1000
|
+
if (nowRow && nowRow.tombstoned_at == null) {
|
|
1001
|
+
const currentId = typeof nowRow.revision_id === "string" ? nowRow.revision_id : null;
|
|
1002
|
+
throw new SkillRevisionConflictError(slug, expectedRevisionId, currentId);
|
|
1003
|
+
}
|
|
1004
|
+
return null;
|
|
1005
|
+
}
|
|
1006
|
+
this.db.run("DELETE FROM skills_tags WHERE org_id = ? AND slug = ?", [principal.orgId, slug]);
|
|
1007
|
+
const insertTag = this.db.prepare("INSERT OR IGNORE INTO skills_tags (org_id, slug, tag) VALUES (?, ?, ?)");
|
|
1008
|
+
for (const tag of next.tags) {
|
|
1009
|
+
if (!tag.trim())
|
|
1010
|
+
continue;
|
|
1011
|
+
insertTag.run(principal.orgId, slug, tag);
|
|
1012
|
+
}
|
|
1013
|
+
return rowToSkill(row);
|
|
1014
|
+
})();
|
|
830
1015
|
}
|
|
831
|
-
async deleteSkill(principal, slug) {
|
|
1016
|
+
async deleteSkill(principal, slug, tombstoneWindowMs) {
|
|
832
1017
|
return this.db.transaction(() => {
|
|
833
|
-
const existing = this.get("SELECT
|
|
1018
|
+
const existing = this.get("SELECT tombstoned_at FROM skills_registry WHERE org_id = ? AND slug = ?", [principal.orgId, slug]);
|
|
834
1019
|
if (!existing)
|
|
835
|
-
return
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1020
|
+
return null;
|
|
1021
|
+
if (existing.tombstoned_at != null) {
|
|
1022
|
+
const row2 = this.get("SELECT * FROM skills_registry WHERE org_id = ? AND slug = ? LIMIT 1", [principal.orgId, slug]);
|
|
1023
|
+
return rowToSkill(row2);
|
|
1024
|
+
}
|
|
1025
|
+
const tombstonedAt = nowIso();
|
|
1026
|
+
const purgeAfter = new Date(Date.now() + tombstoneWindowMs).toISOString();
|
|
1027
|
+
const row = this.get(`UPDATE skills_registry
|
|
1028
|
+
SET tombstoned_at = ?, tombstone_purge_after = ?, updated_at = ?
|
|
1029
|
+
WHERE org_id = ? AND slug = ?
|
|
1030
|
+
RETURNING *`, [tombstonedAt, purgeAfter, tombstonedAt, principal.orgId, slug]);
|
|
1031
|
+
return rowToSkill(row);
|
|
1032
|
+
})();
|
|
1033
|
+
}
|
|
1034
|
+
async purgeExpiredTombstones(principal) {
|
|
1035
|
+
return this.db.transaction(() => {
|
|
1036
|
+
const now = nowIso();
|
|
1037
|
+
const expired = this.all("SELECT * FROM skills_registry WHERE org_id = ? AND tombstoned_at IS NOT NULL AND tombstone_purge_after <= ?", [principal.orgId, now]);
|
|
1038
|
+
const purged = [];
|
|
1039
|
+
for (const row of expired) {
|
|
1040
|
+
const record = rowToSkill(row);
|
|
1041
|
+
this.db.run("DELETE FROM skills_registry WHERE org_id = ? AND slug = ?", [principal.orgId, record.slug]);
|
|
1042
|
+
this.db.run("DELETE FROM skills_tags WHERE org_id = ? AND slug = ?", [principal.orgId, record.slug]);
|
|
1043
|
+
if (record.bundleSha256)
|
|
1044
|
+
this.collectOrphanBundle(principal.orgId, record.bundleSha256);
|
|
1045
|
+
purged.push(record);
|
|
1046
|
+
}
|
|
1047
|
+
return purged;
|
|
840
1048
|
})();
|
|
841
1049
|
}
|
|
842
1050
|
async getSkillBundle(principal, sha256) {
|
|
843
1051
|
const row = this.get("SELECT * FROM skills_bundles WHERE org_id = ? AND sha256 = ? LIMIT 1", [principal.orgId, sha256]);
|
|
844
1052
|
return row ? rowToSkillBundle(row) : null;
|
|
845
1053
|
}
|
|
1054
|
+
async pinSkill(principal, slug, metadata = {}) {
|
|
1055
|
+
const row = this.get(`INSERT INTO skills_pins (org_id, principal, slug, pinned_at, metadata_json)
|
|
1056
|
+
VALUES (?, ?, ?, ?, ?)
|
|
1057
|
+
ON CONFLICT (org_id, principal, slug) DO UPDATE SET
|
|
1058
|
+
pinned_at = excluded.pinned_at,
|
|
1059
|
+
metadata_json = excluded.metadata_json
|
|
1060
|
+
RETURNING *`, [principal.orgId, principal.apiKeyId, slug, nowIso(), JSON.stringify(metadata)]);
|
|
1061
|
+
return rowToPin(row);
|
|
1062
|
+
}
|
|
1063
|
+
async unpinSkill(principal, slug) {
|
|
1064
|
+
const result = this.db.run("DELETE FROM skills_pins WHERE org_id = ? AND principal = ? AND slug = ?", [principal.orgId, principal.apiKeyId, slug]);
|
|
1065
|
+
return result.changes > 0;
|
|
1066
|
+
}
|
|
1067
|
+
async listPins(principal) {
|
|
1068
|
+
return this.all("SELECT * FROM skills_pins WHERE org_id = ? AND principal = ? ORDER BY slug ASC", [principal.orgId, principal.apiKeyId]).map(rowToPin);
|
|
1069
|
+
}
|
|
1070
|
+
async listTags(principal) {
|
|
1071
|
+
await this.purgeExpiredTombstones(principal);
|
|
1072
|
+
return this.all("SELECT DISTINCT tag FROM skills_tags WHERE org_id = ? ORDER BY tag ASC", [principal.orgId]).map((row) => String(row.tag));
|
|
1073
|
+
}
|
|
1074
|
+
async listSkillsByTag(principal, tag) {
|
|
1075
|
+
await this.purgeExpiredTombstones(principal);
|
|
1076
|
+
return this.all(`SELECT s.* FROM skills_registry s
|
|
1077
|
+
JOIN skills_tags t ON t.org_id = s.org_id AND t.slug = s.slug
|
|
1078
|
+
WHERE t.org_id = ? AND t.tag = ? AND s.tombstoned_at IS NULL
|
|
1079
|
+
ORDER BY s.slug ASC`, [principal.orgId, tag]).map(rowToSkill);
|
|
1080
|
+
}
|
|
1081
|
+
async listPinsByTag(principal, tag) {
|
|
1082
|
+
await this.purgeExpiredTombstones(principal);
|
|
1083
|
+
return this.all(`SELECT p.* FROM skills_pins p
|
|
1084
|
+
JOIN skills_tags t ON t.org_id = p.org_id AND t.slug = p.slug
|
|
1085
|
+
JOIN skills_registry s ON s.org_id = p.org_id AND s.slug = p.slug
|
|
1086
|
+
WHERE p.org_id = ? AND p.principal = ? AND t.tag = ? AND s.tombstoned_at IS NULL
|
|
1087
|
+
ORDER BY p.slug ASC`, [principal.orgId, principal.apiKeyId, tag]).map(rowToPin);
|
|
1088
|
+
}
|
|
1089
|
+
async listPublishedSlugs(principal) {
|
|
1090
|
+
return this.all("SELECT slug FROM skills_registry WHERE org_id = ? AND tombstoned_at IS NULL ORDER BY slug ASC", [principal.orgId]).map((row) => String(row.slug));
|
|
1091
|
+
}
|
|
846
1092
|
collectOrphanBundle(orgId, sha256) {
|
|
847
1093
|
const referenced = this.get("SELECT 1 AS present FROM skills_registry WHERE org_id = ? AND bundle_sha256 = ? LIMIT 1", [orgId, sha256]);
|
|
848
1094
|
if (referenced)
|