codeam-cli 2.23.13 → 2.23.15
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 +194 -40
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ 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.23.13] — 2026-05-28
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Pair-auto stays alive in heartbeat-only mode on CODEAM_SKIP_AGENT_LAUNCH
|
|
12
|
+
|
|
13
|
+
## [2.23.12] — 2026-05-27
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Auto-enable codespace keep-alive on start
|
|
18
|
+
|
|
7
19
|
## [2.23.11] — 2026-05-27
|
|
8
20
|
|
|
9
21
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -441,7 +441,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
441
441
|
// package.json
|
|
442
442
|
var package_default = {
|
|
443
443
|
name: "codeam-cli",
|
|
444
|
-
version: "2.23.
|
|
444
|
+
version: "2.23.15",
|
|
445
445
|
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.",
|
|
446
446
|
type: "commonjs",
|
|
447
447
|
main: "dist/index.js",
|
|
@@ -5774,7 +5774,7 @@ function readAnonId() {
|
|
|
5774
5774
|
}
|
|
5775
5775
|
function superProperties() {
|
|
5776
5776
|
return {
|
|
5777
|
-
cliVersion: true ? "2.23.
|
|
5777
|
+
cliVersion: true ? "2.23.15" : "0.0.0-dev",
|
|
5778
5778
|
nodeVersion: process.version,
|
|
5779
5779
|
platform: process.platform,
|
|
5780
5780
|
arch: process.arch,
|
|
@@ -10300,36 +10300,43 @@ function wrapCodexCodeBlocks(lines) {
|
|
|
10300
10300
|
function parseCodexChrome(_line) {
|
|
10301
10301
|
return null;
|
|
10302
10302
|
}
|
|
10303
|
+
var CODEX_OPTION_RE = /^\s*([>›]\s+)?(\d+)\.\s+(.+)/;
|
|
10304
|
+
var CODEX_OPTION_START_RE = /^\s*(?:[>›]\s+)?\d+\.\s/;
|
|
10305
|
+
var CODEX_FOOTER_RE = /\bpress\s+enter\s+to\s+(?:confirm|continue|select)\b/i;
|
|
10303
10306
|
function detectCodexSelector(lines) {
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
10307
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
10308
|
+
const t2 = lines[i].trim();
|
|
10309
|
+
if (!t2) continue;
|
|
10310
|
+
if (/^[›>]\s*$/.test(t2) || /^▌\s*$/.test(t2)) return null;
|
|
10311
|
+
if (/^send:\s*⏎|^esc to interrupt/i.test(t2)) return null;
|
|
10312
|
+
break;
|
|
10313
|
+
}
|
|
10308
10314
|
let optionStartIdx = -1;
|
|
10309
10315
|
for (let i = 0; i < lines.length; i++) {
|
|
10310
|
-
if (
|
|
10316
|
+
if (CODEX_OPTION_START_RE.test(lines[i])) {
|
|
10311
10317
|
optionStartIdx = i;
|
|
10312
10318
|
break;
|
|
10313
10319
|
}
|
|
10314
10320
|
}
|
|
10315
10321
|
if (optionStartIdx === -1) return null;
|
|
10316
|
-
const questionParts = [];
|
|
10317
|
-
for (let i = 0; i < optionStartIdx; i++) {
|
|
10318
|
-
const t2 = lines[i].trim();
|
|
10319
|
-
if (!t2) continue;
|
|
10320
|
-
if (/^[>›]\s*$/.test(t2)) continue;
|
|
10321
|
-
questionParts.push(t2);
|
|
10322
|
-
}
|
|
10323
|
-
const question = questionParts.join("\n").trim();
|
|
10324
10322
|
const optionLabels = /* @__PURE__ */ new Map();
|
|
10325
10323
|
let cursorIndex = 0;
|
|
10326
10324
|
let hasCursor = false;
|
|
10325
|
+
let footerAfterOptions = false;
|
|
10326
|
+
let lastOptionLineIdx = optionStartIdx;
|
|
10327
10327
|
for (let i = optionStartIdx; i < lines.length; i++) {
|
|
10328
|
-
const
|
|
10328
|
+
const raw = lines[i];
|
|
10329
|
+
const t2 = raw.trim();
|
|
10329
10330
|
if (!t2) continue;
|
|
10330
|
-
if (
|
|
10331
|
-
|
|
10332
|
-
|
|
10331
|
+
if (CODEX_FOOTER_RE.test(t2)) {
|
|
10332
|
+
footerAfterOptions = true;
|
|
10333
|
+
break;
|
|
10334
|
+
}
|
|
10335
|
+
const m = t2.match(CODEX_OPTION_RE);
|
|
10336
|
+
if (!m) {
|
|
10337
|
+
if (i - lastOptionLineIdx > 2) break;
|
|
10338
|
+
continue;
|
|
10339
|
+
}
|
|
10333
10340
|
const num = parseInt(m[2], 10);
|
|
10334
10341
|
if (!optionLabels.has(num)) {
|
|
10335
10342
|
optionLabels.set(num, m[3].trim());
|
|
@@ -10338,9 +10345,22 @@ function detectCodexSelector(lines) {
|
|
|
10338
10345
|
hasCursor = true;
|
|
10339
10346
|
}
|
|
10340
10347
|
}
|
|
10348
|
+
lastOptionLineIdx = i;
|
|
10341
10349
|
}
|
|
10342
10350
|
const keys = [...optionLabels.keys()].sort((a, b) => a - b);
|
|
10343
10351
|
if (keys.length < 2 || keys[0] !== 1) return null;
|
|
10352
|
+
const questionParts = [];
|
|
10353
|
+
for (let i = 0; i < optionStartIdx; i++) {
|
|
10354
|
+
const t2 = lines[i].trim();
|
|
10355
|
+
if (!t2) continue;
|
|
10356
|
+
if (/^[>›]\s*$/.test(t2)) continue;
|
|
10357
|
+
questionParts.push(t2);
|
|
10358
|
+
}
|
|
10359
|
+
const question = questionParts.join("\n").trim();
|
|
10360
|
+
const questionEndsWithQuery = /\?\s*$/.test(question);
|
|
10361
|
+
if (!hasCursor && !(questionEndsWithQuery && footerAfterOptions)) {
|
|
10362
|
+
return null;
|
|
10363
|
+
}
|
|
10344
10364
|
return {
|
|
10345
10365
|
question,
|
|
10346
10366
|
options: keys.map((k2) => optionLabels.get(k2)),
|
|
@@ -16172,6 +16192,157 @@ async function autoLinkAfterPair(opts) {
|
|
|
16172
16192
|
var fs28 = __toESM(require("fs"));
|
|
16173
16193
|
var os24 = __toESM(require("os"));
|
|
16174
16194
|
var import_crypto7 = require("crypto");
|
|
16195
|
+
|
|
16196
|
+
// src/commands/start-infra-only.ts
|
|
16197
|
+
var INFRA_ONLY_COMMAND_TYPES = /* @__PURE__ */ new Set([
|
|
16198
|
+
// File ops (drive the dashboard's Files panel + open-file).
|
|
16199
|
+
"read_file",
|
|
16200
|
+
"write_file",
|
|
16201
|
+
"list_files",
|
|
16202
|
+
"search_files",
|
|
16203
|
+
// IDE terminal — the user opens a shell inside the codespace
|
|
16204
|
+
// from the dashboard. Independent of any agent.
|
|
16205
|
+
"terminal_open",
|
|
16206
|
+
"terminal_write",
|
|
16207
|
+
"terminal_resize",
|
|
16208
|
+
"terminal_close",
|
|
16209
|
+
// Git surface — repo browsing / commit / push from the
|
|
16210
|
+
// dashboard. Calls plain `git`, no agent involved.
|
|
16211
|
+
"git_status",
|
|
16212
|
+
"git_diff",
|
|
16213
|
+
"git_diff_staged",
|
|
16214
|
+
"git_log",
|
|
16215
|
+
"git_commit",
|
|
16216
|
+
"git_push",
|
|
16217
|
+
"git_pull",
|
|
16218
|
+
"git_resolve",
|
|
16219
|
+
// Review apply path (dashboard's per-file review surface).
|
|
16220
|
+
"apply_file_review",
|
|
16221
|
+
// CLI-side handoff for `codeam link <agent>` (claims tokens
|
|
16222
|
+
// for the user's LinkedAgents from inside the codespace).
|
|
16223
|
+
"request_link_credentials",
|
|
16224
|
+
// Lets the dashboard toggle the codespace idle-timeout
|
|
16225
|
+
// (defaults to 240 min inside a codespace).
|
|
16226
|
+
"set_keep_alive"
|
|
16227
|
+
]);
|
|
16228
|
+
async function startInfraOnly(agentId) {
|
|
16229
|
+
const session = getActiveSession();
|
|
16230
|
+
if (!session?.pluginId) {
|
|
16231
|
+
throw new Error("startInfraOnly: no active session found in config");
|
|
16232
|
+
}
|
|
16233
|
+
const pluginId = session.pluginId;
|
|
16234
|
+
const cwd = process.cwd();
|
|
16235
|
+
const agentMeta = AGENT_REGISTRY[agentId];
|
|
16236
|
+
if (!agentMeta) {
|
|
16237
|
+
throw new Error(`startInfraOnly: unknown agent id "${agentId}"`);
|
|
16238
|
+
}
|
|
16239
|
+
const keepAliveCtx = {
|
|
16240
|
+
inCodespace: process.env.CODESPACES === "true",
|
|
16241
|
+
codespaceName: process.env.CODESPACE_NAME
|
|
16242
|
+
};
|
|
16243
|
+
const { apply: setKeepAlive2 } = buildKeepAlive(keepAliveCtx);
|
|
16244
|
+
if (keepAliveCtx.inCodespace) {
|
|
16245
|
+
setKeepAlive2(true);
|
|
16246
|
+
}
|
|
16247
|
+
const fileWatcher = session.pluginAuthToken ? new FileWatcherService({
|
|
16248
|
+
workingDir: cwd,
|
|
16249
|
+
sessionId: session.id,
|
|
16250
|
+
pluginId,
|
|
16251
|
+
pluginAuthToken: session.pluginAuthToken
|
|
16252
|
+
}) : null;
|
|
16253
|
+
let relayRef = null;
|
|
16254
|
+
const ctx = {
|
|
16255
|
+
// Agent-touching fields are not used by any of the commands
|
|
16256
|
+
// we dispatch in this mode. Casting through `unknown` keeps
|
|
16257
|
+
// TypeScript happy without forcing a HandlerContext refactor
|
|
16258
|
+
// — the field-touching commands are filtered out by
|
|
16259
|
+
// INFRA_ONLY_COMMAND_TYPES before the handler is even called.
|
|
16260
|
+
agent: null,
|
|
16261
|
+
outputSvc: null,
|
|
16262
|
+
historySvc: null,
|
|
16263
|
+
runtime: null,
|
|
16264
|
+
relay: null,
|
|
16265
|
+
setKeepAlive: setKeepAlive2,
|
|
16266
|
+
keepAliveCtx,
|
|
16267
|
+
pluginId,
|
|
16268
|
+
sessionId: session.id,
|
|
16269
|
+
pluginAuthToken: session.pluginAuthToken ?? void 0
|
|
16270
|
+
};
|
|
16271
|
+
const relay = new CommandRelayService(
|
|
16272
|
+
pluginId,
|
|
16273
|
+
async (cmd) => {
|
|
16274
|
+
if (!INFRA_ONLY_COMMAND_TYPES.has(cmd.type)) {
|
|
16275
|
+
log.trace("infra-only", `dropping agent-only command type=${cmd.type}`);
|
|
16276
|
+
return;
|
|
16277
|
+
}
|
|
16278
|
+
const handler = handlers[cmd.type];
|
|
16279
|
+
if (!handler) {
|
|
16280
|
+
log.trace("infra-only", `no handler registered for type=${cmd.type}`);
|
|
16281
|
+
return;
|
|
16282
|
+
}
|
|
16283
|
+
const parsed = parsePayload2(startCommandSchema, cmd.payload);
|
|
16284
|
+
if (!parsed) {
|
|
16285
|
+
log.trace("infra-only", `malformed payload for type=${cmd.type}`);
|
|
16286
|
+
return;
|
|
16287
|
+
}
|
|
16288
|
+
try {
|
|
16289
|
+
await handler(ctx, cmd, parsed);
|
|
16290
|
+
} catch (err) {
|
|
16291
|
+
log.warn("infra-only", `handler ${cmd.type} threw`, err);
|
|
16292
|
+
}
|
|
16293
|
+
},
|
|
16294
|
+
agentMeta,
|
|
16295
|
+
[]
|
|
16296
|
+
// empty agents list → dashboard renders NoAgentHero
|
|
16297
|
+
);
|
|
16298
|
+
ctx.relay = relay;
|
|
16299
|
+
relayRef = relay;
|
|
16300
|
+
const terminalEmitter = new ChunkEmitter({
|
|
16301
|
+
sessionId: session.id,
|
|
16302
|
+
pluginId,
|
|
16303
|
+
pluginAuthToken: session.pluginAuthToken
|
|
16304
|
+
});
|
|
16305
|
+
registerTerminalHandlers({
|
|
16306
|
+
onData: ({ sessionId: termSessionId, data }) => {
|
|
16307
|
+
void terminalEmitter.send({
|
|
16308
|
+
type: "terminal_data",
|
|
16309
|
+
terminalSessionId: termSessionId,
|
|
16310
|
+
data,
|
|
16311
|
+
done: false
|
|
16312
|
+
});
|
|
16313
|
+
},
|
|
16314
|
+
onExit: ({ sessionId: termSessionId, exitCode }) => {
|
|
16315
|
+
void terminalEmitter.send({
|
|
16316
|
+
type: "terminal_exit",
|
|
16317
|
+
terminalSessionId: termSessionId,
|
|
16318
|
+
exitCode,
|
|
16319
|
+
done: true
|
|
16320
|
+
});
|
|
16321
|
+
}
|
|
16322
|
+
});
|
|
16323
|
+
relay.start();
|
|
16324
|
+
if (fileWatcher) {
|
|
16325
|
+
fileWatcher.start().catch(() => {
|
|
16326
|
+
});
|
|
16327
|
+
}
|
|
16328
|
+
const sigHandler = () => {
|
|
16329
|
+
try {
|
|
16330
|
+
relayRef?.stop();
|
|
16331
|
+
} catch {
|
|
16332
|
+
}
|
|
16333
|
+
void fileWatcher?.stop();
|
|
16334
|
+
closeAllTerminals();
|
|
16335
|
+
cleanupAttachmentTempFiles();
|
|
16336
|
+
process.exit(0);
|
|
16337
|
+
};
|
|
16338
|
+
process.once("SIGINT", sigHandler);
|
|
16339
|
+
process.once("SIGTERM", sigHandler);
|
|
16340
|
+
process.once("SIGHUP", sigHandler);
|
|
16341
|
+
await new Promise(() => {
|
|
16342
|
+
});
|
|
16343
|
+
}
|
|
16344
|
+
|
|
16345
|
+
// src/commands/pair-auto.ts
|
|
16175
16346
|
var API_BASE8 = resolveApiBaseUrl();
|
|
16176
16347
|
function fail(msg) {
|
|
16177
16348
|
console.error(`
|
|
@@ -16320,24 +16491,7 @@ async function pairAuto(args2) {
|
|
|
16320
16491
|
console.log(
|
|
16321
16492
|
" Skipping agent launch \u2014 install an agent from the dashboard to start chatting."
|
|
16322
16493
|
);
|
|
16323
|
-
|
|
16324
|
-
pluginId,
|
|
16325
|
-
async () => {
|
|
16326
|
-
},
|
|
16327
|
-
AGENT_REGISTRY[claimed.agent],
|
|
16328
|
-
[]
|
|
16329
|
-
// empty agents list
|
|
16330
|
-
);
|
|
16331
|
-
heartbeatRelay.start();
|
|
16332
|
-
const sigHandler = () => {
|
|
16333
|
-
heartbeatRelay.stop();
|
|
16334
|
-
process.exit(0);
|
|
16335
|
-
};
|
|
16336
|
-
process.once("SIGINT", sigHandler);
|
|
16337
|
-
process.once("SIGTERM", sigHandler);
|
|
16338
|
-
process.once("SIGHUP", sigHandler);
|
|
16339
|
-
await new Promise(() => {
|
|
16340
|
-
});
|
|
16494
|
+
await startInfraOnly(claimed.agent);
|
|
16341
16495
|
return;
|
|
16342
16496
|
}
|
|
16343
16497
|
console.log(" Starting agent loop\u2026");
|
|
@@ -18586,7 +18740,7 @@ function checkChokidar() {
|
|
|
18586
18740
|
}
|
|
18587
18741
|
async function doctor(args2 = []) {
|
|
18588
18742
|
const json = args2.includes("--json");
|
|
18589
|
-
const cliVersion = true ? "2.23.
|
|
18743
|
+
const cliVersion = true ? "2.23.15" : "0.0.0-dev";
|
|
18590
18744
|
const apiBase = resolveApiBaseUrl();
|
|
18591
18745
|
const diagnosticId = (0, import_node_crypto5.randomUUID)();
|
|
18592
18746
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -18785,7 +18939,7 @@ async function completion(args2) {
|
|
|
18785
18939
|
// src/commands/version.ts
|
|
18786
18940
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
18787
18941
|
function version2() {
|
|
18788
|
-
const v = true ? "2.23.
|
|
18942
|
+
const v = true ? "2.23.15" : "unknown";
|
|
18789
18943
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
18790
18944
|
}
|
|
18791
18945
|
|
|
@@ -19013,7 +19167,7 @@ function checkForUpdates() {
|
|
|
19013
19167
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
19014
19168
|
if (process.env.CI) return;
|
|
19015
19169
|
if (!process.stdout.isTTY) return;
|
|
19016
|
-
const current = true ? "2.23.
|
|
19170
|
+
const current = true ? "2.23.15" : null;
|
|
19017
19171
|
if (!current) return;
|
|
19018
19172
|
const cache = readCache();
|
|
19019
19173
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.23.
|
|
3
|
+
"version": "2.23.15",
|
|
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",
|