agentwheel 0.22.2 → 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 +609 -412
- 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,8 +18594,8 @@ 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
|
|
18516
|
-
import { posix as posix4, relative as relative7, resolve as resolve15, sep as sep5 } from "path";
|
|
18597
|
+
import { lstat as lstat3, readFile as readFile13, readlink, readdir as readdir5 } from "fs/promises";
|
|
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] });
|
|
18519
18601
|
if (probe.exitCode !== 0) return void 0;
|
|
@@ -18540,6 +18622,9 @@ async function assertGitPreflight(repository) {
|
|
|
18540
18622
|
}
|
|
18541
18623
|
}
|
|
18542
18624
|
async function assertHeadLease(repositoryRoot, expectedHead, head, paths, provider) {
|
|
18625
|
+
return assertHeadLeaseWithRecovery(repositoryRoot, expectedHead, head, paths, provider, []);
|
|
18626
|
+
}
|
|
18627
|
+
async function assertHeadLeaseWithRecovery(repositoryRoot, expectedHead, head, paths, provider, recoveryPaths, terminalChanges = /* @__PURE__ */ new Map()) {
|
|
18543
18628
|
if (head === expectedHead) return;
|
|
18544
18629
|
if (provider?.headLease !== "path-scoped" || paths.length === 0) {
|
|
18545
18630
|
throw new Error(`Git HEAD lease mismatch: expected ${expectedHead}, found ${head}.`);
|
|
@@ -18575,10 +18660,65 @@ async function assertHeadLease(repositoryRoot, expectedHead, head, paths, provid
|
|
|
18575
18660
|
"-z",
|
|
18576
18661
|
commit
|
|
18577
18662
|
])).stdout);
|
|
18578
|
-
|
|
18579
|
-
|
|
18663
|
+
for (const path of touched) {
|
|
18664
|
+
if (!protectedPaths.some((protectedPath) => overlaps(path, protectedPath))) continue;
|
|
18665
|
+
if (terminalChanges.get(commit)?.has(path)) continue;
|
|
18666
|
+
const proof = recoveryPaths.find((entry) => entry.path === path && paths.includes(path));
|
|
18667
|
+
if (!proof || overlaps(path, ".agentwheel/config.json") || overlaps(path, ".syncwheel/manifest.json") || await gitPathMode(repositoryRoot, commit, path) !== "100644" || await hashHeadPath(repositoryRoot, expectedHead, path) !== proof.beforeSha256 || await hashHeadPath(repositoryRoot, commit, path) !== proof.afterSha256 || await hashHeadPath(repositoryRoot, head, path) !== proof.afterSha256 || await hashWorkingPath(repositoryRoot, path) !== proof.afterSha256) {
|
|
18668
|
+
throw new Error(`Git HEAD lease overlaps protected paths in intervening commit ${commit}.`);
|
|
18669
|
+
}
|
|
18670
|
+
}
|
|
18671
|
+
}
|
|
18672
|
+
}
|
|
18673
|
+
function overlaps(left, right) {
|
|
18674
|
+
return left === right || left.startsWith(`${right}/`) || right.startsWith(`${left}/`);
|
|
18675
|
+
}
|
|
18676
|
+
async function committedRecoveryPaths(repositoryRoot, expectedHead, head, declarations, receiptPaths, provider) {
|
|
18677
|
+
await verifyRevisionPaths(repositoryRoot, expectedHead, receiptPaths);
|
|
18678
|
+
const committed = [];
|
|
18679
|
+
for (const entry of receiptPaths) {
|
|
18680
|
+
if (!declarations.includes(entry.path)) throw new Error(`Recovery path was not declared: ${entry.path}.`);
|
|
18681
|
+
if (await hashHeadPath(repositoryRoot, head, entry.path) === entry.afterSha256 && entry.beforeSha256 !== entry.afterSha256) {
|
|
18682
|
+
await assertRecoveryFileIdentity(repositoryRoot, expectedHead, head, entry.path);
|
|
18683
|
+
committed.push(entry);
|
|
18580
18684
|
}
|
|
18581
18685
|
}
|
|
18686
|
+
await assertHeadLeaseWithRecovery(repositoryRoot, expectedHead, head, declarations, provider, committed);
|
|
18687
|
+
return committed;
|
|
18688
|
+
}
|
|
18689
|
+
async function verifyCompletedRecoveryPaths(repositoryRoot, expectedHead, declarations, savedPaths, provider, productCommitSha, productPaths, controlCommitSha) {
|
|
18690
|
+
const head = await currentHead(repositoryRoot);
|
|
18691
|
+
await verifyRevisionPaths(repositoryRoot, expectedHead, savedPaths);
|
|
18692
|
+
for (const entry of savedPaths) {
|
|
18693
|
+
await assertRecoveryFileIdentity(repositoryRoot, expectedHead, head, entry.path);
|
|
18694
|
+
if (await hashHeadPath(repositoryRoot, head, entry.path) !== entry.afterSha256) {
|
|
18695
|
+
throw new Error(`Committed recovery path changed during provider completion: ${entry.path}.`);
|
|
18696
|
+
}
|
|
18697
|
+
}
|
|
18698
|
+
const terminalChanges = /* @__PURE__ */ new Map();
|
|
18699
|
+
if (productCommitSha) terminalChanges.set(productCommitSha, new Set(productPaths));
|
|
18700
|
+
if (controlCommitSha) terminalChanges.set(controlCommitSha, /* @__PURE__ */ new Set([".syncwheel/manifest.json"]));
|
|
18701
|
+
await assertHeadLeaseWithRecovery(repositoryRoot, expectedHead, head, declarations, provider, savedPaths, terminalChanges);
|
|
18702
|
+
}
|
|
18703
|
+
async function gitPathMode(repositoryRoot, head, path) {
|
|
18704
|
+
const tree = (await runProcess("git", ["-C", repositoryRoot, "ls-tree", "-z", head, "--", path])).stdout.toString("utf8");
|
|
18705
|
+
const entry = tree.split("\0").find((value) => value.slice(value.indexOf(" ") + 1) === path);
|
|
18706
|
+
return entry?.split(" ")[0];
|
|
18707
|
+
}
|
|
18708
|
+
async function assertRecoveryFileIdentity(repositoryRoot, expectedHead, head, path) {
|
|
18709
|
+
if (await gitPathMode(repositoryRoot, expectedHead, path) !== "100644" || await gitPathMode(repositoryRoot, head, path) !== "100644") {
|
|
18710
|
+
throw new Error(`Recovery requires an existing regular non-executable Git file: ${path}.`);
|
|
18711
|
+
}
|
|
18712
|
+
const absolute = resolve15(repositoryRoot, ...path.split("/"));
|
|
18713
|
+
const stats = await lstat3(absolute);
|
|
18714
|
+
if (!stats.isFile() || (stats.mode & 73) !== 0) throw new Error(`Recovery file identity changed: ${path}.`);
|
|
18715
|
+
let ancestor = dirname10(absolute);
|
|
18716
|
+
while (true) {
|
|
18717
|
+
if ((await lstat3(ancestor)).isSymbolicLink()) throw new Error(`Recovery symlink ancestor is unsupported: ${path}.`);
|
|
18718
|
+
const parent = dirname10(ancestor);
|
|
18719
|
+
if (parent === ancestor) break;
|
|
18720
|
+
ancestor = parent;
|
|
18721
|
+
}
|
|
18582
18722
|
}
|
|
18583
18723
|
function isAgentwheelWritablePath(path) {
|
|
18584
18724
|
return /^\.agentwheel(?:\/|$)/u.test(path) || /^profiles\/[^/]+\/\.agentwheel(?:\/|$)/u.test(path);
|
|
@@ -18661,7 +18801,7 @@ async function hashWorkingPath(repositoryRoot, path) {
|
|
|
18661
18801
|
throw error46;
|
|
18662
18802
|
}
|
|
18663
18803
|
if (stats.isSymbolicLink()) return sha256(Buffer.from(await readlink(absolute), "utf8"));
|
|
18664
|
-
if (stats.isFile()) return sha256(await
|
|
18804
|
+
if (stats.isFile()) return sha256(await readFile13(absolute));
|
|
18665
18805
|
if (stats.isDirectory()) return hashDirectory(absolute);
|
|
18666
18806
|
throw new Error(`Unsupported repository path kind: ${path}`);
|
|
18667
18807
|
}
|
|
@@ -18674,7 +18814,7 @@ async function hashDirectory(root) {
|
|
|
18674
18814
|
const relativePath = normalizeRepoPath(relative7(root, absolute));
|
|
18675
18815
|
if (entry.isDirectory()) await walk2(absolute);
|
|
18676
18816
|
else if (entry.isSymbolicLink()) hash3.update(relativePath).update("\0").update(await readlink(absolute)).update("\0");
|
|
18677
|
-
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");
|
|
18678
18818
|
}
|
|
18679
18819
|
}
|
|
18680
18820
|
await walk2(root);
|
|
@@ -18710,9 +18850,9 @@ var init_repository = __esm({
|
|
|
18710
18850
|
|
|
18711
18851
|
// src/mutation/providers.ts
|
|
18712
18852
|
import { createHash as createHash9 } from "crypto";
|
|
18713
|
-
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";
|
|
18714
18854
|
import { tmpdir as tmpdir2 } from "os";
|
|
18715
|
-
import { isAbsolute as isAbsolute11, join as
|
|
18855
|
+
import { isAbsolute as isAbsolute11, join as join14, resolve as resolve16 } from "path";
|
|
18716
18856
|
function revisionProviderRejection(error46) {
|
|
18717
18857
|
return error46 instanceof RevisionProviderRejectedError ? error46.response : void 0;
|
|
18718
18858
|
}
|
|
@@ -18821,8 +18961,8 @@ async function openImmutableExecutableSnapshot(bytes) {
|
|
|
18821
18961
|
`Command revision providers require an unlinked immutable executable snapshot, which is unsupported on ${process.platform}.`
|
|
18822
18962
|
);
|
|
18823
18963
|
}
|
|
18824
|
-
const root = await mkdtemp(
|
|
18825
|
-
const path =
|
|
18964
|
+
const root = await mkdtemp(join14(tmpdir2(), "agentwheel-revision-command-"));
|
|
18965
|
+
const path = join14(root, "entrypoint");
|
|
18826
18966
|
let snapshot;
|
|
18827
18967
|
try {
|
|
18828
18968
|
await chmod2(root, 448);
|
|
@@ -18976,8 +19116,8 @@ async function finalizeGit(providerId, request, config2) {
|
|
|
18976
19116
|
const indexLease = await captureIndexLease(request.repositoryRoot);
|
|
18977
19117
|
await assertIndexTree(request.repositoryRoot, repository.head);
|
|
18978
19118
|
const hookBaseline = await snapshotRepository(request.repositoryRoot);
|
|
18979
|
-
const tempRoot = await mkdtemp(
|
|
18980
|
-
const indexPath =
|
|
19119
|
+
const tempRoot = await mkdtemp(join14(tmpdir2(), "agentwheel-git-index-"));
|
|
19120
|
+
const indexPath = join14(tempRoot, "index");
|
|
18981
19121
|
const env2 = { ...process.env, GIT_INDEX_FILE: indexPath };
|
|
18982
19122
|
let commitSha;
|
|
18983
19123
|
try {
|
|
@@ -18988,14 +19128,14 @@ async function finalizeGit(providerId, request, config2) {
|
|
|
18988
19128
|
await verifyTemporaryIndexPaths(request, env2);
|
|
18989
19129
|
await runProcess("git", ["-C", request.repositoryRoot, "diff", "--cached", "--check"], { env: env2 });
|
|
18990
19130
|
const tree = (await runProcess("git", ["-C", request.repositoryRoot, "write-tree"], { env: env2 })).stdout.toString("utf8").trim();
|
|
18991
|
-
const messagePath =
|
|
19131
|
+
const messagePath = join14(tempRoot, "COMMIT_EDITMSG");
|
|
18992
19132
|
await writeFile7(messagePath, commitMessage(request, planDigest), { encoding: "utf8", mode: 384 });
|
|
18993
19133
|
await runCommitHooks(request, env2, messagePath);
|
|
18994
19134
|
assertRepositorySnapshotEqual(hookBaseline, await snapshotRepository(request.repositoryRoot), "Git commit hooks");
|
|
18995
19135
|
const stagedAfterHooks = splitNull2((await runProcess("git", ["-C", request.repositoryRoot, "diff", "--cached", "--name-only", "-z"], { env: env2 })).stdout);
|
|
18996
19136
|
assertExactSet(stagedAfterHooks, request.paths.map((entry) => entry.path), "temporary Git index after hooks");
|
|
18997
19137
|
await verifyTemporaryIndexPaths(request, env2);
|
|
18998
|
-
const message = await
|
|
19138
|
+
const message = await readFile14(messagePath, "utf8");
|
|
18999
19139
|
assertCommitMessageContract(message, request, planDigest);
|
|
19000
19140
|
commitSha = (await runProcess("git", ["-C", request.repositoryRoot, "commit-tree", tree, "-p", repository.head], {
|
|
19001
19141
|
env: env2,
|
|
@@ -19114,7 +19254,7 @@ async function captureIndexLease(repositoryRoot) {
|
|
|
19114
19254
|
const rawPath = (await runProcess("git", ["-C", repositoryRoot, "rev-parse", "--git-path", "index"])).stdout.toString("utf8").trim();
|
|
19115
19255
|
const path = isAbsolute11(rawPath) ? rawPath : resolve16(repositoryRoot, rawPath);
|
|
19116
19256
|
try {
|
|
19117
|
-
const [content, info] = await Promise.all([
|
|
19257
|
+
const [content, info] = await Promise.all([readFile14(path), stat3(path)]);
|
|
19118
19258
|
return { path, sha256: sha2562(content), mode: info.mode & 511 };
|
|
19119
19259
|
} catch (error46) {
|
|
19120
19260
|
if (isMissing4(error46)) return { path, sha256: null, mode: 384 };
|
|
@@ -19122,15 +19262,15 @@ async function captureIndexLease(repositoryRoot) {
|
|
|
19122
19262
|
}
|
|
19123
19263
|
}
|
|
19124
19264
|
async function replaceIndexCas(repositoryRoot, lease, commitSha) {
|
|
19125
|
-
const tempRoot = await mkdtemp(
|
|
19126
|
-
const replacementPath =
|
|
19265
|
+
const tempRoot = await mkdtemp(join14(tmpdir2(), "agentwheel-index-replacement-"));
|
|
19266
|
+
const replacementPath = join14(tempRoot, "index");
|
|
19127
19267
|
const lockPath = `${lease.path}.lock`;
|
|
19128
19268
|
let handle;
|
|
19129
19269
|
try {
|
|
19130
19270
|
await runProcess("git", ["-C", repositoryRoot, "read-tree", commitSha], {
|
|
19131
19271
|
env: { ...process.env, GIT_INDEX_FILE: replacementPath }
|
|
19132
19272
|
});
|
|
19133
|
-
const replacement = await
|
|
19273
|
+
const replacement = await readFile14(replacementPath);
|
|
19134
19274
|
handle = await open3(lockPath, "wx", lease.mode);
|
|
19135
19275
|
const current = await readOptionalFile(lease.path);
|
|
19136
19276
|
const currentSha256 = current ? sha2562(current) : null;
|
|
@@ -19172,7 +19312,7 @@ async function hashGitObject(repositoryRoot, spec) {
|
|
|
19172
19312
|
}
|
|
19173
19313
|
async function readOptionalFile(path) {
|
|
19174
19314
|
try {
|
|
19175
|
-
return await
|
|
19315
|
+
return await readFile14(path);
|
|
19176
19316
|
} catch (error46) {
|
|
19177
19317
|
if (isMissing4(error46)) return null;
|
|
19178
19318
|
throw error46;
|
|
@@ -19279,7 +19419,7 @@ var init_providers = __esm({
|
|
|
19279
19419
|
// src/mutation/coordinator.ts
|
|
19280
19420
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
19281
19421
|
import { homedir as homedir6 } from "os";
|
|
19282
|
-
import { dirname as
|
|
19422
|
+
import { dirname as dirname11, isAbsolute as isAbsolute12, relative as relative8, resolve as resolve17, sep as sep6 } from "path";
|
|
19283
19423
|
function dirtyRepositoryPaths(repositoryRoot, baseline, paths) {
|
|
19284
19424
|
const conflicts = /* @__PURE__ */ new Set();
|
|
19285
19425
|
for (const path of paths) {
|
|
@@ -19353,12 +19493,15 @@ async function resumeMutation(operationId, action) {
|
|
|
19353
19493
|
);
|
|
19354
19494
|
receipt = await updateMutationReceipt(receipt, { paths, status: "mutation-applied" });
|
|
19355
19495
|
}
|
|
19356
|
-
await
|
|
19496
|
+
const request = action === "recover" && receipt.runtimeJournals.length > 0 ? await recoveryProviderRequest(receipt, paths) : providerRequest(receipt, action, paths);
|
|
19497
|
+
await invokeRevisionProvider(provider, revisionProviderRequestSchema.parse({ ...request, action: "preflight" }), {
|
|
19357
19498
|
workspaceRoot: receipt.workspaceRoot
|
|
19358
19499
|
});
|
|
19359
|
-
|
|
19500
|
+
if (action === "recover") await verifyRecoveryProjection(receipt, request);
|
|
19501
|
+
const response = await invokeRevisionProvider(provider, request, {
|
|
19360
19502
|
workspaceRoot: receipt.workspaceRoot
|
|
19361
19503
|
});
|
|
19504
|
+
await verifyCompletedRecoveryProjection(receipt, request, response);
|
|
19362
19505
|
return updateMutationReceipt(receipt, {
|
|
19363
19506
|
status: receiptStatusForProvider(response.status),
|
|
19364
19507
|
providerResponse: response,
|
|
@@ -19401,17 +19544,19 @@ async function recoverMutationRuntime(operationId, options = {}) {
|
|
|
19401
19544
|
`Mutation '${receipt.operationId}' repository HEAD lease changed before runtime recovery.`
|
|
19402
19545
|
);
|
|
19403
19546
|
}
|
|
19404
|
-
await assertHeadLease(
|
|
19547
|
+
if (receipt.noCommit) await assertHeadLease(receipt.repositoryRoot, receipt.expectedHead, repository.head, [], receipt.provider);
|
|
19548
|
+
else await committedRecoveryPaths(
|
|
19405
19549
|
receipt.repositoryRoot,
|
|
19406
19550
|
receipt.expectedHead,
|
|
19407
19551
|
repository.head,
|
|
19408
|
-
|
|
19552
|
+
declarations,
|
|
19553
|
+
receipt.paths,
|
|
19409
19554
|
receipt.provider
|
|
19410
19555
|
);
|
|
19411
19556
|
await assertGitPreflight(repository);
|
|
19412
19557
|
await collectIntroducedPaths(receipt.repositoryRoot, receipt.expectedHead, baseline, declarations);
|
|
19413
19558
|
}
|
|
19414
|
-
mutation = GovernedMutation.activateExisting(receipt, baseline, lock);
|
|
19559
|
+
mutation = GovernedMutation.activateExisting(receipt, baseline, lock, options.beforeProviderCompletion);
|
|
19415
19560
|
const [{ recoverPendingApply: recoverPendingApply2 }, { readLinkedLocalApplyJournal: readLinkedLocalApplyJournal2 }] = await Promise.all([
|
|
19416
19561
|
Promise.resolve().then(() => (init_apply(), apply_exports)),
|
|
19417
19562
|
Promise.resolve().then(() => (init_transaction(), transaction_exports))
|
|
@@ -19523,7 +19668,7 @@ async function mutationPolicyForWorkspace(workspaceRoot, globalRoot = homedir6()
|
|
|
19523
19668
|
const globalConfig2 = await readWorkspaceConfig(globalRoot);
|
|
19524
19669
|
const global = globalConfig2.schemaVersion === 4 ? globalConfig2.mutationPolicy : void 0;
|
|
19525
19670
|
let existingRoot = resolve17(workspaceRoot);
|
|
19526
|
-
while (!await pathExists(existingRoot) &&
|
|
19671
|
+
while (!await pathExists(existingRoot) && dirname11(existingRoot) !== existingRoot) existingRoot = dirname11(existingRoot);
|
|
19527
19672
|
const owner = await resolveWorkspaceOwnershipScope(existingRoot, { globalRoot });
|
|
19528
19673
|
const fleetConfig = owner.fleetId ? await readWorkspaceConfig(owner.root) : void 0;
|
|
19529
19674
|
const fleet = fleetConfig?.schemaVersion === 4 ? fleetConfig.mutationPolicy : void 0;
|
|
@@ -19545,6 +19690,50 @@ function mergeMutationPolicies(global, scoped) {
|
|
|
19545
19690
|
revisioning
|
|
19546
19691
|
});
|
|
19547
19692
|
}
|
|
19693
|
+
async function recoveryProviderRequest(receipt, paths) {
|
|
19694
|
+
const request = providerRequest(receipt, "recover", paths);
|
|
19695
|
+
if (receipt.noCommit) return request;
|
|
19696
|
+
const head = await currentHead(request.repositoryRoot);
|
|
19697
|
+
const committed = await committedRecoveryPaths(
|
|
19698
|
+
request.repositoryRoot,
|
|
19699
|
+
request.expectedHead,
|
|
19700
|
+
head,
|
|
19701
|
+
readMutationPathDeclarations(receipt.operationId),
|
|
19702
|
+
paths,
|
|
19703
|
+
receipt.provider
|
|
19704
|
+
);
|
|
19705
|
+
if (committed.length === 0) return request;
|
|
19706
|
+
const saved = new Set(committed.map((entry) => entry.path));
|
|
19707
|
+
return revisionProviderRequestSchema.parse({
|
|
19708
|
+
...request,
|
|
19709
|
+
expectedHead: head,
|
|
19710
|
+
paths: paths.filter((entry) => !saved.has(entry.path))
|
|
19711
|
+
});
|
|
19712
|
+
}
|
|
19713
|
+
async function verifyCompletedRecoveryProjection(receipt, request, response) {
|
|
19714
|
+
if (request.expectedHead === receipt.expectedHead) return;
|
|
19715
|
+
if (response.action !== "recover" && response.action !== "finalize") throw new Error("Recovery requires a terminal provider response.");
|
|
19716
|
+
const remaining = new Set(request.paths.map((entry) => entry.path));
|
|
19717
|
+
await verifyCompletedRecoveryPaths(
|
|
19718
|
+
request.repositoryRoot,
|
|
19719
|
+
receipt.expectedHead,
|
|
19720
|
+
readMutationPathDeclarations(receipt.operationId),
|
|
19721
|
+
receipt.paths.filter((entry) => !remaining.has(entry.path)),
|
|
19722
|
+
receipt.provider,
|
|
19723
|
+
response.productCommitSha,
|
|
19724
|
+
request.paths.map((entry) => entry.path),
|
|
19725
|
+
response.controlCommitSha
|
|
19726
|
+
);
|
|
19727
|
+
}
|
|
19728
|
+
async function verifyRecoveryProjection(receipt, request) {
|
|
19729
|
+
if (request.expectedHead === receipt.expectedHead) return;
|
|
19730
|
+
if (await currentHead(request.repositoryRoot) !== request.expectedHead) throw new Error("Recovery projection HEAD changed.");
|
|
19731
|
+
const verified = await recoveryProviderRequest(receipt, receipt.paths);
|
|
19732
|
+
if (JSON.stringify(verified) !== JSON.stringify(request)) throw new Error("Recovery projection changed before provider completion.");
|
|
19733
|
+
const repository = await discoverGitRepository(request.repositoryRoot);
|
|
19734
|
+
if (!repository) throw new Error("Recovery repository disappeared.");
|
|
19735
|
+
await assertGitPreflight(repository);
|
|
19736
|
+
}
|
|
19548
19737
|
function providerRequest(receipt, action, paths) {
|
|
19549
19738
|
if (!receipt.repositoryRoot || !receipt.expectedHead || !receipt.provider) {
|
|
19550
19739
|
throw new Error(`Mutation '${receipt.operationId}' is missing revision provider request state.`);
|
|
@@ -19614,17 +19803,21 @@ var init_coordinator = __esm({
|
|
|
19614
19803
|
init_repository();
|
|
19615
19804
|
init_session_ownership();
|
|
19616
19805
|
GovernedMutation = class _GovernedMutation {
|
|
19617
|
-
constructor(policy, receipt, baseline, lock) {
|
|
19806
|
+
constructor(policy, receipt, baseline, lock, runtimeRecovery = false, beforeProviderCompletion) {
|
|
19618
19807
|
this.policy = policy;
|
|
19619
19808
|
this.receipt = receipt;
|
|
19620
19809
|
this.baseline = baseline;
|
|
19621
19810
|
this.lock = lock;
|
|
19811
|
+
this.runtimeRecovery = runtimeRecovery;
|
|
19812
|
+
this.beforeProviderCompletion = beforeProviderCompletion;
|
|
19622
19813
|
this.operationId = receipt.operationId;
|
|
19623
19814
|
}
|
|
19624
19815
|
policy;
|
|
19625
19816
|
receipt;
|
|
19626
19817
|
baseline;
|
|
19627
19818
|
lock;
|
|
19819
|
+
runtimeRecovery;
|
|
19820
|
+
beforeProviderCompletion;
|
|
19628
19821
|
operationId;
|
|
19629
19822
|
closed = false;
|
|
19630
19823
|
static async begin(options) {
|
|
@@ -19730,7 +19923,7 @@ var init_coordinator = __esm({
|
|
|
19730
19923
|
);
|
|
19731
19924
|
}
|
|
19732
19925
|
this.receipt = await updateMutationReceipt(this.receipt, { status: "handler-succeeded" });
|
|
19733
|
-
paths = await this.collectPaths();
|
|
19926
|
+
paths = await this.collectPaths(action === "recover" && this.runtimeRecovery);
|
|
19734
19927
|
this.receipt = await updateMutationReceipt(this.receipt, { paths, status: "mutation-applied" });
|
|
19735
19928
|
} catch (error46) {
|
|
19736
19929
|
this.receipt = await updateMutationReceipt(this.receipt, {
|
|
@@ -19748,12 +19941,16 @@ var init_coordinator = __esm({
|
|
|
19748
19941
|
return this.receipt;
|
|
19749
19942
|
}
|
|
19750
19943
|
const provider = this.policy.revisioning.provider;
|
|
19751
|
-
await
|
|
19944
|
+
const request = this.runtimeRecovery && action === "recover" ? await recoveryProviderRequest(this.receipt, paths) : providerRequest(this.receipt, action, paths);
|
|
19945
|
+
await invokeRevisionProvider(provider, revisionProviderRequestSchema.parse({ ...request, action: "preflight" }), {
|
|
19752
19946
|
workspaceRoot: this.receipt.workspaceRoot
|
|
19753
19947
|
});
|
|
19754
|
-
|
|
19948
|
+
if (this.runtimeRecovery) await verifyRecoveryProjection(this.receipt, request);
|
|
19949
|
+
await this.beforeProviderCompletion?.();
|
|
19950
|
+
const response = await invokeRevisionProvider(provider, request, {
|
|
19755
19951
|
workspaceRoot: this.receipt.workspaceRoot
|
|
19756
19952
|
});
|
|
19953
|
+
await verifyCompletedRecoveryProjection(this.receipt, request, response);
|
|
19757
19954
|
this.receipt = await updateMutationReceipt(this.receipt, {
|
|
19758
19955
|
status: receiptStatusForProvider(response.status),
|
|
19759
19956
|
providerResponse: response
|
|
@@ -19813,7 +20010,7 @@ var init_coordinator = __esm({
|
|
|
19813
20010
|
const runtimeJournals = upsertRuntimeJournal(this.receipt.runtimeJournals, existing, status);
|
|
19814
20011
|
this.receipt = await updateMutationReceipt(this.receipt, { runtimeJournals });
|
|
19815
20012
|
}
|
|
19816
|
-
static activateExisting(receipt, baseline, lock) {
|
|
20013
|
+
static activateExisting(receipt, baseline, lock, beforeProviderCompletion) {
|
|
19817
20014
|
if (receipt.revisionMode === "commit-after-verify" && !receipt.provider) {
|
|
19818
20015
|
throw new Error(`Mutation '${receipt.operationId}' is missing its revision provider recovery policy.`);
|
|
19819
20016
|
}
|
|
@@ -19831,24 +20028,41 @@ var init_coordinator = __esm({
|
|
|
19831
20028
|
journal: "required",
|
|
19832
20029
|
revisioning: { mode: "off" }
|
|
19833
20030
|
});
|
|
19834
|
-
const mutation = new _GovernedMutation(policy, receipt, baseline, lock);
|
|
20031
|
+
const mutation = new _GovernedMutation(policy, receipt, baseline, lock, true, beforeProviderCompletion);
|
|
19835
20032
|
activeMutation = mutation;
|
|
19836
20033
|
return mutation;
|
|
19837
20034
|
}
|
|
19838
|
-
async collectPaths() {
|
|
20035
|
+
async collectPaths(recover = false) {
|
|
19839
20036
|
if (!this.receipt.repositoryRoot || !this.receipt.expectedHead || !this.baseline) return [];
|
|
19840
20037
|
const declarations = [.../* @__PURE__ */ new Set([
|
|
19841
20038
|
...declaredMutationPaths(),
|
|
19842
20039
|
...readMutationPathDeclarations(this.receipt.operationId)
|
|
19843
20040
|
])].sort((a, b) => a.localeCompare(b));
|
|
19844
|
-
|
|
20041
|
+
const head = await currentHead(this.receipt.repositoryRoot);
|
|
20042
|
+
const committed = recover && !this.receipt.noCommit ? await committedRecoveryPaths(
|
|
19845
20043
|
this.receipt.repositoryRoot,
|
|
19846
20044
|
this.receipt.expectedHead,
|
|
19847
|
-
|
|
20045
|
+
head,
|
|
20046
|
+
declarations,
|
|
20047
|
+
this.receipt.paths,
|
|
20048
|
+
this.receipt.provider
|
|
20049
|
+
) : [];
|
|
20050
|
+
if (this.receipt.provider && !recover) await assertHeadLease(
|
|
20051
|
+
this.receipt.repositoryRoot,
|
|
20052
|
+
this.receipt.expectedHead,
|
|
20053
|
+
head,
|
|
19848
20054
|
this.receipt.noCommit ? [] : declarations,
|
|
19849
20055
|
this.receipt.provider
|
|
19850
20056
|
);
|
|
19851
|
-
|
|
20057
|
+
if (recover && this.receipt.noCommit) await assertHeadLease(
|
|
20058
|
+
this.receipt.repositoryRoot,
|
|
20059
|
+
this.receipt.expectedHead,
|
|
20060
|
+
head,
|
|
20061
|
+
[],
|
|
20062
|
+
this.receipt.provider
|
|
20063
|
+
);
|
|
20064
|
+
const introduced = await collectIntroducedPaths(this.receipt.repositoryRoot, this.receipt.expectedHead, this.baseline, declarations);
|
|
20065
|
+
return [...committed, ...introduced].sort((a, b) => a.path.localeCompare(b.path));
|
|
19852
20066
|
}
|
|
19853
20067
|
async close() {
|
|
19854
20068
|
if (this.closed) return;
|
|
@@ -19863,13 +20077,13 @@ var init_coordinator = __esm({
|
|
|
19863
20077
|
|
|
19864
20078
|
// src/transport/ownership-snapshot.ts
|
|
19865
20079
|
import { createHash as createHash10 } from "crypto";
|
|
19866
|
-
import { lstat as lstat4, readdir as readdir6, readFile as
|
|
19867
|
-
import { dirname 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";
|
|
19868
20082
|
async function assertSnapshotAncestors(path) {
|
|
19869
20083
|
let current = resolve18(path);
|
|
19870
20084
|
while (true) {
|
|
19871
20085
|
if ((await lstat4(current)).isSymbolicLink()) throw new Error(`Symlink path is unsupported: ${current}`);
|
|
19872
|
-
const parent =
|
|
20086
|
+
const parent = dirname12(current);
|
|
19873
20087
|
if (parent === current) return;
|
|
19874
20088
|
current = parent;
|
|
19875
20089
|
}
|
|
@@ -19884,9 +20098,9 @@ async function ownershipRuntimeSnapshot(path) {
|
|
|
19884
20098
|
}
|
|
19885
20099
|
hash3.update(JSON.stringify([relative9(path, candidate), info.isDirectory() ? "dir" : "file", info.mode & 4095]));
|
|
19886
20100
|
if (info.isDirectory()) {
|
|
19887
|
-
for (const name of (await readdir6(candidate)).sort()) await visit2(
|
|
20101
|
+
for (const name of (await readdir6(candidate)).sort()) await visit2(join15(candidate, name));
|
|
19888
20102
|
} else {
|
|
19889
|
-
const content = await
|
|
20103
|
+
const content = await readFile15(candidate);
|
|
19890
20104
|
hash3.update(String(content.length)).update("\0").update(content);
|
|
19891
20105
|
}
|
|
19892
20106
|
}
|
|
@@ -19935,7 +20149,7 @@ __export(transaction_exports, {
|
|
|
19935
20149
|
});
|
|
19936
20150
|
import { createHash as createHash11 } from "crypto";
|
|
19937
20151
|
import { cp as cp2, lstat as lstat5, mkdir as mkdir7, open as open4, rm as rm5, stat as stat4 } from "fs/promises";
|
|
19938
|
-
import { dirname as
|
|
20152
|
+
import { dirname as dirname13, join as join16, relative as relative10, resolve as resolve19, sep as sep7 } from "path";
|
|
19939
20153
|
async function assertNoSymlinkPath2(path) {
|
|
19940
20154
|
const absolute = resolve19(path);
|
|
19941
20155
|
let current = absolute;
|
|
@@ -19945,7 +20159,7 @@ async function assertNoSymlinkPath2(path) {
|
|
|
19945
20159
|
} catch (error46) {
|
|
19946
20160
|
if (error46.code !== "ENOENT") throw error46;
|
|
19947
20161
|
}
|
|
19948
|
-
const parent =
|
|
20162
|
+
const parent = dirname13(current);
|
|
19949
20163
|
if (parent === current) break;
|
|
19950
20164
|
current = parent;
|
|
19951
20165
|
}
|
|
@@ -19998,7 +20212,7 @@ function metadataAuditPath(audit, path) {
|
|
|
19998
20212
|
if (resolve19(audit.workspaceRoot) !== audit.workspaceRoot || path !== `.agentwheel/${audit.kind === "ownership-handoff" ? "ownership-handoffs" : "ownership-releases"}/${audit.operationId}.json`) {
|
|
19999
20213
|
throw new Error("Invalid ownership release audit path.");
|
|
20000
20214
|
}
|
|
20001
|
-
return
|
|
20215
|
+
return join16(audit.workspaceRoot, ...path.split("/"));
|
|
20002
20216
|
}
|
|
20003
20217
|
function metadataRuntimePath(root, path) {
|
|
20004
20218
|
const result = resolve19(root, path);
|
|
@@ -20016,7 +20230,7 @@ async function syncMetadataPath(path, directoryOnly = false) {
|
|
|
20016
20230
|
await file2.close();
|
|
20017
20231
|
}
|
|
20018
20232
|
}
|
|
20019
|
-
const directory = await open4(directoryOnly ? path :
|
|
20233
|
+
const directory = await open4(directoryOnly ? path : dirname13(path), "r");
|
|
20020
20234
|
try {
|
|
20021
20235
|
await directory.sync();
|
|
20022
20236
|
} finally {
|
|
@@ -20025,19 +20239,19 @@ async function syncMetadataPath(path, directoryOnly = false) {
|
|
|
20025
20239
|
}
|
|
20026
20240
|
function applyLockPath(targetRoot, adapter, scope = {}) {
|
|
20027
20241
|
const installationType = scope.installationType ?? "local";
|
|
20028
|
-
return
|
|
20242
|
+
return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, { installationType })}.runtime-apply-lock`);
|
|
20029
20243
|
}
|
|
20030
20244
|
function applyJournalPath(targetRoot, adapter, scope = {}) {
|
|
20031
|
-
return
|
|
20245
|
+
return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.apply-journal.json`);
|
|
20032
20246
|
}
|
|
20033
20247
|
function applyBackupDir(targetRoot, adapter, scope = {}) {
|
|
20034
|
-
return
|
|
20248
|
+
return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.apply-backups`);
|
|
20035
20249
|
}
|
|
20036
20250
|
async function acquireApplyLock(targetRoot, adapter, transport = localTransport, options = {}, scope = {}) {
|
|
20037
20251
|
assertGovernedRuntimeTransportSupported(transport);
|
|
20038
20252
|
if (transport.kind === "local-run-as") await transport.prepareApply();
|
|
20039
20253
|
const lockPath = applyLockPath(targetRoot, adapter, scope);
|
|
20040
|
-
const ownerPath =
|
|
20254
|
+
const ownerPath = join16(lockPath, "owner.json");
|
|
20041
20255
|
const metadata = {
|
|
20042
20256
|
pid: process.pid,
|
|
20043
20257
|
adapter,
|
|
@@ -20106,7 +20320,7 @@ async function listApplyJournals(targetRoot, adapter, transport = localTransport
|
|
|
20106
20320
|
const found = [];
|
|
20107
20321
|
for (const fileName of await transport.listDir(metadataDir(targetRoot))) {
|
|
20108
20322
|
if (!fileName.endsWith(suffix)) continue;
|
|
20109
|
-
const path =
|
|
20323
|
+
const path = join16(metadataDir(targetRoot), fileName);
|
|
20110
20324
|
const journal = parseApplyJournal(JSON.parse(await transport.readFile(path)));
|
|
20111
20325
|
if (journal.adapter !== adapter || (journal.installationType ?? "local") !== installationType) continue;
|
|
20112
20326
|
found.push({ path, journal });
|
|
@@ -20118,7 +20332,7 @@ async function listAllApplyJournals(targetRoot, adapter, transport = localTransp
|
|
|
20118
20332
|
const found = [];
|
|
20119
20333
|
for (const fileName of await transport.listDir(metadataDir(targetRoot))) {
|
|
20120
20334
|
if (!fileName.endsWith(suffix)) continue;
|
|
20121
|
-
const path =
|
|
20335
|
+
const path = join16(metadataDir(targetRoot), fileName);
|
|
20122
20336
|
const journal = parseApplyJournal(JSON.parse(await transport.readFile(path)));
|
|
20123
20337
|
if (adapter === void 0 || journal.adapter === adapter) found.push({ path, journal });
|
|
20124
20338
|
}
|
|
@@ -20166,7 +20380,7 @@ async function removeApplyJournal(targetRoot, adapter, transport = localTranspor
|
|
|
20166
20380
|
if (existing?.mutation) await beginResolveMutationRuntimeJournal(existing.mutation.operationId, path);
|
|
20167
20381
|
await transport.rm(applyJournalPath(targetRoot, adapter, scope));
|
|
20168
20382
|
await transport.rm(applyBackupDir(targetRoot, adapter, scope));
|
|
20169
|
-
if ((existing?.metadataAudit || existing?.metadataGuards) && transport.kind === "local") await syncMetadataPath(
|
|
20383
|
+
if ((existing?.metadataAudit || existing?.metadataGuards) && transport.kind === "local") await syncMetadataPath(dirname13(path), true);
|
|
20170
20384
|
if (existing?.mutation) await resolveMutationRuntimeJournal(existing.mutation.operationId, path);
|
|
20171
20385
|
}
|
|
20172
20386
|
async function abortApplyJournal(targetRoot, adapter, transport = localTransport, scope = {}) {
|
|
@@ -20176,7 +20390,7 @@ async function abortApplyJournal(targetRoot, adapter, transport = localTransport
|
|
|
20176
20390
|
const journalPath = applyJournalPath(targetRoot, adapter, scope);
|
|
20177
20391
|
if (!await transport.pathExists(journalPath)) return void 0;
|
|
20178
20392
|
const stateKey = stateKeyFor(adapter, scope);
|
|
20179
|
-
const archivePath =
|
|
20393
|
+
const archivePath = join16(metadataDir(targetRoot), "archive", `${stateKey}.apply-journal.failed-${journalTimestamp(/* @__PURE__ */ new Date())}.json`);
|
|
20180
20394
|
const content = await transport.readFile(journalPath);
|
|
20181
20395
|
const journal = parseApplyJournal(JSON.parse(content));
|
|
20182
20396
|
if (journal.metadataAudit || journal.metadataGuards) {
|
|
@@ -20309,7 +20523,7 @@ async function recordBackup(operation, index, targetRoot, adapter, transport = l
|
|
|
20309
20523
|
hadExisting
|
|
20310
20524
|
};
|
|
20311
20525
|
}
|
|
20312
|
-
const backupPath =
|
|
20526
|
+
const backupPath = join16(applyBackupDir(targetRoot, adapter, scope), String(index));
|
|
20313
20527
|
if (transport.kind === "local-run-as") {
|
|
20314
20528
|
assertGovernedRuntimeTransportSupported(transport);
|
|
20315
20529
|
await transport.rm(backupPath);
|
|
@@ -20317,7 +20531,7 @@ async function recordBackup(operation, index, targetRoot, adapter, transport = l
|
|
|
20317
20531
|
await transport.copyWithin(operation.destPath, backupPath, operation.kind);
|
|
20318
20532
|
} else {
|
|
20319
20533
|
await rm5(backupPath, { recursive: true, force: true });
|
|
20320
|
-
await mkdir7(
|
|
20534
|
+
await mkdir7(dirname13(backupPath), { recursive: true });
|
|
20321
20535
|
await cp2(operation.destPath, backupPath, { recursive: operation.kind === "dir", dereference: true });
|
|
20322
20536
|
}
|
|
20323
20537
|
return {
|
|
@@ -20388,7 +20602,7 @@ function assertApplyJournalCompletedOperations(journal) {
|
|
|
20388
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") {
|
|
20389
20603
|
throw new Error("Apply journal completion does not match its immutable operation.");
|
|
20390
20604
|
}
|
|
20391
|
-
const expectedBackup =
|
|
20605
|
+
const expectedBackup = join16(applyBackupDir(journal.targetRoot, journal.adapter, {
|
|
20392
20606
|
installationType: journal.installationType,
|
|
20393
20607
|
stateKey: journal.stateKey
|
|
20394
20608
|
}), String(item.index));
|
|
@@ -20414,16 +20628,25 @@ var init_transaction = __esm({
|
|
|
20414
20628
|
});
|
|
20415
20629
|
|
|
20416
20630
|
// src/install/toml-merge.ts
|
|
20417
|
-
import { mkdir as mkdir8, readFile as
|
|
20418
|
-
import { parse as parseToml } from "smol-toml";
|
|
20419
|
-
import { dirname as
|
|
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";
|
|
20633
|
+
import { dirname as dirname14 } from "path";
|
|
20420
20634
|
async function mergeCodexTomlMcp(sourcePath, destPath) {
|
|
20421
|
-
const source = JSON.parse(await
|
|
20635
|
+
const source = JSON.parse(await readFile17(sourcePath, "utf8"));
|
|
20422
20636
|
const servers = extractMcpServers(source);
|
|
20423
|
-
const current = await pathExists(destPath) ? await
|
|
20424
|
-
const
|
|
20425
|
-
const
|
|
20426
|
-
|
|
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" });
|
|
20649
|
+
await mkdir8(dirname14(destPath), { recursive: true });
|
|
20427
20650
|
await writeFile8(destPath, merged, "utf8");
|
|
20428
20651
|
}
|
|
20429
20652
|
function mismatchedCodexTomlMcpServers(source, currentContent) {
|
|
@@ -20465,7 +20688,7 @@ function isPlainRecord(value) {
|
|
|
20465
20688
|
}
|
|
20466
20689
|
function extractMcpServers(source) {
|
|
20467
20690
|
const raw = isRecord2(source.mcpServers) ? source.mcpServers : source;
|
|
20468
|
-
const servers =
|
|
20691
|
+
const servers = /* @__PURE__ */ Object.create(null);
|
|
20469
20692
|
for (const [name, value] of Object.entries(raw)) {
|
|
20470
20693
|
if (!isRecord2(value)) continue;
|
|
20471
20694
|
servers[name] = value;
|
|
@@ -20476,23 +20699,39 @@ function extractMcpServers(source) {
|
|
|
20476
20699
|
return servers;
|
|
20477
20700
|
}
|
|
20478
20701
|
function removeManagedMcpSections(content, serverNames) {
|
|
20479
|
-
if (serverNames.length === 0 || content.trim() === "") return content;
|
|
20480
20702
|
const names = new Set(serverNames);
|
|
20481
|
-
const lines = content.split(/\r?\n/);
|
|
20482
20703
|
const kept = [];
|
|
20483
20704
|
let skipping = false;
|
|
20484
|
-
|
|
20485
|
-
|
|
20486
|
-
if (
|
|
20487
|
-
|
|
20488
|
-
|
|
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
|
+
}
|
|
20489
20715
|
}
|
|
20490
20716
|
if (!skipping) kept.push(line);
|
|
20717
|
+
offset += line.length;
|
|
20491
20718
|
}
|
|
20492
|
-
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;
|
|
20493
20733
|
}
|
|
20494
|
-
function appendMcpServers(content,
|
|
20495
|
-
const blocks = Object.entries(servers).sort(([a], [b]) => a.localeCompare(b)).map(([name, server]) => formatMcpServer(name, server));
|
|
20734
|
+
function appendMcpServers(content, blocks) {
|
|
20496
20735
|
const prefix = content.trimEnd();
|
|
20497
20736
|
return `${prefix ? `${prefix}
|
|
20498
20737
|
|
|
@@ -20572,14 +20811,14 @@ var init_toml_merge = __esm({
|
|
|
20572
20811
|
});
|
|
20573
20812
|
|
|
20574
20813
|
// src/install/yaml-merge.ts
|
|
20575
|
-
import { mkdir as mkdir9, readFile as
|
|
20576
|
-
import { dirname as
|
|
20814
|
+
import { mkdir as mkdir9, readFile as readFile18, writeFile as writeFile9 } from "fs/promises";
|
|
20815
|
+
import { dirname as dirname15 } from "path";
|
|
20577
20816
|
import { parse as parse7, stringify } from "yaml";
|
|
20578
20817
|
async function mergeYamlFile(sourcePath, destPath) {
|
|
20579
|
-
const source = parseYamlValue(await
|
|
20580
|
-
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")) : {};
|
|
20581
20820
|
const merged = deepMerge2(current, source);
|
|
20582
|
-
await mkdir9(
|
|
20821
|
+
await mkdir9(dirname15(destPath), { recursive: true });
|
|
20583
20822
|
await writeFile9(destPath, stringify(merged), "utf8");
|
|
20584
20823
|
}
|
|
20585
20824
|
function parseYamlValue(content) {
|
|
@@ -20637,8 +20876,8 @@ var init_yaml_merge = __esm({
|
|
|
20637
20876
|
});
|
|
20638
20877
|
|
|
20639
20878
|
// src/install/merge-removal.ts
|
|
20640
|
-
import { mkdir as mkdir10, readFile as
|
|
20641
|
-
import { dirname as
|
|
20879
|
+
import { mkdir as mkdir10, readFile as readFile19, writeFile as writeFile10 } from "fs/promises";
|
|
20880
|
+
import { dirname as dirname16 } from "path";
|
|
20642
20881
|
import { parse as parse8, stringify as stringify2 } from "yaml";
|
|
20643
20882
|
function assertExactMergeContribution(contribution, strategy, currentContent) {
|
|
20644
20883
|
if (strategy === "codex-toml-mcp") {
|
|
@@ -20715,7 +20954,7 @@ async function mergeRemovalForInstall(sourcePath, strategy, currentContent, opti
|
|
|
20715
20954
|
return introducedMergeContent(parseMergeDestination(currentContent, strategy), source);
|
|
20716
20955
|
}
|
|
20717
20956
|
async function removeMergeContribution(destPath, strategy, removal) {
|
|
20718
|
-
const content = await
|
|
20957
|
+
const content = await readFile19(destPath, "utf8");
|
|
20719
20958
|
if (strategy === "codex-toml-mcp") {
|
|
20720
20959
|
const servers = isRecord4(removal.mcpServers) ? removal.mcpServers : removal;
|
|
20721
20960
|
await writeFile10(destPath, removeCodexTomlMcpSections(content, Object.keys(servers)), "utf8");
|
|
@@ -20723,7 +20962,7 @@ async function removeMergeContribution(destPath, strategy, removal) {
|
|
|
20723
20962
|
}
|
|
20724
20963
|
const current = parseMergeDestination(content, strategy);
|
|
20725
20964
|
removeIntroducedContent(current, removal);
|
|
20726
|
-
await mkdir10(
|
|
20965
|
+
await mkdir10(dirname16(destPath), { recursive: true });
|
|
20727
20966
|
await writeFile10(destPath, strategy === "yaml-deep" ? stringify2(current) : `${JSON.stringify(current, null, 2)}
|
|
20728
20967
|
`, "utf8");
|
|
20729
20968
|
}
|
|
@@ -20739,7 +20978,7 @@ async function readMergeSource(sourcePath, strategy) {
|
|
|
20739
20978
|
if (strategy === "openclaw-json-deep") {
|
|
20740
20979
|
return requireRecord(await renderOpenClawJsonMergeSource(sourcePath), "OpenClaw JSON merge source");
|
|
20741
20980
|
}
|
|
20742
|
-
const content = await
|
|
20981
|
+
const content = await readFile19(sourcePath, "utf8");
|
|
20743
20982
|
if (strategy === "yaml-deep") return requireRecord(normalizeYamlValue2(parse8(content)), "YAML merge source");
|
|
20744
20983
|
return requireRecord(JSON.parse(content), "JSON merge source");
|
|
20745
20984
|
}
|
|
@@ -20991,9 +21230,9 @@ var init_desired = __esm({
|
|
|
20991
21230
|
|
|
20992
21231
|
// src/install/instructions-block.ts
|
|
20993
21232
|
import { createHash as createHash12 } from "crypto";
|
|
20994
|
-
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";
|
|
20995
21234
|
import { tmpdir as tmpdir3 } from "os";
|
|
20996
|
-
import { basename as basename2, dirname as
|
|
21235
|
+
import { basename as basename2, dirname as dirname17, join as join17, relative as relative11 } from "path";
|
|
20997
21236
|
function exactManagedInstructionBlockSnapshot(content, selector) {
|
|
20998
21237
|
const beginCount = [...content.matchAll(new RegExp(`<!-- BEGIN openpack:include ${escapeRegex2(selector)}(?=\\s|-->)`, "gu"))].length;
|
|
20999
21238
|
const endCount = [...content.matchAll(new RegExp(`<!-- END openpack:include ${escapeRegex2(selector)}(?=\\s|-->)`, "gu"))].length;
|
|
@@ -21044,7 +21283,7 @@ function exactManagedInstructionBlockSnapshot(content, selector) {
|
|
|
21044
21283
|
};
|
|
21045
21284
|
}
|
|
21046
21285
|
async function desiredManagedInstructionBlockHash(sourcePath) {
|
|
21047
|
-
const source = await
|
|
21286
|
+
const source = await readFile20(sourcePath, "utf8");
|
|
21048
21287
|
return hashText(managedBlockBody(source));
|
|
21049
21288
|
}
|
|
21050
21289
|
async function readManagedInstructionBlockState(destPath, selector, transport) {
|
|
@@ -21064,7 +21303,7 @@ async function readManagedInstructionBlockState(destPath, selector, transport) {
|
|
|
21064
21303
|
};
|
|
21065
21304
|
}
|
|
21066
21305
|
async function writeManagedInstructionBlock(sourcePath, destPath, selector, transport, options = {}) {
|
|
21067
|
-
const source = await
|
|
21306
|
+
const source = await readFile20(sourcePath, "utf8");
|
|
21068
21307
|
const desired = renderManagedInstructionBlock(selector, source);
|
|
21069
21308
|
const existing = await readOptionalText(destPath, transport);
|
|
21070
21309
|
const merged = upsertManagedInstructionBlock(existing ?? "", selector, desired.block, options);
|
|
@@ -21176,7 +21415,7 @@ function assertCleanBlock(block, selector) {
|
|
|
21176
21415
|
}
|
|
21177
21416
|
}
|
|
21178
21417
|
function referencesAgentsMd(content, claudePath, agentsPath) {
|
|
21179
|
-
const claudeDir =
|
|
21418
|
+
const claudeDir = dirname17(claudePath);
|
|
21180
21419
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
21181
21420
|
const line = rawLine.trim();
|
|
21182
21421
|
const atImport = /^@import\s+(.+)$/i.exec(line);
|
|
@@ -21185,8 +21424,8 @@ function referencesAgentsMd(content, claudePath, agentsPath) {
|
|
|
21185
21424
|
if (!referenced) continue;
|
|
21186
21425
|
const cleaned = referenced.trim().replace(/^["']|["']$/g, "");
|
|
21187
21426
|
if (!/AGENTS\.md$/i.test(cleaned)) continue;
|
|
21188
|
-
const candidate = cleaned.startsWith("/") ? cleaned :
|
|
21189
|
-
if (relative11(
|
|
21427
|
+
const candidate = cleaned.startsWith("/") ? cleaned : join17(claudeDir, cleaned);
|
|
21428
|
+
if (relative11(dirname17(agentsPath), candidate).replaceAll("\\", "/") === "AGENTS.md") return true;
|
|
21190
21429
|
if (candidate === agentsPath) return true;
|
|
21191
21430
|
}
|
|
21192
21431
|
return false;
|
|
@@ -21205,8 +21444,8 @@ async function writeTextWithTransport(path, content, transport) {
|
|
|
21205
21444
|
await transport.writeFileAtomic(path, content);
|
|
21206
21445
|
return;
|
|
21207
21446
|
}
|
|
21208
|
-
const tempRoot = await mkdtemp2(
|
|
21209
|
-
const localPath =
|
|
21447
|
+
const tempRoot = await mkdtemp2(join17(tmpdir3(), "agentwheel-instructions-"));
|
|
21448
|
+
const localPath = join17(tempRoot, basename2(path) || "instructions.md");
|
|
21210
21449
|
try {
|
|
21211
21450
|
await writeFile11(localPath, content, "utf8");
|
|
21212
21451
|
await transport.atomicCopy(localPath, path, "file");
|
|
@@ -21244,9 +21483,9 @@ __export(apply_exports, {
|
|
|
21244
21483
|
});
|
|
21245
21484
|
import { execFile as execFile5 } from "child_process";
|
|
21246
21485
|
import { createHash as createHash13, randomUUID as randomUUID3 } from "crypto";
|
|
21247
|
-
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";
|
|
21248
21487
|
import { tmpdir as tmpdir4 } from "os";
|
|
21249
|
-
import { basename as basename3, dirname as
|
|
21488
|
+
import { basename as basename3, dirname as dirname18, join as join18, resolve as resolve20 } from "path";
|
|
21250
21489
|
import { promisify as promisify5 } from "util";
|
|
21251
21490
|
async function applyInstallPlan(plan, sourceLock, options = {}) {
|
|
21252
21491
|
return applyPlanTransactionally(plan, { ...options, sourceLock });
|
|
@@ -21346,6 +21585,10 @@ async function assertRuntimeStateRevision(plan, transport) {
|
|
|
21346
21585
|
async function applyPlanTransactionally(plan, options = {}) {
|
|
21347
21586
|
const transport = options.transport ?? localTransport;
|
|
21348
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
|
+
});
|
|
21349
21592
|
if (plan.hasBlockingChanges) {
|
|
21350
21593
|
const blockers = plan.operations.filter((operation) => operation.action === "drift" || operation.action === "conflict");
|
|
21351
21594
|
throw new Error(`Refusing to apply with blocking changes: ${blockers.map((item) => item.relativeDestPath).join(", ")}`);
|
|
@@ -21406,6 +21649,7 @@ async function applyPlanTransactionally(plan, options = {}) {
|
|
|
21406
21649
|
transport,
|
|
21407
21650
|
now,
|
|
21408
21651
|
executePlugins: options.executePlugins,
|
|
21652
|
+
openClawAcceptCapabilities,
|
|
21409
21653
|
graphLockDigest,
|
|
21410
21654
|
plan
|
|
21411
21655
|
});
|
|
@@ -21641,7 +21885,7 @@ async function assertCommittedJournalState(journal, expectedManifest, transport)
|
|
|
21641
21885
|
}
|
|
21642
21886
|
}
|
|
21643
21887
|
if (journal.workspaceConfigPath && journal.workspaceConfig) {
|
|
21644
|
-
const actual = JSON.parse(await
|
|
21888
|
+
const actual = JSON.parse(await readFile21(journal.workspaceConfigPath, "utf8"));
|
|
21645
21889
|
if (canonicalJson5(actual) !== canonicalJson5(journal.workspaceConfig)) {
|
|
21646
21890
|
throw new Error(`Workspace config postcheck failed for ${journal.workspaceConfigPath}.`);
|
|
21647
21891
|
}
|
|
@@ -21663,7 +21907,7 @@ async function assertMetadataAuditGuards(journal, after, transport, requireAfter
|
|
|
21663
21907
|
throw new Error("Metadata-audit content digest is invalid.");
|
|
21664
21908
|
}
|
|
21665
21909
|
try {
|
|
21666
|
-
if (await
|
|
21910
|
+
if (await readFile21(path, "utf8") !== file2.content) throw new Error(`Metadata-audit file changed: ${path}`);
|
|
21667
21911
|
} catch (error46) {
|
|
21668
21912
|
if (error46.code !== "ENOENT" || requireAfter) throw error46;
|
|
21669
21913
|
}
|
|
@@ -21714,7 +21958,7 @@ async function createPrivateAuditDirectory(path) {
|
|
|
21714
21958
|
} catch (error46) {
|
|
21715
21959
|
if (error46.code !== "ENOENT") throw error46;
|
|
21716
21960
|
}
|
|
21717
|
-
await createPrivateAuditDirectory(
|
|
21961
|
+
await createPrivateAuditDirectory(dirname18(path));
|
|
21718
21962
|
try {
|
|
21719
21963
|
await mkdir11(path, { mode: 448 });
|
|
21720
21964
|
} catch (error46) {
|
|
@@ -21725,14 +21969,14 @@ async function createPrivateAuditDirectory(path) {
|
|
|
21725
21969
|
}
|
|
21726
21970
|
await chmod3(path, 448);
|
|
21727
21971
|
await syncMetadataPath(path, true);
|
|
21728
|
-
await syncMetadataPath(
|
|
21972
|
+
await syncMetadataPath(dirname18(path), true);
|
|
21729
21973
|
}
|
|
21730
21974
|
async function writeAuditFileExclusive(path, content, validateCallerPath) {
|
|
21731
21975
|
await assertNoSymlinkPath2(path);
|
|
21732
|
-
await createPrivateAuditDirectory(
|
|
21976
|
+
await createPrivateAuditDirectory(dirname18(path));
|
|
21733
21977
|
await assertNoSymlinkPath2(path);
|
|
21734
21978
|
await validateCallerPath();
|
|
21735
|
-
await syncMetadataPath(
|
|
21979
|
+
await syncMetadataPath(dirname18(dirname18(path)), true);
|
|
21736
21980
|
const temporary = `${path}.pending-${randomUUID3()}`;
|
|
21737
21981
|
try {
|
|
21738
21982
|
const handle = await open5(temporary, "wx", 384);
|
|
@@ -21746,9 +21990,9 @@ async function writeAuditFileExclusive(path, content, validateCallerPath) {
|
|
|
21746
21990
|
try {
|
|
21747
21991
|
await link2(temporary, path);
|
|
21748
21992
|
} catch (error46) {
|
|
21749
|
-
if (error46.code !== "EEXIST" || await
|
|
21993
|
+
if (error46.code !== "EEXIST" || await readFile21(path, "utf8") !== content) throw error46;
|
|
21750
21994
|
}
|
|
21751
|
-
const directory = await open5(
|
|
21995
|
+
const directory = await open5(dirname18(path), "r");
|
|
21752
21996
|
try {
|
|
21753
21997
|
await directory.sync();
|
|
21754
21998
|
} finally {
|
|
@@ -21771,7 +22015,7 @@ async function applyOperation(operation, context) {
|
|
|
21771
22015
|
throw new Error(`Invalid plugin operation missing hash: ${operation.relativeDestPath}`);
|
|
21772
22016
|
}
|
|
21773
22017
|
if (context.executePlugins) {
|
|
21774
|
-
await executePluginInstall(operation, transport);
|
|
22018
|
+
await executePluginInstall(operation, transport, context.openClawAcceptCapabilities);
|
|
21775
22019
|
}
|
|
21776
22020
|
return manifestEntryForOperation(operation, {
|
|
21777
22021
|
now,
|
|
@@ -21931,8 +22175,15 @@ async function applyOperation(operation, context) {
|
|
|
21931
22175
|
}
|
|
21932
22176
|
return void 0;
|
|
21933
22177
|
}
|
|
21934
|
-
async function executePluginInstall(operation, transport) {
|
|
21935
|
-
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
|
+
}));
|
|
21936
22187
|
if (commands.length === 0) throw new Error(`Invalid plugin operation missing command: ${operation.relativeDestPath}`);
|
|
21937
22188
|
if (!operation.sourcePath) {
|
|
21938
22189
|
throw new Error(`Invalid plugin operation missing source path: ${operation.relativeDestPath}`);
|
|
@@ -21980,10 +22231,10 @@ async function prepareSemanticPluginState(operation, transport) {
|
|
|
21980
22231
|
async function prepareClaudeMarketplace(operation, transport) {
|
|
21981
22232
|
const spec = requireSemanticPluginState(operation);
|
|
21982
22233
|
const marketplaceName = requireMarketplaceName(operation);
|
|
21983
|
-
const marketplaceRoot =
|
|
22234
|
+
const marketplaceRoot = join18(spec.stateRoot, "marketplace");
|
|
21984
22235
|
await transport.rm(spec.stateRoot);
|
|
21985
|
-
await transport.atomicCopy(requireSourcePath(operation),
|
|
21986
|
-
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"), {
|
|
21987
22238
|
name: marketplaceName,
|
|
21988
22239
|
owner: { name: "Agentwheel" },
|
|
21989
22240
|
plugins: [
|
|
@@ -21998,10 +22249,10 @@ async function prepareClaudeMarketplace(operation, transport) {
|
|
|
21998
22249
|
async function prepareCodexMarketplace(operation, transport) {
|
|
21999
22250
|
const spec = requireSemanticPluginState(operation);
|
|
22000
22251
|
const marketplaceName = requireMarketplaceName(operation);
|
|
22001
|
-
const marketplaceRoot =
|
|
22252
|
+
const marketplaceRoot = join18(spec.stateRoot, "marketplace");
|
|
22002
22253
|
await transport.rm(spec.stateRoot);
|
|
22003
|
-
await transport.atomicCopy(requireSourcePath(operation),
|
|
22004
|
-
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"), {
|
|
22005
22256
|
name: marketplaceName,
|
|
22006
22257
|
interface: {
|
|
22007
22258
|
displayName: "Agentwheel"
|
|
@@ -22025,11 +22276,11 @@ async function prepareCodexMarketplace(operation, transport) {
|
|
|
22025
22276
|
async function prepareCopilotPlugin(operation, transport) {
|
|
22026
22277
|
const spec = requireSemanticPluginState(operation);
|
|
22027
22278
|
await transport.rm(spec.stateRoot);
|
|
22028
|
-
await transport.atomicCopy(requireSourcePath(operation),
|
|
22279
|
+
await transport.atomicCopy(requireSourcePath(operation), join18(spec.stateRoot, "plugin"), operation.kind);
|
|
22029
22280
|
}
|
|
22030
22281
|
async function prepareHermesGitShim(operation, transport) {
|
|
22031
22282
|
const spec = requireSemanticPluginState(operation);
|
|
22032
|
-
const repoRoot =
|
|
22283
|
+
const repoRoot = join18(spec.stateRoot, "repo");
|
|
22033
22284
|
await transport.rm(spec.stateRoot);
|
|
22034
22285
|
await transport.atomicCopy(requireSourcePath(operation), repoRoot, operation.kind);
|
|
22035
22286
|
if (!transport.execFile) {
|
|
@@ -22084,8 +22335,8 @@ async function executeSemanticCommands(operation, commands, transport, options =
|
|
|
22084
22335
|
if (!operation.sourcePath) {
|
|
22085
22336
|
throw new Error(`Invalid semantic plugin operation missing source path: ${operation.relativeDestPath}`);
|
|
22086
22337
|
}
|
|
22087
|
-
const stagingRoot =
|
|
22088
|
-
const remoteSourcePath =
|
|
22338
|
+
const stagingRoot = join18(operation.destPath, ".agentwheel", "plugin-staging", `${process.pid}-${Date.now()}`);
|
|
22339
|
+
const remoteSourcePath = join18(stagingRoot, basename3(operation.sourcePath));
|
|
22089
22340
|
try {
|
|
22090
22341
|
await transport.atomicCopy(operation.sourcePath, remoteSourcePath, operation.kind);
|
|
22091
22342
|
for (const [command, ...args] of commands) {
|
|
@@ -22352,8 +22603,8 @@ async function mergeWithTransport(sourcePath, destPath, transport, merge2) {
|
|
|
22352
22603
|
await merge2(sourcePath, destPath);
|
|
22353
22604
|
return;
|
|
22354
22605
|
}
|
|
22355
|
-
const tempRoot = await mkdtemp3(
|
|
22356
|
-
const localDest =
|
|
22606
|
+
const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-merge-"));
|
|
22607
|
+
const localDest = join18(tempRoot, basename3(destPath) || "merged");
|
|
22357
22608
|
try {
|
|
22358
22609
|
if (await transport.pathExists(destPath)) {
|
|
22359
22610
|
await writeFile12(localDest, await transport.readFile(destPath), "utf8");
|
|
@@ -22369,8 +22620,8 @@ async function removeMergeWithTransport(destPath, strategy, removal, transport)
|
|
|
22369
22620
|
await removeMergeContribution(destPath, strategy, removal);
|
|
22370
22621
|
return;
|
|
22371
22622
|
}
|
|
22372
|
-
const tempRoot = await mkdtemp3(
|
|
22373
|
-
const localDest =
|
|
22623
|
+
const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-merge-remove-"));
|
|
22624
|
+
const localDest = join18(tempRoot, basename3(destPath) || "merged");
|
|
22374
22625
|
try {
|
|
22375
22626
|
await writeFile12(localDest, await transport.readFile(destPath), "utf8");
|
|
22376
22627
|
await removeMergeContribution(localDest, strategy, removal);
|
|
@@ -22380,8 +22631,8 @@ async function removeMergeWithTransport(destPath, strategy, removal, transport)
|
|
|
22380
22631
|
}
|
|
22381
22632
|
}
|
|
22382
22633
|
async function mergeOpenClawJsonWithTransport(sourcePath, destPath, transport) {
|
|
22383
|
-
const tempRoot = await mkdtemp3(
|
|
22384
|
-
const localDest =
|
|
22634
|
+
const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-openclaw-merge-"));
|
|
22635
|
+
const localDest = join18(tempRoot, basename3(destPath) || "openclaw.json");
|
|
22385
22636
|
const validationPath = transport.kind === "local" ? localDest : `${destPath}.validate-agentwheel-${process.pid}-${Date.now()}`;
|
|
22386
22637
|
try {
|
|
22387
22638
|
if (await transport.pathExists(destPath)) {
|
|
@@ -22407,8 +22658,8 @@ async function validateOpenClawConfig(configPath, destPath, transport) {
|
|
|
22407
22658
|
if (!transport.execFile) {
|
|
22408
22659
|
throw new Error(`Cannot validate OpenClaw config over ${transport.description}: transport does not support command execution.`);
|
|
22409
22660
|
}
|
|
22410
|
-
const openClawHome =
|
|
22411
|
-
const bundledBin =
|
|
22661
|
+
const openClawHome = dirname18(destPath);
|
|
22662
|
+
const bundledBin = join18(openClawHome, "npm", "node_modules", ".bin", "openclaw");
|
|
22412
22663
|
const script = String.raw`
|
|
22413
22664
|
set -euo pipefail
|
|
22414
22665
|
cfg=$1
|
|
@@ -22436,6 +22687,7 @@ var init_apply = __esm({
|
|
|
22436
22687
|
init_declarations();
|
|
22437
22688
|
init_graph_lock();
|
|
22438
22689
|
init_transport();
|
|
22690
|
+
init_openclaw2();
|
|
22439
22691
|
init_run_as_policy();
|
|
22440
22692
|
init_json_merge();
|
|
22441
22693
|
init_openclaw_json_merge();
|
|
@@ -22494,7 +22746,7 @@ import { createHash as createHash32 } from "crypto";
|
|
|
22494
22746
|
import { existsSync } from "fs";
|
|
22495
22747
|
import { mkdir as mkdir28, mkdtemp as mkdtemp6, readFile as readFile45, realpath as realpath4, rm as rm16, writeFile as writeFile24 } from "fs/promises";
|
|
22496
22748
|
import { homedir as homedir18, tmpdir as tmpdir7 } from "os";
|
|
22497
|
-
import { basename as basename24, dirname as
|
|
22749
|
+
import { basename as basename24, dirname as dirname42, isAbsolute as isAbsolute17, join as join66, relative as relative22, resolve as resolve48, sep as sep12 } from "path";
|
|
22498
22750
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
22499
22751
|
import { Command } from "commander";
|
|
22500
22752
|
|
|
@@ -22586,8 +22838,8 @@ import { basename as basename8, join as join28, relative as relative12 } from "p
|
|
|
22586
22838
|
|
|
22587
22839
|
// src/staging/codex-subagents.ts
|
|
22588
22840
|
init_fs();
|
|
22589
|
-
import { mkdir as mkdir12, readFile as
|
|
22590
|
-
import { basename as basename4, dirname 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";
|
|
22591
22843
|
import { parse as parseYaml } from "yaml";
|
|
22592
22844
|
var requiredCodexAgentFields = ["name", "description", "developer_instructions"];
|
|
22593
22845
|
async function renderCodexSubagents(artifacts, stageRoot, adapter) {
|
|
@@ -22611,36 +22863,36 @@ async function renderCodexSubagents(artifacts, stageRoot, adapter) {
|
|
|
22611
22863
|
async function renderCodexSubagent(artifact, stageRoot) {
|
|
22612
22864
|
const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
|
|
22613
22865
|
const agentName = codexAgentName(artifact);
|
|
22614
|
-
const renderedPath =
|
|
22866
|
+
const renderedPath = join19(stageRoot, ".agentwheel-rendered", "codex-subagents", `${agentName}.toml`);
|
|
22615
22867
|
const lowerSourcePath = sourcePath.toLowerCase();
|
|
22616
22868
|
if (artifact.kind === "file" && (artifact.name.toLowerCase().endsWith(".toml") || lowerSourcePath.endsWith(".toml"))) {
|
|
22617
|
-
const content = await
|
|
22869
|
+
const content = await readFile22(sourcePath, "utf8");
|
|
22618
22870
|
validateCodexAgentToml(content, sourcePath);
|
|
22619
22871
|
return {
|
|
22620
22872
|
...artifact,
|
|
22621
22873
|
name: agentName,
|
|
22622
|
-
relativePath:
|
|
22874
|
+
relativePath: join19("subagents", `${agentName}.toml`),
|
|
22623
22875
|
kind: "file",
|
|
22624
22876
|
hash: await hashPath(sourcePath)
|
|
22625
22877
|
};
|
|
22626
22878
|
}
|
|
22627
|
-
const markdownPath = artifact.kind === "dir" ?
|
|
22879
|
+
const markdownPath = artifact.kind === "dir" ? join19(sourcePath, "AGENTS.md") : sourcePath;
|
|
22628
22880
|
if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
|
|
22629
22881
|
throw new Error(`Codex subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
|
|
22630
22882
|
}
|
|
22631
22883
|
if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md") && !lowerSourcePath.endsWith(".md")) {
|
|
22632
22884
|
throw new Error(`Codex subagent ${artifact.relativePath} must be a .toml file, .md file, or directory containing AGENTS.md.`);
|
|
22633
22885
|
}
|
|
22634
|
-
const markdown = await
|
|
22886
|
+
const markdown = await readFile22(markdownPath, "utf8");
|
|
22635
22887
|
const toml = markdownToCodexAgentToml(agentName, markdown);
|
|
22636
|
-
await mkdir12(
|
|
22888
|
+
await mkdir12(dirname19(renderedPath), { recursive: true });
|
|
22637
22889
|
await writeFile13(renderedPath, toml, "utf8");
|
|
22638
22890
|
return {
|
|
22639
22891
|
...artifact,
|
|
22640
22892
|
name: agentName,
|
|
22641
22893
|
sourcePath: renderedPath,
|
|
22642
22894
|
stagedPath: renderedPath,
|
|
22643
|
-
relativePath:
|
|
22895
|
+
relativePath: join19("subagents", `${agentName}.toml`),
|
|
22644
22896
|
kind: "file",
|
|
22645
22897
|
hash: await hashPath(renderedPath)
|
|
22646
22898
|
};
|
|
@@ -22715,8 +22967,8 @@ function escapeRegExp2(value) {
|
|
|
22715
22967
|
|
|
22716
22968
|
// src/staging/copilot-artifacts.ts
|
|
22717
22969
|
init_fs();
|
|
22718
|
-
import { mkdir as mkdir13, readFile as
|
|
22719
|
-
import { basename as basename5, dirname 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";
|
|
22720
22972
|
async function renderCopilotArtifacts(artifacts, stageRoot, adapter) {
|
|
22721
22973
|
if (adapter?.name !== "copilot") return artifacts;
|
|
22722
22974
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -22738,23 +22990,23 @@ async function renderCopilotArtifacts(artifacts, stageRoot, adapter) {
|
|
|
22738
22990
|
async function renderCopilotSubagent(artifact, stageRoot) {
|
|
22739
22991
|
const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
|
|
22740
22992
|
const agentName = copilotAgentName(artifact);
|
|
22741
|
-
const renderedPath =
|
|
22742
|
-
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;
|
|
22743
22995
|
if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
|
|
22744
22996
|
throw new Error(`Copilot subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
|
|
22745
22997
|
}
|
|
22746
22998
|
if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md")) {
|
|
22747
22999
|
throw new Error(`Copilot subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
|
|
22748
23000
|
}
|
|
22749
|
-
const markdown = await
|
|
22750
|
-
await mkdir13(
|
|
23001
|
+
const markdown = await readFile23(markdownPath, "utf8");
|
|
23002
|
+
await mkdir13(dirname20(renderedPath), { recursive: true });
|
|
22751
23003
|
await writeFile14(renderedPath, ensureCopilotAgentDescription(agentName, markdown), "utf8");
|
|
22752
23004
|
return {
|
|
22753
23005
|
...artifact,
|
|
22754
23006
|
name: `${agentName}.agent.md`,
|
|
22755
23007
|
sourcePath: renderedPath,
|
|
22756
23008
|
stagedPath: renderedPath,
|
|
22757
|
-
relativePath:
|
|
23009
|
+
relativePath: join20("subagents", `${agentName}.agent.md`),
|
|
22758
23010
|
kind: "file",
|
|
22759
23011
|
hash: await hashPath(renderedPath)
|
|
22760
23012
|
};
|
|
@@ -22802,8 +23054,8 @@ function yamlString(value) {
|
|
|
22802
23054
|
|
|
22803
23055
|
// src/staging/openclaw-subagents.ts
|
|
22804
23056
|
init_fs();
|
|
22805
|
-
import { mkdir as mkdir14, readFile as
|
|
22806
|
-
import { basename as basename6, dirname 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";
|
|
22807
23059
|
async function renderOpenClawSubagents(artifacts, stageRoot, adapter) {
|
|
22808
23060
|
if (adapter?.name !== "openclaw") return artifacts;
|
|
22809
23061
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -22825,28 +23077,28 @@ async function renderOpenClawSubagents(artifacts, stageRoot, adapter) {
|
|
|
22825
23077
|
async function renderOpenClawSubagent(artifact, stageRoot) {
|
|
22826
23078
|
const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
|
|
22827
23079
|
const agentId = openClawAgentId(artifact);
|
|
22828
|
-
const markdownPath = artifact.kind === "dir" ?
|
|
23080
|
+
const markdownPath = artifact.kind === "dir" ? join21(sourcePath, "AGENTS.md") : sourcePath;
|
|
22829
23081
|
if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
|
|
22830
23082
|
throw new Error(`OpenClaw subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
|
|
22831
23083
|
}
|
|
22832
23084
|
if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md") && !sourcePath.toLowerCase().endsWith(".md")) {
|
|
22833
23085
|
throw new Error(`OpenClaw subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
|
|
22834
23086
|
}
|
|
22835
|
-
const parsed = splitFrontmatter3(await
|
|
23087
|
+
const parsed = splitFrontmatter3(await readFile24(markdownPath, "utf8"));
|
|
22836
23088
|
const body = parsed.body.trim().length > 0 ? parsed.body.trim() : `# ${titleFromAgentId(agentId)}
|
|
22837
23089
|
|
|
22838
23090
|
${parsed.description ?? `OpenClaw subagent ${agentId}.`}`;
|
|
22839
|
-
const renderedPath =
|
|
22840
|
-
await mkdir14(
|
|
23091
|
+
const renderedPath = join21(stageRoot, ".agentwheel-rendered", "openclaw-subagents", agentId, "AGENTS.md");
|
|
23092
|
+
await mkdir14(dirname21(renderedPath), { recursive: true });
|
|
22841
23093
|
await writeFile15(renderedPath, `${body}
|
|
22842
23094
|
`, "utf8");
|
|
22843
|
-
const renderedDir =
|
|
23095
|
+
const renderedDir = dirname21(renderedPath);
|
|
22844
23096
|
return {
|
|
22845
23097
|
...artifact,
|
|
22846
23098
|
name: agentId,
|
|
22847
23099
|
sourcePath: renderedDir,
|
|
22848
23100
|
stagedPath: renderedDir,
|
|
22849
|
-
relativePath:
|
|
23101
|
+
relativePath: join21("subagents", agentId),
|
|
22850
23102
|
kind: "dir",
|
|
22851
23103
|
hash: await hashPath(renderedDir)
|
|
22852
23104
|
};
|
|
@@ -22871,15 +23123,15 @@ function titleFromAgentId(agentId) {
|
|
|
22871
23123
|
}
|
|
22872
23124
|
|
|
22873
23125
|
// src/targets/plugins/claude.ts
|
|
22874
|
-
import { join as
|
|
23126
|
+
import { join as join23 } from "path";
|
|
22875
23127
|
|
|
22876
23128
|
// src/targets/plugins/common.ts
|
|
22877
23129
|
init_fs();
|
|
22878
|
-
import { readFile as
|
|
22879
|
-
import { join as
|
|
23130
|
+
import { readFile as readFile25 } from "fs/promises";
|
|
23131
|
+
import { join as join22 } from "path";
|
|
22880
23132
|
import { parseDocument } from "yaml";
|
|
22881
23133
|
function pluginStateRoot(request) {
|
|
22882
|
-
return
|
|
23134
|
+
return join22(
|
|
22883
23135
|
request.targetRoot,
|
|
22884
23136
|
".agentwheel",
|
|
22885
23137
|
"plugins",
|
|
@@ -22897,16 +23149,16 @@ function safeNameSegment(value) {
|
|
|
22897
23149
|
return normalized.length > 0 ? normalized : "unnamed";
|
|
22898
23150
|
}
|
|
22899
23151
|
async function jsonPluginName(root, relativeManifestPath, fallback) {
|
|
22900
|
-
const manifestPath =
|
|
23152
|
+
const manifestPath = join22(root, relativeManifestPath);
|
|
22901
23153
|
if (!await pathExists(manifestPath)) return fallback;
|
|
22902
|
-
const parsed = JSON.parse(await
|
|
23154
|
+
const parsed = JSON.parse(await readFile25(manifestPath, "utf8"));
|
|
22903
23155
|
return typeof parsed.name === "string" && parsed.name.trim().length > 0 ? parsed.name.trim() : fallback;
|
|
22904
23156
|
}
|
|
22905
23157
|
async function yamlPluginName(root, relativeManifestPaths, fallback) {
|
|
22906
23158
|
for (const relativeManifestPath of relativeManifestPaths) {
|
|
22907
|
-
const manifestPath =
|
|
23159
|
+
const manifestPath = join22(root, relativeManifestPath);
|
|
22908
23160
|
if (!await pathExists(manifestPath)) continue;
|
|
22909
|
-
const document = parseDocument(await
|
|
23161
|
+
const document = parseDocument(await readFile25(manifestPath, "utf8"));
|
|
22910
23162
|
const parsed = document.toJSON();
|
|
22911
23163
|
if (!isRecord5(parsed)) continue;
|
|
22912
23164
|
for (const key of ["name", "module", "package"]) {
|
|
@@ -22935,7 +23187,7 @@ async function claudePluginSpec(request) {
|
|
|
22935
23187
|
packageName: request.artifact.packageName,
|
|
22936
23188
|
installName: request.installName
|
|
22937
23189
|
});
|
|
22938
|
-
const marketplaceRoot =
|
|
23190
|
+
const marketplaceRoot = join23(stateRoot, "marketplace");
|
|
22939
23191
|
const scope = claudeScope(request.installationType);
|
|
22940
23192
|
const selector = `${pluginName}@${marketplaceName}`;
|
|
22941
23193
|
return {
|
|
@@ -22960,7 +23212,7 @@ function claudeScope(installationType) {
|
|
|
22960
23212
|
}
|
|
22961
23213
|
|
|
22962
23214
|
// src/targets/plugins/codex.ts
|
|
22963
|
-
import { join as
|
|
23215
|
+
import { join as join24 } from "path";
|
|
22964
23216
|
async function codexPluginSpec(request) {
|
|
22965
23217
|
const pluginName = await jsonPluginName(request.sourcePath, ".codex-plugin/plugin.json", request.installName);
|
|
22966
23218
|
const marketplaceName = agentwheelMarketplaceName(request.artifact.packageName, pluginName);
|
|
@@ -22971,7 +23223,7 @@ async function codexPluginSpec(request) {
|
|
|
22971
23223
|
packageName: request.artifact.packageName,
|
|
22972
23224
|
installName: request.installName
|
|
22973
23225
|
});
|
|
22974
|
-
const marketplaceRoot =
|
|
23226
|
+
const marketplaceRoot = join24(stateRoot, "marketplace");
|
|
22975
23227
|
const selector = `${pluginName}@${marketplaceName}`;
|
|
22976
23228
|
return {
|
|
22977
23229
|
runtime: "codex",
|
|
@@ -22990,7 +23242,7 @@ async function codexPluginSpec(request) {
|
|
|
22990
23242
|
}
|
|
22991
23243
|
|
|
22992
23244
|
// src/targets/plugins/copilot.ts
|
|
22993
|
-
import { join as
|
|
23245
|
+
import { join as join25 } from "path";
|
|
22994
23246
|
async function copilotPluginSpec(request) {
|
|
22995
23247
|
if (request.installationType !== "user") {
|
|
22996
23248
|
throw new Error("Copilot plugins are persistent user-level installs only; pass --installation-type user.");
|
|
@@ -23003,7 +23255,7 @@ async function copilotPluginSpec(request) {
|
|
|
23003
23255
|
packageName: request.artifact.packageName,
|
|
23004
23256
|
installName: request.installName
|
|
23005
23257
|
});
|
|
23006
|
-
const pluginRoot =
|
|
23258
|
+
const pluginRoot = join25(stateRoot, "plugin");
|
|
23007
23259
|
return {
|
|
23008
23260
|
runtime: "copilot",
|
|
23009
23261
|
pluginName,
|
|
@@ -23014,7 +23266,7 @@ async function copilotPluginSpec(request) {
|
|
|
23014
23266
|
}
|
|
23015
23267
|
|
|
23016
23268
|
// src/targets/plugins/hermes.ts
|
|
23017
|
-
import { join as
|
|
23269
|
+
import { join as join26 } from "path";
|
|
23018
23270
|
async function hermesPluginSpec(request) {
|
|
23019
23271
|
if (request.installationType !== "user") {
|
|
23020
23272
|
throw new Error("Hermes plugins are user-level installs only; pass --installation-type user.");
|
|
@@ -23027,7 +23279,7 @@ async function hermesPluginSpec(request) {
|
|
|
23027
23279
|
packageName: request.artifact.packageName,
|
|
23028
23280
|
installName: request.installName
|
|
23029
23281
|
});
|
|
23030
|
-
const repoRoot =
|
|
23282
|
+
const repoRoot = join26(stateRoot, "repo");
|
|
23031
23283
|
return {
|
|
23032
23284
|
runtime: "hermes",
|
|
23033
23285
|
pluginName,
|
|
@@ -23037,64 +23289,8 @@ async function hermesPluginSpec(request) {
|
|
|
23037
23289
|
};
|
|
23038
23290
|
}
|
|
23039
23291
|
|
|
23040
|
-
// src/targets/plugins/openclaw.ts
|
|
23041
|
-
init_fs();
|
|
23042
|
-
import { readFile as readFile25 } from "fs/promises";
|
|
23043
|
-
import { join as join26 } from "path";
|
|
23044
|
-
function openClawPluginInstallCommand(request) {
|
|
23045
|
-
return ["openclaw", "plugins", "install", "--force", request.path];
|
|
23046
|
-
}
|
|
23047
|
-
function openClawPluginUninstallCommand(pluginName) {
|
|
23048
|
-
return ["openclaw", "plugins", "uninstall", pluginName, "--force"];
|
|
23049
|
-
}
|
|
23050
|
-
async function openClawPluginSpec(request) {
|
|
23051
|
-
if (request.format === "openclaw-clawhub-plugin") {
|
|
23052
|
-
const metadata = await openClawClawHubPluginMetadata(request.path, request.fallbackPluginName);
|
|
23053
|
-
return {
|
|
23054
|
-
runtime: "openclaw",
|
|
23055
|
-
pluginName: metadata.pluginName,
|
|
23056
|
-
installCommands: [openClawPluginInstallCommand({ path: metadata.installSpec, dryRun: true })],
|
|
23057
|
-
uninstallCommands: [openClawPluginUninstallCommand(metadata.pluginName)]
|
|
23058
|
-
};
|
|
23059
|
-
}
|
|
23060
|
-
const pluginName = await openClawPluginName(request.path, request.fallbackPluginName);
|
|
23061
|
-
return {
|
|
23062
|
-
runtime: "openclaw",
|
|
23063
|
-
pluginName,
|
|
23064
|
-
installCommands: [openClawPluginInstallCommand({ path: request.path, dryRun: true })],
|
|
23065
|
-
uninstallCommands: [openClawPluginUninstallCommand(pluginName)]
|
|
23066
|
-
};
|
|
23067
|
-
}
|
|
23068
|
-
async function openClawPluginName(root, fallback) {
|
|
23069
|
-
for (const manifestName of ["plugin.json", "openclaw.plugin.json"]) {
|
|
23070
|
-
const manifestPath = join26(root, manifestName);
|
|
23071
|
-
if (!await pathExists(manifestPath)) continue;
|
|
23072
|
-
const parsed = JSON.parse(await readFile25(manifestPath, "utf8"));
|
|
23073
|
-
if (typeof parsed.name === "string" && parsed.name.trim().length > 0) return parsed.name.trim();
|
|
23074
|
-
}
|
|
23075
|
-
return fallback;
|
|
23076
|
-
}
|
|
23077
|
-
async function openClawClawHubPluginMetadata(root, fallback) {
|
|
23078
|
-
const metadataPath = join26(root, "clawhub.json");
|
|
23079
|
-
if (!await pathExists(metadataPath)) {
|
|
23080
|
-
throw new Error("OpenClaw ClawHub plugins must contain clawhub.json");
|
|
23081
|
-
}
|
|
23082
|
-
const parsed = JSON.parse(await readFile25(metadataPath, "utf8"));
|
|
23083
|
-
const installSpec = stringField(parsed.installSpec);
|
|
23084
|
-
if (!installSpec?.startsWith("clawhub:")) {
|
|
23085
|
-
throw new Error("OpenClaw ClawHub plugin metadata must declare installSpec starting with clawhub:");
|
|
23086
|
-
}
|
|
23087
|
-
const pluginName = stringField(parsed.runtimeId) ?? installNameFor(stringField(parsed.name) ?? fallback);
|
|
23088
|
-
return { installSpec, pluginName };
|
|
23089
|
-
}
|
|
23090
|
-
function stringField(value) {
|
|
23091
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
23092
|
-
}
|
|
23093
|
-
function installNameFor(value) {
|
|
23094
|
-
return value.split("/").at(-1).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "clawhub-plugin";
|
|
23095
|
-
}
|
|
23096
|
-
|
|
23097
23292
|
// src/targets/plugins/index.ts
|
|
23293
|
+
init_openclaw2();
|
|
23098
23294
|
async function semanticPluginSpecForArtifact(request) {
|
|
23099
23295
|
if (request.semantic === "openclaw-plugin") {
|
|
23100
23296
|
return openClawPluginSpec({
|
|
@@ -25391,7 +25587,7 @@ function errorMessage2(error46) {
|
|
|
25391
25587
|
|
|
25392
25588
|
// src/source/clawhub.ts
|
|
25393
25589
|
import { mkdir as mkdir15, rm as rm8, writeFile as writeFile16 } from "fs/promises";
|
|
25394
|
-
import { basename as basename10, dirname as
|
|
25590
|
+
import { basename as basename10, dirname as dirname22, join as join32, resolve as resolve22 } from "path";
|
|
25395
25591
|
|
|
25396
25592
|
// src/model/package.ts
|
|
25397
25593
|
init_main();
|
|
@@ -25964,7 +26160,7 @@ async function writeGeneratedPackage(root, packageInfo) {
|
|
|
25964
26160
|
};
|
|
25965
26161
|
const pluginPath = join32(root, "plugins", pluginId, "clawhub.json");
|
|
25966
26162
|
await rm8(root, { recursive: true, force: true });
|
|
25967
|
-
await mkdir15(
|
|
26163
|
+
await mkdir15(dirname22(pluginPath), { recursive: true });
|
|
25968
26164
|
await writeFile16(join32(root, "openpack.json"), `${JSON.stringify({
|
|
25969
26165
|
schemaVersion: CURRENT_OPENPACK_SCHEMA_VERSION,
|
|
25970
26166
|
name: `clawhub/${name}`,
|
|
@@ -25997,7 +26193,7 @@ function cachePathFor(packageName, cacheRoot) {
|
|
|
25997
26193
|
import { execFile as execFile6 } from "child_process";
|
|
25998
26194
|
import { mkdir as mkdir17, rename as rename6, rm as rm10, stat as stat7 } from "fs/promises";
|
|
25999
26195
|
import { homedir as homedir8 } from "os";
|
|
26000
|
-
import { basename as basename11, dirname as
|
|
26196
|
+
import { basename as basename11, dirname as dirname24, join as join35, resolve as resolve23, sep as sep8 } from "path";
|
|
26001
26197
|
import { promisify as promisify6 } from "util";
|
|
26002
26198
|
init_fs();
|
|
26003
26199
|
|
|
@@ -26080,7 +26276,7 @@ function isMissingFile(error46) {
|
|
|
26080
26276
|
init_fs();
|
|
26081
26277
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
26082
26278
|
import { mkdir as mkdir16, readdir as readdir9, readFile as readFile29, rm as rm9, stat as stat6, writeFile as writeFile17 } from "fs/promises";
|
|
26083
|
-
import { dirname as
|
|
26279
|
+
import { dirname as dirname23, join as join34 } from "path";
|
|
26084
26280
|
var snapshotNamePattern = /^(.*)-([0-9a-f]{12})$/i;
|
|
26085
26281
|
var leaseMarker = ".agentwheel-lease-";
|
|
26086
26282
|
async function pruneGitCache(cacheRoot, options = {}) {
|
|
@@ -26148,7 +26344,7 @@ async function removeGeneratedEntries(root, preserveGit) {
|
|
|
26148
26344
|
}
|
|
26149
26345
|
}
|
|
26150
26346
|
async function pruneGitCacheUnlocked(cacheRoot, options) {
|
|
26151
|
-
const referencedCommits = await referencedGraphLockCommits(join34(
|
|
26347
|
+
const referencedCommits = await referencedGraphLockCommits(join34(dirname23(cacheRoot), "locks"));
|
|
26152
26348
|
const entries = await readdir9(cacheRoot, { withFileTypes: true });
|
|
26153
26349
|
const groups = /* @__PURE__ */ new Map();
|
|
26154
26350
|
for (const entry of entries) {
|
|
@@ -26215,7 +26411,7 @@ async function walkGraphLocks(root, visit2) {
|
|
|
26215
26411
|
}
|
|
26216
26412
|
}
|
|
26217
26413
|
async function hasLiveSnapshotLease(snapshotPath, dryRun) {
|
|
26218
|
-
const directory =
|
|
26414
|
+
const directory = dirname23(snapshotPath);
|
|
26219
26415
|
const prefix = `${snapshotPath.slice(directory.length + 1)}${leaseMarker}`;
|
|
26220
26416
|
const entries = await readdir9(directory, { withFileTypes: true });
|
|
26221
26417
|
let live = false;
|
|
@@ -26354,7 +26550,7 @@ var GitSourceDriver = class {
|
|
|
26354
26550
|
async fetch(resolved) {
|
|
26355
26551
|
return withFilesystemLock(`${resolved.resolvedPath}.lock`, resolved.cacheLockTimeoutMs ?? 3e4, async () => {
|
|
26356
26552
|
const parsed = parseGitSource(resolved.source);
|
|
26357
|
-
const cacheRoot =
|
|
26553
|
+
const cacheRoot = dirname24(resolved.resolvedPath);
|
|
26358
26554
|
await mkdir17(cacheRoot, { recursive: true });
|
|
26359
26555
|
await assertOwnedByCurrentUser(cacheRoot);
|
|
26360
26556
|
if (await pathExists(resolved.resolvedPath)) await assertOwnedByCurrentUser(resolved.resolvedPath);
|
|
@@ -26449,9 +26645,9 @@ async function resolveCommit(checkoutPath, ref) {
|
|
|
26449
26645
|
throw lastError;
|
|
26450
26646
|
}
|
|
26451
26647
|
async function snapshotCommit(checkoutPath, commit) {
|
|
26452
|
-
const snapshotPath = join35(
|
|
26648
|
+
const snapshotPath = join35(dirname24(checkoutPath), `${basename11(checkoutPath)}-${commit.slice(0, 12)}`);
|
|
26453
26649
|
if (await pathExists(snapshotPath)) return snapshotPath;
|
|
26454
|
-
const tempPath = join35(
|
|
26650
|
+
const tempPath = join35(dirname24(checkoutPath), `${basename11(snapshotPath)}.tmp-${process.pid}-${Date.now()}`);
|
|
26455
26651
|
const tempIndexPath = `${tempPath}.index`;
|
|
26456
26652
|
await rm10(tempPath, { recursive: true, force: true });
|
|
26457
26653
|
await rm10(tempIndexPath, { force: true });
|
|
@@ -26489,7 +26685,7 @@ async function assertOwnedByCurrentUser(path) {
|
|
|
26489
26685
|
|
|
26490
26686
|
// src/source/mcp-registry.ts
|
|
26491
26687
|
import { mkdir as mkdir18, writeFile as writeFile18 } from "fs/promises";
|
|
26492
|
-
import { basename as basename12, dirname as
|
|
26688
|
+
import { basename as basename12, dirname as dirname25, join as join36, resolve as resolve24 } from "path";
|
|
26493
26689
|
init_fs();
|
|
26494
26690
|
var registryBaseUrl = "https://registry.modelcontextprotocol.io/v0.1";
|
|
26495
26691
|
var sourcePrefix2 = "mcp-registry:";
|
|
@@ -26597,7 +26793,7 @@ function isSafeHttpUrl(value) {
|
|
|
26597
26793
|
async function writeGeneratedPackage2(root, server) {
|
|
26598
26794
|
const serverId = installNameFor3(server.serverName);
|
|
26599
26795
|
const mcpPath = join36(root, "mcp", `${serverId}.json`);
|
|
26600
|
-
await mkdir18(
|
|
26796
|
+
await mkdir18(dirname25(mcpPath), { recursive: true });
|
|
26601
26797
|
await writeFile18(join36(root, "openpack.json"), `${JSON.stringify({
|
|
26602
26798
|
schemaVersion: CURRENT_OPENPACK_SCHEMA_VERSION,
|
|
26603
26799
|
name: `mcp-registry/${server.serverName}`,
|
|
@@ -26631,14 +26827,14 @@ import { createHash as createHash16, randomUUID as randomUUID5 } from "crypto";
|
|
|
26631
26827
|
import { execFile as execFile7 } from "child_process";
|
|
26632
26828
|
import { cp as cp3, mkdir as mkdir19, readFile as readFile30, rename as rename7, rm as rm11 } from "fs/promises";
|
|
26633
26829
|
import { homedir as homedir9 } from "os";
|
|
26634
|
-
import { basename as basename14, dirname as
|
|
26830
|
+
import { basename as basename14, dirname as dirname27, join as join38, resolve as resolve25 } from "path";
|
|
26635
26831
|
import { promisify as promisify7 } from "util";
|
|
26636
26832
|
import * as defaultSkillKit from "@skillkit/core";
|
|
26637
26833
|
|
|
26638
26834
|
// src/source/skill-artifacts.ts
|
|
26639
26835
|
init_fs();
|
|
26640
26836
|
import { readdir as readdir10, stat as stat8 } from "fs/promises";
|
|
26641
|
-
import { basename as basename13, dirname as
|
|
26837
|
+
import { basename as basename13, dirname as dirname26, extname as extname2, join as join37 } from "path";
|
|
26642
26838
|
async function artifactsFromSkillPaths(paths, packageName) {
|
|
26643
26839
|
const artifacts = [];
|
|
26644
26840
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -26675,7 +26871,7 @@ async function artifactFromSkillPath(item, packageName) {
|
|
|
26675
26871
|
};
|
|
26676
26872
|
}
|
|
26677
26873
|
if (stats.isFile() && basename13(item.path).toLowerCase() === "skill.md") {
|
|
26678
|
-
const dir =
|
|
26874
|
+
const dir = dirname26(item.path);
|
|
26679
26875
|
const name = sanitizeSkillName(item.name ?? basename13(dir));
|
|
26680
26876
|
return {
|
|
26681
26877
|
type: "skills",
|
|
@@ -26783,7 +26979,7 @@ var SkillKitSourceDriver = class {
|
|
|
26783
26979
|
sourceHash: await hashPath(resolved.resolvedPath)
|
|
26784
26980
|
};
|
|
26785
26981
|
}
|
|
26786
|
-
const specCachePath = cachePathFor4(spec,
|
|
26982
|
+
const specCachePath = cachePathFor4(spec, dirname27(dirname27(resolved.resolvedPath)));
|
|
26787
26983
|
const refIdentity = resolved.requestedRef ?? "default";
|
|
26788
26984
|
const lockPath = `${specCachePath}.ref-${createHash16("sha256").update(refIdentity).digest("hex")}.lock`;
|
|
26789
26985
|
const inflightKey = `${lockPath}\0${requestedCommit ?? "movable"}`;
|
|
@@ -26804,11 +27000,11 @@ var SkillKitSourceDriver = class {
|
|
|
26804
27000
|
throw new Error("SkillKit provider API unavailable or cannot resolve source. Expected @skillkit/core detectProvider().clone().");
|
|
26805
27001
|
}
|
|
26806
27002
|
const materialized = await withFilesystemLock(lockPath, resolved.cacheLockTimeoutMs ?? 3e4, async () => {
|
|
26807
|
-
const immutablePath = requestedCommit ? cachePathFor4(spec,
|
|
27003
|
+
const immutablePath = requestedCommit ? cachePathFor4(spec, dirname27(dirname27(specCachePath)), requestedCommit) : void 0;
|
|
26808
27004
|
if (immutablePath && await pathExists(immutablePath)) {
|
|
26809
27005
|
return { path: immutablePath, commit: requestedCommit, cacheIdentity: requestedCommit };
|
|
26810
27006
|
}
|
|
26811
|
-
await mkdir19(
|
|
27007
|
+
await mkdir19(dirname27(specCachePath), { recursive: true });
|
|
26812
27008
|
const candidatePath = `${specCachePath}.agentwheel-tmp-${process.pid}-${randomUUID5()}`;
|
|
26813
27009
|
const publishPath = `${candidatePath}.publish`;
|
|
26814
27010
|
let result;
|
|
@@ -26830,7 +27026,7 @@ var SkillKitSourceDriver = class {
|
|
|
26830
27026
|
`SkillKit provider resolved ${resolvedIdentity.commit ?? "non-Git content"} instead of requested commit ${requestedCommit}`
|
|
26831
27027
|
);
|
|
26832
27028
|
}
|
|
26833
|
-
const cachePath = cachePathFor4(spec,
|
|
27029
|
+
const cachePath = cachePathFor4(spec, dirname27(dirname27(specCachePath)), resolvedIdentity.cacheKey);
|
|
26834
27030
|
if (await pathExists(cachePath)) {
|
|
26835
27031
|
return { path: cachePath, commit: resolvedIdentity.commit, cacheIdentity: resolvedIdentity.cacheKey };
|
|
26836
27032
|
}
|
|
@@ -27101,7 +27297,7 @@ init_identify();
|
|
|
27101
27297
|
|
|
27102
27298
|
// src/staging/staging.ts
|
|
27103
27299
|
import { chmod as chmod4, cp as cp5, mkdir as mkdir22, mkdtemp as mkdtemp4, readdir as readdir13, stat as stat12 } from "fs/promises";
|
|
27104
|
-
import { basename as basename19, dirname as
|
|
27300
|
+
import { basename as basename19, dirname as dirname31, join as join43, relative as relative16, resolve as resolve29, sep as sep10 } from "path";
|
|
27105
27301
|
import { tmpdir as tmpdir5 } from "os";
|
|
27106
27302
|
init_fs();
|
|
27107
27303
|
|
|
@@ -27110,7 +27306,7 @@ init_artifact();
|
|
|
27110
27306
|
init_fs();
|
|
27111
27307
|
import { createHash as createHash17 } from "crypto";
|
|
27112
27308
|
import { readdir as readdir11, readFile as readFile31, stat as stat10, writeFile as writeFile19 } from "fs/promises";
|
|
27113
|
-
import { basename as basename16, dirname as
|
|
27309
|
+
import { basename as basename16, dirname as dirname28, extname as extname3, join as join40, relative as relative15, resolve as resolve28, sep as sep9 } from "path";
|
|
27114
27310
|
var includePattern = /<!--\s*openpack:include(\?)?\s+([^>]+?)\s*-->/g;
|
|
27115
27311
|
var escapedIncludePattern = /<!--\s*openpack\\:include(\?)?\s+([^>]+?)\s*-->/g;
|
|
27116
27312
|
var generatedPattern = /<!--\s*(?:BEGIN|END)\s+openpack:include\b/;
|
|
@@ -27365,11 +27561,11 @@ async function listMarkdownFiles(root) {
|
|
|
27365
27561
|
function composeEntriesForFile(artifact, file2) {
|
|
27366
27562
|
if (!artifact.compose?.length) return [];
|
|
27367
27563
|
if (artifact.kind === "file") return [resolve28(artifact.stagedPath ?? artifact.sourcePath), resolve28(file2)].every(Boolean) && resolve28(artifact.stagedPath ?? artifact.sourcePath) === resolve28(file2) ? artifact.compose : [];
|
|
27368
|
-
return basename16(file2) === "SKILL.md" &&
|
|
27564
|
+
return basename16(file2) === "SKILL.md" && dirname28(file2) === resolve28(artifact.stagedPath ?? artifact.sourcePath) ? artifact.compose : [];
|
|
27369
27565
|
}
|
|
27370
27566
|
function isPrimaryMarkdownFile(artifact, file2) {
|
|
27371
27567
|
if (artifact.kind === "file") return resolve28(artifact.stagedPath ?? artifact.sourcePath) === resolve28(file2);
|
|
27372
|
-
return basename16(file2) === "SKILL.md" &&
|
|
27568
|
+
return basename16(file2) === "SKILL.md" && dirname28(file2) === resolve28(artifact.stagedPath ?? artifact.sourcePath);
|
|
27373
27569
|
}
|
|
27374
27570
|
function orderedForExpansion(artifacts) {
|
|
27375
27571
|
return [...artifacts].sort((a, b) => Number(a.type === "fragments") - Number(b.type === "fragments"));
|
|
@@ -27417,7 +27613,7 @@ function artifactPathMap(artifacts) {
|
|
|
27417
27613
|
// src/staging/customize.ts
|
|
27418
27614
|
init_fs();
|
|
27419
27615
|
import { cp as cp4, mkdir as mkdir20, readdir as readdir12, readFile as readFile32, writeFile as writeFile20 } from "fs/promises";
|
|
27420
|
-
import { dirname as
|
|
27616
|
+
import { dirname as dirname29, join as join41 } from "path";
|
|
27421
27617
|
async function applyCustomizations(artifacts, options) {
|
|
27422
27618
|
let next = [...artifacts];
|
|
27423
27619
|
next = await applyReplacements2(next, options, "override", installableArtifactTypes());
|
|
@@ -27441,7 +27637,7 @@ async function applyInstructionOverlay(artifacts, options) {
|
|
|
27441
27637
|
const managed = await readFile32(artifact.stagedPath ?? artifact.sourcePath, "utf8");
|
|
27442
27638
|
const local = await readFile32(overlayPath, "utf8");
|
|
27443
27639
|
const composedPath = join41(options.stageRoot, ".agentwheel-composed", "instructions", "AGENTS.md");
|
|
27444
|
-
await mkdir20(
|
|
27640
|
+
await mkdir20(dirname29(composedPath), { recursive: true });
|
|
27445
27641
|
await writeFile20(
|
|
27446
27642
|
composedPath,
|
|
27447
27643
|
[
|
|
@@ -27514,7 +27710,7 @@ async function applyReplacements2(artifacts, options, channel, artifactTypes) {
|
|
|
27514
27710
|
const artifactKind = entry.isDirectory() ? "dir" : "file";
|
|
27515
27711
|
const existing = byKey.get(artifactMapKey);
|
|
27516
27712
|
const stagedPath = join41(options.stageRoot, ".agentwheel-composed", channel, type, entry.name);
|
|
27517
|
-
await mkdir20(
|
|
27713
|
+
await mkdir20(dirname29(stagedPath), { recursive: true });
|
|
27518
27714
|
await cp4(full, stagedPath, { recursive: artifactKind === "dir", dereference: true });
|
|
27519
27715
|
byKey.set(artifactMapKey, {
|
|
27520
27716
|
...existing,
|
|
@@ -27560,7 +27756,7 @@ async function sortedDirEntries2(path) {
|
|
|
27560
27756
|
// src/staging/claude-subagents.ts
|
|
27561
27757
|
init_fs();
|
|
27562
27758
|
import { mkdir as mkdir21, readFile as readFile33, writeFile as writeFile21 } from "fs/promises";
|
|
27563
|
-
import { basename as basename18, dirname as
|
|
27759
|
+
import { basename as basename18, dirname as dirname30, join as join42 } from "path";
|
|
27564
27760
|
async function renderClaudeSubagents(artifacts, stageRoot, adapter) {
|
|
27565
27761
|
if (adapter?.name !== "claude") return artifacts;
|
|
27566
27762
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -27591,7 +27787,7 @@ async function renderClaudeSubagent(artifact, stageRoot) {
|
|
|
27591
27787
|
}
|
|
27592
27788
|
const content = await readFile33(markdownPath, "utf8");
|
|
27593
27789
|
const renderedPath = join42(stageRoot, ".agentwheel-rendered", "claude-subagents", `${agentName}.md`);
|
|
27594
|
-
await mkdir21(
|
|
27790
|
+
await mkdir21(dirname30(renderedPath), { recursive: true });
|
|
27595
27791
|
await writeFile21(renderedPath, content.endsWith("\n") ? content : `${content}
|
|
27596
27792
|
`, "utf8");
|
|
27597
27793
|
return {
|
|
@@ -27634,7 +27830,7 @@ async function stageResolvedArtifactsRaw(resolved, artifacts, parentDir = tmpdir
|
|
|
27634
27830
|
await removeOnFailure(root, async () => {
|
|
27635
27831
|
for (const artifact of artifacts) {
|
|
27636
27832
|
const stagedPath = join43(root, artifact.relativePath);
|
|
27637
|
-
await mkdir22(
|
|
27833
|
+
await mkdir22(dirname31(stagedPath), { recursive: true });
|
|
27638
27834
|
await cp5(artifact.sourcePath, stagedPath, {
|
|
27639
27835
|
recursive: artifact.kind === "dir",
|
|
27640
27836
|
dereference: true,
|
|
@@ -27740,7 +27936,7 @@ async function copyAsset(asset, source, dest) {
|
|
|
27740
27936
|
throw new Error(`Asset include source is not a file or directory: ${source}`);
|
|
27741
27937
|
}
|
|
27742
27938
|
if (!asset.include?.length) {
|
|
27743
|
-
await mkdir22(
|
|
27939
|
+
await mkdir22(dirname31(dest), { recursive: true });
|
|
27744
27940
|
await cp5(source, dest, { recursive: true, dereference: true });
|
|
27745
27941
|
if (asset.mode === "copy") await normalizeCopiedModes(dest);
|
|
27746
27942
|
return;
|
|
@@ -27752,7 +27948,7 @@ async function copyAsset(asset, source, dest) {
|
|
|
27752
27948
|
}
|
|
27753
27949
|
}
|
|
27754
27950
|
async function copyAssetFile(source, dest, asset) {
|
|
27755
|
-
await mkdir22(
|
|
27951
|
+
await mkdir22(dirname31(dest), { recursive: true });
|
|
27756
27952
|
await cp5(source, dest, { dereference: true });
|
|
27757
27953
|
if (asset.mode === "copy") await chmod4(dest, 420);
|
|
27758
27954
|
}
|
|
@@ -27808,7 +28004,7 @@ init_adapter();
|
|
|
27808
28004
|
init_artifact();
|
|
27809
28005
|
init_workspace();
|
|
27810
28006
|
import { appendFile, cp as cp6, lstat as lstat7, mkdir as mkdir23, readdir as readdir15, rm as rm13 } from "fs/promises";
|
|
27811
|
-
import { dirname as
|
|
28007
|
+
import { dirname as dirname33, join as join46, relative as relative17 } from "path";
|
|
27812
28008
|
|
|
27813
28009
|
// src/resolve/graph.ts
|
|
27814
28010
|
import { createHash as createHash19 } from "crypto";
|
|
@@ -27946,7 +28142,7 @@ import { resolve as resolve31 } from "path";
|
|
|
27946
28142
|
// src/registry/client.ts
|
|
27947
28143
|
import { readFile as readFile35, rm as rm12, stat as stat13 } from "fs/promises";
|
|
27948
28144
|
import { homedir as homedir11 } from "os";
|
|
27949
|
-
import { dirname as
|
|
28145
|
+
import { dirname as dirname32, join as join44, resolve as resolve30 } from "path";
|
|
27950
28146
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
27951
28147
|
|
|
27952
28148
|
// src/model/registry.ts
|
|
@@ -28067,7 +28263,7 @@ var RegistryClient = class {
|
|
|
28067
28263
|
const stats = await stat13(fullPath);
|
|
28068
28264
|
return readFile35(stats.isDirectory() ? join44(fullPath, "index.json") : fullPath, "utf8");
|
|
28069
28265
|
}
|
|
28070
|
-
const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join44(
|
|
28266
|
+
const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join44(dirname32(this.cachePath), "registry-repos") }));
|
|
28071
28267
|
return readFile35(join44(resolved.resolvedPath, "index.json"), "utf8");
|
|
28072
28268
|
}
|
|
28073
28269
|
warnCompatibility(entries) {
|
|
@@ -28438,6 +28634,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
|
|
|
28438
28634
|
if (!satisfiesVersionRange(fetched.version, requirement.version)) {
|
|
28439
28635
|
throw new Error(`Package ${fetched.name}@${fetched.version} does not satisfy requested version ${requirement.version}`);
|
|
28440
28636
|
}
|
|
28637
|
+
const requestedRef = frozen ? frozen.node.requestedRef : fetched.resolved.requestedRef;
|
|
28441
28638
|
const nodeKey = `${normalized.normalizedSource}\0${fetched.name}`;
|
|
28442
28639
|
let selectionImport = requirement.selection ? await resolveSelectionImport(fetched.resolved.resolvedPath, fetched.resolved.driver, requirement.selection) : void 0;
|
|
28443
28640
|
const selected = computeSelectedSelectors(
|
|
@@ -28464,7 +28661,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
|
|
|
28464
28661
|
source: fetched.resolved.source,
|
|
28465
28662
|
normalizedSource: normalized.normalizedSource,
|
|
28466
28663
|
driver: fetched.resolved.driver,
|
|
28467
|
-
requestedRef
|
|
28664
|
+
requestedRef,
|
|
28468
28665
|
resolvedCommit: fetched.resolved.resolvedCommit,
|
|
28469
28666
|
cacheIdentity: fetched.resolved.cacheIdentity,
|
|
28470
28667
|
sourceHash: fetched.sourceHash,
|
|
@@ -28522,7 +28719,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
|
|
|
28522
28719
|
alias: requirement.alias,
|
|
28523
28720
|
source: requirement.source,
|
|
28524
28721
|
normalizedSource: normalized.normalizedSource,
|
|
28525
|
-
requestedRef
|
|
28722
|
+
requestedRef,
|
|
28526
28723
|
version: requirement.version,
|
|
28527
28724
|
mode: requirement.mode,
|
|
28528
28725
|
optional: requirement.optional,
|
|
@@ -29194,7 +29391,7 @@ init_declarations();
|
|
|
29194
29391
|
async function remember(workspaceRoot, runtime, text) {
|
|
29195
29392
|
const overlayPath = join46(workspaceRoot, ".agentwheel", "overlays", runtime, "instructions.local.md");
|
|
29196
29393
|
declareMutationPath(overlayPath);
|
|
29197
|
-
await mkdir23(
|
|
29394
|
+
await mkdir23(dirname33(overlayPath), { recursive: true });
|
|
29198
29395
|
await appendFile(overlayPath, `${text.trim()}
|
|
29199
29396
|
`, "utf8");
|
|
29200
29397
|
return { overlayPath };
|
|
@@ -29227,7 +29424,7 @@ async function ejectArtifact(workspaceRoot, item) {
|
|
|
29227
29424
|
} else {
|
|
29228
29425
|
declareMutationPath(ejectedPath);
|
|
29229
29426
|
}
|
|
29230
|
-
await mkdir23(
|
|
29427
|
+
await mkdir23(dirname33(ejectedPath), { recursive: true });
|
|
29231
29428
|
await rm13(ejectedPath, { recursive: true, force: true });
|
|
29232
29429
|
await cp6(sourcePath, ejectedPath, { recursive: artifact.kind === "dir", dereference: true });
|
|
29233
29430
|
return {
|
|
@@ -29346,7 +29543,7 @@ init_adapter();
|
|
|
29346
29543
|
init_graph_lock();
|
|
29347
29544
|
import { createHash as createHash21 } from "crypto";
|
|
29348
29545
|
import { mkdir as mkdir25, readdir as readdir16 } from "fs/promises";
|
|
29349
|
-
import { basename as basename21, dirname as
|
|
29546
|
+
import { basename as basename21, dirname as dirname35, join as join49, posix as posix7, resolve as resolve34 } from "path";
|
|
29350
29547
|
init_paths();
|
|
29351
29548
|
init_merge_removal();
|
|
29352
29549
|
init_transaction();
|
|
@@ -30034,7 +30231,7 @@ init_zod();
|
|
|
30034
30231
|
init_fs();
|
|
30035
30232
|
import { mkdir as mkdir24, readFile as readFile38 } from "fs/promises";
|
|
30036
30233
|
import { homedir as homedir13 } from "os";
|
|
30037
|
-
import { dirname as
|
|
30234
|
+
import { dirname as dirname34, join as join48 } from "path";
|
|
30038
30235
|
var trustStoreSchema = external_exports.object({
|
|
30039
30236
|
version: external_exports.literal(1),
|
|
30040
30237
|
acceptedSources: external_exports.array(external_exports.string().min(1)).default([])
|
|
@@ -30110,7 +30307,7 @@ async function readTrustStore(path) {
|
|
|
30110
30307
|
return trustStoreSchema.parse(JSON.parse(await readFile38(path, "utf8")));
|
|
30111
30308
|
}
|
|
30112
30309
|
async function writeTrustStore(path, store) {
|
|
30113
|
-
await mkdir24(
|
|
30310
|
+
await mkdir24(dirname34(path), { recursive: true });
|
|
30114
30311
|
await writeJsonAtomic(path, trustStoreSchema.parse(store));
|
|
30115
30312
|
}
|
|
30116
30313
|
function defaultTrustStorePath() {
|
|
@@ -30610,7 +30807,7 @@ async function discoverTargetApplyJournal(options) {
|
|
|
30610
30807
|
continue;
|
|
30611
30808
|
}
|
|
30612
30809
|
if (!journal.graphLockPath || !journal.graphLock || !journal.graphLockDigest) continue;
|
|
30613
|
-
if (resolve34(
|
|
30810
|
+
if (resolve34(dirname35(journal.graphLockPath)) !== resolve34(dirname35(options.graphLockPath))) continue;
|
|
30614
30811
|
if (options.transport.kind === "ssh") {
|
|
30615
30812
|
throw new Error(
|
|
30616
30813
|
`Legacy SSH apply journal at ${item.path} does not record its original endpoint; Agentwheel cannot prove endpoint identity, so the journal was preserved.`
|
|
@@ -30752,7 +30949,7 @@ async function resolvePriorTargetState(options) {
|
|
|
30752
30949
|
return {};
|
|
30753
30950
|
}
|
|
30754
30951
|
async function discoverLegacyStateCandidates(options) {
|
|
30755
|
-
const directory =
|
|
30952
|
+
const directory = dirname35(options.graphLockPath);
|
|
30756
30953
|
let names;
|
|
30757
30954
|
try {
|
|
30758
30955
|
names = await readdir16(directory);
|
|
@@ -31040,7 +31237,7 @@ function mcpServerNames(strategy, removal) {
|
|
|
31040
31237
|
return new Set(Object.keys(servers));
|
|
31041
31238
|
}
|
|
31042
31239
|
function globalConfigRoot(globalRoot) {
|
|
31043
|
-
return
|
|
31240
|
+
return dirname35(dirname35(globalWorkspaceConfigPath(globalRoot)));
|
|
31044
31241
|
}
|
|
31045
31242
|
function ownedByWorkspace(owner, desiredOwner, workspaceRoot, ownsSubWorkspaces) {
|
|
31046
31243
|
if (owner === desiredOwner) return true;
|
|
@@ -31188,7 +31385,7 @@ function targetLabel(target) {
|
|
|
31188
31385
|
init_workspace();
|
|
31189
31386
|
init_run_as_identity();
|
|
31190
31387
|
init_fs();
|
|
31191
|
-
import { basename as basename22, dirname as
|
|
31388
|
+
import { basename as basename22, dirname as dirname36, join as join50, resolve as resolve35 } from "path";
|
|
31192
31389
|
var runtimeMarkers = [
|
|
31193
31390
|
{ adapter: "openclaw", dirs: [".openclaw", ".clawdbot", ".moltbot"] },
|
|
31194
31391
|
{ adapter: "claude", dirs: [".claude"] },
|
|
@@ -31314,7 +31511,7 @@ async function detectRuntimeTargets(cwd = process.cwd(), adapterFilter) {
|
|
|
31314
31511
|
if (adapterFilter && marker.adapter !== adapterFilter) continue;
|
|
31315
31512
|
for (const dir of marker.dirs) {
|
|
31316
31513
|
if (basename22(root) === dir) {
|
|
31317
|
-
matches.push({ adapter: marker.adapter, targetRoot:
|
|
31514
|
+
matches.push({ adapter: marker.adapter, targetRoot: dirname36(root) });
|
|
31318
31515
|
} else if (await pathExists(join50(root, dir))) {
|
|
31319
31516
|
matches.push({ adapter: marker.adapter, targetRoot: root });
|
|
31320
31517
|
}
|
|
@@ -31361,7 +31558,7 @@ function dedupeTargets(matches) {
|
|
|
31361
31558
|
function runtimeScanRoot(request) {
|
|
31362
31559
|
const root = resolve35(request.targetRoot ?? request.cwd ?? process.cwd());
|
|
31363
31560
|
if (request.targetRoot) return root;
|
|
31364
|
-
return runtimeMarkers.some((marker) => marker.dirs.includes(basename22(root))) ?
|
|
31561
|
+
return runtimeMarkers.some((marker) => marker.dirs.includes(basename22(root))) ? dirname36(root) : root;
|
|
31365
31562
|
}
|
|
31366
31563
|
|
|
31367
31564
|
// src/lifecycle/profile.ts
|
|
@@ -31695,7 +31892,7 @@ init_selection();
|
|
|
31695
31892
|
// src/cli/update-check.ts
|
|
31696
31893
|
import { mkdir as mkdir26, readFile as readFile39, writeFile as writeFile22 } from "fs/promises";
|
|
31697
31894
|
import { homedir as homedir14 } from "os";
|
|
31698
|
-
import { dirname as
|
|
31895
|
+
import { dirname as dirname37, join as join51 } from "path";
|
|
31699
31896
|
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
31700
31897
|
var DEFAULT_TIMEOUT_MS = 300;
|
|
31701
31898
|
var REGISTRY_URL = "https://registry.npmjs.org/agentwheel";
|
|
@@ -31748,7 +31945,7 @@ async function readCache(path) {
|
|
|
31748
31945
|
}
|
|
31749
31946
|
}
|
|
31750
31947
|
async function writeCache(path, cache) {
|
|
31751
|
-
await mkdir26(
|
|
31948
|
+
await mkdir26(dirname37(path), { recursive: true });
|
|
31752
31949
|
await writeFile22(path, `${JSON.stringify(cache, null, 2)}
|
|
31753
31950
|
`, "utf8");
|
|
31754
31951
|
}
|
|
@@ -31984,11 +32181,11 @@ init_graph_lock();
|
|
|
31984
32181
|
|
|
31985
32182
|
// src/cli/version.ts
|
|
31986
32183
|
import { readFileSync as readFileSync2 } from "fs";
|
|
31987
|
-
import { dirname as
|
|
32184
|
+
import { dirname as dirname38, join as join54 } from "path";
|
|
31988
32185
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
31989
32186
|
var FALLBACK_VERSION = "0.0.0";
|
|
31990
32187
|
function resolveCliVersion() {
|
|
31991
|
-
let dir =
|
|
32188
|
+
let dir = dirname38(fileURLToPath3(import.meta.url));
|
|
31992
32189
|
while (true) {
|
|
31993
32190
|
try {
|
|
31994
32191
|
const pkg = JSON.parse(readFileSync2(join54(dir, "package.json"), "utf8"));
|
|
@@ -31997,7 +32194,7 @@ function resolveCliVersion() {
|
|
|
31997
32194
|
}
|
|
31998
32195
|
} catch {
|
|
31999
32196
|
}
|
|
32000
|
-
const parent =
|
|
32197
|
+
const parent = dirname38(dir);
|
|
32001
32198
|
if (parent === dir) return FALLBACK_VERSION;
|
|
32002
32199
|
dir = parent;
|
|
32003
32200
|
}
|
|
@@ -32906,7 +33103,7 @@ init_graph_lock();
|
|
|
32906
33103
|
init_manifest();
|
|
32907
33104
|
import { createHash as createHash26 } from "crypto";
|
|
32908
33105
|
import { lstat as lstat8, readdir as readdir17 } from "fs/promises";
|
|
32909
|
-
import { basename as basename23, dirname as
|
|
33106
|
+
import { basename as basename23, dirname as dirname39, join as join57, posix as posix8, relative as relative18, resolve as resolve42 } from "path";
|
|
32910
33107
|
async function inventoryHistoricalLocks(fleetRoot) {
|
|
32911
33108
|
const root = join57(fleetRoot, ".agentwheel", "locks");
|
|
32912
33109
|
const found = [];
|
|
@@ -32953,7 +33150,7 @@ async function planLegacyRecovery(input) {
|
|
|
32953
33150
|
const { graphPlan, installRoot, targetKey: targetKey2, adapter, installationType, historicalLocks, transport } = input;
|
|
32954
33151
|
assertCompleteGraphPlan(graphPlan);
|
|
32955
33152
|
const binding = {
|
|
32956
|
-
targetLockDir:
|
|
33153
|
+
targetLockDir: dirname39(graphPlan.graphLockPath),
|
|
32957
33154
|
stableLockPath: graphPlan.graphLockPath,
|
|
32958
33155
|
stableStateKey: graphPlan.plan.stateKey,
|
|
32959
33156
|
currentFingerprint: graphPlan.targetFingerprint,
|
|
@@ -33065,7 +33262,7 @@ function claimFor(item, entry, locks, binding) {
|
|
|
33065
33262
|
const evidence = [];
|
|
33066
33263
|
const owner = "workspaceOwner" in entry ? entry.workspaceOwner : legacyUnownedWorkspaceOwner;
|
|
33067
33264
|
const sameRoot = binding.transportKind === "ssh" ? posix8.normalize(item.manifest.targetRoot) === posix8.normalize(binding.installRoot) : resolve42(item.manifest.targetRoot) === resolve42(binding.installRoot);
|
|
33068
|
-
const inTargetDir = matches.filter((candidate) => resolve42(
|
|
33265
|
+
const inTargetDir = matches.filter((candidate) => resolve42(dirname39(candidate.path)) === resolve42(binding.targetLockDir));
|
|
33069
33266
|
const boundLocks = inTargetDir.filter((candidate) => lockBindsState(candidate, item, binding));
|
|
33070
33267
|
if (owner !== binding.expectedOwner) evidence.push("workspace owner differs from selected Fleet target");
|
|
33071
33268
|
if (item.manifest.version !== 2 || item.manifest.installationType !== binding.installationType) evidence.push("installation type differs or manifest is legacy v1");
|
|
@@ -35114,7 +35311,7 @@ init_fleet();
|
|
|
35114
35311
|
// src/lifecycle/fleet-normalize.ts
|
|
35115
35312
|
import { createHash as createHash31 } from "crypto";
|
|
35116
35313
|
import { homedir as homedir17 } from "os";
|
|
35117
|
-
import { dirname as
|
|
35314
|
+
import { dirname as dirname41, isAbsolute as isAbsolute16, join as join65, relative as relative21, resolve as resolve47 } from "path";
|
|
35118
35315
|
init_manifest2();
|
|
35119
35316
|
init_paths();
|
|
35120
35317
|
init_merge_removal();
|
|
@@ -35140,7 +35337,7 @@ init_caller_write_trust();
|
|
|
35140
35337
|
import { AsyncLocalStorage } from "async_hooks";
|
|
35141
35338
|
import { readFile as readLocalFile, readdir as readLocalDir, rm as removeLocal, mkdir as mkdir27, open as open6, rename as rename9 } from "fs/promises";
|
|
35142
35339
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
35143
|
-
import { dirname as
|
|
35340
|
+
import { dirname as dirname40, isAbsolute as isAbsolute15, relative as relative20, resolve as resolve46, sep as sep11 } from "path";
|
|
35144
35341
|
var contexts = new AsyncLocalStorage();
|
|
35145
35342
|
var inside = (root, path) => {
|
|
35146
35343
|
const rel = relative20(root, resolve46(path));
|
|
@@ -35202,7 +35399,7 @@ async function normalizationRemove(path, options) {
|
|
|
35202
35399
|
}
|
|
35203
35400
|
await assertNormalizationCallerWrite(path);
|
|
35204
35401
|
await removeLocal(path, options);
|
|
35205
|
-
if (normalizationIdentities().length) await syncMetadataPath(
|
|
35402
|
+
if (normalizationIdentities().length) await syncMetadataPath(dirname40(path), true);
|
|
35206
35403
|
}
|
|
35207
35404
|
async function normalizationWriteJson(path, data) {
|
|
35208
35405
|
const transport = normalizationTransport(path);
|
|
@@ -35216,7 +35413,7 @@ async function normalizationWriteJson(path, data) {
|
|
|
35216
35413
|
}
|
|
35217
35414
|
await assertNormalizationCallerWrite(path);
|
|
35218
35415
|
await assertNoSymlinkPath2(path);
|
|
35219
|
-
await mkdir27(
|
|
35416
|
+
await mkdir27(dirname40(path), { recursive: true, mode: 448 });
|
|
35220
35417
|
await assertNormalizationCallerWrite(path);
|
|
35221
35418
|
const temporary = `${path}.pending-${randomUUID8()}`;
|
|
35222
35419
|
try {
|
|
@@ -35230,8 +35427,8 @@ async function normalizationWriteJson(path, data) {
|
|
|
35230
35427
|
await file2.close();
|
|
35231
35428
|
}
|
|
35232
35429
|
await rename9(temporary, path);
|
|
35233
|
-
await syncMetadataPath(
|
|
35234
|
-
await syncMetadataPath(
|
|
35430
|
+
await syncMetadataPath(dirname40(path), true);
|
|
35431
|
+
await syncMetadataPath(dirname40(dirname40(path)), true);
|
|
35235
35432
|
} finally {
|
|
35236
35433
|
await removeLocal(temporary, { force: true });
|
|
35237
35434
|
}
|
|
@@ -36282,7 +36479,7 @@ async function releasedTargetStateForGraph(scope, graph, identityFleetId = scope
|
|
|
36282
36479
|
...current,
|
|
36283
36480
|
stateKey,
|
|
36284
36481
|
targetFingerprint,
|
|
36285
|
-
graphLockPath: join65(
|
|
36482
|
+
graphLockPath: join65(dirname41(graph.path), `${targetFingerprint}.graph-lock.json`),
|
|
36286
36483
|
manifestPath: installManifestPath(current.installRoot, current.adapter, {
|
|
36287
36484
|
installationType: current.installationType,
|
|
36288
36485
|
stateKey
|
|
@@ -37536,7 +37733,7 @@ ownershipCommand.command("recovery-plan").description("write a read-only per-pat
|
|
|
37536
37733
|
const adapter = await resolveAdapterForTarget(target, {});
|
|
37537
37734
|
const transport = transportForTarget(target);
|
|
37538
37735
|
const requestedReport = normalizeCliPath(options.report);
|
|
37539
|
-
const reportPath = join66(await realpath4(
|
|
37736
|
+
const reportPath = join66(await realpath4(dirname42(requestedReport)), basename24(requestedReport));
|
|
37540
37737
|
const reportInsideTarget = relative22(resolve48(target.targetRoot), reportPath);
|
|
37541
37738
|
if (reportInsideTarget === "" || !reportInsideTarget.startsWith("..") && !isAbsolute17(reportInsideTarget)) {
|
|
37542
37739
|
throw new Error("Recovery report must be outside the runtime target root.");
|
|
@@ -40559,7 +40756,7 @@ async function initPackage(root) {
|
|
|
40559
40756
|
await writeFile24(instructionsPath, "# Agent Instructions\n", "utf8");
|
|
40560
40757
|
}
|
|
40561
40758
|
async function defaultBootstrapPackage(_root) {
|
|
40562
|
-
const packageRoot = await findAgentwheelPackageRoot(
|
|
40759
|
+
const packageRoot = await findAgentwheelPackageRoot(dirname42(fileURLToPath4(import.meta.url)));
|
|
40563
40760
|
if (!packageRoot) return void 0;
|
|
40564
40761
|
return {
|
|
40565
40762
|
name: "agentwheel",
|
|
@@ -40606,7 +40803,7 @@ async function findAgentwheelPackageRoot(start) {
|
|
|
40606
40803
|
let current = resolve48(start);
|
|
40607
40804
|
while (true) {
|
|
40608
40805
|
if (await findPackageManifestPath(current, { warnLegacy: false })) return current;
|
|
40609
|
-
const parent =
|
|
40806
|
+
const parent = dirname42(current);
|
|
40610
40807
|
if (parent === current) return void 0;
|
|
40611
40808
|
current = parent;
|
|
40612
40809
|
}
|