nexrall-code 0.5.110 → 0.5.112

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 (2) hide show
  1. package/dist/index.js +241 -135
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3182,12 +3182,11 @@ var require_auth = __commonJS({
3182
3182
  exports2.saveAuth = saveAuth2;
3183
3183
  exports2.loadAuth = loadAuth2;
3184
3184
  exports2.clearAuth = clearAuth2;
3185
- exports2.isAuthenticated = isAuthenticated3;
3185
+ exports2.isAuthenticated = isAuthenticated4;
3186
3186
  exports2.getToken = getToken;
3187
3187
  exports2.getRefreshToken = getRefreshToken;
3188
3188
  exports2.updateTokens = updateTokens;
3189
- exports2.getBillingTeamId = getBillingTeamId;
3190
- exports2.setBillingTeamId = setBillingTeamId;
3189
+ exports2.getBillingTeamOverride = getBillingTeamOverride;
3191
3190
  var fs9 = __importStar(__require("fs"));
3192
3191
  var path8 = __importStar(__require("path"));
3193
3192
  var os6 = __importStar(__require("os"));
@@ -3229,7 +3228,7 @@ var require_auth = __commonJS({
3229
3228
  } catch {
3230
3229
  }
3231
3230
  }
3232
- function isAuthenticated3() {
3231
+ function isAuthenticated4() {
3233
3232
  const auth = loadAuth2();
3234
3233
  return auth !== null && auth.token.length > 0;
3235
3234
  }
@@ -3265,29 +3264,21 @@ var require_auth = __commonJS({
3265
3264
  };
3266
3265
  fs9.writeFileSync(CONFIG_FILE, JSON.stringify(next, null, 2), { mode: 384 });
3267
3266
  }
3268
- function getBillingTeamId() {
3269
- const auth = loadAuth2();
3270
- const v = auth?.billingTeamId;
3271
- return typeof v === "number" && Number.isSafeInteger(v) && v > 0 ? v : null;
3272
- }
3273
- function setBillingTeamId(teamId) {
3274
- let existing = {};
3275
- try {
3276
- if (fs9.existsSync(CONFIG_FILE)) {
3277
- const parsed = JSON.parse(fs9.readFileSync(CONFIG_FILE, "utf-8"));
3278
- if (typeof parsed === "object" && parsed !== null)
3279
- existing = parsed;
3267
+ function getBillingTeamOverride() {
3268
+ const raw = process.env.NEXRALL_BILLING_TEAM;
3269
+ if (raw != null && raw !== "") {
3270
+ const trimmed = raw.trim();
3271
+ if (/^(personal|null|0)$/i.test(trimmed))
3272
+ return null;
3273
+ if (/^\d+$/.test(trimmed)) {
3274
+ const n = Number(trimmed);
3275
+ if (Number.isSafeInteger(n) && n > 0)
3276
+ return n;
3280
3277
  }
3281
- } catch {
3282
3278
  }
3283
- ensureConfigDir();
3284
- const next = { ...existing };
3285
- if (typeof teamId === "number" && Number.isSafeInteger(teamId) && teamId > 0) {
3286
- next.billingTeamId = teamId;
3287
- } else {
3288
- delete next.billingTeamId;
3289
- }
3290
- fs9.writeFileSync(CONFIG_FILE, JSON.stringify(next, null, 2), { mode: 384 });
3279
+ if (process.env.NEXRALL_TOKEN)
3280
+ return null;
3281
+ return void 0;
3291
3282
  }
3292
3283
  }
3293
3284
  });
@@ -9929,7 +9920,9 @@ var require_client = __commonJS({
9929
9920
  exports2.revokeRefreshToken = revokeRefreshToken2;
9930
9921
  exports2.describeAttachment = describeAttachment2;
9931
9922
  exports2.getBalance = getBalance3;
9932
- exports2.getOrgs = getOrgs;
9923
+ exports2.billingOverrideFields = billingOverrideFields2;
9924
+ exports2.setBillingTarget = setBillingTarget2;
9925
+ exports2.getOrgs = getOrgs2;
9933
9926
  exports2.getCodeModels = getCodeModels;
9934
9927
  exports2.getUsageDaily = getUsageDaily;
9935
9928
  exports2.exchangeVscodeCode = exchangeVscodeCode;
@@ -10118,7 +10111,7 @@ var require_client = __commonJS({
10118
10111
  {
10119
10112
  method: "POST",
10120
10113
  headers: authHeaders(),
10121
- body: JSON.stringify({ messages, model, env: env4, editorContext, nexrallMd, mode, effort, clientType, extraTools, agents, skills, turnId, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents, canBrowseWeb, teamId: (0, index_1.getBillingTeamId)() }),
10114
+ body: JSON.stringify({ messages, model, env: env4, editorContext, nexrallMd, mode, effort, clientType, extraTools, agents, skills, turnId, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents, canBrowseWeb, ...billingOverrideFields2() }),
10122
10115
  signal
10123
10116
  }
10124
10117
  ];
@@ -10690,7 +10683,7 @@ var require_client = __commonJS({
10690
10683
  const fetchOnce = () => (0, node_fetch_1.default)(`${exports2.API_BASE}/api/code/assets/describe`, {
10691
10684
  method: "POST",
10692
10685
  headers: { ...authHeaders(), "Content-Type": "application/json" },
10693
- body: JSON.stringify({ kind, data, media_type: mediaType, name, teamId: (0, index_1.getBillingTeamId)() })
10686
+ body: JSON.stringify({ kind, data, media_type: mediaType, name, ...billingOverrideFields2() })
10694
10687
  });
10695
10688
  let response = await fetchOnce();
10696
10689
  if (response.status === 401 || response.status === 403) {
@@ -10735,7 +10728,28 @@ var require_client = __commonJS({
10735
10728
  const data = await response.json();
10736
10729
  return typeof data.balance === "number" ? data.balance : 0;
10737
10730
  }
10738
- async function getOrgs() {
10731
+ function billingOverrideFields2() {
10732
+ const override = (0, index_1.getBillingTeamOverride)();
10733
+ return override === void 0 ? {} : { teamId: override };
10734
+ }
10735
+ async function setBillingTarget2(teamId) {
10736
+ const response = await (0, node_fetch_1.default)(`${exports2.API_BASE}/api/user/billing-target`, {
10737
+ method: "PUT",
10738
+ headers: authHeaders(),
10739
+ body: JSON.stringify({ teamId })
10740
+ });
10741
+ if (!response.ok) {
10742
+ let message = `API error ${response.status}`;
10743
+ try {
10744
+ const parsed = await response.json();
10745
+ if (parsed.error)
10746
+ message = parsed.error;
10747
+ } catch {
10748
+ }
10749
+ throw new Error(message);
10750
+ }
10751
+ }
10752
+ async function getOrgs2() {
10739
10753
  const fetchOnce = () => (0, node_fetch_1.default)(`${exports2.API_BASE}/api/code/orgs`, { method: "GET", headers: authHeaders() });
10740
10754
  let response = await fetchOnce();
10741
10755
  if (response.status === 401 || response.status === 403) {
@@ -10752,7 +10766,8 @@ var require_client = __commonJS({
10752
10766
  const json = await response.json();
10753
10767
  return {
10754
10768
  personal: { balance: typeof json.personal?.balance === "number" ? json.personal.balance : 0 },
10755
- teams: Array.isArray(json.teams) ? json.teams : []
10769
+ teams: Array.isArray(json.teams) ? json.teams : [],
10770
+ billingTargetTeamId: typeof json.billingTargetTeamId === "number" ? json.billingTargetTeamId : null
10756
10771
  };
10757
10772
  }
10758
10773
  async function getCodeModels() {
@@ -101044,13 +101059,14 @@ var require_executor = __commonJS({
101044
101059
  var child_process_1 = __require("child_process");
101045
101060
  var sandbox_1 = require_sandbox();
101046
101061
  var auth_1 = require_auth();
101062
+ var client_1 = require_client();
101047
101063
  var editCompleteness_1 = require_editCompleteness();
101048
101064
  var securityLint_1 = require_securityLint();
101049
101065
  var memory_1 = require_memory();
101050
101066
  var skills_1 = require_skills();
101051
101067
  var testIntegrity_1 = require_testIntegrity();
101052
101068
  var crossFile_1 = require_crossFile();
101053
- var client_1 = require_client();
101069
+ var client_2 = require_client();
101054
101070
  var symbols_1 = require_symbols();
101055
101071
  var tsLangService_1 = require_tsLangService();
101056
101072
  var safeSlice_1 = require_safeSlice();
@@ -103007,7 +103023,7 @@ ${lines.join("\n")}`;
103007
103023
  let cost;
103008
103024
  let balance;
103009
103025
  try {
103010
- const r2 = await _httpsPost(`${client_1.API_BASE}/api/code/assets/generate`, JSON.stringify({ prompt: prompt2, aspect_ratio: aspectRatio, teamId: (0, auth_1.getBillingTeamId)() }), { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, 17e4, abortSignal);
103026
+ const r2 = await _httpsPost(`${client_2.API_BASE}/api/code/assets/generate`, JSON.stringify({ prompt: prompt2, aspect_ratio: aspectRatio, ...(0, client_1.billingOverrideFields)() }), { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, 17e4, abortSignal);
103011
103027
  let json = {};
103012
103028
  try {
103013
103029
  json = JSON.parse(r2.body);
@@ -103056,7 +103072,7 @@ ${lines.join("\n")}`;
103056
103072
  return { error: "Not authenticated. Run `nexrall-code login` first." };
103057
103073
  let photos;
103058
103074
  try {
103059
- const u = new URL(`${client_1.API_BASE}/api/code/assets/stock`);
103075
+ const u = new URL(`${client_2.API_BASE}/api/code/assets/stock`);
103060
103076
  u.searchParams.set("query", query);
103061
103077
  u.searchParams.set("count", String(count));
103062
103078
  if (orientation)
@@ -103112,7 +103128,7 @@ ${lines.join("\n")}` };
103112
103128
  if (!token)
103113
103129
  return { error: "Not authenticated. Run `nexrall-code login` first." };
103114
103130
  try {
103115
- const r2 = await _httpsPost(`${client_1.API_BASE}/api/code/tools/web_search`, JSON.stringify({ query, teamId: (0, auth_1.getBillingTeamId)() }), { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, 3e4, abortSignal);
103131
+ 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);
103116
103132
  let json = {};
103117
103133
  try {
103118
103134
  json = JSON.parse(r2.body);
@@ -104891,7 +104907,6 @@ var require_loop = __commonJS({
104891
104907
  exports2.trimToResumableBoundary = trimToResumableBoundary;
104892
104908
  var types_1 = require_types();
104893
104909
  var client_1 = require_client();
104894
- var index_1 = require_auth();
104895
104910
  var executor_1 = require_executor();
104896
104911
  var agentTypes_1 = require_agentTypes();
104897
104912
  var skills_1 = require_skills();
@@ -104904,7 +104919,7 @@ var require_loop = __commonJS({
104904
104919
  var worktreeEnforcement_1 = require_worktreeEnforcement();
104905
104920
  var agentRegistry_1 = require_agentRegistry();
104906
104921
  var sandbox_1 = require_sandbox();
104907
- var index_2 = require_plugins();
104922
+ var index_1 = require_plugins();
104908
104923
  var testIntegrity_1 = require_testIntegrity();
104909
104924
  var flaky_1 = require_flaky();
104910
104925
  var claimEvidence_1 = require_claimEvidence();
@@ -104924,7 +104939,7 @@ var require_loop = __commonJS({
104924
104939
  fromSettings = JSON.parse(fs9.readFileSync(p, "utf-8")).hooks ?? {};
104925
104940
  } catch {
104926
104941
  }
104927
- const fromPlugins = (0, index_2.pluginHooks)(workDir);
104942
+ const fromPlugins = (0, index_1.pluginHooks)(workDir);
104928
104943
  const merged = { ...fromSettings };
104929
104944
  for (const phase of Object.keys(fromPlugins)) {
104930
104945
  const extra = fromPlugins[phase];
@@ -106447,7 +106462,6 @@ Continue the work from here.` }] });
106447
106462
  break;
106448
106463
  }
106449
106464
  if (status === 403 && typeof code === "string" && TEAM_SCOPE_ERROR_CODES.has(code)) {
106450
- (0, index_1.setBillingTeamId)(null);
106451
106465
  stopReason = "team-unavailable";
106452
106466
  break;
106453
106467
  }
@@ -143350,7 +143364,7 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
143350
143364
  var source_default = chalk;
143351
143365
 
143352
143366
  // src/index.ts
143353
- var import_code_core7 = __toESM(require_dist3(), 1);
143367
+ var import_code_core8 = __toESM(require_dist3(), 1);
143354
143368
 
143355
143369
  // src/commands/auth.ts
143356
143370
  import * as readline from "readline";
@@ -143474,6 +143488,90 @@ function stopSpinner(handle2) {
143474
143488
  process.stdout.write("\r\x1B[K");
143475
143489
  }
143476
143490
 
143491
+ // src/commands/billing.ts
143492
+ var import_code_core2 = __toESM(require_dist3(), 1);
143493
+ function money(usd) {
143494
+ return "$" + usd.toFixed(2);
143495
+ }
143496
+ async function requireAuth() {
143497
+ if ((0, import_code_core2.isAuthenticated)())
143498
+ return true;
143499
+ console.log(source_default.red("Not logged in. Run `nex auth` first."));
143500
+ return false;
143501
+ }
143502
+ async function billingStatusCommand() {
143503
+ if (!await requireAuth())
143504
+ return;
143505
+ let orgs;
143506
+ try {
143507
+ orgs = await (0, import_code_core2.getOrgs)();
143508
+ } catch {
143509
+ console.log(source_default.yellow("Could not read your billing target (offline, or a server without team support)."));
143510
+ return;
143511
+ }
143512
+ const targetId = orgs.billingTargetTeamId ?? null;
143513
+ const team = targetId == null ? null : orgs.teams.find((t2) => t2.id === targetId) ?? null;
143514
+ console.log("");
143515
+ console.log(source_default.bold("Billing target"));
143516
+ if (team) {
143517
+ console.log(` ${source_default.cyan(team.name)} ${source_default.gray(`(${money(team.remainingUsd)} left this month)`)}`);
143518
+ if (team.remainingUsd <= 0) {
143519
+ console.log(source_default.yellow(" \u26A0 This team has no budget left \u2014 ask a team admin to add funds."));
143520
+ }
143521
+ } else if (targetId != null) {
143522
+ console.log(` ${source_default.yellow(`team ${targetId}`)} ${source_default.gray("(not available to this account \u2014 usage falls back to your wallet)")}`);
143523
+ } else {
143524
+ console.log(` Personal wallet ${source_default.gray(`(${money(orgs.personal.balance)} available)`)}`);
143525
+ }
143526
+ if (orgs.teams.length > 0) {
143527
+ console.log("");
143528
+ console.log(source_default.gray("Teams you can bill to:"));
143529
+ for (const t2 of orgs.teams) {
143530
+ const marker = t2.id === targetId ? source_default.green(" \u2190 current") : "";
143531
+ const state = t2.remainingUsd > 0 ? source_default.gray(`${money(t2.remainingUsd)} left`) : source_default.yellow("no budget left");
143532
+ console.log(` ${source_default.bold(String(t2.id))} ${t2.name} ${state}${marker}`);
143533
+ }
143534
+ console.log("");
143535
+ console.log(source_default.gray("Change it with `nex billing use <id>` or `nex billing use personal`."));
143536
+ }
143537
+ const override = (0, import_code_core2.billingOverrideFields)();
143538
+ if ("teamId" in override) {
143539
+ console.log("");
143540
+ console.log(source_default.yellow(
143541
+ `Note: NEXRALL_BILLING_TEAM pins this run to ${override.teamId === null ? "your personal wallet" : `team ${override.teamId}`}, ignoring the account setting above.`
143542
+ ));
143543
+ }
143544
+ console.log("");
143545
+ }
143546
+ async function billingUseCommand(target) {
143547
+ if (!await requireAuth())
143548
+ return;
143549
+ const raw = (target || "").trim();
143550
+ if (/^(personal|null|0)$/i.test(raw)) {
143551
+ await applyTarget(null, "your personal wallet");
143552
+ return;
143553
+ }
143554
+ if (!/^\d+$/.test(raw)) {
143555
+ console.log(source_default.red("Usage: nex billing use <team id|personal> (see `nex billing` for the ids)"));
143556
+ process.exitCode = 1;
143557
+ return;
143558
+ }
143559
+ await applyTarget(Number(raw), `team ${raw}`);
143560
+ }
143561
+ async function applyTarget(teamId, label) {
143562
+ try {
143563
+ await (0, import_code_core2.setBillingTarget)(teamId);
143564
+ } catch (e2) {
143565
+ console.log(source_default.red(e2.message));
143566
+ process.exitCode = 1;
143567
+ return;
143568
+ }
143569
+ console.log(source_default.green(`\u2713 Usage will now be billed to ${label}.`));
143570
+ if (teamId !== null) {
143571
+ console.log(source_default.gray(" This applies to every product and client on this account, not just the CLI."));
143572
+ }
143573
+ }
143574
+
143477
143575
  // src/commands/chat.ts
143478
143576
  import * as readline3 from "readline";
143479
143577
  import * as path6 from "path";
@@ -143483,7 +143581,7 @@ import * as crypto4 from "crypto";
143483
143581
  import { createRequire } from "module";
143484
143582
  import { fileURLToPath as fileURLToPath2 } from "url";
143485
143583
  import { execSync, execFileSync as execFileSync2 } from "child_process";
143486
- var import_code_core4 = __toESM(require_dist3(), 1);
143584
+ var import_code_core5 = __toESM(require_dist3(), 1);
143487
143585
 
143488
143586
  // ../../node_modules/.pnpm/ansi-regex@6.2.2/node_modules/ansi-regex/index.js
143489
143587
  function ansiRegex({ onlyFirst = false } = {}) {
@@ -144441,18 +144539,18 @@ function showDiff(filePath, oldContent, newContent) {
144441
144539
  }
144442
144540
 
144443
144541
  // src/permissions/handler.ts
144444
- var import_code_core2 = __toESM(require_dist3(), 1);
144542
+ var import_code_core3 = __toESM(require_dist3(), 1);
144445
144543
  var autoApproved = /* @__PURE__ */ new Set();
144446
144544
  var _rules = { allow: [], ask: [], deny: [] };
144447
144545
  var _workDir = process.cwd();
144448
144546
  var _mode = "ask";
144449
144547
  function initPermissions(workDir) {
144450
144548
  _workDir = workDir;
144451
- _rules = (0, import_code_core2.loadSettings)(workDir).permissions;
144549
+ _rules = (0, import_code_core3.loadSettings)(workDir).permissions;
144452
144550
  return _rules;
144453
144551
  }
144454
144552
  function setMode(mode) {
144455
- _mode = (0, import_code_core2.parseMode)(mode);
144553
+ _mode = (0, import_code_core3.parseMode)(mode);
144456
144554
  }
144457
144555
  function setAutoApprove(category) {
144458
144556
  autoApproved.add(category);
@@ -144496,12 +144594,12 @@ function askUser(question) {
144496
144594
  }
144497
144595
  async function requestPermission(req) {
144498
144596
  const { tool, input } = req;
144499
- const decision = (0, import_code_core2.evaluatePermission)(_rules, tool, input, _workDir);
144597
+ const decision = (0, import_code_core3.evaluatePermission)(_rules, tool, input, _workDir);
144500
144598
  if (decision === "deny") {
144501
144599
  console.error(source_default.red(` \u2716 Denied by permission rule: ${tool}`));
144502
144600
  return false;
144503
144601
  }
144504
- const destructive = (0, import_code_core2.isDestructiveBash)(tool, input);
144602
+ const destructive = (0, import_code_core3.isDestructiveBash)(tool, input);
144505
144603
  if (destructive && process.env.NEXRALL_ALLOW_DESTRUCTIVE !== "1") {
144506
144604
  const command = input.command ?? input.cmd ?? "";
144507
144605
  console.error();
@@ -144519,7 +144617,7 @@ async function requestPermission(req) {
144519
144617
  }
144520
144618
  if (decision === "allow")
144521
144619
  return true;
144522
- const verdict = (0, import_code_core2.decide)({
144620
+ const verdict = (0, import_code_core3.decide)({
144523
144621
  tool,
144524
144622
  input,
144525
144623
  mode: _mode,
@@ -144681,7 +144779,7 @@ async function requestPermission(req) {
144681
144779
  }
144682
144780
 
144683
144781
  // src/audit.ts
144684
- var import_code_core3 = __toESM(require_dist3(), 1);
144782
+ var import_code_core4 = __toESM(require_dist3(), 1);
144685
144783
  import * as path from "path";
144686
144784
  var _state;
144687
144785
  var _sinks = /* @__PURE__ */ new Map();
@@ -144701,7 +144799,7 @@ function currentAudit() {
144701
144799
  const target = resolveAuditPath(_state);
144702
144800
  let sink = _sinks.get(target);
144703
144801
  if (!sink) {
144704
- sink = (0, import_code_core3.createJsonlAuditSink)(target);
144802
+ sink = (0, import_code_core4.createJsonlAuditSink)(target);
144705
144803
  _sinks.set(target, sink);
144706
144804
  }
144707
144805
  const cfg = {
@@ -144714,14 +144812,14 @@ function currentAudit() {
144714
144812
  // request that caused it. Same trap as @nexrall/agent's and Desktop's.
144715
144813
  sessionId: _state.getSessionId()
144716
144814
  };
144717
- const email = (0, import_code_core3.loadAuth)()?.email;
144815
+ const email = (0, import_code_core4.loadAuth)()?.email;
144718
144816
  if (email)
144719
144817
  cfg.userId = email;
144720
144818
  return cfg;
144721
144819
  }
144722
144820
 
144723
144821
  // src/commands/chat.ts
144724
- var import_code_core5 = __toESM(require_dist3(), 1);
144822
+ var import_code_core6 = __toESM(require_dist3(), 1);
144725
144823
 
144726
144824
  // src/commands/sessions.ts
144727
144825
  import * as fs3 from "fs";
@@ -154890,7 +154988,7 @@ var MODEL_COST_MULTIPLIER = {
154890
154988
  "glm-5.3": 0.6
154891
154989
  };
154892
154990
  function modelWithCostHint(id) {
154893
- const mult = (0, import_code_core4.liveCostMultiplierFor)(id, MODEL_COST_MULTIPLIER[id]);
154991
+ const mult = (0, import_code_core5.liveCostMultiplierFor)(id, MODEL_COST_MULTIPLIER[id]);
154894
154992
  return mult === void 0 ? id : `${id} (${mult}x)`;
154895
154993
  }
154896
154994
  var NO_VISION_MODELS = /* @__PURE__ */ new Set(["qwen3.7-max", "glm-5.3"]);
@@ -154906,13 +155004,13 @@ var NO_PDF_MODELS = /* @__PURE__ */ new Set([
154906
155004
  ...NO_VISION_MODELS
154907
155005
  ]);
154908
155006
  function needsVisionSidecar(model) {
154909
- return !(0, import_code_core4.liveSupportsImageInput)(model, !NO_VISION_MODELS.has(model));
155007
+ return !(0, import_code_core5.liveSupportsImageInput)(model, !NO_VISION_MODELS.has(model));
154910
155008
  }
154911
155009
  function needsPdfSidecar(model) {
154912
- return !(0, import_code_core4.liveSupportsPdfInput)(model, !NO_PDF_MODELS.has(model));
155010
+ return !(0, import_code_core5.liveSupportsPdfInput)(model, !NO_PDF_MODELS.has(model));
154913
155011
  }
154914
155012
  function selectableModelIds() {
154915
- return (0, import_code_core4.liveSelectableModelIds)() ?? SELECTABLE_MODELS;
155013
+ return (0, import_code_core5.liveSelectableModelIds)() ?? SELECTABLE_MODELS;
154916
155014
  }
154917
155015
  function normaliseModelId(model) {
154918
155016
  const raw = (model ?? "").trim();
@@ -154973,9 +155071,9 @@ var _BACKEND_STYLE_TO_LOCAL = {
154973
155071
  };
154974
155072
  function effortStyleFor(modelId) {
154975
155073
  const id = normaliseModelId(modelId);
154976
- if ((0, import_code_core4.liveVendorFor)(id) === "Anthropic")
155074
+ if ((0, import_code_core5.liveVendorFor)(id) === "Anthropic")
154977
155075
  return "anthropic";
154978
- const liveStyle = (0, import_code_core4.liveReasoningEffortStyle)(id);
155076
+ const liveStyle = (0, import_code_core5.liveReasoningEffortStyle)(id);
154979
155077
  if (liveStyle && _BACKEND_STYLE_TO_LOCAL[liveStyle])
154980
155078
  return _BACKEND_STYLE_TO_LOCAL[liveStyle];
154981
155079
  return MODEL_EFFORT_STYLE[id] ?? "anthropic";
@@ -154995,7 +155093,7 @@ function defaultEffortForModel(modelId) {
154995
155093
  }
154996
155094
  function resolveModelLabel(alias) {
154997
155095
  const id = normaliseModelId(alias);
154998
- return (0, import_code_core4.liveLabelFor)(id, MODEL_LABELS[id] ?? id);
155096
+ return (0, import_code_core5.liveLabelFor)(id, MODEL_LABELS[id] ?? id);
154999
155097
  }
155000
155098
  function tryExec(cmd, cwd2) {
155001
155099
  try {
@@ -155008,14 +155106,15 @@ var BILLING_URL = "https://app.nexrall.com/?settings=billing";
155008
155106
  function hyperlink(label, url) {
155009
155107
  return `\x1B]8;;${url}\x1B\\${label}\x1B]8;;\x1B\\`;
155010
155108
  }
155011
- var lastBalanceNoticeState = null;
155109
+ var lastBalanceNoticeShown = false;
155012
155110
  function printBalanceNotice(balance, zero) {
155013
- const state = zero ? "zero" : "low";
155014
- if (lastBalanceNoticeState === state)
155111
+ if (!zero)
155112
+ return;
155113
+ if (lastBalanceNoticeShown)
155015
155114
  return;
155016
- lastBalanceNoticeState = state;
155017
- const title = zero ? "Out of balance" : "Balance running low";
155018
- const detail = zero ? "You're out of funds \u2014 top up to keep the agent working." : `Your wallet is under $5${typeof balance === "number" ? ` ($${balance.toFixed(2)} left)` : ""}. Top up before it runs out.`;
155115
+ lastBalanceNoticeShown = true;
155116
+ const title = "Out of balance";
155117
+ const detail = "You're out of funds \u2014 top up to keep the agent working.";
155019
155118
  console.log();
155020
155119
  console.log(source_default.bgYellow.black(` ${title} `) + " " + source_default.dim(detail));
155021
155120
  console.log(" " + source_default.yellow(hyperlink("\u2192 Top up", BILLING_URL)) + source_default.dim(` (${BILLING_URL})`));
@@ -155056,7 +155155,7 @@ var tryRead = (p) => {
155056
155155
  };
155057
155156
  function readNexrallMd(workDir) {
155058
155157
  const parts = [];
155059
- const memContent = (0, import_code_core4.readAllMemory)(workDir);
155158
+ const memContent = (0, import_code_core5.readAllMemory)(workDir);
155060
155159
  if (memContent)
155061
155160
  parts.push(memContent);
155062
155161
  const globalContent = tryRead(path6.join(os5.homedir(), ".nexrall", "nexrall.md"));
@@ -155166,12 +155265,12 @@ var Spinner = class {
155166
155265
  var _mcpManager = null;
155167
155266
  var _mcpConfig = null;
155168
155267
  async function initMcp(workDir) {
155169
- _mcpConfig = import_code_core4.McpManager.loadConfig(workDir);
155268
+ _mcpConfig = import_code_core5.McpManager.loadConfig(workDir);
155170
155269
  if (Object.keys(_mcpConfig.mcpServers).length === 0) {
155171
155270
  _mcpManager = null;
155172
155271
  return;
155173
155272
  }
155174
- const manager = new import_code_core4.McpManager();
155273
+ const manager = new import_code_core5.McpManager();
155175
155274
  await manager.connectAll(_mcpConfig);
155176
155275
  _mcpManager = manager;
155177
155276
  }
@@ -155192,10 +155291,10 @@ function formatMcpStatus() {
155192
155291
  return lines.join("\n");
155193
155292
  }
155194
155293
  function formatContextUsage(messages, modelAlias) {
155195
- const window2 = (0, import_code_core4.contextWindowFor)(modelAlias);
155196
- const tokens = (0, import_code_core4.estimateTokensRough)(messages);
155197
- const bytes = (0, import_code_core4.estimateBodyBytes)(messages);
155198
- const { prune, compact } = (0, import_code_core4.compactionThresholds)();
155294
+ const window2 = (0, import_code_core5.contextWindowFor)(modelAlias);
155295
+ const tokens = (0, import_code_core5.estimateTokensRough)(messages);
155296
+ const bytes = (0, import_code_core5.estimateBodyBytes)(messages);
155297
+ const { prune, compact } = (0, import_code_core5.compactionThresholds)();
155199
155298
  const pct = Math.min(100, tokens / window2 * 100);
155200
155299
  const barWidth = 30;
155201
155300
  const filled = Math.round(pct / 100 * barWidth);
@@ -155212,7 +155311,7 @@ function formatContextUsage(messages, modelAlias) {
155212
155311
  return lines.join("\n");
155213
155312
  }
155214
155313
  function formatAgentsList(workDir) {
155215
- const { types: types3, warnings } = (0, import_code_core4.loadAgentTypesWithWarnings)(workDir);
155314
+ const { types: types3, warnings } = (0, import_code_core5.loadAgentTypesWithWarnings)(workDir);
155216
155315
  if (!types3.length)
155217
155316
  return source_default.dim(" No agent types found (this should not happen \u2014 builtins always register).");
155218
155317
  const lines = types3.map((t2) => {
@@ -155259,7 +155358,7 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env4, nexrall
155259
155358
  setMode(mode);
155260
155359
  console.log();
155261
155360
  spinner.start("thinking\u2026", { hint: false });
155262
- const result = await (0, import_code_core4.runAgentLoop)(messages, {
155361
+ const result = await (0, import_code_core5.runAgentLoop)(messages, {
155263
155362
  workDir,
155264
155363
  model: modelAlias,
155265
155364
  env: env4,
@@ -155442,7 +155541,7 @@ async function runTurnHeadless(messages, modelAlias, workDir, _abortSignal, env4
155442
155541
  process.stdout.write(JSON.stringify(obj2) + "\n");
155443
155542
  };
155444
155543
  emit({ type: "start", model: modelAlias, workDir });
155445
- const result = await (0, import_code_core4.runAgentLoop)(messages, {
155544
+ const result = await (0, import_code_core5.runAgentLoop)(messages, {
155446
155545
  workDir,
155447
155546
  model: modelAlias,
155448
155547
  env: env4,
@@ -155538,7 +155637,7 @@ async function runTurnHeadless(messages, modelAlias, workDir, _abortSignal, env4
155538
155637
  // no human to confirm, they are denied unless NEXRALL_ALLOW_DESTRUCTIVE=1 is
155539
155638
  // explicitly set for this CI run.
155540
155639
  requestPermission: async ({ tool, input }) => {
155541
- const d = (0, import_code_core4.isDestructiveBash)(tool, input);
155640
+ const d = (0, import_code_core5.isDestructiveBash)(tool, input);
155542
155641
  if (d && process.env.NEXRALL_ALLOW_DESTRUCTIVE !== "1") {
155543
155642
  emit({ type: "error", error: `Destructive command blocked in headless mode (${d.category}): ${d.reason}. Set NEXRALL_ALLOW_DESTRUCTIVE=1 to permit.` });
155544
155643
  return false;
@@ -155643,7 +155742,7 @@ async function startChatSession(options) {
155643
155742
  let peerInbox;
155644
155743
  const peerInboxQueue = [];
155645
155744
  let modelAlias = options.model;
155646
- void (0, import_code_core4.getModelCatalogue)().catch(() => {
155745
+ void (0, import_code_core5.getModelCatalogue)().catch(() => {
155647
155746
  });
155648
155747
  const canPrompt = !headless && !options.prompt && !options.stdinText && process.stdin.isTTY === true && process.stdout.isTTY === true;
155649
155748
  if (!trustGrantedByEnv()) {
@@ -155671,9 +155770,9 @@ Set ${TRUST_ENV_VAR}=1 to confirm non-interactively, or run \`nex\` interactivel
155671
155770
  }
155672
155771
  if (options.worktree !== void 0) {
155673
155772
  const requestedName = typeof options.worktree === "string" ? options.worktree : void 0;
155674
- const existing = requestedName ? (0, import_code_core4.findWorktreeByName)(requestedWorkDir, requestedName) : null;
155773
+ const existing = requestedName ? (0, import_code_core5.findWorktreeByName)(requestedWorkDir, requestedName) : null;
155675
155774
  if (existing) {
155676
- const entered = (0, import_code_core4.enterWorktree)(existing);
155775
+ const entered = (0, import_code_core5.enterWorktree)(existing);
155677
155776
  if (!entered.ok) {
155678
155777
  process.stderr.write(`Failed to resume worktree "${requestedName}": ${entered.error}
155679
155778
  `);
@@ -155683,7 +155782,7 @@ Set ${TRUST_ENV_VAR}=1 to confirm non-interactively, or run \`nex\` interactivel
155683
155782
  if (!headless)
155684
155783
  console.log(source_default.dim(` Resumed worktree: ${source_default.bold(existing.name)} (${existing.worktreePath})`));
155685
155784
  } else {
155686
- const created = (0, import_code_core4.createWorktree)(requestedWorkDir, requestedName);
155785
+ const created = (0, import_code_core5.createWorktree)(requestedWorkDir, requestedName);
155687
155786
  if (!created.ok || !created.state) {
155688
155787
  process.stderr.write(`Failed to create worktree: ${created.error ?? "unknown error"}
155689
155788
  `);
@@ -155702,7 +155801,7 @@ Set ${TRUST_ENV_VAR}=1 to confirm non-interactively, or run \`nex\` interactivel
155702
155801
  process.on("exit", () => {
155703
155802
  if (!worktreeState)
155704
155803
  return;
155705
- const hadWork = (0, import_code_core4.worktreeHasWork)(worktreeState);
155804
+ const hadWork = (0, import_code_core5.worktreeHasWork)(worktreeState);
155706
155805
  if (hadWork) {
155707
155806
  process.stderr.write(
155708
155807
  `
@@ -155713,7 +155812,7 @@ Resume it with: nex --worktree ${worktreeState.name}
155713
155812
  );
155714
155813
  return;
155715
155814
  }
155716
- (0, import_code_core4.removeWorktree)(worktreeState);
155815
+ (0, import_code_core5.removeWorktree)(worktreeState);
155717
155816
  });
155718
155817
  }
155719
155818
  const env4 = collectEnv(workDir);
@@ -155721,8 +155820,8 @@ Resume it with: nex --worktree ${worktreeState.name}
155721
155820
  const interactive = !headless && !options.prompt && !options.stdinText;
155722
155821
  let peerHeartbeatTimer;
155723
155822
  if (interactive) {
155724
- const handle2 = (0, import_code_core4.registerPeer)({ clientType: "cli", workDir: requestedWorkDir });
155725
- const inbox = (0, import_code_core4.startPeerInbox)(handle2.record.id, { onMessage: (m2) => peerInboxQueue.push(m2) });
155823
+ const handle2 = (0, import_code_core5.registerPeer)({ clientType: "cli", workDir: requestedWorkDir });
155824
+ const inbox = (0, import_code_core5.startPeerInbox)(handle2.record.id, { onMessage: (m2) => peerInboxQueue.push(m2) });
155726
155825
  handle2.record.socketPath = inbox.socketPath;
155727
155826
  handle2.heartbeat();
155728
155827
  peerHandle = handle2;
@@ -155792,7 +155891,7 @@ Resume it with: nex --worktree ${worktreeState.name}
155792
155891
  const ruleCount = permRules.allow.length + permRules.ask.length + permRules.deny.length;
155793
155892
  if (ruleCount && !headless)
155794
155893
  console.log(source_default.dim(` ${ruleCount} permission rule(s) loaded`));
155795
- let skills = (0, import_code_core4.loadSkills)(workDir);
155894
+ let skills = (0, import_code_core5.loadSkills)(workDir);
155796
155895
  if (skills.length && !headless)
155797
155896
  console.log(source_default.dim(` ${skills.length} skill(s) loaded`));
155798
155897
  const mcpStarted = (async () => {
@@ -155824,7 +155923,7 @@ Resume it with: nex --worktree ${worktreeState.name}
155824
155923
  sessionId = stored.id;
155825
155924
  sessionTitle = stored.title;
155826
155925
  try {
155827
- const compacted = await (0, import_code_core4.compactMessagesForResume)(messages, {
155926
+ const compacted = await (0, import_code_core5.compactMessagesForResume)(messages, {
155828
155927
  workDir,
155829
155928
  model: modelAlias,
155830
155929
  clientType: "cli",
@@ -155841,7 +155940,7 @@ Resume it with: nex --worktree ${worktreeState.name}
155841
155940
  console.log();
155842
155941
  }
155843
155942
  }
155844
- const checkpoints = new import_code_core4.CheckpointManager(workDir, sessionId);
155943
+ const checkpoints = new import_code_core5.CheckpointManager(workDir, sessionId);
155845
155944
  if (options.audit) {
155846
155945
  const auditPath = enableAudit({
155847
155946
  filePath: typeof options.audit === "string" ? options.audit : void 0,
@@ -155859,7 +155958,7 @@ Resume it with: nex --worktree ${worktreeState.name}
155859
155958
  sessionTitle = raw.length > 60 ? raw.slice(0, 60) + "\u2026" : raw;
155860
155959
  };
155861
155960
  const recoverTurn = (err, current) => {
155862
- const salvaged = (0, import_code_core4.salvageHistory)(err);
155961
+ const salvaged = (0, import_code_core5.salvageHistory)(err);
155863
155962
  console.error("\n" + source_default.red("Error: ") + String(err.message));
155864
155963
  if (!salvaged)
155865
155964
  return current;
@@ -155908,7 +156007,7 @@ ${text}` : "");
155908
156007
  await new Promise((r2) => setImmediate(r2));
155909
156008
  process.exit(0);
155910
156009
  } catch (err) {
155911
- const salvaged = (0, import_code_core4.salvageHistory)(err);
156010
+ const salvaged = (0, import_code_core5.salvageHistory)(err);
155912
156011
  if (salvaged) {
155913
156012
  messages = salvaged;
155914
156013
  try {
@@ -156013,7 +156112,7 @@ ${text}` : "");
156013
156112
  messages = [];
156014
156113
  sessionId = crypto4.randomBytes(8).toString("hex");
156015
156114
  sessionTitle = "";
156016
- (0, import_code_core5.resetSessionSubAgentBudget)();
156115
+ (0, import_code_core6.resetSessionSubAgentBudget)();
156017
156116
  console.log(source_default.dim(" Conversation cleared. New session started."));
156018
156117
  rl.prompt();
156019
156118
  return;
@@ -156047,7 +156146,7 @@ ${text}` : "");
156047
156146
  sessionId = stored.id;
156048
156147
  sessionTitle = stored.title;
156049
156148
  try {
156050
- await (0, import_code_core4.compactMessagesForResume)(messages, {
156149
+ await (0, import_code_core5.compactMessagesForResume)(messages, {
156051
156150
  workDir,
156052
156151
  model: modelAlias,
156053
156152
  clientType: "cli",
@@ -156222,13 +156321,13 @@ ${dirList}`;
156222
156321
  const sub = arg.trim().toLowerCase();
156223
156322
  console.log();
156224
156323
  if (sub === "list") {
156225
- const all = (0, import_code_core4.listWorktrees)(requestedWorkDir);
156324
+ const all = (0, import_code_core5.listWorktrees)(requestedWorkDir);
156226
156325
  if (!all.length) {
156227
156326
  console.log(source_default.dim(" No worktrees under this project."));
156228
156327
  } else {
156229
156328
  console.log(source_default.bold(` Worktrees (${all.length})`));
156230
156329
  for (const w of all) {
156231
- const dirty = (0, import_code_core4.worktreeHasWork)(w) ? source_default.yellow("dirty") : source_default.dim("clean");
156330
+ const dirty = (0, import_code_core5.worktreeHasWork)(w) ? source_default.yellow("dirty") : source_default.dim("clean");
156232
156331
  console.log(` ${source_default.cyan(w.name)} ${source_default.dim(w.worktreePath)} [${dirty}]`);
156233
156332
  }
156234
156333
  console.log();
@@ -156266,7 +156365,7 @@ ${dirList}`;
156266
156365
  if (!targetName || !text) {
156267
156366
  console.log(source_default.dim(" Usage: /peers send <name> <message>"));
156268
156367
  } else {
156269
- const target = (0, import_code_core4.listPeers)().find((p) => p.name === targetName);
156368
+ const target = (0, import_code_core5.listPeers)().find((p) => p.name === targetName);
156270
156369
  if (!target) {
156271
156370
  console.log(source_default.red(` No live session named "${targetName}". Use /peers to list who's reachable.`));
156272
156371
  } else if (!target.socketPath) {
@@ -156283,7 +156382,7 @@ ${dirList}`;
156283
156382
  console.log(source_default.dim(" Usage: /peers broadcast <message>"));
156284
156383
  } else {
156285
156384
  const { broadcastPeerMessage } = await Promise.resolve().then(() => __toESM(require_dist3(), 1));
156286
- const targets = (0, import_code_core4.listPeers)(peerHandle.record.id).filter((p) => p.id !== peerHandle.record.id && p.socketPath && p.inbound !== "refuse").map((p) => ({ name: p.name, socketPath: p.socketPath }));
156385
+ const targets = (0, import_code_core5.listPeers)(peerHandle.record.id).filter((p) => p.id !== peerHandle.record.id && p.socketPath && p.inbound !== "refuse").map((p) => ({ name: p.name, socketPath: p.socketPath }));
156287
156386
  if (!targets.length) {
156288
156387
  console.log(source_default.dim(" No other reachable Nexrall Code sessions to broadcast to."));
156289
156388
  } else {
@@ -156295,7 +156394,7 @@ ${dirList}`;
156295
156394
  }
156296
156395
  }
156297
156396
  } else {
156298
- const peers = (0, import_code_core4.listPeers)(peerHandle.record.id);
156397
+ const peers = (0, import_code_core5.listPeers)(peerHandle.record.id);
156299
156398
  if (peers.length <= 1) {
156300
156399
  console.log(source_default.dim(" No other Nexrall Code sessions are currently discoverable on this machine."));
156301
156400
  } else {
@@ -156325,7 +156424,7 @@ ${dirList}`;
156325
156424
  const label = memScope === "global" ? "GLOBAL" : "this PROJECT's";
156326
156425
  const answer = await new Promise((resolve4) => rl.question(source_default.yellow(` Clear ${label} memory? This cannot be undone. [y/n] `), (a) => resolve4(a.trim())));
156327
156426
  if (answer === "y" || answer === "yes") {
156328
- (0, import_code_core4.clearMemory)(memScope, workDir);
156427
+ (0, import_code_core5.clearMemory)(memScope, workDir);
156329
156428
  console.log(source_default.green(` ${memScope === "global" ? "Global" : "Project"} memory cleared.`));
156330
156429
  } else {
156331
156430
  console.log(source_default.dim(" Cancelled."));
@@ -156336,20 +156435,20 @@ ${dirList}`;
156336
156435
  }
156337
156436
  console.log();
156338
156437
  if (wantsGlobalOnly) {
156339
- const stats = (0, import_code_core4.memoryStats)("global");
156340
- const content = (0, import_code_core4.readMemory)("global", void 0, { includeArchived: wantsArchived });
156438
+ const stats = (0, import_code_core5.memoryStats)("global");
156439
+ const content = (0, import_code_core5.readMemory)("global", void 0, { includeArchived: wantsArchived });
156341
156440
  const archivedNote = stats.archived > 0 ? `, ${stats.archived} archived` : "";
156342
156441
  console.log(source_default.bold(" Global memory ") + source_default.dim(`(${stats.entries} entries${archivedNote}, ${(stats.bytes / 1024).toFixed(1)}KB) \u2014 ${stats.file}`));
156343
156442
  console.log();
156344
156443
  console.log(content || source_default.dim(" No global memories saved yet."));
156345
156444
  } else {
156346
- const projStats = (0, import_code_core4.memoryStats)("project", workDir);
156347
- const globalStats = (0, import_code_core4.memoryStats)("global");
156445
+ const projStats = (0, import_code_core5.memoryStats)("project", workDir);
156446
+ const globalStats = (0, import_code_core5.memoryStats)("global");
156348
156447
  const projArchived = projStats.archived > 0 ? `+${projStats.archived} archived ` : "";
156349
156448
  const globalArchived = globalStats.archived > 0 ? `+${globalStats.archived} archived ` : "";
156350
156449
  console.log(source_default.bold(" Memory") + source_default.dim(` \u2014 project: ${projStats.entries} ${projArchived}entries (${(projStats.bytes / 1024).toFixed(1)}KB) \xB7 global: ${globalStats.entries} ${globalArchived}entries (${(globalStats.bytes / 1024).toFixed(1)}KB)`));
156351
156450
  console.log();
156352
- const merged = (0, import_code_core4.readAllMemory)(workDir, { includeArchived: wantsArchived });
156451
+ const merged = (0, import_code_core5.readAllMemory)(workDir, { includeArchived: wantsArchived });
156353
156452
  console.log(merged || source_default.dim(" No memories saved yet."));
156354
156453
  }
156355
156454
  console.log();
@@ -156388,12 +156487,12 @@ ${dirList}`;
156388
156487
  console.log(source_default.dim(` Current: ${source_default.cyan(agentMode)}`));
156389
156488
  for (const m2 of ["ask", "edit", "auto", "plan"]) {
156390
156489
  const marker = m2 === agentMode ? source_default.cyan("\u276F") : " ";
156391
- console.log(` ${marker} ${source_default.bold(m2.padEnd(5))} ${source_default.dim((0, import_code_core5.describeMode)(m2).replace(`${m2} \u2014 `, ""))}`);
156490
+ console.log(` ${marker} ${source_default.bold(m2.padEnd(5))} ${source_default.dim((0, import_code_core6.describeMode)(m2).replace(`${m2} \u2014 `, ""))}`);
156392
156491
  }
156393
156492
  } else if (["ask", "edit", "plan", "auto"].includes(modeArg)) {
156394
156493
  agentMode = modeArg;
156395
156494
  updateFooter();
156396
- console.log(source_default.green(` Mode \u2192 ${source_default.bold(modeArg)}`) + source_default.dim(` ${(0, import_code_core5.describeMode)(modeArg).replace(`${modeArg} \u2014 `, "")}`));
156495
+ console.log(source_default.green(` Mode \u2192 ${source_default.bold(modeArg)}`) + source_default.dim(` ${(0, import_code_core6.describeMode)(modeArg).replace(`${modeArg} \u2014 `, "")}`));
156397
156496
  } else {
156398
156497
  console.log(source_default.red(` Unknown: ${modeArg}`));
156399
156498
  }
@@ -156424,7 +156523,7 @@ ${dirList}`;
156424
156523
  case "/balance": {
156425
156524
  rl.pause();
156426
156525
  try {
156427
- const bal = await (0, import_code_core4.getBalance)();
156526
+ const bal = await (0, import_code_core5.getBalance)();
156428
156527
  console.log(source_default.dim(" Balance: ") + source_default.cyan(`$${bal.toFixed(4)}`));
156429
156528
  } catch (err) {
156430
156529
  console.error(source_default.red(" Failed: ") + String(err.message));
@@ -156510,7 +156609,7 @@ ${caption}` : `[Attached: ${rel}]`;
156510
156609
  if (needsSidecar) {
156511
156610
  console.log(source_default.dim(` ${resolveModelLabel(modelAlias)} can't read ${isPdf ? "PDFs" : "images"} directly \u2014 describing ${rel} with Claude Sonnet 5 first\u2026`));
156512
156611
  try {
156513
- const { text } = await (0, import_code_core4.describeAttachment)(isPdf ? "pdf" : "image", data, mimeType, rel);
156612
+ const { text } = await (0, import_code_core5.describeAttachment)(isPdf ? "pdf" : "image", data, mimeType, rel);
156514
156613
  content.push({ type: "text", text: `<attachment_description>
156515
156614
  ${text}
156516
156615
  </attachment_description>` });
@@ -156554,7 +156653,7 @@ ${text}
156554
156653
  process.exit(0);
156555
156654
  }
156556
156655
  case "/plugins": {
156557
- const plugins = (0, import_code_core4.loadPlugins)(workDir);
156656
+ const plugins = (0, import_code_core5.loadPlugins)(workDir);
156558
156657
  if (!plugins.length) {
156559
156658
  console.log(source_default.dim(" No plugins installed. Install one: nex plugin install owner/repo"));
156560
156659
  } else {
@@ -156567,7 +156666,7 @@ ${text}
156567
156666
  }
156568
156667
  console.log();
156569
156668
  }
156570
- skills = (0, import_code_core4.loadSkills)(workDir);
156669
+ skills = (0, import_code_core5.loadSkills)(workDir);
156571
156670
  rl.prompt();
156572
156671
  return;
156573
156672
  }
@@ -156702,8 +156801,8 @@ ${text}
156702
156801
  }
156703
156802
  case "/skills":
156704
156803
  case "/commands": {
156705
- skills = (0, import_code_core4.loadSkills)(workDir);
156706
- const invocable = (0, import_code_core4.userInvokableSkills)(skills);
156804
+ skills = (0, import_code_core5.loadSkills)(workDir);
156805
+ const invocable = (0, import_code_core5.userInvokableSkills)(skills);
156707
156806
  if (!invocable.length) {
156708
156807
  console.log(source_default.dim(" No skills. Add .nexrall/skills/<name>/SKILL.md (or .nexrall/commands/<name>.md) to create one."));
156709
156808
  } else {
@@ -156720,14 +156819,14 @@ ${text}
156720
156819
  return;
156721
156820
  }
156722
156821
  default: {
156723
- const custom = (0, import_code_core4.findSkill)(skills, cmd);
156822
+ const custom = (0, import_code_core5.findSkill)(skills, cmd);
156724
156823
  if (!custom) {
156725
156824
  console.log(source_default.red(` Unknown command: ${cmd}`));
156726
156825
  console.log(source_default.dim(" Type /help for built-ins or /skills for custom ones."));
156727
156826
  rl.prompt();
156728
156827
  return;
156729
156828
  }
156730
- const expanded = (0, import_code_core4.expandSkill)(custom, arg, workDir);
156829
+ const expanded = (0, import_code_core5.expandSkill)(custom, arg, workDir);
156731
156830
  const turnModel = custom.model ?? modelAlias;
156732
156831
  const turnMode = custom.mode ?? agentMode;
156733
156832
  console.log(source_default.dim(` Running /${custom.name}\u2026`));
@@ -156789,7 +156888,7 @@ ${text}
156789
156888
 
156790
156889
  // src/commands/plugin.ts
156791
156890
  var import_prompts = __toESM(require_prompts3(), 1);
156792
- var import_code_core6 = __toESM(require_dist3(), 1);
156891
+ var import_code_core7 = __toESM(require_dist3(), 1);
156793
156892
  function describeInspection(i2, name, ctx) {
156794
156893
  console.log();
156795
156894
  console.log(source_default.bold(` Plugin: ${name}`) + (i2.meta.version ? source_default.dim(` v${i2.meta.version}`) : ""));
@@ -156865,14 +156964,14 @@ async function pluginInstallCommand(spec, opts) {
156865
156964
  let registryName;
156866
156965
  const isShortName = /^[\w.-]+$/.test(spec.trim()) && !spec.includes("/");
156867
156966
  if (isShortName) {
156868
- const alias = (0, import_code_core6.resolveSourceAlias)(spec.trim(), process.cwd(), { includeProject: true });
156967
+ const alias = (0, import_code_core7.resolveSourceAlias)(spec.trim(), process.cwd(), { includeProject: true });
156869
156968
  if (alias) {
156870
156969
  source2 = alias.spec;
156871
156970
  console.log(source_default.dim(` Source: ${alias.name} (${alias.tier}) \u2190 ${alias.spec}`));
156872
156971
  }
156873
156972
  }
156874
156973
  if (isShortName && source2 === spec) {
156875
- const entry = await (0, import_code_core6.getRegistryPlugin)(spec.trim()).catch(() => null);
156974
+ const entry = await (0, import_code_core7.getRegistryPlugin)(spec.trim()).catch(() => null);
156876
156975
  if (entry) {
156877
156976
  source2 = entry.source;
156878
156977
  registryName = entry.name;
@@ -156887,7 +156986,7 @@ async function pluginInstallCommand(spec, opts) {
156887
156986
  return;
156888
156987
  }
156889
156988
  }
156890
- const res = await (0, import_code_core6.installPlugin)(source2, {
156989
+ const res = await (0, import_code_core7.installPlugin)(source2, {
156891
156990
  scope,
156892
156991
  workDir: process.cwd(),
156893
156992
  name: opts.name ?? registryName,
@@ -156895,7 +156994,7 @@ async function pluginInstallCommand(spec, opts) {
156895
156994
  confirm: (i2, name, ctx) => confirmInstall(i2, name, opts.yes === true, ctx)
156896
156995
  });
156897
156996
  if (registryName)
156898
- (0, import_code_core6.reportInstall)(registryName);
156997
+ (0, import_code_core7.reportInstall)(registryName);
156899
156998
  console.log();
156900
156999
  console.log(source_default.green(` \u2713 Installed "${res.name}" (${res.scope}) \u2192 ${res.dir}`) + (res.sha ? source_default.dim(` @ ${res.sha.slice(0, 7)}`) : ""));
156901
157000
  if (res.inspection.commands.length) {
@@ -156909,7 +157008,7 @@ async function pluginInstallCommand(spec, opts) {
156909
157008
  }
156910
157009
  function pluginRemoveCommand(name, opts) {
156911
157010
  try {
156912
- const dir = (0, import_code_core6.removePlugin)(name, {
157011
+ const dir = (0, import_code_core7.removePlugin)(name, {
156913
157012
  scope: opts.project ? "project" : void 0,
156914
157013
  // no flag → search both scopes
156915
157014
  workDir: process.cwd()
@@ -156922,14 +157021,14 @@ function pluginRemoveCommand(name, opts) {
156922
157021
  }
156923
157022
  async function pluginUpdateCommand(name, opts) {
156924
157023
  const workDir = process.cwd();
156925
- const targets = name ? [name] : (0, import_code_core6.loadPlugins)(workDir).filter((p) => (0, import_code_core6.readReceipt)(p.dir)?.kind === "github").map((p) => p.name);
157024
+ const targets = name ? [name] : (0, import_code_core7.loadPlugins)(workDir).filter((p) => (0, import_code_core7.readReceipt)(p.dir)?.kind === "github").map((p) => p.name);
156926
157025
  if (!targets.length) {
156927
157026
  console.log(source_default.dim(" No updatable plugins (only GitHub-installed plugins with receipts can update)."));
156928
157027
  return;
156929
157028
  }
156930
157029
  for (const t2 of targets) {
156931
157030
  try {
156932
- const res = await (0, import_code_core6.updatePlugin)(t2, {
157031
+ const res = await (0, import_code_core7.updatePlugin)(t2, {
156933
157032
  workDir,
156934
157033
  confirm: (i2, n, ctx) => confirmInstall(i2, n, opts.yes === true, ctx)
156935
157034
  });
@@ -156946,7 +157045,7 @@ function badgeFor(p) {
156946
157045
  }
156947
157046
  async function pluginSearchCommand(query) {
156948
157047
  try {
156949
- const results = await (0, import_code_core6.searchRegistry)(query);
157048
+ const results = await (0, import_code_core7.searchRegistry)(query);
156950
157049
  if (!results.length) {
156951
157050
  console.log(source_default.dim(query ? ` No plugins matching "${query}".` : " Registry is empty."));
156952
157051
  return;
@@ -156969,7 +157068,7 @@ async function pluginSearchCommand(query) {
156969
157068
  }
156970
157069
  async function pluginInfoCommand(name) {
156971
157070
  try {
156972
- const p = await (0, import_code_core6.getRegistryPlugin)(name);
157071
+ const p = await (0, import_code_core7.getRegistryPlugin)(name);
156973
157072
  if (!p) {
156974
157073
  console.error(source_default.red(` \u2717 "${name}" not found in the registry.`));
156975
157074
  process.exitCode = 1;
@@ -157005,7 +157104,7 @@ async function pluginInfoCommand(name) {
157005
157104
  }
157006
157105
  }
157007
157106
  function pluginListCommand() {
157008
- const plugins = (0, import_code_core6.loadPlugins)(process.cwd());
157107
+ const plugins = (0, import_code_core7.loadPlugins)(process.cwd());
157009
157108
  if (!plugins.length) {
157010
157109
  console.log(source_default.dim(" No plugins installed."));
157011
157110
  console.log(source_default.dim(" Install one: nex plugin install owner/repo"));
@@ -157014,10 +157113,10 @@ function pluginListCommand() {
157014
157113
  console.log();
157015
157114
  console.log(source_default.bold(" Installed plugins:"));
157016
157115
  for (const p of plugins) {
157017
- const receipt = (0, import_code_core6.readReceipt)(p.dir);
157116
+ const receipt = (0, import_code_core7.readReceipt)(p.dir);
157018
157117
  const src = receipt ? source_default.dim(` \u2190 ${receipt.source}`) : source_default.dim(" (manual)");
157019
157118
  const at = receipt?.sha ? source_default.dim(` @ ${receipt.sha.slice(0, 7)}`) : "";
157020
- const insp = (0, import_code_core6.inspectPluginDir)(p.dir);
157119
+ const insp = (0, import_code_core7.inspectPluginDir)(p.dir);
157021
157120
  const runs = insp.hasHooks || insp.hasMcp ? source_default.yellow(` \u26A0 ${[insp.hasHooks && "hooks", insp.hasMcp && "mcp"].filter(Boolean).join("+")}`) : "";
157022
157121
  console.log(
157023
157122
  " " + source_default.cyan(p.name.padEnd(24)) + source_default.dim(`${(p.version ?? "").padEnd(10)}${p.scope.padEnd(9)}`) + src + at + runs
@@ -157027,8 +157126,8 @@ function pluginListCommand() {
157027
157126
  }
157028
157127
  function pluginSourceListCommand() {
157029
157128
  const workDir = process.cwd();
157030
- const sources = (0, import_code_core6.loadDeclaredSources)(workDir, { includeProject: true });
157031
- const patterns = (0, import_code_core6.allowedSourcePatterns)();
157129
+ const sources = (0, import_code_core7.loadDeclaredSources)(workDir, { includeProject: true });
157130
+ const patterns = (0, import_code_core7.allowedSourcePatterns)();
157032
157131
  if (patterns) {
157033
157132
  console.log();
157034
157133
  console.log(source_default.bold(" Organisation policy: ") + source_default.dim(`installs restricted to ${patterns.join(", ")}`));
@@ -157043,7 +157142,7 @@ function pluginSourceListCommand() {
157043
157142
  console.log(source_default.bold(" Declared plugin sources:"));
157044
157143
  for (const s2 of sources) {
157045
157144
  const tier = s2.tier === "project" ? source_default.yellow(s2.tier.padEnd(9)) : source_default.dim(s2.tier.padEnd(9));
157046
- const blocked = !(0, import_code_core6.isSourceAllowed)(s2.spec, patterns) ? source_default.red(" \u2717 blocked by policy") : "";
157145
+ const blocked = !(0, import_code_core7.isSourceAllowed)(s2.spec, patterns) ? source_default.red(" \u2717 blocked by policy") : "";
157047
157146
  console.log(" " + source_default.cyan(s2.name.padEnd(20)) + tier + source_default.white(s2.spec) + blocked);
157048
157147
  }
157049
157148
  console.log();
@@ -157053,17 +157152,17 @@ function pluginSourceListCommand() {
157053
157152
  }
157054
157153
  function pluginSourceAddCommand(name, spec, opts) {
157055
157154
  try {
157056
- (0, import_code_core6.parsePluginSource)(spec);
157057
- const patterns = (0, import_code_core6.allowedSourcePatterns)();
157058
- if (patterns && !(0, import_code_core6.isSourceAllowed)(spec, patterns)) {
157155
+ (0, import_code_core7.parsePluginSource)(spec);
157156
+ const patterns = (0, import_code_core7.allowedSourcePatterns)();
157157
+ if (patterns && !(0, import_code_core7.isSourceAllowed)(spec, patterns)) {
157059
157158
  console.error(source_default.red(` \u2717 "${spec}" is not permitted by your organisation's policy.`));
157060
157159
  console.error(source_default.dim(` Allowed: ${patterns.join(", ")}`));
157061
157160
  process.exitCode = 1;
157062
157161
  return;
157063
157162
  }
157064
157163
  const scope = opts.project ? "project" : "user";
157065
- const file = (0, import_code_core6.sourcesFileFor)(scope, process.cwd());
157066
- (0, import_code_core6.writeDeclaredSource)(file, name, spec);
157164
+ const file = (0, import_code_core7.sourcesFileFor)(scope, process.cwd());
157165
+ (0, import_code_core7.writeDeclaredSource)(file, name, spec);
157067
157166
  console.log();
157068
157167
  console.log(source_default.green(` \u2713 Declared "${name}" \u2192 ${spec}`) + source_default.dim(` (${scope})`));
157069
157168
  console.log(source_default.dim(` ${file}`));
@@ -157077,13 +157176,13 @@ function pluginSourceAddCommand(name, spec, opts) {
157077
157176
  function pluginSourceRemoveCommand(name, opts) {
157078
157177
  const workDir = process.cwd();
157079
157178
  const scope = opts.project ? "project" : "user";
157080
- const file = (0, import_code_core6.sourcesFileFor)(scope, workDir);
157081
- if ((0, import_code_core6.removeDeclaredSource)(file, name)) {
157179
+ const file = (0, import_code_core7.sourcesFileFor)(scope, workDir);
157180
+ if ((0, import_code_core7.removeDeclaredSource)(file, name)) {
157082
157181
  console.log(source_default.green(` \u2713 Removed source "${name}" (${scope})`));
157083
157182
  console.log(source_default.dim(" Plugins already installed from it are untouched \u2014 remove them with nex plugin remove <name>"));
157084
157183
  return;
157085
157184
  }
157086
- const found = (0, import_code_core6.resolveSourceAlias)(name, workDir, { includeProject: true });
157185
+ const found = (0, import_code_core7.resolveSourceAlias)(name, workDir, { includeProject: true });
157087
157186
  if (found) {
157088
157187
  console.error(source_default.red(` \u2717 "${name}" is declared in the ${found.tier} tier, not ${scope}.`));
157089
157188
  console.error(source_default.dim(` ${found.file}`));
@@ -157104,6 +157203,13 @@ var program2 = new Command();
157104
157203
  program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version(NEX_VERSION).enablePositionalOptions();
157105
157204
  program2.command("auth").description("Login to your Nexrall account").action(authCommand);
157106
157205
  program2.command("logout").description("Log out of your Nexrall account").action(logoutCommand);
157206
+ var billing = program2.command("billing").description("Show, or change, which budget pays for your usage");
157207
+ billing.command("use <team|personal>").description("Bill to a team id (see `nex billing`) or back to your personal wallet").action(async (target) => {
157208
+ await billingUseCommand(target);
157209
+ });
157210
+ billing.action(async () => {
157211
+ await billingStatusCommand();
157212
+ });
157107
157213
  program2.command("update").description("Update nex to the latest version").option("-c, --check", "Check for updates without installing").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
157108
157214
  await updateCommand({ check: opts.check, yes: opts.yes });
157109
157215
  });
@@ -157173,7 +157279,7 @@ program2.command("sessions").description("List or delete saved chat sessions").o
157173
157279
  console.log();
157174
157280
  });
157175
157281
  program2.option("-p, --pro", "Use Claude Opus 5 (most capable)").option("-t, --turbo", "Use Claude Sonnet 5 (fast, default)").option("-u, --ultra", "Use Claude Fable 5 (most powerful)").option("-y, --yolo", "Auto-approve all tool calls (no permission prompts)").option("-d, --dir <path>", "Set working directory (default: current directory)").option("-m, --model <name>", "Explicit model, e.g. claude-opus-5-5 | gpt-5.4 | gpt-4.1").option("-r, --resume [id]", "Resume last session, or a specific session id").option("-w, --worktree [name]", "Isolate this session in its own worktree \u2014 a separate directory (and, in a git repo, its own branch) so it can never overwrite files another session (or you) are touching in the main checkout. Omit a name for an auto-generated one; pass an existing name to resume that same worktree.").option("-e, --effort <level>", "Thinking effort \u2014 real levels depend on the model (e.g. DeepSeek: low|high|max, Qwen: low|high); run `nex --model <id>` then `/effort` with no argument to see a model's scale").option("--no-banner", "Skip the ASCII banner (useful in scripts/pipes)").option("--output-format <fmt>", "One-shot output format: text | json | stream-json (implies auto-approve)").option("--audit [path]", "Log every tool call (and refusal) to a JSONL trail (default: .nexrall/audit/<session>.jsonl)").argument("[prompt...]", "One-shot prompt \u2014 if omitted, starts interactive mode").action(async (promptParts, options) => {
157176
- if (!(0, import_code_core7.isAuthenticated)()) {
157282
+ if (!(0, import_code_core8.isAuthenticated)()) {
157177
157283
  console.error("Not logged in. Run: nex auth");
157178
157284
  process.exit(1);
157179
157285
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexrall-code",
3
- "version": "0.5.110",
3
+ "version": "0.5.112",
4
4
  "description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
5
5
  "keywords": [
6
6
  "ai",