codeam-cli 2.39.54 → 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 +6 -0
- package/dist/index.js +674 -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) => {
|
|
@@ -17416,6 +17595,41 @@ function agentIdToHeadroomKind(agentId) {
|
|
|
17416
17595
|
if (normalized.startsWith("copilot")) return "copilot";
|
|
17417
17596
|
return "claude";
|
|
17418
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
|
+
}
|
|
17419
17633
|
async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner) {
|
|
17420
17634
|
const PIP_PACKAGES = [
|
|
17421
17635
|
"headroom-ai",
|
|
@@ -17473,7 +17687,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17473
17687
|
}
|
|
17474
17688
|
const initKind = agentIdToHeadroomKind(agent);
|
|
17475
17689
|
const initOk = await new Promise((resolve7) => {
|
|
17476
|
-
(0,
|
|
17690
|
+
(0, import_node_child_process13.execFile)("headroom", ["init", "--global", initKind], (initErr, stdout, stderr) => {
|
|
17477
17691
|
if (initErr) {
|
|
17478
17692
|
const detail = (stderr || initErr.message).replace(/\n+$/g, "");
|
|
17479
17693
|
log.warn("host-agent", `headroom init failed (best-effort): ${detail}`);
|
|
@@ -17489,7 +17703,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17489
17703
|
return false;
|
|
17490
17704
|
}
|
|
17491
17705
|
try {
|
|
17492
|
-
const proxy = (0,
|
|
17706
|
+
const proxy = (0, import_node_child_process13.spawn)("headroom", ["proxy", "--port", "8787"], {
|
|
17493
17707
|
stdio: "ignore",
|
|
17494
17708
|
detached: true
|
|
17495
17709
|
});
|
|
@@ -17499,20 +17713,81 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17499
17713
|
}
|
|
17500
17714
|
return true;
|
|
17501
17715
|
}
|
|
17502
|
-
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], {
|
|
17503
17717
|
cwd,
|
|
17504
17718
|
env: { ...process.env, ...env },
|
|
17505
17719
|
stdio: ["ignore", "pipe", "pipe"],
|
|
17506
17720
|
detached: false
|
|
17507
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
|
+
}
|
|
17508
17779
|
var defaultOnIdentityRejected = () => {
|
|
17509
17780
|
deleteHostIdentity();
|
|
17510
17781
|
log.warn("host-agent", "host identity rejected by backend \u2014 wiped sealed identity, exiting");
|
|
17511
17782
|
process.exit(1);
|
|
17512
17783
|
};
|
|
17784
|
+
var defaultOnUpdated = (version3) => {
|
|
17785
|
+
log.info("host-agent", `self-update: installed ${version3}, restarting`);
|
|
17786
|
+
process.exit(0);
|
|
17787
|
+
};
|
|
17513
17788
|
var defaultDisableService = () => {
|
|
17514
17789
|
try {
|
|
17515
|
-
(0,
|
|
17790
|
+
(0, import_node_child_process13.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
|
|
17516
17791
|
} catch {
|
|
17517
17792
|
}
|
|
17518
17793
|
};
|
|
@@ -17526,6 +17801,8 @@ var HostAgentSupervisor = class {
|
|
|
17526
17801
|
this.metrics = deps.metricsCollector ?? new MetricsCollector();
|
|
17527
17802
|
this.onIdentityRejected = deps.onIdentityRejected ?? defaultOnIdentityRejected;
|
|
17528
17803
|
this.disableService = deps.disableService ?? defaultDisableService;
|
|
17804
|
+
this.selfUpdate = deps.selfUpdate ?? runSelfUpdate;
|
|
17805
|
+
this.onUpdated = deps.onUpdated ?? defaultOnUpdated;
|
|
17529
17806
|
}
|
|
17530
17807
|
identity;
|
|
17531
17808
|
deps;
|
|
@@ -17535,6 +17812,20 @@ var HostAgentSupervisor = class {
|
|
|
17535
17812
|
setupHeadroom;
|
|
17536
17813
|
relay = null;
|
|
17537
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;
|
|
17538
17829
|
/** Guards the one-shot 'connected' telemetry on the first heartbeat. */
|
|
17539
17830
|
reportedConnected = false;
|
|
17540
17831
|
/** Live-metrics collector — stateful across beats (CPU delta + latency). */
|
|
@@ -17545,6 +17836,19 @@ var HostAgentSupervisor = class {
|
|
|
17545
17836
|
disableService;
|
|
17546
17837
|
/** Guards against firing the self-heal more than once. */
|
|
17547
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
|
+
}
|
|
17548
17852
|
/** Open the control channel (reusing the relay) + start heartbeats. */
|
|
17549
17853
|
start() {
|
|
17550
17854
|
const make = this.deps.makeRelay ?? ((pluginId, onCommand, meta) => new CommandRelayService(pluginId, onCommand, meta));
|
|
@@ -17557,6 +17861,13 @@ var HostAgentSupervisor = class {
|
|
|
17557
17861
|
void this.beat();
|
|
17558
17862
|
this.heartbeatTimer = setInterval(() => void this.beat(), HEARTBEAT_INTERVAL_MS);
|
|
17559
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
|
+
}
|
|
17560
17871
|
log.info("host-agent", `supervisor up host=${this.identity.hostId.slice(0, 8)}`);
|
|
17561
17872
|
}
|
|
17562
17873
|
/** Stop the control channel + heartbeats + kill every child. */
|
|
@@ -17565,6 +17876,10 @@ var HostAgentSupervisor = class {
|
|
|
17565
17876
|
clearInterval(this.heartbeatTimer);
|
|
17566
17877
|
this.heartbeatTimer = null;
|
|
17567
17878
|
}
|
|
17879
|
+
if (this.selfUpdateTimer) {
|
|
17880
|
+
clearInterval(this.selfUpdateTimer);
|
|
17881
|
+
this.selfUpdateTimer = null;
|
|
17882
|
+
}
|
|
17568
17883
|
this.relay?.stop();
|
|
17569
17884
|
for (const child of this.children.values()) {
|
|
17570
17885
|
try {
|
|
@@ -17604,6 +17919,61 @@ var HostAgentSupervisor = class {
|
|
|
17604
17919
|
log.trace("host-agent", "heartbeat failed", err);
|
|
17605
17920
|
}
|
|
17606
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
|
+
}
|
|
17607
17977
|
/** Number of live children — for tests + diagnostics. */
|
|
17608
17978
|
childCount() {
|
|
17609
17979
|
return this.children.size;
|
|
@@ -17699,7 +18069,7 @@ var HostAgentSupervisor = class {
|
|
|
17699
18069
|
report("installing", "installing agent CLI");
|
|
17700
18070
|
await this.runAgentInstall(payload.agentInstallScript);
|
|
17701
18071
|
}
|
|
17702
|
-
const home = process.env.HOME ||
|
|
18072
|
+
const home = process.env.HOME || os32.homedir();
|
|
17703
18073
|
childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
|
|
17704
18074
|
if (payload.previewTunnelToken && payload.previewHostname) {
|
|
17705
18075
|
childEnv.PREVIEW_TUNNEL_TOKEN = payload.previewTunnelToken;
|
|
@@ -17709,16 +18079,21 @@ var HostAgentSupervisor = class {
|
|
|
17709
18079
|
report("headroom", "setting up Headroom proxy");
|
|
17710
18080
|
const headroomOk = await this.setupHeadroom(payload.headroomAgent);
|
|
17711
18081
|
if (headroomOk) {
|
|
17712
|
-
|
|
17713
|
-
|
|
17714
|
-
|
|
17715
|
-
|
|
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");
|
|
17716
18088
|
} else {
|
|
18089
|
+
persistHeadroomConfig({ enabled: false });
|
|
17717
18090
|
log.warn("host-agent", "Headroom setup failed (best-effort) \u2014 child will run without Headroom");
|
|
17718
18091
|
}
|
|
18092
|
+
} else if (payload.headroomEnabled === false) {
|
|
18093
|
+
persistHeadroomConfig({ enabled: false });
|
|
17719
18094
|
}
|
|
17720
18095
|
report("spawning", "starting agent");
|
|
17721
|
-
const proc = this.
|
|
18096
|
+
const proc = this.spawnSessionChild(childEnv, cwd, extraArgs);
|
|
17722
18097
|
const child = { deployId: payload.deployId, proc };
|
|
17723
18098
|
this.children.set(payload.deployId, child);
|
|
17724
18099
|
let tail = "";
|
|
@@ -17752,6 +18127,20 @@ var HostAgentSupervisor = class {
|
|
|
17752
18127
|
report("failed", message);
|
|
17753
18128
|
}
|
|
17754
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
|
+
}
|
|
17755
18144
|
/**
|
|
17756
18145
|
* Run the backend-supplied per-agent CLI install script (e.g.
|
|
17757
18146
|
* `claude.ai/install.sh`, `npm i -g @openai/codex`). Best-effort + bounded:
|
|
@@ -17763,8 +18152,8 @@ var HostAgentSupervisor = class {
|
|
|
17763
18152
|
*/
|
|
17764
18153
|
runAgentInstall(script) {
|
|
17765
18154
|
return new Promise((resolve7) => {
|
|
17766
|
-
const home = process.env.HOME ||
|
|
17767
|
-
const child = (0,
|
|
18155
|
+
const home = process.env.HOME || os32.homedir();
|
|
18156
|
+
const child = (0, import_node_child_process13.spawn)("sh", ["-c", script], {
|
|
17768
18157
|
env: { ...process.env, HOME: home },
|
|
17769
18158
|
stdio: ["ignore", "pipe", "pipe"]
|
|
17770
18159
|
});
|
|
@@ -17888,12 +18277,12 @@ function readTokenFromArgs(args2) {
|
|
|
17888
18277
|
}
|
|
17889
18278
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
17890
18279
|
if (fileFlag) {
|
|
17891
|
-
const
|
|
18280
|
+
const path59 = fileFlag.slice("--token-file=".length);
|
|
17892
18281
|
try {
|
|
17893
|
-
const content =
|
|
17894
|
-
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`);
|
|
17895
18284
|
try {
|
|
17896
|
-
|
|
18285
|
+
fs40.unlinkSync(path59);
|
|
17897
18286
|
} catch {
|
|
17898
18287
|
}
|
|
17899
18288
|
return content;
|
|
@@ -17919,7 +18308,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
|
|
|
17919
18308
|
pluginId,
|
|
17920
18309
|
ideName: "codeam-cli (codespace)",
|
|
17921
18310
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
17922
|
-
hostname:
|
|
18311
|
+
hostname: os33.hostname(),
|
|
17923
18312
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
17924
18313
|
// Current git branch of the codespace's working directory, so the
|
|
17925
18314
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -17980,7 +18369,7 @@ async function claim(token, pluginId, pluginSecretHash) {
|
|
|
17980
18369
|
}
|
|
17981
18370
|
}
|
|
17982
18371
|
function pairAutoLockPath() {
|
|
17983
|
-
return
|
|
18372
|
+
return path46.join(os33.homedir(), ".codeam", "pair-auto.lock");
|
|
17984
18373
|
}
|
|
17985
18374
|
function isLivePairAuto(pid) {
|
|
17986
18375
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -17990,7 +18379,7 @@ function isLivePairAuto(pid) {
|
|
|
17990
18379
|
if (e.code !== "EPERM") return false;
|
|
17991
18380
|
}
|
|
17992
18381
|
try {
|
|
17993
|
-
return
|
|
18382
|
+
return fs40.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
|
|
17994
18383
|
} catch {
|
|
17995
18384
|
return true;
|
|
17996
18385
|
}
|
|
@@ -18000,24 +18389,24 @@ function isLiveCodeam(pid) {
|
|
|
18000
18389
|
}
|
|
18001
18390
|
function daemonLockPath(sessionId) {
|
|
18002
18391
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
18003
|
-
return
|
|
18392
|
+
return path46.join(os33.homedir(), ".codeam", `daemon-${safe}.lock`);
|
|
18004
18393
|
}
|
|
18005
18394
|
function acquireDaemonLock(sessionId) {
|
|
18006
18395
|
const lockPath = daemonLockPath(sessionId);
|
|
18007
18396
|
try {
|
|
18008
|
-
|
|
18397
|
+
fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
|
|
18009
18398
|
try {
|
|
18010
|
-
|
|
18399
|
+
fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
18011
18400
|
} catch (e) {
|
|
18012
18401
|
if (e.code !== "EEXIST") throw e;
|
|
18013
|
-
const holder = Number(
|
|
18402
|
+
const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
|
|
18014
18403
|
if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
|
|
18015
|
-
|
|
18404
|
+
fs40.writeFileSync(lockPath, String(process.pid));
|
|
18016
18405
|
}
|
|
18017
18406
|
const release3 = () => {
|
|
18018
18407
|
try {
|
|
18019
|
-
if (
|
|
18020
|
-
|
|
18408
|
+
if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
18409
|
+
fs40.unlinkSync(lockPath);
|
|
18021
18410
|
}
|
|
18022
18411
|
} catch {
|
|
18023
18412
|
}
|
|
@@ -18039,19 +18428,19 @@ function acquireDaemonLock(sessionId) {
|
|
|
18039
18428
|
function acquireSingletonLock() {
|
|
18040
18429
|
const lockPath = pairAutoLockPath();
|
|
18041
18430
|
try {
|
|
18042
|
-
|
|
18431
|
+
fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
|
|
18043
18432
|
try {
|
|
18044
|
-
|
|
18433
|
+
fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
18045
18434
|
} catch (e) {
|
|
18046
18435
|
if (e.code !== "EEXIST") throw e;
|
|
18047
|
-
const holder = Number(
|
|
18436
|
+
const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
|
|
18048
18437
|
if (isLivePairAuto(holder)) return false;
|
|
18049
|
-
|
|
18438
|
+
fs40.writeFileSync(lockPath, String(process.pid));
|
|
18050
18439
|
}
|
|
18051
18440
|
process.once("exit", () => {
|
|
18052
18441
|
try {
|
|
18053
|
-
if (
|
|
18054
|
-
|
|
18442
|
+
if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
18443
|
+
fs40.unlinkSync(lockPath);
|
|
18055
18444
|
}
|
|
18056
18445
|
} catch {
|
|
18057
18446
|
}
|
|
@@ -18133,7 +18522,7 @@ async function pairAuto(args2) {
|
|
|
18133
18522
|
}
|
|
18134
18523
|
|
|
18135
18524
|
// src/services/headroom/wrap-launch.ts
|
|
18136
|
-
var
|
|
18525
|
+
var import_node_child_process14 = require("child_process");
|
|
18137
18526
|
function wrapWithHeadroom(launch, opts) {
|
|
18138
18527
|
if (!opts.enabled || !opts.headroomPresent) return launch;
|
|
18139
18528
|
return {
|
|
@@ -18146,7 +18535,7 @@ var _present;
|
|
|
18146
18535
|
function headroomPresent() {
|
|
18147
18536
|
if (_present !== void 0) return Promise.resolve(_present);
|
|
18148
18537
|
return new Promise((resolve7) => {
|
|
18149
|
-
(0,
|
|
18538
|
+
(0, import_node_child_process14.execFile)("headroom", ["--version"], (err) => {
|
|
18150
18539
|
_present = !err;
|
|
18151
18540
|
resolve7(_present);
|
|
18152
18541
|
});
|
|
@@ -18496,19 +18885,19 @@ var AgentService = class _AgentService {
|
|
|
18496
18885
|
};
|
|
18497
18886
|
|
|
18498
18887
|
// src/agents/acp/adapters.ts
|
|
18499
|
-
var
|
|
18888
|
+
var path47 = __toESM(require("path"));
|
|
18500
18889
|
var require_ = require;
|
|
18501
18890
|
function resolveBin(pkgName, binName) {
|
|
18502
18891
|
try {
|
|
18503
18892
|
const manifestPath = require_.resolve(`${pkgName}/package.json`);
|
|
18504
18893
|
const manifest = require_(`${pkgName}/package.json`);
|
|
18505
|
-
const pkgDir =
|
|
18894
|
+
const pkgDir = path47.dirname(manifestPath);
|
|
18506
18895
|
const bin = manifest.bin;
|
|
18507
18896
|
if (!bin) return null;
|
|
18508
|
-
if (typeof bin === "string") return
|
|
18897
|
+
if (typeof bin === "string") return path47.resolve(pkgDir, bin);
|
|
18509
18898
|
const target = binName ?? Object.keys(bin)[0];
|
|
18510
18899
|
if (!target || !bin[target]) return null;
|
|
18511
|
-
return
|
|
18900
|
+
return path47.resolve(pkgDir, bin[target]);
|
|
18512
18901
|
} catch {
|
|
18513
18902
|
return null;
|
|
18514
18903
|
}
|
|
@@ -18584,11 +18973,11 @@ function requiresAcp(agent) {
|
|
|
18584
18973
|
var import_node_crypto7 = require("crypto");
|
|
18585
18974
|
|
|
18586
18975
|
// src/agents/acp/client.ts
|
|
18587
|
-
var
|
|
18588
|
-
var
|
|
18976
|
+
var import_node_child_process15 = require("child_process");
|
|
18977
|
+
var fs41 = __toESM(require("fs/promises"));
|
|
18589
18978
|
var fsSync = __toESM(require("fs"));
|
|
18590
|
-
var
|
|
18591
|
-
var
|
|
18979
|
+
var os34 = __toESM(require("os"));
|
|
18980
|
+
var path48 = __toESM(require("path"));
|
|
18592
18981
|
var import_node_stream = require("stream");
|
|
18593
18982
|
|
|
18594
18983
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -21125,7 +21514,7 @@ var AcpClient = class {
|
|
|
21125
21514
|
"acpClient",
|
|
21126
21515
|
`spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
|
|
21127
21516
|
);
|
|
21128
|
-
const child = (0,
|
|
21517
|
+
const child = (0, import_node_child_process15.spawn)(adapter.command, adapter.args, {
|
|
21129
21518
|
cwd,
|
|
21130
21519
|
env: { ...process.env, PATH: augmentedPath },
|
|
21131
21520
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -21375,7 +21764,7 @@ var AcpClient = class {
|
|
|
21375
21764
|
},
|
|
21376
21765
|
readTextFile: async (params) => {
|
|
21377
21766
|
try {
|
|
21378
|
-
const content = await
|
|
21767
|
+
const content = await fs41.readFile(params.path, "utf8");
|
|
21379
21768
|
return applyLineRange(content, params.line ?? null, params.limit ?? null);
|
|
21380
21769
|
} catch (err) {
|
|
21381
21770
|
const code = err.code;
|
|
@@ -21395,7 +21784,7 @@ var AcpClient = class {
|
|
|
21395
21784
|
},
|
|
21396
21785
|
writeTextFile: async (params) => {
|
|
21397
21786
|
try {
|
|
21398
|
-
await
|
|
21787
|
+
await fs41.writeFile(params.path, params.content, "utf8");
|
|
21399
21788
|
return {};
|
|
21400
21789
|
} catch (err) {
|
|
21401
21790
|
const code = err.code;
|
|
@@ -21444,25 +21833,25 @@ function applyLineRange(content, line, limit) {
|
|
|
21444
21833
|
return { content: lines.slice(start2, end).join("\n") };
|
|
21445
21834
|
}
|
|
21446
21835
|
function knownAgentBinaryDirs() {
|
|
21447
|
-
const home =
|
|
21836
|
+
const home = os34.homedir();
|
|
21448
21837
|
const out2 = [];
|
|
21449
21838
|
out2.push("/tmp/codeam-node20/bin");
|
|
21450
21839
|
for (const root of [
|
|
21451
21840
|
"/usr/local/share/nvm/versions/node",
|
|
21452
|
-
|
|
21841
|
+
path48.join(home, ".nvm/versions/node")
|
|
21453
21842
|
]) {
|
|
21454
21843
|
try {
|
|
21455
21844
|
for (const child of fsSync.readdirSync(root)) {
|
|
21456
|
-
out2.push(
|
|
21845
|
+
out2.push(path48.join(root, child, "bin"));
|
|
21457
21846
|
}
|
|
21458
21847
|
} catch {
|
|
21459
21848
|
}
|
|
21460
21849
|
}
|
|
21461
|
-
out2.push(
|
|
21850
|
+
out2.push(path48.join(home, ".volta/bin"));
|
|
21462
21851
|
out2.push("/usr/local/bin");
|
|
21463
21852
|
out2.push("/usr/bin");
|
|
21464
|
-
out2.push(
|
|
21465
|
-
out2.push(
|
|
21853
|
+
out2.push(path48.join(home, ".local/bin"));
|
|
21854
|
+
out2.push(path48.join(home, "bin"));
|
|
21466
21855
|
return out2.filter((p2) => {
|
|
21467
21856
|
try {
|
|
21468
21857
|
return fsSync.statSync(p2).isDirectory();
|
|
@@ -21473,7 +21862,7 @@ function knownAgentBinaryDirs() {
|
|
|
21473
21862
|
}
|
|
21474
21863
|
function expandPathForAgentBinaries(existingPath) {
|
|
21475
21864
|
const existing = new Set(
|
|
21476
|
-
existingPath.split(
|
|
21865
|
+
existingPath.split(path48.delimiter).filter((p2) => p2.length > 0)
|
|
21477
21866
|
);
|
|
21478
21867
|
const additions = [];
|
|
21479
21868
|
for (const dir of knownAgentBinaryDirs()) {
|
|
@@ -21483,12 +21872,12 @@ function expandPathForAgentBinaries(existingPath) {
|
|
|
21483
21872
|
}
|
|
21484
21873
|
}
|
|
21485
21874
|
if (additions.length === 0) return existingPath;
|
|
21486
|
-
return [...additions, existingPath].filter((p2) => p2.length > 0).join(
|
|
21875
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path48.delimiter);
|
|
21487
21876
|
}
|
|
21488
21877
|
|
|
21489
21878
|
// src/services/streaming/transport.ts
|
|
21490
21879
|
var http6 = __toESM(require("http"));
|
|
21491
|
-
var
|
|
21880
|
+
var https7 = __toESM(require("https"));
|
|
21492
21881
|
var _transport4 = {
|
|
21493
21882
|
post: _post3,
|
|
21494
21883
|
get: _get
|
|
@@ -21497,7 +21886,7 @@ function _post3(url, headers, payload) {
|
|
|
21497
21886
|
return new Promise((resolve7, reject) => {
|
|
21498
21887
|
let settled = false;
|
|
21499
21888
|
const u2 = new URL(url);
|
|
21500
|
-
const lib = u2.protocol === "https:" ?
|
|
21889
|
+
const lib = u2.protocol === "https:" ? https7 : http6;
|
|
21501
21890
|
const req = lib.request(
|
|
21502
21891
|
{
|
|
21503
21892
|
hostname: u2.hostname,
|
|
@@ -21539,7 +21928,7 @@ function _get(url, headers) {
|
|
|
21539
21928
|
return new Promise((resolve7, reject) => {
|
|
21540
21929
|
let settled = false;
|
|
21541
21930
|
const u2 = new URL(url);
|
|
21542
|
-
const lib = u2.protocol === "https:" ?
|
|
21931
|
+
const lib = u2.protocol === "https:" ? https7 : http6;
|
|
21543
21932
|
const req = lib.request(
|
|
21544
21933
|
{
|
|
21545
21934
|
hostname: u2.hostname,
|
|
@@ -21810,15 +22199,15 @@ function reconcileCumulative(existing, incoming) {
|
|
|
21810
22199
|
}
|
|
21811
22200
|
|
|
21812
22201
|
// src/agents/acp/onboarding.ts
|
|
21813
|
-
var
|
|
21814
|
-
var
|
|
21815
|
-
var
|
|
22202
|
+
var fs42 = __toESM(require("fs"));
|
|
22203
|
+
var os35 = __toESM(require("os"));
|
|
22204
|
+
var path49 = __toESM(require("path"));
|
|
21816
22205
|
var _onboardingSeam = {
|
|
21817
|
-
markerPath: (sessionId) =>
|
|
21818
|
-
exists: (p2) =>
|
|
22206
|
+
markerPath: (sessionId) => path49.join(os35.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
|
|
22207
|
+
exists: (p2) => fs42.existsSync(p2),
|
|
21819
22208
|
write: (p2) => {
|
|
21820
|
-
|
|
21821
|
-
|
|
22209
|
+
fs42.mkdirSync(path49.dirname(p2), { recursive: true });
|
|
22210
|
+
fs42.writeFileSync(p2, "");
|
|
21822
22211
|
},
|
|
21823
22212
|
disabled: () => {
|
|
21824
22213
|
const v = process.env.CODEAM_ONBOARDING_DISABLED;
|
|
@@ -21826,7 +22215,7 @@ var _onboardingSeam = {
|
|
|
21826
22215
|
}
|
|
21827
22216
|
};
|
|
21828
22217
|
function buildOnboardingWelcome(cwd) {
|
|
21829
|
-
const repo =
|
|
22218
|
+
const repo = path49.basename(cwd || "") || "this project";
|
|
21830
22219
|
return [
|
|
21831
22220
|
`Welcome to CodeAgent Mobile! \u{1F44B} You're now driving this agent from your phone \u2014 and it comes fully wired, zero setup:`,
|
|
21832
22221
|
"",
|
|
@@ -22086,8 +22475,8 @@ var import_crypto5 = require("crypto");
|
|
|
22086
22475
|
|
|
22087
22476
|
// src/services/turn-files/git-changeset.ts
|
|
22088
22477
|
var import_child_process22 = require("child_process");
|
|
22089
|
-
var
|
|
22090
|
-
var
|
|
22478
|
+
var fs43 = __toESM(require("fs/promises"));
|
|
22479
|
+
var path50 = __toESM(require("path"));
|
|
22091
22480
|
async function collectRepoChangeset(opts) {
|
|
22092
22481
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
22093
22482
|
if (status2 === null) return null;
|
|
@@ -22105,7 +22494,7 @@ async function collectRepoChangeset(opts) {
|
|
|
22105
22494
|
let stats;
|
|
22106
22495
|
if (row.fileStatus === "added" && numstatEntry === void 0) {
|
|
22107
22496
|
const lineCount = await readUntrackedLineCount(
|
|
22108
|
-
|
|
22497
|
+
path50.join(opts.repoRoot, row.filePath)
|
|
22109
22498
|
);
|
|
22110
22499
|
stats = { added: lineCount, removed: 0 };
|
|
22111
22500
|
} else {
|
|
@@ -22136,7 +22525,7 @@ function readUntrackedLineCount(absPath) {
|
|
|
22136
22525
|
}
|
|
22137
22526
|
async function defaultReadUntrackedLineCount(absPath) {
|
|
22138
22527
|
try {
|
|
22139
|
-
const content = await
|
|
22528
|
+
const content = await fs43.readFile(absPath, "utf8");
|
|
22140
22529
|
let count = 0;
|
|
22141
22530
|
let pos = -1;
|
|
22142
22531
|
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
|
|
@@ -22228,7 +22617,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
22228
22617
|
});
|
|
22229
22618
|
}
|
|
22230
22619
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
22231
|
-
const
|
|
22620
|
+
const fs48 = await import("fs/promises");
|
|
22232
22621
|
const out2 = [];
|
|
22233
22622
|
await walk(workingDir, 0);
|
|
22234
22623
|
return out2;
|
|
@@ -22236,7 +22625,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22236
22625
|
if (depth > maxDepth) return;
|
|
22237
22626
|
let entries = [];
|
|
22238
22627
|
try {
|
|
22239
|
-
const dirents = await
|
|
22628
|
+
const dirents = await fs48.readdir(dir, { withFileTypes: true });
|
|
22240
22629
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
22241
22630
|
} catch {
|
|
22242
22631
|
return;
|
|
@@ -22247,8 +22636,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22247
22636
|
if (hasGit) {
|
|
22248
22637
|
out2.push({
|
|
22249
22638
|
repoRoot: dir,
|
|
22250
|
-
repoPath:
|
|
22251
|
-
repoName:
|
|
22639
|
+
repoPath: path50.relative(workingDir, dir),
|
|
22640
|
+
repoName: path50.basename(dir)
|
|
22252
22641
|
});
|
|
22253
22642
|
return;
|
|
22254
22643
|
}
|
|
@@ -22256,14 +22645,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22256
22645
|
if (!entry.isDirectory) continue;
|
|
22257
22646
|
if (entry.name === "node_modules") continue;
|
|
22258
22647
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
22259
|
-
await walk(
|
|
22648
|
+
await walk(path50.join(dir, entry.name), depth + 1);
|
|
22260
22649
|
}
|
|
22261
22650
|
}
|
|
22262
22651
|
}
|
|
22263
22652
|
|
|
22264
22653
|
// src/services/turn-files/files-outbox.ts
|
|
22265
|
-
var
|
|
22266
|
-
var
|
|
22654
|
+
var fs44 = __toESM(require("fs/promises"));
|
|
22655
|
+
var path51 = __toESM(require("path"));
|
|
22267
22656
|
var import_os7 = require("os");
|
|
22268
22657
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
22269
22658
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -22296,16 +22685,16 @@ var FilesOutbox = class {
|
|
|
22296
22685
|
backoffIndex = 0;
|
|
22297
22686
|
stopped = false;
|
|
22298
22687
|
constructor(opts) {
|
|
22299
|
-
const base = opts.baseDir ??
|
|
22300
|
-
this.filePath =
|
|
22688
|
+
const base = opts.baseDir ?? path51.join(homeDir(), HOME_OUTBOX_DIR);
|
|
22689
|
+
this.filePath = path51.join(base, `${opts.sessionId}.jsonl`);
|
|
22301
22690
|
this.post = opts.post;
|
|
22302
22691
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
22303
22692
|
}
|
|
22304
22693
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
22305
22694
|
* line is durable on disk (not once the POST succeeds). */
|
|
22306
22695
|
async enqueue(entry) {
|
|
22307
|
-
await
|
|
22308
|
-
await
|
|
22696
|
+
await fs44.mkdir(path51.dirname(this.filePath), { recursive: true });
|
|
22697
|
+
await fs44.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
22309
22698
|
this.backoffIndex = 0;
|
|
22310
22699
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
22311
22700
|
}
|
|
@@ -22394,7 +22783,7 @@ var FilesOutbox = class {
|
|
|
22394
22783
|
async readAll() {
|
|
22395
22784
|
let raw = "";
|
|
22396
22785
|
try {
|
|
22397
|
-
raw = await
|
|
22786
|
+
raw = await fs44.readFile(this.filePath, "utf8");
|
|
22398
22787
|
} catch {
|
|
22399
22788
|
return [];
|
|
22400
22789
|
}
|
|
@@ -22418,12 +22807,12 @@ var FilesOutbox = class {
|
|
|
22418
22807
|
async rewrite(entries) {
|
|
22419
22808
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
22420
22809
|
if (entries.length === 0) {
|
|
22421
|
-
await
|
|
22810
|
+
await fs44.unlink(this.filePath).catch(() => void 0);
|
|
22422
22811
|
return;
|
|
22423
22812
|
}
|
|
22424
22813
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
22425
|
-
await
|
|
22426
|
-
await
|
|
22814
|
+
await fs44.writeFile(tmpPath, payload, "utf8");
|
|
22815
|
+
await fs44.rename(tmpPath, this.filePath);
|
|
22427
22816
|
}
|
|
22428
22817
|
};
|
|
22429
22818
|
function applyJitter(ms) {
|
|
@@ -24154,10 +24543,10 @@ var OutputService = class _OutputService {
|
|
|
24154
24543
|
};
|
|
24155
24544
|
|
|
24156
24545
|
// src/services/history.service.ts
|
|
24157
|
-
var
|
|
24158
|
-
var
|
|
24159
|
-
var
|
|
24160
|
-
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"));
|
|
24161
24550
|
var http7 = __toESM(require("http"));
|
|
24162
24551
|
var import_zod2 = require("zod");
|
|
24163
24552
|
var historyRecordSchema = import_zod2.z.object({
|
|
@@ -24183,7 +24572,7 @@ function parseJsonl(filePath) {
|
|
|
24183
24572
|
const messages = [];
|
|
24184
24573
|
let raw;
|
|
24185
24574
|
try {
|
|
24186
|
-
raw =
|
|
24575
|
+
raw = fs45.readFileSync(filePath, "utf8");
|
|
24187
24576
|
} catch (err) {
|
|
24188
24577
|
if (err.code !== "ENOENT") {
|
|
24189
24578
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -24223,7 +24612,7 @@ function post(endpoint, body, pluginAuthToken) {
|
|
|
24223
24612
|
return new Promise((resolve7) => {
|
|
24224
24613
|
const payload = JSON.stringify(body);
|
|
24225
24614
|
const u2 = new URL(`${API_BASE9}${endpoint}`);
|
|
24226
|
-
const transport = u2.protocol === "https:" ?
|
|
24615
|
+
const transport = u2.protocol === "https:" ? https8 : http7;
|
|
24227
24616
|
const req = transport.request(
|
|
24228
24617
|
{
|
|
24229
24618
|
hostname: u2.hostname,
|
|
@@ -24324,7 +24713,7 @@ var HistoryService = class _HistoryService {
|
|
|
24324
24713
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
24325
24714
|
}
|
|
24326
24715
|
get projectDir() {
|
|
24327
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
24716
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path52.join(os36.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
24328
24717
|
}
|
|
24329
24718
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
24330
24719
|
setCurrentConversationId(id) {
|
|
@@ -24336,7 +24725,7 @@ var HistoryService = class _HistoryService {
|
|
|
24336
24725
|
/** Return the current message count in the active conversation. */
|
|
24337
24726
|
getCurrentMessageCount() {
|
|
24338
24727
|
if (!this.currentConversationId) return 0;
|
|
24339
|
-
const filePath =
|
|
24728
|
+
const filePath = path52.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
24340
24729
|
return parseJsonl(filePath).length;
|
|
24341
24730
|
}
|
|
24342
24731
|
/**
|
|
@@ -24347,7 +24736,7 @@ var HistoryService = class _HistoryService {
|
|
|
24347
24736
|
const deadline = Date.now() + timeoutMs;
|
|
24348
24737
|
while (Date.now() < deadline) {
|
|
24349
24738
|
if (!this.currentConversationId) return null;
|
|
24350
|
-
const filePath =
|
|
24739
|
+
const filePath = path52.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
24351
24740
|
const messages = parseJsonl(filePath);
|
|
24352
24741
|
if (messages.length > previousCount) {
|
|
24353
24742
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -24373,16 +24762,16 @@ var HistoryService = class _HistoryService {
|
|
|
24373
24762
|
const dir = this.projectDir;
|
|
24374
24763
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
24375
24764
|
try {
|
|
24376
|
-
const files =
|
|
24765
|
+
const files = fs45.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
24377
24766
|
try {
|
|
24378
|
-
const stat3 =
|
|
24767
|
+
const stat3 = fs45.statSync(path52.join(dir, e.name));
|
|
24379
24768
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
24380
24769
|
} catch {
|
|
24381
24770
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
24382
24771
|
}
|
|
24383
24772
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
24384
24773
|
if (files.length > 0) {
|
|
24385
|
-
this.currentConversationId =
|
|
24774
|
+
this.currentConversationId = path52.basename(files[0].name, ".jsonl");
|
|
24386
24775
|
}
|
|
24387
24776
|
} catch {
|
|
24388
24777
|
}
|
|
@@ -24416,13 +24805,13 @@ var HistoryService = class _HistoryService {
|
|
|
24416
24805
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
24417
24806
|
let entries;
|
|
24418
24807
|
try {
|
|
24419
|
-
entries =
|
|
24808
|
+
entries = fs45.readdirSync(dir, { withFileTypes: true });
|
|
24420
24809
|
} catch {
|
|
24421
24810
|
return null;
|
|
24422
24811
|
}
|
|
24423
24812
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
24424
24813
|
try {
|
|
24425
|
-
const stat3 =
|
|
24814
|
+
const stat3 = fs45.statSync(path52.join(dir, e.name));
|
|
24426
24815
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
24427
24816
|
} catch {
|
|
24428
24817
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -24431,12 +24820,12 @@ var HistoryService = class _HistoryService {
|
|
|
24431
24820
|
if (files.length === 0) return null;
|
|
24432
24821
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
24433
24822
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
24434
|
-
return this.extractUsageFromFile(
|
|
24823
|
+
return this.extractUsageFromFile(path52.join(dir, targetFile));
|
|
24435
24824
|
}
|
|
24436
24825
|
extractUsageFromFile(filePath) {
|
|
24437
24826
|
let raw;
|
|
24438
24827
|
try {
|
|
24439
|
-
raw =
|
|
24828
|
+
raw = fs45.readFileSync(filePath, "utf8");
|
|
24440
24829
|
} catch {
|
|
24441
24830
|
return null;
|
|
24442
24831
|
}
|
|
@@ -24481,9 +24870,9 @@ var HistoryService = class _HistoryService {
|
|
|
24481
24870
|
let totalCost = 0;
|
|
24482
24871
|
let files;
|
|
24483
24872
|
try {
|
|
24484
|
-
files =
|
|
24873
|
+
files = fs45.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
24485
24874
|
try {
|
|
24486
|
-
return
|
|
24875
|
+
return fs45.statSync(path52.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
24487
24876
|
} catch {
|
|
24488
24877
|
return false;
|
|
24489
24878
|
}
|
|
@@ -24494,7 +24883,7 @@ var HistoryService = class _HistoryService {
|
|
|
24494
24883
|
for (const file of files) {
|
|
24495
24884
|
let raw;
|
|
24496
24885
|
try {
|
|
24497
|
-
raw =
|
|
24886
|
+
raw = fs45.readFileSync(path52.join(projectDir, file), "utf8");
|
|
24498
24887
|
} catch {
|
|
24499
24888
|
continue;
|
|
24500
24889
|
}
|
|
@@ -24562,7 +24951,7 @@ var HistoryService = class _HistoryService {
|
|
|
24562
24951
|
* showing an empty conversation.
|
|
24563
24952
|
*/
|
|
24564
24953
|
async loadConversation(sessionId) {
|
|
24565
|
-
const filePath =
|
|
24954
|
+
const filePath = path52.join(this.projectDir, `${sessionId}.jsonl`);
|
|
24566
24955
|
const messages = parseJsonl(filePath);
|
|
24567
24956
|
if (messages.length === 0) return;
|
|
24568
24957
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -24616,7 +25005,7 @@ var HistoryService = class _HistoryService {
|
|
|
24616
25005
|
if (!this.currentConversationId) return 0;
|
|
24617
25006
|
}
|
|
24618
25007
|
const sessionId = this.currentConversationId;
|
|
24619
|
-
const filePath =
|
|
25008
|
+
const filePath = path52.join(this.projectDir, `${sessionId}.jsonl`);
|
|
24620
25009
|
const messages = parseJsonl(filePath);
|
|
24621
25010
|
if (messages.length === 0) return 0;
|
|
24622
25011
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -25042,15 +25431,15 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
25042
25431
|
}
|
|
25043
25432
|
|
|
25044
25433
|
// src/agents/claude/onboarding.ts
|
|
25045
|
-
var
|
|
25046
|
-
var
|
|
25047
|
-
var
|
|
25434
|
+
var fs46 = __toESM(require("fs"));
|
|
25435
|
+
var os37 = __toESM(require("os"));
|
|
25436
|
+
var path53 = __toESM(require("path"));
|
|
25048
25437
|
function ensureClaudeOnboarded() {
|
|
25049
25438
|
try {
|
|
25050
|
-
const file =
|
|
25439
|
+
const file = path53.join(os37.homedir(), ".claude.json");
|
|
25051
25440
|
let config = {};
|
|
25052
25441
|
try {
|
|
25053
|
-
config = JSON.parse(
|
|
25442
|
+
config = JSON.parse(fs46.readFileSync(file, "utf8"));
|
|
25054
25443
|
} catch {
|
|
25055
25444
|
}
|
|
25056
25445
|
if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
|
|
@@ -25061,8 +25450,8 @@ function ensureClaudeOnboarded() {
|
|
|
25061
25450
|
if (typeof config.lastOnboardingVersion !== "string") {
|
|
25062
25451
|
config.lastOnboardingVersion = "2.1.177";
|
|
25063
25452
|
}
|
|
25064
|
-
|
|
25065
|
-
|
|
25453
|
+
fs46.mkdirSync(path53.dirname(file), { recursive: true });
|
|
25454
|
+
fs46.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
25066
25455
|
log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
|
|
25067
25456
|
} catch (err) {
|
|
25068
25457
|
log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
|
|
@@ -25076,27 +25465,27 @@ async function start(requestedAgent) {
|
|
|
25076
25465
|
if (!session) {
|
|
25077
25466
|
if (requestedAgent) {
|
|
25078
25467
|
const displayName = AGENT_REGISTRY[requestedAgent]?.displayName ?? requestedAgent;
|
|
25079
|
-
console.log(` ${
|
|
25468
|
+
console.log(` ${import_picocolors4.default.dim(`No paired ${displayName} session found.`)}`);
|
|
25080
25469
|
console.log(
|
|
25081
|
-
` ${
|
|
25470
|
+
` ${import_picocolors4.default.dim(`Run ${import_picocolors4.default.white("codeam pair")} from a ${displayName} setup to connect your mobile app.`)}
|
|
25082
25471
|
`
|
|
25083
25472
|
);
|
|
25084
25473
|
} else {
|
|
25085
|
-
console.log(` ${
|
|
25086
|
-
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.`)}
|
|
25087
25476
|
`);
|
|
25088
25477
|
}
|
|
25089
25478
|
process.exit(0);
|
|
25090
25479
|
}
|
|
25091
25480
|
if (!acquireDaemonLock(session.id)) {
|
|
25092
|
-
console.log(` ${
|
|
25481
|
+
console.log(` ${import_picocolors4.default.dim("A codeam daemon for this session is already running \u2014 deferring to it.")}`);
|
|
25093
25482
|
process.exit(0);
|
|
25094
25483
|
}
|
|
25095
25484
|
if (!session.agent) {
|
|
25096
25485
|
throw new Error("Active session has no agent \u2014 re-pair with `codeam pair`.");
|
|
25097
25486
|
}
|
|
25098
25487
|
const pluginId = session.pluginId ?? ensurePluginId();
|
|
25099
|
-
showInfo(`${session.userName} \xB7 ${
|
|
25488
|
+
showInfo(`${session.userName} \xB7 ${import_picocolors4.default.cyan(session.plan)}`);
|
|
25100
25489
|
showInfo(`Launching ${AGENT_REGISTRY[session.agent].displayName}...
|
|
25101
25490
|
`);
|
|
25102
25491
|
identifyUser({
|
|
@@ -25370,7 +25759,7 @@ async function start(requestedAgent) {
|
|
|
25370
25759
|
|
|
25371
25760
|
// src/commands/pair.ts
|
|
25372
25761
|
var import_crypto7 = require("crypto");
|
|
25373
|
-
var
|
|
25762
|
+
var import_picocolors5 = __toESM(require("picocolors"));
|
|
25374
25763
|
|
|
25375
25764
|
// src/utils/agent-prompt.ts
|
|
25376
25765
|
function parseAgentFlag(args2) {
|
|
@@ -25451,7 +25840,7 @@ async function pair(args2 = []) {
|
|
|
25451
25840
|
process.exit(0);
|
|
25452
25841
|
}
|
|
25453
25842
|
showPairingCode(result.code);
|
|
25454
|
-
console.log(
|
|
25843
|
+
console.log(import_picocolors5.default.dim(" Scan the QR code or enter the code in CodeAgent Mobile."));
|
|
25455
25844
|
console.log("");
|
|
25456
25845
|
const waitSpin = dist_exports.spinner();
|
|
25457
25846
|
const waitMessage = () => `Waiting for mobile app... \xB7 expires in ${formatRemaining(result.expiresAt)}`;
|
|
@@ -25566,7 +25955,7 @@ async function autoLinkAfterPair(opts) {
|
|
|
25566
25955
|
}
|
|
25567
25956
|
|
|
25568
25957
|
// src/commands/sessions.ts
|
|
25569
|
-
var
|
|
25958
|
+
var import_picocolors6 = __toESM(require("picocolors"));
|
|
25570
25959
|
async function sessions2(args2) {
|
|
25571
25960
|
const [sub, id] = args2;
|
|
25572
25961
|
if (sub === "switch") return switchSession();
|
|
@@ -25583,18 +25972,18 @@ function listSessions() {
|
|
|
25583
25972
|
showIntro();
|
|
25584
25973
|
const config = getConfig();
|
|
25585
25974
|
if (config.sessions.length === 0) {
|
|
25586
|
-
console.log(
|
|
25975
|
+
console.log(import_picocolors6.default.dim(" No paired sessions. Run codeam pair to connect.\n"));
|
|
25587
25976
|
return;
|
|
25588
25977
|
}
|
|
25589
|
-
console.log(
|
|
25978
|
+
console.log(import_picocolors6.default.bold(" Paired sessions:\n"));
|
|
25590
25979
|
for (const s of config.sessions) {
|
|
25591
25980
|
const isActive = s.id === config.activeSessionId;
|
|
25592
|
-
const bullet = isActive ?
|
|
25593
|
-
const name = isActive ?
|
|
25594
|
-
const plan =
|
|
25595
|
-
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());
|
|
25596
25985
|
console.log(`${bullet} ${name} ${plan} ${date}`);
|
|
25597
|
-
console.log(
|
|
25986
|
+
console.log(import_picocolors6.default.dim(` ${s.id}`));
|
|
25598
25987
|
}
|
|
25599
25988
|
console.log("");
|
|
25600
25989
|
}
|
|
@@ -25612,7 +26001,7 @@ async function switchSession() {
|
|
|
25612
26001
|
}
|
|
25613
26002
|
setActiveSession(chosen);
|
|
25614
26003
|
const s = config.sessions.find((x) => x.id === chosen);
|
|
25615
|
-
console.log(
|
|
26004
|
+
console.log(import_picocolors6.default.green(`
|
|
25616
26005
|
\u2713 Switched to ${s?.userName ?? chosen}
|
|
25617
26006
|
`));
|
|
25618
26007
|
}
|
|
@@ -25630,29 +26019,29 @@ async function deleteSession(id) {
|
|
|
25630
26019
|
return;
|
|
25631
26020
|
}
|
|
25632
26021
|
removeSession(id);
|
|
25633
|
-
console.log(
|
|
26022
|
+
console.log(import_picocolors6.default.green("\n \u2713 Session deleted\n"));
|
|
25634
26023
|
}
|
|
25635
26024
|
|
|
25636
26025
|
// src/commands/status.ts
|
|
25637
|
-
var
|
|
26026
|
+
var import_picocolors7 = __toESM(require("picocolors"));
|
|
25638
26027
|
function status() {
|
|
25639
26028
|
showIntro();
|
|
25640
26029
|
const config = getConfig();
|
|
25641
26030
|
const active = config.sessions.find((s) => s.id === config.activeSessionId) ?? null;
|
|
25642
|
-
console.log(
|
|
25643
|
-
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")}`);
|
|
25644
26033
|
console.log(` Sessions ${config.sessions.length} paired`);
|
|
25645
26034
|
if (active) {
|
|
25646
|
-
console.log(` Active ${
|
|
25647
|
-
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)}`);
|
|
25648
26037
|
} else {
|
|
25649
|
-
console.log(` Active ${
|
|
26038
|
+
console.log(` Active ${import_picocolors7.default.yellow("none")} ${import_picocolors7.default.dim("run codeam pair to connect")}`);
|
|
25650
26039
|
}
|
|
25651
26040
|
console.log("");
|
|
25652
26041
|
}
|
|
25653
26042
|
|
|
25654
26043
|
// src/commands/logout.ts
|
|
25655
|
-
var
|
|
26044
|
+
var import_picocolors8 = __toESM(require("picocolors"));
|
|
25656
26045
|
var API_BASE11 = resolveApiBaseUrl();
|
|
25657
26046
|
async function notifyBackendOffline() {
|
|
25658
26047
|
const cfg = loadCliConfig();
|
|
@@ -25686,17 +26075,17 @@ async function logout() {
|
|
|
25686
26075
|
}
|
|
25687
26076
|
await notifyBackendOffline();
|
|
25688
26077
|
clearAll();
|
|
25689
|
-
console.log(
|
|
26078
|
+
console.log(import_picocolors8.default.green("\n \u2713 Done. All sessions removed.\n"));
|
|
25690
26079
|
}
|
|
25691
26080
|
|
|
25692
26081
|
// src/commands/deploy.ts
|
|
25693
|
-
var
|
|
26082
|
+
var import_picocolors11 = __toESM(require("picocolors"));
|
|
25694
26083
|
|
|
25695
26084
|
// src/services/providers/github-codespaces.ts
|
|
25696
26085
|
var import_child_process23 = require("child_process");
|
|
25697
26086
|
var import_util4 = require("util");
|
|
25698
|
-
var
|
|
25699
|
-
var
|
|
26087
|
+
var import_picocolors9 = __toESM(require("picocolors"));
|
|
26088
|
+
var path54 = __toESM(require("path"));
|
|
25700
26089
|
var execFileP6 = (0, import_util4.promisify)(import_child_process23.execFile);
|
|
25701
26090
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
25702
26091
|
function resetStdinForChild() {
|
|
@@ -25763,7 +26152,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25763
26152
|
if (expectedUser) {
|
|
25764
26153
|
noteLines.push("");
|
|
25765
26154
|
noteLines.push(
|
|
25766
|
-
`${
|
|
26155
|
+
`${import_picocolors9.default.yellow("\u26A0")} Sign in as ${import_picocolors9.default.cyan(expectedUser)} in the browser.`
|
|
25767
26156
|
);
|
|
25768
26157
|
noteLines.push(
|
|
25769
26158
|
" If a different GitHub account is already signed in, sign out"
|
|
@@ -25786,7 +26175,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25786
26175
|
if (refreshCode !== 0) {
|
|
25787
26176
|
const lines = [
|
|
25788
26177
|
"The browser approval came back for a different GitHub account",
|
|
25789
|
-
`than the one gh is configured for${expectedUser ? ` (${
|
|
26178
|
+
`than the one gh is configured for${expectedUser ? ` (${import_picocolors9.default.cyan(expectedUser)})` : ""}.`,
|
|
25790
26179
|
"",
|
|
25791
26180
|
"To recover:",
|
|
25792
26181
|
" 1. Open https://github.com and sign out of any non-target",
|
|
@@ -25795,7 +26184,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25795
26184
|
"",
|
|
25796
26185
|
"You can also grant the scope manually first and skip this step",
|
|
25797
26186
|
"on the next run:",
|
|
25798
|
-
` ${
|
|
26187
|
+
` ${import_picocolors9.default.cyan("gh auth refresh -h github.com -s codespace")}`
|
|
25799
26188
|
];
|
|
25800
26189
|
throw new Error(lines.join("\n"));
|
|
25801
26190
|
}
|
|
@@ -25862,7 +26251,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25862
26251
|
async tryInstallGh() {
|
|
25863
26252
|
const platform3 = process.platform;
|
|
25864
26253
|
wt(
|
|
25865
|
-
`GitHub CLI (${
|
|
26254
|
+
`GitHub CLI (${import_picocolors9.default.cyan("gh")}) is required for Codespaces deploys but isn't on your PATH.`,
|
|
25866
26255
|
"Heads up"
|
|
25867
26256
|
);
|
|
25868
26257
|
if (platform3 === "linux") {
|
|
@@ -25918,7 +26307,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25918
26307
|
return;
|
|
25919
26308
|
}
|
|
25920
26309
|
const proceed = await ot2({
|
|
25921
|
-
message: `Run ${
|
|
26310
|
+
message: `Run ${import_picocolors9.default.cyan(installCmd.describe)} now?`,
|
|
25922
26311
|
initialValue: true
|
|
25923
26312
|
});
|
|
25924
26313
|
if (q(proceed) || !proceed) return;
|
|
@@ -26185,7 +26574,7 @@ var GitHubCodespacesProvider = class {
|
|
|
26185
26574
|
});
|
|
26186
26575
|
}
|
|
26187
26576
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26188
|
-
const remoteDir =
|
|
26577
|
+
const remoteDir = path54.posix.dirname(remotePath);
|
|
26189
26578
|
const parts = [
|
|
26190
26579
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
26191
26580
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -26255,8 +26644,8 @@ function shellQuote(s) {
|
|
|
26255
26644
|
// src/services/providers/gitpod.ts
|
|
26256
26645
|
var import_child_process24 = require("child_process");
|
|
26257
26646
|
var import_util5 = require("util");
|
|
26258
|
-
var
|
|
26259
|
-
var
|
|
26647
|
+
var path55 = __toESM(require("path"));
|
|
26648
|
+
var import_picocolors10 = __toESM(require("picocolors"));
|
|
26260
26649
|
var execFileP7 = (0, import_util5.promisify)(import_child_process24.execFile);
|
|
26261
26650
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
26262
26651
|
function resetStdinForChild2() {
|
|
@@ -26495,7 +26884,7 @@ var GitpodProvider = class {
|
|
|
26495
26884
|
});
|
|
26496
26885
|
}
|
|
26497
26886
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26498
|
-
const remoteDir =
|
|
26887
|
+
const remoteDir = path55.posix.dirname(remotePath);
|
|
26499
26888
|
const parts = [
|
|
26500
26889
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
26501
26890
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -26531,7 +26920,7 @@ function shellQuote2(s) {
|
|
|
26531
26920
|
// src/services/providers/gitlab-workspaces.ts
|
|
26532
26921
|
var import_child_process25 = require("child_process");
|
|
26533
26922
|
var import_util6 = require("util");
|
|
26534
|
-
var
|
|
26923
|
+
var path56 = __toESM(require("path"));
|
|
26535
26924
|
var execFileP8 = (0, import_util6.promisify)(import_child_process25.execFile);
|
|
26536
26925
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
26537
26926
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -26791,7 +27180,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
26791
27180
|
}
|
|
26792
27181
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26793
27182
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
26794
|
-
const remoteDir =
|
|
27183
|
+
const remoteDir = path56.posix.dirname(remotePath);
|
|
26795
27184
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
26796
27185
|
if (options.mode != null) {
|
|
26797
27186
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -26859,7 +27248,7 @@ function shellQuote3(s) {
|
|
|
26859
27248
|
// src/services/providers/railway.ts
|
|
26860
27249
|
var import_child_process26 = require("child_process");
|
|
26861
27250
|
var import_util7 = require("util");
|
|
26862
|
-
var
|
|
27251
|
+
var path57 = __toESM(require("path"));
|
|
26863
27252
|
var execFileP9 = (0, import_util7.promisify)(import_child_process26.execFile);
|
|
26864
27253
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
26865
27254
|
function resetStdinForChild4() {
|
|
@@ -27095,7 +27484,7 @@ var RailwayProvider = class {
|
|
|
27095
27484
|
if (!projectId || !serviceId) {
|
|
27096
27485
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
27097
27486
|
}
|
|
27098
|
-
const remoteDir =
|
|
27487
|
+
const remoteDir = path57.posix.dirname(remotePath);
|
|
27099
27488
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
27100
27489
|
if (options.mode != null) {
|
|
27101
27490
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -27136,7 +27525,7 @@ var PROVIDERS = [
|
|
|
27136
27525
|
// src/commands/deploy.ts
|
|
27137
27526
|
async function deploy(args2 = []) {
|
|
27138
27527
|
console.log();
|
|
27139
|
-
mt(
|
|
27528
|
+
mt(import_picocolors11.default.bgMagenta(import_picocolors11.default.white(" codeam deploy ")));
|
|
27140
27529
|
const provider = await pickProvider();
|
|
27141
27530
|
if (!provider) {
|
|
27142
27531
|
pt("No provider selected.");
|
|
@@ -27173,7 +27562,7 @@ async function deploy(args2 = []) {
|
|
|
27173
27562
|
if (provider.expandListScopes) {
|
|
27174
27563
|
options.push({
|
|
27175
27564
|
value: EXPAND_SCOPES,
|
|
27176
|
-
label:
|
|
27565
|
+
label: import_picocolors11.default.cyan("+ Don't see your project? Expand scopes\u2026"),
|
|
27177
27566
|
hint: "Re-authorize with broader scopes (org / team repos)"
|
|
27178
27567
|
});
|
|
27179
27568
|
}
|
|
@@ -27221,7 +27610,7 @@ async function deploy(args2 = []) {
|
|
|
27221
27610
|
label: w3.displayName ?? w3.id,
|
|
27222
27611
|
hint: [w3.state, formatLastUsed(w3.lastUsedAt)].filter(Boolean).join(" \xB7 ")
|
|
27223
27612
|
})),
|
|
27224
|
-
{ value: "__new__", label:
|
|
27613
|
+
{ value: "__new__", label: import_picocolors11.default.green("+ Create a new workspace"), hint: "fresh codespace" }
|
|
27225
27614
|
]
|
|
27226
27615
|
});
|
|
27227
27616
|
if (q(choice)) {
|
|
@@ -27322,12 +27711,12 @@ async function deploy(args2 = []) {
|
|
|
27322
27711
|
cliStep.stop("\u2713 codeam-cli installed");
|
|
27323
27712
|
wt(
|
|
27324
27713
|
[
|
|
27325
|
-
`Workspace: ${
|
|
27326
|
-
workspace.webUrl ? `Web: ${
|
|
27714
|
+
`Workspace: ${import_picocolors11.default.cyan(workspace.displayName ?? workspace.id)}`,
|
|
27715
|
+
workspace.webUrl ? `Web: ${import_picocolors11.default.cyan(workspace.webUrl)}` : "",
|
|
27327
27716
|
"",
|
|
27328
27717
|
`Starting \`codeam pair\` on the workspace (agent: ${AGENT_REGISTRY[agentId].displayName}).`,
|
|
27329
27718
|
"Scan the QR code from your phone to pair.",
|
|
27330
|
-
|
|
27719
|
+
import_picocolors11.default.dim("(Once paired, this terminal disconnects automatically; the session stays alive on the codespace.)")
|
|
27331
27720
|
].filter(Boolean).join("\n"),
|
|
27332
27721
|
"Almost there"
|
|
27333
27722
|
);
|
|
@@ -27442,11 +27831,11 @@ async function deploy(args2 = []) {
|
|
|
27442
27831
|
].join("\n");
|
|
27443
27832
|
const code = (await provider.streamCommand(workspace.id, `bash -lc ${shellQuoteSingle(wrapper)}`)).code;
|
|
27444
27833
|
if (code === 0) {
|
|
27445
|
-
gt(
|
|
27834
|
+
gt(import_picocolors11.default.green("\u2713 Workspace deployed and paired. Drive from your phone, anywhere."));
|
|
27446
27835
|
} else if (code === 130) {
|
|
27447
|
-
gt(
|
|
27836
|
+
gt(import_picocolors11.default.yellow("Disconnected from local terminal. Mobile session keeps running on the codespace."));
|
|
27448
27837
|
} else {
|
|
27449
|
-
gt(
|
|
27838
|
+
gt(import_picocolors11.default.yellow('Pairing did not complete. Run "codeam pair" inside the codespace if needed.'));
|
|
27450
27839
|
}
|
|
27451
27840
|
}
|
|
27452
27841
|
function shellQuoteSingle(s) {
|
|
@@ -27480,7 +27869,7 @@ async function pickProvider() {
|
|
|
27480
27869
|
message: "Where do you want to deploy?",
|
|
27481
27870
|
options: PROVIDERS.map((prov) => ({
|
|
27482
27871
|
value: prov.id,
|
|
27483
|
-
label: prov.available ? prov.displayName : `${prov.displayName} ${
|
|
27872
|
+
label: prov.available ? prov.displayName : `${prov.displayName} ${import_picocolors11.default.dim("(coming soon)")}`,
|
|
27484
27873
|
hint: prov.tagline
|
|
27485
27874
|
}))
|
|
27486
27875
|
});
|
|
@@ -27497,27 +27886,27 @@ async function pickProvider() {
|
|
|
27497
27886
|
}
|
|
27498
27887
|
|
|
27499
27888
|
// src/commands/deploy-manage.ts
|
|
27500
|
-
var
|
|
27889
|
+
var import_picocolors12 = __toESM(require("picocolors"));
|
|
27501
27890
|
async function deployList() {
|
|
27502
27891
|
console.log();
|
|
27503
|
-
mt(
|
|
27892
|
+
mt(import_picocolors12.default.bgMagenta(import_picocolors12.default.white(" codeam deploy ls ")));
|
|
27504
27893
|
const workspaces = await collectWorkspacesWithStatus();
|
|
27505
27894
|
if (workspaces.length === 0) {
|
|
27506
|
-
gt(
|
|
27895
|
+
gt(import_picocolors12.default.dim("No deployed workspaces found."));
|
|
27507
27896
|
return;
|
|
27508
27897
|
}
|
|
27509
27898
|
for (const w3 of workspaces) {
|
|
27510
|
-
const tag = w3.codeamRunning ?
|
|
27511
|
-
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 + ")")}`);
|
|
27512
27901
|
}
|
|
27513
|
-
gt(
|
|
27902
|
+
gt(import_picocolors12.default.dim("Use `codeam deploy stop` to terminate a session."));
|
|
27514
27903
|
}
|
|
27515
27904
|
async function deployStop() {
|
|
27516
27905
|
console.log();
|
|
27517
|
-
mt(
|
|
27906
|
+
mt(import_picocolors12.default.bgMagenta(import_picocolors12.default.white(" codeam deploy stop ")));
|
|
27518
27907
|
const workspaces = await collectWorkspacesWithStatus();
|
|
27519
27908
|
if (workspaces.length === 0) {
|
|
27520
|
-
gt(
|
|
27909
|
+
gt(import_picocolors12.default.dim("No deployed workspaces found."));
|
|
27521
27910
|
return;
|
|
27522
27911
|
}
|
|
27523
27912
|
const choice = await _t({
|
|
@@ -27527,7 +27916,7 @@ async function deployStop() {
|
|
|
27527
27916
|
label: w3.displayName ?? w3.id,
|
|
27528
27917
|
hint: [
|
|
27529
27918
|
w3.providerName,
|
|
27530
|
-
w3.codeamRunning ?
|
|
27919
|
+
w3.codeamRunning ? import_picocolors12.default.green("\u25CF codeam-pair running") : import_picocolors12.default.dim("\u25CB no codeam-pair"),
|
|
27531
27920
|
w3.state ?? ""
|
|
27532
27921
|
].filter(Boolean).join(" \xB7 ")
|
|
27533
27922
|
}))
|
|
@@ -27555,7 +27944,7 @@ async function deployStop() {
|
|
|
27555
27944
|
O2.info("No codeam-pair process to stop on this workspace.");
|
|
27556
27945
|
}
|
|
27557
27946
|
const alsoStop = await ot2({
|
|
27558
|
-
message: `Also stop the workspace ${
|
|
27947
|
+
message: `Also stop the workspace ${import_picocolors12.default.cyan(target.displayName ?? target.id)} to save compute hours?`,
|
|
27559
27948
|
initialValue: true
|
|
27560
27949
|
});
|
|
27561
27950
|
if (!q(alsoStop) && alsoStop) {
|
|
@@ -27577,7 +27966,7 @@ async function deployStop() {
|
|
|
27577
27966
|
O2.warn(err instanceof Error ? err.message : String(err));
|
|
27578
27967
|
}
|
|
27579
27968
|
}
|
|
27580
|
-
gt(
|
|
27969
|
+
gt(import_picocolors12.default.green("\u2713 Done."));
|
|
27581
27970
|
}
|
|
27582
27971
|
async function collectWorkspacesWithStatus() {
|
|
27583
27972
|
const out2 = [];
|
|
@@ -27683,9 +28072,9 @@ async function host(args2) {
|
|
|
27683
28072
|
var import_node_dns = require("dns");
|
|
27684
28073
|
var import_node_util5 = require("util");
|
|
27685
28074
|
var import_node_crypto8 = require("crypto");
|
|
27686
|
-
var
|
|
27687
|
-
var
|
|
27688
|
-
var
|
|
28075
|
+
var fs47 = __toESM(require("fs"));
|
|
28076
|
+
var path58 = __toESM(require("path"));
|
|
28077
|
+
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27689
28078
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
27690
28079
|
async function checkDns(apiBase2) {
|
|
27691
28080
|
const host2 = (() => {
|
|
@@ -27740,13 +28129,13 @@ async function checkHealth(apiBase2) {
|
|
|
27740
28129
|
}
|
|
27741
28130
|
}
|
|
27742
28131
|
function checkConfigDir() {
|
|
27743
|
-
const dir =
|
|
28132
|
+
const dir = path58.join(require("os").homedir(), ".codeam");
|
|
27744
28133
|
try {
|
|
27745
|
-
|
|
27746
|
-
const probe =
|
|
27747
|
-
|
|
27748
|
-
const read2 =
|
|
27749
|
-
|
|
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);
|
|
27750
28139
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
27751
28140
|
return {
|
|
27752
28141
|
id: "config-dir",
|
|
@@ -27810,7 +28199,7 @@ function checkNodePty() {
|
|
|
27810
28199
|
detail: "not required on this platform"
|
|
27811
28200
|
};
|
|
27812
28201
|
}
|
|
27813
|
-
const vendoredPath =
|
|
28202
|
+
const vendoredPath = path58.join(__dirname, "vendor", "node-pty");
|
|
27814
28203
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
27815
28204
|
try {
|
|
27816
28205
|
require(target);
|
|
@@ -27852,7 +28241,7 @@ function checkChokidar() {
|
|
|
27852
28241
|
}
|
|
27853
28242
|
async function doctor(args2 = []) {
|
|
27854
28243
|
const json = args2.includes("--json");
|
|
27855
|
-
const cliVersion = true ? "2.39.
|
|
28244
|
+
const cliVersion = true ? "2.39.55" : "0.0.0-dev";
|
|
27856
28245
|
const apiBase2 = resolveApiBaseUrl();
|
|
27857
28246
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
27858
28247
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27892,46 +28281,46 @@ async function doctor(args2 = []) {
|
|
|
27892
28281
|
function printHumanReport(r) {
|
|
27893
28282
|
const out2 = process.stderr;
|
|
27894
28283
|
out2.write(`
|
|
27895
|
-
${
|
|
28284
|
+
${import_picocolors13.default.bold(" codeam doctor")}
|
|
27896
28285
|
|
|
27897
28286
|
`);
|
|
27898
|
-
out2.write(` ${
|
|
28287
|
+
out2.write(` ${import_picocolors13.default.dim("cli")} ${r.cliVersion}
|
|
27899
28288
|
`);
|
|
27900
|
-
out2.write(` ${
|
|
28289
|
+
out2.write(` ${import_picocolors13.default.dim("node")} ${r.node}
|
|
27901
28290
|
`);
|
|
27902
|
-
out2.write(` ${
|
|
28291
|
+
out2.write(` ${import_picocolors13.default.dim("os")} ${r.platform} ${r.arch}
|
|
27903
28292
|
`);
|
|
27904
|
-
out2.write(` ${
|
|
28293
|
+
out2.write(` ${import_picocolors13.default.dim("api")} ${r.apiBase}
|
|
27905
28294
|
`);
|
|
27906
28295
|
if (process.env.CODEAM_TEST_MODE === "1" || process.env.CODEAM_TEST_MODE?.toLowerCase() === "true") {
|
|
27907
|
-
out2.write(` ${
|
|
28296
|
+
out2.write(` ${import_picocolors13.default.dim("mode")} ${import_picocolors13.default.yellow("TEST_MODE \u2014 using dev preview")}
|
|
27908
28297
|
`);
|
|
27909
28298
|
} else if (process.env.CODEAM_API_URL) {
|
|
27910
|
-
out2.write(` ${
|
|
28299
|
+
out2.write(` ${import_picocolors13.default.dim("mode")} ${import_picocolors13.default.yellow("CODEAM_API_URL override")}
|
|
27911
28300
|
`);
|
|
27912
28301
|
}
|
|
27913
|
-
out2.write(` ${
|
|
28302
|
+
out2.write(` ${import_picocolors13.default.dim("diag id")} ${r.diagnosticId}
|
|
27914
28303
|
`);
|
|
27915
28304
|
out2.write("\n");
|
|
27916
28305
|
for (const c2 of r.checks) {
|
|
27917
|
-
const mark = c2.ok ?
|
|
27918
|
-
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}`)}
|
|
27919
28308
|
`);
|
|
27920
28309
|
if (!c2.ok && c2.hint) {
|
|
27921
28310
|
for (const line of c2.hint.split("\n")) {
|
|
27922
|
-
out2.write(` ${
|
|
28311
|
+
out2.write(` ${import_picocolors13.default.dim(line)}
|
|
27923
28312
|
`);
|
|
27924
28313
|
}
|
|
27925
28314
|
}
|
|
27926
28315
|
}
|
|
27927
28316
|
out2.write("\n");
|
|
27928
28317
|
if (r.ok) {
|
|
27929
|
-
out2.write(` ${
|
|
28318
|
+
out2.write(` ${import_picocolors13.default.green("All checks passed.")}
|
|
27930
28319
|
|
|
27931
28320
|
`);
|
|
27932
28321
|
} else {
|
|
27933
28322
|
out2.write(
|
|
27934
|
-
` ${
|
|
28323
|
+
` ${import_picocolors13.default.red("Some checks failed.")} ${import_picocolors13.default.dim("Paste the diagnostic id above when opening a bug report.")}
|
|
27935
28324
|
|
|
27936
28325
|
`
|
|
27937
28326
|
);
|
|
@@ -28049,118 +28438,118 @@ async function completion(args2) {
|
|
|
28049
28438
|
}
|
|
28050
28439
|
|
|
28051
28440
|
// src/commands/version.ts
|
|
28052
|
-
var
|
|
28441
|
+
var import_picocolors14 = __toESM(require("picocolors"));
|
|
28053
28442
|
function version2() {
|
|
28054
|
-
const v = true ? "2.39.
|
|
28055
|
-
console.log(`${
|
|
28443
|
+
const v = true ? "2.39.55" : "unknown";
|
|
28444
|
+
console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
|
|
28056
28445
|
}
|
|
28057
28446
|
|
|
28058
28447
|
// src/commands/help.ts
|
|
28059
|
-
var
|
|
28448
|
+
var import_picocolors15 = __toESM(require("picocolors"));
|
|
28060
28449
|
function help() {
|
|
28061
28450
|
const lines = [
|
|
28062
28451
|
"",
|
|
28063
|
-
` ${
|
|
28452
|
+
` ${import_picocolors15.default.bold(import_picocolors15.default.magenta("codeam-cli"))} ${import_picocolors15.default.dim("\u2014 remote-control AI coding agents from your phone")}`,
|
|
28064
28453
|
"",
|
|
28065
|
-
` ${
|
|
28066
|
-
` ${
|
|
28454
|
+
` ${import_picocolors15.default.bold("Usage")}`,
|
|
28455
|
+
` ${import_picocolors15.default.cyan("codeam")} ${import_picocolors15.default.dim("[command]")}`,
|
|
28067
28456
|
"",
|
|
28068
|
-
` ${
|
|
28069
|
-
` ${
|
|
28070
|
-
` ${
|
|
28071
|
-
` ${
|
|
28072
|
-
` ${
|
|
28073
|
-
` ${
|
|
28074
|
-
` ${
|
|
28075
|
-
` ${
|
|
28076
|
-
` ${
|
|
28077
|
-
` ${
|
|
28078
|
-
` ${
|
|
28079
|
-
` ${
|
|
28080
|
-
` ${
|
|
28081
|
-
` ${
|
|
28082
|
-
` ${
|
|
28083
|
-
` ${
|
|
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")}`,
|
|
28084
28473
|
"",
|
|
28085
|
-
` ${
|
|
28086
|
-
` ${
|
|
28087
|
-
` ${
|
|
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")}`,
|
|
28088
28477
|
"",
|
|
28089
|
-
` ${
|
|
28090
|
-
` ${
|
|
28091
|
-
` ${
|
|
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")}`,
|
|
28092
28481
|
""
|
|
28093
28482
|
];
|
|
28094
28483
|
process.stdout.write(lines.join("\n") + "\n");
|
|
28095
28484
|
}
|
|
28096
28485
|
|
|
28097
28486
|
// src/commands/subcommand-help.ts
|
|
28098
|
-
var
|
|
28487
|
+
var import_picocolors16 = __toESM(require("picocolors"));
|
|
28099
28488
|
var HELPS = {
|
|
28100
28489
|
pair: () => print([
|
|
28101
|
-
` ${
|
|
28490
|
+
` ${import_picocolors16.default.bold("codeam pair")} ${import_picocolors16.default.dim("\u2014 pair a mobile device with this CLI")}`,
|
|
28102
28491
|
"",
|
|
28103
|
-
` ${
|
|
28104
|
-
` ${
|
|
28105
|
-
` ${
|
|
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")}`
|
|
28106
28495
|
]),
|
|
28107
28496
|
"pair-auto": () => print([
|
|
28108
|
-
` ${
|
|
28497
|
+
` ${import_picocolors16.default.bold("codeam pair-auto")} ${import_picocolors16.default.dim("\u2014 non-interactive variant of pair for scripted setups")}`,
|
|
28109
28498
|
"",
|
|
28110
|
-
` ${
|
|
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")}`
|
|
28111
28500
|
]),
|
|
28112
28501
|
link: () => print([
|
|
28113
|
-
` ${
|
|
28502
|
+
` ${import_picocolors16.default.bold("codeam link <agent>")} ${import_picocolors16.default.dim("\u2014 upload a local agent token (Claude or Codex) to your vault")}`,
|
|
28114
28503
|
"",
|
|
28115
|
-
` ${
|
|
28116
|
-
` ${
|
|
28504
|
+
` ${import_picocolors16.default.cyan("codeam link claude")}`,
|
|
28505
|
+
` ${import_picocolors16.default.cyan("codeam link codex")}`,
|
|
28117
28506
|
"",
|
|
28118
|
-
` ${
|
|
28119
|
-
` ${
|
|
28120
|
-
` ${
|
|
28121
|
-
` ${
|
|
28122
|
-
` ${
|
|
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")}`
|
|
28123
28512
|
]),
|
|
28124
28513
|
sessions: () => print([
|
|
28125
|
-
` ${
|
|
28514
|
+
` ${import_picocolors16.default.bold("codeam sessions")} ${import_picocolors16.default.dim("\u2014 list, switch, or delete paired mobile sessions")}`,
|
|
28126
28515
|
"",
|
|
28127
|
-
` ${
|
|
28128
|
-
` ${
|
|
28129
|
-
` ${
|
|
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")}`
|
|
28130
28519
|
]),
|
|
28131
28520
|
deploy: () => print([
|
|
28132
|
-
` ${
|
|
28521
|
+
` ${import_picocolors16.default.bold("codeam deploy")} ${import_picocolors16.default.dim("\u2014 provision a cloud workspace (GitHub Codespaces) and pair it")}`,
|
|
28133
28522
|
"",
|
|
28134
|
-
` ${
|
|
28135
|
-
` ${
|
|
28136
|
-
` ${
|
|
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")}`
|
|
28137
28526
|
]),
|
|
28138
28527
|
status: () => print([
|
|
28139
|
-
` ${
|
|
28528
|
+
` ${import_picocolors16.default.bold("codeam status")} ${import_picocolors16.default.dim("\u2014 show the active session, agent, and connection info")}`
|
|
28140
28529
|
]),
|
|
28141
28530
|
logout: () => print([
|
|
28142
|
-
` ${
|
|
28531
|
+
` ${import_picocolors16.default.bold("codeam logout")} ${import_picocolors16.default.dim("\u2014 remove every paired session from this machine")}`
|
|
28143
28532
|
]),
|
|
28144
28533
|
doctor: () => print([
|
|
28145
|
-
` ${
|
|
28534
|
+
` ${import_picocolors16.default.bold("codeam doctor")} ${import_picocolors16.default.dim("\u2014 run diagnostic checks for support triage")}`,
|
|
28146
28535
|
"",
|
|
28147
|
-
` ${
|
|
28148
|
-
` ${
|
|
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)")}`,
|
|
28149
28538
|
"",
|
|
28150
|
-
` ${
|
|
28151
|
-
` ${
|
|
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.")}`
|
|
28152
28541
|
]),
|
|
28153
28542
|
completion: () => print([
|
|
28154
|
-
` ${
|
|
28543
|
+
` ${import_picocolors16.default.bold("codeam completion <shell>")} ${import_picocolors16.default.dim("\u2014 emit a shell-completion script for sourcing")}`,
|
|
28155
28544
|
"",
|
|
28156
|
-
` ${
|
|
28157
|
-
` ${
|
|
28158
|
-
` ${
|
|
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")}`,
|
|
28159
28548
|
"",
|
|
28160
|
-
` ${
|
|
28161
|
-
` ${
|
|
28162
|
-
` ${
|
|
28163
|
-
` ${
|
|
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")}`
|
|
28164
28553
|
])
|
|
28165
28554
|
};
|
|
28166
28555
|
function print(lines) {
|
|
@@ -28178,179 +28567,6 @@ function tryShowSubcommandHelp(cmd, args2) {
|
|
|
28178
28567
|
}
|
|
28179
28568
|
var _subcommandHelpKeys = Object.keys(HELPS);
|
|
28180
28569
|
|
|
28181
|
-
// src/lib/updateNotifier.ts
|
|
28182
|
-
var fs46 = __toESM(require("fs"));
|
|
28183
|
-
var os37 = __toESM(require("os"));
|
|
28184
|
-
var path57 = __toESM(require("path"));
|
|
28185
|
-
var https8 = __toESM(require("https"));
|
|
28186
|
-
var import_node_child_process15 = require("child_process");
|
|
28187
|
-
var import_picocolors16 = __toESM(require("picocolors"));
|
|
28188
|
-
var PKG_NAME = "codeam-cli";
|
|
28189
|
-
var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
28190
|
-
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
28191
|
-
var REQUEST_TIMEOUT_MS = 1500;
|
|
28192
|
-
function cachePath() {
|
|
28193
|
-
const dir = path57.join(os37.homedir(), ".codeam");
|
|
28194
|
-
return path57.join(dir, "update-check.json");
|
|
28195
|
-
}
|
|
28196
|
-
function readCache() {
|
|
28197
|
-
try {
|
|
28198
|
-
const raw = fs46.readFileSync(cachePath(), "utf8");
|
|
28199
|
-
const parsed = JSON.parse(raw);
|
|
28200
|
-
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
28201
|
-
return parsed;
|
|
28202
|
-
} catch {
|
|
28203
|
-
return null;
|
|
28204
|
-
}
|
|
28205
|
-
}
|
|
28206
|
-
function writeCache(cache) {
|
|
28207
|
-
try {
|
|
28208
|
-
const file = cachePath();
|
|
28209
|
-
fs46.mkdirSync(path57.dirname(file), { recursive: true });
|
|
28210
|
-
const tmp = `${file}.${process.pid}.tmp`;
|
|
28211
|
-
fs46.writeFileSync(tmp, JSON.stringify(cache));
|
|
28212
|
-
fs46.renameSync(tmp, file);
|
|
28213
|
-
} catch {
|
|
28214
|
-
}
|
|
28215
|
-
}
|
|
28216
|
-
function compareSemver(a, b) {
|
|
28217
|
-
const stripPre = (s) => s.split("-")[0];
|
|
28218
|
-
const aParts = stripPre(a).split(".").map(Number);
|
|
28219
|
-
const bParts = stripPre(b).split(".").map(Number);
|
|
28220
|
-
for (let i = 0; i < 3; i++) {
|
|
28221
|
-
const ai = aParts[i] ?? 0;
|
|
28222
|
-
const bi = bParts[i] ?? 0;
|
|
28223
|
-
if (Number.isNaN(ai) || Number.isNaN(bi)) return 0;
|
|
28224
|
-
if (ai > bi) return 1;
|
|
28225
|
-
if (ai < bi) return -1;
|
|
28226
|
-
}
|
|
28227
|
-
return 0;
|
|
28228
|
-
}
|
|
28229
|
-
function fetchLatest() {
|
|
28230
|
-
return new Promise((resolve7) => {
|
|
28231
|
-
const req = https8.get(
|
|
28232
|
-
REGISTRY_URL,
|
|
28233
|
-
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
28234
|
-
(res) => {
|
|
28235
|
-
if (res.statusCode !== 200) {
|
|
28236
|
-
res.resume();
|
|
28237
|
-
resolve7(null);
|
|
28238
|
-
return;
|
|
28239
|
-
}
|
|
28240
|
-
let buf = "";
|
|
28241
|
-
res.setEncoding("utf8");
|
|
28242
|
-
res.on("data", (chunk) => {
|
|
28243
|
-
buf += chunk;
|
|
28244
|
-
});
|
|
28245
|
-
res.on("end", () => {
|
|
28246
|
-
try {
|
|
28247
|
-
const json = JSON.parse(buf);
|
|
28248
|
-
if (typeof json.version === "string") {
|
|
28249
|
-
resolve7(json.version);
|
|
28250
|
-
} else {
|
|
28251
|
-
resolve7(null);
|
|
28252
|
-
}
|
|
28253
|
-
} catch {
|
|
28254
|
-
resolve7(null);
|
|
28255
|
-
}
|
|
28256
|
-
});
|
|
28257
|
-
}
|
|
28258
|
-
);
|
|
28259
|
-
req.on("timeout", () => {
|
|
28260
|
-
req.destroy();
|
|
28261
|
-
resolve7(null);
|
|
28262
|
-
});
|
|
28263
|
-
req.on("error", () => resolve7(null));
|
|
28264
|
-
});
|
|
28265
|
-
}
|
|
28266
|
-
function notifyIfStale(currentVersion, latest) {
|
|
28267
|
-
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
28268
|
-
const arrow = import_picocolors16.default.dim("\u2192");
|
|
28269
|
-
const cmd = import_picocolors16.default.cyan("npm install -g codeam-cli");
|
|
28270
|
-
const lines = [
|
|
28271
|
-
"",
|
|
28272
|
-
` ${import_picocolors16.default.yellow("\u25CF")} ${import_picocolors16.default.bold("Update available")} ${import_picocolors16.default.dim(currentVersion)} ${arrow} ${import_picocolors16.default.green(latest)}`,
|
|
28273
|
-
` Run ${cmd} to upgrade.`,
|
|
28274
|
-
""
|
|
28275
|
-
];
|
|
28276
|
-
process.stderr.write(lines.join("\n"));
|
|
28277
|
-
}
|
|
28278
|
-
function isLinkedInstall() {
|
|
28279
|
-
try {
|
|
28280
|
-
const root = (0, import_node_child_process15.execSync)("npm root -g", {
|
|
28281
|
-
encoding: "utf8",
|
|
28282
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
28283
|
-
timeout: 2e3
|
|
28284
|
-
}).trim();
|
|
28285
|
-
if (!root) return false;
|
|
28286
|
-
const pkgPath = path57.join(root, PKG_NAME);
|
|
28287
|
-
return fs46.lstatSync(pkgPath).isSymbolicLink();
|
|
28288
|
-
} catch {
|
|
28289
|
-
return false;
|
|
28290
|
-
}
|
|
28291
|
-
}
|
|
28292
|
-
function maybeAutoUpdate(currentVersion, latest) {
|
|
28293
|
-
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
28294
|
-
if (process.env.CODEAM_NO_AUTO_UPDATE === "1") {
|
|
28295
|
-
notifyIfStale(currentVersion, latest);
|
|
28296
|
-
return;
|
|
28297
|
-
}
|
|
28298
|
-
if (isLinkedInstall()) {
|
|
28299
|
-
notifyIfStale(currentVersion, latest);
|
|
28300
|
-
return;
|
|
28301
|
-
}
|
|
28302
|
-
process.stderr.write(
|
|
28303
|
-
`
|
|
28304
|
-
${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)}...
|
|
28305
|
-
|
|
28306
|
-
`
|
|
28307
|
-
);
|
|
28308
|
-
const install = (0, import_node_child_process15.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
|
|
28309
|
-
stdio: "inherit",
|
|
28310
|
-
env: process.env
|
|
28311
|
-
});
|
|
28312
|
-
if (install.status !== 0) {
|
|
28313
|
-
process.stderr.write(
|
|
28314
|
-
`
|
|
28315
|
-
${import_picocolors16.default.red("!")} Update failed (exit ${install.status ?? "?"}). Continuing on ${currentVersion}.
|
|
28316
|
-
Run ${import_picocolors16.default.cyan("npm install -g codeam-cli")} manually to retry.
|
|
28317
|
-
|
|
28318
|
-
`
|
|
28319
|
-
);
|
|
28320
|
-
return;
|
|
28321
|
-
}
|
|
28322
|
-
try {
|
|
28323
|
-
fs46.unlinkSync(cachePath());
|
|
28324
|
-
} catch {
|
|
28325
|
-
}
|
|
28326
|
-
process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
|
|
28327
|
-
|
|
28328
|
-
`);
|
|
28329
|
-
const child = (0, import_node_child_process15.spawnSync)("codeam", process.argv.slice(2), {
|
|
28330
|
-
stdio: "inherit",
|
|
28331
|
-
env: process.env
|
|
28332
|
-
});
|
|
28333
|
-
process.exit(child.status ?? 0);
|
|
28334
|
-
}
|
|
28335
|
-
function checkForUpdates() {
|
|
28336
|
-
if (process.env.NODE_ENV === "test") return;
|
|
28337
|
-
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
28338
|
-
if (process.env.CI) return;
|
|
28339
|
-
if (!process.stdout.isTTY) return;
|
|
28340
|
-
const current = true ? "2.39.54" : null;
|
|
28341
|
-
if (!current) return;
|
|
28342
|
-
const cache = readCache();
|
|
28343
|
-
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
28344
|
-
if (fresh && cache) {
|
|
28345
|
-
maybeAutoUpdate(current, cache.latest);
|
|
28346
|
-
return;
|
|
28347
|
-
}
|
|
28348
|
-
void fetchLatest().then((latest) => {
|
|
28349
|
-
if (!latest) return;
|
|
28350
|
-
writeCache({ fetchedAt: Date.now(), latest });
|
|
28351
|
-
});
|
|
28352
|
-
}
|
|
28353
|
-
|
|
28354
28570
|
// src/exit-codes.ts
|
|
28355
28571
|
var EXIT_OK = 0;
|
|
28356
28572
|
var EXIT_FAILURE = 1;
|