codeam-cli 2.39.54 → 2.39.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.js +701 -462
- 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.56" : "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.56",
|
|
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"));
|
|
@@ -16917,12 +16919,13 @@ async function redeemEnrollToken(token, label) {
|
|
|
16917
16919
|
controlPluginId: data.controlPluginId
|
|
16918
16920
|
};
|
|
16919
16921
|
}
|
|
16920
|
-
async function sendHostHeartbeat(identity, metrics) {
|
|
16922
|
+
async function sendHostHeartbeat(identity, metrics, sessions3) {
|
|
16921
16923
|
const start2 = process.hrtime.bigint();
|
|
16922
16924
|
await postJson("/api/self-hosted/heartbeat", {
|
|
16923
16925
|
hostId: identity.hostId,
|
|
16924
16926
|
hostToken: identity.hostToken,
|
|
16925
|
-
...metrics ? { metrics } : {}
|
|
16927
|
+
...metrics ? { metrics } : {},
|
|
16928
|
+
...sessions3 ? { sessions: sessions3 } : {}
|
|
16926
16929
|
});
|
|
16927
16930
|
const elapsedNs = process.hrtime.bigint() - start2;
|
|
16928
16931
|
return Math.round(Number(elapsedNs) / 1e6);
|
|
@@ -17199,8 +17202,185 @@ var HeadroomStatsReporter = class {
|
|
|
17199
17202
|
}
|
|
17200
17203
|
};
|
|
17201
17204
|
|
|
17205
|
+
// src/lib/updateNotifier.ts
|
|
17206
|
+
var fs38 = __toESM(require("fs"));
|
|
17207
|
+
var os31 = __toESM(require("os"));
|
|
17208
|
+
var path44 = __toESM(require("path"));
|
|
17209
|
+
var https6 = __toESM(require("https"));
|
|
17210
|
+
var import_node_child_process12 = require("child_process");
|
|
17211
|
+
var import_picocolors3 = __toESM(require("picocolors"));
|
|
17212
|
+
var PKG_NAME = "codeam-cli";
|
|
17213
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
17214
|
+
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
17215
|
+
var REQUEST_TIMEOUT_MS = 1500;
|
|
17216
|
+
function cachePath() {
|
|
17217
|
+
const dir = path44.join(os31.homedir(), ".codeam");
|
|
17218
|
+
return path44.join(dir, "update-check.json");
|
|
17219
|
+
}
|
|
17220
|
+
function readCache() {
|
|
17221
|
+
try {
|
|
17222
|
+
const raw = fs38.readFileSync(cachePath(), "utf8");
|
|
17223
|
+
const parsed = JSON.parse(raw);
|
|
17224
|
+
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
17225
|
+
return parsed;
|
|
17226
|
+
} catch {
|
|
17227
|
+
return null;
|
|
17228
|
+
}
|
|
17229
|
+
}
|
|
17230
|
+
function writeCache(cache) {
|
|
17231
|
+
try {
|
|
17232
|
+
const file = cachePath();
|
|
17233
|
+
fs38.mkdirSync(path44.dirname(file), { recursive: true });
|
|
17234
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
17235
|
+
fs38.writeFileSync(tmp, JSON.stringify(cache));
|
|
17236
|
+
fs38.renameSync(tmp, file);
|
|
17237
|
+
} catch {
|
|
17238
|
+
}
|
|
17239
|
+
}
|
|
17240
|
+
function compareSemver(a, b) {
|
|
17241
|
+
const stripPre = (s) => s.split("-")[0];
|
|
17242
|
+
const aParts = stripPre(a).split(".").map(Number);
|
|
17243
|
+
const bParts = stripPre(b).split(".").map(Number);
|
|
17244
|
+
for (let i = 0; i < 3; i++) {
|
|
17245
|
+
const ai = aParts[i] ?? 0;
|
|
17246
|
+
const bi = bParts[i] ?? 0;
|
|
17247
|
+
if (Number.isNaN(ai) || Number.isNaN(bi)) return 0;
|
|
17248
|
+
if (ai > bi) return 1;
|
|
17249
|
+
if (ai < bi) return -1;
|
|
17250
|
+
}
|
|
17251
|
+
return 0;
|
|
17252
|
+
}
|
|
17253
|
+
function fetchLatest() {
|
|
17254
|
+
return new Promise((resolve7) => {
|
|
17255
|
+
const req = https6.get(
|
|
17256
|
+
REGISTRY_URL,
|
|
17257
|
+
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
17258
|
+
(res) => {
|
|
17259
|
+
if (res.statusCode !== 200) {
|
|
17260
|
+
res.resume();
|
|
17261
|
+
resolve7(null);
|
|
17262
|
+
return;
|
|
17263
|
+
}
|
|
17264
|
+
let buf = "";
|
|
17265
|
+
res.setEncoding("utf8");
|
|
17266
|
+
res.on("data", (chunk) => {
|
|
17267
|
+
buf += chunk;
|
|
17268
|
+
});
|
|
17269
|
+
res.on("end", () => {
|
|
17270
|
+
try {
|
|
17271
|
+
const json = JSON.parse(buf);
|
|
17272
|
+
if (typeof json.version === "string") {
|
|
17273
|
+
resolve7(json.version);
|
|
17274
|
+
} else {
|
|
17275
|
+
resolve7(null);
|
|
17276
|
+
}
|
|
17277
|
+
} catch {
|
|
17278
|
+
resolve7(null);
|
|
17279
|
+
}
|
|
17280
|
+
});
|
|
17281
|
+
}
|
|
17282
|
+
);
|
|
17283
|
+
req.on("timeout", () => {
|
|
17284
|
+
req.destroy();
|
|
17285
|
+
resolve7(null);
|
|
17286
|
+
});
|
|
17287
|
+
req.on("error", () => resolve7(null));
|
|
17288
|
+
});
|
|
17289
|
+
}
|
|
17290
|
+
function notifyIfStale(currentVersion, latest) {
|
|
17291
|
+
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
17292
|
+
const arrow = import_picocolors3.default.dim("\u2192");
|
|
17293
|
+
const cmd = import_picocolors3.default.cyan("npm install -g codeam-cli");
|
|
17294
|
+
const lines = [
|
|
17295
|
+
"",
|
|
17296
|
+
` ${import_picocolors3.default.yellow("\u25CF")} ${import_picocolors3.default.bold("Update available")} ${import_picocolors3.default.dim(currentVersion)} ${arrow} ${import_picocolors3.default.green(latest)}`,
|
|
17297
|
+
` Run ${cmd} to upgrade.`,
|
|
17298
|
+
""
|
|
17299
|
+
];
|
|
17300
|
+
process.stderr.write(lines.join("\n"));
|
|
17301
|
+
}
|
|
17302
|
+
function isLinkedInstall() {
|
|
17303
|
+
try {
|
|
17304
|
+
const root = (0, import_node_child_process12.execSync)("npm root -g", {
|
|
17305
|
+
encoding: "utf8",
|
|
17306
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
17307
|
+
timeout: 2e3
|
|
17308
|
+
}).trim();
|
|
17309
|
+
if (!root) return false;
|
|
17310
|
+
const pkgPath = path44.join(root, PKG_NAME);
|
|
17311
|
+
return fs38.lstatSync(pkgPath).isSymbolicLink();
|
|
17312
|
+
} catch {
|
|
17313
|
+
return false;
|
|
17314
|
+
}
|
|
17315
|
+
}
|
|
17316
|
+
function maybeAutoUpdate(currentVersion, latest) {
|
|
17317
|
+
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
17318
|
+
if (process.env.CODEAM_NO_AUTO_UPDATE === "1") {
|
|
17319
|
+
notifyIfStale(currentVersion, latest);
|
|
17320
|
+
return;
|
|
17321
|
+
}
|
|
17322
|
+
if (isLinkedInstall()) {
|
|
17323
|
+
notifyIfStale(currentVersion, latest);
|
|
17324
|
+
return;
|
|
17325
|
+
}
|
|
17326
|
+
process.stderr.write(
|
|
17327
|
+
`
|
|
17328
|
+
${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)}...
|
|
17329
|
+
|
|
17330
|
+
`
|
|
17331
|
+
);
|
|
17332
|
+
const install = (0, import_node_child_process12.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
|
|
17333
|
+
stdio: "inherit",
|
|
17334
|
+
env: process.env
|
|
17335
|
+
});
|
|
17336
|
+
if (install.status !== 0) {
|
|
17337
|
+
process.stderr.write(
|
|
17338
|
+
`
|
|
17339
|
+
${import_picocolors3.default.red("!")} Update failed (exit ${install.status ?? "?"}). Continuing on ${currentVersion}.
|
|
17340
|
+
Run ${import_picocolors3.default.cyan("npm install -g codeam-cli")} manually to retry.
|
|
17341
|
+
|
|
17342
|
+
`
|
|
17343
|
+
);
|
|
17344
|
+
return;
|
|
17345
|
+
}
|
|
17346
|
+
try {
|
|
17347
|
+
fs38.unlinkSync(cachePath());
|
|
17348
|
+
} catch {
|
|
17349
|
+
}
|
|
17350
|
+
process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
|
|
17351
|
+
|
|
17352
|
+
`);
|
|
17353
|
+
const child = (0, import_node_child_process12.spawnSync)("codeam", process.argv.slice(2), {
|
|
17354
|
+
stdio: "inherit",
|
|
17355
|
+
env: process.env
|
|
17356
|
+
});
|
|
17357
|
+
process.exit(child.status ?? 0);
|
|
17358
|
+
}
|
|
17359
|
+
function checkForUpdates() {
|
|
17360
|
+
if (process.env.NODE_ENV === "test") return;
|
|
17361
|
+
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17362
|
+
if (process.env.CI) return;
|
|
17363
|
+
if (!process.stdout.isTTY) return;
|
|
17364
|
+
const current = true ? "2.39.56" : null;
|
|
17365
|
+
if (!current) return;
|
|
17366
|
+
const cache = readCache();
|
|
17367
|
+
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
17368
|
+
if (fresh && cache) {
|
|
17369
|
+
maybeAutoUpdate(current, cache.latest);
|
|
17370
|
+
return;
|
|
17371
|
+
}
|
|
17372
|
+
void fetchLatest().then((latest) => {
|
|
17373
|
+
if (!latest) return;
|
|
17374
|
+
writeCache({ fetchedAt: Date.now(), latest });
|
|
17375
|
+
});
|
|
17376
|
+
}
|
|
17377
|
+
|
|
17202
17378
|
// src/commands/host-agent.ts
|
|
17203
17379
|
var HEARTBEAT_INTERVAL_MS = 2e4;
|
|
17380
|
+
var SELF_UPDATE_PKG = "codeam-cli";
|
|
17381
|
+
var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
17382
|
+
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
17383
|
+
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
17204
17384
|
function maybeStartHeadroomReporter(ctx) {
|
|
17205
17385
|
if (process.env["HEADROOM_ENABLED"] !== "1") return null;
|
|
17206
17386
|
try {
|
|
@@ -17275,7 +17455,7 @@ var PIP_INSTALL_TIMEOUT_MS = 12e4;
|
|
|
17275
17455
|
var defaultHeadroomRunner = {
|
|
17276
17456
|
which(cmd) {
|
|
17277
17457
|
try {
|
|
17278
|
-
(0,
|
|
17458
|
+
(0, import_node_child_process13.execFileSync)("which", [cmd], { stdio: "ignore" });
|
|
17279
17459
|
return true;
|
|
17280
17460
|
} catch {
|
|
17281
17461
|
return false;
|
|
@@ -17283,7 +17463,7 @@ var defaultHeadroomRunner = {
|
|
|
17283
17463
|
},
|
|
17284
17464
|
run(cmd, args2, opts = {}) {
|
|
17285
17465
|
return new Promise((resolve7) => {
|
|
17286
|
-
const child = (0,
|
|
17466
|
+
const child = (0, import_node_child_process13.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"] });
|
|
17287
17467
|
let stderrBuf = "";
|
|
17288
17468
|
let settled = false;
|
|
17289
17469
|
const done = (code) => {
|
|
@@ -17416,6 +17596,41 @@ function agentIdToHeadroomKind(agentId) {
|
|
|
17416
17596
|
if (normalized.startsWith("copilot")) return "copilot";
|
|
17417
17597
|
return "claude";
|
|
17418
17598
|
}
|
|
17599
|
+
function headroomConfigPath() {
|
|
17600
|
+
return path45.join(os32.homedir(), ".codeam", "headroom-config.json");
|
|
17601
|
+
}
|
|
17602
|
+
function persistHeadroomConfig(config) {
|
|
17603
|
+
try {
|
|
17604
|
+
const file = headroomConfigPath();
|
|
17605
|
+
fs39.mkdirSync(path45.dirname(file), { recursive: true, mode: 448 });
|
|
17606
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
17607
|
+
fs39.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
|
|
17608
|
+
fs39.renameSync(tmp, file);
|
|
17609
|
+
} catch (err) {
|
|
17610
|
+
log.warn(
|
|
17611
|
+
"host-agent",
|
|
17612
|
+
`failed to persist headroom config (best-effort): ${err instanceof Error ? err.message : String(err)}`
|
|
17613
|
+
);
|
|
17614
|
+
}
|
|
17615
|
+
}
|
|
17616
|
+
function readHeadroomChildEnv() {
|
|
17617
|
+
try {
|
|
17618
|
+
const raw = fs39.readFileSync(headroomConfigPath(), "utf8");
|
|
17619
|
+
const parsed = JSON.parse(raw);
|
|
17620
|
+
if (typeof parsed !== "object" || parsed === null) return {};
|
|
17621
|
+
const o = parsed;
|
|
17622
|
+
if (o.enabled === true && typeof o.agent === "string" && o.agent.length > 0 && typeof o.ingestUrl === "string" && o.ingestUrl.length > 0) {
|
|
17623
|
+
return {
|
|
17624
|
+
HEADROOM_ENABLED: "1",
|
|
17625
|
+
HEADROOM_AGENT: o.agent,
|
|
17626
|
+
HEADROOM_SAVINGS_INGEST_URL: o.ingestUrl
|
|
17627
|
+
};
|
|
17628
|
+
}
|
|
17629
|
+
return {};
|
|
17630
|
+
} catch {
|
|
17631
|
+
return {};
|
|
17632
|
+
}
|
|
17633
|
+
}
|
|
17419
17634
|
async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner) {
|
|
17420
17635
|
const PIP_PACKAGES = [
|
|
17421
17636
|
"headroom-ai",
|
|
@@ -17473,7 +17688,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17473
17688
|
}
|
|
17474
17689
|
const initKind = agentIdToHeadroomKind(agent);
|
|
17475
17690
|
const initOk = await new Promise((resolve7) => {
|
|
17476
|
-
(0,
|
|
17691
|
+
(0, import_node_child_process13.execFile)("headroom", ["init", "--global", initKind], (initErr, stdout, stderr) => {
|
|
17477
17692
|
if (initErr) {
|
|
17478
17693
|
const detail = (stderr || initErr.message).replace(/\n+$/g, "");
|
|
17479
17694
|
log.warn("host-agent", `headroom init failed (best-effort): ${detail}`);
|
|
@@ -17489,7 +17704,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17489
17704
|
return false;
|
|
17490
17705
|
}
|
|
17491
17706
|
try {
|
|
17492
|
-
const proxy = (0,
|
|
17707
|
+
const proxy = (0, import_node_child_process13.spawn)("headroom", ["proxy", "--port", "8787"], {
|
|
17493
17708
|
stdio: "ignore",
|
|
17494
17709
|
detached: true
|
|
17495
17710
|
});
|
|
@@ -17499,20 +17714,81 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17499
17714
|
}
|
|
17500
17715
|
return true;
|
|
17501
17716
|
}
|
|
17502
|
-
var defaultSpawner = (env, cwd, args2 = []) => (0,
|
|
17717
|
+
var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process13.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
|
|
17503
17718
|
cwd,
|
|
17504
17719
|
env: { ...process.env, ...env },
|
|
17505
17720
|
stdio: ["ignore", "pipe", "pipe"],
|
|
17506
17721
|
detached: false
|
|
17507
17722
|
});
|
|
17723
|
+
function currentCliVersion() {
|
|
17724
|
+
return true ? "2.39.56" : null;
|
|
17725
|
+
}
|
|
17726
|
+
function runCmd(cmd, args2, timeoutMs) {
|
|
17727
|
+
return new Promise((resolve7) => {
|
|
17728
|
+
(0, import_node_child_process13.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
|
|
17729
|
+
const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
|
|
17730
|
+
resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
|
|
17731
|
+
});
|
|
17732
|
+
});
|
|
17733
|
+
}
|
|
17734
|
+
async function runSelfUpdate() {
|
|
17735
|
+
try {
|
|
17736
|
+
const current = currentCliVersion();
|
|
17737
|
+
if (!current) {
|
|
17738
|
+
log.trace("host-agent", "self-update: no __CLI_VERSION__ \u2014 skipping");
|
|
17739
|
+
return { status: "skipped" };
|
|
17740
|
+
}
|
|
17741
|
+
const view = await runCmd("npm", ["view", SELF_UPDATE_PKG, "version"], SELF_UPDATE_VIEW_TIMEOUT_MS);
|
|
17742
|
+
if (view.code !== 0) {
|
|
17743
|
+
log.trace("host-agent", `self-update: npm view exited ${String(view.code)} \u2014 skipping`);
|
|
17744
|
+
return { status: "skipped" };
|
|
17745
|
+
}
|
|
17746
|
+
const latest = view.stdout.trim();
|
|
17747
|
+
if (!latest) {
|
|
17748
|
+
log.trace("host-agent", "self-update: empty npm view output \u2014 skipping");
|
|
17749
|
+
return { status: "skipped" };
|
|
17750
|
+
}
|
|
17751
|
+
if (compareSemver(latest, current) <= 0) {
|
|
17752
|
+
return { status: "current" };
|
|
17753
|
+
}
|
|
17754
|
+
log.info("host-agent", `self-update: ${current} \u2192 ${latest} available \u2014 installing`);
|
|
17755
|
+
const installArgs = ["install", "-g", `${SELF_UPDATE_PKG}@latest`];
|
|
17756
|
+
let install = await runCmd("npm", installArgs, SELF_UPDATE_INSTALL_TIMEOUT_MS);
|
|
17757
|
+
const isRoot = process.getuid?.() === 0;
|
|
17758
|
+
if (install.code !== 0 && !isRoot && /EACCES/i.test(install.stderr)) {
|
|
17759
|
+
log.info("host-agent", "self-update: install hit EACCES \u2014 retrying with sudo");
|
|
17760
|
+
install = await runCmd("sudo", ["npm", ...installArgs], SELF_UPDATE_INSTALL_TIMEOUT_MS);
|
|
17761
|
+
}
|
|
17762
|
+
if (install.code !== 0) {
|
|
17763
|
+
log.warn(
|
|
17764
|
+
"host-agent",
|
|
17765
|
+
`self-update: install exited ${String(install.code)} \u2014 staying on ${current}`
|
|
17766
|
+
);
|
|
17767
|
+
return { status: "skipped" };
|
|
17768
|
+
}
|
|
17769
|
+
const after = await runCmd("npm", ["view", SELF_UPDATE_PKG, "version"], SELF_UPDATE_VIEW_TIMEOUT_MS);
|
|
17770
|
+
const installed = after.code === 0 ? after.stdout.trim() || latest : latest;
|
|
17771
|
+
return { status: "updated", version: installed };
|
|
17772
|
+
} catch (err) {
|
|
17773
|
+
log.warn(
|
|
17774
|
+
"host-agent",
|
|
17775
|
+
`self-update: unexpected error: ${err instanceof Error ? err.message : String(err)}`
|
|
17776
|
+
);
|
|
17777
|
+
return { status: "skipped" };
|
|
17778
|
+
}
|
|
17779
|
+
}
|
|
17508
17780
|
var defaultOnIdentityRejected = () => {
|
|
17509
17781
|
deleteHostIdentity();
|
|
17510
17782
|
log.warn("host-agent", "host identity rejected by backend \u2014 wiped sealed identity, exiting");
|
|
17511
17783
|
process.exit(1);
|
|
17512
17784
|
};
|
|
17785
|
+
var defaultOnUpdated = (version3) => {
|
|
17786
|
+
log.info("host-agent", `self-update: installed ${version3}, restarting`);
|
|
17787
|
+
process.exit(0);
|
|
17788
|
+
};
|
|
17513
17789
|
var defaultDisableService = () => {
|
|
17514
17790
|
try {
|
|
17515
|
-
(0,
|
|
17791
|
+
(0, import_node_child_process13.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
|
|
17516
17792
|
} catch {
|
|
17517
17793
|
}
|
|
17518
17794
|
};
|
|
@@ -17526,6 +17802,8 @@ var HostAgentSupervisor = class {
|
|
|
17526
17802
|
this.metrics = deps.metricsCollector ?? new MetricsCollector();
|
|
17527
17803
|
this.onIdentityRejected = deps.onIdentityRejected ?? defaultOnIdentityRejected;
|
|
17528
17804
|
this.disableService = deps.disableService ?? defaultDisableService;
|
|
17805
|
+
this.selfUpdate = deps.selfUpdate ?? runSelfUpdate;
|
|
17806
|
+
this.onUpdated = deps.onUpdated ?? defaultOnUpdated;
|
|
17529
17807
|
}
|
|
17530
17808
|
identity;
|
|
17531
17809
|
deps;
|
|
@@ -17535,6 +17813,20 @@ var HostAgentSupervisor = class {
|
|
|
17535
17813
|
setupHeadroom;
|
|
17536
17814
|
relay = null;
|
|
17537
17815
|
heartbeatTimer = null;
|
|
17816
|
+
/** Periodic self-update timer (npm check + install + restart). */
|
|
17817
|
+
selfUpdateTimer = null;
|
|
17818
|
+
/** Self-update check + install (injectable; defaults to runSelfUpdate). */
|
|
17819
|
+
selfUpdate;
|
|
17820
|
+
/** Restart action after a successful self-update (defaults to process.exit). */
|
|
17821
|
+
onUpdated;
|
|
17822
|
+
/** Guards against overlapping self-update ticks (a slow npm install). */
|
|
17823
|
+
selfUpdating = false;
|
|
17824
|
+
/**
|
|
17825
|
+
* Set once a self-update installed a newer version but a child was busy,
|
|
17826
|
+
* so the next idle tick restarts WITHOUT re-installing. Carries the
|
|
17827
|
+
* already-installed version for the restart log.
|
|
17828
|
+
*/
|
|
17829
|
+
pendingRestartVersion = null;
|
|
17538
17830
|
/** Guards the one-shot 'connected' telemetry on the first heartbeat. */
|
|
17539
17831
|
reportedConnected = false;
|
|
17540
17832
|
/** Live-metrics collector — stateful across beats (CPU delta + latency). */
|
|
@@ -17545,6 +17837,19 @@ var HostAgentSupervisor = class {
|
|
|
17545
17837
|
disableService;
|
|
17546
17838
|
/** Guards against firing the self-heal more than once. */
|
|
17547
17839
|
healing = false;
|
|
17840
|
+
/**
|
|
17841
|
+
* Resolve the self-update interval, honoring `CODEAM_HOST_SELF_UPDATE_MS`.
|
|
17842
|
+
* A finite value > 0 overrides the default; 0 or negative DISABLES the
|
|
17843
|
+
* periodic self-update (tests / pinned boxes); a non-numeric/absent value
|
|
17844
|
+
* falls back to {@link SELF_UPDATE_INTERVAL_MS}.
|
|
17845
|
+
*/
|
|
17846
|
+
selfUpdateIntervalMs() {
|
|
17847
|
+
const raw = process.env.CODEAM_HOST_SELF_UPDATE_MS;
|
|
17848
|
+
if (raw === void 0 || raw === "") return SELF_UPDATE_INTERVAL_MS;
|
|
17849
|
+
const parsed = Number(raw);
|
|
17850
|
+
if (!Number.isFinite(parsed)) return SELF_UPDATE_INTERVAL_MS;
|
|
17851
|
+
return parsed;
|
|
17852
|
+
}
|
|
17548
17853
|
/** Open the control channel (reusing the relay) + start heartbeats. */
|
|
17549
17854
|
start() {
|
|
17550
17855
|
const make = this.deps.makeRelay ?? ((pluginId, onCommand, meta) => new CommandRelayService(pluginId, onCommand, meta));
|
|
@@ -17557,6 +17862,13 @@ var HostAgentSupervisor = class {
|
|
|
17557
17862
|
void this.beat();
|
|
17558
17863
|
this.heartbeatTimer = setInterval(() => void this.beat(), HEARTBEAT_INTERVAL_MS);
|
|
17559
17864
|
this.heartbeatTimer.unref?.();
|
|
17865
|
+
const updateMs = this.selfUpdateIntervalMs();
|
|
17866
|
+
if (updateMs > 0) {
|
|
17867
|
+
this.selfUpdateTimer = setInterval(() => void this.selfUpdateTick(), updateMs);
|
|
17868
|
+
this.selfUpdateTimer.unref?.();
|
|
17869
|
+
} else {
|
|
17870
|
+
log.info("host-agent", "self-update disabled (CODEAM_HOST_SELF_UPDATE_MS<=0)");
|
|
17871
|
+
}
|
|
17560
17872
|
log.info("host-agent", `supervisor up host=${this.identity.hostId.slice(0, 8)}`);
|
|
17561
17873
|
}
|
|
17562
17874
|
/** Stop the control channel + heartbeats + kill every child. */
|
|
@@ -17565,6 +17877,10 @@ var HostAgentSupervisor = class {
|
|
|
17565
17877
|
clearInterval(this.heartbeatTimer);
|
|
17566
17878
|
this.heartbeatTimer = null;
|
|
17567
17879
|
}
|
|
17880
|
+
if (this.selfUpdateTimer) {
|
|
17881
|
+
clearInterval(this.selfUpdateTimer);
|
|
17882
|
+
this.selfUpdateTimer = null;
|
|
17883
|
+
}
|
|
17568
17884
|
this.relay?.stop();
|
|
17569
17885
|
for (const child of this.children.values()) {
|
|
17570
17886
|
try {
|
|
@@ -17582,7 +17898,8 @@ var HostAgentSupervisor = class {
|
|
|
17582
17898
|
} catch (err) {
|
|
17583
17899
|
log.trace("host-agent", "metrics collection failed", err);
|
|
17584
17900
|
}
|
|
17585
|
-
const
|
|
17901
|
+
const sessions3 = this.activeSessions();
|
|
17902
|
+
const latencyMs = await sendHostHeartbeat(this.identity, metrics, sessions3);
|
|
17586
17903
|
this.metrics.recordLatency(latencyMs);
|
|
17587
17904
|
if (!this.reportedConnected) {
|
|
17588
17905
|
this.reportedConnected = true;
|
|
@@ -17604,10 +17921,81 @@ var HostAgentSupervisor = class {
|
|
|
17604
17921
|
log.trace("host-agent", "heartbeat failed", err);
|
|
17605
17922
|
}
|
|
17606
17923
|
}
|
|
17924
|
+
/**
|
|
17925
|
+
* One self-update tick. Best-effort + never crashes the supervisor: the
|
|
17926
|
+
* whole body is wrapped in try/catch and the injected updater never
|
|
17927
|
+
* rejects. Sequence:
|
|
17928
|
+
*
|
|
17929
|
+
* 1. If a restart is already PENDING (a prior tick installed a newer
|
|
17930
|
+
* version while a child was busy), skip the npm work and just try to
|
|
17931
|
+
* restart now — no re-install.
|
|
17932
|
+
* 2. Otherwise run the injected `selfUpdate`. On `'updated'`, remember
|
|
17933
|
+
* the new version as pending; on anything else, do nothing.
|
|
17934
|
+
* 3. SAFETY: only restart when no child turn is in flight. If a child is
|
|
17935
|
+
* mid-work, DEFER — the install already happened, so a later idle
|
|
17936
|
+
* tick just restarts. (We prefer deferring to yanking an active turn;
|
|
17937
|
+
* systemd would restart in ~5s but the mobile would drop the turn.)
|
|
17938
|
+
*
|
|
17939
|
+
* `selfUpdating` guards against a slow npm install overlapping the next
|
|
17940
|
+
* tick (the timer keeps firing on its interval).
|
|
17941
|
+
*/
|
|
17942
|
+
async selfUpdateTick() {
|
|
17943
|
+
if (this.selfUpdating) return;
|
|
17944
|
+
this.selfUpdating = true;
|
|
17945
|
+
try {
|
|
17946
|
+
if (this.pendingRestartVersion !== null) {
|
|
17947
|
+
this.maybeRestartForUpdate(this.pendingRestartVersion);
|
|
17948
|
+
return;
|
|
17949
|
+
}
|
|
17950
|
+
const result = await this.selfUpdate();
|
|
17951
|
+
if (result.status !== "updated") return;
|
|
17952
|
+
const version3 = result.version ?? "latest";
|
|
17953
|
+
this.pendingRestartVersion = version3;
|
|
17954
|
+
this.maybeRestartForUpdate(version3);
|
|
17955
|
+
} catch (err) {
|
|
17956
|
+
log.warn(
|
|
17957
|
+
"host-agent",
|
|
17958
|
+
`self-update tick failed: ${err instanceof Error ? err.message : String(err)}`
|
|
17959
|
+
);
|
|
17960
|
+
} finally {
|
|
17961
|
+
this.selfUpdating = false;
|
|
17962
|
+
}
|
|
17963
|
+
}
|
|
17964
|
+
/**
|
|
17965
|
+
* Restart for an already-installed update IFF no child turn is in flight.
|
|
17966
|
+
* When a child is busy we DEFER (the version stays pending for the next
|
|
17967
|
+
* idle tick) rather than yank an active turn.
|
|
17968
|
+
*/
|
|
17969
|
+
maybeRestartForUpdate(version3) {
|
|
17970
|
+
if (this.children.size > 0) {
|
|
17971
|
+
log.info(
|
|
17972
|
+
"host-agent",
|
|
17973
|
+
`self-update: ${version3} installed but ${this.children.size} child(ren) busy \u2014 deferring restart`
|
|
17974
|
+
);
|
|
17975
|
+
return;
|
|
17976
|
+
}
|
|
17977
|
+
this.onUpdated(version3);
|
|
17978
|
+
}
|
|
17607
17979
|
/** Number of live children — for tests + diagnostics. */
|
|
17608
17980
|
childCount() {
|
|
17609
17981
|
return this.children.size;
|
|
17610
17982
|
}
|
|
17983
|
+
/**
|
|
17984
|
+
* Snapshot the supervisor's live children as heartbeat session entries.
|
|
17985
|
+
*
|
|
17986
|
+
* Each entry's `id` is the deployId-correlated sessionId the backend
|
|
17987
|
+
* recognizes (the supervisor keys its children by it — the same id a
|
|
17988
|
+
* `self_hosted_stop` arrives with, see `stopChild`). `agent` is the deploy's
|
|
17989
|
+
* `agentId`; `startedAt` is the epoch-ms spawn time tracked on the child.
|
|
17990
|
+
* Returns `[]` when no children are active so the backend reflects "0 active".
|
|
17991
|
+
*/
|
|
17992
|
+
activeSessions() {
|
|
17993
|
+
return [...this.children.values()].map((child) => ({
|
|
17994
|
+
id: child.deployId,
|
|
17995
|
+
agent: child.agent,
|
|
17996
|
+
startedAt: child.startedAt
|
|
17997
|
+
}));
|
|
17998
|
+
}
|
|
17611
17999
|
/**
|
|
17612
18000
|
* Route a relay command. Only `self_hosted_deploy` / `self_hosted_stop`
|
|
17613
18001
|
* are understood; anything else is ignored (the box accepts no
|
|
@@ -17699,7 +18087,7 @@ var HostAgentSupervisor = class {
|
|
|
17699
18087
|
report("installing", "installing agent CLI");
|
|
17700
18088
|
await this.runAgentInstall(payload.agentInstallScript);
|
|
17701
18089
|
}
|
|
17702
|
-
const home = process.env.HOME ||
|
|
18090
|
+
const home = process.env.HOME || os32.homedir();
|
|
17703
18091
|
childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
|
|
17704
18092
|
if (payload.previewTunnelToken && payload.previewHostname) {
|
|
17705
18093
|
childEnv.PREVIEW_TUNNEL_TOKEN = payload.previewTunnelToken;
|
|
@@ -17709,17 +18097,27 @@ var HostAgentSupervisor = class {
|
|
|
17709
18097
|
report("headroom", "setting up Headroom proxy");
|
|
17710
18098
|
const headroomOk = await this.setupHeadroom(payload.headroomAgent);
|
|
17711
18099
|
if (headroomOk) {
|
|
17712
|
-
|
|
17713
|
-
|
|
17714
|
-
|
|
17715
|
-
|
|
18100
|
+
persistHeadroomConfig({
|
|
18101
|
+
enabled: true,
|
|
18102
|
+
agent: agentIdToHeadroomKind(payload.headroomAgent),
|
|
18103
|
+
ingestUrl: payload.headroomSavingsIngestUrl
|
|
18104
|
+
});
|
|
18105
|
+
log.info("host-agent", "Headroom proxy ready; persisted headroom config for child spawns");
|
|
17716
18106
|
} else {
|
|
18107
|
+
persistHeadroomConfig({ enabled: false });
|
|
17717
18108
|
log.warn("host-agent", "Headroom setup failed (best-effort) \u2014 child will run without Headroom");
|
|
17718
18109
|
}
|
|
18110
|
+
} else if (payload.headroomEnabled === false) {
|
|
18111
|
+
persistHeadroomConfig({ enabled: false });
|
|
17719
18112
|
}
|
|
17720
18113
|
report("spawning", "starting agent");
|
|
17721
|
-
const proc = this.
|
|
17722
|
-
const child = {
|
|
18114
|
+
const proc = this.spawnSessionChild(childEnv, cwd, extraArgs);
|
|
18115
|
+
const child = {
|
|
18116
|
+
deployId: payload.deployId,
|
|
18117
|
+
proc,
|
|
18118
|
+
agent: payload.agentId,
|
|
18119
|
+
startedAt: Date.now()
|
|
18120
|
+
};
|
|
17723
18121
|
this.children.set(payload.deployId, child);
|
|
17724
18122
|
let tail = "";
|
|
17725
18123
|
const appendTail = (buf) => {
|
|
@@ -17752,6 +18150,20 @@ var HostAgentSupervisor = class {
|
|
|
17752
18150
|
report("failed", message);
|
|
17753
18151
|
}
|
|
17754
18152
|
}
|
|
18153
|
+
/**
|
|
18154
|
+
* Spawn a supervised `pair-auto` session child, merging the persisted
|
|
18155
|
+
* Headroom env on top of the caller's env. This is the SINGLE spawn site for
|
|
18156
|
+
* session children: the fresh-deploy path and any future resume / restart
|
|
18157
|
+
* path both go through here, so the HEADROOM_* env (read from
|
|
18158
|
+
* `~/.codeam/headroom-config.json`, the source of truth a prior deploy wrote)
|
|
18159
|
+
* is injected on EVERY spawn — reporting survives session resumes and
|
|
18160
|
+
* supervisor restarts (systemd / periodic self-update), not just fresh
|
|
18161
|
+
* deploys. `readHeadroomChildEnv()` returns `{}` when Headroom is disabled or
|
|
18162
|
+
* was never set up, so this is a no-op there (never-break).
|
|
18163
|
+
*/
|
|
18164
|
+
spawnSessionChild(env, cwd, args2 = []) {
|
|
18165
|
+
return this.spawnChild({ ...env, ...readHeadroomChildEnv() }, cwd, args2);
|
|
18166
|
+
}
|
|
17755
18167
|
/**
|
|
17756
18168
|
* Run the backend-supplied per-agent CLI install script (e.g.
|
|
17757
18169
|
* `claude.ai/install.sh`, `npm i -g @openai/codex`). Best-effort + bounded:
|
|
@@ -17763,8 +18175,8 @@ var HostAgentSupervisor = class {
|
|
|
17763
18175
|
*/
|
|
17764
18176
|
runAgentInstall(script) {
|
|
17765
18177
|
return new Promise((resolve7) => {
|
|
17766
|
-
const home = process.env.HOME ||
|
|
17767
|
-
const child = (0,
|
|
18178
|
+
const home = process.env.HOME || os32.homedir();
|
|
18179
|
+
const child = (0, import_node_child_process13.spawn)("sh", ["-c", script], {
|
|
17768
18180
|
env: { ...process.env, HOME: home },
|
|
17769
18181
|
stdio: ["ignore", "pipe", "pipe"]
|
|
17770
18182
|
});
|
|
@@ -17888,12 +18300,12 @@ function readTokenFromArgs(args2) {
|
|
|
17888
18300
|
}
|
|
17889
18301
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
17890
18302
|
if (fileFlag) {
|
|
17891
|
-
const
|
|
18303
|
+
const path59 = fileFlag.slice("--token-file=".length);
|
|
17892
18304
|
try {
|
|
17893
|
-
const content =
|
|
17894
|
-
if (content.length === 0) fail(`--token-file ${
|
|
18305
|
+
const content = fs40.readFileSync(path59, "utf8").trim();
|
|
18306
|
+
if (content.length === 0) fail(`--token-file ${path59} is empty`);
|
|
17895
18307
|
try {
|
|
17896
|
-
|
|
18308
|
+
fs40.unlinkSync(path59);
|
|
17897
18309
|
} catch {
|
|
17898
18310
|
}
|
|
17899
18311
|
return content;
|
|
@@ -17919,7 +18331,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
|
|
|
17919
18331
|
pluginId,
|
|
17920
18332
|
ideName: "codeam-cli (codespace)",
|
|
17921
18333
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
17922
|
-
hostname:
|
|
18334
|
+
hostname: os33.hostname(),
|
|
17923
18335
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
17924
18336
|
// Current git branch of the codespace's working directory, so the
|
|
17925
18337
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -17980,7 +18392,7 @@ async function claim(token, pluginId, pluginSecretHash) {
|
|
|
17980
18392
|
}
|
|
17981
18393
|
}
|
|
17982
18394
|
function pairAutoLockPath() {
|
|
17983
|
-
return
|
|
18395
|
+
return path46.join(os33.homedir(), ".codeam", "pair-auto.lock");
|
|
17984
18396
|
}
|
|
17985
18397
|
function isLivePairAuto(pid) {
|
|
17986
18398
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -17990,7 +18402,7 @@ function isLivePairAuto(pid) {
|
|
|
17990
18402
|
if (e.code !== "EPERM") return false;
|
|
17991
18403
|
}
|
|
17992
18404
|
try {
|
|
17993
|
-
return
|
|
18405
|
+
return fs40.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
|
|
17994
18406
|
} catch {
|
|
17995
18407
|
return true;
|
|
17996
18408
|
}
|
|
@@ -18000,24 +18412,24 @@ function isLiveCodeam(pid) {
|
|
|
18000
18412
|
}
|
|
18001
18413
|
function daemonLockPath(sessionId) {
|
|
18002
18414
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
18003
|
-
return
|
|
18415
|
+
return path46.join(os33.homedir(), ".codeam", `daemon-${safe}.lock`);
|
|
18004
18416
|
}
|
|
18005
18417
|
function acquireDaemonLock(sessionId) {
|
|
18006
18418
|
const lockPath = daemonLockPath(sessionId);
|
|
18007
18419
|
try {
|
|
18008
|
-
|
|
18420
|
+
fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
|
|
18009
18421
|
try {
|
|
18010
|
-
|
|
18422
|
+
fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
18011
18423
|
} catch (e) {
|
|
18012
18424
|
if (e.code !== "EEXIST") throw e;
|
|
18013
|
-
const holder = Number(
|
|
18425
|
+
const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
|
|
18014
18426
|
if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
|
|
18015
|
-
|
|
18427
|
+
fs40.writeFileSync(lockPath, String(process.pid));
|
|
18016
18428
|
}
|
|
18017
18429
|
const release3 = () => {
|
|
18018
18430
|
try {
|
|
18019
|
-
if (
|
|
18020
|
-
|
|
18431
|
+
if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
18432
|
+
fs40.unlinkSync(lockPath);
|
|
18021
18433
|
}
|
|
18022
18434
|
} catch {
|
|
18023
18435
|
}
|
|
@@ -18039,19 +18451,19 @@ function acquireDaemonLock(sessionId) {
|
|
|
18039
18451
|
function acquireSingletonLock() {
|
|
18040
18452
|
const lockPath = pairAutoLockPath();
|
|
18041
18453
|
try {
|
|
18042
|
-
|
|
18454
|
+
fs40.mkdirSync(path46.dirname(lockPath), { recursive: true });
|
|
18043
18455
|
try {
|
|
18044
|
-
|
|
18456
|
+
fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
18045
18457
|
} catch (e) {
|
|
18046
18458
|
if (e.code !== "EEXIST") throw e;
|
|
18047
|
-
const holder = Number(
|
|
18459
|
+
const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
|
|
18048
18460
|
if (isLivePairAuto(holder)) return false;
|
|
18049
|
-
|
|
18461
|
+
fs40.writeFileSync(lockPath, String(process.pid));
|
|
18050
18462
|
}
|
|
18051
18463
|
process.once("exit", () => {
|
|
18052
18464
|
try {
|
|
18053
|
-
if (
|
|
18054
|
-
|
|
18465
|
+
if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
18466
|
+
fs40.unlinkSync(lockPath);
|
|
18055
18467
|
}
|
|
18056
18468
|
} catch {
|
|
18057
18469
|
}
|
|
@@ -18133,7 +18545,7 @@ async function pairAuto(args2) {
|
|
|
18133
18545
|
}
|
|
18134
18546
|
|
|
18135
18547
|
// src/services/headroom/wrap-launch.ts
|
|
18136
|
-
var
|
|
18548
|
+
var import_node_child_process14 = require("child_process");
|
|
18137
18549
|
function wrapWithHeadroom(launch, opts) {
|
|
18138
18550
|
if (!opts.enabled || !opts.headroomPresent) return launch;
|
|
18139
18551
|
return {
|
|
@@ -18146,7 +18558,7 @@ var _present;
|
|
|
18146
18558
|
function headroomPresent() {
|
|
18147
18559
|
if (_present !== void 0) return Promise.resolve(_present);
|
|
18148
18560
|
return new Promise((resolve7) => {
|
|
18149
|
-
(0,
|
|
18561
|
+
(0, import_node_child_process14.execFile)("headroom", ["--version"], (err) => {
|
|
18150
18562
|
_present = !err;
|
|
18151
18563
|
resolve7(_present);
|
|
18152
18564
|
});
|
|
@@ -18496,19 +18908,19 @@ var AgentService = class _AgentService {
|
|
|
18496
18908
|
};
|
|
18497
18909
|
|
|
18498
18910
|
// src/agents/acp/adapters.ts
|
|
18499
|
-
var
|
|
18911
|
+
var path47 = __toESM(require("path"));
|
|
18500
18912
|
var require_ = require;
|
|
18501
18913
|
function resolveBin(pkgName, binName) {
|
|
18502
18914
|
try {
|
|
18503
18915
|
const manifestPath = require_.resolve(`${pkgName}/package.json`);
|
|
18504
18916
|
const manifest = require_(`${pkgName}/package.json`);
|
|
18505
|
-
const pkgDir =
|
|
18917
|
+
const pkgDir = path47.dirname(manifestPath);
|
|
18506
18918
|
const bin = manifest.bin;
|
|
18507
18919
|
if (!bin) return null;
|
|
18508
|
-
if (typeof bin === "string") return
|
|
18920
|
+
if (typeof bin === "string") return path47.resolve(pkgDir, bin);
|
|
18509
18921
|
const target = binName ?? Object.keys(bin)[0];
|
|
18510
18922
|
if (!target || !bin[target]) return null;
|
|
18511
|
-
return
|
|
18923
|
+
return path47.resolve(pkgDir, bin[target]);
|
|
18512
18924
|
} catch {
|
|
18513
18925
|
return null;
|
|
18514
18926
|
}
|
|
@@ -18584,11 +18996,11 @@ function requiresAcp(agent) {
|
|
|
18584
18996
|
var import_node_crypto7 = require("crypto");
|
|
18585
18997
|
|
|
18586
18998
|
// src/agents/acp/client.ts
|
|
18587
|
-
var
|
|
18588
|
-
var
|
|
18999
|
+
var import_node_child_process15 = require("child_process");
|
|
19000
|
+
var fs41 = __toESM(require("fs/promises"));
|
|
18589
19001
|
var fsSync = __toESM(require("fs"));
|
|
18590
|
-
var
|
|
18591
|
-
var
|
|
19002
|
+
var os34 = __toESM(require("os"));
|
|
19003
|
+
var path48 = __toESM(require("path"));
|
|
18592
19004
|
var import_node_stream = require("stream");
|
|
18593
19005
|
|
|
18594
19006
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -21125,7 +21537,7 @@ var AcpClient = class {
|
|
|
21125
21537
|
"acpClient",
|
|
21126
21538
|
`spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
|
|
21127
21539
|
);
|
|
21128
|
-
const child = (0,
|
|
21540
|
+
const child = (0, import_node_child_process15.spawn)(adapter.command, adapter.args, {
|
|
21129
21541
|
cwd,
|
|
21130
21542
|
env: { ...process.env, PATH: augmentedPath },
|
|
21131
21543
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -21375,7 +21787,7 @@ var AcpClient = class {
|
|
|
21375
21787
|
},
|
|
21376
21788
|
readTextFile: async (params) => {
|
|
21377
21789
|
try {
|
|
21378
|
-
const content = await
|
|
21790
|
+
const content = await fs41.readFile(params.path, "utf8");
|
|
21379
21791
|
return applyLineRange(content, params.line ?? null, params.limit ?? null);
|
|
21380
21792
|
} catch (err) {
|
|
21381
21793
|
const code = err.code;
|
|
@@ -21395,7 +21807,7 @@ var AcpClient = class {
|
|
|
21395
21807
|
},
|
|
21396
21808
|
writeTextFile: async (params) => {
|
|
21397
21809
|
try {
|
|
21398
|
-
await
|
|
21810
|
+
await fs41.writeFile(params.path, params.content, "utf8");
|
|
21399
21811
|
return {};
|
|
21400
21812
|
} catch (err) {
|
|
21401
21813
|
const code = err.code;
|
|
@@ -21444,25 +21856,25 @@ function applyLineRange(content, line, limit) {
|
|
|
21444
21856
|
return { content: lines.slice(start2, end).join("\n") };
|
|
21445
21857
|
}
|
|
21446
21858
|
function knownAgentBinaryDirs() {
|
|
21447
|
-
const home =
|
|
21859
|
+
const home = os34.homedir();
|
|
21448
21860
|
const out2 = [];
|
|
21449
21861
|
out2.push("/tmp/codeam-node20/bin");
|
|
21450
21862
|
for (const root of [
|
|
21451
21863
|
"/usr/local/share/nvm/versions/node",
|
|
21452
|
-
|
|
21864
|
+
path48.join(home, ".nvm/versions/node")
|
|
21453
21865
|
]) {
|
|
21454
21866
|
try {
|
|
21455
21867
|
for (const child of fsSync.readdirSync(root)) {
|
|
21456
|
-
out2.push(
|
|
21868
|
+
out2.push(path48.join(root, child, "bin"));
|
|
21457
21869
|
}
|
|
21458
21870
|
} catch {
|
|
21459
21871
|
}
|
|
21460
21872
|
}
|
|
21461
|
-
out2.push(
|
|
21873
|
+
out2.push(path48.join(home, ".volta/bin"));
|
|
21462
21874
|
out2.push("/usr/local/bin");
|
|
21463
21875
|
out2.push("/usr/bin");
|
|
21464
|
-
out2.push(
|
|
21465
|
-
out2.push(
|
|
21876
|
+
out2.push(path48.join(home, ".local/bin"));
|
|
21877
|
+
out2.push(path48.join(home, "bin"));
|
|
21466
21878
|
return out2.filter((p2) => {
|
|
21467
21879
|
try {
|
|
21468
21880
|
return fsSync.statSync(p2).isDirectory();
|
|
@@ -21473,7 +21885,7 @@ function knownAgentBinaryDirs() {
|
|
|
21473
21885
|
}
|
|
21474
21886
|
function expandPathForAgentBinaries(existingPath) {
|
|
21475
21887
|
const existing = new Set(
|
|
21476
|
-
existingPath.split(
|
|
21888
|
+
existingPath.split(path48.delimiter).filter((p2) => p2.length > 0)
|
|
21477
21889
|
);
|
|
21478
21890
|
const additions = [];
|
|
21479
21891
|
for (const dir of knownAgentBinaryDirs()) {
|
|
@@ -21483,12 +21895,12 @@ function expandPathForAgentBinaries(existingPath) {
|
|
|
21483
21895
|
}
|
|
21484
21896
|
}
|
|
21485
21897
|
if (additions.length === 0) return existingPath;
|
|
21486
|
-
return [...additions, existingPath].filter((p2) => p2.length > 0).join(
|
|
21898
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path48.delimiter);
|
|
21487
21899
|
}
|
|
21488
21900
|
|
|
21489
21901
|
// src/services/streaming/transport.ts
|
|
21490
21902
|
var http6 = __toESM(require("http"));
|
|
21491
|
-
var
|
|
21903
|
+
var https7 = __toESM(require("https"));
|
|
21492
21904
|
var _transport4 = {
|
|
21493
21905
|
post: _post3,
|
|
21494
21906
|
get: _get
|
|
@@ -21497,7 +21909,7 @@ function _post3(url, headers, payload) {
|
|
|
21497
21909
|
return new Promise((resolve7, reject) => {
|
|
21498
21910
|
let settled = false;
|
|
21499
21911
|
const u2 = new URL(url);
|
|
21500
|
-
const lib = u2.protocol === "https:" ?
|
|
21912
|
+
const lib = u2.protocol === "https:" ? https7 : http6;
|
|
21501
21913
|
const req = lib.request(
|
|
21502
21914
|
{
|
|
21503
21915
|
hostname: u2.hostname,
|
|
@@ -21539,7 +21951,7 @@ function _get(url, headers) {
|
|
|
21539
21951
|
return new Promise((resolve7, reject) => {
|
|
21540
21952
|
let settled = false;
|
|
21541
21953
|
const u2 = new URL(url);
|
|
21542
|
-
const lib = u2.protocol === "https:" ?
|
|
21954
|
+
const lib = u2.protocol === "https:" ? https7 : http6;
|
|
21543
21955
|
const req = lib.request(
|
|
21544
21956
|
{
|
|
21545
21957
|
hostname: u2.hostname,
|
|
@@ -21810,15 +22222,15 @@ function reconcileCumulative(existing, incoming) {
|
|
|
21810
22222
|
}
|
|
21811
22223
|
|
|
21812
22224
|
// src/agents/acp/onboarding.ts
|
|
21813
|
-
var
|
|
21814
|
-
var
|
|
21815
|
-
var
|
|
22225
|
+
var fs42 = __toESM(require("fs"));
|
|
22226
|
+
var os35 = __toESM(require("os"));
|
|
22227
|
+
var path49 = __toESM(require("path"));
|
|
21816
22228
|
var _onboardingSeam = {
|
|
21817
|
-
markerPath: (sessionId) =>
|
|
21818
|
-
exists: (p2) =>
|
|
22229
|
+
markerPath: (sessionId) => path49.join(os35.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
|
|
22230
|
+
exists: (p2) => fs42.existsSync(p2),
|
|
21819
22231
|
write: (p2) => {
|
|
21820
|
-
|
|
21821
|
-
|
|
22232
|
+
fs42.mkdirSync(path49.dirname(p2), { recursive: true });
|
|
22233
|
+
fs42.writeFileSync(p2, "");
|
|
21822
22234
|
},
|
|
21823
22235
|
disabled: () => {
|
|
21824
22236
|
const v = process.env.CODEAM_ONBOARDING_DISABLED;
|
|
@@ -21826,7 +22238,7 @@ var _onboardingSeam = {
|
|
|
21826
22238
|
}
|
|
21827
22239
|
};
|
|
21828
22240
|
function buildOnboardingWelcome(cwd) {
|
|
21829
|
-
const repo =
|
|
22241
|
+
const repo = path49.basename(cwd || "") || "this project";
|
|
21830
22242
|
return [
|
|
21831
22243
|
`Welcome to CodeAgent Mobile! \u{1F44B} You're now driving this agent from your phone \u2014 and it comes fully wired, zero setup:`,
|
|
21832
22244
|
"",
|
|
@@ -22086,8 +22498,8 @@ var import_crypto5 = require("crypto");
|
|
|
22086
22498
|
|
|
22087
22499
|
// src/services/turn-files/git-changeset.ts
|
|
22088
22500
|
var import_child_process22 = require("child_process");
|
|
22089
|
-
var
|
|
22090
|
-
var
|
|
22501
|
+
var fs43 = __toESM(require("fs/promises"));
|
|
22502
|
+
var path50 = __toESM(require("path"));
|
|
22091
22503
|
async function collectRepoChangeset(opts) {
|
|
22092
22504
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
22093
22505
|
if (status2 === null) return null;
|
|
@@ -22105,7 +22517,7 @@ async function collectRepoChangeset(opts) {
|
|
|
22105
22517
|
let stats;
|
|
22106
22518
|
if (row.fileStatus === "added" && numstatEntry === void 0) {
|
|
22107
22519
|
const lineCount = await readUntrackedLineCount(
|
|
22108
|
-
|
|
22520
|
+
path50.join(opts.repoRoot, row.filePath)
|
|
22109
22521
|
);
|
|
22110
22522
|
stats = { added: lineCount, removed: 0 };
|
|
22111
22523
|
} else {
|
|
@@ -22136,7 +22548,7 @@ function readUntrackedLineCount(absPath) {
|
|
|
22136
22548
|
}
|
|
22137
22549
|
async function defaultReadUntrackedLineCount(absPath) {
|
|
22138
22550
|
try {
|
|
22139
|
-
const content = await
|
|
22551
|
+
const content = await fs43.readFile(absPath, "utf8");
|
|
22140
22552
|
let count = 0;
|
|
22141
22553
|
let pos = -1;
|
|
22142
22554
|
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
|
|
@@ -22228,7 +22640,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
22228
22640
|
});
|
|
22229
22641
|
}
|
|
22230
22642
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
22231
|
-
const
|
|
22643
|
+
const fs48 = await import("fs/promises");
|
|
22232
22644
|
const out2 = [];
|
|
22233
22645
|
await walk(workingDir, 0);
|
|
22234
22646
|
return out2;
|
|
@@ -22236,7 +22648,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22236
22648
|
if (depth > maxDepth) return;
|
|
22237
22649
|
let entries = [];
|
|
22238
22650
|
try {
|
|
22239
|
-
const dirents = await
|
|
22651
|
+
const dirents = await fs48.readdir(dir, { withFileTypes: true });
|
|
22240
22652
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
22241
22653
|
} catch {
|
|
22242
22654
|
return;
|
|
@@ -22247,8 +22659,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22247
22659
|
if (hasGit) {
|
|
22248
22660
|
out2.push({
|
|
22249
22661
|
repoRoot: dir,
|
|
22250
|
-
repoPath:
|
|
22251
|
-
repoName:
|
|
22662
|
+
repoPath: path50.relative(workingDir, dir),
|
|
22663
|
+
repoName: path50.basename(dir)
|
|
22252
22664
|
});
|
|
22253
22665
|
return;
|
|
22254
22666
|
}
|
|
@@ -22256,14 +22668,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
22256
22668
|
if (!entry.isDirectory) continue;
|
|
22257
22669
|
if (entry.name === "node_modules") continue;
|
|
22258
22670
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
22259
|
-
await walk(
|
|
22671
|
+
await walk(path50.join(dir, entry.name), depth + 1);
|
|
22260
22672
|
}
|
|
22261
22673
|
}
|
|
22262
22674
|
}
|
|
22263
22675
|
|
|
22264
22676
|
// src/services/turn-files/files-outbox.ts
|
|
22265
|
-
var
|
|
22266
|
-
var
|
|
22677
|
+
var fs44 = __toESM(require("fs/promises"));
|
|
22678
|
+
var path51 = __toESM(require("path"));
|
|
22267
22679
|
var import_os7 = require("os");
|
|
22268
22680
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
22269
22681
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -22296,16 +22708,16 @@ var FilesOutbox = class {
|
|
|
22296
22708
|
backoffIndex = 0;
|
|
22297
22709
|
stopped = false;
|
|
22298
22710
|
constructor(opts) {
|
|
22299
|
-
const base = opts.baseDir ??
|
|
22300
|
-
this.filePath =
|
|
22711
|
+
const base = opts.baseDir ?? path51.join(homeDir(), HOME_OUTBOX_DIR);
|
|
22712
|
+
this.filePath = path51.join(base, `${opts.sessionId}.jsonl`);
|
|
22301
22713
|
this.post = opts.post;
|
|
22302
22714
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
22303
22715
|
}
|
|
22304
22716
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
22305
22717
|
* line is durable on disk (not once the POST succeeds). */
|
|
22306
22718
|
async enqueue(entry) {
|
|
22307
|
-
await
|
|
22308
|
-
await
|
|
22719
|
+
await fs44.mkdir(path51.dirname(this.filePath), { recursive: true });
|
|
22720
|
+
await fs44.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
22309
22721
|
this.backoffIndex = 0;
|
|
22310
22722
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
22311
22723
|
}
|
|
@@ -22394,7 +22806,7 @@ var FilesOutbox = class {
|
|
|
22394
22806
|
async readAll() {
|
|
22395
22807
|
let raw = "";
|
|
22396
22808
|
try {
|
|
22397
|
-
raw = await
|
|
22809
|
+
raw = await fs44.readFile(this.filePath, "utf8");
|
|
22398
22810
|
} catch {
|
|
22399
22811
|
return [];
|
|
22400
22812
|
}
|
|
@@ -22418,12 +22830,12 @@ var FilesOutbox = class {
|
|
|
22418
22830
|
async rewrite(entries) {
|
|
22419
22831
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
22420
22832
|
if (entries.length === 0) {
|
|
22421
|
-
await
|
|
22833
|
+
await fs44.unlink(this.filePath).catch(() => void 0);
|
|
22422
22834
|
return;
|
|
22423
22835
|
}
|
|
22424
22836
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
22425
|
-
await
|
|
22426
|
-
await
|
|
22837
|
+
await fs44.writeFile(tmpPath, payload, "utf8");
|
|
22838
|
+
await fs44.rename(tmpPath, this.filePath);
|
|
22427
22839
|
}
|
|
22428
22840
|
};
|
|
22429
22841
|
function applyJitter(ms) {
|
|
@@ -24154,10 +24566,10 @@ var OutputService = class _OutputService {
|
|
|
24154
24566
|
};
|
|
24155
24567
|
|
|
24156
24568
|
// src/services/history.service.ts
|
|
24157
|
-
var
|
|
24158
|
-
var
|
|
24159
|
-
var
|
|
24160
|
-
var
|
|
24569
|
+
var fs45 = __toESM(require("fs"));
|
|
24570
|
+
var path52 = __toESM(require("path"));
|
|
24571
|
+
var os36 = __toESM(require("os"));
|
|
24572
|
+
var https8 = __toESM(require("https"));
|
|
24161
24573
|
var http7 = __toESM(require("http"));
|
|
24162
24574
|
var import_zod2 = require("zod");
|
|
24163
24575
|
var historyRecordSchema = import_zod2.z.object({
|
|
@@ -24183,7 +24595,7 @@ function parseJsonl(filePath) {
|
|
|
24183
24595
|
const messages = [];
|
|
24184
24596
|
let raw;
|
|
24185
24597
|
try {
|
|
24186
|
-
raw =
|
|
24598
|
+
raw = fs45.readFileSync(filePath, "utf8");
|
|
24187
24599
|
} catch (err) {
|
|
24188
24600
|
if (err.code !== "ENOENT") {
|
|
24189
24601
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -24223,7 +24635,7 @@ function post(endpoint, body, pluginAuthToken) {
|
|
|
24223
24635
|
return new Promise((resolve7) => {
|
|
24224
24636
|
const payload = JSON.stringify(body);
|
|
24225
24637
|
const u2 = new URL(`${API_BASE9}${endpoint}`);
|
|
24226
|
-
const transport = u2.protocol === "https:" ?
|
|
24638
|
+
const transport = u2.protocol === "https:" ? https8 : http7;
|
|
24227
24639
|
const req = transport.request(
|
|
24228
24640
|
{
|
|
24229
24641
|
hostname: u2.hostname,
|
|
@@ -24324,7 +24736,7 @@ var HistoryService = class _HistoryService {
|
|
|
24324
24736
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
24325
24737
|
}
|
|
24326
24738
|
get projectDir() {
|
|
24327
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
24739
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path52.join(os36.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
24328
24740
|
}
|
|
24329
24741
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
24330
24742
|
setCurrentConversationId(id) {
|
|
@@ -24336,7 +24748,7 @@ var HistoryService = class _HistoryService {
|
|
|
24336
24748
|
/** Return the current message count in the active conversation. */
|
|
24337
24749
|
getCurrentMessageCount() {
|
|
24338
24750
|
if (!this.currentConversationId) return 0;
|
|
24339
|
-
const filePath =
|
|
24751
|
+
const filePath = path52.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
24340
24752
|
return parseJsonl(filePath).length;
|
|
24341
24753
|
}
|
|
24342
24754
|
/**
|
|
@@ -24347,7 +24759,7 @@ var HistoryService = class _HistoryService {
|
|
|
24347
24759
|
const deadline = Date.now() + timeoutMs;
|
|
24348
24760
|
while (Date.now() < deadline) {
|
|
24349
24761
|
if (!this.currentConversationId) return null;
|
|
24350
|
-
const filePath =
|
|
24762
|
+
const filePath = path52.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
24351
24763
|
const messages = parseJsonl(filePath);
|
|
24352
24764
|
if (messages.length > previousCount) {
|
|
24353
24765
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -24373,16 +24785,16 @@ var HistoryService = class _HistoryService {
|
|
|
24373
24785
|
const dir = this.projectDir;
|
|
24374
24786
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
24375
24787
|
try {
|
|
24376
|
-
const files =
|
|
24788
|
+
const files = fs45.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
24377
24789
|
try {
|
|
24378
|
-
const stat3 =
|
|
24790
|
+
const stat3 = fs45.statSync(path52.join(dir, e.name));
|
|
24379
24791
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
24380
24792
|
} catch {
|
|
24381
24793
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
24382
24794
|
}
|
|
24383
24795
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
24384
24796
|
if (files.length > 0) {
|
|
24385
|
-
this.currentConversationId =
|
|
24797
|
+
this.currentConversationId = path52.basename(files[0].name, ".jsonl");
|
|
24386
24798
|
}
|
|
24387
24799
|
} catch {
|
|
24388
24800
|
}
|
|
@@ -24416,13 +24828,13 @@ var HistoryService = class _HistoryService {
|
|
|
24416
24828
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
24417
24829
|
let entries;
|
|
24418
24830
|
try {
|
|
24419
|
-
entries =
|
|
24831
|
+
entries = fs45.readdirSync(dir, { withFileTypes: true });
|
|
24420
24832
|
} catch {
|
|
24421
24833
|
return null;
|
|
24422
24834
|
}
|
|
24423
24835
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
24424
24836
|
try {
|
|
24425
|
-
const stat3 =
|
|
24837
|
+
const stat3 = fs45.statSync(path52.join(dir, e.name));
|
|
24426
24838
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
24427
24839
|
} catch {
|
|
24428
24840
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -24431,12 +24843,12 @@ var HistoryService = class _HistoryService {
|
|
|
24431
24843
|
if (files.length === 0) return null;
|
|
24432
24844
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
24433
24845
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
24434
|
-
return this.extractUsageFromFile(
|
|
24846
|
+
return this.extractUsageFromFile(path52.join(dir, targetFile));
|
|
24435
24847
|
}
|
|
24436
24848
|
extractUsageFromFile(filePath) {
|
|
24437
24849
|
let raw;
|
|
24438
24850
|
try {
|
|
24439
|
-
raw =
|
|
24851
|
+
raw = fs45.readFileSync(filePath, "utf8");
|
|
24440
24852
|
} catch {
|
|
24441
24853
|
return null;
|
|
24442
24854
|
}
|
|
@@ -24481,9 +24893,9 @@ var HistoryService = class _HistoryService {
|
|
|
24481
24893
|
let totalCost = 0;
|
|
24482
24894
|
let files;
|
|
24483
24895
|
try {
|
|
24484
|
-
files =
|
|
24896
|
+
files = fs45.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
24485
24897
|
try {
|
|
24486
|
-
return
|
|
24898
|
+
return fs45.statSync(path52.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
24487
24899
|
} catch {
|
|
24488
24900
|
return false;
|
|
24489
24901
|
}
|
|
@@ -24494,7 +24906,7 @@ var HistoryService = class _HistoryService {
|
|
|
24494
24906
|
for (const file of files) {
|
|
24495
24907
|
let raw;
|
|
24496
24908
|
try {
|
|
24497
|
-
raw =
|
|
24909
|
+
raw = fs45.readFileSync(path52.join(projectDir, file), "utf8");
|
|
24498
24910
|
} catch {
|
|
24499
24911
|
continue;
|
|
24500
24912
|
}
|
|
@@ -24562,7 +24974,7 @@ var HistoryService = class _HistoryService {
|
|
|
24562
24974
|
* showing an empty conversation.
|
|
24563
24975
|
*/
|
|
24564
24976
|
async loadConversation(sessionId) {
|
|
24565
|
-
const filePath =
|
|
24977
|
+
const filePath = path52.join(this.projectDir, `${sessionId}.jsonl`);
|
|
24566
24978
|
const messages = parseJsonl(filePath);
|
|
24567
24979
|
if (messages.length === 0) return;
|
|
24568
24980
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -24616,7 +25028,7 @@ var HistoryService = class _HistoryService {
|
|
|
24616
25028
|
if (!this.currentConversationId) return 0;
|
|
24617
25029
|
}
|
|
24618
25030
|
const sessionId = this.currentConversationId;
|
|
24619
|
-
const filePath =
|
|
25031
|
+
const filePath = path52.join(this.projectDir, `${sessionId}.jsonl`);
|
|
24620
25032
|
const messages = parseJsonl(filePath);
|
|
24621
25033
|
if (messages.length === 0) return 0;
|
|
24622
25034
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -25042,15 +25454,15 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
25042
25454
|
}
|
|
25043
25455
|
|
|
25044
25456
|
// src/agents/claude/onboarding.ts
|
|
25045
|
-
var
|
|
25046
|
-
var
|
|
25047
|
-
var
|
|
25457
|
+
var fs46 = __toESM(require("fs"));
|
|
25458
|
+
var os37 = __toESM(require("os"));
|
|
25459
|
+
var path53 = __toESM(require("path"));
|
|
25048
25460
|
function ensureClaudeOnboarded() {
|
|
25049
25461
|
try {
|
|
25050
|
-
const file =
|
|
25462
|
+
const file = path53.join(os37.homedir(), ".claude.json");
|
|
25051
25463
|
let config = {};
|
|
25052
25464
|
try {
|
|
25053
|
-
config = JSON.parse(
|
|
25465
|
+
config = JSON.parse(fs46.readFileSync(file, "utf8"));
|
|
25054
25466
|
} catch {
|
|
25055
25467
|
}
|
|
25056
25468
|
if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
|
|
@@ -25061,8 +25473,8 @@ function ensureClaudeOnboarded() {
|
|
|
25061
25473
|
if (typeof config.lastOnboardingVersion !== "string") {
|
|
25062
25474
|
config.lastOnboardingVersion = "2.1.177";
|
|
25063
25475
|
}
|
|
25064
|
-
|
|
25065
|
-
|
|
25476
|
+
fs46.mkdirSync(path53.dirname(file), { recursive: true });
|
|
25477
|
+
fs46.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
25066
25478
|
log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
|
|
25067
25479
|
} catch (err) {
|
|
25068
25480
|
log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
|
|
@@ -25076,27 +25488,27 @@ async function start(requestedAgent) {
|
|
|
25076
25488
|
if (!session) {
|
|
25077
25489
|
if (requestedAgent) {
|
|
25078
25490
|
const displayName = AGENT_REGISTRY[requestedAgent]?.displayName ?? requestedAgent;
|
|
25079
|
-
console.log(` ${
|
|
25491
|
+
console.log(` ${import_picocolors4.default.dim(`No paired ${displayName} session found.`)}`);
|
|
25080
25492
|
console.log(
|
|
25081
|
-
` ${
|
|
25493
|
+
` ${import_picocolors4.default.dim(`Run ${import_picocolors4.default.white("codeam pair")} from a ${displayName} setup to connect your mobile app.`)}
|
|
25082
25494
|
`
|
|
25083
25495
|
);
|
|
25084
25496
|
} else {
|
|
25085
|
-
console.log(` ${
|
|
25086
|
-
console.log(` ${
|
|
25497
|
+
console.log(` ${import_picocolors4.default.dim("No paired session found.")}`);
|
|
25498
|
+
console.log(` ${import_picocolors4.default.dim(`Run ${import_picocolors4.default.white("codeam pair")} to connect your mobile app.`)}
|
|
25087
25499
|
`);
|
|
25088
25500
|
}
|
|
25089
25501
|
process.exit(0);
|
|
25090
25502
|
}
|
|
25091
25503
|
if (!acquireDaemonLock(session.id)) {
|
|
25092
|
-
console.log(` ${
|
|
25504
|
+
console.log(` ${import_picocolors4.default.dim("A codeam daemon for this session is already running \u2014 deferring to it.")}`);
|
|
25093
25505
|
process.exit(0);
|
|
25094
25506
|
}
|
|
25095
25507
|
if (!session.agent) {
|
|
25096
25508
|
throw new Error("Active session has no agent \u2014 re-pair with `codeam pair`.");
|
|
25097
25509
|
}
|
|
25098
25510
|
const pluginId = session.pluginId ?? ensurePluginId();
|
|
25099
|
-
showInfo(`${session.userName} \xB7 ${
|
|
25511
|
+
showInfo(`${session.userName} \xB7 ${import_picocolors4.default.cyan(session.plan)}`);
|
|
25100
25512
|
showInfo(`Launching ${AGENT_REGISTRY[session.agent].displayName}...
|
|
25101
25513
|
`);
|
|
25102
25514
|
identifyUser({
|
|
@@ -25370,7 +25782,7 @@ async function start(requestedAgent) {
|
|
|
25370
25782
|
|
|
25371
25783
|
// src/commands/pair.ts
|
|
25372
25784
|
var import_crypto7 = require("crypto");
|
|
25373
|
-
var
|
|
25785
|
+
var import_picocolors5 = __toESM(require("picocolors"));
|
|
25374
25786
|
|
|
25375
25787
|
// src/utils/agent-prompt.ts
|
|
25376
25788
|
function parseAgentFlag(args2) {
|
|
@@ -25451,7 +25863,7 @@ async function pair(args2 = []) {
|
|
|
25451
25863
|
process.exit(0);
|
|
25452
25864
|
}
|
|
25453
25865
|
showPairingCode(result.code);
|
|
25454
|
-
console.log(
|
|
25866
|
+
console.log(import_picocolors5.default.dim(" Scan the QR code or enter the code in CodeAgent Mobile."));
|
|
25455
25867
|
console.log("");
|
|
25456
25868
|
const waitSpin = dist_exports.spinner();
|
|
25457
25869
|
const waitMessage = () => `Waiting for mobile app... \xB7 expires in ${formatRemaining(result.expiresAt)}`;
|
|
@@ -25566,7 +25978,7 @@ async function autoLinkAfterPair(opts) {
|
|
|
25566
25978
|
}
|
|
25567
25979
|
|
|
25568
25980
|
// src/commands/sessions.ts
|
|
25569
|
-
var
|
|
25981
|
+
var import_picocolors6 = __toESM(require("picocolors"));
|
|
25570
25982
|
async function sessions2(args2) {
|
|
25571
25983
|
const [sub, id] = args2;
|
|
25572
25984
|
if (sub === "switch") return switchSession();
|
|
@@ -25583,18 +25995,18 @@ function listSessions() {
|
|
|
25583
25995
|
showIntro();
|
|
25584
25996
|
const config = getConfig();
|
|
25585
25997
|
if (config.sessions.length === 0) {
|
|
25586
|
-
console.log(
|
|
25998
|
+
console.log(import_picocolors6.default.dim(" No paired sessions. Run codeam pair to connect.\n"));
|
|
25587
25999
|
return;
|
|
25588
26000
|
}
|
|
25589
|
-
console.log(
|
|
26001
|
+
console.log(import_picocolors6.default.bold(" Paired sessions:\n"));
|
|
25590
26002
|
for (const s of config.sessions) {
|
|
25591
26003
|
const isActive = s.id === config.activeSessionId;
|
|
25592
|
-
const bullet = isActive ?
|
|
25593
|
-
const name = isActive ?
|
|
25594
|
-
const plan =
|
|
25595
|
-
const date =
|
|
26004
|
+
const bullet = isActive ? import_picocolors6.default.green(" \u25CF") : import_picocolors6.default.dim(" \u25CB");
|
|
26005
|
+
const name = isActive ? import_picocolors6.default.bold(s.userName) : s.userName;
|
|
26006
|
+
const plan = import_picocolors6.default.cyan(s.plan);
|
|
26007
|
+
const date = import_picocolors6.default.dim(new Date(s.pairedAt).toLocaleDateString());
|
|
25596
26008
|
console.log(`${bullet} ${name} ${plan} ${date}`);
|
|
25597
|
-
console.log(
|
|
26009
|
+
console.log(import_picocolors6.default.dim(` ${s.id}`));
|
|
25598
26010
|
}
|
|
25599
26011
|
console.log("");
|
|
25600
26012
|
}
|
|
@@ -25612,7 +26024,7 @@ async function switchSession() {
|
|
|
25612
26024
|
}
|
|
25613
26025
|
setActiveSession(chosen);
|
|
25614
26026
|
const s = config.sessions.find((x) => x.id === chosen);
|
|
25615
|
-
console.log(
|
|
26027
|
+
console.log(import_picocolors6.default.green(`
|
|
25616
26028
|
\u2713 Switched to ${s?.userName ?? chosen}
|
|
25617
26029
|
`));
|
|
25618
26030
|
}
|
|
@@ -25630,29 +26042,29 @@ async function deleteSession(id) {
|
|
|
25630
26042
|
return;
|
|
25631
26043
|
}
|
|
25632
26044
|
removeSession(id);
|
|
25633
|
-
console.log(
|
|
26045
|
+
console.log(import_picocolors6.default.green("\n \u2713 Session deleted\n"));
|
|
25634
26046
|
}
|
|
25635
26047
|
|
|
25636
26048
|
// src/commands/status.ts
|
|
25637
|
-
var
|
|
26049
|
+
var import_picocolors7 = __toESM(require("picocolors"));
|
|
25638
26050
|
function status() {
|
|
25639
26051
|
showIntro();
|
|
25640
26052
|
const config = getConfig();
|
|
25641
26053
|
const active = config.sessions.find((s) => s.id === config.activeSessionId) ?? null;
|
|
25642
|
-
console.log(
|
|
25643
|
-
console.log(` Plugin ID ${
|
|
26054
|
+
console.log(import_picocolors7.default.bold(" Status\n"));
|
|
26055
|
+
console.log(` Plugin ID ${import_picocolors7.default.dim(config.pluginId || "not generated yet")}`);
|
|
25644
26056
|
console.log(` Sessions ${config.sessions.length} paired`);
|
|
25645
26057
|
if (active) {
|
|
25646
|
-
console.log(` Active ${
|
|
25647
|
-
console.log(` Session ID ${
|
|
26058
|
+
console.log(` Active ${import_picocolors7.default.bold(active.userName)} ${import_picocolors7.default.cyan(active.plan)}`);
|
|
26059
|
+
console.log(` Session ID ${import_picocolors7.default.dim(active.id)}`);
|
|
25648
26060
|
} else {
|
|
25649
|
-
console.log(` Active ${
|
|
26061
|
+
console.log(` Active ${import_picocolors7.default.yellow("none")} ${import_picocolors7.default.dim("run codeam pair to connect")}`);
|
|
25650
26062
|
}
|
|
25651
26063
|
console.log("");
|
|
25652
26064
|
}
|
|
25653
26065
|
|
|
25654
26066
|
// src/commands/logout.ts
|
|
25655
|
-
var
|
|
26067
|
+
var import_picocolors8 = __toESM(require("picocolors"));
|
|
25656
26068
|
var API_BASE11 = resolveApiBaseUrl();
|
|
25657
26069
|
async function notifyBackendOffline() {
|
|
25658
26070
|
const cfg = loadCliConfig();
|
|
@@ -25686,17 +26098,17 @@ async function logout() {
|
|
|
25686
26098
|
}
|
|
25687
26099
|
await notifyBackendOffline();
|
|
25688
26100
|
clearAll();
|
|
25689
|
-
console.log(
|
|
26101
|
+
console.log(import_picocolors8.default.green("\n \u2713 Done. All sessions removed.\n"));
|
|
25690
26102
|
}
|
|
25691
26103
|
|
|
25692
26104
|
// src/commands/deploy.ts
|
|
25693
|
-
var
|
|
26105
|
+
var import_picocolors11 = __toESM(require("picocolors"));
|
|
25694
26106
|
|
|
25695
26107
|
// src/services/providers/github-codespaces.ts
|
|
25696
26108
|
var import_child_process23 = require("child_process");
|
|
25697
26109
|
var import_util4 = require("util");
|
|
25698
|
-
var
|
|
25699
|
-
var
|
|
26110
|
+
var import_picocolors9 = __toESM(require("picocolors"));
|
|
26111
|
+
var path54 = __toESM(require("path"));
|
|
25700
26112
|
var execFileP6 = (0, import_util4.promisify)(import_child_process23.execFile);
|
|
25701
26113
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
25702
26114
|
function resetStdinForChild() {
|
|
@@ -25763,7 +26175,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25763
26175
|
if (expectedUser) {
|
|
25764
26176
|
noteLines.push("");
|
|
25765
26177
|
noteLines.push(
|
|
25766
|
-
`${
|
|
26178
|
+
`${import_picocolors9.default.yellow("\u26A0")} Sign in as ${import_picocolors9.default.cyan(expectedUser)} in the browser.`
|
|
25767
26179
|
);
|
|
25768
26180
|
noteLines.push(
|
|
25769
26181
|
" If a different GitHub account is already signed in, sign out"
|
|
@@ -25786,7 +26198,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25786
26198
|
if (refreshCode !== 0) {
|
|
25787
26199
|
const lines = [
|
|
25788
26200
|
"The browser approval came back for a different GitHub account",
|
|
25789
|
-
`than the one gh is configured for${expectedUser ? ` (${
|
|
26201
|
+
`than the one gh is configured for${expectedUser ? ` (${import_picocolors9.default.cyan(expectedUser)})` : ""}.`,
|
|
25790
26202
|
"",
|
|
25791
26203
|
"To recover:",
|
|
25792
26204
|
" 1. Open https://github.com and sign out of any non-target",
|
|
@@ -25795,7 +26207,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25795
26207
|
"",
|
|
25796
26208
|
"You can also grant the scope manually first and skip this step",
|
|
25797
26209
|
"on the next run:",
|
|
25798
|
-
` ${
|
|
26210
|
+
` ${import_picocolors9.default.cyan("gh auth refresh -h github.com -s codespace")}`
|
|
25799
26211
|
];
|
|
25800
26212
|
throw new Error(lines.join("\n"));
|
|
25801
26213
|
}
|
|
@@ -25862,7 +26274,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25862
26274
|
async tryInstallGh() {
|
|
25863
26275
|
const platform3 = process.platform;
|
|
25864
26276
|
wt(
|
|
25865
|
-
`GitHub CLI (${
|
|
26277
|
+
`GitHub CLI (${import_picocolors9.default.cyan("gh")}) is required for Codespaces deploys but isn't on your PATH.`,
|
|
25866
26278
|
"Heads up"
|
|
25867
26279
|
);
|
|
25868
26280
|
if (platform3 === "linux") {
|
|
@@ -25918,7 +26330,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25918
26330
|
return;
|
|
25919
26331
|
}
|
|
25920
26332
|
const proceed = await ot2({
|
|
25921
|
-
message: `Run ${
|
|
26333
|
+
message: `Run ${import_picocolors9.default.cyan(installCmd.describe)} now?`,
|
|
25922
26334
|
initialValue: true
|
|
25923
26335
|
});
|
|
25924
26336
|
if (q(proceed) || !proceed) return;
|
|
@@ -26185,7 +26597,7 @@ var GitHubCodespacesProvider = class {
|
|
|
26185
26597
|
});
|
|
26186
26598
|
}
|
|
26187
26599
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26188
|
-
const remoteDir =
|
|
26600
|
+
const remoteDir = path54.posix.dirname(remotePath);
|
|
26189
26601
|
const parts = [
|
|
26190
26602
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
26191
26603
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -26255,8 +26667,8 @@ function shellQuote(s) {
|
|
|
26255
26667
|
// src/services/providers/gitpod.ts
|
|
26256
26668
|
var import_child_process24 = require("child_process");
|
|
26257
26669
|
var import_util5 = require("util");
|
|
26258
|
-
var
|
|
26259
|
-
var
|
|
26670
|
+
var path55 = __toESM(require("path"));
|
|
26671
|
+
var import_picocolors10 = __toESM(require("picocolors"));
|
|
26260
26672
|
var execFileP7 = (0, import_util5.promisify)(import_child_process24.execFile);
|
|
26261
26673
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
26262
26674
|
function resetStdinForChild2() {
|
|
@@ -26495,7 +26907,7 @@ var GitpodProvider = class {
|
|
|
26495
26907
|
});
|
|
26496
26908
|
}
|
|
26497
26909
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26498
|
-
const remoteDir =
|
|
26910
|
+
const remoteDir = path55.posix.dirname(remotePath);
|
|
26499
26911
|
const parts = [
|
|
26500
26912
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
26501
26913
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -26531,7 +26943,7 @@ function shellQuote2(s) {
|
|
|
26531
26943
|
// src/services/providers/gitlab-workspaces.ts
|
|
26532
26944
|
var import_child_process25 = require("child_process");
|
|
26533
26945
|
var import_util6 = require("util");
|
|
26534
|
-
var
|
|
26946
|
+
var path56 = __toESM(require("path"));
|
|
26535
26947
|
var execFileP8 = (0, import_util6.promisify)(import_child_process25.execFile);
|
|
26536
26948
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
26537
26949
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -26791,7 +27203,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
26791
27203
|
}
|
|
26792
27204
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
26793
27205
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
26794
|
-
const remoteDir =
|
|
27206
|
+
const remoteDir = path56.posix.dirname(remotePath);
|
|
26795
27207
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
26796
27208
|
if (options.mode != null) {
|
|
26797
27209
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -26859,7 +27271,7 @@ function shellQuote3(s) {
|
|
|
26859
27271
|
// src/services/providers/railway.ts
|
|
26860
27272
|
var import_child_process26 = require("child_process");
|
|
26861
27273
|
var import_util7 = require("util");
|
|
26862
|
-
var
|
|
27274
|
+
var path57 = __toESM(require("path"));
|
|
26863
27275
|
var execFileP9 = (0, import_util7.promisify)(import_child_process26.execFile);
|
|
26864
27276
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
26865
27277
|
function resetStdinForChild4() {
|
|
@@ -27095,7 +27507,7 @@ var RailwayProvider = class {
|
|
|
27095
27507
|
if (!projectId || !serviceId) {
|
|
27096
27508
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
27097
27509
|
}
|
|
27098
|
-
const remoteDir =
|
|
27510
|
+
const remoteDir = path57.posix.dirname(remotePath);
|
|
27099
27511
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
27100
27512
|
if (options.mode != null) {
|
|
27101
27513
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -27136,7 +27548,7 @@ var PROVIDERS = [
|
|
|
27136
27548
|
// src/commands/deploy.ts
|
|
27137
27549
|
async function deploy(args2 = []) {
|
|
27138
27550
|
console.log();
|
|
27139
|
-
mt(
|
|
27551
|
+
mt(import_picocolors11.default.bgMagenta(import_picocolors11.default.white(" codeam deploy ")));
|
|
27140
27552
|
const provider = await pickProvider();
|
|
27141
27553
|
if (!provider) {
|
|
27142
27554
|
pt("No provider selected.");
|
|
@@ -27173,7 +27585,7 @@ async function deploy(args2 = []) {
|
|
|
27173
27585
|
if (provider.expandListScopes) {
|
|
27174
27586
|
options.push({
|
|
27175
27587
|
value: EXPAND_SCOPES,
|
|
27176
|
-
label:
|
|
27588
|
+
label: import_picocolors11.default.cyan("+ Don't see your project? Expand scopes\u2026"),
|
|
27177
27589
|
hint: "Re-authorize with broader scopes (org / team repos)"
|
|
27178
27590
|
});
|
|
27179
27591
|
}
|
|
@@ -27221,7 +27633,7 @@ async function deploy(args2 = []) {
|
|
|
27221
27633
|
label: w3.displayName ?? w3.id,
|
|
27222
27634
|
hint: [w3.state, formatLastUsed(w3.lastUsedAt)].filter(Boolean).join(" \xB7 ")
|
|
27223
27635
|
})),
|
|
27224
|
-
{ value: "__new__", label:
|
|
27636
|
+
{ value: "__new__", label: import_picocolors11.default.green("+ Create a new workspace"), hint: "fresh codespace" }
|
|
27225
27637
|
]
|
|
27226
27638
|
});
|
|
27227
27639
|
if (q(choice)) {
|
|
@@ -27322,12 +27734,12 @@ async function deploy(args2 = []) {
|
|
|
27322
27734
|
cliStep.stop("\u2713 codeam-cli installed");
|
|
27323
27735
|
wt(
|
|
27324
27736
|
[
|
|
27325
|
-
`Workspace: ${
|
|
27326
|
-
workspace.webUrl ? `Web: ${
|
|
27737
|
+
`Workspace: ${import_picocolors11.default.cyan(workspace.displayName ?? workspace.id)}`,
|
|
27738
|
+
workspace.webUrl ? `Web: ${import_picocolors11.default.cyan(workspace.webUrl)}` : "",
|
|
27327
27739
|
"",
|
|
27328
27740
|
`Starting \`codeam pair\` on the workspace (agent: ${AGENT_REGISTRY[agentId].displayName}).`,
|
|
27329
27741
|
"Scan the QR code from your phone to pair.",
|
|
27330
|
-
|
|
27742
|
+
import_picocolors11.default.dim("(Once paired, this terminal disconnects automatically; the session stays alive on the codespace.)")
|
|
27331
27743
|
].filter(Boolean).join("\n"),
|
|
27332
27744
|
"Almost there"
|
|
27333
27745
|
);
|
|
@@ -27442,11 +27854,11 @@ async function deploy(args2 = []) {
|
|
|
27442
27854
|
].join("\n");
|
|
27443
27855
|
const code = (await provider.streamCommand(workspace.id, `bash -lc ${shellQuoteSingle(wrapper)}`)).code;
|
|
27444
27856
|
if (code === 0) {
|
|
27445
|
-
gt(
|
|
27857
|
+
gt(import_picocolors11.default.green("\u2713 Workspace deployed and paired. Drive from your phone, anywhere."));
|
|
27446
27858
|
} else if (code === 130) {
|
|
27447
|
-
gt(
|
|
27859
|
+
gt(import_picocolors11.default.yellow("Disconnected from local terminal. Mobile session keeps running on the codespace."));
|
|
27448
27860
|
} else {
|
|
27449
|
-
gt(
|
|
27861
|
+
gt(import_picocolors11.default.yellow('Pairing did not complete. Run "codeam pair" inside the codespace if needed.'));
|
|
27450
27862
|
}
|
|
27451
27863
|
}
|
|
27452
27864
|
function shellQuoteSingle(s) {
|
|
@@ -27480,7 +27892,7 @@ async function pickProvider() {
|
|
|
27480
27892
|
message: "Where do you want to deploy?",
|
|
27481
27893
|
options: PROVIDERS.map((prov) => ({
|
|
27482
27894
|
value: prov.id,
|
|
27483
|
-
label: prov.available ? prov.displayName : `${prov.displayName} ${
|
|
27895
|
+
label: prov.available ? prov.displayName : `${prov.displayName} ${import_picocolors11.default.dim("(coming soon)")}`,
|
|
27484
27896
|
hint: prov.tagline
|
|
27485
27897
|
}))
|
|
27486
27898
|
});
|
|
@@ -27497,27 +27909,27 @@ async function pickProvider() {
|
|
|
27497
27909
|
}
|
|
27498
27910
|
|
|
27499
27911
|
// src/commands/deploy-manage.ts
|
|
27500
|
-
var
|
|
27912
|
+
var import_picocolors12 = __toESM(require("picocolors"));
|
|
27501
27913
|
async function deployList() {
|
|
27502
27914
|
console.log();
|
|
27503
|
-
mt(
|
|
27915
|
+
mt(import_picocolors12.default.bgMagenta(import_picocolors12.default.white(" codeam deploy ls ")));
|
|
27504
27916
|
const workspaces = await collectWorkspacesWithStatus();
|
|
27505
27917
|
if (workspaces.length === 0) {
|
|
27506
|
-
gt(
|
|
27918
|
+
gt(import_picocolors12.default.dim("No deployed workspaces found."));
|
|
27507
27919
|
return;
|
|
27508
27920
|
}
|
|
27509
27921
|
for (const w3 of workspaces) {
|
|
27510
|
-
const tag = w3.codeamRunning ?
|
|
27511
|
-
console.log(` ${tag} ${
|
|
27922
|
+
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"}`);
|
|
27923
|
+
console.log(` ${tag} ${import_picocolors12.default.cyan(w3.displayName ?? w3.id)} ${import_picocolors12.default.dim("(" + w3.providerName + ")")}`);
|
|
27512
27924
|
}
|
|
27513
|
-
gt(
|
|
27925
|
+
gt(import_picocolors12.default.dim("Use `codeam deploy stop` to terminate a session."));
|
|
27514
27926
|
}
|
|
27515
27927
|
async function deployStop() {
|
|
27516
27928
|
console.log();
|
|
27517
|
-
mt(
|
|
27929
|
+
mt(import_picocolors12.default.bgMagenta(import_picocolors12.default.white(" codeam deploy stop ")));
|
|
27518
27930
|
const workspaces = await collectWorkspacesWithStatus();
|
|
27519
27931
|
if (workspaces.length === 0) {
|
|
27520
|
-
gt(
|
|
27932
|
+
gt(import_picocolors12.default.dim("No deployed workspaces found."));
|
|
27521
27933
|
return;
|
|
27522
27934
|
}
|
|
27523
27935
|
const choice = await _t({
|
|
@@ -27527,7 +27939,7 @@ async function deployStop() {
|
|
|
27527
27939
|
label: w3.displayName ?? w3.id,
|
|
27528
27940
|
hint: [
|
|
27529
27941
|
w3.providerName,
|
|
27530
|
-
w3.codeamRunning ?
|
|
27942
|
+
w3.codeamRunning ? import_picocolors12.default.green("\u25CF codeam-pair running") : import_picocolors12.default.dim("\u25CB no codeam-pair"),
|
|
27531
27943
|
w3.state ?? ""
|
|
27532
27944
|
].filter(Boolean).join(" \xB7 ")
|
|
27533
27945
|
}))
|
|
@@ -27555,7 +27967,7 @@ async function deployStop() {
|
|
|
27555
27967
|
O2.info("No codeam-pair process to stop on this workspace.");
|
|
27556
27968
|
}
|
|
27557
27969
|
const alsoStop = await ot2({
|
|
27558
|
-
message: `Also stop the workspace ${
|
|
27970
|
+
message: `Also stop the workspace ${import_picocolors12.default.cyan(target.displayName ?? target.id)} to save compute hours?`,
|
|
27559
27971
|
initialValue: true
|
|
27560
27972
|
});
|
|
27561
27973
|
if (!q(alsoStop) && alsoStop) {
|
|
@@ -27577,7 +27989,7 @@ async function deployStop() {
|
|
|
27577
27989
|
O2.warn(err instanceof Error ? err.message : String(err));
|
|
27578
27990
|
}
|
|
27579
27991
|
}
|
|
27580
|
-
gt(
|
|
27992
|
+
gt(import_picocolors12.default.green("\u2713 Done."));
|
|
27581
27993
|
}
|
|
27582
27994
|
async function collectWorkspacesWithStatus() {
|
|
27583
27995
|
const out2 = [];
|
|
@@ -27683,9 +28095,9 @@ async function host(args2) {
|
|
|
27683
28095
|
var import_node_dns = require("dns");
|
|
27684
28096
|
var import_node_util5 = require("util");
|
|
27685
28097
|
var import_node_crypto8 = require("crypto");
|
|
27686
|
-
var
|
|
27687
|
-
var
|
|
27688
|
-
var
|
|
28098
|
+
var fs47 = __toESM(require("fs"));
|
|
28099
|
+
var path58 = __toESM(require("path"));
|
|
28100
|
+
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27689
28101
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
27690
28102
|
async function checkDns(apiBase2) {
|
|
27691
28103
|
const host2 = (() => {
|
|
@@ -27740,13 +28152,13 @@ async function checkHealth(apiBase2) {
|
|
|
27740
28152
|
}
|
|
27741
28153
|
}
|
|
27742
28154
|
function checkConfigDir() {
|
|
27743
|
-
const dir =
|
|
28155
|
+
const dir = path58.join(require("os").homedir(), ".codeam");
|
|
27744
28156
|
try {
|
|
27745
|
-
|
|
27746
|
-
const probe =
|
|
27747
|
-
|
|
27748
|
-
const read2 =
|
|
27749
|
-
|
|
28157
|
+
fs47.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
28158
|
+
const probe = path58.join(dir, ".doctor-probe");
|
|
28159
|
+
fs47.writeFileSync(probe, "ok", { mode: 384 });
|
|
28160
|
+
const read2 = fs47.readFileSync(probe, "utf8");
|
|
28161
|
+
fs47.unlinkSync(probe);
|
|
27750
28162
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
27751
28163
|
return {
|
|
27752
28164
|
id: "config-dir",
|
|
@@ -27810,7 +28222,7 @@ function checkNodePty() {
|
|
|
27810
28222
|
detail: "not required on this platform"
|
|
27811
28223
|
};
|
|
27812
28224
|
}
|
|
27813
|
-
const vendoredPath =
|
|
28225
|
+
const vendoredPath = path58.join(__dirname, "vendor", "node-pty");
|
|
27814
28226
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
27815
28227
|
try {
|
|
27816
28228
|
require(target);
|
|
@@ -27852,7 +28264,7 @@ function checkChokidar() {
|
|
|
27852
28264
|
}
|
|
27853
28265
|
async function doctor(args2 = []) {
|
|
27854
28266
|
const json = args2.includes("--json");
|
|
27855
|
-
const cliVersion = true ? "2.39.
|
|
28267
|
+
const cliVersion = true ? "2.39.56" : "0.0.0-dev";
|
|
27856
28268
|
const apiBase2 = resolveApiBaseUrl();
|
|
27857
28269
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
27858
28270
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27892,46 +28304,46 @@ async function doctor(args2 = []) {
|
|
|
27892
28304
|
function printHumanReport(r) {
|
|
27893
28305
|
const out2 = process.stderr;
|
|
27894
28306
|
out2.write(`
|
|
27895
|
-
${
|
|
28307
|
+
${import_picocolors13.default.bold(" codeam doctor")}
|
|
27896
28308
|
|
|
27897
28309
|
`);
|
|
27898
|
-
out2.write(` ${
|
|
28310
|
+
out2.write(` ${import_picocolors13.default.dim("cli")} ${r.cliVersion}
|
|
27899
28311
|
`);
|
|
27900
|
-
out2.write(` ${
|
|
28312
|
+
out2.write(` ${import_picocolors13.default.dim("node")} ${r.node}
|
|
27901
28313
|
`);
|
|
27902
|
-
out2.write(` ${
|
|
28314
|
+
out2.write(` ${import_picocolors13.default.dim("os")} ${r.platform} ${r.arch}
|
|
27903
28315
|
`);
|
|
27904
|
-
out2.write(` ${
|
|
28316
|
+
out2.write(` ${import_picocolors13.default.dim("api")} ${r.apiBase}
|
|
27905
28317
|
`);
|
|
27906
28318
|
if (process.env.CODEAM_TEST_MODE === "1" || process.env.CODEAM_TEST_MODE?.toLowerCase() === "true") {
|
|
27907
|
-
out2.write(` ${
|
|
28319
|
+
out2.write(` ${import_picocolors13.default.dim("mode")} ${import_picocolors13.default.yellow("TEST_MODE \u2014 using dev preview")}
|
|
27908
28320
|
`);
|
|
27909
28321
|
} else if (process.env.CODEAM_API_URL) {
|
|
27910
|
-
out2.write(` ${
|
|
28322
|
+
out2.write(` ${import_picocolors13.default.dim("mode")} ${import_picocolors13.default.yellow("CODEAM_API_URL override")}
|
|
27911
28323
|
`);
|
|
27912
28324
|
}
|
|
27913
|
-
out2.write(` ${
|
|
28325
|
+
out2.write(` ${import_picocolors13.default.dim("diag id")} ${r.diagnosticId}
|
|
27914
28326
|
`);
|
|
27915
28327
|
out2.write("\n");
|
|
27916
28328
|
for (const c2 of r.checks) {
|
|
27917
|
-
const mark = c2.ok ?
|
|
27918
|
-
out2.write(` ${mark} ${c2.label}${
|
|
28329
|
+
const mark = c2.ok ? import_picocolors13.default.green("\u2713") : c2.optional ? import_picocolors13.default.yellow("!") : import_picocolors13.default.red("\u2717");
|
|
28330
|
+
out2.write(` ${mark} ${c2.label}${import_picocolors13.default.dim(` \u2014 ${c2.detail}`)}
|
|
27919
28331
|
`);
|
|
27920
28332
|
if (!c2.ok && c2.hint) {
|
|
27921
28333
|
for (const line of c2.hint.split("\n")) {
|
|
27922
|
-
out2.write(` ${
|
|
28334
|
+
out2.write(` ${import_picocolors13.default.dim(line)}
|
|
27923
28335
|
`);
|
|
27924
28336
|
}
|
|
27925
28337
|
}
|
|
27926
28338
|
}
|
|
27927
28339
|
out2.write("\n");
|
|
27928
28340
|
if (r.ok) {
|
|
27929
|
-
out2.write(` ${
|
|
28341
|
+
out2.write(` ${import_picocolors13.default.green("All checks passed.")}
|
|
27930
28342
|
|
|
27931
28343
|
`);
|
|
27932
28344
|
} else {
|
|
27933
28345
|
out2.write(
|
|
27934
|
-
` ${
|
|
28346
|
+
` ${import_picocolors13.default.red("Some checks failed.")} ${import_picocolors13.default.dim("Paste the diagnostic id above when opening a bug report.")}
|
|
27935
28347
|
|
|
27936
28348
|
`
|
|
27937
28349
|
);
|
|
@@ -28049,118 +28461,118 @@ async function completion(args2) {
|
|
|
28049
28461
|
}
|
|
28050
28462
|
|
|
28051
28463
|
// src/commands/version.ts
|
|
28052
|
-
var
|
|
28464
|
+
var import_picocolors14 = __toESM(require("picocolors"));
|
|
28053
28465
|
function version2() {
|
|
28054
|
-
const v = true ? "2.39.
|
|
28055
|
-
console.log(`${
|
|
28466
|
+
const v = true ? "2.39.56" : "unknown";
|
|
28467
|
+
console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
|
|
28056
28468
|
}
|
|
28057
28469
|
|
|
28058
28470
|
// src/commands/help.ts
|
|
28059
|
-
var
|
|
28471
|
+
var import_picocolors15 = __toESM(require("picocolors"));
|
|
28060
28472
|
function help() {
|
|
28061
28473
|
const lines = [
|
|
28062
28474
|
"",
|
|
28063
|
-
` ${
|
|
28475
|
+
` ${import_picocolors15.default.bold(import_picocolors15.default.magenta("codeam-cli"))} ${import_picocolors15.default.dim("\u2014 remote-control AI coding agents from your phone")}`,
|
|
28064
28476
|
"",
|
|
28065
|
-
` ${
|
|
28066
|
-
` ${
|
|
28477
|
+
` ${import_picocolors15.default.bold("Usage")}`,
|
|
28478
|
+
` ${import_picocolors15.default.cyan("codeam")} ${import_picocolors15.default.dim("[command]")}`,
|
|
28067
28479
|
"",
|
|
28068
|
-
` ${
|
|
28069
|
-
` ${
|
|
28070
|
-
` ${
|
|
28071
|
-
` ${
|
|
28072
|
-
` ${
|
|
28073
|
-
` ${
|
|
28074
|
-
` ${
|
|
28075
|
-
` ${
|
|
28076
|
-
` ${
|
|
28077
|
-
` ${
|
|
28078
|
-
` ${
|
|
28079
|
-
` ${
|
|
28080
|
-
` ${
|
|
28081
|
-
` ${
|
|
28082
|
-
` ${
|
|
28083
|
-
` ${
|
|
28480
|
+
` ${import_picocolors15.default.bold("Commands")}`,
|
|
28481
|
+
` ${import_picocolors15.default.white("codeam")} ${import_picocolors15.default.dim("start the active agent with mobile control")}`,
|
|
28482
|
+
` ${import_picocolors15.default.white("codeam <agent>")} ${import_picocolors15.default.dim("start a specific agent \u2014 e.g. claude, codex")}`,
|
|
28483
|
+
` ${import_picocolors15.default.white("codeam pair")} ${import_picocolors15.default.dim("pair a new mobile device (interactive)")}`,
|
|
28484
|
+
` ${import_picocolors15.default.white("codeam pair --agent <id>")} ${import_picocolors15.default.dim("pair non-interactively for a specific agent")}`,
|
|
28485
|
+
` ${import_picocolors15.default.white("codeam sessions")} ${import_picocolors15.default.dim("list paired devices")}`,
|
|
28486
|
+
` ${import_picocolors15.default.white("codeam sessions switch")} ${import_picocolors15.default.dim("switch the active paired session")}`,
|
|
28487
|
+
` ${import_picocolors15.default.white("codeam sessions delete <id>")} ${import_picocolors15.default.dim("remove a specific paired session")}`,
|
|
28488
|
+
` ${import_picocolors15.default.white("codeam status")} ${import_picocolors15.default.dim("show connection info")}`,
|
|
28489
|
+
` ${import_picocolors15.default.white("codeam logout")} ${import_picocolors15.default.dim("remove all paired sessions")}`,
|
|
28490
|
+
` ${import_picocolors15.default.white("codeam link <agent>")} ${import_picocolors15.default.dim("link an agent (claude, codex) to your CodeAgent account")}`,
|
|
28491
|
+
` ${import_picocolors15.default.white("codeam deploy")} ${import_picocolors15.default.dim("provision a cloud workspace (Codespaces) and pair it")}`,
|
|
28492
|
+
` ${import_picocolors15.default.white("codeam deploy ls | list")} ${import_picocolors15.default.dim("list deployed cloud workspaces")}`,
|
|
28493
|
+
` ${import_picocolors15.default.white("codeam deploy stop | remove")} ${import_picocolors15.default.dim("stop a deployed workspace session")}`,
|
|
28494
|
+
` ${import_picocolors15.default.white("codeam doctor")} ${import_picocolors15.default.dim("run diagnostic checks (DNS, /health, binaries, \u2026)")}`,
|
|
28495
|
+
` ${import_picocolors15.default.white("codeam completion <shell>")} ${import_picocolors15.default.dim("emit a bash/zsh/fish completion script")}`,
|
|
28084
28496
|
"",
|
|
28085
|
-
` ${
|
|
28086
|
-
` ${
|
|
28087
|
-
` ${
|
|
28497
|
+
` ${import_picocolors15.default.bold("Flags")}`,
|
|
28498
|
+
` ${import_picocolors15.default.white("-v, --version")} ${import_picocolors15.default.dim("print the CLI version")}`,
|
|
28499
|
+
` ${import_picocolors15.default.white("-h, --help")} ${import_picocolors15.default.dim("show this help")}`,
|
|
28088
28500
|
"",
|
|
28089
|
-
` ${
|
|
28090
|
-
` ${
|
|
28091
|
-
` ${
|
|
28501
|
+
` ${import_picocolors15.default.bold("Links")}`,
|
|
28502
|
+
` ${import_picocolors15.default.dim("Docs:")} ${import_picocolors15.default.green("https://www.codeagent-mobile.com")}`,
|
|
28503
|
+
` ${import_picocolors15.default.dim("Issues:")} ${import_picocolors15.default.green("https://github.com/edgar-durand/codeagent-mobile-clients/issues")}`,
|
|
28092
28504
|
""
|
|
28093
28505
|
];
|
|
28094
28506
|
process.stdout.write(lines.join("\n") + "\n");
|
|
28095
28507
|
}
|
|
28096
28508
|
|
|
28097
28509
|
// src/commands/subcommand-help.ts
|
|
28098
|
-
var
|
|
28510
|
+
var import_picocolors16 = __toESM(require("picocolors"));
|
|
28099
28511
|
var HELPS = {
|
|
28100
28512
|
pair: () => print([
|
|
28101
|
-
` ${
|
|
28513
|
+
` ${import_picocolors16.default.bold("codeam pair")} ${import_picocolors16.default.dim("\u2014 pair a mobile device with this CLI")}`,
|
|
28102
28514
|
"",
|
|
28103
|
-
` ${
|
|
28104
|
-
` ${
|
|
28105
|
-
` ${
|
|
28515
|
+
` ${import_picocolors16.default.cyan("codeam pair")} ${import_picocolors16.default.dim("interactive pairing (prompts for the agent)")}`,
|
|
28516
|
+
` ${import_picocolors16.default.cyan("codeam pair --agent <id>")} ${import_picocolors16.default.dim("pair non-interactively (agent: claude | codex)")}`,
|
|
28517
|
+
` ${import_picocolors16.default.cyan("codeam pair --dry-run")} ${import_picocolors16.default.dim("request a pairing code, validate the response, exit")}`
|
|
28106
28518
|
]),
|
|
28107
28519
|
"pair-auto": () => print([
|
|
28108
|
-
` ${
|
|
28520
|
+
` ${import_picocolors16.default.bold("codeam pair-auto")} ${import_picocolors16.default.dim("\u2014 non-interactive variant of pair for scripted setups")}`,
|
|
28109
28521
|
"",
|
|
28110
|
-
` ${
|
|
28522
|
+
` ${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
28523
|
]),
|
|
28112
28524
|
link: () => print([
|
|
28113
|
-
` ${
|
|
28525
|
+
` ${import_picocolors16.default.bold("codeam link <agent>")} ${import_picocolors16.default.dim("\u2014 upload a local agent token (Claude or Codex) to your vault")}`,
|
|
28114
28526
|
"",
|
|
28115
|
-
` ${
|
|
28116
|
-
` ${
|
|
28527
|
+
` ${import_picocolors16.default.cyan("codeam link claude")}`,
|
|
28528
|
+
` ${import_picocolors16.default.cyan("codeam link codex")}`,
|
|
28117
28529
|
"",
|
|
28118
|
-
` ${
|
|
28119
|
-
` ${
|
|
28120
|
-
` ${
|
|
28121
|
-
` ${
|
|
28122
|
-
` ${
|
|
28530
|
+
` ${import_picocolors16.default.white("--api-key=<key>")} ${import_picocolors16.default.dim("paste an API key directly (visible in `ps -ef`)")}`,
|
|
28531
|
+
` ${import_picocolors16.default.white("--api-key-file=<path>")} ${import_picocolors16.default.dim("read API key from a file (recommended for CI / scripts)")}`,
|
|
28532
|
+
` ${import_picocolors16.default.white("--reuse-existing")} ${import_picocolors16.default.dim("upload existing creds without re-launching the agent login")}`,
|
|
28533
|
+
` ${import_picocolors16.default.white("--token-file=<path>")} ${import_picocolors16.default.dim("manual credential blob path for unusual vendor locations")}`,
|
|
28534
|
+
` ${import_picocolors16.default.white("--dry-run")} ${import_picocolors16.default.dim("probe the /api/plugin/agents/<agent>/link endpoint and exit")}`
|
|
28123
28535
|
]),
|
|
28124
28536
|
sessions: () => print([
|
|
28125
|
-
` ${
|
|
28537
|
+
` ${import_picocolors16.default.bold("codeam sessions")} ${import_picocolors16.default.dim("\u2014 list, switch, or delete paired mobile sessions")}`,
|
|
28126
28538
|
"",
|
|
28127
|
-
` ${
|
|
28128
|
-
` ${
|
|
28129
|
-
` ${
|
|
28539
|
+
` ${import_picocolors16.default.cyan("codeam sessions")} ${import_picocolors16.default.dim("list all paired sessions on this machine")}`,
|
|
28540
|
+
` ${import_picocolors16.default.cyan("codeam sessions switch")} ${import_picocolors16.default.dim("interactively switch the active session")}`,
|
|
28541
|
+
` ${import_picocolors16.default.cyan("codeam sessions delete <id>")} ${import_picocolors16.default.dim("remove a specific paired session")}`
|
|
28130
28542
|
]),
|
|
28131
28543
|
deploy: () => print([
|
|
28132
|
-
` ${
|
|
28544
|
+
` ${import_picocolors16.default.bold("codeam deploy")} ${import_picocolors16.default.dim("\u2014 provision a cloud workspace (GitHub Codespaces) and pair it")}`,
|
|
28133
28545
|
"",
|
|
28134
|
-
` ${
|
|
28135
|
-
` ${
|
|
28136
|
-
` ${
|
|
28546
|
+
` ${import_picocolors16.default.cyan("codeam deploy")} ${import_picocolors16.default.dim("start a new deploy (prompts for repo + agent)")}`,
|
|
28547
|
+
` ${import_picocolors16.default.cyan("codeam deploy ls | list")} ${import_picocolors16.default.dim("list deployed cloud workspaces")}`,
|
|
28548
|
+
` ${import_picocolors16.default.cyan("codeam deploy stop | remove")} ${import_picocolors16.default.dim("pick a workspace and stop its codeam-pair session")}`
|
|
28137
28549
|
]),
|
|
28138
28550
|
status: () => print([
|
|
28139
|
-
` ${
|
|
28551
|
+
` ${import_picocolors16.default.bold("codeam status")} ${import_picocolors16.default.dim("\u2014 show the active session, agent, and connection info")}`
|
|
28140
28552
|
]),
|
|
28141
28553
|
logout: () => print([
|
|
28142
|
-
` ${
|
|
28554
|
+
` ${import_picocolors16.default.bold("codeam logout")} ${import_picocolors16.default.dim("\u2014 remove every paired session from this machine")}`
|
|
28143
28555
|
]),
|
|
28144
28556
|
doctor: () => print([
|
|
28145
|
-
` ${
|
|
28557
|
+
` ${import_picocolors16.default.bold("codeam doctor")} ${import_picocolors16.default.dim("\u2014 run diagnostic checks for support triage")}`,
|
|
28146
28558
|
"",
|
|
28147
|
-
` ${
|
|
28148
|
-
` ${
|
|
28559
|
+
` ${import_picocolors16.default.cyan("codeam doctor")} ${import_picocolors16.default.dim("human-readable report")}`,
|
|
28560
|
+
` ${import_picocolors16.default.cyan("codeam doctor --json")} ${import_picocolors16.default.dim("machine-parseable report (single JSON document on stdout)")}`,
|
|
28149
28561
|
"",
|
|
28150
|
-
` ${
|
|
28151
|
-
` ${
|
|
28562
|
+
` ${import_picocolors16.default.dim("Output never includes tokens or credentials. Paste the diagnostic id")}`,
|
|
28563
|
+
` ${import_picocolors16.default.dim("into a bug report so support can grep the server-side logs.")}`
|
|
28152
28564
|
]),
|
|
28153
28565
|
completion: () => print([
|
|
28154
|
-
` ${
|
|
28566
|
+
` ${import_picocolors16.default.bold("codeam completion <shell>")} ${import_picocolors16.default.dim("\u2014 emit a shell-completion script for sourcing")}`,
|
|
28155
28567
|
"",
|
|
28156
|
-
` ${
|
|
28157
|
-
` ${
|
|
28158
|
-
` ${
|
|
28568
|
+
` ${import_picocolors16.default.cyan("codeam completion bash")} ${import_picocolors16.default.dim("print a bash completion function")}`,
|
|
28569
|
+
` ${import_picocolors16.default.cyan("codeam completion zsh")} ${import_picocolors16.default.dim("print a zsh completion function")}`,
|
|
28570
|
+
` ${import_picocolors16.default.cyan("codeam completion fish")} ${import_picocolors16.default.dim("print a fish completion file")}`,
|
|
28159
28571
|
"",
|
|
28160
|
-
` ${
|
|
28161
|
-
` ${
|
|
28162
|
-
` ${
|
|
28163
|
-
` ${
|
|
28572
|
+
` ${import_picocolors16.default.dim("Examples:")}`,
|
|
28573
|
+
` ${import_picocolors16.default.dim(" bash: codeam completion bash >> ~/.bashrc")}`,
|
|
28574
|
+
` ${import_picocolors16.default.dim(" zsh: codeam completion zsh >> ~/.zshrc")}`,
|
|
28575
|
+
` ${import_picocolors16.default.dim(" fish: codeam completion fish > ~/.config/fish/completions/codeam.fish")}`
|
|
28164
28576
|
])
|
|
28165
28577
|
};
|
|
28166
28578
|
function print(lines) {
|
|
@@ -28178,179 +28590,6 @@ function tryShowSubcommandHelp(cmd, args2) {
|
|
|
28178
28590
|
}
|
|
28179
28591
|
var _subcommandHelpKeys = Object.keys(HELPS);
|
|
28180
28592
|
|
|
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
28593
|
// src/exit-codes.ts
|
|
28355
28594
|
var EXIT_OK = 0;
|
|
28356
28595
|
var EXIT_FAILURE = 1;
|