codeam-cli 2.23.34 → 2.23.36
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 +22 -0
- package/dist/index.js +82 -30
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@ 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.35] — 2026-05-31
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **cli:** Move bracketed-paste into Claude strategy + agent-leak hook
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **cli:** Wrap multi-line prompts in bracketed-paste so \r submits
|
|
16
|
+
|
|
17
|
+
## [2.23.34] — 2026-05-31
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **cli:** Wrap multi-line prompts in bracketed-paste so \r submits
|
|
22
|
+
|
|
23
|
+
## [2.23.33] — 2026-05-31
|
|
24
|
+
|
|
25
|
+
### Performance
|
|
26
|
+
|
|
27
|
+
- **cli:** Coalesce file-watcher emissions in a 250 ms window
|
|
28
|
+
|
|
7
29
|
## [2.23.32] — 2026-05-31
|
|
8
30
|
|
|
9
31
|
### Added
|
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.36",
|
|
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.36" : "0.0.0-dev",
|
|
5778
5778
|
nodeVersion: process.version,
|
|
5779
5779
|
platform: process.platform,
|
|
5780
5780
|
arch: process.arch,
|
|
@@ -6307,21 +6307,13 @@ var AgentService = class _AgentService {
|
|
|
6307
6307
|
/**
|
|
6308
6308
|
* Write one prompt to the PTY and submit it.
|
|
6309
6309
|
*
|
|
6310
|
-
*
|
|
6311
|
-
*
|
|
6312
|
-
*
|
|
6313
|
-
*
|
|
6314
|
-
*
|
|
6315
|
-
*
|
|
6316
|
-
*
|
|
6317
|
-
* agent reply).
|
|
6318
|
-
*
|
|
6319
|
-
* Fix: explicitly bracket the paste ourselves (`ESC[200~ <text>
|
|
6320
|
-
* ESC[201~`) so the end marker closes the paste deterministically.
|
|
6321
|
-
* A short delay later we send `\r` — now OUTSIDE the bracket — so
|
|
6322
|
-
* Claude's input handler treats it as Submit, not paste content.
|
|
6323
|
-
* Single-line text doesn't trigger paste mode, so we keep the
|
|
6324
|
-
* legacy `text + \r` path for that case (cheaper, no markers).
|
|
6310
|
+
* Per-agent input wire formatting (e.g. Claude Code's bracketed-
|
|
6311
|
+
* paste markers) lives in the runtime strategy's
|
|
6312
|
+
* `prepareInputWrites(text)`. This method only knows the generic
|
|
6313
|
+
* contract: emit N writes in order, wait `submitDelayMs`, then
|
|
6314
|
+
* send `\r` to submit. The default (when the strategy doesn't
|
|
6315
|
+
* override) is one `s.write(text)` followed by `\r` after 50 ms,
|
|
6316
|
+
* which works for plain REPL agents (Aider).
|
|
6325
6317
|
*
|
|
6326
6318
|
* Marks the agent busy so subsequent `sendCommand` calls queue
|
|
6327
6319
|
* instead of stacking pastes.
|
|
@@ -6331,14 +6323,12 @@ var AgentService = class _AgentService {
|
|
|
6331
6323
|
const s = this.strategy;
|
|
6332
6324
|
this.agentBusy = true;
|
|
6333
6325
|
log.trace("agent", `submit text=${text.length}B (queued=${this.pendingInputs.length})`);
|
|
6334
|
-
const
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
setTimeout(() => s.write("\r"), 50);
|
|
6341
|
-
}
|
|
6326
|
+
const prep = this.runtime.prepareInputWrites?.(text) ?? {
|
|
6327
|
+
writes: [text],
|
|
6328
|
+
submitDelayMs: 50
|
|
6329
|
+
};
|
|
6330
|
+
for (const w3 of prep.writes) s.write(w3);
|
|
6331
|
+
setTimeout(() => s.write("\r"), prep.submitDelayMs);
|
|
6342
6332
|
}
|
|
6343
6333
|
drainPending() {
|
|
6344
6334
|
if (!this.strategy || this.pendingInputs.length === 0) return;
|
|
@@ -9831,6 +9821,31 @@ var ClaudeRuntimeStrategy = class {
|
|
|
9831
9821
|
constructor(os26) {
|
|
9832
9822
|
this.os = os26;
|
|
9833
9823
|
}
|
|
9824
|
+
/**
|
|
9825
|
+
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
9826
|
+
* boot (`ESC[?2004h`). When a multi-line write arrives, Claude
|
|
9827
|
+
* opens a paste boundary that stays open until it sees the
|
|
9828
|
+
* matching `ESC[201~` end marker. A naïve `text + \r` lands the
|
|
9829
|
+
* `\r` INSIDE the open bracket as paste CONTENT, and the prompt
|
|
9830
|
+
* sits in the input forever (the user's mobile COMMENT flow was
|
|
9831
|
+
* stacking `[Pasted text #N]` markers with no submit).
|
|
9832
|
+
*
|
|
9833
|
+
* Fix: wrap multi-line prompts in the bracket markers ourselves
|
|
9834
|
+
* so the end marker closes the paste deterministically. The
|
|
9835
|
+
* caller emits `\r` 80 ms later — now OUTSIDE the bracket — and
|
|
9836
|
+
* Claude's input handler treats it as a normal Submit. Single-
|
|
9837
|
+
* line prompts don't trigger paste mode so we keep the bare
|
|
9838
|
+
* `text + \r` path for that case.
|
|
9839
|
+
*/
|
|
9840
|
+
prepareInputWrites(text) {
|
|
9841
|
+
if (text.includes("\n")) {
|
|
9842
|
+
return {
|
|
9843
|
+
writes: [`\x1B[200~${text}\x1B[201~`],
|
|
9844
|
+
submitDelayMs: 80
|
|
9845
|
+
};
|
|
9846
|
+
}
|
|
9847
|
+
return { writes: [text], submitDelayMs: 50 };
|
|
9848
|
+
}
|
|
9834
9849
|
async prepareLaunch() {
|
|
9835
9850
|
const sessionId = (0, import_node_crypto4.randomUUID)();
|
|
9836
9851
|
const sessionArgs = ["--session-id", sessionId];
|
|
@@ -11732,6 +11747,21 @@ var PtyBuffer = class {
|
|
|
11732
11747
|
this.raw = "";
|
|
11733
11748
|
this.lastPushAt = 0;
|
|
11734
11749
|
}
|
|
11750
|
+
/**
|
|
11751
|
+
* Re-arm the terminal-input detector without flipping `active`.
|
|
11752
|
+
* Called by the orchestrator when a pending terminal-turn signal
|
|
11753
|
+
* doesn't pan out — the JSONL polling timed out without finding a
|
|
11754
|
+
* new user message, so whatever produced the printable byte (most
|
|
11755
|
+
* commonly Claude's ghost-text completion painted ~300-500 ms after
|
|
11756
|
+
* the previous turn settled) was NOT a real user keystroke. We
|
|
11757
|
+
* need detection to fire again on the next legitimate keystroke,
|
|
11758
|
+
* otherwise the human's eventual CLI prompt is lost and only the
|
|
11759
|
+
* agent's reply lands on mobile (the duplicate-response /
|
|
11760
|
+
* missing-user-bubble class of bug the user reported).
|
|
11761
|
+
*/
|
|
11762
|
+
resetTerminalInputGate() {
|
|
11763
|
+
this.terminalInputPending = false;
|
|
11764
|
+
}
|
|
11735
11765
|
/**
|
|
11736
11766
|
* Ingest a raw PTY frame. Always accumulates so cold-startup
|
|
11737
11767
|
* frames aren't lost. Returns whether the buffer was active at
|
|
@@ -11916,6 +11946,22 @@ var OutputService = class _OutputService {
|
|
|
11916
11946
|
}
|
|
11917
11947
|
await this.send({ type: "new_turn", done: false }, { critical: true });
|
|
11918
11948
|
}
|
|
11949
|
+
/**
|
|
11950
|
+
* Re-arm the terminal-turn detection gate without opening a bogus
|
|
11951
|
+
* turn. Called by the orchestrator when `waitForNewUserMessage`
|
|
11952
|
+
* times out — Claude's ghost-text completion (painted between
|
|
11953
|
+
* turns) trips the printable-byte detector before the user has
|
|
11954
|
+
* actually typed anything. Calling `startTerminalTurn` here would
|
|
11955
|
+
* emit `clear` + `new_turn` to mobile and then `beginTurn` would
|
|
11956
|
+
* activate the PTY buffer; the tick poll would render the still-
|
|
11957
|
+
* visible previous response as fresh `text` chunks → a duplicate
|
|
11958
|
+
* agent bubble on mobile. Resetting the gates instead means the
|
|
11959
|
+
* next legitimate keystroke re-fires detection cleanly.
|
|
11960
|
+
*/
|
|
11961
|
+
resetTerminalTurnGate() {
|
|
11962
|
+
this.terminalTurnPending = false;
|
|
11963
|
+
this.pty.resetTerminalInputGate();
|
|
11964
|
+
}
|
|
11919
11965
|
/**
|
|
11920
11966
|
* Begin a turn after a `resume_session` request. Includes the
|
|
11921
11967
|
* `resumedSessionId` so the client wipes its history and
|
|
@@ -12403,7 +12449,7 @@ var HistoryService = class _HistoryService {
|
|
|
12403
12449
|
* Poll the JSONL until a new user message appears after previousCount entries.
|
|
12404
12450
|
* Returns the text of the new user message, or null if not found within timeoutMs.
|
|
12405
12451
|
*/
|
|
12406
|
-
async waitForNewUserMessage(previousCount, timeoutMs =
|
|
12452
|
+
async waitForNewUserMessage(previousCount, timeoutMs = 6e4) {
|
|
12407
12453
|
const deadline = Date.now() + timeoutMs;
|
|
12408
12454
|
while (Date.now() < deadline) {
|
|
12409
12455
|
if (!this.currentConversationId) return null;
|
|
@@ -16348,7 +16394,13 @@ async function start(requestedAgent) {
|
|
|
16348
16394
|
},
|
|
16349
16395
|
() => {
|
|
16350
16396
|
const prevCount = historySvc.getCurrentMessageCount();
|
|
16351
|
-
historySvc.waitForNewUserMessage(prevCount).then((userText) =>
|
|
16397
|
+
historySvc.waitForNewUserMessage(prevCount).then((userText) => {
|
|
16398
|
+
if (userText) {
|
|
16399
|
+
void outputSvc.startTerminalTurn(userText);
|
|
16400
|
+
} else {
|
|
16401
|
+
outputSvc.resetTerminalTurnGate();
|
|
16402
|
+
}
|
|
16403
|
+
}).catch(() => outputSvc.resetTerminalTurnGate());
|
|
16352
16404
|
},
|
|
16353
16405
|
session.pluginAuthToken,
|
|
16354
16406
|
runtime
|
|
@@ -19192,7 +19244,7 @@ function checkChokidar() {
|
|
|
19192
19244
|
}
|
|
19193
19245
|
async function doctor(args2 = []) {
|
|
19194
19246
|
const json = args2.includes("--json");
|
|
19195
|
-
const cliVersion = true ? "2.23.
|
|
19247
|
+
const cliVersion = true ? "2.23.36" : "0.0.0-dev";
|
|
19196
19248
|
const apiBase = resolveApiBaseUrl();
|
|
19197
19249
|
const diagnosticId = (0, import_node_crypto6.randomUUID)();
|
|
19198
19250
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -19391,7 +19443,7 @@ async function completion(args2) {
|
|
|
19391
19443
|
// src/commands/version.ts
|
|
19392
19444
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
19393
19445
|
function version2() {
|
|
19394
|
-
const v = true ? "2.23.
|
|
19446
|
+
const v = true ? "2.23.36" : "unknown";
|
|
19395
19447
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
19396
19448
|
}
|
|
19397
19449
|
|
|
@@ -19619,7 +19671,7 @@ function checkForUpdates() {
|
|
|
19619
19671
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
19620
19672
|
if (process.env.CI) return;
|
|
19621
19673
|
if (!process.stdout.isTTY) return;
|
|
19622
|
-
const current = true ? "2.23.
|
|
19674
|
+
const current = true ? "2.23.36" : null;
|
|
19623
19675
|
if (!current) return;
|
|
19624
19676
|
const cache = readCache();
|
|
19625
19677
|
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.36",
|
|
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",
|