codeam-cli 2.60.33 → 2.60.35

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 +210 -70
  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.34] — 2026-07-10
8
+
9
+ ### Added
10
+
11
+ - **cli:** CodeRabbit session-relay OAuth — deliver mobile-intercepted redirect to host loopback
12
+
13
+ ## [2.60.33] — 2026-07-10
14
+
15
+ ### Fixed
16
+
17
+ - **cli:** Pre-accept Claude's per-workspace trust dialog on cloud sessions
18
+
7
19
  ## [2.60.32] — 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.33" : "0.0.0-dev",
5692
+ cliVersion: true ? "2.60.35" : "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.33",
5873
+ version: "2.60.35",
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.33" ? { ideVersion: "2.60.33" } : {}
6966
+ ..."2.60.35" ? { ideVersion: "2.60.35" } : {}
6967
6967
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6968
6968
  }
6969
6969
  /**
@@ -8410,6 +8410,9 @@ var startCommandSchema = import_zod.z.object({
8410
8410
  "status",
8411
8411
  // `coderabbit_configure` — link the reviewer (OAuth or API key) + run a review.
8412
8412
  "link_oauth",
8413
+ // Deliver a mobile-intercepted OAuth redirect to this host's coderabbit
8414
+ // loopback so a remote-host `link_oauth` login completes (session-relay).
8415
+ "link_deliver_callback",
8413
8416
  "link_apikey",
8414
8417
  "review"
8415
8418
  ]).optional(),
@@ -8423,6 +8426,10 @@ var startCommandSchema = import_zod.z.object({
8423
8426
  changeSet: import_zod.z.enum(["all", "committed", "uncommitted"]).optional(),
8424
8427
  base: import_zod.z.string().max(255).optional(),
8425
8428
  reviewDir: import_zod.z.string().max(1024).optional(),
8429
+ // `coderabbit_configure` (action='link_deliver_callback') — the exact loopback
8430
+ // redirect URL the mobile WebView intercepted (`http://127.0.0.1:<port>/callback?…`).
8431
+ // Replayed to the local coderabbit login server; SSRF-guarded to loopback only.
8432
+ callbackUrl: import_zod.z.string().max(4096).optional(),
8426
8433
  // `request_link_credentials` — backend fires this from the
8427
8434
  // heartbeat handler when it notices the user is running an agent
8428
8435
  // they haven't vaulted yet. Also reused by `get_context` /
@@ -15406,15 +15413,16 @@ async function linkDryRunPreflight(ctx) {
15406
15413
  }
15407
15414
 
15408
15415
  // src/agents/coderabbit/configure.ts
15409
- var import_node_child_process14 = require("child_process");
15416
+ var import_node_child_process15 = require("child_process");
15410
15417
  var path36 = __toESM(require("path"));
15411
15418
 
15412
15419
  // src/agents/coderabbit/oauth.ts
15420
+ var import_node_child_process14 = require("child_process");
15413
15421
  var fs31 = __toESM(require("fs"));
15414
15422
  var os27 = __toESM(require("os"));
15415
15423
  var path35 = __toESM(require("path"));
15416
15424
  function parseCoderabbitAuthEvent(line) {
15417
- const l = line.trim();
15425
+ const l = line.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, "").trim();
15418
15426
  if (!l || l[0] !== "{") return null;
15419
15427
  let rec;
15420
15428
  try {
@@ -15448,8 +15456,64 @@ function parseCoderabbitAuthEvent(line) {
15448
15456
  return rec.status ? { kind: "other", status: rec.status } : null;
15449
15457
  }
15450
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
+ }
15451
15514
  function runCoderabbitOAuthLogin(deps) {
15452
15515
  const timeoutMs = deps.timeoutMs ?? 18e4;
15516
+ const spawnProc = deps.spawn ?? spawnCoderabbitLoginProc;
15453
15517
  return new Promise((resolve7) => {
15454
15518
  let settled = false;
15455
15519
  let stdout = "";
@@ -15458,6 +15522,7 @@ function runCoderabbitOAuthLogin(deps) {
15458
15522
  if (settled) return;
15459
15523
  settled = true;
15460
15524
  clearTimeout(timer);
15525
+ setPendingCoderabbitLogin(null);
15461
15526
  try {
15462
15527
  child.kill("SIGKILL");
15463
15528
  } catch {
@@ -15466,7 +15531,7 @@ function runCoderabbitOAuthLogin(deps) {
15466
15531
  };
15467
15532
  let child;
15468
15533
  try {
15469
- child = deps.spawn("coderabbit", ["auth", "login", "--agent"]);
15534
+ child = spawnProc("coderabbit", ["auth", "login", "--agent"]);
15470
15535
  } catch (err) {
15471
15536
  resolve7({ ok: false, error: err instanceof Error ? err.message : "spawn failed" });
15472
15537
  return;
@@ -15479,7 +15544,14 @@ function runCoderabbitOAuthLogin(deps) {
15479
15544
  const e = parseCoderabbitAuthEvent(line);
15480
15545
  if (!e) return;
15481
15546
  deps.onEvent?.(e);
15482
- 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") {
15483
15555
  last = e;
15484
15556
  finish({ ok: true, user: e.user, authType: e.authType, provider: e.provider, org: e.org });
15485
15557
  } else if (e.kind === "failed") {
@@ -15545,7 +15617,7 @@ function diffCapturedCredential(before, home) {
15545
15617
 
15546
15618
  // src/agents/coderabbit/configure.ts
15547
15619
  function defaultIsLoggedIn() {
15548
- 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"], {
15549
15621
  encoding: "utf8",
15550
15622
  timeout: 15e3
15551
15623
  });
@@ -15562,6 +15634,18 @@ function defaultIsLoggedIn() {
15562
15634
  }
15563
15635
  return false;
15564
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
+ }
15565
15649
  async function configureCoderabbit(input, deps = {}) {
15566
15650
  const os50 = deps.os ?? createOsStrategy();
15567
15651
  const ensureInstalled = deps.ensureInstalled ?? ensureCoderabbitInstalled;
@@ -15569,6 +15653,7 @@ async function configureCoderabbit(input, deps = {}) {
15569
15653
  const runOAuth = deps.runOAuthLogin ?? runCoderabbitOAuthLogin;
15570
15654
  const snapshot = deps.snapshotDir ?? (() => snapshotCredentialDir());
15571
15655
  const capture2 = deps.captureCredential ?? ((b) => diffCapturedCredential(b));
15656
+ const loginWithApiKey = deps.loginWithApiKey ?? defaultLoginWithApiKey;
15572
15657
  const home = os50.homeDir();
15573
15658
  os50.augmentPath(
15574
15659
  os50.id === "win32" ? [
@@ -15594,8 +15679,22 @@ async function configureCoderabbit(input, deps = {}) {
15594
15679
  const res2 = base();
15595
15680
  const key = (input.apiKey ?? "").trim();
15596
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
+ }
15597
15691
  const stored = deps.uploadCredential ? await deps.uploadCredential("api_key", key) : false;
15598
- 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
+ };
15599
15698
  }
15600
15699
  if (input.action === "link_oauth") {
15601
15700
  const res2 = base();
@@ -15605,10 +15704,7 @@ async function configureCoderabbit(input, deps = {}) {
15605
15704
  if (!ok) return { ...res2, error: "CodeRabbit CLI could not be installed" };
15606
15705
  }
15607
15706
  const before = snapshot();
15608
- const login = await runOAuth({
15609
- spawn: (cmd, args2) => (0, import_node_child_process14.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"] }),
15610
- onEvent: deps.onEvent
15611
- });
15707
+ const login = await runOAuth({ onEvent: deps.onEvent });
15612
15708
  if (!login.ok) {
15613
15709
  return { ...res2, loggedIn: false, linked: false, error: login.error ?? "CodeRabbit login failed" };
15614
15710
  }
@@ -15655,7 +15751,7 @@ async function configureCoderabbit(input, deps = {}) {
15655
15751
  }
15656
15752
 
15657
15753
  // src/commands/host-agent.ts
15658
- var import_node_child_process22 = require("child_process");
15754
+ var import_node_child_process23 = require("child_process");
15659
15755
  var os35 = __toESM(require("os"));
15660
15756
  var fs41 = __toESM(require("fs"));
15661
15757
  var path44 = __toESM(require("path"));
@@ -15668,7 +15764,7 @@ var path37 = __toESM(require("path"));
15668
15764
  // src/lib/restrict-to-owner.ts
15669
15765
  var import_node_fs5 = __toESM(require("fs"));
15670
15766
  var import_node_os4 = __toESM(require("os"));
15671
- var import_node_child_process15 = require("child_process");
15767
+ var import_node_child_process16 = require("child_process");
15672
15768
  var BROAD_WINDOWS_SIDS = [
15673
15769
  "*S-1-1-0",
15674
15770
  "*S-1-5-11",
@@ -15680,7 +15776,7 @@ function restrictToOwner(filePath) {
15680
15776
  try {
15681
15777
  if (process.platform === "win32") {
15682
15778
  const username = import_node_os4.default.userInfo().username;
15683
- (0, import_node_child_process15.execFileSync)(
15779
+ (0, import_node_child_process16.execFileSync)(
15684
15780
  "icacls",
15685
15781
  [
15686
15782
  filePath,
@@ -15942,9 +16038,9 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
15942
16038
  var fs34 = __toESM(require("fs"));
15943
16039
  var os30 = __toESM(require("os"));
15944
16040
  var path38 = __toESM(require("path"));
15945
- var import_node_child_process16 = require("child_process");
16041
+ var import_node_child_process17 = require("child_process");
15946
16042
  var import_node_util4 = require("util");
15947
- 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);
15948
16044
  function isAbsolutePathTarget(target) {
15949
16045
  return path38.isAbsolute(target);
15950
16046
  }
@@ -16240,7 +16336,7 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os31.homedir(
16240
16336
  }
16241
16337
 
16242
16338
  // src/commands/host/git-tooling.ts
16243
- var import_node_child_process17 = require("child_process");
16339
+ var import_node_child_process18 = require("child_process");
16244
16340
  var fs36 = __toESM(require("fs"));
16245
16341
  var os32 = __toESM(require("os"));
16246
16342
  var path40 = __toESM(require("path"));
@@ -16354,7 +16450,7 @@ var defaultGitToolingRunner = {
16354
16450
  which(cmd) {
16355
16451
  try {
16356
16452
  const probe = process.platform === "win32" ? "where" : "which";
16357
- (0, import_node_child_process17.execFileSync)(probe, [cmd], { stdio: "ignore" });
16453
+ (0, import_node_child_process18.execFileSync)(probe, [cmd], { stdio: "ignore" });
16358
16454
  return true;
16359
16455
  } catch {
16360
16456
  return false;
@@ -16362,7 +16458,7 @@ var defaultGitToolingRunner = {
16362
16458
  },
16363
16459
  run(cmd, args2, opts = {}) {
16364
16460
  return new Promise((resolve7) => {
16365
- const child = (0, import_node_child_process17.spawn)(cmd, args2, {
16461
+ const child = (0, import_node_child_process18.spawn)(cmd, args2, {
16366
16462
  stdio: [opts.input !== void 0 ? "pipe" : "ignore", "ignore", "pipe"]
16367
16463
  });
16368
16464
  let stderr = "";
@@ -16516,12 +16612,12 @@ var HeadroomStatsReporter = class {
16516
16612
  };
16517
16613
 
16518
16614
  // src/commands/host/os-packages.ts
16519
- var import_node_child_process18 = require("child_process");
16615
+ var import_node_child_process19 = require("child_process");
16520
16616
  var PM_INSTALL_TIMEOUT_MS = 18e4;
16521
16617
  var defaultHeadroomRunner = {
16522
16618
  which(cmd) {
16523
16619
  try {
16524
- (0, import_node_child_process18.execFileSync)("which", [cmd], { stdio: "ignore" });
16620
+ (0, import_node_child_process19.execFileSync)("which", [cmd], { stdio: "ignore" });
16525
16621
  return true;
16526
16622
  } catch {
16527
16623
  return false;
@@ -16530,7 +16626,7 @@ var defaultHeadroomRunner = {
16530
16626
  run(cmd, args2, opts = {}) {
16531
16627
  return new Promise((resolve7) => {
16532
16628
  const spawnEnv = opts.env ?? process.env;
16533
- 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 });
16534
16630
  let stderrBuf = "";
16535
16631
  let stdoutBuf = "";
16536
16632
  let settled = false;
@@ -17037,14 +17133,14 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
17037
17133
  }
17038
17134
 
17039
17135
  // src/commands/host/self-update.ts
17040
- var import_node_child_process20 = require("child_process");
17136
+ var import_node_child_process21 = require("child_process");
17041
17137
 
17042
17138
  // src/lib/updateNotifier.ts
17043
17139
  var fs39 = __toESM(require("fs"));
17044
17140
  var os34 = __toESM(require("os"));
17045
17141
  var path43 = __toESM(require("path"));
17046
17142
  var https6 = __toESM(require("https"));
17047
- var import_node_child_process19 = require("child_process");
17143
+ var import_node_child_process20 = require("child_process");
17048
17144
  var import_picocolors3 = __toESM(require("picocolors"));
17049
17145
  var PKG_NAME = "codeam-cli";
17050
17146
  var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
@@ -17138,7 +17234,7 @@ function notifyIfStale(currentVersion, latest) {
17138
17234
  }
17139
17235
  function isLinkedInstall() {
17140
17236
  try {
17141
- const root = (0, import_node_child_process19.execSync)("npm root -g", {
17237
+ const root = (0, import_node_child_process20.execSync)("npm root -g", {
17142
17238
  encoding: "utf8",
17143
17239
  stdio: ["ignore", "pipe", "ignore"],
17144
17240
  timeout: 2e3
@@ -17166,7 +17262,7 @@ function maybeAutoUpdate(currentVersion, latest) {
17166
17262
 
17167
17263
  `
17168
17264
  );
17169
- 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`], {
17170
17266
  stdio: "inherit",
17171
17267
  env: process.env
17172
17268
  });
@@ -17187,7 +17283,7 @@ function maybeAutoUpdate(currentVersion, latest) {
17187
17283
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
17188
17284
 
17189
17285
  `);
17190
- 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), {
17191
17287
  stdio: "inherit",
17192
17288
  env: process.env
17193
17289
  });
@@ -17197,7 +17293,7 @@ async function autoUpgradeBeforeCriticalCommand() {
17197
17293
  if (process.env.NODE_ENV === "test") return;
17198
17294
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17199
17295
  if (process.env.CI) return;
17200
- const current = true ? "2.60.33" : null;
17296
+ const current = true ? "2.60.35" : null;
17201
17297
  if (!current) return;
17202
17298
  const cache = readCache();
17203
17299
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17214,7 +17310,7 @@ function checkForUpdates() {
17214
17310
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17215
17311
  if (process.env.CI) return;
17216
17312
  if (!process.stdout.isTTY) return;
17217
- const current = true ? "2.60.33" : null;
17313
+ const current = true ? "2.60.35" : null;
17218
17314
  if (!current) return;
17219
17315
  const cache = readCache();
17220
17316
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17234,11 +17330,11 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
17234
17330
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
17235
17331
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
17236
17332
  function currentCliVersion() {
17237
- return true ? "2.60.33" : null;
17333
+ return true ? "2.60.35" : null;
17238
17334
  }
17239
17335
  function runCmd(cmd, args2, timeoutMs) {
17240
17336
  return new Promise((resolve7) => {
17241
- (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) => {
17242
17338
  const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
17243
17339
  resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
17244
17340
  });
@@ -17300,11 +17396,11 @@ async function runSelfUpdate() {
17300
17396
  }
17301
17397
 
17302
17398
  // src/commands/host/teardown.ts
17303
- var import_node_child_process21 = require("child_process");
17399
+ var import_node_child_process22 = require("child_process");
17304
17400
  var fs40 = __toESM(require("fs"));
17305
17401
  var defaultDisableService = () => {
17306
17402
  try {
17307
- (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" });
17308
17404
  } catch {
17309
17405
  }
17310
17406
  };
@@ -17312,7 +17408,7 @@ var defaultTeardownHeadroom = () => {
17312
17408
  try {
17313
17409
  const kind = JSON.parse(fs40.readFileSync(headroomConfigPath(), "utf8")).agent;
17314
17410
  if (kind) {
17315
- (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 });
17316
17412
  }
17317
17413
  } catch {
17318
17414
  }
@@ -17470,7 +17566,7 @@ var CONTROL_AGENT_META = {
17470
17566
  headroomWrappable: false,
17471
17567
  acp: false
17472
17568
  };
17473
- 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], {
17474
17570
  cwd,
17475
17571
  env: { ...process.env, ...env },
17476
17572
  stdio: ["ignore", "pipe", "pipe"],
@@ -17950,7 +18046,7 @@ var HostAgentSupervisor = class {
17950
18046
  runAgentInstall(script) {
17951
18047
  return new Promise((resolve7) => {
17952
18048
  const home = process.env.HOME || os35.homedir();
17953
- const child = (0, import_node_child_process22.spawn)("sh", ["-c", script], {
18049
+ const child = (0, import_node_child_process23.spawn)("sh", ["-c", script], {
17954
18050
  env: { ...process.env, HOME: home },
17955
18051
  stdio: ["ignore", "pipe", "pipe"]
17956
18052
  });
@@ -21123,7 +21219,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
21123
21219
  await ctx.relay.sendResult(cmd.id, "completed", result);
21124
21220
  };
21125
21221
  var coderabbitConfigureH = async (ctx, cmd, parsed) => {
21126
- const action = parsed.action ?? "status";
21222
+ const rawAction = parsed.action ?? "status";
21127
21223
  const token = ctx.pluginAuthToken;
21128
21224
  let emitChain = Promise.resolve();
21129
21225
  const emit2 = (type, payload) => {
@@ -21138,6 +21234,70 @@ var coderabbitConfigureH = async (ctx, cmd, parsed) => {
21138
21234
  })
21139
21235
  );
21140
21236
  };
21237
+ if (rawAction === "link_deliver_callback") {
21238
+ const r = deliverPendingCoderabbitCallback(parsed.callbackUrl ?? "");
21239
+ await ctx.relay.sendResult(cmd.id, r.ok ? "completed" : "failed", {
21240
+ action: "link_deliver_callback",
21241
+ supported: true,
21242
+ installed: true,
21243
+ loggedIn: false,
21244
+ delivered: r.ok,
21245
+ ...r.error ? { error: r.error } : {}
21246
+ });
21247
+ return;
21248
+ }
21249
+ const action = rawAction;
21250
+ const onEvent = (e) => {
21251
+ if (e.kind === "awaiting_browser") {
21252
+ emit2("coderabbit_progress", {
21253
+ phase: "awaiting_browser",
21254
+ authUrl: e.authUrl,
21255
+ fallbackAuthUrl: e.fallbackAuthUrl
21256
+ });
21257
+ } else {
21258
+ emit2("coderabbit_progress", { phase: e.kind });
21259
+ }
21260
+ };
21261
+ const uploadCredential = token ? async (method, credential) => {
21262
+ const r = await postLinkCredential({
21263
+ agentId: "coderabbit",
21264
+ sessionId: ctx.sessionId,
21265
+ pluginId: ctx.pluginId,
21266
+ pluginAuthToken: token,
21267
+ method,
21268
+ credential
21269
+ });
21270
+ return r.ok === true;
21271
+ } : void 0;
21272
+ if (action === "link_oauth") {
21273
+ await ctx.relay.sendResult(cmd.id, "completed", {
21274
+ action: "link_oauth",
21275
+ supported: true,
21276
+ installed: true,
21277
+ loggedIn: false,
21278
+ linked: false
21279
+ });
21280
+ void (async () => {
21281
+ try {
21282
+ const result2 = await configureCoderabbit({ action: "link_oauth" }, { onEvent, uploadCredential });
21283
+ emit2("coderabbit_status", {
21284
+ installed: result2.installed,
21285
+ loggedIn: result2.loggedIn,
21286
+ linked: result2.linked ?? false,
21287
+ ...result2.error ? { error: result2.error } : {}
21288
+ });
21289
+ } catch (err) {
21290
+ emit2("coderabbit_status", {
21291
+ installed: false,
21292
+ loggedIn: false,
21293
+ linked: false,
21294
+ error: err instanceof Error ? err.message : "CodeRabbit login failed"
21295
+ });
21296
+ }
21297
+ await emitChain;
21298
+ })();
21299
+ return;
21300
+ }
21141
21301
  const result = await configureCoderabbit(
21142
21302
  {
21143
21303
  action,
@@ -21145,28 +21305,8 @@ var coderabbitConfigureH = async (ctx, cmd, parsed) => {
21145
21305
  review: { changeSet: parsed.changeSet, base: parsed.base, dir: parsed.reviewDir }
21146
21306
  },
21147
21307
  {
21148
- onEvent: (e) => {
21149
- if (e.kind === "awaiting_browser") {
21150
- emit2("coderabbit_progress", {
21151
- phase: "awaiting_browser",
21152
- authUrl: e.authUrl,
21153
- fallbackAuthUrl: e.fallbackAuthUrl
21154
- });
21155
- } else {
21156
- emit2("coderabbit_progress", { phase: e.kind });
21157
- }
21158
- },
21159
- uploadCredential: token ? async (method, credential) => {
21160
- const r = await postLinkCredential({
21161
- agentId: "coderabbit",
21162
- sessionId: ctx.sessionId,
21163
- pluginId: ctx.pluginId,
21164
- pluginAuthToken: token,
21165
- method,
21166
- credential
21167
- });
21168
- return r.ok === true;
21169
- } : void 0,
21308
+ onEvent,
21309
+ uploadCredential,
21170
21310
  runReview: (input) => new CoderabbitRuntimeStrategy(createOsStrategy()).runOneShot(input)
21171
21311
  }
21172
21312
  );
@@ -22416,7 +22556,7 @@ async function pairAuto(args2) {
22416
22556
  }
22417
22557
 
22418
22558
  // src/services/headroom/wrap-launch.ts
22419
- var import_node_child_process23 = require("child_process");
22559
+ var import_node_child_process24 = require("child_process");
22420
22560
  function wrapWithHeadroom(launch, opts) {
22421
22561
  if (!opts.enabled || !opts.headroomPresent) return launch;
22422
22562
  return {
@@ -22429,7 +22569,7 @@ var _present;
22429
22569
  function headroomPresent() {
22430
22570
  if (_present !== void 0) return Promise.resolve(_present);
22431
22571
  return new Promise((resolve7) => {
22432
- (0, import_node_child_process23.execFile)("headroom", ["--version"], (err) => {
22572
+ (0, import_node_child_process24.execFile)("headroom", ["--version"], (err) => {
22433
22573
  _present = !err;
22434
22574
  resolve7(_present);
22435
22575
  });
@@ -22953,7 +23093,7 @@ async function waitForAdapterModuleGraph(command2, args2, opts = {}) {
22953
23093
  }
22954
23094
 
22955
23095
  // src/agents/kimi/installer.ts
22956
- var import_node_child_process24 = require("child_process");
23096
+ var import_node_child_process25 = require("child_process");
22957
23097
  var import_node_os6 = require("os");
22958
23098
  var import_node_path6 = require("path");
22959
23099
  var INSTALL_URL2 = "https://code.kimi.com/kimi-code/install.sh";
@@ -22961,7 +23101,7 @@ function kimiBinDir() {
22961
23101
  return (0, import_node_path6.join)(process.env.KIMI_CODE_HOME || (0, import_node_path6.join)((0, import_node_os6.homedir)(), ".kimi-code"), "bin");
22962
23102
  }
22963
23103
  function kimiRuns() {
22964
- const r = (0, import_node_child_process24.spawnSync)("kimi", ["--version"], { stdio: "ignore", timeout: 15e3 });
23104
+ const r = (0, import_node_child_process25.spawnSync)("kimi", ["--version"], { stdio: "ignore", timeout: 15e3 });
22965
23105
  return !r.error && r.status === 0;
22966
23106
  }
22967
23107
  function augmentPath2() {
@@ -22971,7 +23111,7 @@ function augmentPath2() {
22971
23111
  }
22972
23112
  async function runInstaller2() {
22973
23113
  return new Promise((resolve7) => {
22974
- const proc = (0, import_node_child_process24.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL2} | bash`], { stdio: "inherit" });
23114
+ const proc = (0, import_node_child_process25.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL2} | bash`], { stdio: "inherit" });
22975
23115
  proc.on("close", (code) => resolve7(code === 0));
22976
23116
  proc.on("error", () => resolve7(false));
22977
23117
  });
@@ -23708,7 +23848,7 @@ var HistoryService = class _HistoryService {
23708
23848
  };
23709
23849
 
23710
23850
  // src/agents/acp/client.ts
23711
- var import_node_child_process25 = require("child_process");
23851
+ var import_node_child_process26 = require("child_process");
23712
23852
  var fs57 = __toESM(require("fs/promises"));
23713
23853
  var fsSync = __toESM(require("fs"));
23714
23854
  var os46 = __toESM(require("os"));
@@ -26333,7 +26473,7 @@ var AcpClient = class {
26333
26473
  "acpClient",
26334
26474
  `spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
26335
26475
  );
26336
- const child = (0, import_node_child_process25.spawn)(adapter.command, adapter.args, {
26476
+ const child = (0, import_node_child_process26.spawn)(adapter.command, adapter.args, {
26337
26477
  cwd,
26338
26478
  // extraEnv (e.g. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 on an on-demand
26339
26479
  // re-spawn) layers over process.env; PATH stays last so the augmented
@@ -34243,7 +34383,7 @@ function checkChokidar() {
34243
34383
  }
34244
34384
  async function doctor(args2 = []) {
34245
34385
  const json = args2.includes("--json");
34246
- const cliVersion = true ? "2.60.33" : "0.0.0-dev";
34386
+ const cliVersion = true ? "2.60.35" : "0.0.0-dev";
34247
34387
  const apiBase2 = resolveApiBaseUrl();
34248
34388
  const diagnosticId = (0, import_node_crypto12.randomUUID)();
34249
34389
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -34442,7 +34582,7 @@ async function completion(args2) {
34442
34582
  // src/commands/version.ts
34443
34583
  var import_picocolors15 = __toESM(require("picocolors"));
34444
34584
  function version2() {
34445
- const v = true ? "2.60.33" : "unknown";
34585
+ const v = true ? "2.60.35" : "unknown";
34446
34586
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
34447
34587
  }
34448
34588
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.33",
3
+ "version": "2.60.35",
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",