@pushpalsdev/cli 1.0.36 → 1.0.37
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/pushpals-cli.js +104 -49
- package/package.json +1 -1
package/dist/pushpals-cli.js
CHANGED
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
appendFileSync,
|
|
7
7
|
chmodSync,
|
|
8
8
|
cpSync,
|
|
9
|
-
existsSync as
|
|
9
|
+
existsSync as existsSync5,
|
|
10
10
|
lstatSync,
|
|
11
11
|
mkdirSync,
|
|
12
12
|
readdirSync,
|
|
13
13
|
readFileSync as readFileSync4,
|
|
14
|
-
rmSync,
|
|
14
|
+
rmSync as rmSync2,
|
|
15
15
|
writeFileSync
|
|
16
16
|
} from "fs";
|
|
17
17
|
import { basename, delimiter, dirname, extname, join as join2, resolve as resolve4, win32 as pathWin32 } from "path";
|
|
@@ -269,12 +269,60 @@ class ServiceManager {
|
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
+
// ../../apps/workerpals/src/common/worktree_cleanup.ts
|
|
273
|
+
import { existsSync, rmSync } from "fs";
|
|
274
|
+
function defaultSleep(ms) {
|
|
275
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
276
|
+
}
|
|
277
|
+
function windowsDeletionCandidates(worktreePath) {
|
|
278
|
+
const seen = new Set;
|
|
279
|
+
const out = [];
|
|
280
|
+
const add = (value) => {
|
|
281
|
+
if (!value || seen.has(value))
|
|
282
|
+
return;
|
|
283
|
+
seen.add(value);
|
|
284
|
+
out.push(value);
|
|
285
|
+
};
|
|
286
|
+
add(worktreePath);
|
|
287
|
+
if (process.platform === "win32" && /^[A-Za-z]:[\\/]/.test(worktreePath)) {
|
|
288
|
+
add(`\\\\?\\${worktreePath}`);
|
|
289
|
+
}
|
|
290
|
+
return out;
|
|
291
|
+
}
|
|
292
|
+
async function forceDeleteWorktreePath(worktreePath, options = {}) {
|
|
293
|
+
const retries = Math.max(1, Math.floor(options.retries ?? 5));
|
|
294
|
+
const delayMs = Math.max(0, Math.floor(options.delayMs ?? 120));
|
|
295
|
+
const sleep = options.sleepFn ?? defaultSleep;
|
|
296
|
+
const removePath = options.removeFn ?? ((targetPath) => rmSync(targetPath, { recursive: true, force: true }));
|
|
297
|
+
const pathExists = options.existsFn ?? ((targetPath) => existsSync(targetPath));
|
|
298
|
+
let lastError = "";
|
|
299
|
+
for (let attempt = 1;attempt <= retries; attempt++) {
|
|
300
|
+
if (!pathExists(worktreePath))
|
|
301
|
+
return { removed: true };
|
|
302
|
+
for (const candidate of windowsDeletionCandidates(worktreePath)) {
|
|
303
|
+
try {
|
|
304
|
+
removePath(candidate);
|
|
305
|
+
} catch (error) {
|
|
306
|
+
lastError = String(error);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (!pathExists(worktreePath))
|
|
310
|
+
return { removed: true };
|
|
311
|
+
if (attempt < retries)
|
|
312
|
+
await sleep(delayMs * attempt);
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
removed: !pathExists(worktreePath),
|
|
316
|
+
...lastError ? { lastError } : {}
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
272
320
|
// ../shared/src/client_preflight.ts
|
|
273
|
-
import { existsSync as
|
|
321
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
274
322
|
import { relative, resolve as resolve2 } from "path";
|
|
275
323
|
|
|
276
324
|
// ../shared/src/config.ts
|
|
277
|
-
import { existsSync, readFileSync } from "fs";
|
|
325
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
278
326
|
import { join, resolve, isAbsolute } from "path";
|
|
279
327
|
|
|
280
328
|
// ../shared/src/autonomy_policy.ts
|
|
@@ -399,7 +447,7 @@ function parseIntEnv(name) {
|
|
|
399
447
|
return Number.isFinite(parsed) ? parsed : null;
|
|
400
448
|
}
|
|
401
449
|
function parseTomlFile(path) {
|
|
402
|
-
if (!
|
|
450
|
+
if (!existsSync2(path))
|
|
403
451
|
return {};
|
|
404
452
|
const raw = readFileSync(path, "utf-8");
|
|
405
453
|
const parsed = Bun.TOML.parse(raw);
|
|
@@ -408,7 +456,7 @@ function parseTomlFile(path) {
|
|
|
408
456
|
return parsed;
|
|
409
457
|
}
|
|
410
458
|
function parseRequiredTomlFile(path) {
|
|
411
|
-
if (!
|
|
459
|
+
if (!existsSync2(path)) {
|
|
412
460
|
throw new Error(`Missing required runtime config file: ${path}`);
|
|
413
461
|
}
|
|
414
462
|
return parseTomlFile(path);
|
|
@@ -1201,7 +1249,7 @@ function validateVisionDocStructure(markdown) {
|
|
|
1201
1249
|
// ../shared/src/client_preflight.ts
|
|
1202
1250
|
function runtimeHasConfigDir(runtimeRoot, dirName) {
|
|
1203
1251
|
const dirPath = resolve2(runtimeRoot, dirName);
|
|
1204
|
-
return
|
|
1252
|
+
return existsSync3(resolve2(dirPath, "default.toml")) || existsSync3(resolve2(dirPath, "local.example.toml")) || existsSync3(resolve2(dirPath, "local.toml"));
|
|
1205
1253
|
}
|
|
1206
1254
|
function resolveClientConfigDir(projectRoot, runtimeRoot, explicitConfigDir) {
|
|
1207
1255
|
if (explicitConfigDir && explicitConfigDir.trim()) {
|
|
@@ -1255,21 +1303,21 @@ function evaluateClientRuntimePreflight(options) {
|
|
|
1255
1303
|
});
|
|
1256
1304
|
const issues = [];
|
|
1257
1305
|
const envPath = resolve2(runtimeRoot, ".env");
|
|
1258
|
-
if (!
|
|
1306
|
+
if (!existsSync3(envPath)) {
|
|
1259
1307
|
const envExamplePath = resolve2(runtimeRoot, ".env.example");
|
|
1260
1308
|
issues.push({
|
|
1261
1309
|
code: "missing_env_file",
|
|
1262
1310
|
message: `Missing required local env file: ${toDisplayPath(projectRoot, envPath)}.`,
|
|
1263
|
-
copyCommands:
|
|
1311
|
+
copyCommands: existsSync3(envExamplePath) ? buildCopyCommands(projectRoot, envExamplePath, envPath) : undefined
|
|
1264
1312
|
});
|
|
1265
1313
|
}
|
|
1266
1314
|
const localTomlPath = resolve2(runtimeRoot, "configs", "local.toml");
|
|
1267
|
-
if (!
|
|
1315
|
+
if (!existsSync3(localTomlPath)) {
|
|
1268
1316
|
const localExamplePath = resolve2(runtimeRoot, "configs", "local.example.toml");
|
|
1269
1317
|
issues.push({
|
|
1270
1318
|
code: "missing_local_toml",
|
|
1271
1319
|
message: `Missing required local config file: ${toDisplayPath(projectRoot, localTomlPath)}.`,
|
|
1272
|
-
copyCommands:
|
|
1320
|
+
copyCommands: existsSync3(localExamplePath) ? buildCopyCommands(projectRoot, localExamplePath, localTomlPath) : undefined
|
|
1273
1321
|
});
|
|
1274
1322
|
}
|
|
1275
1323
|
const autonomyEnabled = Boolean(config.remotebuddy.autonomy.enabled);
|
|
@@ -1286,11 +1334,11 @@ function evaluateClientRuntimePreflight(options) {
|
|
|
1286
1334
|
}
|
|
1287
1335
|
const visionPath = resolve2(projectRoot, "vision.md");
|
|
1288
1336
|
const visionTemplatePath = resolve2(visionTemplateRoot, "vision.example.md");
|
|
1289
|
-
if (!
|
|
1337
|
+
if (!existsSync3(visionPath)) {
|
|
1290
1338
|
issues.push({
|
|
1291
1339
|
code: "missing_vision_doc",
|
|
1292
1340
|
message: "Missing required autonomy vision file: vision.md " + "(required when remotebuddy.autonomy.enabled=true).",
|
|
1293
|
-
copyCommands:
|
|
1341
|
+
copyCommands: existsSync3(visionTemplatePath) ? buildCopyCommands(projectRoot, visionTemplatePath, visionPath) : undefined
|
|
1294
1342
|
});
|
|
1295
1343
|
return {
|
|
1296
1344
|
ok: false,
|
|
@@ -1404,14 +1452,14 @@ function normalizePresenceLookupToken(value) {
|
|
|
1404
1452
|
}
|
|
1405
1453
|
|
|
1406
1454
|
// ../shared/src/repo.ts
|
|
1407
|
-
import { existsSync as
|
|
1455
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, statSync } from "fs";
|
|
1408
1456
|
import { resolve as resolve3 } from "path";
|
|
1409
1457
|
function resolveDotGitEntry(repoRoot) {
|
|
1410
1458
|
return resolve3(repoRoot, ".git");
|
|
1411
1459
|
}
|
|
1412
1460
|
function resolveGitMetadataDir(repoRoot) {
|
|
1413
1461
|
const dotGitPath = resolveDotGitEntry(repoRoot);
|
|
1414
|
-
if (!
|
|
1462
|
+
if (!existsSync4(dotGitPath))
|
|
1415
1463
|
return null;
|
|
1416
1464
|
try {
|
|
1417
1465
|
const stat = statSync(dotGitPath);
|
|
@@ -1430,7 +1478,7 @@ function resolveGitMetadataDir(repoRoot) {
|
|
|
1430
1478
|
if (!match)
|
|
1431
1479
|
return null;
|
|
1432
1480
|
const gitDir = resolve3(repoRoot, match[1].trim());
|
|
1433
|
-
return
|
|
1481
|
+
return existsSync4(gitDir) ? gitDir : null;
|
|
1434
1482
|
} catch {
|
|
1435
1483
|
return null;
|
|
1436
1484
|
}
|
|
@@ -1856,7 +1904,7 @@ function copyTrackedRepoPath(repoRoot, sourcePath, destinationPath, force = true
|
|
|
1856
1904
|
throw new Error("sourcePath is required");
|
|
1857
1905
|
}
|
|
1858
1906
|
const absoluteSource = resolve4(repoRoot, normalizedSource);
|
|
1859
|
-
if (!
|
|
1907
|
+
if (!existsSync5(absoluteSource)) {
|
|
1860
1908
|
throw new Error(`tracked repo source is missing: ${absoluteSource}`);
|
|
1861
1909
|
}
|
|
1862
1910
|
const trackedFiles = listTrackedRepoFilesForPath(repoRoot, normalizedSource);
|
|
@@ -1889,7 +1937,7 @@ function copyTrackedRepoPath(repoRoot, sourcePath, destinationPath, force = true
|
|
|
1889
1937
|
}
|
|
1890
1938
|
}
|
|
1891
1939
|
function isCompleteWorkerpalSandboxRoot(root) {
|
|
1892
|
-
return
|
|
1940
|
+
return existsSync5(join2(root, "package.json")) && existsSync5(join2(root, "apps", "workerpals", "Dockerfile.sandbox")) && existsSync5(join2(root, "packages", "shared", "package.json")) && existsSync5(join2(root, "packages", "protocol", "package.json")) && existsSync5(join2(root, "configs", "default.toml")) && existsSync5(join2(root, "prompts", "workerpals")) && existsSync5(join2(root, "protocol", "schemas", "envelope.schema.json")) && existsSync5(join2(root, "protocol", "schemas", "events.schema.json"));
|
|
1893
1941
|
}
|
|
1894
1942
|
function populateWorkerpalSandboxRuntimeAssets(runtimeRoot, force) {
|
|
1895
1943
|
const sandbox = buildWorkerpalSandboxPaths(runtimeRoot);
|
|
@@ -1920,7 +1968,7 @@ function copySourceCheckoutWorkerpalSandboxBuildContext(sourceRoot, runtimeRoot,
|
|
|
1920
1968
|
for (const [fromPath, toPath] of copyPairs) {
|
|
1921
1969
|
copyTrackedRepoPath(sourceRoot, fromPath, toPath, force);
|
|
1922
1970
|
}
|
|
1923
|
-
if (
|
|
1971
|
+
if (existsSync5(join2(sourceRoot, "bun.lock"))) {
|
|
1924
1972
|
copyTrackedRepoPath(sourceRoot, "bun.lock", join2(sandbox.root, "bun.lock"), force);
|
|
1925
1973
|
}
|
|
1926
1974
|
populateWorkerpalSandboxRuntimeAssets(runtimeRoot, force);
|
|
@@ -1938,7 +1986,7 @@ function copyWorkerpalSandboxBuildContext(source, runtimeRoot, force) {
|
|
|
1938
1986
|
copySourceCheckoutWorkerpalSandboxBuildContext(source.root, runtimeRoot, force);
|
|
1939
1987
|
}
|
|
1940
1988
|
function isCompleteRuntimeAssetSource(source) {
|
|
1941
|
-
return
|
|
1989
|
+
return existsSync5(source.envExamplePath) && existsSync5(source.visionExamplePath) && existsSync5(join2(source.configsDir, "default.toml")) && existsSync5(source.promptsDir) && existsSync5(join2(source.protocolSchemasDir, "envelope.schema.json")) && existsSync5(join2(source.protocolSchemasDir, "events.schema.json"));
|
|
1942
1990
|
}
|
|
1943
1991
|
function resolveBundledRuntimeAssetSource() {
|
|
1944
1992
|
const candidates = [
|
|
@@ -1953,10 +2001,10 @@ function resolveBundledRuntimeAssetSource() {
|
|
|
1953
2001
|
return null;
|
|
1954
2002
|
}
|
|
1955
2003
|
function looksLikeMonitoringHubBuild(root) {
|
|
1956
|
-
return
|
|
2004
|
+
return existsSync5(join2(root, "index.html")) && existsSync5(join2(root, "_expo"));
|
|
1957
2005
|
}
|
|
1958
2006
|
function latestPathMtimeMs(pathValue) {
|
|
1959
|
-
if (!
|
|
2007
|
+
if (!existsSync5(pathValue))
|
|
1960
2008
|
return 0;
|
|
1961
2009
|
const stat = lstatSync(pathValue);
|
|
1962
2010
|
let latest = stat.mtimeMs;
|
|
@@ -2009,7 +2057,7 @@ function resolveCliSourceCheckoutRoot() {
|
|
|
2009
2057
|
resolve4(import.meta.dir, "..", "..", "..")
|
|
2010
2058
|
];
|
|
2011
2059
|
for (const candidate of candidates) {
|
|
2012
|
-
if (
|
|
2060
|
+
if (existsSync5(join2(candidate, "package.json")) && existsSync5(join2(candidate, "apps", "client", "app.json")) && existsSync5(join2(candidate, "scripts", "sync-cli-monitor-ui.ts"))) {
|
|
2013
2061
|
return candidate;
|
|
2014
2062
|
}
|
|
2015
2063
|
}
|
|
@@ -2043,7 +2091,7 @@ async function ensureBundledMonitoringHubRoot() {
|
|
|
2043
2091
|
return resolveBundledMonitoringHubRoot();
|
|
2044
2092
|
}
|
|
2045
2093
|
function repoLooksLikePushPalsSourceCheckout(repoRoot) {
|
|
2046
|
-
return
|
|
2094
|
+
return existsSync5(join2(repoRoot, "configs", "default.toml"));
|
|
2047
2095
|
}
|
|
2048
2096
|
function parseSemverFromPackageVersion(value) {
|
|
2049
2097
|
const raw = String(value ?? "").trim();
|
|
@@ -2093,13 +2141,13 @@ async function resolveRuntimeReleaseTag(explicitTag) {
|
|
|
2093
2141
|
return await fetchLatestReleaseTag();
|
|
2094
2142
|
}
|
|
2095
2143
|
function writeTextFileIfMissing(pathValue, text) {
|
|
2096
|
-
if (
|
|
2144
|
+
if (existsSync5(pathValue))
|
|
2097
2145
|
return;
|
|
2098
2146
|
mkdirSync(dirname(pathValue), { recursive: true });
|
|
2099
2147
|
writeFileSync(pathValue, text, "utf8");
|
|
2100
2148
|
}
|
|
2101
2149
|
function migrateEmbeddedRuntimeLocalToml(localTomlPath) {
|
|
2102
|
-
if (!
|
|
2150
|
+
if (!existsSync5(localTomlPath))
|
|
2103
2151
|
return;
|
|
2104
2152
|
let original;
|
|
2105
2153
|
try {
|
|
@@ -2149,8 +2197,8 @@ function copyBundledRuntimeAssets(runtimeRoot, force = true) {
|
|
|
2149
2197
|
}
|
|
2150
2198
|
function hasSeededRuntimePreflightAssets(runtimeRoot) {
|
|
2151
2199
|
const protocolSchemasDir = join2(runtimeRoot, "protocol", "schemas");
|
|
2152
|
-
const hasProtocolSchemas =
|
|
2153
|
-
return
|
|
2200
|
+
const hasProtocolSchemas = existsSync5(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync5(join2(protocolSchemasDir, "events.schema.json"));
|
|
2201
|
+
return existsSync5(join2(runtimeRoot, ".env.example")) && existsSync5(join2(runtimeRoot, "vision.example.md")) && existsSync5(join2(runtimeRoot, "configs", "default.toml")) && existsSync5(join2(runtimeRoot, "prompts")) && hasProtocolSchemas && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
|
|
2154
2202
|
}
|
|
2155
2203
|
function seedRuntimePreflightAssets(runtimeRoot) {
|
|
2156
2204
|
if (!hasSeededRuntimePreflightAssets(runtimeRoot)) {
|
|
@@ -2160,7 +2208,7 @@ function seedRuntimePreflightAssets(runtimeRoot) {
|
|
|
2160
2208
|
`);
|
|
2161
2209
|
const localExamplePath = join2(runtimeRoot, "configs", "local.example.toml");
|
|
2162
2210
|
const localTomlPath = join2(runtimeRoot, "configs", "local.toml");
|
|
2163
|
-
if (
|
|
2211
|
+
if (existsSync5(localExamplePath)) {
|
|
2164
2212
|
writeTextFileIfMissing(localTomlPath, readFileSync4(localExamplePath, "utf8"));
|
|
2165
2213
|
} else {
|
|
2166
2214
|
writeTextFileIfMissing(localTomlPath, `# Local PushPals runtime overrides
|
|
@@ -2205,15 +2253,15 @@ async function downloadRuntimeAssetsFromSourceTag(runtimeRoot, tag) {
|
|
|
2205
2253
|
async function ensureRuntimeAssets(runtimeRoot, runtimeTag) {
|
|
2206
2254
|
console.log(`[pushpals] Preparing embedded runtime assets for ${runtimeTag}...`);
|
|
2207
2255
|
const markerPath = join2(runtimeRoot, ".runtime-assets-tag");
|
|
2208
|
-
const currentTag =
|
|
2256
|
+
const currentTag = existsSync5(markerPath) ? readFileSync4(markerPath, "utf8").trim() : "";
|
|
2209
2257
|
const protocolSchemasDir = join2(runtimeRoot, "protocol", "schemas");
|
|
2210
|
-
const hasProtocolSchemas =
|
|
2211
|
-
const hasAssets =
|
|
2258
|
+
const hasProtocolSchemas = existsSync5(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync5(join2(protocolSchemasDir, "events.schema.json"));
|
|
2259
|
+
const hasAssets = existsSync5(join2(runtimeRoot, ".env.example")) && existsSync5(join2(runtimeRoot, "vision.example.md")) && existsSync5(join2(runtimeRoot, "configs", "default.toml")) && existsSync5(join2(runtimeRoot, "prompts")) && hasProtocolSchemas && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
|
|
2212
2260
|
if (!hasAssets || currentTag !== runtimeTag) {
|
|
2213
2261
|
console.log(`[pushpals] Embedded runtime assets ${hasAssets ? "are stale" : "are missing"}; refreshing bundle...`);
|
|
2214
2262
|
copyBundledRuntimeAssets(runtimeRoot);
|
|
2215
|
-
const hasProtocolSchemasAfterCopy =
|
|
2216
|
-
const hasAssetsAfterCopy =
|
|
2263
|
+
const hasProtocolSchemasAfterCopy = existsSync5(join2(protocolSchemasDir, "envelope.schema.json")) && existsSync5(join2(protocolSchemasDir, "events.schema.json"));
|
|
2264
|
+
const hasAssetsAfterCopy = existsSync5(join2(runtimeRoot, ".env.example")) && existsSync5(join2(runtimeRoot, "vision.example.md")) && existsSync5(join2(runtimeRoot, "configs", "default.toml")) && existsSync5(join2(runtimeRoot, "prompts")) && hasProtocolSchemasAfterCopy && isCompleteWorkerpalSandboxRoot(join2(runtimeRoot, "sandbox"));
|
|
2217
2265
|
if (!hasAssetsAfterCopy) {
|
|
2218
2266
|
console.log("[pushpals] Bundled runtime assets are incomplete; falling back to release source downloads...");
|
|
2219
2267
|
await downloadRuntimeAssetsFromSourceTag(runtimeRoot, runtimeTag);
|
|
@@ -2225,7 +2273,7 @@ async function ensureRuntimeAssets(runtimeRoot, runtimeTag) {
|
|
|
2225
2273
|
`);
|
|
2226
2274
|
const localExamplePath = join2(runtimeRoot, "configs", "local.example.toml");
|
|
2227
2275
|
const localTomlPath = join2(runtimeRoot, "configs", "local.toml");
|
|
2228
|
-
if (
|
|
2276
|
+
if (existsSync5(localExamplePath)) {
|
|
2229
2277
|
writeTextFileIfMissing(localTomlPath, readFileSync4(localExamplePath, "utf8"));
|
|
2230
2278
|
} else {
|
|
2231
2279
|
writeTextFileIfMissing(localTomlPath, `# Local PushPals runtime overrides
|
|
@@ -2279,12 +2327,12 @@ function runtimeBinaryFilename(serviceName, platformKey) {
|
|
|
2279
2327
|
function resolveRuntimeBinaryInstallState(runtimeRoot, platformKey) {
|
|
2280
2328
|
const binDir = join2(runtimeRoot, "bin", platformKey);
|
|
2281
2329
|
const tagMarkerPath = join2(binDir, ".runtime-tag");
|
|
2282
|
-
const installedTag =
|
|
2330
|
+
const installedTag = existsSync5(tagMarkerPath) ? readFileSync4(tagMarkerPath, "utf8").trim() : "";
|
|
2283
2331
|
return { binDir, tagMarkerPath, installedTag };
|
|
2284
2332
|
}
|
|
2285
2333
|
function cleanupLegacyRuntimeBinaryLayouts(runtimeRoot, platformKey, activeBinDir) {
|
|
2286
2334
|
const legacyRoot = join2(runtimeRoot, "bin");
|
|
2287
|
-
if (!
|
|
2335
|
+
if (!existsSync5(legacyRoot))
|
|
2288
2336
|
return;
|
|
2289
2337
|
let entries;
|
|
2290
2338
|
try {
|
|
@@ -2301,7 +2349,7 @@ function cleanupLegacyRuntimeBinaryLayouts(runtimeRoot, platformKey, activeBinDi
|
|
|
2301
2349
|
if (!entry.name.endsWith(`-${platformKey}`))
|
|
2302
2350
|
continue;
|
|
2303
2351
|
try {
|
|
2304
|
-
|
|
2352
|
+
rmSync2(candidateDir, { recursive: true, force: true });
|
|
2305
2353
|
} catch {}
|
|
2306
2354
|
}
|
|
2307
2355
|
}
|
|
@@ -2373,7 +2421,7 @@ function resolveEmbeddedBunExecutableFromEnv(env, platform = process.platform, c
|
|
|
2373
2421
|
continue;
|
|
2374
2422
|
for (const candidate of candidates) {
|
|
2375
2423
|
const fullPath = join2(dir, candidate);
|
|
2376
|
-
if (
|
|
2424
|
+
if (existsSync5(fullPath)) {
|
|
2377
2425
|
return fullPath;
|
|
2378
2426
|
}
|
|
2379
2427
|
}
|
|
@@ -2446,7 +2494,7 @@ function appendRuntimeServicesLogLine(logPath, line) {
|
|
|
2446
2494
|
} catch {}
|
|
2447
2495
|
}
|
|
2448
2496
|
function readLogTail(logPath, maxLines = 40) {
|
|
2449
|
-
if (!
|
|
2497
|
+
if (!existsSync5(logPath))
|
|
2450
2498
|
return "";
|
|
2451
2499
|
const raw = readFileSync4(logPath, "utf8");
|
|
2452
2500
|
const lines = raw.split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line.length > 0);
|
|
@@ -2472,7 +2520,7 @@ function extractRemoteBuddyAutonomousEngineState(logText) {
|
|
|
2472
2520
|
return state;
|
|
2473
2521
|
}
|
|
2474
2522
|
function readRemoteBuddyAutonomousEngineState(logPath) {
|
|
2475
|
-
if (!
|
|
2523
|
+
if (!existsSync5(logPath))
|
|
2476
2524
|
return "unknown";
|
|
2477
2525
|
try {
|
|
2478
2526
|
return extractRemoteBuddyAutonomousEngineState(readFileSync4(logPath, "utf8"));
|
|
@@ -2514,7 +2562,7 @@ async function ensureRuntimeBinaries(runtimeRoot, runtimeTag) {
|
|
|
2514
2562
|
const shouldRefreshAll = installedTag !== runtimeTag;
|
|
2515
2563
|
let downloadedCount = 0;
|
|
2516
2564
|
for (const binaryPath of requiredAssets) {
|
|
2517
|
-
if (!shouldRefreshAll &&
|
|
2565
|
+
if (!shouldRefreshAll && existsSync5(binaryPath))
|
|
2518
2566
|
continue;
|
|
2519
2567
|
const assetName = binaryPath.split(/[\\/]/).pop() || "";
|
|
2520
2568
|
await downloadBinaryAsset(runtimeTag, assetName, binaryPath);
|
|
@@ -2918,6 +2966,7 @@ async function cleanupLingeringWorkerpalWarmContainers(opts) {
|
|
|
2918
2966
|
}
|
|
2919
2967
|
async function cleanupLingeringPushPalsGitWorktrees(opts) {
|
|
2920
2968
|
const runCommandWithEnvFn = opts.runCommandWithEnvFn ?? runCommandWithEnv;
|
|
2969
|
+
const forceDeleteWorktreePathFn = opts.forceDeleteWorktreePathFn ?? forceDeleteWorktreePath;
|
|
2921
2970
|
const list = await runCommandWithEnvFn(["git", "worktree", "list", "--porcelain"], opts.repoRoot, opts.env);
|
|
2922
2971
|
if (!list.ok) {
|
|
2923
2972
|
const detail = list.stderr || list.stdout || `exit ${list.exitCode}`;
|
|
@@ -2945,7 +2994,13 @@ async function cleanupLingeringPushPalsGitWorktrees(opts) {
|
|
|
2945
2994
|
removed += 1;
|
|
2946
2995
|
continue;
|
|
2947
2996
|
}
|
|
2948
|
-
|
|
2997
|
+
const forced = await forceDeleteWorktreePathFn(entry.path);
|
|
2998
|
+
if (forced.removed) {
|
|
2999
|
+
removed += 1;
|
|
3000
|
+
continue;
|
|
3001
|
+
}
|
|
3002
|
+
const removeDetail = remove.stderr || remove.stdout || `exit ${remove.exitCode}`;
|
|
3003
|
+
failures.push(`${entry.path}: ${removeDetail}${forced.lastError ? ` | fallback: ${forced.lastError}` : ""}`);
|
|
2949
3004
|
}
|
|
2950
3005
|
const prune = await runCommandWithEnvFn(["git", "worktree", "prune"], opts.repoRoot, opts.env);
|
|
2951
3006
|
if (!prune.ok) {
|
|
@@ -3300,10 +3355,10 @@ function buildCliClearTargets(opts) {
|
|
|
3300
3355
|
return targets;
|
|
3301
3356
|
}
|
|
3302
3357
|
function removeCliClearTarget(target) {
|
|
3303
|
-
if (!
|
|
3358
|
+
if (!existsSync5(target.path))
|
|
3304
3359
|
return "missing";
|
|
3305
3360
|
try {
|
|
3306
|
-
|
|
3361
|
+
rmSync2(target.path, { recursive: true, force: true });
|
|
3307
3362
|
return "removed";
|
|
3308
3363
|
} catch (err) {
|
|
3309
3364
|
return {
|
|
@@ -4000,7 +4055,7 @@ ${tail}` : ""}`);
|
|
|
4000
4055
|
throw new Error(`Timed out waiting for LocalBuddy at ${opts.localAgentUrl} and RemoteBuddy session consumer after ${DEFAULT_RUNTIME_BOOT_TIMEOUT_MS}ms`);
|
|
4001
4056
|
}
|
|
4002
4057
|
function readCliState(pathValue) {
|
|
4003
|
-
if (!
|
|
4058
|
+
if (!existsSync5(pathValue))
|
|
4004
4059
|
return {};
|
|
4005
4060
|
try {
|
|
4006
4061
|
const raw = readFileSync4(pathValue, "utf8");
|
|
@@ -4103,11 +4158,11 @@ function resolveMonitoringHubAssetPath(assetRoot, pathname) {
|
|
|
4103
4158
|
const candidatePath = resolve4(root, relativePath);
|
|
4104
4159
|
if (candidatePath !== root && !candidatePath.startsWith(rootPrefix))
|
|
4105
4160
|
return null;
|
|
4106
|
-
if (
|
|
4161
|
+
if (existsSync5(candidatePath))
|
|
4107
4162
|
return candidatePath;
|
|
4108
4163
|
if (!extname(relativePath)) {
|
|
4109
4164
|
const nestedIndexPath = resolve4(root, relativePath, "index.html");
|
|
4110
|
-
if ((nestedIndexPath === root || nestedIndexPath.startsWith(rootPrefix)) &&
|
|
4165
|
+
if ((nestedIndexPath === root || nestedIndexPath.startsWith(rootPrefix)) && existsSync5(nestedIndexPath)) {
|
|
4111
4166
|
return nestedIndexPath;
|
|
4112
4167
|
}
|
|
4113
4168
|
return join2(root, "index.html");
|
|
@@ -4116,7 +4171,7 @@ function resolveMonitoringHubAssetPath(assetRoot, pathname) {
|
|
|
4116
4171
|
}
|
|
4117
4172
|
async function serveBundledMonitoringHub(assetRoot, pathname, bootstrap) {
|
|
4118
4173
|
const assetPath = resolveMonitoringHubAssetPath(assetRoot, pathname);
|
|
4119
|
-
if (!assetPath || !
|
|
4174
|
+
if (!assetPath || !existsSync5(assetPath))
|
|
4120
4175
|
return null;
|
|
4121
4176
|
if (assetPath.endsWith("index.html")) {
|
|
4122
4177
|
const html = injectMonitoringHubBootstrap(readFileSync4(assetPath, "utf8"), bootstrap);
|