codeam-cli 2.22.0 → 2.23.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 +240 -60
- 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.22.1] — 2026-05-25
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Payload.agentId — accept any string, not just the public enum (#187)
|
|
12
|
+
|
|
13
|
+
## [2.22.0] — 2026-05-25
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli:** Handle request_link_credentials from backend auto-link (#186)
|
|
18
|
+
|
|
7
19
|
## [2.21.2] — 2026-05-25
|
|
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.
|
|
444
|
+
version: "2.23.0",
|
|
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",
|
|
@@ -734,6 +734,34 @@ async function postLinkCredential(input) {
|
|
|
734
734
|
};
|
|
735
735
|
}
|
|
736
736
|
}
|
|
737
|
+
async function postAiResult(input) {
|
|
738
|
+
const body = {
|
|
739
|
+
sessionId: input.sessionId,
|
|
740
|
+
pluginId: input.pluginId,
|
|
741
|
+
kind: input.kind,
|
|
742
|
+
summary: input.summary
|
|
743
|
+
};
|
|
744
|
+
if (input.turnId) body.turnId = input.turnId;
|
|
745
|
+
if (input.stats) body.stats = input.stats;
|
|
746
|
+
if (input.fileChangeId) body.fileChangeId = input.fileChangeId;
|
|
747
|
+
if (input.reasoning) body.reasoning = input.reasoning;
|
|
748
|
+
if (input.securityNote) body.securityNote = input.securityNote;
|
|
749
|
+
try {
|
|
750
|
+
await _transport.postJsonAuthed(
|
|
751
|
+
`${API_BASE}/api/plugin/ai-result`,
|
|
752
|
+
body,
|
|
753
|
+
input.pluginAuthToken
|
|
754
|
+
);
|
|
755
|
+
return { ok: true };
|
|
756
|
+
} catch (err) {
|
|
757
|
+
const e = err;
|
|
758
|
+
return {
|
|
759
|
+
ok: false,
|
|
760
|
+
status: typeof e.statusCode === "number" ? e.statusCode : 0,
|
|
761
|
+
message: e.message || "unknown"
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
}
|
|
737
765
|
async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
738
766
|
return new Promise((resolve5, reject) => {
|
|
739
767
|
const data = JSON.stringify(body);
|
|
@@ -5740,7 +5768,7 @@ function readAnonId() {
|
|
|
5740
5768
|
}
|
|
5741
5769
|
function superProperties() {
|
|
5742
5770
|
return {
|
|
5743
|
-
cliVersion: true ? "2.
|
|
5771
|
+
cliVersion: true ? "2.23.0" : "0.0.0-dev",
|
|
5744
5772
|
nodeVersion: process.version,
|
|
5745
5773
|
platform: process.platform,
|
|
5746
5774
|
arch: process.arch,
|
|
@@ -9099,6 +9127,59 @@ async function fetchClaudeQuota() {
|
|
|
9099
9127
|
});
|
|
9100
9128
|
}
|
|
9101
9129
|
|
|
9130
|
+
// src/services/spawn-and-capture.ts
|
|
9131
|
+
var import_child_process6 = require("child_process");
|
|
9132
|
+
async function spawnAndCapture(cmd, args2, opts = {}) {
|
|
9133
|
+
const timeoutMs = opts.timeoutMs ?? 6e4;
|
|
9134
|
+
return new Promise((resolve5) => {
|
|
9135
|
+
let settled = false;
|
|
9136
|
+
const settle = (value) => {
|
|
9137
|
+
if (settled) return;
|
|
9138
|
+
settled = true;
|
|
9139
|
+
resolve5(value);
|
|
9140
|
+
};
|
|
9141
|
+
let child;
|
|
9142
|
+
try {
|
|
9143
|
+
child = (0, import_child_process6.spawn)(cmd, [...args2], {
|
|
9144
|
+
cwd: opts.cwd,
|
|
9145
|
+
env: opts.env ?? process.env,
|
|
9146
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
9147
|
+
});
|
|
9148
|
+
} catch {
|
|
9149
|
+
settle(null);
|
|
9150
|
+
return;
|
|
9151
|
+
}
|
|
9152
|
+
let stdout = "";
|
|
9153
|
+
child.stdout?.on("data", (chunk) => {
|
|
9154
|
+
stdout += chunk.toString("utf8");
|
|
9155
|
+
});
|
|
9156
|
+
child.stderr?.on("data", (chunk) => {
|
|
9157
|
+
opts.onStderr?.(chunk.toString("utf8"));
|
|
9158
|
+
});
|
|
9159
|
+
const timer = setTimeout(() => {
|
|
9160
|
+
try {
|
|
9161
|
+
child.kill("SIGKILL");
|
|
9162
|
+
} catch {
|
|
9163
|
+
}
|
|
9164
|
+
settle(null);
|
|
9165
|
+
}, timeoutMs);
|
|
9166
|
+
timer.unref();
|
|
9167
|
+
child.on("error", () => {
|
|
9168
|
+
clearTimeout(timer);
|
|
9169
|
+
settle(null);
|
|
9170
|
+
});
|
|
9171
|
+
child.on("exit", (code) => {
|
|
9172
|
+
clearTimeout(timer);
|
|
9173
|
+
if (code !== 0) {
|
|
9174
|
+
settle(null);
|
|
9175
|
+
return;
|
|
9176
|
+
}
|
|
9177
|
+
const trimmed = stdout.trim();
|
|
9178
|
+
settle(trimmed.length > 0 ? trimmed : null);
|
|
9179
|
+
});
|
|
9180
|
+
});
|
|
9181
|
+
}
|
|
9182
|
+
|
|
9102
9183
|
// src/agents/claude/history.ts
|
|
9103
9184
|
var fs9 = __toESM(require("fs"));
|
|
9104
9185
|
var path12 = __toESM(require("path"));
|
|
@@ -9541,6 +9622,14 @@ var ClaudeRuntimeStrategy = class {
|
|
|
9541
9622
|
loginLauncher() {
|
|
9542
9623
|
return claudeLoginLauncher();
|
|
9543
9624
|
}
|
|
9625
|
+
async generateOneShot(prompt, opts) {
|
|
9626
|
+
const launch = buildClaudeLaunch(["-p", prompt], this.os);
|
|
9627
|
+
if (!launch) return null;
|
|
9628
|
+
return spawnAndCapture(launch.cmd, launch.args, {
|
|
9629
|
+
cwd: opts?.cwd,
|
|
9630
|
+
timeoutMs: opts?.timeoutMs
|
|
9631
|
+
});
|
|
9632
|
+
}
|
|
9544
9633
|
};
|
|
9545
9634
|
|
|
9546
9635
|
// src/agents/claude/deploy.ts
|
|
@@ -9549,12 +9638,12 @@ var os13 = __toESM(require("os"));
|
|
|
9549
9638
|
var path14 = __toESM(require("path"));
|
|
9550
9639
|
|
|
9551
9640
|
// src/agents/claude/credentials.ts
|
|
9552
|
-
var
|
|
9641
|
+
var import_child_process7 = require("child_process");
|
|
9553
9642
|
var fs10 = __toESM(require("fs"));
|
|
9554
9643
|
var os12 = __toESM(require("os"));
|
|
9555
9644
|
var path13 = __toESM(require("path"));
|
|
9556
9645
|
var import_util = require("util");
|
|
9557
|
-
var execFileP2 = (0, import_util.promisify)(
|
|
9646
|
+
var execFileP2 = (0, import_util.promisify)(import_child_process7.execFile);
|
|
9558
9647
|
async function detectLocalClaudeCredentials() {
|
|
9559
9648
|
const localClaudeDir = path13.join(os12.homedir(), ".claude");
|
|
9560
9649
|
const flat = path13.join(localClaudeDir, ".credentials.json");
|
|
@@ -10424,6 +10513,15 @@ var CodexRuntimeStrategy = class {
|
|
|
10424
10513
|
loginLauncher() {
|
|
10425
10514
|
return codexLoginLauncher();
|
|
10426
10515
|
}
|
|
10516
|
+
async generateOneShot(prompt, opts) {
|
|
10517
|
+
const binary = this.os.findInPath("codex");
|
|
10518
|
+
if (!binary) return null;
|
|
10519
|
+
const launch = this.os.buildLaunch(binary, ["exec", prompt]);
|
|
10520
|
+
return spawnAndCapture(launch.cmd, launch.args, {
|
|
10521
|
+
cwd: opts?.cwd,
|
|
10522
|
+
timeoutMs: opts?.timeoutMs
|
|
10523
|
+
});
|
|
10524
|
+
}
|
|
10427
10525
|
};
|
|
10428
10526
|
function resolveNpm(os26) {
|
|
10429
10527
|
return os26.id === "win32" ? "npm.cmd" : "npm";
|
|
@@ -12206,7 +12304,7 @@ var HistoryService = class _HistoryService {
|
|
|
12206
12304
|
};
|
|
12207
12305
|
|
|
12208
12306
|
// src/services/file-watcher.service.ts
|
|
12209
|
-
var
|
|
12307
|
+
var import_child_process8 = require("child_process");
|
|
12210
12308
|
var fs21 = __toESM(require("fs"));
|
|
12211
12309
|
var os22 = __toESM(require("os"));
|
|
12212
12310
|
var path25 = __toESM(require("path"));
|
|
@@ -12744,7 +12842,7 @@ async function _runGitImpl(cwd, args2, opts = {}) {
|
|
|
12744
12842
|
return new Promise((resolve5) => {
|
|
12745
12843
|
let proc;
|
|
12746
12844
|
try {
|
|
12747
|
-
proc = (0,
|
|
12845
|
+
proc = (0, import_child_process8.spawn)("git", args2, { cwd, env: process.env });
|
|
12748
12846
|
} catch {
|
|
12749
12847
|
resolve5(null);
|
|
12750
12848
|
return;
|
|
@@ -12776,7 +12874,7 @@ function _runGit(cwd, args2, opts = {}) {
|
|
|
12776
12874
|
var import_crypto2 = require("crypto");
|
|
12777
12875
|
|
|
12778
12876
|
// src/services/turn-files/git-changeset.ts
|
|
12779
|
-
var
|
|
12877
|
+
var import_child_process9 = require("child_process");
|
|
12780
12878
|
var path26 = __toESM(require("path"));
|
|
12781
12879
|
async function collectRepoChangeset(opts) {
|
|
12782
12880
|
const status2 = await runGit2(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
@@ -12859,7 +12957,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
12859
12957
|
return new Promise((resolve5) => {
|
|
12860
12958
|
let proc;
|
|
12861
12959
|
try {
|
|
12862
|
-
proc = (0,
|
|
12960
|
+
proc = (0, import_child_process9.spawn)("git", args2, { cwd, env: process.env });
|
|
12863
12961
|
} catch {
|
|
12864
12962
|
resolve5(null);
|
|
12865
12963
|
return;
|
|
@@ -13199,6 +13297,7 @@ var TurnFileAggregator = class {
|
|
|
13199
13297
|
sessionId: entry.sessionId,
|
|
13200
13298
|
pluginId: entry.pluginId,
|
|
13201
13299
|
turnId: entry.turnId,
|
|
13300
|
+
agentId: this.opts.agentId,
|
|
13202
13301
|
files: entry.files
|
|
13203
13302
|
});
|
|
13204
13303
|
try {
|
|
@@ -13711,13 +13810,13 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
13711
13810
|
}
|
|
13712
13811
|
|
|
13713
13812
|
// src/commands/start/keep-alive.ts
|
|
13714
|
-
var
|
|
13813
|
+
var import_child_process10 = require("child_process");
|
|
13715
13814
|
function buildKeepAlive(ctx) {
|
|
13716
13815
|
let timer = null;
|
|
13717
13816
|
async function setIdleTimeout(minutes) {
|
|
13718
13817
|
if (!ctx.inCodespace || !ctx.codespaceName) return;
|
|
13719
13818
|
await new Promise((resolve5) => {
|
|
13720
|
-
const proc = (0,
|
|
13819
|
+
const proc = (0, import_child_process10.spawn)(
|
|
13721
13820
|
"gh",
|
|
13722
13821
|
[
|
|
13723
13822
|
"api",
|
|
@@ -13758,7 +13857,7 @@ var fs27 = __toESM(require("fs"));
|
|
|
13758
13857
|
var os23 = __toESM(require("os"));
|
|
13759
13858
|
var path33 = __toESM(require("path"));
|
|
13760
13859
|
var import_crypto5 = require("crypto");
|
|
13761
|
-
var
|
|
13860
|
+
var import_child_process14 = require("child_process");
|
|
13762
13861
|
|
|
13763
13862
|
// src/lib/payload.ts
|
|
13764
13863
|
var import_zod2 = require("zod");
|
|
@@ -13817,11 +13916,33 @@ var startCommandSchema = import_zod2.z.object({
|
|
|
13817
13916
|
action: import_zod2.z.enum(["approved", "rejected"]).optional(),
|
|
13818
13917
|
// `request_link_credentials` — backend fires this from the
|
|
13819
13918
|
// heartbeat handler when it notices the user is running an agent
|
|
13820
|
-
// they haven't vaulted yet.
|
|
13821
|
-
//
|
|
13822
|
-
//
|
|
13823
|
-
//
|
|
13824
|
-
|
|
13919
|
+
// they haven't vaulted yet. Also reused by `get_context` /
|
|
13920
|
+
// `list_models` payloads which carry the currently-selected
|
|
13921
|
+
// agent for that session. We accept any string here (rather than
|
|
13922
|
+
// a narrow enum) because the web sends internal ids ('claude')
|
|
13923
|
+
// while the auto-link backend sends public ids ('claude_code'),
|
|
13924
|
+
// and the consuming handlers normalize themselves.
|
|
13925
|
+
agentId: import_zod2.z.string().max(64).optional(),
|
|
13926
|
+
// `request_ai_summary` / `request_ai_insight` — backend fires
|
|
13927
|
+
// these on turn-end (+ file selection) when LinkedAgent.
|
|
13928
|
+
// aiInsightsEnabled is true. The CLI spawns the agent in
|
|
13929
|
+
// headless one-shot mode (`claude -p "..."` / `codex exec`) and
|
|
13930
|
+
// POSTs the response back to /api/plugin/ai-result.
|
|
13931
|
+
//
|
|
13932
|
+
// `prompt` (declared above for start_task) carries the LLM prompt
|
|
13933
|
+
// the backend pre-rendered with the diff context inlined; the
|
|
13934
|
+
// agent receives it verbatim. `turnId` keys the summary,
|
|
13935
|
+
// `fileChangeId` keys the per-file insight, `stats` is echoed
|
|
13936
|
+
// unchanged on the result POST so the backend doesn't have to
|
|
13937
|
+
// recompute (numbers came from file_changes; the agent only
|
|
13938
|
+
// writes the narrative).
|
|
13939
|
+
turnId: import_zod2.z.string().max(128).optional(),
|
|
13940
|
+
fileChangeId: import_zod2.z.string().max(128).optional(),
|
|
13941
|
+
stats: import_zod2.z.object({
|
|
13942
|
+
added: import_zod2.z.number().int(),
|
|
13943
|
+
removed: import_zod2.z.number().int(),
|
|
13944
|
+
complexityShift: import_zod2.z.number().int()
|
|
13945
|
+
}).optional()
|
|
13825
13946
|
});
|
|
13826
13947
|
function parsePayload2(schema, raw) {
|
|
13827
13948
|
const result = schema.safeParse(raw);
|
|
@@ -13977,11 +14098,11 @@ async function writeProjectFile(rawPath, content) {
|
|
|
13977
14098
|
}
|
|
13978
14099
|
|
|
13979
14100
|
// src/services/project-ops.service.ts
|
|
13980
|
-
var
|
|
14101
|
+
var import_child_process11 = require("child_process");
|
|
13981
14102
|
var import_util2 = require("util");
|
|
13982
14103
|
var fs24 = __toESM(require("fs/promises"));
|
|
13983
14104
|
var path29 = __toESM(require("path"));
|
|
13984
|
-
var execFileP3 = (0, import_util2.promisify)(
|
|
14105
|
+
var execFileP3 = (0, import_util2.promisify)(import_child_process11.execFile);
|
|
13985
14106
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
13986
14107
|
"node_modules",
|
|
13987
14108
|
".git",
|
|
@@ -14321,7 +14442,7 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
14321
14442
|
}
|
|
14322
14443
|
|
|
14323
14444
|
// src/services/terminal-ops.service.ts
|
|
14324
|
-
var
|
|
14445
|
+
var import_child_process12 = require("child_process");
|
|
14325
14446
|
var import_crypto4 = require("crypto");
|
|
14326
14447
|
var import_path3 = __toESM(require("path"));
|
|
14327
14448
|
var MAX_CONCURRENT_SESSIONS = 4;
|
|
@@ -14443,7 +14564,7 @@ function createPythonSession(id, shell, cwd, env, cols, rows) {
|
|
|
14443
14564
|
}
|
|
14444
14565
|
let child;
|
|
14445
14566
|
try {
|
|
14446
|
-
child = (0,
|
|
14567
|
+
child = (0, import_child_process12.spawn)(python, ["-c", PYTHON_TERMINAL_HELPER, shell], {
|
|
14447
14568
|
cwd,
|
|
14448
14569
|
env: { ...env, COLUMNS: String(cols), LINES: String(rows) },
|
|
14449
14570
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -14578,7 +14699,7 @@ function closeAllTerminals() {
|
|
|
14578
14699
|
}
|
|
14579
14700
|
|
|
14580
14701
|
// src/services/apply-file-review.service.ts
|
|
14581
|
-
var
|
|
14702
|
+
var import_child_process13 = require("child_process");
|
|
14582
14703
|
var fs25 = __toESM(require("fs"));
|
|
14583
14704
|
var path31 = __toESM(require("path"));
|
|
14584
14705
|
async function applyFileReview(workingDir, filePath, action) {
|
|
@@ -14620,7 +14741,7 @@ function runGit3(cwd, args2) {
|
|
|
14620
14741
|
return new Promise((resolve5) => {
|
|
14621
14742
|
let proc;
|
|
14622
14743
|
try {
|
|
14623
|
-
proc = (0,
|
|
14744
|
+
proc = (0, import_child_process13.spawn)("git", args2, { cwd, env: process.env });
|
|
14624
14745
|
} catch (err) {
|
|
14625
14746
|
resolve5({ ok: false, code: -1, stdout: "", stderr: err.message });
|
|
14626
14747
|
return;
|
|
@@ -15151,7 +15272,7 @@ var sessionTerminated = (ctx) => {
|
|
|
15151
15272
|
} catch {
|
|
15152
15273
|
}
|
|
15153
15274
|
try {
|
|
15154
|
-
const proc = (0,
|
|
15275
|
+
const proc = (0, import_child_process14.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
15155
15276
|
detached: true,
|
|
15156
15277
|
stdio: "ignore"
|
|
15157
15278
|
});
|
|
@@ -15173,7 +15294,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
15173
15294
|
}
|
|
15174
15295
|
if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
|
|
15175
15296
|
try {
|
|
15176
|
-
const stopProc = (0,
|
|
15297
|
+
const stopProc = (0, import_child_process14.spawn)(
|
|
15177
15298
|
"bash",
|
|
15178
15299
|
["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
|
|
15179
15300
|
{ detached: true, stdio: "ignore" }
|
|
@@ -15183,7 +15304,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
15183
15304
|
}
|
|
15184
15305
|
}
|
|
15185
15306
|
try {
|
|
15186
|
-
const proc = (0,
|
|
15307
|
+
const proc = (0, import_child_process14.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
15187
15308
|
detached: true,
|
|
15188
15309
|
stdio: "ignore"
|
|
15189
15310
|
});
|
|
@@ -15365,6 +15486,62 @@ var requestLinkCredentialsH = async (ctx, _cmd, parsed) => {
|
|
|
15365
15486
|
log.trace("auto-link", `upload failed (${result.status}): ${result.message}`);
|
|
15366
15487
|
}
|
|
15367
15488
|
};
|
|
15489
|
+
var requestAiSummaryH = async (ctx, _cmd, parsed) => {
|
|
15490
|
+
if (!ctx.pluginAuthToken) return;
|
|
15491
|
+
if (typeof ctx.runtime.generateOneShot !== "function") return;
|
|
15492
|
+
if (!parsed.prompt || !parsed.turnId || !parsed.stats) {
|
|
15493
|
+
log.trace("ai-summary", "missing prompt/turnId/stats \u2014 skipping");
|
|
15494
|
+
return;
|
|
15495
|
+
}
|
|
15496
|
+
const text = await ctx.runtime.generateOneShot(parsed.prompt).catch((err) => {
|
|
15497
|
+
log.trace("ai-summary", "generateOneShot threw", err);
|
|
15498
|
+
return null;
|
|
15499
|
+
});
|
|
15500
|
+
if (!text) return;
|
|
15501
|
+
await postAiResult({
|
|
15502
|
+
sessionId: ctx.sessionId,
|
|
15503
|
+
pluginId: ctx.pluginId,
|
|
15504
|
+
pluginAuthToken: ctx.pluginAuthToken,
|
|
15505
|
+
kind: "summary",
|
|
15506
|
+
turnId: parsed.turnId,
|
|
15507
|
+
summary: text,
|
|
15508
|
+
stats: parsed.stats
|
|
15509
|
+
});
|
|
15510
|
+
};
|
|
15511
|
+
var requestAiInsightH = async (ctx, _cmd, parsed) => {
|
|
15512
|
+
if (!ctx.pluginAuthToken) return;
|
|
15513
|
+
if (typeof ctx.runtime.generateOneShot !== "function") return;
|
|
15514
|
+
if (!parsed.prompt || !parsed.fileChangeId) {
|
|
15515
|
+
log.trace("ai-insight", "missing prompt/fileChangeId \u2014 skipping");
|
|
15516
|
+
return;
|
|
15517
|
+
}
|
|
15518
|
+
const text = await ctx.runtime.generateOneShot(parsed.prompt).catch((err) => {
|
|
15519
|
+
log.trace("ai-insight", "generateOneShot threw", err);
|
|
15520
|
+
return null;
|
|
15521
|
+
});
|
|
15522
|
+
if (!text) return;
|
|
15523
|
+
const { summary, reasoning, securityNote } = parseInsightText(text);
|
|
15524
|
+
await postAiResult({
|
|
15525
|
+
sessionId: ctx.sessionId,
|
|
15526
|
+
pluginId: ctx.pluginId,
|
|
15527
|
+
pluginAuthToken: ctx.pluginAuthToken,
|
|
15528
|
+
kind: "insight",
|
|
15529
|
+
fileChangeId: parsed.fileChangeId,
|
|
15530
|
+
summary,
|
|
15531
|
+
reasoning,
|
|
15532
|
+
securityNote
|
|
15533
|
+
});
|
|
15534
|
+
};
|
|
15535
|
+
function parseInsightText(text) {
|
|
15536
|
+
const summaryMatch = text.match(/SUMMARY:\s*([\s\S]*?)(?=\n\s*(?:REASONING|SECURITY):|$)/i);
|
|
15537
|
+
const reasoningMatch = text.match(/REASONING:\s*([\s\S]*?)(?=\n\s*SECURITY:|$)/i);
|
|
15538
|
+
const securityMatch = text.match(/SECURITY:\s*([\s\S]*)/i);
|
|
15539
|
+
return {
|
|
15540
|
+
summary: (summaryMatch?.[1] ?? text).trim(),
|
|
15541
|
+
reasoning: (reasoningMatch?.[1] ?? text).trim(),
|
|
15542
|
+
securityNote: securityMatch?.[1]?.trim() || void 0
|
|
15543
|
+
};
|
|
15544
|
+
}
|
|
15368
15545
|
var handlers = {
|
|
15369
15546
|
start_task: startTask,
|
|
15370
15547
|
provide_input: provideInput,
|
|
@@ -15397,7 +15574,9 @@ var handlers = {
|
|
|
15397
15574
|
git_pull: gitPullH,
|
|
15398
15575
|
git_resolve: gitResolveH,
|
|
15399
15576
|
apply_file_review: applyFileReviewH,
|
|
15400
|
-
request_link_credentials: requestLinkCredentialsH
|
|
15577
|
+
request_link_credentials: requestLinkCredentialsH,
|
|
15578
|
+
request_ai_summary: requestAiSummaryH,
|
|
15579
|
+
request_ai_insight: requestAiInsightH
|
|
15401
15580
|
};
|
|
15402
15581
|
async function dispatchCommand(ctx, cmd) {
|
|
15403
15582
|
const parsed = parsePayload2(startCommandSchema, cmd.payload);
|
|
@@ -15492,6 +15671,7 @@ async function start(requestedAgent) {
|
|
|
15492
15671
|
sessionId: session.id,
|
|
15493
15672
|
pluginId,
|
|
15494
15673
|
pluginAuthToken: session.pluginAuthToken,
|
|
15674
|
+
agentId: runtime.meta.id,
|
|
15495
15675
|
dirtyTracker: dirtyTracker ?? void 0
|
|
15496
15676
|
}) : null;
|
|
15497
15677
|
let streamingEmitter = null;
|
|
@@ -15989,11 +16169,11 @@ async function logout() {
|
|
|
15989
16169
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
15990
16170
|
|
|
15991
16171
|
// src/services/providers/github-codespaces.ts
|
|
15992
|
-
var
|
|
16172
|
+
var import_child_process15 = require("child_process");
|
|
15993
16173
|
var import_util3 = require("util");
|
|
15994
16174
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
15995
16175
|
var path34 = __toESM(require("path"));
|
|
15996
|
-
var execFileP4 = (0, import_util3.promisify)(
|
|
16176
|
+
var execFileP4 = (0, import_util3.promisify)(import_child_process15.execFile);
|
|
15997
16177
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
15998
16178
|
function resetStdinForChild() {
|
|
15999
16179
|
if (process.stdin.isTTY) {
|
|
@@ -16037,7 +16217,7 @@ var GitHubCodespacesProvider = class {
|
|
|
16037
16217
|
if (!isAuthed) {
|
|
16038
16218
|
resetStdinForChild();
|
|
16039
16219
|
await new Promise((resolve5, reject) => {
|
|
16040
|
-
const proc = (0,
|
|
16220
|
+
const proc = (0, import_child_process15.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
|
|
16041
16221
|
stdio: "inherit"
|
|
16042
16222
|
});
|
|
16043
16223
|
proc.on("exit", (code) => {
|
|
@@ -16071,7 +16251,7 @@ var GitHubCodespacesProvider = class {
|
|
|
16071
16251
|
wt(noteLines.join("\n"), "One more permission needed");
|
|
16072
16252
|
resetStdinForChild();
|
|
16073
16253
|
const refreshCode = await new Promise((resolve5, reject) => {
|
|
16074
|
-
const proc = (0,
|
|
16254
|
+
const proc = (0, import_child_process15.spawn)(
|
|
16075
16255
|
"gh",
|
|
16076
16256
|
["auth", "refresh", "-h", "github.com", "-s", "codespace"],
|
|
16077
16257
|
{ stdio: "inherit" }
|
|
@@ -16221,7 +16401,7 @@ var GitHubCodespacesProvider = class {
|
|
|
16221
16401
|
O2.step(`Installing gh via ${installCmd.describe}\u2026`);
|
|
16222
16402
|
resetStdinForChild();
|
|
16223
16403
|
const ok = await new Promise((resolve5) => {
|
|
16224
|
-
const proc = (0,
|
|
16404
|
+
const proc = (0, import_child_process15.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
16225
16405
|
proc.on("exit", (code) => resolve5(code === 0));
|
|
16226
16406
|
proc.on("error", () => resolve5(false));
|
|
16227
16407
|
});
|
|
@@ -16248,7 +16428,7 @@ var GitHubCodespacesProvider = class {
|
|
|
16248
16428
|
);
|
|
16249
16429
|
resetStdinForChild();
|
|
16250
16430
|
await new Promise((resolve5, reject) => {
|
|
16251
|
-
const proc = (0,
|
|
16431
|
+
const proc = (0, import_child_process15.spawn)(
|
|
16252
16432
|
"gh",
|
|
16253
16433
|
["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
|
|
16254
16434
|
{ stdio: "inherit" }
|
|
@@ -16426,7 +16606,7 @@ var GitHubCodespacesProvider = class {
|
|
|
16426
16606
|
async streamCommand(workspaceId, command2) {
|
|
16427
16607
|
resetStdinForChild();
|
|
16428
16608
|
return new Promise((resolve5, reject) => {
|
|
16429
|
-
const proc = (0,
|
|
16609
|
+
const proc = (0, import_child_process15.spawn)(
|
|
16430
16610
|
"gh",
|
|
16431
16611
|
["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
|
|
16432
16612
|
{ stdio: "inherit" }
|
|
@@ -16453,11 +16633,11 @@ var GitHubCodespacesProvider = class {
|
|
|
16453
16633
|
`mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
|
|
16454
16634
|
];
|
|
16455
16635
|
await new Promise((resolve5, reject) => {
|
|
16456
|
-
const tar = (0,
|
|
16636
|
+
const tar = (0, import_child_process15.spawn)("tar", tarArgs, {
|
|
16457
16637
|
stdio: ["ignore", "pipe", "pipe"],
|
|
16458
16638
|
env: tarEnv
|
|
16459
16639
|
});
|
|
16460
|
-
const ssh = (0,
|
|
16640
|
+
const ssh = (0, import_child_process15.spawn)("gh", sshArgs, {
|
|
16461
16641
|
stdio: [tar.stdout, "pipe", "pipe"]
|
|
16462
16642
|
});
|
|
16463
16643
|
let tarErr = "";
|
|
@@ -16491,7 +16671,7 @@ var GitHubCodespacesProvider = class {
|
|
|
16491
16671
|
}
|
|
16492
16672
|
const cmd = parts.join(" && ");
|
|
16493
16673
|
await new Promise((resolve5, reject) => {
|
|
16494
|
-
const proc = (0,
|
|
16674
|
+
const proc = (0, import_child_process15.spawn)(
|
|
16495
16675
|
"gh",
|
|
16496
16676
|
["codespace", "ssh", "-c", workspaceId, "--", cmd],
|
|
16497
16677
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -16549,11 +16729,11 @@ function shellQuote(s) {
|
|
|
16549
16729
|
}
|
|
16550
16730
|
|
|
16551
16731
|
// src/services/providers/gitpod.ts
|
|
16552
|
-
var
|
|
16732
|
+
var import_child_process16 = require("child_process");
|
|
16553
16733
|
var import_util4 = require("util");
|
|
16554
16734
|
var path35 = __toESM(require("path"));
|
|
16555
16735
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
16556
|
-
var execFileP5 = (0, import_util4.promisify)(
|
|
16736
|
+
var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
|
|
16557
16737
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
16558
16738
|
function resetStdinForChild2() {
|
|
16559
16739
|
if (process.stdin.isTTY) {
|
|
@@ -16593,7 +16773,7 @@ var GitpodProvider = class {
|
|
|
16593
16773
|
);
|
|
16594
16774
|
resetStdinForChild2();
|
|
16595
16775
|
await new Promise((resolve5, reject) => {
|
|
16596
|
-
const proc = (0,
|
|
16776
|
+
const proc = (0, import_child_process16.spawn)("gitpod", ["login"], { stdio: "inherit" });
|
|
16597
16777
|
proc.on("exit", (code) => {
|
|
16598
16778
|
if (code === 0) resolve5();
|
|
16599
16779
|
else reject(new Error("gitpod login failed."));
|
|
@@ -16745,7 +16925,7 @@ var GitpodProvider = class {
|
|
|
16745
16925
|
async streamCommand(workspaceId, command2) {
|
|
16746
16926
|
resetStdinForChild2();
|
|
16747
16927
|
return new Promise((resolve5, reject) => {
|
|
16748
|
-
const proc = (0,
|
|
16928
|
+
const proc = (0, import_child_process16.spawn)(
|
|
16749
16929
|
"gitpod",
|
|
16750
16930
|
["workspace", "ssh", workspaceId, "--", "-tt", command2],
|
|
16751
16931
|
{ stdio: "inherit" }
|
|
@@ -16765,11 +16945,11 @@ var GitpodProvider = class {
|
|
|
16765
16945
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
16766
16946
|
const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
|
|
16767
16947
|
await new Promise((resolve5, reject) => {
|
|
16768
|
-
const tar = (0,
|
|
16948
|
+
const tar = (0, import_child_process16.spawn)("tar", tarArgs, {
|
|
16769
16949
|
stdio: ["ignore", "pipe", "pipe"],
|
|
16770
16950
|
env: tarEnv
|
|
16771
16951
|
});
|
|
16772
|
-
const ssh = (0,
|
|
16952
|
+
const ssh = (0, import_child_process16.spawn)(
|
|
16773
16953
|
"gitpod",
|
|
16774
16954
|
["workspace", "ssh", workspaceId, "--", remoteCmd],
|
|
16775
16955
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -16801,7 +16981,7 @@ var GitpodProvider = class {
|
|
|
16801
16981
|
}
|
|
16802
16982
|
const cmd = parts.join(" && ");
|
|
16803
16983
|
await new Promise((resolve5, reject) => {
|
|
16804
|
-
const proc = (0,
|
|
16984
|
+
const proc = (0, import_child_process16.spawn)(
|
|
16805
16985
|
"gitpod",
|
|
16806
16986
|
["workspace", "ssh", workspaceId, "--", cmd],
|
|
16807
16987
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -16825,10 +17005,10 @@ function shellQuote2(s) {
|
|
|
16825
17005
|
}
|
|
16826
17006
|
|
|
16827
17007
|
// src/services/providers/gitlab-workspaces.ts
|
|
16828
|
-
var
|
|
17008
|
+
var import_child_process17 = require("child_process");
|
|
16829
17009
|
var import_util5 = require("util");
|
|
16830
17010
|
var path36 = __toESM(require("path"));
|
|
16831
|
-
var execFileP6 = (0, import_util5.promisify)(
|
|
17011
|
+
var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
|
|
16832
17012
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
16833
17013
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
16834
17014
|
function resetStdinForChild3() {
|
|
@@ -16870,7 +17050,7 @@ var GitLabWorkspacesProvider = class {
|
|
|
16870
17050
|
);
|
|
16871
17051
|
resetStdinForChild3();
|
|
16872
17052
|
await new Promise((resolve5, reject) => {
|
|
16873
|
-
const proc = (0,
|
|
17053
|
+
const proc = (0, import_child_process17.spawn)(
|
|
16874
17054
|
"glab",
|
|
16875
17055
|
["auth", "login", "--scopes", "api,read_user,read_repository"],
|
|
16876
17056
|
{ stdio: "inherit" }
|
|
@@ -17042,7 +17222,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
17042
17222
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
17043
17223
|
resetStdinForChild3();
|
|
17044
17224
|
return new Promise((resolve5, reject) => {
|
|
17045
|
-
const proc = (0,
|
|
17225
|
+
const proc = (0, import_child_process17.spawn)(
|
|
17046
17226
|
"ssh",
|
|
17047
17227
|
["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
|
|
17048
17228
|
{ stdio: "inherit" }
|
|
@@ -17063,8 +17243,8 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
17063
17243
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
17064
17244
|
const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
|
|
17065
17245
|
await new Promise((resolve5, reject) => {
|
|
17066
|
-
const tar = (0,
|
|
17067
|
-
const ssh = (0,
|
|
17246
|
+
const tar = (0, import_child_process17.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
17247
|
+
const ssh = (0, import_child_process17.spawn)(
|
|
17068
17248
|
"ssh",
|
|
17069
17249
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
|
|
17070
17250
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -17094,7 +17274,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
17094
17274
|
}
|
|
17095
17275
|
const cmd = parts.join(" && ");
|
|
17096
17276
|
await new Promise((resolve5, reject) => {
|
|
17097
|
-
const proc = (0,
|
|
17277
|
+
const proc = (0, import_child_process17.spawn)(
|
|
17098
17278
|
"ssh",
|
|
17099
17279
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
|
|
17100
17280
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -17153,10 +17333,10 @@ function shellQuote3(s) {
|
|
|
17153
17333
|
}
|
|
17154
17334
|
|
|
17155
17335
|
// src/services/providers/railway.ts
|
|
17156
|
-
var
|
|
17336
|
+
var import_child_process18 = require("child_process");
|
|
17157
17337
|
var import_util6 = require("util");
|
|
17158
17338
|
var path37 = __toESM(require("path"));
|
|
17159
|
-
var execFileP7 = (0, import_util6.promisify)(
|
|
17339
|
+
var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
|
|
17160
17340
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
17161
17341
|
function resetStdinForChild4() {
|
|
17162
17342
|
if (process.stdin.isTTY) {
|
|
@@ -17197,7 +17377,7 @@ var RailwayProvider = class {
|
|
|
17197
17377
|
);
|
|
17198
17378
|
resetStdinForChild4();
|
|
17199
17379
|
await new Promise((resolve5, reject) => {
|
|
17200
|
-
const proc = (0,
|
|
17380
|
+
const proc = (0, import_child_process18.spawn)("railway", ["login"], { stdio: "inherit" });
|
|
17201
17381
|
proc.on("exit", (code) => {
|
|
17202
17382
|
if (code === 0) resolve5();
|
|
17203
17383
|
else reject(new Error("railway login failed."));
|
|
@@ -17340,7 +17520,7 @@ var RailwayProvider = class {
|
|
|
17340
17520
|
}
|
|
17341
17521
|
resetStdinForChild4();
|
|
17342
17522
|
return new Promise((resolve5, reject) => {
|
|
17343
|
-
const proc = (0,
|
|
17523
|
+
const proc = (0, import_child_process18.spawn)(
|
|
17344
17524
|
"railway",
|
|
17345
17525
|
["shell", "--project", projectId, "--service", serviceId, "--command", command2],
|
|
17346
17526
|
{ stdio: "inherit" }
|
|
@@ -17364,8 +17544,8 @@ var RailwayProvider = class {
|
|
|
17364
17544
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
17365
17545
|
const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
|
|
17366
17546
|
await new Promise((resolve5, reject) => {
|
|
17367
|
-
const tar = (0,
|
|
17368
|
-
const sh = (0,
|
|
17547
|
+
const tar = (0, import_child_process18.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
17548
|
+
const sh = (0, import_child_process18.spawn)(
|
|
17369
17549
|
"railway",
|
|
17370
17550
|
["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
|
|
17371
17551
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -17398,7 +17578,7 @@ var RailwayProvider = class {
|
|
|
17398
17578
|
}
|
|
17399
17579
|
const cmd = parts.join(" && ");
|
|
17400
17580
|
await new Promise((resolve5, reject) => {
|
|
17401
|
-
const proc = (0,
|
|
17581
|
+
const proc = (0, import_child_process18.spawn)(
|
|
17402
17582
|
"railway",
|
|
17403
17583
|
["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
|
|
17404
17584
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -18103,7 +18283,7 @@ function checkChokidar() {
|
|
|
18103
18283
|
}
|
|
18104
18284
|
async function doctor(args2 = []) {
|
|
18105
18285
|
const json = args2.includes("--json");
|
|
18106
|
-
const cliVersion = true ? "2.
|
|
18286
|
+
const cliVersion = true ? "2.23.0" : "0.0.0-dev";
|
|
18107
18287
|
const apiBase = resolveApiBaseUrl();
|
|
18108
18288
|
const diagnosticId = (0, import_node_crypto5.randomUUID)();
|
|
18109
18289
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -18302,7 +18482,7 @@ async function completion(args2) {
|
|
|
18302
18482
|
// src/commands/version.ts
|
|
18303
18483
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
18304
18484
|
function version2() {
|
|
18305
|
-
const v = true ? "2.
|
|
18485
|
+
const v = true ? "2.23.0" : "unknown";
|
|
18306
18486
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
18307
18487
|
}
|
|
18308
18488
|
|
|
@@ -18530,7 +18710,7 @@ function checkForUpdates() {
|
|
|
18530
18710
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
18531
18711
|
if (process.env.CI) return;
|
|
18532
18712
|
if (!process.stdout.isTTY) return;
|
|
18533
|
-
const current = true ? "2.
|
|
18713
|
+
const current = true ? "2.23.0" : null;
|
|
18534
18714
|
if (!current) return;
|
|
18535
18715
|
const cache = readCache();
|
|
18536
18716
|
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.23.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",
|