codeam-cli 2.28.1 → 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 +12 -0
- package/dist/index.js +253 -106
- 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.29.0] — 2026-06-06
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Forward originator HMAC to /api/pairing/code for QR-ready SSE
|
|
12
|
+
|
|
13
|
+
## [2.28.1] — 2026-06-06
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** RequestCode times out at 10s instead of hanging forever
|
|
18
|
+
|
|
7
19
|
## [2.28.0] — 2026-06-06
|
|
8
20
|
|
|
9
21
|
### Added
|
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,18 +682,10 @@ 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;
|
|
696
|
-
async function requestCode(pluginId) {
|
|
688
|
+
async function requestCode(pluginId, options = {}) {
|
|
697
689
|
try {
|
|
698
690
|
const runtime = process.env.CODESPACES === "true" ? "github-codespaces" : "local";
|
|
699
691
|
const codespaceName = process.env.CODESPACE_NAME;
|
|
@@ -705,7 +697,12 @@ async function requestCode(pluginId) {
|
|
|
705
697
|
hostname: os2.hostname(),
|
|
706
698
|
runtime,
|
|
707
699
|
branch,
|
|
708
|
-
...codespaceName ? { codespaceName } : {}
|
|
700
|
+
...codespaceName ? { codespaceName } : {},
|
|
701
|
+
...options.originatorSessionId && options.originatorPluginId && options.originatorAuthToken ? {
|
|
702
|
+
originatorSessionId: options.originatorSessionId,
|
|
703
|
+
originatorPluginId: options.originatorPluginId,
|
|
704
|
+
originatorAuthToken: options.originatorAuthToken
|
|
705
|
+
} : {}
|
|
709
706
|
});
|
|
710
707
|
let timer;
|
|
711
708
|
const timeoutSentinel = /* @__PURE__ */ Symbol("request-code-timeout");
|
|
@@ -736,59 +733,6 @@ async function fetchCurrentPluginAuthToken(sessionId, pluginId) {
|
|
|
736
733
|
return null;
|
|
737
734
|
}
|
|
738
735
|
}
|
|
739
|
-
function pollStatus(pluginId, onPaired, onTimeout) {
|
|
740
|
-
let stopped = false;
|
|
741
|
-
let pollTimer = null;
|
|
742
|
-
let consecutiveFailures = 0;
|
|
743
|
-
const tick = async () => {
|
|
744
|
-
if (stopped) return;
|
|
745
|
-
try {
|
|
746
|
-
const result = await _transport.getJson(
|
|
747
|
-
`${API_BASE}/api/pairing/status?pluginId=${pluginId}`
|
|
748
|
-
);
|
|
749
|
-
consecutiveFailures = 0;
|
|
750
|
-
const data = result?.data;
|
|
751
|
-
if (data?.paired) {
|
|
752
|
-
stop();
|
|
753
|
-
const user = data.user ?? {};
|
|
754
|
-
const rawToken = data.pluginAuthToken;
|
|
755
|
-
onPaired({
|
|
756
|
-
sessionId: data.sessionId,
|
|
757
|
-
userId: typeof user.id === "string" && user.id.length > 0 ? user.id : void 0,
|
|
758
|
-
userName: user.name || "",
|
|
759
|
-
userEmail: user.email || "",
|
|
760
|
-
plan: user.plan || "FREE",
|
|
761
|
-
pluginAuthToken: typeof rawToken === "string" && rawToken.length > 0 ? rawToken : void 0
|
|
762
|
-
});
|
|
763
|
-
return;
|
|
764
|
-
}
|
|
765
|
-
} catch {
|
|
766
|
-
consecutiveFailures += 1;
|
|
767
|
-
}
|
|
768
|
-
if (stopped) return;
|
|
769
|
-
const delay = computePollDelay({ baseMs: 3e3, failures: consecutiveFailures });
|
|
770
|
-
pollTimer = setTimeout(() => {
|
|
771
|
-
void tick();
|
|
772
|
-
}, delay);
|
|
773
|
-
};
|
|
774
|
-
const initialDelay = computePollDelay({ baseMs: 3e3, failures: 0 });
|
|
775
|
-
pollTimer = setTimeout(() => {
|
|
776
|
-
void tick();
|
|
777
|
-
}, initialDelay);
|
|
778
|
-
const timeout = setTimeout(() => {
|
|
779
|
-
stop();
|
|
780
|
-
onTimeout();
|
|
781
|
-
}, 3e5);
|
|
782
|
-
function stop() {
|
|
783
|
-
stopped = true;
|
|
784
|
-
if (pollTimer) {
|
|
785
|
-
clearTimeout(pollTimer);
|
|
786
|
-
pollTimer = null;
|
|
787
|
-
}
|
|
788
|
-
clearTimeout(timeout);
|
|
789
|
-
}
|
|
790
|
-
return stop;
|
|
791
|
-
}
|
|
792
736
|
var _transport = {
|
|
793
737
|
postJson: _postJson,
|
|
794
738
|
getJson: _getJson,
|
|
@@ -1027,6 +971,14 @@ async function _getJson(url) {
|
|
|
1027
971
|
});
|
|
1028
972
|
}
|
|
1029
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
|
+
|
|
1030
982
|
// src/services/logger.ts
|
|
1031
983
|
var fs2 = __toESM(require("fs"));
|
|
1032
984
|
var os3 = __toESM(require("os"));
|
|
@@ -5897,7 +5849,7 @@ function readAnonId() {
|
|
|
5897
5849
|
}
|
|
5898
5850
|
function superProperties() {
|
|
5899
5851
|
return {
|
|
5900
|
-
cliVersion: true ? "2.
|
|
5852
|
+
cliVersion: true ? "2.30.0" : "0.0.0-dev",
|
|
5901
5853
|
nodeVersion: process.version,
|
|
5902
5854
|
platform: process.platform,
|
|
5903
5855
|
arch: process.arch,
|
|
@@ -14655,18 +14607,27 @@ var AcpClient = class {
|
|
|
14655
14607
|
* a ceiling the relay command sits "pending" forever and mobile
|
|
14656
14608
|
* shows a permanent "Thinking…" spinner with no way to recover.
|
|
14657
14609
|
*/
|
|
14658
|
-
async prompt(
|
|
14610
|
+
async prompt(input) {
|
|
14659
14611
|
if (!this.connection || !this.sessionId) {
|
|
14660
14612
|
throw new Error("AcpClient.prompt called before start()");
|
|
14661
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
|
+
);
|
|
14662
14623
|
log.info(
|
|
14663
14624
|
"acpClient",
|
|
14664
|
-
`prompt \u2192 session=${this.sessionId.slice(0, 8)}
|
|
14625
|
+
`prompt \u2192 session=${this.sessionId.slice(0, 8)} textChars=${textLen} imageBlocks=${imageCount}`
|
|
14665
14626
|
);
|
|
14666
14627
|
const t0 = Date.now();
|
|
14667
14628
|
const send = this.connection.prompt({
|
|
14668
14629
|
sessionId: this.sessionId,
|
|
14669
|
-
prompt:
|
|
14630
|
+
prompt: blocks
|
|
14670
14631
|
});
|
|
14671
14632
|
let timeoutId;
|
|
14672
14633
|
const timeout = new Promise((_resolve, reject) => {
|
|
@@ -15138,6 +15099,59 @@ var AcpPublisher = class {
|
|
|
15138
15099
|
}
|
|
15139
15100
|
};
|
|
15140
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
|
+
|
|
15141
15155
|
// src/services/terminal-ops.service.ts
|
|
15142
15156
|
var import_child_process8 = require("child_process");
|
|
15143
15157
|
var import_crypto2 = require("crypto");
|
|
@@ -16315,6 +16329,125 @@ async function selectSession(sessions3, activeId) {
|
|
|
16315
16329
|
return result;
|
|
16316
16330
|
}
|
|
16317
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
|
+
|
|
16318
16451
|
// src/commands/link.ts
|
|
16319
16452
|
function buildLinkContext(agentId) {
|
|
16320
16453
|
const runtime = createRuntimeStrategy(agentId);
|
|
@@ -16381,7 +16514,12 @@ async function link(args2 = []) {
|
|
|
16381
16514
|
const pluginId = (0, import_node_crypto6.randomUUID)();
|
|
16382
16515
|
const spin = dist_exports.spinner();
|
|
16383
16516
|
spin.start("Requesting pairing code...");
|
|
16384
|
-
const
|
|
16517
|
+
const originator = getActiveSession();
|
|
16518
|
+
const pairing = await requestCode(pluginId, {
|
|
16519
|
+
originatorSessionId: originator?.id,
|
|
16520
|
+
originatorPluginId: originator?.pluginId,
|
|
16521
|
+
originatorAuthToken: originator?.pluginAuthToken
|
|
16522
|
+
});
|
|
16385
16523
|
if (!pairing) {
|
|
16386
16524
|
spin.stop("Failed");
|
|
16387
16525
|
showError("Could not reach the server. Check your connection and try again.");
|
|
@@ -16403,7 +16541,7 @@ async function link(args2 = []) {
|
|
|
16403
16541
|
stopPoll?.();
|
|
16404
16542
|
reject(new Error("cancelled"));
|
|
16405
16543
|
};
|
|
16406
|
-
stopPoll =
|
|
16544
|
+
stopPoll = subscribeToPairCompletion(
|
|
16407
16545
|
pluginId,
|
|
16408
16546
|
(info) => {
|
|
16409
16547
|
process.removeListener("SIGINT", sigint);
|
|
@@ -18002,8 +18140,8 @@ function isIgnoredFilePath(filePath) {
|
|
|
18002
18140
|
}
|
|
18003
18141
|
|
|
18004
18142
|
// src/services/file-watcher/transport.ts
|
|
18005
|
-
var
|
|
18006
|
-
var
|
|
18143
|
+
var http5 = __toESM(require("http"));
|
|
18144
|
+
var https5 = __toESM(require("https"));
|
|
18007
18145
|
var _transport3 = {
|
|
18008
18146
|
post: _post2
|
|
18009
18147
|
};
|
|
@@ -18011,7 +18149,7 @@ function _post2(url, headers, payload) {
|
|
|
18011
18149
|
return new Promise((resolve6, reject) => {
|
|
18012
18150
|
let settled = false;
|
|
18013
18151
|
const u2 = new URL(url);
|
|
18014
|
-
const lib = u2.protocol === "https:" ?
|
|
18152
|
+
const lib = u2.protocol === "https:" ? https5 : http5;
|
|
18015
18153
|
const req = lib.request(
|
|
18016
18154
|
{
|
|
18017
18155
|
hostname: u2.hostname,
|
|
@@ -18051,7 +18189,7 @@ function _post2(url, headers, payload) {
|
|
|
18051
18189
|
}
|
|
18052
18190
|
|
|
18053
18191
|
// src/services/file-watcher.service.ts
|
|
18054
|
-
var
|
|
18192
|
+
var API_BASE4 = resolveApiBaseUrl();
|
|
18055
18193
|
var DEBOUNCE_MS = 250;
|
|
18056
18194
|
var COALESCE_WINDOW_MS = 250;
|
|
18057
18195
|
var COALESCE_MAX_HOLD_MS = 2e3;
|
|
@@ -18124,7 +18262,7 @@ function _defaultFindGitRoot(startDir) {
|
|
|
18124
18262
|
var FileWatcherService = class {
|
|
18125
18263
|
constructor(opts) {
|
|
18126
18264
|
this.opts = opts;
|
|
18127
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
18265
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE4;
|
|
18128
18266
|
}
|
|
18129
18267
|
opts;
|
|
18130
18268
|
watcher = null;
|
|
@@ -19075,13 +19213,13 @@ function homeDir() {
|
|
|
19075
19213
|
}
|
|
19076
19214
|
|
|
19077
19215
|
// src/services/turn-files/turn-file-aggregator.ts
|
|
19078
|
-
var
|
|
19216
|
+
var API_BASE5 = resolveApiBaseUrl();
|
|
19079
19217
|
var ENDPOINT = "/api/files/batch";
|
|
19080
19218
|
var MAX_BATCH_SIZE = 1e3;
|
|
19081
19219
|
var TurnFileAggregator = class {
|
|
19082
19220
|
constructor(opts) {
|
|
19083
19221
|
this.opts = opts;
|
|
19084
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
19222
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE5;
|
|
19085
19223
|
this.outbox = new FilesOutbox({
|
|
19086
19224
|
sessionId: opts.sessionId,
|
|
19087
19225
|
baseDir: opts.outboxDir,
|
|
@@ -19721,17 +19859,26 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
|
|
|
19721
19859
|
switch (cmd.type) {
|
|
19722
19860
|
case "start_task": {
|
|
19723
19861
|
const payload = cmd.payload;
|
|
19724
|
-
const
|
|
19725
|
-
if (
|
|
19726
|
-
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");
|
|
19727
19865
|
await relay.sendResult(cmd.id, "failed", { error: "empty prompt" });
|
|
19728
19866
|
return;
|
|
19729
19867
|
}
|
|
19730
|
-
|
|
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
|
+
}
|
|
19731
19878
|
await streaming.beginTurn();
|
|
19732
|
-
history.appendUserPrompt(
|
|
19879
|
+
history.appendUserPrompt(promptText);
|
|
19733
19880
|
try {
|
|
19734
|
-
const reply = await client2.prompt(
|
|
19881
|
+
const reply = await client2.prompt(blocks);
|
|
19735
19882
|
const finalText = streaming.getCurrentText();
|
|
19736
19883
|
await streaming.closeTurnWithInteractiveDetection();
|
|
19737
19884
|
history.appendAgentReply(finalText);
|
|
@@ -20066,13 +20213,13 @@ var ChromeStepTracker = class {
|
|
|
20066
20213
|
};
|
|
20067
20214
|
|
|
20068
20215
|
// src/services/output/chunk-emitter.ts
|
|
20069
|
-
var
|
|
20070
|
-
var
|
|
20071
|
-
var
|
|
20216
|
+
var https6 = __toESM(require("https"));
|
|
20217
|
+
var http6 = __toESM(require("http"));
|
|
20218
|
+
var API_BASE6 = resolveApiBaseUrl();
|
|
20072
20219
|
async function refreshAuthToken(sessionId, pluginId) {
|
|
20073
20220
|
try {
|
|
20074
20221
|
const { statusCode, body } = await _transport4.post(
|
|
20075
|
-
`${
|
|
20222
|
+
`${API_BASE6}/api/pairing/reconnect`,
|
|
20076
20223
|
{
|
|
20077
20224
|
"Content-Type": "application/json",
|
|
20078
20225
|
"X-Codeam-Protocol-Version": PROTOCOL_VERSION,
|
|
@@ -20113,7 +20260,7 @@ var ChunkEmitter = class {
|
|
|
20113
20260
|
}
|
|
20114
20261
|
}
|
|
20115
20262
|
opts;
|
|
20116
|
-
url = `${
|
|
20263
|
+
url = `${API_BASE6}/api/commands/output`;
|
|
20117
20264
|
headers;
|
|
20118
20265
|
/**
|
|
20119
20266
|
* Send a chunk. `body` is the chunk fields minus `sessionId` /
|
|
@@ -20194,7 +20341,7 @@ function _post3(url, headers, payload) {
|
|
|
20194
20341
|
return new Promise((resolve6, reject) => {
|
|
20195
20342
|
let settled = false;
|
|
20196
20343
|
const u2 = new URL(url);
|
|
20197
|
-
const transport = u2.protocol === "https:" ?
|
|
20344
|
+
const transport = u2.protocol === "https:" ? https6 : http6;
|
|
20198
20345
|
const req = transport.request(
|
|
20199
20346
|
{
|
|
20200
20347
|
hostname: u2.hostname,
|
|
@@ -20792,8 +20939,8 @@ var OutputService = class _OutputService {
|
|
|
20792
20939
|
var fs32 = __toESM(require("fs"));
|
|
20793
20940
|
var path38 = __toESM(require("path"));
|
|
20794
20941
|
var os25 = __toESM(require("os"));
|
|
20795
|
-
var
|
|
20796
|
-
var
|
|
20942
|
+
var https7 = __toESM(require("https"));
|
|
20943
|
+
var http7 = __toESM(require("http"));
|
|
20797
20944
|
var import_zod2 = require("zod");
|
|
20798
20945
|
var historyRecordSchema = import_zod2.z.object({
|
|
20799
20946
|
type: import_zod2.z.string().optional(),
|
|
@@ -20805,7 +20952,7 @@ var historyRecordSchema = import_zod2.z.object({
|
|
|
20805
20952
|
content: import_zod2.z.union([import_zod2.z.string(), import_zod2.z.array(import_zod2.z.unknown())]).optional()
|
|
20806
20953
|
}).passthrough().optional()
|
|
20807
20954
|
}).passthrough();
|
|
20808
|
-
var
|
|
20955
|
+
var API_BASE7 = resolveApiBaseUrl();
|
|
20809
20956
|
function extractText3(content) {
|
|
20810
20957
|
if (typeof content === "string") return content;
|
|
20811
20958
|
if (Array.isArray(content)) {
|
|
@@ -20857,8 +21004,8 @@ function parseJsonl(filePath) {
|
|
|
20857
21004
|
function post(endpoint, body) {
|
|
20858
21005
|
return new Promise((resolve6) => {
|
|
20859
21006
|
const payload = JSON.stringify(body);
|
|
20860
|
-
const u2 = new URL(`${
|
|
20861
|
-
const transport = u2.protocol === "https:" ?
|
|
21007
|
+
const u2 = new URL(`${API_BASE7}${endpoint}`);
|
|
21008
|
+
const transport = u2.protocol === "https:" ? https7 : http7;
|
|
20862
21009
|
const req = transport.request(
|
|
20863
21010
|
{
|
|
20864
21011
|
hostname: u2.hostname,
|
|
@@ -21306,7 +21453,7 @@ var RepoDirtyTracker = class {
|
|
|
21306
21453
|
|
|
21307
21454
|
// src/services/streaming-emitter.service.ts
|
|
21308
21455
|
var import_crypto5 = require("crypto");
|
|
21309
|
-
var
|
|
21456
|
+
var API_BASE8 = resolveApiBaseUrl();
|
|
21310
21457
|
var TICK_MS = 50;
|
|
21311
21458
|
var ANSWER_POLL_MS = 1500;
|
|
21312
21459
|
var SELECTOR_STABLE_MS = 800;
|
|
@@ -21317,7 +21464,7 @@ var TAIL_KEEP_BYTES2 = 1.5 * 1024 * 1024;
|
|
|
21317
21464
|
var StreamingEmitterService = class {
|
|
21318
21465
|
constructor(opts) {
|
|
21319
21466
|
this.opts = opts;
|
|
21320
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
21467
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE8;
|
|
21321
21468
|
this.headers = {
|
|
21322
21469
|
"Content-Type": "application/json",
|
|
21323
21470
|
"X-Codeam-Protocol-Version": "2.0.0",
|
|
@@ -22036,7 +22183,7 @@ async function pair(args2 = []) {
|
|
|
22036
22183
|
console.log("");
|
|
22037
22184
|
process.exit(0);
|
|
22038
22185
|
}
|
|
22039
|
-
stopPolling =
|
|
22186
|
+
stopPolling = subscribeToPairCompletion(
|
|
22040
22187
|
pluginId,
|
|
22041
22188
|
(info) => {
|
|
22042
22189
|
process.removeListener("SIGINT", sigintHandler);
|
|
@@ -22282,7 +22429,7 @@ async function startInfraOnly(agentId) {
|
|
|
22282
22429
|
}
|
|
22283
22430
|
|
|
22284
22431
|
// src/commands/pair-auto.ts
|
|
22285
|
-
var
|
|
22432
|
+
var API_BASE9 = resolveApiBaseUrl();
|
|
22286
22433
|
function fail(msg) {
|
|
22287
22434
|
console.error(`
|
|
22288
22435
|
${msg}
|
|
@@ -22322,7 +22469,7 @@ function networkError(msg, cause) {
|
|
|
22322
22469
|
return err;
|
|
22323
22470
|
}
|
|
22324
22471
|
async function claimOnce(token, pluginId) {
|
|
22325
|
-
const url = `${
|
|
22472
|
+
const url = `${API_BASE9}/api/pairing/claim-auto-token`;
|
|
22326
22473
|
const body = {
|
|
22327
22474
|
token,
|
|
22328
22475
|
pluginId,
|
|
@@ -22525,7 +22672,7 @@ function status() {
|
|
|
22525
22672
|
|
|
22526
22673
|
// src/commands/logout.ts
|
|
22527
22674
|
var import_picocolors7 = __toESM(require("picocolors"));
|
|
22528
|
-
var
|
|
22675
|
+
var API_BASE10 = resolveApiBaseUrl();
|
|
22529
22676
|
async function notifyBackendOffline() {
|
|
22530
22677
|
const cfg = loadCliConfig();
|
|
22531
22678
|
const pluginIds = /* @__PURE__ */ new Set([
|
|
@@ -22537,7 +22684,7 @@ async function notifyBackendOffline() {
|
|
|
22537
22684
|
try {
|
|
22538
22685
|
await Promise.all(
|
|
22539
22686
|
Array.from(pluginIds).map(
|
|
22540
|
-
(pluginId) => _postJson(`${
|
|
22687
|
+
(pluginId) => _postJson(`${API_BASE10}/api/plugin/heartbeat`, {
|
|
22541
22688
|
pluginId,
|
|
22542
22689
|
online: false
|
|
22543
22690
|
}).catch((err) => {
|
|
@@ -24679,7 +24826,7 @@ function checkChokidar() {
|
|
|
24679
24826
|
}
|
|
24680
24827
|
async function doctor(args2 = []) {
|
|
24681
24828
|
const json = args2.includes("--json");
|
|
24682
|
-
const cliVersion = true ? "2.
|
|
24829
|
+
const cliVersion = true ? "2.30.0" : "0.0.0-dev";
|
|
24683
24830
|
const apiBase = resolveApiBaseUrl();
|
|
24684
24831
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
24685
24832
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -24878,7 +25025,7 @@ async function completion(args2) {
|
|
|
24878
25025
|
// src/commands/version.ts
|
|
24879
25026
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
24880
25027
|
function version2() {
|
|
24881
|
-
const v = true ? "2.
|
|
25028
|
+
const v = true ? "2.30.0" : "unknown";
|
|
24882
25029
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
24883
25030
|
}
|
|
24884
25031
|
|
|
@@ -25009,7 +25156,7 @@ var _subcommandHelpKeys = Object.keys(HELPS);
|
|
|
25009
25156
|
var fs35 = __toESM(require("fs"));
|
|
25010
25157
|
var os27 = __toESM(require("os"));
|
|
25011
25158
|
var path44 = __toESM(require("path"));
|
|
25012
|
-
var
|
|
25159
|
+
var https8 = __toESM(require("https"));
|
|
25013
25160
|
var import_node_child_process12 = require("child_process");
|
|
25014
25161
|
var import_picocolors16 = __toESM(require("picocolors"));
|
|
25015
25162
|
var PKG_NAME = "codeam-cli";
|
|
@@ -25055,7 +25202,7 @@ function compareSemver(a, b) {
|
|
|
25055
25202
|
}
|
|
25056
25203
|
function fetchLatest() {
|
|
25057
25204
|
return new Promise((resolve6) => {
|
|
25058
|
-
const req =
|
|
25205
|
+
const req = https8.get(
|
|
25059
25206
|
REGISTRY_URL,
|
|
25060
25207
|
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
25061
25208
|
(res) => {
|
|
@@ -25164,7 +25311,7 @@ function checkForUpdates() {
|
|
|
25164
25311
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
25165
25312
|
if (process.env.CI) return;
|
|
25166
25313
|
if (!process.stdout.isTTY) return;
|
|
25167
|
-
const current = true ? "2.
|
|
25314
|
+
const current = true ? "2.30.0" : null;
|
|
25168
25315
|
if (!current) return;
|
|
25169
25316
|
const cache = readCache();
|
|
25170
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",
|