codeam-cli 2.23.18 → 2.23.20

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 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.19] — 2026-05-30
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Serialise prompt submissions while agent is busy
12
+
13
+ ## [2.23.18] — 2026-05-28
14
+
15
+ ### CI
16
+
17
+ - **release:** Fix JetBrains preflight URL + 404000 status-code bug
18
+
7
19
  ## [2.23.14] — 2026-05-28
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.18",
444
+ version: "2.23.20",
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.18" : "0.0.0-dev",
5777
+ cliVersion: true ? "2.23.20" : "0.0.0-dev",
5778
5778
  nodeVersion: process.version,
5779
5779
  platform: process.platform,
5780
5780
  arch: process.arch,
@@ -6190,7 +6190,7 @@ var CommandRelayService = class {
6190
6190
  };
6191
6191
 
6192
6192
  // src/services/agent.service.ts
6193
- var AgentService = class {
6193
+ var AgentService = class _AgentService {
6194
6194
  constructor(runtime, opts) {
6195
6195
  this.runtime = runtime;
6196
6196
  this.opts = opts;
@@ -6200,6 +6200,10 @@ var AgentService = class {
6200
6200
  this.agentReady = true;
6201
6201
  setTimeout(() => this.drainPending(), 250);
6202
6202
  }
6203
+ if (d3.length > 0) {
6204
+ this.lastAgentDataAt = Date.now();
6205
+ this.scheduleQuietCheck();
6206
+ }
6203
6207
  (opts.onData ?? (() => {
6204
6208
  }))(d3);
6205
6209
  },
@@ -6226,6 +6230,34 @@ var AgentService = class {
6226
6230
  */
6227
6231
  agentReady = false;
6228
6232
  pendingInputs = [];
6233
+ /**
6234
+ * Serialised-submission state. Without this, a second `sendCommand`
6235
+ * arriving while the agent is still rendering its response to the
6236
+ * first lands in Claude Code's input field as a `[Pasted text #N]`
6237
+ * marker (bracketed-paste mode kicks in for multi-line writes). The
6238
+ * `\r` we schedule 50 ms later is consumed as paste content, not
6239
+ * submission, so the prompt sits in the input forever — the user
6240
+ * reported "se queda bloqueado en la terminal".
6241
+ *
6242
+ * The fix is agent-agnostic: track when the PTY last emitted bytes
6243
+ * (see `lastAgentDataAt`); after `QUIET_MS` of silence we consider
6244
+ * the agent idle and drain the next queued prompt. Works for any
6245
+ * PTY-spawned runtime (Claude Code, Codex, future agents) because
6246
+ * "no output in N ms" is a universal idle signal — we don't depend
6247
+ * on Claude's `❯` prompt or Codex's input-box rendering.
6248
+ */
6249
+ agentBusy = false;
6250
+ lastAgentDataAt = 0;
6251
+ quietTimer = null;
6252
+ /**
6253
+ * How long the PTY must be silent before we consider the agent
6254
+ * idle and submit the next queued prompt. 1500 ms is generous
6255
+ * enough that a streamed response with brief mid-token pauses
6256
+ * (tool calls, model latency hiccups) doesn't get cut off, but
6257
+ * short enough that the user doesn't perceive lag between a
6258
+ * normal turn finishing and the next queued comment firing.
6259
+ */
6260
+ static QUIET_MS = 1500;
6229
6261
  /**
6230
6262
  * Cached spawn() result so `restart()` can reuse the resolved
6231
6263
  * binary path without re-running the strategy's install path. The
@@ -6234,17 +6266,55 @@ var AgentService = class {
6234
6266
  * the SAME binary with new resume args.
6235
6267
  */
6236
6268
  initialLaunch = null;
6269
+ /**
6270
+ * Debounced "agent went idle" check. Re-arms itself as long as
6271
+ * fresh PTY output keeps arriving. When the gap since the last
6272
+ * byte exceeds `QUIET_MS`, flip `agentBusy=false` and drain the
6273
+ * next queued prompt (if any). Idempotent — a no-op when the
6274
+ * timer is already pending.
6275
+ *
6276
+ * Re-arm uses the REMAINING wait (QUIET_MS - sinceLast), not a
6277
+ * full QUIET_MS — otherwise a single late data byte resets the
6278
+ * waiter to a fresh 1.5 s timer and the queue never drains.
6279
+ */
6280
+ scheduleQuietCheck() {
6281
+ if (this.quietTimer) return;
6282
+ const tick = () => {
6283
+ this.quietTimer = null;
6284
+ const sinceLast = Date.now() - this.lastAgentDataAt;
6285
+ if (sinceLast >= _AgentService.QUIET_MS) {
6286
+ if (this.agentBusy) {
6287
+ this.agentBusy = false;
6288
+ log.trace("agent", "agent went idle \u2014 draining next pending");
6289
+ }
6290
+ this.drainPending();
6291
+ return;
6292
+ }
6293
+ this.quietTimer = setTimeout(tick, _AgentService.QUIET_MS - sinceLast);
6294
+ };
6295
+ this.quietTimer = setTimeout(tick, _AgentService.QUIET_MS);
6296
+ }
6297
+ /**
6298
+ * Write one prompt to the PTY using the existing pacing (text →
6299
+ * 50–300 ms → `\r` submit). Marks the agent busy so subsequent
6300
+ * `sendCommand` calls queue instead of stacking pastes.
6301
+ */
6302
+ submitToPty(text) {
6303
+ if (!this.strategy) return;
6304
+ const s = this.strategy;
6305
+ this.agentBusy = true;
6306
+ log.trace("agent", `submit text=${text.length}B (queued=${this.pendingInputs.length})`);
6307
+ s.write(text);
6308
+ const lineCount = text.split("\n").length;
6309
+ const delay = Math.min(300, 50 + (lineCount - 1) * 40);
6310
+ setTimeout(() => s.write("\r"), delay);
6311
+ }
6237
6312
  drainPending() {
6238
6313
  if (!this.strategy || this.pendingInputs.length === 0) return;
6239
- const s = this.strategy;
6240
- log.trace("claude", `drain pending=${this.pendingInputs.length}`);
6241
- let offset = 0;
6242
- for (const text of this.pendingInputs) {
6243
- setTimeout(() => s.write(text), offset);
6244
- setTimeout(() => s.write("\r"), offset + 50);
6245
- offset += 200;
6246
- }
6247
- this.pendingInputs.length = 0;
6314
+ if (this.agentBusy) return;
6315
+ const next = this.pendingInputs.shift();
6316
+ if (next === void 0) return;
6317
+ this.submitToPty(next);
6248
6318
  }
6249
6319
  async spawn() {
6250
6320
  let launch;
@@ -6332,12 +6402,12 @@ var AgentService = class {
6332
6402
  this.pendingInputs.push(text);
6333
6403
  return;
6334
6404
  }
6335
- const s = this.strategy;
6336
- log.trace("claude", `sendCommand text=${text.length}B`);
6337
- s.write(text);
6338
- const lineCount = text.split("\n").length;
6339
- const delay = Math.min(300, 50 + (lineCount - 1) * 40);
6340
- setTimeout(() => s.write("\r"), delay);
6405
+ if (this.agentBusy) {
6406
+ log.trace("claude", `sendCommand queued (agent busy) text=${text.length}B`);
6407
+ this.pendingInputs.push(text);
6408
+ return;
6409
+ }
6410
+ this.submitToPty(text);
6341
6411
  }
6342
6412
  /**
6343
6413
  * Navigate a React Ink selector to the given 0-based target index and confirm.
@@ -9557,9 +9627,10 @@ function detectSelector(lines) {
9557
9627
  (l) => /\b(?:trust\s+the\s+files|trust\s+this\s+folder|safety\s+check)\b/i.test(l)
9558
9628
  );
9559
9629
  if (!hasCursor && !looksLikeTrust) return null;
9630
+ const OPTION_RE = /^(?:[❯>]\s*)?(\d+)\.(\s+|(?=\D))(.+)/;
9560
9631
  let optionStartIdx = -1;
9561
9632
  for (let i = 0; i < clean.length; i++) {
9562
- if (/^(?:[❯>]\s*)?\d+\.\s/.test(clean[i].trim())) {
9633
+ if (OPTION_RE.test(clean[i].trim())) {
9563
9634
  optionStartIdx = i;
9564
9635
  break;
9565
9636
  }
@@ -9582,11 +9653,11 @@ function detectSelector(lines) {
9582
9653
  for (let i = optionStartIdx; i < clean.length; i++) {
9583
9654
  const t2 = clean[i].trim();
9584
9655
  if (!t2) continue;
9585
- const m = t2.match(/^(?:[❯>]\s*)?(\d+)\.\s+(.+)/);
9656
+ const m = t2.match(OPTION_RE);
9586
9657
  if (m) {
9587
9658
  const num = parseInt(m[1], 10);
9588
9659
  if (!optionLabels.has(num)) {
9589
- optionLabels.set(num, m[2].trim());
9660
+ optionLabels.set(num, m[3].trim());
9590
9661
  optionDescs.set(num, []);
9591
9662
  }
9592
9663
  currentNum = num;
@@ -18733,7 +18804,7 @@ function checkChokidar() {
18733
18804
  }
18734
18805
  async function doctor(args2 = []) {
18735
18806
  const json = args2.includes("--json");
18736
- const cliVersion = true ? "2.23.18" : "0.0.0-dev";
18807
+ const cliVersion = true ? "2.23.20" : "0.0.0-dev";
18737
18808
  const apiBase = resolveApiBaseUrl();
18738
18809
  const diagnosticId = (0, import_node_crypto5.randomUUID)();
18739
18810
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -18932,7 +19003,7 @@ async function completion(args2) {
18932
19003
  // src/commands/version.ts
18933
19004
  var import_picocolors13 = __toESM(require("picocolors"));
18934
19005
  function version2() {
18935
- const v = true ? "2.23.18" : "unknown";
19006
+ const v = true ? "2.23.20" : "unknown";
18936
19007
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
18937
19008
  }
18938
19009
 
@@ -19160,7 +19231,7 @@ function checkForUpdates() {
19160
19231
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
19161
19232
  if (process.env.CI) return;
19162
19233
  if (!process.stdout.isTTY) return;
19163
- const current = true ? "2.23.18" : null;
19234
+ const current = true ? "2.23.20" : null;
19164
19235
  if (!current) return;
19165
19236
  const cache = readCache();
19166
19237
  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.18",
3
+ "version": "2.23.20",
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",