jorgex-stack 1.9.63 → 1.9.64
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/cli.js +475 -436
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4330,7 +4330,7 @@ var init_pi = __esm({
|
|
|
4330
4330
|
|
|
4331
4331
|
// src/cli.ts
|
|
4332
4332
|
import * as p6 from "@clack/prompts";
|
|
4333
|
-
import
|
|
4333
|
+
import fs44 from "fs";
|
|
4334
4334
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
4335
4335
|
|
|
4336
4336
|
// src/install.ts
|
|
@@ -12734,8 +12734,8 @@ init_model_map();
|
|
|
12734
12734
|
|
|
12735
12735
|
// src/lib/pi-runtime.ts
|
|
12736
12736
|
import os6 from "os";
|
|
12737
|
-
import
|
|
12738
|
-
import
|
|
12737
|
+
import path48 from "path";
|
|
12738
|
+
import fs40 from "fs";
|
|
12739
12739
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
12740
12740
|
|
|
12741
12741
|
// src/lib/pi-runtime-pin.json
|
|
@@ -12789,8 +12789,8 @@ init_paths();
|
|
|
12789
12789
|
|
|
12790
12790
|
// src/lib/pi-install-preflight.ts
|
|
12791
12791
|
init_npm_provider();
|
|
12792
|
-
import
|
|
12793
|
-
import
|
|
12792
|
+
import fs36 from "fs";
|
|
12793
|
+
import path44 from "path";
|
|
12794
12794
|
|
|
12795
12795
|
// src/lib/pi-candidate.ts
|
|
12796
12796
|
import fs33 from "fs";
|
|
@@ -13490,18 +13490,121 @@ async function stageVerifiedPiTarball(input, run) {
|
|
|
13490
13490
|
return { stageDir, evidence, sourceAlias };
|
|
13491
13491
|
}
|
|
13492
13492
|
|
|
13493
|
-
// src/lib/pi-
|
|
13493
|
+
// src/lib/pi-host-version.ts
|
|
13494
|
+
import fs35 from "fs";
|
|
13495
|
+
import path43 from "path";
|
|
13494
13496
|
var PI_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
|
|
13497
|
+
function invalidManagedPi(diagnostic) {
|
|
13498
|
+
return { version: null, diagnostic };
|
|
13499
|
+
}
|
|
13500
|
+
function readJsonFile(file) {
|
|
13501
|
+
try {
|
|
13502
|
+
const stat = fs35.lstatSync(file, { throwIfNoEntry: false });
|
|
13503
|
+
if (!stat?.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024) return null;
|
|
13504
|
+
return JSON.parse(fs35.readFileSync(file, "utf8"));
|
|
13505
|
+
} catch {
|
|
13506
|
+
return null;
|
|
13507
|
+
}
|
|
13508
|
+
}
|
|
13509
|
+
function piPackageVersion(file) {
|
|
13510
|
+
try {
|
|
13511
|
+
const value = readJsonFile(file);
|
|
13512
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
|
|
13513
|
+
const packageName = Reflect.get(value, "name");
|
|
13514
|
+
const version = Reflect.get(value, "version");
|
|
13515
|
+
return packageName === PI_PACKAGE_NAME && typeof version === "string" && version !== "" && !/\s/.test(version) ? version : null;
|
|
13516
|
+
} catch {
|
|
13517
|
+
return null;
|
|
13518
|
+
}
|
|
13519
|
+
}
|
|
13520
|
+
function managedPiVersion(executable, resolved2) {
|
|
13521
|
+
const binDir = path43.dirname(resolved2);
|
|
13522
|
+
if (path43.basename(resolved2) !== "pi" || path43.basename(binDir) !== "bin") {
|
|
13523
|
+
return invalidManagedPi("launcher gestionado de Pi no reconocido");
|
|
13524
|
+
}
|
|
13525
|
+
const agentDir = path43.dirname(binDir);
|
|
13526
|
+
const installDir = path43.join(agentDir, "install");
|
|
13527
|
+
try {
|
|
13528
|
+
if (!fs35.lstatSync(executable).isSymbolicLink()) {
|
|
13529
|
+
return invalidManagedPi("el entrypoint gestionado de Pi no es un symlink");
|
|
13530
|
+
}
|
|
13531
|
+
const metadata = readJsonFile(path43.join(installDir, "managed-install.json"));
|
|
13532
|
+
if (metadata === null || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
13533
|
+
return invalidManagedPi("install/managed-install.json falta o no es JSON v\xE1lido");
|
|
13534
|
+
}
|
|
13535
|
+
const entrypoint = Reflect.get(metadata, "entrypoint");
|
|
13536
|
+
if (Reflect.get(metadata, "kind") !== "pi-managed-install" || Reflect.get(metadata, "schemaVersion") !== 1 || Reflect.get(metadata, "layout") !== "releases-v1" || entrypoint === null || typeof entrypoint !== "object" || Array.isArray(entrypoint) || Reflect.get(entrypoint, "type") !== "symlink" || Reflect.get(entrypoint, "path") !== executable) {
|
|
13537
|
+
return invalidManagedPi("install/managed-install.json no coincide con el entrypoint de Pi");
|
|
13538
|
+
}
|
|
13539
|
+
const currentPath = path43.join(installDir, "current-version");
|
|
13540
|
+
const currentStat = fs35.lstatSync(currentPath, { throwIfNoEntry: false });
|
|
13541
|
+
if (!currentStat?.isFile() || currentStat.isSymbolicLink() || currentStat.size > 128) {
|
|
13542
|
+
return invalidManagedPi("install/current-version falta o no es un archivo regular acotado");
|
|
13543
|
+
}
|
|
13544
|
+
const version = fs35.readFileSync(currentPath, "utf8").trim();
|
|
13545
|
+
if (version === "." || version === ".." || !/^[0-9A-Za-z._+-]+$/.test(version)) {
|
|
13546
|
+
return invalidManagedPi("install/current-version contiene una versi\xF3n inv\xE1lida");
|
|
13547
|
+
}
|
|
13548
|
+
const releaseDir = path43.join(installDir, "releases", version);
|
|
13549
|
+
if (fs35.realpathSync(releaseDir) !== releaseDir) {
|
|
13550
|
+
return invalidManagedPi("install/releases contiene un enlace fuera del release gestionado");
|
|
13551
|
+
}
|
|
13552
|
+
const packageDir = path43.join(releaseDir, "node_modules", "@earendil-works", "pi-coding-agent");
|
|
13553
|
+
if (fs35.realpathSync(packageDir) !== packageDir) {
|
|
13554
|
+
return invalidManagedPi("el paquete Pi del release gestionado es un symlink");
|
|
13555
|
+
}
|
|
13556
|
+
const packageVersion = piPackageVersion(path43.join(packageDir, "package.json"));
|
|
13557
|
+
return packageVersion === version ? { version, diagnostic: null } : invalidManagedPi("el manifest de @earendil-works/pi-coding-agent no coincide con install/current-version");
|
|
13558
|
+
} catch {
|
|
13559
|
+
return invalidManagedPi("no se pudo leer la metadata del release Pi gestionado");
|
|
13560
|
+
}
|
|
13561
|
+
}
|
|
13562
|
+
function hasManagedPiMarker(resolved2) {
|
|
13563
|
+
const binDir = path43.dirname(resolved2);
|
|
13564
|
+
if (path43.basename(resolved2) !== "pi" || path43.basename(binDir) !== "bin") return false;
|
|
13565
|
+
const installDir = path43.join(path43.dirname(binDir), "install");
|
|
13566
|
+
try {
|
|
13567
|
+
return fs35.lstatSync(path43.join(installDir, "managed-install.json"), { throwIfNoEntry: false }) !== void 0 || fs35.lstatSync(path43.join(installDir, "current-version"), { throwIfNoEntry: false }) !== void 0;
|
|
13568
|
+
} catch {
|
|
13569
|
+
return true;
|
|
13570
|
+
}
|
|
13571
|
+
}
|
|
13572
|
+
function inspectPiHostVersion(executable) {
|
|
13573
|
+
const absoluteExecutable = path43.resolve(executable);
|
|
13574
|
+
let resolved2;
|
|
13575
|
+
try {
|
|
13576
|
+
resolved2 = fs35.realpathSync(absoluteExecutable);
|
|
13577
|
+
} catch {
|
|
13578
|
+
return { version: null, diagnostic: "no se pudo resolver el ejecutable Pi" };
|
|
13579
|
+
}
|
|
13580
|
+
if (hasManagedPiMarker(resolved2)) return managedPiVersion(absoluteExecutable, resolved2);
|
|
13581
|
+
let current = path43.dirname(resolved2);
|
|
13582
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
13583
|
+
for (const manifest of [
|
|
13584
|
+
path43.join(current, "package.json"),
|
|
13585
|
+
path43.join(current, "node_modules", "@earendil-works", "pi-coding-agent", "package.json")
|
|
13586
|
+
]) {
|
|
13587
|
+
const version = piPackageVersion(manifest);
|
|
13588
|
+
if (version !== null) return { version, diagnostic: null };
|
|
13589
|
+
}
|
|
13590
|
+
const parent = path43.dirname(current);
|
|
13591
|
+
if (parent === current) break;
|
|
13592
|
+
current = parent;
|
|
13593
|
+
}
|
|
13594
|
+
return { version: null, diagnostic: "no se encontr\xF3 el manifest del paquete Pi instalado" };
|
|
13595
|
+
}
|
|
13596
|
+
|
|
13597
|
+
// src/lib/pi-install-preflight.ts
|
|
13495
13598
|
function fail9(message) {
|
|
13496
13599
|
throw new Error(`pi-install-preflight: ${message}`);
|
|
13497
13600
|
}
|
|
13498
13601
|
function isStrictChild3(child, root) {
|
|
13499
|
-
const rel =
|
|
13500
|
-
return rel !== "" && rel !== ".." && !rel.startsWith(`..${
|
|
13602
|
+
const rel = path44.relative(path44.resolve(root), path44.resolve(child));
|
|
13603
|
+
return rel !== "" && rel !== ".." && !rel.startsWith(`..${path44.sep}`) && !path44.isAbsolute(rel);
|
|
13501
13604
|
}
|
|
13502
13605
|
function lstatOrNull4(p7) {
|
|
13503
13606
|
try {
|
|
13504
|
-
return
|
|
13607
|
+
return fs36.lstatSync(p7);
|
|
13505
13608
|
} catch {
|
|
13506
13609
|
return null;
|
|
13507
13610
|
}
|
|
@@ -13517,24 +13620,24 @@ function validatePaths(paths) {
|
|
|
13517
13620
|
fail9("paths must be an object");
|
|
13518
13621
|
}
|
|
13519
13622
|
const { homeDir, agentDir, piExecutable, downloadsDir } = paths;
|
|
13520
|
-
if (typeof homeDir !== "string" || homeDir === "" || !
|
|
13623
|
+
if (typeof homeDir !== "string" || homeDir === "" || !path44.isAbsolute(homeDir)) {
|
|
13521
13624
|
fail9("homeDir must be a non-empty absolute path");
|
|
13522
13625
|
}
|
|
13523
|
-
if (typeof agentDir !== "string" || agentDir === "" || !
|
|
13626
|
+
if (typeof agentDir !== "string" || agentDir === "" || !path44.isAbsolute(agentDir)) {
|
|
13524
13627
|
fail9("agentDir must be a non-empty absolute path");
|
|
13525
13628
|
}
|
|
13526
|
-
if (typeof piExecutable !== "string" || piExecutable === "" || !
|
|
13629
|
+
if (typeof piExecutable !== "string" || piExecutable === "" || !path44.isAbsolute(piExecutable)) {
|
|
13527
13630
|
fail9("piExecutable must be a non-empty absolute path");
|
|
13528
13631
|
}
|
|
13529
13632
|
if (piExecutable === "npm") {
|
|
13530
13633
|
fail9("piExecutable must be the detected Pi CLI, never npm");
|
|
13531
13634
|
}
|
|
13532
|
-
if (typeof downloadsDir !== "string" || downloadsDir === "" || !
|
|
13635
|
+
if (typeof downloadsDir !== "string" || downloadsDir === "" || !path44.isAbsolute(downloadsDir)) {
|
|
13533
13636
|
fail9("downloadsDir must be a non-empty absolute path");
|
|
13534
13637
|
}
|
|
13535
|
-
const homeResolved =
|
|
13536
|
-
const agentResolved =
|
|
13537
|
-
const downloadsResolved =
|
|
13638
|
+
const homeResolved = path44.resolve(homeDir);
|
|
13639
|
+
const agentResolved = path44.resolve(agentDir);
|
|
13640
|
+
const downloadsResolved = path44.resolve(downloadsDir);
|
|
13538
13641
|
assertRealDir2(homeResolved, "homeDir");
|
|
13539
13642
|
assertRealDir2(agentResolved, "agentDir");
|
|
13540
13643
|
assertRealDir2(downloadsResolved, "downloadsDir");
|
|
@@ -13562,43 +13665,6 @@ function validateDeps(deps) {
|
|
|
13562
13665
|
}
|
|
13563
13666
|
return { fetchImpl, run };
|
|
13564
13667
|
}
|
|
13565
|
-
function readJsonFile(file) {
|
|
13566
|
-
return JSON.parse(fs35.readFileSync(file, "utf8"));
|
|
13567
|
-
}
|
|
13568
|
-
function detectPiHostVersion(piExecutable) {
|
|
13569
|
-
let current;
|
|
13570
|
-
try {
|
|
13571
|
-
current = path43.dirname(fs35.realpathSync(piExecutable));
|
|
13572
|
-
} catch {
|
|
13573
|
-
fail9(`cannot resolve Pi executable: ${piExecutable}`);
|
|
13574
|
-
}
|
|
13575
|
-
for (let depth = 0; depth < 8; depth++) {
|
|
13576
|
-
const manifests = [
|
|
13577
|
-
path43.join(current, "package.json"),
|
|
13578
|
-
path43.join(current, "node_modules", PI_PACKAGE_NAME, "package.json")
|
|
13579
|
-
];
|
|
13580
|
-
for (const manifest of manifests) {
|
|
13581
|
-
let parsed;
|
|
13582
|
-
try {
|
|
13583
|
-
parsed = readJsonFile(manifest);
|
|
13584
|
-
} catch {
|
|
13585
|
-
continue;
|
|
13586
|
-
}
|
|
13587
|
-
if (parsed !== null && typeof parsed === "object" && Reflect.get(parsed, "name") === PI_PACKAGE_NAME && typeof Reflect.get(parsed, "version") === "string") {
|
|
13588
|
-
const version = Reflect.get(parsed, "version");
|
|
13589
|
-
if (version !== "" && !/\s/.test(version)) {
|
|
13590
|
-
return version;
|
|
13591
|
-
}
|
|
13592
|
-
}
|
|
13593
|
-
}
|
|
13594
|
-
const parent = path43.dirname(current);
|
|
13595
|
-
if (parent === current) {
|
|
13596
|
-
break;
|
|
13597
|
-
}
|
|
13598
|
-
current = parent;
|
|
13599
|
-
}
|
|
13600
|
-
fail9(`cannot detect Pi host version from executable: ${piExecutable}`);
|
|
13601
|
-
}
|
|
13602
13668
|
async function preparePiManagedInstall(paths, deps) {
|
|
13603
13669
|
const { homeDir, agentDir, piExecutable, downloadsDir } = validatePaths(paths);
|
|
13604
13670
|
const { fetchImpl, run } = validateDeps(deps);
|
|
@@ -13627,8 +13693,8 @@ async function preparePiManagedInstall(paths, deps) {
|
|
|
13627
13693
|
`pi-install-preflight: producer commit resolution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
13628
13694
|
);
|
|
13629
13695
|
}
|
|
13630
|
-
const downloadsResolved =
|
|
13631
|
-
const destination =
|
|
13696
|
+
const downloadsResolved = path44.resolve(downloadsDir);
|
|
13697
|
+
const destination = path44.join(downloadsResolved, `jorgex-pi-${release.version}.tgz`);
|
|
13632
13698
|
if (!isStrictChild3(destination, downloadsResolved)) {
|
|
13633
13699
|
fail9(`tarball destination escapes downloadsDir: ${destination}`);
|
|
13634
13700
|
}
|
|
@@ -13657,7 +13723,8 @@ async function preparePiManagedInstall(paths, deps) {
|
|
|
13657
13723
|
} catch (error) {
|
|
13658
13724
|
throw error;
|
|
13659
13725
|
}
|
|
13660
|
-
const
|
|
13726
|
+
const hostInspection = inspectPiHostVersion(piExecutable);
|
|
13727
|
+
const hostVersion = hostInspection.version ?? fail9(`cannot detect Pi host version: ${hostInspection.diagnostic ?? "unknown reason"}`);
|
|
13661
13728
|
let candidate;
|
|
13662
13729
|
try {
|
|
13663
13730
|
candidate = await buildStagedPiCandidate({
|
|
@@ -13679,16 +13746,16 @@ import { createHash as createHash8 } from "crypto";
|
|
|
13679
13746
|
|
|
13680
13747
|
// src/lib/pi-private-release.ts
|
|
13681
13748
|
import crypto2 from "crypto";
|
|
13682
|
-
import
|
|
13683
|
-
import
|
|
13749
|
+
import fs37 from "fs";
|
|
13750
|
+
import path45 from "path";
|
|
13684
13751
|
var RELEASE_ID_PATTERN = /^[0-9a-f]{64}$/;
|
|
13685
13752
|
var EXPECTED_ENTRY = "jorgex-pi";
|
|
13686
13753
|
function resolved(p7) {
|
|
13687
|
-
return
|
|
13754
|
+
return path45.resolve(p7);
|
|
13688
13755
|
}
|
|
13689
13756
|
function isStrictChild4(child, root) {
|
|
13690
|
-
const rel =
|
|
13691
|
-
return rel !== "" && rel !== ".." && !rel.startsWith(`..${
|
|
13757
|
+
const rel = path45.relative(resolved(root), resolved(child));
|
|
13758
|
+
return rel !== "" && rel !== ".." && !rel.startsWith(`..${path45.sep}`) && !path45.isAbsolute(rel);
|
|
13692
13759
|
}
|
|
13693
13760
|
function assertStrictChild(child, root, label) {
|
|
13694
13761
|
if (!isStrictChild4(child, root)) {
|
|
@@ -13697,7 +13764,7 @@ function assertStrictChild(child, root, label) {
|
|
|
13697
13764
|
}
|
|
13698
13765
|
function lstatOrNull5(p7) {
|
|
13699
13766
|
try {
|
|
13700
|
-
return
|
|
13767
|
+
return fs37.lstatSync(p7);
|
|
13701
13768
|
} catch {
|
|
13702
13769
|
return null;
|
|
13703
13770
|
}
|
|
@@ -13719,7 +13786,7 @@ function assertAncestorsClean(dir, stop, label) {
|
|
|
13719
13786
|
throw new Error(`${label} ancestor is a symlink: ${cur}`);
|
|
13720
13787
|
}
|
|
13721
13788
|
if (cur === stopResolved) break;
|
|
13722
|
-
const parent =
|
|
13789
|
+
const parent = path45.dirname(cur);
|
|
13723
13790
|
if (parent === cur) break;
|
|
13724
13791
|
cur = parent;
|
|
13725
13792
|
if (cur.length < stopResolved.length) break;
|
|
@@ -13731,7 +13798,7 @@ function assertFilePathClean(file, stop, label) {
|
|
|
13731
13798
|
if (st !== null && st.isSymbolicLink()) {
|
|
13732
13799
|
throw new Error(`${label} is a symlink: ${file}`);
|
|
13733
13800
|
}
|
|
13734
|
-
assertAncestorsClean(
|
|
13801
|
+
assertAncestorsClean(path45.dirname(resolved(file)), stop, label);
|
|
13735
13802
|
}
|
|
13736
13803
|
function assertDirClean(dir, stop, label) {
|
|
13737
13804
|
assertStrictChild(dir, stop, label);
|
|
@@ -13743,17 +13810,17 @@ function assertDirClean(dir, stop, label) {
|
|
|
13743
13810
|
}
|
|
13744
13811
|
function assertLinkInsideRoot(linkPath, allowedRoot, label, finalKind) {
|
|
13745
13812
|
const allowedResolved = resolved(allowedRoot);
|
|
13746
|
-
const linkParent =
|
|
13813
|
+
const linkParent = path45.dirname(resolved(linkPath));
|
|
13747
13814
|
if (linkParent !== allowedResolved && !isStrictChild4(linkParent, allowedResolved)) {
|
|
13748
13815
|
throw new Error(`${label} escapes owner root: ${linkPath}`);
|
|
13749
13816
|
}
|
|
13750
13817
|
let target;
|
|
13751
13818
|
try {
|
|
13752
|
-
target =
|
|
13819
|
+
target = fs37.readlinkSync(linkPath);
|
|
13753
13820
|
} catch {
|
|
13754
13821
|
throw new Error(`${label} is broken or unreadable: ${linkPath}`);
|
|
13755
13822
|
}
|
|
13756
|
-
if (target === "" ||
|
|
13823
|
+
if (target === "" || path45.isAbsolute(target)) {
|
|
13757
13824
|
throw new Error(`${label} must be a relative symlink: ${linkPath}`);
|
|
13758
13825
|
}
|
|
13759
13826
|
const parentStat = lstatOrNull5(linkParent);
|
|
@@ -13769,7 +13836,7 @@ function assertLinkInsideRoot(linkPath, allowedRoot, label, finalKind) {
|
|
|
13769
13836
|
const part = ops[i];
|
|
13770
13837
|
const isLast = i === ops.length - 1;
|
|
13771
13838
|
if (part === "..") {
|
|
13772
|
-
cur =
|
|
13839
|
+
cur = path45.dirname(cur);
|
|
13773
13840
|
if (cur !== allowedResolved && !isStrictChild4(cur, allowedResolved)) {
|
|
13774
13841
|
throw new Error(`${label} escapes owner root: ${linkPath} -> ${target}`);
|
|
13775
13842
|
}
|
|
@@ -13792,7 +13859,7 @@ function assertLinkInsideRoot(linkPath, allowedRoot, label, finalKind) {
|
|
|
13792
13859
|
}
|
|
13793
13860
|
continue;
|
|
13794
13861
|
}
|
|
13795
|
-
const next =
|
|
13862
|
+
const next = path45.join(cur, part);
|
|
13796
13863
|
if (next !== allowedResolved && !isStrictChild4(next, allowedResolved)) {
|
|
13797
13864
|
throw new Error(`${label} escapes owner root: ${linkPath} -> ${target}`);
|
|
13798
13865
|
}
|
|
@@ -13832,12 +13899,12 @@ function validateStageTree(stagedNpm) {
|
|
|
13832
13899
|
const dir = stack.pop();
|
|
13833
13900
|
let entries;
|
|
13834
13901
|
try {
|
|
13835
|
-
entries =
|
|
13902
|
+
entries = fs37.readdirSync(dir, { withFileTypes: true });
|
|
13836
13903
|
} catch {
|
|
13837
13904
|
throw new Error(`staged tree unreadable: ${dir}`);
|
|
13838
13905
|
}
|
|
13839
13906
|
for (const entry of entries) {
|
|
13840
|
-
const full =
|
|
13907
|
+
const full = path45.join(dir, entry.name);
|
|
13841
13908
|
if (entry.isSymbolicLink()) {
|
|
13842
13909
|
assertInternalSymlink(full, root, "staged symlink");
|
|
13843
13910
|
continue;
|
|
@@ -13849,39 +13916,39 @@ function validateStageTree(stagedNpm) {
|
|
|
13849
13916
|
}
|
|
13850
13917
|
}
|
|
13851
13918
|
function atomicWritePrivate(target, content) {
|
|
13852
|
-
const dir =
|
|
13853
|
-
|
|
13854
|
-
const tmp =
|
|
13919
|
+
const dir = path45.dirname(resolved(target));
|
|
13920
|
+
fs37.mkdirSync(dir, { recursive: true });
|
|
13921
|
+
const tmp = path45.join(dir, `.tmp-${crypto2.randomBytes(16).toString("hex")}`);
|
|
13855
13922
|
let fd = null;
|
|
13856
13923
|
try {
|
|
13857
|
-
fd =
|
|
13858
|
-
|
|
13859
|
-
|
|
13860
|
-
|
|
13924
|
+
fd = fs37.openSync(tmp, "wx", 384);
|
|
13925
|
+
fs37.writeFileSync(fd, content, "utf8");
|
|
13926
|
+
fs37.fsyncSync(fd);
|
|
13927
|
+
fs37.closeSync(fd);
|
|
13861
13928
|
fd = null;
|
|
13862
13929
|
} finally {
|
|
13863
13930
|
if (fd !== null) {
|
|
13864
13931
|
try {
|
|
13865
|
-
|
|
13932
|
+
fs37.closeSync(fd);
|
|
13866
13933
|
} catch {
|
|
13867
13934
|
}
|
|
13868
|
-
|
|
13935
|
+
fs37.rmSync(tmp, { force: true });
|
|
13869
13936
|
}
|
|
13870
13937
|
}
|
|
13871
13938
|
const tmpStat = lstatOrNull5(tmp);
|
|
13872
13939
|
if (tmpStat === null || !tmpStat.isFile()) {
|
|
13873
13940
|
try {
|
|
13874
|
-
|
|
13941
|
+
fs37.rmSync(tmp, { force: true });
|
|
13875
13942
|
} catch {
|
|
13876
13943
|
failIncomplete(`cannot clean private temp (recovery incomplete): ${tmp}`);
|
|
13877
13944
|
}
|
|
13878
13945
|
throw new Error(`private temp is not a regular file: ${target}`);
|
|
13879
13946
|
}
|
|
13880
13947
|
try {
|
|
13881
|
-
|
|
13948
|
+
fs37.renameSync(tmp, target);
|
|
13882
13949
|
} catch (err) {
|
|
13883
13950
|
try {
|
|
13884
|
-
|
|
13951
|
+
fs37.rmSync(tmp, { force: true });
|
|
13885
13952
|
} catch {
|
|
13886
13953
|
const original = err instanceof Error ? err.message : String(err ?? "rename failed");
|
|
13887
13954
|
failIncomplete(`cannot clean private temp after rename failure (recovery incomplete): ${tmp}: ${original}`);
|
|
@@ -13898,7 +13965,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
13898
13965
|
if (typeof input.homeDir !== "string" || input.homeDir === "") {
|
|
13899
13966
|
throw new Error(`homeDir must be a non-empty absolute path`);
|
|
13900
13967
|
}
|
|
13901
|
-
if (!
|
|
13968
|
+
if (!path45.isAbsolute(input.homeDir)) {
|
|
13902
13969
|
throw new Error(`homeDir must be absolute: ${input.homeDir}`);
|
|
13903
13970
|
}
|
|
13904
13971
|
if (!RELEASE_ID_PATTERN.test(releaseId)) {
|
|
@@ -13934,22 +14001,22 @@ async function activateVerifiedPiRelease(input) {
|
|
|
13934
14001
|
if (stageStat === null || !stageStat.isDirectory() || stageStat.isSymbolicLink()) {
|
|
13935
14002
|
throw new Error(`stageDir must be a real directory: ${input.stageDir}`);
|
|
13936
14003
|
}
|
|
13937
|
-
const settingsPath =
|
|
13938
|
-
const npmDir =
|
|
13939
|
-
const nodeModules =
|
|
13940
|
-
const linkPath =
|
|
13941
|
-
const stagedNpm =
|
|
13942
|
-
const stagedModules =
|
|
13943
|
-
const stagedEntry =
|
|
13944
|
-
const releaseRoot =
|
|
13945
|
-
const releaseDir =
|
|
13946
|
-
const managedRoot =
|
|
13947
|
-
const markerPath =
|
|
13948
|
-
const lockPath =
|
|
13949
|
-
const backupDir =
|
|
13950
|
-
const backupEntry =
|
|
13951
|
-
const backupSettings =
|
|
13952
|
-
const backupReceipt =
|
|
14004
|
+
const settingsPath = path45.join(agentDir, "settings.json");
|
|
14005
|
+
const npmDir = path45.join(agentDir, "npm");
|
|
14006
|
+
const nodeModules = path45.join(npmDir, "node_modules");
|
|
14007
|
+
const linkPath = path45.join(nodeModules, EXPECTED_ENTRY);
|
|
14008
|
+
const stagedNpm = path45.join(stageDir, "npm");
|
|
14009
|
+
const stagedModules = path45.join(stagedNpm, "node_modules");
|
|
14010
|
+
const stagedEntry = path45.join(stagedModules, EXPECTED_ENTRY);
|
|
14011
|
+
const releaseRoot = path45.join(npmDir, "jorgex-pi-managed", "releases");
|
|
14012
|
+
const releaseDir = path45.join(releaseRoot, releaseId);
|
|
14013
|
+
const managedRoot = path45.join(npmDir, "jorgex-pi-managed");
|
|
14014
|
+
const markerPath = path45.join(managedRoot, "active-transaction.json");
|
|
14015
|
+
const lockPath = path45.join(managedRoot, "transaction.lock");
|
|
14016
|
+
const backupDir = path45.join(stageDir, ".activate-backup");
|
|
14017
|
+
const backupEntry = path45.join(backupDir, "entry");
|
|
14018
|
+
const backupSettings = path45.join(backupDir, "settings.json");
|
|
14019
|
+
const backupReceipt = path45.join(backupDir, "receipt.json");
|
|
13953
14020
|
const expectedTarget = `../jorgex-pi-managed/releases/${releaseId}/node_modules/${EXPECTED_ENTRY}`;
|
|
13954
14021
|
assertStrictChild(agentDir, homeDir, "agentDir");
|
|
13955
14022
|
assertStrictChild(receiptPath, homeDir, "receiptPath");
|
|
@@ -14002,7 +14069,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14002
14069
|
let oldEntryExisted = false;
|
|
14003
14070
|
if (linkStat !== null) {
|
|
14004
14071
|
oldEntryExisted = true;
|
|
14005
|
-
assertAncestorsClean(
|
|
14072
|
+
assertAncestorsClean(path45.dirname(linkPath), homeDir, "managed entry");
|
|
14006
14073
|
if (linkStat.isSymbolicLink()) {
|
|
14007
14074
|
assertManagedEntrySymlink(linkPath, npmDir, "managed entry");
|
|
14008
14075
|
} else if (!linkStat.isDirectory()) {
|
|
@@ -14019,10 +14086,10 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14019
14086
|
let oldReceipt = null;
|
|
14020
14087
|
try {
|
|
14021
14088
|
if (lstatOrNull5(settingsPath) !== null) {
|
|
14022
|
-
oldSettings =
|
|
14089
|
+
oldSettings = fs37.readFileSync(settingsPath, "utf8");
|
|
14023
14090
|
}
|
|
14024
14091
|
if (lstatOrNull5(receiptPath) !== null) {
|
|
14025
|
-
oldReceipt =
|
|
14092
|
+
oldReceipt = fs37.readFileSync(receiptPath, "utf8");
|
|
14026
14093
|
}
|
|
14027
14094
|
} catch {
|
|
14028
14095
|
throw new Error(`cannot read previous settings/receipt`);
|
|
@@ -14034,7 +14101,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14034
14101
|
const ownedBackupFiles = /* @__PURE__ */ new Map();
|
|
14035
14102
|
const releaseLock = () => {
|
|
14036
14103
|
if (!lockAcquired) return;
|
|
14037
|
-
|
|
14104
|
+
fs37.rmSync(lockPath, { force: true });
|
|
14038
14105
|
lockAcquired = false;
|
|
14039
14106
|
};
|
|
14040
14107
|
const captureBackupDirIdentity = () => {
|
|
@@ -14060,7 +14127,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14060
14127
|
if (dirStat.dev !== backupDirDev || dirStat.ino !== backupDirIno) return "backup dir replaced";
|
|
14061
14128
|
let entries;
|
|
14062
14129
|
try {
|
|
14063
|
-
entries =
|
|
14130
|
+
entries = fs37.readdirSync(backupDir);
|
|
14064
14131
|
} catch {
|
|
14065
14132
|
return "cannot list backup";
|
|
14066
14133
|
}
|
|
@@ -14070,7 +14137,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14070
14137
|
if (!allowed.has(entry)) return `unknown backup entry: ${entry}`;
|
|
14071
14138
|
}
|
|
14072
14139
|
for (const entry of entries) {
|
|
14073
|
-
const full = resolved(
|
|
14140
|
+
const full = resolved(path45.join(backupDir, entry));
|
|
14074
14141
|
const owned = ownedBackupFiles.get(full);
|
|
14075
14142
|
if (!owned) return `unowned backup file: ${entry}`;
|
|
14076
14143
|
const st = lstatOrNull5(full);
|
|
@@ -14078,14 +14145,14 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14078
14145
|
if (st.dev !== owned.dev || st.ino !== owned.ino) return `backup file replaced: ${entry}`;
|
|
14079
14146
|
let cur;
|
|
14080
14147
|
try {
|
|
14081
|
-
cur =
|
|
14148
|
+
cur = fs37.readFileSync(full, "utf8");
|
|
14082
14149
|
} catch {
|
|
14083
14150
|
return `cannot read backup file: ${entry}`;
|
|
14084
14151
|
}
|
|
14085
14152
|
if (cur !== owned.content) return `backup file bytes drifted: ${entry}`;
|
|
14086
14153
|
}
|
|
14087
14154
|
for (const [fullPath] of ownedBackupFiles) {
|
|
14088
|
-
const base =
|
|
14155
|
+
const base = path45.basename(fullPath);
|
|
14089
14156
|
if (!entries.includes(base)) return `owned backup file missing: ${base}`;
|
|
14090
14157
|
}
|
|
14091
14158
|
return null;
|
|
@@ -14107,7 +14174,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14107
14174
|
}
|
|
14108
14175
|
let cur;
|
|
14109
14176
|
try {
|
|
14110
|
-
cur =
|
|
14177
|
+
cur = fs37.readFileSync(fullPath, "utf8");
|
|
14111
14178
|
} catch {
|
|
14112
14179
|
failIncomplete(
|
|
14113
14180
|
`backup drifted during cleanup, preserving foreign state (recovery incomplete): ${fullPath}: ${original}`
|
|
@@ -14119,7 +14186,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14119
14186
|
`backup drifted during cleanup, preserving foreign state (recovery incomplete): ${fullPath}: ${original}`
|
|
14120
14187
|
);
|
|
14121
14188
|
}
|
|
14122
|
-
|
|
14189
|
+
fs37.unlinkSync(fullPath);
|
|
14123
14190
|
}
|
|
14124
14191
|
} catch (err) {
|
|
14125
14192
|
if (err instanceof Error && err.recovery === "incomplete") throw err;
|
|
@@ -14129,13 +14196,13 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14129
14196
|
);
|
|
14130
14197
|
}
|
|
14131
14198
|
try {
|
|
14132
|
-
const remaining =
|
|
14199
|
+
const remaining = fs37.readdirSync(backupDir);
|
|
14133
14200
|
if (remaining.length !== 0) {
|
|
14134
14201
|
failIncomplete(
|
|
14135
14202
|
`backup dir not empty after owned cleanup, preserving foreign state (recovery incomplete): ${backupDir}: ${original}`
|
|
14136
14203
|
);
|
|
14137
14204
|
}
|
|
14138
|
-
|
|
14205
|
+
fs37.rmdirSync(backupDir);
|
|
14139
14206
|
} catch (err) {
|
|
14140
14207
|
if (err instanceof Error && err.recovery === "incomplete") throw err;
|
|
14141
14208
|
const msg = err instanceof Error ? err.message : String(err ?? "rmdir failed");
|
|
@@ -14144,7 +14211,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14144
14211
|
);
|
|
14145
14212
|
}
|
|
14146
14213
|
try {
|
|
14147
|
-
|
|
14214
|
+
fs37.rmSync(markerPath, { force: true });
|
|
14148
14215
|
releaseLock();
|
|
14149
14216
|
} catch {
|
|
14150
14217
|
failIncomplete(`cannot clear transaction state after rollback: ${original}`);
|
|
@@ -14160,7 +14227,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14160
14227
|
if (!backupCreated) {
|
|
14161
14228
|
const problems = [];
|
|
14162
14229
|
try {
|
|
14163
|
-
|
|
14230
|
+
fs37.rmSync(markerPath, { force: true });
|
|
14164
14231
|
} catch {
|
|
14165
14232
|
problems.push("cannot remove marker");
|
|
14166
14233
|
}
|
|
@@ -14179,7 +14246,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14179
14246
|
if (err instanceof Error) throw err;
|
|
14180
14247
|
throw new Error(original);
|
|
14181
14248
|
};
|
|
14182
|
-
|
|
14249
|
+
fs37.mkdirSync(managedRoot, { recursive: true });
|
|
14183
14250
|
assertAncestorsClean(managedRoot, homeDir, "managed root");
|
|
14184
14251
|
const managedRootStat = lstatOrNull5(managedRoot);
|
|
14185
14252
|
if (managedRootStat === null || !managedRootStat.isDirectory() || managedRootStat.isSymbolicLink()) {
|
|
@@ -14188,14 +14255,14 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14188
14255
|
const lockToken = `${JSON.stringify({ pid: process.pid, stageDir, releaseId, startedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
14189
14256
|
`;
|
|
14190
14257
|
try {
|
|
14191
|
-
|
|
14258
|
+
fs37.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
14192
14259
|
lockAcquired = true;
|
|
14193
14260
|
} catch {
|
|
14194
14261
|
failIncomplete(`transaction lock busy: concurrent activation holds the exclusive lock (recovery incomplete): ${lockPath}`);
|
|
14195
14262
|
}
|
|
14196
14263
|
if (lstatOrNull5(markerPath) !== null) {
|
|
14197
14264
|
try {
|
|
14198
|
-
|
|
14265
|
+
fs37.rmSync(lockPath, { force: true });
|
|
14199
14266
|
lockAcquired = false;
|
|
14200
14267
|
} catch {
|
|
14201
14268
|
}
|
|
@@ -14204,10 +14271,10 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14204
14271
|
const markerContent = `${JSON.stringify({ stageDir, backupDir, releaseId, releaseDir, phase: "prepared", pid: process.pid }, null, 2)}
|
|
14205
14272
|
`;
|
|
14206
14273
|
try {
|
|
14207
|
-
|
|
14274
|
+
fs37.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
14208
14275
|
} catch {
|
|
14209
14276
|
try {
|
|
14210
|
-
|
|
14277
|
+
fs37.rmSync(lockPath, { force: true });
|
|
14211
14278
|
lockAcquired = false;
|
|
14212
14279
|
} catch {
|
|
14213
14280
|
}
|
|
@@ -14225,7 +14292,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14225
14292
|
}
|
|
14226
14293
|
}
|
|
14227
14294
|
try {
|
|
14228
|
-
|
|
14295
|
+
fs37.mkdirSync(backupDir);
|
|
14229
14296
|
backupCreated = true;
|
|
14230
14297
|
captureBackupDirIdentity();
|
|
14231
14298
|
} catch (err) {
|
|
@@ -14245,7 +14312,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14245
14312
|
}
|
|
14246
14313
|
const persistBackupCopy = (target, content) => {
|
|
14247
14314
|
if (content === null) return;
|
|
14248
|
-
|
|
14315
|
+
fs37.writeFileSync(target, content, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
14249
14316
|
trackOwnedBackupFile(target, content);
|
|
14250
14317
|
};
|
|
14251
14318
|
let entryMoved = false;
|
|
@@ -14255,10 +14322,10 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14255
14322
|
try {
|
|
14256
14323
|
persistBackupCopy(backupSettings, oldSettings);
|
|
14257
14324
|
persistBackupCopy(backupReceipt, oldReceipt);
|
|
14258
|
-
const metaPath =
|
|
14325
|
+
const metaPath = path45.join(backupDir, "meta.json");
|
|
14259
14326
|
const metaContent = `${JSON.stringify({ releaseId, oldEntryExisted }, null, 2)}
|
|
14260
14327
|
`;
|
|
14261
|
-
|
|
14328
|
+
fs37.writeFileSync(metaPath, metaContent, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
14262
14329
|
trackOwnedBackupFile(metaPath, metaContent);
|
|
14263
14330
|
} catch {
|
|
14264
14331
|
abortBeforePublish(new Error(`cannot persist private backup`));
|
|
@@ -14274,7 +14341,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14274
14341
|
} else {
|
|
14275
14342
|
let target = null;
|
|
14276
14343
|
try {
|
|
14277
|
-
target =
|
|
14344
|
+
target = fs37.readlinkSync(linkPath);
|
|
14278
14345
|
} catch {
|
|
14279
14346
|
target = null;
|
|
14280
14347
|
}
|
|
@@ -14286,7 +14353,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14286
14353
|
if (drift === null && wroteSettings) {
|
|
14287
14354
|
let cur = null;
|
|
14288
14355
|
try {
|
|
14289
|
-
cur =
|
|
14356
|
+
cur = fs37.readFileSync(settingsPath, "utf8");
|
|
14290
14357
|
} catch {
|
|
14291
14358
|
cur = null;
|
|
14292
14359
|
}
|
|
@@ -14295,7 +14362,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14295
14362
|
if (drift === null && wroteReceipt) {
|
|
14296
14363
|
let cur = null;
|
|
14297
14364
|
try {
|
|
14298
|
-
cur =
|
|
14365
|
+
cur = fs37.readFileSync(receiptPath, "utf8");
|
|
14299
14366
|
} catch {
|
|
14300
14367
|
cur = null;
|
|
14301
14368
|
}
|
|
@@ -14311,7 +14378,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14311
14378
|
if (cur === null || !cur.isSymbolicLink()) {
|
|
14312
14379
|
problems.push("published entry link missing");
|
|
14313
14380
|
} else {
|
|
14314
|
-
|
|
14381
|
+
fs37.unlinkSync(linkPath);
|
|
14315
14382
|
}
|
|
14316
14383
|
} else if (lstatOrNull5(linkPath) !== null) {
|
|
14317
14384
|
problems.push("unexpected managed entry");
|
|
@@ -14327,7 +14394,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14327
14394
|
} else if (lstatOrNull5(linkPath) !== null) {
|
|
14328
14395
|
problems.push("managed entry still present");
|
|
14329
14396
|
} else {
|
|
14330
|
-
|
|
14397
|
+
fs37.renameSync(backupEntry, linkPath);
|
|
14331
14398
|
}
|
|
14332
14399
|
} else if (lstatOrNull5(linkPath) !== null) {
|
|
14333
14400
|
problems.push("unexpected managed entry");
|
|
@@ -14340,7 +14407,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14340
14407
|
if (oldSettings !== null) {
|
|
14341
14408
|
atomicWritePrivate(settingsPath, oldSettings);
|
|
14342
14409
|
} else {
|
|
14343
|
-
|
|
14410
|
+
fs37.rmSync(settingsPath, { force: true });
|
|
14344
14411
|
}
|
|
14345
14412
|
}
|
|
14346
14413
|
} catch {
|
|
@@ -14351,7 +14418,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14351
14418
|
if (oldReceipt !== null) {
|
|
14352
14419
|
atomicWritePrivate(receiptPath, oldReceipt);
|
|
14353
14420
|
} else {
|
|
14354
|
-
|
|
14421
|
+
fs37.rmSync(receiptPath, { force: true });
|
|
14355
14422
|
}
|
|
14356
14423
|
}
|
|
14357
14424
|
} catch {
|
|
@@ -14361,7 +14428,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14361
14428
|
const destStat = lstatOrNull5(releaseDir);
|
|
14362
14429
|
const stagedStat = lstatOrNull5(stagedNpm);
|
|
14363
14430
|
if (destStat !== null && stagedStat === null) {
|
|
14364
|
-
|
|
14431
|
+
fs37.renameSync(releaseDir, stagedNpm);
|
|
14365
14432
|
} else if (destStat !== null && stagedStat !== null) {
|
|
14366
14433
|
problems.push("staged tree and promoted release both present");
|
|
14367
14434
|
} else if (destStat === null && stagedStat === null) {
|
|
@@ -14381,7 +14448,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14381
14448
|
clearOwnedBackupThenCooperativeState(original);
|
|
14382
14449
|
} else {
|
|
14383
14450
|
try {
|
|
14384
|
-
|
|
14451
|
+
fs37.rmSync(markerPath, { force: true });
|
|
14385
14452
|
releaseLock();
|
|
14386
14453
|
} catch {
|
|
14387
14454
|
failIncomplete(`cannot clear transaction state after rollback: ${original}`);
|
|
@@ -14397,14 +14464,14 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14397
14464
|
};
|
|
14398
14465
|
try {
|
|
14399
14466
|
if (oldEntryExisted) {
|
|
14400
|
-
|
|
14467
|
+
fs37.renameSync(linkPath, backupEntry);
|
|
14401
14468
|
entryMoved = true;
|
|
14402
14469
|
}
|
|
14403
14470
|
} catch {
|
|
14404
14471
|
abortBeforePublish(new Error(`cannot backup previous managed entry`));
|
|
14405
14472
|
}
|
|
14406
14473
|
try {
|
|
14407
|
-
|
|
14474
|
+
fs37.mkdirSync(releaseRoot, { recursive: true });
|
|
14408
14475
|
assertAncestorsClean(releaseRoot, homeDir, "release root");
|
|
14409
14476
|
const rootStat = lstatOrNull5(releaseRoot);
|
|
14410
14477
|
if (rootStat === null || !rootStat.isDirectory() || rootStat.isSymbolicLink()) {
|
|
@@ -14413,8 +14480,8 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14413
14480
|
if (lstatOrNull5(releaseDir) !== null) {
|
|
14414
14481
|
throw new Error(`release already exists: ${releaseDir}`);
|
|
14415
14482
|
}
|
|
14416
|
-
|
|
14417
|
-
|
|
14483
|
+
fs37.renameSync(stagedNpm, releaseDir);
|
|
14484
|
+
fs37.symlinkSync(expectedTarget, linkPath, "dir");
|
|
14418
14485
|
publishedLink = true;
|
|
14419
14486
|
atomicWritePrivate(settingsPath, input.nextSettings);
|
|
14420
14487
|
wroteSettings = true;
|
|
@@ -14432,7 +14499,7 @@ async function activateVerifiedPiRelease(input) {
|
|
|
14432
14499
|
rollback(err);
|
|
14433
14500
|
}
|
|
14434
14501
|
try {
|
|
14435
|
-
|
|
14502
|
+
fs37.rmSync(markerPath, { force: true });
|
|
14436
14503
|
releaseLock();
|
|
14437
14504
|
} catch {
|
|
14438
14505
|
failIncomplete(`cannot clear transaction state after activation (recovery incomplete): ${markerPath}`);
|
|
@@ -14448,14 +14515,14 @@ function isManagedDependency(value) {
|
|
|
14448
14515
|
}
|
|
14449
14516
|
function readTextOrNull(p7) {
|
|
14450
14517
|
try {
|
|
14451
|
-
return
|
|
14518
|
+
return fs37.readFileSync(p7, "utf8");
|
|
14452
14519
|
} catch {
|
|
14453
14520
|
return null;
|
|
14454
14521
|
}
|
|
14455
14522
|
}
|
|
14456
14523
|
function safeReadlink(p7) {
|
|
14457
14524
|
try {
|
|
14458
|
-
return
|
|
14525
|
+
return fs37.readlinkSync(p7);
|
|
14459
14526
|
} catch {
|
|
14460
14527
|
return null;
|
|
14461
14528
|
}
|
|
@@ -14471,7 +14538,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14471
14538
|
if (typeof input.homeDir !== "string" || input.homeDir === "" || typeof input.agentDir !== "string" || input.agentDir === "" || typeof input.receiptPath !== "string" || input.receiptPath === "" || typeof mp.releaseDir !== "string" || mp.releaseDir === "" || typeof mp.linkPath !== "string" || mp.linkPath === "" || typeof mp.backupDir !== "string" || mp.backupDir === "") {
|
|
14472
14539
|
throw new Error(`homeDir, agentDir, receiptPath and managedPackage paths must be non-empty strings`);
|
|
14473
14540
|
}
|
|
14474
|
-
if (!
|
|
14541
|
+
if (!path45.isAbsolute(input.homeDir)) {
|
|
14475
14542
|
throw new Error(`homeDir must be absolute: ${input.homeDir}`);
|
|
14476
14543
|
}
|
|
14477
14544
|
if (typeof mp.lockSha256 !== "string" || !HEX64_PATTERN.test(mp.lockSha256)) {
|
|
@@ -14512,23 +14579,23 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14512
14579
|
if (agentStat === null || !agentStat.isDirectory() || agentStat.isSymbolicLink()) {
|
|
14513
14580
|
throw new Error(`agentDir must be a real directory: ${input.agentDir}`);
|
|
14514
14581
|
}
|
|
14515
|
-
const settingsPath =
|
|
14516
|
-
const npmDir =
|
|
14517
|
-
const nodeModules =
|
|
14518
|
-
const expectedLink =
|
|
14519
|
-
const releaseRoot =
|
|
14520
|
-
const managedRoot =
|
|
14521
|
-
const markerPath =
|
|
14522
|
-
const lockPath =
|
|
14582
|
+
const settingsPath = path45.join(agentDir, "settings.json");
|
|
14583
|
+
const npmDir = path45.join(agentDir, "npm");
|
|
14584
|
+
const nodeModules = path45.join(npmDir, "node_modules");
|
|
14585
|
+
const expectedLink = path45.join(nodeModules, EXPECTED_ENTRY);
|
|
14586
|
+
const releaseRoot = path45.join(npmDir, "jorgex-pi-managed", "releases");
|
|
14587
|
+
const managedRoot = path45.join(npmDir, "jorgex-pi-managed");
|
|
14588
|
+
const markerPath = path45.join(managedRoot, "active-transaction.json");
|
|
14589
|
+
const lockPath = path45.join(managedRoot, "transaction.lock");
|
|
14523
14590
|
if (linkPath !== expectedLink) {
|
|
14524
14591
|
throw new Error(`managed link must be the owned entry: ${expectedLink}`);
|
|
14525
14592
|
}
|
|
14526
|
-
const releaseId =
|
|
14527
|
-
if (
|
|
14593
|
+
const releaseId = path45.basename(releaseDir);
|
|
14594
|
+
if (path45.dirname(releaseDir) !== releaseRoot || !HEX64_PATTERN.test(releaseId)) {
|
|
14528
14595
|
throw new Error(`managed release must live under the private releases root: ${releaseDir}`);
|
|
14529
14596
|
}
|
|
14530
14597
|
const expectedTarget = `../jorgex-pi-managed/releases/${releaseId}/node_modules/${EXPECTED_ENTRY}`;
|
|
14531
|
-
const packageRoot =
|
|
14598
|
+
const packageRoot = path45.join(releaseDir, "node_modules", EXPECTED_ENTRY);
|
|
14532
14599
|
assertStrictChild(agentDir, homeDir, "agentDir");
|
|
14533
14600
|
assertStrictChild(receiptPath, homeDir, "receiptPath");
|
|
14534
14601
|
assertStrictChild(releaseDir, agentDir, "managed release");
|
|
@@ -14567,7 +14634,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14567
14634
|
if (linkStat === null || !linkStat.isSymbolicLink()) {
|
|
14568
14635
|
throw new Error(`managed entry must be the owned symlink: ${linkPath}`);
|
|
14569
14636
|
}
|
|
14570
|
-
assertAncestorsClean(
|
|
14637
|
+
assertAncestorsClean(path45.dirname(linkPath), homeDir, "managed entry");
|
|
14571
14638
|
const observedTarget = safeReadlink(linkPath);
|
|
14572
14639
|
if (observedTarget === null || observedTarget !== expectedTarget) {
|
|
14573
14640
|
throw new Error(`managed entry points outside the owned release: ${linkPath}`);
|
|
@@ -14579,7 +14646,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14579
14646
|
}
|
|
14580
14647
|
let liveRealpath = null;
|
|
14581
14648
|
try {
|
|
14582
|
-
liveRealpath =
|
|
14649
|
+
liveRealpath = fs37.realpathSync(linkPath);
|
|
14583
14650
|
} catch {
|
|
14584
14651
|
liveRealpath = null;
|
|
14585
14652
|
}
|
|
@@ -14596,7 +14663,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14596
14663
|
throw new Error(`activation backup must be a real directory: ${mp.backupDir}`);
|
|
14597
14664
|
}
|
|
14598
14665
|
assertAncestorsClean(activationBackupDir, homeDir, "activation backup");
|
|
14599
|
-
const lockFile =
|
|
14666
|
+
const lockFile = path45.join(releaseDir, "package-lock.json");
|
|
14600
14667
|
const lockStat = lstatOrNull5(lockFile);
|
|
14601
14668
|
if (lockStat === null || lockStat.isSymbolicLink() || !lockStat.isFile()) {
|
|
14602
14669
|
throw new Error(`managed lock must be a regular file: ${lockFile}`);
|
|
@@ -14606,7 +14673,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14606
14673
|
}
|
|
14607
14674
|
let lockBytes;
|
|
14608
14675
|
try {
|
|
14609
|
-
lockBytes =
|
|
14676
|
+
lockBytes = fs37.readFileSync(lockFile);
|
|
14610
14677
|
} catch {
|
|
14611
14678
|
throw new Error(`cannot read managed lock: ${lockFile}`);
|
|
14612
14679
|
}
|
|
@@ -14624,19 +14691,19 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14624
14691
|
let oldReceipt = null;
|
|
14625
14692
|
try {
|
|
14626
14693
|
if (lstatOrNull5(settingsPath) !== null) {
|
|
14627
|
-
oldSettings =
|
|
14694
|
+
oldSettings = fs37.readFileSync(settingsPath, "utf8");
|
|
14628
14695
|
}
|
|
14629
|
-
oldReceipt =
|
|
14696
|
+
oldReceipt = fs37.readFileSync(receiptPath, "utf8");
|
|
14630
14697
|
} catch {
|
|
14631
14698
|
throw new Error(`cannot read previous settings/receipt`);
|
|
14632
14699
|
}
|
|
14633
14700
|
let lockAcquired = false;
|
|
14634
14701
|
const releaseLock = () => {
|
|
14635
14702
|
if (!lockAcquired) return;
|
|
14636
|
-
|
|
14703
|
+
fs37.rmSync(lockPath, { force: true });
|
|
14637
14704
|
lockAcquired = false;
|
|
14638
14705
|
};
|
|
14639
|
-
|
|
14706
|
+
fs37.mkdirSync(managedRoot, { recursive: true });
|
|
14640
14707
|
assertAncestorsClean(managedRoot, homeDir, "managed root");
|
|
14641
14708
|
const managedRootStat = lstatOrNull5(managedRoot);
|
|
14642
14709
|
if (managedRootStat === null || !managedRootStat.isDirectory() || managedRootStat.isSymbolicLink()) {
|
|
@@ -14644,7 +14711,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14644
14711
|
}
|
|
14645
14712
|
let uninstallBackupDir = "";
|
|
14646
14713
|
for (let i = 0; i < 5 && uninstallBackupDir === ""; i++) {
|
|
14647
|
-
const candidateDir =
|
|
14714
|
+
const candidateDir = path45.join(managedRoot, `uninstall-backup-${crypto2.randomBytes(8).toString("hex")}`);
|
|
14648
14715
|
if (lstatOrNull5(candidateDir) === null) uninstallBackupDir = candidateDir;
|
|
14649
14716
|
}
|
|
14650
14717
|
if (uninstallBackupDir === "") {
|
|
@@ -14654,14 +14721,14 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14654
14721
|
const lockToken = `${JSON.stringify({ op: "uninstall", pid: process.pid, agentDir, releaseId, startedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
14655
14722
|
`;
|
|
14656
14723
|
try {
|
|
14657
|
-
|
|
14724
|
+
fs37.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
14658
14725
|
lockAcquired = true;
|
|
14659
14726
|
} catch {
|
|
14660
14727
|
failIncomplete(`transaction lock busy: concurrent operation holds the exclusive lock (recovery incomplete): ${lockPath}`);
|
|
14661
14728
|
}
|
|
14662
14729
|
if (lstatOrNull5(markerPath) !== null) {
|
|
14663
14730
|
try {
|
|
14664
|
-
|
|
14731
|
+
fs37.rmSync(lockPath, { force: true });
|
|
14665
14732
|
lockAcquired = false;
|
|
14666
14733
|
} catch {
|
|
14667
14734
|
}
|
|
@@ -14670,10 +14737,10 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14670
14737
|
const markerContent = `${JSON.stringify({ phase: "uninstall", releaseDir, linkPath, receiptPath, backupDir: uninstallBackupDir, activationBackupDir, releaseId, pid: process.pid }, null, 2)}
|
|
14671
14738
|
`;
|
|
14672
14739
|
try {
|
|
14673
|
-
|
|
14740
|
+
fs37.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
14674
14741
|
} catch {
|
|
14675
14742
|
try {
|
|
14676
|
-
|
|
14743
|
+
fs37.rmSync(lockPath, { force: true });
|
|
14677
14744
|
lockAcquired = false;
|
|
14678
14745
|
} catch {
|
|
14679
14746
|
}
|
|
@@ -14682,7 +14749,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14682
14749
|
const abortOwnTransaction = (err) => {
|
|
14683
14750
|
const problems = [];
|
|
14684
14751
|
try {
|
|
14685
|
-
|
|
14752
|
+
fs37.rmSync(markerPath, { force: true });
|
|
14686
14753
|
} catch {
|
|
14687
14754
|
problems.push("cannot remove marker");
|
|
14688
14755
|
}
|
|
@@ -14692,7 +14759,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14692
14759
|
problems.push("cannot release lock");
|
|
14693
14760
|
}
|
|
14694
14761
|
try {
|
|
14695
|
-
|
|
14762
|
+
fs37.rmSync(uninstallBackupDir, { recursive: true, force: true });
|
|
14696
14763
|
} catch {
|
|
14697
14764
|
problems.push("cannot clear backup");
|
|
14698
14765
|
}
|
|
@@ -14728,7 +14795,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14728
14795
|
}
|
|
14729
14796
|
if (drift !== null) {
|
|
14730
14797
|
try {
|
|
14731
|
-
|
|
14798
|
+
fs37.rmSync(markerPath, { force: true });
|
|
14732
14799
|
releaseLock();
|
|
14733
14800
|
} catch {
|
|
14734
14801
|
}
|
|
@@ -14737,7 +14804,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14737
14804
|
};
|
|
14738
14805
|
recheckLiveState();
|
|
14739
14806
|
try {
|
|
14740
|
-
|
|
14807
|
+
fs37.mkdirSync(uninstallBackupDir, { recursive: true });
|
|
14741
14808
|
} catch (err) {
|
|
14742
14809
|
abortOwnTransaction(err);
|
|
14743
14810
|
}
|
|
@@ -14747,22 +14814,22 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14747
14814
|
}
|
|
14748
14815
|
let backupEntries = [];
|
|
14749
14816
|
try {
|
|
14750
|
-
backupEntries =
|
|
14817
|
+
backupEntries = fs37.readdirSync(uninstallBackupDir);
|
|
14751
14818
|
} catch {
|
|
14752
14819
|
abortOwnTransaction(new Error(`cannot inspect uninstall backup: ${uninstallBackupDir}`));
|
|
14753
14820
|
}
|
|
14754
14821
|
if (backupEntries.length !== 0) {
|
|
14755
14822
|
abortOwnTransaction(new Error(`uninstall backup is not empty: ${uninstallBackupDir}`));
|
|
14756
14823
|
}
|
|
14757
|
-
const backupReleaseDir =
|
|
14758
|
-
const backupReceiptFile =
|
|
14759
|
-
const backupSettingsFile =
|
|
14824
|
+
const backupReleaseDir = path45.join(uninstallBackupDir, "release");
|
|
14825
|
+
const backupReceiptFile = path45.join(uninstallBackupDir, "pi-receipt.json");
|
|
14826
|
+
const backupSettingsFile = path45.join(uninstallBackupDir, "settings.json");
|
|
14760
14827
|
try {
|
|
14761
14828
|
if (oldSettings !== null) {
|
|
14762
|
-
|
|
14829
|
+
fs37.writeFileSync(backupSettingsFile, oldSettings, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
14763
14830
|
}
|
|
14764
|
-
|
|
14765
|
-
|
|
14831
|
+
fs37.writeFileSync(
|
|
14832
|
+
path45.join(uninstallBackupDir, "meta.json"),
|
|
14766
14833
|
`${JSON.stringify({ phase: "uninstall", releaseDir, linkPath, receiptPath, linkTarget: observedTarget }, null, 2)}
|
|
14767
14834
|
`,
|
|
14768
14835
|
{ encoding: "utf8", flag: "wx", mode: 384 }
|
|
@@ -14815,14 +14882,14 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14815
14882
|
const problems = [];
|
|
14816
14883
|
if (movedRelease) {
|
|
14817
14884
|
try {
|
|
14818
|
-
|
|
14885
|
+
fs37.renameSync(backupReleaseDir, releaseDir);
|
|
14819
14886
|
} catch {
|
|
14820
14887
|
problems.push("cannot restore release");
|
|
14821
14888
|
}
|
|
14822
14889
|
}
|
|
14823
14890
|
if (removedLink) {
|
|
14824
14891
|
try {
|
|
14825
|
-
|
|
14892
|
+
fs37.symlinkSync(observedTarget, linkPath, "dir");
|
|
14826
14893
|
} catch {
|
|
14827
14894
|
problems.push("cannot restore managed entry");
|
|
14828
14895
|
}
|
|
@@ -14832,7 +14899,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14832
14899
|
if (oldSettings !== null) {
|
|
14833
14900
|
atomicWritePrivate(settingsPath, oldSettings);
|
|
14834
14901
|
} else {
|
|
14835
|
-
|
|
14902
|
+
fs37.rmSync(settingsPath, { force: true });
|
|
14836
14903
|
}
|
|
14837
14904
|
} catch {
|
|
14838
14905
|
problems.push("cannot restore previous settings");
|
|
@@ -14840,7 +14907,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14840
14907
|
}
|
|
14841
14908
|
if (movedReceipt) {
|
|
14842
14909
|
try {
|
|
14843
|
-
|
|
14910
|
+
fs37.renameSync(backupReceiptFile, receiptPath);
|
|
14844
14911
|
} catch {
|
|
14845
14912
|
problems.push("cannot restore receipt");
|
|
14846
14913
|
}
|
|
@@ -14849,9 +14916,9 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14849
14916
|
failIncomplete(`uninstall rollback incomplete (${problems.join("; ")}): ${original}`);
|
|
14850
14917
|
}
|
|
14851
14918
|
try {
|
|
14852
|
-
|
|
14919
|
+
fs37.rmSync(markerPath, { force: true });
|
|
14853
14920
|
releaseLock();
|
|
14854
|
-
|
|
14921
|
+
fs37.rmSync(uninstallBackupDir, { recursive: true, force: true });
|
|
14855
14922
|
} catch {
|
|
14856
14923
|
failIncomplete(`cannot clear transaction state after rollback: ${original}`);
|
|
14857
14924
|
}
|
|
@@ -14864,11 +14931,11 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14864
14931
|
throw wrapped;
|
|
14865
14932
|
};
|
|
14866
14933
|
try {
|
|
14867
|
-
|
|
14934
|
+
fs37.unlinkSync(linkPath);
|
|
14868
14935
|
removedLink = true;
|
|
14869
|
-
|
|
14936
|
+
fs37.renameSync(releaseDir, backupReleaseDir);
|
|
14870
14937
|
movedRelease = true;
|
|
14871
|
-
|
|
14938
|
+
fs37.renameSync(receiptPath, backupReceiptFile);
|
|
14872
14939
|
movedReceipt = true;
|
|
14873
14940
|
atomicWritePrivate(settingsPath, input.nextSettings);
|
|
14874
14941
|
wroteSettings = true;
|
|
@@ -14890,7 +14957,7 @@ function deactivateVerifiedPiRelease(input) {
|
|
|
14890
14957
|
rollbackDeactivate(new Error(`verify must be synchronous and return void, got thenable`));
|
|
14891
14958
|
}
|
|
14892
14959
|
try {
|
|
14893
|
-
|
|
14960
|
+
fs37.rmSync(markerPath, { force: true });
|
|
14894
14961
|
releaseLock();
|
|
14895
14962
|
} catch {
|
|
14896
14963
|
failIncomplete(`cannot clear transaction state after uninstall (recovery incomplete): ${markerPath}`);
|
|
@@ -14931,7 +14998,7 @@ function readRegularTextLegacy(file, label) {
|
|
|
14931
14998
|
throw new Error(`${label} exceeds size bound: ${file}`);
|
|
14932
14999
|
}
|
|
14933
15000
|
try {
|
|
14934
|
-
return
|
|
15001
|
+
return fs37.readFileSync(file, "utf8");
|
|
14935
15002
|
} catch {
|
|
14936
15003
|
throw new Error(`cannot read ${label}: ${file}`);
|
|
14937
15004
|
}
|
|
@@ -14943,7 +15010,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
14943
15010
|
if (typeof input.homeDir !== "string" || input.homeDir === "" || typeof input.agentDir !== "string" || input.agentDir === "" || typeof input.receiptPath !== "string" || input.receiptPath === "" || typeof input.source !== "string" || input.source === "") {
|
|
14944
15011
|
throw new Error(`homeDir, agentDir, receiptPath and source must be non-empty strings`);
|
|
14945
15012
|
}
|
|
14946
|
-
if (!
|
|
15013
|
+
if (!path45.isAbsolute(input.homeDir)) {
|
|
14947
15014
|
throw new Error(`homeDir must be absolute: ${input.homeDir}`);
|
|
14948
15015
|
}
|
|
14949
15016
|
const sourceMatch = LEGACY_SOURCE_PATTERN.exec(input.source);
|
|
@@ -14977,13 +15044,13 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
14977
15044
|
if (agentStat === null || !agentStat.isDirectory() || agentStat.isSymbolicLink()) {
|
|
14978
15045
|
throw new Error(`agentDir must be a real directory: ${input.agentDir}`);
|
|
14979
15046
|
}
|
|
14980
|
-
const settingsPath =
|
|
14981
|
-
const npmDir =
|
|
14982
|
-
const nodeModules =
|
|
14983
|
-
const legacyEntry =
|
|
14984
|
-
const managedRoot =
|
|
14985
|
-
const markerPath =
|
|
14986
|
-
const lockPath =
|
|
15047
|
+
const settingsPath = path45.join(agentDir, "settings.json");
|
|
15048
|
+
const npmDir = path45.join(agentDir, "npm");
|
|
15049
|
+
const nodeModules = path45.join(npmDir, "node_modules");
|
|
15050
|
+
const legacyEntry = path45.join(nodeModules, EXPECTED_ENTRY);
|
|
15051
|
+
const managedRoot = path45.join(npmDir, "jorgex-pi-managed");
|
|
15052
|
+
const markerPath = path45.join(managedRoot, "active-transaction.json");
|
|
15053
|
+
const lockPath = path45.join(managedRoot, "transaction.lock");
|
|
14987
15054
|
assertStrictChild(agentDir, homeDir, "agentDir");
|
|
14988
15055
|
assertStrictChild(receiptPath, homeDir, "receiptPath");
|
|
14989
15056
|
assertStrictChild(managedRoot, agentDir, "managed root");
|
|
@@ -15016,8 +15083,8 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15016
15083
|
if (entryStat === null || !entryStat.isDirectory() || entryStat.isSymbolicLink()) {
|
|
15017
15084
|
throw new Error(`managed entry must be a real directory, not a symlink: ${legacyEntry}`);
|
|
15018
15085
|
}
|
|
15019
|
-
assertAncestorsClean(
|
|
15020
|
-
const manifestPath =
|
|
15086
|
+
assertAncestorsClean(path45.dirname(legacyEntry), homeDir, "managed entry");
|
|
15087
|
+
const manifestPath = path45.join(legacyEntry, "package.json");
|
|
15021
15088
|
const manifestStat = lstatOrNull5(manifestPath);
|
|
15022
15089
|
if (manifestStat === null || !manifestStat.isFile() || manifestStat.isSymbolicLink()) {
|
|
15023
15090
|
throw new Error(`managed entry manifest must be a regular file: ${manifestPath}`);
|
|
@@ -15114,10 +15181,10 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15114
15181
|
let lockAcquired = false;
|
|
15115
15182
|
const releaseLock = () => {
|
|
15116
15183
|
if (!lockAcquired) return;
|
|
15117
|
-
|
|
15184
|
+
fs37.rmSync(lockPath, { force: true });
|
|
15118
15185
|
lockAcquired = false;
|
|
15119
15186
|
};
|
|
15120
|
-
|
|
15187
|
+
fs37.mkdirSync(managedRoot, { recursive: true });
|
|
15121
15188
|
assertAncestorsClean(managedRoot, homeDir, "managed root");
|
|
15122
15189
|
const managedRootStat = lstatOrNull5(managedRoot);
|
|
15123
15190
|
if (managedRootStat === null || !managedRootStat.isDirectory() || managedRootStat.isSymbolicLink()) {
|
|
@@ -15125,7 +15192,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15125
15192
|
}
|
|
15126
15193
|
let uninstallBackupDir = "";
|
|
15127
15194
|
for (let i = 0; i < 5 && uninstallBackupDir === ""; i++) {
|
|
15128
|
-
const candidateDir =
|
|
15195
|
+
const candidateDir = path45.join(managedRoot, `uninstall-backup-${crypto2.randomBytes(8).toString("hex")}`);
|
|
15129
15196
|
if (lstatOrNull5(candidateDir) === null) uninstallBackupDir = candidateDir;
|
|
15130
15197
|
}
|
|
15131
15198
|
if (uninstallBackupDir === "") {
|
|
@@ -15135,14 +15202,14 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15135
15202
|
const lockToken = `${JSON.stringify({ op: "uninstall-legacy", pid: process.pid, agentDir, source: input.source, startedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
15136
15203
|
`;
|
|
15137
15204
|
try {
|
|
15138
|
-
|
|
15205
|
+
fs37.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
15139
15206
|
lockAcquired = true;
|
|
15140
15207
|
} catch {
|
|
15141
15208
|
failIncomplete(`transaction lock busy: concurrent operation holds the exclusive lock (recovery incomplete): ${lockPath}`);
|
|
15142
15209
|
}
|
|
15143
15210
|
if (lstatOrNull5(markerPath) !== null) {
|
|
15144
15211
|
try {
|
|
15145
|
-
|
|
15212
|
+
fs37.rmSync(lockPath, { force: true });
|
|
15146
15213
|
lockAcquired = false;
|
|
15147
15214
|
} catch {
|
|
15148
15215
|
}
|
|
@@ -15151,10 +15218,10 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15151
15218
|
const markerContent = `${JSON.stringify({ phase: "uninstall-legacy", legacyEntry, receiptPath, backupDir: uninstallBackupDir, source: input.source, pid: process.pid }, null, 2)}
|
|
15152
15219
|
`;
|
|
15153
15220
|
try {
|
|
15154
|
-
|
|
15221
|
+
fs37.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
15155
15222
|
} catch {
|
|
15156
15223
|
try {
|
|
15157
|
-
|
|
15224
|
+
fs37.rmSync(lockPath, { force: true });
|
|
15158
15225
|
lockAcquired = false;
|
|
15159
15226
|
} catch {
|
|
15160
15227
|
}
|
|
@@ -15163,7 +15230,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15163
15230
|
const abortOwnTransaction = (err) => {
|
|
15164
15231
|
const problems = [];
|
|
15165
15232
|
try {
|
|
15166
|
-
|
|
15233
|
+
fs37.rmSync(markerPath, { force: true });
|
|
15167
15234
|
} catch {
|
|
15168
15235
|
problems.push("cannot remove marker");
|
|
15169
15236
|
}
|
|
@@ -15173,7 +15240,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15173
15240
|
problems.push("cannot release lock");
|
|
15174
15241
|
}
|
|
15175
15242
|
try {
|
|
15176
|
-
|
|
15243
|
+
fs37.rmSync(uninstallBackupDir, { recursive: true, force: true });
|
|
15177
15244
|
} catch {
|
|
15178
15245
|
problems.push("cannot clear backup");
|
|
15179
15246
|
}
|
|
@@ -15192,7 +15259,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15192
15259
|
abortOwnTransaction(new Error(`receipt or settings drifted before uninstall: ${legacyEntry}`));
|
|
15193
15260
|
}
|
|
15194
15261
|
try {
|
|
15195
|
-
|
|
15262
|
+
fs37.mkdirSync(uninstallBackupDir, { recursive: true });
|
|
15196
15263
|
} catch (err) {
|
|
15197
15264
|
abortOwnTransaction(err);
|
|
15198
15265
|
}
|
|
@@ -15202,20 +15269,20 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15202
15269
|
}
|
|
15203
15270
|
let backupEntries = [];
|
|
15204
15271
|
try {
|
|
15205
|
-
backupEntries =
|
|
15272
|
+
backupEntries = fs37.readdirSync(uninstallBackupDir);
|
|
15206
15273
|
} catch {
|
|
15207
15274
|
abortOwnTransaction(new Error(`cannot inspect uninstall backup: ${uninstallBackupDir}`));
|
|
15208
15275
|
}
|
|
15209
15276
|
if (backupEntries.length !== 0) {
|
|
15210
15277
|
abortOwnTransaction(new Error(`uninstall backup is not empty: ${uninstallBackupDir}`));
|
|
15211
15278
|
}
|
|
15212
|
-
const backupEntryDir =
|
|
15213
|
-
const backupReceiptFile =
|
|
15214
|
-
const backupSettingsFile =
|
|
15279
|
+
const backupEntryDir = path45.join(uninstallBackupDir, "entry");
|
|
15280
|
+
const backupReceiptFile = path45.join(uninstallBackupDir, "pi-receipt.json");
|
|
15281
|
+
const backupSettingsFile = path45.join(uninstallBackupDir, "settings.json");
|
|
15215
15282
|
try {
|
|
15216
|
-
|
|
15217
|
-
|
|
15218
|
-
|
|
15283
|
+
fs37.writeFileSync(backupSettingsFile, oldSettings, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
15284
|
+
fs37.writeFileSync(
|
|
15285
|
+
path45.join(uninstallBackupDir, "meta.json"),
|
|
15219
15286
|
`${JSON.stringify({ phase: "uninstall-legacy", legacyEntry, receiptPath, source: input.source }, null, 2)}
|
|
15220
15287
|
`,
|
|
15221
15288
|
{ encoding: "utf8", flag: "wx", mode: 384 }
|
|
@@ -15259,14 +15326,14 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15259
15326
|
const problems = [];
|
|
15260
15327
|
if (movedReceipt) {
|
|
15261
15328
|
try {
|
|
15262
|
-
|
|
15329
|
+
fs37.renameSync(backupReceiptFile, receiptPath);
|
|
15263
15330
|
} catch {
|
|
15264
15331
|
problems.push("cannot restore receipt");
|
|
15265
15332
|
}
|
|
15266
15333
|
}
|
|
15267
15334
|
if (movedEntry) {
|
|
15268
15335
|
try {
|
|
15269
|
-
|
|
15336
|
+
fs37.renameSync(backupEntryDir, legacyEntry);
|
|
15270
15337
|
} catch {
|
|
15271
15338
|
problems.push("cannot restore previous entry");
|
|
15272
15339
|
}
|
|
@@ -15282,9 +15349,9 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15282
15349
|
failIncomplete(`uninstall rollback incomplete (${problems.join("; ")}): ${original}`);
|
|
15283
15350
|
}
|
|
15284
15351
|
try {
|
|
15285
|
-
|
|
15352
|
+
fs37.rmSync(markerPath, { force: true });
|
|
15286
15353
|
releaseLock();
|
|
15287
|
-
|
|
15354
|
+
fs37.rmSync(uninstallBackupDir, { recursive: true, force: true });
|
|
15288
15355
|
} catch {
|
|
15289
15356
|
failIncomplete(`cannot clear transaction state after rollback: ${original}`);
|
|
15290
15357
|
}
|
|
@@ -15297,9 +15364,9 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15297
15364
|
throw wrapped;
|
|
15298
15365
|
};
|
|
15299
15366
|
try {
|
|
15300
|
-
|
|
15367
|
+
fs37.renameSync(legacyEntry, backupEntryDir);
|
|
15301
15368
|
movedEntry = true;
|
|
15302
|
-
|
|
15369
|
+
fs37.renameSync(receiptPath, backupReceiptFile);
|
|
15303
15370
|
movedReceipt = true;
|
|
15304
15371
|
atomicWritePrivate(settingsPath, input.nextSettings);
|
|
15305
15372
|
wroteSettings = true;
|
|
@@ -15321,7 +15388,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
|
|
|
15321
15388
|
rollbackLegacy(new Error(`verify must be synchronous and return void, got thenable`));
|
|
15322
15389
|
}
|
|
15323
15390
|
try {
|
|
15324
|
-
|
|
15391
|
+
fs37.rmSync(markerPath, { force: true });
|
|
15325
15392
|
releaseLock();
|
|
15326
15393
|
} catch {
|
|
15327
15394
|
failIncomplete(`cannot clear transaction state after uninstall (recovery incomplete): ${markerPath}`);
|
|
@@ -15377,8 +15444,8 @@ async function activatePreparedPiInstall(input, deps) {
|
|
|
15377
15444
|
// src/lib/pi-stage-smoke.ts
|
|
15378
15445
|
init_detect();
|
|
15379
15446
|
import { spawn, spawnSync as spawnSync4 } from "child_process";
|
|
15380
|
-
import
|
|
15381
|
-
import
|
|
15447
|
+
import fs38 from "fs";
|
|
15448
|
+
import path46 from "path";
|
|
15382
15449
|
var REQUIRED_COMMANDS = ["goal", "subagents", "permission-system", "websearch", "jorgex:header"];
|
|
15383
15450
|
var EXPECTED_ARGV = ["--mode", "rpc", "--no-session", "--no-approve", "--offline", "--no-context-files"];
|
|
15384
15451
|
var KNOWN_STDERR_WARNING = "[pi-web-access] Dynamic tool activation requires Pi 0.86.1 or newer; web tools remain eagerly available.";
|
|
@@ -15395,13 +15462,13 @@ function isRecord12(value) {
|
|
|
15395
15462
|
}
|
|
15396
15463
|
function lstatOrNull6(p7) {
|
|
15397
15464
|
try {
|
|
15398
|
-
return
|
|
15465
|
+
return fs38.lstatSync(p7);
|
|
15399
15466
|
} catch {
|
|
15400
15467
|
return null;
|
|
15401
15468
|
}
|
|
15402
15469
|
}
|
|
15403
15470
|
function assertPiExecutable(piExecutable) {
|
|
15404
|
-
const absolute =
|
|
15471
|
+
const absolute = path46.resolve(piExecutable);
|
|
15405
15472
|
const linkStat = lstatOrNull6(absolute);
|
|
15406
15473
|
if (linkStat === null) {
|
|
15407
15474
|
fail10(`piExecutable must exist: ${piExecutable}`);
|
|
@@ -15409,13 +15476,13 @@ function assertPiExecutable(piExecutable) {
|
|
|
15409
15476
|
if (linkStat.isSymbolicLink()) {
|
|
15410
15477
|
let real;
|
|
15411
15478
|
try {
|
|
15412
|
-
real =
|
|
15479
|
+
real = fs38.realpathSync(absolute);
|
|
15413
15480
|
} catch {
|
|
15414
15481
|
fail10(`piExecutable symlink is broken: ${piExecutable}`);
|
|
15415
15482
|
}
|
|
15416
15483
|
let targetStat;
|
|
15417
15484
|
try {
|
|
15418
|
-
targetStat =
|
|
15485
|
+
targetStat = fs38.statSync(real);
|
|
15419
15486
|
} catch {
|
|
15420
15487
|
fail10(`piExecutable symlink target is missing: ${piExecutable}`);
|
|
15421
15488
|
}
|
|
@@ -15424,7 +15491,7 @@ function assertPiExecutable(piExecutable) {
|
|
|
15424
15491
|
}
|
|
15425
15492
|
if (process.platform !== "win32") {
|
|
15426
15493
|
try {
|
|
15427
|
-
|
|
15494
|
+
fs38.accessSync(real, fs38.constants.X_OK);
|
|
15428
15495
|
} catch {
|
|
15429
15496
|
fail10(`piExecutable symlink target is not executable: ${piExecutable}`);
|
|
15430
15497
|
}
|
|
@@ -15436,7 +15503,7 @@ function assertPiExecutable(piExecutable) {
|
|
|
15436
15503
|
}
|
|
15437
15504
|
if (process.platform !== "win32") {
|
|
15438
15505
|
try {
|
|
15439
|
-
|
|
15506
|
+
fs38.accessSync(absolute, fs38.constants.X_OK);
|
|
15440
15507
|
} catch {
|
|
15441
15508
|
fail10(`piExecutable is not executable: ${piExecutable}`);
|
|
15442
15509
|
}
|
|
@@ -15444,7 +15511,7 @@ function assertPiExecutable(piExecutable) {
|
|
|
15444
15511
|
return absolute;
|
|
15445
15512
|
}
|
|
15446
15513
|
function assertRealDir3(p7, label) {
|
|
15447
|
-
const resolved2 =
|
|
15514
|
+
const resolved2 = path46.resolve(p7);
|
|
15448
15515
|
const st = lstatOrNull6(resolved2);
|
|
15449
15516
|
if (st === null || !st.isDirectory() || st.isSymbolicLink()) {
|
|
15450
15517
|
fail10(`${label} must be a real directory: ${p7}`);
|
|
@@ -15459,24 +15526,24 @@ function sleep(ms) {
|
|
|
15459
15526
|
}
|
|
15460
15527
|
function runtimePath2(piExecutable) {
|
|
15461
15528
|
const entries = process.platform === "win32" ? [
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
process.env.SystemRoot ?
|
|
15465
|
-
] : [
|
|
15466
|
-
return [...new Set(entries.filter((entry) => entry !== null))].join(
|
|
15529
|
+
path46.dirname(piExecutable),
|
|
15530
|
+
path46.dirname(process.execPath),
|
|
15531
|
+
process.env.SystemRoot ? path46.join(process.env.SystemRoot, "System32") : null
|
|
15532
|
+
] : [path46.dirname(piExecutable), path46.dirname(process.execPath), "/usr/local/bin", "/usr/bin", "/bin"];
|
|
15533
|
+
return [...new Set(entries.filter((entry) => entry !== null))].join(path46.delimiter);
|
|
15467
15534
|
}
|
|
15468
15535
|
function buildSandboxEnv(stageRoot, stageDir, piExecutable) {
|
|
15469
|
-
const home =
|
|
15470
|
-
const appdata =
|
|
15471
|
-
const localappdata =
|
|
15472
|
-
const xdgConfig =
|
|
15473
|
-
const xdgData =
|
|
15474
|
-
const xdgCache =
|
|
15475
|
-
const temporary =
|
|
15476
|
-
const npmCache =
|
|
15536
|
+
const home = path46.join(stageRoot, "home");
|
|
15537
|
+
const appdata = path46.join(stageRoot, "appdata");
|
|
15538
|
+
const localappdata = path46.join(stageRoot, "localappdata");
|
|
15539
|
+
const xdgConfig = path46.join(stageRoot, "xdg-config");
|
|
15540
|
+
const xdgData = path46.join(stageRoot, "xdg-data");
|
|
15541
|
+
const xdgCache = path46.join(stageRoot, "xdg-cache");
|
|
15542
|
+
const temporary = path46.join(stageRoot, "tmp");
|
|
15543
|
+
const npmCache = path46.join(stageRoot, "npm-cache");
|
|
15477
15544
|
for (const dir of [home, appdata, localappdata, xdgConfig, xdgData, xdgCache, temporary, npmCache]) {
|
|
15478
15545
|
try {
|
|
15479
|
-
|
|
15546
|
+
fs38.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
15480
15547
|
} catch {
|
|
15481
15548
|
fail10(`cannot prepare isolated stage dir: ${dir}`);
|
|
15482
15549
|
}
|
|
@@ -15553,7 +15620,7 @@ async function stopOwned(child) {
|
|
|
15553
15620
|
if (process.platform === "win32") {
|
|
15554
15621
|
try {
|
|
15555
15622
|
const systemRoot = process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows";
|
|
15556
|
-
const taskkill =
|
|
15623
|
+
const taskkill = path46.join(systemRoot, "System32", "taskkill.exe");
|
|
15557
15624
|
spawnSync4(taskkill, ["/pid", String(pid), "/t", "/f"], {
|
|
15558
15625
|
shell: false,
|
|
15559
15626
|
stdio: "ignore",
|
|
@@ -15702,26 +15769,26 @@ async function smokeStagedPiRuntime(input) {
|
|
|
15702
15769
|
async function runSmoke(input) {
|
|
15703
15770
|
if (!isRecord12(input)) fail10("input must be an object");
|
|
15704
15771
|
const { piExecutable, stageDir, timeoutMs } = input;
|
|
15705
|
-
if (typeof piExecutable !== "string" || piExecutable === "" || !
|
|
15772
|
+
if (typeof piExecutable !== "string" || piExecutable === "" || !path46.isAbsolute(piExecutable)) {
|
|
15706
15773
|
fail10("piExecutable must be a non-empty absolute path");
|
|
15707
15774
|
}
|
|
15708
|
-
if (typeof stageDir !== "string" || stageDir === "" || !
|
|
15775
|
+
if (typeof stageDir !== "string" || stageDir === "" || !path46.isAbsolute(stageDir)) {
|
|
15709
15776
|
fail10("stageDir must be a non-empty absolute path");
|
|
15710
15777
|
}
|
|
15711
15778
|
const piResolved = assertPiExecutable(piExecutable);
|
|
15712
15779
|
const stageResolved = assertRealDir3(stageDir, "stageDir");
|
|
15713
|
-
if (
|
|
15780
|
+
if (path46.basename(stageResolved) !== "pi-agent") {
|
|
15714
15781
|
fail10("stageDir must be the staged pi-agent dir (stageRoot/pi-agent)");
|
|
15715
15782
|
}
|
|
15716
|
-
const stageRoot =
|
|
15783
|
+
const stageRoot = path46.dirname(stageResolved);
|
|
15717
15784
|
const stageRootStat = lstatOrNull6(stageRoot);
|
|
15718
15785
|
if (stageRootStat === null || !stageRootStat.isDirectory() || stageRootStat.isSymbolicLink()) {
|
|
15719
15786
|
fail10("stageRoot must be a real directory");
|
|
15720
15787
|
}
|
|
15721
|
-
if (!
|
|
15788
|
+
if (!path46.basename(stageRoot).startsWith("stage-")) {
|
|
15722
15789
|
fail10("stageRoot must be a private stage- dir");
|
|
15723
15790
|
}
|
|
15724
|
-
const workspace =
|
|
15791
|
+
const workspace = path46.join(stageRoot, "workspace");
|
|
15725
15792
|
assertRealDir3(workspace, "stage workspace");
|
|
15726
15793
|
let timeout = DEFAULT_TIMEOUT_MS;
|
|
15727
15794
|
if (timeoutMs !== void 0) {
|
|
@@ -15900,8 +15967,8 @@ ${JSON.stringify({ id: commandsId, type: "get_commands" })}
|
|
|
15900
15967
|
// src/lib/pi-cached-artifact.ts
|
|
15901
15968
|
init_npm_provider();
|
|
15902
15969
|
import { createHash as createHash9, timingSafeEqual as timingSafeEqual6 } from "crypto";
|
|
15903
|
-
import
|
|
15904
|
-
import
|
|
15970
|
+
import fs39 from "fs";
|
|
15971
|
+
import path47 from "path";
|
|
15905
15972
|
var PACKAGE_NAME5 = "jorgex-pi";
|
|
15906
15973
|
var HEX643 = /^[0-9a-f]{64}$/;
|
|
15907
15974
|
var HEX1283 = /^[0-9a-f]{128}$/;
|
|
@@ -15912,14 +15979,14 @@ function isRecord13(value) {
|
|
|
15912
15979
|
}
|
|
15913
15980
|
function lstatOrNull7(p7) {
|
|
15914
15981
|
try {
|
|
15915
|
-
return
|
|
15982
|
+
return fs39.lstatSync(p7);
|
|
15916
15983
|
} catch {
|
|
15917
15984
|
return null;
|
|
15918
15985
|
}
|
|
15919
15986
|
}
|
|
15920
15987
|
function isStrictChild5(child, root) {
|
|
15921
|
-
const rel =
|
|
15922
|
-
return rel !== "" && rel !== ".." && !rel.startsWith(`..${
|
|
15988
|
+
const rel = path47.relative(root, child);
|
|
15989
|
+
return rel !== "" && rel !== ".." && !rel.startsWith(`..${path47.sep}`) && !path47.isAbsolute(rel);
|
|
15923
15990
|
}
|
|
15924
15991
|
function equalHex2(aHex, bHex) {
|
|
15925
15992
|
let a;
|
|
@@ -15936,12 +16003,12 @@ function verifyCachedPiArtifact(input) {
|
|
|
15936
16003
|
try {
|
|
15937
16004
|
if (!isRecord13(input)) return false;
|
|
15938
16005
|
const { receipt, homeDir, downloadsDir } = input;
|
|
15939
|
-
if (typeof homeDir !== "string" || homeDir === "" || !
|
|
15940
|
-
if (typeof downloadsDir !== "string" || downloadsDir === "" || !
|
|
16006
|
+
if (typeof homeDir !== "string" || homeDir === "" || !path47.isAbsolute(homeDir)) return false;
|
|
16007
|
+
if (typeof downloadsDir !== "string" || downloadsDir === "" || !path47.isAbsolute(downloadsDir)) {
|
|
15941
16008
|
return false;
|
|
15942
16009
|
}
|
|
15943
|
-
const homeResolved =
|
|
15944
|
-
const downloadsResolved =
|
|
16010
|
+
const homeResolved = path47.resolve(homeDir);
|
|
16011
|
+
const downloadsResolved = path47.resolve(downloadsDir);
|
|
15945
16012
|
const homeStat = lstatOrNull7(homeResolved);
|
|
15946
16013
|
if (homeStat === null || !homeStat.isDirectory() || homeStat.isSymbolicLink()) return false;
|
|
15947
16014
|
const downloadsStat = lstatOrNull7(downloadsResolved);
|
|
@@ -15949,12 +16016,12 @@ function verifyCachedPiArtifact(input) {
|
|
|
15949
16016
|
return false;
|
|
15950
16017
|
}
|
|
15951
16018
|
if (!isStrictChild5(downloadsResolved, homeResolved)) return false;
|
|
15952
|
-
const rel =
|
|
15953
|
-
const parts = rel.split(
|
|
16019
|
+
const rel = path47.relative(homeResolved, downloadsResolved);
|
|
16020
|
+
const parts = rel.split(path47.sep);
|
|
15954
16021
|
let cursor = homeResolved;
|
|
15955
16022
|
for (const part of parts) {
|
|
15956
16023
|
if (part === "" || part === "." || part === "..") return false;
|
|
15957
|
-
cursor =
|
|
16024
|
+
cursor = path47.join(cursor, part);
|
|
15958
16025
|
const st2 = lstatOrNull7(cursor);
|
|
15959
16026
|
if (st2 === null || !st2.isDirectory() || st2.isSymbolicLink()) return false;
|
|
15960
16027
|
}
|
|
@@ -15980,8 +16047,8 @@ function verifyCachedPiArtifact(input) {
|
|
|
15980
16047
|
if (typeof sha2562 !== "string" || !HEX643.test(sha2562)) return false;
|
|
15981
16048
|
if (typeof sha512 !== "string" || !HEX1283.test(sha512)) return false;
|
|
15982
16049
|
const fileName = `${PACKAGE_NAME5}-${version}.tgz`;
|
|
15983
|
-
const target =
|
|
15984
|
-
if (
|
|
16050
|
+
const target = path47.join(downloadsResolved, fileName);
|
|
16051
|
+
if (path47.dirname(target) !== downloadsResolved) return false;
|
|
15985
16052
|
const st = lstatOrNull7(target);
|
|
15986
16053
|
if (st === null) return false;
|
|
15987
16054
|
if (st.isSymbolicLink()) return false;
|
|
@@ -15990,7 +16057,7 @@ function verifyCachedPiArtifact(input) {
|
|
|
15990
16057
|
if (st.size > MAX_TARBALL_BYTES4) return false;
|
|
15991
16058
|
let fd;
|
|
15992
16059
|
try {
|
|
15993
|
-
fd =
|
|
16060
|
+
fd = fs39.openSync(target, "r");
|
|
15994
16061
|
} catch {
|
|
15995
16062
|
return false;
|
|
15996
16063
|
}
|
|
@@ -16002,7 +16069,7 @@ function verifyCachedPiArtifact(input) {
|
|
|
16002
16069
|
for (; ; ) {
|
|
16003
16070
|
let read;
|
|
16004
16071
|
try {
|
|
16005
|
-
read =
|
|
16072
|
+
read = fs39.readSync(fd, buffer, 0, buffer.length, null);
|
|
16006
16073
|
} catch {
|
|
16007
16074
|
return false;
|
|
16008
16075
|
}
|
|
@@ -16014,7 +16081,7 @@ function verifyCachedPiArtifact(input) {
|
|
|
16014
16081
|
}
|
|
16015
16082
|
} finally {
|
|
16016
16083
|
try {
|
|
16017
|
-
|
|
16084
|
+
fs39.closeSync(fd);
|
|
16018
16085
|
} catch {
|
|
16019
16086
|
}
|
|
16020
16087
|
}
|
|
@@ -16176,30 +16243,30 @@ async function resolvePiEngramRequirement(input, deps) {
|
|
|
16176
16243
|
} : { kind: "existing", bin: detected, scope: "host" };
|
|
16177
16244
|
}
|
|
16178
16245
|
function runtimePath3(piExecutable) {
|
|
16179
|
-
const entries = process.platform === "win32" ? [piExecutable === void 0 ? null :
|
|
16180
|
-
return [...new Set(entries.filter((entry) => entry !== null))].join(
|
|
16246
|
+
const entries = process.platform === "win32" ? [piExecutable === void 0 ? null : path48.dirname(piExecutable), path48.dirname(process.execPath), process.env.SystemRoot ? path48.join(process.env.SystemRoot, "System32") : null] : [piExecutable === void 0 ? null : path48.dirname(piExecutable), path48.dirname(process.execPath), "/usr/local/bin", "/usr/bin", "/bin"];
|
|
16247
|
+
return [...new Set(entries.filter((entry) => entry !== null))].join(path48.delimiter);
|
|
16181
16248
|
}
|
|
16182
16249
|
function targetPaths(targetDir, engramBin, piExecutable) {
|
|
16183
|
-
const root =
|
|
16184
|
-
const codingAgentDir =
|
|
16185
|
-
const home =
|
|
16186
|
-
const temporary =
|
|
16250
|
+
const root = path48.resolve(targetDir);
|
|
16251
|
+
const codingAgentDir = path48.join(root, "pi-agent");
|
|
16252
|
+
const home = path48.join(root, "home");
|
|
16253
|
+
const temporary = path48.join(root, "tmp");
|
|
16187
16254
|
return {
|
|
16188
16255
|
codingAgentDir,
|
|
16189
|
-
receiptPath:
|
|
16190
|
-
packageRunner:
|
|
16256
|
+
receiptPath: path48.join(root, "state", "pi-receipt.json"),
|
|
16257
|
+
packageRunner: path48.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
|
|
16191
16258
|
environment: {
|
|
16192
16259
|
HOME: home,
|
|
16193
16260
|
USERPROFILE: home,
|
|
16194
|
-
APPDATA:
|
|
16195
|
-
LOCALAPPDATA:
|
|
16196
|
-
XDG_CONFIG_HOME:
|
|
16197
|
-
XDG_DATA_HOME:
|
|
16198
|
-
XDG_CACHE_HOME:
|
|
16261
|
+
APPDATA: path48.join(root, "appdata"),
|
|
16262
|
+
LOCALAPPDATA: path48.join(root, "localappdata"),
|
|
16263
|
+
XDG_CONFIG_HOME: path48.join(root, "xdg-config"),
|
|
16264
|
+
XDG_DATA_HOME: path48.join(root, "xdg-data"),
|
|
16265
|
+
XDG_CACHE_HOME: path48.join(root, "xdg-cache"),
|
|
16199
16266
|
TEMP: temporary,
|
|
16200
16267
|
TMP: temporary,
|
|
16201
16268
|
TMPDIR: temporary,
|
|
16202
|
-
npm_config_cache:
|
|
16269
|
+
npm_config_cache: path48.join(root, "npm-cache"),
|
|
16203
16270
|
NPM_CONFIG_IGNORE_SCRIPTS: "true",
|
|
16204
16271
|
NPM_CONFIG_UPDATE_NOTIFIER: "false",
|
|
16205
16272
|
PI_CODING_AGENT_DIR: codingAgentDir,
|
|
@@ -16210,15 +16277,15 @@ function targetPaths(targetDir, engramBin, piExecutable) {
|
|
|
16210
16277
|
}
|
|
16211
16278
|
function userPaths(engramBin, piExecutable) {
|
|
16212
16279
|
const home = os6.homedir();
|
|
16213
|
-
const codingAgentDir = process.env.PI_CODING_AGENT_DIR ??
|
|
16280
|
+
const codingAgentDir = process.env.PI_CODING_AGENT_DIR ?? path48.join(home, ".pi", "agent");
|
|
16214
16281
|
return {
|
|
16215
16282
|
codingAgentDir,
|
|
16216
|
-
receiptPath:
|
|
16217
|
-
packageRunner:
|
|
16283
|
+
receiptPath: path48.join(dataDir(), "pi-receipt.json"),
|
|
16284
|
+
packageRunner: path48.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
|
|
16218
16285
|
environment: {
|
|
16219
16286
|
HOME: home,
|
|
16220
|
-
XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME ??
|
|
16221
|
-
XDG_CACHE_HOME: process.env.XDG_CACHE_HOME ??
|
|
16287
|
+
XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME ?? path48.join(home, ".config"),
|
|
16288
|
+
XDG_CACHE_HOME: process.env.XDG_CACHE_HOME ?? path48.join(home, ".cache"),
|
|
16222
16289
|
TMPDIR: os6.tmpdir(),
|
|
16223
16290
|
NPM_CONFIG_IGNORE_SCRIPTS: "true",
|
|
16224
16291
|
NPM_CONFIG_UPDATE_NOTIFIER: "false",
|
|
@@ -16254,7 +16321,7 @@ function runPiRuntime(input, deps) {
|
|
|
16254
16321
|
}
|
|
16255
16322
|
const candidate = input.candidate ?? PI_RUNTIME_CANDIDATE;
|
|
16256
16323
|
const paths = input.targetDir === void 0 ? userPaths(input.engramBin, input.detected.executable) : targetPaths(input.targetDir, input.engramBin, input.detected.executable);
|
|
16257
|
-
const settingsJson = deps.readSettings(
|
|
16324
|
+
const settingsJson = deps.readSettings(path48.join(paths.codingAgentDir, "settings.json"));
|
|
16258
16325
|
const receiptJson = deps.readReceipt(paths.receiptPath);
|
|
16259
16326
|
const lifecycleInput = {
|
|
16260
16327
|
candidate,
|
|
@@ -16319,60 +16386,32 @@ function runPiRuntime(input, deps) {
|
|
|
16319
16386
|
persistReturnedReceipt(result, paths, deps);
|
|
16320
16387
|
return result;
|
|
16321
16388
|
}
|
|
16322
|
-
function readJsonFile2(file) {
|
|
16323
|
-
return JSON.parse(fs39.readFileSync(file, "utf8"));
|
|
16324
|
-
}
|
|
16325
|
-
function packageVersionFromExecutable(executable) {
|
|
16326
|
-
let current;
|
|
16327
|
-
try {
|
|
16328
|
-
current = path47.dirname(fs39.realpathSync(executable));
|
|
16329
|
-
} catch {
|
|
16330
|
-
return null;
|
|
16331
|
-
}
|
|
16332
|
-
for (let depth = 0; depth < 8; depth++) {
|
|
16333
|
-
const manifests = [
|
|
16334
|
-
path47.join(current, "package.json"),
|
|
16335
|
-
path47.join(current, "node_modules", "@earendil-works", "pi-coding-agent", "package.json")
|
|
16336
|
-
];
|
|
16337
|
-
for (const manifest of manifests) {
|
|
16338
|
-
try {
|
|
16339
|
-
const parsed = readJsonFile2(manifest);
|
|
16340
|
-
if (parsed !== null && typeof parsed === "object" && Reflect.get(parsed, "name") === "@earendil-works/pi-coding-agent" && typeof Reflect.get(parsed, "version") === "string") {
|
|
16341
|
-
return Reflect.get(parsed, "version");
|
|
16342
|
-
}
|
|
16343
|
-
} catch {
|
|
16344
|
-
}
|
|
16345
|
-
}
|
|
16346
|
-
const parent = path47.dirname(current);
|
|
16347
|
-
if (parent === current) break;
|
|
16348
|
-
current = parent;
|
|
16349
|
-
}
|
|
16350
|
-
return null;
|
|
16351
|
-
}
|
|
16352
16389
|
function detectPiRuntime() {
|
|
16353
16390
|
const executable = lookPath("pi");
|
|
16354
16391
|
const home = os6.homedir();
|
|
16392
|
+
const inspection = executable === null ? null : inspectPiHostVersion(executable);
|
|
16355
16393
|
return {
|
|
16356
16394
|
id: "pi",
|
|
16357
16395
|
name: "Pi",
|
|
16358
16396
|
installed: executable !== null,
|
|
16359
16397
|
executable,
|
|
16360
|
-
version:
|
|
16361
|
-
|
|
16398
|
+
version: inspection?.version ?? null,
|
|
16399
|
+
versionDiagnostic: inspection?.diagnostic ?? null,
|
|
16400
|
+
codingAgentDir: process.env.PI_CODING_AGENT_DIR ?? path48.join(home, ".pi", "agent")
|
|
16362
16401
|
};
|
|
16363
16402
|
}
|
|
16364
16403
|
function hasManagedPiRuntime(targetDir) {
|
|
16365
|
-
const receipt = targetDir === void 0 ?
|
|
16366
|
-
return
|
|
16404
|
+
const receipt = targetDir === void 0 ? path48.join(dataDir(), "pi-receipt.json") : path48.join(path48.resolve(targetDir), "state", "pi-receipt.json");
|
|
16405
|
+
return fs40.statSync(receipt, { throwIfNoEntry: false })?.isFile() === true;
|
|
16367
16406
|
}
|
|
16368
16407
|
function resolvePiEngramBin(targetDir) {
|
|
16369
16408
|
if (targetDir === void 0) return detectEngram();
|
|
16370
|
-
const candidate =
|
|
16371
|
-
return
|
|
16409
|
+
const candidate = path48.join(path48.resolve(targetDir), "bin", process.platform === "win32" ? "engram.exe" : "engram");
|
|
16410
|
+
return fs40.statSync(candidate, { throwIfNoEntry: false })?.isFile() ? candidate : null;
|
|
16372
16411
|
}
|
|
16373
16412
|
function readOptional(file, fallback) {
|
|
16374
16413
|
try {
|
|
16375
|
-
return
|
|
16414
|
+
return fs40.readFileSync(file, "utf8");
|
|
16376
16415
|
} catch (error) {
|
|
16377
16416
|
if (error.code === "ENOENT") return fallback;
|
|
16378
16417
|
throw error;
|
|
@@ -16438,7 +16477,7 @@ function preparedInstallMismatch(candidate, prepared) {
|
|
|
16438
16477
|
return "la release preparada no coincide con la versi\xF3n/SRI del candidato";
|
|
16439
16478
|
}
|
|
16440
16479
|
const stageDir = prepared?.stageDir;
|
|
16441
|
-
if (typeof stageDir !== "string" || stageDir === "" || !/(^|[\\/])stage-[0-9a-f]{32}[\\/]pi-agent$/.test(
|
|
16480
|
+
if (typeof stageDir !== "string" || stageDir === "" || !/(^|[\\/])stage-[0-9a-f]{32}[\\/]pi-agent$/.test(path48.resolve(stageDir))) {
|
|
16442
16481
|
return "el stage preparado no tiene el layout aislado esperado (stage-<hex>/pi-agent)";
|
|
16443
16482
|
}
|
|
16444
16483
|
const evidence = prepared?.evidence;
|
|
@@ -16513,12 +16552,12 @@ function backupLegacyMigrationState(settingsPath, receiptPath, backupRoot) {
|
|
|
16513
16552
|
}
|
|
16514
16553
|
}
|
|
16515
16554
|
function verifyActivePiRelease(input) {
|
|
16516
|
-
const agentDir =
|
|
16517
|
-
const npmDir =
|
|
16518
|
-
const managedRoot =
|
|
16555
|
+
const agentDir = path48.resolve(input.agentDir);
|
|
16556
|
+
const npmDir = path48.join(agentDir, "npm");
|
|
16557
|
+
const managedRoot = path48.join(npmDir, "jorgex-pi-managed");
|
|
16519
16558
|
let receiptRaw;
|
|
16520
16559
|
try {
|
|
16521
|
-
receiptRaw =
|
|
16560
|
+
receiptRaw = fs40.readFileSync(input.receiptPath, "utf8");
|
|
16522
16561
|
} catch {
|
|
16523
16562
|
throw new Error(`pi-verify-active: no se pudo leer el receipt promovido: ${input.receiptPath}`);
|
|
16524
16563
|
}
|
|
@@ -16547,7 +16586,7 @@ function verifyActivePiRelease(input) {
|
|
|
16547
16586
|
throw new Error("pi-verify-active: el scope del receipt promovido no coincide con el esperado");
|
|
16548
16587
|
}
|
|
16549
16588
|
const scopeDir = scopeRecord["codingAgentDir"];
|
|
16550
|
-
if (typeof scopeDir !== "string" || !
|
|
16589
|
+
if (typeof scopeDir !== "string" || !path48.isAbsolute(scopeDir) || path48.resolve(scopeDir) !== agentDir) {
|
|
16551
16590
|
throw new Error("pi-verify-active: el codingAgentDir del receipt promovido no coincide con el agentDir");
|
|
16552
16591
|
}
|
|
16553
16592
|
const receiptEngram = record["engram"];
|
|
@@ -16578,40 +16617,40 @@ function verifyActivePiRelease(input) {
|
|
|
16578
16617
|
throw new Error("pi-verify-active: el receipt promovido no conserva las seis dependencias de la evidencia");
|
|
16579
16618
|
}
|
|
16580
16619
|
const linkPath = managedRecord["linkPath"];
|
|
16581
|
-
if (typeof linkPath !== "string" || !
|
|
16620
|
+
if (typeof linkPath !== "string" || !path48.isAbsolute(linkPath)) {
|
|
16582
16621
|
throw new Error("pi-verify-active: el receipt promovido no trae un linkPath absoluto");
|
|
16583
16622
|
}
|
|
16584
|
-
const linkResolved =
|
|
16585
|
-
if (linkResolved !==
|
|
16623
|
+
const linkResolved = path48.resolve(linkPath);
|
|
16624
|
+
if (linkResolved !== path48.join(npmDir, "node_modules", "jorgex-pi")) {
|
|
16586
16625
|
throw new Error("pi-verify-active: el enlace publicado sale del entry propio");
|
|
16587
16626
|
}
|
|
16588
16627
|
const releaseDir = managedRecord["releaseDir"];
|
|
16589
|
-
if (typeof releaseDir !== "string" || !
|
|
16628
|
+
if (typeof releaseDir !== "string" || !path48.isAbsolute(releaseDir)) {
|
|
16590
16629
|
throw new Error("pi-verify-active: el receipt promovido no trae un releaseDir absoluto");
|
|
16591
16630
|
}
|
|
16592
|
-
const releaseResolved =
|
|
16593
|
-
const releaseRel =
|
|
16594
|
-
if (releaseRel === "" || releaseRel === ".." || releaseRel.startsWith(`..${
|
|
16631
|
+
const releaseResolved = path48.resolve(releaseDir);
|
|
16632
|
+
const releaseRel = path48.relative(managedRoot, releaseResolved);
|
|
16633
|
+
if (releaseRel === "" || releaseRel === ".." || releaseRel.startsWith(`..${path48.sep}`) || path48.isAbsolute(releaseRel)) {
|
|
16595
16634
|
throw new Error("pi-verify-active: el release promovido sale del root gestionado");
|
|
16596
16635
|
}
|
|
16597
16636
|
let target;
|
|
16598
16637
|
try {
|
|
16599
|
-
const linkStat =
|
|
16638
|
+
const linkStat = fs40.lstatSync(linkResolved);
|
|
16600
16639
|
if (!linkStat.isSymbolicLink()) {
|
|
16601
16640
|
throw new Error("pi-verify-active: el entry publicado no es un enlace");
|
|
16602
16641
|
}
|
|
16603
|
-
target =
|
|
16642
|
+
target = fs40.readlinkSync(linkResolved);
|
|
16604
16643
|
} catch (error) {
|
|
16605
16644
|
if (error instanceof Error && error.message.startsWith("pi-verify-active: ")) throw error;
|
|
16606
16645
|
throw new Error("pi-verify-active: no se pudo leer el enlace publicado");
|
|
16607
16646
|
}
|
|
16608
|
-
const packageRoot =
|
|
16609
|
-
if (target === "" ||
|
|
16647
|
+
const packageRoot = path48.join(releaseResolved, "node_modules", "jorgex-pi");
|
|
16648
|
+
if (target === "" || path48.isAbsolute(target) || path48.resolve(path48.dirname(linkResolved), target) !== packageRoot) {
|
|
16610
16649
|
throw new Error("pi-verify-active: el enlace publicado no apunta al release promovido");
|
|
16611
16650
|
}
|
|
16612
16651
|
let realRoot;
|
|
16613
16652
|
try {
|
|
16614
|
-
realRoot =
|
|
16653
|
+
realRoot = fs40.realpathSync(linkResolved);
|
|
16615
16654
|
} catch {
|
|
16616
16655
|
throw new Error("pi-verify-active: no se pudo resolver el realpath del enlace publicado");
|
|
16617
16656
|
}
|
|
@@ -16629,8 +16668,8 @@ function verifyActivePiRelease(input) {
|
|
|
16629
16668
|
}
|
|
16630
16669
|
}
|
|
16631
16670
|
function isStrictChildPath(child, root) {
|
|
16632
|
-
const rel =
|
|
16633
|
-
return rel !== "" && rel !== ".." && !rel.startsWith(`..${
|
|
16671
|
+
const rel = path48.relative(path48.resolve(root), path48.resolve(child));
|
|
16672
|
+
return rel !== "" && rel !== ".." && !rel.startsWith(`..${path48.sep}`) && !path48.isAbsolute(rel);
|
|
16634
16673
|
}
|
|
16635
16674
|
async function preparePiRuntimeSystem(input) {
|
|
16636
16675
|
if (input.operation !== "install" && input.operation !== "update") {
|
|
@@ -16648,7 +16687,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16648
16687
|
remedy: "El update con --target-dir nunca ejecuta preflight de red; aporta un stage preverificado o usa update real."
|
|
16649
16688
|
};
|
|
16650
16689
|
}
|
|
16651
|
-
if (typeof input.engramBin !== "string" || input.engramBin === "" || !
|
|
16690
|
+
if (typeof input.engramBin !== "string" || input.engramBin === "" || !path48.isAbsolute(input.engramBin)) {
|
|
16652
16691
|
return {
|
|
16653
16692
|
kind: "blocked",
|
|
16654
16693
|
reason: "engram-required",
|
|
@@ -16656,7 +16695,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16656
16695
|
};
|
|
16657
16696
|
}
|
|
16658
16697
|
const updateExecutable = input.detected.executable;
|
|
16659
|
-
if (typeof updateExecutable !== "string" || updateExecutable === "" || !
|
|
16698
|
+
if (typeof updateExecutable !== "string" || updateExecutable === "" || !path48.isAbsolute(updateExecutable)) {
|
|
16660
16699
|
return {
|
|
16661
16700
|
kind: "blocked",
|
|
16662
16701
|
reason: "pi-executable-missing",
|
|
@@ -16671,16 +16710,16 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16671
16710
|
};
|
|
16672
16711
|
}
|
|
16673
16712
|
const updateHomeDir = os6.homedir();
|
|
16674
|
-
if (typeof updateHomeDir !== "string" || updateHomeDir === "" || !
|
|
16713
|
+
if (typeof updateHomeDir !== "string" || updateHomeDir === "" || !path48.isAbsolute(updateHomeDir)) {
|
|
16675
16714
|
return {
|
|
16676
16715
|
kind: "blocked",
|
|
16677
16716
|
reason: "preflight-failed",
|
|
16678
16717
|
remedy: "HOME ilegible para el preflight Pi; Pi no qued\xF3 activado."
|
|
16679
16718
|
};
|
|
16680
16719
|
}
|
|
16681
|
-
const updateAgentDir = process.env.PI_CODING_AGENT_DIR ??
|
|
16682
|
-
const updateReceiptPath =
|
|
16683
|
-
const updateDownloadsDir =
|
|
16720
|
+
const updateAgentDir = process.env.PI_CODING_AGENT_DIR ?? path48.join(updateHomeDir, ".pi", "agent");
|
|
16721
|
+
const updateReceiptPath = path48.join(updateHomeDir, ".jorgex-stack", "pi-receipt.json");
|
|
16722
|
+
const updateDownloadsDir = path48.join(updateHomeDir, ".jorgex-stack", "packages");
|
|
16684
16723
|
if (!isStrictChildPath(updateAgentDir, updateHomeDir)) {
|
|
16685
16724
|
return {
|
|
16686
16725
|
kind: "blocked",
|
|
@@ -16688,7 +16727,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16688
16727
|
remedy: `PI_CODING_AGENT_DIR (${updateAgentDir}) est\xE1 fuera de la frontera de restore HOME (${updateHomeDir}); corrige el destino antes de reintentar; Pi no qued\xF3 activado.`
|
|
16689
16728
|
};
|
|
16690
16729
|
}
|
|
16691
|
-
const updateSettingsPath =
|
|
16730
|
+
const updateSettingsPath = path48.join(updateAgentDir, "settings.json");
|
|
16692
16731
|
let updateReceiptRaw;
|
|
16693
16732
|
let updateSettingsRaw;
|
|
16694
16733
|
try {
|
|
@@ -16704,7 +16743,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16704
16743
|
const stripUpdateGateNewline = (value) => value.endsWith("\n") ? value.slice(0, -1) : value;
|
|
16705
16744
|
const updateReceiptJson = updateReceiptRaw === null ? null : stripUpdateGateNewline(updateReceiptRaw);
|
|
16706
16745
|
const updateSettingsJson = stripUpdateGateNewline(updateSettingsRaw);
|
|
16707
|
-
const updatePackageRunner =
|
|
16746
|
+
const updatePackageRunner = path48.join(updateAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs");
|
|
16708
16747
|
const updateGate = verifyOfflineManagedPiRelease(
|
|
16709
16748
|
{
|
|
16710
16749
|
detected: {
|
|
@@ -16732,7 +16771,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16732
16771
|
return "remedy" in updateGate && typeof updateGate.remedy === "string" ? updateGate : { kind: "blocked", reason: updateGate.reason, remedy: `Verificaci\xF3n offline del receipt Pi fall\xF3 (${updateGate.reason}); sin preflight ni cambios. Pi no qued\xF3 activado.` };
|
|
16733
16772
|
}
|
|
16734
16773
|
try {
|
|
16735
|
-
|
|
16774
|
+
fs40.mkdirSync(updateDownloadsDir, { recursive: true });
|
|
16736
16775
|
} catch (error) {
|
|
16737
16776
|
return {
|
|
16738
16777
|
kind: "blocked",
|
|
@@ -16788,7 +16827,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16788
16827
|
};
|
|
16789
16828
|
}
|
|
16790
16829
|
const piExecutable = input.detected.executable;
|
|
16791
|
-
if (typeof piExecutable !== "string" || piExecutable === "" || !
|
|
16830
|
+
if (typeof piExecutable !== "string" || piExecutable === "" || !path48.isAbsolute(piExecutable)) {
|
|
16792
16831
|
return {
|
|
16793
16832
|
kind: "blocked",
|
|
16794
16833
|
reason: "pi-executable-missing",
|
|
@@ -16804,7 +16843,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16804
16843
|
}
|
|
16805
16844
|
const homeDir = os6.homedir();
|
|
16806
16845
|
const agentDir = userPaths(input.engramBin, piExecutable).codingAgentDir;
|
|
16807
|
-
const downloadsDir =
|
|
16846
|
+
const downloadsDir = path48.join(dataDir(), "packages");
|
|
16808
16847
|
if (!isStrictChildPath(agentDir, homeDir)) {
|
|
16809
16848
|
return {
|
|
16810
16849
|
kind: "blocked",
|
|
@@ -16814,7 +16853,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16814
16853
|
}
|
|
16815
16854
|
let preflightReceipt;
|
|
16816
16855
|
try {
|
|
16817
|
-
preflightReceipt =
|
|
16856
|
+
preflightReceipt = fs40.lstatSync(path48.join(dataDir(), "pi-receipt.json"), { throwIfNoEntry: false });
|
|
16818
16857
|
} catch (error) {
|
|
16819
16858
|
if (error.code === "ENOENT") {
|
|
16820
16859
|
preflightReceipt = void 0;
|
|
@@ -16829,7 +16868,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16829
16868
|
if (preflightReceipt === void 0) {
|
|
16830
16869
|
let preflightEntry;
|
|
16831
16870
|
try {
|
|
16832
|
-
preflightEntry =
|
|
16871
|
+
preflightEntry = fs40.lstatSync(path48.join(agentDir, "npm", "node_modules", "jorgex-pi"), {
|
|
16833
16872
|
throwIfNoEntry: false
|
|
16834
16873
|
});
|
|
16835
16874
|
} catch (error) {
|
|
@@ -16852,7 +16891,7 @@ async function preparePiRuntimeSystem(input) {
|
|
|
16852
16891
|
}
|
|
16853
16892
|
}
|
|
16854
16893
|
try {
|
|
16855
|
-
|
|
16894
|
+
fs40.mkdirSync(downloadsDir, { recursive: true });
|
|
16856
16895
|
} catch (error) {
|
|
16857
16896
|
return {
|
|
16858
16897
|
kind: "blocked",
|
|
@@ -16948,7 +16987,7 @@ async function runPiRuntimeSystem(input) {
|
|
|
16948
16987
|
remedy: `${mismatch}; Pi no qued\xF3 activado y no se descarg\xF3 ni modific\xF3 nada.`
|
|
16949
16988
|
};
|
|
16950
16989
|
}
|
|
16951
|
-
const settingsPath =
|
|
16990
|
+
const settingsPath = path48.join(paths.codingAgentDir, "settings.json");
|
|
16952
16991
|
let settingsJson = readOptional(settingsPath, '{"packages":[]}');
|
|
16953
16992
|
const receiptJson = readOptional(paths.receiptPath, null);
|
|
16954
16993
|
const scopeKind = input.targetDir === void 0 ? "real" : "target-dir";
|
|
@@ -16991,8 +17030,8 @@ async function runPiRuntimeSystem(input) {
|
|
|
16991
17030
|
};
|
|
16992
17031
|
}
|
|
16993
17032
|
try {
|
|
16994
|
-
const freshEntry =
|
|
16995
|
-
if (
|
|
17033
|
+
const freshEntry = path48.join(paths.codingAgentDir, "npm", "node_modules", "jorgex-pi");
|
|
17034
|
+
if (fs40.lstatSync(freshEntry, { throwIfNoEntry: false }) !== void 0) {
|
|
16996
17035
|
return {
|
|
16997
17036
|
kind: "blocked",
|
|
16998
17037
|
reason: "unowned-entry",
|
|
@@ -17102,7 +17141,7 @@ async function runPiRuntimeSystem(input) {
|
|
|
17102
17141
|
backupLegacyMigrationState(
|
|
17103
17142
|
settingsPath,
|
|
17104
17143
|
paths.receiptPath,
|
|
17105
|
-
input.targetDir === void 0 ? void 0 :
|
|
17144
|
+
input.targetDir === void 0 ? void 0 : path48.join(path48.resolve(input.targetDir), "backups")
|
|
17106
17145
|
);
|
|
17107
17146
|
} catch (error) {
|
|
17108
17147
|
return {
|
|
@@ -17112,7 +17151,7 @@ async function runPiRuntimeSystem(input) {
|
|
|
17112
17151
|
};
|
|
17113
17152
|
}
|
|
17114
17153
|
}
|
|
17115
|
-
const homeDir = input.targetDir === void 0 ? os6.homedir() :
|
|
17154
|
+
const homeDir = input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir);
|
|
17116
17155
|
const agentDir = paths.codingAgentDir;
|
|
17117
17156
|
const receiptPath = paths.receiptPath;
|
|
17118
17157
|
const stageDir = prepared.stageDir;
|
|
@@ -17165,7 +17204,7 @@ async function runPiRuntimeSystem(input) {
|
|
|
17165
17204
|
}
|
|
17166
17205
|
if (input.operation === "update") {
|
|
17167
17206
|
const engramBinForUpdate = input.engramBin;
|
|
17168
|
-
if (engramBinForUpdate === null || !
|
|
17207
|
+
if (engramBinForUpdate === null || !path48.isAbsolute(engramBinForUpdate)) {
|
|
17169
17208
|
return {
|
|
17170
17209
|
kind: "blocked",
|
|
17171
17210
|
reason: "engram-required",
|
|
@@ -17196,10 +17235,10 @@ async function runPiRuntimeSystem(input) {
|
|
|
17196
17235
|
remedy: `${updateMismatch}; Pi no qued\xF3 activado y no se descarg\xF3 ni modific\xF3 nada.`
|
|
17197
17236
|
};
|
|
17198
17237
|
}
|
|
17199
|
-
const updateSettingsPath =
|
|
17238
|
+
const updateSettingsPath = path48.join(paths.codingAgentDir, "settings.json");
|
|
17200
17239
|
const updateScopeKind = input.targetDir === void 0 ? "real" : "target-dir";
|
|
17201
|
-
const updateHomeDir = input.targetDir === void 0 ? os6.homedir() :
|
|
17202
|
-
const updateDownloadsDir = input.targetDir === void 0 ?
|
|
17240
|
+
const updateHomeDir = input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir);
|
|
17241
|
+
const updateDownloadsDir = input.targetDir === void 0 ? path48.join(dataDir(), "packages") : path48.join(path48.resolve(input.targetDir), "downloads");
|
|
17203
17242
|
const stripUpdateNewline = (value) => value.endsWith("\n") ? value.slice(0, -1) : value;
|
|
17204
17243
|
let updateSettingsRaw;
|
|
17205
17244
|
let updateReceiptRaw;
|
|
@@ -17378,13 +17417,13 @@ async function runPiRuntimeSystem(input) {
|
|
|
17378
17417
|
};
|
|
17379
17418
|
}
|
|
17380
17419
|
}
|
|
17381
|
-
const packageRoot =
|
|
17420
|
+
const packageRoot = path48.dirname(path48.dirname(paths.packageRunner));
|
|
17382
17421
|
const writeReceipt = (receipt) => {
|
|
17383
17422
|
writeText(paths.receiptPath, `${JSON.stringify(receipt, null, 2)}
|
|
17384
17423
|
`);
|
|
17385
17424
|
};
|
|
17386
17425
|
if (input.operation === "sync") {
|
|
17387
|
-
const settingsJson = readOptional(
|
|
17426
|
+
const settingsJson = readOptional(path48.join(paths.codingAgentDir, "settings.json"), '{"packages":[]}');
|
|
17388
17427
|
const receiptJson = readOptional(paths.receiptPath, null);
|
|
17389
17428
|
if (receiptJson === null) {
|
|
17390
17429
|
return {
|
|
@@ -17435,11 +17474,11 @@ async function runPiRuntimeSystem(input) {
|
|
|
17435
17474
|
run: runProcess,
|
|
17436
17475
|
verifyManagedArtifact: (receipt) => verifyCachedPiArtifact({
|
|
17437
17476
|
receipt,
|
|
17438
|
-
homeDir: input.targetDir === void 0 ? os6.homedir() :
|
|
17439
|
-
downloadsDir: input.targetDir === void 0 ?
|
|
17477
|
+
homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
|
|
17478
|
+
downloadsDir: input.targetDir === void 0 ? path48.join(dataDir(), "packages") : path48.join(path48.resolve(input.targetDir), "downloads")
|
|
17440
17479
|
}),
|
|
17441
|
-
isPackageAbsent: () => !
|
|
17442
|
-
deleteReceipt: () =>
|
|
17480
|
+
isPackageAbsent: () => !fs40.existsSync(packageRoot),
|
|
17481
|
+
deleteReceipt: () => fs40.rmSync(paths.receiptPath, { force: true })
|
|
17443
17482
|
}
|
|
17444
17483
|
);
|
|
17445
17484
|
}
|
|
@@ -17451,7 +17490,7 @@ async function runPiRuntimeSystem(input) {
|
|
|
17451
17490
|
}
|
|
17452
17491
|
}
|
|
17453
17492
|
if (input.operation === "models") {
|
|
17454
|
-
const settingsJson = readOptional(
|
|
17493
|
+
const settingsJson = readOptional(path48.join(paths.codingAgentDir, "settings.json"), '{"packages":[]}');
|
|
17455
17494
|
const receiptJson = readOptional(paths.receiptPath, null);
|
|
17456
17495
|
if (receiptJson === null) {
|
|
17457
17496
|
return {
|
|
@@ -17502,11 +17541,11 @@ async function runPiRuntimeSystem(input) {
|
|
|
17502
17541
|
run: runProcess,
|
|
17503
17542
|
verifyManagedArtifact: (receipt) => verifyCachedPiArtifact({
|
|
17504
17543
|
receipt,
|
|
17505
|
-
homeDir: input.targetDir === void 0 ? os6.homedir() :
|
|
17506
|
-
downloadsDir: input.targetDir === void 0 ?
|
|
17544
|
+
homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
|
|
17545
|
+
downloadsDir: input.targetDir === void 0 ? path48.join(dataDir(), "packages") : path48.join(path48.resolve(input.targetDir), "downloads")
|
|
17507
17546
|
}),
|
|
17508
|
-
isPackageAbsent: () => !
|
|
17509
|
-
deleteReceipt: () =>
|
|
17547
|
+
isPackageAbsent: () => !fs40.existsSync(packageRoot),
|
|
17548
|
+
deleteReceipt: () => fs40.rmSync(paths.receiptPath, { force: true })
|
|
17510
17549
|
}
|
|
17511
17550
|
);
|
|
17512
17551
|
}
|
|
@@ -17523,17 +17562,17 @@ async function runPiRuntimeSystem(input) {
|
|
|
17523
17562
|
value,
|
|
17524
17563
|
{
|
|
17525
17564
|
backupSettings: () => createBackup(
|
|
17526
|
-
[
|
|
17565
|
+
[path48.join(paths.codingAgentDir, "settings.json")],
|
|
17527
17566
|
"pi-package-uninstall",
|
|
17528
|
-
input.targetDir === void 0 ? void 0 :
|
|
17567
|
+
input.targetDir === void 0 ? void 0 : path48.join(path48.resolve(input.targetDir), "backups")
|
|
17529
17568
|
),
|
|
17530
17569
|
run: runProcess,
|
|
17531
17570
|
verifyManagedArtifact: (receipt) => verifyCachedPiArtifact({
|
|
17532
17571
|
receipt,
|
|
17533
|
-
homeDir: input.targetDir === void 0 ? os6.homedir() :
|
|
17534
|
-
downloadsDir: input.targetDir === void 0 ?
|
|
17572
|
+
homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
|
|
17573
|
+
downloadsDir: input.targetDir === void 0 ? path48.join(dataDir(), "packages") : path48.join(path48.resolve(input.targetDir), "downloads")
|
|
17535
17574
|
}),
|
|
17536
|
-
readSettings: () =>
|
|
17575
|
+
readSettings: () => fs40.readFileSync(path48.join(paths.codingAgentDir, "settings.json"), "utf8"),
|
|
17537
17576
|
verifyLegacyPackage: (receipt) => {
|
|
17538
17577
|
const op = value;
|
|
17539
17578
|
let effectiveEngram = op.engramBin;
|
|
@@ -17542,7 +17581,7 @@ async function runPiRuntimeSystem(input) {
|
|
|
17542
17581
|
const engram = Reflect.get(receipt, "engram");
|
|
17543
17582
|
if (engram === null || typeof engram !== "object" || Array.isArray(engram)) return false;
|
|
17544
17583
|
const binary = Reflect.get(engram, "binary");
|
|
17545
|
-
if (typeof binary !== "string" || binary === "" || !
|
|
17584
|
+
if (typeof binary !== "string" || binary === "" || !path48.isAbsolute(binary)) return false;
|
|
17546
17585
|
effectiveEngram = binary;
|
|
17547
17586
|
}
|
|
17548
17587
|
if (typeof effectiveEngram !== "string" || effectiveEngram === "") return false;
|
|
@@ -17566,17 +17605,17 @@ async function runPiRuntimeSystem(input) {
|
|
|
17566
17605
|
}
|
|
17567
17606
|
let currentReceiptRaw = null;
|
|
17568
17607
|
try {
|
|
17569
|
-
currentReceiptRaw =
|
|
17608
|
+
currentReceiptRaw = fs40.readFileSync(paths.receiptPath, "utf8");
|
|
17570
17609
|
} catch {
|
|
17571
17610
|
return { kind: "blocked", reason: "remove-failed" };
|
|
17572
17611
|
}
|
|
17573
17612
|
if (typeof op.receiptJson === "string" && currentReceiptRaw !== op.receiptJson) {
|
|
17574
17613
|
return { kind: "blocked", reason: "receipt-untrusted" };
|
|
17575
17614
|
}
|
|
17576
|
-
const settingsPath =
|
|
17577
|
-
const legacyEntry =
|
|
17615
|
+
const settingsPath = path48.join(paths.codingAgentDir, "settings.json");
|
|
17616
|
+
const legacyEntry = path48.join(paths.codingAgentDir, "npm", "node_modules", "jorgex-pi");
|
|
17578
17617
|
return deactivateVerifiedLegacyPiEntry({
|
|
17579
|
-
homeDir: input.targetDir === void 0 ? os6.homedir() :
|
|
17618
|
+
homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
|
|
17580
17619
|
agentDir: paths.codingAgentDir,
|
|
17581
17620
|
receiptPath: paths.receiptPath,
|
|
17582
17621
|
source,
|
|
@@ -17584,19 +17623,19 @@ async function runPiRuntimeSystem(input) {
|
|
|
17584
17623
|
verify: () => {
|
|
17585
17624
|
let entryStat = null;
|
|
17586
17625
|
try {
|
|
17587
|
-
entryStat =
|
|
17626
|
+
entryStat = fs40.lstatSync(legacyEntry);
|
|
17588
17627
|
} catch (error) {
|
|
17589
17628
|
if (error.code !== "ENOENT") throw error;
|
|
17590
17629
|
}
|
|
17591
17630
|
if (entryStat !== null) throw new Error("managed entry still present after uninstall");
|
|
17592
17631
|
let receiptStat = null;
|
|
17593
17632
|
try {
|
|
17594
|
-
receiptStat =
|
|
17633
|
+
receiptStat = fs40.lstatSync(paths.receiptPath);
|
|
17595
17634
|
} catch (error) {
|
|
17596
17635
|
if (error.code !== "ENOENT") throw error;
|
|
17597
17636
|
}
|
|
17598
17637
|
if (receiptStat !== null) throw new Error("receipt still present after uninstall");
|
|
17599
|
-
if (
|
|
17638
|
+
if (fs40.readFileSync(settingsPath, "utf8") !== nextSettings) {
|
|
17600
17639
|
throw new Error("settings mismatch after uninstall");
|
|
17601
17640
|
}
|
|
17602
17641
|
}
|
|
@@ -17611,9 +17650,9 @@ async function runPiRuntimeSystem(input) {
|
|
|
17611
17650
|
if (typeof mp.releaseDir !== "string" || typeof mp.linkPath !== "string" || typeof mp.backupDir !== "string") {
|
|
17612
17651
|
return { kind: "blocked", reason: "remove-failed" };
|
|
17613
17652
|
}
|
|
17614
|
-
const settingsPath =
|
|
17653
|
+
const settingsPath = path48.join(paths.codingAgentDir, "settings.json");
|
|
17615
17654
|
return deactivateVerifiedPiRelease({
|
|
17616
|
-
homeDir: input.targetDir === void 0 ? os6.homedir() :
|
|
17655
|
+
homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
|
|
17617
17656
|
agentDir: paths.codingAgentDir,
|
|
17618
17657
|
receiptPath: paths.receiptPath,
|
|
17619
17658
|
managedPackage: mp,
|
|
@@ -17621,33 +17660,33 @@ async function runPiRuntimeSystem(input) {
|
|
|
17621
17660
|
verify: () => {
|
|
17622
17661
|
let entryStat = null;
|
|
17623
17662
|
try {
|
|
17624
|
-
entryStat =
|
|
17663
|
+
entryStat = fs40.lstatSync(mp.linkPath);
|
|
17625
17664
|
} catch (error) {
|
|
17626
17665
|
if (error.code !== "ENOENT") throw error;
|
|
17627
17666
|
}
|
|
17628
17667
|
if (entryStat !== null) throw new Error("managed entry still present after uninstall");
|
|
17629
17668
|
let releaseStat = null;
|
|
17630
17669
|
try {
|
|
17631
|
-
releaseStat =
|
|
17670
|
+
releaseStat = fs40.lstatSync(mp.releaseDir);
|
|
17632
17671
|
} catch (error) {
|
|
17633
17672
|
if (error.code !== "ENOENT") throw error;
|
|
17634
17673
|
}
|
|
17635
17674
|
if (releaseStat !== null) throw new Error("managed release still present after uninstall");
|
|
17636
17675
|
let receiptStat = null;
|
|
17637
17676
|
try {
|
|
17638
|
-
receiptStat =
|
|
17677
|
+
receiptStat = fs40.lstatSync(paths.receiptPath);
|
|
17639
17678
|
} catch (error) {
|
|
17640
17679
|
if (error.code !== "ENOENT") throw error;
|
|
17641
17680
|
}
|
|
17642
17681
|
if (receiptStat !== null) throw new Error("receipt still present after uninstall");
|
|
17643
|
-
if (
|
|
17682
|
+
if (fs40.readFileSync(settingsPath, "utf8") !== nextSettings) {
|
|
17644
17683
|
throw new Error("settings mismatch after uninstall");
|
|
17645
17684
|
}
|
|
17646
17685
|
}
|
|
17647
17686
|
});
|
|
17648
17687
|
},
|
|
17649
|
-
isPackageAbsent: () => !
|
|
17650
|
-
deleteReceipt: () =>
|
|
17688
|
+
isPackageAbsent: () => !fs40.existsSync(packageRoot),
|
|
17689
|
+
deleteReceipt: () => fs40.rmSync(paths.receiptPath, { force: true })
|
|
17651
17690
|
}
|
|
17652
17691
|
)
|
|
17653
17692
|
};
|
|
@@ -17660,8 +17699,8 @@ init_pi();
|
|
|
17660
17699
|
init_system_prompt_sections();
|
|
17661
17700
|
|
|
17662
17701
|
// src/lib/pi-browser-contract.ts
|
|
17663
|
-
import
|
|
17664
|
-
import
|
|
17702
|
+
import fs41 from "fs";
|
|
17703
|
+
import path49 from "path";
|
|
17665
17704
|
var CONTRACT_FILE = "browser-handoffs.v1.json";
|
|
17666
17705
|
var MAX_CONTRACT_BYTES = 4 * 1024;
|
|
17667
17706
|
function fail11(message) {
|
|
@@ -17672,23 +17711,23 @@ function validSchemas(value) {
|
|
|
17672
17711
|
}
|
|
17673
17712
|
function requirePiBrowserHandoffSchemas(packageRoot, required) {
|
|
17674
17713
|
if (required.playwright === void 0 && required.devtools === void 0) return;
|
|
17675
|
-
if (typeof packageRoot !== "string" || !
|
|
17714
|
+
if (typeof packageRoot !== "string" || !path49.isAbsolute(packageRoot)) fail11("package root is not absolute");
|
|
17676
17715
|
let realRoot;
|
|
17677
17716
|
try {
|
|
17678
|
-
realRoot =
|
|
17679
|
-
if (!
|
|
17717
|
+
realRoot = fs41.realpathSync(packageRoot);
|
|
17718
|
+
if (!fs41.statSync(realRoot).isDirectory()) fail11("package root is not a directory");
|
|
17680
17719
|
} catch {
|
|
17681
17720
|
fail11("installed Pi package root is unavailable");
|
|
17682
17721
|
}
|
|
17683
|
-
const contractDir =
|
|
17684
|
-
const file =
|
|
17722
|
+
const contractDir = path49.join(realRoot, "contract");
|
|
17723
|
+
const file = path49.join(contractDir, CONTRACT_FILE);
|
|
17685
17724
|
let raw;
|
|
17686
17725
|
try {
|
|
17687
|
-
const dirStat =
|
|
17688
|
-
const stat =
|
|
17726
|
+
const dirStat = fs41.lstatSync(contractDir);
|
|
17727
|
+
const stat = fs41.lstatSync(file);
|
|
17689
17728
|
if (!dirStat.isDirectory() || dirStat.isSymbolicLink() || !stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_CONTRACT_BYTES) fail11("contract is not a bounded regular file");
|
|
17690
|
-
if (
|
|
17691
|
-
raw =
|
|
17729
|
+
if (fs41.realpathSync(file) !== file) fail11("contract path is not canonical");
|
|
17730
|
+
raw = fs41.readFileSync(file);
|
|
17692
17731
|
if (raw.byteLength > MAX_CONTRACT_BYTES || !Buffer.from(raw.toString("utf8"), "utf8").equals(raw)) {
|
|
17693
17732
|
fail11("contract is not bounded UTF-8");
|
|
17694
17733
|
}
|
|
@@ -17717,8 +17756,8 @@ function requirePiBrowserHandoffSchemas(packageRoot, required) {
|
|
|
17717
17756
|
|
|
17718
17757
|
// src/lib/pi-managed-runtime.ts
|
|
17719
17758
|
init_paths();
|
|
17720
|
-
import
|
|
17721
|
-
import
|
|
17759
|
+
import fs42 from "fs";
|
|
17760
|
+
import path50 from "path";
|
|
17722
17761
|
function projectionOperation(operation) {
|
|
17723
17762
|
return operation === "update" ? "sync" : operation;
|
|
17724
17763
|
}
|
|
@@ -17876,7 +17915,7 @@ async function runManagedPiSystem(input) {
|
|
|
17876
17915
|
const needsDevtoolsObservation = devtoolsMcpEnabled === true && input.operation !== "uninstall" && input.operation !== "models";
|
|
17877
17916
|
let devtoolsMcpObservedVersion = null;
|
|
17878
17917
|
let devtoolsVerifiedForPersist;
|
|
17879
|
-
const devtoolsManagedStateDir = input.targetDir === void 0 ? dataDir() :
|
|
17918
|
+
const devtoolsManagedStateDir = input.targetDir === void 0 ? dataDir() : path50.join(input.targetDir, "home", ".jorgex-stack");
|
|
17880
17919
|
if (needsDevtoolsObservation) {
|
|
17881
17920
|
if (input.targetDir !== void 0) {
|
|
17882
17921
|
devtoolsMcpObservedVersion = isValidObservedVersion(injectedDevtoolsObserved) ? { version: injectedDevtoolsObserved.version, integrity: injectedDevtoolsObserved.integrity } : null;
|
|
@@ -17924,8 +17963,8 @@ async function runManagedPiSystem(input) {
|
|
|
17924
17963
|
if (needsDevtoolsObservation) {
|
|
17925
17964
|
try {
|
|
17926
17965
|
if (input.targetDir !== void 0) {
|
|
17927
|
-
const target =
|
|
17928
|
-
const home =
|
|
17966
|
+
const target = fs42.lstatSync(input.targetDir);
|
|
17967
|
+
const home = fs42.lstatSync(path50.join(input.targetDir, "home"));
|
|
17929
17968
|
if (!target.isDirectory() || target.isSymbolicLink() || !home.isDirectory() || home.isSymbolicLink()) {
|
|
17930
17969
|
throw new Error("HOME del target Pi no es un directorio real aislado");
|
|
17931
17970
|
}
|
|
@@ -17949,7 +17988,7 @@ async function runManagedPiSystem(input) {
|
|
|
17949
17988
|
const playwrightCapabilityEffective = playwrightCapability?.effective === true;
|
|
17950
17989
|
const playwrightCliEnabled = input.targetDir === void 0 && supportsPlaywright && selectedPlaywright && playwrightCapabilityEffective;
|
|
17951
17990
|
const playwrightManagedStateDir = playwrightCliEnabled && input.operation !== "uninstall" && input.operation !== "models" ? dataDir() : void 0;
|
|
17952
|
-
const playwrightDispatcherPath = playwrightManagedStateDir === void 0 ? void 0 :
|
|
17991
|
+
const playwrightDispatcherPath = playwrightManagedStateDir === void 0 ? void 0 : path50.join(path50.dirname(stackRoot()), "dist", "browser-playwright.js");
|
|
17953
17992
|
let effectivePackageSource = PI_RUNTIME_CANDIDATE.package.source;
|
|
17954
17993
|
const projectionInput = {
|
|
17955
17994
|
writingStyle,
|
|
@@ -18006,7 +18045,7 @@ async function runManagedPiSystem(input) {
|
|
|
18006
18045
|
},
|
|
18007
18046
|
runProjection(operation) {
|
|
18008
18047
|
if (playwrightCliEnabled || devtoolsMcpEnabled) {
|
|
18009
|
-
const packageRoot =
|
|
18048
|
+
const packageRoot = path50.join(path50.dirname(piSystemPromptFile(input.targetDir)), "npm", "node_modules", "jorgex-pi");
|
|
18010
18049
|
try {
|
|
18011
18050
|
requirePiBrowserHandoffSchemas(packageRoot, {
|
|
18012
18051
|
...playwrightCliEnabled ? { playwright: 2 } : {},
|
|
@@ -18059,7 +18098,7 @@ init_fsx();
|
|
|
18059
18098
|
|
|
18060
18099
|
// src/lib/quality-runner.ts
|
|
18061
18100
|
init_detect();
|
|
18062
|
-
import
|
|
18101
|
+
import path51 from "path";
|
|
18063
18102
|
import { spawn as spawn2, spawnSync as spawnSync6 } from "child_process";
|
|
18064
18103
|
|
|
18065
18104
|
// src/lib/quality-policy.ts
|
|
@@ -18652,7 +18691,7 @@ function killProcessTree(child) {
|
|
|
18652
18691
|
if (pid === void 0) return;
|
|
18653
18692
|
if (process.platform === "win32") {
|
|
18654
18693
|
const systemRoot = process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows";
|
|
18655
|
-
const taskkill =
|
|
18694
|
+
const taskkill = path51.join(systemRoot, "System32", "taskkill.exe");
|
|
18656
18695
|
const result = spawnSync6(taskkill, ["/pid", String(pid), "/t", "/f"], {
|
|
18657
18696
|
shell: false,
|
|
18658
18697
|
stdio: "ignore",
|
|
@@ -18898,9 +18937,9 @@ async function runQualityPlan(input) {
|
|
|
18898
18937
|
}
|
|
18899
18938
|
|
|
18900
18939
|
// src/lib/engram-install.ts
|
|
18901
|
-
import
|
|
18940
|
+
import fs43 from "fs";
|
|
18902
18941
|
import os7 from "os";
|
|
18903
|
-
import
|
|
18942
|
+
import path52 from "path";
|
|
18904
18943
|
import { execFileSync as execFileSync8 } from "child_process";
|
|
18905
18944
|
import { createHash as createHash11 } from "crypto";
|
|
18906
18945
|
var MAX_ENGRAM_ARCHIVE_BYTES = 64 * 1024 * 1024;
|
|
@@ -18909,16 +18948,16 @@ var DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
|
|
|
18909
18948
|
async function installMissingEngram(options = {}) {
|
|
18910
18949
|
const platform = options.platform ?? process.platform;
|
|
18911
18950
|
const homeDir = options.homeDir ?? os7.homedir();
|
|
18912
|
-
if (!
|
|
18951
|
+
if (!path52.isAbsolute(homeDir)) return { ok: false, reason: "El directorio personal debe ser absoluto." };
|
|
18913
18952
|
const binaryName = platform === "win32" ? "engram.exe" : "engram";
|
|
18914
|
-
const bin =
|
|
18953
|
+
const bin = path52.join(homeDir, ".local", "bin", binaryName);
|
|
18915
18954
|
let staging;
|
|
18916
18955
|
let outcome;
|
|
18917
18956
|
try {
|
|
18918
|
-
const existing =
|
|
18957
|
+
const existing = fs43.lstatSync(bin, { throwIfNoEntry: false });
|
|
18919
18958
|
if (existing) {
|
|
18920
|
-
if (!
|
|
18921
|
-
|
|
18959
|
+
if (!fs43.statSync(bin).isFile()) throw new Error(`El destino Engram no es un archivo: ${bin}`);
|
|
18960
|
+
fs43.accessSync(bin, platform === "win32" ? fs43.constants.F_OK : fs43.constants.X_OK);
|
|
18922
18961
|
outcome = { ok: true, bin };
|
|
18923
18962
|
} else {
|
|
18924
18963
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
@@ -19031,19 +19070,19 @@ async function installMissingEngram(options = {}) {
|
|
|
19031
19070
|
if (size !== approvedSize || createHash11("sha256").update(archive).digest("hex") !== approvedSha) {
|
|
19032
19071
|
throw new Error("Engram: tama\xF1o o hash SHA-256 no coincide con el artefacto aprobado.");
|
|
19033
19072
|
}
|
|
19034
|
-
|
|
19035
|
-
staging =
|
|
19036
|
-
const archivePath =
|
|
19037
|
-
|
|
19073
|
+
fs43.mkdirSync(path52.dirname(bin), { recursive: true });
|
|
19074
|
+
staging = fs43.mkdtempSync(path52.join(path52.dirname(bin), ".engram-install-"));
|
|
19075
|
+
const archivePath = path52.join(staging, expectedName);
|
|
19076
|
+
fs43.writeFileSync(archivePath, archive, { flag: "wx", mode: 384 });
|
|
19038
19077
|
const binary = execFileSync8(resolveTarBin(), ["-xOf", archivePath, binaryName], {
|
|
19039
19078
|
maxBuffer: 64 * 1024 * 1024,
|
|
19040
19079
|
timeout: 3e4,
|
|
19041
19080
|
stdio: ["ignore", "pipe", "pipe"]
|
|
19042
19081
|
});
|
|
19043
19082
|
if (binary.length === 0) throw new Error("El artefacto Engram no contiene un binario v\xE1lido.");
|
|
19044
|
-
const stagedBin =
|
|
19045
|
-
|
|
19046
|
-
|
|
19083
|
+
const stagedBin = path52.join(staging, binaryName);
|
|
19084
|
+
fs43.writeFileSync(stagedBin, binary, { flag: "wx", mode: 493 });
|
|
19085
|
+
fs43.linkSync(stagedBin, bin);
|
|
19047
19086
|
outcome = { ok: true, bin };
|
|
19048
19087
|
}
|
|
19049
19088
|
} catch (error) {
|
|
@@ -19051,7 +19090,7 @@ async function installMissingEngram(options = {}) {
|
|
|
19051
19090
|
}
|
|
19052
19091
|
if (staging !== void 0) {
|
|
19053
19092
|
try {
|
|
19054
|
-
|
|
19093
|
+
fs43.rmSync(staging, { recursive: true, force: true });
|
|
19055
19094
|
} catch (cleanupError) {
|
|
19056
19095
|
const cleanupMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
19057
19096
|
if (outcome !== void 0 && outcome.ok) {
|
|
@@ -19447,7 +19486,7 @@ async function runSelectedPi(options) {
|
|
|
19447
19486
|
return 1;
|
|
19448
19487
|
}
|
|
19449
19488
|
if (detected.version === null) {
|
|
19450
|
-
console.error(
|
|
19489
|
+
console.error(`No se pudo verificar la versi\xF3n instalada de Pi sin ejecutarlo: ${detected.versionDiagnostic ?? "causa desconocida"}. Repara Pi con su instalador oficial antes de reintentar.`);
|
|
19451
19490
|
return 1;
|
|
19452
19491
|
}
|
|
19453
19492
|
let engramBin = resolvedEngramBin === void 0 ? resolvePiEngramBin(targetDir) : resolvedEngramBin;
|
|
@@ -19618,7 +19657,7 @@ Flags disponibles: jorgex-stack --help`
|
|
|
19618
19657
|
return;
|
|
19619
19658
|
}
|
|
19620
19659
|
try {
|
|
19621
|
-
const plan = JSON.parse(
|
|
19660
|
+
const plan = JSON.parse(fs44.readFileSync(flags.positional[0], "utf8"));
|
|
19622
19661
|
const result = await runQualityPlan(plan);
|
|
19623
19662
|
const serialized = serializeQualityReceipt(result.receipt);
|
|
19624
19663
|
if (flags.receipt === void 0) process.stdout.write(`${serialized}
|