codeam-cli 2.29.0 → 2.30.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 +240 -103
- 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.29.0] — 2026-06-06
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Forward originator HMAC to /api/pairing/code for QR-ready SSE
|
|
12
|
+
|
|
7
13
|
## [2.28.1] — 2026-06-06
|
|
8
14
|
|
|
9
15
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
498
498
|
// package.json
|
|
499
499
|
var package_default = {
|
|
500
500
|
name: "codeam-cli",
|
|
501
|
-
version: "2.
|
|
501
|
+
version: "2.30.0",
|
|
502
502
|
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.",
|
|
503
503
|
type: "commonjs",
|
|
504
504
|
main: "dist/index.js",
|
|
@@ -682,14 +682,6 @@ var _execSeam = {
|
|
|
682
682
|
}
|
|
683
683
|
};
|
|
684
684
|
|
|
685
|
-
// src/lib/poll-delay.ts
|
|
686
|
-
var MAX_DELAY_MS = 3e4;
|
|
687
|
-
function computePollDelay({ baseMs, failures }) {
|
|
688
|
-
const exp = Math.min(MAX_DELAY_MS, baseMs * Math.pow(2, failures));
|
|
689
|
-
const jitter = exp * (0.9 + Math.random() * 0.2);
|
|
690
|
-
return Math.round(jitter);
|
|
691
|
-
}
|
|
692
|
-
|
|
693
685
|
// src/services/pairing.service.ts
|
|
694
686
|
var API_BASE = resolveApiBaseUrl();
|
|
695
687
|
var REQUEST_CODE_TIMEOUT_MS = 1e4;
|
|
@@ -741,59 +733,6 @@ async function fetchCurrentPluginAuthToken(sessionId, pluginId) {
|
|
|
741
733
|
return null;
|
|
742
734
|
}
|
|
743
735
|
}
|
|
744
|
-
function pollStatus(pluginId, onPaired, onTimeout) {
|
|
745
|
-
let stopped = false;
|
|
746
|
-
let pollTimer = null;
|
|
747
|
-
let consecutiveFailures = 0;
|
|
748
|
-
const tick = async () => {
|
|
749
|
-
if (stopped) return;
|
|
750
|
-
try {
|
|
751
|
-
const result = await _transport.getJson(
|
|
752
|
-
`${API_BASE}/api/pairing/status?pluginId=${pluginId}`
|
|
753
|
-
);
|
|
754
|
-
consecutiveFailures = 0;
|
|
755
|
-
const data = result?.data;
|
|
756
|
-
if (data?.paired) {
|
|
757
|
-
stop();
|
|
758
|
-
const user = data.user ?? {};
|
|
759
|
-
const rawToken = data.pluginAuthToken;
|
|
760
|
-
onPaired({
|
|
761
|
-
sessionId: data.sessionId,
|
|
762
|
-
userId: typeof user.id === "string" && user.id.length > 0 ? user.id : void 0,
|
|
763
|
-
userName: user.name || "",
|
|
764
|
-
userEmail: user.email || "",
|
|
765
|
-
plan: user.plan || "FREE",
|
|
766
|
-
pluginAuthToken: typeof rawToken === "string" && rawToken.length > 0 ? rawToken : void 0
|
|
767
|
-
});
|
|
768
|
-
return;
|
|
769
|
-
}
|
|
770
|
-
} catch {
|
|
771
|
-
consecutiveFailures += 1;
|
|
772
|
-
}
|
|
773
|
-
if (stopped) return;
|
|
774
|
-
const delay = computePollDelay({ baseMs: 3e3, failures: consecutiveFailures });
|
|
775
|
-
pollTimer = setTimeout(() => {
|
|
776
|
-
void tick();
|
|
777
|
-
}, delay);
|
|
778
|
-
};
|
|
779
|
-
const initialDelay = computePollDelay({ baseMs: 3e3, failures: 0 });
|
|
780
|
-
pollTimer = setTimeout(() => {
|
|
781
|
-
void tick();
|
|
782
|
-
}, initialDelay);
|
|
783
|
-
const timeout = setTimeout(() => {
|
|
784
|
-
stop();
|
|
785
|
-
onTimeout();
|
|
786
|
-
}, 3e5);
|
|
787
|
-
function stop() {
|
|
788
|
-
stopped = true;
|
|
789
|
-
if (pollTimer) {
|
|
790
|
-
clearTimeout(pollTimer);
|
|
791
|
-
pollTimer = null;
|
|
792
|
-
}
|
|
793
|
-
clearTimeout(timeout);
|
|
794
|
-
}
|
|
795
|
-
return stop;
|
|
796
|
-
}
|
|
797
736
|
var _transport = {
|
|
798
737
|
postJson: _postJson,
|
|
799
738
|
getJson: _getJson,
|
|
@@ -1032,6 +971,14 @@ async function _getJson(url) {
|
|
|
1032
971
|
});
|
|
1033
972
|
}
|
|
1034
973
|
|
|
974
|
+
// src/lib/poll-delay.ts
|
|
975
|
+
var MAX_DELAY_MS = 3e4;
|
|
976
|
+
function computePollDelay({ baseMs, failures }) {
|
|
977
|
+
const exp = Math.min(MAX_DELAY_MS, baseMs * Math.pow(2, failures));
|
|
978
|
+
const jitter = exp * (0.9 + Math.random() * 0.2);
|
|
979
|
+
return Math.round(jitter);
|
|
980
|
+
}
|
|
981
|
+
|
|
1035
982
|
// src/services/logger.ts
|
|
1036
983
|
var fs2 = __toESM(require("fs"));
|
|
1037
984
|
var os3 = __toESM(require("os"));
|
|
@@ -5902,7 +5849,7 @@ function readAnonId() {
|
|
|
5902
5849
|
}
|
|
5903
5850
|
function superProperties() {
|
|
5904
5851
|
return {
|
|
5905
|
-
cliVersion: true ? "2.
|
|
5852
|
+
cliVersion: true ? "2.30.0" : "0.0.0-dev",
|
|
5906
5853
|
nodeVersion: process.version,
|
|
5907
5854
|
platform: process.platform,
|
|
5908
5855
|
arch: process.arch,
|
|
@@ -14660,18 +14607,27 @@ var AcpClient = class {
|
|
|
14660
14607
|
* a ceiling the relay command sits "pending" forever and mobile
|
|
14661
14608
|
* shows a permanent "Thinking…" spinner with no way to recover.
|
|
14662
14609
|
*/
|
|
14663
|
-
async prompt(
|
|
14610
|
+
async prompt(input) {
|
|
14664
14611
|
if (!this.connection || !this.sessionId) {
|
|
14665
14612
|
throw new Error("AcpClient.prompt called before start()");
|
|
14666
14613
|
}
|
|
14614
|
+
const blocks = typeof input === "string" ? [{ type: "text", text: input }] : input;
|
|
14615
|
+
const textLen = blocks.reduce(
|
|
14616
|
+
(n, b) => b.type === "text" ? n + b.text.length : n,
|
|
14617
|
+
0
|
|
14618
|
+
);
|
|
14619
|
+
const imageCount = blocks.reduce(
|
|
14620
|
+
(n, b) => b.type === "image" ? n + 1 : n,
|
|
14621
|
+
0
|
|
14622
|
+
);
|
|
14667
14623
|
log.info(
|
|
14668
14624
|
"acpClient",
|
|
14669
|
-
`prompt \u2192 session=${this.sessionId.slice(0, 8)}
|
|
14625
|
+
`prompt \u2192 session=${this.sessionId.slice(0, 8)} textChars=${textLen} imageBlocks=${imageCount}`
|
|
14670
14626
|
);
|
|
14671
14627
|
const t0 = Date.now();
|
|
14672
14628
|
const send = this.connection.prompt({
|
|
14673
14629
|
sessionId: this.sessionId,
|
|
14674
|
-
prompt:
|
|
14630
|
+
prompt: blocks
|
|
14675
14631
|
});
|
|
14676
14632
|
let timeoutId;
|
|
14677
14633
|
const timeout = new Promise((_resolve, reject) => {
|
|
@@ -15143,6 +15099,59 @@ var AcpPublisher = class {
|
|
|
15143
15099
|
}
|
|
15144
15100
|
};
|
|
15145
15101
|
|
|
15102
|
+
// src/agents/acp/buildAcpPromptBlocks.ts
|
|
15103
|
+
var MIME_FROM_EXT = {
|
|
15104
|
+
png: "image/png",
|
|
15105
|
+
jpg: "image/jpeg",
|
|
15106
|
+
jpeg: "image/jpeg",
|
|
15107
|
+
gif: "image/gif",
|
|
15108
|
+
webp: "image/webp",
|
|
15109
|
+
heic: "image/heic",
|
|
15110
|
+
heif: "image/heif"
|
|
15111
|
+
};
|
|
15112
|
+
function inferMime(filename) {
|
|
15113
|
+
const ext = filename.toLowerCase().split(".").pop() ?? "";
|
|
15114
|
+
return MIME_FROM_EXT[ext] ?? "application/octet-stream";
|
|
15115
|
+
}
|
|
15116
|
+
var PLACEHOLDER_PROMPT = "Please review the attached image(s) and let me know what you find.";
|
|
15117
|
+
function buildAcpPromptBlocks(payload) {
|
|
15118
|
+
const blocks = [];
|
|
15119
|
+
for (const file of payload.files ?? []) {
|
|
15120
|
+
if (!file.base64 || file.base64.length === 0) continue;
|
|
15121
|
+
blocks.push({
|
|
15122
|
+
type: "image",
|
|
15123
|
+
mimeType: file.mimeType ?? inferMime(file.filename),
|
|
15124
|
+
data: file.base64
|
|
15125
|
+
});
|
|
15126
|
+
}
|
|
15127
|
+
const text = (payload.prompt ?? "").trim();
|
|
15128
|
+
if (text.length > 0) {
|
|
15129
|
+
blocks.push({ type: "text", text });
|
|
15130
|
+
} else if (blocks.length > 0) {
|
|
15131
|
+
blocks.push({ type: "text", text: PLACEHOLDER_PROMPT });
|
|
15132
|
+
}
|
|
15133
|
+
return blocks;
|
|
15134
|
+
}
|
|
15135
|
+
|
|
15136
|
+
// src/agents/acp/promptEcho.ts
|
|
15137
|
+
var MAX_PROMPT_CHARS = 200;
|
|
15138
|
+
function formatPromptEchoLine(payload) {
|
|
15139
|
+
const rawText = (payload.prompt ?? "").replace(/\s+/g, " ").trim();
|
|
15140
|
+
const imageCount = (payload.files ?? []).filter(
|
|
15141
|
+
(f) => typeof f.base64 === "string" && f.base64.length > 0
|
|
15142
|
+
).length;
|
|
15143
|
+
if (rawText.length === 0 && imageCount === 0) return "";
|
|
15144
|
+
const truncatedText = rawText.length > MAX_PROMPT_CHARS ? rawText.slice(0, MAX_PROMPT_CHARS) + "\u2026" : rawText;
|
|
15145
|
+
const parts = [];
|
|
15146
|
+
if (truncatedText.length > 0) {
|
|
15147
|
+
parts.push(`Mobile: ${truncatedText}`);
|
|
15148
|
+
}
|
|
15149
|
+
if (imageCount > 0) {
|
|
15150
|
+
parts.push(`+ ${imageCount} image${imageCount === 1 ? "" : "s"}`);
|
|
15151
|
+
}
|
|
15152
|
+
return `\u203A ${parts.join(" ")}`;
|
|
15153
|
+
}
|
|
15154
|
+
|
|
15146
15155
|
// src/services/terminal-ops.service.ts
|
|
15147
15156
|
var import_child_process8 = require("child_process");
|
|
15148
15157
|
var import_crypto2 = require("crypto");
|
|
@@ -16320,6 +16329,125 @@ async function selectSession(sessions3, activeId) {
|
|
|
16320
16329
|
return result;
|
|
16321
16330
|
}
|
|
16322
16331
|
|
|
16332
|
+
// src/services/pair-completion-subscriber.ts
|
|
16333
|
+
var https4 = __toESM(require("https"));
|
|
16334
|
+
var http4 = __toESM(require("http"));
|
|
16335
|
+
var API_BASE3 = resolveApiBaseUrl();
|
|
16336
|
+
var PAIR_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
16337
|
+
var dispatchers = /* @__PURE__ */ new Set();
|
|
16338
|
+
function subscribeToPairCompletion(pluginId, onPaired, onTimeout) {
|
|
16339
|
+
let stopped = false;
|
|
16340
|
+
let req = null;
|
|
16341
|
+
let timeoutTimer = null;
|
|
16342
|
+
const dispatch = (cmd) => {
|
|
16343
|
+
if (stopped) return;
|
|
16344
|
+
if (cmd.pluginId !== pluginId) return;
|
|
16345
|
+
if (cmd.type !== "pair_completed") return;
|
|
16346
|
+
const payload = cmd.payload ?? {};
|
|
16347
|
+
const info = {
|
|
16348
|
+
sessionId: typeof payload.sessionId === "string" ? payload.sessionId : cmd.sessionId,
|
|
16349
|
+
userId: typeof payload.userId === "string" ? payload.userId : void 0,
|
|
16350
|
+
userName: typeof payload.userName === "string" ? payload.userName : "",
|
|
16351
|
+
userEmail: typeof payload.userEmail === "string" ? payload.userEmail : "",
|
|
16352
|
+
plan: typeof payload.plan === "string" ? payload.plan : "FREE",
|
|
16353
|
+
pluginAuthToken: typeof payload.pluginAuthToken === "string" ? payload.pluginAuthToken : void 0
|
|
16354
|
+
};
|
|
16355
|
+
stop();
|
|
16356
|
+
onPaired(info);
|
|
16357
|
+
};
|
|
16358
|
+
dispatchers.add(dispatch);
|
|
16359
|
+
const connect = () => {
|
|
16360
|
+
if (stopped) return;
|
|
16361
|
+
const url = new URL(`${API_BASE3}/api/commands/pending/stream`);
|
|
16362
|
+
url.searchParams.set("pluginId", pluginId);
|
|
16363
|
+
const transport = url.protocol === "https:" ? https4 : http4;
|
|
16364
|
+
req = transport.request(
|
|
16365
|
+
{
|
|
16366
|
+
hostname: url.hostname,
|
|
16367
|
+
port: url.port || (url.protocol === "https:" ? 443 : 80),
|
|
16368
|
+
path: `${url.pathname}${url.search}`,
|
|
16369
|
+
method: "GET",
|
|
16370
|
+
headers: {
|
|
16371
|
+
Accept: "text/event-stream",
|
|
16372
|
+
"Cache-Control": "no-cache",
|
|
16373
|
+
...vercelBypassHeader()
|
|
16374
|
+
},
|
|
16375
|
+
timeout: 35e3
|
|
16376
|
+
},
|
|
16377
|
+
(res) => {
|
|
16378
|
+
if (res.statusCode !== 200) {
|
|
16379
|
+
log.trace(
|
|
16380
|
+
"pairSubscribe",
|
|
16381
|
+
`sse status=${res.statusCode}; will reconnect in 1s`
|
|
16382
|
+
);
|
|
16383
|
+
res.resume();
|
|
16384
|
+
setTimeout(connect, 1e3);
|
|
16385
|
+
return;
|
|
16386
|
+
}
|
|
16387
|
+
let buf = "";
|
|
16388
|
+
res.setEncoding("utf8");
|
|
16389
|
+
res.on("data", (chunk) => {
|
|
16390
|
+
buf += chunk;
|
|
16391
|
+
let idx;
|
|
16392
|
+
while ((idx = buf.indexOf("\n\n")) >= 0) {
|
|
16393
|
+
const frame = buf.slice(0, idx);
|
|
16394
|
+
buf = buf.slice(idx + 2);
|
|
16395
|
+
parseFrame(frame, dispatch);
|
|
16396
|
+
}
|
|
16397
|
+
});
|
|
16398
|
+
res.on("end", () => {
|
|
16399
|
+
if (!stopped) setTimeout(connect, 250);
|
|
16400
|
+
});
|
|
16401
|
+
res.on("error", () => {
|
|
16402
|
+
if (!stopped) setTimeout(connect, 1e3);
|
|
16403
|
+
});
|
|
16404
|
+
}
|
|
16405
|
+
);
|
|
16406
|
+
req.on("error", () => {
|
|
16407
|
+
if (!stopped) setTimeout(connect, 1e3);
|
|
16408
|
+
});
|
|
16409
|
+
req.on("timeout", () => {
|
|
16410
|
+
req?.destroy();
|
|
16411
|
+
if (!stopped) setTimeout(connect, 250);
|
|
16412
|
+
});
|
|
16413
|
+
req.end();
|
|
16414
|
+
};
|
|
16415
|
+
connect();
|
|
16416
|
+
timeoutTimer = setTimeout(() => {
|
|
16417
|
+
stop();
|
|
16418
|
+
onTimeout();
|
|
16419
|
+
}, PAIR_TIMEOUT_MS);
|
|
16420
|
+
function stop() {
|
|
16421
|
+
if (stopped) return;
|
|
16422
|
+
stopped = true;
|
|
16423
|
+
dispatchers.delete(dispatch);
|
|
16424
|
+
if (timeoutTimer) {
|
|
16425
|
+
clearTimeout(timeoutTimer);
|
|
16426
|
+
timeoutTimer = null;
|
|
16427
|
+
}
|
|
16428
|
+
if (req) {
|
|
16429
|
+
req.destroy();
|
|
16430
|
+
req = null;
|
|
16431
|
+
}
|
|
16432
|
+
}
|
|
16433
|
+
return stop;
|
|
16434
|
+
}
|
|
16435
|
+
function parseFrame(frame, dispatch) {
|
|
16436
|
+
let eventType = "message";
|
|
16437
|
+
let data = "";
|
|
16438
|
+
for (const line of frame.split("\n")) {
|
|
16439
|
+
if (line.startsWith("event:")) eventType = line.slice(6).trim();
|
|
16440
|
+
else if (line.startsWith("data:")) data += line.slice(5).trimStart();
|
|
16441
|
+
}
|
|
16442
|
+
if (eventType !== "commands") return;
|
|
16443
|
+
try {
|
|
16444
|
+
const parsed = JSON.parse(data);
|
|
16445
|
+
if (!Array.isArray(parsed.commands)) return;
|
|
16446
|
+
for (const cmd of parsed.commands) dispatch(cmd);
|
|
16447
|
+
} catch {
|
|
16448
|
+
}
|
|
16449
|
+
}
|
|
16450
|
+
|
|
16323
16451
|
// src/commands/link.ts
|
|
16324
16452
|
function buildLinkContext(agentId) {
|
|
16325
16453
|
const runtime = createRuntimeStrategy(agentId);
|
|
@@ -16413,7 +16541,7 @@ async function link(args2 = []) {
|
|
|
16413
16541
|
stopPoll?.();
|
|
16414
16542
|
reject(new Error("cancelled"));
|
|
16415
16543
|
};
|
|
16416
|
-
stopPoll =
|
|
16544
|
+
stopPoll = subscribeToPairCompletion(
|
|
16417
16545
|
pluginId,
|
|
16418
16546
|
(info) => {
|
|
16419
16547
|
process.removeListener("SIGINT", sigint);
|
|
@@ -18012,8 +18140,8 @@ function isIgnoredFilePath(filePath) {
|
|
|
18012
18140
|
}
|
|
18013
18141
|
|
|
18014
18142
|
// src/services/file-watcher/transport.ts
|
|
18015
|
-
var
|
|
18016
|
-
var
|
|
18143
|
+
var http5 = __toESM(require("http"));
|
|
18144
|
+
var https5 = __toESM(require("https"));
|
|
18017
18145
|
var _transport3 = {
|
|
18018
18146
|
post: _post2
|
|
18019
18147
|
};
|
|
@@ -18021,7 +18149,7 @@ function _post2(url, headers, payload) {
|
|
|
18021
18149
|
return new Promise((resolve6, reject) => {
|
|
18022
18150
|
let settled = false;
|
|
18023
18151
|
const u2 = new URL(url);
|
|
18024
|
-
const lib = u2.protocol === "https:" ?
|
|
18152
|
+
const lib = u2.protocol === "https:" ? https5 : http5;
|
|
18025
18153
|
const req = lib.request(
|
|
18026
18154
|
{
|
|
18027
18155
|
hostname: u2.hostname,
|
|
@@ -18061,7 +18189,7 @@ function _post2(url, headers, payload) {
|
|
|
18061
18189
|
}
|
|
18062
18190
|
|
|
18063
18191
|
// src/services/file-watcher.service.ts
|
|
18064
|
-
var
|
|
18192
|
+
var API_BASE4 = resolveApiBaseUrl();
|
|
18065
18193
|
var DEBOUNCE_MS = 250;
|
|
18066
18194
|
var COALESCE_WINDOW_MS = 250;
|
|
18067
18195
|
var COALESCE_MAX_HOLD_MS = 2e3;
|
|
@@ -18134,7 +18262,7 @@ function _defaultFindGitRoot(startDir) {
|
|
|
18134
18262
|
var FileWatcherService = class {
|
|
18135
18263
|
constructor(opts) {
|
|
18136
18264
|
this.opts = opts;
|
|
18137
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
18265
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE4;
|
|
18138
18266
|
}
|
|
18139
18267
|
opts;
|
|
18140
18268
|
watcher = null;
|
|
@@ -19085,13 +19213,13 @@ function homeDir() {
|
|
|
19085
19213
|
}
|
|
19086
19214
|
|
|
19087
19215
|
// src/services/turn-files/turn-file-aggregator.ts
|
|
19088
|
-
var
|
|
19216
|
+
var API_BASE5 = resolveApiBaseUrl();
|
|
19089
19217
|
var ENDPOINT = "/api/files/batch";
|
|
19090
19218
|
var MAX_BATCH_SIZE = 1e3;
|
|
19091
19219
|
var TurnFileAggregator = class {
|
|
19092
19220
|
constructor(opts) {
|
|
19093
19221
|
this.opts = opts;
|
|
19094
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
19222
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE5;
|
|
19095
19223
|
this.outbox = new FilesOutbox({
|
|
19096
19224
|
sessionId: opts.sessionId,
|
|
19097
19225
|
baseDir: opts.outboxDir,
|
|
@@ -19731,17 +19859,26 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
|
|
|
19731
19859
|
switch (cmd.type) {
|
|
19732
19860
|
case "start_task": {
|
|
19733
19861
|
const payload = cmd.payload;
|
|
19734
|
-
const
|
|
19735
|
-
if (
|
|
19736
|
-
log.warn("acpRunner", "start_task with empty prompt; ignoring");
|
|
19862
|
+
const blocks = buildAcpPromptBlocks(payload ?? {});
|
|
19863
|
+
if (blocks.length === 0) {
|
|
19864
|
+
log.warn("acpRunner", "start_task with empty prompt + no attachments; ignoring");
|
|
19737
19865
|
await relay.sendResult(cmd.id, "failed", { error: "empty prompt" });
|
|
19738
19866
|
return;
|
|
19739
19867
|
}
|
|
19740
|
-
|
|
19868
|
+
const promptText = blocks.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
19869
|
+
const imageCount = blocks.filter((b) => b.type === "image").length;
|
|
19870
|
+
log.info(
|
|
19871
|
+
"acpRunner",
|
|
19872
|
+
`start_task \u2192 forwarding textChars=${promptText.length} imageBlocks=${imageCount} id=${cmd.id.slice(0, 8)}`
|
|
19873
|
+
);
|
|
19874
|
+
const echoLine = formatPromptEchoLine(payload ?? {});
|
|
19875
|
+
if (echoLine.length > 0) {
|
|
19876
|
+
showInfo(echoLine);
|
|
19877
|
+
}
|
|
19741
19878
|
await streaming.beginTurn();
|
|
19742
|
-
history.appendUserPrompt(
|
|
19879
|
+
history.appendUserPrompt(promptText);
|
|
19743
19880
|
try {
|
|
19744
|
-
const reply = await client2.prompt(
|
|
19881
|
+
const reply = await client2.prompt(blocks);
|
|
19745
19882
|
const finalText = streaming.getCurrentText();
|
|
19746
19883
|
await streaming.closeTurnWithInteractiveDetection();
|
|
19747
19884
|
history.appendAgentReply(finalText);
|
|
@@ -20076,13 +20213,13 @@ var ChromeStepTracker = class {
|
|
|
20076
20213
|
};
|
|
20077
20214
|
|
|
20078
20215
|
// src/services/output/chunk-emitter.ts
|
|
20079
|
-
var
|
|
20080
|
-
var
|
|
20081
|
-
var
|
|
20216
|
+
var https6 = __toESM(require("https"));
|
|
20217
|
+
var http6 = __toESM(require("http"));
|
|
20218
|
+
var API_BASE6 = resolveApiBaseUrl();
|
|
20082
20219
|
async function refreshAuthToken(sessionId, pluginId) {
|
|
20083
20220
|
try {
|
|
20084
20221
|
const { statusCode, body } = await _transport4.post(
|
|
20085
|
-
`${
|
|
20222
|
+
`${API_BASE6}/api/pairing/reconnect`,
|
|
20086
20223
|
{
|
|
20087
20224
|
"Content-Type": "application/json",
|
|
20088
20225
|
"X-Codeam-Protocol-Version": PROTOCOL_VERSION,
|
|
@@ -20123,7 +20260,7 @@ var ChunkEmitter = class {
|
|
|
20123
20260
|
}
|
|
20124
20261
|
}
|
|
20125
20262
|
opts;
|
|
20126
|
-
url = `${
|
|
20263
|
+
url = `${API_BASE6}/api/commands/output`;
|
|
20127
20264
|
headers;
|
|
20128
20265
|
/**
|
|
20129
20266
|
* Send a chunk. `body` is the chunk fields minus `sessionId` /
|
|
@@ -20204,7 +20341,7 @@ function _post3(url, headers, payload) {
|
|
|
20204
20341
|
return new Promise((resolve6, reject) => {
|
|
20205
20342
|
let settled = false;
|
|
20206
20343
|
const u2 = new URL(url);
|
|
20207
|
-
const transport = u2.protocol === "https:" ?
|
|
20344
|
+
const transport = u2.protocol === "https:" ? https6 : http6;
|
|
20208
20345
|
const req = transport.request(
|
|
20209
20346
|
{
|
|
20210
20347
|
hostname: u2.hostname,
|
|
@@ -20802,8 +20939,8 @@ var OutputService = class _OutputService {
|
|
|
20802
20939
|
var fs32 = __toESM(require("fs"));
|
|
20803
20940
|
var path38 = __toESM(require("path"));
|
|
20804
20941
|
var os25 = __toESM(require("os"));
|
|
20805
|
-
var
|
|
20806
|
-
var
|
|
20942
|
+
var https7 = __toESM(require("https"));
|
|
20943
|
+
var http7 = __toESM(require("http"));
|
|
20807
20944
|
var import_zod2 = require("zod");
|
|
20808
20945
|
var historyRecordSchema = import_zod2.z.object({
|
|
20809
20946
|
type: import_zod2.z.string().optional(),
|
|
@@ -20815,7 +20952,7 @@ var historyRecordSchema = import_zod2.z.object({
|
|
|
20815
20952
|
content: import_zod2.z.union([import_zod2.z.string(), import_zod2.z.array(import_zod2.z.unknown())]).optional()
|
|
20816
20953
|
}).passthrough().optional()
|
|
20817
20954
|
}).passthrough();
|
|
20818
|
-
var
|
|
20955
|
+
var API_BASE7 = resolveApiBaseUrl();
|
|
20819
20956
|
function extractText3(content) {
|
|
20820
20957
|
if (typeof content === "string") return content;
|
|
20821
20958
|
if (Array.isArray(content)) {
|
|
@@ -20867,8 +21004,8 @@ function parseJsonl(filePath) {
|
|
|
20867
21004
|
function post(endpoint, body) {
|
|
20868
21005
|
return new Promise((resolve6) => {
|
|
20869
21006
|
const payload = JSON.stringify(body);
|
|
20870
|
-
const u2 = new URL(`${
|
|
20871
|
-
const transport = u2.protocol === "https:" ?
|
|
21007
|
+
const u2 = new URL(`${API_BASE7}${endpoint}`);
|
|
21008
|
+
const transport = u2.protocol === "https:" ? https7 : http7;
|
|
20872
21009
|
const req = transport.request(
|
|
20873
21010
|
{
|
|
20874
21011
|
hostname: u2.hostname,
|
|
@@ -21316,7 +21453,7 @@ var RepoDirtyTracker = class {
|
|
|
21316
21453
|
|
|
21317
21454
|
// src/services/streaming-emitter.service.ts
|
|
21318
21455
|
var import_crypto5 = require("crypto");
|
|
21319
|
-
var
|
|
21456
|
+
var API_BASE8 = resolveApiBaseUrl();
|
|
21320
21457
|
var TICK_MS = 50;
|
|
21321
21458
|
var ANSWER_POLL_MS = 1500;
|
|
21322
21459
|
var SELECTOR_STABLE_MS = 800;
|
|
@@ -21327,7 +21464,7 @@ var TAIL_KEEP_BYTES2 = 1.5 * 1024 * 1024;
|
|
|
21327
21464
|
var StreamingEmitterService = class {
|
|
21328
21465
|
constructor(opts) {
|
|
21329
21466
|
this.opts = opts;
|
|
21330
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
21467
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE8;
|
|
21331
21468
|
this.headers = {
|
|
21332
21469
|
"Content-Type": "application/json",
|
|
21333
21470
|
"X-Codeam-Protocol-Version": "2.0.0",
|
|
@@ -22046,7 +22183,7 @@ async function pair(args2 = []) {
|
|
|
22046
22183
|
console.log("");
|
|
22047
22184
|
process.exit(0);
|
|
22048
22185
|
}
|
|
22049
|
-
stopPolling =
|
|
22186
|
+
stopPolling = subscribeToPairCompletion(
|
|
22050
22187
|
pluginId,
|
|
22051
22188
|
(info) => {
|
|
22052
22189
|
process.removeListener("SIGINT", sigintHandler);
|
|
@@ -22292,7 +22429,7 @@ async function startInfraOnly(agentId) {
|
|
|
22292
22429
|
}
|
|
22293
22430
|
|
|
22294
22431
|
// src/commands/pair-auto.ts
|
|
22295
|
-
var
|
|
22432
|
+
var API_BASE9 = resolveApiBaseUrl();
|
|
22296
22433
|
function fail(msg) {
|
|
22297
22434
|
console.error(`
|
|
22298
22435
|
${msg}
|
|
@@ -22332,7 +22469,7 @@ function networkError(msg, cause) {
|
|
|
22332
22469
|
return err;
|
|
22333
22470
|
}
|
|
22334
22471
|
async function claimOnce(token, pluginId) {
|
|
22335
|
-
const url = `${
|
|
22472
|
+
const url = `${API_BASE9}/api/pairing/claim-auto-token`;
|
|
22336
22473
|
const body = {
|
|
22337
22474
|
token,
|
|
22338
22475
|
pluginId,
|
|
@@ -22535,7 +22672,7 @@ function status() {
|
|
|
22535
22672
|
|
|
22536
22673
|
// src/commands/logout.ts
|
|
22537
22674
|
var import_picocolors7 = __toESM(require("picocolors"));
|
|
22538
|
-
var
|
|
22675
|
+
var API_BASE10 = resolveApiBaseUrl();
|
|
22539
22676
|
async function notifyBackendOffline() {
|
|
22540
22677
|
const cfg = loadCliConfig();
|
|
22541
22678
|
const pluginIds = /* @__PURE__ */ new Set([
|
|
@@ -22547,7 +22684,7 @@ async function notifyBackendOffline() {
|
|
|
22547
22684
|
try {
|
|
22548
22685
|
await Promise.all(
|
|
22549
22686
|
Array.from(pluginIds).map(
|
|
22550
|
-
(pluginId) => _postJson(`${
|
|
22687
|
+
(pluginId) => _postJson(`${API_BASE10}/api/plugin/heartbeat`, {
|
|
22551
22688
|
pluginId,
|
|
22552
22689
|
online: false
|
|
22553
22690
|
}).catch((err) => {
|
|
@@ -24689,7 +24826,7 @@ function checkChokidar() {
|
|
|
24689
24826
|
}
|
|
24690
24827
|
async function doctor(args2 = []) {
|
|
24691
24828
|
const json = args2.includes("--json");
|
|
24692
|
-
const cliVersion = true ? "2.
|
|
24829
|
+
const cliVersion = true ? "2.30.0" : "0.0.0-dev";
|
|
24693
24830
|
const apiBase = resolveApiBaseUrl();
|
|
24694
24831
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
24695
24832
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -24888,7 +25025,7 @@ async function completion(args2) {
|
|
|
24888
25025
|
// src/commands/version.ts
|
|
24889
25026
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
24890
25027
|
function version2() {
|
|
24891
|
-
const v = true ? "2.
|
|
25028
|
+
const v = true ? "2.30.0" : "unknown";
|
|
24892
25029
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
24893
25030
|
}
|
|
24894
25031
|
|
|
@@ -25019,7 +25156,7 @@ var _subcommandHelpKeys = Object.keys(HELPS);
|
|
|
25019
25156
|
var fs35 = __toESM(require("fs"));
|
|
25020
25157
|
var os27 = __toESM(require("os"));
|
|
25021
25158
|
var path44 = __toESM(require("path"));
|
|
25022
|
-
var
|
|
25159
|
+
var https8 = __toESM(require("https"));
|
|
25023
25160
|
var import_node_child_process12 = require("child_process");
|
|
25024
25161
|
var import_picocolors16 = __toESM(require("picocolors"));
|
|
25025
25162
|
var PKG_NAME = "codeam-cli";
|
|
@@ -25065,7 +25202,7 @@ function compareSemver(a, b) {
|
|
|
25065
25202
|
}
|
|
25066
25203
|
function fetchLatest() {
|
|
25067
25204
|
return new Promise((resolve6) => {
|
|
25068
|
-
const req =
|
|
25205
|
+
const req = https8.get(
|
|
25069
25206
|
REGISTRY_URL,
|
|
25070
25207
|
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
25071
25208
|
(res) => {
|
|
@@ -25174,7 +25311,7 @@ function checkForUpdates() {
|
|
|
25174
25311
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
25175
25312
|
if (process.env.CI) return;
|
|
25176
25313
|
if (!process.stdout.isTTY) return;
|
|
25177
|
-
const current = true ? "2.
|
|
25314
|
+
const current = true ? "2.30.0" : null;
|
|
25178
25315
|
if (!current) return;
|
|
25179
25316
|
const cache = readCache();
|
|
25180
25317
|
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.
|
|
3
|
+
"version": "2.30.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",
|