nexrall-code 0.5.206 → 0.5.208

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/README.md +4 -2
  2. package/dist/index.js +1005 -630
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -10114,6 +10114,8 @@ var require_client = __commonJS({
10114
10114
  exports.getUsageDaily = getUsageDaily;
10115
10115
  exports.exchangeVscodeCode = exchangeVscodeCode;
10116
10116
  exports.login = login2;
10117
+ exports.exchangeAuthCode = exchangeAuthCode2;
10118
+ exports.checkToken = checkToken2;
10117
10119
  exports.getUserProfile = getUserProfile;
10118
10120
  exports.clampScheduleMinutes = clampScheduleMinutes;
10119
10121
  exports.listCloudSchedules = listCloudSchedules3;
@@ -10173,7 +10175,7 @@ var require_client = __commonJS({
10173
10175
  function authHeaders() {
10174
10176
  const token = (0, index_1.getToken)();
10175
10177
  if (!token) {
10176
- throw new Error("Not authenticated. Run `nexrall-code login` first.");
10178
+ throw new Error("Not authenticated. Run `nex auth` first.");
10177
10179
  }
10178
10180
  const headers = {
10179
10181
  "Content-Type": "application/json",
@@ -11159,6 +11161,42 @@ var require_client = __commonJS({
11159
11161
  email: data.email ?? email
11160
11162
  };
11161
11163
  }
11164
+ async function exchangeAuthCode2(code) {
11165
+ const response = await (0, node_fetch_1.default)(`${exports.API_BASE}/api/auth/vscode-exchange`, {
11166
+ method: "POST",
11167
+ headers: { "Content-Type": "application/json", ...deviceHeader() },
11168
+ body: JSON.stringify({ code })
11169
+ });
11170
+ if (response.status === 401 || response.status === 400) {
11171
+ throw new Error("That sign-in code is invalid or has expired (codes last 5 minutes). Run `nex auth --browser` again.");
11172
+ }
11173
+ if (!response.ok) {
11174
+ const errText3 = await response.text().catch(() => "");
11175
+ throw new Error(`Sign-in failed (${response.status}): ${errText3}`);
11176
+ }
11177
+ const data = await response.json();
11178
+ if (!data.token)
11179
+ throw new Error("Sign-in response missing token");
11180
+ return {
11181
+ token: data.token,
11182
+ ...data.refreshToken ? { refreshToken: data.refreshToken } : {},
11183
+ email: data.user?.email ?? ""
11184
+ };
11185
+ }
11186
+ async function checkToken2(token) {
11187
+ try {
11188
+ const response = await (0, node_fetch_1.default)(`${exports.API_BASE}/api/user/profile`, {
11189
+ method: "GET",
11190
+ headers: { Authorization: `Bearer ${token}`, ...deviceHeader() }
11191
+ });
11192
+ if (!response.ok)
11193
+ return { ok: false, status: response.status };
11194
+ const data = await response.json().catch(() => ({}));
11195
+ return { ok: true, status: response.status, ...data.email ? { email: data.email } : {} };
11196
+ } catch {
11197
+ return { ok: false, status: 0 };
11198
+ }
11199
+ }
11162
11200
  async function getUserProfile() {
11163
11201
  const fetchOnce = () => (0, node_fetch_1.default)(`${exports.API_BASE}/api/user/profile`, { method: "GET", headers: authHeaders() });
11164
11202
  let response = await fetchOnce();
@@ -11393,6 +11431,102 @@ var require_client = __commonJS({
11393
11431
  }
11394
11432
  });
11395
11433
 
11434
+ // ../core/dist/util/proc.js
11435
+ var require_proc = __commonJS({
11436
+ "../core/dist/util/proc.js"(exports) {
11437
+ "use strict";
11438
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m2, k, k2) {
11439
+ if (k2 === void 0)
11440
+ k2 = k;
11441
+ var desc = Object.getOwnPropertyDescriptor(m2, k);
11442
+ if (!desc || ("get" in desc ? !m2.__esModule : desc.writable || desc.configurable)) {
11443
+ desc = { enumerable: true, get: function() {
11444
+ return m2[k];
11445
+ } };
11446
+ }
11447
+ Object.defineProperty(o, k2, desc);
11448
+ } : function(o, m2, k, k2) {
11449
+ if (k2 === void 0)
11450
+ k2 = k;
11451
+ o[k2] = m2[k];
11452
+ });
11453
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
11454
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11455
+ } : function(o, v) {
11456
+ o["default"] = v;
11457
+ });
11458
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
11459
+ var ownKeys = function(o) {
11460
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
11461
+ var ar = [];
11462
+ for (var k in o2)
11463
+ if (Object.prototype.hasOwnProperty.call(o2, k))
11464
+ ar[ar.length] = k;
11465
+ return ar;
11466
+ };
11467
+ return ownKeys(o);
11468
+ };
11469
+ return function(mod) {
11470
+ if (mod && mod.__esModule)
11471
+ return mod;
11472
+ var result = {};
11473
+ if (mod != null) {
11474
+ for (var k = ownKeys(mod), i2 = 0; i2 < k.length; i2++)
11475
+ if (k[i2] !== "default")
11476
+ __createBinding(result, mod, k[i2]);
11477
+ }
11478
+ __setModuleDefault(result, mod);
11479
+ return result;
11480
+ };
11481
+ }();
11482
+ Object.defineProperty(exports, "__esModule", { value: true });
11483
+ exports.DETACH_GROUP = exports.IS_WINDOWS = exports.execFile = exports.execFileSync = exports.execSync = exports.spawnSync = exports.spawn = void 0;
11484
+ exports.killProcessTree = killProcessTree3;
11485
+ var cp = __importStar(__require("child_process"));
11486
+ var isOpts = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
11487
+ function hide(args, insertAt2) {
11488
+ const out = args.slice();
11489
+ for (let i2 = 1; i2 < out.length; i2++) {
11490
+ if (isOpts(out[i2])) {
11491
+ out[i2] = { windowsHide: true, ...out[i2] };
11492
+ return out;
11493
+ }
11494
+ }
11495
+ let at = insertAt2;
11496
+ if (Array.isArray(out[1]))
11497
+ at = Math.max(at, 2);
11498
+ out.splice(at, 0, { windowsHide: true });
11499
+ return out;
11500
+ }
11501
+ exports.spawn = (...a) => cp.spawn(...hide(a, 1));
11502
+ exports.spawnSync = (...a) => cp.spawnSync(...hide(a, 1));
11503
+ exports.execSync = (...a) => cp.execSync(...hide(a, 1));
11504
+ exports.execFileSync = (...a) => cp.execFileSync(...hide(a, 1));
11505
+ exports.execFile = (...a) => cp.execFile(...hide(a, 1));
11506
+ exports.IS_WINDOWS = process.platform === "win32";
11507
+ exports.DETACH_GROUP = !exports.IS_WINDOWS;
11508
+ function killProcessTree3(pid, sig = "SIGTERM") {
11509
+ if (!pid)
11510
+ return;
11511
+ if (exports.IS_WINDOWS) {
11512
+ try {
11513
+ cp.spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], { windowsHide: true, stdio: "ignore", timeout: 5e3 });
11514
+ } catch {
11515
+ }
11516
+ return;
11517
+ }
11518
+ try {
11519
+ process.kill(-pid, sig);
11520
+ } catch {
11521
+ try {
11522
+ process.kill(pid, sig);
11523
+ } catch {
11524
+ }
11525
+ }
11526
+ }
11527
+ }
11528
+ });
11529
+
11396
11530
  // ../core/dist/tools/sandbox.js
11397
11531
  var require_sandbox = __commonJS({
11398
11532
  "../core/dist/tools/sandbox.js"(exports) {
@@ -11444,7 +11578,7 @@ var require_sandbox = __commonJS({
11444
11578
  Object.defineProperty(exports, "__esModule", { value: true });
11445
11579
  exports.parseSandboxConfig = parseSandboxConfig;
11446
11580
  exports.wrapCommandForSandbox = wrapCommandForSandbox;
11447
- var child_process_1 = __require("child_process");
11581
+ var proc_1 = require_proc();
11448
11582
  var os25 = __importStar(__require("os"));
11449
11583
  function parseSandboxConfig(raw) {
11450
11584
  if (raw === void 0 || raw === null || raw === false || raw === "off")
@@ -11467,7 +11601,7 @@ var require_sandbox = __commonJS({
11467
11601
  var _bwrapAvailable = false;
11468
11602
  function commandExists3(cmd) {
11469
11603
  try {
11470
- (0, child_process_1.execSync)(`command -v ${cmd}`, { stdio: "ignore" });
11604
+ (0, proc_1.execSync)(process.platform === "win32" ? `where ${cmd}` : `command -v ${cmd}`, { stdio: "ignore" });
11471
11605
  return true;
11472
11606
  } catch {
11473
11607
  return false;
@@ -15869,7 +16003,7 @@ var require_loader = __commonJS({
15869
16003
  var fs33 = __importStar(__require("fs"));
15870
16004
  var path36 = __importStar(__require("path"));
15871
16005
  var os25 = __importStar(__require("os"));
15872
- var child_process_1 = __require("child_process");
16006
+ var proc_1 = require_proc();
15873
16007
  var index_1 = require_plugins();
15874
16008
  var frontmatter_1 = require_frontmatter();
15875
16009
  var agentTypes_1 = require_agentTypes();
@@ -15958,7 +16092,7 @@ var require_loader = __commonJS({
15958
16092
  let out = body;
15959
16093
  out = out.replace(/!`([^`]+)`/g, (_m, c) => {
15960
16094
  try {
15961
- const stdout = (0, child_process_1.execSync)(c, {
16095
+ const stdout = (0, proc_1.execSync)(c, {
15962
16096
  cwd: workDir,
15963
16097
  encoding: "utf-8",
15964
16098
  timeout: 15e3,
@@ -16063,7 +16197,7 @@ var require_skills = __commonJS({
16063
16197
  var fs33 = __importStar(__require("fs"));
16064
16198
  var path36 = __importStar(__require("path"));
16065
16199
  var os25 = __importStar(__require("os"));
16066
- var child_process_1 = __require("child_process");
16200
+ var proc_1 = require_proc();
16067
16201
  var index_1 = require_plugins();
16068
16202
  var resolve_1 = require_resolve();
16069
16203
  var loader_1 = require_loader();
@@ -16447,7 +16581,7 @@ var require_skills = __commonJS({
16447
16581
  verdict = true;
16448
16582
  } else {
16449
16583
  try {
16450
- const r2 = (0, child_process_1.spawnSync)("git", ["-C", workDir, "check-ignore", "-q", "--", dir], {
16584
+ const r2 = (0, proc_1.spawnSync)("git", ["-C", workDir, "check-ignore", "-q", "--", dir], {
16451
16585
  stdio: "ignore",
16452
16586
  timeout: 3e3
16453
16587
  });
@@ -18583,7 +18717,7 @@ var require_executor = __commonJS({
18583
18717
  var https3 = __importStar(__require("https"));
18584
18718
  var http4 = __importStar(__require("http"));
18585
18719
  var dns = __importStar(__require("dns"));
18586
- var child_process_1 = __require("child_process");
18720
+ var proc_1 = require_proc();
18587
18721
  var sandbox_1 = require_sandbox();
18588
18722
  var auth_1 = require_auth();
18589
18723
  var client_1 = require_client();
@@ -19105,11 +19239,11 @@ Resolve the conflict (remove <<<<<<< / ======= / >>>>>>> markers and keep the in
19105
19239
  }
19106
19240
  function startBackgroundShell(command, displayCommand, workDir, note) {
19107
19241
  const id = `bg_${++_bgCounter}`;
19108
- const child = (0, child_process_1.spawn)(command, {
19242
+ const child = (0, proc_1.spawn)(command, {
19109
19243
  shell: true,
19110
19244
  cwd: workDir ?? process.cwd(),
19111
19245
  env: bashSpawnEnv(workDir),
19112
- detached: true,
19246
+ detached: proc_1.DETACH_GROUP,
19113
19247
  stdio: ["ignore", "pipe", "pipe"]
19114
19248
  });
19115
19249
  const shell = {
@@ -19224,14 +19358,10 @@ ${fresh || "(no new output)"}${trunc}` };
19224
19358
  if (shell.status === "running") {
19225
19359
  shell.status = "killed";
19226
19360
  const killTree = (sig) => {
19361
+ (0, proc_1.killProcessTree)(shell.child.pid, sig);
19227
19362
  try {
19228
- if (shell.child.pid)
19229
- process.kill(-shell.child.pid, sig);
19363
+ shell.child.kill(sig);
19230
19364
  } catch {
19231
- try {
19232
- shell.child.kill(sig);
19233
- } catch {
19234
- }
19235
19365
  }
19236
19366
  };
19237
19367
  killTree("SIGTERM");
@@ -19273,22 +19403,18 @@ ${fresh || "(no new output)"}${trunc}` };
19273
19403
  ${r2.output}`;
19274
19404
  return r2;
19275
19405
  };
19276
- const child = (0, child_process_1.spawn)(effectiveCommand, {
19406
+ const child = (0, proc_1.spawn)(effectiveCommand, {
19277
19407
  shell: true,
19278
19408
  cwd: workDir ?? process.cwd(),
19279
19409
  env: bashSpawnEnv(workDir),
19280
- detached: true,
19410
+ detached: proc_1.DETACH_GROUP,
19281
19411
  stdio: ["ignore", "pipe", "pipe"]
19282
19412
  });
19283
19413
  const killTree = (sig) => {
19414
+ (0, proc_1.killProcessTree)(child.pid, sig);
19284
19415
  try {
19285
- if (child.pid)
19286
- process.kill(-child.pid, sig);
19416
+ child.kill(sig);
19287
19417
  } catch {
19288
- try {
19289
- child.kill(sig);
19290
- } catch {
19291
- }
19292
19418
  }
19293
19419
  };
19294
19420
  const HEAD_CHARS = Math.floor(MAX_OUTPUT_CHARS * 0.25);
@@ -19473,7 +19599,7 @@ ${(0, safeSlice_1.sliceSafeStart)(output, output.length - tailLen)}`;
19473
19599
  let settled = false;
19474
19600
  let child;
19475
19601
  try {
19476
- child = (0, child_process_1.spawn)(cmd, args, { cwd: opts.cwd, stdio: ["ignore", "pipe", "pipe"] });
19602
+ child = (0, proc_1.spawn)(cmd, args, { cwd: opts.cwd, stdio: ["ignore", "pipe", "pipe"] });
19477
19603
  } catch (e2) {
19478
19604
  resolve19({ stdout: "", stderr: "", status: null, signal: null, error: e2 });
19479
19605
  return;
@@ -19610,7 +19736,7 @@ ${(0, safeSlice_1.sliceSafeStart)(output, output.length - tailLen)}`;
19610
19736
  for (const bin of ripgrepCandidates()) {
19611
19737
  if (path36.isAbsolute(bin) && !fs33.existsSync(bin))
19612
19738
  continue;
19613
- const probe = (0, child_process_1.spawnSync)(bin, ["--version"], { encoding: "utf-8", timeout: 3e3 });
19739
+ const probe = (0, proc_1.spawnSync)(bin, ["--version"], { encoding: "utf-8", timeout: 3e3 });
19614
19740
  if (probe.status === 0) {
19615
19741
  _rgBin = bin;
19616
19742
  _rgAvailable = true;
@@ -20994,7 +21120,7 @@ ${lines.join("\n")}`;
20994
21120
  return { error: "Missing required parameter: path" };
20995
21121
  const token = (0, auth_1.getToken)();
20996
21122
  if (!token)
20997
- return { error: "Not authenticated. Run `nexrall-code login` first." };
21123
+ return { error: "Not authenticated. Run `nex auth` first." };
20998
21124
  let imageUrl;
20999
21125
  let cost;
21000
21126
  let balance;
@@ -21048,7 +21174,7 @@ ${lines.join("\n")}`;
21048
21174
  return { error: "Missing required parameter: query" };
21049
21175
  const token = (0, auth_1.getToken)();
21050
21176
  if (!token)
21051
- return { error: "Not authenticated. Run `nexrall-code login` first." };
21177
+ return { error: "Not authenticated. Run `nex auth` first." };
21052
21178
  let photos;
21053
21179
  try {
21054
21180
  const u = new URL(`${client_2.API_BASE}/api/code/assets/stock`);
@@ -21105,7 +21231,7 @@ ${lines.join("\n")}` };
21105
21231
  return { error: "Missing required parameter: query" };
21106
21232
  const token = (0, auth_1.getToken)();
21107
21233
  if (!token)
21108
- return { error: "Not authenticated. Run `nexrall-code login` first." };
21234
+ return { error: "Not authenticated. Run `nex auth` first." };
21109
21235
  try {
21110
21236
  const r2 = await _httpsPost(`${client_2.API_BASE}/api/code/tools/web_search`, JSON.stringify({ query, ...(0, client_1.billingOverrideFields)() }), { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, 3e4, abortSignal);
21111
21237
  let json = {};
@@ -22643,7 +22769,7 @@ var require_worktree = __commonJS({
22643
22769
  exports.findWorktreeByName = findWorktreeByName2;
22644
22770
  var fs33 = __importStar(__require("fs"));
22645
22771
  var path36 = __importStar(__require("path"));
22646
- var child_process_1 = __require("child_process");
22772
+ var proc_1 = require_proc();
22647
22773
  var crypto6 = __importStar(__require("crypto"));
22648
22774
  var rules_1 = require_rules();
22649
22775
  function prRefFromUrl(spec) {
@@ -22669,7 +22795,7 @@ var require_worktree = __commonJS({
22669
22795
  }
22670
22796
  function resolveFreshStartPoint(gitRoot) {
22671
22797
  const run = (args) => {
22672
- const r2 = (0, child_process_1.spawnSync)("git", args, { cwd: gitRoot, encoding: "utf-8", timeout: 1e4 });
22798
+ const r2 = (0, proc_1.spawnSync)("git", args, { cwd: gitRoot, encoding: "utf-8", timeout: 1e4 });
22673
22799
  return { status: r2.status, stdout: r2.stdout };
22674
22800
  };
22675
22801
  const head = run(["symbolic-ref", "--quiet", "--short", "refs/remotes/origin/HEAD"]);
@@ -22698,7 +22824,7 @@ var require_worktree = __commonJS({
22698
22824
  ]);
22699
22825
  function isGitRepo2(dir) {
22700
22826
  try {
22701
- const r2 = (0, child_process_1.spawnSync)("git", ["rev-parse", "--show-toplevel"], {
22827
+ const r2 = (0, proc_1.spawnSync)("git", ["rev-parse", "--show-toplevel"], {
22702
22828
  cwd: dir,
22703
22829
  encoding: "utf-8",
22704
22830
  timeout: 5e3
@@ -22739,7 +22865,7 @@ var require_worktree = __commonJS({
22739
22865
  if (!cmd)
22740
22866
  return { ran: false, ok: false };
22741
22867
  try {
22742
- const r2 = (0, child_process_1.spawnSync)(cmd, {
22868
+ const r2 = (0, proc_1.spawnSync)(cmd, {
22743
22869
  shell: true,
22744
22870
  cwd: workDir,
22745
22871
  timeout: 6e4,
@@ -22806,7 +22932,7 @@ var require_worktree = __commonJS({
22806
22932
  let startPoint;
22807
22933
  let baseLabel;
22808
22934
  if (prRef) {
22809
- const fetched = (0, child_process_1.spawnSync)("git", ["fetch", "--no-tags", "origin", prRef.refspec], {
22935
+ const fetched = (0, proc_1.spawnSync)("git", ["fetch", "--no-tags", "origin", prRef.refspec], {
22810
22936
  cwd: git.root,
22811
22937
  encoding: "utf-8",
22812
22938
  timeout: 12e4
@@ -22817,7 +22943,7 @@ var require_worktree = __commonJS({
22817
22943
  error: `Could not fetch ${prRef.label} (${prRef.refspec}): ${(fetched.stderr ?? fetched.stdout ?? "").trim() || "unknown error"}`
22818
22944
  };
22819
22945
  }
22820
- const head = (0, child_process_1.spawnSync)("git", ["rev-parse", "FETCH_HEAD"], { cwd: git.root, encoding: "utf-8", timeout: 1e4 });
22946
+ const head = (0, proc_1.spawnSync)("git", ["rev-parse", "FETCH_HEAD"], { cwd: git.root, encoding: "utf-8", timeout: 1e4 });
22821
22947
  const sha = head.status === 0 ? (head.stdout ?? "").trim() : "";
22822
22948
  if (!/^[0-9a-f]{40}$/i.test(sha)) {
22823
22949
  return { ok: false, error: `Fetched ${prRef.label} but could not resolve its commit.` };
@@ -22834,7 +22960,7 @@ var require_worktree = __commonJS({
22834
22960
  baseLabel = startPoint;
22835
22961
  }
22836
22962
  const args = ["worktree", "add", "-b", branch, worktreePath, ...startPoint ? [startPoint] : []];
22837
- const r2 = (0, child_process_1.spawnSync)("git", args, {
22963
+ const r2 = (0, proc_1.spawnSync)("git", args, {
22838
22964
  cwd: git.root,
22839
22965
  encoding: "utf-8",
22840
22966
  timeout: 3e4
@@ -22865,7 +22991,7 @@ var require_worktree = __commonJS({
22865
22991
  function worktreeHasWork2(state) {
22866
22992
  if (state.backend === "git") {
22867
22993
  try {
22868
- const status = (0, child_process_1.spawnSync)("git", ["status", "--porcelain"], {
22994
+ const status = (0, proc_1.spawnSync)("git", ["status", "--porcelain"], {
22869
22995
  cwd: state.worktreePath,
22870
22996
  encoding: "utf-8",
22871
22997
  timeout: 1e4
@@ -22873,7 +22999,7 @@ var require_worktree = __commonJS({
22873
22999
  const meaningfulLines = (status.stdout ?? "").split("\n").filter((line) => line.trim().length > 0 && !line.includes(METADATA_FILENAME));
22874
23000
  if (meaningfulLines.length > 0)
22875
23001
  return true;
22876
- const unpushed = (0, child_process_1.spawnSync)("git", ["log", "@{u}..HEAD", "--oneline"], {
23002
+ const unpushed = (0, proc_1.spawnSync)("git", ["log", "@{u}..HEAD", "--oneline"], {
22877
23003
  cwd: state.worktreePath,
22878
23004
  encoding: "utf-8",
22879
23005
  timeout: 1e4
@@ -22911,7 +23037,7 @@ var require_worktree = __commonJS({
22911
23037
  fs33.unlinkSync(metadataPath(state.worktreePath));
22912
23038
  } catch {
22913
23039
  }
22914
- const r2 = (0, child_process_1.spawnSync)("git", ["worktree", "remove", state.worktreePath, ...opts.force ? ["--force"] : []], {
23040
+ const r2 = (0, proc_1.spawnSync)("git", ["worktree", "remove", state.worktreePath, ...opts.force ? ["--force"] : []], {
22915
23041
  cwd: state.mainCheckout,
22916
23042
  encoding: "utf-8",
22917
23043
  timeout: 3e4
@@ -22923,7 +23049,7 @@ var require_worktree = __commonJS({
22923
23049
  };
22924
23050
  }
22925
23051
  if (state.branch) {
22926
- (0, child_process_1.spawnSync)("git", ["branch", "-D", state.branch], { cwd: state.mainCheckout, encoding: "utf-8", timeout: 1e4 });
23052
+ (0, proc_1.spawnSync)("git", ["branch", "-D", state.branch], { cwd: state.mainCheckout, encoding: "utf-8", timeout: 1e4 });
22927
23053
  }
22928
23054
  return { ok: true };
22929
23055
  }
@@ -23685,7 +23811,7 @@ var require_hooks = __commonJS({
23685
23811
  var data_1 = require_data();
23686
23812
  var fs33 = __importStar(__require("fs"));
23687
23813
  var path36 = __importStar(__require("path"));
23688
- var child_process_1 = __require("child_process");
23814
+ var proc_1 = require_proc();
23689
23815
  function withAgentHooks(base, agent) {
23690
23816
  if (!agent)
23691
23817
  return base;
@@ -24019,7 +24145,7 @@ ${d.text}
24019
24145
  };
24020
24146
  let child;
24021
24147
  try {
24022
- child = (0, child_process_1.spawn)(command, {
24148
+ child = (0, proc_1.spawn)(command, {
24023
24149
  shell: true,
24024
24150
  cwd: opts.cwd,
24025
24151
  env: opts.env ?? process.env,
@@ -28722,6 +28848,50 @@ ${s2.prompt}`;
28722
28848
  var require_client2 = __commonJS({
28723
28849
  "../core/dist/mcp/client.js"(exports) {
28724
28850
  "use strict";
28851
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m2, k, k2) {
28852
+ if (k2 === void 0)
28853
+ k2 = k;
28854
+ var desc = Object.getOwnPropertyDescriptor(m2, k);
28855
+ if (!desc || ("get" in desc ? !m2.__esModule : desc.writable || desc.configurable)) {
28856
+ desc = { enumerable: true, get: function() {
28857
+ return m2[k];
28858
+ } };
28859
+ }
28860
+ Object.defineProperty(o, k2, desc);
28861
+ } : function(o, m2, k, k2) {
28862
+ if (k2 === void 0)
28863
+ k2 = k;
28864
+ o[k2] = m2[k];
28865
+ });
28866
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
28867
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28868
+ } : function(o, v) {
28869
+ o["default"] = v;
28870
+ });
28871
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
28872
+ var ownKeys = function(o) {
28873
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
28874
+ var ar = [];
28875
+ for (var k in o2)
28876
+ if (Object.prototype.hasOwnProperty.call(o2, k))
28877
+ ar[ar.length] = k;
28878
+ return ar;
28879
+ };
28880
+ return ownKeys(o);
28881
+ };
28882
+ return function(mod) {
28883
+ if (mod && mod.__esModule)
28884
+ return mod;
28885
+ var result = {};
28886
+ if (mod != null) {
28887
+ for (var k = ownKeys(mod), i2 = 0; i2 < k.length; i2++)
28888
+ if (k[i2] !== "default")
28889
+ __createBinding(result, mod, k[i2]);
28890
+ }
28891
+ __setModuleDefault(result, mod);
28892
+ return result;
28893
+ };
28894
+ }();
28725
28895
  Object.defineProperty(exports, "__esModule", { value: true });
28726
28896
  exports.McpClient = exports.MCP_PROTOCOL_VERSION = exports.MCP_PROTOCOL_VERSIONS = exports.MCP_ELICITATION_CAPABILITY = exports.MAX_RESULT_SIZE_CHARS = void 0;
28727
28897
  exports.toolResultSizeCap = toolResultSizeCap;
@@ -28730,7 +28900,8 @@ var require_client2 = __commonJS({
28730
28900
  exports.elicitationCapability = elicitationCapability;
28731
28901
  exports.normalizeElicitationRequest = normalizeElicitationRequest;
28732
28902
  exports.serverRequestReply = serverRequestReply;
28733
- var child_process_1 = __require("child_process");
28903
+ var path36 = __importStar(__require("path"));
28904
+ var proc_1 = require_proc();
28734
28905
  exports.MAX_RESULT_SIZE_CHARS = 5e5;
28735
28906
  function toolResultSizeCap(tool) {
28736
28907
  const raw = (tool._meta ?? {})["anthropic/maxResultSizeChars"];
@@ -28843,10 +29014,11 @@ var require_client2 = __commonJS({
28843
29014
  if (!this.config.command)
28844
29015
  throw new Error(`MCP server "${this.name}" has no command (stdio transport requires one).`);
28845
29016
  const env3 = { ...process.env, ...this.config.env ?? {} };
28846
- this._proc = (0, child_process_1.spawn)(this.config.command, this.config.args ?? [], {
29017
+ const needsShell = process.platform === "win32" && /^(npx|npm|pnpm|yarn|bunx)(\.cmd)?$/i.test(path36.basename(this.config.command));
29018
+ this._proc = (0, proc_1.spawn)(this.config.command, this.config.args ?? [], {
28847
29019
  env: env3,
28848
29020
  stdio: ["pipe", "pipe", "pipe"],
28849
- shell: false
29021
+ shell: needsShell
28850
29022
  });
28851
29023
  this._proc.stdout.on("data", (chunk) => {
28852
29024
  this._buf += chunk.toString("utf-8");
@@ -30522,7 +30694,7 @@ var require_manager2 = __commonJS({
30522
30694
  var os25 = __importStar(__require("os"));
30523
30695
  var path36 = __importStar(__require("path"));
30524
30696
  var crypto6 = __importStar(__require("crypto"));
30525
- var child_process_1 = __require("child_process");
30697
+ var proc_1 = require_proc();
30526
30698
  var MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024;
30527
30699
  var MAX_PERSISTED_TURNS = 50;
30528
30700
  var MUTATING_TOOLS = /* @__PURE__ */ new Set([
@@ -30663,7 +30835,7 @@ var require_manager2 = __commonJS({
30663
30835
  }
30664
30836
  tryGitStashCreate() {
30665
30837
  try {
30666
- const r2 = (0, child_process_1.spawnSync)("git", ["stash", "create", "nexrall-checkpoint"], {
30838
+ const r2 = (0, proc_1.spawnSync)("git", ["stash", "create", "nexrall-checkpoint"], {
30667
30839
  cwd: this.workDir,
30668
30840
  encoding: "utf-8",
30669
30841
  timeout: 1e4
@@ -31524,7 +31696,7 @@ var require_installer = __commonJS({
31524
31696
  var fs33 = __importStar(__require("fs"));
31525
31697
  var path36 = __importStar(__require("path"));
31526
31698
  var os25 = __importStar(__require("os"));
31527
- var child_process_1 = __require("child_process");
31699
+ var proc_1 = require_proc();
31528
31700
  var client_1 = require_client();
31529
31701
  var index_1 = require_plugins();
31530
31702
  var data_1 = require_data();
@@ -31882,7 +32054,7 @@ var require_installer = __commonJS({
31882
32054
  }
31883
32055
  function extractTarball(tarFile, destDir) {
31884
32056
  fs33.mkdirSync(destDir, { recursive: true });
31885
- (0, child_process_1.execFileSync)("tar", ["-xzf", tarFile, "-C", destDir], { stdio: "pipe" });
32057
+ (0, proc_1.execFileSync)("tar", ["-xzf", tarFile, "-C", destDir], { stdio: "pipe" });
31886
32058
  const entries = fs33.readdirSync(destDir).filter((e2) => {
31887
32059
  try {
31888
32060
  return fs33.statSync(path36.join(destDir, e2)).isDirectory();
@@ -32939,7 +33111,7 @@ var require_monitor = __commonJS({
32939
33111
  exports.stopMonitor = stopMonitor;
32940
33112
  exports.stopAllMonitors = stopAllMonitors;
32941
33113
  exports.executeMonitorTool = executeMonitorTool2;
32942
- var child_process_1 = __require("child_process");
33114
+ var proc_1 = require_proc();
32943
33115
  exports.MONITOR_TOOL_NAME = "monitor";
32944
33116
  exports.DEFAULT_TIMEOUT_MS = 5 * 6e4;
32945
33117
  exports.MAX_TIMEOUT_MS = 30 * 6e4;
@@ -32967,10 +33139,8 @@ var require_monitor = __commonJS({
32967
33139
  }
32968
33140
  function killTree(m2) {
32969
33141
  try {
32970
- if (m2.child.pid)
32971
- process.kill(-m2.child.pid, "SIGTERM");
32972
- else
32973
- m2.child.kill("SIGTERM");
33142
+ (0, proc_1.killProcessTree)(m2.child.pid, "SIGTERM");
33143
+ m2.child.kill("SIGTERM");
32974
33144
  } catch {
32975
33145
  }
32976
33146
  if (m2.killTimer)
@@ -32978,8 +33148,7 @@ var require_monitor = __commonJS({
32978
33148
  m2.killTimer = setTimeout(() => {
32979
33149
  m2.killTimer = null;
32980
33150
  try {
32981
- if (m2.child.pid)
32982
- process.kill(-m2.child.pid, "SIGKILL");
33151
+ (0, proc_1.killProcessTree)(m2.child.pid, "SIGKILL");
32983
33152
  } catch {
32984
33153
  }
32985
33154
  }, m2.timing.killGraceMs);
@@ -33100,7 +33269,7 @@ var require_monitor = __commonJS({
33100
33269
  const now = opts.now ?? Date.now;
33101
33270
  const id = `mon${++_seq}`;
33102
33271
  const label = opts.label && String(opts.label).trim().slice(0, 60) || command.slice(0, 60);
33103
- const spawnFn = opts.spawnFn ?? child_process_1.spawn;
33272
+ const spawnFn = opts.spawnFn ?? proc_1.spawn;
33104
33273
  let child;
33105
33274
  try {
33106
33275
  child = spawnFn(command, {
@@ -33110,7 +33279,7 @@ var require_monitor = __commonJS({
33110
33279
  // Own process group so the deadline kill reaches `sh -c "tail -f | grep"`
33111
33280
  // trees; stdin closed so a watcher that reads blocks on nothing and gets
33112
33281
  // EOF instead of hanging the watch until its deadline.
33113
- detached: true,
33282
+ detached: proc_1.DETACH_GROUP,
33114
33283
  stdio: ["ignore", "pipe", "pipe"]
33115
33284
  });
33116
33285
  } catch (e2) {
@@ -33206,8 +33375,7 @@ var require_monitor = __commonJS({
33206
33375
  if (silent) {
33207
33376
  const m2 = _monitors.get(id);
33208
33377
  try {
33209
- if (m2.child.pid)
33210
- process.kill(-m2.child.pid, "SIGKILL");
33378
+ (0, proc_1.killProcessTree)(m2.child.pid, "SIGKILL");
33211
33379
  } catch {
33212
33380
  }
33213
33381
  finalize(m2);
@@ -33964,12 +34132,12 @@ var require_collect = __commonJS({
33964
34132
  exports.gitDiffRaw = gitDiffRaw2;
33965
34133
  exports.collectChangedFiles = collectChangedFiles2;
33966
34134
  exports.gitBranch = gitBranch2;
33967
- var child_process_1 = __require("child_process");
34135
+ var proc_1 = require_proc();
33968
34136
  var fs33 = __importStar(__require("fs"));
33969
34137
  var path36 = __importStar(__require("path"));
33970
34138
  var diffView_1 = require_diffView();
33971
34139
  function gitDiffRaw2(cwd2) {
33972
- const run = (args) => (0, child_process_1.execFileSync)("git", args, {
34140
+ const run = (args) => (0, proc_1.execFileSync)("git", args, {
33973
34141
  cwd: cwd2,
33974
34142
  encoding: "utf8",
33975
34143
  stdio: ["ignore", "pipe", "ignore"],
@@ -47693,7 +47861,7 @@ var require_mergeAssistant = __commonJS({
47693
47861
  exports.parseMergeTree = parseMergeTree2;
47694
47862
  exports.checkBranchMerges = checkBranchMerges2;
47695
47863
  exports.formatMergePanel = formatMergePanel2;
47696
- var child_process_1 = __require("child_process");
47864
+ var proc_1 = require_proc();
47697
47865
  var globalSearch_1 = require_globalSearch();
47698
47866
  var collect_1 = require_collect();
47699
47867
  exports.MAX_NODE_FILES = 40;
@@ -47709,7 +47877,7 @@ var require_mergeAssistant = __commonJS({
47709
47877
  }
47710
47878
  var gitRunnerForMerge2 = (cwd2, args) => {
47711
47879
  try {
47712
- const stdout = (0, child_process_1.execFileSync)("git", args, {
47880
+ const stdout = (0, proc_1.execFileSync)("git", args, {
47713
47881
  cwd: cwd2,
47714
47882
  encoding: "utf-8",
47715
47883
  stdio: ["ignore", "pipe", "pipe"],
@@ -78310,7 +78478,7 @@ import * as fs32 from "fs";
78310
78478
  import { createRequire as createRequire2 } from "module";
78311
78479
 
78312
78480
  // src/commands/auth.ts
78313
- var import_code_core = __toESM(require_dist2(), 1);
78481
+ var import_code_core2 = __toESM(require_dist2(), 1);
78314
78482
  import * as readline from "readline";
78315
78483
 
78316
78484
  // ../../node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
@@ -79626,7 +79794,452 @@ function formatUsage(outputTokens) {
79626
79794
  return paint.dim(`\u2193 ${tok} tokens`);
79627
79795
  }
79628
79796
 
79797
+ // src/mcp/oauth.ts
79798
+ var import_proc = __toESM(require_proc(), 1);
79799
+ var import_code_core = __toESM(require_dist2(), 1);
79800
+ import * as fs2 from "fs";
79801
+ import * as os2 from "os";
79802
+ import * as path from "path";
79803
+ import * as http3 from "http";
79804
+ import * as crypto from "crypto";
79805
+ var CALLBACK_TIMEOUT_MS = 5 * 60 * 1e3;
79806
+ function tokensFile(env3 = process.env) {
79807
+ return env3.NEXRALL_MCP_AUTH_FILE || path.join(os2.homedir(), ".nexrall", "mcp-auth.json");
79808
+ }
79809
+ function readStore(file) {
79810
+ try {
79811
+ const parsed = JSON.parse(fs2.readFileSync(file, "utf-8"));
79812
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
79813
+ return {};
79814
+ const out = {};
79815
+ for (const [k, v] of Object.entries(parsed)) {
79816
+ const b = v;
79817
+ if (b && typeof b.access_token === "string" && typeof b.token_endpoint === "string")
79818
+ out[k] = b;
79819
+ }
79820
+ return out;
79821
+ } catch {
79822
+ return {};
79823
+ }
79824
+ }
79825
+ function writeStore(file, store) {
79826
+ fs2.mkdirSync(path.dirname(file), { recursive: true });
79827
+ fs2.writeFileSync(file, JSON.stringify(store, null, 2), { mode: 384 });
79828
+ try {
79829
+ fs2.chmodSync(file, 384);
79830
+ } catch {
79831
+ }
79832
+ }
79833
+ function loadToken(server, file = tokensFile()) {
79834
+ return readStore(file)[server] ?? null;
79835
+ }
79836
+ function saveToken(server, bundle, file = tokensFile()) {
79837
+ const store = readStore(file);
79838
+ store[server] = bundle;
79839
+ writeStore(file, store);
79840
+ }
79841
+ function clearToken(server, file = tokensFile()) {
79842
+ const store = readStore(file);
79843
+ if (!(server in store))
79844
+ return false;
79845
+ delete store[server];
79846
+ writeStore(file, store);
79847
+ return true;
79848
+ }
79849
+ function defaultFetch() {
79850
+ const f3 = globalThis.fetch;
79851
+ if (typeof f3 !== "function")
79852
+ throw new Error("global fetch unavailable \u2014 Node 18+ is required for MCP OAuth");
79853
+ return f3;
79854
+ }
79855
+ async function getValidAccessToken(server, opts = {}) {
79856
+ const file = opts.file ?? tokensFile();
79857
+ const bundle = loadToken(server, file);
79858
+ if (!bundle)
79859
+ return null;
79860
+ const fresh = !bundle.expires_at || bundle.expires_at - Date.now() > 6e4;
79861
+ if (fresh || !bundle.refresh_token)
79862
+ return bundle.access_token;
79863
+ try {
79864
+ const refreshed = await refreshAccessToken(bundle, opts.fetchImpl ?? defaultFetch());
79865
+ saveToken(server, refreshed, file);
79866
+ return refreshed.access_token;
79867
+ } catch {
79868
+ return bundle.access_token;
79869
+ }
79870
+ }
79871
+ function parseResourceMetadataUrl(wwwAuthenticate) {
79872
+ const m2 = /resource_metadata\s*=\s*"([^"]+)"/i.exec(wwwAuthenticate || "");
79873
+ return m2 ? m2[1] : null;
79874
+ }
79875
+ function protectedResourceCandidates(serverUrl) {
79876
+ const u = new URL(serverUrl);
79877
+ const base = u.origin;
79878
+ const p = u.pathname.replace(/\/$/, "");
79879
+ return [
79880
+ ...p ? [`${base}/.well-known/oauth-protected-resource${p}`] : [],
79881
+ `${base}/.well-known/oauth-protected-resource`
79882
+ ];
79883
+ }
79884
+ function authServerCandidates(authServer) {
79885
+ const u = new URL(authServer);
79886
+ const base = u.origin;
79887
+ const p = u.pathname.replace(/\/$/, "");
79888
+ const root = authServer.replace(/\/$/, "");
79889
+ return [
79890
+ `${base}/.well-known/oauth-authorization-server${p}`,
79891
+ `${base}/.well-known/openid-configuration${p}`,
79892
+ `${root}/.well-known/oauth-authorization-server`,
79893
+ `${root}/.well-known/openid-configuration`
79894
+ ];
79895
+ }
79896
+ function buildAuthorizeUrl(meta, p) {
79897
+ const url = new URL(meta.authorization_endpoint);
79898
+ url.searchParams.set("response_type", "code");
79899
+ url.searchParams.set("client_id", p.clientId);
79900
+ url.searchParams.set("redirect_uri", p.redirectUri);
79901
+ url.searchParams.set("state", p.state);
79902
+ url.searchParams.set("code_challenge", p.codeChallenge);
79903
+ url.searchParams.set("code_challenge_method", "S256");
79904
+ url.searchParams.set("resource", meta.resource);
79905
+ if (meta.scope)
79906
+ url.searchParams.set("scope", meta.scope);
79907
+ return url.toString();
79908
+ }
79909
+ function toBundle(data, p) {
79910
+ const accessToken = data.access_token;
79911
+ if (!accessToken)
79912
+ throw new Error("Token response had no access_token");
79913
+ const expiresIn = typeof data.expires_in === "number" ? data.expires_in : void 0;
79914
+ return {
79915
+ access_token: accessToken,
79916
+ refresh_token: data.refresh_token ?? p.prevRefresh,
79917
+ expires_at: expiresIn ? Date.now() + expiresIn * 1e3 : void 0,
79918
+ token_endpoint: p.tokenEndpoint,
79919
+ client_id: p.clientId,
79920
+ client_secret: p.clientSecret,
79921
+ resource: p.resource,
79922
+ scope: data.scope ?? p.scope
79923
+ };
79924
+ }
79925
+ async function fetchJsonSafe(f3, url) {
79926
+ try {
79927
+ const resp = await f3(url, { headers: { Accept: "application/json" } });
79928
+ if (!resp.ok)
79929
+ return null;
79930
+ return await resp.json();
79931
+ } catch {
79932
+ return null;
79933
+ }
79934
+ }
79935
+ async function discover(serverUrl, wwwAuthenticate, f3 = defaultFetch()) {
79936
+ const origin = new URL(serverUrl).origin;
79937
+ let authServer = null;
79938
+ let resource = serverUrl;
79939
+ let scope;
79940
+ const prmCandidates = [parseResourceMetadataUrl(wwwAuthenticate), ...protectedResourceCandidates(serverUrl)].filter(
79941
+ (u) => Boolean(u)
79942
+ );
79943
+ let prm = null;
79944
+ for (const url of new Set(prmCandidates)) {
79945
+ prm = await fetchJsonSafe(f3, url);
79946
+ if (prm)
79947
+ break;
79948
+ }
79949
+ if (prm) {
79950
+ const servers = prm.authorization_servers;
79951
+ if (Array.isArray(servers) && servers.length)
79952
+ authServer = servers[0];
79953
+ if (typeof prm.resource === "string")
79954
+ resource = prm.resource;
79955
+ const scopes = prm.scopes_supported;
79956
+ if (Array.isArray(scopes) && scopes.length)
79957
+ scope = scopes.join(" ");
79958
+ }
79959
+ if (!authServer)
79960
+ authServer = origin;
79961
+ let asm = null;
79962
+ for (const url of authServerCandidates(authServer)) {
79963
+ asm = await fetchJsonSafe(f3, url);
79964
+ if (asm && asm.authorization_endpoint && asm.token_endpoint)
79965
+ break;
79966
+ asm = null;
79967
+ }
79968
+ if (!asm)
79969
+ throw new Error(`No OAuth metadata found for authorization server ${authServer}`);
79970
+ return {
79971
+ authorization_endpoint: asm.authorization_endpoint,
79972
+ token_endpoint: asm.token_endpoint,
79973
+ registration_endpoint: asm.registration_endpoint,
79974
+ resource,
79975
+ scope
79976
+ };
79977
+ }
79978
+ async function registerClient(meta, redirectUri, f3) {
79979
+ if (!meta.registration_endpoint) {
79980
+ throw new Error(
79981
+ 'Authorization server does not support dynamic client registration; a client_id must be configured manually \u2014 create an OAuth client for this server, then re-run `nex mcp login <server> --client-id <id> [--client-secret <secret>]` (or set "clientId" / "clientSecret" in its mcp.json entry).'
79982
+ );
79983
+ }
79984
+ const resp = await f3(meta.registration_endpoint, {
79985
+ method: "POST",
79986
+ headers: { "Content-Type": "application/json", Accept: "application/json" },
79987
+ body: JSON.stringify({
79988
+ client_name: "Nexrall Code CLI",
79989
+ redirect_uris: [redirectUri],
79990
+ grant_types: ["authorization_code", "refresh_token"],
79991
+ response_types: ["code"],
79992
+ token_endpoint_auth_method: "none",
79993
+ scope: meta.scope
79994
+ })
79995
+ });
79996
+ if (!resp.ok)
79997
+ throw new Error(`Client registration failed (HTTP ${resp.status})`);
79998
+ const data = await resp.json();
79999
+ if (!data.client_id)
80000
+ throw new Error("Client registration returned no client_id");
80001
+ return data.client_id;
80002
+ }
80003
+ async function postToken(tokenEndpoint, body, f3) {
80004
+ const resp = await f3(tokenEndpoint, {
80005
+ method: "POST",
80006
+ headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json" },
80007
+ body: body.toString()
80008
+ });
80009
+ if (!resp.ok) {
80010
+ const txt = await resp.text().catch(() => "");
80011
+ throw new Error(`Token endpoint error (HTTP ${resp.status})${txt ? `: ${txt.slice(0, 200)}` : ""}`);
80012
+ }
80013
+ return await resp.json();
80014
+ }
80015
+ async function exchangeCode(meta, clientId, clientSecret, code, verifier, redirectUri, f3) {
80016
+ const body = new URLSearchParams({
80017
+ grant_type: "authorization_code",
80018
+ code,
80019
+ redirect_uri: redirectUri,
80020
+ client_id: clientId,
80021
+ code_verifier: verifier,
80022
+ resource: meta.resource
80023
+ });
80024
+ if (clientSecret)
80025
+ body.set("client_secret", clientSecret);
80026
+ const data = await postToken(meta.token_endpoint, body, f3);
80027
+ return toBundle(data, {
80028
+ tokenEndpoint: meta.token_endpoint,
80029
+ clientId,
80030
+ clientSecret,
80031
+ resource: meta.resource,
80032
+ scope: meta.scope
80033
+ });
80034
+ }
80035
+ async function refreshAccessToken(bundle, f3) {
80036
+ const body = new URLSearchParams({
80037
+ grant_type: "refresh_token",
80038
+ refresh_token: bundle.refresh_token,
80039
+ client_id: bundle.client_id,
80040
+ resource: bundle.resource
80041
+ });
80042
+ if (bundle.client_secret)
80043
+ body.set("client_secret", bundle.client_secret);
80044
+ const data = await postToken(bundle.token_endpoint, body, f3);
80045
+ return toBundle(data, {
80046
+ tokenEndpoint: bundle.token_endpoint,
80047
+ clientId: bundle.client_id,
80048
+ clientSecret: bundle.client_secret,
80049
+ resource: bundle.resource,
80050
+ scope: bundle.scope,
80051
+ prevRefresh: bundle.refresh_token
80052
+ });
80053
+ }
80054
+ function startLoopback() {
80055
+ return new Promise((resolve19, reject) => {
80056
+ let resolveCode;
80057
+ let rejectCode;
80058
+ const codePromise = new Promise((res, rej) => {
80059
+ resolveCode = res;
80060
+ rejectCode = rej;
80061
+ });
80062
+ codePromise.catch(() => void 0);
80063
+ const server = http3.createServer((req, res) => {
80064
+ const url = new URL(req.url ?? "/", "http://127.0.0.1");
80065
+ if (url.pathname !== "/callback") {
80066
+ res.writeHead(404);
80067
+ res.end();
80068
+ return;
80069
+ }
80070
+ const code = url.searchParams.get("code");
80071
+ const state = url.searchParams.get("state");
80072
+ const error = url.searchParams.get("error");
80073
+ res.writeHead(200, { "Content-Type": "text/html", Connection: "close" });
80074
+ res.end(
80075
+ `<!doctype html><html><body style="font-family:system-ui;text-align:center;padding:40px"><h2>${error || !code ? "Authentication failed" : "Authentication complete"}</h2><p>You can close this tab and return to the terminal.</p></body></html>`
80076
+ );
80077
+ if (error) {
80078
+ rejectCode(new Error(`Authorization denied: ${error}`));
80079
+ return;
80080
+ }
80081
+ if (!code) {
80082
+ rejectCode(new Error("No authorization code in redirect"));
80083
+ return;
80084
+ }
80085
+ resolveCode({ code, state });
80086
+ });
80087
+ server.on("error", reject);
80088
+ server.listen(0, "127.0.0.1", () => {
80089
+ const port = server.address().port;
80090
+ resolve19({
80091
+ port,
80092
+ waitForCode(expectedState) {
80093
+ const timeout = setTimeout(
80094
+ () => rejectCode(new Error("Timed out waiting for authorization")),
80095
+ CALLBACK_TIMEOUT_MS
80096
+ );
80097
+ return codePromise.then(
80098
+ ({ code, state }) => {
80099
+ clearTimeout(timeout);
80100
+ if (state !== expectedState)
80101
+ throw new Error("OAuth state mismatch \u2014 possible CSRF, aborting");
80102
+ return code;
80103
+ },
80104
+ // A denial must clear the timer too: otherwise `nex mcp login` reports the
80105
+ // failure but the process sits on a 5-minute keep-alive before exiting.
80106
+ (err) => {
80107
+ clearTimeout(timeout);
80108
+ throw err;
80109
+ }
80110
+ );
80111
+ },
80112
+ close() {
80113
+ try {
80114
+ server.closeAllConnections?.();
80115
+ } catch {
80116
+ }
80117
+ try {
80118
+ server.close();
80119
+ } catch {
80120
+ }
80121
+ }
80122
+ });
80123
+ });
80124
+ });
80125
+ }
80126
+ function b64url(buf) {
80127
+ return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
80128
+ }
80129
+ function openInBrowser(url) {
80130
+ const win = process.platform === "win32";
80131
+ const cmd = process.platform === "darwin" ? "open" : win ? "rundll32" : "xdg-open";
80132
+ const args = win ? ["url.dll,FileProtocolHandler", url] : [url];
80133
+ try {
80134
+ const child = (0, import_proc.spawn)(cmd, args, { stdio: "ignore", detached: !win });
80135
+ child.on("error", () => void 0);
80136
+ child.unref();
80137
+ } catch {
80138
+ }
80139
+ }
80140
+ async function probeAuthChallenge(serverUrl, f3 = defaultFetch()) {
80141
+ const steps = [
80142
+ {
80143
+ method: "initialize",
80144
+ params: {
80145
+ protocolVersion: import_code_core.MCP_PROTOCOL_VERSION,
80146
+ capabilities: {},
80147
+ clientInfo: { name: "nexrall-code", version: "1.0" }
80148
+ }
80149
+ },
80150
+ { method: "tools/list", params: {} }
80151
+ ];
80152
+ for (const { method, params } of steps) {
80153
+ try {
80154
+ const resp = await f3(serverUrl, {
80155
+ method: "POST",
80156
+ headers: { "Content-Type": "application/json", Accept: "application/json, text/event-stream" },
80157
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params })
80158
+ });
80159
+ const challenge = resp.headers?.get("www-authenticate") ?? "";
80160
+ if (challenge)
80161
+ return challenge;
80162
+ } catch {
80163
+ return "";
80164
+ }
80165
+ }
80166
+ return "";
80167
+ }
80168
+ async function authorizeServer(o) {
80169
+ const f3 = o.fetchImpl ?? defaultFetch();
80170
+ const challenge = o.wwwAuthenticate ?? await probeAuthChallenge(o.serverUrl, f3);
80171
+ const meta = await discover(o.serverUrl, challenge, f3);
80172
+ const scope = [meta.scope, (0, import_code_core.parseOAuthChallenge)(challenge).scope, o.extraScope].map((s2) => s2?.trim()).filter((s2) => Boolean(s2)).join(" ").split(/\s+/).filter((s2, i2, a) => Boolean(s2) && a.indexOf(s2) === i2).join(" ");
80173
+ meta.scope = scope || void 0;
80174
+ const loopback = await startLoopback();
80175
+ const redirectUri = `http://127.0.0.1:${loopback.port}/callback`;
80176
+ try {
80177
+ const creds = o.credentials ?? {};
80178
+ let clientId;
80179
+ if (creds.clientId) {
80180
+ clientId = creds.clientId;
80181
+ o.onStep?.("Using the OAuth client configured for this server\u2026");
80182
+ } else {
80183
+ o.onStep?.(`Registering with ${new URL(meta.token_endpoint).origin}\u2026`);
80184
+ clientId = await registerClient(meta, redirectUri, f3);
80185
+ }
80186
+ const verifier = b64url(crypto.randomBytes(32));
80187
+ const challengeB64 = b64url(crypto.createHash("sha256").update(verifier).digest());
80188
+ const state = b64url(crypto.randomBytes(16));
80189
+ const authUrl = buildAuthorizeUrl(meta, { clientId, redirectUri, codeChallenge: challengeB64, state });
80190
+ o.onStep?.("Opening your browser to authorize\u2026");
80191
+ await o.openUrl(authUrl);
80192
+ const code = await loopback.waitForCode(state);
80193
+ const bundle = await exchangeCode(meta, clientId, creds.clientSecret, code, verifier, redirectUri, f3);
80194
+ saveToken(o.server, bundle, o.file ?? tokensFile());
80195
+ } finally {
80196
+ loopback.close();
80197
+ }
80198
+ }
80199
+ var isRemote = (cfg) => cfg.type === "http" || cfg.type === "sse" || !cfg.command && !!cfg.url;
80200
+ async function injectMcpTokens(config, opts = {}) {
80201
+ const file = opts.file ?? tokensFile();
80202
+ const injected = [];
80203
+ for (const [name, cfg] of Object.entries(config.mcpServers ?? {})) {
80204
+ if (!isRemote(cfg))
80205
+ continue;
80206
+ const hasAuth = cfg.headers && Object.keys(cfg.headers).some((h2) => h2.toLowerCase() === "authorization");
80207
+ if (hasAuth)
80208
+ continue;
80209
+ let token;
80210
+ try {
80211
+ token = await getValidAccessToken(name, { file, fetchImpl: opts.fetchImpl });
80212
+ } catch {
80213
+ token = null;
80214
+ }
80215
+ if (!token)
80216
+ continue;
80217
+ cfg.headers = { ...cfg.headers ?? {}, Authorization: `Bearer ${token}` };
80218
+ injected.push(name);
80219
+ }
80220
+ return injected;
80221
+ }
80222
+
79629
80223
  // src/commands/auth.ts
80224
+ var AUTH_APP_URL = "https://app.nexrall.com";
80225
+ function browserAuthUrl() {
80226
+ return `${AUTH_APP_URL}/auth/vscode?cli=1`;
80227
+ }
80228
+ function normalizeAuthCode(raw) {
80229
+ const cleaned = raw.trim().replace(/^[`'"“”‘’]+|[`'"“”‘’]+$/g, "").trim();
80230
+ const fromUrl = /[?&]code=([^&\s]+)/.exec(cleaned);
80231
+ return fromUrl ? decodeURIComponent(fromUrl[1]) : cleaned.replace(/\s+/g, "");
80232
+ }
80233
+ function parseAuthMethod(input) {
80234
+ const v = input.trim().toLowerCase();
80235
+ if (v === "" || v === "1" || v === "b" || v === "browser")
80236
+ return "browser";
80237
+ if (v === "2" || v === "p" || v === "e" || v === "email" || v === "password")
80238
+ return "password";
80239
+ if (v === "3" || v === "t" || v === "token")
80240
+ return "token";
80241
+ return null;
80242
+ }
79630
80243
  function prompt(question, hidden = false) {
79631
80244
  return new Promise((resolve19) => {
79632
80245
  const rl = readline.createInterface({
@@ -79653,13 +80266,14 @@ function prompt(question, hidden = false) {
79653
80266
  process.exit(0);
79654
80267
  }
79655
80268
  resolve19(value);
79656
- } else if (char === "\x7F" || char === "\b") {
79657
- if (value.length > 0) {
80269
+ return;
80270
+ }
80271
+ if (char === "\x7F" || char === "\b") {
80272
+ if (value.length > 0)
79658
80273
  value = value.slice(0, -1);
79659
- }
79660
- } else {
79661
- value += char;
80274
+ return;
79662
80275
  }
80276
+ value += char;
79663
80277
  };
79664
80278
  stdin.on("data", onData);
79665
80279
  } else {
@@ -79670,12 +80284,12 @@ function prompt(question, hidden = false) {
79670
80284
  }
79671
80285
  });
79672
80286
  }
79673
- async function authCommand() {
80287
+ async function authCommand(opts = {}) {
79674
80288
  console.log();
79675
80289
  console.log(paint.boldBlue(" Nexrall Code \u2014 Login"));
79676
80290
  console.log(paint.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
79677
80291
  console.log();
79678
- if ((0, import_code_core.isAuthenticated)()) {
80292
+ if ((0, import_code_core2.isAuthenticated)() && !opts.token && !opts.code) {
79679
80293
  const overwrite = await prompt(paint.yellow(" Already logged in. Login again? ") + paint.dim("[y/n] > "));
79680
80294
  if (overwrite !== "y" && overwrite !== "yes") {
79681
80295
  console.log(paint.dim(" Cancelled."));
@@ -79683,21 +80297,90 @@ async function authCommand() {
79683
80297
  }
79684
80298
  console.log();
79685
80299
  }
80300
+ if (opts.token)
80301
+ return loginWithToken(opts.token);
80302
+ if (opts.browser || opts.code)
80303
+ return loginWithBrowser(opts.code);
80304
+ if (opts.password)
80305
+ return loginWithPassword();
80306
+ if (!process.stdin.isTTY)
80307
+ return loginWithPassword();
80308
+ const method = await chooseMethod();
80309
+ if (method === null) {
80310
+ console.log(paint.dim(" Cancelled."));
80311
+ return;
80312
+ }
80313
+ if (method === "browser")
80314
+ return loginWithBrowser();
80315
+ if (method === "token")
80316
+ return loginWithTokenPrompt();
80317
+ return loginWithPassword();
80318
+ }
80319
+ async function chooseMethod() {
80320
+ console.log(" How do you want to sign in?");
80321
+ console.log();
80322
+ console.log(
80323
+ ` ${paint.bold("1.")} Browser ${paint.dim("Google, Apple, SSO or email + password \u2014 recommended")}`
80324
+ );
80325
+ console.log(` ${paint.bold("2.")} Email + password ${paint.dim("typed here in the terminal")}`);
80326
+ console.log(` ${paint.bold("3.")} Token ${paint.dim("CI / headless \u2014 paste a token")}`);
80327
+ console.log();
80328
+ for (; ; ) {
80329
+ const answer = await prompt(paint.bold(" Choose ") + paint.dim("[1] > "));
80330
+ const method = parseAuthMethod(answer);
80331
+ if (method)
80332
+ return method;
80333
+ console.log(paint.yellow(" Pick 1, 2 or 3."));
80334
+ }
80335
+ }
80336
+ async function loginWithBrowser(codeArg) {
80337
+ let code = codeArg ? normalizeAuthCode(codeArg) : "";
80338
+ if (!code) {
80339
+ const url = browserAuthUrl();
80340
+ openInBrowser(url);
80341
+ console.log(paint.dim(" Opened: ") + paint.cyan(url));
80342
+ console.log();
80343
+ console.log(" Sign in there \u2014 Google, Apple, SSO or your password all work.");
80344
+ console.log(paint.dim(" Copy the code the page shows, then paste it here."));
80345
+ console.log();
80346
+ code = normalizeAuthCode(await prompt(paint.bold(" Code ") + paint.dim("> ")));
80347
+ }
80348
+ if (!code) {
80349
+ console.log(paint.red(" \u2717 No code entered."));
80350
+ console.log();
80351
+ process.exitCode = 1;
80352
+ return;
80353
+ }
80354
+ console.log();
80355
+ const spinner = startSpinner("Signing in\u2026");
80356
+ try {
80357
+ const authConfig = await (0, import_code_core2.exchangeAuthCode)(code);
80358
+ (0, import_code_core2.saveAuth)(authConfig);
80359
+ stopSpinner(spinner);
80360
+ console.log(paint.green(" \u2713 Logged in as ") + paint.bold(authConfig.email || "your account"));
80361
+ await showBalance();
80362
+ console.log();
80363
+ console.log(paint.dim(" Run ") + paint.bold("nex") + paint.dim(" to start coding."));
80364
+ console.log();
80365
+ } catch (err) {
80366
+ stopSpinner(spinner);
80367
+ console.log();
80368
+ console.log(paint.red(" \u2717 Login failed: ") + String(err.message));
80369
+ console.log();
80370
+ process.exitCode = 1;
80371
+ }
80372
+ }
80373
+ async function loginWithPassword() {
79686
80374
  const email = await prompt(paint.bold(" Email ") + paint.dim("> "));
79687
80375
  const password = await prompt(paint.bold(" Password ") + paint.dim("> "), true);
79688
80376
  console.log();
79689
80377
  const spinner = startSpinner("Logging in\u2026");
79690
80378
  try {
79691
- const authConfig = await (0, import_code_core.login)(email, password);
79692
- (0, import_code_core.saveAuth)(authConfig);
80379
+ const authConfig = await (0, import_code_core2.login)(email, password);
80380
+ (0, import_code_core2.saveAuth)(authConfig);
79693
80381
  stopSpinner(spinner);
79694
80382
  console.log(paint.green(" \u2713 Logged in as ") + paint.bold(authConfig.email ?? email));
79695
- console.log();
79696
- try {
79697
- const balance = await (0, import_code_core.getBalance)();
79698
- console.log(paint.dim(" Wallet balance: ") + paint.cyan(`$${balance.toFixed(4)}`));
79699
- } catch {
79700
- }
80383
+ await showBalance();
79701
80384
  console.log();
79702
80385
  console.log(paint.dim(" Run ") + paint.bold("nex") + paint.dim(" to start coding."));
79703
80386
  console.log();
@@ -79706,12 +80389,71 @@ async function authCommand() {
79706
80389
  console.log();
79707
80390
  console.log(paint.red(" \u2717 Login failed: ") + String(err.message));
79708
80391
  console.log();
79709
- process.exit(1);
80392
+ process.exitCode = 1;
80393
+ }
80394
+ }
80395
+ async function loginWithTokenPrompt() {
80396
+ console.log(paint.dim(" Paste a token from the Nexrall dashboard."));
80397
+ const token = await prompt(paint.bold(" Token ") + paint.dim("> "), true);
80398
+ if (!token) {
80399
+ console.log(paint.red(" \u2717 No token entered."));
80400
+ console.log();
80401
+ process.exitCode = 1;
80402
+ return;
80403
+ }
80404
+ await loginWithToken(token);
80405
+ }
80406
+ async function loginWithToken(rawToken) {
80407
+ const token = rawToken.trim();
80408
+ if (!token) {
80409
+ console.log(paint.red(" \u2717 Empty token."));
80410
+ console.log();
80411
+ process.exitCode = 1;
80412
+ return;
80413
+ }
80414
+ console.log();
80415
+ const spinner = startSpinner("Checking the token\u2026");
80416
+ const check2 = await (0, import_code_core2.checkToken)(token);
80417
+ if (!check2.ok && check2.status !== 0) {
80418
+ stopSpinner(spinner);
80419
+ console.log();
80420
+ console.log(paint.red(` \u2717 The API refused this token (HTTP ${check2.status}).`) + paint.dim(" Nothing was saved."));
80421
+ console.log();
80422
+ process.exitCode = 1;
80423
+ return;
80424
+ }
80425
+ (0, import_code_core2.saveAuth)({ token, ...check2.email ? { email: check2.email } : {} });
80426
+ stopSpinner(spinner);
80427
+ console.log(paint.green(" \u2713 Token saved") + (check2.email ? paint.dim(` for ${check2.email}`) : ""));
80428
+ if (check2.status === 0) {
80429
+ console.log(paint.yellow(" Could not reach the API to verify it \u2014 check the token once you are online."));
80430
+ }
80431
+ warnIfEnvTokenWins();
80432
+ await showBalance();
80433
+ console.log();
80434
+ }
80435
+ function warnIfEnvTokenWins() {
80436
+ const envToken = process.env.NEXRALL_TOKEN?.trim();
80437
+ if (!envToken)
80438
+ return;
80439
+ console.log(
80440
+ paint.yellow(" NEXRALL_TOKEN is set in this shell and takes precedence over the saved login.") + paint.dim(" Unset it to use what you just saved.")
80441
+ );
80442
+ }
80443
+ async function showBalance() {
80444
+ try {
80445
+ const balance = await (0, import_code_core2.getBalance)();
80446
+ console.log(paint.dim(" Wallet balance: ") + paint.cyan(`$${balance.toFixed(4)}`));
80447
+ } catch {
79710
80448
  }
79711
80449
  }
80450
+ async function signOut() {
80451
+ await (0, import_code_core2.revokeRefreshToken)();
80452
+ (0, import_code_core2.clearAuth)();
80453
+ }
79712
80454
  async function logoutCommand() {
79713
80455
  console.log();
79714
- if (!(0, import_code_core.isAuthenticated)()) {
80456
+ if (!(0, import_code_core2.isAuthenticated)()) {
79715
80457
  console.log(paint.dim(" Not logged in."));
79716
80458
  console.log();
79717
80459
  return;
@@ -79722,9 +80464,13 @@ async function logoutCommand() {
79722
80464
  console.log();
79723
80465
  return;
79724
80466
  }
79725
- await (0, import_code_core.revokeRefreshToken)();
79726
- (0, import_code_core.clearAuth)();
80467
+ await signOut();
79727
80468
  console.log(paint.green(" \u2713 Logged out."));
80469
+ if (process.env.NEXRALL_TOKEN?.trim()) {
80470
+ console.log(
80471
+ paint.yellow(" NEXRALL_TOKEN is still set in this shell") + paint.dim(" \u2014 unset it, or the CLI stays signed in with that token.")
80472
+ );
80473
+ }
79728
80474
  console.log();
79729
80475
  }
79730
80476
  function startSpinner(text) {
@@ -79743,12 +80489,12 @@ function stopSpinner(handle2) {
79743
80489
  }
79744
80490
 
79745
80491
  // src/commands/billing.ts
79746
- var import_code_core2 = __toESM(require_dist2(), 1);
80492
+ var import_code_core3 = __toESM(require_dist2(), 1);
79747
80493
  function money(usd) {
79748
80494
  return "$" + usd.toFixed(2);
79749
80495
  }
79750
80496
  async function requireAuth() {
79751
- if ((0, import_code_core2.isAuthenticated)())
80497
+ if ((0, import_code_core3.isAuthenticated)())
79752
80498
  return true;
79753
80499
  console.log(paint.red("Not logged in. Run `nex auth` first."));
79754
80500
  return false;
@@ -79758,7 +80504,7 @@ async function billingStatusCommand() {
79758
80504
  return;
79759
80505
  let orgs;
79760
80506
  try {
79761
- orgs = await (0, import_code_core2.getOrgs)();
80507
+ orgs = await (0, import_code_core3.getOrgs)();
79762
80508
  } catch {
79763
80509
  console.log(paint.yellow("Could not read your billing target (offline, or a server without team support)."));
79764
80510
  return;
@@ -79790,7 +80536,7 @@ async function billingStatusCommand() {
79790
80536
  console.log("");
79791
80537
  console.log(paint.gray("Change it with `nex billing use <id>` or `nex billing use personal`."));
79792
80538
  }
79793
- const override = (0, import_code_core2.billingOverrideFields)();
80539
+ const override = (0, import_code_core3.billingOverrideFields)();
79794
80540
  if ("teamId" in override) {
79795
80541
  console.log("");
79796
80542
  console.log(
@@ -79818,7 +80564,7 @@ async function billingUseCommand(target) {
79818
80564
  }
79819
80565
  async function applyTarget(teamId, label) {
79820
80566
  try {
79821
- await (0, import_code_core2.setBillingTarget)(teamId);
80567
+ await (0, import_code_core3.setBillingTarget)(teamId);
79822
80568
  } catch (e2) {
79823
80569
  console.log(paint.red(e2.message));
79824
80570
  process.exitCode = 1;
@@ -79832,14 +80578,14 @@ async function applyTarget(teamId, label) {
79832
80578
 
79833
80579
  // src/commands/schedule.ts
79834
80580
  var import_prompts = __toESM(require_prompts3(), 1);
79835
- var import_code_core4 = __toESM(require_dist2(), 1);
80581
+ var import_code_core5 = __toESM(require_dist2(), 1);
79836
80582
 
79837
80583
  // src/ui/scheduleLines.ts
79838
- var import_code_core3 = __toESM(require_dist2(), 1);
80584
+ var import_code_core4 = __toESM(require_dist2(), 1);
79839
80585
 
79840
80586
  // src/commands/schedule.ts
79841
80587
  async function requireAuth2() {
79842
- if ((0, import_code_core4.isAuthenticated)())
80588
+ if ((0, import_code_core5.isAuthenticated)())
79843
80589
  return true;
79844
80590
  console.log(paint.red("Not logged in. Run `nex auth` first."));
79845
80591
  process.exitCode = 1;
@@ -79860,7 +80606,7 @@ async function scheduleListCommand(opts = {}) {
79860
80606
  return;
79861
80607
  let list;
79862
80608
  try {
79863
- list = await (0, import_code_core4.listCloudSchedules)();
80609
+ list = await (0, import_code_core5.listCloudSchedules)();
79864
80610
  } catch (e2) {
79865
80611
  fail(errText(e2));
79866
80612
  return;
@@ -79869,7 +80615,7 @@ async function scheduleListCommand(opts = {}) {
79869
80615
  console.log(JSON.stringify(list, null, 2));
79870
80616
  return;
79871
80617
  }
79872
- for (const line of (0, import_code_core3.scheduleListLines)(list, { cols: cols() }))
80618
+ for (const line of (0, import_code_core4.scheduleListLines)(list, { cols: cols() }))
79873
80619
  console.log(line);
79874
80620
  if (list.length) {
79875
80621
  console.log(paint.dim(`
@@ -79889,7 +80635,7 @@ async function scheduleAddCommand(taskParts, opts) {
79889
80635
  fail("Missing --every. Usage: nex schedule add --every 1d <task> (e.g. --every 2h)");
79890
80636
  return;
79891
80637
  }
79892
- const every = (0, import_code_core3.parseScheduleEvery)(everyRaw);
80638
+ const every = (0, import_code_core4.parseScheduleEvery)(everyRaw);
79893
80639
  if ("error" in every) {
79894
80640
  fail(every.error);
79895
80641
  return;
@@ -79897,7 +80643,7 @@ async function scheduleAddCommand(taskParts, opts) {
79897
80643
  const domains = (opts.domains ?? "").split(",").map((d) => d.trim()).filter(Boolean);
79898
80644
  let s2;
79899
80645
  try {
79900
- s2 = await (0, import_code_core4.createCloudSchedule)({
80646
+ s2 = await (0, import_code_core5.createCloudSchedule)({
79901
80647
  task,
79902
80648
  intervalMinutes: every.minutes,
79903
80649
  startUrl: opts.startUrl,
@@ -79909,12 +80655,12 @@ async function scheduleAddCommand(taskParts, opts) {
79909
80655
  return;
79910
80656
  }
79911
80657
  console.log(
79912
- `\u2714 Scheduled ${paint.bold(`#${s2.id}`)} \u2014 every ${(0, import_code_core3.formatEvery)(s2.intervalMinutes)}${s2.enabled ? "" : paint.yellow(" (paused)")}`
80658
+ `\u2714 Scheduled ${paint.bold(`#${s2.id}`)} \u2014 every ${(0, import_code_core4.formatEvery)(s2.intervalMinutes)}${s2.enabled ? "" : paint.yellow(" (paused)")}`
79913
80659
  );
79914
80660
  console.log(` ${s2.task}`);
79915
80661
  if (s2.nextRunAt) {
79916
80662
  console.log(
79917
- paint.dim(` Next run ${(0, import_code_core3.fmtScheduleWhen)(s2.nextRunAt)} \u2014 on Nexrall's servers; your laptop can be closed.`)
80663
+ paint.dim(` Next run ${(0, import_code_core4.fmtScheduleWhen)(s2.nextRunAt)} \u2014 on Nexrall's servers; your laptop can be closed.`)
79918
80664
  );
79919
80665
  }
79920
80666
  console.log(paint.dim(` History: nex schedule runs ${s2.id} \xB7 Pause: nex schedule pause ${s2.id}`));
@@ -79927,8 +80673,8 @@ async function scheduleSetEnabled(id, enabled) {
79927
80673
  return;
79928
80674
  }
79929
80675
  try {
79930
- const s2 = await (0, import_code_core4.updateCloudSchedule)(id, { enabled });
79931
- const next = s2.nextRunAt ? paint.dim(` \u2014 next run ${(0, import_code_core3.fmtScheduleWhen)(s2.nextRunAt)}`) : "";
80676
+ const s2 = await (0, import_code_core5.updateCloudSchedule)(id, { enabled });
80677
+ const next = s2.nextRunAt ? paint.dim(` \u2014 next run ${(0, import_code_core4.fmtScheduleWhen)(s2.nextRunAt)}`) : "";
79932
80678
  console.log(`\u2714 Schedule #${s2.id} is now ${s2.enabled ? "on" : "paused"}${next}`);
79933
80679
  } catch (e2) {
79934
80680
  fail(errText(e2));
@@ -79949,7 +80695,7 @@ async function scheduleRunCommand(id) {
79949
80695
  return;
79950
80696
  }
79951
80697
  try {
79952
- const s2 = await (0, import_code_core4.runCloudScheduleNow)(clean);
80698
+ const s2 = await (0, import_code_core5.runCloudScheduleNow)(clean);
79953
80699
  console.log(`\u2714 Schedule #${s2.id} armed \u2014 the cloud runner picks it up within ~60s.`);
79954
80700
  console.log(paint.dim(` Result: nex schedule runs ${s2.id}`));
79955
80701
  } catch (e2) {
@@ -79983,7 +80729,7 @@ async function scheduleRemoveCommand(id, opts = {}) {
79983
80729
  }
79984
80730
  }
79985
80731
  try {
79986
- await (0, import_code_core4.deleteCloudSchedule)(clean);
80732
+ await (0, import_code_core5.deleteCloudSchedule)(clean);
79987
80733
  console.log(`\u2714 Removed schedule #${clean}`);
79988
80734
  } catch (e2) {
79989
80735
  fail(errText(e2));
@@ -79999,7 +80745,7 @@ async function scheduleRunsCommand(id, opts = {}) {
79999
80745
  }
80000
80746
  let runs2;
80001
80747
  try {
80002
- runs2 = await (0, import_code_core4.getCloudScheduleRuns)(clean);
80748
+ runs2 = await (0, import_code_core5.getCloudScheduleRuns)(clean);
80003
80749
  } catch (e2) {
80004
80750
  fail(errText(e2));
80005
80751
  return;
@@ -80008,7 +80754,7 @@ async function scheduleRunsCommand(id, opts = {}) {
80008
80754
  console.log(JSON.stringify(runs2, null, 2));
80009
80755
  return;
80010
80756
  }
80011
- for (const line of (0, import_code_core3.scheduleRunsLines)(runs2, { cols: cols() }))
80757
+ for (const line of (0, import_code_core4.scheduleRunsLines)(runs2, { cols: cols() }))
80012
80758
  console.log(line);
80013
80759
  if (runs2.length) {
80014
80760
  console.log(
@@ -80021,10 +80767,10 @@ async function scheduleRunsCommand(id, opts = {}) {
80021
80767
  }
80022
80768
 
80023
80769
  // src/commands/cloud.ts
80024
- var import_code_core5 = __toESM(require_dist2(), 1);
80025
- import { spawn } from "child_process";
80770
+ var import_proc2 = __toESM(require_proc(), 1);
80771
+ var import_code_core6 = __toESM(require_dist2(), 1);
80026
80772
  async function requireAuth3() {
80027
- if ((0, import_code_core5.isAuthenticated)())
80773
+ if ((0, import_code_core6.isAuthenticated)())
80028
80774
  return true;
80029
80775
  console.log(paint.red("Not logged in. Run `nex auth` first."));
80030
80776
  process.exitCode = 1;
@@ -80058,10 +80804,11 @@ var writeRaw = (s2) => {
80058
80804
  process.stdout.write(s2);
80059
80805
  };
80060
80806
  function openUrl(url) {
80061
- const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
80062
- const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
80807
+ const win = process.platform === "win32";
80808
+ const cmd = process.platform === "darwin" ? "open" : win ? "rundll32" : "xdg-open";
80809
+ const args = win ? ["url.dll,FileProtocolHandler", url] : [url];
80063
80810
  try {
80064
- const child = spawn(cmd, args, { stdio: "ignore", detached: true });
80811
+ const child = (0, import_proc2.spawn)(cmd, args, { stdio: "ignore", detached: !win });
80065
80812
  child.on("error", () => {
80066
80813
  });
80067
80814
  child.unref();
@@ -80093,7 +80840,7 @@ async function cloudRunCommand(taskParts, opts) {
80093
80840
  }
80094
80841
  let created;
80095
80842
  try {
80096
- created = await (0, import_code_core5.createCloudSession)({ repo: opts.repo, task, baseBranch: opts.base, pat: pat || void 0 });
80843
+ created = await (0, import_code_core6.createCloudSession)({ repo: opts.repo, task, baseBranch: opts.base, pat: pat || void 0 });
80097
80844
  } catch (e2) {
80098
80845
  return fail2(errText2(e2));
80099
80846
  }
@@ -80112,7 +80859,7 @@ async function cloudListCommand(opts = {}) {
80112
80859
  return;
80113
80860
  let list;
80114
80861
  try {
80115
- list = await (0, import_code_core5.listCloudSessions)();
80862
+ list = await (0, import_code_core6.listCloudSessions)();
80116
80863
  } catch (e2) {
80117
80864
  return fail2(errText2(e2));
80118
80865
  }
@@ -80120,7 +80867,7 @@ async function cloudListCommand(opts = {}) {
80120
80867
  console.log(JSON.stringify({ sessions: list }, null, 2));
80121
80868
  return;
80122
80869
  }
80123
- for (const line of (0, import_code_core5.cloudListLines)(list, { cols: cols2() }))
80870
+ for (const line of (0, import_code_core6.cloudListLines)(list, { cols: cols2() }))
80124
80871
  console.log(` ${line}`);
80125
80872
  }
80126
80873
  async function cloudLogsCommand(id, opts) {
@@ -80133,7 +80880,7 @@ async function cloudLogsCommand(id, opts) {
80133
80880
  if (!opts.follow) {
80134
80881
  let r2;
80135
80882
  try {
80136
- r2 = await (0, import_code_core5.getCloudSessionLogs)(id, tail ?? 300);
80883
+ r2 = await (0, import_code_core6.getCloudSessionLogs)(id, tail ?? 300);
80137
80884
  } catch (e2) {
80138
80885
  return fail2(errText2(e2));
80139
80886
  }
@@ -80159,7 +80906,7 @@ async function cloudLogsCommand(id, opts) {
80159
80906
  for (; ; ) {
80160
80907
  let r2;
80161
80908
  try {
80162
- r2 = await (0, import_code_core5.getCloudSessionLogs)(id, tail ?? 1e3);
80909
+ r2 = await (0, import_code_core6.getCloudSessionLogs)(id, tail ?? 1e3);
80163
80910
  consecutiveErrors = 0;
80164
80911
  } catch (e2) {
80165
80912
  const msg = errText2(e2);
@@ -80208,7 +80955,7 @@ async function cloudStopCommand(id) {
80208
80955
  return;
80209
80956
  let s2;
80210
80957
  try {
80211
- s2 = await (0, import_code_core5.stopCloudSession)(id);
80958
+ s2 = await (0, import_code_core6.stopCloudSession)(id);
80212
80959
  } catch (e2) {
80213
80960
  return fail2(errText2(e2));
80214
80961
  }
@@ -80223,7 +80970,7 @@ async function cloudWatchCommand(id, opts = {}) {
80223
80970
  return;
80224
80971
  let s2;
80225
80972
  try {
80226
- s2 = await (0, import_code_core5.getCloudSession)(id);
80973
+ s2 = await (0, import_code_core6.getCloudSession)(id);
80227
80974
  } catch (e2) {
80228
80975
  return fail2(errText2(e2));
80229
80976
  }
@@ -80393,11 +81140,11 @@ async function channelPushCommand(textParts, opts, deps = {}) {
80393
81140
  }
80394
81141
 
80395
81142
  // src/commands/usageCmd.ts
80396
- import fs2 from "node:fs";
80397
- import path from "node:path";
81143
+ import fs3 from "node:fs";
81144
+ import path2 from "node:path";
80398
81145
 
80399
81146
  // src/sessionEvents.ts
80400
- var import_code_core6 = __toESM(require_dist2(), 1);
81147
+ var import_code_core7 = __toESM(require_dist2(), 1);
80401
81148
 
80402
81149
  // src/usageExport.ts
80403
81150
  var DURATION_RE = /^(\d+)([mhdw])$/;
@@ -80694,7 +81441,7 @@ var USAGE_FORMATS = ["json", "jsonl", "csv"];
80694
81441
  function logFileIds(dir) {
80695
81442
  let names;
80696
81443
  try {
80697
- names = fs2.readdirSync(dir);
81444
+ names = fs3.readdirSync(dir);
80698
81445
  } catch {
80699
81446
  return [];
80700
81447
  }
@@ -80704,7 +81451,7 @@ function readRows(file) {
80704
81451
  const rows = [];
80705
81452
  let text;
80706
81453
  try {
80707
- text = fs2.readFileSync(file, "utf8");
81454
+ text = fs3.readFileSync(file, "utf8");
80708
81455
  } catch {
80709
81456
  return rows;
80710
81457
  }
@@ -80752,13 +81499,13 @@ function usageExportCommand(opts, deps = {}) {
80752
81499
  }
80753
81500
  limit = n;
80754
81501
  }
80755
- const dir = deps.eventsDirPath ?? (0, import_code_core6.eventsDir)(deps.env ?? process.env);
81502
+ const dir = deps.eventsDirPath ?? (0, import_code_core7.eventsDir)(deps.env ?? process.env);
80756
81503
  const ids = logFileIds(dir);
80757
81504
  const acc = createAccumulator({ since, until });
80758
81505
  acc.filesTotal = ids.length;
80759
81506
  let candidates = ids;
80760
81507
  if (opts.session) {
80761
- const wanted = (0, import_code_core6.safeId)(opts.session);
81508
+ const wanted = (0, import_code_core7.safeId)(opts.session);
80762
81509
  if (!candidates.includes(wanted)) {
80763
81510
  stderr(paint.red(`Session not found: ${opts.session}`));
80764
81511
  stderr(paint.dim(` Logs live in ${dir} (one .jsonl per session).`));
@@ -80769,7 +81516,7 @@ function usageExportCommand(opts, deps = {}) {
80769
81516
  if (since !== void 0) {
80770
81517
  candidates = candidates.filter((id) => {
80771
81518
  try {
80772
- return fs2.statSync(path.join(dir, `${id}.jsonl`)).mtimeMs >= since;
81519
+ return fs3.statSync(path2.join(dir, `${id}.jsonl`)).mtimeMs >= since;
80773
81520
  } catch {
80774
81521
  return false;
80775
81522
  }
@@ -80777,7 +81524,7 @@ function usageExportCommand(opts, deps = {}) {
80777
81524
  }
80778
81525
  const byNewest = candidates.map((id) => {
80779
81526
  try {
80780
- return { id, mtime: fs2.statSync(path.join(dir, `${id}.jsonl`)).mtimeMs };
81527
+ return { id, mtime: fs3.statSync(path2.join(dir, `${id}.jsonl`)).mtimeMs };
80781
81528
  } catch {
80782
81529
  return { id, mtime: 0 };
80783
81530
  }
@@ -80786,7 +81533,7 @@ function usageExportCommand(opts, deps = {}) {
80786
81533
  acc.truncated = taken.length < byNewest.length;
80787
81534
  for (const { id } of taken) {
80788
81535
  acc.filesRead += 1;
80789
- addSessionFile(acc, id, readRows(path.join(dir, `${id}.jsonl`)));
81536
+ addSessionFile(acc, id, readRows(path2.join(dir, `${id}.jsonl`)));
80790
81537
  }
80791
81538
  const report = finalizeUsage(acc, now);
80792
81539
  let content;
@@ -80798,7 +81545,7 @@ function usageExportCommand(opts, deps = {}) {
80798
81545
  content = formatUsageJson(report);
80799
81546
  if (opts.out) {
80800
81547
  try {
80801
- fs2.writeFileSync(opts.out, content);
81548
+ fs3.writeFileSync(opts.out, content);
80802
81549
  } catch (e2) {
80803
81550
  stderr(paint.red(`Could not write ${opts.out}: ${e2.message}`));
80804
81551
  return USAGE_EXIT.FAIL;
@@ -80832,7 +81579,7 @@ import * as path27 from "path";
80832
81579
  import * as fs26 from "fs";
80833
81580
 
80834
81581
  // src/ui/diffView.ts
80835
- var import_code_core7 = __toESM(require_dist2(), 1);
81582
+ var import_code_core8 = __toESM(require_dist2(), 1);
80836
81583
  function paintLine(l) {
80837
81584
  switch (l.kind) {
80838
81585
  case "file":
@@ -80853,431 +81600,7 @@ function paintLine(l) {
80853
81600
  }
80854
81601
 
80855
81602
  // src/ui/reviewQueue.ts
80856
- var import_code_core8 = __toESM(require_dist2(), 1);
80857
-
80858
- // src/mcp/oauth.ts
80859
81603
  var import_code_core9 = __toESM(require_dist2(), 1);
80860
- import * as fs3 from "fs";
80861
- import * as os2 from "os";
80862
- import * as path2 from "path";
80863
- import * as http3 from "http";
80864
- import * as crypto from "crypto";
80865
- import { spawn as spawn2 } from "child_process";
80866
- var CALLBACK_TIMEOUT_MS = 5 * 60 * 1e3;
80867
- function tokensFile(env3 = process.env) {
80868
- return env3.NEXRALL_MCP_AUTH_FILE || path2.join(os2.homedir(), ".nexrall", "mcp-auth.json");
80869
- }
80870
- function readStore(file) {
80871
- try {
80872
- const parsed = JSON.parse(fs3.readFileSync(file, "utf-8"));
80873
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
80874
- return {};
80875
- const out = {};
80876
- for (const [k, v] of Object.entries(parsed)) {
80877
- const b = v;
80878
- if (b && typeof b.access_token === "string" && typeof b.token_endpoint === "string")
80879
- out[k] = b;
80880
- }
80881
- return out;
80882
- } catch {
80883
- return {};
80884
- }
80885
- }
80886
- function writeStore(file, store) {
80887
- fs3.mkdirSync(path2.dirname(file), { recursive: true });
80888
- fs3.writeFileSync(file, JSON.stringify(store, null, 2), { mode: 384 });
80889
- try {
80890
- fs3.chmodSync(file, 384);
80891
- } catch {
80892
- }
80893
- }
80894
- function loadToken(server, file = tokensFile()) {
80895
- return readStore(file)[server] ?? null;
80896
- }
80897
- function saveToken(server, bundle, file = tokensFile()) {
80898
- const store = readStore(file);
80899
- store[server] = bundle;
80900
- writeStore(file, store);
80901
- }
80902
- function clearToken(server, file = tokensFile()) {
80903
- const store = readStore(file);
80904
- if (!(server in store))
80905
- return false;
80906
- delete store[server];
80907
- writeStore(file, store);
80908
- return true;
80909
- }
80910
- function defaultFetch() {
80911
- const f3 = globalThis.fetch;
80912
- if (typeof f3 !== "function")
80913
- throw new Error("global fetch unavailable \u2014 Node 18+ is required for MCP OAuth");
80914
- return f3;
80915
- }
80916
- async function getValidAccessToken(server, opts = {}) {
80917
- const file = opts.file ?? tokensFile();
80918
- const bundle = loadToken(server, file);
80919
- if (!bundle)
80920
- return null;
80921
- const fresh = !bundle.expires_at || bundle.expires_at - Date.now() > 6e4;
80922
- if (fresh || !bundle.refresh_token)
80923
- return bundle.access_token;
80924
- try {
80925
- const refreshed = await refreshAccessToken(bundle, opts.fetchImpl ?? defaultFetch());
80926
- saveToken(server, refreshed, file);
80927
- return refreshed.access_token;
80928
- } catch {
80929
- return bundle.access_token;
80930
- }
80931
- }
80932
- function parseResourceMetadataUrl(wwwAuthenticate) {
80933
- const m2 = /resource_metadata\s*=\s*"([^"]+)"/i.exec(wwwAuthenticate || "");
80934
- return m2 ? m2[1] : null;
80935
- }
80936
- function protectedResourceCandidates(serverUrl) {
80937
- const u = new URL(serverUrl);
80938
- const base = u.origin;
80939
- const p = u.pathname.replace(/\/$/, "");
80940
- return [
80941
- ...p ? [`${base}/.well-known/oauth-protected-resource${p}`] : [],
80942
- `${base}/.well-known/oauth-protected-resource`
80943
- ];
80944
- }
80945
- function authServerCandidates(authServer) {
80946
- const u = new URL(authServer);
80947
- const base = u.origin;
80948
- const p = u.pathname.replace(/\/$/, "");
80949
- const root = authServer.replace(/\/$/, "");
80950
- return [
80951
- `${base}/.well-known/oauth-authorization-server${p}`,
80952
- `${base}/.well-known/openid-configuration${p}`,
80953
- `${root}/.well-known/oauth-authorization-server`,
80954
- `${root}/.well-known/openid-configuration`
80955
- ];
80956
- }
80957
- function buildAuthorizeUrl(meta, p) {
80958
- const url = new URL(meta.authorization_endpoint);
80959
- url.searchParams.set("response_type", "code");
80960
- url.searchParams.set("client_id", p.clientId);
80961
- url.searchParams.set("redirect_uri", p.redirectUri);
80962
- url.searchParams.set("state", p.state);
80963
- url.searchParams.set("code_challenge", p.codeChallenge);
80964
- url.searchParams.set("code_challenge_method", "S256");
80965
- url.searchParams.set("resource", meta.resource);
80966
- if (meta.scope)
80967
- url.searchParams.set("scope", meta.scope);
80968
- return url.toString();
80969
- }
80970
- function toBundle(data, p) {
80971
- const accessToken = data.access_token;
80972
- if (!accessToken)
80973
- throw new Error("Token response had no access_token");
80974
- const expiresIn = typeof data.expires_in === "number" ? data.expires_in : void 0;
80975
- return {
80976
- access_token: accessToken,
80977
- refresh_token: data.refresh_token ?? p.prevRefresh,
80978
- expires_at: expiresIn ? Date.now() + expiresIn * 1e3 : void 0,
80979
- token_endpoint: p.tokenEndpoint,
80980
- client_id: p.clientId,
80981
- client_secret: p.clientSecret,
80982
- resource: p.resource,
80983
- scope: data.scope ?? p.scope
80984
- };
80985
- }
80986
- async function fetchJsonSafe(f3, url) {
80987
- try {
80988
- const resp = await f3(url, { headers: { Accept: "application/json" } });
80989
- if (!resp.ok)
80990
- return null;
80991
- return await resp.json();
80992
- } catch {
80993
- return null;
80994
- }
80995
- }
80996
- async function discover(serverUrl, wwwAuthenticate, f3 = defaultFetch()) {
80997
- const origin = new URL(serverUrl).origin;
80998
- let authServer = null;
80999
- let resource = serverUrl;
81000
- let scope;
81001
- const prmCandidates = [parseResourceMetadataUrl(wwwAuthenticate), ...protectedResourceCandidates(serverUrl)].filter(
81002
- (u) => Boolean(u)
81003
- );
81004
- let prm = null;
81005
- for (const url of new Set(prmCandidates)) {
81006
- prm = await fetchJsonSafe(f3, url);
81007
- if (prm)
81008
- break;
81009
- }
81010
- if (prm) {
81011
- const servers = prm.authorization_servers;
81012
- if (Array.isArray(servers) && servers.length)
81013
- authServer = servers[0];
81014
- if (typeof prm.resource === "string")
81015
- resource = prm.resource;
81016
- const scopes = prm.scopes_supported;
81017
- if (Array.isArray(scopes) && scopes.length)
81018
- scope = scopes.join(" ");
81019
- }
81020
- if (!authServer)
81021
- authServer = origin;
81022
- let asm = null;
81023
- for (const url of authServerCandidates(authServer)) {
81024
- asm = await fetchJsonSafe(f3, url);
81025
- if (asm && asm.authorization_endpoint && asm.token_endpoint)
81026
- break;
81027
- asm = null;
81028
- }
81029
- if (!asm)
81030
- throw new Error(`No OAuth metadata found for authorization server ${authServer}`);
81031
- return {
81032
- authorization_endpoint: asm.authorization_endpoint,
81033
- token_endpoint: asm.token_endpoint,
81034
- registration_endpoint: asm.registration_endpoint,
81035
- resource,
81036
- scope
81037
- };
81038
- }
81039
- async function registerClient(meta, redirectUri, f3) {
81040
- if (!meta.registration_endpoint) {
81041
- throw new Error(
81042
- 'Authorization server does not support dynamic client registration; a client_id must be configured manually \u2014 create an OAuth client for this server, then re-run `nex mcp login <server> --client-id <id> [--client-secret <secret>]` (or set "clientId" / "clientSecret" in its mcp.json entry).'
81043
- );
81044
- }
81045
- const resp = await f3(meta.registration_endpoint, {
81046
- method: "POST",
81047
- headers: { "Content-Type": "application/json", Accept: "application/json" },
81048
- body: JSON.stringify({
81049
- client_name: "Nexrall Code CLI",
81050
- redirect_uris: [redirectUri],
81051
- grant_types: ["authorization_code", "refresh_token"],
81052
- response_types: ["code"],
81053
- token_endpoint_auth_method: "none",
81054
- scope: meta.scope
81055
- })
81056
- });
81057
- if (!resp.ok)
81058
- throw new Error(`Client registration failed (HTTP ${resp.status})`);
81059
- const data = await resp.json();
81060
- if (!data.client_id)
81061
- throw new Error("Client registration returned no client_id");
81062
- return data.client_id;
81063
- }
81064
- async function postToken(tokenEndpoint, body, f3) {
81065
- const resp = await f3(tokenEndpoint, {
81066
- method: "POST",
81067
- headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json" },
81068
- body: body.toString()
81069
- });
81070
- if (!resp.ok) {
81071
- const txt = await resp.text().catch(() => "");
81072
- throw new Error(`Token endpoint error (HTTP ${resp.status})${txt ? `: ${txt.slice(0, 200)}` : ""}`);
81073
- }
81074
- return await resp.json();
81075
- }
81076
- async function exchangeCode(meta, clientId, clientSecret, code, verifier, redirectUri, f3) {
81077
- const body = new URLSearchParams({
81078
- grant_type: "authorization_code",
81079
- code,
81080
- redirect_uri: redirectUri,
81081
- client_id: clientId,
81082
- code_verifier: verifier,
81083
- resource: meta.resource
81084
- });
81085
- if (clientSecret)
81086
- body.set("client_secret", clientSecret);
81087
- const data = await postToken(meta.token_endpoint, body, f3);
81088
- return toBundle(data, {
81089
- tokenEndpoint: meta.token_endpoint,
81090
- clientId,
81091
- clientSecret,
81092
- resource: meta.resource,
81093
- scope: meta.scope
81094
- });
81095
- }
81096
- async function refreshAccessToken(bundle, f3) {
81097
- const body = new URLSearchParams({
81098
- grant_type: "refresh_token",
81099
- refresh_token: bundle.refresh_token,
81100
- client_id: bundle.client_id,
81101
- resource: bundle.resource
81102
- });
81103
- if (bundle.client_secret)
81104
- body.set("client_secret", bundle.client_secret);
81105
- const data = await postToken(bundle.token_endpoint, body, f3);
81106
- return toBundle(data, {
81107
- tokenEndpoint: bundle.token_endpoint,
81108
- clientId: bundle.client_id,
81109
- clientSecret: bundle.client_secret,
81110
- resource: bundle.resource,
81111
- scope: bundle.scope,
81112
- prevRefresh: bundle.refresh_token
81113
- });
81114
- }
81115
- function startLoopback() {
81116
- return new Promise((resolve19, reject) => {
81117
- let resolveCode;
81118
- let rejectCode;
81119
- const codePromise = new Promise((res, rej) => {
81120
- resolveCode = res;
81121
- rejectCode = rej;
81122
- });
81123
- codePromise.catch(() => void 0);
81124
- const server = http3.createServer((req, res) => {
81125
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
81126
- if (url.pathname !== "/callback") {
81127
- res.writeHead(404);
81128
- res.end();
81129
- return;
81130
- }
81131
- const code = url.searchParams.get("code");
81132
- const state = url.searchParams.get("state");
81133
- const error = url.searchParams.get("error");
81134
- res.writeHead(200, { "Content-Type": "text/html", Connection: "close" });
81135
- res.end(
81136
- `<!doctype html><html><body style="font-family:system-ui;text-align:center;padding:40px"><h2>${error || !code ? "Authentication failed" : "Authentication complete"}</h2><p>You can close this tab and return to the terminal.</p></body></html>`
81137
- );
81138
- if (error) {
81139
- rejectCode(new Error(`Authorization denied: ${error}`));
81140
- return;
81141
- }
81142
- if (!code) {
81143
- rejectCode(new Error("No authorization code in redirect"));
81144
- return;
81145
- }
81146
- resolveCode({ code, state });
81147
- });
81148
- server.on("error", reject);
81149
- server.listen(0, "127.0.0.1", () => {
81150
- const port = server.address().port;
81151
- resolve19({
81152
- port,
81153
- waitForCode(expectedState) {
81154
- const timeout = setTimeout(
81155
- () => rejectCode(new Error("Timed out waiting for authorization")),
81156
- CALLBACK_TIMEOUT_MS
81157
- );
81158
- return codePromise.then(
81159
- ({ code, state }) => {
81160
- clearTimeout(timeout);
81161
- if (state !== expectedState)
81162
- throw new Error("OAuth state mismatch \u2014 possible CSRF, aborting");
81163
- return code;
81164
- },
81165
- // A denial must clear the timer too: otherwise `nex mcp login` reports the
81166
- // failure but the process sits on a 5-minute keep-alive before exiting.
81167
- (err) => {
81168
- clearTimeout(timeout);
81169
- throw err;
81170
- }
81171
- );
81172
- },
81173
- close() {
81174
- try {
81175
- server.closeAllConnections?.();
81176
- } catch {
81177
- }
81178
- try {
81179
- server.close();
81180
- } catch {
81181
- }
81182
- }
81183
- });
81184
- });
81185
- });
81186
- }
81187
- function b64url(buf) {
81188
- return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
81189
- }
81190
- function openInBrowser(url) {
81191
- const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
81192
- try {
81193
- const child = spawn2(cmd, [url], { stdio: "ignore", detached: true, shell: process.platform === "win32" });
81194
- child.on("error", () => void 0);
81195
- child.unref();
81196
- } catch {
81197
- }
81198
- }
81199
- async function probeAuthChallenge(serverUrl, f3 = defaultFetch()) {
81200
- const steps = [
81201
- {
81202
- method: "initialize",
81203
- params: {
81204
- protocolVersion: import_code_core9.MCP_PROTOCOL_VERSION,
81205
- capabilities: {},
81206
- clientInfo: { name: "nexrall-code", version: "1.0" }
81207
- }
81208
- },
81209
- { method: "tools/list", params: {} }
81210
- ];
81211
- for (const { method, params } of steps) {
81212
- try {
81213
- const resp = await f3(serverUrl, {
81214
- method: "POST",
81215
- headers: { "Content-Type": "application/json", Accept: "application/json, text/event-stream" },
81216
- body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params })
81217
- });
81218
- const challenge = resp.headers?.get("www-authenticate") ?? "";
81219
- if (challenge)
81220
- return challenge;
81221
- } catch {
81222
- return "";
81223
- }
81224
- }
81225
- return "";
81226
- }
81227
- async function authorizeServer(o) {
81228
- const f3 = o.fetchImpl ?? defaultFetch();
81229
- const challenge = o.wwwAuthenticate ?? await probeAuthChallenge(o.serverUrl, f3);
81230
- const meta = await discover(o.serverUrl, challenge, f3);
81231
- const scope = [meta.scope, (0, import_code_core9.parseOAuthChallenge)(challenge).scope, o.extraScope].map((s2) => s2?.trim()).filter((s2) => Boolean(s2)).join(" ").split(/\s+/).filter((s2, i2, a) => Boolean(s2) && a.indexOf(s2) === i2).join(" ");
81232
- meta.scope = scope || void 0;
81233
- const loopback = await startLoopback();
81234
- const redirectUri = `http://127.0.0.1:${loopback.port}/callback`;
81235
- try {
81236
- const creds = o.credentials ?? {};
81237
- let clientId;
81238
- if (creds.clientId) {
81239
- clientId = creds.clientId;
81240
- o.onStep?.("Using the OAuth client configured for this server\u2026");
81241
- } else {
81242
- o.onStep?.(`Registering with ${new URL(meta.token_endpoint).origin}\u2026`);
81243
- clientId = await registerClient(meta, redirectUri, f3);
81244
- }
81245
- const verifier = b64url(crypto.randomBytes(32));
81246
- const challengeB64 = b64url(crypto.createHash("sha256").update(verifier).digest());
81247
- const state = b64url(crypto.randomBytes(16));
81248
- const authUrl = buildAuthorizeUrl(meta, { clientId, redirectUri, codeChallenge: challengeB64, state });
81249
- o.onStep?.("Opening your browser to authorize\u2026");
81250
- await o.openUrl(authUrl);
81251
- const code = await loopback.waitForCode(state);
81252
- const bundle = await exchangeCode(meta, clientId, creds.clientSecret, code, verifier, redirectUri, f3);
81253
- saveToken(o.server, bundle, o.file ?? tokensFile());
81254
- } finally {
81255
- loopback.close();
81256
- }
81257
- }
81258
- var isRemote = (cfg) => cfg.type === "http" || cfg.type === "sse" || !cfg.command && !!cfg.url;
81259
- async function injectMcpTokens(config, opts = {}) {
81260
- const file = opts.file ?? tokensFile();
81261
- const injected = [];
81262
- for (const [name, cfg] of Object.entries(config.mcpServers ?? {})) {
81263
- if (!isRemote(cfg))
81264
- continue;
81265
- const hasAuth = cfg.headers && Object.keys(cfg.headers).some((h2) => h2.toLowerCase() === "authorization");
81266
- if (hasAuth)
81267
- continue;
81268
- let token;
81269
- try {
81270
- token = await getValidAccessToken(name, { file, fetchImpl: opts.fetchImpl });
81271
- } catch {
81272
- token = null;
81273
- }
81274
- if (!token)
81275
- continue;
81276
- cfg.headers = { ...cfg.headers ?? {}, Authorization: `Bearer ${token}` };
81277
- injected.push(name);
81278
- }
81279
- return injected;
81280
- }
81281
81604
 
81282
81605
  // src/commands/mcpCmd.ts
81283
81606
  var import_code_core10 = __toESM(require_dist2(), 1);
@@ -82344,7 +82667,7 @@ function classify(err, opts) {
82344
82667
  return {
82345
82668
  kind: "auth",
82346
82669
  title: "Not signed in",
82347
- hints: ["Run `nexrall-code login` to sign in again", "Your session keeps its place: /resume picks it back up"]
82670
+ hints: ["Run `nex auth` to sign in again", "Your session keeps its place: /resume picks it back up"]
82348
82671
  };
82349
82672
  }
82350
82673
  if (status === 429 || RATE_RE.test(msg)) {
@@ -82463,15 +82786,15 @@ async function executeMcpResourceTool(name, input, mgr) {
82463
82786
  }
82464
82787
 
82465
82788
  // src/ui/clipboardImage.ts
82789
+ var import_proc3 = __toESM(require_proc(), 1);
82466
82790
  import * as fs6 from "fs";
82467
82791
  import * as os3 from "os";
82468
82792
  import * as path5 from "path";
82469
- import { spawnSync } from "child_process";
82470
82793
  var MAX_PASTE_BYTES = 10 * 1024 * 1024;
82471
82794
  var PNG_MAGIC = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
82472
82795
  var realRunner = (cmd, args) => {
82473
82796
  try {
82474
- return spawnSync(cmd, args, { stdio: "ignore", timeout: 8e3 }).status === 0;
82797
+ return (0, import_proc3.spawnSync)(cmd, args, { stdio: "ignore", timeout: 8e3 }).status === 0;
82475
82798
  } catch {
82476
82799
  return false;
82477
82800
  }
@@ -83009,7 +83332,7 @@ function capEffortForScale(levels, effort, cap) {
83009
83332
  var import_code_core26 = __toESM(require_dist2(), 1);
83010
83333
 
83011
83334
  // src/ui/statusLine.ts
83012
- import { spawn as spawn3 } from "child_process";
83335
+ var import_proc4 = __toESM(require_proc(), 1);
83013
83336
  var STATUSLINE_TIMEOUT_MS = 2e3;
83014
83337
  var MIN_INTERVAL_MS2 = 1500;
83015
83338
  var MAX_OUTPUT_BYTES = 4096;
@@ -83056,7 +83379,7 @@ var shellRunner = (command, stdin, cwd2, timeoutMs) => new Promise((resolve19) =
83056
83379
  };
83057
83380
  let child;
83058
83381
  try {
83059
- child = spawn3(command, { shell: true, cwd: cwd2, stdio: ["pipe", "pipe", "ignore"], env: process.env });
83382
+ child = (0, import_proc4.spawn)(command, { shell: true, cwd: cwd2, stdio: ["pipe", "pipe", "ignore"], env: process.env });
83060
83383
  } catch {
83061
83384
  resolve19(null);
83062
83385
  return;
@@ -84838,12 +85161,12 @@ function formatDeployTargets(targets, cols3) {
84838
85161
  }
84839
85162
 
84840
85163
  // src/commands/chat.ts
85164
+ var import_proc12 = __toESM(require_proc(), 1);
84841
85165
  var import_code_core66 = __toESM(require_dist2(), 1);
84842
85166
  import * as os17 from "os";
84843
85167
  import * as crypto4 from "crypto";
84844
85168
  import { createRequire } from "module";
84845
85169
  import { fileURLToPath as fileURLToPath2 } from "url";
84846
- import { execFile as execFile2, execFileSync as execFileSync6 } from "child_process";
84847
85170
 
84848
85171
  // src/permissions/handler.ts
84849
85172
  import * as readline2 from "readline";
@@ -87118,17 +87441,17 @@ function debugLog(event, fields) {
87118
87441
  }
87119
87442
 
87120
87443
  // src/commands/doctor.ts
87444
+ var import_proc6 = __toESM(require_proc(), 1);
87121
87445
  var import_code_core46 = __toESM(require_dist2(), 1);
87122
87446
  import fs11 from "fs";
87123
87447
  import os6 from "os";
87124
87448
  import path13 from "path";
87125
- import { spawnSync as spawnSync3, execFileSync as execFileSync2 } from "child_process";
87126
87449
 
87127
87450
  // src/commands/sessionTools.ts
87451
+ var import_proc5 = __toESM(require_proc(), 1);
87128
87452
  var import_code_core42 = __toESM(require_dist2(), 1);
87129
87453
  var import_code_core43 = __toESM(require_dist2(), 1);
87130
87454
  var import_code_core44 = __toESM(require_dist2(), 1);
87131
- import { spawnSync as spawnSync2, execFileSync } from "child_process";
87132
87455
  var UsageTotals = class {
87133
87456
  input = 0;
87134
87457
  output = 0;
@@ -87221,7 +87544,7 @@ function copyToClipboard(text, platform3 = process.platform) {
87221
87544
  ];
87222
87545
  for (const [cmd, args] of candidates) {
87223
87546
  try {
87224
- const r2 = spawnSync2(cmd, args, { input: text, stdio: ["pipe", "ignore", "ignore"], timeout: 5e3 });
87547
+ const r2 = (0, import_proc5.spawnSync)(cmd, args, { input: text, stdio: ["pipe", "ignore", "ignore"], timeout: 5e3 });
87225
87548
  if (!r2.error && r2.status === 0)
87226
87549
  return cmd;
87227
87550
  } catch {
@@ -87233,7 +87556,7 @@ function osc52(text) {
87233
87556
  return `\x1B]52;c;${Buffer.from(text, "utf8").toString("base64")}\x07`;
87234
87557
  }
87235
87558
  function gitChanges(cwd2) {
87236
- const run = (args) => execFileSync("git", args, { cwd: cwd2, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 1e4 }).trimEnd();
87559
+ const run = (args) => (0, import_proc5.execFileSync)("git", args, { cwd: cwd2, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 1e4 }).trimEnd();
87237
87560
  try {
87238
87561
  run(["rev-parse", "--is-inside-work-tree"]);
87239
87562
  return { status: run(["status", "--short"]), stat: run(["diff", "--stat", "HEAD"]) };
@@ -87714,7 +88037,7 @@ function doctorExitCode(checks) {
87714
88037
  return checks.some((c) => c.status === "fail") ? 1 : 0;
87715
88038
  }
87716
88039
  function commandExists(cmd, platform3 = process.platform) {
87717
- const r2 = spawnSync3(platform3 === "win32" ? "where" : "which", [cmd], { stdio: "ignore", timeout: 5e3 });
88040
+ const r2 = (0, import_proc6.spawnSync)(platform3 === "win32" ? "where" : "which", [cmd], { stdio: "ignore", timeout: 5e3 });
87718
88041
  return !r2.error && r2.status === 0;
87719
88042
  }
87720
88043
  function ripgrepInstallHint(platform3) {
@@ -87765,7 +88088,7 @@ function realProbes(c) {
87765
88088
  resolveRipgrep: () => (0, import_code_core46.resolveRipgrepBinary)(),
87766
88089
  gitInfo: () => {
87767
88090
  try {
87768
- execFileSync2("git", ["rev-parse", "--is-inside-work-tree"], { cwd: c.workDir, stdio: "ignore", timeout: 5e3 });
88091
+ (0, import_proc6.execFileSync)("git", ["rev-parse", "--is-inside-work-tree"], { cwd: c.workDir, stdio: "ignore", timeout: 5e3 });
87769
88092
  return { inRepo: true, branch: (0, import_code_core43.gitBranch)(c.workDir) ?? void 0 };
87770
88093
  } catch {
87771
88094
  return { inRepo: false };
@@ -87847,7 +88170,7 @@ function knownSessionIds() {
87847
88170
  }
87848
88171
  };
87849
88172
  add(SESSIONS_DIR, ".json");
87850
- add((0, import_code_core6.eventsDir)(), ".jsonl");
88173
+ add((0, import_code_core7.eventsDir)(), ".jsonl");
87851
88174
  return [...ids];
87852
88175
  }
87853
88176
  function findSessionsByLink(link2) {
@@ -87920,7 +88243,7 @@ function deleteSession(id) {
87920
88243
  return false;
87921
88244
  }
87922
88245
  try {
87923
- fs12.unlinkSync((0, import_code_core6.eventsPath)(r2.id));
88246
+ fs12.unlinkSync((0, import_code_core7.eventsPath)(r2.id));
87924
88247
  } catch {
87925
88248
  }
87926
88249
  return true;
@@ -87954,7 +88277,7 @@ function exportSession(id, events) {
87954
88277
  version: 1,
87955
88278
  exportedAt: Date.now(),
87956
88279
  session,
87957
- events: events ?? (0, import_code_core6.readEvents)(r2.id)
88280
+ events: events ?? (0, import_code_core7.readEvents)(r2.id)
87958
88281
  };
87959
88282
  return JSON.stringify(bundle, null, 2);
87960
88283
  }
@@ -87996,7 +88319,7 @@ function importSession(bundle) {
87996
88319
  renamed = true;
87997
88320
  }
87998
88321
  saveSession(id, title, bundle.session.workDir || process.cwd(), bundle.session.messages);
87999
- (0, import_code_core6.writeEvents)(id, bundle.events);
88322
+ (0, import_code_core7.writeEvents)(id, bundle.events);
88000
88323
  return { id, messages: bundle.session.messages.length, renamed };
88001
88324
  }
88002
88325
 
@@ -88232,7 +88555,7 @@ async function enableAppleTerminalOptionAsMeta(deps) {
88232
88555
  }
88233
88556
 
88234
88557
  // src/commands/update.ts
88235
- import { execFileSync as execFileSync3, spawn as spawn4 } from "child_process";
88558
+ var import_proc7 = __toESM(require_proc(), 1);
88236
88559
  import * as fs13 from "fs";
88237
88560
  import * as https2 from "https";
88238
88561
  import * as path16 from "path";
@@ -88285,7 +88608,7 @@ function installArgs(version) {
88285
88608
  }
88286
88609
  function installedGlobalVersion() {
88287
88610
  try {
88288
- const root = execFileSync3("npm", ["root", "-g"], { encoding: "utf-8" }).trim();
88611
+ const root = (0, import_proc7.execFileSync)("npm", ["root", "-g"], { encoding: "utf-8" }).trim();
88289
88612
  return JSON.parse(fs13.readFileSync(path16.join(root, "nexrall-code", "package.json"), "utf-8")).version ?? null;
88290
88613
  } catch {
88291
88614
  return null;
@@ -88293,7 +88616,7 @@ function installedGlobalVersion() {
88293
88616
  }
88294
88617
  function npmInstallGlobal(version) {
88295
88618
  return new Promise((resolve19) => {
88296
- const child = spawn4("npm", installArgs(version), { stdio: "pipe" });
88619
+ const child = (0, import_proc7.spawn)("npm", installArgs(version), { stdio: "pipe" });
88297
88620
  let stderr = "";
88298
88621
  child.stderr?.on("data", (c) => {
88299
88622
  stderr += c.toString();
@@ -88302,7 +88625,7 @@ function npmInstallGlobal(version) {
88302
88625
  if (code === 0)
88303
88626
  return resolve19({ ok: true, usedSudo: false });
88304
88627
  if (/EACCES|permission denied/i.test(stderr)) {
88305
- const sudo = spawn4("sudo", ["npm", ...installArgs(version)], { stdio: "inherit" });
88628
+ const sudo = (0, import_proc7.spawn)("sudo", ["npm", ...installArgs(version)], { stdio: "inherit" });
88306
88629
  sudo.on("close", (sudoCode) => resolve19({ ok: sudoCode === 0, usedSudo: true }));
88307
88630
  } else {
88308
88631
  console.error(paint.dim(stderr.trim()));
@@ -98194,6 +98517,11 @@ var BUILTIN_SLASH_COMMANDS = [
98194
98517
  kind: "builtin"
98195
98518
  },
98196
98519
  { name: "cost", description: "Where the tokens and money went (per model, per agent, per turn)", kind: "builtin" },
98520
+ {
98521
+ name: "logout",
98522
+ description: "Sign out on this machine (revokes the saved refresh token)",
98523
+ kind: "builtin"
98524
+ },
98197
98525
  {
98198
98526
  name: "stats",
98199
98527
  description: "Usage across sessions: activity by day, tokens and models (local event logs)",
@@ -99340,9 +99668,9 @@ function decidePick(item, tab2) {
99340
99668
  }
99341
99669
 
99342
99670
  // src/commands/bangShell.ts
99671
+ var import_proc8 = __toESM(require_proc(), 1);
99343
99672
  var import_code_core50 = __toESM(require_dist2(), 1);
99344
99673
  var import_code_core51 = __toESM(require_dist2(), 1);
99345
- import { spawn as spawn5 } from "child_process";
99346
99674
  function parseBang(line) {
99347
99675
  const t2 = line.trim();
99348
99676
  if (!t2.startsWith("!"))
@@ -99365,18 +99693,14 @@ function runBang(cmd, opts) {
99365
99693
  let aborted = false;
99366
99694
  let settled = false;
99367
99695
  let detached = false;
99368
- const child = spawn5("bash", ["-c", cmd], {
99369
- cwd: opts.cwd,
99370
- env: opts.env ?? process.env,
99371
- stdio: ["ignore", "pipe", "pipe"],
99372
- detached: process.platform !== "win32"
99373
- });
99696
+ const common = { cwd: opts.cwd, env: opts.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] };
99697
+ const child = import_proc8.IS_WINDOWS ? (0, import_proc8.spawn)(cmd, { ...common, shell: true }) : (0, import_proc8.spawn)("bash", ["-c", cmd], { ...common, detached: true });
99374
99698
  const kill = () => {
99375
99699
  try {
99376
99700
  if (child.pid && process.platform !== "win32")
99377
99701
  process.kill(-child.pid, "SIGTERM");
99378
99702
  else
99379
- child.kill("SIGTERM");
99703
+ (0, import_proc8.killProcessTree)(child.pid);
99380
99704
  } catch {
99381
99705
  }
99382
99706
  setTimeout(() => {
@@ -99537,16 +99861,16 @@ function searchMeta(scope, origin) {
99537
99861
  var SEARCH_HINT = " type to search \xB7 Ctrl+R older \xB7 Ctrl+S all/this project \xB7 Enter/Tab use it \xB7 Esc cancel";
99538
99862
 
99539
99863
  // src/ui/externalEditor.ts
99864
+ var import_proc9 = __toESM(require_proc(), 1);
99540
99865
  import * as fs20 from "fs";
99541
99866
  import * as os13 from "os";
99542
99867
  import * as path20 from "path";
99543
- import { spawnSync as spawnSync4 } from "child_process";
99544
99868
  function resolveEditor(env3) {
99545
99869
  const pick = (v) => v && v.trim() ? v.trim() : null;
99546
99870
  return pick(env3.VISUAL) ?? pick(env3.EDITOR) ?? "vi";
99547
99871
  }
99548
99872
  function defaultRun(editor, file) {
99549
- const r2 = spawnSync4("sh", ["-c", `${editor} "$1"`, "sh", file], { stdio: "inherit" });
99873
+ const r2 = process.platform === "win32" ? (0, import_proc9.spawnSync)(`${editor} "${file}"`, { stdio: "inherit", shell: true }) : (0, import_proc9.spawnSync)("sh", ["-c", `${editor} "$1"`, "sh", file], { stdio: "inherit" });
99550
99874
  return { status: r2.status, error: r2.error };
99551
99875
  }
99552
99876
  function editInEditor(text, opts = {}) {
@@ -99579,7 +99903,7 @@ function editInEditor(text, opts = {}) {
99579
99903
  }
99580
99904
 
99581
99905
  // src/ui/openInEditor.ts
99582
- import { spawn as spawn6, spawnSync as spawnSync5 } from "node:child_process";
99906
+ var import_proc10 = __toESM(require_proc(), 1);
99583
99907
  import * as fs21 from "node:fs";
99584
99908
  import * as os14 from "node:os";
99585
99909
  import * as path21 from "node:path";
@@ -99799,7 +100123,7 @@ function launchEditor(spec, target, opts = {}) {
99799
100123
  const needsShell = /\s/.test(spec.command);
99800
100124
  const argv = () => needsShell ? ["sh", ["-c", `${spec.command} "$@"`, "sh", ...args]] : [spec.command, args];
99801
100125
  if (spec.kind === "gui") {
99802
- const runSpawn = opts.spawnImpl ?? spawn6;
100126
+ const runSpawn = opts.spawnImpl ?? import_proc10.spawn;
99803
100127
  try {
99804
100128
  const child = runSpawn(...argv(), { detached: true, stdio: "ignore" });
99805
100129
  child.on("error", (e2) => opts.onAsyncError?.(`could not start ${spec.command}: ${e2.message}`));
@@ -99809,7 +100133,7 @@ function launchEditor(spec, target, opts = {}) {
99809
100133
  return { ok: false, reason: `could not start ${spec.command}: ${e2.message}` };
99810
100134
  }
99811
100135
  }
99812
- const r2 = (opts.spawnSyncImpl ?? spawnSync5)(...argv(), { stdio: "inherit" });
100136
+ const r2 = (opts.spawnSyncImpl ?? import_proc10.spawnSync)(...argv(), { stdio: "inherit" });
99813
100137
  if (r2.error)
99814
100138
  return { ok: false, reason: `could not start ${spec.command}: ${r2.error.message}` };
99815
100139
  if (typeof r2.status === "number" && r2.status !== 0)
@@ -99826,9 +100150,9 @@ function describeOpen(spec, target, cwd2) {
99826
100150
  }
99827
100151
 
99828
100152
  // src/ui/fileMention.ts
100153
+ var import_proc11 = __toESM(require_proc(), 1);
99829
100154
  import * as fs22 from "fs";
99830
100155
  import * as path22 from "path";
99831
- import { execFile, execFileSync as execFileSync5 } from "child_process";
99832
100156
 
99833
100157
  // src/ui/contextFiles.ts
99834
100158
  var import_code_core52 = __toESM(require_dist2(), 1);
@@ -99873,7 +100197,7 @@ function listProjectFiles(cwd2) {
99873
100197
  function listProjectFilesFrom(cwd2) {
99874
100198
  let files = null;
99875
100199
  try {
99876
- const out = execFileSync5("git", ["-C", cwd2, "ls-files", "-co", "--exclude-standard", "-z"], {
100200
+ const out = (0, import_proc11.execFileSync)("git", ["-C", cwd2, "ls-files", "-co", "--exclude-standard", "-z"], {
99877
100201
  encoding: "utf-8",
99878
100202
  maxBuffer: 64 * 1024 * 1024,
99879
100203
  stdio: ["ignore", "pipe", "ignore"],
@@ -100009,7 +100333,7 @@ function primeMentionIndex(cwd2) {
100009
100333
  building.cancelled = true;
100010
100334
  const job = { cwd: cwd2, cancelled: false };
100011
100335
  building = job;
100012
- execFile(
100336
+ (0, import_proc11.execFile)(
100013
100337
  "git",
100014
100338
  ["-C", cwd2, "ls-files", "-co", "--exclude-standard", "-z"],
100015
100339
  {
@@ -103752,7 +104076,7 @@ function scanRecentSkillEvents(dir, maxFiles = DOCTOR_SESSION_WINDOW) {
103752
104076
  const out = [];
103753
104077
  for (const { full } of withTime.slice(0, maxFiles)) {
103754
104078
  try {
103755
- out.push((0, import_code_core6.readEvents)("", { file: full }));
104079
+ out.push((0, import_code_core7.readEvents)("", { file: full }));
103756
104080
  } catch {
103757
104081
  }
103758
104082
  }
@@ -104364,7 +104688,7 @@ function agentFooterBadge() {
104364
104688
  }
104365
104689
  var runGitForMerge = (cwd2, args) => {
104366
104690
  try {
104367
- const stdout = execFileSync6("git", args, {
104691
+ const stdout = (0, import_proc12.execFileSync)("git", args, {
104368
104692
  cwd: cwd2,
104369
104693
  encoding: "utf-8",
104370
104694
  stdio: ["ignore", "pipe", "pipe"],
@@ -104621,7 +104945,7 @@ function resolveModelLabel(alias) {
104621
104945
  async function tryExecAsync(file, args, cwd2) {
104622
104946
  return new Promise((resolve19) => {
104623
104947
  try {
104624
- execFile2(file, args, { cwd: cwd2, encoding: "utf-8" }, (err, stdout) => {
104948
+ (0, import_proc12.execFile)(file, args, { cwd: cwd2, encoding: "utf-8" }, (err, stdout) => {
104625
104949
  resolve19(err ? void 0 : String(stdout).trim() || void 0);
104626
104950
  });
104627
104951
  } catch {
@@ -105300,7 +105624,7 @@ function emitEvent(type, data = {}) {
105300
105624
  }
105301
105625
  function startSessionLog(id, resumed, extra = {}) {
105302
105626
  const previous = liveSessionId;
105303
- sessionLog = (0, import_code_core6.eventsEnabled)() ? new import_code_core6.EventLog(id) : null;
105627
+ sessionLog = (0, import_code_core7.eventsEnabled)() ? new import_code_core7.EventLog(id) : null;
105304
105628
  liveSessionId = id;
105305
105629
  if (previous && previous !== id)
105306
105630
  (0, import_code_core22.rebindSessionShare)(id);
@@ -105645,7 +105969,7 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env3, nexrall
105645
105969
  emitEvent("tool.started", {
105646
105970
  name,
105647
105971
  sub: !!isSubTask,
105648
- target: name === "use_skill" && typeof input.name === "string" ? input.name : (0, import_code_core6.toolTarget)(name, input)
105972
+ target: name === "use_skill" && typeof input.name === "string" ? input.name : (0, import_code_core7.toolTarget)(name, input)
105649
105973
  });
105650
105974
  if (!isSubTask)
105651
105975
  sessionToolCalls++;
@@ -105698,7 +106022,7 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env3, nexrall
105698
106022
  const changed = noteToolResult(turnStats, tracked?.name ?? name, tracked?.input, cmdOk);
105699
106023
  for (const t2 of changed)
105700
106024
  failureLedger.noteEdit(t2);
105701
- for (const t2 of changed.slice(0, import_code_core6.MAX_FILE_EVENTS))
106025
+ for (const t2 of changed.slice(0, import_code_core7.MAX_FILE_EVENTS))
105702
106026
  emitEvent("file.changed", { path: t2 });
105703
106027
  }
105704
106028
  if (!isSubTask && tracked?.command)
@@ -106040,7 +106364,7 @@ async function runTurnHeadless(messages, modelAlias, workDir, _abortSignal, env3
106040
106364
  onToolUse: (name, input, isSubTask, meta) => {
106041
106365
  debugLog("tool_use", { tool: name, sub: !!isSubTask });
106042
106366
  emit({ type: "tool_use", tool: name, input, ...toolIds(isSubTask, meta) });
106043
- verbose(`[verbose] -> ${name}${isSubTask ? " (sub-agent)" : ""} ${(0, import_code_core6.toolTarget)(name, input)}`);
106367
+ verbose(`[verbose] -> ${name}${isSubTask ? " (sub-agent)" : ""} ${(0, import_code_core7.toolTarget)(name, input)}`);
106044
106368
  },
106045
106369
  // Live bash progress for scripted/CI consumers — lets a wrapper tail a
106046
106370
  // long-running build/test command instead of blocking silently until
@@ -106320,6 +106644,7 @@ function printHelp() {
106320
106644
  ["/yolo", "Auto-approve all permissions"],
106321
106645
  ["/balance", "Show what is paying (personal wallet or team) and what is left"],
106322
106646
  ["/team [use <id|personal>]", "List your teams, or switch what usage is billed to"],
106647
+ ["/logout", "Sign out on this machine (revokes the saved refresh token)"],
106323
106648
  ["/cost [--all]", "Cost and tokens: per model, per sub-agent, per turn (/balance shows the wallet)"],
106324
106649
  ["/stats", "Usage across sessions: activity by day, tokens and models (local event logs)"],
106325
106650
  [
@@ -107036,7 +107361,7 @@ Resume it with: nex --worktree ${worktreeState.name}
107036
107361
  console.log(paint.green(` Resumed session: ${paint.bold(stored.title.slice(0, 60))}`));
107037
107362
  console.log(paint.dim(` ${messages.length} messages restored`));
107038
107363
  if (autoRecap) {
107039
- const recap = (0, import_code_core33.buildRecap)((0, import_code_core6.readEvents)(stored.id, { last: import_code_core33.RECAP_EVENT_WINDOW }), { now: Date.now() });
107364
+ const recap = (0, import_code_core33.buildRecap)((0, import_code_core7.readEvents)(stored.id, { last: import_code_core33.RECAP_EVENT_WINDOW }), { now: Date.now() });
107040
107365
  if (recap)
107041
107366
  console.log(paint.dim(` Recap: ${recap}`));
107042
107367
  }
@@ -108876,6 +109201,26 @@ ${dirList}`;
108876
109201
  rl.prompt();
108877
109202
  return;
108878
109203
  }
109204
+ case "/logout": {
109205
+ const answer = await new Promise(
109206
+ (resolve19) => rl.question(paint.yellow(" Sign out on this machine? ") + paint.dim("[y/n] "), (a) => resolve19(a.trim()))
109207
+ );
109208
+ if (answer !== "y" && answer !== "yes") {
109209
+ console.log(paint.dim(" Cancelled."));
109210
+ rl.prompt();
109211
+ return;
109212
+ }
109213
+ await signOut();
109214
+ console.log(paint.green(" \u2713 Logged out."));
109215
+ if (process.env.NEXRALL_TOKEN?.trim()) {
109216
+ console.log(
109217
+ paint.yellow(" NEXRALL_TOKEN is still set in this shell") + paint.dim(" \u2014 unset it, or the CLI stays signed in with that token.")
109218
+ );
109219
+ }
109220
+ console.log(paint.dim(" Run `nex auth` (in any terminal) to sign in again; this session picks it up."));
109221
+ rl.prompt();
109222
+ return;
109223
+ }
108879
109224
  case "/cost": {
108880
109225
  const parsed = parseCostArgs(arg);
108881
109226
  if ("error" in parsed) {
@@ -108938,14 +109283,14 @@ ${dirList}`;
108938
109283
  return;
108939
109284
  }
108940
109285
  case "/recap": {
108941
- if (!(0, import_code_core6.eventsEnabled)()) {
109286
+ if (!(0, import_code_core7.eventsEnabled)()) {
108942
109287
  console.log(
108943
109288
  paint.dim(" Events are off for this run (NEXRALL_EVENTS=off), so there is nothing to read back.")
108944
109289
  );
108945
109290
  rl.prompt();
108946
109291
  return;
108947
109292
  }
108948
- const recap = (0, import_code_core33.buildRecap)((0, import_code_core6.readEvents)(sessionId, { last: import_code_core33.RECAP_EVENT_WINDOW }), { now: Date.now() });
109293
+ const recap = (0, import_code_core33.buildRecap)((0, import_code_core7.readEvents)(sessionId, { last: import_code_core33.RECAP_EVENT_WINDOW }), { now: Date.now() });
108949
109294
  console.log();
108950
109295
  if (recap)
108951
109296
  console.log(` ${paint.bold("Recap: ")}${recap}`);
@@ -109509,11 +109854,11 @@ ${dirList}`;
109509
109854
  return;
109510
109855
  }
109511
109856
  if (!(0, import_code_core64.getToken)()) {
109512
- console.log(paint.yellow(" Sign in first (`nex login`) \u2014 watching uses your Nexrall account."));
109857
+ console.log(paint.yellow(" Sign in first (`nex auth`) \u2014 watching uses your Nexrall account."));
109513
109858
  rl.prompt();
109514
109859
  return;
109515
109860
  }
109516
- if (!(0, import_code_core6.eventsEnabled)()) {
109861
+ if (!(0, import_code_core7.eventsEnabled)()) {
109517
109862
  console.log(
109518
109863
  paint.yellow(" Sharing follows the event stream, and this run has it off (NEXRALL_EVENTS=off).")
109519
109864
  );
@@ -109617,7 +109962,7 @@ ${dirList}`;
109617
109962
  }
109618
109963
  if (!(0, import_code_core64.getToken)()) {
109619
109964
  console.log(
109620
- paint.yellow(" Sign in first (`nex login`) \u2014 pushes find this session through your account.")
109965
+ paint.yellow(" Sign in first (`nex auth`) \u2014 pushes find this session through your account.")
109621
109966
  );
109622
109967
  rl.prompt();
109623
109968
  return;
@@ -109688,7 +110033,7 @@ ${dirList}`;
109688
110033
  }
109689
110034
  case "/schedule":
109690
110035
  case "/routines": {
109691
- const action = (0, import_code_core3.parseScheduleChatArg)(arg);
110036
+ const action = (0, import_code_core4.parseScheduleChatArg)(arg);
109692
110037
  if (action.kind === "error") {
109693
110038
  console.log(paint.yellow(" " + action.message));
109694
110039
  rl.prompt();
@@ -109699,7 +110044,7 @@ ${dirList}`;
109699
110044
  const panelCols = Math.max(60, (process.stdout.columns || 100) - 2);
109700
110045
  if (action.kind === "list") {
109701
110046
  const list = await (0, import_code_core63.listCloudSchedules)();
109702
- for (const l of (0, import_code_core3.scheduleListLines)(list, { cols: panelCols }))
110047
+ for (const l of (0, import_code_core4.scheduleListLines)(list, { cols: panelCols }))
109703
110048
  console.log(" " + l);
109704
110049
  if (list.length)
109705
110050
  console.log(
@@ -109709,7 +110054,7 @@ ${dirList}`;
109709
110054
  const s2 = await (0, import_code_core63.createCloudSchedule)({ task: action.task, intervalMinutes: action.intervalMinutes });
109710
110055
  console.log(
109711
110056
  paint.green(
109712
- ` \u2713 Scheduled #${s2.id} \u2014 every ${(0, import_code_core3.formatEvery)(s2.intervalMinutes)}${s2.nextRunAt ? `, next run ${(0, import_code_core3.fmtScheduleWhen)(s2.nextRunAt)}` : ""}.`
110057
+ ` \u2713 Scheduled #${s2.id} \u2014 every ${(0, import_code_core4.formatEvery)(s2.intervalMinutes)}${s2.nextRunAt ? `, next run ${(0, import_code_core4.fmtScheduleWhen)(s2.nextRunAt)}` : ""}.`
109713
110058
  )
109714
110059
  );
109715
110060
  console.log(
@@ -109727,7 +110072,7 @@ ${dirList}`;
109727
110072
  console.log(paint.dim(` Removed schedule #${action.id} \u2014 no further runs fire.`));
109728
110073
  } else {
109729
110074
  const runs2 = await (0, import_code_core63.getCloudScheduleRuns)(action.id);
109730
- for (const l of (0, import_code_core3.scheduleRunsLines)(runs2, { cols: panelCols }))
110075
+ for (const l of (0, import_code_core4.scheduleRunsLines)(runs2, { cols: panelCols }))
109731
110076
  console.log(" " + l);
109732
110077
  }
109733
110078
  } catch (err) {
@@ -109945,7 +110290,7 @@ ${dirList}`;
109945
110290
  };
109946
110291
  const want = arg.trim();
109947
110292
  if (want) {
109948
- const hit = (0, import_code_core7.findFiles)(files, want);
110293
+ const hit = (0, import_code_core8.findFiles)(files, want);
109949
110294
  if (!hit.length)
109950
110295
  console.log(paint.dim(` No changed file matches "${want}". (/diff lists them all)`));
109951
110296
  else if (hit.length > 1) {
@@ -109954,14 +110299,14 @@ ${dirList}`;
109954
110299
  console.log(" " + f3.path);
109955
110300
  } else {
109956
110301
  verification.noteDiffReviewed();
109957
- out((0, import_code_core7.capLines)((0, import_code_core7.renderFile)(hit[0], { foldHunks: false })));
110302
+ out((0, import_code_core8.capLines)((0, import_code_core8.renderFile)(hit[0], { foldHunks: false })));
109958
110303
  }
109959
110304
  } else {
109960
110305
  console.log(paint.bold(" Uncommitted changes"));
109961
- out((0, import_code_core7.summaryLines)(files));
110306
+ out((0, import_code_core8.summaryLines)(files));
109962
110307
  console.log();
109963
110308
  verification.noteDiffReviewed();
109964
- out((0, import_code_core7.renderAll)(files));
110309
+ out((0, import_code_core8.renderAll)(files));
109965
110310
  }
109966
110311
  rl.prompt();
109967
110312
  return;
@@ -109982,7 +110327,7 @@ ${dirList}`;
109982
110327
  const emit = (line) => console.log(truncateCells(line, cols3));
109983
110328
  const want = arg.replace(/(^|\s)--all(?=\s|$)/, " ").trim();
109984
110329
  if (want) {
109985
- const hit = (0, import_code_core7.findFiles)(files, want);
110330
+ const hit = (0, import_code_core8.findFiles)(files, want);
109986
110331
  if (!hit.length)
109987
110332
  emit(paint.dim(` No changed file matches "${want}". (/review lists them all)`));
109988
110333
  else if (hit.length > 1) {
@@ -109990,14 +110335,14 @@ ${dirList}`;
109990
110335
  for (const f3 of hit.slice(0, 10))
109991
110336
  emit(" " + f3.path);
109992
110337
  } else {
109993
- const ctx = { tests: files.filter((x2) => (0, import_code_core8.isTestPath)(x2.path)) };
109994
- for (const line of (0, import_code_core8.formatReviewDetail)((0, import_code_core8.classifyFile)(hit[0], ctx), cols3))
110338
+ const ctx = { tests: files.filter((x2) => (0, import_code_core9.isTestPath)(x2.path)) };
110339
+ for (const line of (0, import_code_core9.formatReviewDetail)((0, import_code_core9.classifyFile)(hit[0], ctx), cols3))
109995
110340
  emit(" " + line);
109996
110341
  }
109997
110342
  } else {
109998
110343
  const all = /(^|\s)--all(\s|$)/.test(arg);
109999
- const q = (0, import_code_core8.buildReviewQueue)(files, all ? Number.POSITIVE_INFINITY : import_code_core8.DEFAULT_PER_GROUP);
110000
- for (const line of (0, import_code_core8.formatReviewQueue)(q, cols3))
110344
+ const q = (0, import_code_core9.buildReviewQueue)(files, all ? Number.POSITIVE_INFINITY : import_code_core9.DEFAULT_PER_GROUP);
110345
+ for (const line of (0, import_code_core9.formatReviewQueue)(q, cols3))
110001
110346
  emit(" " + line);
110002
110347
  emit(paint.dim(" /review <file> for one entry's reasons \xB7 /diff for the change itself"));
110003
110348
  }
@@ -110643,7 +110988,7 @@ ${text}
110643
110988
  const res = await enableAppleTerminalOptionAsMeta({
110644
110989
  run: async (cmd2, args) => {
110645
110990
  try {
110646
- const stdout = execFileSync6(cmd2, args, { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
110991
+ const stdout = (0, import_proc12.execFileSync)(cmd2, args, { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
110647
110992
  return { code: 0, stdout };
110648
110993
  } catch (err) {
110649
110994
  const e2 = err;
@@ -110774,7 +111119,7 @@ ${text}
110774
111119
  }
110775
111120
  case "/skill-doctor": {
110776
111121
  const loadedSkills = (0, import_code_core66.loadSkills)(workDir);
110777
- const usage2 = collectSkillUsage(scanRecentSkillEvents((0, import_code_core6.eventsDir)()));
111122
+ const usage2 = collectSkillUsage(scanRecentSkillEvents((0, import_code_core7.eventsDir)()));
110778
111123
  for (const l of buildSkillDoctorReport(loadedSkills, usage2).lines)
110779
111124
  console.log(l);
110780
111125
  rl.prompt();
@@ -112212,11 +112557,11 @@ function pluginSourceRemoveCommand(name, opts) {
112212
112557
  }
112213
112558
 
112214
112559
  // src/commands/pluginEvalCmd.ts
112560
+ var import_proc13 = __toESM(require_proc(), 1);
112215
112561
  var import_code_core71 = __toESM(require_dist2(), 1);
112216
112562
  import * as fs27 from "fs";
112217
112563
  import * as os18 from "os";
112218
112564
  import * as path28 from "path";
112219
- import { spawn as spawn7 } from "node:child_process";
112220
112565
  function pluginEvalInitCommand(dir) {
112221
112566
  const target = path28.resolve(dir ?? process.cwd());
112222
112567
  const displayPath = (p) => {
@@ -112328,7 +112673,7 @@ function walkFiles(root) {
112328
112673
  }
112329
112674
  function runChild(args, cwd2, env3, timeoutMs) {
112330
112675
  return new Promise((resolve19) => {
112331
- const child = spawn7(process.execPath, args, {
112676
+ const child = (0, import_proc13.spawn)(process.execPath, args, {
112332
112677
  cwd: cwd2,
112333
112678
  env: env3,
112334
112679
  stdio: ["ignore", "pipe", "pipe"]
@@ -112682,7 +113027,7 @@ function planProjectPurge(targetDir, env3 = process.env) {
112682
113027
  }
112683
113028
  }
112684
113029
  for (const id of sessionIds) {
112685
- const p = (0, import_code_core6.eventsPath)(id, env3);
113030
+ const p = (0, import_code_core7.eventsPath)(id, env3);
112686
113031
  if (fs28.existsSync(p))
112687
113032
  items.push({ kind: "events", path: p, dir: false });
112688
113033
  }
@@ -112836,11 +113181,11 @@ async function projectPurgeCommand(dir, opts = {}) {
112836
113181
  }
112837
113182
 
112838
113183
  // src/commands/sessionPlugins.ts
113184
+ var import_proc14 = __toESM(require_proc(), 1);
112839
113185
  var import_code_core73 = __toESM(require_dist2(), 1);
112840
113186
  import * as fs29 from "node:fs";
112841
113187
  import * as os20 from "node:os";
112842
113188
  import * as path30 from "node:path";
112843
- import { spawnSync as spawnSync6 } from "node:child_process";
112844
113189
  var MAX_ARCHIVE_BYTES = 50 * 1024 * 1024;
112845
113190
  function mkTemp(label) {
112846
113191
  return fs29.mkdtempSync(path30.join(os20.tmpdir(), `nex-${label}-`));
@@ -112862,7 +113207,14 @@ function descendIntoWrapper(root) {
112862
113207
  return root;
112863
113208
  }
112864
113209
  function extractZip(archive, dest) {
112865
- const r2 = spawnSync6("unzip", ["-o", "-q", archive, "-d", dest], { encoding: "utf-8", timeout: 6e4 });
113210
+ if (process.platform === "win32") {
113211
+ const t2 = (0, import_proc14.spawnSync)("tar", ["-xf", archive, "-C", dest], { encoding: "utf-8", timeout: 6e4 });
113212
+ if (t2.status !== 0) {
113213
+ return { ok: false, error: `tar failed: ${(t2.stderr ?? "").trim() || (t2.error?.message ?? "unknown error")}` };
113214
+ }
113215
+ return { ok: true };
113216
+ }
113217
+ const r2 = (0, import_proc14.spawnSync)("unzip", ["-o", "-q", archive, "-d", dest], { encoding: "utf-8", timeout: 6e4 });
112866
113218
  if (r2.error && r2.error.code === "ENOENT") {
112867
113219
  return { ok: false, error: "The `unzip` command was not found \u2014 install it, or use a .tar.gz archive." };
112868
113220
  }
@@ -112872,7 +113224,7 @@ function extractZip(archive, dest) {
112872
113224
  return { ok: true };
112873
113225
  }
112874
113226
  function extractTarGz(archive, dest) {
112875
- const r2 = spawnSync6("tar", ["-xzf", archive, "-C", dest], { encoding: "utf-8", timeout: 6e4 });
113227
+ const r2 = (0, import_proc14.spawnSync)("tar", ["-xzf", archive, "-C", dest], { encoding: "utf-8", timeout: 6e4 });
112876
113228
  if (r2.status !== 0) {
112877
113229
  return { ok: false, error: `tar failed: ${(r2.stderr ?? "").trim() || (r2.error?.message ?? "unknown error")}` };
112878
113230
  }
@@ -113239,11 +113591,11 @@ async function autoModeResetCommand(opts) {
113239
113591
  var import_code_core79 = __toESM(require_dist2(), 1);
113240
113592
 
113241
113593
  // src/commands/bgJobs.ts
113594
+ var import_proc15 = __toESM(require_proc(), 1);
113242
113595
  import * as fs31 from "node:fs";
113243
113596
  import * as os22 from "node:os";
113244
113597
  import * as path32 from "node:path";
113245
113598
  import * as crypto5 from "node:crypto";
113246
- import { spawn as spawn8 } from "node:child_process";
113247
113599
  function bgDir(env3 = process.env) {
113248
113600
  return env3.NEXRALL_CLI_BG_DIR || path32.join(os22.homedir(), ".nexrall", "cli-bg");
113249
113601
  }
@@ -113306,9 +113658,11 @@ function startJob(o) {
113306
113658
  const codeFile = path32.join(dir, `${id}.code`);
113307
113659
  const fd = fs31.openSync(log, "a");
113308
113660
  const command = o.shell !== void 0 ? ["/bin/sh", "-c", o.shell] : [o.execPath ?? process.execPath, o.script ?? "", ...o.args ?? []];
113309
- const child = spawn8("/bin/sh", ["-c", '"$@"; echo $? > "$0"', codeFile, ...command], {
113661
+ const [wrapBin, wrapArgs] = wrapperArgv(codeFile, command, o.shell, process.execPath);
113662
+ const child = (0, import_proc15.spawn)(wrapBin, wrapArgs, {
113310
113663
  cwd: o.cwd,
113311
- detached: true,
113664
+ detached: !import_proc15.IS_WINDOWS,
113665
+ // detached on Windows = DETACHED_PROCESS: ignores windowsHide, pops a console
113312
113666
  stdio: ["ignore", fd, fd],
113313
113667
  env: { ...process.env, NEXRALL_BG_JOB: id }
113314
113668
  });
@@ -113368,6 +113722,23 @@ function respawnJob(job, opts) {
113368
113722
  });
113369
113723
  return { ok: true, job: meta };
113370
113724
  }
113725
+ var WIN_WRAPPER = [
113726
+ "const {spawn}=require('child_process'),fs=require('fs');",
113727
+ "const [codeFile,mode,...rest]=process.argv.slice(1);",
113728
+ "const o={stdio:'inherit',windowsHide:true};",
113729
+ "const c=mode==='shell'?spawn(rest[0],{...o,shell:true}):spawn(rest[0],rest.slice(1),o);",
113730
+ "c.on('error',()=>{fs.writeFileSync(codeFile,'127\\n');process.exit(127)});",
113731
+ "c.on('exit',(code)=>{fs.writeFileSync(codeFile,String(code??1)+'\\n');process.exit(code??1)});"
113732
+ ].join("");
113733
+ function wrapperArgv(codeFile, command, shell, nodePath) {
113734
+ if (import_proc15.IS_WINDOWS) {
113735
+ return [
113736
+ nodePath,
113737
+ ["-e", WIN_WRAPPER, codeFile, shell !== void 0 ? "shell" : "argv", ...shell !== void 0 ? [shell] : command]
113738
+ ];
113739
+ }
113740
+ return ["/bin/sh", ["-c", '"$@"; echo $? > "$0"', codeFile, ...command]];
113741
+ }
113371
113742
  function killJob(job, dir = bgDir()) {
113372
113743
  if (job.state !== "running")
113373
113744
  return false;
@@ -113375,6 +113746,10 @@ function killJob(job, dir = bgDir()) {
113375
113746
  fs31.writeFileSync(path32.join(dir, `${job.id}.killed`), "");
113376
113747
  } catch {
113377
113748
  }
113749
+ if (import_proc15.IS_WINDOWS) {
113750
+ (0, import_proc15.killProcessTree)(job.pid);
113751
+ return true;
113752
+ }
113378
113753
  try {
113379
113754
  process.kill(-job.pid, "SIGTERM");
113380
113755
  return true;
@@ -113936,7 +114311,7 @@ var NEX_VERSION = require3("../package.json").version;
113936
114311
  installEpipeGuard();
113937
114312
  var program2 = new Command();
113938
114313
  program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version(NEX_VERSION).enablePositionalOptions();
113939
- var auth = program2.command("auth").description("Login to your Nexrall account").action(authCommand);
114314
+ var auth = program2.command("auth").alias("login").description("Log in (browser, email + password, or a token)").option("--browser", "Sign in through the browser \u2014 works for Google, Apple and SSO accounts").option("--code <code>", "Finish a browser sign-in with a code you already copied (no browser is opened)").option("--token <token>", "Save a token directly (CI/headless). Prefer NEXRALL_TOKEN where you can").option("--password", "Ask for email and password in this terminal (skips the method menu)").action(authCommand);
113940
114315
  auth.command("status").description("Show whether you are logged in (exit 0 = yes, 1 = no). --json for scripts; the token is never printed").option("--json", "Machine-readable output").action((opts) => {
113941
114316
  const r2 = authStatusReport((0, import_code_core79.loadAuth)(), process.env);
113942
114317
  if (opts.json)
@@ -114394,7 +114769,7 @@ program2.command("sessions").description("List, export, import, or delete saved
114394
114769
  process.exitCode = 1;
114395
114770
  return;
114396
114771
  }
114397
- const events = (0, import_code_core6.readEvents)(hit.id, { last: Number.isFinite(want) && want > 0 ? want : 20 });
114772
+ const events = (0, import_code_core7.readEvents)(hit.id, { last: Number.isFinite(want) && want > 0 ? want : 20 });
114398
114773
  if (!events.length) {
114399
114774
  console.log(
114400
114775
  paint.dim(` No events recorded for ${hit.id.slice(0, 8)} (NEXRALL_EVENTS=off disables the stream).`)
@@ -114409,9 +114784,9 @@ program2.command("sessions").description("List, export, import, or delete saved
114409
114784
  console.log();
114410
114785
  console.log(paint.bold(` Events for ${hit.id.slice(0, 8)} `) + paint.dim(`(last ${events.length})`));
114411
114786
  for (const ev of events)
114412
- console.log(" " + paint.dim((0, import_code_core6.summarizeEvent)(ev)));
114787
+ console.log(" " + paint.dim((0, import_code_core7.summarizeEvent)(ev)));
114413
114788
  console.log(paint.dim(`
114414
- Raw JSONL: ${(0, import_code_core6.eventsPath)(hit.id)}`));
114789
+ Raw JSONL: ${(0, import_code_core7.eventsPath)(hit.id)}`));
114415
114790
  console.log();
114416
114791
  return;
114417
114792
  }