@pushpalsdev/cli 1.0.94 → 1.0.95
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 +120 -15
- package/package.json +1 -1
package/dist/pushpals-cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
mkdirSync,
|
|
12
12
|
readdirSync,
|
|
13
13
|
readFileSync as readFileSync4,
|
|
14
|
+
renameSync,
|
|
14
15
|
rmSync as rmSync2,
|
|
15
16
|
writeFileSync
|
|
16
17
|
} from "fs";
|
|
@@ -1978,8 +1979,29 @@ async function runCommandWithEnv(command, cwd, env, timeoutMs) {
|
|
|
1978
1979
|
};
|
|
1979
1980
|
}
|
|
1980
1981
|
}
|
|
1982
|
+
function appendGitConfigEnv(env, key, value) {
|
|
1983
|
+
const existingCount = Number.parseInt(String(env.GIT_CONFIG_COUNT ?? "0").trim(), 10);
|
|
1984
|
+
const count = Number.isFinite(existingCount) && existingCount >= 0 ? existingCount : 0;
|
|
1985
|
+
for (let index = 0;index < count; index++) {
|
|
1986
|
+
if (String(env[`GIT_CONFIG_KEY_${index}`] ?? "") === key)
|
|
1987
|
+
return env;
|
|
1988
|
+
}
|
|
1989
|
+
return {
|
|
1990
|
+
...env,
|
|
1991
|
+
GIT_CONFIG_COUNT: String(count + 1),
|
|
1992
|
+
[`GIT_CONFIG_KEY_${count}`]: key,
|
|
1993
|
+
[`GIT_CONFIG_VALUE_${count}`]: value
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
function withWindowsGitSchannelEnv(env, platform = process.platform) {
|
|
1997
|
+
if (platform !== "win32")
|
|
1998
|
+
return env;
|
|
1999
|
+
if (parseBooleanFlag(env.PUSHPALS_DISABLE_WINDOWS_GIT_SCHANNEL) === true)
|
|
2000
|
+
return env;
|
|
2001
|
+
return appendGitConfigEnv(env, "http.sslBackend", "schannel");
|
|
2002
|
+
}
|
|
1981
2003
|
async function runGitWithEnv(args, cwd, env) {
|
|
1982
|
-
return await runCommandWithEnv(["git", ...args], cwd, env);
|
|
2004
|
+
return await runCommandWithEnv(["git", ...args], cwd, withWindowsGitSchannelEnv(env));
|
|
1983
2005
|
}
|
|
1984
2006
|
async function runGit(args, cwd) {
|
|
1985
2007
|
return await runGitWithEnv(args, cwd, {
|
|
@@ -2264,15 +2286,59 @@ function resolveRuntimePlatformKey() {
|
|
|
2264
2286
|
throw new Error(`Unsupported platform for embedded runtime binaries: ${process.platform}/${process.arch}`);
|
|
2265
2287
|
}
|
|
2266
2288
|
async function fetchLatestReleaseTag() {
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2289
|
+
try {
|
|
2290
|
+
const response = await fetchWithTimeout(`${GITHUB_API_URL}/releases/latest`, { headers: GITHUB_HEADERS }, 20000);
|
|
2291
|
+
if (!response.ok) {
|
|
2292
|
+
throw new Error(`Failed to resolve latest release tag (HTTP ${response.status})`);
|
|
2293
|
+
}
|
|
2294
|
+
const payload = await response.json();
|
|
2295
|
+
const tagName = String(payload.tag_name ?? "").trim();
|
|
2296
|
+
if (!tagName)
|
|
2297
|
+
throw new Error("Latest release payload did not include tag_name");
|
|
2298
|
+
return tagName;
|
|
2299
|
+
} catch (err) {
|
|
2300
|
+
const fallback = await fetchLatestReleaseTagWithGitFallback(err);
|
|
2301
|
+
if (fallback)
|
|
2302
|
+
return fallback;
|
|
2303
|
+
throw err;
|
|
2270
2304
|
}
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2305
|
+
}
|
|
2306
|
+
async function fetchLatestReleaseTagWithGitFallback(cause) {
|
|
2307
|
+
const message = String(cause instanceof Error ? cause.message : cause ?? "");
|
|
2308
|
+
if (process.platform !== "win32" || !/certificate|cert_|unable to verify|self[- ]signed|tls|ssl/i.test(message) && !/fetch failed/i.test(message)) {
|
|
2309
|
+
return null;
|
|
2310
|
+
}
|
|
2311
|
+
console.warn("[pushpals] Bun could not verify the GitHub API certificate; resolving latest release tag with Git instead.");
|
|
2312
|
+
const result = await runGitWithEnv([
|
|
2313
|
+
"ls-remote",
|
|
2314
|
+
"--tags",
|
|
2315
|
+
"--refs",
|
|
2316
|
+
`https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}.git`,
|
|
2317
|
+
"refs/tags/v*"
|
|
2318
|
+
], process.cwd(), {
|
|
2319
|
+
...process.env,
|
|
2320
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
2321
|
+
GCM_INTERACTIVE: "Never"
|
|
2322
|
+
});
|
|
2323
|
+
if (!result.ok)
|
|
2324
|
+
return null;
|
|
2325
|
+
const tags = result.stdout.split(/\r?\n/g).map((line) => line.trim().match(/refs\/tags\/(v\d+\.\d+\.\d+(?:[-.][0-9A-Za-z.-]+)?)$/)?.[1]).filter((tag) => Boolean(tag));
|
|
2326
|
+
return sortReleaseTagsDescending(tags)[0] ?? null;
|
|
2327
|
+
}
|
|
2328
|
+
function sortReleaseTagsDescending(tags) {
|
|
2329
|
+
return [...new Set(tags)].sort((a, b) => compareReleaseTags(b, a));
|
|
2330
|
+
}
|
|
2331
|
+
function compareReleaseTags(a, b) {
|
|
2332
|
+
const parse = (value) => String(value).replace(/^v/i, "").split(/[.-]/g).map((part) => Number.parseInt(part, 10)).map((part) => Number.isFinite(part) ? part : 0);
|
|
2333
|
+
const left = parse(a);
|
|
2334
|
+
const right = parse(b);
|
|
2335
|
+
const max = Math.max(left.length, right.length, 3);
|
|
2336
|
+
for (let index = 0;index < max; index++) {
|
|
2337
|
+
const delta = (left[index] ?? 0) - (right[index] ?? 0);
|
|
2338
|
+
if (delta !== 0)
|
|
2339
|
+
return delta;
|
|
2340
|
+
}
|
|
2341
|
+
return a.localeCompare(b);
|
|
2276
2342
|
}
|
|
2277
2343
|
function resolvePreferredRuntimeReleaseTag(explicitTag, env = process.env) {
|
|
2278
2344
|
const fromArg = String(explicitTag ?? "").trim();
|
|
@@ -2588,7 +2654,7 @@ function buildEmbeddedRuntimeEnv(baseEnv, opts) {
|
|
|
2588
2654
|
const existing = env[key];
|
|
2589
2655
|
return typeof existing !== "string" || existing.trim().length === 0;
|
|
2590
2656
|
})) : {};
|
|
2591
|
-
|
|
2657
|
+
const runtimeEnv = {
|
|
2592
2658
|
...inherited,
|
|
2593
2659
|
PUSHPALS_REPO_ROOT_OVERRIDE: opts.repoRoot,
|
|
2594
2660
|
PUSHPALS_PROJECT_ROOT_OVERRIDE: opts.repoRoot,
|
|
@@ -2609,6 +2675,7 @@ function buildEmbeddedRuntimeEnv(baseEnv, opts) {
|
|
|
2609
2675
|
...typeof env.PUSHPALS_DOCKER_BIN === "string" && env.PUSHPALS_DOCKER_BIN.trim() ? { PUSHPALS_DOCKER_BIN: env.PUSHPALS_DOCKER_BIN.trim() } : {},
|
|
2610
2676
|
...typeof env.PUSHPALS_DOCKER_BIN_ABSOLUTE === "string" && env.PUSHPALS_DOCKER_BIN_ABSOLUTE.trim() ? { PUSHPALS_DOCKER_BIN_ABSOLUTE: env.PUSHPALS_DOCKER_BIN_ABSOLUTE.trim() } : {}
|
|
2611
2677
|
};
|
|
2678
|
+
return withWindowsGitSchannelEnv(runtimeEnv, platform);
|
|
2612
2679
|
}
|
|
2613
2680
|
function parseBooleanFlag(raw) {
|
|
2614
2681
|
const normalized = String(raw ?? "").trim().toLowerCase();
|
|
@@ -2752,13 +2819,51 @@ function readRemoteBuddyAutonomousEngineState(logPath) {
|
|
|
2752
2819
|
async function downloadBinaryAsset(tag, assetName, outPath) {
|
|
2753
2820
|
console.log(`[pushpals] Downloading embedded runtime binary ${assetName} from ${tag}...`);
|
|
2754
2821
|
const url = `${GITHUB_RELEASE_URL}/${encodeURIComponent(tag)}/${assetName}`;
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2822
|
+
try {
|
|
2823
|
+
const response = await fetchWithTimeout(url, { headers: GITHUB_HEADERS }, 60000);
|
|
2824
|
+
if (!response.ok) {
|
|
2825
|
+
throw new Error(`Failed to download ${assetName} from ${tag} (HTTP ${response.status})`);
|
|
2826
|
+
}
|
|
2827
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
2828
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
2829
|
+
await Bun.write(outPath, bytes);
|
|
2830
|
+
return;
|
|
2831
|
+
} catch (err) {
|
|
2832
|
+
const fallback = await downloadBinaryAssetWithWindowsCurlFallback(url, outPath, err);
|
|
2833
|
+
if (fallback)
|
|
2834
|
+
return;
|
|
2835
|
+
throw err;
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
async function downloadBinaryAssetWithWindowsCurlFallback(url, outPath, cause) {
|
|
2839
|
+
if (process.platform !== "win32")
|
|
2840
|
+
return false;
|
|
2841
|
+
const message = String(cause instanceof Error ? cause.message : cause ?? "");
|
|
2842
|
+
if (!/certificate|cert_|unable to verify|self[- ]signed|tls|ssl/i.test(message) && !/fetch failed/i.test(message)) {
|
|
2843
|
+
return false;
|
|
2758
2844
|
}
|
|
2759
|
-
const
|
|
2845
|
+
const tmpPath = `${outPath}.download-${process.pid}-${Date.now()}.tmp`;
|
|
2760
2846
|
mkdirSync(dirname(outPath), { recursive: true });
|
|
2761
|
-
|
|
2847
|
+
rmSync2(tmpPath, { force: true });
|
|
2848
|
+
console.warn("[pushpals] Bun could not verify the GitHub release certificate; retrying download with Windows curl certificate handling.");
|
|
2849
|
+
const result = await runCommandWithEnv([
|
|
2850
|
+
"curl.exe",
|
|
2851
|
+
"--fail",
|
|
2852
|
+
"--location",
|
|
2853
|
+
"--silent",
|
|
2854
|
+
"--show-error",
|
|
2855
|
+
"--ssl-no-revoke",
|
|
2856
|
+
"--output",
|
|
2857
|
+
tmpPath,
|
|
2858
|
+
url
|
|
2859
|
+
], process.cwd(), process.env, 120000);
|
|
2860
|
+
if (!result.ok || !existsSync5(tmpPath)) {
|
|
2861
|
+
rmSync2(tmpPath, { force: true });
|
|
2862
|
+
const detail = result.stderr || result.stdout || `exit ${result.exitCode}`;
|
|
2863
|
+
throw new Error(`Windows curl fallback failed while downloading runtime binary: ${detail}`);
|
|
2864
|
+
}
|
|
2865
|
+
renameSync(tmpPath, outPath);
|
|
2866
|
+
return true;
|
|
2762
2867
|
}
|
|
2763
2868
|
async function ensureRuntimeBinaries(runtimeRoot, runtimeTag) {
|
|
2764
2869
|
const platformKey = resolveRuntimePlatformKey();
|