codeam-cli 2.9.5 → 2.9.7
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 +7 -57
- 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.9.5] — 2026-05-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Preserve newlines when scanning PTY for API errors
|
|
12
|
+
|
|
7
13
|
## [2.9.4] — 2026-05-10
|
|
8
14
|
|
|
9
15
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -1477,7 +1477,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
1477
1477
|
// package.json
|
|
1478
1478
|
var package_default = {
|
|
1479
1479
|
name: "codeam-cli",
|
|
1480
|
-
version: "2.9.
|
|
1480
|
+
version: "2.9.7",
|
|
1481
1481
|
description: "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands \u2014 from anywhere.",
|
|
1482
1482
|
type: "commonjs",
|
|
1483
1483
|
main: "dist/index.js",
|
|
@@ -5285,13 +5285,6 @@ var OutputService = class _OutputService {
|
|
|
5285
5285
|
pollTimer = null;
|
|
5286
5286
|
startTime = 0;
|
|
5287
5287
|
terminalTurnPending = false;
|
|
5288
|
-
/**
|
|
5289
|
-
* Tracks whether we already emitted an api-error status chunk for
|
|
5290
|
-
* the current turn. The error pattern usually appears in multiple
|
|
5291
|
-
* consecutive PTY frames as Claude redraws — without this flag the
|
|
5292
|
-
* mobile/web client would see the same banner several times in a row.
|
|
5293
|
-
*/
|
|
5294
|
-
apiErrorEmittedThisTurn = false;
|
|
5295
5288
|
onSessionIdDetected;
|
|
5296
5289
|
onRateLimitDetected;
|
|
5297
5290
|
onTurnComplete;
|
|
@@ -5382,7 +5375,6 @@ var OutputService = class _OutputService {
|
|
|
5382
5375
|
);
|
|
5383
5376
|
this.tryExtractSessionId(raw);
|
|
5384
5377
|
this.tryDetectRateLimit(raw);
|
|
5385
|
-
this.tryDetectApiError(this.pty.content);
|
|
5386
5378
|
}
|
|
5387
5379
|
dispose() {
|
|
5388
5380
|
this.stopPoll();
|
|
@@ -5394,7 +5386,6 @@ var OutputService = class _OutputService {
|
|
|
5394
5386
|
this.pty.activate();
|
|
5395
5387
|
this.steps.reset();
|
|
5396
5388
|
this.lastSentContent = "";
|
|
5397
|
-
this.apiErrorEmittedThisTurn = false;
|
|
5398
5389
|
this.startTime = Date.now();
|
|
5399
5390
|
this.pollTimer = setInterval(() => this.tick(), _OutputService.POLL_MS);
|
|
5400
5391
|
}
|
|
@@ -5535,51 +5526,7 @@ var OutputService = class _OutputService {
|
|
|
5535
5526
|
this.onRateLimitDetected(match[1].trim());
|
|
5536
5527
|
}
|
|
5537
5528
|
}
|
|
5538
|
-
/**
|
|
5539
|
-
* Detect provider-side API errors that block the turn (out of
|
|
5540
|
-
* credits, quota exceeded, auth invalid). These appear in Claude's
|
|
5541
|
-
* TUI as `└ Credit balance too low …` / `└ API Error: …` and would
|
|
5542
|
-
* otherwise be filtered by `filterChrome` as box-drawing chrome —
|
|
5543
|
-
* leaving the mobile chat looking frozen when the user actually
|
|
5544
|
-
* just needs to add funds or wait.
|
|
5545
|
-
*
|
|
5546
|
-
* Side-channel: emits a `status` chunk so the UI can render a
|
|
5547
|
-
* banner above the (empty) reply. Does NOT modify the chrome
|
|
5548
|
-
* filter — that's tuned for Windows ConPTY quirks and stays as-is.
|
|
5549
|
-
*
|
|
5550
|
-
* Once-per-turn guard: Claude redraws the same error in multiple
|
|
5551
|
-
* frames. Without the guard the user sees the same banner several
|
|
5552
|
-
* times in a row.
|
|
5553
|
-
*/
|
|
5554
|
-
tryDetectApiError(text) {
|
|
5555
|
-
if (this.apiErrorEmittedThisTurn) return;
|
|
5556
|
-
const printable = text.replace(/\x1B\[[^@-~]*[@-~]/g, "").replace(/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/g, "");
|
|
5557
|
-
const message = extractApiErrorMessage(printable);
|
|
5558
|
-
if (!message) return;
|
|
5559
|
-
this.apiErrorEmittedThisTurn = true;
|
|
5560
|
-
this.send({ type: "status", content: message }, { critical: true }).catch(() => {
|
|
5561
|
-
});
|
|
5562
|
-
}
|
|
5563
5529
|
};
|
|
5564
|
-
function extractApiErrorMessage(text) {
|
|
5565
|
-
const credit = text.match(/Credit balance too low[^\n]*/i);
|
|
5566
|
-
if (credit) {
|
|
5567
|
-
return credit[0].trim().replace(/\s+/g, " ");
|
|
5568
|
-
}
|
|
5569
|
-
const apiError = text.match(/API Error[:\s]+([^\n]{3,200})/i);
|
|
5570
|
-
if (apiError) {
|
|
5571
|
-
return `API Error: ${apiError[1].trim()}`;
|
|
5572
|
-
}
|
|
5573
|
-
if (/(?:\bquota\b.*\b(?:exceeded|exhausted)\b|\binsufficient[\s_-]+(?:credits?|funds?|quota)\b)/i.test(text)) {
|
|
5574
|
-
const m = text.match(/(?:\bquota\b[^\n]{0,200}|insufficient[^\n]{0,200})/i);
|
|
5575
|
-
return m ? m[0].trim().replace(/\s+/g, " ") : "API quota exceeded";
|
|
5576
|
-
}
|
|
5577
|
-
const auth = text.match(/(?:authentication failed|invalid api key|unauthorized)[^\n]{0,200}/i);
|
|
5578
|
-
if (auth) {
|
|
5579
|
-
return auth[0].trim().replace(/\s+/g, " ");
|
|
5580
|
-
}
|
|
5581
|
-
return null;
|
|
5582
|
-
}
|
|
5583
5530
|
|
|
5584
5531
|
// src/services/history.service.ts
|
|
5585
5532
|
var fs5 = __toESM(require("fs"));
|
|
@@ -6021,7 +5968,10 @@ var HistoryService = class {
|
|
|
6021
5968
|
* Returns the number of messages uploaded (0 means nothing new).
|
|
6022
5969
|
*/
|
|
6023
5970
|
async uploadDelta() {
|
|
6024
|
-
if (!this.currentConversationId)
|
|
5971
|
+
if (!this.currentConversationId) {
|
|
5972
|
+
this.detectCurrentConversation();
|
|
5973
|
+
if (!this.currentConversationId) return 0;
|
|
5974
|
+
}
|
|
6025
5975
|
const sessionId = this.currentConversationId;
|
|
6026
5976
|
const filePath = path8.join(this.projectDir, `${sessionId}.jsonl`);
|
|
6027
5977
|
const messages = parseJsonl(filePath);
|
|
@@ -9371,7 +9321,7 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
9371
9321
|
// src/commands/version.ts
|
|
9372
9322
|
var import_picocolors11 = __toESM(require("picocolors"));
|
|
9373
9323
|
function version() {
|
|
9374
|
-
const v = true ? "2.9.
|
|
9324
|
+
const v = true ? "2.9.7" : "unknown";
|
|
9375
9325
|
console.log(`${import_picocolors11.default.bold("codeam-cli")} ${import_picocolors11.default.cyan(v)}`);
|
|
9376
9326
|
}
|
|
9377
9327
|
|
|
@@ -9506,7 +9456,7 @@ function checkForUpdates() {
|
|
|
9506
9456
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
9507
9457
|
if (process.env.CI) return;
|
|
9508
9458
|
if (!process.stdout.isTTY) return;
|
|
9509
|
-
const current = true ? "2.9.
|
|
9459
|
+
const current = true ? "2.9.7" : null;
|
|
9510
9460
|
if (!current) return;
|
|
9511
9461
|
const cache = readCache();
|
|
9512
9462
|
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.9.
|
|
3
|
+
"version": "2.9.7",
|
|
4
4
|
"description": "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands — from anywhere.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.js",
|