@leuria/cli 0.1.1 → 0.1.2
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.
- package/dist/{chunk-ES2YTJPL.js → chunk-JOCM56MT.js} +35 -15
- package/dist/cli.js +11 -2
- package/dist/index.js +1 -1
- package/package.json +3 -1
|
@@ -343,6 +343,7 @@ import { createHash } from "crypto";
|
|
|
343
343
|
import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync4, readdirSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
344
344
|
import { dirname, join as join3 } from "path";
|
|
345
345
|
import { promisify as promisify2 } from "util";
|
|
346
|
+
import crossSpawn from "cross-spawn";
|
|
346
347
|
|
|
347
348
|
// src/codex.ts
|
|
348
349
|
import { execFile } from "child_process";
|
|
@@ -374,7 +375,11 @@ async function prepareCodexHome(agent) {
|
|
|
374
375
|
"",
|
|
375
376
|
"[features]",
|
|
376
377
|
...features.map((name) => `${name} = ${ENABLED_FEATURES.has(name)}`),
|
|
377
|
-
""
|
|
378
|
+
"",
|
|
379
|
+
// Windows: the sandbox that needs no administrator rights (a restricted token).
|
|
380
|
+
// The other one asks for them the first time: out of the blue, and a dead end
|
|
381
|
+
// on a work computer without them.
|
|
382
|
+
...process.platform === "win32" ? ["[windows]", 'sandbox = "unelevated"', ""] : []
|
|
378
383
|
];
|
|
379
384
|
writeFileSync2(join2(home, "config.toml"), lines.join("\n"), { mode: 384 });
|
|
380
385
|
writeFileSync2(stamp, agent.version);
|
|
@@ -576,12 +581,7 @@ async function installPackage(dir, spec, args, env) {
|
|
|
576
581
|
if (process.versions.bun) {
|
|
577
582
|
await execFileAsync2(process.execPath, ["add", spec], { cwd: dir, env: { ...process.env, BUN_BE_BUN: "1" }, timeout: 5 * 6e4 });
|
|
578
583
|
} else {
|
|
579
|
-
|
|
580
|
-
await execFileAsync2(npm, ["install", "--no-audit", "--no-fund", "--omit=dev", "--loglevel=error", spec], {
|
|
581
|
-
cwd: dir,
|
|
582
|
-
timeout: 5 * 6e4,
|
|
583
|
-
shell: process.platform === "win32"
|
|
584
|
-
});
|
|
584
|
+
await run("npm", ["install", "--no-audit", "--no-fund", "--omit=dev", "--loglevel=error", spec], { cwd: dir, timeout: 5 * 6e4 });
|
|
585
585
|
}
|
|
586
586
|
const name = spec.lastIndexOf("@") > 0 ? spec.slice(0, spec.lastIndexOf("@")) : spec;
|
|
587
587
|
const pkgDir = join3(dir, "node_modules", ...name.split("/"));
|
|
@@ -593,6 +593,25 @@ async function installPackage(dir, spec, args, env) {
|
|
|
593
593
|
const isScript = /\.[cm]?js$/.test(entry) || /^#!.*\b(node|bun)\b/.test(readFileSync3(entry, "utf-8").slice(0, 100));
|
|
594
594
|
return isScript ? { command: process.execPath, launchArgs: [entry], args, env } : { command: entry, launchArgs: [], args, env };
|
|
595
595
|
}
|
|
596
|
+
function run(command, args, options) {
|
|
597
|
+
return new Promise((resolve, reject) => {
|
|
598
|
+
const child = crossSpawn(command, args, { cwd: options.cwd, stdio: ["ignore", "ignore", "pipe"], windowsHide: true });
|
|
599
|
+
let stderr = "";
|
|
600
|
+
child.stderr?.on("data", (chunk) => {
|
|
601
|
+
stderr += chunk.toString("utf-8");
|
|
602
|
+
});
|
|
603
|
+
const timer = setTimeout(() => child.kill(), options.timeout);
|
|
604
|
+
child.on("error", (error) => {
|
|
605
|
+
clearTimeout(timer);
|
|
606
|
+
reject(error);
|
|
607
|
+
});
|
|
608
|
+
child.on("close", (code) => {
|
|
609
|
+
clearTimeout(timer);
|
|
610
|
+
if (code === 0) resolve();
|
|
611
|
+
else reject(new Error(`${command} ${args.join(" ")} failed (${code ?? "stopped"})${stderr.trim() ? `: ${stderr.trim()}` : ""}`));
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
}
|
|
596
615
|
async function installBinary(dir, target) {
|
|
597
616
|
const res = await fetch(target.archive, { signal: AbortSignal.timeout(5 * 6e4) });
|
|
598
617
|
if (!res.ok) throw new Error(`Download failed (${res.status}): ${target.archive}`);
|
|
@@ -635,16 +654,17 @@ function compareVersions(a, b) {
|
|
|
635
654
|
}
|
|
636
655
|
|
|
637
656
|
// src/version.ts
|
|
638
|
-
var VERSION = true ? "0.1.
|
|
657
|
+
var VERSION = true ? "0.1.2" : "0.0.0-dev";
|
|
639
658
|
|
|
640
659
|
// src/auth.ts
|
|
641
|
-
import
|
|
660
|
+
import crossSpawn3 from "cross-spawn";
|
|
642
661
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "fs";
|
|
643
662
|
import { tmpdir as tmpdir2 } from "os";
|
|
644
663
|
import { join as join5 } from "path";
|
|
645
664
|
|
|
646
665
|
// src/acp/acp-client.ts
|
|
647
666
|
import { spawn } from "child_process";
|
|
667
|
+
import crossSpawn2 from "cross-spawn";
|
|
648
668
|
import { Readable, Writable } from "stream";
|
|
649
669
|
var rawParams = {
|
|
650
670
|
// biome-ignore lint/suspicious/noExplicitAny: ACP payloads are untyped here
|
|
@@ -707,11 +727,11 @@ var AcpLiveSession = class {
|
|
|
707
727
|
const env = { ...process.env, ...this.options.envVars };
|
|
708
728
|
for (const key of REMOVED_ENV_VARS) delete env[key];
|
|
709
729
|
if (process.versions.bun) env.BUN_BE_BUN = "1";
|
|
710
|
-
const child =
|
|
730
|
+
const child = crossSpawn2(this.options.command, this.options.args, {
|
|
711
731
|
stdio: ["pipe", "pipe", "pipe"],
|
|
712
732
|
env,
|
|
713
733
|
cwd: this.options.cwd,
|
|
714
|
-
|
|
734
|
+
windowsHide: true,
|
|
715
735
|
// Its own process group, so close() also stops what the agent starts
|
|
716
736
|
// (Gemini relaunches itself as a child process).
|
|
717
737
|
detached: process.platform !== "win32"
|
|
@@ -915,7 +935,7 @@ ${file.text}
|
|
|
915
935
|
function killTree(child) {
|
|
916
936
|
try {
|
|
917
937
|
if (process.platform === "win32" && child.pid) {
|
|
918
|
-
spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], { stdio: "ignore" });
|
|
938
|
+
spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
|
|
919
939
|
} else if (child.pid) {
|
|
920
940
|
process.kill(-child.pid, "SIGTERM");
|
|
921
941
|
} else {
|
|
@@ -1161,11 +1181,11 @@ async function signIn(id, options = {}) {
|
|
|
1161
1181
|
else options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
1162
1182
|
});
|
|
1163
1183
|
try {
|
|
1164
|
-
return await Promise.race([cancelled,
|
|
1184
|
+
return await Promise.race([cancelled, run2()]);
|
|
1165
1185
|
} finally {
|
|
1166
1186
|
close();
|
|
1167
1187
|
}
|
|
1168
|
-
async function
|
|
1188
|
+
async function run2() {
|
|
1169
1189
|
let session = opened.session;
|
|
1170
1190
|
const connected = await session.connect();
|
|
1171
1191
|
if (connected.error) return { ok: false, detail: `the agent did not start: ${connected.error}`, methods: [] };
|
|
@@ -1180,7 +1200,7 @@ async function signIn(id, options = {}) {
|
|
|
1180
1200
|
if (isTerminal(method)) {
|
|
1181
1201
|
session.close();
|
|
1182
1202
|
const code = await new Promise((resolve, reject) => {
|
|
1183
|
-
const child =
|
|
1203
|
+
const child = crossSpawn3(agent.command, [...agent.launchArgs, ...method.args ?? []], {
|
|
1184
1204
|
stdio: "inherit",
|
|
1185
1205
|
cwd: sandbox,
|
|
1186
1206
|
env: { ...process.env, ...env, ...method.env ?? {} }
|
package/dist/cli.js
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
signIn,
|
|
41
41
|
startEngine,
|
|
42
42
|
updateAgents
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-JOCM56MT.js";
|
|
44
44
|
|
|
45
45
|
// src/cli.ts
|
|
46
46
|
import { spawn } from "child_process";
|
|
@@ -1086,7 +1086,10 @@ function sites(args) {
|
|
|
1086
1086
|
}
|
|
1087
1087
|
}
|
|
1088
1088
|
function openInBrowser(url) {
|
|
1089
|
-
const [command, args] = process.platform === "darwin" ? ["open", [url]] :
|
|
1089
|
+
const [command, args] = process.platform === "darwin" ? ["open", [url]] : (
|
|
1090
|
+
// Not `cmd /c start`: cmd would read the & between query parameters as a new command.
|
|
1091
|
+
process.platform === "win32" ? ["rundll32", ["url.dll,FileProtocolHandler", url]] : ["xdg-open", [url]]
|
|
1092
|
+
);
|
|
1090
1093
|
try {
|
|
1091
1094
|
const child = spawn(command, args, { stdio: "ignore", detached: true });
|
|
1092
1095
|
child.on("error", () => void 0);
|
|
@@ -1226,13 +1229,19 @@ async function startForApp(config, verbose, devPairing) {
|
|
|
1226
1229
|
});
|
|
1227
1230
|
setTimeout(updateAis, AI_UPDATE_DELAY_MS).unref();
|
|
1228
1231
|
setInterval(updateAis, AI_UPDATE_EVERY_MS).unref();
|
|
1232
|
+
let stopping = false;
|
|
1229
1233
|
const shutdown = async () => {
|
|
1234
|
+
if (stopping) return;
|
|
1235
|
+
stopping = true;
|
|
1230
1236
|
await engine.close();
|
|
1231
1237
|
process.exit(0);
|
|
1232
1238
|
};
|
|
1233
1239
|
process.on("SIGINT", shutdown);
|
|
1234
1240
|
process.on("SIGTERM", shutdown);
|
|
1235
1241
|
process.stdin.on("end", shutdown);
|
|
1242
|
+
process.stdin.on("data", (chunk) => {
|
|
1243
|
+
if (chunk.toString("utf-8").split(/\r?\n/).includes("quit")) void shutdown();
|
|
1244
|
+
});
|
|
1236
1245
|
process.stdin.resume();
|
|
1237
1246
|
}
|
|
1238
1247
|
function out(text) {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leuria/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Bring your own AI to the web: the Leuria engine. Lets websites you approve use the AI on your machine, through tools the page provides.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@agentclientprotocol/sdk": "^1.5.0",
|
|
32
32
|
"cacache": "^21.0.1",
|
|
33
|
+
"cross-spawn": "^7.0.6",
|
|
33
34
|
"giget": "^3.3.1",
|
|
34
35
|
"ipaddr.js": "^2.5.0",
|
|
35
36
|
"ws": "^8.18.0",
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@types/cacache": "^20.0.1",
|
|
41
|
+
"@types/cross-spawn": "^6.0.6",
|
|
40
42
|
"@types/node": "^22.0.0",
|
|
41
43
|
"@types/ws": "^8.5.0",
|
|
42
44
|
"tsup": "^8.4.0",
|