nexo-code 0.1.2 → 0.1.3

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/nexo.mjs +60 -11
  2. package/package.json +1 -1
package/nexo.mjs CHANGED
@@ -14550,7 +14550,7 @@ var require_cross_spawn = __commonJS({
14550
14550
  var cp = __require("child_process");
14551
14551
  var parse4 = require_parse();
14552
14552
  var enoent = require_enoent();
14553
- function spawn5(command, args, options) {
14553
+ function spawn6(command, args, options) {
14554
14554
  const parsed = parse4(command, args, options);
14555
14555
  const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
14556
14556
  enoent.hookChildProcess(spawned, parsed);
@@ -14562,8 +14562,8 @@ var require_cross_spawn = __commonJS({
14562
14562
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
14563
14563
  return result;
14564
14564
  }
14565
- module.exports = spawn5;
14566
- module.exports.spawn = spawn5;
14565
+ module.exports = spawn6;
14566
+ module.exports.spawn = spawn6;
14567
14567
  module.exports.sync = spawnSync3;
14568
14568
  module.exports._parse = parse4;
14569
14569
  module.exports._enoent = enoent;
@@ -14690,7 +14690,7 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
14690
14690
  import { join } from "node:path";
14691
14691
 
14692
14692
  // dist/version.js
14693
- var VERSION = "0.1.2";
14693
+ var VERSION = "0.1.3";
14694
14694
 
14695
14695
  // dist/update.js
14696
14696
  var PACKAGE = "nexo-code";
@@ -35138,6 +35138,8 @@ var SpeakSchema = external_exports.strictObject({
35138
35138
  var loginEmail = external_exports.string().trim().toLowerCase().pipe(external_exports.email().max(320));
35139
35139
  var EmailLoginStartSchema = external_exports.strictObject({ email: loginEmail, adult: external_exports.literal(true) });
35140
35140
  var EmailLoginVerifySchema = external_exports.strictObject({ email: loginEmail, code: external_exports.string().trim().regex(/^\d{6}$/, "six digits") });
35141
+ var DeviceApproveSchema = external_exports.strictObject({ userCode: external_exports.string().trim().toUpperCase().regex(/^[A-Z]{4}-[A-Z]{4}$/, "a code like ABCD-EFGH") });
35142
+ var DevicePollSchema = external_exports.strictObject({ deviceCode: external_exports.string().regex(/^[A-Za-z0-9_-]{43}$/) });
35141
35143
 
35142
35144
  // ../../packages/core/dist/sse.js
35143
35145
  var MAX_SSE_FRAME_CHARS = 2e6;
@@ -37665,6 +37667,7 @@ async function errorFromResponse(res) {
37665
37667
  }
37666
37668
 
37667
37669
  // dist/commands.js
37670
+ import { spawn as spawn3 } from "node:child_process";
37668
37671
  import { join as join15 } from "node:path";
37669
37672
 
37670
37673
  // dist/project.js
@@ -44247,7 +44250,8 @@ async function login(io, opts) {
44247
44250
  io.err(`${s.error(s.sym.fail)} Use an https:// API URL (plain http is only allowed for localhost).`);
44248
44251
  return 2;
44249
44252
  }
44250
- const token = !opts.token && io.interactive && io.readLine ? await emailSignIn(io, apiUrl) : await io.readSecret(`Paste your Nexo token (input hidden): `);
44253
+ const terminal = !opts.token && io.interactive && io.readLine;
44254
+ const token = !terminal ? await io.readSecret(`Paste your Nexo token (input hidden): `) : opts.email ? await emailSignIn(io, apiUrl) : await browserSignIn(io, apiUrl);
44251
44255
  if (token === null)
44252
44256
  return 1;
44253
44257
  if (!TOKEN2.test(token)) {
@@ -44261,6 +44265,50 @@ async function login(io, opts) {
44261
44265
  io.out(s.dim(` user ${me.userId}`));
44262
44266
  return 0;
44263
44267
  }
44268
+ async function browserSignIn(io, apiUrl) {
44269
+ const { style: s } = io;
44270
+ const post = (path2, body) => (io.fetch ?? fetch)(new URL(path2, apiUrl), { method: "POST", headers: { "content-type": "application/json", "x-nexo-client": "cli" }, body: JSON.stringify(body), signal: io.signal });
44271
+ const res = await post("/v1/auth/device/start", {});
44272
+ if (!res.ok)
44273
+ throw await errorFromResponse(res);
44274
+ const start = await res.json();
44275
+ io.err(`${s.bold("Sign in to Nexo")} ${s.dim("(Ctrl+C to cancel)")}`);
44276
+ io.err(`Your code: ${s.bold(s.primary(start.userCode))} ${s.dim("(check that the browser shows the same)")}`);
44277
+ const opened = /^https:\/\//.test(start.verifyUrl) && (io.openUrl ?? openInBrowser)(start.verifyUrl);
44278
+ io.err(opened ? s.dim(`Opening your browser. If it did not open, go to ${start.verifyUrl}`) : `Open this page to approve: ${start.verifyUrl}`);
44279
+ io.err(s.dim(`${s.sym.busy} waiting for you to approve in the browser`));
44280
+ const until = Date.now() + start.expiresInMs;
44281
+ while (Date.now() < until) {
44282
+ await new Promise((resolve3) => {
44283
+ const t = setTimeout(resolve3, Math.max(1e3, start.intervalMs));
44284
+ io.signal.addEventListener("abort", () => (clearTimeout(t), resolve3()), { once: true });
44285
+ });
44286
+ if (io.signal.aborted)
44287
+ return null;
44288
+ const r = await post("/v1/auth/device/poll", { deviceCode: start.deviceCode }).catch(() => null);
44289
+ if (!r)
44290
+ continue;
44291
+ const body = await r.json().catch(() => ({}));
44292
+ if (body.status === "done" && body.token)
44293
+ return body.token;
44294
+ if (body.status === "expired" || r.status === 410)
44295
+ break;
44296
+ }
44297
+ io.err(`${s.error(s.sym.fail)} The sign-in was not approved in time. Run nexo login again.`);
44298
+ return null;
44299
+ }
44300
+ function openInBrowser(url2) {
44301
+ try {
44302
+ const [cmd, args] = process.platform === "win32" ? ["rundll32.exe", ["url.dll,FileProtocolHandler", url2]] : process.platform === "darwin" ? ["open", [url2]] : ["xdg-open", [url2]];
44303
+ const child = spawn3(cmd, args, { stdio: "ignore", detached: true, windowsHide: true });
44304
+ child.on("error", () => {
44305
+ });
44306
+ child.unref();
44307
+ return true;
44308
+ } catch {
44309
+ return false;
44310
+ }
44311
+ }
44264
44312
  async function emailSignIn(io, apiUrl) {
44265
44313
  const { style: s } = io;
44266
44314
  io.err(`${s.bold("Sign in to Nexo")} ${s.dim("(Ctrl+C to cancel)")}`);
@@ -44341,7 +44389,7 @@ async function logout(io) {
44341
44389
  }
44342
44390
 
44343
44391
  // dist/statusline.js
44344
- import { spawn as spawn3 } from "node:child_process";
44392
+ import { spawn as spawn4 } from "node:child_process";
44345
44393
  var TIMEOUT_MS2 = 2e3;
44346
44394
  var MAX_CHARS = 160;
44347
44395
  function runStatusLine(command, input2, cwd) {
@@ -44357,7 +44405,7 @@ function runStatusLine(command, input2, cwd) {
44357
44405
  };
44358
44406
  let child;
44359
44407
  try {
44360
- child = spawn3(command, { cwd, shell: true, windowsHide: true, stdio: ["pipe", "pipe", "ignore"] });
44408
+ child = spawn4(command, { cwd, shell: true, windowsHide: true, stdio: ["pipe", "pipe", "ignore"] });
44361
44409
  } catch {
44362
44410
  return end(null);
44363
44411
  }
@@ -44661,7 +44709,7 @@ function skillsText(skills) {
44661
44709
  }
44662
44710
 
44663
44711
  // dist/notify.js
44664
- import { spawn as spawn4 } from "node:child_process";
44712
+ import { spawn as spawn5 } from "node:child_process";
44665
44713
  import { join as join18 } from "node:path";
44666
44714
  var NOTIFY_AFTER_MS = 3e4;
44667
44715
  function notificationCommand(title, body, platform = process.platform) {
@@ -44691,7 +44739,7 @@ function notify(write2, title, body) {
44691
44739
  if (!cmd)
44692
44740
  return;
44693
44741
  try {
44694
- const child = spawn4(cmd[0], cmd.slice(1), { stdio: "ignore", detached: true, windowsHide: true });
44742
+ const child = spawn5(cmd[0], cmd.slice(1), { stdio: "ignore", detached: true, windowsHide: true });
44695
44743
  child.on("error", () => {
44696
44744
  });
44697
44745
  child.unref();
@@ -46477,7 +46525,7 @@ Usage:
46477
46525
  nexo remote Take tasks from the Nexo app (Code) in this folder: they run here, and
46478
46526
  every file change and command is approved on your phone
46479
46527
  nexo models The models you can put in a team (nexo run --team)
46480
- nexo login Sign in with your email and the code it receives (--token to paste a token)
46528
+ nexo login Sign in: approve in your browser (--email for a code by email, --token to paste one)
46481
46529
  nexo auth status Show login and this month's usage against your cap
46482
46530
  nexo logout Revoke the token and remove it from this machine
46483
46531
  nexo update Install the latest Nexo Code (npm install -g nexo-code@latest)
@@ -46580,6 +46628,7 @@ async function run2(argv, io) {
46580
46628
  output: { type: "string" },
46581
46629
  "api-url": { type: "string" },
46582
46630
  token: { type: "boolean" },
46631
+ email: { type: "boolean" },
46583
46632
  "no-color": { type: "boolean" },
46584
46633
  debug: { type: "boolean" }
46585
46634
  }
@@ -46694,7 +46743,7 @@ async function run2(argv, io) {
46694
46743
  return remote(io, budget);
46695
46744
  }
46696
46745
  if (cmd === "login")
46697
- return login(io, { ...values["api-url"] ? { apiUrl: values["api-url"] } : {}, ...values.token ? { token: true } : {} });
46746
+ return login(io, { ...values["api-url"] ? { apiUrl: values["api-url"] } : {}, ...values.token ? { token: true } : {}, ...values.email ? { email: true } : {} });
46698
46747
  if (cmd === "models")
46699
46748
  return listModels(io);
46700
46749
  if (cmd === "logout")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-code",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Nexo Code: an AI coding agent for your terminal. Sign in with your Nexo account.",
5
5
  "homepage": "https://usenexoai.com",
6
6
  "license": "UNLICENSED",