@4pm/cli 1.4.1 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +287 -127
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28550,7 +28550,7 @@ ${INSECURE_URL_WARNING}
|
|
|
28550
28550
|
|
|
28551
28551
|
// src/commands/start.ts
|
|
28552
28552
|
import { spawn as spawn9 } from "child_process";
|
|
28553
|
-
import { join as
|
|
28553
|
+
import { join as join29 } from "path";
|
|
28554
28554
|
|
|
28555
28555
|
// src/core/update.ts
|
|
28556
28556
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -28723,7 +28723,7 @@ async function checkAndUpdate(serverUrl, autoUpdate) {
|
|
|
28723
28723
|
// src/core/ws-client.ts
|
|
28724
28724
|
init_wrapper();
|
|
28725
28725
|
import { randomUUID } from "crypto";
|
|
28726
|
-
import { basename as basename4, join as
|
|
28726
|
+
import { basename as basename4, join as join24 } from "path";
|
|
28727
28727
|
|
|
28728
28728
|
// vendor/@4pm/utils/helpers.ts
|
|
28729
28729
|
function backoffJitterMs(attempt, baseMs = 500, maxMs = 1e4) {
|
|
@@ -33087,6 +33087,19 @@ var createProjectRequestSchema = external_exports.object({
|
|
|
33087
33087
|
var copyProjectRequestSchema = external_exports.object({
|
|
33088
33088
|
name: external_exports.string().min(1).max(100)
|
|
33089
33089
|
});
|
|
33090
|
+
var PROJECT_ALERT_KINDS = ["budgetPercent", "absolute"];
|
|
33091
|
+
var projectAlertRuleSchema = external_exports.object({
|
|
33092
|
+
id: external_exports.string().min(1).max(64),
|
|
33093
|
+
kind: external_exports.enum(PROJECT_ALERT_KINDS),
|
|
33094
|
+
metric: external_exports.enum([UsageMetric.AI_TOKENS, UsageMetric.COMMANDS]),
|
|
33095
|
+
threshold: external_exports.number().int().min(1),
|
|
33096
|
+
email: external_exports.union([external_exports.string().email(), external_exports.literal("")]).optional(),
|
|
33097
|
+
notifyUserId: external_exports.union([external_exports.string().uuid(), external_exports.literal("")]).optional(),
|
|
33098
|
+
enabled: external_exports.boolean().default(true)
|
|
33099
|
+
});
|
|
33100
|
+
var projectAlertsSchema = external_exports.object({
|
|
33101
|
+
rules: external_exports.array(projectAlertRuleSchema).max(20).default([])
|
|
33102
|
+
});
|
|
33090
33103
|
var DEFAULT_OUTBOUND_RULES = {
|
|
33091
33104
|
secret: [
|
|
33092
33105
|
String.raw`/\b(api[_-]?key|secret|password|passwd|access[_-]?token|bearer)\b\s*[:=]\s*\S+/i`,
|
|
@@ -33309,9 +33322,47 @@ async function readCgroup(file) {
|
|
|
33309
33322
|
return null;
|
|
33310
33323
|
}
|
|
33311
33324
|
}
|
|
33325
|
+
function parseKv(text) {
|
|
33326
|
+
const map = /* @__PURE__ */ new Map();
|
|
33327
|
+
if (!text) return map;
|
|
33328
|
+
for (const line of text.split("\n")) {
|
|
33329
|
+
const [k, v] = line.trim().split(/\s+/);
|
|
33330
|
+
if (k && v !== void 0) {
|
|
33331
|
+
const n = Number(v);
|
|
33332
|
+
if (Number.isFinite(n)) map.set(k, n);
|
|
33333
|
+
}
|
|
33334
|
+
}
|
|
33335
|
+
return map;
|
|
33336
|
+
}
|
|
33337
|
+
function parsePressureSome(text) {
|
|
33338
|
+
if (!text) return void 0;
|
|
33339
|
+
const some = text.split("\n").find((l) => l.startsWith("some "));
|
|
33340
|
+
const m = some?.match(/avg10=([\d.]+)/);
|
|
33341
|
+
const n = m ? Number(m[1]) : NaN;
|
|
33342
|
+
return Number.isFinite(n) ? clampPct(n) : void 0;
|
|
33343
|
+
}
|
|
33344
|
+
function parseIoStat(text) {
|
|
33345
|
+
if (!text) return null;
|
|
33346
|
+
let rBytes = 0;
|
|
33347
|
+
let wBytes = 0;
|
|
33348
|
+
for (const line of text.split("\n")) {
|
|
33349
|
+
const r = line.match(/\brbytes=(\d+)/);
|
|
33350
|
+
const w = line.match(/\bwbytes=(\d+)/);
|
|
33351
|
+
if (r) rBytes += Number(r[1]);
|
|
33352
|
+
if (w) wBytes += Number(w[1]);
|
|
33353
|
+
}
|
|
33354
|
+
return { rBytes, wBytes };
|
|
33355
|
+
}
|
|
33356
|
+
function parseMaybeMax(text) {
|
|
33357
|
+
if (text === null) return null;
|
|
33358
|
+
if (text === "max") return null;
|
|
33359
|
+
const n = Number(text);
|
|
33360
|
+
return Number.isFinite(n) ? n : null;
|
|
33361
|
+
}
|
|
33312
33362
|
function createWorkerMetricsSampler(diskPath) {
|
|
33313
33363
|
const cgroupV2 = existsSync4(`${CGROUP}/cpu.stat`) && existsSync4(`${CGROUP}/memory.current`);
|
|
33314
|
-
let
|
|
33364
|
+
let cgPrev = null;
|
|
33365
|
+
let osPrev = null;
|
|
33315
33366
|
async function cgroupCpuCount() {
|
|
33316
33367
|
const raw = await readCgroup("cpu.max");
|
|
33317
33368
|
if (raw) {
|
|
@@ -33323,22 +33374,6 @@ function createWorkerMetricsSampler(diskPath) {
|
|
|
33323
33374
|
}
|
|
33324
33375
|
return cpus().length;
|
|
33325
33376
|
}
|
|
33326
|
-
async function cgroupCpuPct(cpuCount) {
|
|
33327
|
-
const stat2 = await readCgroup("cpu.stat");
|
|
33328
|
-
const m = stat2?.match(/usage_usec\s+(\d+)/);
|
|
33329
|
-
const usageUsec = m ? Number(m[1]) : NaN;
|
|
33330
|
-
const now = Date.now();
|
|
33331
|
-
if (!Number.isFinite(usageUsec)) return 0;
|
|
33332
|
-
if (!prev) {
|
|
33333
|
-
prev = { busy: usageUsec, ref: now };
|
|
33334
|
-
return 0;
|
|
33335
|
-
}
|
|
33336
|
-
const dUsage = usageUsec - prev.busy;
|
|
33337
|
-
const dWall = (now - prev.ref) * 1e3;
|
|
33338
|
-
prev = { busy: usageUsec, ref: now };
|
|
33339
|
-
if (dWall <= 0) return 0;
|
|
33340
|
-
return clampPct(dUsage / (dWall * cpuCount) * 100);
|
|
33341
|
-
}
|
|
33342
33377
|
function osCpuPct() {
|
|
33343
33378
|
let busy = 0;
|
|
33344
33379
|
let total = 0;
|
|
@@ -33347,13 +33382,13 @@ function createWorkerMetricsSampler(diskPath) {
|
|
|
33347
33382
|
busy += t.user + t.nice + t.sys + t.irq;
|
|
33348
33383
|
total += t.user + t.nice + t.sys + t.irq + t.idle;
|
|
33349
33384
|
}
|
|
33350
|
-
if (!
|
|
33351
|
-
|
|
33385
|
+
if (!osPrev) {
|
|
33386
|
+
osPrev = { busy, total };
|
|
33352
33387
|
return 0;
|
|
33353
33388
|
}
|
|
33354
|
-
const dBusy = busy -
|
|
33355
|
-
const dTotal = total -
|
|
33356
|
-
|
|
33389
|
+
const dBusy = busy - osPrev.busy;
|
|
33390
|
+
const dTotal = total - osPrev.total;
|
|
33391
|
+
osPrev = { busy, total };
|
|
33357
33392
|
if (dTotal <= 0) return 0;
|
|
33358
33393
|
return clampPct(dBusy / dTotal * 100);
|
|
33359
33394
|
}
|
|
@@ -33367,9 +33402,74 @@ function createWorkerMetricsSampler(diskPath) {
|
|
|
33367
33402
|
return { usedGb: 0, totalGb: 0 };
|
|
33368
33403
|
}
|
|
33369
33404
|
}
|
|
33405
|
+
async function cgroupExtended(cpuCount, now) {
|
|
33406
|
+
const [cpuStatRaw, memStatRaw, ioStatRaw, cpuPsi, memPsi, ioPsi, swapCurRaw, swapMaxRaw, memEventsRaw, pidsCurRaw, pidsMaxRaw] = await Promise.all([
|
|
33407
|
+
readCgroup("cpu.stat"),
|
|
33408
|
+
readCgroup("memory.stat"),
|
|
33409
|
+
readCgroup("io.stat"),
|
|
33410
|
+
readCgroup("cpu.pressure"),
|
|
33411
|
+
readCgroup("memory.pressure"),
|
|
33412
|
+
readCgroup("io.pressure"),
|
|
33413
|
+
readCgroup("memory.swap.current"),
|
|
33414
|
+
readCgroup("memory.swap.max"),
|
|
33415
|
+
readCgroup("memory.events"),
|
|
33416
|
+
readCgroup("pids.current"),
|
|
33417
|
+
readCgroup("pids.max")
|
|
33418
|
+
]);
|
|
33419
|
+
const cpuStat = parseKv(cpuStatRaw);
|
|
33420
|
+
const usageUsec = cpuStat.get("usage_usec") ?? NaN;
|
|
33421
|
+
const nrThrottled = cpuStat.get("nr_throttled") ?? 0;
|
|
33422
|
+
const nrPeriods = cpuStat.get("nr_periods") ?? 0;
|
|
33423
|
+
const io = parseIoStat(ioStatRaw);
|
|
33424
|
+
const extra = {};
|
|
33425
|
+
extra.cpuPressurePct = parsePressureSome(cpuPsi);
|
|
33426
|
+
extra.memPressurePct = parsePressureSome(memPsi);
|
|
33427
|
+
extra.ioPressurePct = parsePressureSome(ioPsi);
|
|
33428
|
+
const memStat = parseKv(memStatRaw);
|
|
33429
|
+
if (memStat.has("anon")) extra.memAnonMb = Math.round(memStat.get("anon") / MB);
|
|
33430
|
+
if (memStat.has("file")) extra.memCacheMb = Math.round(memStat.get("file") / MB);
|
|
33431
|
+
if (swapCurRaw !== null) extra.swapUsedMb = Math.round(Number(swapCurRaw) / MB);
|
|
33432
|
+
if (swapMaxRaw !== null) {
|
|
33433
|
+
const max = parseMaybeMax(swapMaxRaw);
|
|
33434
|
+
extra.swapTotalMb = max === null ? null : Math.round(max / MB);
|
|
33435
|
+
}
|
|
33436
|
+
const memEvents = parseKv(memEventsRaw);
|
|
33437
|
+
if (memEvents.has("oom_kill")) extra.oomKills = memEvents.get("oom_kill");
|
|
33438
|
+
if (pidsCurRaw !== null) {
|
|
33439
|
+
const n = Number(pidsCurRaw);
|
|
33440
|
+
if (Number.isFinite(n)) extra.pidsCurrent = n;
|
|
33441
|
+
}
|
|
33442
|
+
if (pidsMaxRaw !== null) extra.pidsMax = parseMaybeMax(pidsMaxRaw);
|
|
33443
|
+
let cpuPct = 0;
|
|
33444
|
+
if (Number.isFinite(usageUsec)) {
|
|
33445
|
+
if (cgPrev) {
|
|
33446
|
+
const dWallUsec = (now - cgPrev.wallMs) * 1e3;
|
|
33447
|
+
if (dWallUsec > 0) cpuPct = clampPct((usageUsec - cgPrev.usageUsec) / (dWallUsec * cpuCount) * 100);
|
|
33448
|
+
const dPeriods = nrPeriods - cgPrev.nrPeriods;
|
|
33449
|
+
if (dPeriods > 0) extra.cpuThrottledPct = clampPct((nrThrottled - cgPrev.nrThrottled) / dPeriods * 100);
|
|
33450
|
+
if (io) {
|
|
33451
|
+
const dSec = (now - cgPrev.wallMs) / 1e3;
|
|
33452
|
+
if (dSec > 0) {
|
|
33453
|
+
extra.diskReadMbps = round1((io.rBytes - cgPrev.ioR) / MB / dSec);
|
|
33454
|
+
extra.diskWriteMbps = round1((io.wBytes - cgPrev.ioW) / MB / dSec);
|
|
33455
|
+
}
|
|
33456
|
+
}
|
|
33457
|
+
}
|
|
33458
|
+
cgPrev = {
|
|
33459
|
+
usageUsec,
|
|
33460
|
+
nrThrottled,
|
|
33461
|
+
nrPeriods,
|
|
33462
|
+
ioR: io?.rBytes ?? 0,
|
|
33463
|
+
ioW: io?.wBytes ?? 0,
|
|
33464
|
+
wallMs: now
|
|
33465
|
+
};
|
|
33466
|
+
}
|
|
33467
|
+
return { cpuPct, extra };
|
|
33468
|
+
}
|
|
33370
33469
|
return {
|
|
33371
33470
|
async sample() {
|
|
33372
|
-
const
|
|
33471
|
+
const now = Date.now();
|
|
33472
|
+
const at = new Date(now).toISOString();
|
|
33373
33473
|
const { usedGb: diskUsedGb, totalGb: diskTotalGb } = await disk();
|
|
33374
33474
|
const base = { platform: platform(), arch: arch(), diskUsedGb, diskTotalGb, at };
|
|
33375
33475
|
if (cgroupV2) {
|
|
@@ -33378,14 +33478,15 @@ function createWorkerMetricsSampler(diskPath) {
|
|
|
33378
33478
|
const memTotalBytes = memMaxRaw && memMaxRaw !== "max" ? Number(memMaxRaw) : totalmem();
|
|
33379
33479
|
const memUsedBytes = memCurRaw ? Number(memCurRaw) : totalmem() - freemem();
|
|
33380
33480
|
const cpuCount = await cgroupCpuCount();
|
|
33381
|
-
const cpuPct = await
|
|
33481
|
+
const { cpuPct, extra } = await cgroupExtended(cpuCount, now);
|
|
33382
33482
|
return {
|
|
33383
33483
|
...base,
|
|
33384
33484
|
source: "cgroup",
|
|
33385
33485
|
cpuCount,
|
|
33386
33486
|
cpuPct,
|
|
33387
33487
|
memUsedMb: Math.round(memUsedBytes / MB),
|
|
33388
|
-
memTotalMb: Math.round(memTotalBytes / MB)
|
|
33488
|
+
memTotalMb: Math.round(memTotalBytes / MB),
|
|
33489
|
+
...extra
|
|
33389
33490
|
};
|
|
33390
33491
|
}
|
|
33391
33492
|
const total = totalmem();
|
|
@@ -33641,7 +33742,7 @@ function decryptPayload(key, payloadBase64, nonceBase64) {
|
|
|
33641
33742
|
}
|
|
33642
33743
|
|
|
33643
33744
|
// src/core/ws-client.ts
|
|
33644
|
-
import { existsSync as
|
|
33745
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5, rmSync as rmSync4 } from "fs";
|
|
33645
33746
|
import { randomUUID as randomCommandId } from "crypto";
|
|
33646
33747
|
|
|
33647
33748
|
// src/core/update-scheduler.ts
|
|
@@ -35404,28 +35505,87 @@ async function removePackage(root, slug) {
|
|
|
35404
35505
|
}
|
|
35405
35506
|
}
|
|
35406
35507
|
|
|
35407
|
-
// src/core/
|
|
35408
|
-
import {
|
|
35409
|
-
import {
|
|
35410
|
-
var
|
|
35411
|
-
|
|
35412
|
-
|
|
35508
|
+
// src/core/network-probe.ts
|
|
35509
|
+
import { existsSync as existsSync9, readFileSync as readFileSync14 } from "fs";
|
|
35510
|
+
import { connect } from "net";
|
|
35511
|
+
var CANARY_TARGETS = [
|
|
35512
|
+
{ host: "1.1.1.1", port: 443 },
|
|
35513
|
+
{ host: "8.8.8.8", port: 443 }
|
|
35514
|
+
];
|
|
35515
|
+
var PROBE_TIMEOUT_MS = 2500;
|
|
35516
|
+
function detectContainerized() {
|
|
35413
35517
|
try {
|
|
35414
|
-
if (
|
|
35415
|
-
|
|
35416
|
-
|
|
35417
|
-
|
|
35418
|
-
|
|
35419
|
-
|
|
35518
|
+
if (existsSync9("/.dockerenv")) return true;
|
|
35519
|
+
const cgroup = readFileSync14("/proc/1/cgroup", "utf8");
|
|
35520
|
+
return /docker|containerd|kubepods|libpod/.test(cgroup);
|
|
35521
|
+
} catch {
|
|
35522
|
+
return false;
|
|
35523
|
+
}
|
|
35524
|
+
}
|
|
35525
|
+
function canReach(host, port) {
|
|
35526
|
+
return new Promise((resolve8) => {
|
|
35527
|
+
const socket = connect({ host, port });
|
|
35528
|
+
let done = false;
|
|
35529
|
+
const finish = (ok) => {
|
|
35530
|
+
if (done) return;
|
|
35531
|
+
done = true;
|
|
35532
|
+
socket.destroy();
|
|
35533
|
+
resolve8(ok);
|
|
35534
|
+
};
|
|
35535
|
+
socket.setTimeout(PROBE_TIMEOUT_MS);
|
|
35536
|
+
socket.once("connect", () => finish(true));
|
|
35537
|
+
socket.once("timeout", () => finish(false));
|
|
35538
|
+
socket.once("error", () => finish(false));
|
|
35539
|
+
});
|
|
35540
|
+
}
|
|
35541
|
+
async function probeOutbound() {
|
|
35542
|
+
try {
|
|
35543
|
+
const results = await Promise.all(CANARY_TARGETS.map((t) => canReach(t.host, t.port)));
|
|
35544
|
+
return results.some(Boolean) ? "open" : "restricted";
|
|
35545
|
+
} catch {
|
|
35546
|
+
return "restricted";
|
|
35547
|
+
}
|
|
35548
|
+
}
|
|
35549
|
+
function probeInbound() {
|
|
35550
|
+
const isExposed = (path, loopbackHexPrefixes) => {
|
|
35551
|
+
let body;
|
|
35552
|
+
try {
|
|
35553
|
+
body = readFileSync14(path, "utf8");
|
|
35554
|
+
} catch {
|
|
35555
|
+
return false;
|
|
35420
35556
|
}
|
|
35557
|
+
for (const line of body.split("\n").slice(1)) {
|
|
35558
|
+
const cols = line.trim().split(/\s+/);
|
|
35559
|
+
const local = cols[1];
|
|
35560
|
+
const st = cols[3];
|
|
35561
|
+
if (!local || st !== "0A") continue;
|
|
35562
|
+
const addrHex = local.split(":")[0]?.toUpperCase() ?? "";
|
|
35563
|
+
if (loopbackHexPrefixes.some((p) => addrHex === p)) continue;
|
|
35564
|
+
return true;
|
|
35565
|
+
}
|
|
35566
|
+
return false;
|
|
35567
|
+
};
|
|
35568
|
+
try {
|
|
35569
|
+
const v4 = isExposed("/proc/net/tcp", ["0100007F"]);
|
|
35570
|
+
const v6 = isExposed("/proc/net/tcp6", ["00000000000000000000000001000000"]);
|
|
35571
|
+
return v4 || v6 ? "exposed" : "isolated";
|
|
35421
35572
|
} catch {
|
|
35573
|
+
return "isolated";
|
|
35422
35574
|
}
|
|
35423
35575
|
}
|
|
35576
|
+
async function probeNetwork() {
|
|
35577
|
+
return {
|
|
35578
|
+
outbound: await probeOutbound(),
|
|
35579
|
+
inbound: probeInbound(),
|
|
35580
|
+
containerized: detectContainerized(),
|
|
35581
|
+
checkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
35582
|
+
};
|
|
35583
|
+
}
|
|
35424
35584
|
|
|
35425
35585
|
// src/core/git-auth.ts
|
|
35426
|
-
import { writeFileSync as
|
|
35586
|
+
import { writeFileSync as writeFileSync6 } from "fs";
|
|
35427
35587
|
import { homedir as homedir4 } from "os";
|
|
35428
|
-
import { join as
|
|
35588
|
+
import { join as join16 } from "path";
|
|
35429
35589
|
function tokenTarget(method) {
|
|
35430
35590
|
if (method === "gitlab-group-token") {
|
|
35431
35591
|
return { host: process.env.FOURPM_GIT_HOST || "gitlab.com", user: "oauth2" };
|
|
@@ -35443,7 +35603,7 @@ function applyGitAuth(method) {
|
|
|
35443
35603
|
try {
|
|
35444
35604
|
const line = `https://${target.user}:${token}@${target.host}
|
|
35445
35605
|
`;
|
|
35446
|
-
|
|
35606
|
+
writeFileSync6(join16(homedir4(), ".git-credentials"), line, { encoding: "utf8", mode: 384 });
|
|
35447
35607
|
return true;
|
|
35448
35608
|
} catch {
|
|
35449
35609
|
return false;
|
|
@@ -35452,7 +35612,7 @@ function applyGitAuth(method) {
|
|
|
35452
35612
|
|
|
35453
35613
|
// src/core/secrets.ts
|
|
35454
35614
|
import { readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
35455
|
-
import { join as
|
|
35615
|
+
import { join as join17 } from "path";
|
|
35456
35616
|
var SECURITY_REL = "AI_SECURITY.md";
|
|
35457
35617
|
var PLACEHOLDER_REL = "AI_PLACEHOLDER.md";
|
|
35458
35618
|
var SECRETS_REL = "project.secrets.json";
|
|
@@ -35465,7 +35625,7 @@ async function readText3(path, fallback = "") {
|
|
|
35465
35625
|
}
|
|
35466
35626
|
async function readSecretsObject(root) {
|
|
35467
35627
|
try {
|
|
35468
|
-
const v = JSON.parse(await readFile6(
|
|
35628
|
+
const v = JSON.parse(await readFile6(join17(root, SECRETS_REL), "utf8"));
|
|
35469
35629
|
return v && typeof v === "object" ? v : {};
|
|
35470
35630
|
} catch {
|
|
35471
35631
|
return {};
|
|
@@ -35484,8 +35644,8 @@ function placeholderKeys(text) {
|
|
|
35484
35644
|
}
|
|
35485
35645
|
async function readSecrets(root) {
|
|
35486
35646
|
const [security, placeholder, secrets] = await Promise.all([
|
|
35487
|
-
readText3(
|
|
35488
|
-
readText3(
|
|
35647
|
+
readText3(join17(root, SECURITY_REL)),
|
|
35648
|
+
readText3(join17(root, PLACEHOLDER_REL)),
|
|
35489
35649
|
readSecretsObject(root)
|
|
35490
35650
|
]);
|
|
35491
35651
|
const names = /* @__PURE__ */ new Set([...placeholderKeys(placeholder), ...Object.keys(secrets)]);
|
|
@@ -35498,14 +35658,14 @@ async function readSecrets(root) {
|
|
|
35498
35658
|
async function writeSecrets(root, req) {
|
|
35499
35659
|
try {
|
|
35500
35660
|
if (req.kind === "security") {
|
|
35501
|
-
await writeFile5(
|
|
35661
|
+
await writeFile5(join17(root, SECURITY_REL), req.content, "utf8");
|
|
35502
35662
|
} else if (req.kind === "placeholder") {
|
|
35503
|
-
await writeFile5(
|
|
35663
|
+
await writeFile5(join17(root, PLACEHOLDER_REL), req.content, "utf8");
|
|
35504
35664
|
} else {
|
|
35505
35665
|
const secrets = await readSecretsObject(root);
|
|
35506
35666
|
if (req.kind === "secret") secrets[req.key] = req.value;
|
|
35507
35667
|
else delete secrets[req.key];
|
|
35508
|
-
await writeFile5(
|
|
35668
|
+
await writeFile5(join17(root, SECRETS_REL), JSON.stringify(secrets, null, 2) + "\n", "utf8");
|
|
35509
35669
|
}
|
|
35510
35670
|
return { ok: true };
|
|
35511
35671
|
} catch (err) {
|
|
@@ -35515,13 +35675,13 @@ async function writeSecrets(root, req) {
|
|
|
35515
35675
|
|
|
35516
35676
|
// src/core/agent-tools.ts
|
|
35517
35677
|
import { readFile as readFile7, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
|
|
35518
|
-
import { dirname as dirname5, join as
|
|
35678
|
+
import { dirname as dirname5, join as join18 } from "path";
|
|
35519
35679
|
var SHARED_REL = ".claude/settings.json";
|
|
35520
35680
|
var LOCAL_REL = ".claude/settings.local.json";
|
|
35521
35681
|
var SECRETS_DENY = "Read(./project.secrets.json)";
|
|
35522
35682
|
var MODES = ["default", "acceptEdits", "plan", "bypassPermissions"];
|
|
35523
35683
|
function fileFor(root, scope) {
|
|
35524
|
-
return
|
|
35684
|
+
return join18(root, scope === "shared" ? SHARED_REL : LOCAL_REL);
|
|
35525
35685
|
}
|
|
35526
35686
|
async function readSettingsObject(path) {
|
|
35527
35687
|
try {
|
|
@@ -35558,7 +35718,7 @@ async function writeAgentTools(root, scope, permissions) {
|
|
|
35558
35718
|
|
|
35559
35719
|
// src/core/graph.ts
|
|
35560
35720
|
import { readFile as readFile8, readdir as readdir5 } from "fs/promises";
|
|
35561
|
-
import { join as
|
|
35721
|
+
import { join as join19, relative as relative2, dirname as dirname6, resolve as resolve4, extname, basename as basename2 } from "path";
|
|
35562
35722
|
var MAX_FILES = 2e3;
|
|
35563
35723
|
var MAX_NODES = 3e3;
|
|
35564
35724
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", "out", "coverage", ".turbo"]);
|
|
@@ -35578,7 +35738,7 @@ async function walk(root, accept) {
|
|
|
35578
35738
|
if (e.name.startsWith(".") && e.name !== ".claude") {
|
|
35579
35739
|
if (e.isDirectory()) continue;
|
|
35580
35740
|
}
|
|
35581
|
-
const full =
|
|
35741
|
+
const full = join19(dir2, e.name);
|
|
35582
35742
|
if (e.isDirectory()) {
|
|
35583
35743
|
if (!SKIP_DIRS.has(e.name)) stack.push(full);
|
|
35584
35744
|
} else if (accept(full)) {
|
|
@@ -35698,10 +35858,10 @@ async function buildGraph(root, mode) {
|
|
|
35698
35858
|
|
|
35699
35859
|
// src/core/rag.ts
|
|
35700
35860
|
import { readFile as readFile9, writeFile as writeFile7, statfs as statfs2, mkdir as mkdir6 } from "fs/promises";
|
|
35701
|
-
import { existsSync as
|
|
35861
|
+
import { existsSync as existsSync10 } from "fs";
|
|
35702
35862
|
import { execFile as execFile4, spawn as spawn7 } from "child_process";
|
|
35703
35863
|
import { totalmem as totalmem2, cpus as cpus2 } from "os";
|
|
35704
|
-
import { join as
|
|
35864
|
+
import { join as join20 } from "path";
|
|
35705
35865
|
import { promisify as promisify4 } from "util";
|
|
35706
35866
|
var run3 = promisify4(execFile4);
|
|
35707
35867
|
var RAG_REL = ".claude/rag";
|
|
@@ -35722,7 +35882,7 @@ async function detectPython() {
|
|
|
35722
35882
|
}
|
|
35723
35883
|
async function installLog(root) {
|
|
35724
35884
|
try {
|
|
35725
|
-
const text = await readFile9(
|
|
35885
|
+
const text = await readFile9(join20(root, RAG_REL, "install.log"), "utf8");
|
|
35726
35886
|
return text.split("\n").filter((l) => l.length > 0).slice(-200);
|
|
35727
35887
|
} catch {
|
|
35728
35888
|
return [];
|
|
@@ -35784,14 +35944,14 @@ async function ragStatus(root) {
|
|
|
35784
35944
|
};
|
|
35785
35945
|
let modelName = "";
|
|
35786
35946
|
try {
|
|
35787
|
-
modelName = (await readFile9(
|
|
35947
|
+
modelName = (await readFile9(join20(root, RAG_REL, ".installed"), "utf8")).trim();
|
|
35788
35948
|
} catch {
|
|
35789
35949
|
modelName = "";
|
|
35790
35950
|
}
|
|
35791
35951
|
const modelPresent = modelName.length > 0;
|
|
35792
35952
|
return {
|
|
35793
35953
|
installed: fastembed && sqliteVec && modelPresent,
|
|
35794
|
-
installing:
|
|
35954
|
+
installing: existsSync10(join20(root, RAG_REL, ".installing")),
|
|
35795
35955
|
python: { found: py.found, version: py.version },
|
|
35796
35956
|
deps: { pip, fastembed, sqliteVec },
|
|
35797
35957
|
model: { present: modelPresent, name: modelName },
|
|
@@ -35802,9 +35962,9 @@ async function ragStatus(root) {
|
|
|
35802
35962
|
};
|
|
35803
35963
|
}
|
|
35804
35964
|
async function readIndexMeta(root) {
|
|
35805
|
-
const indexing =
|
|
35965
|
+
const indexing = existsSync10(join20(root, RAG_REL, ".indexing"));
|
|
35806
35966
|
try {
|
|
35807
|
-
const m = JSON.parse(await readFile9(
|
|
35967
|
+
const m = JSON.parse(await readFile9(join20(root, RAG_REL, ".index.json"), "utf8"));
|
|
35808
35968
|
return {
|
|
35809
35969
|
present: true,
|
|
35810
35970
|
indexing,
|
|
@@ -35871,14 +36031,14 @@ if __name__ == "__main__":
|
|
|
35871
36031
|
elif cmd == "query": query(sys.argv[2], int(sys.argv[3]) if len(sys.argv) > 3 else 8)
|
|
35872
36032
|
`;
|
|
35873
36033
|
async function ensureEngine(root) {
|
|
35874
|
-
await mkdir6(
|
|
35875
|
-
await writeFile7(
|
|
36034
|
+
await mkdir6(join20(root, RAG_REL), { recursive: true }).catch(() => void 0);
|
|
36035
|
+
await writeFile7(join20(root, RAG_REL, "rag_engine.py"), RAG_ENGINE_PY, "utf8");
|
|
35876
36036
|
}
|
|
35877
36037
|
async function ragReindex(root) {
|
|
35878
36038
|
const py = await detectPython();
|
|
35879
36039
|
if (!py.found) return { ok: false, started: false, error: "python3 not found" };
|
|
35880
|
-
if (!
|
|
35881
|
-
if (
|
|
36040
|
+
if (!existsSync10(join20(root, RAG_REL, ".installed"))) return { ok: false, started: false, error: "RAG is not installed" };
|
|
36041
|
+
if (existsSync10(join20(root, RAG_REL, ".indexing"))) return { ok: true, started: true };
|
|
35882
36042
|
await ensureEngine(root);
|
|
35883
36043
|
const script = `
|
|
35884
36044
|
set +e
|
|
@@ -35898,12 +36058,12 @@ rm -f "${RAG_REL}/.indexing"
|
|
|
35898
36058
|
async function ragQuery(root, queryText, k = 8) {
|
|
35899
36059
|
const py = await detectPython();
|
|
35900
36060
|
if (!py.found) return { results: [], error: "python3 not found" };
|
|
35901
|
-
if (!
|
|
36061
|
+
if (!existsSync10(join20(root, RAG_REL, "index.db"))) return { results: [], error: "no index \u2014 reindex first" };
|
|
35902
36062
|
await ensureEngine(root);
|
|
35903
36063
|
try {
|
|
35904
36064
|
const { stdout } = await run3(
|
|
35905
36065
|
py.bin,
|
|
35906
|
-
[
|
|
36066
|
+
[join20(RAG_REL, "rag_engine.py"), "query", queryText, String(Math.min(Math.max(k, 1), 20))],
|
|
35907
36067
|
{ cwd: root, timeout: 3e4, maxBuffer: 4 * 1024 * 1024 }
|
|
35908
36068
|
);
|
|
35909
36069
|
const parsed = JSON.parse(stdout.trim() || '{"results":[]}');
|
|
@@ -35915,9 +36075,9 @@ async function ragQuery(root, queryText, k = 8) {
|
|
|
35915
36075
|
async function ragInstall(root, model) {
|
|
35916
36076
|
const py = await detectPython();
|
|
35917
36077
|
if (!py.found) return { ok: false, started: false, error: "python3 not found on the worker" };
|
|
35918
|
-
if (
|
|
36078
|
+
if (existsSync10(join20(root, RAG_REL, ".installing"))) return { ok: true, started: true };
|
|
35919
36079
|
try {
|
|
35920
|
-
await mkdir6(
|
|
36080
|
+
await mkdir6(join20(root, RAG_REL), { recursive: true });
|
|
35921
36081
|
} catch {
|
|
35922
36082
|
}
|
|
35923
36083
|
const script = `
|
|
@@ -36005,12 +36165,12 @@ ${stderr}`;
|
|
|
36005
36165
|
// src/core/git-ssh-key.ts
|
|
36006
36166
|
import { execFile as execFile7 } from "child_process";
|
|
36007
36167
|
import { readFile as readFile11, rm as rm3, mkdir as mkdir7 } from "fs/promises";
|
|
36008
|
-
import { join as
|
|
36168
|
+
import { join as join21 } from "path";
|
|
36009
36169
|
import { promisify as promisify7 } from "util";
|
|
36010
36170
|
var run6 = promisify7(execFile7);
|
|
36011
36171
|
function keyPaths(profileDir2) {
|
|
36012
|
-
const dir2 =
|
|
36013
|
-
const key =
|
|
36172
|
+
const dir2 = join21(profileDir2, ".ssh");
|
|
36173
|
+
const key = join21(dir2, "id_4pm");
|
|
36014
36174
|
return { dir: dir2, key, pub: `${key}.pub` };
|
|
36015
36175
|
}
|
|
36016
36176
|
async function readPublicKey(pub) {
|
|
@@ -36202,7 +36362,7 @@ async function setCommitAuthor(cwd2, machineUsername) {
|
|
|
36202
36362
|
// src/core/scaffold.ts
|
|
36203
36363
|
import { cp, mkdir as mkdir8, writeFile as writeFile8 } from "fs/promises";
|
|
36204
36364
|
import { execFile as execFile10 } from "child_process";
|
|
36205
|
-
import { dirname as dirname8, join as
|
|
36365
|
+
import { dirname as dirname8, join as join22, resolve as resolve7 } from "path";
|
|
36206
36366
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
36207
36367
|
import { promisify as promisify10 } from "util";
|
|
36208
36368
|
var run9 = promisify10(execFile10);
|
|
@@ -36231,7 +36391,7 @@ async function provisionRepos(target, repos, emit, opts = {}) {
|
|
|
36231
36391
|
}
|
|
36232
36392
|
continue;
|
|
36233
36393
|
}
|
|
36234
|
-
const dir2 =
|
|
36394
|
+
const dir2 = join22(target, subDirName(repo));
|
|
36235
36395
|
if (repo.url) {
|
|
36236
36396
|
emit("git", `Cloning sub-repo ${repo.url}\u2026`);
|
|
36237
36397
|
await run9("git", ["clone", repo.url, dir2], { timeout: 12e4 });
|
|
@@ -36251,14 +36411,14 @@ async function scaffoldProject(payload, profileDir2, onProgress) {
|
|
|
36251
36411
|
const emit = (step, message) => onProgress?.({ projectId: payload.projectId, step, message });
|
|
36252
36412
|
try {
|
|
36253
36413
|
const root = process.env.SCAFFOLD_ROOT ? resolve7(process.env.SCAFFOLD_ROOT) : resolve7(profileDir2);
|
|
36254
|
-
const target =
|
|
36414
|
+
const target = join22(root, payload.projectName);
|
|
36255
36415
|
await mkdir8(target, { recursive: true });
|
|
36256
36416
|
emit("copy", "Copying the sample template\u2026");
|
|
36257
36417
|
await cp(sampleDir(), target, { recursive: true, force: false, errorOnExist: false });
|
|
36258
36418
|
if (payload.spec) {
|
|
36259
36419
|
emit("spec", "Writing project.spec.json\u2026");
|
|
36260
36420
|
await writeFile8(
|
|
36261
|
-
|
|
36421
|
+
join22(target, "project.spec.json"),
|
|
36262
36422
|
JSON.stringify(payload.spec, null, 2),
|
|
36263
36423
|
"utf8"
|
|
36264
36424
|
);
|
|
@@ -36276,7 +36436,7 @@ async function aiInit(target, spec, emit) {
|
|
|
36276
36436
|
emit("ai-init", "AI init: subagents, README, CLAUDE.md\u2026");
|
|
36277
36437
|
const subagents = Array.isArray(spec.subagents) ? spec.subagents : [];
|
|
36278
36438
|
if (subagents.length > 0) {
|
|
36279
|
-
await mkdir8(
|
|
36439
|
+
await mkdir8(join22(target, ".claude", "agents"), { recursive: true });
|
|
36280
36440
|
for (const sa of subagents) {
|
|
36281
36441
|
const name = (sa.name || "").trim().replace(/[^\w.-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
36282
36442
|
if (!name) continue;
|
|
@@ -36286,17 +36446,17 @@ name: ${name}
|
|
|
36286
36446
|
|
|
36287
36447
|
${(sa.description || "").trim()}
|
|
36288
36448
|
`;
|
|
36289
|
-
await writeFile8(
|
|
36449
|
+
await writeFile8(join22(target, ".claude", "agents", `${name}.md`), body, "utf8");
|
|
36290
36450
|
}
|
|
36291
36451
|
}
|
|
36292
36452
|
const specJson = JSON.stringify(spec);
|
|
36293
36453
|
await generateFile(
|
|
36294
|
-
|
|
36454
|
+
join22(target, "README.md"),
|
|
36295
36455
|
`Write a concise README.md (Markdown only, no preamble) for this project from its spec JSON:
|
|
36296
36456
|
${specJson}`
|
|
36297
36457
|
);
|
|
36298
36458
|
await generateFile(
|
|
36299
|
-
|
|
36459
|
+
join22(target, "CLAUDE.md"),
|
|
36300
36460
|
`Write a CLAUDE.md (Markdown only, no preamble) with guidance/conventions for AI agents working in this project, derived from its spec JSON:
|
|
36301
36461
|
${specJson}`
|
|
36302
36462
|
);
|
|
@@ -36312,7 +36472,7 @@ async function addProject(payload, profileDir2, onProgress) {
|
|
|
36312
36472
|
const emit = (step, message) => onProgress?.({ projectId: payload.projectId, step, message });
|
|
36313
36473
|
try {
|
|
36314
36474
|
const root = process.env.SCAFFOLD_ROOT ? resolve7(process.env.SCAFFOLD_ROOT) : resolve7(profileDir2);
|
|
36315
|
-
const target =
|
|
36475
|
+
const target = join22(root, payload.projectName);
|
|
36316
36476
|
await mkdir8(target, { recursive: true });
|
|
36317
36477
|
const repos = payload.repos ?? [];
|
|
36318
36478
|
if (repos.length > 0) await provisionRepos(target, repos, emit, { clonePrimary: true });
|
|
@@ -36324,14 +36484,14 @@ async function addProject(payload, profileDir2, onProgress) {
|
|
|
36324
36484
|
}
|
|
36325
36485
|
|
|
36326
36486
|
// src/core/config-sync.ts
|
|
36327
|
-
import { existsSync as
|
|
36328
|
-
import { join as
|
|
36487
|
+
import { existsSync as existsSync11, readFileSync as readFileSync15 } from "fs";
|
|
36488
|
+
import { join as join23 } from "path";
|
|
36329
36489
|
var SERVER_MANAGED_KEYS = ["physicPath", "sessionSwitchPct", "perPromptTokenLimit"];
|
|
36330
36490
|
function readConfigText(profileDir2) {
|
|
36331
|
-
const path =
|
|
36332
|
-
if (
|
|
36491
|
+
const path = join23(profileDir2, "config.json");
|
|
36492
|
+
if (existsSync11(path)) {
|
|
36333
36493
|
try {
|
|
36334
|
-
return
|
|
36494
|
+
return readFileSync15(path, "utf8");
|
|
36335
36495
|
} catch {
|
|
36336
36496
|
}
|
|
36337
36497
|
}
|
|
@@ -36756,7 +36916,6 @@ var WsClient = class {
|
|
|
36756
36916
|
});
|
|
36757
36917
|
this.outboundReviewEnabled = token.outboundReview?.enabled === true;
|
|
36758
36918
|
this.restrictToFolder = token.aiRestrictToFolder === true;
|
|
36759
|
-
writeEgressAllowlist(this.context.profileDir, token.aiSandbox ?? null);
|
|
36760
36919
|
applyGitAuth(token.gitAuth ?? null);
|
|
36761
36920
|
this.machineUsername = token.machineUsername ?? "";
|
|
36762
36921
|
if (token.scope && token.scope !== this.credential.scope) {
|
|
@@ -36904,8 +37063,8 @@ var WsClient = class {
|
|
|
36904
37063
|
const oldRoot = this.physicFolderPath(sync.oldName);
|
|
36905
37064
|
if (oldRoot) void uninstallCron(oldRoot).catch(() => void 0);
|
|
36906
37065
|
}
|
|
36907
|
-
if (sync.oldName)
|
|
36908
|
-
mkdirSync5(
|
|
37066
|
+
if (sync.oldName) rmSync4(join24(this.context.profileDir, sync.oldName), { recursive: true, force: true });
|
|
37067
|
+
mkdirSync5(join24(this.context.profileDir, sync.newName), { recursive: true });
|
|
36909
37068
|
this.physicRoot = this.physicFolderPath(sync.newName);
|
|
36910
37069
|
this.bus.setProject(sync.newName);
|
|
36911
37070
|
this.bus.log(`Physic project folder synced \u2192 ${sync.newName}`);
|
|
@@ -36916,7 +37075,7 @@ var WsClient = class {
|
|
|
36916
37075
|
if (del.name) {
|
|
36917
37076
|
const delRoot = this.physicFolderPath(del.name);
|
|
36918
37077
|
if (delRoot) void uninstallCron(delRoot).catch(() => void 0);
|
|
36919
|
-
|
|
37078
|
+
rmSync4(join24(this.context.profileDir, del.name), { recursive: true, force: true });
|
|
36920
37079
|
this.bus.log(`Physic project folder deleted (project removed) \u2192 ${del.name}`);
|
|
36921
37080
|
}
|
|
36922
37081
|
void manageSshKey("delete", this.context.profileDir).catch(() => void 0);
|
|
@@ -37288,7 +37447,7 @@ var WsClient = class {
|
|
|
37288
37447
|
}
|
|
37289
37448
|
case WsChannels.LOG_READ: {
|
|
37290
37449
|
const limit = Math.min(Math.max(payload.limit ?? 200, 1), 2e3);
|
|
37291
|
-
const lines = readRecentLogLines(
|
|
37450
|
+
const lines = readRecentLogLines(join24(this.context.profileDir, "logs"), limit);
|
|
37292
37451
|
this.send(WsChannels.LOG_READ, { lines }, message.id);
|
|
37293
37452
|
break;
|
|
37294
37453
|
}
|
|
@@ -37874,7 +38033,7 @@ var WsClient = class {
|
|
|
37874
38033
|
/** Create the physic folder at an absolute path if missing (best-effort). */
|
|
37875
38034
|
ensurePhysicFolderPath(folder) {
|
|
37876
38035
|
try {
|
|
37877
|
-
if (!
|
|
38036
|
+
if (!existsSync12(folder)) {
|
|
37878
38037
|
mkdirSync5(folder, { recursive: true });
|
|
37879
38038
|
this.bus.log(`Created physic project folder: ${folder}`);
|
|
37880
38039
|
}
|
|
@@ -37889,7 +38048,7 @@ var WsClient = class {
|
|
|
37889
38048
|
*/
|
|
37890
38049
|
physicFolderPath(projectName) {
|
|
37891
38050
|
const safe = projectName.replace(/[/\\]/g, "_").replace(/\.\./g, "_").trim();
|
|
37892
|
-
return safe ?
|
|
38051
|
+
return safe ? join24(this.context.profileDir, safe) : null;
|
|
37893
38052
|
}
|
|
37894
38053
|
/**
|
|
37895
38054
|
* Report machine.status: version + the state of the physic project being served
|
|
@@ -37903,7 +38062,7 @@ var WsClient = class {
|
|
|
37903
38062
|
projects: [],
|
|
37904
38063
|
version: CLI_VERSION,
|
|
37905
38064
|
physicPath,
|
|
37906
|
-
physicPathExists: physicPath ?
|
|
38065
|
+
physicPathExists: physicPath ? existsSync12(physicPath) : void 0,
|
|
37907
38066
|
// Real coarse state (ADR-0152): !paused and a recent tick (was hard-coded false).
|
|
37908
38067
|
autonomousRunning: physicPath ? isAutonomousRunning(physicPath) : false
|
|
37909
38068
|
});
|
|
@@ -37951,6 +38110,7 @@ var WsClient = class {
|
|
|
37951
38110
|
};
|
|
37952
38111
|
snapshot.aiCli = aiCli2;
|
|
37953
38112
|
snapshot.profile = profile;
|
|
38113
|
+
snapshot.network = await probeNetwork();
|
|
37954
38114
|
this.usageSnapshot = snapshot;
|
|
37955
38115
|
this.bus.setUsage?.(snapshot);
|
|
37956
38116
|
this.send(WsChannels.MACHINE_USAGE, snapshot);
|
|
@@ -37992,7 +38152,7 @@ var WsClient = class {
|
|
|
37992
38152
|
*/
|
|
37993
38153
|
uploadLog() {
|
|
37994
38154
|
try {
|
|
37995
|
-
const upload = readLogUpload(
|
|
38155
|
+
const upload = readLogUpload(join24(this.context.profileDir, "logs"));
|
|
37996
38156
|
if (!upload) return;
|
|
37997
38157
|
const sig = `${upload.fileName}:${upload.totalBytes}`;
|
|
37998
38158
|
if (sig === this.lastLogSig) return;
|
|
@@ -38020,10 +38180,10 @@ var WsClient = class {
|
|
|
38020
38180
|
};
|
|
38021
38181
|
|
|
38022
38182
|
// src/core/instance-lock.ts
|
|
38023
|
-
import { readFileSync as
|
|
38024
|
-
import { join as
|
|
38183
|
+
import { readFileSync as readFileSync16, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
38184
|
+
import { join as join25 } from "path";
|
|
38025
38185
|
function lockPath(profileDir2) {
|
|
38026
|
-
return
|
|
38186
|
+
return join25(profileDir2, "start.lock");
|
|
38027
38187
|
}
|
|
38028
38188
|
function isAlive(pid) {
|
|
38029
38189
|
try {
|
|
@@ -38035,7 +38195,7 @@ function isAlive(pid) {
|
|
|
38035
38195
|
}
|
|
38036
38196
|
function lockHolder(profileDir2) {
|
|
38037
38197
|
try {
|
|
38038
|
-
const pid = Number.parseInt(
|
|
38198
|
+
const pid = Number.parseInt(readFileSync16(lockPath(profileDir2), "utf8").trim(), 10);
|
|
38039
38199
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && isAlive(pid)) return pid;
|
|
38040
38200
|
} catch {
|
|
38041
38201
|
}
|
|
@@ -38043,13 +38203,13 @@ function lockHolder(profileDir2) {
|
|
|
38043
38203
|
}
|
|
38044
38204
|
function acquireInstanceLock(profileDir2) {
|
|
38045
38205
|
if (lockHolder(profileDir2) !== null) return false;
|
|
38046
|
-
|
|
38206
|
+
writeFileSync7(lockPath(profileDir2), String(process.pid), "utf8");
|
|
38047
38207
|
return true;
|
|
38048
38208
|
}
|
|
38049
38209
|
function releaseInstanceLock(profileDir2) {
|
|
38050
38210
|
try {
|
|
38051
|
-
const pid = Number.parseInt(
|
|
38052
|
-
if (pid === process.pid)
|
|
38211
|
+
const pid = Number.parseInt(readFileSync16(lockPath(profileDir2), "utf8").trim(), 10);
|
|
38212
|
+
if (pid === process.pid) rmSync5(lockPath(profileDir2), { force: true });
|
|
38053
38213
|
} catch {
|
|
38054
38214
|
}
|
|
38055
38215
|
}
|
|
@@ -38310,8 +38470,8 @@ var SessionBus = class {
|
|
|
38310
38470
|
|
|
38311
38471
|
// src/core/control-server.ts
|
|
38312
38472
|
import { createServer } from "net";
|
|
38313
|
-
import { rmSync as
|
|
38314
|
-
import { join as
|
|
38473
|
+
import { rmSync as rmSync6 } from "fs";
|
|
38474
|
+
import { join as join26 } from "path";
|
|
38315
38475
|
|
|
38316
38476
|
// src/core/control-protocol.ts
|
|
38317
38477
|
var CONTROL_SOCKET_FILE = "control.sock";
|
|
@@ -38340,9 +38500,9 @@ function createFrameParser() {
|
|
|
38340
38500
|
|
|
38341
38501
|
// src/core/control-server.ts
|
|
38342
38502
|
function startControlServer(bus, profileDir2, info) {
|
|
38343
|
-
const socketPath =
|
|
38503
|
+
const socketPath = join26(profileDir2, CONTROL_SOCKET_FILE);
|
|
38344
38504
|
try {
|
|
38345
|
-
|
|
38505
|
+
rmSync6(socketPath, { force: true });
|
|
38346
38506
|
} catch {
|
|
38347
38507
|
}
|
|
38348
38508
|
const clients = /* @__PURE__ */ new Set();
|
|
@@ -38408,7 +38568,7 @@ function startControlServer(bus, profileDir2, info) {
|
|
|
38408
38568
|
clients.clear();
|
|
38409
38569
|
server.close();
|
|
38410
38570
|
try {
|
|
38411
|
-
|
|
38571
|
+
rmSync6(socketPath, { force: true });
|
|
38412
38572
|
} catch {
|
|
38413
38573
|
}
|
|
38414
38574
|
};
|
|
@@ -40388,7 +40548,7 @@ var src_default = Yoga;
|
|
|
40388
40548
|
|
|
40389
40549
|
// ../../node_modules/.pnpm/ink@5.2.1_@types+react@18.3.31_react@18.3.1/node_modules/ink/build/reconciler.js
|
|
40390
40550
|
var import_react_reconciler = __toESM(require_react_reconciler(), 1);
|
|
40391
|
-
var
|
|
40551
|
+
var import_constants7 = __toESM(require_constants2(), 1);
|
|
40392
40552
|
import process3 from "process";
|
|
40393
40553
|
|
|
40394
40554
|
// ../../node_modules/.pnpm/ansi-regex@6.2.2/node_modules/ansi-regex/index.js
|
|
@@ -41630,7 +41790,7 @@ var reconciler_default = (0, import_react_reconciler.default)({
|
|
|
41630
41790
|
scheduleTimeout: setTimeout,
|
|
41631
41791
|
cancelTimeout: clearTimeout,
|
|
41632
41792
|
noTimeout: -1,
|
|
41633
|
-
getCurrentEventPriority: () =>
|
|
41793
|
+
getCurrentEventPriority: () => import_constants7.DefaultEventPriority,
|
|
41634
41794
|
beforeActiveInstanceBlur() {
|
|
41635
41795
|
},
|
|
41636
41796
|
afterActiveInstanceBlur() {
|
|
@@ -44072,17 +44232,17 @@ var import_react21 = __toESM(require_react(), 1);
|
|
|
44072
44232
|
var import_react26 = __toESM(require_react(), 1);
|
|
44073
44233
|
|
|
44074
44234
|
// src/core/input-history.ts
|
|
44075
|
-
import { existsSync as
|
|
44076
|
-
import { join as
|
|
44235
|
+
import { existsSync as existsSync14, readFileSync as readFileSync18, writeFileSync as writeFileSync8 } from "fs";
|
|
44236
|
+
import { join as join27 } from "path";
|
|
44077
44237
|
var MAX_HISTORY = 200;
|
|
44078
44238
|
function historyPath(profileDir2) {
|
|
44079
|
-
return
|
|
44239
|
+
return join27(profileDir2, "input-history.json");
|
|
44080
44240
|
}
|
|
44081
44241
|
function loadInputHistory(profileDir2) {
|
|
44082
44242
|
const path = historyPath(profileDir2);
|
|
44083
|
-
if (!
|
|
44243
|
+
if (!existsSync14(path)) return [];
|
|
44084
44244
|
try {
|
|
44085
|
-
const data = JSON.parse(
|
|
44245
|
+
const data = JSON.parse(readFileSync18(path, "utf8"));
|
|
44086
44246
|
return Array.isArray(data) ? data.filter((x) => typeof x === "string") : [];
|
|
44087
44247
|
} catch {
|
|
44088
44248
|
return [];
|
|
@@ -44093,7 +44253,7 @@ function appendInputHistory(profileDir2, line, current) {
|
|
|
44093
44253
|
if (!trimmed || current[current.length - 1] === trimmed) return current;
|
|
44094
44254
|
const next = [...current, trimmed].slice(-MAX_HISTORY);
|
|
44095
44255
|
try {
|
|
44096
|
-
|
|
44256
|
+
writeFileSync8(historyPath(profileDir2), JSON.stringify(next), "utf8");
|
|
44097
44257
|
} catch {
|
|
44098
44258
|
}
|
|
44099
44259
|
return next;
|
|
@@ -44342,8 +44502,8 @@ function TranscriptLine({ line }) {
|
|
|
44342
44502
|
var import_react24 = __toESM(require_react(), 1);
|
|
44343
44503
|
|
|
44344
44504
|
// src/ui/slash-commands.ts
|
|
44345
|
-
import { existsSync as
|
|
44346
|
-
import { join as
|
|
44505
|
+
import { existsSync as existsSync15 } from "fs";
|
|
44506
|
+
import { join as join28 } from "path";
|
|
44347
44507
|
var CONFIG_KEYS = [
|
|
44348
44508
|
"aiCli",
|
|
44349
44509
|
"claudeHome",
|
|
@@ -44355,7 +44515,7 @@ var CONFIG_KEYS = [
|
|
|
44355
44515
|
"aiEnv"
|
|
44356
44516
|
];
|
|
44357
44517
|
function configPath(profileDir2) {
|
|
44358
|
-
return
|
|
44518
|
+
return join28(profileDir2, "config.json");
|
|
44359
44519
|
}
|
|
44360
44520
|
function parseConfigAssignment(key, valueTokens) {
|
|
44361
44521
|
const value = valueTokens.join(" ").trim();
|
|
@@ -44405,7 +44565,7 @@ function runConfig(ctx) {
|
|
|
44405
44565
|
ctx.print(`\u2714 ${verb} default config: ${path}`);
|
|
44406
44566
|
ctx.print("add claude profiles: /config set claudeHome .claude .claude-1 (tried in order)");
|
|
44407
44567
|
};
|
|
44408
|
-
if (
|
|
44568
|
+
if (existsSync15(path)) {
|
|
44409
44569
|
ctx.confirm(
|
|
44410
44570
|
`config exists: ${path} \u2014 replace it with defaults? (y/N)`,
|
|
44411
44571
|
() => writeDefaults("replaced with")
|
|
@@ -44490,7 +44650,7 @@ function runOutput(ctx) {
|
|
|
44490
44650
|
}
|
|
44491
44651
|
function runLogs(ctx) {
|
|
44492
44652
|
const n = Math.max(1, Math.min(200, Number(ctx.args[0]) || 20));
|
|
44493
|
-
const dir2 =
|
|
44653
|
+
const dir2 = join28(ctx.info.profileDir, "logs");
|
|
44494
44654
|
const lines = readRecentLogLines(dir2, n);
|
|
44495
44655
|
if (lines.length === 0) {
|
|
44496
44656
|
ctx.print("No log lines yet.");
|
|
@@ -45011,7 +45171,7 @@ async function runStart(profileDir2, profileName) {
|
|
|
45011
45171
|
return;
|
|
45012
45172
|
}
|
|
45013
45173
|
logger.configure({
|
|
45014
|
-
dir:
|
|
45174
|
+
dir: join29(profileDir2, "logs"),
|
|
45015
45175
|
level: resolveLogLevel(),
|
|
45016
45176
|
base: { version: CLI_VERSION, profile: profileName, scope: credential.scope }
|
|
45017
45177
|
});
|
|
@@ -45117,13 +45277,13 @@ async function runStart(profileDir2, profileName) {
|
|
|
45117
45277
|
}
|
|
45118
45278
|
|
|
45119
45279
|
// src/commands/attach.ts
|
|
45120
|
-
import { join as
|
|
45280
|
+
import { join as join30 } from "path";
|
|
45121
45281
|
|
|
45122
45282
|
// src/core/control-client.ts
|
|
45123
|
-
import { connect } from "net";
|
|
45283
|
+
import { connect as connect2 } from "net";
|
|
45124
45284
|
function connectControl(socketPath, bus) {
|
|
45125
45285
|
return new Promise((resolve8, reject) => {
|
|
45126
|
-
const socket =
|
|
45286
|
+
const socket = connect2(socketPath);
|
|
45127
45287
|
socket.setEncoding("utf8");
|
|
45128
45288
|
let ready = false;
|
|
45129
45289
|
const forwardSubmit = bus.onLocalSubmit((input) => {
|
|
@@ -45216,7 +45376,7 @@ async function runAttach(profileDir2, profileName) {
|
|
|
45216
45376
|
process.exitCode = 1;
|
|
45217
45377
|
return;
|
|
45218
45378
|
}
|
|
45219
|
-
const socketPath =
|
|
45379
|
+
const socketPath = join30(profileDir2, CONTROL_SOCKET_FILE);
|
|
45220
45380
|
const bus = new SessionBus();
|
|
45221
45381
|
let conn;
|
|
45222
45382
|
try {
|
|
@@ -45301,7 +45461,7 @@ Tip: for the credentials to survive \`docker rm\`/recreate, keep each profile pa
|
|
|
45301
45461
|
}
|
|
45302
45462
|
|
|
45303
45463
|
// src/commands/unlink.ts
|
|
45304
|
-
import { rmSync as
|
|
45464
|
+
import { rmSync as rmSync7 } from "fs";
|
|
45305
45465
|
async function runUnlink(profileDir2, profileName) {
|
|
45306
45466
|
const cred = readCredential(profileDir2, profileName);
|
|
45307
45467
|
if (!cred) {
|
|
@@ -45316,7 +45476,7 @@ async function runUnlink(profileDir2, profileName) {
|
|
|
45316
45476
|
`\u26A0 Could not reach the server to revoke \u2014 revoke it at web /machines. (${err.message})`
|
|
45317
45477
|
);
|
|
45318
45478
|
}
|
|
45319
|
-
|
|
45479
|
+
rmSync7(profileDir2, { recursive: true, force: true });
|
|
45320
45480
|
clearDefaultProfileIf(profileName);
|
|
45321
45481
|
console.log("\u2714 Deleted the profile and its physic project folder.");
|
|
45322
45482
|
}
|