release-skill 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +4 -4
- package/.kimi-plugin/plugin.json +27 -0
- package/CHANGELOG.md +53 -0
- package/INSTALL.md +73 -2
- package/INSTALL.zh-CN.md +94 -99
- package/LICENSE +1 -0
- package/NOTICE +10 -0
- package/README.md +53 -81
- package/README.zh-CN.md +86 -352
- package/adapters/claude/.claude-plugin/marketplace.json +3 -3
- package/adapters/claude/.claude-plugin/plugin.json +2 -2
- package/adapters/claude/bin/release-skill.bundle.mjs +1061 -182
- package/adapters/claude/schemas/.render-manifest.json +4 -4
- package/adapters/claude/schemas/release-plan.schema.json +20 -2
- package/adapters/claude/schemas/release-project.schema.json +22 -4
- package/adapters/claude/schemas/release-run.schema.json +1 -0
- package/adapters/codex/.codex-plugin/plugin.json +4 -4
- package/adapters/codex/bin/release-skill.bundle.mjs +1061 -182
- package/adapters/codex/schemas/.render-manifest.json +4 -4
- package/adapters/codex/schemas/release-plan.schema.json +20 -2
- package/adapters/codex/schemas/release-project.schema.json +22 -4
- package/adapters/codex/schemas/release-run.schema.json +1 -0
- package/adapters/kimi/.kimi-plugin/plugin.json +27 -0
- package/adapters/kimi/bin/release-skill.bundle.mjs +84415 -0
- package/adapters/kimi/bin/release-skill.mjs +54 -0
- package/adapters/kimi/native/safe-write/binding.gyp +41 -0
- package/adapters/kimi/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
- package/adapters/kimi/native/safe-write/prebuilds.json +24 -0
- package/adapters/kimi/native/safe-write/src/safe_write.cc +2032 -0
- package/adapters/kimi/schemas/.render-manifest.json +37 -0
- package/adapters/kimi/schemas/approval-record.schema.json +115 -0
- package/adapters/kimi/schemas/artifact-lock.schema.json +111 -0
- package/adapters/kimi/schemas/artifact-plan.schema.json +52 -0
- package/adapters/kimi/schemas/artifact-policy.schema.json +76 -0
- package/adapters/kimi/schemas/evidence-event.schema.json +89 -0
- package/adapters/kimi/schemas/release-plan.schema.json +878 -0
- package/adapters/kimi/schemas/release-project.schema.json +895 -0
- package/adapters/kimi/schemas/release-run.schema.json +343 -0
- package/adapters/kimi/skills/release-assess/SKILL.md +58 -0
- package/adapters/kimi/skills/release-help/SKILL.md +84 -0
- package/adapters/kimi/skills/release-prepare/SKILL.md +99 -0
- package/adapters/kimi/skills/release-publish/SKILL.md +64 -0
- package/adapters/kimi/skills/release-reconcile/SKILL.md +80 -0
- package/adapters/kimi/skills/release-setup/SKILL.md +102 -0
- package/adapters/kimi/skills/release-verify/SKILL.md +77 -0
- package/bin/release-skill-cli.mjs +16 -4
- package/bin/release-skill.bundle.mjs +1061 -182
- package/package.json +15 -5
- package/schemas/.render-manifest.json +4 -4
- package/schemas/release-plan.schema.json +20 -2
- package/schemas/release-project.schema.json +22 -4
- package/schemas/release-run.schema.json +1 -0
- package/src/adapters/contract.mjs +1 -0
- package/src/adapters/plugin-marketplace.mjs +990 -30
- package/src/commands/assess.mjs +50 -1
- package/src/commands/prepare.mjs +65 -0
- package/src/commands/publish.mjs +3 -0
- package/src/commands/reconcile.mjs +3 -0
- package/src/commands/setup.mjs +10 -5
- package/src/commands/verify.mjs +16 -6
- package/src/core/plan.mjs +118 -0
- package/src/core/verification-gates.mjs +1 -1
- package/src/producers/build-adapters.mjs +38 -8
|
@@ -9,7 +9,7 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.1.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.1.8"});
|
|
13
13
|
|
|
14
14
|
var __create = Object.create;
|
|
15
15
|
var __defProp = Object.defineProperty;
|
|
@@ -16344,7 +16344,7 @@ async function walkDiscoveryFiles(root, maxDepth = 8) {
|
|
|
16344
16344
|
const absolute = join2(directory, child.name);
|
|
16345
16345
|
if (child.isDirectory()) {
|
|
16346
16346
|
if (!SKIP_DIRS.has(child.name)) await walk(absolute, depth + 1);
|
|
16347
|
-
} else if (child.isFile() && (child.name === "package.json" || child.name === "public-release.json" || child.name === "SKILL.md" || /^README(?:\.|$)/i.test(child.name) || /^LICENSE(?:\.|$)/i.test(child.name) || /^CHANGELOG(?:\.|$)/i.test(child.name) || absolute.endsWith("/.claude-plugin/plugin.json") || absolute.endsWith("/.codex-plugin/plugin.json") || absolute.endsWith("/.claude-plugin/marketplace.json") || absolute.endsWith("/.codex-plugin/marketplace.json"))) {
|
|
16347
|
+
} else if (child.isFile() && (child.name === "package.json" || child.name === "public-release.json" || child.name === "SKILL.md" || /^README(?:\.|$)/i.test(child.name) || /^LICENSE(?:\.|$)/i.test(child.name) || /^CHANGELOG(?:\.|$)/i.test(child.name) || absolute.endsWith("/.claude-plugin/plugin.json") || absolute.endsWith("/.codex-plugin/plugin.json") || absolute.endsWith("/.kimi-plugin/plugin.json") || absolute.endsWith("/.claude-plugin/marketplace.json") || absolute.endsWith("/.codex-plugin/marketplace.json"))) {
|
|
16348
16348
|
found.push(absolute);
|
|
16349
16349
|
}
|
|
16350
16350
|
}
|
|
@@ -16569,7 +16569,7 @@ async function discoverUnitGit(unitAbsDir, parentRoot) {
|
|
|
16569
16569
|
}
|
|
16570
16570
|
async function discoverFacts(root) {
|
|
16571
16571
|
const files = await walkDiscoveryFiles(root);
|
|
16572
|
-
const packageFiles = files.filter((path3) => basename(path3) === "package.json" && !/[\\/]adapters[\\/](?:claude|codex)[\\/]package\.json$/.test(path3));
|
|
16572
|
+
const packageFiles = files.filter((path3) => basename(path3) === "package.json" && !/[\\/]adapters[\\/](?:claude|codex|kimi)[\\/]package\.json$/.test(path3));
|
|
16573
16573
|
const pluginFiles = files.filter((path3) => path3.endsWith("/plugin.json"));
|
|
16574
16574
|
const marketplaceFiles = files.filter((path3) => path3.endsWith("/marketplace.json"));
|
|
16575
16575
|
const legacyReleaseFiles = files.filter((path3) => basename(path3) === "public-release.json");
|
|
@@ -16601,7 +16601,7 @@ async function discoverFacts(root) {
|
|
|
16601
16601
|
const value = await readJsonBounded(path3, "discovered plugin manifest");
|
|
16602
16602
|
manifests.push({
|
|
16603
16603
|
path: safeRelative(root, path3),
|
|
16604
|
-
host: path3.includes("/.claude-plugin/") ? "claude" : "codex",
|
|
16604
|
+
host: path3.includes("/.claude-plugin/") ? "claude" : path3.includes("/.kimi-plugin/") ? "kimi" : "codex",
|
|
16605
16605
|
kind: path3.endsWith("/marketplace.json") ? "marketplace" : "plugin",
|
|
16606
16606
|
name: typeof value.name === "string" ? value.name : null,
|
|
16607
16607
|
version: typeof value.version === "string" ? value.version : null
|
|
@@ -16620,7 +16620,7 @@ async function discoverFacts(root) {
|
|
|
16620
16620
|
return {
|
|
16621
16621
|
path: relPath,
|
|
16622
16622
|
name: skillIndex >= 0 ? segments[skillIndex + 1] ?? null : null,
|
|
16623
|
-
host: relPath.includes("/adapters/claude/") ? "claude" : relPath.includes("/adapters/codex/") ? "codex" : "shared"
|
|
16623
|
+
host: relPath.includes("/adapters/claude/") ? "claude" : relPath.includes("/adapters/codex/") ? "codex" : relPath.includes("/adapters/kimi/") ? "kimi" : "shared"
|
|
16624
16624
|
};
|
|
16625
16625
|
}).filter((item) => item.name).sort((a, b) => canonicalJson(a).localeCompare(canonicalJson(b)));
|
|
16626
16626
|
const unitGit = {};
|
|
@@ -16764,7 +16764,7 @@ function buildCandidates(facts) {
|
|
|
16764
16764
|
const ids = /* @__PURE__ */ new Set();
|
|
16765
16765
|
const knownFiles = new Set(facts.fileDigests.map((file) => file.path));
|
|
16766
16766
|
const manifestRoots = facts.manifests.map((manifest) => {
|
|
16767
|
-
const match = manifest.path.match(/^(.*?)(?:\/)?(?:\.claude-plugin|\.codex-plugin)\/(?:plugin|marketplace)\.json$/);
|
|
16767
|
+
const match = manifest.path.match(/^(.*?)(?:\/)?(?:\.claude-plugin|\.codex-plugin|\.kimi-plugin)\/(?:plugin|marketplace)\.json$/);
|
|
16768
16768
|
return { ...manifest, root: match?.[1] || "." };
|
|
16769
16769
|
});
|
|
16770
16770
|
const manifestOwners = /* @__PURE__ */ new Map();
|
|
@@ -16790,6 +16790,7 @@ function buildCandidates(facts) {
|
|
|
16790
16790
|
if (!pkg.private && pkg.name && !npmExplicitlyForbidden) distributions.push("npm");
|
|
16791
16791
|
if (pluginHosts.includes("claude")) distributions.push("claude-plugin");
|
|
16792
16792
|
if (pluginHosts.includes("codex")) distributions.push("codex-plugin");
|
|
16793
|
+
if (pluginHosts.includes("kimi")) distributions.push("kimi-plugin");
|
|
16793
16794
|
if (pkg.private && matchingLegacyUnits.length === 0 && facts.legacyReleaseConfigs.length > 0) continue;
|
|
16794
16795
|
if (pkg.private && distributions.length === 0) continue;
|
|
16795
16796
|
const unitGitEntry = unitGit[pkg.directory];
|
|
@@ -17496,6 +17497,7 @@ var init_setup = __esm({
|
|
|
17496
17497
|
".worktrees",
|
|
17497
17498
|
".claude",
|
|
17498
17499
|
".codex",
|
|
17500
|
+
".kimi",
|
|
17499
17501
|
".cache",
|
|
17500
17502
|
".tmp",
|
|
17501
17503
|
".pytest_cache",
|
|
@@ -18188,7 +18190,7 @@ function identifyTopology(config) {
|
|
|
18188
18190
|
const uniqueDistTypes = [...new Set(allDistTypes)];
|
|
18189
18191
|
let type = "unknown";
|
|
18190
18192
|
const hasNpm = uniqueDistTypes.includes("npm");
|
|
18191
|
-
const hasPlugin = uniqueDistTypes.includes("claude-plugin") || uniqueDistTypes.includes("codex-plugin");
|
|
18193
|
+
const hasPlugin = uniqueDistTypes.includes("claude-plugin") || uniqueDistTypes.includes("codex-plugin") || uniqueDistTypes.includes("kimi-plugin");
|
|
18192
18194
|
if (units.length === 0) {
|
|
18193
18195
|
type = "no-release-units";
|
|
18194
18196
|
} else if (units.length === 1) {
|
|
@@ -18398,6 +18400,53 @@ async function checkPluginManifests(root, config) {
|
|
|
18398
18400
|
}
|
|
18399
18401
|
}
|
|
18400
18402
|
}
|
|
18403
|
+
if (distributionTypes.has("kimi-plugin")) {
|
|
18404
|
+
const manifestPath = resolve7(unitRoot, ".kimi-plugin", "plugin.json");
|
|
18405
|
+
const displayPath = unitFile(unit, ".kimi-plugin/plugin.json");
|
|
18406
|
+
const exists = await fileExists(manifestPath);
|
|
18407
|
+
if (!exists) {
|
|
18408
|
+
gaps.push(
|
|
18409
|
+
createGap({
|
|
18410
|
+
scope: GapScope.PROFILE,
|
|
18411
|
+
category: GapCategory.MANIFEST,
|
|
18412
|
+
severity: Severity.ERROR,
|
|
18413
|
+
code: "KIMI_MANIFEST_MISSING",
|
|
18414
|
+
message: `\u53D1\u5E03\u5355\u5143 "${unit.id}" \u7F3A\u5C11 .kimi-plugin/plugin.json \u63D2\u4EF6\u6E05\u5355`,
|
|
18415
|
+
file: displayPath
|
|
18416
|
+
})
|
|
18417
|
+
);
|
|
18418
|
+
} else {
|
|
18419
|
+
try {
|
|
18420
|
+
const content = await readFile5(manifestPath, "utf8");
|
|
18421
|
+
const manifest = JSON.parse(content);
|
|
18422
|
+
const requiredFields = ["name", "version", "description"];
|
|
18423
|
+
const missingFields = requiredFields.filter((f) => !(f in manifest));
|
|
18424
|
+
if (missingFields.length > 0) {
|
|
18425
|
+
gaps.push(
|
|
18426
|
+
createGap({
|
|
18427
|
+
scope: GapScope.PROFILE,
|
|
18428
|
+
category: GapCategory.MANIFEST,
|
|
18429
|
+
severity: Severity.ERROR,
|
|
18430
|
+
code: "KIMI_MANIFEST_INCOMPLETE",
|
|
18431
|
+
message: `Kimi \u63D2\u4EF6\u6E05\u5355\u7F3A\u5C11\u5FC5\u586B\u5B57\u6BB5: ${missingFields.join(", ")}`,
|
|
18432
|
+
file: displayPath
|
|
18433
|
+
})
|
|
18434
|
+
);
|
|
18435
|
+
}
|
|
18436
|
+
} catch {
|
|
18437
|
+
gaps.push(
|
|
18438
|
+
createGap({
|
|
18439
|
+
scope: GapScope.PROFILE,
|
|
18440
|
+
category: GapCategory.MANIFEST,
|
|
18441
|
+
severity: Severity.ERROR,
|
|
18442
|
+
code: "KIMI_MANIFEST_INVALID",
|
|
18443
|
+
message: ".kimi-plugin/plugin.json \u89E3\u6790\u5931\u8D25",
|
|
18444
|
+
file: displayPath
|
|
18445
|
+
})
|
|
18446
|
+
);
|
|
18447
|
+
}
|
|
18448
|
+
}
|
|
18449
|
+
}
|
|
18401
18450
|
}
|
|
18402
18451
|
return gaps;
|
|
18403
18452
|
}
|
|
@@ -19481,7 +19530,7 @@ function validateGate(gate) {
|
|
|
19481
19530
|
if (!gate.scope || typeof gate.scope.unit !== "string") {
|
|
19482
19531
|
throw gateError(gate, "must declare scope.unit");
|
|
19483
19532
|
}
|
|
19484
|
-
if (gate.phase === "consumer-verify" && !["npm", "claude-plugin", "codex-plugin"].includes(gate.scope.distribution)) {
|
|
19533
|
+
if (gate.phase === "consumer-verify" && !["npm", "claude-plugin", "codex-plugin", "kimi-plugin"].includes(gate.scope.distribution)) {
|
|
19485
19534
|
throw gateError(gate, "consumer-verify must declare a supported scope.distribution");
|
|
19486
19535
|
}
|
|
19487
19536
|
if (!Array.isArray(gate.command) || gate.command.length === 0 || gate.command.some((value) => typeof value !== "string")) {
|
|
@@ -20567,6 +20616,97 @@ function validatePlanActionCompleteness(plan, options = {}) {
|
|
|
20567
20616
|
}
|
|
20568
20617
|
}
|
|
20569
20618
|
}
|
|
20619
|
+
const kimiDist = distributions.find((d) => d.type === "kimi-plugin");
|
|
20620
|
+
if (kimiDist) {
|
|
20621
|
+
const plugin = kimiDist.plugin;
|
|
20622
|
+
const marketplace = kimiDist.marketplace;
|
|
20623
|
+
const entrySkill = kimiDist.entrySkill;
|
|
20624
|
+
if (!plugin || !entrySkill) {
|
|
20625
|
+
failures.push(`unit "${unitId}": kimi-plugin distribution requires plugin and entrySkill`);
|
|
20626
|
+
}
|
|
20627
|
+
expectedCount++;
|
|
20628
|
+
const expectedActionId = `kimi-marketplace-install-${unitId}`;
|
|
20629
|
+
const kimiActions = actions.filter(
|
|
20630
|
+
(a) => a.unitId === unitId && a.type === "kimi-marketplace-install"
|
|
20631
|
+
);
|
|
20632
|
+
if (kimiActions.length === 0) {
|
|
20633
|
+
failures.push(
|
|
20634
|
+
`unit "${unitId}": kimi-plugin distribution declared but "kimi-marketplace-install" action is missing`
|
|
20635
|
+
);
|
|
20636
|
+
} else if (kimiActions.length > 1) {
|
|
20637
|
+
failures.push(
|
|
20638
|
+
`unit "${unitId}": duplicate kimi-marketplace-install actions (${kimiActions.length} found, expected 1)`
|
|
20639
|
+
);
|
|
20640
|
+
} else {
|
|
20641
|
+
const action = kimiActions[0];
|
|
20642
|
+
if (action.id !== expectedActionId) {
|
|
20643
|
+
failures.push(
|
|
20644
|
+
`unit "${unitId}", action "${action.id}": id is "${action.id}", expected "${expectedActionId}"`
|
|
20645
|
+
);
|
|
20646
|
+
}
|
|
20647
|
+
if (action.unitId !== unitId) {
|
|
20648
|
+
failures.push(
|
|
20649
|
+
`unit "${unitId}", action "${action.id}": unitId is "${action.unitId}", expected "${unitId}"`
|
|
20650
|
+
);
|
|
20651
|
+
}
|
|
20652
|
+
if (action.adapter !== "plugin-marketplace") {
|
|
20653
|
+
failures.push(
|
|
20654
|
+
`unit "${unitId}", action "${action.id}": adapter is "${action.adapter}", expected "plugin-marketplace"`
|
|
20655
|
+
);
|
|
20656
|
+
}
|
|
20657
|
+
if (action.status !== "PENDING") {
|
|
20658
|
+
failures.push(
|
|
20659
|
+
`unit "${unitId}", action "${action.id}": status is "${action.status ?? "(missing)"}", expected "PENDING"`
|
|
20660
|
+
);
|
|
20661
|
+
}
|
|
20662
|
+
_checkRequired(action, "parameters.consumer", action.parameters?.consumer, "kimi", unitId, failures);
|
|
20663
|
+
_checkRequired(action, "parameters.plugin", action.parameters?.plugin, plugin, unitId, failures);
|
|
20664
|
+
if (action.parameters?.marketplace !== void 0 && marketplace !== void 0 && action.parameters.marketplace !== marketplace) {
|
|
20665
|
+
failures.push(
|
|
20666
|
+
`unit "${unitId}", action "${action.id}": parameters.marketplace is "${action.parameters.marketplace}", expected optional legacy value "${marketplace}"`
|
|
20667
|
+
);
|
|
20668
|
+
}
|
|
20669
|
+
_checkRequired(action, "parameters.repo", action.parameters?.repo, publicRepo, unitId, failures);
|
|
20670
|
+
_checkRequired(action, "parameters.version", action.parameters?.version, targetVersion, unitId, failures);
|
|
20671
|
+
_checkRequired(action, "parameters.entrySkill", action.parameters?.entrySkill, entrySkill, unitId, failures);
|
|
20672
|
+
if (production) {
|
|
20673
|
+
_checkRequired(action, "parameters.snapshotPath", action.parameters?.snapshotPath, frozen?.path, unitId, failures);
|
|
20674
|
+
_checkRequired(action, "parameters.ref", action.parameters?.ref, expectedTag, unitId, failures);
|
|
20675
|
+
_checkRequired(action, "parameters.manifestDigest", action.parameters?.manifestDigest, frozen?.manifestDigest, unitId, failures);
|
|
20676
|
+
}
|
|
20677
|
+
{
|
|
20678
|
+
const raw = action.parameters?.timeoutMs;
|
|
20679
|
+
if (raw === void 0) {
|
|
20680
|
+
if (!options.legacyCompatibility) {
|
|
20681
|
+
failures.push(
|
|
20682
|
+
`unit "${unitId}", action "${action.id}": parameters.timeoutMs is missing, expected a valid timeout (30000-900000)`
|
|
20683
|
+
);
|
|
20684
|
+
}
|
|
20685
|
+
} else {
|
|
20686
|
+
if (typeof raw !== "number" || !Number.isFinite(raw) || !Number.isInteger(raw)) {
|
|
20687
|
+
failures.push(
|
|
20688
|
+
`unit "${unitId}", action "${action.id}": parameters.timeoutMs must be a finite integer, got: ${JSON.stringify(raw)}`
|
|
20689
|
+
);
|
|
20690
|
+
} else if (raw < 3e4 || raw > 9e5) {
|
|
20691
|
+
failures.push(
|
|
20692
|
+
`unit "${unitId}", action "${action.id}": parameters.timeoutMs must be between 30000 and 900000, got: ${raw}`
|
|
20693
|
+
);
|
|
20694
|
+
}
|
|
20695
|
+
}
|
|
20696
|
+
}
|
|
20697
|
+
_checkRequired(action, "expected.installed", action.expected?.installed, true, unitId, failures);
|
|
20698
|
+
_checkRequired(action, "expected.plugin", action.expected?.plugin, plugin, unitId, failures);
|
|
20699
|
+
_checkRequired(action, "expected.version", action.expected?.version, targetVersion, unitId, failures);
|
|
20700
|
+
_checkRequired(action, "expected.entrySkill", action.expected?.entrySkill, entrySkill, unitId, failures);
|
|
20701
|
+
if (production) {
|
|
20702
|
+
_checkRequired(action, "expected.consumer", action.expected?.consumer, "kimi", unitId, failures);
|
|
20703
|
+
_checkRequired(action, "expected.repo", action.expected?.repo, publicRepo, unitId, failures);
|
|
20704
|
+
_checkRequired(action, "expected.ref", action.expected?.ref, expectedTag, unitId, failures);
|
|
20705
|
+
_checkRequired(action, "expected.entrySkillFound", action.expected?.entrySkillFound, true, unitId, failures);
|
|
20706
|
+
_checkRequired(action, "expected.manifestDigest", action.expected?.manifestDigest, frozen?.manifestDigest, unitId, failures);
|
|
20707
|
+
}
|
|
20708
|
+
}
|
|
20709
|
+
}
|
|
20570
20710
|
if (branchStrategy === "initialize-default-branch") {
|
|
20571
20711
|
const oldBranch = productionConfig.expectedCurrentDefaultBranch;
|
|
20572
20712
|
const newBranch = frozen?.branch;
|
|
@@ -20670,6 +20810,7 @@ var init_plan = __esm({
|
|
|
20670
20810
|
"npm-publish": "npm",
|
|
20671
20811
|
"claude-marketplace-install": "plugin-marketplace",
|
|
20672
20812
|
"codex-marketplace-install": "plugin-marketplace",
|
|
20813
|
+
"kimi-marketplace-install": "plugin-marketplace",
|
|
20673
20814
|
"set-default-branch": "git-github"
|
|
20674
20815
|
};
|
|
20675
20816
|
REQUIRED_ACTION_TYPES = ["push-snapshot", "create-tag", "github-release"];
|
|
@@ -66791,6 +66932,7 @@ var init_contract2 = __esm({
|
|
|
66791
66932
|
// consumer marketplace install (production)
|
|
66792
66933
|
CLAUDE_MARKETPLACE_INSTALL: "claude-marketplace-install",
|
|
66793
66934
|
CODEX_MARKETPLACE_INSTALL: "codex-marketplace-install",
|
|
66935
|
+
KIMI_MARKETPLACE_INSTALL: "kimi-marketplace-install",
|
|
66794
66936
|
// default branch management
|
|
66795
66937
|
SET_DEFAULT_BRANCH: "set-default-branch"
|
|
66796
66938
|
});
|
|
@@ -73782,6 +73924,32 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
|
|
|
73782
73924
|
status: "PENDING"
|
|
73783
73925
|
});
|
|
73784
73926
|
}
|
|
73927
|
+
const kimiDist = (unit.distributions ?? []).find((d) => d.type === "kimi-plugin");
|
|
73928
|
+
if (kimiDist) {
|
|
73929
|
+
const identity = marketplaceIdentity(kimiDist);
|
|
73930
|
+
const kimiTimeoutMs = Number.isInteger(kimiDist.timeoutMs) ? kimiDist.timeoutMs : 3e5;
|
|
73931
|
+
actions.push({
|
|
73932
|
+
id: `kimi-marketplace-install-${unit.id}`,
|
|
73933
|
+
type: "kimi-marketplace-install",
|
|
73934
|
+
adapter: "plugin-marketplace",
|
|
73935
|
+
unitId: unit.id,
|
|
73936
|
+
parameters: {
|
|
73937
|
+
consumer: "kimi",
|
|
73938
|
+
plugin: identity.plugin,
|
|
73939
|
+
repo: unit.publicRepo,
|
|
73940
|
+
version,
|
|
73941
|
+
entrySkill: identity.entrySkill,
|
|
73942
|
+
timeoutMs: kimiTimeoutMs
|
|
73943
|
+
},
|
|
73944
|
+
expected: {
|
|
73945
|
+
installed: true,
|
|
73946
|
+
plugin: identity.plugin,
|
|
73947
|
+
version,
|
|
73948
|
+
entrySkill: identity.entrySkill
|
|
73949
|
+
},
|
|
73950
|
+
status: "PENDING"
|
|
73951
|
+
});
|
|
73952
|
+
}
|
|
73785
73953
|
}
|
|
73786
73954
|
return actions;
|
|
73787
73955
|
}
|
|
@@ -73979,6 +74147,40 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets) {
|
|
|
73979
74147
|
status: "PENDING"
|
|
73980
74148
|
});
|
|
73981
74149
|
}
|
|
74150
|
+
const kimiDist = (unit.distributions ?? []).find((d) => d.type === "kimi-plugin");
|
|
74151
|
+
if (kimiDist) {
|
|
74152
|
+
const identity = marketplaceIdentity(kimiDist);
|
|
74153
|
+
const kimiTimeoutMs = Number.isInteger(kimiDist.timeoutMs) ? kimiDist.timeoutMs : 3e5;
|
|
74154
|
+
actions.push({
|
|
74155
|
+
id: `kimi-marketplace-install-${unit.id}`,
|
|
74156
|
+
type: "kimi-marketplace-install",
|
|
74157
|
+
adapter: "plugin-marketplace",
|
|
74158
|
+
unitId: unit.id,
|
|
74159
|
+
parameters: {
|
|
74160
|
+
consumer: "kimi",
|
|
74161
|
+
plugin: identity.plugin,
|
|
74162
|
+
repo: unit.publicRepo,
|
|
74163
|
+
ref: resolvedTag,
|
|
74164
|
+
version: unitVersion,
|
|
74165
|
+
entrySkill: identity.entrySkill,
|
|
74166
|
+
snapshotPath: asset.snapshotPath,
|
|
74167
|
+
manifestDigest: asset.manifestDigest,
|
|
74168
|
+
timeoutMs: kimiTimeoutMs
|
|
74169
|
+
},
|
|
74170
|
+
expected: {
|
|
74171
|
+
installed: true,
|
|
74172
|
+
consumer: "kimi",
|
|
74173
|
+
plugin: identity.plugin,
|
|
74174
|
+
repo: unit.publicRepo,
|
|
74175
|
+
version: unitVersion,
|
|
74176
|
+
ref: resolvedTag,
|
|
74177
|
+
entrySkill: identity.entrySkill,
|
|
74178
|
+
entrySkillFound: true,
|
|
74179
|
+
manifestDigest: asset.manifestDigest
|
|
74180
|
+
},
|
|
74181
|
+
status: "PENDING"
|
|
74182
|
+
});
|
|
74183
|
+
}
|
|
73982
74184
|
}
|
|
73983
74185
|
return actions;
|
|
73984
74186
|
}
|
|
@@ -76099,7 +76301,8 @@ var init_reconcile = __esm({
|
|
|
76099
76301
|
"npm-publish",
|
|
76100
76302
|
"github-release",
|
|
76101
76303
|
"claude-marketplace-install",
|
|
76102
|
-
"codex-marketplace-install"
|
|
76304
|
+
"codex-marketplace-install",
|
|
76305
|
+
"kimi-marketplace-install"
|
|
76103
76306
|
];
|
|
76104
76307
|
ADAPTER_ACTION_TYPE_MAP = {
|
|
76105
76308
|
"push-commit": "git-push",
|
|
@@ -76109,11 +76312,13 @@ var init_reconcile = __esm({
|
|
|
76109
76312
|
"npm-publish": "npm-publish",
|
|
76110
76313
|
"github-release": "github-release",
|
|
76111
76314
|
"claude-marketplace-install": "claude-marketplace-install",
|
|
76112
|
-
"codex-marketplace-install": "codex-marketplace-install"
|
|
76315
|
+
"codex-marketplace-install": "codex-marketplace-install",
|
|
76316
|
+
"kimi-marketplace-install": "kimi-marketplace-install"
|
|
76113
76317
|
};
|
|
76114
76318
|
MARKETPLACE_TYPES = /* @__PURE__ */ new Set([
|
|
76115
76319
|
"claude-marketplace-install",
|
|
76116
|
-
"codex-marketplace-install"
|
|
76320
|
+
"codex-marketplace-install",
|
|
76321
|
+
"kimi-marketplace-install"
|
|
76117
76322
|
]);
|
|
76118
76323
|
__name(defaultClock2, "defaultClock");
|
|
76119
76324
|
__name(reconcileRelease, "reconcileRelease");
|
|
@@ -76704,7 +76909,9 @@ var init_git_github = __esm({
|
|
|
76704
76909
|
// src/adapters/plugin-marketplace.mjs
|
|
76705
76910
|
var plugin_marketplace_exports = {};
|
|
76706
76911
|
__export(plugin_marketplace_exports, {
|
|
76707
|
-
createPluginMarketplaceAdapter: () => createPluginMarketplaceAdapter
|
|
76912
|
+
createPluginMarketplaceAdapter: () => createPluginMarketplaceAdapter,
|
|
76913
|
+
readKimiManifest: () => readKimiManifest,
|
|
76914
|
+
resolveKimiEntrySkillFile: () => resolveKimiEntrySkillFile
|
|
76708
76915
|
});
|
|
76709
76916
|
import { execFile as execFileCb10 } from "node:child_process";
|
|
76710
76917
|
import { promisify as promisify10 } from "node:util";
|
|
@@ -76734,7 +76941,7 @@ async function verifyInstalledMarketplacePayload(action, context, installPath, c
|
|
|
76734
76941
|
throw new Error("frozen marketplace snapshot digest no longer matches the plan");
|
|
76735
76942
|
}
|
|
76736
76943
|
const installedSnapshot = await computeFrozenSnapshot(installPath, {
|
|
76737
|
-
excludeRootEntries: consumer === "codex" ? [".git"] : []
|
|
76944
|
+
excludeRootEntries: consumer === "codex" || consumer === "kimi" ? [".git"] : []
|
|
76738
76945
|
});
|
|
76739
76946
|
if (JSON.stringify(transportPayload(sourceSnapshot.entries)) !== JSON.stringify(transportPayload(installedSnapshot.entries))) {
|
|
76740
76947
|
throw new Error("installed marketplace payload differs in path, bytes, size, or non-write mode bits");
|
|
@@ -76753,6 +76960,356 @@ async function writeEvidenceAtomic(filePath, value) {
|
|
|
76753
76960
|
throw err;
|
|
76754
76961
|
}
|
|
76755
76962
|
}
|
|
76963
|
+
function normalizePlanForDigest(plan) {
|
|
76964
|
+
const normalized = { ...plan, status: "PREPARED" };
|
|
76965
|
+
if (Array.isArray(plan.externalActions)) {
|
|
76966
|
+
normalized.externalActions = plan.externalActions.map((action) => action && typeof action === "object" && !Array.isArray(action) ? { ...action, status: "PENDING" } : action);
|
|
76967
|
+
}
|
|
76968
|
+
return normalized;
|
|
76969
|
+
}
|
|
76970
|
+
function resolveBoundPlanDigest(context) {
|
|
76971
|
+
const plan = context?.plan;
|
|
76972
|
+
if (!plan || typeof plan !== "object" || Array.isArray(plan)) {
|
|
76973
|
+
throw new Error("context.plan is required to bind the kimi plan digest");
|
|
76974
|
+
}
|
|
76975
|
+
const carried = plan.digest;
|
|
76976
|
+
if (typeof carried !== "string" || !HEX_DIGEST_RE.test(carried)) {
|
|
76977
|
+
throw new Error("context.plan.digest must be a 64-char lowercase hex frozen plan digest");
|
|
76978
|
+
}
|
|
76979
|
+
const normalized = normalizePlanForDigest(plan);
|
|
76980
|
+
if (computePlanDigest(normalized) !== carried) {
|
|
76981
|
+
throw new Error("context.plan.digest does not match the normalized frozen plan (a non-lifecycle field was tampered)");
|
|
76982
|
+
}
|
|
76983
|
+
return carried;
|
|
76984
|
+
}
|
|
76985
|
+
function kimiAuthorityDir(context, planDigest, plugin) {
|
|
76986
|
+
if (!context?.root) {
|
|
76987
|
+
throw new Error("context.root is required for the kimi attestation authority");
|
|
76988
|
+
}
|
|
76989
|
+
if (!HEX_DIGEST_RE.test(planDigest)) {
|
|
76990
|
+
throw new Error("kimi attestation authority requires a 64-hex plan digest");
|
|
76991
|
+
}
|
|
76992
|
+
if (!SAFE_ID_RE.test(plugin)) {
|
|
76993
|
+
throw new Error(`kimi attestation authority requires a safe plugin id: "${plugin}"`);
|
|
76994
|
+
}
|
|
76995
|
+
const base = resolve19(context.root, ".release-skill", "kimi-attestations");
|
|
76996
|
+
const dir = resolve19(base, planDigest, plugin);
|
|
76997
|
+
const rel = relative16(base, dir);
|
|
76998
|
+
const sep4 = process.platform === "win32" ? "\\" : "/";
|
|
76999
|
+
if (rel === "" || rel === ".." || isAbsolute13(rel) || rel.startsWith(`..${sep4}`) || rel.split(sep4).some((segment) => segment === ".." || segment === "")) {
|
|
77000
|
+
throw new Error("kimi attestation authority path escapes its base");
|
|
77001
|
+
}
|
|
77002
|
+
return dir;
|
|
77003
|
+
}
|
|
77004
|
+
function buildKimiInstallUrl(repo, ref) {
|
|
77005
|
+
return `https://github.com/${repo}/releases/tag/${ref}`;
|
|
77006
|
+
}
|
|
77007
|
+
function buildKimiManualInstructions({ installUrl, plugin, version, ref, isolatedHome, attestationDir }) {
|
|
77008
|
+
return [
|
|
77009
|
+
`Kimi Code has no scriptable plugin-install CLI; installation is a manual, interactive step.`,
|
|
77010
|
+
`1) publish fails closed at this kimi checkpoint and leaves the run PARTIAL (the automated Git branch/tag, npm, and GitHub Release writes still complete first).`,
|
|
77011
|
+
`2) Launch Kimi Code with the ISOLATED home from this requirement so the managed copy lands inside it: set HOME="${isolatedHome}" and KIMI_CODE_HOME="${isolatedHome}". The plugin installs to "${isolatedHome}/plugins/managed/${plugin}/".`,
|
|
77012
|
+
`3) In that isolated Kimi Code session run: /plugins install ${installUrl} (pinned to frozen ref "${ref}", version ${version}; never install the bare repository URL). Confirm the trust prompt for plugin "${plugin}", then run /plugins reload (or /new).`,
|
|
77013
|
+
`4) Write the attestation JSON to: ${attestationDir}/${KIMI_ATTESTATION_FILE}. planDigest MUST be the frozen plan digest; payloadDigest MUST be the frozen snapshot payload digest; installPath MUST be the isolated managed directory above. attestedAt must not be in the future and expiresAt must be within 24 hours of attestedAt.`,
|
|
77014
|
+
` Required fields: consumer="kimi", plugin, version, entrySkill, repo, ref, installPath, planDigest, payloadDigest, attestedBy, attestedAt, expiresAt.`,
|
|
77015
|
+
`5) Re-run release-skill reconcile (promotes PARTIAL -> PUBLISHED) and then verify (-> VERIFIED). Both read the attestation from this same plan-digest-keyed authority directory, so a fresh run directory does not lose the proof.`,
|
|
77016
|
+
`An install into the ordinary ~/.kimi-code is NOT acceptable proof: the attested installPath must resolve inside this requirement's isolated KIMI_CODE_HOME managed root, otherwise verification fails closed.`
|
|
77017
|
+
];
|
|
77018
|
+
}
|
|
77019
|
+
async function readKimiManifest(pluginRootReal) {
|
|
77020
|
+
const candidates = [
|
|
77021
|
+
"kimi.plugin.json",
|
|
77022
|
+
join12(".kimi-plugin", "plugin.json")
|
|
77023
|
+
];
|
|
77024
|
+
for (const manifestRelative of candidates) {
|
|
77025
|
+
const manifestPath = resolve19(pluginRootReal, manifestRelative);
|
|
77026
|
+
let content;
|
|
77027
|
+
try {
|
|
77028
|
+
content = await readFile17(manifestPath, "utf8");
|
|
77029
|
+
} catch {
|
|
77030
|
+
continue;
|
|
77031
|
+
}
|
|
77032
|
+
let manifest;
|
|
77033
|
+
try {
|
|
77034
|
+
manifest = JSON.parse(content);
|
|
77035
|
+
} catch {
|
|
77036
|
+
throw new Error(`kimi plugin manifest ${manifestRelative} is not valid JSON`);
|
|
77037
|
+
}
|
|
77038
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
77039
|
+
throw new Error(`kimi plugin manifest ${manifestRelative} is not an object`);
|
|
77040
|
+
}
|
|
77041
|
+
return { manifest, manifestRelative };
|
|
77042
|
+
}
|
|
77043
|
+
throw new Error("no kimi plugin manifest found (expected kimi.plugin.json or .kimi-plugin/plugin.json)");
|
|
77044
|
+
}
|
|
77045
|
+
function normalizeKimiSkillsRel(skillsRaw) {
|
|
77046
|
+
if (typeof skillsRaw !== "string" || skillsRaw.length === 0) {
|
|
77047
|
+
throw new Error("kimi manifest skills must be a non-empty relative path when present");
|
|
77048
|
+
}
|
|
77049
|
+
if (skillsRaw.startsWith("/") || skillsRaw.includes("..") || skillsRaw.includes("\\") || /^https?:\/\//i.test(skillsRaw)) {
|
|
77050
|
+
throw new Error(`kimi manifest skills "${skillsRaw}" is not a safe relative path`);
|
|
77051
|
+
}
|
|
77052
|
+
let rel = skillsRaw.replace(/^\.\//, "");
|
|
77053
|
+
rel = rel.replace(/\/+$/, "");
|
|
77054
|
+
if (rel.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
77055
|
+
throw new Error(`kimi manifest skills "${skillsRaw}" is not a safe relative path`);
|
|
77056
|
+
}
|
|
77057
|
+
return rel;
|
|
77058
|
+
}
|
|
77059
|
+
async function resolveKimiEntrySkillFile(pluginRootReal, manifest, entrySkill) {
|
|
77060
|
+
if (!entrySkill || typeof entrySkill !== "string" || !SAFE_ID_RE.test(entrySkill)) {
|
|
77061
|
+
throw new Error(`unsafe entrySkill: "${entrySkill}"`);
|
|
77062
|
+
}
|
|
77063
|
+
let entryAbs;
|
|
77064
|
+
if (manifest.skills === void 0 || manifest.skills === null) {
|
|
77065
|
+
entryAbs = resolve19(pluginRootReal, "SKILL.md");
|
|
77066
|
+
} else {
|
|
77067
|
+
const skillsRel = normalizeKimiSkillsRel(manifest.skills);
|
|
77068
|
+
const skillsRootAbs = skillsRel === "" ? pluginRootReal : resolve19(pluginRootReal, skillsRel);
|
|
77069
|
+
const skillsRootReal = await realpath11(skillsRootAbs).catch(() => null);
|
|
77070
|
+
if (!skillsRootReal) {
|
|
77071
|
+
throw new Error(`kimi manifest skills root does not exist: ${manifest.skills}`);
|
|
77072
|
+
}
|
|
77073
|
+
const skillsContainment = relative16(pluginRootReal, skillsRootReal);
|
|
77074
|
+
const sepK = process.platform === "win32" ? "\\" : "/";
|
|
77075
|
+
if (skillsContainment !== "" && (isAbsolute13(skillsContainment) || skillsContainment === ".." || skillsContainment.startsWith(`..${sepK}`))) {
|
|
77076
|
+
throw new Error(`kimi manifest skills "${manifest.skills}" escapes the plugin root after symlink resolution`);
|
|
77077
|
+
}
|
|
77078
|
+
entryAbs = resolve19(skillsRootReal, entrySkill, "SKILL.md");
|
|
77079
|
+
}
|
|
77080
|
+
let entryLexicalStat;
|
|
77081
|
+
try {
|
|
77082
|
+
entryLexicalStat = await lstat11(entryAbs);
|
|
77083
|
+
} catch {
|
|
77084
|
+
throw new Error(`kimi entry skill not found: ${relative16(pluginRootReal, entryAbs) || "SKILL.md"}`);
|
|
77085
|
+
}
|
|
77086
|
+
if (entryLexicalStat.isSymbolicLink()) {
|
|
77087
|
+
throw new Error("kimi entry skill must not be a symlink");
|
|
77088
|
+
}
|
|
77089
|
+
if (!entryLexicalStat.isFile()) {
|
|
77090
|
+
throw new Error("kimi entry skill is not a regular file");
|
|
77091
|
+
}
|
|
77092
|
+
const entryReal = await realpath11(entryAbs).catch(() => null);
|
|
77093
|
+
if (!entryReal) {
|
|
77094
|
+
throw new Error(`kimi entry skill not found: ${relative16(pluginRootReal, entryAbs) || "SKILL.md"}`);
|
|
77095
|
+
}
|
|
77096
|
+
const entryContainment = relative16(pluginRootReal, entryReal);
|
|
77097
|
+
const sepE = process.platform === "win32" ? "\\" : "/";
|
|
77098
|
+
if (entryContainment !== "" && (isAbsolute13(entryContainment) || entryContainment === ".." || entryContainment.startsWith(`..${sepE}`))) {
|
|
77099
|
+
throw new Error("kimi entry skill escapes the plugin root after symlink resolution");
|
|
77100
|
+
}
|
|
77101
|
+
return entryReal;
|
|
77102
|
+
}
|
|
77103
|
+
function validateKimiAttestation(attestation, action, isoNow, boundPlanDigest) {
|
|
77104
|
+
if (!attestation || typeof attestation !== "object" || Array.isArray(attestation)) {
|
|
77105
|
+
return { valid: false, error: "kimi attestation is not an object" };
|
|
77106
|
+
}
|
|
77107
|
+
const requiredStrings = ["plugin", "version", "entrySkill", "repo", "ref", "installPath", "payloadDigest", "planDigest", "attestedBy", "attestedAt", "expiresAt"];
|
|
77108
|
+
for (const field of requiredStrings) {
|
|
77109
|
+
if (typeof attestation[field] !== "string" || attestation[field].length === 0) {
|
|
77110
|
+
return { valid: false, error: `kimi attestation missing required field "${field}"` };
|
|
77111
|
+
}
|
|
77112
|
+
}
|
|
77113
|
+
if (attestation.consumer !== "kimi") {
|
|
77114
|
+
return { valid: false, error: `kimi attestation consumer "${attestation.consumer}" must be "kimi"` };
|
|
77115
|
+
}
|
|
77116
|
+
if (!HEX_DIGEST_RE.test(attestation.planDigest)) {
|
|
77117
|
+
return { valid: false, error: "kimi attestation planDigest must be a 64-char lowercase hex digest" };
|
|
77118
|
+
}
|
|
77119
|
+
if (attestation.planDigest !== boundPlanDigest) {
|
|
77120
|
+
return { valid: false, error: "kimi attestation planDigest does not match the frozen plan digest" };
|
|
77121
|
+
}
|
|
77122
|
+
if (attestation.plugin !== action.plugin) {
|
|
77123
|
+
return { valid: false, error: `kimi attestation plugin "${attestation.plugin}" does not match action plugin "${action.plugin}"` };
|
|
77124
|
+
}
|
|
77125
|
+
if (attestation.version !== action.version) {
|
|
77126
|
+
return { valid: false, error: `kimi attestation version "${attestation.version}" does not match action version "${action.version}"` };
|
|
77127
|
+
}
|
|
77128
|
+
if (attestation.entrySkill !== action.entrySkill) {
|
|
77129
|
+
return { valid: false, error: `kimi attestation entrySkill "${attestation.entrySkill}" does not match action entrySkill "${action.entrySkill}"` };
|
|
77130
|
+
}
|
|
77131
|
+
if (attestation.repo !== action.repo) {
|
|
77132
|
+
return { valid: false, error: `kimi attestation repo "${attestation.repo}" does not match action repo "${action.repo}"` };
|
|
77133
|
+
}
|
|
77134
|
+
const expectedRef = action.ref ?? `v${action.version}`;
|
|
77135
|
+
if (attestation.ref !== expectedRef) {
|
|
77136
|
+
return { valid: false, error: `kimi attestation ref "${attestation.ref}" does not match frozen ref "${expectedRef}"` };
|
|
77137
|
+
}
|
|
77138
|
+
if (attestation.payloadDigest !== action.manifestDigest) {
|
|
77139
|
+
return { valid: false, error: "kimi attestation payloadDigest does not match the frozen payload digest" };
|
|
77140
|
+
}
|
|
77141
|
+
const attestedMs = Date.parse(attestation.attestedAt);
|
|
77142
|
+
const expiresMs = Date.parse(attestation.expiresAt);
|
|
77143
|
+
const nowMs = Date.parse(isoNow);
|
|
77144
|
+
if (!Number.isFinite(attestedMs) || !Number.isFinite(expiresMs) || !Number.isFinite(nowMs)) {
|
|
77145
|
+
return { valid: false, error: "kimi attestation attestedAt/expiresAt must be valid ISO timestamps" };
|
|
77146
|
+
}
|
|
77147
|
+
if (attestedMs > nowMs) {
|
|
77148
|
+
return { valid: false, error: "kimi attestation attestedAt is in the future" };
|
|
77149
|
+
}
|
|
77150
|
+
if (expiresMs <= attestedMs) {
|
|
77151
|
+
return { valid: false, error: "kimi attestation expiresAt must be after attestedAt" };
|
|
77152
|
+
}
|
|
77153
|
+
if (expiresMs - attestedMs > KIMI_MAX_ATTESTATION_VALIDITY_MS) {
|
|
77154
|
+
return { valid: false, error: "kimi attestation validity must not exceed 24 hours" };
|
|
77155
|
+
}
|
|
77156
|
+
if (nowMs > expiresMs) {
|
|
77157
|
+
return { valid: false, error: "kimi attestation has expired" };
|
|
77158
|
+
}
|
|
77159
|
+
return { valid: true, error: null };
|
|
77160
|
+
}
|
|
77161
|
+
async function executeKimiManualRequirement(action, context) {
|
|
77162
|
+
const actionType = ActionType.KIMI_MARKETPLACE_INSTALL;
|
|
77163
|
+
let planDigest;
|
|
77164
|
+
try {
|
|
77165
|
+
planDigest = resolveBoundPlanDigest(context);
|
|
77166
|
+
} catch (planErr) {
|
|
77167
|
+
return createResult({
|
|
77168
|
+
actionType,
|
|
77169
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77170
|
+
error: `cannot bind kimi requirement to the frozen plan: ${planErr.message}`
|
|
77171
|
+
});
|
|
77172
|
+
}
|
|
77173
|
+
try {
|
|
77174
|
+
resolveTimeoutMs(action);
|
|
77175
|
+
} catch (timeoutErr) {
|
|
77176
|
+
return createResult({
|
|
77177
|
+
actionType,
|
|
77178
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77179
|
+
error: timeoutErr.message
|
|
77180
|
+
});
|
|
77181
|
+
}
|
|
77182
|
+
const ref = action.ref ?? `v${action.version}`;
|
|
77183
|
+
const installUrl = buildKimiInstallUrl(action.repo, ref);
|
|
77184
|
+
let attestationDir;
|
|
77185
|
+
try {
|
|
77186
|
+
attestationDir = kimiAuthorityDir(context, planDigest, action.plugin);
|
|
77187
|
+
} catch (dirErr) {
|
|
77188
|
+
return createResult({
|
|
77189
|
+
actionType,
|
|
77190
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77191
|
+
error: dirErr.message
|
|
77192
|
+
});
|
|
77193
|
+
}
|
|
77194
|
+
const kimiHome = resolve19(attestationDir, "kimi-home");
|
|
77195
|
+
const managedParent = resolve19(kimiHome, KIMI_MANAGED_SUBPATH);
|
|
77196
|
+
const managedInstallRoot = resolve19(managedParent, action.plugin);
|
|
77197
|
+
const instructions = buildKimiManualInstructions({
|
|
77198
|
+
installUrl,
|
|
77199
|
+
plugin: action.plugin,
|
|
77200
|
+
version: action.version,
|
|
77201
|
+
ref,
|
|
77202
|
+
isolatedHome: kimiHome,
|
|
77203
|
+
attestationDir
|
|
77204
|
+
});
|
|
77205
|
+
const requirement = {
|
|
77206
|
+
kind: "kimi-manual-install-requirement",
|
|
77207
|
+
consumer: "kimi",
|
|
77208
|
+
plugin: action.plugin,
|
|
77209
|
+
version: action.version,
|
|
77210
|
+
entrySkill: action.entrySkill,
|
|
77211
|
+
repo: action.repo,
|
|
77212
|
+
ref,
|
|
77213
|
+
installUrl,
|
|
77214
|
+
// (A) planDigest binds to the real frozen plan digest;
|
|
77215
|
+
// expectedPayloadDigest binds separately to the snapshot payload digest.
|
|
77216
|
+
planDigest,
|
|
77217
|
+
expectedPayloadDigest: action.manifestDigest,
|
|
77218
|
+
isolatedHome: kimiHome,
|
|
77219
|
+
kimiCodeHome: kimiHome,
|
|
77220
|
+
managedInstallRoot,
|
|
77221
|
+
attestationDir,
|
|
77222
|
+
attestationFile: KIMI_ATTESTATION_FILE,
|
|
77223
|
+
attestationTemplate: {
|
|
77224
|
+
consumer: "kimi",
|
|
77225
|
+
plugin: action.plugin,
|
|
77226
|
+
version: action.version,
|
|
77227
|
+
entrySkill: action.entrySkill,
|
|
77228
|
+
repo: action.repo,
|
|
77229
|
+
ref,
|
|
77230
|
+
installPath: managedInstallRoot,
|
|
77231
|
+
planDigest,
|
|
77232
|
+
payloadDigest: action.manifestDigest,
|
|
77233
|
+
attestedBy: "<person responsible for the manual install>",
|
|
77234
|
+
attestedAt: "<ISO 8601 now; must not be in the future>",
|
|
77235
|
+
expiresAt: "<ISO 8601; within 24h of attestedAt>"
|
|
77236
|
+
},
|
|
77237
|
+
instructions
|
|
77238
|
+
};
|
|
77239
|
+
try {
|
|
77240
|
+
await mkdir11(managedParent, { recursive: true, mode: 448 });
|
|
77241
|
+
} catch (mkdirErr) {
|
|
77242
|
+
return createResult({
|
|
77243
|
+
actionType,
|
|
77244
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77245
|
+
error: `cannot create kimi managed parent directory: ${mkdirErr.message}`
|
|
77246
|
+
});
|
|
77247
|
+
}
|
|
77248
|
+
const requirementPath = resolve19(attestationDir, KIMI_REQUIREMENT_FILE);
|
|
77249
|
+
let existing = null;
|
|
77250
|
+
let requirementMissing = false;
|
|
77251
|
+
try {
|
|
77252
|
+
const existingRaw = await readFile17(requirementPath, "utf8");
|
|
77253
|
+
try {
|
|
77254
|
+
existing = JSON.parse(existingRaw);
|
|
77255
|
+
} catch (parseErr) {
|
|
77256
|
+
return createResult({
|
|
77257
|
+
actionType,
|
|
77258
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77259
|
+
error: `existing kimi manual-install requirement is invalid JSON; refusing to overwrite: ${parseErr.message}`
|
|
77260
|
+
});
|
|
77261
|
+
}
|
|
77262
|
+
} catch (readErr) {
|
|
77263
|
+
if (readErr?.code === "ENOENT") {
|
|
77264
|
+
requirementMissing = true;
|
|
77265
|
+
} else {
|
|
77266
|
+
return createResult({
|
|
77267
|
+
actionType,
|
|
77268
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77269
|
+
error: `existing kimi manual-install requirement cannot be read; refusing to overwrite: ${readErr.message}`
|
|
77270
|
+
});
|
|
77271
|
+
}
|
|
77272
|
+
}
|
|
77273
|
+
if (!requirementMissing) {
|
|
77274
|
+
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
77275
|
+
return createResult({
|
|
77276
|
+
actionType,
|
|
77277
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77278
|
+
error: "existing kimi manual-install requirement is not an object; refusing to overwrite"
|
|
77279
|
+
});
|
|
77280
|
+
}
|
|
77281
|
+
const { createdAt: _existingCreatedAt, ...existingBody } = existing;
|
|
77282
|
+
if (canonicalJson(existingBody) !== canonicalJson(requirement)) {
|
|
77283
|
+
return createResult({
|
|
77284
|
+
actionType,
|
|
77285
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77286
|
+
error: "existing kimi manual-install requirement conflicts with the current frozen action; refusing to overwrite"
|
|
77287
|
+
});
|
|
77288
|
+
}
|
|
77289
|
+
} else {
|
|
77290
|
+
await writeEvidenceAtomic(requirementPath, { ...requirement, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
77291
|
+
}
|
|
77292
|
+
return createResult({
|
|
77293
|
+
actionType,
|
|
77294
|
+
status: ActionStatus.EXECUTED,
|
|
77295
|
+
observation: {
|
|
77296
|
+
installed: false,
|
|
77297
|
+
manualInstallRequired: true,
|
|
77298
|
+
consumer: "kimi",
|
|
77299
|
+
plugin: action.plugin,
|
|
77300
|
+
version: action.version,
|
|
77301
|
+
entrySkill: action.entrySkill,
|
|
77302
|
+
repo: action.repo,
|
|
77303
|
+
ref,
|
|
77304
|
+
installUrl,
|
|
77305
|
+
planDigest,
|
|
77306
|
+
attestationDir,
|
|
77307
|
+
kimiCodeHome: kimiHome,
|
|
77308
|
+
managedInstallRoot,
|
|
77309
|
+
instructions
|
|
77310
|
+
}
|
|
77311
|
+
});
|
|
77312
|
+
}
|
|
76756
77313
|
function validateSafeRef(ref) {
|
|
76757
77314
|
if (!ref || typeof ref !== "string") {
|
|
76758
77315
|
return { valid: false, error: "ref is required" };
|
|
@@ -76800,13 +77357,17 @@ function validateMarketplaceParams(params) {
|
|
|
76800
77357
|
return { valid: false, error: "parameters must be an object" };
|
|
76801
77358
|
}
|
|
76802
77359
|
const { consumer, plugin, marketplace, repo, version, entrySkill } = params;
|
|
76803
|
-
if (!["claude", "codex"].includes(consumer)) {
|
|
77360
|
+
if (!["claude", "codex", "kimi"].includes(consumer)) {
|
|
76804
77361
|
return { valid: false, error: `invalid consumer: "${consumer}"` };
|
|
76805
77362
|
}
|
|
76806
77363
|
if (!plugin || !SAFE_ID_RE.test(plugin)) {
|
|
76807
77364
|
return { valid: false, error: `unsafe plugin identifier: "${plugin}"` };
|
|
76808
77365
|
}
|
|
76809
|
-
if (
|
|
77366
|
+
if (consumer === "kimi") {
|
|
77367
|
+
if (marketplace !== void 0 && marketplace !== null && !SAFE_ID_RE.test(marketplace)) {
|
|
77368
|
+
return { valid: false, error: `unsafe marketplace identifier: "${marketplace}"` };
|
|
77369
|
+
}
|
|
77370
|
+
} else if (!marketplace || !SAFE_ID_RE.test(marketplace)) {
|
|
76810
77371
|
return { valid: false, error: `unsafe marketplace identifier: "${marketplace}"` };
|
|
76811
77372
|
}
|
|
76812
77373
|
if (!repo || !SAFE_REPO_RE.test(repo)) {
|
|
@@ -76945,7 +77506,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
76945
77506
|
status: ActionStatus.PREFLIGHT_PASSED
|
|
76946
77507
|
});
|
|
76947
77508
|
}
|
|
76948
|
-
if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL) {
|
|
77509
|
+
if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
|
|
76949
77510
|
const validation = validateMarketplaceParams(action);
|
|
76950
77511
|
if (!validation.valid) {
|
|
76951
77512
|
return createResult({
|
|
@@ -77009,6 +77570,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77009
77570
|
}
|
|
77010
77571
|
const consumer = action.consumer;
|
|
77011
77572
|
let snapshotDirReal;
|
|
77573
|
+
let kimiSnapshotManifest = null;
|
|
77012
77574
|
try {
|
|
77013
77575
|
snapshotDirReal = await resolveFrozenPath(context.root, snapshotPath, "frozen snapshot path");
|
|
77014
77576
|
} catch (frozenErr) {
|
|
@@ -77018,120 +77580,162 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77018
77580
|
error: `frozen snapshot validation failed: ${frozenErr.message}`
|
|
77019
77581
|
});
|
|
77020
77582
|
}
|
|
77021
|
-
|
|
77022
|
-
|
|
77023
|
-
|
|
77024
|
-
|
|
77025
|
-
|
|
77026
|
-
|
|
77027
|
-
|
|
77028
|
-
|
|
77029
|
-
|
|
77030
|
-
|
|
77031
|
-
|
|
77032
|
-
|
|
77033
|
-
|
|
77034
|
-
|
|
77035
|
-
|
|
77036
|
-
|
|
77037
|
-
|
|
77038
|
-
|
|
77039
|
-
|
|
77040
|
-
|
|
77041
|
-
|
|
77042
|
-
|
|
77043
|
-
|
|
77044
|
-
|
|
77045
|
-
|
|
77046
|
-
|
|
77047
|
-
|
|
77048
|
-
return createResult({
|
|
77049
|
-
actionType,
|
|
77050
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77051
|
-
error: `expected exactly one plugins[] entry with name "${action.plugin}", found ${pluginEntry.length}`
|
|
77052
|
-
});
|
|
77053
|
-
}
|
|
77054
|
-
const entry = pluginEntry[0];
|
|
77055
|
-
const sourcePath = consumer === "claude" ? entry.source : entry.source?.source === "local" ? entry.source?.path : null;
|
|
77056
|
-
if (typeof sourcePath !== "string" || sourcePath.length === 0) {
|
|
77057
|
-
return createResult({
|
|
77058
|
-
actionType,
|
|
77059
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77060
|
-
error: `marketplace plugin entry source must be a non-empty relative path${consumer === "codex" ? ' (object with source:"local")' : ""}, got ${JSON.stringify(entry.source)}`
|
|
77061
|
-
});
|
|
77062
|
-
}
|
|
77063
|
-
if (sourcePath.startsWith("/") || sourcePath.includes("..") || sourcePath.includes("\\") || /^https?:\/\//i.test(sourcePath)) {
|
|
77064
|
-
return createResult({
|
|
77065
|
-
actionType,
|
|
77066
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77067
|
-
error: `marketplace plugin entry source "${sourcePath}" is not a safe relative path`
|
|
77068
|
-
});
|
|
77069
|
-
}
|
|
77070
|
-
const sourceDirAbs = resolve19(snapshotDirReal, sourcePath);
|
|
77071
|
-
const sourceDirReal = await realpath11(sourceDirAbs).catch(() => null);
|
|
77072
|
-
if (!sourceDirReal) {
|
|
77073
|
-
return createResult({
|
|
77074
|
-
actionType,
|
|
77075
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77076
|
-
error: `marketplace plugin entry source directory does not exist: ${sourcePath}`
|
|
77077
|
-
});
|
|
77078
|
-
}
|
|
77079
|
-
const sourceRelCheck = relative16(snapshotDirReal, sourceDirReal);
|
|
77080
|
-
if (sourceRelCheck.startsWith("..") || isAbsolute13(sourceRelCheck)) {
|
|
77081
|
-
return createResult({
|
|
77082
|
-
actionType,
|
|
77083
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77084
|
-
error: `marketplace plugin entry source "${sourcePath}" escapes the frozen snapshot`
|
|
77085
|
-
});
|
|
77086
|
-
}
|
|
77087
|
-
const manifestRelative = consumer === "claude" ? join12(sourcePath, ".claude-plugin", "plugin.json") : join12(sourcePath, ".codex-plugin", "plugin.json");
|
|
77088
|
-
const manifestPath = resolve19(snapshotDirReal, manifestRelative);
|
|
77089
|
-
const manifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
|
|
77090
|
-
if (!manifestResult.valid) {
|
|
77091
|
-
return createResult({
|
|
77092
|
-
actionType,
|
|
77093
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77094
|
-
error: `frozen snapshot ${manifestRelative} invalid: ${manifestResult.error}`
|
|
77095
|
-
});
|
|
77096
|
-
}
|
|
77097
|
-
if (consumer === "claude" && entry.version !== action.version) {
|
|
77098
|
-
return createResult({
|
|
77099
|
-
actionType,
|
|
77100
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77101
|
-
error: `marketplace plugin entry version "${entry.version}" does not match action version "${action.version}"`
|
|
77102
|
-
});
|
|
77103
|
-
}
|
|
77104
|
-
const pluginManifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
|
|
77105
|
-
if (!pluginManifestResult.valid) {
|
|
77106
|
-
return createResult({
|
|
77107
|
-
actionType,
|
|
77108
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77109
|
-
error: `frozen snapshot ${manifestRelative} invalid: ${pluginManifestResult.error}`
|
|
77110
|
-
});
|
|
77111
|
-
}
|
|
77112
|
-
if (pluginManifestResult.manifest.name !== entry.name) {
|
|
77113
|
-
return createResult({
|
|
77114
|
-
actionType,
|
|
77115
|
-
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77116
|
-
error: `plugin manifest name "${pluginManifestResult.manifest.name}" does not match marketplace entry name "${entry.name}"`
|
|
77117
|
-
});
|
|
77583
|
+
if (consumer === "kimi") {
|
|
77584
|
+
let kimiManifestResult;
|
|
77585
|
+
try {
|
|
77586
|
+
kimiManifestResult = await readKimiManifest(snapshotDirReal);
|
|
77587
|
+
} catch (manifestErr) {
|
|
77588
|
+
return createResult({
|
|
77589
|
+
actionType,
|
|
77590
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77591
|
+
error: `frozen snapshot kimi manifest invalid: ${manifestErr.message}`
|
|
77592
|
+
});
|
|
77593
|
+
}
|
|
77594
|
+
const kimiManifest = kimiManifestResult.manifest;
|
|
77595
|
+
if (typeof kimiManifest.name !== "string" || kimiManifest.name !== action.plugin) {
|
|
77596
|
+
return createResult({
|
|
77597
|
+
actionType,
|
|
77598
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77599
|
+
error: `plugin manifest name "${kimiManifest.name}" does not match action plugin "${action.plugin}"`
|
|
77600
|
+
});
|
|
77601
|
+
}
|
|
77602
|
+
if (typeof kimiManifest.version !== "string" || kimiManifest.version !== action.version) {
|
|
77603
|
+
return createResult({
|
|
77604
|
+
actionType,
|
|
77605
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77606
|
+
error: `plugin manifest version "${kimiManifest.version}" does not match action version "${action.version}"`
|
|
77607
|
+
});
|
|
77608
|
+
}
|
|
77609
|
+
kimiSnapshotManifest = kimiManifest;
|
|
77118
77610
|
}
|
|
77119
|
-
if (
|
|
77120
|
-
|
|
77121
|
-
|
|
77122
|
-
|
|
77123
|
-
|
|
77124
|
-
|
|
77611
|
+
if (consumer !== "kimi") {
|
|
77612
|
+
const marketplaceRelative = consumer === "claude" ? ".claude-plugin/marketplace.json" : ".agents/plugins/marketplace.json";
|
|
77613
|
+
const marketplacePath = resolve19(snapshotDirReal, marketplaceRelative);
|
|
77614
|
+
const marketplaceResult = await validateManifestFile(marketplacePath, ["name"]);
|
|
77615
|
+
if (!marketplaceResult.valid) {
|
|
77616
|
+
return createResult({
|
|
77617
|
+
actionType,
|
|
77618
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77619
|
+
error: `frozen snapshot ${marketplaceRelative} invalid: ${marketplaceResult.error}`
|
|
77620
|
+
});
|
|
77621
|
+
}
|
|
77622
|
+
if (marketplaceResult.manifest.name !== action.marketplace) {
|
|
77623
|
+
return createResult({
|
|
77624
|
+
actionType,
|
|
77625
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77626
|
+
error: `marketplace.json name "${marketplaceResult.manifest.name}" does not match action marketplace "${action.marketplace}"`
|
|
77627
|
+
});
|
|
77628
|
+
}
|
|
77629
|
+
const plugins = marketplaceResult.manifest.plugins;
|
|
77630
|
+
if (!Array.isArray(plugins)) {
|
|
77631
|
+
return createResult({
|
|
77632
|
+
actionType,
|
|
77633
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77634
|
+
error: `${marketplaceRelative} must have a plugins[] array`
|
|
77635
|
+
});
|
|
77636
|
+
}
|
|
77637
|
+
const pluginEntry = plugins.filter((p) => p.name === action.plugin);
|
|
77638
|
+
if (pluginEntry.length !== 1) {
|
|
77639
|
+
return createResult({
|
|
77640
|
+
actionType,
|
|
77641
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77642
|
+
error: `expected exactly one plugins[] entry with name "${action.plugin}", found ${pluginEntry.length}`
|
|
77643
|
+
});
|
|
77644
|
+
}
|
|
77645
|
+
const entry = pluginEntry[0];
|
|
77646
|
+
const sourcePath = consumer === "claude" ? entry.source : entry.source?.source === "local" ? entry.source?.path : null;
|
|
77647
|
+
if (typeof sourcePath !== "string" || sourcePath.length === 0) {
|
|
77648
|
+
return createResult({
|
|
77649
|
+
actionType,
|
|
77650
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77651
|
+
error: `marketplace plugin entry source must be a non-empty relative path${consumer === "codex" ? ' (object with source:"local")' : ""}, got ${JSON.stringify(entry.source)}`
|
|
77652
|
+
});
|
|
77653
|
+
}
|
|
77654
|
+
if (sourcePath.startsWith("/") || sourcePath.includes("..") || sourcePath.includes("\\") || /^https?:\/\//i.test(sourcePath)) {
|
|
77655
|
+
return createResult({
|
|
77656
|
+
actionType,
|
|
77657
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77658
|
+
error: `marketplace plugin entry source "${sourcePath}" is not a safe relative path`
|
|
77659
|
+
});
|
|
77660
|
+
}
|
|
77661
|
+
const sourceDirAbs = resolve19(snapshotDirReal, sourcePath);
|
|
77662
|
+
const sourceDirReal = await realpath11(sourceDirAbs).catch(() => null);
|
|
77663
|
+
if (!sourceDirReal) {
|
|
77664
|
+
return createResult({
|
|
77665
|
+
actionType,
|
|
77666
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77667
|
+
error: `marketplace plugin entry source directory does not exist: ${sourcePath}`
|
|
77668
|
+
});
|
|
77669
|
+
}
|
|
77670
|
+
const sourceRelCheck = relative16(snapshotDirReal, sourceDirReal);
|
|
77671
|
+
if (sourceRelCheck.startsWith("..") || isAbsolute13(sourceRelCheck)) {
|
|
77672
|
+
return createResult({
|
|
77673
|
+
actionType,
|
|
77674
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77675
|
+
error: `marketplace plugin entry source "${sourcePath}" escapes the frozen snapshot`
|
|
77676
|
+
});
|
|
77677
|
+
}
|
|
77678
|
+
const manifestRelative = consumer === "claude" ? join12(sourcePath, ".claude-plugin", "plugin.json") : join12(sourcePath, ".codex-plugin", "plugin.json");
|
|
77679
|
+
const manifestPath = resolve19(snapshotDirReal, manifestRelative);
|
|
77680
|
+
const manifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
|
|
77681
|
+
if (!manifestResult.valid) {
|
|
77682
|
+
return createResult({
|
|
77683
|
+
actionType,
|
|
77684
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77685
|
+
error: `frozen snapshot ${manifestRelative} invalid: ${manifestResult.error}`
|
|
77686
|
+
});
|
|
77687
|
+
}
|
|
77688
|
+
if (consumer === "claude" && entry.version !== action.version) {
|
|
77689
|
+
return createResult({
|
|
77690
|
+
actionType,
|
|
77691
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77692
|
+
error: `marketplace plugin entry version "${entry.version}" does not match action version "${action.version}"`
|
|
77693
|
+
});
|
|
77694
|
+
}
|
|
77695
|
+
const pluginManifestResult = await validateManifestFile(manifestPath, ["name", "version"]);
|
|
77696
|
+
if (!pluginManifestResult.valid) {
|
|
77697
|
+
return createResult({
|
|
77698
|
+
actionType,
|
|
77699
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77700
|
+
error: `frozen snapshot ${manifestRelative} invalid: ${pluginManifestResult.error}`
|
|
77701
|
+
});
|
|
77702
|
+
}
|
|
77703
|
+
if (pluginManifestResult.manifest.name !== entry.name) {
|
|
77704
|
+
return createResult({
|
|
77705
|
+
actionType,
|
|
77706
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77707
|
+
error: `plugin manifest name "${pluginManifestResult.manifest.name}" does not match marketplace entry name "${entry.name}"`
|
|
77708
|
+
});
|
|
77709
|
+
}
|
|
77710
|
+
if (pluginManifestResult.manifest.version !== action.version) {
|
|
77711
|
+
return createResult({
|
|
77712
|
+
actionType,
|
|
77713
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77714
|
+
error: `plugin manifest version "${pluginManifestResult.manifest.version}" does not match action version "${action.version}"`
|
|
77715
|
+
});
|
|
77716
|
+
}
|
|
77125
77717
|
}
|
|
77126
|
-
|
|
77127
|
-
|
|
77128
|
-
|
|
77129
|
-
|
|
77130
|
-
|
|
77131
|
-
|
|
77132
|
-
|
|
77133
|
-
|
|
77134
|
-
|
|
77718
|
+
if (consumer === "kimi") {
|
|
77719
|
+
try {
|
|
77720
|
+
await resolveKimiEntrySkillFile(snapshotDirReal, kimiSnapshotManifest, action.entrySkill);
|
|
77721
|
+
} catch (entryErr) {
|
|
77722
|
+
return createResult({
|
|
77723
|
+
actionType,
|
|
77724
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77725
|
+
error: `entry skill not resolvable in snapshot: ${entryErr.message}`
|
|
77726
|
+
});
|
|
77727
|
+
}
|
|
77728
|
+
} else {
|
|
77729
|
+
const entrySkillFile = resolve19(snapshotDirReal, "skills", action.entrySkill, "SKILL.md");
|
|
77730
|
+
try {
|
|
77731
|
+
await stat5(entrySkillFile);
|
|
77732
|
+
} catch {
|
|
77733
|
+
return createResult({
|
|
77734
|
+
actionType,
|
|
77735
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
77736
|
+
error: `entry skill not found in snapshot: skills/${action.entrySkill}/SKILL.md`
|
|
77737
|
+
});
|
|
77738
|
+
}
|
|
77135
77739
|
}
|
|
77136
77740
|
try {
|
|
77137
77741
|
const { digest: actualDigest } = await computeFrozenSnapshot(snapshotDirReal);
|
|
@@ -77255,7 +77859,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77255
77859
|
});
|
|
77256
77860
|
}
|
|
77257
77861
|
}
|
|
77258
|
-
if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL) {
|
|
77862
|
+
if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
|
|
77259
77863
|
try {
|
|
77260
77864
|
assertIsolatedConsumerWritesAuthorized(context, actionType);
|
|
77261
77865
|
const validation = validateMarketplaceParams(action);
|
|
@@ -77280,6 +77884,9 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77280
77884
|
error: "context.runDir is required for marketplace install"
|
|
77281
77885
|
});
|
|
77282
77886
|
}
|
|
77887
|
+
if (action.consumer === "kimi") {
|
|
77888
|
+
return executeKimiManualRequirement(action, context);
|
|
77889
|
+
}
|
|
77283
77890
|
const consumer = action.consumer;
|
|
77284
77891
|
const runDir = context.runDir;
|
|
77285
77892
|
const isolatedHome = resolve19(runDir, "consumers", `${consumer}-${action.plugin}`);
|
|
@@ -77317,41 +77924,43 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77317
77924
|
});
|
|
77318
77925
|
}
|
|
77319
77926
|
const ref = action.ref ?? `v${action.version}`;
|
|
77320
|
-
let addOutput;
|
|
77321
|
-
|
|
77322
|
-
|
|
77323
|
-
|
|
77324
|
-
|
|
77325
|
-
|
|
77326
|
-
|
|
77327
|
-
|
|
77328
|
-
|
|
77329
|
-
|
|
77330
|
-
|
|
77331
|
-
|
|
77332
|
-
|
|
77333
|
-
|
|
77334
|
-
|
|
77927
|
+
let addOutput = null;
|
|
77928
|
+
if (consumer !== "kimi") {
|
|
77929
|
+
const marketplaceArgs = consumer === "claude" ? ["plugin", "marketplace", "add", `${action.repo}@${ref}`] : ["plugin", "marketplace", "add", action.repo, "--ref", ref, "--json"];
|
|
77930
|
+
try {
|
|
77931
|
+
const addResult = await exec(cliCmd, marketplaceArgs, { env, cwd: context.root, timeout: frozenTimeoutMs });
|
|
77932
|
+
if (consumer === "codex") {
|
|
77933
|
+
try {
|
|
77934
|
+
addOutput = JSON.parse(addResult.stdout);
|
|
77935
|
+
if (!addOutput || typeof addOutput !== "object") {
|
|
77936
|
+
return createResult({
|
|
77937
|
+
actionType,
|
|
77938
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77939
|
+
error: "marketplace add returned invalid JSON output"
|
|
77940
|
+
});
|
|
77941
|
+
}
|
|
77942
|
+
if (addOutput.marketplaceName !== action.marketplace) {
|
|
77943
|
+
return createResult({
|
|
77944
|
+
actionType,
|
|
77945
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77946
|
+
error: `marketplace add marketplaceName "${addOutput.marketplaceName}" does not match action marketplace "${action.marketplace}"`
|
|
77947
|
+
});
|
|
77948
|
+
}
|
|
77949
|
+
} catch {
|
|
77335
77950
|
return createResult({
|
|
77336
77951
|
actionType,
|
|
77337
77952
|
status: ActionStatus.EXECUTE_FAILED,
|
|
77338
|
-
error:
|
|
77953
|
+
error: "marketplace add returned malformed JSON"
|
|
77339
77954
|
});
|
|
77340
77955
|
}
|
|
77341
|
-
} catch {
|
|
77342
|
-
return createResult({
|
|
77343
|
-
actionType,
|
|
77344
|
-
status: ActionStatus.EXECUTE_FAILED,
|
|
77345
|
-
error: "marketplace add returned malformed JSON"
|
|
77346
|
-
});
|
|
77347
77956
|
}
|
|
77957
|
+
} catch (addErr) {
|
|
77958
|
+
return createResult({
|
|
77959
|
+
actionType,
|
|
77960
|
+
status: ActionStatus.EXECUTE_FAILED,
|
|
77961
|
+
error: `marketplace add failed: ${addErr.message}`
|
|
77962
|
+
});
|
|
77348
77963
|
}
|
|
77349
|
-
} catch (addErr) {
|
|
77350
|
-
return createResult({
|
|
77351
|
-
actionType,
|
|
77352
|
-
status: ActionStatus.EXECUTE_FAILED,
|
|
77353
|
-
error: `marketplace add failed: ${addErr.message}`
|
|
77354
|
-
});
|
|
77355
77964
|
}
|
|
77356
77965
|
let installOutput;
|
|
77357
77966
|
const installArgs = consumer === "claude" ? ["plugin", "install", `${action.plugin}@${action.marketplace}`] : ["plugin", "add", `${action.plugin}@${action.marketplace}`, "--json"];
|
|
@@ -77489,6 +78098,10 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77489
78098
|
* For Codex: uses pluginId === "plugin@marketplace" match in installed array,
|
|
77490
78099
|
* reads installedPath from add/install output or list, verifies install dir
|
|
77491
78100
|
* is inside isolated HOME, computes real manifestDigest.
|
|
78101
|
+
*
|
|
78102
|
+
* For Kimi: uses name === plugin match in installed array, reads
|
|
78103
|
+
* installedPath from validated install evidence, verifies install dir
|
|
78104
|
+
* is inside isolated HOME, computes real manifestDigest.
|
|
77492
78105
|
*/
|
|
77493
78106
|
async observe(action, context) {
|
|
77494
78107
|
const { actionType } = action;
|
|
@@ -77529,7 +78142,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77529
78142
|
}
|
|
77530
78143
|
});
|
|
77531
78144
|
}
|
|
77532
|
-
if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL) {
|
|
78145
|
+
if (actionType === ActionType.CLAUDE_MARKETPLACE_INSTALL || actionType === ActionType.CODEX_MARKETPLACE_INSTALL || actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
|
|
77533
78146
|
const consumer = action.consumer;
|
|
77534
78147
|
const runDir = context.runDir;
|
|
77535
78148
|
if (!runDir) {
|
|
@@ -77540,11 +78153,11 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77540
78153
|
});
|
|
77541
78154
|
}
|
|
77542
78155
|
const isolatedHome = resolve19(runDir, "consumers", `${consumer}-${action.plugin}`);
|
|
77543
|
-
const cliCmd = consumer === "claude" ? "claude" : "codex";
|
|
78156
|
+
const cliCmd = consumer === "claude" ? "claude" : consumer === "codex" ? "codex" : "kimi";
|
|
77544
78157
|
const baseEnv = { ...process.env, ...context.env ?? {} };
|
|
77545
78158
|
const env = {
|
|
77546
78159
|
...baseEnv,
|
|
77547
|
-
...consumer === "claude" ? { HOME: isolatedHome, CLAUDE_CONFIG_DIR: resolve19(isolatedHome, ".claude") } : { HOME: isolatedHome, CODEX_HOME: isolatedHome }
|
|
78160
|
+
...consumer === "claude" ? { HOME: isolatedHome, CLAUDE_CONFIG_DIR: resolve19(isolatedHome, ".claude") } : consumer === "codex" ? { HOME: isolatedHome, CODEX_HOME: isolatedHome } : { HOME: isolatedHome, KIMI_CODE_HOME: isolatedHome }
|
|
77548
78161
|
};
|
|
77549
78162
|
let frozenTimeoutMs;
|
|
77550
78163
|
try {
|
|
@@ -77557,6 +78170,236 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77557
78170
|
error: timeoutErr.message
|
|
77558
78171
|
});
|
|
77559
78172
|
}
|
|
78173
|
+
if (consumer === "kimi") {
|
|
78174
|
+
const expectedRef = action.ref ?? `v${action.version}`;
|
|
78175
|
+
let boundPlanDigest;
|
|
78176
|
+
try {
|
|
78177
|
+
boundPlanDigest = resolveBoundPlanDigest(context);
|
|
78178
|
+
} catch (planErr) {
|
|
78179
|
+
return createResult({
|
|
78180
|
+
actionType,
|
|
78181
|
+
status: ActionStatus.OBSERVED,
|
|
78182
|
+
observation: {
|
|
78183
|
+
installed: false,
|
|
78184
|
+
error: `cannot bind kimi observation to the frozen plan: ${planErr.message}`
|
|
78185
|
+
}
|
|
78186
|
+
});
|
|
78187
|
+
}
|
|
78188
|
+
let attestationDir;
|
|
78189
|
+
try {
|
|
78190
|
+
attestationDir = kimiAuthorityDir(context, boundPlanDigest, action.plugin);
|
|
78191
|
+
} catch (dirErr) {
|
|
78192
|
+
return createResult({
|
|
78193
|
+
actionType,
|
|
78194
|
+
status: ActionStatus.OBSERVED,
|
|
78195
|
+
observation: { installed: false, error: dirErr.message }
|
|
78196
|
+
});
|
|
78197
|
+
}
|
|
78198
|
+
let requirement = null;
|
|
78199
|
+
try {
|
|
78200
|
+
requirement = JSON.parse(await readFile17(resolve19(attestationDir, KIMI_REQUIREMENT_FILE), "utf8"));
|
|
78201
|
+
} catch {
|
|
78202
|
+
return createResult({
|
|
78203
|
+
actionType,
|
|
78204
|
+
status: ActionStatus.OBSERVED,
|
|
78205
|
+
observation: {
|
|
78206
|
+
installed: false,
|
|
78207
|
+
manualInstallRequired: true,
|
|
78208
|
+
error: "kimi manual-install requirement is missing; run execute first"
|
|
78209
|
+
}
|
|
78210
|
+
});
|
|
78211
|
+
}
|
|
78212
|
+
if (requirement.planDigest !== boundPlanDigest || requirement.plugin !== action.plugin || requirement.version !== action.version || requirement.entrySkill !== action.entrySkill || requirement.repo !== action.repo || requirement.ref !== expectedRef) {
|
|
78213
|
+
return createResult({
|
|
78214
|
+
actionType,
|
|
78215
|
+
status: ActionStatus.OBSERVED,
|
|
78216
|
+
observation: {
|
|
78217
|
+
installed: false,
|
|
78218
|
+
error: "kimi manual-install requirement does not match the frozen plan/action"
|
|
78219
|
+
}
|
|
78220
|
+
});
|
|
78221
|
+
}
|
|
78222
|
+
let attestation = null;
|
|
78223
|
+
try {
|
|
78224
|
+
attestation = JSON.parse(await readFile17(resolve19(attestationDir, KIMI_ATTESTATION_FILE), "utf8"));
|
|
78225
|
+
} catch {
|
|
78226
|
+
return createResult({
|
|
78227
|
+
actionType,
|
|
78228
|
+
status: ActionStatus.OBSERVED,
|
|
78229
|
+
observation: {
|
|
78230
|
+
installed: false,
|
|
78231
|
+
manualInstallRequired: true,
|
|
78232
|
+
installUrl: requirement.installUrl,
|
|
78233
|
+
attestationDir,
|
|
78234
|
+
error: `kimi attestation is missing; write ${resolve19(attestationDir, KIMI_ATTESTATION_FILE)} after the interactive install (${requirement.installUrl})`
|
|
78235
|
+
}
|
|
78236
|
+
});
|
|
78237
|
+
}
|
|
78238
|
+
const attestationCheck = validateKimiAttestation(attestation, action, (/* @__PURE__ */ new Date()).toISOString(), boundPlanDigest);
|
|
78239
|
+
if (!attestationCheck.valid) {
|
|
78240
|
+
return createResult({
|
|
78241
|
+
actionType,
|
|
78242
|
+
status: ActionStatus.OBSERVED,
|
|
78243
|
+
observation: { installed: false, error: attestationCheck.error }
|
|
78244
|
+
});
|
|
78245
|
+
}
|
|
78246
|
+
const kimiCodeHome = resolve19(attestationDir, "kimi-home");
|
|
78247
|
+
const kimiCodeHomeReal = await realpath11(kimiCodeHome).catch(() => null);
|
|
78248
|
+
if (!kimiCodeHomeReal) {
|
|
78249
|
+
return createResult({
|
|
78250
|
+
actionType,
|
|
78251
|
+
status: ActionStatus.OBSERVED,
|
|
78252
|
+
observation: {
|
|
78253
|
+
installed: false,
|
|
78254
|
+
error: `KIMI_CODE_HOME does not exist or cannot be resolved: ${kimiCodeHome}`
|
|
78255
|
+
}
|
|
78256
|
+
});
|
|
78257
|
+
}
|
|
78258
|
+
const managedRootReal = await realpath11(resolve19(kimiCodeHomeReal, KIMI_MANAGED_SUBPATH, action.plugin)).catch(() => null);
|
|
78259
|
+
if (!managedRootReal) {
|
|
78260
|
+
return createResult({
|
|
78261
|
+
actionType,
|
|
78262
|
+
status: ActionStatus.OBSERVED,
|
|
78263
|
+
observation: {
|
|
78264
|
+
installed: false,
|
|
78265
|
+
error: `kimi managed plugin root does not exist: ${resolve19(kimiCodeHomeReal, KIMI_MANAGED_SUBPATH, action.plugin)}`
|
|
78266
|
+
}
|
|
78267
|
+
});
|
|
78268
|
+
}
|
|
78269
|
+
const installPath2 = resolve19(attestation.installPath);
|
|
78270
|
+
let installPathStat;
|
|
78271
|
+
try {
|
|
78272
|
+
installPathStat = await lstat11(installPath2);
|
|
78273
|
+
} catch {
|
|
78274
|
+
return createResult({
|
|
78275
|
+
actionType,
|
|
78276
|
+
status: ActionStatus.OBSERVED,
|
|
78277
|
+
observation: { installed: false, error: `kimi install path does not exist: ${attestation.installPath}` }
|
|
78278
|
+
});
|
|
78279
|
+
}
|
|
78280
|
+
if (installPathStat.isSymbolicLink()) {
|
|
78281
|
+
return createResult({
|
|
78282
|
+
actionType,
|
|
78283
|
+
status: ActionStatus.OBSERVED,
|
|
78284
|
+
observation: { installed: false, error: `kimi install path must not be a symlink: ${attestation.installPath}` }
|
|
78285
|
+
});
|
|
78286
|
+
}
|
|
78287
|
+
if (!installPathStat.isDirectory()) {
|
|
78288
|
+
return createResult({
|
|
78289
|
+
actionType,
|
|
78290
|
+
status: ActionStatus.OBSERVED,
|
|
78291
|
+
observation: { installed: false, error: `kimi install path must be a directory: ${attestation.installPath}` }
|
|
78292
|
+
});
|
|
78293
|
+
}
|
|
78294
|
+
const installPathReal2 = await realpath11(installPath2).catch(() => null);
|
|
78295
|
+
if (!installPathReal2) {
|
|
78296
|
+
return createResult({
|
|
78297
|
+
actionType,
|
|
78298
|
+
status: ActionStatus.OBSERVED,
|
|
78299
|
+
observation: { installed: false, error: `kimi install path cannot be resolved: ${attestation.installPath}` }
|
|
78300
|
+
});
|
|
78301
|
+
}
|
|
78302
|
+
const sepK = process.platform === "win32" ? "\\" : "/";
|
|
78303
|
+
const relToManaged = relative16(managedRootReal, installPathReal2);
|
|
78304
|
+
if (relToManaged !== "" && (isAbsolute13(relToManaged) || relToManaged === ".." || relToManaged.startsWith(`..${sepK}`))) {
|
|
78305
|
+
return createResult({
|
|
78306
|
+
actionType,
|
|
78307
|
+
status: ActionStatus.OBSERVED,
|
|
78308
|
+
observation: {
|
|
78309
|
+
installed: false,
|
|
78310
|
+
error: `kimi install path escapes the managed root (${managedRootReal}): ${attestation.installPath}`
|
|
78311
|
+
}
|
|
78312
|
+
});
|
|
78313
|
+
}
|
|
78314
|
+
let manifestDigest2;
|
|
78315
|
+
try {
|
|
78316
|
+
manifestDigest2 = await verifyInstalledMarketplacePayload(action, context, installPathReal2, consumer);
|
|
78317
|
+
} catch (digestErr) {
|
|
78318
|
+
return createResult({
|
|
78319
|
+
actionType,
|
|
78320
|
+
status: ActionStatus.OBSERVED,
|
|
78321
|
+
observation: {
|
|
78322
|
+
installed: true,
|
|
78323
|
+
installPath: installPathReal2,
|
|
78324
|
+
error: `failed to bind installed kimi payload to frozen authority: ${digestErr.message}`
|
|
78325
|
+
}
|
|
78326
|
+
});
|
|
78327
|
+
}
|
|
78328
|
+
if (manifestDigest2 !== action.manifestDigest) {
|
|
78329
|
+
return createResult({
|
|
78330
|
+
actionType,
|
|
78331
|
+
status: ActionStatus.OBSERVED,
|
|
78332
|
+
observation: {
|
|
78333
|
+
installed: true,
|
|
78334
|
+
installPath: installPathReal2,
|
|
78335
|
+
error: "installed kimi payload digest does not match the frozen plan digest"
|
|
78336
|
+
}
|
|
78337
|
+
});
|
|
78338
|
+
}
|
|
78339
|
+
let installedManifest;
|
|
78340
|
+
let entrySkillFound2 = false;
|
|
78341
|
+
try {
|
|
78342
|
+
const readManifest = await readKimiManifest(installPathReal2);
|
|
78343
|
+
installedManifest = readManifest.manifest;
|
|
78344
|
+
await resolveKimiEntrySkillFile(installPathReal2, installedManifest, action.entrySkill);
|
|
78345
|
+
entrySkillFound2 = true;
|
|
78346
|
+
} catch (entryErr) {
|
|
78347
|
+
return createResult({
|
|
78348
|
+
actionType,
|
|
78349
|
+
status: ActionStatus.OBSERVED,
|
|
78350
|
+
observation: {
|
|
78351
|
+
installed: true,
|
|
78352
|
+
installPath: installPathReal2,
|
|
78353
|
+
manifestDigest: manifestDigest2,
|
|
78354
|
+
entrySkillFound: false,
|
|
78355
|
+
error: `kimi entry skill not resolvable in installed copy: ${entryErr.message}`
|
|
78356
|
+
}
|
|
78357
|
+
});
|
|
78358
|
+
}
|
|
78359
|
+
if (installedManifest.name !== action.plugin) {
|
|
78360
|
+
return createResult({
|
|
78361
|
+
actionType,
|
|
78362
|
+
status: ActionStatus.OBSERVED,
|
|
78363
|
+
observation: {
|
|
78364
|
+
installed: true,
|
|
78365
|
+
installPath: installPathReal2,
|
|
78366
|
+
manifestDigest: manifestDigest2,
|
|
78367
|
+
entrySkillFound: true,
|
|
78368
|
+
error: `installed kimi manifest name "${installedManifest.name}" does not match action plugin "${action.plugin}"`
|
|
78369
|
+
}
|
|
78370
|
+
});
|
|
78371
|
+
}
|
|
78372
|
+
if (installedManifest.version !== action.version) {
|
|
78373
|
+
return createResult({
|
|
78374
|
+
actionType,
|
|
78375
|
+
status: ActionStatus.OBSERVED,
|
|
78376
|
+
observation: {
|
|
78377
|
+
installed: true,
|
|
78378
|
+
installPath: installPathReal2,
|
|
78379
|
+
manifestDigest: manifestDigest2,
|
|
78380
|
+
entrySkillFound: true,
|
|
78381
|
+
error: `installed kimi manifest version "${installedManifest.version}" does not match action version "${action.version}"`
|
|
78382
|
+
}
|
|
78383
|
+
});
|
|
78384
|
+
}
|
|
78385
|
+
const observation2 = {
|
|
78386
|
+
installed: true,
|
|
78387
|
+
installPath: installPathReal2,
|
|
78388
|
+
entrySkillFound: true,
|
|
78389
|
+
entrySkill: action.entrySkill,
|
|
78390
|
+
manifestDigest: manifestDigest2,
|
|
78391
|
+
consumer,
|
|
78392
|
+
plugin: installedManifest.name,
|
|
78393
|
+
version: installedManifest.version,
|
|
78394
|
+
repo: action.repo,
|
|
78395
|
+
ref: expectedRef
|
|
78396
|
+
};
|
|
78397
|
+
return createResult({
|
|
78398
|
+
actionType,
|
|
78399
|
+
status: ActionStatus.OBSERVED,
|
|
78400
|
+
observation: observation2
|
|
78401
|
+
});
|
|
78402
|
+
}
|
|
77560
78403
|
let evidence = null;
|
|
77561
78404
|
try {
|
|
77562
78405
|
const evidenceRaw = await readFile17(resolve19(runDir, "evidence", `${consumer}-${action.plugin}`, "release-skill-install-evidence.json"), "utf8");
|
|
@@ -77581,7 +78424,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77581
78424
|
}
|
|
77582
78425
|
});
|
|
77583
78426
|
}
|
|
77584
|
-
const listArgs =
|
|
78427
|
+
const listArgs = ["plugin", "list", "--json"];
|
|
77585
78428
|
let listOutput;
|
|
77586
78429
|
try {
|
|
77587
78430
|
const result = await exec(cliCmd, listArgs, { env, cwd: context.root, timeout: frozenTimeoutMs });
|
|
@@ -77632,7 +78475,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77632
78475
|
});
|
|
77633
78476
|
}
|
|
77634
78477
|
installPath = found.installPath;
|
|
77635
|
-
} else {
|
|
78478
|
+
} else if (consumer === "codex") {
|
|
77636
78479
|
installPath = evidence.installOutput?.installedPath;
|
|
77637
78480
|
if (!installPath) {
|
|
77638
78481
|
return createResult({
|
|
@@ -77735,7 +78578,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77735
78578
|
} catch (digestErr) {
|
|
77736
78579
|
try {
|
|
77737
78580
|
const installedSnapshot = await computeFrozenSnapshot(installPath, {
|
|
77738
|
-
excludeRootEntries: consumer === "codex" ? [".git"] : []
|
|
78581
|
+
excludeRootEntries: consumer === "codex" || consumer === "kimi" ? [".git"] : []
|
|
77739
78582
|
});
|
|
77740
78583
|
manifestDigest = installedSnapshot.digest;
|
|
77741
78584
|
} catch {
|
|
@@ -77756,7 +78599,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77756
78599
|
observation.plugin = idParts[0];
|
|
77757
78600
|
observation.marketplace = idParts.slice(1).join("@");
|
|
77758
78601
|
if (found.version) observation.version = found.version;
|
|
77759
|
-
} else {
|
|
78602
|
+
} else if (consumer === "codex") {
|
|
77760
78603
|
if (found.name) observation.plugin = found.name;
|
|
77761
78604
|
if (found.marketplaceName) observation.marketplace = found.marketplaceName;
|
|
77762
78605
|
if (found.version) observation.version = found.version;
|
|
@@ -77891,21 +78734,39 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
77891
78734
|
}
|
|
77892
78735
|
});
|
|
77893
78736
|
}
|
|
77894
|
-
var execFile9, NAME4, SUPPORTED_TYPES, SAFE_ID_RE, SAFE_REPO_RE, STRICT_SEMVER_RE;
|
|
78737
|
+
var execFile9, NAME4, KIMI_REQUIREMENT_FILE, KIMI_ATTESTATION_FILE, KIMI_MANAGED_SUBPATH, KIMI_MAX_ATTESTATION_VALIDITY_MS, HEX_DIGEST_RE, SUPPORTED_TYPES, SAFE_ID_RE, SAFE_REPO_RE, STRICT_SEMVER_RE;
|
|
77895
78738
|
var init_plugin_marketplace = __esm({
|
|
77896
|
-
"src/adapters/plugin-marketplace.mjs"() {
|
|
78739
|
+
async "src/adapters/plugin-marketplace.mjs"() {
|
|
77897
78740
|
init_contract2();
|
|
77898
78741
|
init_frozen();
|
|
78742
|
+
await init_plan();
|
|
78743
|
+
init_digest();
|
|
77899
78744
|
execFile9 = promisify10(execFileCb10);
|
|
77900
78745
|
NAME4 = "plugin-marketplace";
|
|
77901
78746
|
__name(transportPayload, "transportPayload");
|
|
77902
78747
|
__name(verifyInstalledMarketplacePayload, "verifyInstalledMarketplacePayload");
|
|
77903
78748
|
__name(writeEvidenceAtomic, "writeEvidenceAtomic");
|
|
78749
|
+
KIMI_REQUIREMENT_FILE = "release-skill-kimi-manual-install.json";
|
|
78750
|
+
KIMI_ATTESTATION_FILE = "release-skill-kimi-attestation.json";
|
|
78751
|
+
KIMI_MANAGED_SUBPATH = join12("plugins", "managed");
|
|
78752
|
+
KIMI_MAX_ATTESTATION_VALIDITY_MS = 24 * 60 * 60 * 1e3;
|
|
78753
|
+
HEX_DIGEST_RE = /^[a-f0-9]{64}$/;
|
|
78754
|
+
__name(normalizePlanForDigest, "normalizePlanForDigest");
|
|
78755
|
+
__name(resolveBoundPlanDigest, "resolveBoundPlanDigest");
|
|
78756
|
+
__name(kimiAuthorityDir, "kimiAuthorityDir");
|
|
78757
|
+
__name(buildKimiInstallUrl, "buildKimiInstallUrl");
|
|
78758
|
+
__name(buildKimiManualInstructions, "buildKimiManualInstructions");
|
|
78759
|
+
__name(readKimiManifest, "readKimiManifest");
|
|
78760
|
+
__name(normalizeKimiSkillsRel, "normalizeKimiSkillsRel");
|
|
78761
|
+
__name(resolveKimiEntrySkillFile, "resolveKimiEntrySkillFile");
|
|
78762
|
+
__name(validateKimiAttestation, "validateKimiAttestation");
|
|
78763
|
+
__name(executeKimiManualRequirement, "executeKimiManualRequirement");
|
|
77904
78764
|
SUPPORTED_TYPES = [
|
|
77905
78765
|
ActionType.PLUGIN_MANIFEST_VALIDATE,
|
|
77906
78766
|
ActionType.PLUGIN_INSTALL_CHECK,
|
|
77907
78767
|
ActionType.CLAUDE_MARKETPLACE_INSTALL,
|
|
77908
|
-
ActionType.CODEX_MARKETPLACE_INSTALL
|
|
78768
|
+
ActionType.CODEX_MARKETPLACE_INSTALL,
|
|
78769
|
+
ActionType.KIMI_MARKETPLACE_INSTALL
|
|
77909
78770
|
];
|
|
77910
78771
|
SAFE_ID_RE = /^[a-z0-9][a-z0-9._-]*$/;
|
|
77911
78772
|
SAFE_REPO_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
@@ -78364,7 +79225,8 @@ async function verifyRelease(options) {
|
|
|
78364
79225
|
const actions = plan.externalActions ?? [];
|
|
78365
79226
|
const MARKETPLACE_TYPES3 = /* @__PURE__ */ new Set([
|
|
78366
79227
|
"claude-marketplace-install",
|
|
78367
|
-
"codex-marketplace-install"
|
|
79228
|
+
"codex-marketplace-install",
|
|
79229
|
+
"kimi-marketplace-install"
|
|
78368
79230
|
]);
|
|
78369
79231
|
for (const action of actions) {
|
|
78370
79232
|
const adapterActionType = ADAPTER_ACTION_TYPE_MAP2[action.type];
|
|
@@ -78453,7 +79315,7 @@ async function verifyRelease(options) {
|
|
|
78453
79315
|
{ actionId: action.id, observation: verifyResult.observation }
|
|
78454
79316
|
);
|
|
78455
79317
|
}
|
|
78456
|
-
const distribution = action.type === "claude-marketplace-install" ? "claude-plugin" : "codex-plugin";
|
|
79318
|
+
const distribution = action.type === "claude-marketplace-install" ? "claude-plugin" : action.type === "codex-marketplace-install" ? "codex-plugin" : "kimi-plugin";
|
|
78457
79319
|
const installPath = verifyResult.observation?.installPath;
|
|
78458
79320
|
consumerGateResults.push(...await runConsumerVerificationGates({
|
|
78459
79321
|
plan,
|
|
@@ -78465,9 +79327,12 @@ async function verifyRelease(options) {
|
|
|
78465
79327
|
fixedEnv: action.type === "claude-marketplace-install" ? {
|
|
78466
79328
|
HOME: resolve20(runDir, "consumers", `claude-${action.parameters.plugin}`),
|
|
78467
79329
|
CLAUDE_CONFIG_DIR: resolve20(runDir, "consumers", `claude-${action.parameters.plugin}`, ".claude")
|
|
78468
|
-
} : {
|
|
79330
|
+
} : action.type === "codex-marketplace-install" ? {
|
|
78469
79331
|
HOME: resolve20(runDir, "consumers", `codex-${action.parameters.plugin}`),
|
|
78470
79332
|
CODEX_HOME: resolve20(runDir, "consumers", `codex-${action.parameters.plugin}`)
|
|
79333
|
+
} : {
|
|
79334
|
+
HOME: resolve20(runDir, "consumers", `kimi-${action.parameters.plugin}`),
|
|
79335
|
+
KIMI_CODE_HOME: resolve20(runDir, "consumers", `kimi-${action.parameters.plugin}`)
|
|
78471
79336
|
}
|
|
78472
79337
|
}));
|
|
78473
79338
|
} else {
|
|
@@ -78628,7 +79493,8 @@ var init_verify = __esm({
|
|
|
78628
79493
|
"npm-publish": "npm-publish",
|
|
78629
79494
|
"github-release": "github-release",
|
|
78630
79495
|
"claude-marketplace-install": "claude-marketplace-install",
|
|
78631
|
-
"codex-marketplace-install": "codex-marketplace-install"
|
|
79496
|
+
"codex-marketplace-install": "codex-marketplace-install",
|
|
79497
|
+
"kimi-marketplace-install": "kimi-marketplace-install"
|
|
78632
79498
|
};
|
|
78633
79499
|
__name(defaultClock3, "defaultClock");
|
|
78634
79500
|
__name(matchesSubset2, "matchesSubset");
|
|
@@ -79345,7 +80211,8 @@ var init_publish = __esm({
|
|
|
79345
80211
|
"npm-publish",
|
|
79346
80212
|
"github-release",
|
|
79347
80213
|
"claude-marketplace-install",
|
|
79348
|
-
"codex-marketplace-install"
|
|
80214
|
+
"codex-marketplace-install",
|
|
80215
|
+
"kimi-marketplace-install"
|
|
79349
80216
|
];
|
|
79350
80217
|
ADAPTER_ACTION_TYPE_MAP3 = {
|
|
79351
80218
|
"push-commit": "git-push",
|
|
@@ -79355,11 +80222,13 @@ var init_publish = __esm({
|
|
|
79355
80222
|
"npm-publish": "npm-publish",
|
|
79356
80223
|
"github-release": "github-release",
|
|
79357
80224
|
"claude-marketplace-install": "claude-marketplace-install",
|
|
79358
|
-
"codex-marketplace-install": "codex-marketplace-install"
|
|
80225
|
+
"codex-marketplace-install": "codex-marketplace-install",
|
|
80226
|
+
"kimi-marketplace-install": "kimi-marketplace-install"
|
|
79359
80227
|
};
|
|
79360
80228
|
MARKETPLACE_TYPES2 = /* @__PURE__ */ new Set([
|
|
79361
80229
|
"claude-marketplace-install",
|
|
79362
|
-
"codex-marketplace-install"
|
|
80230
|
+
"codex-marketplace-install",
|
|
80231
|
+
"kimi-marketplace-install"
|
|
79363
80232
|
]);
|
|
79364
80233
|
__name(defaultClock4, "defaultClock");
|
|
79365
80234
|
__name(deepClone, "deepClone");
|
|
@@ -82756,6 +83625,12 @@ async function performEnvironmentChecks() {
|
|
|
82756
83625
|
required: false,
|
|
82757
83626
|
usage: "\u4EC5\u5F53\u8BA1\u5212\u58F0\u660E codex-plugin distribution \u65F6\u7528\u4E8E\u6D88\u8D39\u8005\u5B89\u88C5\u9A8C\u8BC1"
|
|
82758
83627
|
};
|
|
83628
|
+
const kimiCheck = await checkDependency("kimi", ["--version"]);
|
|
83629
|
+
checks.kimi = {
|
|
83630
|
+
...kimiCheck,
|
|
83631
|
+
required: false,
|
|
83632
|
+
usage: "\u4EC5\u5F53\u8BA1\u5212\u58F0\u660E kimi-plugin distribution \u65F6\u7528\u4E8E\u6D88\u8D39\u8005\u5B89\u88C5\u9A8C\u8BC1"
|
|
83633
|
+
};
|
|
82759
83634
|
return checks;
|
|
82760
83635
|
}
|
|
82761
83636
|
__name(performEnvironmentChecks, "performEnvironmentChecks");
|
|
@@ -82784,7 +83659,7 @@ function getCapabilityMaturity() {
|
|
|
82784
83659
|
publish: {
|
|
82785
83660
|
available: true,
|
|
82786
83661
|
mode: "controlled production (protocol-tested; no OS/network sandbox)",
|
|
82787
|
-
description: "Publishes frozen GitHub/npm artifacts and runs configured Claude/Codex consumer checkpoints with approval and exact digest confirmation"
|
|
83662
|
+
description: "Publishes frozen GitHub/npm artifacts and runs configured Claude/Codex/Kimi consumer checkpoints with approval and exact digest confirmation"
|
|
82788
83663
|
},
|
|
82789
83664
|
reconcile: {
|
|
82790
83665
|
available: true,
|
|
@@ -82794,7 +83669,7 @@ function getCapabilityMaturity() {
|
|
|
82794
83669
|
verify: {
|
|
82795
83670
|
available: true,
|
|
82796
83671
|
mode: "fresh consumer verification (protocol-tested; no OS/network sandbox)",
|
|
82797
|
-
description: "Recheck remote state, exact npm installation, CLI help, and configured Claude/Codex installs before VERIFIED"
|
|
83672
|
+
description: "Recheck remote state, exact npm installation, CLI help, and configured Claude/Codex/Kimi installs before VERIFIED"
|
|
82798
83673
|
}
|
|
82799
83674
|
};
|
|
82800
83675
|
}
|
|
@@ -82917,7 +83792,8 @@ if (!command || command === "help") {
|
|
|
82917
83792
|
authentication: "\u8FD0\u884C\u751F\u4EA7\u53D1\u5E03\u524D\u8FD8\u9700\u9A8C\u8BC1 gh auth\u3001Git HTTPS credential \u4E0E npm auth\uFF1Bhelp \u4E0D\u53D1\u8D77\u7F51\u7EDC\u8BA4\u8BC1\u68C0\u67E5\u3002",
|
|
82918
83793
|
conditionalConsumers: {
|
|
82919
83794
|
claude: "\u58F0\u660E claude-plugin distribution \u65F6\u5FC5\u987B\u53EF\u7528",
|
|
82920
|
-
codex: "\u58F0\u660E codex-plugin distribution \u65F6\u5FC5\u987B\u53EF\u7528"
|
|
83795
|
+
codex: "\u58F0\u660E codex-plugin distribution \u65F6\u5FC5\u987B\u53EF\u7528",
|
|
83796
|
+
kimi: "\u58F0\u660E kimi-plugin distribution \u65F6\u5FC5\u987B\u53EF\u7528"
|
|
82921
83797
|
}
|
|
82922
83798
|
}
|
|
82923
83799
|
},
|
|
@@ -82929,9 +83805,9 @@ if (!command || command === "help") {
|
|
|
82929
83805
|
prepare: "offline local writes; configured hooks/gates require their explicit side-effect acknowledgements",
|
|
82930
83806
|
docs: "read-only dry-run by default; write requires --write, exact --confirm-refresh, and --ack-local-document-write; never commits, pushes, or publishes",
|
|
82931
83807
|
onlinePrepare: "previous-public-baseline observation available; production mode freezes publish artifacts and fails closed on drift or unknown state",
|
|
82932
|
-
publish: "GitHub/npm plus configured Claude/Codex consumer checkpoints are protocol-tested without an OS/network sandbox; approval and exact digest confirmation required",
|
|
83808
|
+
publish: "GitHub/npm plus configured Claude/Codex/Kimi consumer checkpoints are protocol-tested without an OS/network sandbox; approval and exact digest confirmation required",
|
|
82933
83809
|
reconcile: "PARTIAL recovery is protocol-tested without an OS/network sandbox; remote conflicts require human intervention",
|
|
82934
|
-
verify: "fresh exact npm and Claude/Codex consumer installation checks are protocol-tested without an OS/network sandbox; configured consumer processes require explicit acknowledgement; success reaches VERIFIED"
|
|
83810
|
+
verify: "fresh exact npm and Claude/Codex/Kimi consumer installation checks are protocol-tested without an OS/network sandbox; configured consumer processes require explicit acknowledgement; success reaches VERIFIED"
|
|
82935
83811
|
},
|
|
82936
83812
|
recommendations: []
|
|
82937
83813
|
};
|
|
@@ -82958,6 +83834,9 @@ if (!command || command === "help") {
|
|
|
82958
83834
|
if (!checks.codex.available) {
|
|
82959
83835
|
output.recommendations.push("Install Codex CLI before releasing a configured codex-plugin distribution");
|
|
82960
83836
|
}
|
|
83837
|
+
if (!checks.kimi.available) {
|
|
83838
|
+
output.recommendations.push("Install Kimi Code CLI before releasing a configured kimi-plugin distribution");
|
|
83839
|
+
}
|
|
82961
83840
|
console.log(JSON.stringify(output, null, 2));
|
|
82962
83841
|
process.exit(readiness.status === "READY" ? 0 : 1);
|
|
82963
83842
|
} else {
|
|
@@ -83180,7 +84059,7 @@ if (command === "reconcile") {
|
|
|
83180
84059
|
const { reconcileRelease: reconcileRelease2 } = await init_reconcile().then(() => reconcile_exports);
|
|
83181
84060
|
const { createGitGithubAdapter: createGitGithubAdapter2 } = await Promise.resolve().then(() => (init_git_github(), git_github_exports));
|
|
83182
84061
|
const { createNpmAdapter: createNpmAdapter2 } = await Promise.resolve().then(() => (init_npm(), npm_exports));
|
|
83183
|
-
const { createPluginMarketplaceAdapter: createPluginMarketplaceAdapter2 } = await
|
|
84062
|
+
const { createPluginMarketplaceAdapter: createPluginMarketplaceAdapter2 } = await init_plugin_marketplace().then(() => plugin_marketplace_exports);
|
|
83184
84063
|
const { createPushSnapshotAdapter: createPushSnapshotAdapter2 } = await Promise.resolve().then(() => (init_push_snapshot(), push_snapshot_exports));
|
|
83185
84064
|
const { createAdapterRegistry: createAdapterRegistry2 } = await Promise.resolve().then(() => (init_contract2(), contract_exports));
|
|
83186
84065
|
const registry = createAdapterRegistry2([
|
|
@@ -83242,7 +84121,7 @@ if (command === "verify") {
|
|
|
83242
84121
|
const { verifyRelease: verifyRelease2 } = await init_verify().then(() => verify_exports);
|
|
83243
84122
|
const { createGitGithubAdapter: createGitGithubAdapter2 } = await Promise.resolve().then(() => (init_git_github(), git_github_exports));
|
|
83244
84123
|
const { createNpmAdapter: createNpmAdapter2 } = await Promise.resolve().then(() => (init_npm(), npm_exports));
|
|
83245
|
-
const { createPluginMarketplaceAdapter: createPluginMarketplaceAdapter2 } = await
|
|
84124
|
+
const { createPluginMarketplaceAdapter: createPluginMarketplaceAdapter2 } = await init_plugin_marketplace().then(() => plugin_marketplace_exports);
|
|
83246
84125
|
const { createPushSnapshotAdapter: createPushSnapshotAdapter2 } = await Promise.resolve().then(() => (init_push_snapshot(), push_snapshot_exports));
|
|
83247
84126
|
const { createAdapterRegistry: createAdapterRegistry2 } = await Promise.resolve().then(() => (init_contract2(), contract_exports));
|
|
83248
84127
|
const registry = createAdapterRegistry2([
|
|
@@ -83303,7 +84182,7 @@ if (command === "publish") {
|
|
|
83303
84182
|
const { publishRelease: publishRelease2 } = await init_publish().then(() => publish_exports);
|
|
83304
84183
|
const { createGitGithubAdapter: createGitGithubAdapter2 } = await Promise.resolve().then(() => (init_git_github(), git_github_exports));
|
|
83305
84184
|
const { createNpmAdapter: createNpmAdapter2 } = await Promise.resolve().then(() => (init_npm(), npm_exports));
|
|
83306
|
-
const { createPluginMarketplaceAdapter: createPluginMarketplaceAdapter2 } = await
|
|
84185
|
+
const { createPluginMarketplaceAdapter: createPluginMarketplaceAdapter2 } = await init_plugin_marketplace().then(() => plugin_marketplace_exports);
|
|
83307
84186
|
const { createPushSnapshotAdapter: createPushSnapshotAdapter2 } = await Promise.resolve().then(() => (init_push_snapshot(), push_snapshot_exports));
|
|
83308
84187
|
const { createAdapterRegistry: createAdapterRegistry2 } = await Promise.resolve().then(() => (init_contract2(), contract_exports));
|
|
83309
84188
|
const registry = createAdapterRegistry2([
|