codeam-cli 2.60.34 → 2.60.36

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +150 -83
  3. 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.60.35] — 2026-07-10
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** CodeRabbit OAuth works headless (codespace/self-hosted) via a PTY + stdin token
12
+
13
+ ## [2.60.34] — 2026-07-10
14
+
15
+ ### Added
16
+
17
+ - **cli:** CodeRabbit session-relay OAuth — deliver mobile-intercepted redirect to host loopback
18
+
7
19
  ## [2.60.33] — 2026-07-10
8
20
 
9
21
  ### Fixed
package/dist/index.js CHANGED
@@ -5689,7 +5689,7 @@ function readAnonId() {
5689
5689
  }
5690
5690
  function superProperties() {
5691
5691
  return {
5692
- cliVersion: true ? "2.60.34" : "0.0.0-dev",
5692
+ cliVersion: true ? "2.60.36" : "0.0.0-dev",
5693
5693
  nodeVersion: process.version,
5694
5694
  platform: process.platform,
5695
5695
  arch: process.arch,
@@ -5870,7 +5870,7 @@ var os4 = __toESM(require("os"));
5870
5870
  // package.json
5871
5871
  var package_default = {
5872
5872
  name: "codeam-cli",
5873
- version: "2.60.34",
5873
+ version: "2.60.36",
5874
5874
  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.",
5875
5875
  type: "commonjs",
5876
5876
  main: "dist/index.js",
@@ -6963,7 +6963,7 @@ var CommandRelayService = class {
6963
6963
  // fresh + clear the "CLI update available" banner after a self-update
6964
6964
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
6965
6965
  // pair/reconnect). Older backends ignore the extra field.
6966
- ..."2.60.34" ? { ideVersion: "2.60.34" } : {}
6966
+ ..."2.60.36" ? { ideVersion: "2.60.36" } : {}
6967
6967
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6968
6968
  }
6969
6969
  /**
@@ -15413,16 +15413,16 @@ async function linkDryRunPreflight(ctx) {
15413
15413
  }
15414
15414
 
15415
15415
  // src/agents/coderabbit/configure.ts
15416
- var import_node_child_process14 = require("child_process");
15416
+ var import_node_child_process15 = require("child_process");
15417
15417
  var path36 = __toESM(require("path"));
15418
15418
 
15419
15419
  // src/agents/coderabbit/oauth.ts
15420
+ var import_node_child_process14 = require("child_process");
15420
15421
  var fs31 = __toESM(require("fs"));
15421
- var http6 = __toESM(require("http"));
15422
15422
  var os27 = __toESM(require("os"));
15423
15423
  var path35 = __toESM(require("path"));
15424
15424
  function parseCoderabbitAuthEvent(line) {
15425
- const l = line.trim();
15425
+ const l = line.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, "").trim();
15426
15426
  if (!l || l[0] !== "{") return null;
15427
15427
  let rec;
15428
15428
  try {
@@ -15456,8 +15456,64 @@ function parseCoderabbitAuthEvent(line) {
15456
15456
  return rec.status ? { kind: "other", status: rec.status } : null;
15457
15457
  }
15458
15458
  }
15459
+ function resolvePython() {
15460
+ for (const bin of ["python3", "python"]) {
15461
+ try {
15462
+ const r = (0, import_node_child_process14.spawnSync)(bin, ["--version"], { stdio: "ignore", timeout: 4e3 });
15463
+ if (!r.error && r.status === 0) return bin;
15464
+ } catch {
15465
+ }
15466
+ }
15467
+ return null;
15468
+ }
15469
+ function spawnCoderabbitLoginProc(cmd, args2) {
15470
+ const python = resolvePython();
15471
+ if (python) {
15472
+ const helper = path35.join(os27.tmpdir(), "codeam-cr-pty.py");
15473
+ fs31.writeFileSync(helper, PYTHON_PTY_HELPER, { mode: 420 });
15474
+ return (0, import_node_child_process14.spawn)(python, [helper, cmd, ...args2], {
15475
+ stdio: ["pipe", "pipe", "pipe"],
15476
+ env: { ...process.env, TERM: "xterm-256color", COLUMNS: "220", LINES: "50" },
15477
+ shell: false
15478
+ });
15479
+ }
15480
+ return (0, import_node_child_process14.spawn)(cmd, args2, { stdio: ["pipe", "pipe", "pipe"], shell: false });
15481
+ }
15482
+ var pendingCoderabbitLogin = null;
15483
+ function setPendingCoderabbitLogin(handle) {
15484
+ pendingCoderabbitLogin = handle;
15485
+ }
15486
+ function normalizeCoderabbitCallback(input) {
15487
+ const s = (input ?? "").trim();
15488
+ if (!s) return null;
15489
+ if (/^coderabbit-cli:\/\/auth-callback/i.test(s) || /^http:\/\/(127\.0\.0\.1|localhost|\[::1\])(:\d+)?\//i.test(s)) {
15490
+ return s;
15491
+ }
15492
+ if (/^[A-Za-z0-9+/=]+$/.test(s) && s.length >= 40) {
15493
+ try {
15494
+ const decoded = Buffer.from(s, "base64").toString("utf8");
15495
+ if (/^coderabbit-cli:\/\/auth-callback/i.test(decoded)) return decoded;
15496
+ } catch {
15497
+ }
15498
+ }
15499
+ return null;
15500
+ }
15501
+ function deliverPendingCoderabbitCallback(callbackUrl) {
15502
+ const url = normalizeCoderabbitCallback(callbackUrl);
15503
+ if (!url) return { ok: false, error: "not a CodeRabbit callback token/URL" };
15504
+ if (!pendingCoderabbitLogin) {
15505
+ return { ok: false, error: "no CodeRabbit login is awaiting a callback" };
15506
+ }
15507
+ try {
15508
+ pendingCoderabbitLogin.deliver(url);
15509
+ return { ok: true };
15510
+ } catch (err) {
15511
+ return { ok: false, error: err instanceof Error ? err.message : "deliver failed" };
15512
+ }
15513
+ }
15459
15514
  function runCoderabbitOAuthLogin(deps) {
15460
15515
  const timeoutMs = deps.timeoutMs ?? 18e4;
15516
+ const spawnProc = deps.spawn ?? spawnCoderabbitLoginProc;
15461
15517
  return new Promise((resolve7) => {
15462
15518
  let settled = false;
15463
15519
  let stdout = "";
@@ -15466,6 +15522,7 @@ function runCoderabbitOAuthLogin(deps) {
15466
15522
  if (settled) return;
15467
15523
  settled = true;
15468
15524
  clearTimeout(timer);
15525
+ setPendingCoderabbitLogin(null);
15469
15526
  try {
15470
15527
  child.kill("SIGKILL");
15471
15528
  } catch {
@@ -15474,7 +15531,7 @@ function runCoderabbitOAuthLogin(deps) {
15474
15531
  };
15475
15532
  let child;
15476
15533
  try {
15477
- child = deps.spawn("coderabbit", ["auth", "login", "--agent"]);
15534
+ child = spawnProc("coderabbit", ["auth", "login", "--agent"]);
15478
15535
  } catch (err) {
15479
15536
  resolve7({ ok: false, error: err instanceof Error ? err.message : "spawn failed" });
15480
15537
  return;
@@ -15487,7 +15544,14 @@ function runCoderabbitOAuthLogin(deps) {
15487
15544
  const e = parseCoderabbitAuthEvent(line);
15488
15545
  if (!e) return;
15489
15546
  deps.onEvent?.(e);
15490
- if (e.kind === "authenticated") {
15547
+ if (e.kind === "awaiting_browser") {
15548
+ setPendingCoderabbitLogin({
15549
+ deliver: (callbackUrl) => {
15550
+ child.stdin?.write(`${callbackUrl}
15551
+ `);
15552
+ }
15553
+ });
15554
+ } else if (e.kind === "authenticated") {
15491
15555
  last = e;
15492
15556
  finish({ ok: true, user: e.user, authType: e.authType, provider: e.provider, org: e.org });
15493
15557
  } else if (e.kind === "failed") {
@@ -15550,38 +15614,10 @@ function diffCapturedCredential(before, home) {
15550
15614
  return null;
15551
15615
  }
15552
15616
  }
15553
- function deliverLoopbackCallback(callbackUrl, opts = {}) {
15554
- return new Promise((resolve7) => {
15555
- let url;
15556
- try {
15557
- url = new URL(callbackUrl);
15558
- } catch {
15559
- resolve7({ ok: false, error: "invalid callback URL" });
15560
- return;
15561
- }
15562
- const host2 = url.hostname.replace(/^\[|\]$/g, "");
15563
- const isLoopback = url.protocol === "http:" && (host2 === "127.0.0.1" || host2 === "localhost" || host2 === "::1");
15564
- if (!isLoopback) {
15565
- resolve7({ ok: false, error: `refusing non-loopback callback host: ${url.hostname}` });
15566
- return;
15567
- }
15568
- const get3 = opts.get ?? http6.get;
15569
- const req = get3(url, { timeout: opts.timeoutMs ?? 1e4 }, (res) => {
15570
- res.resume();
15571
- const status2 = res.statusCode ?? 0;
15572
- resolve7({ ok: status2 >= 200 && status2 < 400, status: status2 });
15573
- });
15574
- req.on("timeout", () => {
15575
- req.destroy();
15576
- resolve7({ ok: false, error: "callback delivery timed out" });
15577
- });
15578
- req.on("error", (err) => resolve7({ ok: false, error: err.message }));
15579
- });
15580
- }
15581
15617
 
15582
15618
  // src/agents/coderabbit/configure.ts
15583
15619
  function defaultIsLoggedIn() {
15584
- const r = (0, import_node_child_process14.spawnSync)("coderabbit", ["auth", "status", "--agent"], {
15620
+ const r = (0, import_node_child_process15.spawnSync)("coderabbit", ["auth", "status", "--agent"], {
15585
15621
  encoding: "utf8",
15586
15622
  timeout: 15e3
15587
15623
  });
@@ -15598,6 +15634,18 @@ function defaultIsLoggedIn() {
15598
15634
  }
15599
15635
  return false;
15600
15636
  }
15637
+ function defaultLoginWithApiKey(key) {
15638
+ const r = (0, import_node_child_process15.spawnSync)("coderabbit", ["auth", "login", "--api-key", key], {
15639
+ encoding: "utf8",
15640
+ timeout: 3e4
15641
+ });
15642
+ const out2 = `${typeof r.stdout === "string" ? r.stdout : ""}${typeof r.stderr === "string" ? r.stderr : ""}`;
15643
+ if (r.error) return { ok: false, error: r.error.message };
15644
+ const failLine = out2.match(/API key authentication failed:[^\n]*/i);
15645
+ if (failLine) return { ok: false, error: failLine[0].replace(/^[✗\s]+/, "").trim() };
15646
+ if (r.status !== 0) return { ok: false, error: out2.trim() || "API key authentication failed" };
15647
+ return { ok: true };
15648
+ }
15601
15649
  async function configureCoderabbit(input, deps = {}) {
15602
15650
  const os50 = deps.os ?? createOsStrategy();
15603
15651
  const ensureInstalled = deps.ensureInstalled ?? ensureCoderabbitInstalled;
@@ -15605,6 +15653,7 @@ async function configureCoderabbit(input, deps = {}) {
15605
15653
  const runOAuth = deps.runOAuthLogin ?? runCoderabbitOAuthLogin;
15606
15654
  const snapshot = deps.snapshotDir ?? (() => snapshotCredentialDir());
15607
15655
  const capture2 = deps.captureCredential ?? ((b) => diffCapturedCredential(b));
15656
+ const loginWithApiKey = deps.loginWithApiKey ?? defaultLoginWithApiKey;
15608
15657
  const home = os50.homeDir();
15609
15658
  os50.augmentPath(
15610
15659
  os50.id === "win32" ? [
@@ -15630,8 +15679,22 @@ async function configureCoderabbit(input, deps = {}) {
15630
15679
  const res2 = base();
15631
15680
  const key = (input.apiKey ?? "").trim();
15632
15681
  if (!key) return { ...res2, error: "No API key provided" };
15682
+ if (!res2.installed) {
15683
+ const ok = await ensureInstalled(os50);
15684
+ res2.installed = ok;
15685
+ if (!ok) return { ...res2, error: "CodeRabbit CLI could not be installed" };
15686
+ }
15687
+ const login = loginWithApiKey(key);
15688
+ if (!login.ok) {
15689
+ return { ...res2, loggedIn: false, linked: false, error: login.error ?? "Invalid or expired API key" };
15690
+ }
15633
15691
  const stored = deps.uploadCredential ? await deps.uploadCredential("api_key", key) : false;
15634
- return { ...res2, linked: stored, error: stored ? void 0 : "Failed to store API key" };
15692
+ return {
15693
+ ...res2,
15694
+ loggedIn: true,
15695
+ linked: stored,
15696
+ ...stored ? {} : { error: "Signed in, but storing the API key for reuse failed" }
15697
+ };
15635
15698
  }
15636
15699
  if (input.action === "link_oauth") {
15637
15700
  const res2 = base();
@@ -15641,10 +15704,7 @@ async function configureCoderabbit(input, deps = {}) {
15641
15704
  if (!ok) return { ...res2, error: "CodeRabbit CLI could not be installed" };
15642
15705
  }
15643
15706
  const before = snapshot();
15644
- const login = await runOAuth({
15645
- spawn: (cmd, args2) => (0, import_node_child_process14.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"] }),
15646
- onEvent: deps.onEvent
15647
- });
15707
+ const login = await runOAuth({ onEvent: deps.onEvent });
15648
15708
  if (!login.ok) {
15649
15709
  return { ...res2, loggedIn: false, linked: false, error: login.error ?? "CodeRabbit login failed" };
15650
15710
  }
@@ -15691,7 +15751,7 @@ async function configureCoderabbit(input, deps = {}) {
15691
15751
  }
15692
15752
 
15693
15753
  // src/commands/host-agent.ts
15694
- var import_node_child_process22 = require("child_process");
15754
+ var import_node_child_process23 = require("child_process");
15695
15755
  var os35 = __toESM(require("os"));
15696
15756
  var fs41 = __toESM(require("fs"));
15697
15757
  var path44 = __toESM(require("path"));
@@ -15704,7 +15764,7 @@ var path37 = __toESM(require("path"));
15704
15764
  // src/lib/restrict-to-owner.ts
15705
15765
  var import_node_fs5 = __toESM(require("fs"));
15706
15766
  var import_node_os4 = __toESM(require("os"));
15707
- var import_node_child_process15 = require("child_process");
15767
+ var import_node_child_process16 = require("child_process");
15708
15768
  var BROAD_WINDOWS_SIDS = [
15709
15769
  "*S-1-1-0",
15710
15770
  "*S-1-5-11",
@@ -15716,7 +15776,7 @@ function restrictToOwner(filePath) {
15716
15776
  try {
15717
15777
  if (process.platform === "win32") {
15718
15778
  const username = import_node_os4.default.userInfo().username;
15719
- (0, import_node_child_process15.execFileSync)(
15779
+ (0, import_node_child_process16.execFileSync)(
15720
15780
  "icacls",
15721
15781
  [
15722
15782
  filePath,
@@ -15978,9 +16038,9 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
15978
16038
  var fs34 = __toESM(require("fs"));
15979
16039
  var os30 = __toESM(require("os"));
15980
16040
  var path38 = __toESM(require("path"));
15981
- var import_node_child_process16 = require("child_process");
16041
+ var import_node_child_process17 = require("child_process");
15982
16042
  var import_node_util4 = require("util");
15983
- var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process16.execFile);
16043
+ var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process17.execFile);
15984
16044
  function isAbsolutePathTarget(target) {
15985
16045
  return path38.isAbsolute(target);
15986
16046
  }
@@ -16276,7 +16336,7 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os31.homedir(
16276
16336
  }
16277
16337
 
16278
16338
  // src/commands/host/git-tooling.ts
16279
- var import_node_child_process17 = require("child_process");
16339
+ var import_node_child_process18 = require("child_process");
16280
16340
  var fs36 = __toESM(require("fs"));
16281
16341
  var os32 = __toESM(require("os"));
16282
16342
  var path40 = __toESM(require("path"));
@@ -16390,7 +16450,7 @@ var defaultGitToolingRunner = {
16390
16450
  which(cmd) {
16391
16451
  try {
16392
16452
  const probe = process.platform === "win32" ? "where" : "which";
16393
- (0, import_node_child_process17.execFileSync)(probe, [cmd], { stdio: "ignore" });
16453
+ (0, import_node_child_process18.execFileSync)(probe, [cmd], { stdio: "ignore" });
16394
16454
  return true;
16395
16455
  } catch {
16396
16456
  return false;
@@ -16398,7 +16458,7 @@ var defaultGitToolingRunner = {
16398
16458
  },
16399
16459
  run(cmd, args2, opts = {}) {
16400
16460
  return new Promise((resolve7) => {
16401
- const child = (0, import_node_child_process17.spawn)(cmd, args2, {
16461
+ const child = (0, import_node_child_process18.spawn)(cmd, args2, {
16402
16462
  stdio: [opts.input !== void 0 ? "pipe" : "ignore", "ignore", "pipe"]
16403
16463
  });
16404
16464
  let stderr = "";
@@ -16552,12 +16612,12 @@ var HeadroomStatsReporter = class {
16552
16612
  };
16553
16613
 
16554
16614
  // src/commands/host/os-packages.ts
16555
- var import_node_child_process18 = require("child_process");
16615
+ var import_node_child_process19 = require("child_process");
16556
16616
  var PM_INSTALL_TIMEOUT_MS = 18e4;
16557
16617
  var defaultHeadroomRunner = {
16558
16618
  which(cmd) {
16559
16619
  try {
16560
- (0, import_node_child_process18.execFileSync)("which", [cmd], { stdio: "ignore" });
16620
+ (0, import_node_child_process19.execFileSync)("which", [cmd], { stdio: "ignore" });
16561
16621
  return true;
16562
16622
  } catch {
16563
16623
  return false;
@@ -16566,7 +16626,7 @@ var defaultHeadroomRunner = {
16566
16626
  run(cmd, args2, opts = {}) {
16567
16627
  return new Promise((resolve7) => {
16568
16628
  const spawnEnv = opts.env ?? process.env;
16569
- const child = (0, import_node_child_process18.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
16629
+ const child = (0, import_node_child_process19.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
16570
16630
  let stderrBuf = "";
16571
16631
  let stdoutBuf = "";
16572
16632
  let settled = false;
@@ -17073,14 +17133,14 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
17073
17133
  }
17074
17134
 
17075
17135
  // src/commands/host/self-update.ts
17076
- var import_node_child_process20 = require("child_process");
17136
+ var import_node_child_process21 = require("child_process");
17077
17137
 
17078
17138
  // src/lib/updateNotifier.ts
17079
17139
  var fs39 = __toESM(require("fs"));
17080
17140
  var os34 = __toESM(require("os"));
17081
17141
  var path43 = __toESM(require("path"));
17082
17142
  var https6 = __toESM(require("https"));
17083
- var import_node_child_process19 = require("child_process");
17143
+ var import_node_child_process20 = require("child_process");
17084
17144
  var import_picocolors3 = __toESM(require("picocolors"));
17085
17145
  var PKG_NAME = "codeam-cli";
17086
17146
  var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
@@ -17174,7 +17234,7 @@ function notifyIfStale(currentVersion, latest) {
17174
17234
  }
17175
17235
  function isLinkedInstall() {
17176
17236
  try {
17177
- const root = (0, import_node_child_process19.execSync)("npm root -g", {
17237
+ const root = (0, import_node_child_process20.execSync)("npm root -g", {
17178
17238
  encoding: "utf8",
17179
17239
  stdio: ["ignore", "pipe", "ignore"],
17180
17240
  timeout: 2e3
@@ -17202,7 +17262,7 @@ function maybeAutoUpdate(currentVersion, latest) {
17202
17262
 
17203
17263
  `
17204
17264
  );
17205
- const install = (0, import_node_child_process19.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
17265
+ const install = (0, import_node_child_process20.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
17206
17266
  stdio: "inherit",
17207
17267
  env: process.env
17208
17268
  });
@@ -17223,7 +17283,7 @@ function maybeAutoUpdate(currentVersion, latest) {
17223
17283
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
17224
17284
 
17225
17285
  `);
17226
- const child = (0, import_node_child_process19.spawnSync)("codeam", process.argv.slice(2), {
17286
+ const child = (0, import_node_child_process20.spawnSync)("codeam", process.argv.slice(2), {
17227
17287
  stdio: "inherit",
17228
17288
  env: process.env
17229
17289
  });
@@ -17233,7 +17293,7 @@ async function autoUpgradeBeforeCriticalCommand() {
17233
17293
  if (process.env.NODE_ENV === "test") return;
17234
17294
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17235
17295
  if (process.env.CI) return;
17236
- const current = true ? "2.60.34" : null;
17296
+ const current = true ? "2.60.36" : null;
17237
17297
  if (!current) return;
17238
17298
  const cache = readCache();
17239
17299
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17250,7 +17310,7 @@ function checkForUpdates() {
17250
17310
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17251
17311
  if (process.env.CI) return;
17252
17312
  if (!process.stdout.isTTY) return;
17253
- const current = true ? "2.60.34" : null;
17313
+ const current = true ? "2.60.36" : null;
17254
17314
  if (!current) return;
17255
17315
  const cache = readCache();
17256
17316
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17270,11 +17330,11 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
17270
17330
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
17271
17331
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
17272
17332
  function currentCliVersion() {
17273
- return true ? "2.60.34" : null;
17333
+ return true ? "2.60.36" : null;
17274
17334
  }
17275
17335
  function runCmd(cmd, args2, timeoutMs) {
17276
17336
  return new Promise((resolve7) => {
17277
- (0, import_node_child_process20.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
17337
+ (0, import_node_child_process21.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
17278
17338
  const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
17279
17339
  resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
17280
17340
  });
@@ -17336,11 +17396,11 @@ async function runSelfUpdate() {
17336
17396
  }
17337
17397
 
17338
17398
  // src/commands/host/teardown.ts
17339
- var import_node_child_process21 = require("child_process");
17399
+ var import_node_child_process22 = require("child_process");
17340
17400
  var fs40 = __toESM(require("fs"));
17341
17401
  var defaultDisableService = () => {
17342
17402
  try {
17343
- (0, import_node_child_process21.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
17403
+ (0, import_node_child_process22.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
17344
17404
  } catch {
17345
17405
  }
17346
17406
  };
@@ -17348,7 +17408,7 @@ var defaultTeardownHeadroom = () => {
17348
17408
  try {
17349
17409
  const kind = JSON.parse(fs40.readFileSync(headroomConfigPath(), "utf8")).agent;
17350
17410
  if (kind) {
17351
- (0, import_node_child_process21.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
17411
+ (0, import_node_child_process22.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
17352
17412
  }
17353
17413
  } catch {
17354
17414
  }
@@ -17506,7 +17566,7 @@ var CONTROL_AGENT_META = {
17506
17566
  headroomWrappable: false,
17507
17567
  acp: false
17508
17568
  };
17509
- var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process22.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
17569
+ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process23.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
17510
17570
  cwd,
17511
17571
  env: { ...process.env, ...env },
17512
17572
  stdio: ["ignore", "pipe", "pipe"],
@@ -17986,7 +18046,7 @@ var HostAgentSupervisor = class {
17986
18046
  runAgentInstall(script) {
17987
18047
  return new Promise((resolve7) => {
17988
18048
  const home = process.env.HOME || os35.homedir();
17989
- const child = (0, import_node_child_process22.spawn)("sh", ["-c", script], {
18049
+ const child = (0, import_node_child_process23.spawn)("sh", ["-c", script], {
17990
18050
  env: { ...process.env, HOME: home },
17991
18051
  stdio: ["ignore", "pipe", "pipe"]
17992
18052
  });
@@ -21175,7 +21235,7 @@ var coderabbitConfigureH = async (ctx, cmd, parsed) => {
21175
21235
  );
21176
21236
  };
21177
21237
  if (rawAction === "link_deliver_callback") {
21178
- const r = await deliverLoopbackCallback(parsed.callbackUrl ?? "");
21238
+ const r = deliverPendingCoderabbitCallback(parsed.callbackUrl ?? "");
21179
21239
  await ctx.relay.sendResult(cmd.id, r.ok ? "completed" : "failed", {
21180
21240
  action: "link_deliver_callback",
21181
21241
  supported: true,
@@ -21205,7 +21265,14 @@ var coderabbitConfigureH = async (ctx, cmd, parsed) => {
21205
21265
  pluginId: ctx.pluginId,
21206
21266
  pluginAuthToken: token,
21207
21267
  method,
21208
- credential
21268
+ credential,
21269
+ // ⚠️ CodeRabbit is an IN-SESSION reviewer add-on — the link ALWAYS
21270
+ // rides the user's REAL active session (codespace / self-hosted /
21271
+ // local), never a throwaway `codeam link` pairing. Without this the
21272
+ // backend `linkFromCli` treats the session as the disposable
21273
+ // handshake session and DELETES it — the codespace vanished the
21274
+ // instant the OAuth link completed (2026-07-10).
21275
+ preserveSession: true
21209
21276
  });
21210
21277
  return r.ok === true;
21211
21278
  } : void 0;
@@ -22496,7 +22563,7 @@ async function pairAuto(args2) {
22496
22563
  }
22497
22564
 
22498
22565
  // src/services/headroom/wrap-launch.ts
22499
- var import_node_child_process23 = require("child_process");
22566
+ var import_node_child_process24 = require("child_process");
22500
22567
  function wrapWithHeadroom(launch, opts) {
22501
22568
  if (!opts.enabled || !opts.headroomPresent) return launch;
22502
22569
  return {
@@ -22509,7 +22576,7 @@ var _present;
22509
22576
  function headroomPresent() {
22510
22577
  if (_present !== void 0) return Promise.resolve(_present);
22511
22578
  return new Promise((resolve7) => {
22512
- (0, import_node_child_process23.execFile)("headroom", ["--version"], (err) => {
22579
+ (0, import_node_child_process24.execFile)("headroom", ["--version"], (err) => {
22513
22580
  _present = !err;
22514
22581
  resolve7(_present);
22515
22582
  });
@@ -23033,7 +23100,7 @@ async function waitForAdapterModuleGraph(command2, args2, opts = {}) {
23033
23100
  }
23034
23101
 
23035
23102
  // src/agents/kimi/installer.ts
23036
- var import_node_child_process24 = require("child_process");
23103
+ var import_node_child_process25 = require("child_process");
23037
23104
  var import_node_os6 = require("os");
23038
23105
  var import_node_path6 = require("path");
23039
23106
  var INSTALL_URL2 = "https://code.kimi.com/kimi-code/install.sh";
@@ -23041,7 +23108,7 @@ function kimiBinDir() {
23041
23108
  return (0, import_node_path6.join)(process.env.KIMI_CODE_HOME || (0, import_node_path6.join)((0, import_node_os6.homedir)(), ".kimi-code"), "bin");
23042
23109
  }
23043
23110
  function kimiRuns() {
23044
- const r = (0, import_node_child_process24.spawnSync)("kimi", ["--version"], { stdio: "ignore", timeout: 15e3 });
23111
+ const r = (0, import_node_child_process25.spawnSync)("kimi", ["--version"], { stdio: "ignore", timeout: 15e3 });
23045
23112
  return !r.error && r.status === 0;
23046
23113
  }
23047
23114
  function augmentPath2() {
@@ -23051,7 +23118,7 @@ function augmentPath2() {
23051
23118
  }
23052
23119
  async function runInstaller2() {
23053
23120
  return new Promise((resolve7) => {
23054
- const proc = (0, import_node_child_process24.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL2} | bash`], { stdio: "inherit" });
23121
+ const proc = (0, import_node_child_process25.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL2} | bash`], { stdio: "inherit" });
23055
23122
  proc.on("close", (code) => resolve7(code === 0));
23056
23123
  proc.on("error", () => resolve7(false));
23057
23124
  });
@@ -23215,7 +23282,7 @@ var fs56 = __toESM(require("fs"));
23215
23282
  var path61 = __toESM(require("path"));
23216
23283
  var os45 = __toESM(require("os"));
23217
23284
  var https7 = __toESM(require("https"));
23218
- var http7 = __toESM(require("http"));
23285
+ var http6 = __toESM(require("http"));
23219
23286
  var import_zod2 = require("zod");
23220
23287
  var historyRecordSchema = import_zod2.z.object({
23221
23288
  type: import_zod2.z.string().optional(),
@@ -23280,7 +23347,7 @@ function post(endpoint, body, pluginAuthToken) {
23280
23347
  return new Promise((resolve7) => {
23281
23348
  const payload = JSON.stringify(body);
23282
23349
  const u2 = new URL(`${API_BASE8}${endpoint}`);
23283
- const transport = u2.protocol === "https:" ? https7 : http7;
23350
+ const transport = u2.protocol === "https:" ? https7 : http6;
23284
23351
  const req = transport.request(
23285
23352
  {
23286
23353
  hostname: u2.hostname,
@@ -23788,7 +23855,7 @@ var HistoryService = class _HistoryService {
23788
23855
  };
23789
23856
 
23790
23857
  // src/agents/acp/client.ts
23791
- var import_node_child_process25 = require("child_process");
23858
+ var import_node_child_process26 = require("child_process");
23792
23859
  var fs57 = __toESM(require("fs/promises"));
23793
23860
  var fsSync = __toESM(require("fs"));
23794
23861
  var os46 = __toESM(require("os"));
@@ -26413,7 +26480,7 @@ var AcpClient = class {
26413
26480
  "acpClient",
26414
26481
  `spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
26415
26482
  );
26416
- const child = (0, import_node_child_process25.spawn)(adapter.command, adapter.args, {
26483
+ const child = (0, import_node_child_process26.spawn)(adapter.command, adapter.args, {
26417
26484
  cwd,
26418
26485
  // extraEnv (e.g. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 on an on-demand
26419
26486
  // re-spawn) layers over process.env; PATH stays last so the augmented
@@ -26895,7 +26962,7 @@ var relaunchProxyWithoutBudget = async () => {
26895
26962
  };
26896
26963
 
26897
26964
  // src/services/streaming/transport.ts
26898
- var http8 = __toESM(require("http"));
26965
+ var http7 = __toESM(require("http"));
26899
26966
  var https8 = __toESM(require("https"));
26900
26967
  var _transport4 = {
26901
26968
  post: _post3,
@@ -26905,7 +26972,7 @@ function _post3(url, headers, payload) {
26905
26972
  return new Promise((resolve7, reject) => {
26906
26973
  let settled = false;
26907
26974
  const u2 = new URL(url);
26908
- const lib = u2.protocol === "https:" ? https8 : http8;
26975
+ const lib = u2.protocol === "https:" ? https8 : http7;
26909
26976
  const req = lib.request(
26910
26977
  {
26911
26978
  hostname: u2.hostname,
@@ -26947,7 +27014,7 @@ function _get(url, headers) {
26947
27014
  return new Promise((resolve7, reject) => {
26948
27015
  let settled = false;
26949
27016
  const u2 = new URL(url);
26950
- const lib = u2.protocol === "https:" ? https8 : http8;
27017
+ const lib = u2.protocol === "https:" ? https8 : http7;
26951
27018
  const req = lib.request(
26952
27019
  {
26953
27020
  hostname: u2.hostname,
@@ -34323,7 +34390,7 @@ function checkChokidar() {
34323
34390
  }
34324
34391
  async function doctor(args2 = []) {
34325
34392
  const json = args2.includes("--json");
34326
- const cliVersion = true ? "2.60.34" : "0.0.0-dev";
34393
+ const cliVersion = true ? "2.60.36" : "0.0.0-dev";
34327
34394
  const apiBase2 = resolveApiBaseUrl();
34328
34395
  const diagnosticId = (0, import_node_crypto12.randomUUID)();
34329
34396
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -34522,7 +34589,7 @@ async function completion(args2) {
34522
34589
  // src/commands/version.ts
34523
34590
  var import_picocolors15 = __toESM(require("picocolors"));
34524
34591
  function version2() {
34525
- const v = true ? "2.60.34" : "unknown";
34592
+ const v = true ? "2.60.36" : "unknown";
34526
34593
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
34527
34594
  }
34528
34595
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.34",
3
+ "version": "2.60.36",
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",