nexo-code 0.1.1 → 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 +78 -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;
@@ -14681,6 +14681,8 @@ var require_content_type = __commonJS({
14681
14681
 
14682
14682
  // dist/main.js
14683
14683
  import { spawnSync as spawnSync2 } from "node:child_process";
14684
+ import { rmSync } from "node:fs";
14685
+ import { join as join19 } from "node:path";
14684
14686
  import { createInterface } from "node:readline";
14685
14687
 
14686
14688
  // dist/update.js
@@ -14688,7 +14690,7 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
14688
14690
  import { join } from "node:path";
14689
14691
 
14690
14692
  // dist/version.js
14691
- var VERSION = "0.1.1";
14693
+ var VERSION = "0.1.3";
14692
14694
 
14693
14695
  // dist/update.js
14694
14696
  var PACKAGE = "nexo-code";
@@ -35136,6 +35138,8 @@ var SpeakSchema = external_exports.strictObject({
35136
35138
  var loginEmail = external_exports.string().trim().toLowerCase().pipe(external_exports.email().max(320));
35137
35139
  var EmailLoginStartSchema = external_exports.strictObject({ email: loginEmail, adult: external_exports.literal(true) });
35138
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}$/) });
35139
35143
 
35140
35144
  // ../../packages/core/dist/sse.js
35141
35145
  var MAX_SSE_FRAME_CHARS = 2e6;
@@ -37663,6 +37667,7 @@ async function errorFromResponse(res) {
37663
37667
  }
37664
37668
 
37665
37669
  // dist/commands.js
37670
+ import { spawn as spawn3 } from "node:child_process";
37666
37671
  import { join as join15 } from "node:path";
37667
37672
 
37668
37673
  // dist/project.js
@@ -44245,7 +44250,8 @@ async function login(io, opts) {
44245
44250
  io.err(`${s.error(s.sym.fail)} Use an https:// API URL (plain http is only allowed for localhost).`);
44246
44251
  return 2;
44247
44252
  }
44248
- 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);
44249
44255
  if (token === null)
44250
44256
  return 1;
44251
44257
  if (!TOKEN2.test(token)) {
@@ -44259,8 +44265,54 @@ async function login(io, opts) {
44259
44265
  io.out(s.dim(` user ${me.userId}`));
44260
44266
  return 0;
44261
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
+ }
44262
44312
  async function emailSignIn(io, apiUrl) {
44263
44313
  const { style: s } = io;
44314
+ io.err(`${s.bold("Sign in to Nexo")} ${s.dim("(Ctrl+C to cancel)")}`);
44315
+ io.err("Type your email address and press Enter:");
44264
44316
  const email3 = (await io.readLine(`${s.primary("\u203A")} Your email: `))?.trim();
44265
44317
  if (!email3)
44266
44318
  return null;
@@ -44274,6 +44326,7 @@ async function emailSignIn(io, apiUrl) {
44274
44326
  throw await errorFromResponse(started);
44275
44327
  io.err(s.dim(` If ${email3} has a Nexo account, a six-digit code is on its way. No account yet? Sign up at https://usenexoai.com`));
44276
44328
  for (let tries = 0; tries < 3; tries++) {
44329
+ io.err("Type the six-digit code from the email and press Enter:");
44277
44330
  const code = (await io.readLine(`${s.primary("\u203A")} Code from the email: `))?.replace(/\s+/g, "");
44278
44331
  if (!code)
44279
44332
  return null;
@@ -44336,7 +44389,7 @@ async function logout(io) {
44336
44389
  }
44337
44390
 
44338
44391
  // dist/statusline.js
44339
- import { spawn as spawn3 } from "node:child_process";
44392
+ import { spawn as spawn4 } from "node:child_process";
44340
44393
  var TIMEOUT_MS2 = 2e3;
44341
44394
  var MAX_CHARS = 160;
44342
44395
  function runStatusLine(command, input2, cwd) {
@@ -44352,7 +44405,7 @@ function runStatusLine(command, input2, cwd) {
44352
44405
  };
44353
44406
  let child;
44354
44407
  try {
44355
- 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"] });
44356
44409
  } catch {
44357
44410
  return end(null);
44358
44411
  }
@@ -44656,7 +44709,7 @@ function skillsText(skills) {
44656
44709
  }
44657
44710
 
44658
44711
  // dist/notify.js
44659
- import { spawn as spawn4 } from "node:child_process";
44712
+ import { spawn as spawn5 } from "node:child_process";
44660
44713
  import { join as join18 } from "node:path";
44661
44714
  var NOTIFY_AFTER_MS = 3e4;
44662
44715
  function notificationCommand(title, body, platform = process.platform) {
@@ -44686,7 +44739,7 @@ function notify(write2, title, body) {
44686
44739
  if (!cmd)
44687
44740
  return;
44688
44741
  try {
44689
- 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 });
44690
44743
  child.on("error", () => {
44691
44744
  });
44692
44745
  child.unref();
@@ -46472,7 +46525,7 @@ Usage:
46472
46525
  nexo remote Take tasks from the Nexo app (Code) in this folder: they run here, and
46473
46526
  every file change and command is approved on your phone
46474
46527
  nexo models The models you can put in a team (nexo run --team)
46475
- 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)
46476
46529
  nexo auth status Show login and this month's usage against your cap
46477
46530
  nexo logout Revoke the token and remove it from this machine
46478
46531
  nexo update Install the latest Nexo Code (npm install -g nexo-code@latest)
@@ -46575,6 +46628,7 @@ async function run2(argv, io) {
46575
46628
  output: { type: "string" },
46576
46629
  "api-url": { type: "string" },
46577
46630
  token: { type: "boolean" },
46631
+ email: { type: "boolean" },
46578
46632
  "no-color": { type: "boolean" },
46579
46633
  debug: { type: "boolean" }
46580
46634
  }
@@ -46672,6 +46726,8 @@ async function run2(argv, io) {
46672
46726
  io.err(`${io.style.error(io.style.sym.fail)} Could not run npm. Install the update yourself: npm install -g ${PACKAGE}@latest`);
46673
46727
  return 1;
46674
46728
  }
46729
+ if (npm.status === 0 && process.platform === "win32")
46730
+ dropBlockedLauncher();
46675
46731
  return npm.status ?? 1;
46676
46732
  }
46677
46733
  if (cmd === "remote") {
@@ -46687,7 +46743,7 @@ async function run2(argv, io) {
46687
46743
  return remote(io, budget);
46688
46744
  }
46689
46745
  if (cmd === "login")
46690
- 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 } : {} });
46691
46747
  if (cmd === "models")
46692
46748
  return listModels(io);
46693
46749
  if (cmd === "logout")
@@ -46764,6 +46820,17 @@ async function headless(io, words, format, yes) {
46764
46820
  line2({ type: "result", exitCode: code, answer: text2.trim(), ...result ?? { outcome: code === 0 ? "done" : "failed", filesChanged: [], costMicros: 0 } });
46765
46821
  return code;
46766
46822
  }
46823
+ function dropBlockedLauncher() {
46824
+ try {
46825
+ const policy = spawnSync2("powershell.exe", ["-NoProfile", "-Command", "Get-ExecutionPolicy"], { encoding: "utf8", windowsHide: true }).stdout.trim();
46826
+ if (policy !== "Restricted" && policy !== "AllSigned")
46827
+ return;
46828
+ const prefix = spawnSync2("npm.cmd", ["prefix", "-g"], { encoding: "utf8", shell: true, windowsHide: true }).stdout.trim();
46829
+ if (prefix)
46830
+ rmSync(join19(prefix, "nexo.ps1"), { force: true });
46831
+ } catch {
46832
+ }
46833
+ }
46767
46834
  var isMain = true;
46768
46835
  if (isMain) {
46769
46836
  const settings = loadSettings(configDir(process.env));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-code",
3
- "version": "0.1.1",
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",