nexrall-code 0.5.208 → 0.5.210

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 +1 -1
  2. package/dist/index.js +77 -30
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -7,7 +7,7 @@ npm install -g nexrall-code
7
7
  nex
8
8
  ```
9
9
 
10
- Requires Node.js 20+ and a Nexrall account — it signs in with the same account as the extension; billing stays in one place and there are no API keys to configure.
10
+ Requires Node.js 20+ and a Nexrall account. **Signing in happens in the terminal** — no editor, no VS Code login first: the first `nex` (or `nex auth`) asks how you want to sign in, with a browser hand-off that works for Google/Apple/SSO accounts as well as email + password or a token. It is the same account as the extension, so billing stays in one place and there are no API keys to configure.
11
11
 
12
12
  ## Quick start
13
13
 
package/dist/index.js CHANGED
@@ -10097,7 +10097,7 @@ var require_client = __commonJS({
10097
10097
  return mod && mod.__esModule ? mod : { "default": mod };
10098
10098
  };
10099
10099
  Object.defineProperty(exports, "__esModule", { value: true });
10100
- exports.SCHEDULE_MAX_MINUTES = exports.SCHEDULE_MIN_MINUTES = exports.API_BASE = void 0;
10100
+ exports.SCHEDULE_MAX_MINUTES = exports.SCHEDULE_MIN_MINUTES = exports.DEVICE_ACCOUNT_LIMIT = exports.API_BASE = void 0;
10101
10101
  exports.chooseFinalContent = chooseFinalContent;
10102
10102
  exports.refreshAccessToken = refreshAccessToken3;
10103
10103
  exports.earlyToolResolveEnabled = earlyToolResolveEnabled;
@@ -10112,6 +10112,8 @@ var require_client = __commonJS({
10112
10112
  exports.getOrgs = getOrgs3;
10113
10113
  exports.getCodeModels = getCodeModels;
10114
10114
  exports.getUsageDaily = getUsageDaily;
10115
+ exports.parseApiRefusal = parseApiRefusal;
10116
+ exports.refusalMessage = refusalMessage;
10115
10117
  exports.exchangeVscodeCode = exchangeVscodeCode;
10116
10118
  exports.login = login2;
10117
10119
  exports.exchangeAuthCode = exchangeAuthCode2;
@@ -11122,15 +11124,41 @@ var require_client = __commonJS({
11122
11124
  totalSpent: typeof data.totalSpent === "number" ? data.totalSpent : 0
11123
11125
  };
11124
11126
  }
11125
- async function exchangeVscodeCode(code) {
11126
- const response = await (0, node_fetch_1.default)(`${exports.API_BASE}/api/auth/vscode-exchange`, {
11127
+ exports.DEVICE_ACCOUNT_LIMIT = "device_account_limit";
11128
+ function parseApiRefusal(raw) {
11129
+ const text = raw.trim();
11130
+ try {
11131
+ const body = JSON.parse(text);
11132
+ const message = typeof body.error === "string" && body.error.trim() ? body.error.trim() : void 0;
11133
+ return {
11134
+ raw: text,
11135
+ ...message ? { message } : {},
11136
+ ...typeof body.code === "string" && body.code ? { code: body.code } : {},
11137
+ ...typeof body.limit === "number" ? { limit: body.limit } : {}
11138
+ };
11139
+ } catch {
11140
+ return { raw: text };
11141
+ }
11142
+ }
11143
+ function refusalMessage(raw) {
11144
+ const { code, message, limit, raw: text } = parseApiRefusal(raw);
11145
+ if (code === exports.DEVICE_ACCOUNT_LIMIT) {
11146
+ return message ?? `This device has reached its limit of ${limit ?? "the maximum number of"} accounts. Sign in with an account already used on this device, or use a different device.`;
11147
+ }
11148
+ return message ?? text;
11149
+ }
11150
+ function postVscodeExchange(code) {
11151
+ return (0, node_fetch_1.default)(`${exports.API_BASE}/api/auth/vscode-exchange`, {
11127
11152
  method: "POST",
11128
11153
  headers: { "Content-Type": "application/json", ...deviceHeader() },
11129
11154
  body: JSON.stringify({ code })
11130
11155
  });
11156
+ }
11157
+ async function exchangeVscodeCode(code) {
11158
+ const response = await postVscodeExchange(code);
11131
11159
  if (!response.ok) {
11132
11160
  const errText3 = await response.text();
11133
- throw new Error(`OAuth exchange failed (${response.status}): ${errText3}`);
11161
+ throw new Error(`OAuth exchange failed (${response.status}): ${refusalMessage(errText3)}`);
11134
11162
  }
11135
11163
  const data = await response.json();
11136
11164
  if (!data.token)
@@ -11149,7 +11177,7 @@ var require_client = __commonJS({
11149
11177
  });
11150
11178
  if (!response.ok) {
11151
11179
  const errText3 = await response.text();
11152
- throw new Error(`Login failed (${response.status}): ${errText3}`);
11180
+ throw new Error(`Login failed (${response.status}): ${refusalMessage(errText3)}`);
11153
11181
  }
11154
11182
  const data = await response.json();
11155
11183
  if (!data.token) {
@@ -11162,17 +11190,13 @@ var require_client = __commonJS({
11162
11190
  };
11163
11191
  }
11164
11192
  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
- });
11193
+ const response = await postVscodeExchange(code);
11170
11194
  if (response.status === 401 || response.status === 400) {
11171
11195
  throw new Error("That sign-in code is invalid or has expired (codes last 5 minutes). Run `nex auth --browser` again.");
11172
11196
  }
11173
11197
  if (!response.ok) {
11174
11198
  const errText3 = await response.text().catch(() => "");
11175
- throw new Error(`Sign-in failed (${response.status}): ${errText3}`);
11199
+ throw new Error(`Sign-in failed (${response.status}): ${refusalMessage(errText3)}`);
11176
11200
  }
11177
11201
  const data = await response.json();
11178
11202
  if (!data.token)
@@ -80240,6 +80264,12 @@ function parseAuthMethod(input) {
80240
80264
  return "token";
80241
80265
  return null;
80242
80266
  }
80267
+ function shouldOfferLogin(ctx) {
80268
+ return ctx.isTTY && !ctx.headless;
80269
+ }
80270
+ function stripPasteMarkers(raw) {
80271
+ return raw.replace(/\u001b\[[0-9;?]*[~A-Za-z]/g, "").replace(/\u001b/g, "");
80272
+ }
80243
80273
  function prompt(question, hidden = false) {
80244
80274
  return new Promise((resolve19) => {
80245
80275
  const rl = readline.createInterface({
@@ -80250,30 +80280,38 @@ function prompt(question, hidden = false) {
80250
80280
  if (hidden) {
80251
80281
  process.stdout.write(question);
80252
80282
  let value = "";
80283
+ let finished = false;
80253
80284
  const { stdin } = process;
80254
80285
  const wasRaw = stdin.isRaw;
80255
80286
  stdin.setRawMode(true);
80256
80287
  stdin.resume();
80257
80288
  stdin.setEncoding("utf8");
80258
- const onData = (char) => {
80259
- if (char === "\n" || char === "\r" || char === "") {
80260
- stdin.setRawMode(wasRaw ?? false);
80261
- stdin.pause();
80262
- stdin.removeListener("data", onData);
80263
- rl.close();
80264
- process.stdout.write("\n");
80265
- if (char === "") {
80266
- process.exit(0);
80267
- }
80268
- resolve19(value);
80269
- return;
80270
- }
80271
- if (char === "\x7F" || char === "\b") {
80272
- if (value.length > 0)
80273
- value = value.slice(0, -1);
80289
+ const finish = (submit) => {
80290
+ if (finished)
80274
80291
  return;
80292
+ finished = true;
80293
+ stdin.setRawMode(wasRaw ?? false);
80294
+ stdin.pause();
80295
+ stdin.removeListener("data", onData);
80296
+ rl.close();
80297
+ process.stdout.write("\n");
80298
+ if (!submit)
80299
+ process.exit(0);
80300
+ resolve19(stripPasteMarkers(value));
80301
+ };
80302
+ const onData = (chunk) => {
80303
+ for (const char of chunk) {
80304
+ if (char === "\n" || char === "\r")
80305
+ return finish(true);
80306
+ if (char === "")
80307
+ return finish(false);
80308
+ if (char === "\x7F" || char === "\b") {
80309
+ if (value.length > 0)
80310
+ value = value.slice(0, -1);
80311
+ continue;
80312
+ }
80313
+ value += char;
80275
80314
  }
80276
- value += char;
80277
80315
  };
80278
80316
  stdin.on("data", onData);
80279
80317
  } else {
@@ -114900,8 +114938,17 @@ program2.option("-y, --yolo", "Auto-approve all tool calls (no permission prompt
114900
114938
  "Settings (permissions, hooks\u2026) for this run only: a JSON file or an inline JSON object; merged over the user/project settings"
114901
114939
  ).option("--debug-file <path>", "Write the --debug diagnostics log to this file (implies --debug)").argument("[prompt...]", "One-shot prompt \u2014 if omitted, starts interactive mode").action(async (promptParts, options) => {
114902
114940
  if (!(0, import_code_core78.isAuthenticated)()) {
114903
- console.error("Not logged in. Run: nex auth");
114904
- process.exit(1);
114941
+ if (!shouldOfferLogin({
114942
+ isTTY: !!process.stdin.isTTY,
114943
+ headless: !!(options.print || options.outputFormat)
114944
+ })) {
114945
+ console.error("Not logged in. Run: nex auth (or set NEXRALL_TOKEN for CI)");
114946
+ process.exit(1);
114947
+ }
114948
+ console.log(paint.dim(" Not signed in yet \u2014 signing in first (Ctrl+C cancels)."));
114949
+ await authCommand();
114950
+ if (!(0, import_code_core78.isAuthenticated)())
114951
+ process.exit(process.exitCode || 1);
114905
114952
  }
114906
114953
  const model = options.model ?? "deepseek-flash";
114907
114954
  const workDir = options.dir ? path35.resolve(options.dir) : process.cwd();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexrall-code",
3
- "version": "0.5.208",
3
+ "version": "0.5.210",
4
4
  "description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
5
5
  "keywords": [
6
6
  "ai",