codeam-cli 2.39.53 → 2.39.55
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/CHANGELOG.md +12 -0
- package/dist/index.js +682 -458
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -87,7 +87,7 @@ var require_src = __commonJS({
|
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
// src/commands/start.ts
|
|
90
|
-
var
|
|
90
|
+
var import_picocolors4 = __toESM(require("picocolors"));
|
|
91
91
|
|
|
92
92
|
// ../../packages/shared/src/protocol/constants.ts
|
|
93
93
|
var PROTOCOL_VERSION = "2.0.0";
|
|
@@ -513,9 +513,9 @@ var _default = makeConfig();
|
|
|
513
513
|
var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, clearAll, saveCliConfig, loadCliConfig } = _default;
|
|
514
514
|
|
|
515
515
|
// src/commands/pair-auto.ts
|
|
516
|
-
var
|
|
517
|
-
var
|
|
518
|
-
var
|
|
516
|
+
var fs40 = __toESM(require("fs"));
|
|
517
|
+
var os33 = __toESM(require("os"));
|
|
518
|
+
var path46 = __toESM(require("path"));
|
|
519
519
|
var import_crypto4 = require("crypto");
|
|
520
520
|
|
|
521
521
|
// src/services/telemetry.service.ts
|
|
@@ -551,8 +551,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
551
551
|
return decodedFile;
|
|
552
552
|
};
|
|
553
553
|
}
|
|
554
|
-
function normalizeWindowsPath(
|
|
555
|
-
return
|
|
554
|
+
function normalizeWindowsPath(path59) {
|
|
555
|
+
return path59.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
556
556
|
}
|
|
557
557
|
|
|
558
558
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -3032,9 +3032,9 @@ async function addSourceContext(frames) {
|
|
|
3032
3032
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
3033
3033
|
return frames;
|
|
3034
3034
|
}
|
|
3035
|
-
function getContextLinesFromFile(
|
|
3035
|
+
function getContextLinesFromFile(path59, ranges, output) {
|
|
3036
3036
|
return new Promise((resolve7) => {
|
|
3037
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
3037
|
+
const stream = (0, import_node_fs.createReadStream)(path59);
|
|
3038
3038
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3039
3039
|
input: stream
|
|
3040
3040
|
});
|
|
@@ -3049,7 +3049,7 @@ function getContextLinesFromFile(path58, ranges, output) {
|
|
|
3049
3049
|
let rangeStart = range[0];
|
|
3050
3050
|
let rangeEnd = range[1];
|
|
3051
3051
|
function onStreamError() {
|
|
3052
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
3052
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path59, 1);
|
|
3053
3053
|
lineReaded.close();
|
|
3054
3054
|
lineReaded.removeAllListeners();
|
|
3055
3055
|
destroyStreamAndResolve();
|
|
@@ -3110,8 +3110,8 @@ function clearLineContext(frame) {
|
|
|
3110
3110
|
delete frame.context_line;
|
|
3111
3111
|
delete frame.post_context;
|
|
3112
3112
|
}
|
|
3113
|
-
function shouldSkipContextLinesForFile(
|
|
3114
|
-
return
|
|
3113
|
+
function shouldSkipContextLinesForFile(path59) {
|
|
3114
|
+
return path59.startsWith("node:") || path59.endsWith(".min.js") || path59.endsWith(".min.cjs") || path59.endsWith(".min.mjs") || path59.startsWith("data:");
|
|
3115
3115
|
}
|
|
3116
3116
|
function shouldSkipContextLinesForFrame(frame) {
|
|
3117
3117
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -5388,7 +5388,7 @@ function readAnonId() {
|
|
|
5388
5388
|
}
|
|
5389
5389
|
function superProperties() {
|
|
5390
5390
|
return {
|
|
5391
|
-
cliVersion: true ? "2.39.
|
|
5391
|
+
cliVersion: true ? "2.39.55" : "0.0.0-dev",
|
|
5392
5392
|
nodeVersion: process.version,
|
|
5393
5393
|
platform: process.platform,
|
|
5394
5394
|
arch: process.arch,
|
|
@@ -5547,7 +5547,7 @@ var os4 = __toESM(require("os"));
|
|
|
5547
5547
|
// package.json
|
|
5548
5548
|
var package_default = {
|
|
5549
5549
|
name: "codeam-cli",
|
|
5550
|
-
version: "2.39.
|
|
5550
|
+
version: "2.39.55",
|
|
5551
5551
|
description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
|
|
5552
5552
|
type: "commonjs",
|
|
5553
5553
|
main: "dist/index.js",
|
|
@@ -12502,11 +12502,11 @@ function parseReview(stdout) {
|
|
|
12502
12502
|
for (const line of lines) {
|
|
12503
12503
|
const m = line.match(HUNK_LINE_RE);
|
|
12504
12504
|
if (!m) continue;
|
|
12505
|
-
const [,
|
|
12506
|
-
if (!
|
|
12505
|
+
const [, path59, lineNo, sevToken, message] = m;
|
|
12506
|
+
if (!path59 || !lineNo || !message) continue;
|
|
12507
12507
|
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
12508
12508
|
hunks.push({
|
|
12509
|
-
path:
|
|
12509
|
+
path: path59.trim(),
|
|
12510
12510
|
line: Number(lineNo),
|
|
12511
12511
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
12512
12512
|
message: cleanedMessage
|
|
@@ -16779,8 +16779,10 @@ async function startInfraOnly(agentId) {
|
|
|
16779
16779
|
}
|
|
16780
16780
|
|
|
16781
16781
|
// src/commands/host-agent.ts
|
|
16782
|
-
var
|
|
16783
|
-
var
|
|
16782
|
+
var import_node_child_process13 = require("child_process");
|
|
16783
|
+
var os32 = __toESM(require("os"));
|
|
16784
|
+
var fs39 = __toESM(require("fs"));
|
|
16785
|
+
var path45 = __toESM(require("path"));
|
|
16784
16786
|
|
|
16785
16787
|
// src/commands/host/host-client.ts
|
|
16786
16788
|
var fs35 = __toESM(require("fs"));
|
|
@@ -17199,8 +17201,185 @@ var HeadroomStatsReporter = class {
|
|
|
17199
17201
|
}
|
|
17200
17202
|
};
|
|
17201
17203
|
|
|
17204
|
+
// src/lib/updateNotifier.ts
|
|
17205
|
+
var fs38 = __toESM(require("fs"));
|
|
17206
|
+
var os31 = __toESM(require("os"));
|
|
17207
|
+
var path44 = __toESM(require("path"));
|
|
17208
|
+
var https6 = __toESM(require("https"));
|
|
17209
|
+
var import_node_child_process12 = require("child_process");
|
|
17210
|
+
var import_picocolors3 = __toESM(require("picocolors"));
|
|
17211
|
+
var PKG_NAME = "codeam-cli";
|
|
17212
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
17213
|
+
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
17214
|
+
var REQUEST_TIMEOUT_MS = 1500;
|
|
17215
|
+
function cachePath() {
|
|
17216
|
+
const dir = path44.join(os31.homedir(), ".codeam");
|
|
17217
|
+
return path44.join(dir, "update-check.json");
|
|
17218
|
+
}
|
|
17219
|
+
function readCache() {
|
|
17220
|
+
try {
|
|
17221
|
+
const raw = fs38.readFileSync(cachePath(), "utf8");
|
|
17222
|
+
const parsed = JSON.parse(raw);
|
|
17223
|
+
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
17224
|
+
return parsed;
|
|
17225
|
+
} catch {
|
|
17226
|
+
return null;
|
|
17227
|
+
}
|
|
17228
|
+
}
|
|
17229
|
+
function writeCache(cache) {
|
|
17230
|
+
try {
|
|
17231
|
+
const file = cachePath();
|
|
17232
|
+
fs38.mkdirSync(path44.dirname(file), { recursive: true });
|
|
17233
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
17234
|
+
fs38.writeFileSync(tmp, JSON.stringify(cache));
|
|
17235
|
+
fs38.renameSync(tmp, file);
|
|
17236
|
+
} catch {
|
|
17237
|
+
}
|
|
17238
|
+
}
|
|
17239
|
+
function compareSemver(a, b) {
|
|
17240
|
+
const stripPre = (s) => s.split("-")[0];
|
|
17241
|
+
const aParts = stripPre(a).split(".").map(Number);
|
|
17242
|
+
const bParts = stripPre(b).split(".").map(Number);
|
|
17243
|
+
for (let i = 0; i < 3; i++) {
|
|
17244
|
+
const ai = aParts[i] ?? 0;
|
|
17245
|
+
const bi = bParts[i] ?? 0;
|
|
17246
|
+
if (Number.isNaN(ai) || Number.isNaN(bi)) return 0;
|
|
17247
|
+
if (ai > bi) return 1;
|
|
17248
|
+
if (ai < bi) return -1;
|
|
17249
|
+
}
|
|
17250
|
+
return 0;
|
|
17251
|
+
}
|
|
17252
|
+
function fetchLatest() {
|
|
17253
|
+
return new Promise((resolve7) => {
|
|
17254
|
+
const req = https6.get(
|
|
17255
|
+
REGISTRY_URL,
|
|
17256
|
+
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
17257
|
+
(res) => {
|
|
17258
|
+
if (res.statusCode !== 200) {
|
|
17259
|
+
res.resume();
|
|
17260
|
+
resolve7(null);
|
|
17261
|
+
return;
|
|
17262
|
+
}
|
|
17263
|
+
let buf = "";
|
|
17264
|
+
res.setEncoding("utf8");
|
|
17265
|
+
res.on("data", (chunk) => {
|
|
17266
|
+
buf += chunk;
|
|
17267
|
+
});
|
|
17268
|
+
res.on("end", () => {
|
|
17269
|
+
try {
|
|
17270
|
+
const json = JSON.parse(buf);
|
|
17271
|
+
if (typeof json.version === "string") {
|
|
17272
|
+
resolve7(json.version);
|
|
17273
|
+
} else {
|
|
17274
|
+
resolve7(null);
|
|
17275
|
+
}
|
|
17276
|
+
} catch {
|
|
17277
|
+
resolve7(null);
|
|
17278
|
+
}
|
|
17279
|
+
});
|
|
17280
|
+
}
|
|
17281
|
+
);
|
|
17282
|
+
req.on("timeout", () => {
|
|
17283
|
+
req.destroy();
|
|
17284
|
+
resolve7(null);
|
|
17285
|
+
});
|
|
17286
|
+
req.on("error", () => resolve7(null));
|
|
17287
|
+
});
|
|
17288
|
+
}
|
|
17289
|
+
function notifyIfStale(currentVersion, latest) {
|
|
17290
|
+
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
17291
|
+
const arrow = import_picocolors3.default.dim("\u2192");
|
|
17292
|
+
const cmd = import_picocolors3.default.cyan("npm install -g codeam-cli");
|
|
17293
|
+
const lines = [
|
|
17294
|
+
"",
|
|
17295
|
+
` ${import_picocolors3.default.yellow("\u25CF")} ${import_picocolors3.default.bold("Update available")} ${import_picocolors3.default.dim(currentVersion)} ${arrow} ${import_picocolors3.default.green(latest)}`,
|
|
17296
|
+
` Run ${cmd} to upgrade.`,
|
|
17297
|
+
""
|
|
17298
|
+
];
|
|
17299
|
+
process.stderr.write(lines.join("\n"));
|
|
17300
|
+
}
|
|
17301
|
+
function isLinkedInstall() {
|
|
17302
|
+
try {
|
|
17303
|
+
const root = (0, import_node_child_process12.execSync)("npm root -g", {
|
|
17304
|
+
encoding: "utf8",
|
|
17305
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
17306
|
+
timeout: 2e3
|
|
17307
|
+
}).trim();
|
|
17308
|
+
if (!root) return false;
|
|
17309
|
+
const pkgPath = path44.join(root, PKG_NAME);
|
|
17310
|
+
return fs38.lstatSync(pkgPath).isSymbolicLink();
|
|
17311
|
+
} catch {
|
|
17312
|
+
return false;
|
|
17313
|
+
}
|
|
17314
|
+
}
|
|
17315
|
+
function maybeAutoUpdate(currentVersion, latest) {
|
|
17316
|
+
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
17317
|
+
if (process.env.CODEAM_NO_AUTO_UPDATE === "1") {
|
|
17318
|
+
notifyIfStale(currentVersion, latest);
|
|
17319
|
+
return;
|
|
17320
|
+
}
|
|
17321
|
+
if (isLinkedInstall()) {
|
|
17322
|
+
notifyIfStale(currentVersion, latest);
|
|
17323
|
+
return;
|
|
17324
|
+
}
|
|
17325
|
+
process.stderr.write(
|
|
17326
|
+
`
|
|
17327
|
+
${import_picocolors3.default.yellow("\u25CF")} ${import_picocolors3.default.bold("Updating codeam-cli")} ${import_picocolors3.default.dim(currentVersion)} ${import_picocolors3.default.dim("\u2192")} ${import_picocolors3.default.green(latest)}...
|
|
17328
|
+
|
|
17329
|
+
`
|
|
17330
|
+
);
|
|
17331
|
+
const install = (0, import_node_child_process12.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
|
|
17332
|
+
stdio: "inherit",
|
|
17333
|
+
env: process.env
|
|
17334
|
+
});
|
|
17335
|
+
if (install.status !== 0) {
|
|
17336
|
+
process.stderr.write(
|
|
17337
|
+
`
|
|
17338
|
+
${import_picocolors3.default.red("!")} Update failed (exit ${install.status ?? "?"}). Continuing on ${currentVersion}.
|
|
17339
|
+
Run ${import_picocolors3.default.cyan("npm install -g codeam-cli")} manually to retry.
|
|
17340
|
+
|
|
17341
|
+
`
|
|
17342
|
+
);
|
|
17343
|
+
return;
|
|
17344
|
+
}
|
|
17345
|
+
try {
|
|
17346
|
+
fs38.unlinkSync(cachePath());
|
|
17347
|
+
} catch {
|
|
17348
|
+
}
|
|
17349
|
+
process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
|
|
17350
|
+
|
|
17351
|
+
`);
|
|
17352
|
+
const child = (0, import_node_child_process12.spawnSync)("codeam", process.argv.slice(2), {
|
|
17353
|
+
stdio: "inherit",
|
|
17354
|
+
env: process.env
|
|
17355
|
+
});
|
|
17356
|
+
process.exit(child.status ?? 0);
|
|
17357
|
+
}
|
|
17358
|
+
function checkForUpdates() {
|
|
17359
|
+
if (process.env.NODE_ENV === "test") return;
|
|
17360
|
+
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17361
|
+
if (process.env.CI) return;
|
|
17362
|
+
if (!process.stdout.isTTY) return;
|
|
17363
|
+
const current = true ? "2.39.55" : null;
|
|
17364
|
+
if (!current) return;
|
|
17365
|
+
const cache = readCache();
|
|
17366
|
+
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
17367
|
+
if (fresh && cache) {
|
|
17368
|
+
maybeAutoUpdate(current, cache.latest);
|
|
17369
|
+
return;
|
|
17370
|
+
}
|
|
17371
|
+
void fetchLatest().then((latest) => {
|
|
17372
|
+
if (!latest) return;
|
|
17373
|
+
writeCache({ fetchedAt: Date.now(), latest });
|
|
17374
|
+
});
|
|
17375
|
+
}
|
|
17376
|
+
|
|
17202
17377
|
// src/commands/host-agent.ts
|
|
17203
17378
|
var HEARTBEAT_INTERVAL_MS = 2e4;
|
|
17379
|
+
var SELF_UPDATE_PKG = "codeam-cli";
|
|
17380
|
+
var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
17381
|
+
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
17382
|
+
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
17204
17383
|
function maybeStartHeadroomReporter(ctx) {
|
|
17205
17384
|
if (process.env["HEADROOM_ENABLED"] !== "1") return null;
|
|
17206
17385
|
try {
|
|
@@ -17275,7 +17454,7 @@ var PIP_INSTALL_TIMEOUT_MS = 12e4;
|
|
|
17275
17454
|
var defaultHeadroomRunner = {
|
|
17276
17455
|
which(cmd) {
|
|
17277
17456
|
try {
|
|
17278
|
-
(0,
|
|
17457
|
+
(0, import_node_child_process13.execFileSync)("which", [cmd], { stdio: "ignore" });
|
|
17279
17458
|
return true;
|
|
17280
17459
|
} catch {
|
|
17281
17460
|
return false;
|
|
@@ -17283,7 +17462,7 @@ var defaultHeadroomRunner = {
|
|
|
17283
17462
|
},
|
|
17284
17463
|
run(cmd, args2, opts = {}) {
|
|
17285
17464
|
return new Promise((resolve7) => {
|
|
17286
|
-
const child = (0,
|
|
17465
|
+
const child = (0, import_node_child_process13.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"] });
|
|
17287
17466
|
let stderrBuf = "";
|
|
17288
17467
|
let settled = false;
|
|
17289
17468
|
const done = (code) => {
|
|
@@ -17409,6 +17588,48 @@ async function ensurePip(runner) {
|
|
|
17409
17588
|
log.info("host-agent", `bare box provisioned via ${pm} (python3+pip+ca-certificates+curl)`);
|
|
17410
17589
|
return true;
|
|
17411
17590
|
}
|
|
17591
|
+
function agentIdToHeadroomKind(agentId) {
|
|
17592
|
+
const normalized = (agentId ?? "").toLowerCase().replace(/[_-]/g, "");
|
|
17593
|
+
if (normalized.startsWith("claude")) return "claude";
|
|
17594
|
+
if (normalized.startsWith("codex")) return "codex";
|
|
17595
|
+
if (normalized.startsWith("copilot")) return "copilot";
|
|
17596
|
+
return "claude";
|
|
17597
|
+
}
|
|
17598
|
+
function headroomConfigPath() {
|
|
17599
|
+
return path45.join(os32.homedir(), ".codeam", "headroom-config.json");
|
|
17600
|
+
}
|
|
17601
|
+
function persistHeadroomConfig(config) {
|
|
17602
|
+
try {
|
|
17603
|
+
const file = headroomConfigPath();
|
|
17604
|
+
fs39.mkdirSync(path45.dirname(file), { recursive: true, mode: 448 });
|
|
17605
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
17606
|
+
fs39.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
|
|
17607
|
+
fs39.renameSync(tmp, file);
|
|
17608
|
+
} catch (err) {
|
|
17609
|
+
log.warn(
|
|
17610
|
+
"host-agent",
|
|
17611
|
+
`failed to persist headroom config (best-effort): ${err instanceof Error ? err.message : String(err)}`
|
|
17612
|
+
);
|
|
17613
|
+
}
|
|
17614
|
+
}
|
|
17615
|
+
function readHeadroomChildEnv() {
|
|
17616
|
+
try {
|
|
17617
|
+
const raw = fs39.readFileSync(headroomConfigPath(), "utf8");
|
|
17618
|
+
const parsed = JSON.parse(raw);
|
|
17619
|
+
if (typeof parsed !== "object" || parsed === null) return {};
|
|
17620
|
+
const o = parsed;
|
|
17621
|
+
if (o.enabled === true && typeof o.agent === "string" && o.agent.length > 0 && typeof o.ingestUrl === "string" && o.ingestUrl.length > 0) {
|
|
17622
|
+
return {
|
|
17623
|
+
HEADROOM_ENABLED: "1",
|
|
17624
|
+
HEADROOM_AGENT: o.agent,
|
|
17625
|
+
HEADROOM_SAVINGS_INGEST_URL: o.ingestUrl
|
|
17626
|
+
};
|
|
17627
|
+
}
|
|
17628
|
+
return {};
|
|
17629
|
+
} catch {
|
|
17630
|
+
return {};
|
|
17631
|
+
}
|
|
17632
|
+
}
|
|
17412
17633
|
async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner) {
|
|
17413
17634
|
const PIP_PACKAGES = [
|
|
17414
17635
|
"headroom-ai",
|
|
@@ -17464,8 +17685,9 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17464
17685
|
log.warn("host-agent", "headroom not found on PATH after install \u2014 skipping init");
|
|
17465
17686
|
return false;
|
|
17466
17687
|
}
|
|
17688
|
+
const initKind = agentIdToHeadroomKind(agent);
|
|
17467
17689
|
const initOk = await new Promise((resolve7) => {
|
|
17468
|
-
(0,
|
|
17690
|
+
(0, import_node_child_process13.execFile)("headroom", ["init", "--global", initKind], (initErr, stdout, stderr) => {
|
|
17469
17691
|
if (initErr) {
|
|
17470
17692
|
const detail = (stderr || initErr.message).replace(/\n+$/g, "");
|
|
17471
17693
|
log.warn("host-agent", `headroom init failed (best-effort): ${detail}`);
|
|
@@ -17481,7 +17703,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17481
17703
|
return false;
|
|
17482
17704
|
}
|
|
17483
17705
|
try {
|
|
17484
|
-
const proxy = (0,
|
|
17706
|
+
const proxy = (0, import_node_child_process13.spawn)("headroom", ["proxy", "--port", "8787"], {
|
|
17485
17707
|
stdio: "ignore",
|
|
17486
17708
|
detached: true
|
|
17487
17709
|
});
|
|
@@ -17491,20 +17713,81 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17491
17713
|
}
|
|
17492
17714
|
return true;
|
|
17493
17715
|
}
|
|
17494
|
-
var defaultSpawner = (env, cwd, args2 = []) => (0,
|
|
17716
|
+
var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process13.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
|
|
17495
17717
|
cwd,
|
|
17496
17718
|
env: { ...process.env, ...env },
|
|
17497
17719
|
stdio: ["ignore", "pipe", "pipe"],
|
|
17498
17720
|
detached: false
|
|
17499
17721
|
});
|
|
17722
|
+
function currentCliVersion() {
|
|
17723
|
+
return true ? "2.39.55" : null;
|
|
17724
|
+
}
|
|
17725
|
+
function runCmd(cmd, args2, timeoutMs) {
|
|
17726
|
+
return new Promise((resolve7) => {
|
|
17727
|
+
(0, import_node_child_process13.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
|
|
17728
|
+
const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
|
|
17729
|
+
resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
|
|
17730
|
+
});
|
|
17731
|
+
});
|
|
17732
|
+
}
|
|
17733
|
+
async function runSelfUpdate() {
|
|
17734
|
+
try {
|
|
17735
|
+
const current = currentCliVersion();
|
|
17736
|
+
if (!current) {
|
|
17737
|
+
log.trace("host-agent", "self-update: no __CLI_VERSION__ \u2014 skipping");
|
|
17738
|
+
return { status: "skipped" };
|
|
17739
|
+
}
|
|
17740
|
+
const view = await runCmd("npm", ["view", SELF_UPDATE_PKG, "version"], SELF_UPDATE_VIEW_TIMEOUT_MS);
|
|
17741
|
+
if (view.code !== 0) {
|
|
17742
|
+
log.trace("host-agent", `self-update: npm view exited ${String(view.code)} \u2014 skipping`);
|
|
17743
|
+
return { status: "skipped" };
|
|
17744
|
+
}
|
|
17745
|
+
const latest = view.stdout.trim();
|
|
17746
|
+
if (!latest) {
|
|
17747
|
+
log.trace("host-agent", "self-update: empty npm view output \u2014 skipping");
|
|
17748
|
+
return { status: "skipped" };
|
|
17749
|
+
}
|
|
17750
|
+
if (compareSemver(latest, current) <= 0) {
|
|
17751
|
+
return { status: "current" };
|
|
17752
|
+
}
|
|
17753
|
+
log.info("host-agent", `self-update: ${current} \u2192 ${latest} available \u2014 installing`);
|
|
17754
|
+
const installArgs = ["install", "-g", `${SELF_UPDATE_PKG}@latest`];
|
|
17755
|
+
let install = await runCmd("npm", installArgs, SELF_UPDATE_INSTALL_TIMEOUT_MS);
|
|
17756
|
+
const isRoot = process.getuid?.() === 0;
|
|
17757
|
+
if (install.code !== 0 && !isRoot && /EACCES/i.test(install.stderr)) {
|
|
17758
|
+
log.info("host-agent", "self-update: install hit EACCES \u2014 retrying with sudo");
|
|
17759
|
+
install = await runCmd("sudo", ["npm", ...installArgs], SELF_UPDATE_INSTALL_TIMEOUT_MS);
|
|
17760
|
+
}
|
|
17761
|
+
if (install.code !== 0) {
|
|
17762
|
+
log.warn(
|
|
17763
|
+
"host-agent",
|
|
17764
|
+
`self-update: install exited ${String(install.code)} \u2014 staying on ${current}`
|
|
17765
|
+
);
|
|
17766
|
+
return { status: "skipped" };
|
|
17767
|
+
}
|
|
17768
|
+
const after = await runCmd("npm", ["view", SELF_UPDATE_PKG, "version"], SELF_UPDATE_VIEW_TIMEOUT_MS);
|
|
17769
|
+
const installed = after.code === 0 ? after.stdout.trim() || latest : latest;
|
|
17770
|
+
return { status: "updated", version: installed };
|
|
17771
|
+
} catch (err) {
|
|
17772
|
+
log.warn(
|
|
17773
|
+
"host-agent",
|
|
17774
|
+
`self-update: unexpected error: ${err instanceof Error ? err.message : String(err)}`
|
|
17775
|
+
);
|
|
17776
|
+
return { status: "skipped" };
|
|
17777
|
+
}
|
|
17778
|
+
}
|
|
17500
17779
|
var defaultOnIdentityRejected = () => {
|
|
17501
17780
|
deleteHostIdentity();
|
|
17502
17781
|
log.warn("host-agent", "host identity rejected by backend \u2014 wiped sealed identity, exiting");
|
|
17503
17782
|
process.exit(1);
|
|
17504
17783
|
};
|
|
17784
|
+
var defaultOnUpdated = (version3) => {
|
|
17785
|
+
log.info("host-agent", `self-update: installed ${version3}, restarting`);
|
|
17786
|
+
process.exit(0);
|
|
17787
|
+
};
|
|
17505
17788
|
var defaultDisableService = () => {
|
|
17506
17789
|
try {
|
|
17507
|
-
(0,
|
|
17790
|
+
(0, import_node_child_process13.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
|
|
17508
17791
|
} catch {
|
|
17509
17792
|
}
|
|
17510
17793
|
};
|
|
@@ -17518,6 +17801,8 @@ var HostAgentSupervisor = class {
|
|
|
17518
17801
|
this.metrics = deps.metricsCollector ?? new MetricsCollector();
|
|
17519
17802
|
this.onIdentityRejected = deps.onIdentityRejected ?? defaultOnIdentityRejected;
|
|
17520
17803
|
this.disableService = deps.disableService ?? defaultDisableService;
|
|
17804
|
+
this.selfUpdate = deps.selfUpdate ?? runSelfUpdate;
|
|
17805
|
+
this.onUpdated = deps.onUpdated ?? defaultOnUpdated;
|
|
17521
17806
|
}
|
|
17522
17807
|
identity;
|
|
17523
17808
|
deps;
|
|
@@ -17527,6 +17812,20 @@ var HostAgentSupervisor = class {
|
|
|
17527
17812
|
setupHeadroom;
|
|
17528
17813
|
relay = null;
|
|
17529
17814
|
heartbeatTimer = null;
|
|
17815
|
+
/** Periodic self-update timer (npm check + install + restart). */
|
|
17816
|
+
selfUpdateTimer = null;
|
|
17817
|
+
/** Self-update check + install (injectable; defaults to runSelfUpdate). */
|
|
17818
|
+
selfUpdate;
|
|
17819
|
+
/** Restart action after a successful self-update (defaults to process.exit). */
|
|
17820
|
+
onUpdated;
|
|
17821
|
+
/** Guards against overlapping self-update ticks (a slow npm install). */
|
|
17822
|
+
selfUpdating = false;
|
|
17823
|
+
/**
|
|
17824
|
+
* Set once a self-update installed a newer version but a child was busy,
|
|
17825
|
+
* so the next idle tick restarts WITHOUT re-installing. Carries the
|
|
17826
|
+
* already-installed version for the restart log.
|
|
17827
|
+
*/
|
|
17828
|
+
pendingRestartVersion = null;
|
|
17530
17829
|
/** Guards the one-shot 'connected' telemetry on the first heartbeat. */
|
|
17531
17830
|
reportedConnected = false;
|
|
17532
17831
|
/** Live-metrics collector — stateful across beats (CPU delta + latency). */
|
|
@@ -17537,6 +17836,19 @@ var HostAgentSupervisor = class {
|
|
|
17537
17836
|
disableService;
|
|
17538
17837
|
/** Guards against firing the self-heal more than once. */
|
|
17539
17838
|
healing = false;
|
|
17839
|
+
/**
|
|
17840
|
+
* Resolve the self-update interval, honoring `CODEAM_HOST_SELF_UPDATE_MS`.
|
|
17841
|
+
* A finite value > 0 overrides the default; 0 or negative DISABLES the
|
|
17842
|
+
* periodic self-update (tests / pinned boxes); a non-numeric/absent value
|
|
17843
|
+
* falls back to {@link SELF_UPDATE_INTERVAL_MS}.
|
|
17844
|
+
*/
|
|
17845
|
+
selfUpdateIntervalMs() {
|
|
17846
|
+
const raw = process.env.CODEAM_HOST_SELF_UPDATE_MS;
|
|
17847
|
+
if (raw === void 0 || raw === "") return SELF_UPDATE_INTERVAL_MS;
|
|
17848
|
+
const parsed = Number(raw);
|
|
17849
|
+
if (!Number.isFinite(parsed)) return SELF_UPDATE_INTERVAL_MS;
|
|
17850
|
+
return parsed;
|
|
17851
|
+
}
|
|
17540
17852
|
/** Open the control channel (reusing the relay) + start heartbeats. */
|
|
17541
17853
|
start() {
|
|
17542
17854
|
const make = this.deps.makeRelay ?? ((pluginId, onCommand, meta) => new CommandRelayService(pluginId, onCommand, meta));
|
|
@@ -17549,6 +17861,13 @@ var HostAgentSupervisor = class {
|
|
|
17549
17861
|
void this.beat();
|
|
17550
17862
|
this.heartbeatTimer = setInterval(() => void this.beat(), HEARTBEAT_INTERVAL_MS);
|
|
17551
17863
|
this.heartbeatTimer.unref?.();
|
|
17864
|
+
const updateMs = this.selfUpdateIntervalMs();
|
|
17865
|
+
if (updateMs > 0) {
|
|
17866
|
+
this.selfUpdateTimer = setInterval(() => void this.selfUpdateTick(), updateMs);
|
|
17867
|
+
this.selfUpdateTimer.unref?.();
|
|
17868
|
+
} else {
|
|
17869
|
+
log.info("host-agent", "self-update disabled (CODEAM_HOST_SELF_UPDATE_MS<=0)");
|
|
17870
|
+
}
|
|
17552
17871
|
log.info("host-agent", `supervisor up host=${this.identity.hostId.slice(0, 8)}`);
|
|
17553
17872
|
}
|
|
17554
17873
|
/** Stop the control channel + heartbeats + kill every child. */
|
|
@@ -17557,6 +17876,10 @@ var HostAgentSupervisor = class {
|
|
|
17557
17876
|
clearInterval(this.heartbeatTimer);
|
|
17558
17877
|
this.heartbeatTimer = null;
|
|
17559
17878
|
}
|
|
17879
|
+
if (this.selfUpdateTimer) {
|
|
17880
|
+
clearInterval(this.selfUpdateTimer);
|
|
17881
|
+
this.selfUpdateTimer = null;
|
|
17882
|
+
}
|
|
17560
17883
|
this.relay?.stop();
|
|
17561
17884
|
for (const child of this.children.values()) {
|
|
17562
17885
|
try {
|
|
@@ -17596,6 +17919,61 @@ var HostAgentSupervisor = class {
|
|
|
17596
17919
|
log.trace("host-agent", "heartbeat failed", err);
|
|
17597
17920
|
}
|
|
17598
17921
|
}
|
|
17922
|
+
/**
|
|
17923
|
+
* One self-update tick. Best-effort + never crashes the supervisor: the
|
|
17924
|
+
* whole body is wrapped in try/catch and the injected updater never
|
|
17925
|
+
* rejects. Sequence:
|
|
17926
|
+
*
|
|
17927
|
+
* 1. If a restart is already PENDING (a prior tick installed a newer
|
|
17928
|
+
* version while a child was busy), skip the npm work and just try to
|
|
17929
|
+
* restart now — no re-install.
|
|
17930
|
+
* 2. Otherwise run the injected `selfUpdate`. On `'updated'`, remember
|
|
17931
|
+
* the new version as pending; on anything else, do nothing.
|
|
17932
|
+
* 3. SAFETY: only restart when no child turn is in flight. If a child is
|
|
17933
|
+
* mid-work, DEFER — the install already happened, so a later idle
|
|
17934
|
+
* tick just restarts. (We prefer deferring to yanking an active turn;
|
|
17935
|
+
* systemd would restart in ~5s but the mobile would drop the turn.)
|
|
17936
|
+
*
|
|
17937
|
+
* `selfUpdating` guards against a slow npm install overlapping the next
|
|
17938
|
+
* tick (the timer keeps firing on its interval).
|
|
17939
|
+
*/
|
|
17940
|
+
async selfUpdateTick() {
|
|
17941
|
+
if (this.selfUpdating) return;
|
|
17942
|
+
this.selfUpdating = true;
|
|
17943
|
+
try {
|
|
17944
|
+
if (this.pendingRestartVersion !== null) {
|
|
17945
|
+
this.maybeRestartForUpdate(this.pendingRestartVersion);
|
|
17946
|
+
return;
|
|
17947
|
+
}
|
|
17948
|
+
const result = await this.selfUpdate();
|
|
17949
|
+
if (result.status !== "updated") return;
|
|
17950
|
+
const version3 = result.version ?? "latest";
|
|
17951
|
+
this.pendingRestartVersion = version3;
|
|
17952
|
+
this.maybeRestartForUpdate(version3);
|
|
17953
|
+
} catch (err) {
|
|
17954
|
+
log.warn(
|
|
17955
|
+
"host-agent",
|
|
17956
|
+
`self-update tick failed: ${err instanceof Error ? err.message : String(err)}`
|
|
17957
|
+
);
|
|
17958
|
+
} finally {
|
|
17959
|
+
this.selfUpdating = false;
|
|
17960
|
+
}
|
|
17961
|
+
}
|
|
17962
|
+
/**
|
|
17963
|
+
* Restart for an already-installed update IFF no child turn is in flight.
|
|
17964
|
+
* When a child is busy we DEFER (the version stays pending for the next
|
|
17965
|
+
* idle tick) rather than yank an active turn.
|
|
17966
|
+
*/
|
|
17967
|
+
maybeRestartForUpdate(version3) {
|
|
17968
|
+
if (this.children.size > 0) {
|
|
17969
|
+
log.info(
|
|
17970
|
+
"host-agent",
|
|
17971
|
+
`self-update: ${version3} installed but ${this.children.size} child(ren) busy \u2014 deferring restart`
|
|
17972
|
+
);
|
|
17973
|
+
return;
|
|
17974
|
+
}
|
|
17975
|
+
this.onUpdated(version3);
|
|
17976
|
+
}
|
|
17599
17977
|
/** Number of live children — for tests + diagnostics. */
|
|
17600
17978
|
childCount() {
|
|
17601
17979
|
return this.children.size;
|
|
@@ -17691,7 +18069,7 @@ var HostAgentSupervisor = class {
|
|
|
17691
18069
|
report("installing", "installing agent CLI");
|
|
17692
18070
|
await this.runAgentInstall(payload.agentInstallScript);
|
|
17693
18071
|
}
|
|
17694
|
-
const home = process.env.HOME ||
|
|
18072
|
+
const home = process.env.HOME || os32.homedir();
|
|
17695
18073
|
childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
|
|
17696
18074
|
if (payload.previewTunnelToken && payload.previewHostname) {
|
|
17697
18075
|
childEnv.PREVIEW_TUNNEL_TOKEN = payload.previewTunnelToken;
|
|
@@ -17701,16 +18079,21 @@ var HostAgentSupervisor = class {
|
|
|
17701
18079
|
report("headroom", "setting up Headroom proxy");
|
|
17702
18080
|
const headroomOk = await this.setupHeadroom(payload.headroomAgent);
|
|
17703
18081
|
if (headroomOk) {
|
|
17704
|
-
|
|
17705
|
-
|
|
17706
|
-
|
|
17707
|
-
|
|
18082
|
+
persistHeadroomConfig({
|
|
18083
|
+
enabled: true,
|
|
18084
|
+
agent: agentIdToHeadroomKind(payload.headroomAgent),
|
|
18085
|
+
ingestUrl: payload.headroomSavingsIngestUrl
|
|
18086
|
+
});
|
|
18087
|
+
log.info("host-agent", "Headroom proxy ready; persisted headroom config for child spawns");
|
|
17708
18088
|
} else {
|
|
18089
|
+
persistHeadroomConfig({ enabled: false });
|
|
17709
18090
|
log.warn("host-agent", "Headroom setup failed (best-effort) \u2014 child will run without Headroom");
|
|
17710
18091
|
}
|
|
18092
|
+
} else if (payload.headroomEnabled === false) {
|
|
18093
|
+
persistHeadroomConfig({ enabled: false });
|
|
17711
18094
|
}
|
|
17712
18095
|
report("spawning", "starting agent");
|
|
17713
|
-
const proc = this.
|
|
18096
|
+
const proc = this.spawnSessionChild(childEnv, cwd, extraArgs);
|
|
17714
18097
|
const child = { deployId: payload.deployId, proc };
|
|
17715
18098
|
this.children.set(payload.deployId, child);
|
|
17716
18099
|
let tail = "";
|
|
@@ -17744,6 +18127,20 @@ var HostAgentSupervisor = class {
|
|
|
17744
18127
|
report("failed", message);
|
|
17745
18128
|
}
|
|
17746
18129
|
}
|
|
18130
|
+
/**
|
|
18131
|
+
* Spawn a supervised `pair-auto` session child, merging the persisted
|
|
18132
|
+
* Headroom env on top of the caller's env. This is the SINGLE spawn site for
|
|
18133
|
+
* session children: the fresh-deploy path and any future resume / restart
|
|
18134
|
+
* path both go through here, so the HEADROOM_* env (read from
|
|
18135
|
+
* `~/.codeam/headroom-config.json`, the source of truth a prior deploy wrote)
|
|
18136
|
+
* is injected on EVERY spawn — reporting survives session resumes and
|
|
18137
|
+
* supervisor restarts (systemd / periodic self-update), not just fresh
|
|
18138
|
+
* deploys. `readHeadroomChildEnv()` returns `{}` when Headroom is disabled or
|
|
18139
|
+
* was never set up, so this is a no-op there (never-break).
|
|
18140
|
+
*/
|
|
18141
|
+
spawnSessionChild(env, cwd, args2 = []) {
|
|
18142
|
+
return this.spawnChild({ ...env, ...readHeadroomChildEnv() }, cwd, args2);
|
|
18143
|
+
}
|
|
17747
18144
|
/**
|
|
17748
18145
|
* Run the backend-supplied per-agent CLI install script (e.g.
|
|
17749
18146
|
* `claude.ai/install.sh`, `npm i -g @openai/codex`). Best-effort + bounded:
|
|
@@ -17755,8 +18152,8 @@ var HostAgentSupervisor = class {
|
|
|
17755
18152
|
*/
|
|
17756
18153
|
runAgentInstall(script) {
|
|
17757
18154
|
return new Promise((resolve7) => {
|
|
17758
|
-
const home = process.env.HOME ||
|
|
17759
|
-
const child = (0,
|
|
18155
|
+
const home = process.env.HOME || os32.homedir();
|
|
18156
|
+
const child = (0, import_node_child_process13.spawn)("sh", ["-c", script], {
|
|
17760
18157
|
env: { ...process.env, HOME: home },
|
|
17761
18158
|
stdio: ["ignore", "pipe", "pipe"]
|
|
17762
18159
|
});
|
|
@@ -17880,12 +18277,12 @@ function readTokenFromArgs(args2) {
|
|
|
17880
18277
|
}
|
|
17881
18278
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
17882
18279
|
if (fileFlag) {
|
|
17883
|
-
const
|
|
18280
|
+
const path59 = fileFlag.slice("--token-file=".length);
|
|
17884
18281
|
try {
|
|
17885
|
-
const content =
|
|
17886
|
-
if (content.length === 0) fail(`--token-file ${
|
|
18282
|
+
const content = fs40.readFileSync(path59, "utf8").trim();
|
|
18283
|
+
if (content.length === 0) fail(`--token-file ${path59} is empty`);
|
|
17887
18284
|
try {
|
|
17888
|
-
|
|
18285
|
+
fs40.unlinkSync(path59);
|
|
17889
18286
|
} catch {
|
|
17890
18287
|
}
|
|
17891
18288
|
return content;
|
|
@@ -17911,7 +18308,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
|
|
|
17911
18308
|
pluginId,
|
|
17912
18309
|
ideName: "codeam-cli (codespace)",
|
|
17913
18310
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
17914
|
-
hostname:
|
|
18311
|
+
hostname: os33.hostname(),
|
|
17915
18312
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
17916
18313
|
// Current git branch of the codespace's working directory, so the
|
|
17917
18314
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -17972,7 +18369,7 @@ async function claim(token, pluginId, pluginSecretHash) {
|
|
|
17972
18369
|
}
|
|
17973
18370
|
}
|
|
17974
18371
|
function pairAutoLockPath() {
|
|
17975
|
-
return
|
|
18372
|
+
return path46.join(os33.homedir(), ".codeam", "pair-auto.lock");
|
|
17976
18373
|
}
|
|
17977
18374
|
function isLivePairAuto(pid) {
|
|
17978
18375
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -17982,7 +18379,7 @@ function isLivePairAuto(pid) {
|
|
|
17982
18379
|
if (e.code !== "EPERM") return false;
|
|
17983
18380
|
}
|
|
17984
18381
|
try {
|
|
17985
|
-
return
|
|
18382
|
+
return fs40.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
|
|
17986
18383
|
} catch {
|
|
17987
18384
|
return true;
|
|
17988
18385
|
}
|
|
@@ -17992,24 +18389,24 @@ function isLiveCodeam(pid) {
|
|
|
17992
18389
|
}
|
|
17993
18390
|
function daemonLockPath(sessionId) {
|
|
17994
18391
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
17995
|
-
return
|
|
18392
|
+
return path46.join(os33.homedir(), ".codeam", `daemon-${safe}.lock`);
|
|
17996
18393
|
}
|
|
17997
18394
|
function acquireDaemonLock(sessionId) {
|
|
17998
18395
|
const lockPath = daemonLockPath(sessionId);
|
|
17999
18396
|
try {
|
|
18000
|
-
|
|
18397
|
+
fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
|
|
18001
18398
|
try {
|
|
18002
|
-
|
|
18399
|
+
fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
18003
18400
|
} catch (e) {
|
|
18004
18401
|
if (e.code !== "EEXIST") throw e;
|
|
18005
|
-
const holder = Number(
|
|
18402
|
+
const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
|
|
18006
18403
|
if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
|
|
18007
|
-
|
|
18404
|
+
fs40.writeFileSync(lockPath, String(process.pid));
|
|
18008
18405
|
}
|
|
18009
18406
|
const release3 = () => {
|
|
18010
18407
|
try {
|
|
18011
|
-
if (
|
|
18012
|
-
|
|
18408
|
+
if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
18409
|
+
fs40.unlinkSync(lockPath);
|
|
18013
18410
|
}
|
|
18014
18411
|
} catch {
|
|
18015
18412
|
}
|
|
@@ -18031,19 +18428,19 @@ function acquireDaemonLock(sessionId) {
|
|
|
18031
18428
|
function acquireSingletonLock() {
|
|
18032
18429
|
const lockPath = pairAutoLockPath();
|
|
18033
18430
|
try {
|
|
18034
|
-
|
|
18431
|
+
fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
|
|
18035
18432
|
try {
|
|
18036
|
-
|
|
18433
|
+
fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
18037
18434
|
} catch (e) {
|
|
18038
18435
|
if (e.code !== "EEXIST") throw e;
|
|
18039
|
-
const holder = Number(
|
|
18436
|
+
const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
|
|
18040
18437
|
if (isLivePairAuto(holder)) return false;
|
|
18041
|
-
|
|
18438
|
+
fs40.writeFileSync(lockPath, String(process.pid));
|
|
18042
18439
|
}
|
|
18043
18440
|
process.once("exit", () => {
|
|
18044
18441
|
try {
|
|
18045
|
-
if (
|
|
18046
|
-
|
|
18442
|
+
if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
18443
|
+
fs40.unlinkSync(lockPath);
|
|
18047
18444
|
}
|
|
18048
18445
|
} catch {
|
|
18049
18446
|
}
|
|
@@ -18125,7 +18522,7 @@ async function pairAuto(args2) {
|
|
|
18125
18522
|
}
|
|
18126
18523
|
|
|
18127
18524
|
// src/services/headroom/wrap-launch.ts
|
|
18128
|
-
var
|
|
18525
|
+
var import_node_child_process14 = require("child_process");
|
|
18129
18526
|
function wrapWithHeadroom(launch, opts) {
|
|
18130
18527
|
if (!opts.enabled || !opts.headroomPresent) return launch;
|
|
18131
18528
|
return {
|
|
@@ -18138,7 +18535,7 @@ var _present;
|
|
|
18138
18535
|
function headroomPresent() {
|
|
18139
18536
|
if (_present !== void 0) return Promise.resolve(_present);
|
|
18140
18537
|
return new Promise((resolve7) => {
|
|
18141
|
-
(0,
|
|
18538
|
+
(0, import_node_child_process14.execFile)("headroom", ["--version"], (err) => {
|
|
18142
18539
|
_present = !err;
|
|
18143
18540
|
resolve7(_present);
|
|
18144
18541
|
});
|
|
@@ -18488,19 +18885,19 @@ var AgentService = class _AgentService {
|
|
|
18488
18885
|
};
|
|
18489
18886
|
|
|
18490
18887
|
// src/agents/acp/adapters.ts
|
|
18491
|
-
var
|
|
18888
|
+
var path47 = __toESM(require("path"));
|
|
18492
18889
|
var require_ = require;
|
|
18493
18890
|
function resolveBin(pkgName, binName) {
|
|
18494
18891
|
try {
|
|
18495
18892
|
const manifestPath = require_.resolve(`${pkgName}/package.json`);
|
|
18496
18893
|
const manifest = require_(`${pkgName}/package.json`);
|
|
18497
|
-
const pkgDir =
|
|
18894
|
+
const pkgDir = path47.dirname(manifestPath);
|
|
18498
18895
|
const bin = manifest.bin;
|
|
18499
18896
|
if (!bin) return null;
|
|
18500
|
-
if (typeof bin === "string") return
|
|
18897
|
+
if (typeof bin === "string") return path47.resolve(pkgDir, bin);
|
|
18501
18898
|
const target = binName ?? Object.keys(bin)[0];
|
|
18502
18899
|
if (!target || !bin[target]) return null;
|
|
18503
|
-
return
|
|
18900
|
+
return path47.resolve(pkgDir, bin[target]);
|
|
18504
18901
|
} catch {
|
|
18505
18902
|
return null;
|
|
18506
18903
|
}
|
|
@@ -18576,11 +18973,11 @@ function requiresAcp(agent) {
|
|
|
18576
18973
|
var import_node_crypto7 = require("crypto");
|
|
18577
18974
|
|
|
18578
18975
|
// src/agents/acp/client.ts
|
|
18579
|
-
var
|
|
18580
|
-
var
|
|
18976
|
+
var import_node_child_process15 = require("child_process");
|
|
18977
|
+
var fs41 = __toESM(require("fs/promises"));
|
|
18581
18978
|
var fsSync = __toESM(require("fs"));
|
|
18582
|
-
var
|
|
18583
|
-
var
|
|
18979
|
+
var os34 = __toESM(require("os"));
|
|
18980
|
+
var path48 = __toESM(require("path"));
|
|
18584
18981
|
var import_node_stream = require("stream");
|
|
18585
18982
|
|
|
18586
18983
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -21117,7 +21514,7 @@ var AcpClient = class {
|
|
|
21117
21514
|
"acpClient",
|
|
21118
21515
|
`spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
|
|
21119
21516
|
);
|
|
21120
|
-
const child = (0,
|
|
21517
|
+
const child = (0, import_node_child_process15.spawn)(adapter.command, adapter.args, {
|
|
21121
21518
|
cwd,
|
|
21122
21519
|
env: { ...process.env, PATH: augmentedPath },
|
|
21123
21520
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -21367,7 +21764,7 @@ var AcpClient = class {
|
|
|
21367
21764
|
},
|
|
21368
21765
|
readTextFile: async (params) => {
|
|
21369
21766
|
try {
|
|
21370
|
-
const content = await
|
|
21767
|
+
const content = await fs41.readFile(params.path, "utf8");
|
|
21371
21768
|
return applyLineRange(content, params.line ?? null, params.limit ?? null);
|
|
21372
21769
|
} catch (err) {
|
|
21373
21770
|
const code = err.code;
|
|
@@ -21387,7 +21784,7 @@ var AcpClient = class {
|
|
|
21387
21784
|
},
|
|
21388
21785
|
writeTextFile: async (params) => {
|
|
21389
21786
|
try {
|
|
21390
|
-
await
|
|
21787
|
+
await fs41.writeFile(params.path, params.content, "utf8");
|
|
21391
21788
|
return {};
|
|
21392
21789
|
} catch (err) {
|
|
21393
21790
|
const code = err.code;
|
|
@@ -21436,25 +21833,25 @@ function applyLineRange(content, line, limit) {
|
|
|
21436
21833
|
return { content: lines.slice(start2, end).join("\n") };
|
|
21437
21834
|
}
|
|
21438
21835
|
function knownAgentBinaryDirs() {
|
|
21439
|
-
const home =
|
|
21836
|
+
const home = os34.homedir();
|
|
21440
21837
|
const out2 = [];
|
|
21441
21838
|
out2.push("/tmp/codeam-node20/bin");
|
|
21442
21839
|
for (const root of [
|
|
21443
21840
|
"/usr/local/share/nvm/versions/node",
|
|
21444
|
-
|
|
21841
|
+
path48.join(home, ".nvm/versions/node")
|
|
21445
21842
|
]) {
|
|
21446
21843
|
try {
|
|
21447
21844
|
for (const child of fsSync.readdirSync(root)) {
|
|
21448
|
-
out2.push(
|
|
21845
|
+
out2.push(path48.join(root, child, "bin"));
|
|
21449
21846
|
}
|
|
21450
21847
|
} catch {
|
|
21451
21848
|
}
|
|
21452
21849
|
}
|
|
21453
|
-
out2.push(
|
|
21850
|
+
out2.push(path48.join(home, ".volta/bin"));
|
|
21454
21851
|
out2.push("/usr/local/bin");
|
|
21455
21852
|
out2.push("/usr/bin");
|
|
21456
|
-
out2.push(
|
|
21457
|
-
out2.push(
|
|
21853
|
+
out2.push(path48.join(home, ".local/bin"));
|
|
21854
|
+
out2.push(path48.join(home, "bin"));
|
|
21458
21855
|
return out2.filter((p2) => {
|
|
21459
21856
|
try {
|
|
21460
21857
|
return fsSync.statSync(p2).isDirectory();
|
|
@@ -21465,7 +21862,7 @@ function knownAgentBinaryDirs() {
|
|
|
21465
21862
|
}
|
|
21466
21863
|
function expandPathForAgentBinaries(existingPath) {
|
|
21467
21864
|
const existing = new Set(
|
|
21468
|
-
existingPath.split(
|
|
21865
|
+
existingPath.split(path48.delimiter).filter((p2) => p2.length > 0)
|
|
21469
21866
|
);
|
|
21470
21867
|
const additions = [];
|
|
21471
21868
|
for (const dir of knownAgentBinaryDirs()) {
|
|
@@ -21475,12 +21872,12 @@ function expandPathForAgentBinaries(existingPath) {
|
|
|
21475
21872
|
}
|
|
21476
21873
|
}
|
|
21477
21874
|
if (additions.length === 0) return existingPath;
|
|
21478
|
-
return [...additions, existingPath].filter((p2) => p2.length > 0).join(
|
|
21875
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path48.delimiter);
|
|
21479
21876
|
}
|
|
21480
21877
|
|
|
21481
21878
|
// src/services/streaming/transport.ts
|
|
21482
21879
|
var http6 = __toESM(require("http"));
|
|
21483
|
-
var
|
|
21880
|
+
var https7 = __toESM(require("https"));
|
|
21484
21881
|
var _transport4 = {
|
|
21485
21882
|
post: _post3,
|
|
21486
21883
|
get: _get
|
|
@@ -21489,7 +21886,7 @@ function _post3(url, headers, payload) {
|
|
|
21489
21886
|
return new Promise((resolve7, reject) => {
|
|
21490
21887
|
let settled = false;
|
|
21491
21888
|
const u2 = new URL(url);
|
|
21492
|
-
const lib = u2.protocol === "https:" ?
|
|
21889
|
+
const lib = u2.protocol === "https:" ? https7 : http6;
|
|
21493
21890
|
const req = lib.request(
|
|
21494
21891
|
{
|
|
21495
21892
|
hostname: u2.hostname,
|
|
@@ -21531,7 +21928,7 @@ function _get(url, headers) {
|
|
|
21531
21928
|
return new Promise((resolve7, reject) => {
|
|
21532
21929
|
let settled = false;
|
|
21533
21930
|
const u2 = new URL(url);
|
|
21534
|
-
const lib = u2.protocol === "https:" ?
|
|
21931
|
+
const lib = u2.protocol === "https:" ? https7 : http6;
|
|
21535
21932
|
const req = lib.request(
|
|
21536
21933
|
{
|
|
21537
21934
|
hostname: u2.hostname,
|
|
@@ -21802,15 +22199,15 @@ function reconcileCumulative(existing, incoming) {
|
|
|
21802
22199
|
}
|
|
21803
22200
|
|
|
21804
22201
|
// src/agents/acp/onboarding.ts
|
|
21805
|
-
var
|
|
21806
|
-
var
|
|
21807
|
-
var
|
|
22202
|
+
var fs42 = __toESM(require("fs"));
|
|
22203
|
+
var os35 = __toESM(require("os"));
|
|
22204
|
+
var path49 = __toESM(require("path"));
|
|
21808
22205
|
var _onboardingSeam = {
|
|
21809
|
-
markerPath: (sessionId) =>
|
|
21810
|
-
exists: (p2) =>
|
|
22206
|
+
markerPath: (sessionId) => path49.join(os35.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
|
|
22207
|
+
exists: (p2) => fs42.existsSync(p2),
|
|
21811
22208
|
write: (p2) => {
|
|
21812
|
-
|
|
21813
|
-
|
|
22209
|
+
fs42.mkdirSync(path49.dirname(p2), { recursive: true });
|
|
22210
|
+
fs42.writeFileSync(p2, "");
|
|
21814
22211
|
},
|
|
21815
22212
|
disabled: () => {
|
|
21816
22213
|
const v = process.env.CODEAM_ONBOARDING_DISABLED;
|
|
@@ -21818,7 +22215,7 @@ var _onboardingSeam = {
|
|
|
21818
22215
|
}
|
|
21819
22216
|
};
|
|
21820
22217
|
function buildOnboardingWelcome(cwd) {
|
|
21821
|
-
const repo =
|
|
22218
|
+
const repo = path49.basename(cwd || "") || "this project";
|
|
21822
22219
|
return [
|
|
21823
22220
|
`Welcome to CodeAgent Mobile! \u{1F44B} You're now driving this agent from your phone \u2014 and it comes fully wired, zero setup:`,
|
|
21824
22221
|
"",
|
|
@@ -22078,8 +22475,8 @@ var import_crypto5 = require("crypto");
|
|
|
22078
22475
|
|
|
22079
22476
|
// src/services/turn-files/git-changeset.ts
|
|
22080
22477
|
var import_child_process22 = require("child_process");
|
|
22081
|
-
var
|
|
22082
|
-
var
|
|
22478
|
+
var fs43 = __toESM(require("fs/promises"));
|
|
22479
|
+
var path50 = __toESM(require("path"));
|
|
22083
22480
|
async function collectRepoChangeset(opts) {
|
|
22084
22481
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
22085
22482
|
if (status2 === null) return null;
|
|
@@ -22097,7 +22494,7 @@ async function collectRepoChangeset(opts) {
|
|
|
22097
22494
|
let stats;
|
|
22098
22495
|
if (row.fileStatus === "added" && numstatEntry === void 0) {
|
|
22099
22496
|
const lineCount = await readUntrackedLineCount(
|
|
22100
|
-
|
|
22497
|
+
path50.join(opts.repoRoot, row.filePath)
|
|
22101
22498
|
);
|
|
22102
22499
|
stats = { added: lineCount, removed: 0 };
|
|
22103
22500
|
} else {
|
|
@@ -22128,7 +22525,7 @@ function readUntrackedLineCount(absPath) {
|
|
|
22128
22525
|
}
|
|
22129
22526
|
async function defaultReadUntrackedLineCount(absPath) {
|
|
22130
22527
|
try {
|
|
22131
|
-
const content = await
|
|
22528
|
+
const content = await fs43.readFile(absPath, "utf8");
|
|
22132
22529
|
let count = 0;
|
|
22133
22530
|
let pos = -1;
|
|
22134
22531
|
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
|
|
@@ -22220,7 +22617,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
22220
22617
|
});
|
|
22221
22618
|
}
|
|
22222
22619
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
22223
|
-
const
|
|
22620
|
+
const fs48 = await import("fs/promises");
|
|
22224
22621
|
const out2 = [];
|
|
22225
22622
|
await walk(workingDir, 0);
|
|
22226
22623
|
return out2;
|
|
@@ -22228,7 +22625,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22228
22625
|
if (depth > maxDepth) return;
|
|
22229
22626
|
let entries = [];
|
|
22230
22627
|
try {
|
|
22231
|
-
const dirents = await
|
|
22628
|
+
const dirents = await fs48.readdir(dir, { withFileTypes: true });
|
|
22232
22629
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
22233
22630
|
} catch {
|
|
22234
22631
|
return;
|
|
@@ -22239,8 +22636,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22239
22636
|
if (hasGit) {
|
|
22240
22637
|
out2.push({
|
|
22241
22638
|
repoRoot: dir,
|
|
22242
|
-
repoPath:
|
|
22243
|
-
repoName:
|
|
22639
|
+
repoPath: path50.relative(workingDir, dir),
|
|
22640
|
+
repoName: path50.basename(dir)
|
|
22244
22641
|
});
|
|
22245
22642
|
return;
|
|
22246
22643
|
}
|
|
@@ -22248,14 +22645,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22248
22645
|
if (!entry.isDirectory) continue;
|
|
22249
22646
|
if (entry.name === "node_modules") continue;
|
|
22250
22647
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
22251
|
-
await walk(
|
|
22648
|
+
await walk(path50.join(dir, entry.name), depth + 1);
|
|
22252
22649
|
}
|
|
22253
22650
|
}
|
|
22254
22651
|
}
|
|
22255
22652
|
|
|
22256
22653
|
// src/services/turn-files/files-outbox.ts
|
|
22257
|
-
var
|
|
22258
|
-
var
|
|
22654
|
+
var fs44 = __toESM(require("fs/promises"));
|
|
22655
|
+
var path51 = __toESM(require("path"));
|
|
22259
22656
|
var import_os7 = require("os");
|
|
22260
22657
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
22261
22658
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -22288,16 +22685,16 @@ var FilesOutbox = class {
|
|
|
22288
22685
|
backoffIndex = 0;
|
|
22289
22686
|
stopped = false;
|
|
22290
22687
|
constructor(opts) {
|
|
22291
|
-
const base = opts.baseDir ??
|
|
22292
|
-
this.filePath =
|
|
22688
|
+
const base = opts.baseDir ?? path51.join(homeDir(), HOME_OUTBOX_DIR);
|
|
22689
|
+
this.filePath = path51.join(base, `${opts.sessionId}.jsonl`);
|
|
22293
22690
|
this.post = opts.post;
|
|
22294
22691
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
22295
22692
|
}
|
|
22296
22693
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
22297
22694
|
* line is durable on disk (not once the POST succeeds). */
|
|
22298
22695
|
async enqueue(entry) {
|
|
22299
|
-
await
|
|
22300
|
-
await
|
|
22696
|
+
await fs44.mkdir(path51.dirname(this.filePath), { recursive: true });
|
|
22697
|
+
await fs44.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
22301
22698
|
this.backoffIndex = 0;
|
|
22302
22699
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
22303
22700
|
}
|
|
@@ -22386,7 +22783,7 @@ var FilesOutbox = class {
|
|
|
22386
22783
|
async readAll() {
|
|
22387
22784
|
let raw = "";
|
|
22388
22785
|
try {
|
|
22389
|
-
raw = await
|
|
22786
|
+
raw = await fs44.readFile(this.filePath, "utf8");
|
|
22390
22787
|
} catch {
|
|
22391
22788
|
return [];
|
|
22392
22789
|
}
|
|
@@ -22410,12 +22807,12 @@ var FilesOutbox = class {
|
|
|
22410
22807
|
async rewrite(entries) {
|
|
22411
22808
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
22412
22809
|
if (entries.length === 0) {
|
|
22413
|
-
await
|
|
22810
|
+
await fs44.unlink(this.filePath).catch(() => void 0);
|
|
22414
22811
|
return;
|
|
22415
22812
|
}
|
|
22416
22813
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
22417
|
-
await
|
|
22418
|
-
await
|
|
22814
|
+
await fs44.writeFile(tmpPath, payload, "utf8");
|
|
22815
|
+
await fs44.rename(tmpPath, this.filePath);
|
|
22419
22816
|
}
|
|
22420
22817
|
};
|
|
22421
22818
|
function applyJitter(ms) {
|
|
@@ -24146,10 +24543,10 @@ var OutputService = class _OutputService {
|
|
|
24146
24543
|
};
|
|
24147
24544
|
|
|
24148
24545
|
// src/services/history.service.ts
|
|
24149
|
-
var
|
|
24150
|
-
var
|
|
24151
|
-
var
|
|
24152
|
-
var
|
|
24546
|
+
var fs45 = __toESM(require("fs"));
|
|
24547
|
+
var path52 = __toESM(require("path"));
|
|
24548
|
+
var os36 = __toESM(require("os"));
|
|
24549
|
+
var https8 = __toESM(require("https"));
|
|
24153
24550
|
var http7 = __toESM(require("http"));
|
|
24154
24551
|
var import_zod2 = require("zod");
|
|
24155
24552
|
var historyRecordSchema = import_zod2.z.object({
|
|
@@ -24175,7 +24572,7 @@ function parseJsonl(filePath) {
|
|
|
24175
24572
|
const messages = [];
|
|
24176
24573
|
let raw;
|
|
24177
24574
|
try {
|
|
24178
|
-
raw =
|
|
24575
|
+
raw = fs45.readFileSync(filePath, "utf8");
|
|
24179
24576
|
} catch (err) {
|
|
24180
24577
|
if (err.code !== "ENOENT") {
|
|
24181
24578
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -24215,7 +24612,7 @@ function post(endpoint, body, pluginAuthToken) {
|
|
|
24215
24612
|
return new Promise((resolve7) => {
|
|
24216
24613
|
const payload = JSON.stringify(body);
|
|
24217
24614
|
const u2 = new URL(`${API_BASE9}${endpoint}`);
|
|
24218
|
-
const transport = u2.protocol === "https:" ?
|
|
24615
|
+
const transport = u2.protocol === "https:" ? https8 : http7;
|
|
24219
24616
|
const req = transport.request(
|
|
24220
24617
|
{
|
|
24221
24618
|
hostname: u2.hostname,
|
|
@@ -24316,7 +24713,7 @@ var HistoryService = class _HistoryService {
|
|
|
24316
24713
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
24317
24714
|
}
|
|
24318
24715
|
get projectDir() {
|
|
24319
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
24716
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path52.join(os36.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
24320
24717
|
}
|
|
24321
24718
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
24322
24719
|
setCurrentConversationId(id) {
|
|
@@ -24328,7 +24725,7 @@ var HistoryService = class _HistoryService {
|
|
|
24328
24725
|
/** Return the current message count in the active conversation. */
|
|
24329
24726
|
getCurrentMessageCount() {
|
|
24330
24727
|
if (!this.currentConversationId) return 0;
|
|
24331
|
-
const filePath =
|
|
24728
|
+
const filePath = path52.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
24332
24729
|
return parseJsonl(filePath).length;
|
|
24333
24730
|
}
|
|
24334
24731
|
/**
|
|
@@ -24339,7 +24736,7 @@ var HistoryService = class _HistoryService {
|
|
|
24339
24736
|
const deadline = Date.now() + timeoutMs;
|
|
24340
24737
|
while (Date.now() < deadline) {
|
|
24341
24738
|
if (!this.currentConversationId) return null;
|
|
24342
|
-
const filePath =
|
|
24739
|
+
const filePath = path52.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
24343
24740
|
const messages = parseJsonl(filePath);
|
|
24344
24741
|
if (messages.length > previousCount) {
|
|
24345
24742
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -24365,16 +24762,16 @@ var HistoryService = class _HistoryService {
|
|
|
24365
24762
|
const dir = this.projectDir;
|
|
24366
24763
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
24367
24764
|
try {
|
|
24368
|
-
const files =
|
|
24765
|
+
const files = fs45.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
24369
24766
|
try {
|
|
24370
|
-
const stat3 =
|
|
24767
|
+
const stat3 = fs45.statSync(path52.join(dir, e.name));
|
|
24371
24768
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
24372
24769
|
} catch {
|
|
24373
24770
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
24374
24771
|
}
|
|
24375
24772
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
24376
24773
|
if (files.length > 0) {
|
|
24377
|
-
this.currentConversationId =
|
|
24774
|
+
this.currentConversationId = path52.basename(files[0].name, ".jsonl");
|
|
24378
24775
|
}
|
|
24379
24776
|
} catch {
|
|
24380
24777
|
}
|
|
@@ -24408,13 +24805,13 @@ var HistoryService = class _HistoryService {
|
|
|
24408
24805
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
24409
24806
|
let entries;
|
|
24410
24807
|
try {
|
|
24411
|
-
entries =
|
|
24808
|
+
entries = fs45.readdirSync(dir, { withFileTypes: true });
|
|
24412
24809
|
} catch {
|
|
24413
24810
|
return null;
|
|
24414
24811
|
}
|
|
24415
24812
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
24416
24813
|
try {
|
|
24417
|
-
const stat3 =
|
|
24814
|
+
const stat3 = fs45.statSync(path52.join(dir, e.name));
|
|
24418
24815
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
24419
24816
|
} catch {
|
|
24420
24817
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -24423,12 +24820,12 @@ var HistoryService = class _HistoryService {
|
|
|
24423
24820
|
if (files.length === 0) return null;
|
|
24424
24821
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
24425
24822
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
24426
|
-
return this.extractUsageFromFile(
|
|
24823
|
+
return this.extractUsageFromFile(path52.join(dir, targetFile));
|
|
24427
24824
|
}
|
|
24428
24825
|
extractUsageFromFile(filePath) {
|
|
24429
24826
|
let raw;
|
|
24430
24827
|
try {
|
|
24431
|
-
raw =
|
|
24828
|
+
raw = fs45.readFileSync(filePath, "utf8");
|
|
24432
24829
|
} catch {
|
|
24433
24830
|
return null;
|
|
24434
24831
|
}
|
|
@@ -24473,9 +24870,9 @@ var HistoryService = class _HistoryService {
|
|
|
24473
24870
|
let totalCost = 0;
|
|
24474
24871
|
let files;
|
|
24475
24872
|
try {
|
|
24476
|
-
files =
|
|
24873
|
+
files = fs45.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
24477
24874
|
try {
|
|
24478
|
-
return
|
|
24875
|
+
return fs45.statSync(path52.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
24479
24876
|
} catch {
|
|
24480
24877
|
return false;
|
|
24481
24878
|
}
|
|
@@ -24486,7 +24883,7 @@ var HistoryService = class _HistoryService {
|
|
|
24486
24883
|
for (const file of files) {
|
|
24487
24884
|
let raw;
|
|
24488
24885
|
try {
|
|
24489
|
-
raw =
|
|
24886
|
+
raw = fs45.readFileSync(path52.join(projectDir, file), "utf8");
|
|
24490
24887
|
} catch {
|
|
24491
24888
|
continue;
|
|
24492
24889
|
}
|
|
@@ -24554,7 +24951,7 @@ var HistoryService = class _HistoryService {
|
|
|
24554
24951
|
* showing an empty conversation.
|
|
24555
24952
|
*/
|
|
24556
24953
|
async loadConversation(sessionId) {
|
|
24557
|
-
const filePath =
|
|
24954
|
+
const filePath = path52.join(this.projectDir, `${sessionId}.jsonl`);
|
|
24558
24955
|
const messages = parseJsonl(filePath);
|
|
24559
24956
|
if (messages.length === 0) return;
|
|
24560
24957
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -24608,7 +25005,7 @@ var HistoryService = class _HistoryService {
|
|
|
24608
25005
|
if (!this.currentConversationId) return 0;
|
|
24609
25006
|
}
|
|
24610
25007
|
const sessionId = this.currentConversationId;
|
|
24611
|
-
const filePath =
|
|
25008
|
+
const filePath = path52.join(this.projectDir, `${sessionId}.jsonl`);
|
|
24612
25009
|
const messages = parseJsonl(filePath);
|
|
24613
25010
|
if (messages.length === 0) return 0;
|
|
24614
25011
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -25034,15 +25431,15 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
25034
25431
|
}
|
|
25035
25432
|
|
|
25036
25433
|
// src/agents/claude/onboarding.ts
|
|
25037
|
-
var
|
|
25038
|
-
var
|
|
25039
|
-
var
|
|
25434
|
+
var fs46 = __toESM(require("fs"));
|
|
25435
|
+
var os37 = __toESM(require("os"));
|
|
25436
|
+
var path53 = __toESM(require("path"));
|
|
25040
25437
|
function ensureClaudeOnboarded() {
|
|
25041
25438
|
try {
|
|
25042
|
-
const file =
|
|
25439
|
+
const file = path53.join(os37.homedir(), ".claude.json");
|
|
25043
25440
|
let config = {};
|
|
25044
25441
|
try {
|
|
25045
|
-
config = JSON.parse(
|
|
25442
|
+
config = JSON.parse(fs46.readFileSync(file, "utf8"));
|
|
25046
25443
|
} catch {
|
|
25047
25444
|
}
|
|
25048
25445
|
if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
|
|
@@ -25053,8 +25450,8 @@ function ensureClaudeOnboarded() {
|
|
|
25053
25450
|
if (typeof config.lastOnboardingVersion !== "string") {
|
|
25054
25451
|
config.lastOnboardingVersion = "2.1.177";
|
|
25055
25452
|
}
|
|
25056
|
-
|
|
25057
|
-
|
|
25453
|
+
fs46.mkdirSync(path53.dirname(file), { recursive: true });
|
|
25454
|
+
fs46.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
25058
25455
|
log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
|
|
25059
25456
|
} catch (err) {
|
|
25060
25457
|
log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
|
|
@@ -25068,27 +25465,27 @@ async function start(requestedAgent) {
|
|
|
25068
25465
|
if (!session) {
|
|
25069
25466
|
if (requestedAgent) {
|
|
25070
25467
|
const displayName = AGENT_REGISTRY[requestedAgent]?.displayName ?? requestedAgent;
|
|
25071
|
-
console.log(` ${
|
|
25468
|
+
console.log(` ${import_picocolors4.default.dim(`No paired ${displayName} session found.`)}`);
|
|
25072
25469
|
console.log(
|
|
25073
|
-
` ${
|
|
25470
|
+
` ${import_picocolors4.default.dim(`Run ${import_picocolors4.default.white("codeam pair")} from a ${displayName} setup to connect your mobile app.`)}
|
|
25074
25471
|
`
|
|
25075
25472
|
);
|
|
25076
25473
|
} else {
|
|
25077
|
-
console.log(` ${
|
|
25078
|
-
console.log(` ${
|
|
25474
|
+
console.log(` ${import_picocolors4.default.dim("No paired session found.")}`);
|
|
25475
|
+
console.log(` ${import_picocolors4.default.dim(`Run ${import_picocolors4.default.white("codeam pair")} to connect your mobile app.`)}
|
|
25079
25476
|
`);
|
|
25080
25477
|
}
|
|
25081
25478
|
process.exit(0);
|
|
25082
25479
|
}
|
|
25083
25480
|
if (!acquireDaemonLock(session.id)) {
|
|
25084
|
-
console.log(` ${
|
|
25481
|
+
console.log(` ${import_picocolors4.default.dim("A codeam daemon for this session is already running \u2014 deferring to it.")}`);
|
|
25085
25482
|
process.exit(0);
|
|
25086
25483
|
}
|
|
25087
25484
|
if (!session.agent) {
|
|
25088
25485
|
throw new Error("Active session has no agent \u2014 re-pair with `codeam pair`.");
|
|
25089
25486
|
}
|
|
25090
25487
|
const pluginId = session.pluginId ?? ensurePluginId();
|
|
25091
|
-
showInfo(`${session.userName} \xB7 ${
|
|
25488
|
+
showInfo(`${session.userName} \xB7 ${import_picocolors4.default.cyan(session.plan)}`);
|
|
25092
25489
|
showInfo(`Launching ${AGENT_REGISTRY[session.agent].displayName}...
|
|
25093
25490
|
`);
|
|
25094
25491
|
identifyUser({
|
|
@@ -25362,7 +25759,7 @@ async function start(requestedAgent) {
|
|
|
25362
25759
|
|
|
25363
25760
|
// src/commands/pair.ts
|
|
25364
25761
|
var import_crypto7 = require("crypto");
|
|
25365
|
-
var
|
|
25762
|
+
var import_picocolors5 = __toESM(require("picocolors"));
|
|
25366
25763
|
|
|
25367
25764
|
// src/utils/agent-prompt.ts
|
|
25368
25765
|
function parseAgentFlag(args2) {
|
|
@@ -25443,7 +25840,7 @@ async function pair(args2 = []) {
|
|
|
25443
25840
|
process.exit(0);
|
|
25444
25841
|
}
|
|
25445
25842
|
showPairingCode(result.code);
|
|
25446
|
-
console.log(
|
|
25843
|
+
console.log(import_picocolors5.default.dim(" Scan the QR code or enter the code in CodeAgent Mobile."));
|
|
25447
25844
|
console.log("");
|
|
25448
25845
|
const waitSpin = dist_exports.spinner();
|
|
25449
25846
|
const waitMessage = () => `Waiting for mobile app... \xB7 expires in ${formatRemaining(result.expiresAt)}`;
|
|
@@ -25558,7 +25955,7 @@ async function autoLinkAfterPair(opts) {
|
|
|
25558
25955
|
}
|
|
25559
25956
|
|
|
25560
25957
|
// src/commands/sessions.ts
|
|
25561
|
-
var
|
|
25958
|
+
var import_picocolors6 = __toESM(require("picocolors"));
|
|
25562
25959
|
async function sessions2(args2) {
|
|
25563
25960
|
const [sub, id] = args2;
|
|
25564
25961
|
if (sub === "switch") return switchSession();
|
|
@@ -25575,18 +25972,18 @@ function listSessions() {
|
|
|
25575
25972
|
showIntro();
|
|
25576
25973
|
const config = getConfig();
|
|
25577
25974
|
if (config.sessions.length === 0) {
|
|
25578
|
-
console.log(
|
|
25975
|
+
console.log(import_picocolors6.default.dim(" No paired sessions. Run codeam pair to connect.\n"));
|
|
25579
25976
|
return;
|
|
25580
25977
|
}
|
|
25581
|
-
console.log(
|
|
25978
|
+
console.log(import_picocolors6.default.bold(" Paired sessions:\n"));
|
|
25582
25979
|
for (const s of config.sessions) {
|
|
25583
25980
|
const isActive = s.id === config.activeSessionId;
|
|
25584
|
-
const bullet = isActive ?
|
|
25585
|
-
const name = isActive ?
|
|
25586
|
-
const plan =
|
|
25587
|
-
const date =
|
|
25981
|
+
const bullet = isActive ? import_picocolors6.default.green(" \u25CF") : import_picocolors6.default.dim(" \u25CB");
|
|
25982
|
+
const name = isActive ? import_picocolors6.default.bold(s.userName) : s.userName;
|
|
25983
|
+
const plan = import_picocolors6.default.cyan(s.plan);
|
|
25984
|
+
const date = import_picocolors6.default.dim(new Date(s.pairedAt).toLocaleDateString());
|
|
25588
25985
|
console.log(`${bullet} ${name} ${plan} ${date}`);
|
|
25589
|
-
console.log(
|
|
25986
|
+
console.log(import_picocolors6.default.dim(` ${s.id}`));
|
|
25590
25987
|
}
|
|
25591
25988
|
console.log("");
|
|
25592
25989
|
}
|
|
@@ -25604,7 +26001,7 @@ async function switchSession() {
|
|
|
25604
26001
|
}
|
|
25605
26002
|
setActiveSession(chosen);
|
|
25606
26003
|
const s = config.sessions.find((x) => x.id === chosen);
|
|
25607
|
-
console.log(
|
|
26004
|
+
console.log(import_picocolors6.default.green(`
|
|
25608
26005
|
\u2713 Switched to ${s?.userName ?? chosen}
|
|
25609
26006
|
`));
|
|
25610
26007
|
}
|
|
@@ -25622,29 +26019,29 @@ async function deleteSession(id) {
|
|
|
25622
26019
|
return;
|
|
25623
26020
|
}
|
|
25624
26021
|
removeSession(id);
|
|
25625
|
-
console.log(
|
|
26022
|
+
console.log(import_picocolors6.default.green("\n \u2713 Session deleted\n"));
|
|
25626
26023
|
}
|
|
25627
26024
|
|
|
25628
26025
|
// src/commands/status.ts
|
|
25629
|
-
var
|
|
26026
|
+
var import_picocolors7 = __toESM(require("picocolors"));
|
|
25630
26027
|
function status() {
|
|
25631
26028
|
showIntro();
|
|
25632
26029
|
const config = getConfig();
|
|
25633
26030
|
const active = config.sessions.find((s) => s.id === config.activeSessionId) ?? null;
|
|
25634
|
-
console.log(
|
|
25635
|
-
console.log(` Plugin ID ${
|
|
26031
|
+
console.log(import_picocolors7.default.bold(" Status\n"));
|
|
26032
|
+
console.log(` Plugin ID ${import_picocolors7.default.dim(config.pluginId || "not generated yet")}`);
|
|
25636
26033
|
console.log(` Sessions ${config.sessions.length} paired`);
|
|
25637
26034
|
if (active) {
|
|
25638
|
-
console.log(` Active ${
|
|
25639
|
-
console.log(` Session ID ${
|
|
26035
|
+
console.log(` Active ${import_picocolors7.default.bold(active.userName)} ${import_picocolors7.default.cyan(active.plan)}`);
|
|
26036
|
+
console.log(` Session ID ${import_picocolors7.default.dim(active.id)}`);
|
|
25640
26037
|
} else {
|
|
25641
|
-
console.log(` Active ${
|
|
26038
|
+
console.log(` Active ${import_picocolors7.default.yellow("none")} ${import_picocolors7.default.dim("run codeam pair to connect")}`);
|
|
25642
26039
|
}
|
|
25643
26040
|
console.log("");
|
|
25644
26041
|
}
|
|
25645
26042
|
|
|
25646
26043
|
// src/commands/logout.ts
|
|
25647
|
-
var
|
|
26044
|
+
var import_picocolors8 = __toESM(require("picocolors"));
|
|
25648
26045
|
var API_BASE11 = resolveApiBaseUrl();
|
|
25649
26046
|
async function notifyBackendOffline() {
|
|
25650
26047
|
const cfg = loadCliConfig();
|
|
@@ -25678,17 +26075,17 @@ async function logout() {
|
|
|
25678
26075
|
}
|
|
25679
26076
|
await notifyBackendOffline();
|
|
25680
26077
|
clearAll();
|
|
25681
|
-
console.log(
|
|
26078
|
+
console.log(import_picocolors8.default.green("\n \u2713 Done. All sessions removed.\n"));
|
|
25682
26079
|
}
|
|
25683
26080
|
|
|
25684
26081
|
// src/commands/deploy.ts
|
|
25685
|
-
var
|
|
26082
|
+
var import_picocolors11 = __toESM(require("picocolors"));
|
|
25686
26083
|
|
|
25687
26084
|
// src/services/providers/github-codespaces.ts
|
|
25688
26085
|
var import_child_process23 = require("child_process");
|
|
25689
26086
|
var import_util4 = require("util");
|
|
25690
|
-
var
|
|
25691
|
-
var
|
|
26087
|
+
var import_picocolors9 = __toESM(require("picocolors"));
|
|
26088
|
+
var path54 = __toESM(require("path"));
|
|
25692
26089
|
var execFileP6 = (0, import_util4.promisify)(import_child_process23.execFile);
|
|
25693
26090
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
25694
26091
|
function resetStdinForChild() {
|
|
@@ -25755,7 +26152,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25755
26152
|
if (expectedUser) {
|
|
25756
26153
|
noteLines.push("");
|
|
25757
26154
|
noteLines.push(
|
|
25758
|
-
`${
|
|
26155
|
+
`${import_picocolors9.default.yellow("\u26A0")} Sign in as ${import_picocolors9.default.cyan(expectedUser)} in the browser.`
|
|
25759
26156
|
);
|
|
25760
26157
|
noteLines.push(
|
|
25761
26158
|
" If a different GitHub account is already signed in, sign out"
|
|
@@ -25778,7 +26175,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25778
26175
|
if (refreshCode !== 0) {
|
|
25779
26176
|
const lines = [
|
|
25780
26177
|
"The browser approval came back for a different GitHub account",
|
|
25781
|
-
`than the one gh is configured for${expectedUser ? ` (${
|
|
26178
|
+
`than the one gh is configured for${expectedUser ? ` (${import_picocolors9.default.cyan(expectedUser)})` : ""}.`,
|
|
25782
26179
|
"",
|
|
25783
26180
|
"To recover:",
|
|
25784
26181
|
" 1. Open https://github.com and sign out of any non-target",
|
|
@@ -25787,7 +26184,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25787
26184
|
"",
|
|
25788
26185
|
"You can also grant the scope manually first and skip this step",
|
|
25789
26186
|
"on the next run:",
|
|
25790
|
-
` ${
|
|
26187
|
+
` ${import_picocolors9.default.cyan("gh auth refresh -h github.com -s codespace")}`
|
|
25791
26188
|
];
|
|
25792
26189
|
throw new Error(lines.join("\n"));
|
|
25793
26190
|
}
|
|
@@ -25854,7 +26251,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25854
26251
|
async tryInstallGh() {
|
|
25855
26252
|
const platform3 = process.platform;
|
|
25856
26253
|
wt(
|
|
25857
|
-
`GitHub CLI (${
|
|
26254
|
+
`GitHub CLI (${import_picocolors9.default.cyan("gh")}) is required for Codespaces deploys but isn't on your PATH.`,
|
|
25858
26255
|
"Heads up"
|
|
25859
26256
|
);
|
|
25860
26257
|
if (platform3 === "linux") {
|
|
@@ -25910,7 +26307,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25910
26307
|
return;
|
|
25911
26308
|
}
|
|
25912
26309
|
const proceed = await ot2({
|
|
25913
|
-
message: `Run ${
|
|
26310
|
+
message: `Run ${import_picocolors9.default.cyan(installCmd.describe)} now?`,
|
|
25914
26311
|
initialValue: true
|
|
25915
26312
|
});
|
|
25916
26313
|
if (q(proceed) || !proceed) return;
|
|
@@ -26177,7 +26574,7 @@ var GitHubCodespacesProvider = class {
|
|
|
26177
26574
|
});
|
|
26178
26575
|
}
|
|
26179
26576
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26180
|
-
const remoteDir =
|
|
26577
|
+
const remoteDir = path54.posix.dirname(remotePath);
|
|
26181
26578
|
const parts = [
|
|
26182
26579
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
26183
26580
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -26247,8 +26644,8 @@ function shellQuote(s) {
|
|
|
26247
26644
|
// src/services/providers/gitpod.ts
|
|
26248
26645
|
var import_child_process24 = require("child_process");
|
|
26249
26646
|
var import_util5 = require("util");
|
|
26250
|
-
var
|
|
26251
|
-
var
|
|
26647
|
+
var path55 = __toESM(require("path"));
|
|
26648
|
+
var import_picocolors10 = __toESM(require("picocolors"));
|
|
26252
26649
|
var execFileP7 = (0, import_util5.promisify)(import_child_process24.execFile);
|
|
26253
26650
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
26254
26651
|
function resetStdinForChild2() {
|
|
@@ -26487,7 +26884,7 @@ var GitpodProvider = class {
|
|
|
26487
26884
|
});
|
|
26488
26885
|
}
|
|
26489
26886
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26490
|
-
const remoteDir =
|
|
26887
|
+
const remoteDir = path55.posix.dirname(remotePath);
|
|
26491
26888
|
const parts = [
|
|
26492
26889
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
26493
26890
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -26523,7 +26920,7 @@ function shellQuote2(s) {
|
|
|
26523
26920
|
// src/services/providers/gitlab-workspaces.ts
|
|
26524
26921
|
var import_child_process25 = require("child_process");
|
|
26525
26922
|
var import_util6 = require("util");
|
|
26526
|
-
var
|
|
26923
|
+
var path56 = __toESM(require("path"));
|
|
26527
26924
|
var execFileP8 = (0, import_util6.promisify)(import_child_process25.execFile);
|
|
26528
26925
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
26529
26926
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -26783,7 +27180,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
26783
27180
|
}
|
|
26784
27181
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26785
27182
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
26786
|
-
const remoteDir =
|
|
27183
|
+
const remoteDir = path56.posix.dirname(remotePath);
|
|
26787
27184
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
26788
27185
|
if (options.mode != null) {
|
|
26789
27186
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -26851,7 +27248,7 @@ function shellQuote3(s) {
|
|
|
26851
27248
|
// src/services/providers/railway.ts
|
|
26852
27249
|
var import_child_process26 = require("child_process");
|
|
26853
27250
|
var import_util7 = require("util");
|
|
26854
|
-
var
|
|
27251
|
+
var path57 = __toESM(require("path"));
|
|
26855
27252
|
var execFileP9 = (0, import_util7.promisify)(import_child_process26.execFile);
|
|
26856
27253
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
26857
27254
|
function resetStdinForChild4() {
|
|
@@ -27087,7 +27484,7 @@ var RailwayProvider = class {
|
|
|
27087
27484
|
if (!projectId || !serviceId) {
|
|
27088
27485
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
27089
27486
|
}
|
|
27090
|
-
const remoteDir =
|
|
27487
|
+
const remoteDir = path57.posix.dirname(remotePath);
|
|
27091
27488
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
27092
27489
|
if (options.mode != null) {
|
|
27093
27490
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -27128,7 +27525,7 @@ var PROVIDERS = [
|
|
|
27128
27525
|
// src/commands/deploy.ts
|
|
27129
27526
|
async function deploy(args2 = []) {
|
|
27130
27527
|
console.log();
|
|
27131
|
-
mt(
|
|
27528
|
+
mt(import_picocolors11.default.bgMagenta(import_picocolors11.default.white(" codeam deploy ")));
|
|
27132
27529
|
const provider = await pickProvider();
|
|
27133
27530
|
if (!provider) {
|
|
27134
27531
|
pt("No provider selected.");
|
|
@@ -27165,7 +27562,7 @@ async function deploy(args2 = []) {
|
|
|
27165
27562
|
if (provider.expandListScopes) {
|
|
27166
27563
|
options.push({
|
|
27167
27564
|
value: EXPAND_SCOPES,
|
|
27168
|
-
label:
|
|
27565
|
+
label: import_picocolors11.default.cyan("+ Don't see your project? Expand scopes\u2026"),
|
|
27169
27566
|
hint: "Re-authorize with broader scopes (org / team repos)"
|
|
27170
27567
|
});
|
|
27171
27568
|
}
|
|
@@ -27213,7 +27610,7 @@ async function deploy(args2 = []) {
|
|
|
27213
27610
|
label: w3.displayName ?? w3.id,
|
|
27214
27611
|
hint: [w3.state, formatLastUsed(w3.lastUsedAt)].filter(Boolean).join(" \xB7 ")
|
|
27215
27612
|
})),
|
|
27216
|
-
{ value: "__new__", label:
|
|
27613
|
+
{ value: "__new__", label: import_picocolors11.default.green("+ Create a new workspace"), hint: "fresh codespace" }
|
|
27217
27614
|
]
|
|
27218
27615
|
});
|
|
27219
27616
|
if (q(choice)) {
|
|
@@ -27314,12 +27711,12 @@ async function deploy(args2 = []) {
|
|
|
27314
27711
|
cliStep.stop("\u2713 codeam-cli installed");
|
|
27315
27712
|
wt(
|
|
27316
27713
|
[
|
|
27317
|
-
`Workspace: ${
|
|
27318
|
-
workspace.webUrl ? `Web: ${
|
|
27714
|
+
`Workspace: ${import_picocolors11.default.cyan(workspace.displayName ?? workspace.id)}`,
|
|
27715
|
+
workspace.webUrl ? `Web: ${import_picocolors11.default.cyan(workspace.webUrl)}` : "",
|
|
27319
27716
|
"",
|
|
27320
27717
|
`Starting \`codeam pair\` on the workspace (agent: ${AGENT_REGISTRY[agentId].displayName}).`,
|
|
27321
27718
|
"Scan the QR code from your phone to pair.",
|
|
27322
|
-
|
|
27719
|
+
import_picocolors11.default.dim("(Once paired, this terminal disconnects automatically; the session stays alive on the codespace.)")
|
|
27323
27720
|
].filter(Boolean).join("\n"),
|
|
27324
27721
|
"Almost there"
|
|
27325
27722
|
);
|
|
@@ -27434,11 +27831,11 @@ async function deploy(args2 = []) {
|
|
|
27434
27831
|
].join("\n");
|
|
27435
27832
|
const code = (await provider.streamCommand(workspace.id, `bash -lc ${shellQuoteSingle(wrapper)}`)).code;
|
|
27436
27833
|
if (code === 0) {
|
|
27437
|
-
gt(
|
|
27834
|
+
gt(import_picocolors11.default.green("\u2713 Workspace deployed and paired. Drive from your phone, anywhere."));
|
|
27438
27835
|
} else if (code === 130) {
|
|
27439
|
-
gt(
|
|
27836
|
+
gt(import_picocolors11.default.yellow("Disconnected from local terminal. Mobile session keeps running on the codespace."));
|
|
27440
27837
|
} else {
|
|
27441
|
-
gt(
|
|
27838
|
+
gt(import_picocolors11.default.yellow('Pairing did not complete. Run "codeam pair" inside the codespace if needed.'));
|
|
27442
27839
|
}
|
|
27443
27840
|
}
|
|
27444
27841
|
function shellQuoteSingle(s) {
|
|
@@ -27472,7 +27869,7 @@ async function pickProvider() {
|
|
|
27472
27869
|
message: "Where do you want to deploy?",
|
|
27473
27870
|
options: PROVIDERS.map((prov) => ({
|
|
27474
27871
|
value: prov.id,
|
|
27475
|
-
label: prov.available ? prov.displayName : `${prov.displayName} ${
|
|
27872
|
+
label: prov.available ? prov.displayName : `${prov.displayName} ${import_picocolors11.default.dim("(coming soon)")}`,
|
|
27476
27873
|
hint: prov.tagline
|
|
27477
27874
|
}))
|
|
27478
27875
|
});
|
|
@@ -27489,27 +27886,27 @@ async function pickProvider() {
|
|
|
27489
27886
|
}
|
|
27490
27887
|
|
|
27491
27888
|
// src/commands/deploy-manage.ts
|
|
27492
|
-
var
|
|
27889
|
+
var import_picocolors12 = __toESM(require("picocolors"));
|
|
27493
27890
|
async function deployList() {
|
|
27494
27891
|
console.log();
|
|
27495
|
-
mt(
|
|
27892
|
+
mt(import_picocolors12.default.bgMagenta(import_picocolors12.default.white(" codeam deploy ls ")));
|
|
27496
27893
|
const workspaces = await collectWorkspacesWithStatus();
|
|
27497
27894
|
if (workspaces.length === 0) {
|
|
27498
|
-
gt(
|
|
27895
|
+
gt(import_picocolors12.default.dim("No deployed workspaces found."));
|
|
27499
27896
|
return;
|
|
27500
27897
|
}
|
|
27501
27898
|
for (const w3 of workspaces) {
|
|
27502
|
-
const tag = w3.codeamRunning ?
|
|
27503
|
-
console.log(` ${tag} ${
|
|
27899
|
+
const tag = w3.codeamRunning ? import_picocolors12.default.green("\u25CF running") : w3.state === "Available" ? import_picocolors12.default.dim("\u25CB idle") : import_picocolors12.default.dim(`\u25CB ${w3.state ?? "stopped"}`);
|
|
27900
|
+
console.log(` ${tag} ${import_picocolors12.default.cyan(w3.displayName ?? w3.id)} ${import_picocolors12.default.dim("(" + w3.providerName + ")")}`);
|
|
27504
27901
|
}
|
|
27505
|
-
gt(
|
|
27902
|
+
gt(import_picocolors12.default.dim("Use `codeam deploy stop` to terminate a session."));
|
|
27506
27903
|
}
|
|
27507
27904
|
async function deployStop() {
|
|
27508
27905
|
console.log();
|
|
27509
|
-
mt(
|
|
27906
|
+
mt(import_picocolors12.default.bgMagenta(import_picocolors12.default.white(" codeam deploy stop ")));
|
|
27510
27907
|
const workspaces = await collectWorkspacesWithStatus();
|
|
27511
27908
|
if (workspaces.length === 0) {
|
|
27512
|
-
gt(
|
|
27909
|
+
gt(import_picocolors12.default.dim("No deployed workspaces found."));
|
|
27513
27910
|
return;
|
|
27514
27911
|
}
|
|
27515
27912
|
const choice = await _t({
|
|
@@ -27519,7 +27916,7 @@ async function deployStop() {
|
|
|
27519
27916
|
label: w3.displayName ?? w3.id,
|
|
27520
27917
|
hint: [
|
|
27521
27918
|
w3.providerName,
|
|
27522
|
-
w3.codeamRunning ?
|
|
27919
|
+
w3.codeamRunning ? import_picocolors12.default.green("\u25CF codeam-pair running") : import_picocolors12.default.dim("\u25CB no codeam-pair"),
|
|
27523
27920
|
w3.state ?? ""
|
|
27524
27921
|
].filter(Boolean).join(" \xB7 ")
|
|
27525
27922
|
}))
|
|
@@ -27547,7 +27944,7 @@ async function deployStop() {
|
|
|
27547
27944
|
O2.info("No codeam-pair process to stop on this workspace.");
|
|
27548
27945
|
}
|
|
27549
27946
|
const alsoStop = await ot2({
|
|
27550
|
-
message: `Also stop the workspace ${
|
|
27947
|
+
message: `Also stop the workspace ${import_picocolors12.default.cyan(target.displayName ?? target.id)} to save compute hours?`,
|
|
27551
27948
|
initialValue: true
|
|
27552
27949
|
});
|
|
27553
27950
|
if (!q(alsoStop) && alsoStop) {
|
|
@@ -27569,7 +27966,7 @@ async function deployStop() {
|
|
|
27569
27966
|
O2.warn(err instanceof Error ? err.message : String(err));
|
|
27570
27967
|
}
|
|
27571
27968
|
}
|
|
27572
|
-
gt(
|
|
27969
|
+
gt(import_picocolors12.default.green("\u2713 Done."));
|
|
27573
27970
|
}
|
|
27574
27971
|
async function collectWorkspacesWithStatus() {
|
|
27575
27972
|
const out2 = [];
|
|
@@ -27675,9 +28072,9 @@ async function host(args2) {
|
|
|
27675
28072
|
var import_node_dns = require("dns");
|
|
27676
28073
|
var import_node_util5 = require("util");
|
|
27677
28074
|
var import_node_crypto8 = require("crypto");
|
|
27678
|
-
var
|
|
27679
|
-
var
|
|
27680
|
-
var
|
|
28075
|
+
var fs47 = __toESM(require("fs"));
|
|
28076
|
+
var path58 = __toESM(require("path"));
|
|
28077
|
+
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27681
28078
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
27682
28079
|
async function checkDns(apiBase2) {
|
|
27683
28080
|
const host2 = (() => {
|
|
@@ -27732,13 +28129,13 @@ async function checkHealth(apiBase2) {
|
|
|
27732
28129
|
}
|
|
27733
28130
|
}
|
|
27734
28131
|
function checkConfigDir() {
|
|
27735
|
-
const dir =
|
|
28132
|
+
const dir = path58.join(require("os").homedir(), ".codeam");
|
|
27736
28133
|
try {
|
|
27737
|
-
|
|
27738
|
-
const probe =
|
|
27739
|
-
|
|
27740
|
-
const read2 =
|
|
27741
|
-
|
|
28134
|
+
fs47.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
28135
|
+
const probe = path58.join(dir, ".doctor-probe");
|
|
28136
|
+
fs47.writeFileSync(probe, "ok", { mode: 384 });
|
|
28137
|
+
const read2 = fs47.readFileSync(probe, "utf8");
|
|
28138
|
+
fs47.unlinkSync(probe);
|
|
27742
28139
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
27743
28140
|
return {
|
|
27744
28141
|
id: "config-dir",
|
|
@@ -27802,7 +28199,7 @@ function checkNodePty() {
|
|
|
27802
28199
|
detail: "not required on this platform"
|
|
27803
28200
|
};
|
|
27804
28201
|
}
|
|
27805
|
-
const vendoredPath =
|
|
28202
|
+
const vendoredPath = path58.join(__dirname, "vendor", "node-pty");
|
|
27806
28203
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
27807
28204
|
try {
|
|
27808
28205
|
require(target);
|
|
@@ -27844,7 +28241,7 @@ function checkChokidar() {
|
|
|
27844
28241
|
}
|
|
27845
28242
|
async function doctor(args2 = []) {
|
|
27846
28243
|
const json = args2.includes("--json");
|
|
27847
|
-
const cliVersion = true ? "2.39.
|
|
28244
|
+
const cliVersion = true ? "2.39.55" : "0.0.0-dev";
|
|
27848
28245
|
const apiBase2 = resolveApiBaseUrl();
|
|
27849
28246
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
27850
28247
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27884,46 +28281,46 @@ async function doctor(args2 = []) {
|
|
|
27884
28281
|
function printHumanReport(r) {
|
|
27885
28282
|
const out2 = process.stderr;
|
|
27886
28283
|
out2.write(`
|
|
27887
|
-
${
|
|
28284
|
+
${import_picocolors13.default.bold(" codeam doctor")}
|
|
27888
28285
|
|
|
27889
28286
|
`);
|
|
27890
|
-
out2.write(` ${
|
|
28287
|
+
out2.write(` ${import_picocolors13.default.dim("cli")} ${r.cliVersion}
|
|
27891
28288
|
`);
|
|
27892
|
-
out2.write(` ${
|
|
28289
|
+
out2.write(` ${import_picocolors13.default.dim("node")} ${r.node}
|
|
27893
28290
|
`);
|
|
27894
|
-
out2.write(` ${
|
|
28291
|
+
out2.write(` ${import_picocolors13.default.dim("os")} ${r.platform} ${r.arch}
|
|
27895
28292
|
`);
|
|
27896
|
-
out2.write(` ${
|
|
28293
|
+
out2.write(` ${import_picocolors13.default.dim("api")} ${r.apiBase}
|
|
27897
28294
|
`);
|
|
27898
28295
|
if (process.env.CODEAM_TEST_MODE === "1" || process.env.CODEAM_TEST_MODE?.toLowerCase() === "true") {
|
|
27899
|
-
out2.write(` ${
|
|
28296
|
+
out2.write(` ${import_picocolors13.default.dim("mode")} ${import_picocolors13.default.yellow("TEST_MODE \u2014 using dev preview")}
|
|
27900
28297
|
`);
|
|
27901
28298
|
} else if (process.env.CODEAM_API_URL) {
|
|
27902
|
-
out2.write(` ${
|
|
28299
|
+
out2.write(` ${import_picocolors13.default.dim("mode")} ${import_picocolors13.default.yellow("CODEAM_API_URL override")}
|
|
27903
28300
|
`);
|
|
27904
28301
|
}
|
|
27905
|
-
out2.write(` ${
|
|
28302
|
+
out2.write(` ${import_picocolors13.default.dim("diag id")} ${r.diagnosticId}
|
|
27906
28303
|
`);
|
|
27907
28304
|
out2.write("\n");
|
|
27908
28305
|
for (const c2 of r.checks) {
|
|
27909
|
-
const mark = c2.ok ?
|
|
27910
|
-
out2.write(` ${mark} ${c2.label}${
|
|
28306
|
+
const mark = c2.ok ? import_picocolors13.default.green("\u2713") : c2.optional ? import_picocolors13.default.yellow("!") : import_picocolors13.default.red("\u2717");
|
|
28307
|
+
out2.write(` ${mark} ${c2.label}${import_picocolors13.default.dim(` \u2014 ${c2.detail}`)}
|
|
27911
28308
|
`);
|
|
27912
28309
|
if (!c2.ok && c2.hint) {
|
|
27913
28310
|
for (const line of c2.hint.split("\n")) {
|
|
27914
|
-
out2.write(` ${
|
|
28311
|
+
out2.write(` ${import_picocolors13.default.dim(line)}
|
|
27915
28312
|
`);
|
|
27916
28313
|
}
|
|
27917
28314
|
}
|
|
27918
28315
|
}
|
|
27919
28316
|
out2.write("\n");
|
|
27920
28317
|
if (r.ok) {
|
|
27921
|
-
out2.write(` ${
|
|
28318
|
+
out2.write(` ${import_picocolors13.default.green("All checks passed.")}
|
|
27922
28319
|
|
|
27923
28320
|
`);
|
|
27924
28321
|
} else {
|
|
27925
28322
|
out2.write(
|
|
27926
|
-
` ${
|
|
28323
|
+
` ${import_picocolors13.default.red("Some checks failed.")} ${import_picocolors13.default.dim("Paste the diagnostic id above when opening a bug report.")}
|
|
27927
28324
|
|
|
27928
28325
|
`
|
|
27929
28326
|
);
|
|
@@ -28041,118 +28438,118 @@ async function completion(args2) {
|
|
|
28041
28438
|
}
|
|
28042
28439
|
|
|
28043
28440
|
// src/commands/version.ts
|
|
28044
|
-
var
|
|
28441
|
+
var import_picocolors14 = __toESM(require("picocolors"));
|
|
28045
28442
|
function version2() {
|
|
28046
|
-
const v = true ? "2.39.
|
|
28047
|
-
console.log(`${
|
|
28443
|
+
const v = true ? "2.39.55" : "unknown";
|
|
28444
|
+
console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
|
|
28048
28445
|
}
|
|
28049
28446
|
|
|
28050
28447
|
// src/commands/help.ts
|
|
28051
|
-
var
|
|
28448
|
+
var import_picocolors15 = __toESM(require("picocolors"));
|
|
28052
28449
|
function help() {
|
|
28053
28450
|
const lines = [
|
|
28054
28451
|
"",
|
|
28055
|
-
` ${
|
|
28452
|
+
` ${import_picocolors15.default.bold(import_picocolors15.default.magenta("codeam-cli"))} ${import_picocolors15.default.dim("\u2014 remote-control AI coding agents from your phone")}`,
|
|
28056
28453
|
"",
|
|
28057
|
-
` ${
|
|
28058
|
-
` ${
|
|
28454
|
+
` ${import_picocolors15.default.bold("Usage")}`,
|
|
28455
|
+
` ${import_picocolors15.default.cyan("codeam")} ${import_picocolors15.default.dim("[command]")}`,
|
|
28059
28456
|
"",
|
|
28060
|
-
` ${
|
|
28061
|
-
` ${
|
|
28062
|
-
` ${
|
|
28063
|
-
` ${
|
|
28064
|
-
` ${
|
|
28065
|
-
` ${
|
|
28066
|
-
` ${
|
|
28067
|
-
` ${
|
|
28068
|
-
` ${
|
|
28069
|
-
` ${
|
|
28070
|
-
` ${
|
|
28071
|
-
` ${
|
|
28072
|
-
` ${
|
|
28073
|
-
` ${
|
|
28074
|
-
` ${
|
|
28075
|
-
` ${
|
|
28457
|
+
` ${import_picocolors15.default.bold("Commands")}`,
|
|
28458
|
+
` ${import_picocolors15.default.white("codeam")} ${import_picocolors15.default.dim("start the active agent with mobile control")}`,
|
|
28459
|
+
` ${import_picocolors15.default.white("codeam <agent>")} ${import_picocolors15.default.dim("start a specific agent \u2014 e.g. claude, codex")}`,
|
|
28460
|
+
` ${import_picocolors15.default.white("codeam pair")} ${import_picocolors15.default.dim("pair a new mobile device (interactive)")}`,
|
|
28461
|
+
` ${import_picocolors15.default.white("codeam pair --agent <id>")} ${import_picocolors15.default.dim("pair non-interactively for a specific agent")}`,
|
|
28462
|
+
` ${import_picocolors15.default.white("codeam sessions")} ${import_picocolors15.default.dim("list paired devices")}`,
|
|
28463
|
+
` ${import_picocolors15.default.white("codeam sessions switch")} ${import_picocolors15.default.dim("switch the active paired session")}`,
|
|
28464
|
+
` ${import_picocolors15.default.white("codeam sessions delete <id>")} ${import_picocolors15.default.dim("remove a specific paired session")}`,
|
|
28465
|
+
` ${import_picocolors15.default.white("codeam status")} ${import_picocolors15.default.dim("show connection info")}`,
|
|
28466
|
+
` ${import_picocolors15.default.white("codeam logout")} ${import_picocolors15.default.dim("remove all paired sessions")}`,
|
|
28467
|
+
` ${import_picocolors15.default.white("codeam link <agent>")} ${import_picocolors15.default.dim("link an agent (claude, codex) to your CodeAgent account")}`,
|
|
28468
|
+
` ${import_picocolors15.default.white("codeam deploy")} ${import_picocolors15.default.dim("provision a cloud workspace (Codespaces) and pair it")}`,
|
|
28469
|
+
` ${import_picocolors15.default.white("codeam deploy ls | list")} ${import_picocolors15.default.dim("list deployed cloud workspaces")}`,
|
|
28470
|
+
` ${import_picocolors15.default.white("codeam deploy stop | remove")} ${import_picocolors15.default.dim("stop a deployed workspace session")}`,
|
|
28471
|
+
` ${import_picocolors15.default.white("codeam doctor")} ${import_picocolors15.default.dim("run diagnostic checks (DNS, /health, binaries, \u2026)")}`,
|
|
28472
|
+
` ${import_picocolors15.default.white("codeam completion <shell>")} ${import_picocolors15.default.dim("emit a bash/zsh/fish completion script")}`,
|
|
28076
28473
|
"",
|
|
28077
|
-
` ${
|
|
28078
|
-
` ${
|
|
28079
|
-
` ${
|
|
28474
|
+
` ${import_picocolors15.default.bold("Flags")}`,
|
|
28475
|
+
` ${import_picocolors15.default.white("-v, --version")} ${import_picocolors15.default.dim("print the CLI version")}`,
|
|
28476
|
+
` ${import_picocolors15.default.white("-h, --help")} ${import_picocolors15.default.dim("show this help")}`,
|
|
28080
28477
|
"",
|
|
28081
|
-
` ${
|
|
28082
|
-
` ${
|
|
28083
|
-
` ${
|
|
28478
|
+
` ${import_picocolors15.default.bold("Links")}`,
|
|
28479
|
+
` ${import_picocolors15.default.dim("Docs:")} ${import_picocolors15.default.green("https://www.codeagent-mobile.com")}`,
|
|
28480
|
+
` ${import_picocolors15.default.dim("Issues:")} ${import_picocolors15.default.green("https://github.com/edgar-durand/codeagent-mobile-clients/issues")}`,
|
|
28084
28481
|
""
|
|
28085
28482
|
];
|
|
28086
28483
|
process.stdout.write(lines.join("\n") + "\n");
|
|
28087
28484
|
}
|
|
28088
28485
|
|
|
28089
28486
|
// src/commands/subcommand-help.ts
|
|
28090
|
-
var
|
|
28487
|
+
var import_picocolors16 = __toESM(require("picocolors"));
|
|
28091
28488
|
var HELPS = {
|
|
28092
28489
|
pair: () => print([
|
|
28093
|
-
` ${
|
|
28490
|
+
` ${import_picocolors16.default.bold("codeam pair")} ${import_picocolors16.default.dim("\u2014 pair a mobile device with this CLI")}`,
|
|
28094
28491
|
"",
|
|
28095
|
-
` ${
|
|
28096
|
-
` ${
|
|
28097
|
-
` ${
|
|
28492
|
+
` ${import_picocolors16.default.cyan("codeam pair")} ${import_picocolors16.default.dim("interactive pairing (prompts for the agent)")}`,
|
|
28493
|
+
` ${import_picocolors16.default.cyan("codeam pair --agent <id>")} ${import_picocolors16.default.dim("pair non-interactively (agent: claude | codex)")}`,
|
|
28494
|
+
` ${import_picocolors16.default.cyan("codeam pair --dry-run")} ${import_picocolors16.default.dim("request a pairing code, validate the response, exit")}`
|
|
28098
28495
|
]),
|
|
28099
28496
|
"pair-auto": () => print([
|
|
28100
|
-
` ${
|
|
28497
|
+
` ${import_picocolors16.default.bold("codeam pair-auto")} ${import_picocolors16.default.dim("\u2014 non-interactive variant of pair for scripted setups")}`,
|
|
28101
28498
|
"",
|
|
28102
|
-
` ${
|
|
28499
|
+
` ${import_picocolors16.default.cyan("codeam pair-auto --agent <id>")} ${import_picocolors16.default.dim("pair using the supplied agent id; exit on success or timeout")}`
|
|
28103
28500
|
]),
|
|
28104
28501
|
link: () => print([
|
|
28105
|
-
` ${
|
|
28502
|
+
` ${import_picocolors16.default.bold("codeam link <agent>")} ${import_picocolors16.default.dim("\u2014 upload a local agent token (Claude or Codex) to your vault")}`,
|
|
28106
28503
|
"",
|
|
28107
|
-
` ${
|
|
28108
|
-
` ${
|
|
28504
|
+
` ${import_picocolors16.default.cyan("codeam link claude")}`,
|
|
28505
|
+
` ${import_picocolors16.default.cyan("codeam link codex")}`,
|
|
28109
28506
|
"",
|
|
28110
|
-
` ${
|
|
28111
|
-
` ${
|
|
28112
|
-
` ${
|
|
28113
|
-
` ${
|
|
28114
|
-
` ${
|
|
28507
|
+
` ${import_picocolors16.default.white("--api-key=<key>")} ${import_picocolors16.default.dim("paste an API key directly (visible in `ps -ef`)")}`,
|
|
28508
|
+
` ${import_picocolors16.default.white("--api-key-file=<path>")} ${import_picocolors16.default.dim("read API key from a file (recommended for CI / scripts)")}`,
|
|
28509
|
+
` ${import_picocolors16.default.white("--reuse-existing")} ${import_picocolors16.default.dim("upload existing creds without re-launching the agent login")}`,
|
|
28510
|
+
` ${import_picocolors16.default.white("--token-file=<path>")} ${import_picocolors16.default.dim("manual credential blob path for unusual vendor locations")}`,
|
|
28511
|
+
` ${import_picocolors16.default.white("--dry-run")} ${import_picocolors16.default.dim("probe the /api/plugin/agents/<agent>/link endpoint and exit")}`
|
|
28115
28512
|
]),
|
|
28116
28513
|
sessions: () => print([
|
|
28117
|
-
` ${
|
|
28514
|
+
` ${import_picocolors16.default.bold("codeam sessions")} ${import_picocolors16.default.dim("\u2014 list, switch, or delete paired mobile sessions")}`,
|
|
28118
28515
|
"",
|
|
28119
|
-
` ${
|
|
28120
|
-
` ${
|
|
28121
|
-
` ${
|
|
28516
|
+
` ${import_picocolors16.default.cyan("codeam sessions")} ${import_picocolors16.default.dim("list all paired sessions on this machine")}`,
|
|
28517
|
+
` ${import_picocolors16.default.cyan("codeam sessions switch")} ${import_picocolors16.default.dim("interactively switch the active session")}`,
|
|
28518
|
+
` ${import_picocolors16.default.cyan("codeam sessions delete <id>")} ${import_picocolors16.default.dim("remove a specific paired session")}`
|
|
28122
28519
|
]),
|
|
28123
28520
|
deploy: () => print([
|
|
28124
|
-
` ${
|
|
28521
|
+
` ${import_picocolors16.default.bold("codeam deploy")} ${import_picocolors16.default.dim("\u2014 provision a cloud workspace (GitHub Codespaces) and pair it")}`,
|
|
28125
28522
|
"",
|
|
28126
|
-
` ${
|
|
28127
|
-
` ${
|
|
28128
|
-
` ${
|
|
28523
|
+
` ${import_picocolors16.default.cyan("codeam deploy")} ${import_picocolors16.default.dim("start a new deploy (prompts for repo + agent)")}`,
|
|
28524
|
+
` ${import_picocolors16.default.cyan("codeam deploy ls | list")} ${import_picocolors16.default.dim("list deployed cloud workspaces")}`,
|
|
28525
|
+
` ${import_picocolors16.default.cyan("codeam deploy stop | remove")} ${import_picocolors16.default.dim("pick a workspace and stop its codeam-pair session")}`
|
|
28129
28526
|
]),
|
|
28130
28527
|
status: () => print([
|
|
28131
|
-
` ${
|
|
28528
|
+
` ${import_picocolors16.default.bold("codeam status")} ${import_picocolors16.default.dim("\u2014 show the active session, agent, and connection info")}`
|
|
28132
28529
|
]),
|
|
28133
28530
|
logout: () => print([
|
|
28134
|
-
` ${
|
|
28531
|
+
` ${import_picocolors16.default.bold("codeam logout")} ${import_picocolors16.default.dim("\u2014 remove every paired session from this machine")}`
|
|
28135
28532
|
]),
|
|
28136
28533
|
doctor: () => print([
|
|
28137
|
-
` ${
|
|
28534
|
+
` ${import_picocolors16.default.bold("codeam doctor")} ${import_picocolors16.default.dim("\u2014 run diagnostic checks for support triage")}`,
|
|
28138
28535
|
"",
|
|
28139
|
-
` ${
|
|
28140
|
-
` ${
|
|
28536
|
+
` ${import_picocolors16.default.cyan("codeam doctor")} ${import_picocolors16.default.dim("human-readable report")}`,
|
|
28537
|
+
` ${import_picocolors16.default.cyan("codeam doctor --json")} ${import_picocolors16.default.dim("machine-parseable report (single JSON document on stdout)")}`,
|
|
28141
28538
|
"",
|
|
28142
|
-
` ${
|
|
28143
|
-
` ${
|
|
28539
|
+
` ${import_picocolors16.default.dim("Output never includes tokens or credentials. Paste the diagnostic id")}`,
|
|
28540
|
+
` ${import_picocolors16.default.dim("into a bug report so support can grep the server-side logs.")}`
|
|
28144
28541
|
]),
|
|
28145
28542
|
completion: () => print([
|
|
28146
|
-
` ${
|
|
28543
|
+
` ${import_picocolors16.default.bold("codeam completion <shell>")} ${import_picocolors16.default.dim("\u2014 emit a shell-completion script for sourcing")}`,
|
|
28147
28544
|
"",
|
|
28148
|
-
` ${
|
|
28149
|
-
` ${
|
|
28150
|
-
` ${
|
|
28545
|
+
` ${import_picocolors16.default.cyan("codeam completion bash")} ${import_picocolors16.default.dim("print a bash completion function")}`,
|
|
28546
|
+
` ${import_picocolors16.default.cyan("codeam completion zsh")} ${import_picocolors16.default.dim("print a zsh completion function")}`,
|
|
28547
|
+
` ${import_picocolors16.default.cyan("codeam completion fish")} ${import_picocolors16.default.dim("print a fish completion file")}`,
|
|
28151
28548
|
"",
|
|
28152
|
-
` ${
|
|
28153
|
-
` ${
|
|
28154
|
-
` ${
|
|
28155
|
-
` ${
|
|
28549
|
+
` ${import_picocolors16.default.dim("Examples:")}`,
|
|
28550
|
+
` ${import_picocolors16.default.dim(" bash: codeam completion bash >> ~/.bashrc")}`,
|
|
28551
|
+
` ${import_picocolors16.default.dim(" zsh: codeam completion zsh >> ~/.zshrc")}`,
|
|
28552
|
+
` ${import_picocolors16.default.dim(" fish: codeam completion fish > ~/.config/fish/completions/codeam.fish")}`
|
|
28156
28553
|
])
|
|
28157
28554
|
};
|
|
28158
28555
|
function print(lines) {
|
|
@@ -28170,179 +28567,6 @@ function tryShowSubcommandHelp(cmd, args2) {
|
|
|
28170
28567
|
}
|
|
28171
28568
|
var _subcommandHelpKeys = Object.keys(HELPS);
|
|
28172
28569
|
|
|
28173
|
-
// src/lib/updateNotifier.ts
|
|
28174
|
-
var fs46 = __toESM(require("fs"));
|
|
28175
|
-
var os37 = __toESM(require("os"));
|
|
28176
|
-
var path57 = __toESM(require("path"));
|
|
28177
|
-
var https8 = __toESM(require("https"));
|
|
28178
|
-
var import_node_child_process15 = require("child_process");
|
|
28179
|
-
var import_picocolors16 = __toESM(require("picocolors"));
|
|
28180
|
-
var PKG_NAME = "codeam-cli";
|
|
28181
|
-
var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
28182
|
-
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
28183
|
-
var REQUEST_TIMEOUT_MS = 1500;
|
|
28184
|
-
function cachePath() {
|
|
28185
|
-
const dir = path57.join(os37.homedir(), ".codeam");
|
|
28186
|
-
return path57.join(dir, "update-check.json");
|
|
28187
|
-
}
|
|
28188
|
-
function readCache() {
|
|
28189
|
-
try {
|
|
28190
|
-
const raw = fs46.readFileSync(cachePath(), "utf8");
|
|
28191
|
-
const parsed = JSON.parse(raw);
|
|
28192
|
-
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
28193
|
-
return parsed;
|
|
28194
|
-
} catch {
|
|
28195
|
-
return null;
|
|
28196
|
-
}
|
|
28197
|
-
}
|
|
28198
|
-
function writeCache(cache) {
|
|
28199
|
-
try {
|
|
28200
|
-
const file = cachePath();
|
|
28201
|
-
fs46.mkdirSync(path57.dirname(file), { recursive: true });
|
|
28202
|
-
const tmp = `${file}.${process.pid}.tmp`;
|
|
28203
|
-
fs46.writeFileSync(tmp, JSON.stringify(cache));
|
|
28204
|
-
fs46.renameSync(tmp, file);
|
|
28205
|
-
} catch {
|
|
28206
|
-
}
|
|
28207
|
-
}
|
|
28208
|
-
function compareSemver(a, b) {
|
|
28209
|
-
const stripPre = (s) => s.split("-")[0];
|
|
28210
|
-
const aParts = stripPre(a).split(".").map(Number);
|
|
28211
|
-
const bParts = stripPre(b).split(".").map(Number);
|
|
28212
|
-
for (let i = 0; i < 3; i++) {
|
|
28213
|
-
const ai = aParts[i] ?? 0;
|
|
28214
|
-
const bi = bParts[i] ?? 0;
|
|
28215
|
-
if (Number.isNaN(ai) || Number.isNaN(bi)) return 0;
|
|
28216
|
-
if (ai > bi) return 1;
|
|
28217
|
-
if (ai < bi) return -1;
|
|
28218
|
-
}
|
|
28219
|
-
return 0;
|
|
28220
|
-
}
|
|
28221
|
-
function fetchLatest() {
|
|
28222
|
-
return new Promise((resolve7) => {
|
|
28223
|
-
const req = https8.get(
|
|
28224
|
-
REGISTRY_URL,
|
|
28225
|
-
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
28226
|
-
(res) => {
|
|
28227
|
-
if (res.statusCode !== 200) {
|
|
28228
|
-
res.resume();
|
|
28229
|
-
resolve7(null);
|
|
28230
|
-
return;
|
|
28231
|
-
}
|
|
28232
|
-
let buf = "";
|
|
28233
|
-
res.setEncoding("utf8");
|
|
28234
|
-
res.on("data", (chunk) => {
|
|
28235
|
-
buf += chunk;
|
|
28236
|
-
});
|
|
28237
|
-
res.on("end", () => {
|
|
28238
|
-
try {
|
|
28239
|
-
const json = JSON.parse(buf);
|
|
28240
|
-
if (typeof json.version === "string") {
|
|
28241
|
-
resolve7(json.version);
|
|
28242
|
-
} else {
|
|
28243
|
-
resolve7(null);
|
|
28244
|
-
}
|
|
28245
|
-
} catch {
|
|
28246
|
-
resolve7(null);
|
|
28247
|
-
}
|
|
28248
|
-
});
|
|
28249
|
-
}
|
|
28250
|
-
);
|
|
28251
|
-
req.on("timeout", () => {
|
|
28252
|
-
req.destroy();
|
|
28253
|
-
resolve7(null);
|
|
28254
|
-
});
|
|
28255
|
-
req.on("error", () => resolve7(null));
|
|
28256
|
-
});
|
|
28257
|
-
}
|
|
28258
|
-
function notifyIfStale(currentVersion, latest) {
|
|
28259
|
-
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
28260
|
-
const arrow = import_picocolors16.default.dim("\u2192");
|
|
28261
|
-
const cmd = import_picocolors16.default.cyan("npm install -g codeam-cli");
|
|
28262
|
-
const lines = [
|
|
28263
|
-
"",
|
|
28264
|
-
` ${import_picocolors16.default.yellow("\u25CF")} ${import_picocolors16.default.bold("Update available")} ${import_picocolors16.default.dim(currentVersion)} ${arrow} ${import_picocolors16.default.green(latest)}`,
|
|
28265
|
-
` Run ${cmd} to upgrade.`,
|
|
28266
|
-
""
|
|
28267
|
-
];
|
|
28268
|
-
process.stderr.write(lines.join("\n"));
|
|
28269
|
-
}
|
|
28270
|
-
function isLinkedInstall() {
|
|
28271
|
-
try {
|
|
28272
|
-
const root = (0, import_node_child_process15.execSync)("npm root -g", {
|
|
28273
|
-
encoding: "utf8",
|
|
28274
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
28275
|
-
timeout: 2e3
|
|
28276
|
-
}).trim();
|
|
28277
|
-
if (!root) return false;
|
|
28278
|
-
const pkgPath = path57.join(root, PKG_NAME);
|
|
28279
|
-
return fs46.lstatSync(pkgPath).isSymbolicLink();
|
|
28280
|
-
} catch {
|
|
28281
|
-
return false;
|
|
28282
|
-
}
|
|
28283
|
-
}
|
|
28284
|
-
function maybeAutoUpdate(currentVersion, latest) {
|
|
28285
|
-
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
28286
|
-
if (process.env.CODEAM_NO_AUTO_UPDATE === "1") {
|
|
28287
|
-
notifyIfStale(currentVersion, latest);
|
|
28288
|
-
return;
|
|
28289
|
-
}
|
|
28290
|
-
if (isLinkedInstall()) {
|
|
28291
|
-
notifyIfStale(currentVersion, latest);
|
|
28292
|
-
return;
|
|
28293
|
-
}
|
|
28294
|
-
process.stderr.write(
|
|
28295
|
-
`
|
|
28296
|
-
${import_picocolors16.default.yellow("\u25CF")} ${import_picocolors16.default.bold("Updating codeam-cli")} ${import_picocolors16.default.dim(currentVersion)} ${import_picocolors16.default.dim("\u2192")} ${import_picocolors16.default.green(latest)}...
|
|
28297
|
-
|
|
28298
|
-
`
|
|
28299
|
-
);
|
|
28300
|
-
const install = (0, import_node_child_process15.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
|
|
28301
|
-
stdio: "inherit",
|
|
28302
|
-
env: process.env
|
|
28303
|
-
});
|
|
28304
|
-
if (install.status !== 0) {
|
|
28305
|
-
process.stderr.write(
|
|
28306
|
-
`
|
|
28307
|
-
${import_picocolors16.default.red("!")} Update failed (exit ${install.status ?? "?"}). Continuing on ${currentVersion}.
|
|
28308
|
-
Run ${import_picocolors16.default.cyan("npm install -g codeam-cli")} manually to retry.
|
|
28309
|
-
|
|
28310
|
-
`
|
|
28311
|
-
);
|
|
28312
|
-
return;
|
|
28313
|
-
}
|
|
28314
|
-
try {
|
|
28315
|
-
fs46.unlinkSync(cachePath());
|
|
28316
|
-
} catch {
|
|
28317
|
-
}
|
|
28318
|
-
process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
|
|
28319
|
-
|
|
28320
|
-
`);
|
|
28321
|
-
const child = (0, import_node_child_process15.spawnSync)("codeam", process.argv.slice(2), {
|
|
28322
|
-
stdio: "inherit",
|
|
28323
|
-
env: process.env
|
|
28324
|
-
});
|
|
28325
|
-
process.exit(child.status ?? 0);
|
|
28326
|
-
}
|
|
28327
|
-
function checkForUpdates() {
|
|
28328
|
-
if (process.env.NODE_ENV === "test") return;
|
|
28329
|
-
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
28330
|
-
if (process.env.CI) return;
|
|
28331
|
-
if (!process.stdout.isTTY) return;
|
|
28332
|
-
const current = true ? "2.39.53" : null;
|
|
28333
|
-
if (!current) return;
|
|
28334
|
-
const cache = readCache();
|
|
28335
|
-
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
28336
|
-
if (fresh && cache) {
|
|
28337
|
-
maybeAutoUpdate(current, cache.latest);
|
|
28338
|
-
return;
|
|
28339
|
-
}
|
|
28340
|
-
void fetchLatest().then((latest) => {
|
|
28341
|
-
if (!latest) return;
|
|
28342
|
-
writeCache({ fetchedAt: Date.now(), latest });
|
|
28343
|
-
});
|
|
28344
|
-
}
|
|
28345
|
-
|
|
28346
28570
|
// src/exit-codes.ts
|
|
28347
28571
|
var EXIT_OK = 0;
|
|
28348
28572
|
var EXIT_FAILURE = 1;
|