agentwheel 0.22.3 → 0.22.4
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/dist/index.js +371 -306
- package/openpack.json +1 -1
- package/package.json +1 -1
- package/skills/agentwheel/SKILL.md +1 -1
- package/skills/agentwheel-discovery/SKILL.md +1 -1
package/dist/index.js
CHANGED
|
@@ -16558,7 +16558,8 @@ var init_local = __esm({
|
|
|
16558
16558
|
atomicCopy,
|
|
16559
16559
|
rm: (path) => rm3(path, { recursive: true, force: true }),
|
|
16560
16560
|
async execFile(command, args, options = {}) {
|
|
16561
|
-
await execFileAsync(command, args, { cwd: options.cwd });
|
|
16561
|
+
const { stdout } = await execFileAsync(command, args, { cwd: options.cwd });
|
|
16562
|
+
return stdout;
|
|
16562
16563
|
}
|
|
16563
16564
|
};
|
|
16564
16565
|
}
|
|
@@ -16627,7 +16628,7 @@ function createSshTransport(config2) {
|
|
|
16627
16628
|
execFile(command, commandArgs, options = {}) {
|
|
16628
16629
|
const quoted = [command, ...commandArgs].map(quoteSh).join(" ");
|
|
16629
16630
|
const remoteCommand = options.cwd ? `cd ${quoteSh(options.cwd)} && ${quoted}` : quoted;
|
|
16630
|
-
return run(remoteCommand)
|
|
16631
|
+
return run(remoteCommand);
|
|
16631
16632
|
}
|
|
16632
16633
|
};
|
|
16633
16634
|
}
|
|
@@ -17180,6 +17181,189 @@ var init_transport = __esm({
|
|
|
17180
17181
|
}
|
|
17181
17182
|
});
|
|
17182
17183
|
|
|
17184
|
+
// src/resolve/semver.ts
|
|
17185
|
+
function parseSemver(value) {
|
|
17186
|
+
const match = semverPattern.exec(value.trim());
|
|
17187
|
+
if (!match) return void 0;
|
|
17188
|
+
return {
|
|
17189
|
+
major: Number(match[1]),
|
|
17190
|
+
minor: Number(match[2]),
|
|
17191
|
+
patch: Number(match[3]),
|
|
17192
|
+
prerelease: match[4]
|
|
17193
|
+
};
|
|
17194
|
+
}
|
|
17195
|
+
function satisfiesVersionRange(version2, range) {
|
|
17196
|
+
if (!range || range.trim() === "" || range.trim() === "*") return true;
|
|
17197
|
+
const parsedVersion = parseSemver(version2);
|
|
17198
|
+
const trimmed = range.trim();
|
|
17199
|
+
if (!parsedVersion) {
|
|
17200
|
+
return trimmed === "*" || trimmed === version2;
|
|
17201
|
+
}
|
|
17202
|
+
const comparators = parseRange(trimmed);
|
|
17203
|
+
if (!comparators) return trimmed === version2;
|
|
17204
|
+
return comparators.every((comparator) => compareWith(parsedVersion, comparator));
|
|
17205
|
+
}
|
|
17206
|
+
function semverMajorOrVersion(version2) {
|
|
17207
|
+
const parsed = parseSemver(version2);
|
|
17208
|
+
return parsed ? String(parsed.major) : version2;
|
|
17209
|
+
}
|
|
17210
|
+
function compareSemverStrings(a, b) {
|
|
17211
|
+
const parsedA = parseSemver(a);
|
|
17212
|
+
const parsedB = parseSemver(b);
|
|
17213
|
+
if (!parsedA || !parsedB) return a.localeCompare(b);
|
|
17214
|
+
return compareSemver(parsedA, parsedB);
|
|
17215
|
+
}
|
|
17216
|
+
function isSupportedVersionRange(range) {
|
|
17217
|
+
const trimmed = range.trim();
|
|
17218
|
+
return trimmed === "*" || parseRange(trimmed) !== void 0;
|
|
17219
|
+
}
|
|
17220
|
+
function parseRange(range) {
|
|
17221
|
+
if (range === "*") return [];
|
|
17222
|
+
if (range.startsWith("^")) {
|
|
17223
|
+
const base = parseSemver(range.slice(1));
|
|
17224
|
+
if (!base) return void 0;
|
|
17225
|
+
return [
|
|
17226
|
+
{ op: ">=", version: base },
|
|
17227
|
+
{ op: "<", version: caretUpperBound(base) }
|
|
17228
|
+
];
|
|
17229
|
+
}
|
|
17230
|
+
if (range.startsWith("~")) {
|
|
17231
|
+
const base = parseSemver(range.slice(1));
|
|
17232
|
+
if (!base) return void 0;
|
|
17233
|
+
return [
|
|
17234
|
+
{ op: ">=", version: base },
|
|
17235
|
+
{ op: "<", version: { major: base.major, minor: base.minor + 1, patch: 0 } }
|
|
17236
|
+
];
|
|
17237
|
+
}
|
|
17238
|
+
const parts = range.split(/\s+/).filter(Boolean);
|
|
17239
|
+
const comparators = [];
|
|
17240
|
+
for (const part of parts) {
|
|
17241
|
+
const match = /^(>=|<=|>|<|=)?(.+)$/.exec(part);
|
|
17242
|
+
if (!match) return void 0;
|
|
17243
|
+
const version2 = parseSemver(match[2] ?? "");
|
|
17244
|
+
if (!version2) return void 0;
|
|
17245
|
+
comparators.push({ op: match[1] ?? "=", version: version2 });
|
|
17246
|
+
}
|
|
17247
|
+
return comparators;
|
|
17248
|
+
}
|
|
17249
|
+
function caretUpperBound(version2) {
|
|
17250
|
+
if (version2.major > 0) return { major: version2.major + 1, minor: 0, patch: 0 };
|
|
17251
|
+
if (version2.minor > 0) return { major: 0, minor: version2.minor + 1, patch: 0 };
|
|
17252
|
+
return { major: 0, minor: 0, patch: version2.patch + 1 };
|
|
17253
|
+
}
|
|
17254
|
+
function compareWith(version2, comparator) {
|
|
17255
|
+
const order = compareSemver(version2, comparator.version);
|
|
17256
|
+
switch (comparator.op) {
|
|
17257
|
+
case "=":
|
|
17258
|
+
return order === 0;
|
|
17259
|
+
case ">":
|
|
17260
|
+
return order > 0;
|
|
17261
|
+
case ">=":
|
|
17262
|
+
return order >= 0;
|
|
17263
|
+
case "<":
|
|
17264
|
+
return order < 0;
|
|
17265
|
+
case "<=":
|
|
17266
|
+
return order <= 0;
|
|
17267
|
+
}
|
|
17268
|
+
}
|
|
17269
|
+
function compareSemver(a, b) {
|
|
17270
|
+
for (const key of ["major", "minor", "patch"]) {
|
|
17271
|
+
if (a[key] !== b[key]) return a[key] > b[key] ? 1 : -1;
|
|
17272
|
+
}
|
|
17273
|
+
if (a.prerelease === b.prerelease) return 0;
|
|
17274
|
+
if (!a.prerelease) return 1;
|
|
17275
|
+
if (!b.prerelease) return -1;
|
|
17276
|
+
return a.prerelease.localeCompare(b.prerelease);
|
|
17277
|
+
}
|
|
17278
|
+
var semverPattern;
|
|
17279
|
+
var init_semver = __esm({
|
|
17280
|
+
"src/resolve/semver.ts"() {
|
|
17281
|
+
"use strict";
|
|
17282
|
+
semverPattern = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
17283
|
+
}
|
|
17284
|
+
});
|
|
17285
|
+
|
|
17286
|
+
// src/targets/plugins/openclaw.ts
|
|
17287
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
17288
|
+
import { join as join10 } from "path";
|
|
17289
|
+
function openClawPluginInstallCommand(request) {
|
|
17290
|
+
return ["openclaw", "plugins", "install", "--force", ...request.acceptCapabilities ? ["--accept-capabilities"] : [], request.path];
|
|
17291
|
+
}
|
|
17292
|
+
function createOpenClawCapabilityDetector(run) {
|
|
17293
|
+
let cached2;
|
|
17294
|
+
return () => cached2 ??= detectOpenClawCapabilitySupport(run);
|
|
17295
|
+
}
|
|
17296
|
+
async function detectOpenClawCapabilitySupport(run) {
|
|
17297
|
+
try {
|
|
17298
|
+
const help = await run(["plugins", "install", "--help"]);
|
|
17299
|
+
if (help?.trim()) return /(?:^|\s)--accept-capabilities(?=[\s=,]|$)/m.test(help);
|
|
17300
|
+
} catch {
|
|
17301
|
+
}
|
|
17302
|
+
try {
|
|
17303
|
+
const output = await run(["--version"]);
|
|
17304
|
+
const version2 = output?.match(/(?:^|\s)v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)(?=\s|$)/)?.[1];
|
|
17305
|
+
return version2 !== void 0 && parseSemver(version2) !== void 0 && satisfiesVersionRange(version2, ">=2026.8.1");
|
|
17306
|
+
} catch {
|
|
17307
|
+
return false;
|
|
17308
|
+
}
|
|
17309
|
+
}
|
|
17310
|
+
function openClawPluginUninstallCommand(pluginName) {
|
|
17311
|
+
return ["openclaw", "plugins", "uninstall", pluginName, "--force"];
|
|
17312
|
+
}
|
|
17313
|
+
async function openClawPluginSpec(request) {
|
|
17314
|
+
if (request.format === "openclaw-clawhub-plugin") {
|
|
17315
|
+
const metadata = await openClawClawHubPluginMetadata(request.path, request.fallbackPluginName);
|
|
17316
|
+
return {
|
|
17317
|
+
runtime: "openclaw",
|
|
17318
|
+
pluginName: metadata.pluginName,
|
|
17319
|
+
installCommands: [openClawPluginInstallCommand({ path: metadata.installSpec, dryRun: true })],
|
|
17320
|
+
uninstallCommands: [openClawPluginUninstallCommand(metadata.pluginName)]
|
|
17321
|
+
};
|
|
17322
|
+
}
|
|
17323
|
+
const pluginName = await openClawPluginName(request.path, request.fallbackPluginName);
|
|
17324
|
+
return {
|
|
17325
|
+
runtime: "openclaw",
|
|
17326
|
+
pluginName,
|
|
17327
|
+
installCommands: [openClawPluginInstallCommand({ path: request.path, dryRun: true })],
|
|
17328
|
+
uninstallCommands: [openClawPluginUninstallCommand(pluginName)]
|
|
17329
|
+
};
|
|
17330
|
+
}
|
|
17331
|
+
async function openClawPluginName(root, fallback) {
|
|
17332
|
+
for (const manifestName of ["plugin.json", "openclaw.plugin.json"]) {
|
|
17333
|
+
const manifestPath = join10(root, manifestName);
|
|
17334
|
+
if (!await pathExists(manifestPath)) continue;
|
|
17335
|
+
const parsed = JSON.parse(await readFile8(manifestPath, "utf8"));
|
|
17336
|
+
if (typeof parsed.name === "string" && parsed.name.trim().length > 0) return parsed.name.trim();
|
|
17337
|
+
}
|
|
17338
|
+
return fallback;
|
|
17339
|
+
}
|
|
17340
|
+
async function openClawClawHubPluginMetadata(root, fallback) {
|
|
17341
|
+
const metadataPath = join10(root, "clawhub.json");
|
|
17342
|
+
if (!await pathExists(metadataPath)) {
|
|
17343
|
+
throw new Error("OpenClaw ClawHub plugins must contain clawhub.json");
|
|
17344
|
+
}
|
|
17345
|
+
const parsed = JSON.parse(await readFile8(metadataPath, "utf8"));
|
|
17346
|
+
const installSpec = stringField(parsed.installSpec);
|
|
17347
|
+
if (!installSpec?.startsWith("clawhub:")) {
|
|
17348
|
+
throw new Error("OpenClaw ClawHub plugin metadata must declare installSpec starting with clawhub:");
|
|
17349
|
+
}
|
|
17350
|
+
const pluginName = stringField(parsed.runtimeId) ?? installNameFor(stringField(parsed.name) ?? fallback);
|
|
17351
|
+
return { installSpec, pluginName };
|
|
17352
|
+
}
|
|
17353
|
+
function stringField(value) {
|
|
17354
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
17355
|
+
}
|
|
17356
|
+
function installNameFor(value) {
|
|
17357
|
+
return value.split("/").at(-1).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "clawhub-plugin";
|
|
17358
|
+
}
|
|
17359
|
+
var init_openclaw2 = __esm({
|
|
17360
|
+
"src/targets/plugins/openclaw.ts"() {
|
|
17361
|
+
"use strict";
|
|
17362
|
+
init_fs();
|
|
17363
|
+
init_semver();
|
|
17364
|
+
}
|
|
17365
|
+
});
|
|
17366
|
+
|
|
17183
17367
|
// src/transport/run-as-policy.ts
|
|
17184
17368
|
function assertRunAsPlanSupported(plan, transport) {
|
|
17185
17369
|
if (transport.kind !== "local-run-as") return;
|
|
@@ -17194,12 +17378,12 @@ var init_run_as_policy = __esm({
|
|
|
17194
17378
|
});
|
|
17195
17379
|
|
|
17196
17380
|
// src/install/json-merge.ts
|
|
17197
|
-
import { readFile as
|
|
17381
|
+
import { readFile as readFile9, writeFile as writeFile5 } from "fs/promises";
|
|
17198
17382
|
import { dirname as dirname7 } from "path";
|
|
17199
17383
|
import { mkdir as mkdir5 } from "fs/promises";
|
|
17200
17384
|
async function mergeJsonFile(sourcePath, destPath) {
|
|
17201
|
-
const source = JSON.parse(await
|
|
17202
|
-
const current = await pathExists(destPath) ? JSON.parse(await
|
|
17385
|
+
const source = JSON.parse(await readFile9(sourcePath, "utf8"));
|
|
17386
|
+
const current = await pathExists(destPath) ? JSON.parse(await readFile9(destPath, "utf8")) : {};
|
|
17203
17387
|
const merged = deepMerge(current, source);
|
|
17204
17388
|
await mkdir5(dirname7(destPath), { recursive: true });
|
|
17205
17389
|
await writeFile5(destPath, `${JSON.stringify(merged, null, 2)}
|
|
@@ -17240,11 +17424,11 @@ var init_json_merge = __esm({
|
|
|
17240
17424
|
});
|
|
17241
17425
|
|
|
17242
17426
|
// src/install/openclaw-json-merge.ts
|
|
17243
|
-
import { mkdir as mkdir6, readFile as
|
|
17427
|
+
import { mkdir as mkdir6, readFile as readFile10, writeFile as writeFile6 } from "fs/promises";
|
|
17244
17428
|
import { dirname as dirname8 } from "path";
|
|
17245
17429
|
async function mergeOpenClawJsonFile(sourcePath, destPath) {
|
|
17246
17430
|
const source = await renderOpenClawJsonMergeSource(sourcePath);
|
|
17247
|
-
const current = await pathExists(destPath) ? JSON.parse(await
|
|
17431
|
+
const current = await pathExists(destPath) ? JSON.parse(await readFile10(destPath, "utf8")) : {};
|
|
17248
17432
|
const merged = mergeOpenClawJson(current, source);
|
|
17249
17433
|
await mkdir6(dirname8(destPath), { recursive: true });
|
|
17250
17434
|
await writeFile6(destPath, `${JSON.stringify(merged, null, 2)}
|
|
@@ -17252,7 +17436,7 @@ async function mergeOpenClawJsonFile(sourcePath, destPath) {
|
|
|
17252
17436
|
}
|
|
17253
17437
|
async function renderOpenClawJsonMergeSource(sourcePath) {
|
|
17254
17438
|
return expandEnvPlaceholders(
|
|
17255
|
-
normalizeOpenClawConfig(JSON.parse(await
|
|
17439
|
+
normalizeOpenClawConfig(JSON.parse(await readFile10(sourcePath, "utf8"))),
|
|
17256
17440
|
sourcePath
|
|
17257
17441
|
);
|
|
17258
17442
|
}
|
|
@@ -17517,9 +17701,9 @@ var init_manifest = __esm({
|
|
|
17517
17701
|
});
|
|
17518
17702
|
|
|
17519
17703
|
// src/install/paths.ts
|
|
17520
|
-
import { join as
|
|
17704
|
+
import { join as join11 } from "path";
|
|
17521
17705
|
function metadataDir(targetRoot) {
|
|
17522
|
-
return
|
|
17706
|
+
return join11(targetRoot, ".agentwheel");
|
|
17523
17707
|
}
|
|
17524
17708
|
function stateKeyFor(adapter, scope = {}) {
|
|
17525
17709
|
assertPathSafeAdapterName(adapter);
|
|
@@ -17539,10 +17723,10 @@ function assertPathSafeAdapterName(adapter) {
|
|
|
17539
17723
|
}
|
|
17540
17724
|
}
|
|
17541
17725
|
function installManifestPath(targetRoot, adapter, scope = {}) {
|
|
17542
|
-
return
|
|
17726
|
+
return join11(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.install-manifest.json`);
|
|
17543
17727
|
}
|
|
17544
17728
|
function sourceLockPath(targetRoot, adapter, scope = {}) {
|
|
17545
|
-
return
|
|
17729
|
+
return join11(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.source-lock.json`);
|
|
17546
17730
|
}
|
|
17547
17731
|
function sanitizeStateKey(value) {
|
|
17548
17732
|
return value.replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "default";
|
|
@@ -17556,7 +17740,7 @@ var init_paths = __esm({
|
|
|
17556
17740
|
|
|
17557
17741
|
// src/install/manifest.ts
|
|
17558
17742
|
import { createHash as createHash7 } from "crypto";
|
|
17559
|
-
import { join as
|
|
17743
|
+
import { join as join12, resolve as resolve10 } from "path";
|
|
17560
17744
|
async function readInstallManifest(targetRoot, adapter, transport = localTransport, scope = {}) {
|
|
17561
17745
|
const path = installManifestPath(targetRoot, adapter, scope);
|
|
17562
17746
|
if (!await transport.pathExists(path)) return void 0;
|
|
@@ -17574,7 +17758,7 @@ async function listInstallManifests(targetRoot, adapter, transport = localTransp
|
|
|
17574
17758
|
for (const fileName of await transport.listDir(dir)) {
|
|
17575
17759
|
if (!fileName.endsWith(suffix)) continue;
|
|
17576
17760
|
const stateKey = fileName.slice(0, -suffix.length);
|
|
17577
|
-
const path =
|
|
17761
|
+
const path = join12(dir, fileName);
|
|
17578
17762
|
try {
|
|
17579
17763
|
const raw = JSON.parse(await transport.readFile(path));
|
|
17580
17764
|
const parsed = installManifestSchema.parse(raw);
|
|
@@ -17759,108 +17943,6 @@ if private and (s.st_uid!=os.geteuid() or not stat.S_ISREG(s.st_mode) or s.st_nl
|
|
|
17759
17943
|
}
|
|
17760
17944
|
});
|
|
17761
17945
|
|
|
17762
|
-
// src/resolve/semver.ts
|
|
17763
|
-
function parseSemver(value) {
|
|
17764
|
-
const match = semverPattern.exec(value.trim());
|
|
17765
|
-
if (!match) return void 0;
|
|
17766
|
-
return {
|
|
17767
|
-
major: Number(match[1]),
|
|
17768
|
-
minor: Number(match[2]),
|
|
17769
|
-
patch: Number(match[3]),
|
|
17770
|
-
prerelease: match[4]
|
|
17771
|
-
};
|
|
17772
|
-
}
|
|
17773
|
-
function satisfiesVersionRange(version2, range) {
|
|
17774
|
-
if (!range || range.trim() === "" || range.trim() === "*") return true;
|
|
17775
|
-
const parsedVersion = parseSemver(version2);
|
|
17776
|
-
const trimmed = range.trim();
|
|
17777
|
-
if (!parsedVersion) {
|
|
17778
|
-
return trimmed === "*" || trimmed === version2;
|
|
17779
|
-
}
|
|
17780
|
-
const comparators = parseRange(trimmed);
|
|
17781
|
-
if (!comparators) return trimmed === version2;
|
|
17782
|
-
return comparators.every((comparator) => compareWith(parsedVersion, comparator));
|
|
17783
|
-
}
|
|
17784
|
-
function semverMajorOrVersion(version2) {
|
|
17785
|
-
const parsed = parseSemver(version2);
|
|
17786
|
-
return parsed ? String(parsed.major) : version2;
|
|
17787
|
-
}
|
|
17788
|
-
function compareSemverStrings(a, b) {
|
|
17789
|
-
const parsedA = parseSemver(a);
|
|
17790
|
-
const parsedB = parseSemver(b);
|
|
17791
|
-
if (!parsedA || !parsedB) return a.localeCompare(b);
|
|
17792
|
-
return compareSemver(parsedA, parsedB);
|
|
17793
|
-
}
|
|
17794
|
-
function isSupportedVersionRange(range) {
|
|
17795
|
-
const trimmed = range.trim();
|
|
17796
|
-
return trimmed === "*" || parseRange(trimmed) !== void 0;
|
|
17797
|
-
}
|
|
17798
|
-
function parseRange(range) {
|
|
17799
|
-
if (range === "*") return [];
|
|
17800
|
-
if (range.startsWith("^")) {
|
|
17801
|
-
const base = parseSemver(range.slice(1));
|
|
17802
|
-
if (!base) return void 0;
|
|
17803
|
-
return [
|
|
17804
|
-
{ op: ">=", version: base },
|
|
17805
|
-
{ op: "<", version: caretUpperBound(base) }
|
|
17806
|
-
];
|
|
17807
|
-
}
|
|
17808
|
-
if (range.startsWith("~")) {
|
|
17809
|
-
const base = parseSemver(range.slice(1));
|
|
17810
|
-
if (!base) return void 0;
|
|
17811
|
-
return [
|
|
17812
|
-
{ op: ">=", version: base },
|
|
17813
|
-
{ op: "<", version: { major: base.major, minor: base.minor + 1, patch: 0 } }
|
|
17814
|
-
];
|
|
17815
|
-
}
|
|
17816
|
-
const parts = range.split(/\s+/).filter(Boolean);
|
|
17817
|
-
const comparators = [];
|
|
17818
|
-
for (const part of parts) {
|
|
17819
|
-
const match = /^(>=|<=|>|<|=)?(.+)$/.exec(part);
|
|
17820
|
-
if (!match) return void 0;
|
|
17821
|
-
const version2 = parseSemver(match[2] ?? "");
|
|
17822
|
-
if (!version2) return void 0;
|
|
17823
|
-
comparators.push({ op: match[1] ?? "=", version: version2 });
|
|
17824
|
-
}
|
|
17825
|
-
return comparators;
|
|
17826
|
-
}
|
|
17827
|
-
function caretUpperBound(version2) {
|
|
17828
|
-
if (version2.major > 0) return { major: version2.major + 1, minor: 0, patch: 0 };
|
|
17829
|
-
if (version2.minor > 0) return { major: 0, minor: version2.minor + 1, patch: 0 };
|
|
17830
|
-
return { major: 0, minor: 0, patch: version2.patch + 1 };
|
|
17831
|
-
}
|
|
17832
|
-
function compareWith(version2, comparator) {
|
|
17833
|
-
const order = compareSemver(version2, comparator.version);
|
|
17834
|
-
switch (comparator.op) {
|
|
17835
|
-
case "=":
|
|
17836
|
-
return order === 0;
|
|
17837
|
-
case ">":
|
|
17838
|
-
return order > 0;
|
|
17839
|
-
case ">=":
|
|
17840
|
-
return order >= 0;
|
|
17841
|
-
case "<":
|
|
17842
|
-
return order < 0;
|
|
17843
|
-
case "<=":
|
|
17844
|
-
return order <= 0;
|
|
17845
|
-
}
|
|
17846
|
-
}
|
|
17847
|
-
function compareSemver(a, b) {
|
|
17848
|
-
for (const key of ["major", "minor", "patch"]) {
|
|
17849
|
-
if (a[key] !== b[key]) return a[key] > b[key] ? 1 : -1;
|
|
17850
|
-
}
|
|
17851
|
-
if (a.prerelease === b.prerelease) return 0;
|
|
17852
|
-
if (!a.prerelease) return 1;
|
|
17853
|
-
if (!b.prerelease) return -1;
|
|
17854
|
-
return a.prerelease.localeCompare(b.prerelease);
|
|
17855
|
-
}
|
|
17856
|
-
var semverPattern;
|
|
17857
|
-
var init_semver = __esm({
|
|
17858
|
-
"src/resolve/semver.ts"() {
|
|
17859
|
-
"use strict";
|
|
17860
|
-
semverPattern = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
17861
|
-
}
|
|
17862
|
-
});
|
|
17863
|
-
|
|
17864
17946
|
// src/model/selection.ts
|
|
17865
17947
|
function artifactSelectorKey(artifact) {
|
|
17866
17948
|
return `${artifact.type}/${artifact.name}`;
|
|
@@ -17918,9 +18000,9 @@ var init_selection = __esm({
|
|
|
17918
18000
|
});
|
|
17919
18001
|
|
|
17920
18002
|
// src/model/workspace.ts
|
|
17921
|
-
import { readFile as
|
|
18003
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
17922
18004
|
import { homedir as homedir4 } from "os";
|
|
17923
|
-
import { dirname as dirname9, join as
|
|
18005
|
+
import { dirname as dirname9, join as join13, resolve as resolve13 } from "path";
|
|
17924
18006
|
function packagesForTarget(packages, target, targetForPackage2) {
|
|
17925
18007
|
return packages.filter((pkg) => !pkg.runtimes || pkg.runtimes.includes((targetForPackage2?.(pkg) ?? target).adapter));
|
|
17926
18008
|
}
|
|
@@ -17928,12 +18010,12 @@ function supportsFleetConfig(config2) {
|
|
|
17928
18010
|
return config2.schemaVersion === 3 || config2.schemaVersion === 4;
|
|
17929
18011
|
}
|
|
17930
18012
|
function workspaceConfigPath(workspaceRoot) {
|
|
17931
|
-
return
|
|
18013
|
+
return join13(workspaceRoot, ".agentwheel", "config.json");
|
|
17932
18014
|
}
|
|
17933
18015
|
async function readWorkspaceConfig(workspaceRoot) {
|
|
17934
18016
|
const path = workspaceConfigPath(workspaceRoot);
|
|
17935
18017
|
if (!await pathExists(path)) return emptyWorkspaceConfig();
|
|
17936
|
-
return workspaceConfigSchema.parse(JSON.parse(await
|
|
18018
|
+
return workspaceConfigSchema.parse(JSON.parse(await readFile11(path, "utf8")));
|
|
17937
18019
|
}
|
|
17938
18020
|
async function writeWorkspaceConfig(workspaceRoot, config2) {
|
|
17939
18021
|
const path = workspaceConfigPath(workspaceRoot);
|
|
@@ -17947,7 +18029,7 @@ async function pinConfiguredPackages(workspaceRoot, input, options = {}) {
|
|
|
17947
18029
|
throw new Error("Package declarations require unique aliases.");
|
|
17948
18030
|
}
|
|
17949
18031
|
const path2 = workspaceConfigPath(workspaceRoot);
|
|
17950
|
-
const config3 = JSON.parse(await
|
|
18032
|
+
const config3 = JSON.parse(await readFile11(path2, "utf8"));
|
|
17951
18033
|
workspaceConfigSchema.parse(config3);
|
|
17952
18034
|
config3.packages = input;
|
|
17953
18035
|
workspaceConfigSchema.parse(config3);
|
|
@@ -17970,7 +18052,7 @@ async function pinConfiguredPackages(workspaceRoot, input, options = {}) {
|
|
|
17970
18052
|
throw new Error("Pin requires unique configured aliases.");
|
|
17971
18053
|
}
|
|
17972
18054
|
const path = workspaceConfigPath(workspaceRoot);
|
|
17973
|
-
const config2 = JSON.parse(await
|
|
18055
|
+
const config2 = JSON.parse(await readFile11(path, "utf8"));
|
|
17974
18056
|
workspaceConfigSchema.parse(config2);
|
|
17975
18057
|
const updates = pins.map(({ alias, commit, select }) => {
|
|
17976
18058
|
const matches = (config2.packages ?? []).filter((pkg2) => pkg2.name === alias);
|
|
@@ -18004,7 +18086,7 @@ function upsertPackage(config2, entry) {
|
|
|
18004
18086
|
return workspaceConfigSchema.parse({ ...parsed, packages });
|
|
18005
18087
|
}
|
|
18006
18088
|
function globalWorkspaceConfigPath(globalRoot = homedir4()) {
|
|
18007
|
-
return
|
|
18089
|
+
return join13(globalRoot, ".agentwheel", "config.json");
|
|
18008
18090
|
}
|
|
18009
18091
|
async function findWorkspaceRoot(start = process.cwd()) {
|
|
18010
18092
|
let current = resolve13(start);
|
|
@@ -18063,7 +18145,7 @@ function isCompositeWorkspaceProfile(profile) {
|
|
|
18063
18145
|
}
|
|
18064
18146
|
async function readConfigPath(path) {
|
|
18065
18147
|
if (!await pathExists(path)) return emptyWorkspaceConfig();
|
|
18066
|
-
return workspaceConfigSchema.parse(JSON.parse(await
|
|
18148
|
+
return workspaceConfigSchema.parse(JSON.parse(await readFile11(path, "utf8")));
|
|
18067
18149
|
}
|
|
18068
18150
|
function mergeWorkspaceTrust(global, project) {
|
|
18069
18151
|
return {
|
|
@@ -18324,7 +18406,7 @@ var init_workspace = __esm({
|
|
|
18324
18406
|
});
|
|
18325
18407
|
|
|
18326
18408
|
// src/model/fleet.ts
|
|
18327
|
-
import { lstat as lstat2, readFile as
|
|
18409
|
+
import { lstat as lstat2, readFile as readFile12, realpath } from "fs/promises";
|
|
18328
18410
|
import { homedir as homedir5 } from "os";
|
|
18329
18411
|
import { isAbsolute as isAbsolute10, relative as relative6, resolve as resolve14 } from "path";
|
|
18330
18412
|
async function resolveWorkspaceScope(request = {}) {
|
|
@@ -18441,7 +18523,7 @@ async function readRequiredConfig(root, label) {
|
|
|
18441
18523
|
const path = workspaceConfigPath(root);
|
|
18442
18524
|
if (!await pathExists(path)) throw missingScopeError(label);
|
|
18443
18525
|
try {
|
|
18444
|
-
return workspaceConfigSchema.parse(JSON.parse(await
|
|
18526
|
+
return workspaceConfigSchema.parse(JSON.parse(await readFile12(path, "utf8")));
|
|
18445
18527
|
} catch (error46) {
|
|
18446
18528
|
throw new Error(`Invalid ${label} Agentwheel config at ${path}: ${error46 instanceof Error ? error46.message : String(error46)}`);
|
|
18447
18529
|
}
|
|
@@ -18512,7 +18594,7 @@ var init_fleet = __esm({
|
|
|
18512
18594
|
|
|
18513
18595
|
// src/mutation/repository.ts
|
|
18514
18596
|
import { createHash as createHash8 } from "crypto";
|
|
18515
|
-
import { lstat as lstat3, readFile as
|
|
18597
|
+
import { lstat as lstat3, readFile as readFile13, readlink, readdir as readdir5 } from "fs/promises";
|
|
18516
18598
|
import { dirname as dirname10, posix as posix4, relative as relative7, resolve as resolve15, sep as sep5 } from "path";
|
|
18517
18599
|
async function discoverGitRepository(start) {
|
|
18518
18600
|
const probe = await runProcess("git", ["-C", start, "rev-parse", "--show-toplevel"], { allowExitCodes: [0, 128] });
|
|
@@ -18719,7 +18801,7 @@ async function hashWorkingPath(repositoryRoot, path) {
|
|
|
18719
18801
|
throw error46;
|
|
18720
18802
|
}
|
|
18721
18803
|
if (stats.isSymbolicLink()) return sha256(Buffer.from(await readlink(absolute), "utf8"));
|
|
18722
|
-
if (stats.isFile()) return sha256(await
|
|
18804
|
+
if (stats.isFile()) return sha256(await readFile13(absolute));
|
|
18723
18805
|
if (stats.isDirectory()) return hashDirectory(absolute);
|
|
18724
18806
|
throw new Error(`Unsupported repository path kind: ${path}`);
|
|
18725
18807
|
}
|
|
@@ -18732,7 +18814,7 @@ async function hashDirectory(root) {
|
|
|
18732
18814
|
const relativePath = normalizeRepoPath(relative7(root, absolute));
|
|
18733
18815
|
if (entry.isDirectory()) await walk2(absolute);
|
|
18734
18816
|
else if (entry.isSymbolicLink()) hash3.update(relativePath).update("\0").update(await readlink(absolute)).update("\0");
|
|
18735
|
-
else if (entry.isFile()) hash3.update(relativePath).update("\0").update(await
|
|
18817
|
+
else if (entry.isFile()) hash3.update(relativePath).update("\0").update(await readFile13(absolute)).update("\0");
|
|
18736
18818
|
}
|
|
18737
18819
|
}
|
|
18738
18820
|
await walk2(root);
|
|
@@ -18768,9 +18850,9 @@ var init_repository = __esm({
|
|
|
18768
18850
|
|
|
18769
18851
|
// src/mutation/providers.ts
|
|
18770
18852
|
import { createHash as createHash9 } from "crypto";
|
|
18771
|
-
import { chmod as chmod2, mkdtemp, open as open3, readFile as
|
|
18853
|
+
import { chmod as chmod2, mkdtemp, open as open3, readFile as readFile14, rename as rename5, rm as rm4, rmdir, stat as stat3, writeFile as writeFile7 } from "fs/promises";
|
|
18772
18854
|
import { tmpdir as tmpdir2 } from "os";
|
|
18773
|
-
import { isAbsolute as isAbsolute11, join as
|
|
18855
|
+
import { isAbsolute as isAbsolute11, join as join14, resolve as resolve16 } from "path";
|
|
18774
18856
|
function revisionProviderRejection(error46) {
|
|
18775
18857
|
return error46 instanceof RevisionProviderRejectedError ? error46.response : void 0;
|
|
18776
18858
|
}
|
|
@@ -18879,8 +18961,8 @@ async function openImmutableExecutableSnapshot(bytes) {
|
|
|
18879
18961
|
`Command revision providers require an unlinked immutable executable snapshot, which is unsupported on ${process.platform}.`
|
|
18880
18962
|
);
|
|
18881
18963
|
}
|
|
18882
|
-
const root = await mkdtemp(
|
|
18883
|
-
const path =
|
|
18964
|
+
const root = await mkdtemp(join14(tmpdir2(), "agentwheel-revision-command-"));
|
|
18965
|
+
const path = join14(root, "entrypoint");
|
|
18884
18966
|
let snapshot;
|
|
18885
18967
|
try {
|
|
18886
18968
|
await chmod2(root, 448);
|
|
@@ -19034,8 +19116,8 @@ async function finalizeGit(providerId, request, config2) {
|
|
|
19034
19116
|
const indexLease = await captureIndexLease(request.repositoryRoot);
|
|
19035
19117
|
await assertIndexTree(request.repositoryRoot, repository.head);
|
|
19036
19118
|
const hookBaseline = await snapshotRepository(request.repositoryRoot);
|
|
19037
|
-
const tempRoot = await mkdtemp(
|
|
19038
|
-
const indexPath =
|
|
19119
|
+
const tempRoot = await mkdtemp(join14(tmpdir2(), "agentwheel-git-index-"));
|
|
19120
|
+
const indexPath = join14(tempRoot, "index");
|
|
19039
19121
|
const env2 = { ...process.env, GIT_INDEX_FILE: indexPath };
|
|
19040
19122
|
let commitSha;
|
|
19041
19123
|
try {
|
|
@@ -19046,14 +19128,14 @@ async function finalizeGit(providerId, request, config2) {
|
|
|
19046
19128
|
await verifyTemporaryIndexPaths(request, env2);
|
|
19047
19129
|
await runProcess("git", ["-C", request.repositoryRoot, "diff", "--cached", "--check"], { env: env2 });
|
|
19048
19130
|
const tree = (await runProcess("git", ["-C", request.repositoryRoot, "write-tree"], { env: env2 })).stdout.toString("utf8").trim();
|
|
19049
|
-
const messagePath =
|
|
19131
|
+
const messagePath = join14(tempRoot, "COMMIT_EDITMSG");
|
|
19050
19132
|
await writeFile7(messagePath, commitMessage(request, planDigest), { encoding: "utf8", mode: 384 });
|
|
19051
19133
|
await runCommitHooks(request, env2, messagePath);
|
|
19052
19134
|
assertRepositorySnapshotEqual(hookBaseline, await snapshotRepository(request.repositoryRoot), "Git commit hooks");
|
|
19053
19135
|
const stagedAfterHooks = splitNull2((await runProcess("git", ["-C", request.repositoryRoot, "diff", "--cached", "--name-only", "-z"], { env: env2 })).stdout);
|
|
19054
19136
|
assertExactSet(stagedAfterHooks, request.paths.map((entry) => entry.path), "temporary Git index after hooks");
|
|
19055
19137
|
await verifyTemporaryIndexPaths(request, env2);
|
|
19056
|
-
const message = await
|
|
19138
|
+
const message = await readFile14(messagePath, "utf8");
|
|
19057
19139
|
assertCommitMessageContract(message, request, planDigest);
|
|
19058
19140
|
commitSha = (await runProcess("git", ["-C", request.repositoryRoot, "commit-tree", tree, "-p", repository.head], {
|
|
19059
19141
|
env: env2,
|
|
@@ -19172,7 +19254,7 @@ async function captureIndexLease(repositoryRoot) {
|
|
|
19172
19254
|
const rawPath = (await runProcess("git", ["-C", repositoryRoot, "rev-parse", "--git-path", "index"])).stdout.toString("utf8").trim();
|
|
19173
19255
|
const path = isAbsolute11(rawPath) ? rawPath : resolve16(repositoryRoot, rawPath);
|
|
19174
19256
|
try {
|
|
19175
|
-
const [content, info] = await Promise.all([
|
|
19257
|
+
const [content, info] = await Promise.all([readFile14(path), stat3(path)]);
|
|
19176
19258
|
return { path, sha256: sha2562(content), mode: info.mode & 511 };
|
|
19177
19259
|
} catch (error46) {
|
|
19178
19260
|
if (isMissing4(error46)) return { path, sha256: null, mode: 384 };
|
|
@@ -19180,15 +19262,15 @@ async function captureIndexLease(repositoryRoot) {
|
|
|
19180
19262
|
}
|
|
19181
19263
|
}
|
|
19182
19264
|
async function replaceIndexCas(repositoryRoot, lease, commitSha) {
|
|
19183
|
-
const tempRoot = await mkdtemp(
|
|
19184
|
-
const replacementPath =
|
|
19265
|
+
const tempRoot = await mkdtemp(join14(tmpdir2(), "agentwheel-index-replacement-"));
|
|
19266
|
+
const replacementPath = join14(tempRoot, "index");
|
|
19185
19267
|
const lockPath = `${lease.path}.lock`;
|
|
19186
19268
|
let handle;
|
|
19187
19269
|
try {
|
|
19188
19270
|
await runProcess("git", ["-C", repositoryRoot, "read-tree", commitSha], {
|
|
19189
19271
|
env: { ...process.env, GIT_INDEX_FILE: replacementPath }
|
|
19190
19272
|
});
|
|
19191
|
-
const replacement = await
|
|
19273
|
+
const replacement = await readFile14(replacementPath);
|
|
19192
19274
|
handle = await open3(lockPath, "wx", lease.mode);
|
|
19193
19275
|
const current = await readOptionalFile(lease.path);
|
|
19194
19276
|
const currentSha256 = current ? sha2562(current) : null;
|
|
@@ -19230,7 +19312,7 @@ async function hashGitObject(repositoryRoot, spec) {
|
|
|
19230
19312
|
}
|
|
19231
19313
|
async function readOptionalFile(path) {
|
|
19232
19314
|
try {
|
|
19233
|
-
return await
|
|
19315
|
+
return await readFile14(path);
|
|
19234
19316
|
} catch (error46) {
|
|
19235
19317
|
if (isMissing4(error46)) return null;
|
|
19236
19318
|
throw error46;
|
|
@@ -19995,8 +20077,8 @@ var init_coordinator = __esm({
|
|
|
19995
20077
|
|
|
19996
20078
|
// src/transport/ownership-snapshot.ts
|
|
19997
20079
|
import { createHash as createHash10 } from "crypto";
|
|
19998
|
-
import { lstat as lstat4, readdir as readdir6, readFile as
|
|
19999
|
-
import { dirname as dirname12, join as
|
|
20080
|
+
import { lstat as lstat4, readdir as readdir6, readFile as readFile15 } from "fs/promises";
|
|
20081
|
+
import { dirname as dirname12, join as join15, relative as relative9, resolve as resolve18 } from "path";
|
|
20000
20082
|
async function assertSnapshotAncestors(path) {
|
|
20001
20083
|
let current = resolve18(path);
|
|
20002
20084
|
while (true) {
|
|
@@ -20016,9 +20098,9 @@ async function ownershipRuntimeSnapshot(path) {
|
|
|
20016
20098
|
}
|
|
20017
20099
|
hash3.update(JSON.stringify([relative9(path, candidate), info.isDirectory() ? "dir" : "file", info.mode & 4095]));
|
|
20018
20100
|
if (info.isDirectory()) {
|
|
20019
|
-
for (const name of (await readdir6(candidate)).sort()) await visit2(
|
|
20101
|
+
for (const name of (await readdir6(candidate)).sort()) await visit2(join15(candidate, name));
|
|
20020
20102
|
} else {
|
|
20021
|
-
const content = await
|
|
20103
|
+
const content = await readFile15(candidate);
|
|
20022
20104
|
hash3.update(String(content.length)).update("\0").update(content);
|
|
20023
20105
|
}
|
|
20024
20106
|
}
|
|
@@ -20067,7 +20149,7 @@ __export(transaction_exports, {
|
|
|
20067
20149
|
});
|
|
20068
20150
|
import { createHash as createHash11 } from "crypto";
|
|
20069
20151
|
import { cp as cp2, lstat as lstat5, mkdir as mkdir7, open as open4, rm as rm5, stat as stat4 } from "fs/promises";
|
|
20070
|
-
import { dirname as dirname13, join as
|
|
20152
|
+
import { dirname as dirname13, join as join16, relative as relative10, resolve as resolve19, sep as sep7 } from "path";
|
|
20071
20153
|
async function assertNoSymlinkPath2(path) {
|
|
20072
20154
|
const absolute = resolve19(path);
|
|
20073
20155
|
let current = absolute;
|
|
@@ -20130,7 +20212,7 @@ function metadataAuditPath(audit, path) {
|
|
|
20130
20212
|
if (resolve19(audit.workspaceRoot) !== audit.workspaceRoot || path !== `.agentwheel/${audit.kind === "ownership-handoff" ? "ownership-handoffs" : "ownership-releases"}/${audit.operationId}.json`) {
|
|
20131
20213
|
throw new Error("Invalid ownership release audit path.");
|
|
20132
20214
|
}
|
|
20133
|
-
return
|
|
20215
|
+
return join16(audit.workspaceRoot, ...path.split("/"));
|
|
20134
20216
|
}
|
|
20135
20217
|
function metadataRuntimePath(root, path) {
|
|
20136
20218
|
const result = resolve19(root, path);
|
|
@@ -20157,19 +20239,19 @@ async function syncMetadataPath(path, directoryOnly = false) {
|
|
|
20157
20239
|
}
|
|
20158
20240
|
function applyLockPath(targetRoot, adapter, scope = {}) {
|
|
20159
20241
|
const installationType = scope.installationType ?? "local";
|
|
20160
|
-
return
|
|
20242
|
+
return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, { installationType })}.runtime-apply-lock`);
|
|
20161
20243
|
}
|
|
20162
20244
|
function applyJournalPath(targetRoot, adapter, scope = {}) {
|
|
20163
|
-
return
|
|
20245
|
+
return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.apply-journal.json`);
|
|
20164
20246
|
}
|
|
20165
20247
|
function applyBackupDir(targetRoot, adapter, scope = {}) {
|
|
20166
|
-
return
|
|
20248
|
+
return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.apply-backups`);
|
|
20167
20249
|
}
|
|
20168
20250
|
async function acquireApplyLock(targetRoot, adapter, transport = localTransport, options = {}, scope = {}) {
|
|
20169
20251
|
assertGovernedRuntimeTransportSupported(transport);
|
|
20170
20252
|
if (transport.kind === "local-run-as") await transport.prepareApply();
|
|
20171
20253
|
const lockPath = applyLockPath(targetRoot, adapter, scope);
|
|
20172
|
-
const ownerPath =
|
|
20254
|
+
const ownerPath = join16(lockPath, "owner.json");
|
|
20173
20255
|
const metadata = {
|
|
20174
20256
|
pid: process.pid,
|
|
20175
20257
|
adapter,
|
|
@@ -20238,7 +20320,7 @@ async function listApplyJournals(targetRoot, adapter, transport = localTransport
|
|
|
20238
20320
|
const found = [];
|
|
20239
20321
|
for (const fileName of await transport.listDir(metadataDir(targetRoot))) {
|
|
20240
20322
|
if (!fileName.endsWith(suffix)) continue;
|
|
20241
|
-
const path =
|
|
20323
|
+
const path = join16(metadataDir(targetRoot), fileName);
|
|
20242
20324
|
const journal = parseApplyJournal(JSON.parse(await transport.readFile(path)));
|
|
20243
20325
|
if (journal.adapter !== adapter || (journal.installationType ?? "local") !== installationType) continue;
|
|
20244
20326
|
found.push({ path, journal });
|
|
@@ -20250,7 +20332,7 @@ async function listAllApplyJournals(targetRoot, adapter, transport = localTransp
|
|
|
20250
20332
|
const found = [];
|
|
20251
20333
|
for (const fileName of await transport.listDir(metadataDir(targetRoot))) {
|
|
20252
20334
|
if (!fileName.endsWith(suffix)) continue;
|
|
20253
|
-
const path =
|
|
20335
|
+
const path = join16(metadataDir(targetRoot), fileName);
|
|
20254
20336
|
const journal = parseApplyJournal(JSON.parse(await transport.readFile(path)));
|
|
20255
20337
|
if (adapter === void 0 || journal.adapter === adapter) found.push({ path, journal });
|
|
20256
20338
|
}
|
|
@@ -20308,7 +20390,7 @@ async function abortApplyJournal(targetRoot, adapter, transport = localTransport
|
|
|
20308
20390
|
const journalPath = applyJournalPath(targetRoot, adapter, scope);
|
|
20309
20391
|
if (!await transport.pathExists(journalPath)) return void 0;
|
|
20310
20392
|
const stateKey = stateKeyFor(adapter, scope);
|
|
20311
|
-
const archivePath =
|
|
20393
|
+
const archivePath = join16(metadataDir(targetRoot), "archive", `${stateKey}.apply-journal.failed-${journalTimestamp(/* @__PURE__ */ new Date())}.json`);
|
|
20312
20394
|
const content = await transport.readFile(journalPath);
|
|
20313
20395
|
const journal = parseApplyJournal(JSON.parse(content));
|
|
20314
20396
|
if (journal.metadataAudit || journal.metadataGuards) {
|
|
@@ -20441,7 +20523,7 @@ async function recordBackup(operation, index, targetRoot, adapter, transport = l
|
|
|
20441
20523
|
hadExisting
|
|
20442
20524
|
};
|
|
20443
20525
|
}
|
|
20444
|
-
const backupPath =
|
|
20526
|
+
const backupPath = join16(applyBackupDir(targetRoot, adapter, scope), String(index));
|
|
20445
20527
|
if (transport.kind === "local-run-as") {
|
|
20446
20528
|
assertGovernedRuntimeTransportSupported(transport);
|
|
20447
20529
|
await transport.rm(backupPath);
|
|
@@ -20520,7 +20602,7 @@ function assertApplyJournalCompletedOperations(journal) {
|
|
|
20520
20602
|
if (!operation || !["create", "update", "remove"].includes(operation.action) || item.destPath !== operation.destPath || item.kind !== operation.kind || typeof item.hadExisting !== "boolean" || item.completed !== void 0 && typeof item.completed !== "boolean") {
|
|
20521
20603
|
throw new Error("Apply journal completion does not match its immutable operation.");
|
|
20522
20604
|
}
|
|
20523
|
-
const expectedBackup =
|
|
20605
|
+
const expectedBackup = join16(applyBackupDir(journal.targetRoot, journal.adapter, {
|
|
20524
20606
|
installationType: journal.installationType,
|
|
20525
20607
|
stateKey: journal.stateKey
|
|
20526
20608
|
}), String(item.index));
|
|
@@ -20546,15 +20628,24 @@ var init_transaction = __esm({
|
|
|
20546
20628
|
});
|
|
20547
20629
|
|
|
20548
20630
|
// src/install/toml-merge.ts
|
|
20549
|
-
import { mkdir as mkdir8, readFile as
|
|
20550
|
-
import { parse as parseToml } from "smol-toml";
|
|
20631
|
+
import { mkdir as mkdir8, readFile as readFile17, writeFile as writeFile8 } from "fs/promises";
|
|
20632
|
+
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
20551
20633
|
import { dirname as dirname14 } from "path";
|
|
20552
20634
|
async function mergeCodexTomlMcp(sourcePath, destPath) {
|
|
20553
|
-
const source = JSON.parse(await
|
|
20635
|
+
const source = JSON.parse(await readFile17(sourcePath, "utf8"));
|
|
20554
20636
|
const servers = extractMcpServers(source);
|
|
20555
|
-
const current = await pathExists(destPath) ? await
|
|
20556
|
-
const
|
|
20557
|
-
const
|
|
20637
|
+
const current = await pathExists(destPath) ? await readFile17(destPath, "utf8") : "";
|
|
20638
|
+
const parsed = parseToml(current, { integersAsBigInt: "asNeeded" });
|
|
20639
|
+
const currentServers = isPlainRecord(parsed.mcp_servers) ? parsed.mcp_servers : {};
|
|
20640
|
+
const blocks = [];
|
|
20641
|
+
for (const [name, server] of Object.entries(servers).sort(([a], [b]) => a.localeCompare(b))) {
|
|
20642
|
+
const rendered = parseToml(formatMcpServer(name, server), { integersAsBigInt: "asNeeded" });
|
|
20643
|
+
const declared = rendered.mcp_servers[name];
|
|
20644
|
+
const mergedServer = mergeManagedFields(currentServers[name], declared);
|
|
20645
|
+
blocks.push(managedValueMatches(declared, mergedServer) ? formatMcpServer(name, server) : stringifyToml({ mcp_servers: { [name]: mergedServer } }).trimEnd());
|
|
20646
|
+
}
|
|
20647
|
+
const merged = appendMcpServers(removeManagedMcpSections(current, Object.keys(servers)), blocks);
|
|
20648
|
+
parseToml(merged, { integersAsBigInt: "asNeeded" });
|
|
20558
20649
|
await mkdir8(dirname14(destPath), { recursive: true });
|
|
20559
20650
|
await writeFile8(destPath, merged, "utf8");
|
|
20560
20651
|
}
|
|
@@ -20597,7 +20688,7 @@ function isPlainRecord(value) {
|
|
|
20597
20688
|
}
|
|
20598
20689
|
function extractMcpServers(source) {
|
|
20599
20690
|
const raw = isRecord2(source.mcpServers) ? source.mcpServers : source;
|
|
20600
|
-
const servers =
|
|
20691
|
+
const servers = /* @__PURE__ */ Object.create(null);
|
|
20601
20692
|
for (const [name, value] of Object.entries(raw)) {
|
|
20602
20693
|
if (!isRecord2(value)) continue;
|
|
20603
20694
|
servers[name] = value;
|
|
@@ -20608,23 +20699,39 @@ function extractMcpServers(source) {
|
|
|
20608
20699
|
return servers;
|
|
20609
20700
|
}
|
|
20610
20701
|
function removeManagedMcpSections(content, serverNames) {
|
|
20611
|
-
if (serverNames.length === 0 || content.trim() === "") return content;
|
|
20612
20702
|
const names = new Set(serverNames);
|
|
20613
|
-
const lines = content.split(/\r?\n/);
|
|
20614
20703
|
const kept = [];
|
|
20615
20704
|
let skipping = false;
|
|
20616
|
-
|
|
20617
|
-
|
|
20618
|
-
if (
|
|
20619
|
-
|
|
20620
|
-
|
|
20705
|
+
let offset = 0;
|
|
20706
|
+
for (const line of content.split(/(?<=\n)/)) {
|
|
20707
|
+
if (line.trimStart().startsWith("[")) {
|
|
20708
|
+
try {
|
|
20709
|
+
parseToml(content.slice(0, offset), { integersAsBigInt: "asNeeded" });
|
|
20710
|
+
const header = parseToml(line, { integersAsBigInt: "asNeeded" });
|
|
20711
|
+
const servers = isPlainRecord(header.mcp_servers) ? header.mcp_servers : {};
|
|
20712
|
+
skipping = Object.keys(servers).some((name) => names.has(name));
|
|
20713
|
+
} catch {
|
|
20714
|
+
}
|
|
20621
20715
|
}
|
|
20622
20716
|
if (!skipping) kept.push(line);
|
|
20717
|
+
offset += line.length;
|
|
20623
20718
|
}
|
|
20624
|
-
return kept.join("
|
|
20719
|
+
return kept.join("");
|
|
20720
|
+
}
|
|
20721
|
+
function mergeManagedFields(current, declared) {
|
|
20722
|
+
if (!isPlainRecord(declared)) return declared;
|
|
20723
|
+
const merged = isPlainRecord(current) ? { ...current } : {};
|
|
20724
|
+
for (const [key, value] of Object.entries(declared)) {
|
|
20725
|
+
Object.defineProperty(merged, key, {
|
|
20726
|
+
value: mergeManagedFields(Object.hasOwn(merged, key) ? merged[key] : void 0, value),
|
|
20727
|
+
enumerable: true,
|
|
20728
|
+
configurable: true,
|
|
20729
|
+
writable: true
|
|
20730
|
+
});
|
|
20731
|
+
}
|
|
20732
|
+
return merged;
|
|
20625
20733
|
}
|
|
20626
|
-
function appendMcpServers(content,
|
|
20627
|
-
const blocks = Object.entries(servers).sort(([a], [b]) => a.localeCompare(b)).map(([name, server]) => formatMcpServer(name, server));
|
|
20734
|
+
function appendMcpServers(content, blocks) {
|
|
20628
20735
|
const prefix = content.trimEnd();
|
|
20629
20736
|
return `${prefix ? `${prefix}
|
|
20630
20737
|
|
|
@@ -20704,12 +20811,12 @@ var init_toml_merge = __esm({
|
|
|
20704
20811
|
});
|
|
20705
20812
|
|
|
20706
20813
|
// src/install/yaml-merge.ts
|
|
20707
|
-
import { mkdir as mkdir9, readFile as
|
|
20814
|
+
import { mkdir as mkdir9, readFile as readFile18, writeFile as writeFile9 } from "fs/promises";
|
|
20708
20815
|
import { dirname as dirname15 } from "path";
|
|
20709
20816
|
import { parse as parse7, stringify } from "yaml";
|
|
20710
20817
|
async function mergeYamlFile(sourcePath, destPath) {
|
|
20711
|
-
const source = parseYamlValue(await
|
|
20712
|
-
const current = await pathExists(destPath) ? parseYamlValue(await
|
|
20818
|
+
const source = parseYamlValue(await readFile18(sourcePath, "utf8"));
|
|
20819
|
+
const current = await pathExists(destPath) ? parseYamlValue(await readFile18(destPath, "utf8")) : {};
|
|
20713
20820
|
const merged = deepMerge2(current, source);
|
|
20714
20821
|
await mkdir9(dirname15(destPath), { recursive: true });
|
|
20715
20822
|
await writeFile9(destPath, stringify(merged), "utf8");
|
|
@@ -20769,7 +20876,7 @@ var init_yaml_merge = __esm({
|
|
|
20769
20876
|
});
|
|
20770
20877
|
|
|
20771
20878
|
// src/install/merge-removal.ts
|
|
20772
|
-
import { mkdir as mkdir10, readFile as
|
|
20879
|
+
import { mkdir as mkdir10, readFile as readFile19, writeFile as writeFile10 } from "fs/promises";
|
|
20773
20880
|
import { dirname as dirname16 } from "path";
|
|
20774
20881
|
import { parse as parse8, stringify as stringify2 } from "yaml";
|
|
20775
20882
|
function assertExactMergeContribution(contribution, strategy, currentContent) {
|
|
@@ -20847,7 +20954,7 @@ async function mergeRemovalForInstall(sourcePath, strategy, currentContent, opti
|
|
|
20847
20954
|
return introducedMergeContent(parseMergeDestination(currentContent, strategy), source);
|
|
20848
20955
|
}
|
|
20849
20956
|
async function removeMergeContribution(destPath, strategy, removal) {
|
|
20850
|
-
const content = await
|
|
20957
|
+
const content = await readFile19(destPath, "utf8");
|
|
20851
20958
|
if (strategy === "codex-toml-mcp") {
|
|
20852
20959
|
const servers = isRecord4(removal.mcpServers) ? removal.mcpServers : removal;
|
|
20853
20960
|
await writeFile10(destPath, removeCodexTomlMcpSections(content, Object.keys(servers)), "utf8");
|
|
@@ -20871,7 +20978,7 @@ async function readMergeSource(sourcePath, strategy) {
|
|
|
20871
20978
|
if (strategy === "openclaw-json-deep") {
|
|
20872
20979
|
return requireRecord(await renderOpenClawJsonMergeSource(sourcePath), "OpenClaw JSON merge source");
|
|
20873
20980
|
}
|
|
20874
|
-
const content = await
|
|
20981
|
+
const content = await readFile19(sourcePath, "utf8");
|
|
20875
20982
|
if (strategy === "yaml-deep") return requireRecord(normalizeYamlValue2(parse8(content)), "YAML merge source");
|
|
20876
20983
|
return requireRecord(JSON.parse(content), "JSON merge source");
|
|
20877
20984
|
}
|
|
@@ -21123,9 +21230,9 @@ var init_desired = __esm({
|
|
|
21123
21230
|
|
|
21124
21231
|
// src/install/instructions-block.ts
|
|
21125
21232
|
import { createHash as createHash12 } from "crypto";
|
|
21126
|
-
import { mkdtemp as mkdtemp2, readFile as
|
|
21233
|
+
import { mkdtemp as mkdtemp2, readFile as readFile20, realpath as realpath2, rm as rm6, writeFile as writeFile11 } from "fs/promises";
|
|
21127
21234
|
import { tmpdir as tmpdir3 } from "os";
|
|
21128
|
-
import { basename as basename2, dirname as dirname17, join as
|
|
21235
|
+
import { basename as basename2, dirname as dirname17, join as join17, relative as relative11 } from "path";
|
|
21129
21236
|
function exactManagedInstructionBlockSnapshot(content, selector) {
|
|
21130
21237
|
const beginCount = [...content.matchAll(new RegExp(`<!-- BEGIN openpack:include ${escapeRegex2(selector)}(?=\\s|-->)`, "gu"))].length;
|
|
21131
21238
|
const endCount = [...content.matchAll(new RegExp(`<!-- END openpack:include ${escapeRegex2(selector)}(?=\\s|-->)`, "gu"))].length;
|
|
@@ -21176,7 +21283,7 @@ function exactManagedInstructionBlockSnapshot(content, selector) {
|
|
|
21176
21283
|
};
|
|
21177
21284
|
}
|
|
21178
21285
|
async function desiredManagedInstructionBlockHash(sourcePath) {
|
|
21179
|
-
const source = await
|
|
21286
|
+
const source = await readFile20(sourcePath, "utf8");
|
|
21180
21287
|
return hashText(managedBlockBody(source));
|
|
21181
21288
|
}
|
|
21182
21289
|
async function readManagedInstructionBlockState(destPath, selector, transport) {
|
|
@@ -21196,7 +21303,7 @@ async function readManagedInstructionBlockState(destPath, selector, transport) {
|
|
|
21196
21303
|
};
|
|
21197
21304
|
}
|
|
21198
21305
|
async function writeManagedInstructionBlock(sourcePath, destPath, selector, transport, options = {}) {
|
|
21199
|
-
const source = await
|
|
21306
|
+
const source = await readFile20(sourcePath, "utf8");
|
|
21200
21307
|
const desired = renderManagedInstructionBlock(selector, source);
|
|
21201
21308
|
const existing = await readOptionalText(destPath, transport);
|
|
21202
21309
|
const merged = upsertManagedInstructionBlock(existing ?? "", selector, desired.block, options);
|
|
@@ -21317,7 +21424,7 @@ function referencesAgentsMd(content, claudePath, agentsPath) {
|
|
|
21317
21424
|
if (!referenced) continue;
|
|
21318
21425
|
const cleaned = referenced.trim().replace(/^["']|["']$/g, "");
|
|
21319
21426
|
if (!/AGENTS\.md$/i.test(cleaned)) continue;
|
|
21320
|
-
const candidate = cleaned.startsWith("/") ? cleaned :
|
|
21427
|
+
const candidate = cleaned.startsWith("/") ? cleaned : join17(claudeDir, cleaned);
|
|
21321
21428
|
if (relative11(dirname17(agentsPath), candidate).replaceAll("\\", "/") === "AGENTS.md") return true;
|
|
21322
21429
|
if (candidate === agentsPath) return true;
|
|
21323
21430
|
}
|
|
@@ -21337,8 +21444,8 @@ async function writeTextWithTransport(path, content, transport) {
|
|
|
21337
21444
|
await transport.writeFileAtomic(path, content);
|
|
21338
21445
|
return;
|
|
21339
21446
|
}
|
|
21340
|
-
const tempRoot = await mkdtemp2(
|
|
21341
|
-
const localPath =
|
|
21447
|
+
const tempRoot = await mkdtemp2(join17(tmpdir3(), "agentwheel-instructions-"));
|
|
21448
|
+
const localPath = join17(tempRoot, basename2(path) || "instructions.md");
|
|
21342
21449
|
try {
|
|
21343
21450
|
await writeFile11(localPath, content, "utf8");
|
|
21344
21451
|
await transport.atomicCopy(localPath, path, "file");
|
|
@@ -21376,9 +21483,9 @@ __export(apply_exports, {
|
|
|
21376
21483
|
});
|
|
21377
21484
|
import { execFile as execFile5 } from "child_process";
|
|
21378
21485
|
import { createHash as createHash13, randomUUID as randomUUID3 } from "crypto";
|
|
21379
|
-
import { chmod as chmod3, link as link2, lstat as lstat6, mkdir as mkdir11, mkdtemp as mkdtemp3, open as open5, readFile as
|
|
21486
|
+
import { chmod as chmod3, link as link2, lstat as lstat6, mkdir as mkdir11, mkdtemp as mkdtemp3, open as open5, readFile as readFile21, rm as rm7, writeFile as writeFile12 } from "fs/promises";
|
|
21380
21487
|
import { tmpdir as tmpdir4 } from "os";
|
|
21381
|
-
import { basename as basename3, dirname as dirname18, join as
|
|
21488
|
+
import { basename as basename3, dirname as dirname18, join as join18, resolve as resolve20 } from "path";
|
|
21382
21489
|
import { promisify as promisify5 } from "util";
|
|
21383
21490
|
async function applyInstallPlan(plan, sourceLock, options = {}) {
|
|
21384
21491
|
return applyPlanTransactionally(plan, { ...options, sourceLock });
|
|
@@ -21478,6 +21585,10 @@ async function assertRuntimeStateRevision(plan, transport) {
|
|
|
21478
21585
|
async function applyPlanTransactionally(plan, options = {}) {
|
|
21479
21586
|
const transport = options.transport ?? localTransport;
|
|
21480
21587
|
const scope = { installationType: plan.installationType, stateKey: plan.stateKey };
|
|
21588
|
+
const openClawAcceptCapabilities = createOpenClawCapabilityDetector(async (args) => {
|
|
21589
|
+
if (transport.kind === "local") return (await execFileAsync4("openclaw", args, { timeout: 1e4 })).stdout;
|
|
21590
|
+
return transport.execFile?.("openclaw", args, { cwd: plan.targetRoot });
|
|
21591
|
+
});
|
|
21481
21592
|
if (plan.hasBlockingChanges) {
|
|
21482
21593
|
const blockers = plan.operations.filter((operation) => operation.action === "drift" || operation.action === "conflict");
|
|
21483
21594
|
throw new Error(`Refusing to apply with blocking changes: ${blockers.map((item) => item.relativeDestPath).join(", ")}`);
|
|
@@ -21538,6 +21649,7 @@ async function applyPlanTransactionally(plan, options = {}) {
|
|
|
21538
21649
|
transport,
|
|
21539
21650
|
now,
|
|
21540
21651
|
executePlugins: options.executePlugins,
|
|
21652
|
+
openClawAcceptCapabilities,
|
|
21541
21653
|
graphLockDigest,
|
|
21542
21654
|
plan
|
|
21543
21655
|
});
|
|
@@ -21773,7 +21885,7 @@ async function assertCommittedJournalState(journal, expectedManifest, transport)
|
|
|
21773
21885
|
}
|
|
21774
21886
|
}
|
|
21775
21887
|
if (journal.workspaceConfigPath && journal.workspaceConfig) {
|
|
21776
|
-
const actual = JSON.parse(await
|
|
21888
|
+
const actual = JSON.parse(await readFile21(journal.workspaceConfigPath, "utf8"));
|
|
21777
21889
|
if (canonicalJson5(actual) !== canonicalJson5(journal.workspaceConfig)) {
|
|
21778
21890
|
throw new Error(`Workspace config postcheck failed for ${journal.workspaceConfigPath}.`);
|
|
21779
21891
|
}
|
|
@@ -21795,7 +21907,7 @@ async function assertMetadataAuditGuards(journal, after, transport, requireAfter
|
|
|
21795
21907
|
throw new Error("Metadata-audit content digest is invalid.");
|
|
21796
21908
|
}
|
|
21797
21909
|
try {
|
|
21798
|
-
if (await
|
|
21910
|
+
if (await readFile21(path, "utf8") !== file2.content) throw new Error(`Metadata-audit file changed: ${path}`);
|
|
21799
21911
|
} catch (error46) {
|
|
21800
21912
|
if (error46.code !== "ENOENT" || requireAfter) throw error46;
|
|
21801
21913
|
}
|
|
@@ -21878,7 +21990,7 @@ async function writeAuditFileExclusive(path, content, validateCallerPath) {
|
|
|
21878
21990
|
try {
|
|
21879
21991
|
await link2(temporary, path);
|
|
21880
21992
|
} catch (error46) {
|
|
21881
|
-
if (error46.code !== "EEXIST" || await
|
|
21993
|
+
if (error46.code !== "EEXIST" || await readFile21(path, "utf8") !== content) throw error46;
|
|
21882
21994
|
}
|
|
21883
21995
|
const directory = await open5(dirname18(path), "r");
|
|
21884
21996
|
try {
|
|
@@ -21903,7 +22015,7 @@ async function applyOperation(operation, context) {
|
|
|
21903
22015
|
throw new Error(`Invalid plugin operation missing hash: ${operation.relativeDestPath}`);
|
|
21904
22016
|
}
|
|
21905
22017
|
if (context.executePlugins) {
|
|
21906
|
-
await executePluginInstall(operation, transport);
|
|
22018
|
+
await executePluginInstall(operation, transport, context.openClawAcceptCapabilities);
|
|
21907
22019
|
}
|
|
21908
22020
|
return manifestEntryForOperation(operation, {
|
|
21909
22021
|
now,
|
|
@@ -22063,8 +22175,15 @@ async function applyOperation(operation, context) {
|
|
|
22063
22175
|
}
|
|
22064
22176
|
return void 0;
|
|
22065
22177
|
}
|
|
22066
|
-
async function executePluginInstall(operation, transport) {
|
|
22067
|
-
const commands = semanticInstallCommands(operation)
|
|
22178
|
+
async function executePluginInstall(operation, transport, openClawAcceptCapabilities) {
|
|
22179
|
+
const commands = await Promise.all(semanticInstallCommands(operation).map(async (command) => {
|
|
22180
|
+
if (command.length !== 5 || command.slice(0, 4).join(" ") !== "openclaw plugins install --force") return command;
|
|
22181
|
+
return openClawPluginInstallCommand({
|
|
22182
|
+
path: command[4],
|
|
22183
|
+
dryRun: false,
|
|
22184
|
+
acceptCapabilities: await openClawAcceptCapabilities?.() ?? false
|
|
22185
|
+
});
|
|
22186
|
+
}));
|
|
22068
22187
|
if (commands.length === 0) throw new Error(`Invalid plugin operation missing command: ${operation.relativeDestPath}`);
|
|
22069
22188
|
if (!operation.sourcePath) {
|
|
22070
22189
|
throw new Error(`Invalid plugin operation missing source path: ${operation.relativeDestPath}`);
|
|
@@ -22112,10 +22231,10 @@ async function prepareSemanticPluginState(operation, transport) {
|
|
|
22112
22231
|
async function prepareClaudeMarketplace(operation, transport) {
|
|
22113
22232
|
const spec = requireSemanticPluginState(operation);
|
|
22114
22233
|
const marketplaceName = requireMarketplaceName(operation);
|
|
22115
|
-
const marketplaceRoot =
|
|
22234
|
+
const marketplaceRoot = join18(spec.stateRoot, "marketplace");
|
|
22116
22235
|
await transport.rm(spec.stateRoot);
|
|
22117
|
-
await transport.atomicCopy(requireSourcePath(operation),
|
|
22118
|
-
await transport.writeJsonAtomic(
|
|
22236
|
+
await transport.atomicCopy(requireSourcePath(operation), join18(marketplaceRoot, "plugins", spec.pluginName), operation.kind);
|
|
22237
|
+
await transport.writeJsonAtomic(join18(marketplaceRoot, ".claude-plugin", "marketplace.json"), {
|
|
22119
22238
|
name: marketplaceName,
|
|
22120
22239
|
owner: { name: "Agentwheel" },
|
|
22121
22240
|
plugins: [
|
|
@@ -22130,10 +22249,10 @@ async function prepareClaudeMarketplace(operation, transport) {
|
|
|
22130
22249
|
async function prepareCodexMarketplace(operation, transport) {
|
|
22131
22250
|
const spec = requireSemanticPluginState(operation);
|
|
22132
22251
|
const marketplaceName = requireMarketplaceName(operation);
|
|
22133
|
-
const marketplaceRoot =
|
|
22252
|
+
const marketplaceRoot = join18(spec.stateRoot, "marketplace");
|
|
22134
22253
|
await transport.rm(spec.stateRoot);
|
|
22135
|
-
await transport.atomicCopy(requireSourcePath(operation),
|
|
22136
|
-
await transport.writeJsonAtomic(
|
|
22254
|
+
await transport.atomicCopy(requireSourcePath(operation), join18(marketplaceRoot, "plugins", spec.pluginName), operation.kind);
|
|
22255
|
+
await transport.writeJsonAtomic(join18(marketplaceRoot, ".agents", "plugins", "marketplace.json"), {
|
|
22137
22256
|
name: marketplaceName,
|
|
22138
22257
|
interface: {
|
|
22139
22258
|
displayName: "Agentwheel"
|
|
@@ -22157,11 +22276,11 @@ async function prepareCodexMarketplace(operation, transport) {
|
|
|
22157
22276
|
async function prepareCopilotPlugin(operation, transport) {
|
|
22158
22277
|
const spec = requireSemanticPluginState(operation);
|
|
22159
22278
|
await transport.rm(spec.stateRoot);
|
|
22160
|
-
await transport.atomicCopy(requireSourcePath(operation),
|
|
22279
|
+
await transport.atomicCopy(requireSourcePath(operation), join18(spec.stateRoot, "plugin"), operation.kind);
|
|
22161
22280
|
}
|
|
22162
22281
|
async function prepareHermesGitShim(operation, transport) {
|
|
22163
22282
|
const spec = requireSemanticPluginState(operation);
|
|
22164
|
-
const repoRoot =
|
|
22283
|
+
const repoRoot = join18(spec.stateRoot, "repo");
|
|
22165
22284
|
await transport.rm(spec.stateRoot);
|
|
22166
22285
|
await transport.atomicCopy(requireSourcePath(operation), repoRoot, operation.kind);
|
|
22167
22286
|
if (!transport.execFile) {
|
|
@@ -22216,8 +22335,8 @@ async function executeSemanticCommands(operation, commands, transport, options =
|
|
|
22216
22335
|
if (!operation.sourcePath) {
|
|
22217
22336
|
throw new Error(`Invalid semantic plugin operation missing source path: ${operation.relativeDestPath}`);
|
|
22218
22337
|
}
|
|
22219
|
-
const stagingRoot =
|
|
22220
|
-
const remoteSourcePath =
|
|
22338
|
+
const stagingRoot = join18(operation.destPath, ".agentwheel", "plugin-staging", `${process.pid}-${Date.now()}`);
|
|
22339
|
+
const remoteSourcePath = join18(stagingRoot, basename3(operation.sourcePath));
|
|
22221
22340
|
try {
|
|
22222
22341
|
await transport.atomicCopy(operation.sourcePath, remoteSourcePath, operation.kind);
|
|
22223
22342
|
for (const [command, ...args] of commands) {
|
|
@@ -22484,8 +22603,8 @@ async function mergeWithTransport(sourcePath, destPath, transport, merge2) {
|
|
|
22484
22603
|
await merge2(sourcePath, destPath);
|
|
22485
22604
|
return;
|
|
22486
22605
|
}
|
|
22487
|
-
const tempRoot = await mkdtemp3(
|
|
22488
|
-
const localDest =
|
|
22606
|
+
const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-merge-"));
|
|
22607
|
+
const localDest = join18(tempRoot, basename3(destPath) || "merged");
|
|
22489
22608
|
try {
|
|
22490
22609
|
if (await transport.pathExists(destPath)) {
|
|
22491
22610
|
await writeFile12(localDest, await transport.readFile(destPath), "utf8");
|
|
@@ -22501,8 +22620,8 @@ async function removeMergeWithTransport(destPath, strategy, removal, transport)
|
|
|
22501
22620
|
await removeMergeContribution(destPath, strategy, removal);
|
|
22502
22621
|
return;
|
|
22503
22622
|
}
|
|
22504
|
-
const tempRoot = await mkdtemp3(
|
|
22505
|
-
const localDest =
|
|
22623
|
+
const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-merge-remove-"));
|
|
22624
|
+
const localDest = join18(tempRoot, basename3(destPath) || "merged");
|
|
22506
22625
|
try {
|
|
22507
22626
|
await writeFile12(localDest, await transport.readFile(destPath), "utf8");
|
|
22508
22627
|
await removeMergeContribution(localDest, strategy, removal);
|
|
@@ -22512,8 +22631,8 @@ async function removeMergeWithTransport(destPath, strategy, removal, transport)
|
|
|
22512
22631
|
}
|
|
22513
22632
|
}
|
|
22514
22633
|
async function mergeOpenClawJsonWithTransport(sourcePath, destPath, transport) {
|
|
22515
|
-
const tempRoot = await mkdtemp3(
|
|
22516
|
-
const localDest =
|
|
22634
|
+
const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-openclaw-merge-"));
|
|
22635
|
+
const localDest = join18(tempRoot, basename3(destPath) || "openclaw.json");
|
|
22517
22636
|
const validationPath = transport.kind === "local" ? localDest : `${destPath}.validate-agentwheel-${process.pid}-${Date.now()}`;
|
|
22518
22637
|
try {
|
|
22519
22638
|
if (await transport.pathExists(destPath)) {
|
|
@@ -22540,7 +22659,7 @@ async function validateOpenClawConfig(configPath, destPath, transport) {
|
|
|
22540
22659
|
throw new Error(`Cannot validate OpenClaw config over ${transport.description}: transport does not support command execution.`);
|
|
22541
22660
|
}
|
|
22542
22661
|
const openClawHome = dirname18(destPath);
|
|
22543
|
-
const bundledBin =
|
|
22662
|
+
const bundledBin = join18(openClawHome, "npm", "node_modules", ".bin", "openclaw");
|
|
22544
22663
|
const script = String.raw`
|
|
22545
22664
|
set -euo pipefail
|
|
22546
22665
|
cfg=$1
|
|
@@ -22568,6 +22687,7 @@ var init_apply = __esm({
|
|
|
22568
22687
|
init_declarations();
|
|
22569
22688
|
init_graph_lock();
|
|
22570
22689
|
init_transport();
|
|
22690
|
+
init_openclaw2();
|
|
22571
22691
|
init_run_as_policy();
|
|
22572
22692
|
init_json_merge();
|
|
22573
22693
|
init_openclaw_json_merge();
|
|
@@ -22718,8 +22838,8 @@ import { basename as basename8, join as join28, relative as relative12 } from "p
|
|
|
22718
22838
|
|
|
22719
22839
|
// src/staging/codex-subagents.ts
|
|
22720
22840
|
init_fs();
|
|
22721
|
-
import { mkdir as mkdir12, readFile as
|
|
22722
|
-
import { basename as basename4, dirname as dirname19, join as
|
|
22841
|
+
import { mkdir as mkdir12, readFile as readFile22, writeFile as writeFile13 } from "fs/promises";
|
|
22842
|
+
import { basename as basename4, dirname as dirname19, join as join19 } from "path";
|
|
22723
22843
|
import { parse as parseYaml } from "yaml";
|
|
22724
22844
|
var requiredCodexAgentFields = ["name", "description", "developer_instructions"];
|
|
22725
22845
|
async function renderCodexSubagents(artifacts, stageRoot, adapter) {
|
|
@@ -22743,27 +22863,27 @@ async function renderCodexSubagents(artifacts, stageRoot, adapter) {
|
|
|
22743
22863
|
async function renderCodexSubagent(artifact, stageRoot) {
|
|
22744
22864
|
const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
|
|
22745
22865
|
const agentName = codexAgentName(artifact);
|
|
22746
|
-
const renderedPath =
|
|
22866
|
+
const renderedPath = join19(stageRoot, ".agentwheel-rendered", "codex-subagents", `${agentName}.toml`);
|
|
22747
22867
|
const lowerSourcePath = sourcePath.toLowerCase();
|
|
22748
22868
|
if (artifact.kind === "file" && (artifact.name.toLowerCase().endsWith(".toml") || lowerSourcePath.endsWith(".toml"))) {
|
|
22749
|
-
const content = await
|
|
22869
|
+
const content = await readFile22(sourcePath, "utf8");
|
|
22750
22870
|
validateCodexAgentToml(content, sourcePath);
|
|
22751
22871
|
return {
|
|
22752
22872
|
...artifact,
|
|
22753
22873
|
name: agentName,
|
|
22754
|
-
relativePath:
|
|
22874
|
+
relativePath: join19("subagents", `${agentName}.toml`),
|
|
22755
22875
|
kind: "file",
|
|
22756
22876
|
hash: await hashPath(sourcePath)
|
|
22757
22877
|
};
|
|
22758
22878
|
}
|
|
22759
|
-
const markdownPath = artifact.kind === "dir" ?
|
|
22879
|
+
const markdownPath = artifact.kind === "dir" ? join19(sourcePath, "AGENTS.md") : sourcePath;
|
|
22760
22880
|
if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
|
|
22761
22881
|
throw new Error(`Codex subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
|
|
22762
22882
|
}
|
|
22763
22883
|
if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md") && !lowerSourcePath.endsWith(".md")) {
|
|
22764
22884
|
throw new Error(`Codex subagent ${artifact.relativePath} must be a .toml file, .md file, or directory containing AGENTS.md.`);
|
|
22765
22885
|
}
|
|
22766
|
-
const markdown = await
|
|
22886
|
+
const markdown = await readFile22(markdownPath, "utf8");
|
|
22767
22887
|
const toml = markdownToCodexAgentToml(agentName, markdown);
|
|
22768
22888
|
await mkdir12(dirname19(renderedPath), { recursive: true });
|
|
22769
22889
|
await writeFile13(renderedPath, toml, "utf8");
|
|
@@ -22772,7 +22892,7 @@ async function renderCodexSubagent(artifact, stageRoot) {
|
|
|
22772
22892
|
name: agentName,
|
|
22773
22893
|
sourcePath: renderedPath,
|
|
22774
22894
|
stagedPath: renderedPath,
|
|
22775
|
-
relativePath:
|
|
22895
|
+
relativePath: join19("subagents", `${agentName}.toml`),
|
|
22776
22896
|
kind: "file",
|
|
22777
22897
|
hash: await hashPath(renderedPath)
|
|
22778
22898
|
};
|
|
@@ -22847,8 +22967,8 @@ function escapeRegExp2(value) {
|
|
|
22847
22967
|
|
|
22848
22968
|
// src/staging/copilot-artifacts.ts
|
|
22849
22969
|
init_fs();
|
|
22850
|
-
import { mkdir as mkdir13, readFile as
|
|
22851
|
-
import { basename as basename5, dirname as dirname20, join as
|
|
22970
|
+
import { mkdir as mkdir13, readFile as readFile23, writeFile as writeFile14 } from "fs/promises";
|
|
22971
|
+
import { basename as basename5, dirname as dirname20, join as join20 } from "path";
|
|
22852
22972
|
async function renderCopilotArtifacts(artifacts, stageRoot, adapter) {
|
|
22853
22973
|
if (adapter?.name !== "copilot") return artifacts;
|
|
22854
22974
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -22870,15 +22990,15 @@ async function renderCopilotArtifacts(artifacts, stageRoot, adapter) {
|
|
|
22870
22990
|
async function renderCopilotSubagent(artifact, stageRoot) {
|
|
22871
22991
|
const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
|
|
22872
22992
|
const agentName = copilotAgentName(artifact);
|
|
22873
|
-
const renderedPath =
|
|
22874
|
-
const markdownPath = artifact.kind === "dir" ?
|
|
22993
|
+
const renderedPath = join20(stageRoot, ".agentwheel-rendered", "copilot-subagents", `${agentName}.agent.md`);
|
|
22994
|
+
const markdownPath = artifact.kind === "dir" ? join20(sourcePath, "AGENTS.md") : sourcePath;
|
|
22875
22995
|
if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
|
|
22876
22996
|
throw new Error(`Copilot subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
|
|
22877
22997
|
}
|
|
22878
22998
|
if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md")) {
|
|
22879
22999
|
throw new Error(`Copilot subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
|
|
22880
23000
|
}
|
|
22881
|
-
const markdown = await
|
|
23001
|
+
const markdown = await readFile23(markdownPath, "utf8");
|
|
22882
23002
|
await mkdir13(dirname20(renderedPath), { recursive: true });
|
|
22883
23003
|
await writeFile14(renderedPath, ensureCopilotAgentDescription(agentName, markdown), "utf8");
|
|
22884
23004
|
return {
|
|
@@ -22886,7 +23006,7 @@ async function renderCopilotSubagent(artifact, stageRoot) {
|
|
|
22886
23006
|
name: `${agentName}.agent.md`,
|
|
22887
23007
|
sourcePath: renderedPath,
|
|
22888
23008
|
stagedPath: renderedPath,
|
|
22889
|
-
relativePath:
|
|
23009
|
+
relativePath: join20("subagents", `${agentName}.agent.md`),
|
|
22890
23010
|
kind: "file",
|
|
22891
23011
|
hash: await hashPath(renderedPath)
|
|
22892
23012
|
};
|
|
@@ -22934,8 +23054,8 @@ function yamlString(value) {
|
|
|
22934
23054
|
|
|
22935
23055
|
// src/staging/openclaw-subagents.ts
|
|
22936
23056
|
init_fs();
|
|
22937
|
-
import { mkdir as mkdir14, readFile as
|
|
22938
|
-
import { basename as basename6, dirname as dirname21, join as
|
|
23057
|
+
import { mkdir as mkdir14, readFile as readFile24, writeFile as writeFile15 } from "fs/promises";
|
|
23058
|
+
import { basename as basename6, dirname as dirname21, join as join21 } from "path";
|
|
22939
23059
|
async function renderOpenClawSubagents(artifacts, stageRoot, adapter) {
|
|
22940
23060
|
if (adapter?.name !== "openclaw") return artifacts;
|
|
22941
23061
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -22957,18 +23077,18 @@ async function renderOpenClawSubagents(artifacts, stageRoot, adapter) {
|
|
|
22957
23077
|
async function renderOpenClawSubagent(artifact, stageRoot) {
|
|
22958
23078
|
const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
|
|
22959
23079
|
const agentId = openClawAgentId(artifact);
|
|
22960
|
-
const markdownPath = artifact.kind === "dir" ?
|
|
23080
|
+
const markdownPath = artifact.kind === "dir" ? join21(sourcePath, "AGENTS.md") : sourcePath;
|
|
22961
23081
|
if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
|
|
22962
23082
|
throw new Error(`OpenClaw subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
|
|
22963
23083
|
}
|
|
22964
23084
|
if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md") && !sourcePath.toLowerCase().endsWith(".md")) {
|
|
22965
23085
|
throw new Error(`OpenClaw subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
|
|
22966
23086
|
}
|
|
22967
|
-
const parsed = splitFrontmatter3(await
|
|
23087
|
+
const parsed = splitFrontmatter3(await readFile24(markdownPath, "utf8"));
|
|
22968
23088
|
const body = parsed.body.trim().length > 0 ? parsed.body.trim() : `# ${titleFromAgentId(agentId)}
|
|
22969
23089
|
|
|
22970
23090
|
${parsed.description ?? `OpenClaw subagent ${agentId}.`}`;
|
|
22971
|
-
const renderedPath =
|
|
23091
|
+
const renderedPath = join21(stageRoot, ".agentwheel-rendered", "openclaw-subagents", agentId, "AGENTS.md");
|
|
22972
23092
|
await mkdir14(dirname21(renderedPath), { recursive: true });
|
|
22973
23093
|
await writeFile15(renderedPath, `${body}
|
|
22974
23094
|
`, "utf8");
|
|
@@ -22978,7 +23098,7 @@ ${parsed.description ?? `OpenClaw subagent ${agentId}.`}`;
|
|
|
22978
23098
|
name: agentId,
|
|
22979
23099
|
sourcePath: renderedDir,
|
|
22980
23100
|
stagedPath: renderedDir,
|
|
22981
|
-
relativePath:
|
|
23101
|
+
relativePath: join21("subagents", agentId),
|
|
22982
23102
|
kind: "dir",
|
|
22983
23103
|
hash: await hashPath(renderedDir)
|
|
22984
23104
|
};
|
|
@@ -23003,15 +23123,15 @@ function titleFromAgentId(agentId) {
|
|
|
23003
23123
|
}
|
|
23004
23124
|
|
|
23005
23125
|
// src/targets/plugins/claude.ts
|
|
23006
|
-
import { join as
|
|
23126
|
+
import { join as join23 } from "path";
|
|
23007
23127
|
|
|
23008
23128
|
// src/targets/plugins/common.ts
|
|
23009
23129
|
init_fs();
|
|
23010
|
-
import { readFile as
|
|
23011
|
-
import { join as
|
|
23130
|
+
import { readFile as readFile25 } from "fs/promises";
|
|
23131
|
+
import { join as join22 } from "path";
|
|
23012
23132
|
import { parseDocument } from "yaml";
|
|
23013
23133
|
function pluginStateRoot(request) {
|
|
23014
|
-
return
|
|
23134
|
+
return join22(
|
|
23015
23135
|
request.targetRoot,
|
|
23016
23136
|
".agentwheel",
|
|
23017
23137
|
"plugins",
|
|
@@ -23029,16 +23149,16 @@ function safeNameSegment(value) {
|
|
|
23029
23149
|
return normalized.length > 0 ? normalized : "unnamed";
|
|
23030
23150
|
}
|
|
23031
23151
|
async function jsonPluginName(root, relativeManifestPath, fallback) {
|
|
23032
|
-
const manifestPath =
|
|
23152
|
+
const manifestPath = join22(root, relativeManifestPath);
|
|
23033
23153
|
if (!await pathExists(manifestPath)) return fallback;
|
|
23034
|
-
const parsed = JSON.parse(await
|
|
23154
|
+
const parsed = JSON.parse(await readFile25(manifestPath, "utf8"));
|
|
23035
23155
|
return typeof parsed.name === "string" && parsed.name.trim().length > 0 ? parsed.name.trim() : fallback;
|
|
23036
23156
|
}
|
|
23037
23157
|
async function yamlPluginName(root, relativeManifestPaths, fallback) {
|
|
23038
23158
|
for (const relativeManifestPath of relativeManifestPaths) {
|
|
23039
|
-
const manifestPath =
|
|
23159
|
+
const manifestPath = join22(root, relativeManifestPath);
|
|
23040
23160
|
if (!await pathExists(manifestPath)) continue;
|
|
23041
|
-
const document = parseDocument(await
|
|
23161
|
+
const document = parseDocument(await readFile25(manifestPath, "utf8"));
|
|
23042
23162
|
const parsed = document.toJSON();
|
|
23043
23163
|
if (!isRecord5(parsed)) continue;
|
|
23044
23164
|
for (const key of ["name", "module", "package"]) {
|
|
@@ -23067,7 +23187,7 @@ async function claudePluginSpec(request) {
|
|
|
23067
23187
|
packageName: request.artifact.packageName,
|
|
23068
23188
|
installName: request.installName
|
|
23069
23189
|
});
|
|
23070
|
-
const marketplaceRoot =
|
|
23190
|
+
const marketplaceRoot = join23(stateRoot, "marketplace");
|
|
23071
23191
|
const scope = claudeScope(request.installationType);
|
|
23072
23192
|
const selector = `${pluginName}@${marketplaceName}`;
|
|
23073
23193
|
return {
|
|
@@ -23092,7 +23212,7 @@ function claudeScope(installationType) {
|
|
|
23092
23212
|
}
|
|
23093
23213
|
|
|
23094
23214
|
// src/targets/plugins/codex.ts
|
|
23095
|
-
import { join as
|
|
23215
|
+
import { join as join24 } from "path";
|
|
23096
23216
|
async function codexPluginSpec(request) {
|
|
23097
23217
|
const pluginName = await jsonPluginName(request.sourcePath, ".codex-plugin/plugin.json", request.installName);
|
|
23098
23218
|
const marketplaceName = agentwheelMarketplaceName(request.artifact.packageName, pluginName);
|
|
@@ -23103,7 +23223,7 @@ async function codexPluginSpec(request) {
|
|
|
23103
23223
|
packageName: request.artifact.packageName,
|
|
23104
23224
|
installName: request.installName
|
|
23105
23225
|
});
|
|
23106
|
-
const marketplaceRoot =
|
|
23226
|
+
const marketplaceRoot = join24(stateRoot, "marketplace");
|
|
23107
23227
|
const selector = `${pluginName}@${marketplaceName}`;
|
|
23108
23228
|
return {
|
|
23109
23229
|
runtime: "codex",
|
|
@@ -23122,7 +23242,7 @@ async function codexPluginSpec(request) {
|
|
|
23122
23242
|
}
|
|
23123
23243
|
|
|
23124
23244
|
// src/targets/plugins/copilot.ts
|
|
23125
|
-
import { join as
|
|
23245
|
+
import { join as join25 } from "path";
|
|
23126
23246
|
async function copilotPluginSpec(request) {
|
|
23127
23247
|
if (request.installationType !== "user") {
|
|
23128
23248
|
throw new Error("Copilot plugins are persistent user-level installs only; pass --installation-type user.");
|
|
@@ -23135,7 +23255,7 @@ async function copilotPluginSpec(request) {
|
|
|
23135
23255
|
packageName: request.artifact.packageName,
|
|
23136
23256
|
installName: request.installName
|
|
23137
23257
|
});
|
|
23138
|
-
const pluginRoot =
|
|
23258
|
+
const pluginRoot = join25(stateRoot, "plugin");
|
|
23139
23259
|
return {
|
|
23140
23260
|
runtime: "copilot",
|
|
23141
23261
|
pluginName,
|
|
@@ -23146,7 +23266,7 @@ async function copilotPluginSpec(request) {
|
|
|
23146
23266
|
}
|
|
23147
23267
|
|
|
23148
23268
|
// src/targets/plugins/hermes.ts
|
|
23149
|
-
import { join as
|
|
23269
|
+
import { join as join26 } from "path";
|
|
23150
23270
|
async function hermesPluginSpec(request) {
|
|
23151
23271
|
if (request.installationType !== "user") {
|
|
23152
23272
|
throw new Error("Hermes plugins are user-level installs only; pass --installation-type user.");
|
|
@@ -23159,7 +23279,7 @@ async function hermesPluginSpec(request) {
|
|
|
23159
23279
|
packageName: request.artifact.packageName,
|
|
23160
23280
|
installName: request.installName
|
|
23161
23281
|
});
|
|
23162
|
-
const repoRoot =
|
|
23282
|
+
const repoRoot = join26(stateRoot, "repo");
|
|
23163
23283
|
return {
|
|
23164
23284
|
runtime: "hermes",
|
|
23165
23285
|
pluginName,
|
|
@@ -23169,64 +23289,8 @@ async function hermesPluginSpec(request) {
|
|
|
23169
23289
|
};
|
|
23170
23290
|
}
|
|
23171
23291
|
|
|
23172
|
-
// src/targets/plugins/openclaw.ts
|
|
23173
|
-
init_fs();
|
|
23174
|
-
import { readFile as readFile25 } from "fs/promises";
|
|
23175
|
-
import { join as join26 } from "path";
|
|
23176
|
-
function openClawPluginInstallCommand(request) {
|
|
23177
|
-
return ["openclaw", "plugins", "install", "--force", request.path];
|
|
23178
|
-
}
|
|
23179
|
-
function openClawPluginUninstallCommand(pluginName) {
|
|
23180
|
-
return ["openclaw", "plugins", "uninstall", pluginName, "--force"];
|
|
23181
|
-
}
|
|
23182
|
-
async function openClawPluginSpec(request) {
|
|
23183
|
-
if (request.format === "openclaw-clawhub-plugin") {
|
|
23184
|
-
const metadata = await openClawClawHubPluginMetadata(request.path, request.fallbackPluginName);
|
|
23185
|
-
return {
|
|
23186
|
-
runtime: "openclaw",
|
|
23187
|
-
pluginName: metadata.pluginName,
|
|
23188
|
-
installCommands: [openClawPluginInstallCommand({ path: metadata.installSpec, dryRun: true })],
|
|
23189
|
-
uninstallCommands: [openClawPluginUninstallCommand(metadata.pluginName)]
|
|
23190
|
-
};
|
|
23191
|
-
}
|
|
23192
|
-
const pluginName = await openClawPluginName(request.path, request.fallbackPluginName);
|
|
23193
|
-
return {
|
|
23194
|
-
runtime: "openclaw",
|
|
23195
|
-
pluginName,
|
|
23196
|
-
installCommands: [openClawPluginInstallCommand({ path: request.path, dryRun: true })],
|
|
23197
|
-
uninstallCommands: [openClawPluginUninstallCommand(pluginName)]
|
|
23198
|
-
};
|
|
23199
|
-
}
|
|
23200
|
-
async function openClawPluginName(root, fallback) {
|
|
23201
|
-
for (const manifestName of ["plugin.json", "openclaw.plugin.json"]) {
|
|
23202
|
-
const manifestPath = join26(root, manifestName);
|
|
23203
|
-
if (!await pathExists(manifestPath)) continue;
|
|
23204
|
-
const parsed = JSON.parse(await readFile25(manifestPath, "utf8"));
|
|
23205
|
-
if (typeof parsed.name === "string" && parsed.name.trim().length > 0) return parsed.name.trim();
|
|
23206
|
-
}
|
|
23207
|
-
return fallback;
|
|
23208
|
-
}
|
|
23209
|
-
async function openClawClawHubPluginMetadata(root, fallback) {
|
|
23210
|
-
const metadataPath = join26(root, "clawhub.json");
|
|
23211
|
-
if (!await pathExists(metadataPath)) {
|
|
23212
|
-
throw new Error("OpenClaw ClawHub plugins must contain clawhub.json");
|
|
23213
|
-
}
|
|
23214
|
-
const parsed = JSON.parse(await readFile25(metadataPath, "utf8"));
|
|
23215
|
-
const installSpec = stringField(parsed.installSpec);
|
|
23216
|
-
if (!installSpec?.startsWith("clawhub:")) {
|
|
23217
|
-
throw new Error("OpenClaw ClawHub plugin metadata must declare installSpec starting with clawhub:");
|
|
23218
|
-
}
|
|
23219
|
-
const pluginName = stringField(parsed.runtimeId) ?? installNameFor(stringField(parsed.name) ?? fallback);
|
|
23220
|
-
return { installSpec, pluginName };
|
|
23221
|
-
}
|
|
23222
|
-
function stringField(value) {
|
|
23223
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
23224
|
-
}
|
|
23225
|
-
function installNameFor(value) {
|
|
23226
|
-
return value.split("/").at(-1).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "clawhub-plugin";
|
|
23227
|
-
}
|
|
23228
|
-
|
|
23229
23292
|
// src/targets/plugins/index.ts
|
|
23293
|
+
init_openclaw2();
|
|
23230
23294
|
async function semanticPluginSpecForArtifact(request) {
|
|
23231
23295
|
if (request.semantic === "openclaw-plugin") {
|
|
23232
23296
|
return openClawPluginSpec({
|
|
@@ -28570,6 +28634,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
|
|
|
28570
28634
|
if (!satisfiesVersionRange(fetched.version, requirement.version)) {
|
|
28571
28635
|
throw new Error(`Package ${fetched.name}@${fetched.version} does not satisfy requested version ${requirement.version}`);
|
|
28572
28636
|
}
|
|
28637
|
+
const requestedRef = frozen ? frozen.node.requestedRef : fetched.resolved.requestedRef;
|
|
28573
28638
|
const nodeKey = `${normalized.normalizedSource}\0${fetched.name}`;
|
|
28574
28639
|
let selectionImport = requirement.selection ? await resolveSelectionImport(fetched.resolved.resolvedPath, fetched.resolved.driver, requirement.selection) : void 0;
|
|
28575
28640
|
const selected = computeSelectedSelectors(
|
|
@@ -28596,7 +28661,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
|
|
|
28596
28661
|
source: fetched.resolved.source,
|
|
28597
28662
|
normalizedSource: normalized.normalizedSource,
|
|
28598
28663
|
driver: fetched.resolved.driver,
|
|
28599
|
-
requestedRef
|
|
28664
|
+
requestedRef,
|
|
28600
28665
|
resolvedCommit: fetched.resolved.resolvedCommit,
|
|
28601
28666
|
cacheIdentity: fetched.resolved.cacheIdentity,
|
|
28602
28667
|
sourceHash: fetched.sourceHash,
|
|
@@ -28654,7 +28719,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
|
|
|
28654
28719
|
alias: requirement.alias,
|
|
28655
28720
|
source: requirement.source,
|
|
28656
28721
|
normalizedSource: normalized.normalizedSource,
|
|
28657
|
-
requestedRef
|
|
28722
|
+
requestedRef,
|
|
28658
28723
|
version: requirement.version,
|
|
28659
28724
|
mode: requirement.mode,
|
|
28660
28725
|
optional: requirement.optional,
|