codeam-cli 2.47.1 → 2.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/index.js +135 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to `codeam-cli` are documented here.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [2.47.1] — 2026-06-26
|
|
8
|
+
|
|
9
|
+
### Chore
|
|
10
|
+
|
|
11
|
+
- **plugins:** Cloud-fallback follow-ups — test await, validated narrowing, repoSlug+learnMoreUrl tests, path-preserving probe URL, detached-HEAD parity, drop vestigial param (#393)
|
|
12
|
+
|
|
7
13
|
## [2.47.0] — 2026-06-26
|
|
8
14
|
|
|
9
15
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -1093,12 +1093,12 @@ var PromiseQueue = class {
|
|
|
1093
1093
|
return promise;
|
|
1094
1094
|
}
|
|
1095
1095
|
async join() {
|
|
1096
|
-
let
|
|
1097
|
-
let length =
|
|
1096
|
+
let promises3 = Object.values(this.promiseByIds);
|
|
1097
|
+
let length = promises3.length;
|
|
1098
1098
|
while (length > 0) {
|
|
1099
|
-
await Promise.all(
|
|
1100
|
-
|
|
1101
|
-
length =
|
|
1099
|
+
await Promise.all(promises3);
|
|
1100
|
+
promises3 = Object.values(this.promiseByIds);
|
|
1101
|
+
length = promises3.length;
|
|
1102
1102
|
}
|
|
1103
1103
|
}
|
|
1104
1104
|
get length() {
|
|
@@ -1436,8 +1436,8 @@ function safeSetTimeout(fn, timeout) {
|
|
|
1436
1436
|
return t2;
|
|
1437
1437
|
}
|
|
1438
1438
|
var isError = (x) => x instanceof Error;
|
|
1439
|
-
function allSettled(
|
|
1440
|
-
return Promise.all(
|
|
1439
|
+
function allSettled(promises3) {
|
|
1440
|
+
return Promise.all(promises3.map((p2) => (p2 ?? Promise.resolve()).then((value) => ({
|
|
1441
1441
|
status: "fulfilled",
|
|
1442
1442
|
value
|
|
1443
1443
|
}), (reason) => ({
|
|
@@ -5397,7 +5397,7 @@ function readAnonId() {
|
|
|
5397
5397
|
}
|
|
5398
5398
|
function superProperties() {
|
|
5399
5399
|
return {
|
|
5400
|
-
cliVersion: true ? "2.
|
|
5400
|
+
cliVersion: true ? "2.48.0" : "0.0.0-dev",
|
|
5401
5401
|
nodeVersion: process.version,
|
|
5402
5402
|
platform: process.platform,
|
|
5403
5403
|
arch: process.arch,
|
|
@@ -5578,7 +5578,7 @@ var os4 = __toESM(require("os"));
|
|
|
5578
5578
|
// package.json
|
|
5579
5579
|
var package_default = {
|
|
5580
5580
|
name: "codeam-cli",
|
|
5581
|
-
version: "2.
|
|
5581
|
+
version: "2.48.0",
|
|
5582
5582
|
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.",
|
|
5583
5583
|
type: "commonjs",
|
|
5584
5584
|
main: "dist/index.js",
|
|
@@ -7817,7 +7817,16 @@ var startCommandSchema = import_zod.z.object({
|
|
|
7817
7817
|
})
|
|
7818
7818
|
).max(32).optional(),
|
|
7819
7819
|
notes: import_zod.z.string().max(4096).nullable().optional()
|
|
7820
|
-
}).optional()
|
|
7820
|
+
}).optional(),
|
|
7821
|
+
// `env_write` carries the full desired set of environment variables
|
|
7822
|
+
// for the project `.env`. Bounded so a malformed payload can't flood
|
|
7823
|
+
// the disk-side serializer. `env_read` / `preview_restart` send no payload.
|
|
7824
|
+
vars: import_zod.z.array(
|
|
7825
|
+
import_zod.z.object({
|
|
7826
|
+
key: import_zod.z.string().min(1).max(256),
|
|
7827
|
+
value: import_zod.z.string().max(32768)
|
|
7828
|
+
})
|
|
7829
|
+
).max(512).optional()
|
|
7821
7830
|
});
|
|
7822
7831
|
function parsePayload2(schema, raw) {
|
|
7823
7832
|
const result = schema.safeParse(raw);
|
|
@@ -13991,6 +14000,47 @@ async function writePreviewConfig(cwd, detection) {
|
|
|
13991
14000
|
await import_promises3.default.writeFile(filePath, JSON.stringify(detection, null, 2) + "\n", "utf-8");
|
|
13992
14001
|
}
|
|
13993
14002
|
|
|
14003
|
+
// src/services/preview/dotenv.ts
|
|
14004
|
+
var ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
14005
|
+
function parseDotenv(raw) {
|
|
14006
|
+
const order = [];
|
|
14007
|
+
const map = /* @__PURE__ */ new Map();
|
|
14008
|
+
for (const rawLine of raw.split(/\r?\n/)) {
|
|
14009
|
+
const line = rawLine.trim();
|
|
14010
|
+
if (line === "" || line.startsWith("#")) continue;
|
|
14011
|
+
const body = line.startsWith("export ") ? line.slice("export ".length).trim() : line;
|
|
14012
|
+
const eq = body.indexOf("=");
|
|
14013
|
+
if (eq <= 0) continue;
|
|
14014
|
+
const key = body.slice(0, eq).trim();
|
|
14015
|
+
if (!ENV_KEY_RE.test(key)) continue;
|
|
14016
|
+
let value = body.slice(eq + 1).trim();
|
|
14017
|
+
value = unquote(value);
|
|
14018
|
+
if (!map.has(key)) order.push(key);
|
|
14019
|
+
map.set(key, value);
|
|
14020
|
+
}
|
|
14021
|
+
return order.map((key) => ({ key, value: map.get(key) }));
|
|
14022
|
+
}
|
|
14023
|
+
function unquote(value) {
|
|
14024
|
+
if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) {
|
|
14025
|
+
return value.slice(1, -1).replace(/\\n/g, "\n").replace(/\\"/g, '"');
|
|
14026
|
+
}
|
|
14027
|
+
if (value.length >= 2 && value.startsWith("'") && value.endsWith("'")) {
|
|
14028
|
+
return value.slice(1, -1);
|
|
14029
|
+
}
|
|
14030
|
+
return value;
|
|
14031
|
+
}
|
|
14032
|
+
function serializeDotenv(vars) {
|
|
14033
|
+
const lines = vars.map(({ key, value }) => `${key}=${quoteIfNeeded(value)}`);
|
|
14034
|
+
return `# Managed by CodeAgent
|
|
14035
|
+
${lines.join("\n")}${lines.length ? "\n" : ""}`;
|
|
14036
|
+
}
|
|
14037
|
+
function quoteIfNeeded(value) {
|
|
14038
|
+
if (/[\s#=]/.test(value) || value.includes("\n")) {
|
|
14039
|
+
return `"${value.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
|
|
14040
|
+
}
|
|
14041
|
+
return value;
|
|
14042
|
+
}
|
|
14043
|
+
|
|
13994
14044
|
// src/services/preview/parser.ts
|
|
13995
14045
|
var REQUIRED_FIELDS2 = [
|
|
13996
14046
|
"framework",
|
|
@@ -15917,6 +15967,51 @@ var listFiles = async (ctx, cmd, parsed) => {
|
|
|
15917
15967
|
const result = await listProjectFiles({ query: parsed.query });
|
|
15918
15968
|
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
15919
15969
|
};
|
|
15970
|
+
var envReadH = async (ctx, cmd) => {
|
|
15971
|
+
const envPath = path40.join(process.cwd(), ".env");
|
|
15972
|
+
try {
|
|
15973
|
+
const raw = await fs34.promises.readFile(envPath, "utf8");
|
|
15974
|
+
await ctx.relay.sendResult(cmd.id, "completed", {
|
|
15975
|
+
exists: true,
|
|
15976
|
+
vars: parseDotenv(raw)
|
|
15977
|
+
});
|
|
15978
|
+
} catch (err) {
|
|
15979
|
+
if (err.code === "ENOENT") {
|
|
15980
|
+
await ctx.relay.sendResult(cmd.id, "completed", { exists: false, vars: [] });
|
|
15981
|
+
return;
|
|
15982
|
+
}
|
|
15983
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
|
|
15984
|
+
}
|
|
15985
|
+
};
|
|
15986
|
+
var envWriteH = async (ctx, cmd, parsed) => {
|
|
15987
|
+
const vars = parsed.vars;
|
|
15988
|
+
if (!Array.isArray(vars)) {
|
|
15989
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: "Missing vars" });
|
|
15990
|
+
return;
|
|
15991
|
+
}
|
|
15992
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15993
|
+
for (const v of vars) {
|
|
15994
|
+
if (!ENV_KEY_RE.test(v.key)) {
|
|
15995
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: `Invalid key: ${v.key}` });
|
|
15996
|
+
return;
|
|
15997
|
+
}
|
|
15998
|
+
if (seen.has(v.key)) {
|
|
15999
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: `Duplicate key: ${v.key}` });
|
|
16000
|
+
return;
|
|
16001
|
+
}
|
|
16002
|
+
seen.add(v.key);
|
|
16003
|
+
}
|
|
16004
|
+
const envPath = path40.join(process.cwd(), ".env");
|
|
16005
|
+
const tmpPath = path40.join(process.cwd(), ".env.codeam.tmp");
|
|
16006
|
+
try {
|
|
16007
|
+
await fs34.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
|
|
16008
|
+
await fs34.promises.rename(tmpPath, envPath);
|
|
16009
|
+
await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
|
|
16010
|
+
} catch (err) {
|
|
16011
|
+
await fs34.promises.rm(tmpPath, { force: true }).catch(() => void 0);
|
|
16012
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
|
|
16013
|
+
}
|
|
16014
|
+
};
|
|
15920
16015
|
var terminalOpenH = async (ctx, cmd, parsed) => {
|
|
15921
16016
|
const r = openTerminal({
|
|
15922
16017
|
cols: typeof parsed.cols === "number" ? parsed.cols : void 0,
|
|
@@ -16372,8 +16467,9 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
16372
16467
|
log.info("preview", "start: no detection in payload");
|
|
16373
16468
|
return;
|
|
16374
16469
|
}
|
|
16375
|
-
|
|
16376
|
-
|
|
16470
|
+
startPreviewFromDetection(ctx, rawDetection, ctx.pluginAuthToken);
|
|
16471
|
+
};
|
|
16472
|
+
function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
16377
16473
|
const emitProgress = (step, message) => {
|
|
16378
16474
|
void postPreviewEvent({
|
|
16379
16475
|
sessionId: ctx.sessionId,
|
|
@@ -16791,7 +16887,8 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
16791
16887
|
devServer,
|
|
16792
16888
|
tunnel,
|
|
16793
16889
|
url,
|
|
16794
|
-
framework: detection.framework
|
|
16890
|
+
framework: detection.framework,
|
|
16891
|
+
detection
|
|
16795
16892
|
});
|
|
16796
16893
|
log.info("preview", `ready: ${detection.framework} at ${url}`);
|
|
16797
16894
|
void postPreviewEvent({
|
|
@@ -16812,7 +16909,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
16812
16909
|
payload: { stage: "spawn", message: `Preview failed to start: ${message}` }
|
|
16813
16910
|
});
|
|
16814
16911
|
});
|
|
16815
|
-
}
|
|
16912
|
+
}
|
|
16816
16913
|
var previewStopH = (ctx) => {
|
|
16817
16914
|
if (!ctx.pluginAuthToken) {
|
|
16818
16915
|
log.info("preview", "no pluginAuthToken \u2014 skipping stop");
|
|
@@ -16831,6 +16928,21 @@ var previewStopH = (ctx) => {
|
|
|
16831
16928
|
});
|
|
16832
16929
|
})();
|
|
16833
16930
|
};
|
|
16931
|
+
var previewRestartH = async (ctx, cmd) => {
|
|
16932
|
+
if (!ctx.pluginAuthToken) {
|
|
16933
|
+
await ctx.relay.sendResult(cmd.id, "completed", { restarted: false });
|
|
16934
|
+
return;
|
|
16935
|
+
}
|
|
16936
|
+
const preview = activePreviews.get(ctx.sessionId);
|
|
16937
|
+
if (!preview) {
|
|
16938
|
+
await ctx.relay.sendResult(cmd.id, "completed", { restarted: false });
|
|
16939
|
+
return;
|
|
16940
|
+
}
|
|
16941
|
+
await killPreview(ctx.sessionId);
|
|
16942
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
16943
|
+
startPreviewFromDetection(ctx, preview.detection, ctx.pluginAuthToken);
|
|
16944
|
+
await ctx.relay.sendResult(cmd.id, "completed", { restarted: true });
|
|
16945
|
+
};
|
|
16834
16946
|
var savePreviewConfigH = (_ctx, _cmd, parsed) => {
|
|
16835
16947
|
const detection = parsed.detection;
|
|
16836
16948
|
if (!detection) {
|
|
@@ -16880,7 +16992,10 @@ var handlers = {
|
|
|
16880
16992
|
request_preview_detect: requestPreviewDetectH,
|
|
16881
16993
|
preview_start: previewStartH,
|
|
16882
16994
|
preview_stop: previewStopH,
|
|
16883
|
-
|
|
16995
|
+
preview_restart: previewRestartH,
|
|
16996
|
+
save_preview_config: savePreviewConfigH,
|
|
16997
|
+
env_read: envReadH,
|
|
16998
|
+
env_write: envWriteH
|
|
16884
16999
|
};
|
|
16885
17000
|
async function dispatchCommand(ctx, cmd) {
|
|
16886
17001
|
if (cmd.type === "beads_action") {
|
|
@@ -18022,7 +18137,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
18022
18137
|
if (process.env.NODE_ENV === "test") return;
|
|
18023
18138
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
18024
18139
|
if (process.env.CI) return;
|
|
18025
|
-
const current = true ? "2.
|
|
18140
|
+
const current = true ? "2.48.0" : null;
|
|
18026
18141
|
if (!current) return;
|
|
18027
18142
|
const cache = readCache();
|
|
18028
18143
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -18039,7 +18154,7 @@ function checkForUpdates() {
|
|
|
18039
18154
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
18040
18155
|
if (process.env.CI) return;
|
|
18041
18156
|
if (!process.stdout.isTTY) return;
|
|
18042
|
-
const current = true ? "2.
|
|
18157
|
+
const current = true ? "2.48.0" : null;
|
|
18043
18158
|
if (!current) return;
|
|
18044
18159
|
const cache = readCache();
|
|
18045
18160
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -18481,7 +18596,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.s
|
|
|
18481
18596
|
detached: false
|
|
18482
18597
|
});
|
|
18483
18598
|
function currentCliVersion() {
|
|
18484
|
-
return true ? "2.
|
|
18599
|
+
return true ? "2.48.0" : null;
|
|
18485
18600
|
}
|
|
18486
18601
|
function runCmd(cmd, args2, timeoutMs) {
|
|
18487
18602
|
return new Promise((resolve7) => {
|
|
@@ -29849,7 +29964,7 @@ function checkChokidar() {
|
|
|
29849
29964
|
}
|
|
29850
29965
|
async function doctor(args2 = []) {
|
|
29851
29966
|
const json = args2.includes("--json");
|
|
29852
|
-
const cliVersion = true ? "2.
|
|
29967
|
+
const cliVersion = true ? "2.48.0" : "0.0.0-dev";
|
|
29853
29968
|
const apiBase2 = resolveApiBaseUrl();
|
|
29854
29969
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
29855
29970
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -30048,7 +30163,7 @@ async function completion(args2) {
|
|
|
30048
30163
|
// src/commands/version.ts
|
|
30049
30164
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
30050
30165
|
function version2() {
|
|
30051
|
-
const v = true ? "2.
|
|
30166
|
+
const v = true ? "2.48.0" : "unknown";
|
|
30052
30167
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
30053
30168
|
}
|
|
30054
30169
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.48.0",
|
|
4
4
|
"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 — async. The terminal companion for CodeAgent Mobile.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.js",
|