@vibe-agent-toolkit/cli 0.2.0-rc.10 → 0.2.0-rc.12
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 +3 -3
- package/dist/bin/supervise-cli.d.ts +45 -0
- package/dist/bin/supervise-cli.d.ts.map +1 -0
- package/dist/bin/supervise-cli.js +83 -0
- package/dist/bin/supervise-cli.js.map +1 -0
- package/dist/bin/vat +94 -40
- package/dist/bin/vat.d.ts +15 -4
- package/dist/bin/vat.d.ts.map +1 -1
- package/dist/bin/vat.js +94 -40
- package/dist/bin/vat.js.map +1 -1
- package/dist/bin.js +21 -29
- package/dist/bin.js.map +1 -1
- package/dist/command-tree.d.ts +45 -0
- package/dist/command-tree.d.ts.map +1 -0
- package/dist/command-tree.js +60 -0
- package/dist/command-tree.js.map +1 -0
- package/dist/commands/agent/build-schema.d.ts +100 -0
- package/dist/commands/agent/build-schema.d.ts.map +1 -0
- package/dist/commands/agent/build-schema.js +32 -0
- package/dist/commands/agent/build-schema.js.map +1 -0
- package/dist/commands/agent/build.d.ts +1 -0
- package/dist/commands/agent/build.d.ts.map +1 -1
- package/dist/commands/agent/build.js +63 -33
- package/dist/commands/agent/build.js.map +1 -1
- package/dist/commands/agent/import-schema.d.ts +75 -0
- package/dist/commands/agent/import-schema.d.ts.map +1 -0
- package/dist/commands/agent/import-schema.js +25 -0
- package/dist/commands/agent/import-schema.js.map +1 -0
- package/dist/commands/agent/import.d.ts.map +1 -1
- package/dist/commands/agent/import.js +33 -27
- package/dist/commands/agent/import.js.map +1 -1
- package/dist/commands/agent/index.d.ts.map +1 -1
- package/dist/commands/agent/index.js +132 -37
- package/dist/commands/agent/index.js.map +1 -1
- package/dist/commands/agent/install-path.d.ts.map +1 -1
- package/dist/commands/agent/install-path.js +2 -1
- package/dist/commands/agent/install-path.js.map +1 -1
- package/dist/commands/agent/install-schema.d.ts +89 -0
- package/dist/commands/agent/install-schema.d.ts.map +1 -0
- package/dist/commands/agent/install-schema.js +29 -0
- package/dist/commands/agent/install-schema.js.map +1 -0
- package/dist/commands/agent/install.d.ts +7 -1
- package/dist/commands/agent/install.d.ts.map +1 -1
- package/dist/commands/agent/install.js +78 -108
- package/dist/commands/agent/install.js.map +1 -1
- package/dist/commands/agent/installed-schema.d.ts +140 -0
- package/dist/commands/agent/installed-schema.d.ts.map +1 -0
- package/dist/commands/agent/installed-schema.js +36 -0
- package/dist/commands/agent/installed-schema.js.map +1 -0
- package/dist/commands/agent/installed.d.ts +1 -1
- package/dist/commands/agent/installed.d.ts.map +1 -1
- package/dist/commands/agent/installed.js +104 -75
- package/dist/commands/agent/installed.js.map +1 -1
- package/dist/commands/agent/list-schema.d.ts +128 -0
- package/dist/commands/agent/list-schema.d.ts.map +1 -0
- package/dist/commands/agent/list-schema.js +34 -0
- package/dist/commands/agent/list-schema.js.map +1 -0
- package/dist/commands/agent/list.d.ts +4 -3
- package/dist/commands/agent/list.d.ts.map +1 -1
- package/dist/commands/agent/list.js +50 -37
- package/dist/commands/agent/list.js.map +1 -1
- package/dist/commands/agent/run.d.ts +3 -0
- package/dist/commands/agent/run.d.ts.map +1 -1
- package/dist/commands/agent/run.js +8 -3
- package/dist/commands/agent/run.js.map +1 -1
- package/dist/commands/agent/uninstall-schema.d.ts +89 -0
- package/dist/commands/agent/uninstall-schema.d.ts.map +1 -0
- package/dist/commands/agent/uninstall-schema.js +29 -0
- package/dist/commands/agent/uninstall-schema.js.map +1 -0
- package/dist/commands/agent/uninstall.d.ts +5 -1
- package/dist/commands/agent/uninstall.d.ts.map +1 -1
- package/dist/commands/agent/uninstall.js +50 -38
- package/dist/commands/agent/uninstall.js.map +1 -1
- package/dist/commands/agent/validate-schema.d.ts +129 -0
- package/dist/commands/agent/validate-schema.d.ts.map +1 -0
- package/dist/commands/agent/validate-schema.js +35 -0
- package/dist/commands/agent/validate-schema.js.map +1 -0
- package/dist/commands/agent/validate.d.ts +6 -0
- package/dist/commands/agent/validate.d.ts.map +1 -1
- package/dist/commands/agent/validate.js +64 -36
- package/dist/commands/agent/validate.js.map +1 -1
- package/dist/commands/ard/emit-schema.d.ts +108 -0
- package/dist/commands/ard/emit-schema.d.ts.map +1 -0
- package/dist/commands/ard/emit-schema.js +37 -0
- package/dist/commands/ard/emit-schema.js.map +1 -0
- package/dist/commands/ard/emit.d.ts +31 -63
- package/dist/commands/ard/emit.d.ts.map +1 -1
- package/dist/commands/ard/emit.js +124 -68
- package/dist/commands/ard/emit.js.map +1 -1
- package/dist/commands/ard/index.d.ts.map +1 -1
- package/dist/commands/ard/index.js +17 -10
- package/dist/commands/ard/index.js.map +1 -1
- package/dist/commands/audit/compat-lane-findings.d.ts +65 -0
- package/dist/commands/audit/compat-lane-findings.d.ts.map +1 -0
- package/dist/commands/audit/compat-lane-findings.js +72 -0
- package/dist/commands/audit/compat-lane-findings.js.map +1 -0
- package/dist/commands/audit/distributed-tree.d.ts +2 -2
- package/dist/commands/audit/distributed-tree.d.ts.map +1 -1
- package/dist/commands/audit/distributed-tree.js +23 -12
- package/dist/commands/audit/distributed-tree.js.map +1 -1
- package/dist/commands/audit/git-url-clone.d.ts +15 -7
- package/dist/commands/audit/git-url-clone.d.ts.map +1 -1
- package/dist/commands/audit/git-url-clone.js +85 -42
- package/dist/commands/audit/git-url-clone.js.map +1 -1
- package/dist/commands/audit/hierarchical-output.d.ts +28 -4
- package/dist/commands/audit/hierarchical-output.d.ts.map +1 -1
- package/dist/commands/audit/hierarchical-output.js +44 -27
- package/dist/commands/audit/hierarchical-output.js.map +1 -1
- package/dist/commands/audit/scan-population.d.ts.map +1 -1
- package/dist/commands/audit/scan-population.js +2 -1
- package/dist/commands/audit/scan-population.js.map +1 -1
- package/dist/commands/audit-schema.d.ts +1247 -0
- package/dist/commands/audit-schema.d.ts.map +1 -0
- package/dist/commands/audit-schema.js +139 -0
- package/dist/commands/audit-schema.js.map +1 -0
- package/dist/commands/audit-settings-schema.d.ts +417 -0
- package/dist/commands/audit-settings-schema.d.ts.map +1 -0
- package/dist/commands/audit-settings-schema.js +77 -0
- package/dist/commands/audit-settings-schema.js.map +1 -0
- package/dist/commands/audit-settings.d.ts +28 -9
- package/dist/commands/audit-settings.d.ts.map +1 -1
- package/dist/commands/audit-settings.js +215 -151
- package/dist/commands/audit-settings.js.map +1 -1
- package/dist/commands/audit.d.ts +72 -33
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +415 -397
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/build.d.ts +61 -4
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +176 -190
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/cache/clear-schema.d.ts +111 -0
- package/dist/commands/cache/clear-schema.d.ts.map +1 -0
- package/dist/commands/cache/clear-schema.js +37 -0
- package/dist/commands/cache/clear-schema.js.map +1 -0
- package/dist/commands/cache/clear.d.ts +28 -26
- package/dist/commands/cache/clear.d.ts.map +1 -1
- package/dist/commands/cache/clear.js +108 -103
- package/dist/commands/cache/clear.js.map +1 -1
- package/dist/commands/cache/index.d.ts.map +1 -1
- package/dist/commands/cache/index.js +13 -7
- package/dist/commands/cache/index.js.map +1 -1
- package/dist/commands/claude/claude-config.d.ts +23 -6
- package/dist/commands/claude/claude-config.d.ts.map +1 -1
- package/dist/commands/claude/claude-config.js +29 -15
- package/dist/commands/claude/claude-config.js.map +1 -1
- package/dist/commands/claude/context.d.ts +87 -2
- package/dist/commands/claude/context.d.ts.map +1 -1
- package/dist/commands/claude/context.js +116 -57
- package/dist/commands/claude/context.js.map +1 -1
- package/dist/commands/claude/marketplace/changelog-utils.js +2 -2
- package/dist/commands/claude/marketplace/changelog-utils.js.map +1 -1
- package/dist/commands/claude/marketplace/git-publish.d.ts +14 -1
- package/dist/commands/claude/marketplace/git-publish.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/git-publish.js +135 -68
- package/dist/commands/claude/marketplace/git-publish.js.map +1 -1
- package/dist/commands/claude/marketplace/license-utils.d.ts +3 -5
- package/dist/commands/claude/marketplace/license-utils.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/license-utils.js +16 -7
- package/dist/commands/claude/marketplace/license-utils.js.map +1 -1
- package/dist/commands/claude/marketplace/publish-schema.d.ts +137 -0
- package/dist/commands/claude/marketplace/publish-schema.d.ts.map +1 -0
- package/dist/commands/claude/marketplace/publish-schema.js +32 -0
- package/dist/commands/claude/marketplace/publish-schema.js.map +1 -0
- package/dist/commands/claude/marketplace/publish-tree.d.ts +6 -0
- package/dist/commands/claude/marketplace/publish-tree.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/publish-tree.js +75 -17
- package/dist/commands/claude/marketplace/publish-tree.js.map +1 -1
- package/dist/commands/claude/marketplace/publish.d.ts +27 -0
- package/dist/commands/claude/marketplace/publish.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/publish.js +84 -50
- package/dist/commands/claude/marketplace/publish.js.map +1 -1
- package/dist/commands/claude/marketplace/validate-schema.d.ts +362 -0
- package/dist/commands/claude/marketplace/validate-schema.d.ts.map +1 -0
- package/dist/commands/claude/marketplace/validate-schema.js +67 -0
- package/dist/commands/claude/marketplace/validate-schema.js.map +1 -0
- package/dist/commands/claude/marketplace/validate.d.ts +40 -53
- package/dist/commands/claude/marketplace/validate.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/validate.js +358 -214
- package/dist/commands/claude/marketplace/validate.js.map +1 -1
- package/dist/commands/claude/org/api-keys.d.ts +3 -0
- package/dist/commands/claude/org/api-keys.d.ts.map +1 -1
- package/dist/commands/claude/org/api-keys.js +4 -5
- package/dist/commands/claude/org/api-keys.js.map +1 -1
- package/dist/commands/claude/org/code-analytics.js +1 -1
- package/dist/commands/claude/org/code-analytics.js.map +1 -1
- package/dist/commands/claude/org/cost.d.ts.map +1 -1
- package/dist/commands/claude/org/cost.js +11 -33
- package/dist/commands/claude/org/cost.js.map +1 -1
- package/dist/commands/claude/org/helpers.d.ts +40 -27
- package/dist/commands/claude/org/helpers.d.ts.map +1 -1
- package/dist/commands/claude/org/helpers.js +61 -66
- package/dist/commands/claude/org/helpers.js.map +1 -1
- package/dist/commands/claude/org/index.d.ts.map +1 -1
- package/dist/commands/claude/org/index.js +10 -4
- package/dist/commands/claude/org/index.js.map +1 -1
- package/dist/commands/claude/org/info.d.ts.map +1 -1
- package/dist/commands/claude/org/info.js +2 -3
- package/dist/commands/claude/org/info.js.map +1 -1
- package/dist/commands/claude/org/invites.d.ts +3 -0
- package/dist/commands/claude/org/invites.d.ts.map +1 -1
- package/dist/commands/claude/org/invites.js +5 -7
- package/dist/commands/claude/org/invites.js.map +1 -1
- package/dist/commands/claude/org/skills.d.ts +76 -21
- package/dist/commands/claude/org/skills.d.ts.map +1 -1
- package/dist/commands/claude/org/skills.js +273 -246
- package/dist/commands/claude/org/skills.js.map +1 -1
- package/dist/commands/claude/org/stubs-schema.d.ts +56 -0
- package/dist/commands/claude/org/stubs-schema.d.ts.map +1 -0
- package/dist/commands/claude/org/stubs-schema.js +23 -0
- package/dist/commands/claude/org/stubs-schema.js.map +1 -0
- package/dist/commands/claude/org/stubs.d.ts +8 -3
- package/dist/commands/claude/org/stubs.d.ts.map +1 -1
- package/dist/commands/claude/org/stubs.js +9 -9
- package/dist/commands/claude/org/stubs.js.map +1 -1
- package/dist/commands/claude/org/usage.d.ts.map +1 -1
- package/dist/commands/claude/org/usage.js +1 -2
- package/dist/commands/claude/org/usage.js.map +1 -1
- package/dist/commands/claude/org/users.d.ts +3 -0
- package/dist/commands/claude/org/users.d.ts.map +1 -1
- package/dist/commands/claude/org/users.js +6 -8
- package/dist/commands/claude/org/users.js.map +1 -1
- package/dist/commands/claude/org/workspaces.d.ts +3 -0
- package/dist/commands/claude/org/workspaces.d.ts.map +1 -1
- package/dist/commands/claude/org/workspaces.js +10 -15
- package/dist/commands/claude/org/workspaces.js.map +1 -1
- package/dist/commands/claude/plugin/build-schema.d.ts +642 -0
- package/dist/commands/claude/plugin/build-schema.d.ts.map +1 -0
- package/dist/commands/claude/plugin/build-schema.js +51 -0
- package/dist/commands/claude/plugin/build-schema.js.map +1 -0
- package/dist/commands/claude/plugin/build.d.ts +220 -45
- package/dist/commands/claude/plugin/build.d.ts.map +1 -1
- package/dist/commands/claude/plugin/build.js +466 -249
- package/dist/commands/claude/plugin/build.js.map +1 -1
- package/dist/commands/claude/plugin/helpers.d.ts +186 -24
- package/dist/commands/claude/plugin/helpers.d.ts.map +1 -1
- package/dist/commands/claude/plugin/helpers.js +110 -68
- package/dist/commands/claude/plugin/helpers.js.map +1 -1
- package/dist/commands/claude/plugin/install-schema.d.ts +144 -0
- package/dist/commands/claude/plugin/install-schema.d.ts.map +1 -0
- package/dist/commands/claude/plugin/install-schema.js +36 -0
- package/dist/commands/claude/plugin/install-schema.js.map +1 -0
- package/dist/commands/claude/plugin/install.d.ts +191 -11
- package/dist/commands/claude/plugin/install.d.ts.map +1 -1
- package/dist/commands/claude/plugin/install.js +688 -628
- package/dist/commands/claude/plugin/install.js.map +1 -1
- package/dist/commands/claude/plugin/kept-findings.d.ts +19 -0
- package/dist/commands/claude/plugin/kept-findings.d.ts.map +1 -0
- package/dist/commands/claude/plugin/kept-findings.js +24 -0
- package/dist/commands/claude/plugin/kept-findings.js.map +1 -0
- package/dist/commands/claude/plugin/list-schema.d.ts +223 -0
- package/dist/commands/claude/plugin/list-schema.d.ts.map +1 -0
- package/dist/commands/claude/plugin/list-schema.js +34 -0
- package/dist/commands/claude/plugin/list-schema.js.map +1 -0
- package/dist/commands/claude/plugin/list.d.ts +18 -0
- package/dist/commands/claude/plugin/list.d.ts.map +1 -1
- package/dist/commands/claude/plugin/list.js +53 -45
- package/dist/commands/claude/plugin/list.js.map +1 -1
- package/dist/commands/claude/plugin/npm-pack.d.ts +15 -0
- package/dist/commands/claude/plugin/npm-pack.d.ts.map +1 -0
- package/dist/commands/claude/plugin/npm-pack.js +39 -0
- package/dist/commands/claude/plugin/npm-pack.js.map +1 -0
- package/dist/commands/claude/plugin/plugin-changelog.d.ts +5 -1
- package/dist/commands/claude/plugin/plugin-changelog.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-changelog.js +9 -5
- package/dist/commands/claude/plugin/plugin-changelog.js.map +1 -1
- package/dist/commands/claude/plugin/plugin-files.d.ts +21 -2
- package/dist/commands/claude/plugin/plugin-files.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-files.js +65 -32
- package/dist/commands/claude/plugin/plugin-files.js.map +1 -1
- package/dist/commands/claude/plugin/plugin-validators.d.ts +13 -0
- package/dist/commands/claude/plugin/plugin-validators.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-validators.js +64 -16
- package/dist/commands/claude/plugin/plugin-validators.js.map +1 -1
- package/dist/commands/claude/plugin/tree-copy.d.ts.map +1 -1
- package/dist/commands/claude/plugin/tree-copy.js +63 -37
- package/dist/commands/claude/plugin/tree-copy.js.map +1 -1
- package/dist/commands/claude/plugin/uninstall-schema.d.ts +112 -0
- package/dist/commands/claude/plugin/uninstall-schema.d.ts.map +1 -0
- package/dist/commands/claude/plugin/uninstall-schema.js +28 -0
- package/dist/commands/claude/plugin/uninstall-schema.js.map +1 -0
- package/dist/commands/claude/plugin/uninstall.d.ts +57 -0
- package/dist/commands/claude/plugin/uninstall.d.ts.map +1 -1
- package/dist/commands/claude/plugin/uninstall.js +176 -64
- package/dist/commands/claude/plugin/uninstall.js.map +1 -1
- package/dist/commands/consistency-check.d.ts.map +1 -1
- package/dist/commands/consistency-check.js +8 -6
- 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 +26 -10
- package/dist/commands/corpus/index.js.map +1 -1
- package/dist/commands/corpus/report.d.ts +34 -16
- package/dist/commands/corpus/report.d.ts.map +1 -1
- package/dist/commands/corpus/report.js +36 -18
- package/dist/commands/corpus/report.js.map +1 -1
- package/dist/commands/corpus/runner.d.ts +25 -20
- package/dist/commands/corpus/runner.d.ts.map +1 -1
- package/dist/commands/corpus/runner.js +123 -67
- package/dist/commands/corpus/runner.js.map +1 -1
- package/dist/commands/corpus/scan-schema.d.ts +127 -0
- package/dist/commands/corpus/scan-schema.d.ts.map +1 -0
- package/dist/commands/corpus/scan-schema.js +31 -0
- package/dist/commands/corpus/scan-schema.js.map +1 -0
- package/dist/commands/corpus/scan.d.ts +31 -0
- package/dist/commands/corpus/scan.d.ts.map +1 -1
- package/dist/commands/corpus/scan.js +124 -50
- package/dist/commands/corpus/scan.js.map +1 -1
- package/dist/commands/corpus/seed.d.ts +11 -8
- package/dist/commands/corpus/seed.d.ts.map +1 -1
- package/dist/commands/corpus/seed.js +29 -11
- package/dist/commands/corpus/seed.js.map +1 -1
- package/dist/commands/doctor-render.d.ts +52 -0
- package/dist/commands/doctor-render.d.ts.map +1 -0
- package/dist/commands/doctor-render.js +110 -0
- package/dist/commands/doctor-render.js.map +1 -0
- package/dist/commands/doctor-schema.d.ts +191 -0
- package/dist/commands/doctor-schema.d.ts.map +1 -0
- package/dist/commands/doctor-schema.js +44 -0
- package/dist/commands/doctor-schema.js.map +1 -0
- package/dist/commands/doctor.d.ts +7 -62
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +126 -165
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/inventory-schema.d.ts +7297 -0
- package/dist/commands/inventory-schema.d.ts.map +1 -0
- package/dist/commands/inventory-schema.js +28 -0
- package/dist/commands/inventory-schema.js.map +1 -0
- package/dist/commands/inventory.d.ts +1 -1
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +89 -41
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/mcp/index.d.ts.map +1 -1
- package/dist/commands/mcp/index.js +15 -0
- package/dist/commands/mcp/index.js.map +1 -1
- package/dist/commands/mcp/list-collections-schema.d.ts +101 -0
- package/dist/commands/mcp/list-collections-schema.d.ts.map +1 -0
- package/dist/commands/mcp/list-collections-schema.js +22 -0
- package/dist/commands/mcp/list-collections-schema.js.map +1 -0
- package/dist/commands/mcp/list-collections.d.ts +1 -1
- package/dist/commands/mcp/list-collections.d.ts.map +1 -1
- package/dist/commands/mcp/list-collections.js +19 -17
- package/dist/commands/mcp/list-collections.js.map +1 -1
- package/dist/commands/mcp/serve.d.ts +5 -0
- package/dist/commands/mcp/serve.d.ts.map +1 -1
- package/dist/commands/mcp/serve.js +29 -15
- package/dist/commands/mcp/serve.js.map +1 -1
- package/dist/commands/okf/index.d.ts.map +1 -1
- package/dist/commands/okf/index.js +13 -10
- package/dist/commands/okf/index.js.map +1 -1
- package/dist/commands/okf/validate-schema.d.ts +171 -0
- package/dist/commands/okf/validate-schema.d.ts.map +1 -0
- package/dist/commands/okf/validate-schema.js +44 -0
- package/dist/commands/okf/validate-schema.js.map +1 -0
- package/dist/commands/okf/validate.d.ts +16 -145
- package/dist/commands/okf/validate.d.ts.map +1 -1
- package/dist/commands/okf/validate.js +63 -52
- package/dist/commands/okf/validate.js.map +1 -1
- package/dist/commands/orchestrator-schema.d.ts +419 -0
- package/dist/commands/orchestrator-schema.d.ts.map +1 -0
- package/dist/commands/orchestrator-schema.js +91 -0
- package/dist/commands/orchestrator-schema.js.map +1 -0
- package/dist/commands/phase-utils.d.ts +188 -220
- package/dist/commands/phase-utils.d.ts.map +1 -1
- package/dist/commands/phase-utils.js +210 -258
- package/dist/commands/phase-utils.js.map +1 -1
- package/dist/commands/positional-args.d.ts +13 -11
- package/dist/commands/positional-args.d.ts.map +1 -1
- package/dist/commands/positional-args.js +16 -15
- package/dist/commands/positional-args.js.map +1 -1
- package/dist/commands/rag/admin-schema.d.ts +152 -0
- package/dist/commands/rag/admin-schema.d.ts.map +1 -0
- package/dist/commands/rag/admin-schema.js +31 -0
- package/dist/commands/rag/admin-schema.js.map +1 -0
- package/dist/commands/rag/clear-command.d.ts.map +1 -1
- package/dist/commands/rag/clear-command.js +30 -15
- package/dist/commands/rag/clear-command.js.map +1 -1
- package/dist/commands/rag/command-helpers.d.ts +31 -7
- package/dist/commands/rag/command-helpers.d.ts.map +1 -1
- package/dist/commands/rag/command-helpers.js +41 -21
- package/dist/commands/rag/command-helpers.js.map +1 -1
- package/dist/commands/rag/index-command.d.ts +37 -48
- package/dist/commands/rag/index-command.d.ts.map +1 -1
- package/dist/commands/rag/index-command.js +80 -65
- package/dist/commands/rag/index-command.js.map +1 -1
- package/dist/commands/rag/index-schema.d.ts +107 -0
- package/dist/commands/rag/index-schema.d.ts.map +1 -0
- package/dist/commands/rag/index-schema.js +34 -0
- package/dist/commands/rag/index-schema.js.map +1 -0
- package/dist/commands/rag/index.d.ts.map +1 -1
- package/dist/commands/rag/index.js +88 -41
- package/dist/commands/rag/index.js.map +1 -1
- package/dist/commands/rag/query-command.d.ts +18 -4
- package/dist/commands/rag/query-command.d.ts.map +1 -1
- package/dist/commands/rag/query-command.js +42 -27
- package/dist/commands/rag/query-command.js.map +1 -1
- package/dist/commands/rag/query-schema.d.ts +363 -0
- package/dist/commands/rag/query-schema.d.ts.map +1 -0
- package/dist/commands/rag/query-schema.js +59 -0
- package/dist/commands/rag/query-schema.js.map +1 -0
- package/dist/commands/rag/stats-command.d.ts.map +1 -1
- package/dist/commands/rag/stats-command.js +19 -18
- package/dist/commands/rag/stats-command.js.map +1 -1
- package/dist/commands/resources/check-progress.d.ts +79 -13
- package/dist/commands/resources/check-progress.d.ts.map +1 -1
- package/dist/commands/resources/check-progress.js +112 -11
- package/dist/commands/resources/check-progress.js.map +1 -1
- package/dist/commands/resources/check-schema.d.ts +335 -0
- package/dist/commands/resources/check-schema.d.ts.map +1 -0
- package/dist/commands/resources/check-schema.js +104 -0
- package/dist/commands/resources/check-schema.js.map +1 -0
- package/dist/commands/resources/check-supervisor.d.ts +329 -71
- package/dist/commands/resources/check-supervisor.d.ts.map +1 -1
- package/dist/commands/resources/check-supervisor.js +507 -107
- package/dist/commands/resources/check-supervisor.js.map +1 -1
- package/dist/commands/resources/check.d.ts +88 -254
- package/dist/commands/resources/check.d.ts.map +1 -1
- package/dist/commands/resources/check.js +537 -310
- 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 +189 -103
- package/dist/commands/resources/index.js.map +1 -1
- package/dist/commands/resources/query-schema.d.ts +188 -0
- package/dist/commands/resources/query-schema.d.ts.map +1 -0
- package/dist/commands/resources/query-schema.js +48 -0
- package/dist/commands/resources/query-schema.js.map +1 -0
- package/dist/commands/resources/query.d.ts +18 -13
- package/dist/commands/resources/query.d.ts.map +1 -1
- package/dist/commands/resources/query.js +61 -49
- package/dist/commands/resources/query.js.map +1 -1
- package/dist/commands/resources/scan-schema.d.ts +195 -0
- package/dist/commands/resources/scan-schema.d.ts.map +1 -0
- package/dist/commands/resources/scan-schema.js +53 -0
- package/dist/commands/resources/scan-schema.js.map +1 -0
- package/dist/commands/resources/scan.d.ts +26 -3
- package/dist/commands/resources/scan.d.ts.map +1 -1
- package/dist/commands/resources/scan.js +51 -53
- package/dist/commands/resources/scan.js.map +1 -1
- package/dist/commands/resources/validate-schema.d.ts +326 -0
- package/dist/commands/resources/validate-schema.d.ts.map +1 -0
- package/dist/commands/resources/validate-schema.js +60 -0
- package/dist/commands/resources/validate-schema.js.map +1 -0
- package/dist/commands/resources/validate.d.ts +45 -169
- package/dist/commands/resources/validate.d.ts.map +1 -1
- package/dist/commands/resources/validate.js +221 -485
- package/dist/commands/resources/validate.js.map +1 -1
- package/dist/commands/skill/review-checklist.d.ts.map +1 -1
- package/dist/commands/skill/review-checklist.js +0 -1
- package/dist/commands/skill/review-checklist.js.map +1 -1
- package/dist/commands/skill/review-schema.d.ts +278 -0
- package/dist/commands/skill/review-schema.d.ts.map +1 -0
- package/dist/commands/skill/review-schema.js +46 -0
- package/dist/commands/skill/review-schema.js.map +1 -0
- package/dist/commands/skill/review.d.ts +8 -234
- package/dist/commands/skill/review.d.ts.map +1 -1
- package/dist/commands/skill/review.js +54 -77
- package/dist/commands/skill/review.js.map +1 -1
- package/dist/commands/skill/test/auth-flags.d.ts +3 -0
- package/dist/commands/skill/test/auth-flags.d.ts.map +1 -1
- package/dist/commands/skill/test/auth-flags.js +6 -2
- package/dist/commands/skill/test/auth-flags.js.map +1 -1
- package/dist/commands/skill/test/configure-schema.d.ts +67 -0
- package/dist/commands/skill/test/configure-schema.d.ts.map +1 -0
- package/dist/commands/skill/test/configure-schema.js +27 -0
- package/dist/commands/skill/test/configure-schema.js.map +1 -0
- package/dist/commands/skill/test/configure.d.ts +12 -5
- package/dist/commands/skill/test/configure.d.ts.map +1 -1
- package/dist/commands/skill/test/configure.js +101 -31
- package/dist/commands/skill/test/configure.js.map +1 -1
- package/dist/commands/skill/test/run-schema.d.ts +107 -0
- package/dist/commands/skill/test/run-schema.d.ts.map +1 -0
- package/dist/commands/skill/test/run-schema.js +36 -0
- package/dist/commands/skill/test/run-schema.js.map +1 -0
- package/dist/commands/skill/test/run.d.ts +3 -2
- package/dist/commands/skill/test/run.d.ts.map +1 -1
- package/dist/commands/skill/test/run.js +316 -155
- package/dist/commands/skill/test/run.js.map +1 -1
- package/dist/commands/skills/build-schema.d.ts +199 -0
- package/dist/commands/skills/build-schema.d.ts.map +1 -0
- package/dist/commands/skills/build-schema.js +55 -0
- package/dist/commands/skills/build-schema.js.map +1 -0
- package/dist/commands/skills/build.d.ts +95 -298
- package/dist/commands/skills/build.d.ts.map +1 -1
- package/dist/commands/skills/build.js +415 -818
- package/dist/commands/skills/build.js.map +1 -1
- package/dist/commands/skills/command-helpers.d.ts +5 -11
- package/dist/commands/skills/command-helpers.d.ts.map +1 -1
- package/dist/commands/skills/command-helpers.js +7 -17
- package/dist/commands/skills/command-helpers.js.map +1 -1
- package/dist/commands/skills/index.js +12 -6
- package/dist/commands/skills/index.js.map +1 -1
- package/dist/commands/skills/install-schema.d.ts +153 -0
- package/dist/commands/skills/install-schema.d.ts.map +1 -0
- package/dist/commands/skills/install-schema.js +44 -0
- package/dist/commands/skills/install-schema.js.map +1 -0
- package/dist/commands/skills/install.d.ts +76 -8
- package/dist/commands/skills/install.d.ts.map +1 -1
- package/dist/commands/skills/install.js +230 -194
- package/dist/commands/skills/install.js.map +1 -1
- package/dist/commands/skills/list-schema.d.ts +145 -0
- package/dist/commands/skills/list-schema.d.ts.map +1 -0
- package/dist/commands/skills/list-schema.js +37 -0
- package/dist/commands/skills/list-schema.js.map +1 -0
- package/dist/commands/skills/list.d.ts +39 -8
- package/dist/commands/skills/list.d.ts.map +1 -1
- package/dist/commands/skills/list.js +110 -122
- package/dist/commands/skills/list.js.map +1 -1
- package/dist/commands/skills/package-schema.d.ts +98 -0
- package/dist/commands/skills/package-schema.d.ts.map +1 -0
- package/dist/commands/skills/package-schema.js +32 -0
- package/dist/commands/skills/package-schema.js.map +1 -0
- package/dist/commands/skills/package.d.ts +85 -14
- package/dist/commands/skills/package.d.ts.map +1 -1
- package/dist/commands/skills/package.js +288 -207
- package/dist/commands/skills/package.js.map +1 -1
- package/dist/commands/skills/scope-guard.d.ts +27 -20
- package/dist/commands/skills/scope-guard.d.ts.map +1 -1
- package/dist/commands/skills/scope-guard.js +43 -28
- package/dist/commands/skills/scope-guard.js.map +1 -1
- package/dist/commands/skills/skill-discovery.d.ts +1 -1
- package/dist/commands/skills/skill-discovery.d.ts.map +1 -1
- package/dist/commands/skills/skill-discovery.js +40 -19
- package/dist/commands/skills/skill-discovery.js.map +1 -1
- package/dist/commands/skills/source-resolvers.d.ts +58 -8
- package/dist/commands/skills/source-resolvers.d.ts.map +1 -1
- package/dist/commands/skills/source-resolvers.js +113 -38
- 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 +31 -51
- package/dist/commands/skills/validate-command.js.map +1 -1
- package/dist/commands/skills/validate-schema.d.ts +199 -0
- package/dist/commands/skills/validate-schema.d.ts.map +1 -0
- package/dist/commands/skills/validate-schema.js +44 -0
- package/dist/commands/skills/validate-schema.js.map +1 -0
- package/dist/commands/skills/validate.d.ts +100 -136
- package/dist/commands/skills/validate.d.ts.map +1 -1
- package/dist/commands/skills/validate.js +257 -343
- package/dist/commands/skills/validate.js.map +1 -1
- package/dist/commands/validate.d.ts +17 -5
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +139 -94
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/verify.d.ts +121 -110
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +230 -294
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/report-schemas.d.ts +12398 -35
- package/dist/report-schemas.d.ts.map +1 -1
- package/dist/report-schemas.js +624 -66
- package/dist/report-schemas.js.map +1 -1
- package/dist/skill-resolution/packaging-config.js +2 -2
- 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 +20 -13
- package/dist/skill-resolution/resolve-skill-reference.js.map +1 -1
- package/dist/utils/agent-discovery.d.ts +34 -1
- package/dist/utils/agent-discovery.d.ts.map +1 -1
- package/dist/utils/agent-discovery.js +80 -38
- package/dist/utils/agent-discovery.js.map +1 -1
- package/dist/utils/claude-context-lens.d.ts +13 -6
- package/dist/utils/claude-context-lens.d.ts.map +1 -1
- package/dist/utils/claude-context-lens.js +11 -12
- package/dist/utils/claude-context-lens.js.map +1 -1
- package/dist/utils/command-error-codes.d.ts +12 -0
- package/dist/utils/command-error-codes.d.ts.map +1 -0
- package/dist/utils/command-error-codes.js +12 -0
- package/dist/utils/command-error-codes.js.map +1 -0
- package/dist/utils/command-refusal.d.ts +58 -0
- package/dist/utils/command-refusal.d.ts.map +1 -0
- package/dist/utils/command-refusal.js +170 -0
- package/dist/utils/command-refusal.js.map +1 -0
- package/dist/utils/commander-ending.d.ts +40 -0
- package/dist/utils/commander-ending.d.ts.map +1 -0
- package/dist/utils/commander-ending.js +42 -0
- package/dist/utils/commander-ending.js.map +1 -0
- package/dist/utils/config-loader.d.ts +13 -8
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +84 -45
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/corpus-target.d.ts +1 -1
- package/dist/utils/corpus-target.d.ts.map +1 -1
- package/dist/utils/corpus-target.js +44 -5
- package/dist/utils/corpus-target.js.map +1 -1
- package/dist/utils/debug-diagnostics.d.ts +18 -0
- package/dist/utils/debug-diagnostics.d.ts.map +1 -0
- package/dist/utils/debug-diagnostics.js +23 -0
- package/dist/utils/debug-diagnostics.js.map +1 -0
- package/dist/utils/document-writer.d.ts +191 -0
- package/dist/utils/document-writer.d.ts.map +1 -0
- package/dist/utils/document-writer.js +319 -0
- package/dist/utils/document-writer.js.map +1 -0
- package/dist/utils/help-loader.d.ts +2 -2
- package/dist/utils/help-loader.js +2 -2
- package/dist/utils/install-plan.d.ts +99 -0
- package/dist/utils/install-plan.d.ts.map +1 -0
- package/dist/utils/install-plan.js +146 -0
- package/dist/utils/install-plan.js.map +1 -0
- package/dist/utils/issue-anchor.d.ts +1 -1
- package/dist/utils/issue-anchor.d.ts.map +1 -1
- package/dist/utils/issue-anchor.js.map +1 -1
- package/dist/utils/issue-rendering.d.ts +8 -3
- package/dist/utils/issue-rendering.d.ts.map +1 -1
- package/dist/utils/issue-rendering.js +4 -0
- package/dist/utils/issue-rendering.js.map +1 -1
- package/dist/utils/lens-population.d.ts +20 -0
- package/dist/utils/lens-population.d.ts.map +1 -0
- package/dist/utils/lens-population.js +15 -0
- package/dist/utils/lens-population.js.map +1 -0
- package/dist/utils/marketplace-io.d.ts +63 -0
- package/dist/utils/marketplace-io.d.ts.map +1 -0
- package/dist/utils/marketplace-io.js +63 -0
- package/dist/utils/marketplace-io.js.map +1 -0
- package/dist/utils/operator-notices.d.ts +97 -0
- package/dist/utils/operator-notices.d.ts.map +1 -0
- package/dist/utils/operator-notices.js +115 -0
- package/dist/utils/operator-notices.js.map +1 -0
- package/dist/utils/optional-backend.d.ts +18 -15
- package/dist/utils/optional-backend.d.ts.map +1 -1
- package/dist/utils/optional-backend.js +22 -33
- package/dist/utils/optional-backend.js.map +1 -1
- package/dist/utils/output.d.ts +5 -43
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +8 -63
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/package-json.d.ts +3 -4
- package/dist/utils/package-json.d.ts.map +1 -1
- package/dist/utils/package-json.js +8 -8
- package/dist/utils/package-json.js.map +1 -1
- package/dist/utils/population-wiring.d.ts +31 -38
- package/dist/utils/population-wiring.d.ts.map +1 -1
- package/dist/utils/population-wiring.js +38 -32
- package/dist/utils/population-wiring.js.map +1 -1
- package/dist/utils/project-root-policy.d.ts +74 -1
- package/dist/utils/project-root-policy.d.ts.map +1 -1
- package/dist/utils/project-root-policy.js +146 -8
- package/dist/utils/project-root-policy.js.map +1 -1
- package/dist/utils/projection-lenses.d.ts +25 -7
- package/dist/utils/projection-lenses.d.ts.map +1 -1
- package/dist/utils/projection-lenses.js +20 -6
- package/dist/utils/projection-lenses.js.map +1 -1
- package/dist/utils/projection-query.d.ts +18 -11
- package/dist/utils/projection-query.d.ts.map +1 -1
- package/dist/utils/projection-query.js +47 -28
- package/dist/utils/projection-query.js.map +1 -1
- package/dist/utils/projection-store.d.ts +2 -2
- package/dist/utils/projection-store.d.ts.map +1 -1
- package/dist/utils/projection-store.js +74 -45
- package/dist/utils/projection-store.js.map +1 -1
- package/dist/utils/rag-database.d.ts +61 -0
- package/dist/utils/rag-database.d.ts.map +1 -0
- package/dist/utils/rag-database.js +178 -0
- package/dist/utils/rag-database.js.map +1 -0
- package/dist/utils/relation-limits.d.ts +7 -2
- package/dist/utils/relation-limits.d.ts.map +1 -1
- package/dist/utils/relation-limits.js +6 -1
- package/dist/utils/relation-limits.js.map +1 -1
- package/dist/utils/relativize-paths.d.ts +23 -0
- package/dist/utils/relativize-paths.d.ts.map +1 -1
- package/dist/utils/relativize-paths.js +32 -1
- package/dist/utils/relativize-paths.js.map +1 -1
- package/dist/utils/resource-loader.d.ts +78 -32
- package/dist/utils/resource-loader.d.ts.map +1 -1
- package/dist/utils/resource-loader.js +134 -66
- package/dist/utils/resource-loader.js.map +1 -1
- package/dist/utils/run-integrity.d.ts +64 -31
- package/dist/utils/run-integrity.d.ts.map +1 -1
- package/dist/utils/run-integrity.js +76 -35
- package/dist/utils/run-integrity.js.map +1 -1
- package/dist/utils/scope-locations.d.ts +7 -5
- package/dist/utils/scope-locations.d.ts.map +1 -1
- package/dist/utils/scope-locations.js +37 -12
- package/dist/utils/scope-locations.js.map +1 -1
- package/dist/utils/staging-dir.d.ts +7 -0
- package/dist/utils/staging-dir.d.ts.map +1 -0
- package/dist/utils/staging-dir.js +12 -0
- package/dist/utils/staging-dir.js.map +1 -0
- package/dist/utils/url-redact.d.ts +9 -0
- package/dist/utils/url-redact.d.ts.map +1 -1
- package/dist/utils/url-redact.js +13 -0
- package/dist/utils/url-redact.js.map +1 -1
- package/dist/utils/user-context-scanner.d.ts +3 -2
- package/dist/utils/user-context-scanner.d.ts.map +1 -1
- package/dist/utils/user-context-scanner.js +24 -4
- 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 +8 -14
- 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 +3 -3
- package/dist/utils/vat-bin-path.js.map +1 -1
- package/dist/utils/verdict-helpers.d.ts.map +1 -1
- package/dist/utils/verdict-helpers.js +5 -5
- package/dist/utils/verdict-helpers.js.map +1 -1
- package/docs/agent.md +347 -2
- package/docs/audit.md +312 -89
- package/docs/doctor.md +65 -19
- package/docs/index.md +571 -20
- package/docs/mcp.md +64 -12
- package/docs/rag.md +176 -48
- package/docs/resources.md +257 -71
- package/docs/skill-test.md +148 -19
- package/docs/skills.md +459 -174
- package/package.json +17 -20
- package/schemas/agent-build.json +268 -0
- package/schemas/agent-import.json +252 -0
- package/schemas/agent-install.json +260 -0
- package/schemas/agent-installed.json +287 -0
- package/schemas/agent-list.json +279 -0
- package/schemas/agent-uninstall.json +260 -0
- package/schemas/agent-validate.json +279 -0
- package/schemas/ard-emit.json +228 -107
- package/schemas/audit-settings.json +472 -0
- package/schemas/audit.json +635 -0
- package/schemas/cache-clear.json +273 -0
- package/schemas/claude-marketplace-publish.json +286 -0
- package/schemas/claude-marketplace-validate.json +352 -0
- package/schemas/claude-org-not-implemented.json +239 -0
- package/schemas/claude-plugin-build.json +446 -0
- package/schemas/claude-plugin-install.json +291 -0
- package/schemas/claude-plugin-list.json +326 -0
- package/schemas/claude-plugin-uninstall.json +272 -0
- package/schemas/corpus-audit.json +635 -0
- package/schemas/corpus-scan.json +293 -0
- package/schemas/doctor.json +299 -0
- package/schemas/inventory.json +982 -0
- package/schemas/mcp-list-collections.json +268 -0
- package/schemas/okf-validate.json +224 -106
- package/schemas/orchestrator.json +299 -0
- package/schemas/rag-clear.json +253 -0
- package/schemas/rag-index.json +273 -0
- package/schemas/rag-query.json +365 -0
- package/schemas/rag-stats.json +269 -0
- package/schemas/resources-check.json +280 -118
- package/schemas/resources-query.json +333 -0
- package/schemas/resources-scan.json +321 -0
- package/schemas/resources-validate.json +332 -0
- package/schemas/skill-review.json +224 -106
- package/schemas/skill-test-configure.json +256 -0
- package/schemas/skill-test-run.json +296 -0
- package/schemas/skills-build.json +325 -0
- package/schemas/skills-install.json +287 -0
- package/schemas/skills-list.json +283 -0
- package/schemas/skills-package.json +270 -0
- package/schemas/skills-validate.json +285 -0
- package/dist/commands/skills/shared.d.ts +0 -29
- package/dist/commands/skills/shared.d.ts.map +0 -1
- package/dist/commands/skills/shared.js +0 -33
- package/dist/commands/skills/shared.js.map +0 -1
- package/dist/utils/command-error.d.ts +0 -189
- package/dist/utils/command-error.d.ts.map +0 -1
- package/dist/utils/command-error.js +0 -230
- package/dist/utils/command-error.js.map +0 -1
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `vat claude org skills` — manage organization skills via Skills API.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
5
5
|
import { basename } from 'node:path';
|
|
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';
|
|
6
|
+
import { API_SKILL_MAX_UPLOAD_BYTES, collectNonPortableAssetReferenceIssues, collectNonPortableCommandIssues, collectUnqualifiedMcpToolIssues, declaredSkillNameIn, describeOversizeBundle, evalSuiteUnitPath, formatBytes, hostAddedToSkillZip, 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 { direntKindFollowingSync, isAbsoluteAnyPlatform,
|
|
9
|
+
import { ARCHIVE_REFUSED_CODE, archiveEntryPlace, direntKindFollowingSync, everywhere, forEachInOrder, isAbsoluteAnyPlatform, isArchiveEntryReadRefusal, isVatError, pathPresent, requireFollowedStatSync, safePath, toForwardSlash, toForwardSlashAnyPlatform, withTempDir } from '@vibe-agent-toolkit/utils';
|
|
10
10
|
import { Command } from 'commander';
|
|
11
11
|
import { resolveSkillPackagingConfig } from '../../../skill-resolution/packaging-config.js';
|
|
12
|
+
import { CommandRefusalError, errorMessageOf, refusalCodeOf } from '../../../utils/command-refusal.js';
|
|
13
|
+
import { leftoverIssueOf } from '../../../utils/document-writer.js';
|
|
14
|
+
import { requireSkillZipLayout } from '../../../utils/install-plan.js';
|
|
15
|
+
import { requireInputPath } from '../../../utils/project-root-policy.js';
|
|
12
16
|
import { downloadNpmPackage } from '../plugin/helpers.js';
|
|
13
17
|
import { autopaginateSkills, executeOrgCommand, orgCommandFailure } from './helpers.js';
|
|
14
18
|
const SKILL_ID_ARG = '<skill-id>';
|
|
@@ -47,7 +51,7 @@ function readSkillUploadResponse(endpoint, raw, fields) {
|
|
|
47
51
|
[fields.version, version], [fields.createdAt, createdAt],
|
|
48
52
|
].filter(([, value]) => value === undefined).map(([key]) => String(key));
|
|
49
53
|
const present = Object.keys(body).join(', ') || '(none)';
|
|
50
|
-
throw new
|
|
54
|
+
throw new CommandRefusalError('EXTERNAL_API_FAILED', `${endpoint} returned a body with no usable ${missing.join(', ')}. Keys present: ${present}. `
|
|
51
55
|
+ 'Refusing to report success for an upload whose identifiers cannot be read.');
|
|
52
56
|
}
|
|
53
57
|
return { id, displayTitle, version, createdAt };
|
|
@@ -86,7 +90,7 @@ export function readCreateSkillResponse(raw) {
|
|
|
86
90
|
* `skill_deleted` came back from a live `DELETE /v1/skills/{id}`;
|
|
87
91
|
* `skill_version_deleted` is the plausible spelling for the version endpoint and
|
|
88
92
|
* has never been seen. A single guessed string would make every version delete
|
|
89
|
-
* report `deleted: false` — and now exit
|
|
93
|
+
* report `deleted: false` — and now exit 2 — if the vendor spells it differently
|
|
90
94
|
* by one character. Accepting either keeps the check honest about what it knows:
|
|
91
95
|
* a body naming something that is neither is a real divergence worth failing on.
|
|
92
96
|
*/
|
|
@@ -106,6 +110,8 @@ export const SKILL_DELETED_TYPES = ['skill_deleted'];
|
|
|
106
110
|
* {@link readDeleteResponse} for why this is two and not one.
|
|
107
111
|
*/
|
|
108
112
|
export const SKILL_VERSION_DELETED_TYPES = ['skill_version_deleted', 'skill_deleted'];
|
|
113
|
+
/** A delete the API answered with an outcome other than a deletion: nothing was destroyed. */
|
|
114
|
+
const NOT_CONFIRMED = { kind: 'failed', cause: 'the API named an outcome other than a deletion' };
|
|
109
115
|
/**
|
|
110
116
|
* A delete's document, tagged as a FAILED run when the API said the thing was
|
|
111
117
|
* not deleted.
|
|
@@ -123,7 +129,7 @@ export const SKILL_VERSION_DELETED_TYPES = ['skill_version_deleted', 'skill_dele
|
|
|
123
129
|
*/
|
|
124
130
|
export function reportDelete(raw, requestedId, expectedTypes) {
|
|
125
131
|
const result = readDeleteResponse(raw, requestedId, expectedTypes);
|
|
126
|
-
return result.deleted ? result : orgCommandFailure(result);
|
|
132
|
+
return result.deleted ? result : orgCommandFailure(result, NOT_CONFIRMED);
|
|
127
133
|
}
|
|
128
134
|
/**
|
|
129
135
|
* A version delete's document — the same verdict as {@link reportDelete}, about
|
|
@@ -148,7 +154,7 @@ export function reportDelete(raw, requestedId, expectedTypes) {
|
|
|
148
154
|
export function reportVersionDelete(raw, skillId, version) {
|
|
149
155
|
const { deleted } = readDeleteResponse(raw, skillId, SKILL_VERSION_DELETED_TYPES);
|
|
150
156
|
const document = { id: skillId, version, deleted };
|
|
151
|
-
return deleted ? document : orgCommandFailure(document);
|
|
157
|
+
return deleted ? document : orgCommandFailure(document, NOT_CONFIRMED);
|
|
152
158
|
}
|
|
153
159
|
/**
|
|
154
160
|
* Add the versions a `--all` run destroyed to its report, preserving whatever
|
|
@@ -160,9 +166,9 @@ export function reportVersionDelete(raw, skillId, version) {
|
|
|
160
166
|
* skill's fields and publish the tag as part of the operator's document.
|
|
161
167
|
*/
|
|
162
168
|
export function mergeDeleteReport(result, deletedVersions) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return
|
|
169
|
+
if (!('orgCommandFailed' in result))
|
|
170
|
+
return { ...result, deletedVersions };
|
|
171
|
+
return orgCommandFailure({ ...result.document, deletedVersions }, result.outcome);
|
|
166
172
|
}
|
|
167
173
|
/** Read `POST /v1/skills/{id}/versions`. */
|
|
168
174
|
export function readSkillVersionResponse(raw) {
|
|
@@ -230,7 +236,7 @@ export function buildUploadBodyOrRefuse(fields, files, bundleRoot) {
|
|
|
230
236
|
if (multipart.body.length > API_SKILL_MAX_UPLOAD_BYTES) {
|
|
231
237
|
const sized = files.map(f => ({ path: bundleRelativeName(f.filename, bundleRoot), bytes: f.content.length }));
|
|
232
238
|
const measure = { of: 'upload-request', bytes: multipart.body.length };
|
|
233
|
-
throw new
|
|
239
|
+
throw new CommandRefusalError('USAGE_INVALID', `${describeOversizeBundle(sized, measure)}. The API will refuse this upload.`);
|
|
234
240
|
}
|
|
235
241
|
return multipart;
|
|
236
242
|
}
|
|
@@ -413,10 +419,10 @@ export function explainAnsweredNothing(error, bodyBytes) {
|
|
|
413
419
|
if (!(error instanceof ApiTransportError))
|
|
414
420
|
return error;
|
|
415
421
|
if (error.bytesSent === 0) {
|
|
416
|
-
return new
|
|
422
|
+
return new CommandRefusalError('EXTERNAL_API_FAILED', `${error.message}\nNo byte of the request left this machine, so nothing was created and `
|
|
417
423
|
+ 'there is nothing to clean up. Fix the connection and re-run the same command.', { cause: error });
|
|
418
424
|
}
|
|
419
|
-
return new
|
|
425
|
+
return new CommandRefusalError('EXTERNAL_API_FAILED', `${error.message}\nThe connection closed before the API answered, so this is not a verdict on `
|
|
420
426
|
+ `the upload. VAT had sent ${formatBytes(error.bytesSent)} of a ${formatBytes(bodyBytes)} `
|
|
421
427
|
+ `request body against a ${formatBytes(API_SKILL_MAX_UPLOAD_BYTES)} ceiling; the API has `
|
|
422
428
|
+ 'been observed to drop a connection near that ceiling instead of returning 413. Whether '
|
|
@@ -463,9 +469,9 @@ export function resolveSourceArgument(source) {
|
|
|
463
469
|
*
|
|
464
470
|
* Not a limit on what may be PUBLISHED — the API's own ceiling decides that, and
|
|
465
471
|
* a bigger document simply goes unread rather than refused. It bounds the
|
|
466
|
-
* allocations this module performs on attacker-supplied metadata:
|
|
467
|
-
* inflates
|
|
468
|
-
* megabyte is two orders of magnitude above any real skill document.
|
|
472
|
+
* allocations this module performs on attacker-supplied metadata: reading an
|
|
473
|
+
* entry inflates up to the size its header claims, and a header can claim
|
|
474
|
+
* anything. A megabyte is two orders of magnitude above any real skill document.
|
|
469
475
|
*
|
|
470
476
|
* ⚠️ It is a PER-ENTRY bound. The total is bounded separately, and more
|
|
471
477
|
* tightly: nothing is inflated at all until the archive's declared uncompressed
|
|
@@ -502,44 +508,69 @@ const MAX_INSPECTED_DOCUMENT_BYTES = 1024 * 1024;
|
|
|
502
508
|
*
|
|
503
509
|
* ⚠️ **Reading an entry is not free, and the docstring here used to claim it
|
|
504
510
|
* was** — "no zip-slip or zip-bomb surface is opened — the entries are read, not
|
|
505
|
-
* written" was true of the enumeration half and FALSE of the one
|
|
506
|
-
*
|
|
511
|
+
* written" was true of the enumeration half and FALSE of the one read of an
|
|
512
|
+
* entry, which inflates up to its declared size into memory. Worse, it ran BEFORE the
|
|
507
513
|
* caller's uncompressed-total gate, so the ceiling this function exists to
|
|
508
514
|
* enforce could not protect the inflation this function performed. Nothing is
|
|
509
515
|
* written to disk — that part stands — but the decompression is now ordered
|
|
510
516
|
* after the total is known and bounded by {@link MAX_INSPECTED_DOCUMENT_BYTES},
|
|
511
517
|
* so an archive declaring a 4 GiB SKILL.md is enumerated and never inflated.
|
|
518
|
+
*
|
|
519
|
+
* 🔑 **The archive is read through the ONE archive primitive, and held to its ONE
|
|
520
|
+
* entry policy.** An archive holding an entry VAT would refuse to extract — a
|
|
521
|
+
* symbolic link, a device, a name outside the archive, two entries that are one
|
|
522
|
+
* name (a name listed twice included) — or one past the archive limits, or one
|
|
523
|
+
* that is not a skill ZIP by the one layout rule (`requireSkillZipLayout`), is
|
|
524
|
+
* refused here (`INPUT_UNREADABLE`), before anything is sent: the same archive is
|
|
525
|
+
* refused by every verb that takes one. Only bytes the reader cannot PARSE as a
|
|
526
|
+
* ZIP at all are let through, announced (see the catch).
|
|
527
|
+
*
|
|
528
|
+
* @throws ArchiveRefusedError (`INPUT_UNREADABLE`) for an archive the entry policy
|
|
529
|
+
* or the archive limits refuse; FsFaultError side `source` when the OS refuses the read
|
|
512
530
|
*/
|
|
513
531
|
export async function inspectZipArchive(zipPath) {
|
|
514
|
-
//
|
|
515
|
-
|
|
516
|
-
//
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
let entries;
|
|
532
|
+
// Loaded on demand: the archive readers are needed by this one lane of the org commands.
|
|
533
|
+
const { ARCHIVE_LIMITS, archiveEntryRefusal, ArchiveRefusedError: Refused, openArchive, readArchiveFile, zipOfArchive } = await import('@vibe-agent-toolkit/utils/archive');
|
|
534
|
+
// Read ONCE: what is judged below, what is re-zipped and what an unreadable upload sends are these bytes.
|
|
535
|
+
const bytes = await readArchiveFile(zipPath, 'source', ARCHIVE_LIMITS);
|
|
536
|
+
const source = { bytes, label: toForwardSlash(zipPath) };
|
|
537
|
+
let opened;
|
|
521
538
|
try {
|
|
522
|
-
|
|
539
|
+
opened = await openArchive(source, { format: 'zip', limits: ARCHIVE_LIMITS });
|
|
523
540
|
}
|
|
524
541
|
catch (error) {
|
|
525
|
-
//
|
|
526
|
-
// is the authority on
|
|
527
|
-
// "our reader disagrees with your zip tool" into a failed publish. The
|
|
542
|
+
// Bytes that are no ZIP at all (`unreadable`: no ZIP signature anywhere) are
|
|
543
|
+
// not VAT's to block: the API is the authority on that upload, and the
|
|
528
544
|
// caller is told why, so "checks skipped" is never silent.
|
|
529
545
|
//
|
|
530
|
-
//
|
|
531
|
-
//
|
|
532
|
-
//
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
546
|
+
// That is the ONLY reason let through. A ZIP VAT will not take
|
|
547
|
+
// (`unsupported`: ZIP64, an ambiguous end record, a directory two readers
|
|
548
|
+
// would read differently, an end record padded past the 64 KiB a reader
|
|
549
|
+
// searches) stays loud, like an archive past the limits — were it passed
|
|
550
|
+
// on, a 20-byte edit or a 64 KiB append to any refused ZIP would send it
|
|
551
|
+
// with every check skipped. So does one the FILESYSTEM refuses (the path
|
|
552
|
+
// was readable a moment ago — the caller holds its bytes).
|
|
553
|
+
if (isUnparseableArchive(error))
|
|
554
|
+
return { archiveUnreadable: error.message, bytes };
|
|
555
|
+
throw error;
|
|
536
556
|
}
|
|
557
|
+
const refusal = archiveEntryRefusal(opened.entries);
|
|
558
|
+
if (refusal !== undefined)
|
|
559
|
+
throw new Refused(opened.label, refusal);
|
|
560
|
+
// The one layout rule for a skill ZIP, shared with the two install verbs: an archive that is
|
|
561
|
+
// not a skill by it is refused here, never sent for the API to make what it can of.
|
|
562
|
+
const skillRoot = requireSkillZipLayout(opened.label, opened.entries);
|
|
537
563
|
// PASS 1 — headers only. Nothing is decompressed while this runs, so both
|
|
538
564
|
// refusals the caller can reach are decided on metadata alone.
|
|
539
|
-
const
|
|
540
|
-
const
|
|
565
|
+
const hostAdded = opened.entries.map(entry => entry.name).filter(name => hostAddedToSkillZip(name));
|
|
566
|
+
const sent = {
|
|
567
|
+
fileBytes: bytes.length,
|
|
568
|
+
upload: () => zipOfArchive(source, { format: 'zip', limits: ARCHIVE_LIMITS, omit: (entry) => hostAddedToSkillZip(entry.name) }),
|
|
569
|
+
};
|
|
570
|
+
const files = opened.entries.filter(entry => entry.kind === 'file' && !hostAddedToSkillZip(entry.name));
|
|
571
|
+
const uncompressedBytes = files.reduce((sum, entry) => sum + entry.size, 0);
|
|
541
572
|
const neverUploaded = files
|
|
542
|
-
.map(entry => toForwardSlashAnyPlatform(entry.
|
|
573
|
+
.map(entry => toForwardSlashAnyPlatform(entry.name))
|
|
543
574
|
.filter(name => name.split('/').some(segment => NEVER_UPLOADED_DIR_NAMES.has(segment)));
|
|
544
575
|
// PASS 2 — the entries worth inflating, and only once the total says this
|
|
545
576
|
// archive is not already refused. An over-ceiling archive is about to be
|
|
@@ -547,23 +578,25 @@ export async function inspectZipArchive(zipPath) {
|
|
|
547
578
|
// on an upload that cannot happen.
|
|
548
579
|
if (uncompressedBytes > API_SKILL_MAX_UPLOAD_BYTES) {
|
|
549
580
|
return {
|
|
550
|
-
uncompressedBytes, declaredName: undefined, neverUploaded, documents: [], bundleRoot: undefined, unreadable: [],
|
|
581
|
+
uncompressedBytes, declaredName: undefined, neverUploaded, documents: [], bundleRoot: undefined, hostAdded, unreadable: [], ...sent,
|
|
551
582
|
};
|
|
552
583
|
}
|
|
553
|
-
const elected =
|
|
584
|
+
const elected = skillMdOf(files, skillRoot);
|
|
554
585
|
const unreadable = [];
|
|
555
586
|
return {
|
|
556
587
|
uncompressedBytes,
|
|
557
|
-
declaredName: declaredNameOf(elected, unreadable),
|
|
588
|
+
declaredName: declaredNameOf(opened, elected, unreadable),
|
|
558
589
|
neverUploaded,
|
|
559
|
-
documents: inflateMarkdownMembers(files, unreadable),
|
|
560
|
-
bundleRoot:
|
|
590
|
+
documents: inflateMarkdownMembers(opened, files, unreadable),
|
|
591
|
+
bundleRoot: skillRoot === '' ? undefined : skillRoot,
|
|
592
|
+
hostAdded,
|
|
561
593
|
unreadable,
|
|
594
|
+
...sent,
|
|
562
595
|
};
|
|
563
596
|
}
|
|
564
|
-
/**
|
|
565
|
-
function
|
|
566
|
-
return error
|
|
597
|
+
/** Whether `error` is the archive module saying the bytes are no ZIP at all — by its code and reason, never its prose. A ZIP it will not take, an entry that does not inflate included, is `unsupported`, and is not this. */
|
|
598
|
+
function isUnparseableArchive(error) {
|
|
599
|
+
return isVatError(error, ARCHIVE_REFUSED_CODE) && error.reason === 'unreadable';
|
|
567
600
|
}
|
|
568
601
|
/**
|
|
569
602
|
* Every markdown member of the archive, as an upload part.
|
|
@@ -577,19 +610,19 @@ function describeZipFailure(error) {
|
|
|
577
610
|
* {@link warnUnportableReferences} keeps ONE implementation of the checks — a
|
|
578
611
|
* second copy of the three collector calls is how the two lanes start disagreeing.
|
|
579
612
|
*
|
|
580
|
-
* An entry that will not inflate is SKIPPED
|
|
581
|
-
*
|
|
582
|
-
*
|
|
613
|
+
* An entry that will not inflate is SKIPPED here and named: the checks it feeds
|
|
614
|
+
* only ever warn. The upload is what refuses it — VAT sends its own ZIP of what
|
|
615
|
+
* it read, and it could not read this.
|
|
583
616
|
*/
|
|
584
|
-
function inflateMarkdownMembers(files, unreadable) {
|
|
617
|
+
function inflateMarkdownMembers(archive, files, unreadable) {
|
|
585
618
|
const documents = [];
|
|
586
619
|
for (const entry of files) {
|
|
587
|
-
const filename = toForwardSlashAnyPlatform(entry.
|
|
620
|
+
const filename = toForwardSlashAnyPlatform(entry.name);
|
|
588
621
|
if (!filename.toLowerCase().endsWith('.md'))
|
|
589
622
|
continue;
|
|
590
|
-
if (entry.
|
|
623
|
+
if (entry.size > MAX_INSPECTED_DOCUMENT_BYTES)
|
|
591
624
|
continue;
|
|
592
|
-
const content = inflateOrRecord(entry, unreadable);
|
|
625
|
+
const content = inflateOrRecord(archive, entry, unreadable);
|
|
593
626
|
if (content !== undefined)
|
|
594
627
|
documents.push({ fieldName: 'files[]', filename, content });
|
|
595
628
|
}
|
|
@@ -598,87 +631,42 @@ function inflateMarkdownMembers(files, unreadable) {
|
|
|
598
631
|
/**
|
|
599
632
|
* One member's bytes, or `undefined` with the refusal RECORDED.
|
|
600
633
|
*
|
|
601
|
-
*
|
|
602
|
-
* that can throw here:
|
|
603
|
-
* store/deflate,
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
634
|
+
* Reading an entry is the only decompression in this module, so it is the only
|
|
635
|
+
* thing that can throw here: the archive module refuses an entry with a bad CRC,
|
|
636
|
+
* a compression method that is not store/deflate, an encrypted entry, or one
|
|
637
|
+
* that does not hold what it declares (`ArchiveEntryReadError`, `ARCHIVE_ENTRY_UNREADABLE`).
|
|
638
|
+
* The inspection skips the member AND names it, so every finding the other
|
|
639
|
+
* members earn is still reported; the archive is not thereby accepted — the
|
|
640
|
+
* upload re-reads every entry for VAT's own ZIP and refuses this one, so nothing
|
|
641
|
+
* is sent.
|
|
607
642
|
*/
|
|
608
|
-
function inflateOrRecord(entry, unreadable) {
|
|
643
|
+
function inflateOrRecord(archive, entry, unreadable) {
|
|
609
644
|
try {
|
|
610
|
-
return
|
|
645
|
+
return archive.read(entry);
|
|
611
646
|
}
|
|
612
647
|
catch (error) {
|
|
648
|
+
if (!isArchiveEntryReadRefusal(error))
|
|
649
|
+
throw error;
|
|
613
650
|
// Once per member: the elected SKILL.md is asked for twice (its name, then
|
|
614
651
|
// its text), and one refusal is one fact.
|
|
615
|
-
const name = toForwardSlashAnyPlatform(entry.
|
|
652
|
+
const name = toForwardSlashAnyPlatform(entry.name);
|
|
616
653
|
if (!unreadable.some((failure) => failure.entry === name)) {
|
|
617
|
-
unreadable.push({ entry: name, reason:
|
|
654
|
+
unreadable.push({ entry: name, reason: error.message });
|
|
618
655
|
}
|
|
619
656
|
return undefined;
|
|
620
657
|
}
|
|
621
658
|
}
|
|
622
659
|
/**
|
|
623
|
-
* The
|
|
660
|
+
* The archive's own SKILL.md: the one at the place the layout rule found the skill
|
|
661
|
+
* (`requireSkillZipLayout`), which is the one whose `name` the API keys the skill by.
|
|
662
|
+
* Never a `SKILL.md` deeper in the bundle — a fixture a skill ships is not the skill.
|
|
624
663
|
*
|
|
625
|
-
*
|
|
626
|
-
* root
|
|
627
|
-
* fixes `/` as the entry separator, so this reads the format rather than handling
|
|
628
|
-
* a host path.
|
|
664
|
+
* @param files - The archive's file entries
|
|
665
|
+
* @param root - Where the skill is: `''` for the archive's top level, or its one top-level folder
|
|
629
666
|
*/
|
|
630
|
-
function
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
const cut = toForwardSlashAnyPlatform(entryName).lastIndexOf('/');
|
|
634
|
-
return cut === -1 ? undefined : entryName.slice(0, cut);
|
|
635
|
-
}
|
|
636
|
-
/**
|
|
637
|
-
* The SKILL.md nearest the archive root, which is the one whose `name` the API
|
|
638
|
-
* will key the skill by.
|
|
639
|
-
*
|
|
640
|
-
* 🪤 Compared on DEPTH, with name length only as a tiebreak. It used to compare
|
|
641
|
-
* `entryName.length` alone, on the reasoning that "a shortest-path comparison
|
|
642
|
-
* needs no separator at all" — but shortest string is not shallowest path:
|
|
643
|
-
* `a/b/SKILL.md` (12 chars, depth 2) beats `my-skill-bundle/SKILL.md` (24
|
|
644
|
-
* chars, depth 1), so a bundled FIXTURE supplied the name and the operator was
|
|
645
|
-
* advised to `--title` it. ZIP fixes `/` as the entry separator on every
|
|
646
|
-
* platform, so splitting on it is not path handling — it is reading the format.
|
|
647
|
-
*/
|
|
648
|
-
function electShallowestSkillMd(files) {
|
|
649
|
-
let elected;
|
|
650
|
-
for (const entry of files) {
|
|
651
|
-
if (basename(entry.entryName) !== 'SKILL.md')
|
|
652
|
-
continue;
|
|
653
|
-
if (elected !== undefined && !isShallower(entry.entryName, elected.entryName))
|
|
654
|
-
continue;
|
|
655
|
-
elected = entry;
|
|
656
|
-
}
|
|
657
|
-
return elected;
|
|
658
|
-
}
|
|
659
|
-
/** Fewer path segments wins; equal depth falls back to the shorter name. */
|
|
660
|
-
function isShallower(candidate, incumbent) {
|
|
661
|
-
const candidateDepth = zipEntryDepth(candidate);
|
|
662
|
-
const incumbentDepth = zipEntryDepth(incumbent);
|
|
663
|
-
return candidateDepth === incumbentDepth
|
|
664
|
-
? candidate.length < incumbent.length
|
|
665
|
-
: candidateDepth < incumbentDepth;
|
|
666
|
-
}
|
|
667
|
-
/**
|
|
668
|
-
* How many segments a ZIP entry name has.
|
|
669
|
-
*
|
|
670
|
-
* Counted rather than `split('/')`-ed because the linter — correctly, for
|
|
671
|
-
* FILESYSTEM paths — refuses that idiom: a host path's separator depends on the
|
|
672
|
-
* platform. A ZIP entry name's does not; the format fixes it as `/`. Counting
|
|
673
|
-
* the separator states that, and needs no exemption.
|
|
674
|
-
*/
|
|
675
|
-
function zipEntryDepth(entryName) {
|
|
676
|
-
let depth = 1;
|
|
677
|
-
for (const character of entryName) {
|
|
678
|
-
if (character === '/')
|
|
679
|
-
depth += 1;
|
|
680
|
-
}
|
|
681
|
-
return depth;
|
|
667
|
+
function skillMdOf(files, root) {
|
|
668
|
+
const place = root === '' ? 'SKILL.md' : `${root}/SKILL.md`;
|
|
669
|
+
return files.find(entry => archiveEntryPlace(entry.name).join('/') === place);
|
|
682
670
|
}
|
|
683
671
|
/**
|
|
684
672
|
* The frontmatter `name` inside the ELECTED entry — or `undefined`, including
|
|
@@ -695,10 +683,10 @@ function zipEntryDepth(entryName) {
|
|
|
695
683
|
* is already computed from headers) — see {@link inflateOrRecord}, which records
|
|
696
684
|
* the refusal so the operator learns why no name was read.
|
|
697
685
|
*/
|
|
698
|
-
function declaredNameOf(entry, unreadable) {
|
|
699
|
-
if (entry === undefined || entry.
|
|
686
|
+
function declaredNameOf(archive, entry, unreadable) {
|
|
687
|
+
if (entry === undefined || entry.size > MAX_INSPECTED_DOCUMENT_BYTES)
|
|
700
688
|
return undefined;
|
|
701
|
-
const content = inflateOrRecord(entry, unreadable);
|
|
689
|
+
const content = inflateOrRecord(archive, entry, unreadable);
|
|
702
690
|
return content === undefined ? undefined : declaredSkillNameIn(content.toString('utf8'));
|
|
703
691
|
}
|
|
704
692
|
async function sendSkillUpload(client, displayTitle, files, bundleRoot) {
|
|
@@ -712,7 +700,7 @@ async function sendSkillUpload(client, displayTitle, files, bundleRoot) {
|
|
|
712
700
|
function requireDeclaredName(skillMdPath) {
|
|
713
701
|
const declared = readDeclaredSkillName(skillMdPath);
|
|
714
702
|
if (declared === undefined) {
|
|
715
|
-
throw new
|
|
703
|
+
throw new CommandRefusalError('USAGE_INVALID', `SKILL.md has no usable frontmatter "name" field: ${skillMdPath}`);
|
|
716
704
|
}
|
|
717
705
|
return declared;
|
|
718
706
|
}
|
|
@@ -757,19 +745,21 @@ async function declaredTestInputPaths(skillDir) {
|
|
|
757
745
|
* named no path and said nothing about what to do. A dangling link produced the
|
|
758
746
|
* same shape of failure with `ENOENT`.
|
|
759
747
|
*
|
|
760
|
-
* `
|
|
748
|
+
* `requireFollowedStatSync` follows the link (its chain read first), which is the same thing the build-time size walk
|
|
761
749
|
* does to classify one — so both lanes reach the same verdict about the same
|
|
762
750
|
* entry.
|
|
763
751
|
*/
|
|
764
|
-
function resolvesToDirectory(entry, fullPath, relativePath) {
|
|
752
|
+
function resolvesToDirectory(entry, fullPath, relativePath, within) {
|
|
765
753
|
if (!entry.isSymbolicLink())
|
|
766
754
|
return false;
|
|
767
755
|
try {
|
|
768
|
-
|
|
756
|
+
// The chain is read beneath the skill directory first: a link to a network path is refused
|
|
757
|
+
// here, by name, before the kernel is asked to follow it.
|
|
758
|
+
return requireFollowedStatSync(fullPath, within).isDirectory();
|
|
769
759
|
}
|
|
770
760
|
catch (error) {
|
|
771
761
|
const cause = error instanceof Error ? error.message : String(error);
|
|
772
|
-
throw new
|
|
762
|
+
throw new CommandRefusalError('INPUT_UNREADABLE', `Cannot upload ${relativePath}: it is a symbolic link whose target could not be read `
|
|
773
763
|
+ `(${cause}). Replace it with the file or directory it should point at, or remove it.`);
|
|
774
764
|
}
|
|
775
765
|
}
|
|
@@ -809,7 +799,7 @@ function collectFiles(dir, base, testInput, collected) {
|
|
|
809
799
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
810
800
|
const fullPath = safePath.join(dir, entry.name);
|
|
811
801
|
const relativePath = safePath.relative(base, fullPath);
|
|
812
|
-
const linkedDirectory = resolvesToDirectory(entry, fullPath, relativePath);
|
|
802
|
+
const linkedDirectory = resolvesToDirectory(entry, fullPath, relativePath, base);
|
|
813
803
|
const directoryLike = entry.isDirectory() || linkedDirectory;
|
|
814
804
|
if (testInput.has(safePath.resolve(fullPath))
|
|
815
805
|
|| (directoryLike && NEVER_UPLOADED_DIR_NAMES.has(entry.name))) {
|
|
@@ -822,7 +812,7 @@ function collectFiles(dir, base, testInput, collected) {
|
|
|
822
812
|
else if (entry.isSymbolicLink()) {
|
|
823
813
|
// Whatever it points at. A link to a FILE used to fall through to the
|
|
824
814
|
// branch below and be read through — see this function's doc comment.
|
|
825
|
-
throw new
|
|
815
|
+
throw new CommandRefusalError('INPUT_UNREADABLE', `Cannot upload ${relativePath}: it is a symbolic link${linkedDirectory ? ' to a directory' : ''}, `
|
|
826
816
|
+ 'which a multipart upload cannot express. VAT will not publish the bytes it points '
|
|
827
817
|
+ 'at under this name: a link out of the skill directory would send whatever the '
|
|
828
818
|
+ 'target holds into a workspace every org member can read. Replace it with a real '
|
|
@@ -844,6 +834,17 @@ export async function collectSkillUploadFiles(skillDir) {
|
|
|
844
834
|
collectFiles(skillDir, skillDir, await declaredTestInputPaths(skillDir), collected);
|
|
845
835
|
return collected;
|
|
846
836
|
}
|
|
837
|
+
/**
|
|
838
|
+
* Stat a path the operator named, refusing through the one absent-vs-unreadable
|
|
839
|
+
* predicate: absent is the invocation's mistake (`USAGE_INVALID`, with this
|
|
840
|
+
* site's own sentence); anything else — an `EACCES` parent, an `ELOOP` — means
|
|
841
|
+
* whether it exists is unknown, the INPUT's refusal (`INPUT_UNREADABLE`).
|
|
842
|
+
* Never `existsSync`: it answers `false` for both.
|
|
843
|
+
*/
|
|
844
|
+
function statNamedPath(path, within, absentMessage) {
|
|
845
|
+
// Every path from the operator's named tree down to it is the operator's input.
|
|
846
|
+
return requireInputPath(path, within, { origin: 'argument', message: absentMessage }, everywhere('source'));
|
|
847
|
+
}
|
|
847
848
|
/**
|
|
848
849
|
* Package a skill directory into the multipart file set the API takes.
|
|
849
850
|
*
|
|
@@ -855,9 +856,7 @@ export async function collectSkillUploadFiles(skillDir) {
|
|
|
855
856
|
*/
|
|
856
857
|
async function prepareSkillUpload(skillDir, titleOverride, logger) {
|
|
857
858
|
const skillMdPath = safePath.join(skillDir, 'SKILL.md');
|
|
858
|
-
|
|
859
|
-
throw new Error(`SKILL.md not found in ${skillDir}. Is this a built skill directory?`);
|
|
860
|
-
}
|
|
859
|
+
statNamedPath(skillMdPath, skillDir, `SKILL.md not found in ${skillDir}. Is this a built skill directory?`);
|
|
861
860
|
// The skill's own declared name — not the directory it happens to sit in,
|
|
862
861
|
// which for a built or extracted tree carries no reliable identity.
|
|
863
862
|
const declaredName = requireDeclaredName(skillMdPath);
|
|
@@ -1019,19 +1018,19 @@ async function uploadSkillVersionDir(client, skillId, skillDir, logger) {
|
|
|
1019
1018
|
* untested — `packages/cli/src/commands/**` is coverage-excluded, so nothing in
|
|
1020
1019
|
* any report said so.
|
|
1021
1020
|
*/
|
|
1022
|
-
export function listNodeModulePackages(nodeModulesDir) {
|
|
1023
|
-
if (!
|
|
1021
|
+
export function listNodeModulePackages(nodeModulesDir, within) {
|
|
1022
|
+
if (!pathPresent(nodeModulesDir, { follow: within }, everywhere('source'), 'probe'))
|
|
1024
1023
|
return [];
|
|
1025
1024
|
const results = [];
|
|
1026
1025
|
// Followed: a workspace package under node_modules IS a symlink, and a walk
|
|
1027
1026
|
// that tested `isDirectory()` on the link skipped every one of them.
|
|
1028
1027
|
for (const entry of readdirSync(nodeModulesDir, { withFileTypes: true })) {
|
|
1029
|
-
if (direntKindFollowingSync(nodeModulesDir, entry) !== 'directory')
|
|
1028
|
+
if (direntKindFollowingSync(nodeModulesDir, entry, within) !== 'directory')
|
|
1030
1029
|
continue;
|
|
1031
1030
|
if (entry.name.startsWith('@')) {
|
|
1032
1031
|
const scopeDir = safePath.join(nodeModulesDir, entry.name);
|
|
1033
1032
|
for (const scopedEntry of readdirSync(scopeDir, { withFileTypes: true })) {
|
|
1034
|
-
if (direntKindFollowingSync(scopeDir, scopedEntry) === 'directory')
|
|
1033
|
+
if (direntKindFollowingSync(scopeDir, scopedEntry, within) === 'directory')
|
|
1035
1034
|
results.push(safePath.join(scopeDir, scopedEntry.name));
|
|
1036
1035
|
}
|
|
1037
1036
|
}
|
|
@@ -1046,17 +1045,27 @@ export function listNodeModulePackages(nodeModulesDir) {
|
|
|
1046
1045
|
* first, then scans node_modules for sub-packages that contain built skills.
|
|
1047
1046
|
*/
|
|
1048
1047
|
export function findSkillsDir(packageDir) {
|
|
1048
|
+
// Every probe is beneath the package directory: its links are read before the kernel follows them,
|
|
1049
|
+
// and a probe the OS refuses is the package's source fault, never "no skills here".
|
|
1050
|
+
const present = (path) => pathPresent(path, { follow: packageDir }, everywhere('source'), 'probe');
|
|
1049
1051
|
const direct = safePath.join(packageDir, 'dist', 'skills');
|
|
1050
|
-
if (
|
|
1052
|
+
if (present(direct))
|
|
1051
1053
|
return direct;
|
|
1052
|
-
const candidates = listNodeModulePackages(safePath.join(packageDir, 'node_modules'));
|
|
1054
|
+
const candidates = listNodeModulePackages(safePath.join(packageDir, 'node_modules'), packageDir);
|
|
1053
1055
|
for (const pkgDir of candidates) {
|
|
1054
1056
|
const candidate = safePath.join(pkgDir, 'dist', 'skills');
|
|
1055
|
-
if (
|
|
1057
|
+
if (present(candidate))
|
|
1056
1058
|
return candidate;
|
|
1057
1059
|
}
|
|
1058
1060
|
return undefined;
|
|
1059
1061
|
}
|
|
1062
|
+
/**
|
|
1063
|
+
* The failure row for one skill, coded by the thrown value exactly as a run-level
|
|
1064
|
+
* refusal would be. Exported for testing.
|
|
1065
|
+
*/
|
|
1066
|
+
export function skillUploadFailure(skill, error) {
|
|
1067
|
+
return { skill, error: { code: refusalCodeOf(error), message: errorMessageOf(error) } };
|
|
1068
|
+
}
|
|
1060
1069
|
/**
|
|
1061
1070
|
* The batch's report, tagged as a failure when ANY skill did not publish.
|
|
1062
1071
|
*
|
|
@@ -1073,79 +1082,83 @@ export function findSkillsDir(packageDir) {
|
|
|
1073
1082
|
* the same lie, only smaller. What did land stays in the document, so the reader
|
|
1074
1083
|
* can see how far the run got.
|
|
1075
1084
|
*/
|
|
1076
|
-
export function summarizeNpmInstall(source, results, errors) {
|
|
1085
|
+
export function summarizeNpmInstall(source, results, errors, leftover) {
|
|
1077
1086
|
const summary = {
|
|
1078
1087
|
source,
|
|
1079
1088
|
skillsUploaded: results.length,
|
|
1080
1089
|
...(errors.length > 0 ? { skillsFailed: errors.length, errors } : {}),
|
|
1081
1090
|
skills: results,
|
|
1091
|
+
...(leftover === undefined ? {} : { warnings: [leftoverIssueOf(leftover)] }),
|
|
1082
1092
|
};
|
|
1083
|
-
|
|
1093
|
+
if (errors.length === 0)
|
|
1094
|
+
return summary;
|
|
1095
|
+
// Some landed: the workspace is in a mixed state (`partial`). None did: `failed`.
|
|
1096
|
+
return orgCommandFailure(summary, results.length > 0
|
|
1097
|
+
? { kind: 'partial', failed: errors.length }
|
|
1098
|
+
: { kind: 'failed', cause: `no skill from ${source} uploaded` });
|
|
1084
1099
|
}
|
|
1085
1100
|
/**
|
|
1086
|
-
* Upload skills from an npm package.
|
|
1101
|
+
* Upload skills from an npm package. Exported for testing.
|
|
1087
1102
|
*/
|
|
1088
|
-
async function installFromNpm(npmPackage, skillFilter, client, logger) {
|
|
1089
|
-
|
|
1090
|
-
|
|
1103
|
+
export async function installFromNpm(npmPackage, skillFilter, client, logger) {
|
|
1104
|
+
// The download lives in a temp dir disposed of however the upload ends. One the OS will not
|
|
1105
|
+
// remove after the uploads is reported beside them, never in their place: they landed.
|
|
1106
|
+
const { value, leftover } = await withTempDir('vat-org-skills-', async (tempDir) => {
|
|
1091
1107
|
logger.info(`Downloading: ${npmPackage}`);
|
|
1092
|
-
const packageDir = downloadNpmPackage(npmPackage, tempDir);
|
|
1108
|
+
const packageDir = await downloadNpmPackage(npmPackage, tempDir);
|
|
1093
1109
|
const skillsDir = findSkillsDir(packageDir);
|
|
1094
1110
|
if (!skillsDir) {
|
|
1095
|
-
throw new
|
|
1111
|
+
throw new CommandRefusalError('USAGE_INVALID', `No dist/skills/ directory found in ${npmPackage}. Was the package built with vat skills build?`);
|
|
1096
1112
|
}
|
|
1097
1113
|
logger.info(`Found skills at: ${safePath.relative(packageDir, skillsDir) || 'dist/skills/'}`);
|
|
1098
1114
|
// Followed: a built skill directory that is a link is still a skill to upload.
|
|
1099
1115
|
const skillDirs = readdirSync(skillsDir, { withFileTypes: true })
|
|
1100
|
-
.filter(e => direntKindFollowingSync(skillsDir, e) === 'directory')
|
|
1116
|
+
.filter(e => direntKindFollowingSync(skillsDir, e, packageDir) === 'directory')
|
|
1101
1117
|
.map(e => e.name);
|
|
1102
1118
|
if (skillDirs.length === 0) {
|
|
1103
|
-
throw new
|
|
1119
|
+
throw new CommandRefusalError('USAGE_INVALID', `No skills found in dist/skills/ of ${npmPackage}`);
|
|
1104
1120
|
}
|
|
1105
1121
|
const toUpload = skillFilter
|
|
1106
1122
|
? skillDirs.filter(name => name === skillFilter)
|
|
1107
1123
|
: skillDirs;
|
|
1108
1124
|
if (toUpload.length === 0) {
|
|
1109
|
-
throw new
|
|
1125
|
+
throw new CommandRefusalError('USAGE_INVALID', `Skill "${String(skillFilter)}" not found in ${npmPackage}. Available: ${skillDirs.join(', ')}`);
|
|
1110
1126
|
}
|
|
1111
1127
|
logger.info(`Found ${toUpload.length} skill(s) to upload from ${npmPackage}`);
|
|
1112
1128
|
const results = [];
|
|
1113
1129
|
const errors = [];
|
|
1114
|
-
|
|
1130
|
+
// In order: one rate-limited API, and the result and failure lists follow `toUpload`.
|
|
1131
|
+
await forEachInOrder(toUpload, async (skillName) => {
|
|
1115
1132
|
const skillDir = safePath.join(skillsDir, skillName);
|
|
1116
1133
|
try {
|
|
1117
1134
|
const result = await uploadSkillDir(client, skillDir, undefined, logger);
|
|
1118
1135
|
results.push(result);
|
|
1119
1136
|
}
|
|
1120
1137
|
catch (error) {
|
|
1121
|
-
const
|
|
1122
|
-
logger.info(` ⚠ ${skillName}: ${
|
|
1123
|
-
errors.push(
|
|
1138
|
+
const failure = skillUploadFailure(skillName, error);
|
|
1139
|
+
logger.info(` ⚠ ${skillName}: ${failure.error.message}`);
|
|
1140
|
+
errors.push(failure);
|
|
1124
1141
|
}
|
|
1125
|
-
}
|
|
1126
|
-
return
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
1130
|
-
}
|
|
1142
|
+
});
|
|
1143
|
+
return { results, errors };
|
|
1144
|
+
});
|
|
1145
|
+
return summarizeNpmInstall(npmPackage, value.results, value.errors, leftover);
|
|
1131
1146
|
}
|
|
1132
1147
|
/**
|
|
1133
1148
|
* Upload a local skill directory or ZIP file. Exported for testing.
|
|
1134
1149
|
*/
|
|
1135
1150
|
export async function installFromLocal(source, titleOverride, client, logger) {
|
|
1136
1151
|
const sourcePath = resolveSourceArgument(source);
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
}
|
|
1140
|
-
const stat = statSync(sourcePath);
|
|
1152
|
+
// The operator's own argument: its own `within`.
|
|
1153
|
+
const stat = statNamedPath(sourcePath, sourcePath, `Source not found: ${sourcePath}`);
|
|
1141
1154
|
// Case-INSENSITIVE. `endsWith('.zip')` refused `MySkill.ZIP` as "not a directory
|
|
1142
1155
|
// or .zip file" — a file Windows and macOS both consider a zip archive, and one
|
|
1143
1156
|
// an operator has no way to read that refusal as being about capitalisation.
|
|
1144
1157
|
if (!stat.isDirectory() && sourcePath.toLowerCase().endsWith('.zip')) {
|
|
1145
|
-
return installZipArchive(sourcePath, titleOverride, client, logger);
|
|
1158
|
+
return await installZipArchive(sourcePath, titleOverride, client, logger);
|
|
1146
1159
|
}
|
|
1147
1160
|
if (!stat.isDirectory()) {
|
|
1148
|
-
throw new
|
|
1161
|
+
throw new CommandRefusalError('USAGE_INVALID', `Source must be a directory or .zip file: ${sourcePath}`);
|
|
1149
1162
|
}
|
|
1150
1163
|
// "Packaging", not "Uploading". Everything that follows this line — reading the
|
|
1151
1164
|
// config, collecting the file set, weighing the request — happens locally and
|
|
@@ -1156,7 +1169,7 @@ export async function installFromLocal(source, titleOverride, client, logger) {
|
|
|
1156
1169
|
// all — `--from-npm` packages several skills in a loop, and a packaging error
|
|
1157
1170
|
// with no path above it names nothing.
|
|
1158
1171
|
logger.info(`Packaging skill directory: ${sourcePath}`);
|
|
1159
|
-
return uploadSkillDir(client, sourcePath, titleOverride, logger);
|
|
1172
|
+
return await uploadSkillDir(client, sourcePath, titleOverride, logger);
|
|
1160
1173
|
}
|
|
1161
1174
|
/**
|
|
1162
1175
|
* Publish a ZIP archive as a NEW skill.
|
|
@@ -1171,12 +1184,9 @@ async function installZipArchive(sourcePath, titleOverride, client, logger) {
|
|
|
1171
1184
|
// `basename(path, ext)` matches the extension exactly, so the literal '.zip'
|
|
1172
1185
|
// leaves `.ZIP` on the title. Slice the length instead.
|
|
1173
1186
|
const displayTitle = titleOverride ?? basename(sourcePath).slice(0, -'.zip'.length);
|
|
1174
|
-
|
|
1175
|
-
const
|
|
1176
|
-
|
|
1177
|
-
filename: basename(sourcePath),
|
|
1178
|
-
content: zipContent,
|
|
1179
|
-
}];
|
|
1187
|
+
// The ONE read of the file: everything below is decided on, and sent from, what this read.
|
|
1188
|
+
const inspected = await inspectZipArchive(sourcePath);
|
|
1189
|
+
const fileBytes = 'archiveUnreadable' in inspected ? inspected.bytes.length : inspected.fileBytes;
|
|
1180
1190
|
// A ZIP is by construction a single large binary, so this is the shape most
|
|
1181
1191
|
// likely to be over the ceiling — and the one that reached the wire unmeasured
|
|
1182
1192
|
// while the check lived only in the directory-packaging path. It is gated in
|
|
@@ -1186,37 +1196,34 @@ async function installZipArchive(sourcePath, titleOverride, client, logger) {
|
|
|
1186
1196
|
// "Preparing", not "Uploading": nothing has been sent at this point, and the
|
|
1187
1197
|
// very next step can refuse locally. A line that claims an upload started is
|
|
1188
1198
|
// the log telling the operator about work that never happened.
|
|
1189
|
-
logger.info(`Preparing ZIP: ${sourcePath} (${formatBytes(
|
|
1199
|
+
logger.info(`Preparing ZIP: ${sourcePath} (${formatBytes(fileBytes)} of file content)`);
|
|
1190
1200
|
// Where the title came FROM, not just what it is. A ZIP's title is the
|
|
1191
1201
|
// filename — `wiki-lint-v2.zip` publishes a skill called `wiki-lint-v2`,
|
|
1192
1202
|
// which is a DIFFERENT skill from `wiki-lint` and is not refused, because
|
|
1193
1203
|
// display_title uniqueness is enforced only when the field is sent. A
|
|
1194
1204
|
// directory takes its title from SKILL.md instead, so the same tree zipped
|
|
1195
|
-
// and unzipped can publish under two names
|
|
1196
|
-
//
|
|
1197
|
-
// ⛔ This comment used to end "VAT cannot read the SKILL.md inside the
|
|
1198
|
-
// archive: Node ships no ZIP reader, and adding a dependency to parse one
|
|
1199
|
-
// here would mean owning central-directory, zip64 and zip-slip handling for
|
|
1200
|
-
// a log line." The PREMISE was false — `adm-zip` is already a runtime
|
|
1201
|
-
// dependency of this package — and the cost/benefit was weighed against the
|
|
1202
|
-
// wrong benefit: the same read also answers whether the archive EXPANDS
|
|
1203
|
-
// past the ceiling, which is a refusal, not a log line. So the archive is
|
|
1204
|
-
// now read (see {@link inspectZipArchive}) and the divergence is reported
|
|
1205
|
-
// as a fact below, in addition to this provenance line.
|
|
1205
|
+
// and unzipped can publish under two names — the inspection reads the name
|
|
1206
|
+
// the archive's SKILL.md declares, and the divergence is reported below.
|
|
1206
1207
|
logger.info(`Display title: "${displayTitle}" (${titleOverride === undefined
|
|
1207
1208
|
? 'from the ZIP filename — NOT from the SKILL.md inside it; pass --title to set it'
|
|
1208
1209
|
: 'from --title'})`);
|
|
1209
|
-
|
|
1210
|
+
let content;
|
|
1210
1211
|
if ('archiveUnreadable' in inspected) {
|
|
1211
1212
|
// Degrade, and SAY so. Every check below is skipped, and a skipped check
|
|
1212
1213
|
// that is not announced is indistinguishable from one that passed.
|
|
1213
1214
|
logger.warn(`Could not read the archive (${inspected.archiveUnreadable}); the answer-key, expanded-size, `
|
|
1214
1215
|
+ `name and portability checks were not run on it. The API decides the upload.`);
|
|
1216
|
+
content = inspected.bytes;
|
|
1215
1217
|
}
|
|
1216
1218
|
else {
|
|
1217
|
-
refuseOrWarnOnArchive(inspected, displayTitle,
|
|
1219
|
+
refuseOrWarnOnArchive(inspected, displayTitle, fileBytes, logger);
|
|
1220
|
+
if (inspected.hostAdded.length > 0) {
|
|
1221
|
+
logger.info(`Left out of the upload (added by the host that made the archive, not part of the skill): ${inspected.hostAdded.join(', ')}`);
|
|
1222
|
+
}
|
|
1223
|
+
// What is sent is what was judged: VAT's own ZIP of the entries it read, never the operator's bytes.
|
|
1224
|
+
content = await inspected.upload();
|
|
1218
1225
|
}
|
|
1219
|
-
return sendSkillUpload(client, displayTitle, files);
|
|
1226
|
+
return sendSkillUpload(client, displayTitle, [{ fieldName: 'files[]', filename: basename(sourcePath), content }]);
|
|
1220
1227
|
}
|
|
1221
1228
|
/**
|
|
1222
1229
|
* The archive lane's own decisions, over what {@link inspectZipArchive} read:
|
|
@@ -1239,7 +1246,7 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
|
|
|
1239
1246
|
// unreadable here. That is a narrower check than the directory lane's,
|
|
1240
1247
|
// not a looser verdict on what it does see.
|
|
1241
1248
|
if (inspected.neverUploaded.length > 0) {
|
|
1242
|
-
throw new
|
|
1249
|
+
throw new CommandRefusalError('USAGE_INVALID', `This ZIP contains ${String(inspected.neverUploaded.length)} entr`
|
|
1243
1250
|
+ `${inspected.neverUploaded.length === 1 ? 'y' : 'ies'} that are never published with a `
|
|
1244
1251
|
+ `skill: ${inspected.neverUploaded.slice(0, 10).join(', ')}`
|
|
1245
1252
|
+ `${inspected.neverUploaded.length > 10 ? ', …' : ''}. An eval suite is the skill's ANSWER `
|
|
@@ -1248,7 +1255,7 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
|
|
|
1248
1255
|
+ `\`install <dir>\` withholds these and reports each one.`);
|
|
1249
1256
|
}
|
|
1250
1257
|
if (inspected.uncompressedBytes > API_SKILL_MAX_UPLOAD_BYTES) {
|
|
1251
|
-
throw new
|
|
1258
|
+
throw new CommandRefusalError('USAGE_INVALID', `ZIP expands to ${formatBytes(inspected.uncompressedBytes)}, over the `
|
|
1252
1259
|
+ `${formatBytes(API_SKILL_MAX_UPLOAD_BYTES)} ceiling. The API expands the archive and `
|
|
1253
1260
|
+ `weighs the UNCOMPRESSED total, so ${formatBytes(wireBytes)} on the wire does not `
|
|
1254
1261
|
+ `get this under the limit — it will refuse with "Zip file uncompressed size exceeds 30MB". `
|
|
@@ -1284,8 +1291,8 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
|
|
|
1284
1291
|
warnUnportableReferences(inspected.documents, inspected.bundleRoot, undefined, logger);
|
|
1285
1292
|
if (inspected.unreadable.length > 0) {
|
|
1286
1293
|
const named = inspected.unreadable.map(({ entry, reason }) => `${entry} (${reason})`).join(', ');
|
|
1287
|
-
logger.warn(`${String(inspected.unreadable.length)} archive member(s) could not be inflated
|
|
1288
|
-
+
|
|
1294
|
+
logger.warn(`${String(inspected.unreadable.length)} archive member(s) could not be inflated: ${named}. `
|
|
1295
|
+
+ 'They were not checked, and the upload will refuse the archive when it re-reads them — nothing is sent.');
|
|
1289
1296
|
}
|
|
1290
1297
|
}
|
|
1291
1298
|
/**
|
|
@@ -1300,9 +1307,9 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
|
|
|
1300
1307
|
* 2 of 30 hid the state of the other 28.
|
|
1301
1308
|
*
|
|
1302
1309
|
* 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
|
|
1304
|
-
*
|
|
1305
|
-
*
|
|
1310
|
+
* decides what the outcome means: some deleted plus some failed is a `partial`
|
|
1311
|
+
* write that publishes the record; nothing deleted at all is a refusal with no
|
|
1312
|
+
* record worth publishing. Both end on 2.
|
|
1306
1313
|
*
|
|
1307
1314
|
* ⛔ It deliberately does NOT stop early on a repeated failure. A "the API is
|
|
1308
1315
|
* clearly down, give up" heuristic is how the abandoned-versions defect reads
|
|
@@ -1312,7 +1319,8 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
|
|
|
1312
1319
|
export async function deleteEveryVersion(client, skillId, versions, logger) {
|
|
1313
1320
|
const deleted = [];
|
|
1314
1321
|
const failures = [];
|
|
1315
|
-
|
|
1322
|
+
// In order: one rate-limited API, and both lists follow the order versions were handed in.
|
|
1323
|
+
await forEachInOrder(versions, async (version) => {
|
|
1316
1324
|
try {
|
|
1317
1325
|
await client.deleteSkillVersion(skillId, version);
|
|
1318
1326
|
}
|
|
@@ -1320,16 +1328,16 @@ export async function deleteEveryVersion(client, skillId, versions, logger) {
|
|
|
1320
1328
|
const reason = error instanceof Error ? error.message : String(error);
|
|
1321
1329
|
failures.push({ version, reason });
|
|
1322
1330
|
logger.info(` ⚠ version ${version} was not deleted: ${reason}`);
|
|
1323
|
-
|
|
1331
|
+
return;
|
|
1324
1332
|
}
|
|
1325
1333
|
deleted.push(version);
|
|
1326
1334
|
logger.info(` Deleted version ${version}`);
|
|
1327
|
-
}
|
|
1335
|
+
});
|
|
1328
1336
|
return { deleted, failures };
|
|
1329
1337
|
}
|
|
1330
1338
|
/**
|
|
1331
1339
|
* Every version the sweep could not delete, and why — the one sentence both the
|
|
1332
|
-
* published report and the
|
|
1340
|
+
* published report and the refusal's throw are built from, so the two endings never
|
|
1333
1341
|
* describe the same run differently.
|
|
1334
1342
|
*/
|
|
1335
1343
|
export function describeVersionSweepFailures(failures) {
|
|
@@ -1341,10 +1349,10 @@ export function describeVersionSweepFailures(failures) {
|
|
|
1341
1349
|
*
|
|
1342
1350
|
* 🔑 The deleted list is a RECORD, not a progress counter. Version deletion is
|
|
1343
1351
|
* irreversible, so a failure part-way through leaves a workspace nobody can
|
|
1344
|
-
* reconstruct — and throwing here would
|
|
1345
|
-
*
|
|
1346
|
-
*
|
|
1347
|
-
*
|
|
1352
|
+
* reconstruct — and throwing here would publish only the refusal and DISCARD
|
|
1353
|
+
* the document. It happened, and it destroyed things the operator now has no
|
|
1354
|
+
* other list of. So the lists travel with the failure as a `partial` outcome:
|
|
1355
|
+
* the payload is published, and the adapter ends the run on 2.
|
|
1348
1356
|
*
|
|
1349
1357
|
* `failedVersions` is the other half, and the half a re-run needs: what is still
|
|
1350
1358
|
* there. Without it the operator knows what they lost and not what they still
|
|
@@ -1352,17 +1360,20 @@ export function describeVersionSweepFailures(failures) {
|
|
|
1352
1360
|
*/
|
|
1353
1361
|
export function reportHalfDeleted(report) {
|
|
1354
1362
|
const { skillId, deletedVersions, failedVersions } = report;
|
|
1363
|
+
// Some writes landed (the deleted versions) and some did not: every version
|
|
1364
|
+
// still there, plus the skill itself, which is never deleted on this path.
|
|
1365
|
+
const outcome = { kind: 'partial', failed: failedVersions.length + 1 };
|
|
1355
1366
|
return orgCommandFailure({
|
|
1356
1367
|
id: skillId,
|
|
1357
1368
|
deleted: false,
|
|
1358
1369
|
deletedVersions,
|
|
1359
1370
|
failedVersions,
|
|
1360
|
-
|
|
1371
|
+
reason: report.reason,
|
|
1361
1372
|
note: `${String(deletedVersions.length)} version(s) of ${skillId} were deleted and cannot be `
|
|
1362
1373
|
+ `restored; ${String(failedVersions.length)} could not be deleted and are still there. `
|
|
1363
1374
|
+ 'The skill itself still exists — the API refuses a skill that still has versions. '
|
|
1364
1375
|
+ 'Re-run `--all` once the cause is cleared: it will attempt only what is left.',
|
|
1365
|
-
});
|
|
1376
|
+
}, outcome);
|
|
1366
1377
|
}
|
|
1367
1378
|
// ── Commands ───────────────────────────────────────────────────────────
|
|
1368
1379
|
export function createOrgSkillsCommand() {
|
|
@@ -1376,7 +1387,7 @@ export function createOrgSkillsCommand() {
|
|
|
1376
1387
|
.description('List organization skills')
|
|
1377
1388
|
.option('--debug', DEBUG_OPT_DESC)
|
|
1378
1389
|
.action(async (options) => {
|
|
1379
|
-
await executeOrgCommand('
|
|
1390
|
+
await executeOrgCommand('claude org skills list', options.debug, ({ client }) => {
|
|
1380
1391
|
return autopaginateSkills(client, '/v1/skills');
|
|
1381
1392
|
});
|
|
1382
1393
|
})
|
|
@@ -1399,8 +1410,7 @@ Example:
|
|
|
1399
1410
|
.option('--title <title>', 'Display title override (single skill only)')
|
|
1400
1411
|
.option('--debug', DEBUG_OPT_DESC)
|
|
1401
1412
|
.action(async (source, options) => {
|
|
1402
|
-
|
|
1403
|
-
await executeOrgCommand(commandName, options.debug, async ({ client, logger }) => {
|
|
1413
|
+
await executeOrgCommand('claude org skills install', options.debug, ({ client, logger }) => {
|
|
1404
1414
|
// INSIDE the action, like `versions add`'s own guards. Thrown from the
|
|
1405
1415
|
// Commander handler instead, these were a floating rejection that
|
|
1406
1416
|
// reached no catch: Node printed a raw stack trace with absolute $HOME
|
|
@@ -1408,22 +1418,22 @@ Example:
|
|
|
1408
1418
|
// exited 1 — which the documented contract reads as "at least one
|
|
1409
1419
|
// error-severity finding" for a run in which nothing executed.
|
|
1410
1420
|
if (!source && !options.fromNpm) {
|
|
1411
|
-
throw new
|
|
1421
|
+
throw new CommandRefusalError('USAGE_INVALID', 'Provide a <source> path or use --from-npm <package>');
|
|
1412
1422
|
}
|
|
1413
1423
|
if (source && options.fromNpm) {
|
|
1414
|
-
throw new
|
|
1424
|
+
throw new CommandRefusalError('USAGE_INVALID', 'Provide either <source> or --from-npm, not both');
|
|
1415
1425
|
}
|
|
1416
1426
|
// The other two illegal combinations, refused rather than dropped. Both
|
|
1417
1427
|
// flags used to be accepted and silently ignored on the lane that cannot
|
|
1418
1428
|
// honour them, which is how an operator gets a skill published under the
|
|
1419
1429
|
// wrong title — or every skill in a package published when they named one.
|
|
1420
1430
|
if (options.title !== undefined && options.fromNpm) {
|
|
1421
|
-
throw new
|
|
1431
|
+
throw new CommandRefusalError('USAGE_INVALID', '--title applies to a single skill and --from-npm can publish several, so it is '
|
|
1422
1432
|
+ 'refused here rather than silently ignored. Publish the one skill with '
|
|
1423
1433
|
+ '--skill and set its title in its SKILL.md, or upload its directory directly.');
|
|
1424
1434
|
}
|
|
1425
1435
|
if (options.skill !== undefined && !options.fromNpm) {
|
|
1426
|
-
throw new
|
|
1436
|
+
throw new CommandRefusalError('USAGE_INVALID', '--skill selects one skill inside an npm package; it applies only with --from-npm');
|
|
1427
1437
|
}
|
|
1428
1438
|
if (options.fromNpm) {
|
|
1429
1439
|
return installFromNpm(options.fromNpm, options.skill, client, logger);
|
|
@@ -1442,10 +1452,27 @@ Description:
|
|
|
1442
1452
|
|
|
1443
1453
|
A ZIP takes its display_title from the ZIP FILENAME, so my-skill-v2.zip
|
|
1444
1454
|
publishes a skill titled "my-skill-v2", which is a separate skill from
|
|
1445
|
-
"my-skill" and is not refused as a duplicate. VAT reads the SKILL.md
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1455
|
+
"my-skill" and is not refused as a duplicate. VAT reads the archive's SKILL.md
|
|
1456
|
+
and WARNS when the name it declares differs from that title, because every
|
|
1457
|
+
version the skill ever gets will carry the declared name. Pass --title to set
|
|
1458
|
+
the title explicitly.
|
|
1459
|
+
|
|
1460
|
+
A ZIP holds SKILL.md at its top level, or exactly one top-level folder with
|
|
1461
|
+
SKILL.md directly inside (a skill folder, compressed) — the layout the install
|
|
1462
|
+
verbs take. Any other layout is refused (INPUT_UNREADABLE), and so is a ZIP
|
|
1463
|
+
holding a symbolic link, a name that leaves the archive, one name twice, or
|
|
1464
|
+
more than 50,000 entries / 256 MiB expanded, a name Windows cannot hold (a
|
|
1465
|
+
":", < > " | ? *, a control character, a device name such as CON or aux.md,
|
|
1466
|
+
a trailing "." or space), a ZIP64 archive, one whose end record two readers
|
|
1467
|
+
could read differently or is not in its last 64 KiB, one with data before its
|
|
1468
|
+
first local header (a self-extracting ZIP) or a directory entry whose local
|
|
1469
|
+
header is not its own, or one holding an entry VAT cannot inflate. What is
|
|
1470
|
+
sent is VAT's own ZIP of the entries it read and checked (its names, order,
|
|
1471
|
+
timestamps, compression and 0644/0755 modes) — never your file's bytes — so a
|
|
1472
|
+
top-level __MACOSX/ folder or .DS_Store (what macOS adds) is left out.
|
|
1473
|
+
Only bytes that are no ZIP at all (no local-file-header or end-record
|
|
1474
|
+
signature anywhere in them) are sent as they are, with a warning that the
|
|
1475
|
+
checks below were skipped.
|
|
1449
1476
|
|
|
1450
1477
|
A skill's eval suite is its answer key and is never uploaded: whatever the
|
|
1451
1478
|
governing vibe-agent-toolkit.config.yaml declares as this skill's test input
|
|
@@ -1494,9 +1521,10 @@ Description:
|
|
|
1494
1521
|
|
|
1495
1522
|
Exit Codes:
|
|
1496
1523
|
0 - Every skill uploaded
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1524
|
+
2 - At least one skill failed to upload (--from-npm uploads several; the ones
|
|
1525
|
+
that landed are still listed under skills, each failure under errors as
|
|
1526
|
+
{ skill, error: { code, message } }), or the run was refused: no
|
|
1527
|
+
API key, no such source, unusable input ({ error: { code, message } })
|
|
1500
1528
|
|
|
1501
1529
|
Examples:
|
|
1502
1530
|
$ vat claude org skills install dist/skills/org-admin
|
|
@@ -1512,23 +1540,22 @@ Examples:
|
|
|
1512
1540
|
.option('--all', 'Auto-delete all versions before deleting the skill')
|
|
1513
1541
|
.option('--debug', DEBUG_OPT_DESC)
|
|
1514
1542
|
.action(async (skillId, options) => {
|
|
1515
|
-
await executeOrgCommand('
|
|
1543
|
+
await executeOrgCommand('claude org skills delete', options.debug, async ({ client, logger }) => {
|
|
1516
1544
|
// Every version this run actually destroyed, accumulated as it goes.
|
|
1517
1545
|
//
|
|
1518
1546
|
// 🔑 It is a RECORD, not a progress counter. Version deletion is
|
|
1519
1547
|
// irreversible and `--all` does it in a loop, so a failure part-way
|
|
1520
1548
|
// through leaves a workspace nobody can reconstruct — and the old code
|
|
1521
|
-
// threw at that point, which
|
|
1522
|
-
//
|
|
1523
|
-
//
|
|
1524
|
-
//
|
|
1525
|
-
// outcome is wrong.
|
|
1549
|
+
// threw at that point, which publishes only the refusal and DISCARDS
|
|
1550
|
+
// the document. It happened, and it destroyed things the operator now
|
|
1551
|
+
// has no list of. So the list travels with the failure as a `partial`
|
|
1552
|
+
// outcome: published, and ending on 2.
|
|
1526
1553
|
const deletedVersions = [];
|
|
1527
1554
|
const halfDeleted = (error, failedVersions) => reportHalfDeleted({
|
|
1528
1555
|
skillId,
|
|
1529
1556
|
deletedVersions,
|
|
1530
1557
|
failedVersions,
|
|
1531
|
-
|
|
1558
|
+
reason: errorMessageOf(error),
|
|
1532
1559
|
});
|
|
1533
1560
|
if (options.all) {
|
|
1534
1561
|
const versions = await autopaginateSkills(client, skillVersionsPath(skillId));
|
|
@@ -1544,11 +1571,11 @@ Examples:
|
|
|
1544
1571
|
if (sweep.failures.length > 0) {
|
|
1545
1572
|
const detail = describeVersionSweepFailures(sweep.failures);
|
|
1546
1573
|
// Nothing was destroyed, so there is no record worth publishing and
|
|
1547
|
-
//
|
|
1574
|
+
// the refusal (EXTERNAL_API_FAILED, exit 2, via the throw) is the honest ending —
|
|
1548
1575
|
// the same rule as before, now decided on the WHOLE sweep rather than
|
|
1549
1576
|
// on its first refusal.
|
|
1550
1577
|
if (deletedVersions.length === 0) {
|
|
1551
|
-
throw new
|
|
1578
|
+
throw new CommandRefusalError('EXTERNAL_API_FAILED', `No version of ${skillId} could be deleted, so the skill was left alone. `
|
|
1552
1579
|
+ `${String(sweep.failures.length)} attempt(s) failed — ${detail}`);
|
|
1553
1580
|
}
|
|
1554
1581
|
// The skill delete is not attempted: the API refuses a skill that still
|
|
@@ -1594,10 +1621,11 @@ Description:
|
|
|
1594
1621
|
--all deletes irreversibly and in a loop, and it ATTEMPTS EVERY VERSION even
|
|
1595
1622
|
when one refuses — one refusal is a fact about one version, not about the ones
|
|
1596
1623
|
after it. When the sweep ends with anything left, the versions it destroyed are
|
|
1597
|
-
listed under deletedVersions, the ones still there under failedVersions,
|
|
1598
|
-
|
|
1624
|
+
listed under deletedVersions, the ones still there under failedVersions, why
|
|
1625
|
+
under reason, and the run exits 2 with that record published. The skill itself
|
|
1599
1626
|
is then left alone, because the API refuses a skill that still has versions.
|
|
1600
|
-
|
|
1627
|
+
When nothing was deleted at all, it publishes only the refusal
|
|
1628
|
+
({ error: { code, message } }), also at 2.
|
|
1601
1629
|
|
|
1602
1630
|
A version delete whose response is lost is replayed, and the replay is answered
|
|
1603
1631
|
404 because the first attempt already removed it. That 404 is read as the
|
|
@@ -1605,10 +1633,10 @@ Description:
|
|
|
1605
1633
|
|
|
1606
1634
|
Exit Codes:
|
|
1607
1635
|
0 - The skill was deleted
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
--all deleted no version at all
|
|
1636
|
+
2 - The skill was NOT deleted: the API named a different outcome, or --all
|
|
1637
|
+
destroyed some versions and could not destroy the rest (the document
|
|
1638
|
+
lists both); or the run was refused — no API key, the first request was
|
|
1639
|
+
refused, or --all deleted no version at all ({ error: { code, message } })
|
|
1612
1640
|
|
|
1613
1641
|
Example:
|
|
1614
1642
|
$ vat claude org skills delete skill_abc123 --all
|
|
@@ -1622,7 +1650,7 @@ Example:
|
|
|
1622
1650
|
.argument(SKILL_ID_ARG, SKILL_ID_DESC)
|
|
1623
1651
|
.option('--debug', DEBUG_OPT_DESC)
|
|
1624
1652
|
.action(async (skillId, options) => {
|
|
1625
|
-
await executeOrgCommand('
|
|
1653
|
+
await executeOrgCommand('claude org skills versions list', options.debug, ({ client }) => {
|
|
1626
1654
|
return autopaginateSkills(client, skillVersionsPath(skillId));
|
|
1627
1655
|
});
|
|
1628
1656
|
})
|
|
@@ -1641,7 +1669,7 @@ Example:
|
|
|
1641
1669
|
.argument('<version>', 'Version to delete')
|
|
1642
1670
|
.option('--debug', DEBUG_OPT_DESC)
|
|
1643
1671
|
.action(async (skillId, version, options) => {
|
|
1644
|
-
await executeOrgCommand('
|
|
1672
|
+
await executeOrgCommand('claude org skills versions delete', options.debug, async ({ client, logger }) => {
|
|
1645
1673
|
logger.info(`Deleting version ${version} of skill ${skillId}`);
|
|
1646
1674
|
return reportVersionDelete(await client.deleteSkillVersion(skillId, version), skillId, version);
|
|
1647
1675
|
});
|
|
@@ -1659,8 +1687,8 @@ Output:
|
|
|
1659
1687
|
|
|
1660
1688
|
Exit Codes:
|
|
1661
1689
|
0 - The version was deleted
|
|
1662
|
-
|
|
1663
|
-
|
|
1690
|
+
2 - The API named an outcome other than a deletion, or the run was refused:
|
|
1691
|
+
no API key, or the request was refused ({ error: { code, message } })
|
|
1664
1692
|
|
|
1665
1693
|
Example:
|
|
1666
1694
|
$ vat claude org skills versions delete skill_abc123 1775007400733130
|
|
@@ -1678,11 +1706,9 @@ Example:
|
|
|
1678
1706
|
.argument('<source>', 'Path to a built skill directory')
|
|
1679
1707
|
.option('--debug', DEBUG_OPT_DESC)
|
|
1680
1708
|
.action(async (skillId, source, options) => {
|
|
1681
|
-
await executeOrgCommand('
|
|
1709
|
+
await executeOrgCommand('claude org skills versions add', options.debug, ({ client, logger }) => {
|
|
1682
1710
|
const resolved = resolveSourceArgument(source);
|
|
1683
|
-
if (!
|
|
1684
|
-
throw new Error(`Source not found: ${resolved}`);
|
|
1685
|
-
if (!statSync(resolved).isDirectory()) {
|
|
1711
|
+
if (!statNamedPath(resolved, resolved, `Source not found: ${resolved}`).isDirectory()) {
|
|
1686
1712
|
// Name the asymmetry IN the refusal, not only in --help. `install`
|
|
1687
1713
|
// accepts a ZIP and this verb does not, so the operator most likely to
|
|
1688
1714
|
// hit this is the one who just read that `install` takes one — and a
|
|
@@ -1692,7 +1718,7 @@ Example:
|
|
|
1692
1718
|
? ' A ZIP is accepted by `vat claude org skills install`, not here:'
|
|
1693
1719
|
+ ' publish a new version from the built skill directory instead.'
|
|
1694
1720
|
: '';
|
|
1695
|
-
throw new
|
|
1721
|
+
throw new CommandRefusalError('USAGE_INVALID', `Source must be a skill directory: ${resolved}.${zipHint}`);
|
|
1696
1722
|
}
|
|
1697
1723
|
// "Packaging", not "Publishing" — see `installFromLocal`. Measured: this
|
|
1698
1724
|
// line printed, then `Failed to load config: …`, and nothing had been
|
|
@@ -1731,7 +1757,8 @@ Description:
|
|
|
1731
1757
|
|
|
1732
1758
|
Exit Codes:
|
|
1733
1759
|
0 - The version was published
|
|
1734
|
-
2 - The run
|
|
1760
|
+
2 - The run was refused ({ error: { code, message } }): no API key, no such
|
|
1761
|
+
source, not a directory,
|
|
1735
1762
|
over the upload ceiling, or a response the version identifier
|
|
1736
1763
|
cannot be read from
|
|
1737
1764
|
|