codeam-cli 2.22.1 → 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 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.22.1] — 2026-05-25
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Payload.agentId — accept any string, not just the public enum (#187)
12
+
7
13
  ## [2.22.0] — 2026-05-25
8
14
 
9
15
  ### Added
package/dist/index.js CHANGED
@@ -441,7 +441,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
441
441
  // package.json
442
442
  var package_default = {
443
443
  name: "codeam-cli",
444
- version: "2.22.1",
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.22.1" : "0.0.0-dev",
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 import_child_process6 = require("child_process");
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)(import_child_process6.execFile);
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 import_child_process7 = require("child_process");
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, import_child_process7.spawn)("git", args2, { cwd, env: process.env });
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 import_child_process8 = require("child_process");
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, import_child_process8.spawn)("git", args2, { cwd, env: process.env });
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 import_child_process9 = require("child_process");
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, import_child_process9.spawn)(
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 import_child_process13 = require("child_process");
13860
+ var import_child_process14 = require("child_process");
13762
13861
 
13763
13862
  // src/lib/payload.ts
13764
13863
  var import_zod2 = require("zod");
@@ -13823,7 +13922,27 @@ var startCommandSchema = import_zod2.z.object({
13823
13922
  // a narrow enum) because the web sends internal ids ('claude')
13824
13923
  // while the auto-link backend sends public ids ('claude_code'),
13825
13924
  // and the consuming handlers normalize themselves.
13826
- agentId: import_zod2.z.string().max(64).optional()
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()
13827
13946
  });
13828
13947
  function parsePayload2(schema, raw) {
13829
13948
  const result = schema.safeParse(raw);
@@ -13979,11 +14098,11 @@ async function writeProjectFile(rawPath, content) {
13979
14098
  }
13980
14099
 
13981
14100
  // src/services/project-ops.service.ts
13982
- var import_child_process10 = require("child_process");
14101
+ var import_child_process11 = require("child_process");
13983
14102
  var import_util2 = require("util");
13984
14103
  var fs24 = __toESM(require("fs/promises"));
13985
14104
  var path29 = __toESM(require("path"));
13986
- var execFileP3 = (0, import_util2.promisify)(import_child_process10.execFile);
14105
+ var execFileP3 = (0, import_util2.promisify)(import_child_process11.execFile);
13987
14106
  var PROJECT_IGNORE = /* @__PURE__ */ new Set([
13988
14107
  "node_modules",
13989
14108
  ".git",
@@ -14323,7 +14442,7 @@ async function jsSearchFiles(opts, cwd, cap) {
14323
14442
  }
14324
14443
 
14325
14444
  // src/services/terminal-ops.service.ts
14326
- var import_child_process11 = require("child_process");
14445
+ var import_child_process12 = require("child_process");
14327
14446
  var import_crypto4 = require("crypto");
14328
14447
  var import_path3 = __toESM(require("path"));
14329
14448
  var MAX_CONCURRENT_SESSIONS = 4;
@@ -14445,7 +14564,7 @@ function createPythonSession(id, shell, cwd, env, cols, rows) {
14445
14564
  }
14446
14565
  let child;
14447
14566
  try {
14448
- child = (0, import_child_process11.spawn)(python, ["-c", PYTHON_TERMINAL_HELPER, shell], {
14567
+ child = (0, import_child_process12.spawn)(python, ["-c", PYTHON_TERMINAL_HELPER, shell], {
14449
14568
  cwd,
14450
14569
  env: { ...env, COLUMNS: String(cols), LINES: String(rows) },
14451
14570
  stdio: ["pipe", "pipe", "pipe"]
@@ -14580,7 +14699,7 @@ function closeAllTerminals() {
14580
14699
  }
14581
14700
 
14582
14701
  // src/services/apply-file-review.service.ts
14583
- var import_child_process12 = require("child_process");
14702
+ var import_child_process13 = require("child_process");
14584
14703
  var fs25 = __toESM(require("fs"));
14585
14704
  var path31 = __toESM(require("path"));
14586
14705
  async function applyFileReview(workingDir, filePath, action) {
@@ -14622,7 +14741,7 @@ function runGit3(cwd, args2) {
14622
14741
  return new Promise((resolve5) => {
14623
14742
  let proc;
14624
14743
  try {
14625
- proc = (0, import_child_process12.spawn)("git", args2, { cwd, env: process.env });
14744
+ proc = (0, import_child_process13.spawn)("git", args2, { cwd, env: process.env });
14626
14745
  } catch (err) {
14627
14746
  resolve5({ ok: false, code: -1, stdout: "", stderr: err.message });
14628
14747
  return;
@@ -15153,7 +15272,7 @@ var sessionTerminated = (ctx) => {
15153
15272
  } catch {
15154
15273
  }
15155
15274
  try {
15156
- const proc = (0, import_child_process13.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
15275
+ const proc = (0, import_child_process14.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
15157
15276
  detached: true,
15158
15277
  stdio: "ignore"
15159
15278
  });
@@ -15175,7 +15294,7 @@ var shutdownSession = async (ctx, cmd) => {
15175
15294
  }
15176
15295
  if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
15177
15296
  try {
15178
- const stopProc = (0, import_child_process13.spawn)(
15297
+ const stopProc = (0, import_child_process14.spawn)(
15179
15298
  "bash",
15180
15299
  ["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
15181
15300
  { detached: true, stdio: "ignore" }
@@ -15185,7 +15304,7 @@ var shutdownSession = async (ctx, cmd) => {
15185
15304
  }
15186
15305
  }
15187
15306
  try {
15188
- const proc = (0, import_child_process13.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
15307
+ const proc = (0, import_child_process14.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
15189
15308
  detached: true,
15190
15309
  stdio: "ignore"
15191
15310
  });
@@ -15367,6 +15486,62 @@ var requestLinkCredentialsH = async (ctx, _cmd, parsed) => {
15367
15486
  log.trace("auto-link", `upload failed (${result.status}): ${result.message}`);
15368
15487
  }
15369
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
+ }
15370
15545
  var handlers = {
15371
15546
  start_task: startTask,
15372
15547
  provide_input: provideInput,
@@ -15399,7 +15574,9 @@ var handlers = {
15399
15574
  git_pull: gitPullH,
15400
15575
  git_resolve: gitResolveH,
15401
15576
  apply_file_review: applyFileReviewH,
15402
- request_link_credentials: requestLinkCredentialsH
15577
+ request_link_credentials: requestLinkCredentialsH,
15578
+ request_ai_summary: requestAiSummaryH,
15579
+ request_ai_insight: requestAiInsightH
15403
15580
  };
15404
15581
  async function dispatchCommand(ctx, cmd) {
15405
15582
  const parsed = parsePayload2(startCommandSchema, cmd.payload);
@@ -15494,6 +15671,7 @@ async function start(requestedAgent) {
15494
15671
  sessionId: session.id,
15495
15672
  pluginId,
15496
15673
  pluginAuthToken: session.pluginAuthToken,
15674
+ agentId: runtime.meta.id,
15497
15675
  dirtyTracker: dirtyTracker ?? void 0
15498
15676
  }) : null;
15499
15677
  let streamingEmitter = null;
@@ -15991,11 +16169,11 @@ async function logout() {
15991
16169
  var import_picocolors10 = __toESM(require("picocolors"));
15992
16170
 
15993
16171
  // src/services/providers/github-codespaces.ts
15994
- var import_child_process14 = require("child_process");
16172
+ var import_child_process15 = require("child_process");
15995
16173
  var import_util3 = require("util");
15996
16174
  var import_picocolors8 = __toESM(require("picocolors"));
15997
16175
  var path34 = __toESM(require("path"));
15998
- var execFileP4 = (0, import_util3.promisify)(import_child_process14.execFile);
16176
+ var execFileP4 = (0, import_util3.promisify)(import_child_process15.execFile);
15999
16177
  var MAX_BUFFER = 8 * 1024 * 1024;
16000
16178
  function resetStdinForChild() {
16001
16179
  if (process.stdin.isTTY) {
@@ -16039,7 +16217,7 @@ var GitHubCodespacesProvider = class {
16039
16217
  if (!isAuthed) {
16040
16218
  resetStdinForChild();
16041
16219
  await new Promise((resolve5, reject) => {
16042
- const proc = (0, import_child_process14.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
16220
+ const proc = (0, import_child_process15.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
16043
16221
  stdio: "inherit"
16044
16222
  });
16045
16223
  proc.on("exit", (code) => {
@@ -16073,7 +16251,7 @@ var GitHubCodespacesProvider = class {
16073
16251
  wt(noteLines.join("\n"), "One more permission needed");
16074
16252
  resetStdinForChild();
16075
16253
  const refreshCode = await new Promise((resolve5, reject) => {
16076
- const proc = (0, import_child_process14.spawn)(
16254
+ const proc = (0, import_child_process15.spawn)(
16077
16255
  "gh",
16078
16256
  ["auth", "refresh", "-h", "github.com", "-s", "codespace"],
16079
16257
  { stdio: "inherit" }
@@ -16223,7 +16401,7 @@ var GitHubCodespacesProvider = class {
16223
16401
  O2.step(`Installing gh via ${installCmd.describe}\u2026`);
16224
16402
  resetStdinForChild();
16225
16403
  const ok = await new Promise((resolve5) => {
16226
- const proc = (0, import_child_process14.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
16404
+ const proc = (0, import_child_process15.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
16227
16405
  proc.on("exit", (code) => resolve5(code === 0));
16228
16406
  proc.on("error", () => resolve5(false));
16229
16407
  });
@@ -16250,7 +16428,7 @@ var GitHubCodespacesProvider = class {
16250
16428
  );
16251
16429
  resetStdinForChild();
16252
16430
  await new Promise((resolve5, reject) => {
16253
- const proc = (0, import_child_process14.spawn)(
16431
+ const proc = (0, import_child_process15.spawn)(
16254
16432
  "gh",
16255
16433
  ["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
16256
16434
  { stdio: "inherit" }
@@ -16428,7 +16606,7 @@ var GitHubCodespacesProvider = class {
16428
16606
  async streamCommand(workspaceId, command2) {
16429
16607
  resetStdinForChild();
16430
16608
  return new Promise((resolve5, reject) => {
16431
- const proc = (0, import_child_process14.spawn)(
16609
+ const proc = (0, import_child_process15.spawn)(
16432
16610
  "gh",
16433
16611
  ["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
16434
16612
  { stdio: "inherit" }
@@ -16455,11 +16633,11 @@ var GitHubCodespacesProvider = class {
16455
16633
  `mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
16456
16634
  ];
16457
16635
  await new Promise((resolve5, reject) => {
16458
- const tar = (0, import_child_process14.spawn)("tar", tarArgs, {
16636
+ const tar = (0, import_child_process15.spawn)("tar", tarArgs, {
16459
16637
  stdio: ["ignore", "pipe", "pipe"],
16460
16638
  env: tarEnv
16461
16639
  });
16462
- const ssh = (0, import_child_process14.spawn)("gh", sshArgs, {
16640
+ const ssh = (0, import_child_process15.spawn)("gh", sshArgs, {
16463
16641
  stdio: [tar.stdout, "pipe", "pipe"]
16464
16642
  });
16465
16643
  let tarErr = "";
@@ -16493,7 +16671,7 @@ var GitHubCodespacesProvider = class {
16493
16671
  }
16494
16672
  const cmd = parts.join(" && ");
16495
16673
  await new Promise((resolve5, reject) => {
16496
- const proc = (0, import_child_process14.spawn)(
16674
+ const proc = (0, import_child_process15.spawn)(
16497
16675
  "gh",
16498
16676
  ["codespace", "ssh", "-c", workspaceId, "--", cmd],
16499
16677
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -16551,11 +16729,11 @@ function shellQuote(s) {
16551
16729
  }
16552
16730
 
16553
16731
  // src/services/providers/gitpod.ts
16554
- var import_child_process15 = require("child_process");
16732
+ var import_child_process16 = require("child_process");
16555
16733
  var import_util4 = require("util");
16556
16734
  var path35 = __toESM(require("path"));
16557
16735
  var import_picocolors9 = __toESM(require("picocolors"));
16558
- var execFileP5 = (0, import_util4.promisify)(import_child_process15.execFile);
16736
+ var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
16559
16737
  var MAX_BUFFER2 = 8 * 1024 * 1024;
16560
16738
  function resetStdinForChild2() {
16561
16739
  if (process.stdin.isTTY) {
@@ -16595,7 +16773,7 @@ var GitpodProvider = class {
16595
16773
  );
16596
16774
  resetStdinForChild2();
16597
16775
  await new Promise((resolve5, reject) => {
16598
- const proc = (0, import_child_process15.spawn)("gitpod", ["login"], { stdio: "inherit" });
16776
+ const proc = (0, import_child_process16.spawn)("gitpod", ["login"], { stdio: "inherit" });
16599
16777
  proc.on("exit", (code) => {
16600
16778
  if (code === 0) resolve5();
16601
16779
  else reject(new Error("gitpod login failed."));
@@ -16747,7 +16925,7 @@ var GitpodProvider = class {
16747
16925
  async streamCommand(workspaceId, command2) {
16748
16926
  resetStdinForChild2();
16749
16927
  return new Promise((resolve5, reject) => {
16750
- const proc = (0, import_child_process15.spawn)(
16928
+ const proc = (0, import_child_process16.spawn)(
16751
16929
  "gitpod",
16752
16930
  ["workspace", "ssh", workspaceId, "--", "-tt", command2],
16753
16931
  { stdio: "inherit" }
@@ -16767,11 +16945,11 @@ var GitpodProvider = class {
16767
16945
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
16768
16946
  const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
16769
16947
  await new Promise((resolve5, reject) => {
16770
- const tar = (0, import_child_process15.spawn)("tar", tarArgs, {
16948
+ const tar = (0, import_child_process16.spawn)("tar", tarArgs, {
16771
16949
  stdio: ["ignore", "pipe", "pipe"],
16772
16950
  env: tarEnv
16773
16951
  });
16774
- const ssh = (0, import_child_process15.spawn)(
16952
+ const ssh = (0, import_child_process16.spawn)(
16775
16953
  "gitpod",
16776
16954
  ["workspace", "ssh", workspaceId, "--", remoteCmd],
16777
16955
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -16803,7 +16981,7 @@ var GitpodProvider = class {
16803
16981
  }
16804
16982
  const cmd = parts.join(" && ");
16805
16983
  await new Promise((resolve5, reject) => {
16806
- const proc = (0, import_child_process15.spawn)(
16984
+ const proc = (0, import_child_process16.spawn)(
16807
16985
  "gitpod",
16808
16986
  ["workspace", "ssh", workspaceId, "--", cmd],
16809
16987
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -16827,10 +17005,10 @@ function shellQuote2(s) {
16827
17005
  }
16828
17006
 
16829
17007
  // src/services/providers/gitlab-workspaces.ts
16830
- var import_child_process16 = require("child_process");
17008
+ var import_child_process17 = require("child_process");
16831
17009
  var import_util5 = require("util");
16832
17010
  var path36 = __toESM(require("path"));
16833
- var execFileP6 = (0, import_util5.promisify)(import_child_process16.execFile);
17011
+ var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
16834
17012
  var MAX_BUFFER3 = 8 * 1024 * 1024;
16835
17013
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
16836
17014
  function resetStdinForChild3() {
@@ -16872,7 +17050,7 @@ var GitLabWorkspacesProvider = class {
16872
17050
  );
16873
17051
  resetStdinForChild3();
16874
17052
  await new Promise((resolve5, reject) => {
16875
- const proc = (0, import_child_process16.spawn)(
17053
+ const proc = (0, import_child_process17.spawn)(
16876
17054
  "glab",
16877
17055
  ["auth", "login", "--scopes", "api,read_user,read_repository"],
16878
17056
  { stdio: "inherit" }
@@ -17044,7 +17222,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
17044
17222
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
17045
17223
  resetStdinForChild3();
17046
17224
  return new Promise((resolve5, reject) => {
17047
- const proc = (0, import_child_process16.spawn)(
17225
+ const proc = (0, import_child_process17.spawn)(
17048
17226
  "ssh",
17049
17227
  ["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
17050
17228
  { stdio: "inherit" }
@@ -17065,8 +17243,8 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
17065
17243
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
17066
17244
  const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
17067
17245
  await new Promise((resolve5, reject) => {
17068
- const tar = (0, import_child_process16.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
17069
- const ssh = (0, import_child_process16.spawn)(
17246
+ const tar = (0, import_child_process17.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
17247
+ const ssh = (0, import_child_process17.spawn)(
17070
17248
  "ssh",
17071
17249
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
17072
17250
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -17096,7 +17274,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
17096
17274
  }
17097
17275
  const cmd = parts.join(" && ");
17098
17276
  await new Promise((resolve5, reject) => {
17099
- const proc = (0, import_child_process16.spawn)(
17277
+ const proc = (0, import_child_process17.spawn)(
17100
17278
  "ssh",
17101
17279
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
17102
17280
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -17155,10 +17333,10 @@ function shellQuote3(s) {
17155
17333
  }
17156
17334
 
17157
17335
  // src/services/providers/railway.ts
17158
- var import_child_process17 = require("child_process");
17336
+ var import_child_process18 = require("child_process");
17159
17337
  var import_util6 = require("util");
17160
17338
  var path37 = __toESM(require("path"));
17161
- var execFileP7 = (0, import_util6.promisify)(import_child_process17.execFile);
17339
+ var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
17162
17340
  var MAX_BUFFER4 = 8 * 1024 * 1024;
17163
17341
  function resetStdinForChild4() {
17164
17342
  if (process.stdin.isTTY) {
@@ -17199,7 +17377,7 @@ var RailwayProvider = class {
17199
17377
  );
17200
17378
  resetStdinForChild4();
17201
17379
  await new Promise((resolve5, reject) => {
17202
- const proc = (0, import_child_process17.spawn)("railway", ["login"], { stdio: "inherit" });
17380
+ const proc = (0, import_child_process18.spawn)("railway", ["login"], { stdio: "inherit" });
17203
17381
  proc.on("exit", (code) => {
17204
17382
  if (code === 0) resolve5();
17205
17383
  else reject(new Error("railway login failed."));
@@ -17342,7 +17520,7 @@ var RailwayProvider = class {
17342
17520
  }
17343
17521
  resetStdinForChild4();
17344
17522
  return new Promise((resolve5, reject) => {
17345
- const proc = (0, import_child_process17.spawn)(
17523
+ const proc = (0, import_child_process18.spawn)(
17346
17524
  "railway",
17347
17525
  ["shell", "--project", projectId, "--service", serviceId, "--command", command2],
17348
17526
  { stdio: "inherit" }
@@ -17366,8 +17544,8 @@ var RailwayProvider = class {
17366
17544
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
17367
17545
  const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
17368
17546
  await new Promise((resolve5, reject) => {
17369
- const tar = (0, import_child_process17.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
17370
- const sh = (0, import_child_process17.spawn)(
17547
+ const tar = (0, import_child_process18.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
17548
+ const sh = (0, import_child_process18.spawn)(
17371
17549
  "railway",
17372
17550
  ["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
17373
17551
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -17400,7 +17578,7 @@ var RailwayProvider = class {
17400
17578
  }
17401
17579
  const cmd = parts.join(" && ");
17402
17580
  await new Promise((resolve5, reject) => {
17403
- const proc = (0, import_child_process17.spawn)(
17581
+ const proc = (0, import_child_process18.spawn)(
17404
17582
  "railway",
17405
17583
  ["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
17406
17584
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -18105,7 +18283,7 @@ function checkChokidar() {
18105
18283
  }
18106
18284
  async function doctor(args2 = []) {
18107
18285
  const json = args2.includes("--json");
18108
- const cliVersion = true ? "2.22.1" : "0.0.0-dev";
18286
+ const cliVersion = true ? "2.23.0" : "0.0.0-dev";
18109
18287
  const apiBase = resolveApiBaseUrl();
18110
18288
  const diagnosticId = (0, import_node_crypto5.randomUUID)();
18111
18289
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -18304,7 +18482,7 @@ async function completion(args2) {
18304
18482
  // src/commands/version.ts
18305
18483
  var import_picocolors13 = __toESM(require("picocolors"));
18306
18484
  function version2() {
18307
- const v = true ? "2.22.1" : "unknown";
18485
+ const v = true ? "2.23.0" : "unknown";
18308
18486
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
18309
18487
  }
18310
18488
 
@@ -18532,7 +18710,7 @@ function checkForUpdates() {
18532
18710
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
18533
18711
  if (process.env.CI) return;
18534
18712
  if (!process.stdout.isTTY) return;
18535
- const current = true ? "2.22.1" : null;
18713
+ const current = true ? "2.23.0" : null;
18536
18714
  if (!current) return;
18537
18715
  const cache = readCache();
18538
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.22.1",
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",