@vibe-agent-toolkit/cli 0.2.0-rc.6 → 0.2.0-rc.8
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 +4 -5
- package/dist/bin/vat +34 -19
- package/dist/bin/vat.js +34 -19
- package/dist/bin/vat.js.map +1 -1
- package/dist/bin.js +44 -158
- package/dist/bin.js.map +1 -1
- package/dist/command-loaders.d.ts +2 -2
- package/dist/command-loaders.d.ts.map +1 -1
- package/dist/command-loaders.js +4 -2
- package/dist/command-loaders.js.map +1 -1
- package/dist/commands/agent/build.d.ts.map +1 -1
- package/dist/commands/agent/build.js +2 -1
- package/dist/commands/agent/build.js.map +1 -1
- package/dist/commands/agent/import.d.ts.map +1 -1
- package/dist/commands/agent/import.js +3 -2
- package/dist/commands/agent/import.js.map +1 -1
- package/dist/commands/agent/install-path.d.ts +36 -0
- package/dist/commands/agent/install-path.d.ts.map +1 -0
- package/dist/commands/agent/install-path.js +44 -0
- package/dist/commands/agent/install-path.js.map +1 -0
- package/dist/commands/agent/install.d.ts.map +1 -1
- package/dist/commands/agent/install.js +22 -10
- package/dist/commands/agent/install.js.map +1 -1
- package/dist/commands/agent/installed.d.ts.map +1 -1
- package/dist/commands/agent/installed.js +22 -12
- package/dist/commands/agent/installed.js.map +1 -1
- package/dist/commands/agent/list.d.ts.map +1 -1
- package/dist/commands/agent/list.js +2 -1
- package/dist/commands/agent/list.js.map +1 -1
- package/dist/commands/agent/run.d.ts.map +1 -1
- package/dist/commands/agent/run.js +2 -1
- package/dist/commands/agent/run.js.map +1 -1
- package/dist/commands/agent/uninstall.d.ts.map +1 -1
- package/dist/commands/agent/uninstall.js +13 -6
- package/dist/commands/agent/uninstall.js.map +1 -1
- package/dist/commands/agent/validate.d.ts.map +1 -1
- package/dist/commands/agent/validate.js +3 -2
- package/dist/commands/agent/validate.js.map +1 -1
- package/dist/commands/ard/emit.d.ts +153 -0
- package/dist/commands/ard/emit.d.ts.map +1 -0
- package/dist/commands/ard/emit.js +276 -0
- package/dist/commands/ard/emit.js.map +1 -0
- package/dist/commands/ard/index.d.ts +12 -0
- package/dist/commands/ard/index.d.ts.map +1 -0
- package/dist/commands/ard/index.js +80 -0
- package/dist/commands/ard/index.js.map +1 -0
- package/dist/commands/ard/surfaces.d.ts +56 -0
- package/dist/commands/ard/surfaces.d.ts.map +1 -0
- package/dist/commands/ard/surfaces.js +150 -0
- package/dist/commands/ard/surfaces.js.map +1 -0
- package/dist/commands/audit/distributed-tree.d.ts.map +1 -1
- package/dist/commands/audit/distributed-tree.js +9 -6
- package/dist/commands/audit/distributed-tree.js.map +1 -1
- package/dist/commands/audit/scan-population.d.ts +158 -0
- package/dist/commands/audit/scan-population.d.ts.map +1 -0
- package/dist/commands/audit/scan-population.js +292 -0
- package/dist/commands/audit/scan-population.js.map +1 -0
- package/dist/commands/audit-settings.d.ts.map +1 -1
- package/dist/commands/audit-settings.js +6 -5
- package/dist/commands/audit-settings.js.map +1 -1
- package/dist/commands/audit.d.ts +78 -9
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +853 -473
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +24 -24
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/cache/clear.d.ts.map +1 -1
- package/dist/commands/cache/clear.js +17 -10
- package/dist/commands/cache/clear.js.map +1 -1
- package/dist/commands/claude/budget.d.ts +136 -24
- package/dist/commands/claude/budget.d.ts.map +1 -1
- package/dist/commands/claude/budget.js +152 -57
- package/dist/commands/claude/budget.js.map +1 -1
- package/dist/commands/claude/context.d.ts.map +1 -1
- package/dist/commands/claude/context.js +4 -3
- package/dist/commands/claude/context.js.map +1 -1
- package/dist/commands/claude/marketplace/changelog-utils.d.ts +1 -1
- package/dist/commands/claude/marketplace/changelog-utils.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/changelog-utils.js +1 -2
- package/dist/commands/claude/marketplace/changelog-utils.js.map +1 -1
- package/dist/commands/claude/marketplace/git-publish.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/git-publish.js +3 -2
- package/dist/commands/claude/marketplace/git-publish.js.map +1 -1
- package/dist/commands/claude/marketplace/license-utils.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/license-utils.js +0 -1
- package/dist/commands/claude/marketplace/license-utils.js.map +1 -1
- package/dist/commands/claude/marketplace/publish-tree.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/publish-tree.js +0 -6
- package/dist/commands/claude/marketplace/publish-tree.js.map +1 -1
- package/dist/commands/claude/marketplace/publish.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/publish.js +2 -1
- package/dist/commands/claude/marketplace/publish.js.map +1 -1
- package/dist/commands/claude/marketplace/validate.d.ts +55 -22
- package/dist/commands/claude/marketplace/validate.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/validate.js +392 -77
- package/dist/commands/claude/marketplace/validate.js.map +1 -1
- package/dist/commands/claude/org/api-keys.d.ts +0 -3
- package/dist/commands/claude/org/api-keys.d.ts.map +1 -1
- package/dist/commands/claude/org/api-keys.js +2 -1
- package/dist/commands/claude/org/api-keys.js.map +1 -1
- package/dist/commands/claude/org/helpers.d.ts +17 -22
- package/dist/commands/claude/org/helpers.d.ts.map +1 -1
- package/dist/commands/claude/org/helpers.js +6 -22
- package/dist/commands/claude/org/helpers.js.map +1 -1
- package/dist/commands/claude/org/invites.d.ts +0 -3
- package/dist/commands/claude/org/invites.d.ts.map +1 -1
- package/dist/commands/claude/org/invites.js +3 -2
- package/dist/commands/claude/org/invites.js.map +1 -1
- package/dist/commands/claude/org/skills.d.ts +103 -4
- package/dist/commands/claude/org/skills.d.ts.map +1 -1
- package/dist/commands/claude/org/skills.js +331 -123
- package/dist/commands/claude/org/skills.js.map +1 -1
- package/dist/commands/claude/org/users.d.ts +0 -3
- package/dist/commands/claude/org/users.d.ts.map +1 -1
- package/dist/commands/claude/org/users.js +3 -2
- package/dist/commands/claude/org/users.js.map +1 -1
- package/dist/commands/claude/org/workspaces.d.ts +0 -3
- package/dist/commands/claude/org/workspaces.d.ts.map +1 -1
- package/dist/commands/claude/org/workspaces.js +6 -5
- package/dist/commands/claude/org/workspaces.js.map +1 -1
- package/dist/commands/claude/plugin/build.d.ts +8 -0
- package/dist/commands/claude/plugin/build.d.ts.map +1 -1
- package/dist/commands/claude/plugin/build.js +28 -33
- package/dist/commands/claude/plugin/build.js.map +1 -1
- package/dist/commands/claude/plugin/helpers.d.ts.map +1 -1
- package/dist/commands/claude/plugin/helpers.js +0 -6
- package/dist/commands/claude/plugin/helpers.js.map +1 -1
- package/dist/commands/claude/plugin/install.d.ts +12 -0
- package/dist/commands/claude/plugin/install.d.ts.map +1 -1
- package/dist/commands/claude/plugin/install.js +71 -60
- package/dist/commands/claude/plugin/install.js.map +1 -1
- package/dist/commands/claude/plugin/list.d.ts.map +1 -1
- package/dist/commands/claude/plugin/list.js +3 -2
- package/dist/commands/claude/plugin/list.js.map +1 -1
- package/dist/commands/claude/plugin/plugin-changelog.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-changelog.js +0 -2
- package/dist/commands/claude/plugin/plugin-changelog.js.map +1 -1
- package/dist/commands/claude/plugin/plugin-files.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-files.js +0 -3
- package/dist/commands/claude/plugin/plugin-files.js.map +1 -1
- package/dist/commands/claude/plugin/plugin-validators.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-validators.js +3 -6
- package/dist/commands/claude/plugin/plugin-validators.js.map +1 -1
- package/dist/commands/claude/plugin/tree-copy.d.ts +73 -0
- package/dist/commands/claude/plugin/tree-copy.d.ts.map +1 -1
- package/dist/commands/claude/plugin/tree-copy.js +221 -15
- package/dist/commands/claude/plugin/tree-copy.js.map +1 -1
- package/dist/commands/claude/plugin/uninstall.d.ts.map +1 -1
- package/dist/commands/claude/plugin/uninstall.js +4 -4
- package/dist/commands/claude/plugin/uninstall.js.map +1 -1
- package/dist/commands/consistency-check.d.ts +9 -13
- package/dist/commands/consistency-check.d.ts.map +1 -1
- package/dist/commands/consistency-check.js +91 -81
- package/dist/commands/consistency-check.js.map +1 -1
- package/dist/commands/corpus/index.d.ts.map +1 -1
- package/dist/commands/corpus/index.js +3 -0
- package/dist/commands/corpus/index.js.map +1 -1
- package/dist/commands/corpus/report.d.ts +0 -1
- package/dist/commands/corpus/report.d.ts.map +1 -1
- package/dist/commands/corpus/report.js +1 -3
- package/dist/commands/corpus/report.js.map +1 -1
- package/dist/commands/corpus/runner.d.ts +58 -1
- package/dist/commands/corpus/runner.d.ts.map +1 -1
- package/dist/commands/corpus/runner.js +92 -21
- package/dist/commands/corpus/runner.js.map +1 -1
- package/dist/commands/corpus/scan.d.ts.map +1 -1
- package/dist/commands/corpus/scan.js +2 -4
- package/dist/commands/corpus/scan.js.map +1 -1
- package/dist/commands/corpus/seed.d.ts +4 -4
- package/dist/commands/corpus/seed.d.ts.map +1 -1
- package/dist/commands/corpus/seed.js +1 -3
- package/dist/commands/corpus/seed.js.map +1 -1
- package/dist/commands/doctor.d.ts +14 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +147 -51
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +6 -7
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/mcp/list-collections.d.ts.map +1 -1
- package/dist/commands/mcp/list-collections.js +2 -1
- package/dist/commands/mcp/list-collections.js.map +1 -1
- package/dist/commands/mcp/serve.d.ts.map +1 -1
- package/dist/commands/mcp/serve.js +3 -2
- package/dist/commands/mcp/serve.js.map +1 -1
- package/dist/commands/okf/index.d.ts +11 -0
- package/dist/commands/okf/index.d.ts.map +1 -0
- package/dist/commands/okf/index.js +114 -0
- package/dist/commands/okf/index.js.map +1 -0
- package/dist/commands/okf/validate.d.ts +191 -0
- package/dist/commands/okf/validate.d.ts.map +1 -0
- package/dist/commands/okf/validate.js +190 -0
- package/dist/commands/okf/validate.js.map +1 -0
- package/dist/commands/phase-utils.d.ts +30 -13
- package/dist/commands/phase-utils.d.ts.map +1 -1
- package/dist/commands/phase-utils.js +56 -19
- package/dist/commands/phase-utils.js.map +1 -1
- package/dist/commands/positional-args.d.ts.map +1 -1
- package/dist/commands/positional-args.js +2 -1
- package/dist/commands/positional-args.js.map +1 -1
- package/dist/commands/rag/clear-command.d.ts.map +1 -1
- package/dist/commands/rag/clear-command.js +2 -1
- package/dist/commands/rag/clear-command.js.map +1 -1
- package/dist/commands/rag/index-command.d.ts +27 -2
- package/dist/commands/rag/index-command.d.ts.map +1 -1
- package/dist/commands/rag/index-command.js +48 -8
- package/dist/commands/rag/index-command.js.map +1 -1
- package/dist/commands/rag/index.d.ts.map +1 -1
- package/dist/commands/rag/index.js +2 -0
- package/dist/commands/rag/index.js.map +1 -1
- package/dist/commands/rag/query-command.d.ts.map +1 -1
- package/dist/commands/rag/query-command.js +2 -1
- package/dist/commands/rag/query-command.js.map +1 -1
- package/dist/commands/rag/stats-command.d.ts.map +1 -1
- package/dist/commands/rag/stats-command.js +2 -1
- package/dist/commands/rag/stats-command.js.map +1 -1
- package/dist/commands/resources/check-progress.d.ts +3 -0
- package/dist/commands/resources/check-progress.d.ts.map +1 -1
- package/dist/commands/resources/check-progress.js +11 -2
- package/dist/commands/resources/check-progress.js.map +1 -1
- package/dist/commands/resources/check-supervisor.d.ts.map +1 -1
- package/dist/commands/resources/check-supervisor.js +14 -7
- package/dist/commands/resources/check-supervisor.js.map +1 -1
- package/dist/commands/resources/check.d.ts +168 -8
- package/dist/commands/resources/check.d.ts.map +1 -1
- package/dist/commands/resources/check.js +222 -118
- package/dist/commands/resources/check.js.map +1 -1
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +64 -29
- package/dist/commands/resources/index.js.map +1 -1
- package/dist/commands/resources/query.d.ts +18 -1
- package/dist/commands/resources/query.d.ts.map +1 -1
- package/dist/commands/resources/query.js +33 -12
- package/dist/commands/resources/query.js.map +1 -1
- package/dist/commands/resources/scan.d.ts.map +1 -1
- package/dist/commands/resources/scan.js +4 -8
- package/dist/commands/resources/scan.js.map +1 -1
- package/dist/commands/resources/validate.d.ts +30 -1
- package/dist/commands/resources/validate.d.ts.map +1 -1
- package/dist/commands/resources/validate.js +116 -14
- package/dist/commands/resources/validate.js.map +1 -1
- package/dist/commands/skill/review-checklist.d.ts +3 -2
- package/dist/commands/skill/review-checklist.d.ts.map +1 -1
- package/dist/commands/skill/review-checklist.js +4 -2
- package/dist/commands/skill/review-checklist.js.map +1 -1
- package/dist/commands/skill/review.d.ts +247 -0
- package/dist/commands/skill/review.d.ts.map +1 -1
- package/dist/commands/skill/review.js +98 -61
- package/dist/commands/skill/review.js.map +1 -1
- package/dist/commands/skill/test/configure.d.ts.map +1 -1
- package/dist/commands/skill/test/configure.js +0 -1
- package/dist/commands/skill/test/configure.js.map +1 -1
- package/dist/commands/skill/test/run.d.ts +12 -6
- package/dist/commands/skill/test/run.d.ts.map +1 -1
- package/dist/commands/skill/test/run.js +137 -67
- package/dist/commands/skill/test/run.js.map +1 -1
- package/dist/commands/skills/build.d.ts +69 -2
- package/dist/commands/skills/build.d.ts.map +1 -1
- package/dist/commands/skills/build.js +128 -42
- package/dist/commands/skills/build.js.map +1 -1
- package/dist/commands/skills/install.d.ts +2 -1
- package/dist/commands/skills/install.d.ts.map +1 -1
- package/dist/commands/skills/install.js +20 -30
- package/dist/commands/skills/install.js.map +1 -1
- package/dist/commands/skills/list.d.ts +2 -1
- package/dist/commands/skills/list.d.ts.map +1 -1
- package/dist/commands/skills/list.js +44 -26
- package/dist/commands/skills/list.js.map +1 -1
- package/dist/commands/skills/package.d.ts +1 -1
- package/dist/commands/skills/package.d.ts.map +1 -1
- package/dist/commands/skills/package.js +6 -8
- package/dist/commands/skills/package.js.map +1 -1
- package/dist/commands/skills/scope-guard.d.ts.map +1 -1
- package/dist/commands/skills/scope-guard.js +2 -4
- package/dist/commands/skills/scope-guard.js.map +1 -1
- package/dist/commands/skills/shared.d.ts.map +1 -1
- package/dist/commands/skills/shared.js +2 -4
- package/dist/commands/skills/shared.js.map +1 -1
- package/dist/commands/skills/skill-discovery.d.ts +40 -1
- package/dist/commands/skills/skill-discovery.d.ts.map +1 -1
- package/dist/commands/skills/skill-discovery.js +32 -4
- package/dist/commands/skills/skill-discovery.js.map +1 -1
- package/dist/commands/skills/source-resolvers.d.ts +15 -0
- package/dist/commands/skills/source-resolvers.d.ts.map +1 -1
- package/dist/commands/skills/source-resolvers.js +25 -4
- package/dist/commands/skills/source-resolvers.js.map +1 -1
- package/dist/commands/skills/validate-command.d.ts.map +1 -1
- package/dist/commands/skills/validate-command.js +11 -3
- package/dist/commands/skills/validate-command.js.map +1 -1
- package/dist/commands/skills/validate.d.ts +66 -7
- package/dist/commands/skills/validate.d.ts.map +1 -1
- package/dist/commands/skills/validate.js +133 -29
- package/dist/commands/skills/validate.js.map +1 -1
- package/dist/commands/validate.d.ts +1 -1
- package/dist/commands/validate.js +8 -6
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/verify.d.ts +102 -5
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +246 -69
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/report-schemas.d.ts +45 -0
- package/dist/report-schemas.d.ts.map +1 -0
- package/dist/report-schemas.js +102 -0
- package/dist/report-schemas.js.map +1 -0
- package/dist/skill-resolution/packaging-config.d.ts +49 -5
- package/dist/skill-resolution/packaging-config.d.ts.map +1 -1
- package/dist/skill-resolution/packaging-config.js +59 -19
- package/dist/skill-resolution/packaging-config.js.map +1 -1
- package/dist/skill-resolution/resolve-skill-reference.d.ts.map +1 -1
- package/dist/skill-resolution/resolve-skill-reference.js +8 -6
- package/dist/skill-resolution/resolve-skill-reference.js.map +1 -1
- package/dist/utils/agent-discovery.d.ts.map +1 -1
- package/dist/utils/agent-discovery.js +22 -11
- package/dist/utils/agent-discovery.js.map +1 -1
- package/dist/utils/agent-runner.d.ts.map +1 -1
- package/dist/utils/agent-runner.js +0 -1
- package/dist/utils/agent-runner.js.map +1 -1
- package/dist/utils/command-error.d.ts +87 -55
- package/dist/utils/command-error.d.ts.map +1 -1
- package/dist/utils/command-error.js +113 -64
- package/dist/utils/command-error.js.map +1 -1
- package/dist/utils/config-loader.d.ts +2 -1
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +3 -6
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/context-budget-issues.d.ts +1 -1
- package/dist/utils/context-budget-issues.js +1 -1
- package/dist/utils/corpus-target.d.ts +5 -27
- package/dist/utils/corpus-target.d.ts.map +1 -1
- package/dist/utils/corpus-target.js +7 -33
- package/dist/utils/corpus-target.js.map +1 -1
- package/dist/utils/edge-lens-evaluation.d.ts +83 -0
- package/dist/utils/edge-lens-evaluation.d.ts.map +1 -0
- package/dist/utils/edge-lens-evaluation.js +110 -0
- package/dist/utils/edge-lens-evaluation.js.map +1 -0
- package/dist/utils/help-loader.d.ts.map +1 -1
- package/dist/utils/help-loader.js +0 -1
- package/dist/utils/help-loader.js.map +1 -1
- package/dist/utils/issue-rendering.d.ts +2 -2
- package/dist/utils/issue-rendering.js +2 -2
- package/dist/utils/optional-backend.d.ts +5 -4
- package/dist/utils/optional-backend.d.ts.map +1 -1
- package/dist/utils/optional-backend.js +7 -5
- package/dist/utils/optional-backend.js.map +1 -1
- package/dist/utils/output.d.ts +9 -0
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +16 -0
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/package-json.d.ts +24 -0
- package/dist/utils/package-json.d.ts.map +1 -0
- package/dist/utils/package-json.js +49 -0
- package/dist/utils/package-json.js.map +1 -0
- package/dist/utils/project-root-policy.d.ts +20 -0
- package/dist/utils/project-root-policy.d.ts.map +1 -1
- package/dist/utils/project-root-policy.js +30 -0
- package/dist/utils/project-root-policy.js.map +1 -1
- package/dist/utils/projection-query.d.ts +41 -4
- package/dist/utils/projection-query.d.ts.map +1 -1
- package/dist/utils/projection-query.js +44 -10
- package/dist/utils/projection-query.js.map +1 -1
- package/dist/utils/projection-store.d.ts +41 -15
- package/dist/utils/projection-store.d.ts.map +1 -1
- package/dist/utils/projection-store.js +65 -18
- package/dist/utils/projection-store.js.map +1 -1
- package/dist/utils/repeatable-option.d.ts +37 -0
- package/dist/utils/repeatable-option.d.ts.map +1 -0
- package/dist/utils/repeatable-option.js +39 -0
- package/dist/utils/repeatable-option.js.map +1 -0
- package/dist/utils/resource-loader.d.ts +4 -3
- package/dist/utils/resource-loader.d.ts.map +1 -1
- package/dist/utils/resource-loader.js +63 -32
- package/dist/utils/resource-loader.js.map +1 -1
- package/dist/utils/root-argv.d.ts +53 -0
- package/dist/utils/root-argv.d.ts.map +1 -0
- package/dist/utils/root-argv.js +215 -0
- package/dist/utils/root-argv.js.map +1 -0
- package/dist/utils/run-integrity.d.ts +95 -0
- package/dist/utils/run-integrity.d.ts.map +1 -0
- package/dist/utils/run-integrity.js +102 -0
- package/dist/utils/run-integrity.js.map +1 -0
- package/dist/utils/skill-packaging-config.d.ts +27 -0
- package/dist/utils/skill-packaging-config.d.ts.map +1 -1
- package/dist/utils/skill-packaging-config.js +30 -0
- package/dist/utils/skill-packaging-config.js.map +1 -1
- package/dist/utils/sqlite-experimental-warning.d.ts +69 -0
- package/dist/utils/sqlite-experimental-warning.d.ts.map +1 -0
- package/dist/utils/sqlite-experimental-warning.js +144 -0
- package/dist/utils/sqlite-experimental-warning.js.map +1 -0
- package/dist/utils/url-redact.d.ts.map +1 -1
- package/dist/utils/url-redact.js +4 -6
- package/dist/utils/url-redact.js.map +1 -1
- package/dist/utils/user-context-scanner.d.ts +8 -0
- package/dist/utils/user-context-scanner.d.ts.map +1 -1
- package/dist/utils/user-context-scanner.js +4 -2
- package/dist/utils/user-context-scanner.js.map +1 -1
- package/dist/utils/validate-help-files.d.ts.map +1 -1
- package/dist/utils/validate-help-files.js +12 -6
- package/dist/utils/validate-help-files.js.map +1 -1
- package/dist/utils/vat-bin-path.d.ts.map +1 -1
- package/dist/utils/vat-bin-path.js +0 -1
- package/dist/utils/vat-bin-path.js.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -3
- package/dist/version.js.map +1 -1
- package/docs/audit.md +141 -37
- package/docs/doctor.md +7 -6
- package/docs/index.md +19 -11
- package/docs/rag.md +3 -2
- package/docs/resources.md +5 -2
- package/docs/skill-test.md +10 -9
- package/docs/skills.md +53 -69
- package/package.json +24 -29
- package/schemas/ard-emit.json +149 -0
- package/schemas/claude-budget.json +197 -0
- package/schemas/okf-validate.json +170 -0
- package/schemas/resources-check.json +186 -0
- package/schemas/skill-review.json +230 -0
|
@@ -6,7 +6,7 @@ import { basename } from 'node:path';
|
|
|
6
6
|
import { API_SKILL_MAX_UPLOAD_BYTES, collectNonPortableAssetReferenceIssues, collectNonPortableCommandIssues, collectUnqualifiedMcpToolIssues, declaredSkillNameIn, describeOversizeBundle, evalSuiteUnitPath, formatBytes, NEVER_UPLOADED_DIR_NAMES, readDeclaredSkillName, } from '@vibe-agent-toolkit/agent-skills';
|
|
7
7
|
import { ApiRequestError, ApiTransportError, buildMultipartFormData, skillVersionsPath, } from '@vibe-agent-toolkit/claude-marketplace';
|
|
8
8
|
import { createAllowUsageLedger, runValidationFramework } from '@vibe-agent-toolkit/schema';
|
|
9
|
-
import { isAbsoluteAnyPlatform, normalizedTmpdir, safePath, toForwardSlash, } from '@vibe-agent-toolkit/utils';
|
|
9
|
+
import { direntKindFollowingSync, isAbsoluteAnyPlatform, isFilesystemAccessError, normalizedTmpdir, safePath, toForwardSlash, } from '@vibe-agent-toolkit/utils';
|
|
10
10
|
import { Command } from 'commander';
|
|
11
11
|
import { resolveSkillPackagingConfig } from '../../../skill-resolution/packaging-config.js';
|
|
12
12
|
import { downloadNpmPackage } from '../plugin/helpers.js';
|
|
@@ -459,19 +459,23 @@ export function resolveSourceArgument(source) {
|
|
|
459
459
|
: safePath.resolve(process.cwd(), source);
|
|
460
460
|
}
|
|
461
461
|
/**
|
|
462
|
-
* The largest
|
|
462
|
+
* The largest single markdown member this will decompress to read.
|
|
463
463
|
*
|
|
464
464
|
* Not a limit on what may be PUBLISHED — the API's own ceiling decides that, and
|
|
465
|
-
* a bigger document simply goes unread rather than refused. It bounds the
|
|
466
|
-
*
|
|
465
|
+
* a bigger document simply goes unread rather than refused. It bounds the
|
|
466
|
+
* allocations this module performs on attacker-supplied metadata: `getData()`
|
|
467
467
|
* inflates whatever `header.size` claims, and a header can claim anything. A
|
|
468
|
-
* megabyte is two orders of magnitude above any real
|
|
468
|
+
* megabyte is two orders of magnitude above any real skill document.
|
|
469
|
+
*
|
|
470
|
+
* ⚠️ It is a PER-ENTRY bound. The total is bounded separately, and more
|
|
471
|
+
* tightly: nothing is inflated at all until the archive's declared uncompressed
|
|
472
|
+
* total is known to be within {@link API_SKILL_MAX_UPLOAD_BYTES}.
|
|
469
473
|
*/
|
|
470
|
-
const
|
|
474
|
+
const MAX_INSPECTED_DOCUMENT_BYTES = 1024 * 1024;
|
|
471
475
|
/**
|
|
472
476
|
* What a ZIP will weigh AFTER the API expands it, read from the archive's own
|
|
473
|
-
* central directory — plus the name its inner SKILL.md declares,
|
|
474
|
-
*
|
|
477
|
+
* central directory — plus the name its inner SKILL.md declares, any answer key
|
|
478
|
+
* it carries, and the markdown members the portability checks read.
|
|
475
479
|
*
|
|
476
480
|
* 🔑 **The API expands a ZIP and applies the ceiling to the UNCOMPRESSED total,
|
|
477
481
|
* not to the archive.** Measured against the live API by an adopter: a
|
|
@@ -503,7 +507,7 @@ const MAX_INSPECTED_SKILL_MD_BYTES = 1024 * 1024;
|
|
|
503
507
|
* caller's uncompressed-total gate, so the ceiling this function exists to
|
|
504
508
|
* enforce could not protect the inflation this function performed. Nothing is
|
|
505
509
|
* written to disk — that part stands — but the decompression is now ordered
|
|
506
|
-
* after the total is known and bounded by {@link
|
|
510
|
+
* after the total is known and bounded by {@link MAX_INSPECTED_DOCUMENT_BYTES},
|
|
507
511
|
* so an archive declaring a 4 GiB SKILL.md is enumerated and never inflated.
|
|
508
512
|
*/
|
|
509
513
|
export async function inspectZipArchive(zipPath) {
|
|
@@ -517,11 +521,18 @@ export async function inspectZipArchive(zipPath) {
|
|
|
517
521
|
try {
|
|
518
522
|
entries = new AdmZip(zipPath).getEntries();
|
|
519
523
|
}
|
|
520
|
-
catch {
|
|
521
|
-
// An archive VAT cannot
|
|
524
|
+
catch (error) {
|
|
525
|
+
// An archive VAT cannot PARSE is not an archive VAT should block. The API
|
|
522
526
|
// is the authority on the upload either way, and refusing here would turn
|
|
523
|
-
// "our reader disagrees with your zip tool" into a failed publish.
|
|
524
|
-
|
|
527
|
+
// "our reader disagrees with your zip tool" into a failed publish. The
|
|
528
|
+
// caller is told why, so "checks skipped" is never silent.
|
|
529
|
+
//
|
|
530
|
+
// An archive the FILESYSTEM refuses is a different thing: the path was
|
|
531
|
+
// readable a moment ago (the caller holds its bytes), so a refusal here
|
|
532
|
+
// is not a parse disagreement and stays loud.
|
|
533
|
+
if (isFilesystemAccessError(error))
|
|
534
|
+
throw error;
|
|
535
|
+
return { archiveUnreadable: describeZipFailure(error) };
|
|
525
536
|
}
|
|
526
537
|
// PASS 1 — headers only. Nothing is decompressed while this runs, so both
|
|
527
538
|
// refusals the caller can reach are decided on metadata alone.
|
|
@@ -530,14 +541,97 @@ export async function inspectZipArchive(zipPath) {
|
|
|
530
541
|
const neverUploaded = files
|
|
531
542
|
.map(entry => toForwardSlash(entry.entryName))
|
|
532
543
|
.filter(name => name.split('/').some(segment => NEVER_UPLOADED_DIR_NAMES.has(segment)));
|
|
533
|
-
// PASS 2 — the
|
|
544
|
+
// PASS 2 — the entries worth inflating, and only once the total says this
|
|
534
545
|
// archive is not already refused. An over-ceiling archive is about to be
|
|
535
546
|
// rejected by the caller, so inflating anything out of it would be work spent
|
|
536
547
|
// on an upload that cannot happen.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
548
|
+
if (uncompressedBytes > API_SKILL_MAX_UPLOAD_BYTES) {
|
|
549
|
+
return {
|
|
550
|
+
uncompressedBytes, declaredName: undefined, neverUploaded, documents: [], bundleRoot: undefined, unreadable: [],
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
const elected = electShallowestSkillMd(files);
|
|
554
|
+
const unreadable = [];
|
|
555
|
+
return {
|
|
556
|
+
uncompressedBytes,
|
|
557
|
+
declaredName: declaredNameOf(elected, unreadable),
|
|
558
|
+
neverUploaded,
|
|
559
|
+
documents: inflateMarkdownMembers(files, unreadable),
|
|
560
|
+
bundleRoot: archiveRootOf(elected?.entryName),
|
|
561
|
+
unreadable,
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
/** adm-zip throws plain `Error`s; the message is all it has to say. */
|
|
565
|
+
function describeZipFailure(error) {
|
|
566
|
+
return error instanceof Error ? error.message : String(error);
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Every markdown member of the archive, as an upload part.
|
|
570
|
+
*
|
|
571
|
+
* 🔑 This exists so the ZIP lane can run the portability family through the ONE
|
|
572
|
+
* function the directory lane runs it through. Until it did, `install <zip>`
|
|
573
|
+
* performed none of the checks `install --help` promises of "every markdown
|
|
574
|
+
* document in the bundle": the archive went to `sendSkillUpload` as one opaque
|
|
575
|
+
* part, and an operator following the documented contract got silence where they
|
|
576
|
+
* were promised warnings. Routing the parts back through
|
|
577
|
+
* {@link warnUnportableReferences} keeps ONE implementation of the checks — a
|
|
578
|
+
* second copy of the three collector calls is how the two lanes start disagreeing.
|
|
579
|
+
*
|
|
580
|
+
* An entry that will not inflate is SKIPPED, never fatal: this module's standing
|
|
581
|
+
* position is that an archive VAT cannot read is not an archive VAT should block,
|
|
582
|
+
* and the checks it feeds only ever warn.
|
|
583
|
+
*/
|
|
584
|
+
function inflateMarkdownMembers(files, unreadable) {
|
|
585
|
+
const documents = [];
|
|
586
|
+
for (const entry of files) {
|
|
587
|
+
const filename = toForwardSlash(entry.entryName);
|
|
588
|
+
if (!filename.toLowerCase().endsWith('.md'))
|
|
589
|
+
continue;
|
|
590
|
+
if (entry.header.size > MAX_INSPECTED_DOCUMENT_BYTES)
|
|
591
|
+
continue;
|
|
592
|
+
const content = inflateOrRecord(entry, unreadable);
|
|
593
|
+
if (content !== undefined)
|
|
594
|
+
documents.push({ fieldName: 'files[]', filename, content });
|
|
595
|
+
}
|
|
596
|
+
return documents;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* One member's bytes, or `undefined` with the refusal RECORDED.
|
|
600
|
+
*
|
|
601
|
+
* `getData()` is the only decompression in this module, so it is the only thing
|
|
602
|
+
* that can throw here: adm-zip raises on BAD_CRC, on any compression method but
|
|
603
|
+
* store/deflate, and on an encrypted entry. Those used to escape and abort the
|
|
604
|
+
* publish on exit 2 — contradicting this module's own stance that an archive VAT
|
|
605
|
+
* cannot parse is not an archive VAT should block — and then, once caught, were
|
|
606
|
+
* dropped without a word. The member is skipped AND named.
|
|
607
|
+
*/
|
|
608
|
+
function inflateOrRecord(entry, unreadable) {
|
|
609
|
+
try {
|
|
610
|
+
return entry.getData();
|
|
611
|
+
}
|
|
612
|
+
catch (error) {
|
|
613
|
+
// Once per member: the elected SKILL.md is asked for twice (its name, then
|
|
614
|
+
// its text), and one refusal is one fact.
|
|
615
|
+
const name = toForwardSlash(entry.entryName);
|
|
616
|
+
if (!unreadable.some((failure) => failure.entry === name)) {
|
|
617
|
+
unreadable.push({ entry: name, reason: describeZipFailure(error) });
|
|
618
|
+
}
|
|
619
|
+
return undefined;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* The directory the elected SKILL.md sits in, which is the archive's bundle root.
|
|
624
|
+
*
|
|
625
|
+
* `my-skill/SKILL.md` roots the bundle at `my-skill`; a SKILL.md at the archive
|
|
626
|
+
* root has no prefix, and neither does an archive with no SKILL.md at all. ZIP
|
|
627
|
+
* fixes `/` as the entry separator, so this reads the format rather than handling
|
|
628
|
+
* a host path.
|
|
629
|
+
*/
|
|
630
|
+
function archiveRootOf(entryName) {
|
|
631
|
+
if (entryName === undefined)
|
|
632
|
+
return undefined;
|
|
633
|
+
const cut = toForwardSlash(entryName).lastIndexOf('/');
|
|
634
|
+
return cut === -1 ? undefined : entryName.slice(0, cut);
|
|
541
635
|
}
|
|
542
636
|
/**
|
|
543
637
|
* The SKILL.md nearest the archive root, which is the one whose `name` the API
|
|
@@ -597,22 +691,15 @@ function zipEntryDepth(entryName) {
|
|
|
597
691
|
* the root of their archive. The election decides; whatever it holds is the
|
|
598
692
|
* answer, absence included.
|
|
599
693
|
*
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
* publish on exit 2 — contradicting this module's own stance that an archive VAT
|
|
604
|
-
* cannot parse is not an archive VAT should block. The size total is already
|
|
605
|
-
* computed from headers, so failing here costs only the name.
|
|
694
|
+
* An elected SKILL.md that will not inflate costs only the name (the size total
|
|
695
|
+
* is already computed from headers) — see {@link inflateOrRecord}, which records
|
|
696
|
+
* the refusal so the operator learns why no name was read.
|
|
606
697
|
*/
|
|
607
|
-
function declaredNameOf(entry) {
|
|
608
|
-
if (entry === undefined || entry.header.size >
|
|
609
|
-
return undefined;
|
|
610
|
-
try {
|
|
611
|
-
return declaredSkillNameIn(entry.getData().toString('utf8'));
|
|
612
|
-
}
|
|
613
|
-
catch {
|
|
698
|
+
function declaredNameOf(entry, unreadable) {
|
|
699
|
+
if (entry === undefined || entry.header.size > MAX_INSPECTED_DOCUMENT_BYTES)
|
|
614
700
|
return undefined;
|
|
615
|
-
|
|
701
|
+
const content = inflateOrRecord(entry, unreadable);
|
|
702
|
+
return content === undefined ? undefined : declaredSkillNameIn(content.toString('utf8'));
|
|
616
703
|
}
|
|
617
704
|
async function sendSkillUpload(client, displayTitle, files, bundleRoot) {
|
|
618
705
|
const multipart = buildUploadBodyOrRefuse({ display_title: displayTitle }, files, bundleRoot);
|
|
@@ -650,7 +737,10 @@ function requireDeclaredName(skillMdPath) {
|
|
|
650
737
|
* skill dir — nothing inside the tree to withhold.
|
|
651
738
|
*/
|
|
652
739
|
async function declaredTestInputPaths(skillDir) {
|
|
653
|
-
|
|
740
|
+
// `'refuse'`: an upload that cannot tell which paths are test input might
|
|
741
|
+
// publish an answer key. The throw is reported per skill by the install
|
|
742
|
+
// loop's catch (logged, and counted in its failures) — never swallowed.
|
|
743
|
+
const config = await resolveSkillPackagingConfig(safePath.join(skillDir, 'SKILL.md'), 'refuse');
|
|
654
744
|
const declared = config?.test?.evals;
|
|
655
745
|
if (declared === undefined)
|
|
656
746
|
return new Set();
|
|
@@ -675,7 +765,6 @@ function resolvesToDirectory(entry, fullPath, relativePath) {
|
|
|
675
765
|
if (!entry.isSymbolicLink())
|
|
676
766
|
return false;
|
|
677
767
|
try {
|
|
678
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- collected from dir walk
|
|
679
768
|
return statSync(fullPath).isDirectory();
|
|
680
769
|
}
|
|
681
770
|
catch (error) {
|
|
@@ -717,7 +806,6 @@ function resolvesToDirectory(entry, fullPath, relativePath) {
|
|
|
717
806
|
* would have sent.
|
|
718
807
|
*/
|
|
719
808
|
function collectFiles(dir, base, testInput, collected) {
|
|
720
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- dir from CLI arg
|
|
721
809
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
722
810
|
const fullPath = safePath.join(dir, entry.name);
|
|
723
811
|
const relativePath = safePath.relative(base, fullPath);
|
|
@@ -767,7 +855,6 @@ export async function collectSkillUploadFiles(skillDir) {
|
|
|
767
855
|
*/
|
|
768
856
|
async function prepareSkillUpload(skillDir, titleOverride, logger) {
|
|
769
857
|
const skillMdPath = safePath.join(skillDir, 'SKILL.md');
|
|
770
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- derived from CLI arg
|
|
771
858
|
if (!existsSync(skillMdPath)) {
|
|
772
859
|
throw new Error(`SKILL.md not found in ${skillDir}. Is this a built skill directory?`);
|
|
773
860
|
}
|
|
@@ -780,7 +867,6 @@ async function prepareSkillUpload(skillDir, titleOverride, logger) {
|
|
|
780
867
|
const collected = await collectSkillUploadFiles(skillDir);
|
|
781
868
|
const files = [];
|
|
782
869
|
for (const file of collected.files) {
|
|
783
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- collected from dir walk
|
|
784
870
|
const content = readFileSync(file.absolutePath);
|
|
785
871
|
files.push({
|
|
786
872
|
fieldName: 'files[]',
|
|
@@ -805,7 +891,7 @@ async function prepareSkillUpload(skillDir, titleOverride, logger) {
|
|
|
805
891
|
// Resolved HERE rather than plumbed out of `collectSkillUploadFiles`, which is
|
|
806
892
|
// exported and deliberately resolves its own so no caller can hand it a config
|
|
807
893
|
// with the exclusion skipped.
|
|
808
|
-
const packaging = await resolveSkillPackagingConfig(skillMdPath);
|
|
894
|
+
const packaging = await resolveSkillPackagingConfig(skillMdPath, 'refuse');
|
|
809
895
|
warnUnportableReferences(files, dirName, packaging?.validation, logger);
|
|
810
896
|
return { displayTitle, files, dirName };
|
|
811
897
|
}
|
|
@@ -934,19 +1020,18 @@ async function uploadSkillVersionDir(client, skillId, skillDir, logger) {
|
|
|
934
1020
|
* any report said so.
|
|
935
1021
|
*/
|
|
936
1022
|
export function listNodeModulePackages(nodeModulesDir) {
|
|
937
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- constructed from temp dir
|
|
938
1023
|
if (!existsSync(nodeModulesDir))
|
|
939
1024
|
return [];
|
|
940
1025
|
const results = [];
|
|
941
|
-
//
|
|
1026
|
+
// Followed: a workspace package under node_modules IS a symlink, and a walk
|
|
1027
|
+
// that tested `isDirectory()` on the link skipped every one of them.
|
|
942
1028
|
for (const entry of readdirSync(nodeModulesDir, { withFileTypes: true })) {
|
|
943
|
-
if (
|
|
1029
|
+
if (direntKindFollowingSync(nodeModulesDir, entry) !== 'directory')
|
|
944
1030
|
continue;
|
|
945
1031
|
if (entry.name.startsWith('@')) {
|
|
946
1032
|
const scopeDir = safePath.join(nodeModulesDir, entry.name);
|
|
947
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- constructed from temp dir
|
|
948
1033
|
for (const scopedEntry of readdirSync(scopeDir, { withFileTypes: true })) {
|
|
949
|
-
if (scopedEntry
|
|
1034
|
+
if (direntKindFollowingSync(scopeDir, scopedEntry) === 'directory')
|
|
950
1035
|
results.push(safePath.join(scopeDir, scopedEntry.name));
|
|
951
1036
|
}
|
|
952
1037
|
}
|
|
@@ -962,13 +1047,11 @@ export function listNodeModulePackages(nodeModulesDir) {
|
|
|
962
1047
|
*/
|
|
963
1048
|
export function findSkillsDir(packageDir) {
|
|
964
1049
|
const direct = safePath.join(packageDir, 'dist', 'skills');
|
|
965
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- constructed from temp dir
|
|
966
1050
|
if (existsSync(direct))
|
|
967
1051
|
return direct;
|
|
968
1052
|
const candidates = listNodeModulePackages(safePath.join(packageDir, 'node_modules'));
|
|
969
1053
|
for (const pkgDir of candidates) {
|
|
970
1054
|
const candidate = safePath.join(pkgDir, 'dist', 'skills');
|
|
971
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- constructed from temp dir
|
|
972
1055
|
if (existsSync(candidate))
|
|
973
1056
|
return candidate;
|
|
974
1057
|
}
|
|
@@ -1012,9 +1095,9 @@ async function installFromNpm(npmPackage, skillFilter, client, logger) {
|
|
|
1012
1095
|
throw new Error(`No dist/skills/ directory found in ${npmPackage}. Was the package built with vat skills build?`);
|
|
1013
1096
|
}
|
|
1014
1097
|
logger.info(`Found skills at: ${safePath.relative(packageDir, skillsDir) || 'dist/skills/'}`);
|
|
1015
|
-
//
|
|
1098
|
+
// Followed: a built skill directory that is a link is still a skill to upload.
|
|
1016
1099
|
const skillDirs = readdirSync(skillsDir, { withFileTypes: true })
|
|
1017
|
-
.filter(e => e
|
|
1100
|
+
.filter(e => direntKindFollowingSync(skillsDir, e) === 'directory')
|
|
1018
1101
|
.map(e => e.name);
|
|
1019
1102
|
if (skillDirs.length === 0) {
|
|
1020
1103
|
throw new Error(`No skills found in dist/skills/ of ${npmPackage}`);
|
|
@@ -1051,11 +1134,9 @@ async function installFromNpm(npmPackage, skillFilter, client, logger) {
|
|
|
1051
1134
|
*/
|
|
1052
1135
|
export async function installFromLocal(source, titleOverride, client, logger) {
|
|
1053
1136
|
const sourcePath = resolveSourceArgument(source);
|
|
1054
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from CLI arg
|
|
1055
1137
|
if (!existsSync(sourcePath)) {
|
|
1056
1138
|
throw new Error(`Source not found: ${sourcePath}`);
|
|
1057
1139
|
}
|
|
1058
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from CLI arg
|
|
1059
1140
|
const stat = statSync(sourcePath);
|
|
1060
1141
|
// Case-INSENSITIVE. `endsWith('.zip')` refused `MySkill.ZIP` as "not a directory
|
|
1061
1142
|
// or .zip file" — a file Windows and macOS both consider a zip archive, and one
|
|
@@ -1090,7 +1171,6 @@ async function installZipArchive(sourcePath, titleOverride, client, logger) {
|
|
|
1090
1171
|
// `basename(path, ext)` matches the extension exactly, so the literal '.zip'
|
|
1091
1172
|
// leaves `.ZIP` on the title. Slice the length instead.
|
|
1092
1173
|
const displayTitle = titleOverride ?? basename(sourcePath).slice(0, -'.zip'.length);
|
|
1093
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from CLI arg
|
|
1094
1174
|
const zipContent = readFileSync(sourcePath);
|
|
1095
1175
|
const files = [{
|
|
1096
1176
|
fieldName: 'files[]',
|
|
@@ -1127,50 +1207,162 @@ async function installZipArchive(sourcePath, titleOverride, client, logger) {
|
|
|
1127
1207
|
? 'from the ZIP filename — NOT from the SKILL.md inside it; pass --title to set it'
|
|
1128
1208
|
: 'from --title'})`);
|
|
1129
1209
|
const inspected = await inspectZipArchive(sourcePath);
|
|
1130
|
-
if (
|
|
1131
|
-
//
|
|
1132
|
-
//
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1210
|
+
if ('archiveUnreadable' in inspected) {
|
|
1211
|
+
// Degrade, and SAY so. Every check below is skipped, and a skipped check
|
|
1212
|
+
// that is not announced is indistinguishable from one that passed.
|
|
1213
|
+
logger.warn(`Could not read the archive (${inspected.archiveUnreadable}); the answer-key, expanded-size, `
|
|
1214
|
+
+ `name and portability checks were not run on it. The API decides the upload.`);
|
|
1215
|
+
}
|
|
1216
|
+
else {
|
|
1217
|
+
refuseOrWarnOnArchive(inspected, displayTitle, zipContent.length, logger);
|
|
1218
|
+
}
|
|
1219
|
+
return sendSkillUpload(client, displayTitle, files);
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* The archive lane's own decisions, over what {@link inspectZipArchive} read:
|
|
1223
|
+
* two refusals (answer key, expanded size), and the warnings the inspection
|
|
1224
|
+
* earns (title/name divergence, portability, members it could not inflate).
|
|
1225
|
+
*/
|
|
1226
|
+
function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
|
|
1227
|
+
// 🚨 REFUSED, not warned. The directory lane refuses an answer key
|
|
1228
|
+
// unconditionally (`NEVER_UPLOADED_DIR_NAMES`, plus whatever the config
|
|
1229
|
+
// declares), and until this existed the ZIP lane bypassed `collectFiles`
|
|
1230
|
+
// entirely and posted the archive as one opaque part — so
|
|
1231
|
+
// `zip -r my-skill.zip my-skill/` over a tree holding
|
|
1232
|
+
// `my-skill/evals/evals.json` published the answer key org-wide with a
|
|
1233
|
+
// green tick, while `install my-skill/` on the very same tree refused.
|
|
1234
|
+
// Two lanes of one command must not disagree about whether a skill's
|
|
1235
|
+
// answer key may be published, and a warning is a disagreement.
|
|
1236
|
+
//
|
|
1237
|
+
// This lane can only see the CONVENTIONAL names: there is no skill
|
|
1238
|
+
// directory to walk up from, so a config-declared suite location is
|
|
1239
|
+
// unreadable here. That is a narrower check than the directory lane's,
|
|
1240
|
+
// not a looser verdict on what it does see.
|
|
1241
|
+
if (inspected.neverUploaded.length > 0) {
|
|
1242
|
+
throw new Error(`This ZIP contains ${String(inspected.neverUploaded.length)} entr`
|
|
1243
|
+
+ `${inspected.neverUploaded.length === 1 ? 'y' : 'ies'} that are never published with a `
|
|
1244
|
+
+ `skill: ${inspected.neverUploaded.slice(0, 10).join(', ')}`
|
|
1245
|
+
+ `${inspected.neverUploaded.length > 10 ? ', …' : ''}. An eval suite is the skill's ANSWER `
|
|
1246
|
+
+ `KEY and this would publish it to everyone in the organization. Rebuild the archive from `
|
|
1247
|
+
+ `the BUILT skill directory (\`vat skills build\`), or upload that directory directly — `
|
|
1248
|
+
+ `\`install <dir>\` withholds these and reports each one.`);
|
|
1249
|
+
}
|
|
1250
|
+
if (inspected.uncompressedBytes > API_SKILL_MAX_UPLOAD_BYTES) {
|
|
1251
|
+
throw new Error(`ZIP expands to ${formatBytes(inspected.uncompressedBytes)}, over the `
|
|
1252
|
+
+ `${formatBytes(API_SKILL_MAX_UPLOAD_BYTES)} ceiling. The API expands the archive and `
|
|
1253
|
+
+ `weighs the UNCOMPRESSED total, so ${formatBytes(wireBytes)} on the wire does not `
|
|
1254
|
+
+ `get this under the limit — it will refuse with "Zip file uncompressed size exceeds 30MB". `
|
|
1255
|
+
+ `Remove files from the bundle; compressing harder cannot help.`);
|
|
1256
|
+
}
|
|
1257
|
+
// The title/name divergence this branch discloses above, now stated as a
|
|
1258
|
+
// FACT rather than as a caveat, because the archive can be read after
|
|
1259
|
+
// all. A ZIP whose inner SKILL.md declares a different name publishes a
|
|
1260
|
+
// skill whose title and versions disagree — and that divergence is what
|
|
1261
|
+
// makes a title-keyed lookup unsafe, so it is worth naming at the moment
|
|
1262
|
+
// it is minted rather than diagnosing later.
|
|
1263
|
+
if (inspected.declaredName !== undefined && inspected.declaredName !== displayTitle) {
|
|
1264
|
+
logger.warn(`Title/name divergence: this uploads with display title "${displayTitle}", but the `
|
|
1265
|
+
+ `SKILL.md inside declares name "${inspected.declaredName}". Every version will carry `
|
|
1266
|
+
+ `the declared name. Pass --title "${inspected.declaredName}" to make them agree.`);
|
|
1267
|
+
}
|
|
1268
|
+
// 🚨 The SAME function the directory lane calls, over the archive's own
|
|
1269
|
+
// markdown. Until this line existed, `install <zip>` ran NONE of the
|
|
1270
|
+
// portability checks its `--help` promises of "every markdown document in
|
|
1271
|
+
// the bundle" — the archive went straight to `sendSkillUpload`, so the
|
|
1272
|
+
// adopter finding that produced the family (10 of 54 skills referencing a
|
|
1273
|
+
// path outside their own tree, published green and unable to run) was
|
|
1274
|
+
// invisible on the lane most likely to carry a hand-built bundle.
|
|
1275
|
+
//
|
|
1276
|
+
// ⚠️ NO validation config, and that is a real narrowing, stated in the
|
|
1277
|
+
// help text. `validation.allow` / `validation.severity` are resolved by
|
|
1278
|
+
// walking up from a skill's SKILL.md to its governing project — and an
|
|
1279
|
+
// archive member has no path on disk to walk up from, the same reason a
|
|
1280
|
+
// config-declared eval-suite location is unreadable here. So a waiver that
|
|
1281
|
+
// silences `vat skills build` does NOT silence this lane. The checks only
|
|
1282
|
+
// warn, so the cost of the narrowing is noise, never a blocked publish;
|
|
1283
|
+
// the cost of skipping them was silence on a documented promise.
|
|
1284
|
+
warnUnportableReferences(inspected.documents, inspected.bundleRoot, undefined, logger);
|
|
1285
|
+
if (inspected.unreadable.length > 0) {
|
|
1286
|
+
const named = inspected.unreadable.map(({ entry, reason }) => `${entry} (${reason})`).join(', ');
|
|
1287
|
+
logger.warn(`${String(inspected.unreadable.length)} archive member(s) could not be inflated and were `
|
|
1288
|
+
+ `not checked: ${named}`);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Delete every version handed in, and keep going when one refuses.
|
|
1293
|
+
*
|
|
1294
|
+
* 🚨 **One refusal is a fact about ONE version.** This loop used to return on the
|
|
1295
|
+
* first one, so every version after it was never ATTEMPTED — not failed, not
|
|
1296
|
+
* reported, unexamined. Deleting a workspace skill requires deleting every
|
|
1297
|
+
* version first, so the operator was left with a skill that could not be deleted,
|
|
1298
|
+
* a report that named one problem out of an unknown number, and no way to tell
|
|
1299
|
+
* from the output which versions were still there. A transient refusal on version
|
|
1300
|
+
* 2 of 30 hid the state of the other 28.
|
|
1301
|
+
*
|
|
1302
|
+
* The sweep therefore ATTEMPTS all of them and reports both lists. The caller
|
|
1303
|
+
* decides what the outcome means: some deleted plus some failed is a run that
|
|
1304
|
+
* happened and went wrong (exit 1, with the record); nothing deleted at all is
|
|
1305
|
+
* the ending the command's help documents as exit 2.
|
|
1306
|
+
*
|
|
1307
|
+
* ⛔ It deliberately does NOT stop early on a repeated failure. A "the API is
|
|
1308
|
+
* clearly down, give up" heuristic is how the abandoned-versions defect reads
|
|
1309
|
+
* from inside: the whole value here is that every version's state is KNOWN when
|
|
1310
|
+
* the command ends.
|
|
1311
|
+
*/
|
|
1312
|
+
export async function deleteEveryVersion(client, skillId, versions, logger) {
|
|
1313
|
+
const deleted = [];
|
|
1314
|
+
const failures = [];
|
|
1315
|
+
for (const version of versions) {
|
|
1316
|
+
try {
|
|
1317
|
+
await client.deleteSkillVersion(skillId, version);
|
|
1160
1318
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
// it is minted rather than diagnosing later.
|
|
1167
|
-
if (inspected.declaredName !== undefined && inspected.declaredName !== displayTitle) {
|
|
1168
|
-
logger.warn(`Title/name divergence: this uploads with display title "${displayTitle}", but the `
|
|
1169
|
-
+ `SKILL.md inside declares name "${inspected.declaredName}". Every version will carry `
|
|
1170
|
-
+ `the declared name. Pass --title "${inspected.declaredName}" to make them agree.`);
|
|
1319
|
+
catch (error) {
|
|
1320
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1321
|
+
failures.push({ version, reason });
|
|
1322
|
+
logger.info(` ⚠ version ${version} was not deleted: ${reason}`);
|
|
1323
|
+
continue;
|
|
1171
1324
|
}
|
|
1325
|
+
deleted.push(version);
|
|
1326
|
+
logger.info(` Deleted version ${version}`);
|
|
1172
1327
|
}
|
|
1173
|
-
return
|
|
1328
|
+
return { deleted, failures };
|
|
1329
|
+
}
|
|
1330
|
+
/**
|
|
1331
|
+
* Every version the sweep could not delete, and why — the one sentence both the
|
|
1332
|
+
* published report and the exit-2 throw are built from, so the two endings never
|
|
1333
|
+
* describe the same run differently.
|
|
1334
|
+
*/
|
|
1335
|
+
export function describeVersionSweepFailures(failures) {
|
|
1336
|
+
return failures.map(failure => `${failure.version}: ${failure.reason}`).join('; ');
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* The document a `--all` run publishes when it destroyed something and then did
|
|
1340
|
+
* not finish.
|
|
1341
|
+
*
|
|
1342
|
+
* 🔑 The deleted list is a RECORD, not a progress counter. Version deletion is
|
|
1343
|
+
* irreversible, so a failure part-way through leaves a workspace nobody can
|
|
1344
|
+
* reconstruct — and throwing here would end on `handleCommandError`'s exit 2
|
|
1345
|
+
* ("the run could not happen") and DISCARD the document. It happened, and it
|
|
1346
|
+
* destroyed things the operator now has no other list of. So the lists travel
|
|
1347
|
+
* with the failure and the run ends 1: it happened, and its outcome is wrong.
|
|
1348
|
+
*
|
|
1349
|
+
* `failedVersions` is the other half, and the half a re-run needs: what is still
|
|
1350
|
+
* there. Without it the operator knows what they lost and not what they still
|
|
1351
|
+
* have to deal with.
|
|
1352
|
+
*/
|
|
1353
|
+
export function reportHalfDeleted(report) {
|
|
1354
|
+
const { skillId, deletedVersions, failedVersions } = report;
|
|
1355
|
+
return orgCommandFailure({
|
|
1356
|
+
id: skillId,
|
|
1357
|
+
deleted: false,
|
|
1358
|
+
deletedVersions,
|
|
1359
|
+
failedVersions,
|
|
1360
|
+
error: report.error,
|
|
1361
|
+
note: `${String(deletedVersions.length)} version(s) of ${skillId} were deleted and cannot be `
|
|
1362
|
+
+ `restored; ${String(failedVersions.length)} could not be deleted and are still there. `
|
|
1363
|
+
+ 'The skill itself still exists — the API refuses a skill that still has versions. '
|
|
1364
|
+
+ 'Re-run `--all` once the cause is cleared: it will attempt only what is left.',
|
|
1365
|
+
});
|
|
1174
1366
|
}
|
|
1175
1367
|
// ── Commands ───────────────────────────────────────────────────────────
|
|
1176
1368
|
export function createOrgSkillsCommand() {
|
|
@@ -1279,9 +1471,16 @@ Description:
|
|
|
1279
1471
|
the non-portable reference, non-portable command, and unqualified MCP tool-name
|
|
1280
1472
|
checks — the ones that catch a skill referencing a path outside its own tree,
|
|
1281
1473
|
which cannot resolve once the API publishes it alone. These WARN and never
|
|
1282
|
-
block
|
|
1283
|
-
|
|
1284
|
-
|
|
1474
|
+
block. Run \`vat audit <dir>\` for the full report.
|
|
1475
|
+
|
|
1476
|
+
A ZIP faces the same three checks: its markdown members are read out of the
|
|
1477
|
+
archive and run through them, so a hand-built bundle is not the quiet lane.
|
|
1478
|
+
The one difference is the config. On a DIRECTORY, \`validation.allow\` /
|
|
1479
|
+
\`validation.severity\` from the governing vibe-agent-toolkit.config.yaml are
|
|
1480
|
+
honoured, so a waiver that makes \`vat skills build\` green makes this quiet
|
|
1481
|
+
too. On a ZIP there is no directory to resolve that config from — the same
|
|
1482
|
+
reason a config-declared eval-suite location is invisible here — so the checks
|
|
1483
|
+
run UNWAIVED and a warning you have already waived elsewhere will still print.
|
|
1285
1484
|
|
|
1286
1485
|
There are TWO size gates and a ZIP faces both. The REQUEST gate weighs the
|
|
1287
1486
|
multipart body — file bytes plus about 156 bytes of framing per file — against
|
|
@@ -1325,14 +1524,11 @@ Examples:
|
|
|
1325
1524
|
// travels with the failure, and the run ends 1: it happened, and its
|
|
1326
1525
|
// outcome is wrong.
|
|
1327
1526
|
const deletedVersions = [];
|
|
1328
|
-
const halfDeleted = (error) =>
|
|
1329
|
-
|
|
1330
|
-
deleted: false,
|
|
1527
|
+
const halfDeleted = (error, failedVersions) => reportHalfDeleted({
|
|
1528
|
+
skillId,
|
|
1331
1529
|
deletedVersions,
|
|
1530
|
+
failedVersions,
|
|
1332
1531
|
error: error instanceof Error ? error.message : String(error),
|
|
1333
|
-
note: `${String(deletedVersions.length)} version(s) of ${skillId} were deleted before this `
|
|
1334
|
-
+ 'failed and cannot be restored. The skill itself still exists. Re-run '
|
|
1335
|
-
+ '`--all` once the cause is cleared; the versions listed here are already gone.',
|
|
1336
1532
|
});
|
|
1337
1533
|
if (options.all) {
|
|
1338
1534
|
const versions = await autopaginateSkills(client, skillVersionsPath(skillId));
|
|
@@ -1340,21 +1536,25 @@ Examples:
|
|
|
1340
1536
|
// "Found …", not "Deleting …": nothing has been deleted at this point
|
|
1341
1537
|
// and the very next call can be refused. Cf. `installFromLocal`.
|
|
1342
1538
|
logger.info(`Found ${String(versionData.length)} version(s) of ${skillId} to delete first`);
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1539
|
+
// ATTEMPTS every version, whatever any one of them answers. See
|
|
1540
|
+
// `deleteEveryVersion`: returning on the first refusal left the rest
|
|
1541
|
+
// unexamined, and the skill undeletable with no record of what remained.
|
|
1542
|
+
const sweep = await deleteEveryVersion(client, skillId, versionData.map(v => v.version), logger);
|
|
1543
|
+
deletedVersions.push(...sweep.deleted);
|
|
1544
|
+
if (sweep.failures.length > 0) {
|
|
1545
|
+
const detail = describeVersionSweepFailures(sweep.failures);
|
|
1546
|
+
// Nothing was destroyed, so there is no record worth publishing and
|
|
1547
|
+
// "could not happen" (exit 2, via the throw) is the honest ending —
|
|
1548
|
+
// the same rule as before, now decided on the WHOLE sweep rather than
|
|
1549
|
+
// on its first refusal.
|
|
1550
|
+
if (deletedVersions.length === 0) {
|
|
1551
|
+
throw new Error(`No version of ${skillId} could be deleted, so the skill was left alone. `
|
|
1552
|
+
+ `${String(sweep.failures.length)} attempt(s) failed — ${detail}`);
|
|
1346
1553
|
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
if (deletedVersions.length === 0)
|
|
1352
|
-
throw error;
|
|
1353
|
-
logger.info(` ⚠ version ${ver.version} was not deleted`);
|
|
1354
|
-
return halfDeleted(error);
|
|
1355
|
-
}
|
|
1356
|
-
deletedVersions.push(ver.version);
|
|
1357
|
-
logger.info(` Deleted version ${ver.version}`);
|
|
1554
|
+
// The skill delete is not attempted: the API refuses a skill that still
|
|
1555
|
+
// has versions, so it would spend a round trip to be told what is
|
|
1556
|
+
// already known here.
|
|
1557
|
+
return halfDeleted(new Error(detail), sweep.failures.map(failure => failure.version));
|
|
1358
1558
|
}
|
|
1359
1559
|
}
|
|
1360
1560
|
logger.info(`Deleting skill: ${skillId}`);
|
|
@@ -1369,7 +1569,9 @@ Examples:
|
|
|
1369
1569
|
catch (error) {
|
|
1370
1570
|
if (deletedVersions.length === 0)
|
|
1371
1571
|
throw error;
|
|
1372
|
-
|
|
1572
|
+
// The sweep completed — every version is gone — and the SKILL delete is
|
|
1573
|
+
// what failed, so nothing is left in `failedVersions`.
|
|
1574
|
+
return halfDeleted(error, []);
|
|
1373
1575
|
}
|
|
1374
1576
|
const deleted = reportDelete(raw, skillId, SKILL_DELETED_TYPES);
|
|
1375
1577
|
return deletedVersions.length === 0
|
|
@@ -1389,16 +1591,24 @@ Description:
|
|
|
1389
1591
|
delete every version and then the skill in one command; without it, delete the
|
|
1390
1592
|
versions yourself with \`vat claude org skills versions delete\` first.
|
|
1391
1593
|
|
|
1392
|
-
--all deletes irreversibly and in a loop
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1594
|
+
--all deletes irreversibly and in a loop, and it ATTEMPTS EVERY VERSION even
|
|
1595
|
+
when one refuses — one refusal is a fact about one version, not about the ones
|
|
1596
|
+
after it. When the sweep ends with anything left, the versions it destroyed are
|
|
1597
|
+
listed under deletedVersions, the ones still there under failedVersions, and
|
|
1598
|
+
the run exits 1 — the run happened, and its outcome is wrong. The skill itself
|
|
1599
|
+
is then left alone, because the API refuses a skill that still has versions.
|
|
1600
|
+
It exits 2 only when nothing was deleted at all.
|
|
1601
|
+
|
|
1602
|
+
A version delete whose response is lost is replayed, and the replay is answered
|
|
1603
|
+
404 because the first attempt already removed it. That 404 is read as the
|
|
1604
|
+
delete it is, not as a failure — the version appears under deletedVersions.
|
|
1396
1605
|
|
|
1397
1606
|
Exit Codes:
|
|
1398
1607
|
0 - The skill was deleted
|
|
1399
1608
|
1 - The run completed and the skill was NOT deleted: the API named a different
|
|
1400
|
-
outcome, or --all destroyed some versions and
|
|
1401
|
-
2 - The run could not happen: no API key,
|
|
1609
|
+
outcome, or --all destroyed some versions and could not destroy the rest
|
|
1610
|
+
2 - The run could not happen: no API key, the first request was refused, or
|
|
1611
|
+
--all deleted no version at all
|
|
1402
1612
|
|
|
1403
1613
|
Example:
|
|
1404
1614
|
$ vat claude org skills delete skill_abc123 --all
|
|
@@ -1470,10 +1680,8 @@ Example:
|
|
|
1470
1680
|
.action(async (skillId, source, options) => {
|
|
1471
1681
|
await executeOrgCommand('OrgSkillsVersionsAdd', options.debug, async ({ client, logger }) => {
|
|
1472
1682
|
const resolved = resolveSourceArgument(source);
|
|
1473
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from CLI arg
|
|
1474
1683
|
if (!existsSync(resolved))
|
|
1475
1684
|
throw new Error(`Source not found: ${resolved}`);
|
|
1476
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename -- path from CLI arg
|
|
1477
1685
|
if (!statSync(resolved).isDirectory()) {
|
|
1478
1686
|
// Name the asymmetry IN the refusal, not only in --help. `install`
|
|
1479
1687
|
// accepts a ZIP and this verb does not, so the operator most likely to
|