@openape/apes 0.12.6 → 0.13.1
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/cli.js
CHANGED
|
@@ -61,7 +61,7 @@ import {
|
|
|
61
61
|
} from "./chunk-6GPSKAMU.js";
|
|
62
62
|
|
|
63
63
|
// src/cli.ts
|
|
64
|
-
import
|
|
64
|
+
import consola28 from "consola";
|
|
65
65
|
|
|
66
66
|
// src/ape-shell.ts
|
|
67
67
|
import path from "path";
|
|
@@ -91,7 +91,7 @@ function rewriteApeShellArgs(argv, argv0) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// src/cli.ts
|
|
94
|
-
import { defineCommand as
|
|
94
|
+
import { defineCommand as defineCommand34, runMain } from "citty";
|
|
95
95
|
|
|
96
96
|
// src/commands/auth/login.ts
|
|
97
97
|
import { Buffer } from "buffer";
|
|
@@ -256,7 +256,7 @@ async function loginWithPKCE(idp) {
|
|
|
256
256
|
authUrl.searchParams.set("state", state);
|
|
257
257
|
authUrl.searchParams.set("nonce", nonce);
|
|
258
258
|
authUrl.searchParams.set("scope", "openid email profile offline_access");
|
|
259
|
-
const code = await new Promise((
|
|
259
|
+
const code = await new Promise((resolve4, reject) => {
|
|
260
260
|
const server = createServer((req, res) => {
|
|
261
261
|
const url = new URL(req.url, `http://localhost:${CALLBACK_PORT}`);
|
|
262
262
|
if (url.pathname === "/callback") {
|
|
@@ -273,7 +273,7 @@ async function loginWithPKCE(idp) {
|
|
|
273
273
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
274
274
|
res.end("<h1>Login successful!</h1><p>You can close this window.</p>");
|
|
275
275
|
server.close();
|
|
276
|
-
|
|
276
|
+
resolve4(authCode);
|
|
277
277
|
return;
|
|
278
278
|
}
|
|
279
279
|
res.writeHead(400);
|
|
@@ -833,7 +833,7 @@ async function waitForApproval2(grantsUrl, grantId) {
|
|
|
833
833
|
if (grant.status === "revoked") {
|
|
834
834
|
throw new CliError("Grant revoked.");
|
|
835
835
|
}
|
|
836
|
-
await new Promise((
|
|
836
|
+
await new Promise((resolve4) => setTimeout(resolve4, interval));
|
|
837
837
|
}
|
|
838
838
|
throw new CliError("Timed out waiting for approval.");
|
|
839
839
|
}
|
|
@@ -2455,9 +2455,222 @@ async function runAudienceMode(audience, action, args) {
|
|
|
2455
2455
|
}
|
|
2456
2456
|
}
|
|
2457
2457
|
|
|
2458
|
-
// src/commands/
|
|
2458
|
+
// src/commands/proxy.ts
|
|
2459
|
+
import { spawn as spawn2 } from "child_process";
|
|
2459
2460
|
import { defineCommand as defineCommand22 } from "citty";
|
|
2460
|
-
|
|
2461
|
+
import consola20 from "consola";
|
|
2462
|
+
|
|
2463
|
+
// src/proxy/config.ts
|
|
2464
|
+
import { homedir as homedir4 } from "os";
|
|
2465
|
+
import { join as join2 } from "path";
|
|
2466
|
+
function defaultAuditPath() {
|
|
2467
|
+
const xdg = process.env.XDG_STATE_HOME;
|
|
2468
|
+
const stateDir = xdg && xdg.length > 0 ? xdg : join2(homedir4(), ".local", "state");
|
|
2469
|
+
return join2(stateDir, "openape", "proxy-audit.jsonl");
|
|
2470
|
+
}
|
|
2471
|
+
function buildDefaultProxyConfigToml() {
|
|
2472
|
+
const auditPath = defaultAuditPath();
|
|
2473
|
+
return `# Auto-generated by apes proxy -- (M1a). Do not edit; this file is
|
|
2474
|
+
# recreated for every \`apes proxy --\` invocation and deleted on exit.
|
|
2475
|
+
[proxy]
|
|
2476
|
+
listen = "127.0.0.1:0"
|
|
2477
|
+
idp_url = "https://id.openape.ai"
|
|
2478
|
+
agent_email = "ephemeral@apes-proxy.local"
|
|
2479
|
+
default_action = "allow"
|
|
2480
|
+
audit_log = "${auditPath.replace(/"/g, '\\"')}"
|
|
2481
|
+
|
|
2482
|
+
# Cloud / link-local metadata endpoints \u2014 never let agent traffic reach these
|
|
2483
|
+
# even if a downstream policy mistake would otherwise allow it.
|
|
2484
|
+
[[deny]]
|
|
2485
|
+
domain = "169.254.169.254"
|
|
2486
|
+
note = "AWS / DigitalOcean / Azure metadata endpoint"
|
|
2487
|
+
|
|
2488
|
+
[[deny]]
|
|
2489
|
+
domain = "metadata.google.internal"
|
|
2490
|
+
note = "GCP metadata endpoint"
|
|
2491
|
+
|
|
2492
|
+
[[deny]]
|
|
2493
|
+
domain = "*.internal"
|
|
2494
|
+
note = "VPC-internal hostname suffix"
|
|
2495
|
+
`;
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
// src/proxy/local-proxy.ts
|
|
2499
|
+
import { spawn } from "child_process";
|
|
2500
|
+
import { mkdtempSync, rmSync, writeFileSync } from "fs";
|
|
2501
|
+
import { createRequire } from "module";
|
|
2502
|
+
import { tmpdir } from "os";
|
|
2503
|
+
import { dirname, join as join3, resolve as resolve2 } from "path";
|
|
2504
|
+
var require2 = createRequire(import.meta.url);
|
|
2505
|
+
function findProxyBin() {
|
|
2506
|
+
const pkgPath = require2.resolve("@openape/proxy/package.json");
|
|
2507
|
+
const pkg = require2("@openape/proxy/package.json");
|
|
2508
|
+
const binRel = pkg.bin?.["openape-proxy"];
|
|
2509
|
+
if (!binRel) {
|
|
2510
|
+
throw new Error("@openape/proxy is missing the openape-proxy bin entry");
|
|
2511
|
+
}
|
|
2512
|
+
return resolve2(dirname(pkgPath), binRel);
|
|
2513
|
+
}
|
|
2514
|
+
async function startEphemeralProxy(configToml) {
|
|
2515
|
+
const tmpDir = mkdtempSync(join3(tmpdir(), "openape-proxy-"));
|
|
2516
|
+
const configPath = join3(tmpDir, "config.toml");
|
|
2517
|
+
writeFileSync(configPath, configToml, { mode: 384 });
|
|
2518
|
+
const binPath = findProxyBin();
|
|
2519
|
+
const child = spawn(process.execPath, [binPath, "-c", configPath], {
|
|
2520
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2521
|
+
detached: false
|
|
2522
|
+
});
|
|
2523
|
+
const cleanupTmp = () => {
|
|
2524
|
+
try {
|
|
2525
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
2526
|
+
} catch {
|
|
2527
|
+
}
|
|
2528
|
+
};
|
|
2529
|
+
let port;
|
|
2530
|
+
try {
|
|
2531
|
+
port = await waitForListenLine(child);
|
|
2532
|
+
} catch (err) {
|
|
2533
|
+
child.kill("SIGTERM");
|
|
2534
|
+
cleanupTmp();
|
|
2535
|
+
throw err;
|
|
2536
|
+
}
|
|
2537
|
+
child.stderr?.on("data", (chunk) => process.stderr.write(chunk));
|
|
2538
|
+
return {
|
|
2539
|
+
url: `http://127.0.0.1:${port}`,
|
|
2540
|
+
port,
|
|
2541
|
+
child,
|
|
2542
|
+
close: () => new Promise((resolveClose) => {
|
|
2543
|
+
const done = () => {
|
|
2544
|
+
cleanupTmp();
|
|
2545
|
+
resolveClose();
|
|
2546
|
+
};
|
|
2547
|
+
if (child.exitCode !== null || child.signalCode !== null) {
|
|
2548
|
+
done();
|
|
2549
|
+
return;
|
|
2550
|
+
}
|
|
2551
|
+
child.once("exit", done);
|
|
2552
|
+
child.kill("SIGTERM");
|
|
2553
|
+
setTimeout(() => {
|
|
2554
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
2555
|
+
child.kill("SIGKILL");
|
|
2556
|
+
}
|
|
2557
|
+
}, 2e3).unref();
|
|
2558
|
+
})
|
|
2559
|
+
};
|
|
2560
|
+
}
|
|
2561
|
+
function waitForListenLine(child) {
|
|
2562
|
+
return new Promise((resolveWait, rejectWait) => {
|
|
2563
|
+
let buf = "";
|
|
2564
|
+
let timer;
|
|
2565
|
+
function onData(chunk) {
|
|
2566
|
+
buf += chunk.toString("utf8");
|
|
2567
|
+
const m = buf.match(/Listening on http:\/\/[^:\s]+:(\d+)/);
|
|
2568
|
+
if (m) {
|
|
2569
|
+
cleanup();
|
|
2570
|
+
resolveWait(Number(m[1]));
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
function onExit(code) {
|
|
2574
|
+
cleanup();
|
|
2575
|
+
rejectWait(new Error(`openape-proxy exited before listening (code=${code}, stderr accumulated above)`));
|
|
2576
|
+
}
|
|
2577
|
+
function onError(err) {
|
|
2578
|
+
cleanup();
|
|
2579
|
+
rejectWait(err);
|
|
2580
|
+
}
|
|
2581
|
+
function cleanup() {
|
|
2582
|
+
clearTimeout(timer);
|
|
2583
|
+
child.stdout?.off("data", onData);
|
|
2584
|
+
child.off("exit", onExit);
|
|
2585
|
+
child.off("error", onError);
|
|
2586
|
+
}
|
|
2587
|
+
timer = setTimeout(() => {
|
|
2588
|
+
cleanup();
|
|
2589
|
+
rejectWait(new Error("openape-proxy startup timeout (5s)"));
|
|
2590
|
+
}, 5e3);
|
|
2591
|
+
timer.unref();
|
|
2592
|
+
child.stdout?.on("data", onData);
|
|
2593
|
+
child.once("exit", onExit);
|
|
2594
|
+
child.once("error", onError);
|
|
2595
|
+
});
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
// src/commands/proxy.ts
|
|
2599
|
+
var proxyCommand = defineCommand22({
|
|
2600
|
+
meta: {
|
|
2601
|
+
name: "proxy",
|
|
2602
|
+
description: "Run a command with HTTPS_PROXY routed through the OpenApe egress proxy."
|
|
2603
|
+
},
|
|
2604
|
+
args: {
|
|
2605
|
+
_: {
|
|
2606
|
+
type: "positional",
|
|
2607
|
+
description: "Command to execute (after --)",
|
|
2608
|
+
required: false
|
|
2609
|
+
}
|
|
2610
|
+
},
|
|
2611
|
+
async run({ rawArgs }) {
|
|
2612
|
+
const wrapped = extractWrappedCommand(rawArgs ?? []);
|
|
2613
|
+
if (wrapped.length === 0) {
|
|
2614
|
+
throw new CliError("Usage: apes proxy -- <cmd> [args...]");
|
|
2615
|
+
}
|
|
2616
|
+
const reuseUrl = process.env.OPENAPE_PROXY_URL;
|
|
2617
|
+
let proxyUrl;
|
|
2618
|
+
let close = null;
|
|
2619
|
+
if (reuseUrl) {
|
|
2620
|
+
proxyUrl = reuseUrl;
|
|
2621
|
+
consola20.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
|
|
2622
|
+
} else {
|
|
2623
|
+
const ephemeral = await startEphemeralProxy(buildDefaultProxyConfigToml());
|
|
2624
|
+
proxyUrl = ephemeral.url;
|
|
2625
|
+
close = ephemeral.close;
|
|
2626
|
+
consola20.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
|
|
2627
|
+
}
|
|
2628
|
+
const noProxy = process.env.NO_PROXY ?? process.env.no_proxy ?? "127.0.0.1,localhost";
|
|
2629
|
+
const childEnv = {
|
|
2630
|
+
...process.env,
|
|
2631
|
+
HTTPS_PROXY: proxyUrl,
|
|
2632
|
+
https_proxy: proxyUrl,
|
|
2633
|
+
HTTP_PROXY: proxyUrl,
|
|
2634
|
+
http_proxy: proxyUrl,
|
|
2635
|
+
ALL_PROXY: proxyUrl,
|
|
2636
|
+
all_proxy: proxyUrl,
|
|
2637
|
+
NO_PROXY: noProxy,
|
|
2638
|
+
no_proxy: noProxy,
|
|
2639
|
+
NODE_USE_ENV_PROXY: "1"
|
|
2640
|
+
};
|
|
2641
|
+
const exitCode = await new Promise((resolveExit) => {
|
|
2642
|
+
const child = spawn2(wrapped[0], wrapped.slice(1), {
|
|
2643
|
+
stdio: "inherit",
|
|
2644
|
+
env: childEnv
|
|
2645
|
+
});
|
|
2646
|
+
const forward = (sig) => () => child.kill(sig);
|
|
2647
|
+
const onSigint = forward("SIGINT");
|
|
2648
|
+
const onSigterm = forward("SIGTERM");
|
|
2649
|
+
process.on("SIGINT", onSigint);
|
|
2650
|
+
process.on("SIGTERM", onSigterm);
|
|
2651
|
+
child.once("exit", (code, signal) => {
|
|
2652
|
+
process.off("SIGINT", onSigint);
|
|
2653
|
+
process.off("SIGTERM", onSigterm);
|
|
2654
|
+
if (signal) resolveExit(128 + (signalNumber(signal) ?? 0));
|
|
2655
|
+
else resolveExit(code ?? 0);
|
|
2656
|
+
});
|
|
2657
|
+
child.once("error", (err) => {
|
|
2658
|
+
consola20.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
|
|
2659
|
+
resolveExit(127);
|
|
2660
|
+
});
|
|
2661
|
+
});
|
|
2662
|
+
if (close) await close();
|
|
2663
|
+
if (exitCode !== 0) throw new CliExit(exitCode);
|
|
2664
|
+
}
|
|
2665
|
+
});
|
|
2666
|
+
function signalNumber(signal) {
|
|
2667
|
+
const map = { SIGINT: 2, SIGTERM: 15, SIGHUP: 1, SIGQUIT: 3, SIGKILL: 9 };
|
|
2668
|
+
return map[signal];
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
// src/commands/explain.ts
|
|
2672
|
+
import { defineCommand as defineCommand23 } from "citty";
|
|
2673
|
+
var explainCommand = defineCommand23({
|
|
2461
2674
|
meta: {
|
|
2462
2675
|
name: "explain",
|
|
2463
2676
|
description: "Show what permission a command would need"
|
|
@@ -2495,9 +2708,9 @@ var explainCommand = defineCommand22({
|
|
|
2495
2708
|
});
|
|
2496
2709
|
|
|
2497
2710
|
// src/commands/config/get.ts
|
|
2498
|
-
import { defineCommand as
|
|
2499
|
-
import
|
|
2500
|
-
var configGetCommand =
|
|
2711
|
+
import { defineCommand as defineCommand24 } from "citty";
|
|
2712
|
+
import consola21 from "consola";
|
|
2713
|
+
var configGetCommand = defineCommand24({
|
|
2501
2714
|
meta: {
|
|
2502
2715
|
name: "get",
|
|
2503
2716
|
description: "Get a configuration value"
|
|
@@ -2517,7 +2730,7 @@ var configGetCommand = defineCommand23({
|
|
|
2517
2730
|
if (idp)
|
|
2518
2731
|
console.log(idp);
|
|
2519
2732
|
else
|
|
2520
|
-
|
|
2733
|
+
consola21.info("No IdP configured.");
|
|
2521
2734
|
break;
|
|
2522
2735
|
}
|
|
2523
2736
|
case "email": {
|
|
@@ -2525,7 +2738,7 @@ var configGetCommand = defineCommand23({
|
|
|
2525
2738
|
if (auth?.email)
|
|
2526
2739
|
console.log(auth.email);
|
|
2527
2740
|
else
|
|
2528
|
-
|
|
2741
|
+
consola21.info("Not logged in.");
|
|
2529
2742
|
break;
|
|
2530
2743
|
}
|
|
2531
2744
|
default: {
|
|
@@ -2538,7 +2751,7 @@ var configGetCommand = defineCommand23({
|
|
|
2538
2751
|
if (sectionObj && field in sectionObj) {
|
|
2539
2752
|
console.log(sectionObj[field]);
|
|
2540
2753
|
} else {
|
|
2541
|
-
|
|
2754
|
+
consola21.info(`Key "${key}" not set.`);
|
|
2542
2755
|
}
|
|
2543
2756
|
} else {
|
|
2544
2757
|
throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
|
|
@@ -2549,9 +2762,9 @@ var configGetCommand = defineCommand23({
|
|
|
2549
2762
|
});
|
|
2550
2763
|
|
|
2551
2764
|
// src/commands/config/set.ts
|
|
2552
|
-
import { defineCommand as
|
|
2553
|
-
import
|
|
2554
|
-
var configSetCommand =
|
|
2765
|
+
import { defineCommand as defineCommand25 } from "citty";
|
|
2766
|
+
import consola22 from "consola";
|
|
2767
|
+
var configSetCommand = defineCommand25({
|
|
2555
2768
|
meta: {
|
|
2556
2769
|
name: "set",
|
|
2557
2770
|
description: "Set a configuration value"
|
|
@@ -2587,12 +2800,12 @@ var configSetCommand = defineCommand24({
|
|
|
2587
2800
|
throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
|
|
2588
2801
|
}
|
|
2589
2802
|
saveConfig(config);
|
|
2590
|
-
|
|
2803
|
+
consola22.success(`Set ${key} = ${value}`);
|
|
2591
2804
|
}
|
|
2592
2805
|
});
|
|
2593
2806
|
|
|
2594
2807
|
// src/commands/fetch/index.ts
|
|
2595
|
-
import { defineCommand as
|
|
2808
|
+
import { defineCommand as defineCommand26 } from "citty";
|
|
2596
2809
|
async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
2597
2810
|
const token = getAuthToken();
|
|
2598
2811
|
if (!token) {
|
|
@@ -2628,13 +2841,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
|
2628
2841
|
throw new CliError(`HTTP ${response.status} ${response.statusText}`);
|
|
2629
2842
|
}
|
|
2630
2843
|
}
|
|
2631
|
-
var fetchCommand =
|
|
2844
|
+
var fetchCommand = defineCommand26({
|
|
2632
2845
|
meta: {
|
|
2633
2846
|
name: "fetch",
|
|
2634
2847
|
description: "Make authenticated HTTP requests"
|
|
2635
2848
|
},
|
|
2636
2849
|
subCommands: {
|
|
2637
|
-
get:
|
|
2850
|
+
get: defineCommand26({
|
|
2638
2851
|
meta: {
|
|
2639
2852
|
name: "get",
|
|
2640
2853
|
description: "GET request with auth token"
|
|
@@ -2660,7 +2873,7 @@ var fetchCommand = defineCommand25({
|
|
|
2660
2873
|
await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
|
|
2661
2874
|
}
|
|
2662
2875
|
}),
|
|
2663
|
-
post:
|
|
2876
|
+
post: defineCommand26({
|
|
2664
2877
|
meta: {
|
|
2665
2878
|
name: "post",
|
|
2666
2879
|
description: "POST request with auth token"
|
|
@@ -2699,8 +2912,8 @@ var fetchCommand = defineCommand25({
|
|
|
2699
2912
|
});
|
|
2700
2913
|
|
|
2701
2914
|
// src/commands/mcp/index.ts
|
|
2702
|
-
import { defineCommand as
|
|
2703
|
-
var mcpCommand =
|
|
2915
|
+
import { defineCommand as defineCommand27 } from "citty";
|
|
2916
|
+
var mcpCommand = defineCommand27({
|
|
2704
2917
|
meta: {
|
|
2705
2918
|
name: "mcp",
|
|
2706
2919
|
description: "Start MCP server for AI agents"
|
|
@@ -2723,25 +2936,25 @@ var mcpCommand = defineCommand26({
|
|
|
2723
2936
|
if (transport !== "stdio" && transport !== "sse") {
|
|
2724
2937
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
2725
2938
|
}
|
|
2726
|
-
const { startMcpServer } = await import("./server-
|
|
2939
|
+
const { startMcpServer } = await import("./server-6RPIR76X.js");
|
|
2727
2940
|
await startMcpServer(transport, port);
|
|
2728
2941
|
}
|
|
2729
2942
|
});
|
|
2730
2943
|
|
|
2731
2944
|
// src/commands/init/index.ts
|
|
2732
|
-
import { existsSync as existsSync3, copyFileSync, writeFileSync } from "fs";
|
|
2945
|
+
import { existsSync as existsSync3, copyFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
2733
2946
|
import { randomBytes } from "crypto";
|
|
2734
2947
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
2735
|
-
import { join as
|
|
2736
|
-
import { defineCommand as
|
|
2737
|
-
import
|
|
2948
|
+
import { join as join4 } from "path";
|
|
2949
|
+
import { defineCommand as defineCommand28 } from "citty";
|
|
2950
|
+
import consola23 from "consola";
|
|
2738
2951
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
2739
2952
|
async function downloadTemplate(repo, targetDir) {
|
|
2740
2953
|
const { downloadTemplate: gigetDownload } = await import("giget");
|
|
2741
2954
|
await gigetDownload(`gh:${repo}`, { dir: targetDir, force: false });
|
|
2742
2955
|
}
|
|
2743
2956
|
function installDeps(dir) {
|
|
2744
|
-
const hasLockFile = (name) => existsSync3(
|
|
2957
|
+
const hasLockFile = (name) => existsSync3(join4(dir, name));
|
|
2745
2958
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
2746
2959
|
execFileSync3("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
2747
2960
|
} else if (hasLockFile("bun.lockb")) {
|
|
@@ -2751,20 +2964,20 @@ function installDeps(dir) {
|
|
|
2751
2964
|
}
|
|
2752
2965
|
}
|
|
2753
2966
|
async function promptChoice(message, choices) {
|
|
2754
|
-
const result = await
|
|
2967
|
+
const result = await consola23.prompt(message, { type: "select", options: choices });
|
|
2755
2968
|
if (typeof result === "symbol") {
|
|
2756
2969
|
throw new CliExit(0);
|
|
2757
2970
|
}
|
|
2758
2971
|
return result;
|
|
2759
2972
|
}
|
|
2760
2973
|
async function promptText(message, defaultValue) {
|
|
2761
|
-
const result = await
|
|
2974
|
+
const result = await consola23.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
|
|
2762
2975
|
if (typeof result === "symbol") {
|
|
2763
2976
|
throw new CliExit(0);
|
|
2764
2977
|
}
|
|
2765
2978
|
return result || defaultValue || "";
|
|
2766
2979
|
}
|
|
2767
|
-
var initCommand =
|
|
2980
|
+
var initCommand = defineCommand28({
|
|
2768
2981
|
meta: {
|
|
2769
2982
|
name: "init",
|
|
2770
2983
|
description: "Scaffold a new OpenApe project"
|
|
@@ -2806,23 +3019,23 @@ var initCommand = defineCommand27({
|
|
|
2806
3019
|
});
|
|
2807
3020
|
async function initSP(targetDir) {
|
|
2808
3021
|
const dir = targetDir || "my-app";
|
|
2809
|
-
if (existsSync3(
|
|
3022
|
+
if (existsSync3(join4(dir, "package.json"))) {
|
|
2810
3023
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
2811
3024
|
}
|
|
2812
|
-
|
|
3025
|
+
consola23.start("Scaffolding SP starter...");
|
|
2813
3026
|
await downloadTemplate("openape-ai/openape-sp-starter", dir);
|
|
2814
|
-
|
|
2815
|
-
|
|
3027
|
+
consola23.success("Scaffolded from openape-sp-starter");
|
|
3028
|
+
consola23.start("Installing dependencies...");
|
|
2816
3029
|
installDeps(dir);
|
|
2817
|
-
|
|
2818
|
-
const envExample =
|
|
2819
|
-
const envFile =
|
|
3030
|
+
consola23.success("Dependencies installed");
|
|
3031
|
+
const envExample = join4(dir, ".env.example");
|
|
3032
|
+
const envFile = join4(dir, ".env");
|
|
2820
3033
|
if (existsSync3(envExample) && !existsSync3(envFile)) {
|
|
2821
3034
|
copyFileSync(envExample, envFile);
|
|
2822
|
-
|
|
3035
|
+
consola23.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
2823
3036
|
}
|
|
2824
3037
|
console.log("");
|
|
2825
|
-
|
|
3038
|
+
consola23.box([
|
|
2826
3039
|
`cd ${dir}`,
|
|
2827
3040
|
"npm run dev",
|
|
2828
3041
|
"",
|
|
@@ -2831,7 +3044,7 @@ async function initSP(targetDir) {
|
|
|
2831
3044
|
}
|
|
2832
3045
|
async function initIdP(targetDir) {
|
|
2833
3046
|
const dir = targetDir || "my-idp";
|
|
2834
|
-
if (existsSync3(
|
|
3047
|
+
if (existsSync3(join4(dir, "package.json"))) {
|
|
2835
3048
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
2836
3049
|
}
|
|
2837
3050
|
const domain = await promptText("Domain for the IdP", "localhost");
|
|
@@ -2841,15 +3054,15 @@ async function initIdP(targetDir) {
|
|
|
2841
3054
|
"s3 (S3-compatible)"
|
|
2842
3055
|
]);
|
|
2843
3056
|
const adminEmail = await promptText("Admin email");
|
|
2844
|
-
|
|
3057
|
+
consola23.start("Scaffolding IdP starter...");
|
|
2845
3058
|
await downloadTemplate("openape-ai/openape-idp-starter", dir);
|
|
2846
|
-
|
|
2847
|
-
|
|
3059
|
+
consola23.success("Scaffolded from openape-idp-starter");
|
|
3060
|
+
consola23.start("Installing dependencies...");
|
|
2848
3061
|
installDeps(dir);
|
|
2849
|
-
|
|
3062
|
+
consola23.success("Dependencies installed");
|
|
2850
3063
|
const sessionSecret = randomBytes(32).toString("hex");
|
|
2851
3064
|
const managementToken = randomBytes(32).toString("hex");
|
|
2852
|
-
|
|
3065
|
+
consola23.success("Secrets generated");
|
|
2853
3066
|
const isLocalhost = domain === "localhost";
|
|
2854
3067
|
const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
|
|
2855
3068
|
const envContent = [
|
|
@@ -2863,11 +3076,11 @@ async function initIdP(targetDir) {
|
|
|
2863
3076
|
`NUXT_OPENAPE_RP_ID=${domain}`,
|
|
2864
3077
|
`NUXT_OPENAPE_RP_ORIGIN=${origin}`
|
|
2865
3078
|
].join("\n");
|
|
2866
|
-
|
|
3079
|
+
writeFileSync2(join4(dir, ".env"), `${envContent}
|
|
2867
3080
|
`, { mode: 384 });
|
|
2868
|
-
|
|
3081
|
+
consola23.success(".env created");
|
|
2869
3082
|
console.log("");
|
|
2870
|
-
|
|
3083
|
+
consola23.box([
|
|
2871
3084
|
`cd ${dir}`,
|
|
2872
3085
|
"npm run dev",
|
|
2873
3086
|
"",
|
|
@@ -2884,19 +3097,19 @@ async function initIdP(targetDir) {
|
|
|
2884
3097
|
|
|
2885
3098
|
// src/commands/enroll.ts
|
|
2886
3099
|
import { Buffer as Buffer2 } from "buffer";
|
|
2887
|
-
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as
|
|
3100
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync } from "fs";
|
|
2888
3101
|
import { execFile as execFile2 } from "child_process";
|
|
2889
3102
|
import { generateKeyPairSync, sign } from "crypto";
|
|
2890
|
-
import { dirname, resolve as
|
|
2891
|
-
import { homedir as
|
|
2892
|
-
import { defineCommand as
|
|
2893
|
-
import
|
|
3103
|
+
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
3104
|
+
import { homedir as homedir5 } from "os";
|
|
3105
|
+
import { defineCommand as defineCommand29 } from "citty";
|
|
3106
|
+
import consola24 from "consola";
|
|
2894
3107
|
var DEFAULT_IDP_URL2 = "https://id.openape.at";
|
|
2895
3108
|
var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
|
|
2896
3109
|
var POLL_INTERVAL = 3e3;
|
|
2897
3110
|
var POLL_TIMEOUT = 3e5;
|
|
2898
3111
|
function resolvePath2(p) {
|
|
2899
|
-
return
|
|
3112
|
+
return resolve3(p.replace(/^~/, homedir5()));
|
|
2900
3113
|
}
|
|
2901
3114
|
function openBrowser2(url) {
|
|
2902
3115
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
@@ -2922,13 +3135,13 @@ function readPublicKey(keyPath) {
|
|
|
2922
3135
|
}
|
|
2923
3136
|
function generateAndSaveKey(keyPath) {
|
|
2924
3137
|
const resolved = resolvePath2(keyPath);
|
|
2925
|
-
const dir =
|
|
3138
|
+
const dir = dirname2(resolved);
|
|
2926
3139
|
if (!existsSync4(dir)) {
|
|
2927
3140
|
mkdirSync(dir, { recursive: true });
|
|
2928
3141
|
}
|
|
2929
3142
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
2930
3143
|
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
2931
|
-
|
|
3144
|
+
writeFileSync3(resolved, privatePem, { mode: 384 });
|
|
2932
3145
|
const jwk = publicKey.export({ format: "jwk" });
|
|
2933
3146
|
const pubBytes = Buffer2.from(jwk.x, "base64url");
|
|
2934
3147
|
const keyTypeStr = "ssh-ed25519";
|
|
@@ -2938,7 +3151,7 @@ function generateAndSaveKey(keyPath) {
|
|
|
2938
3151
|
pubKeyLen.writeUInt32BE(pubBytes.length);
|
|
2939
3152
|
const blob = Buffer2.concat([keyTypeLen, Buffer2.from(keyTypeStr), pubKeyLen, pubBytes]);
|
|
2940
3153
|
const pubKeyStr = `ssh-ed25519 ${blob.toString("base64")}`;
|
|
2941
|
-
|
|
3154
|
+
writeFileSync3(`${resolved}.pub`, `${pubKeyStr}
|
|
2942
3155
|
`, { mode: 420 });
|
|
2943
3156
|
return pubKeyStr;
|
|
2944
3157
|
}
|
|
@@ -2971,11 +3184,11 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
2971
3184
|
}
|
|
2972
3185
|
} catch {
|
|
2973
3186
|
}
|
|
2974
|
-
await new Promise((
|
|
3187
|
+
await new Promise((resolve4) => setTimeout(resolve4, POLL_INTERVAL));
|
|
2975
3188
|
}
|
|
2976
3189
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
2977
3190
|
}
|
|
2978
|
-
var enrollCommand =
|
|
3191
|
+
var enrollCommand = defineCommand29({
|
|
2979
3192
|
meta: {
|
|
2980
3193
|
name: "enroll",
|
|
2981
3194
|
description: "Enroll an agent with an Identity Provider"
|
|
@@ -2995,18 +3208,18 @@ var enrollCommand = defineCommand28({
|
|
|
2995
3208
|
}
|
|
2996
3209
|
},
|
|
2997
3210
|
async run({ args }) {
|
|
2998
|
-
const idp = args.idp || await
|
|
3211
|
+
const idp = args.idp || await consola24.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
|
|
2999
3212
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
3000
3213
|
return r;
|
|
3001
3214
|
}) || DEFAULT_IDP_URL2;
|
|
3002
|
-
const agentName = args.name || await
|
|
3215
|
+
const agentName = args.name || await consola24.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
|
|
3003
3216
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
3004
3217
|
return r;
|
|
3005
3218
|
});
|
|
3006
3219
|
if (!agentName) {
|
|
3007
3220
|
throw new CliError("Agent name is required.");
|
|
3008
3221
|
}
|
|
3009
|
-
const keyPath = args.key || await
|
|
3222
|
+
const keyPath = args.key || await consola24.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
|
|
3010
3223
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
3011
3224
|
return r;
|
|
3012
3225
|
}) || DEFAULT_KEY_PATH;
|
|
@@ -3014,19 +3227,19 @@ var enrollCommand = defineCommand28({
|
|
|
3014
3227
|
let publicKey;
|
|
3015
3228
|
if (existsSync4(resolvedKey)) {
|
|
3016
3229
|
publicKey = readPublicKey(resolvedKey);
|
|
3017
|
-
|
|
3230
|
+
consola24.success(`Using existing key ${keyPath}`);
|
|
3018
3231
|
} else {
|
|
3019
|
-
|
|
3232
|
+
consola24.start(`Generating Ed25519 key pair at ${keyPath}...`);
|
|
3020
3233
|
publicKey = generateAndSaveKey(keyPath);
|
|
3021
|
-
|
|
3234
|
+
consola24.success(`Key pair generated at ${keyPath}`);
|
|
3022
3235
|
}
|
|
3023
3236
|
const encodedKey = encodeURIComponent(publicKey);
|
|
3024
3237
|
const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
|
|
3025
|
-
|
|
3026
|
-
|
|
3238
|
+
consola24.info("Opening browser for enrollment...");
|
|
3239
|
+
consola24.info(`\u2192 ${idp}/enroll`);
|
|
3027
3240
|
openBrowser2(enrollUrl);
|
|
3028
3241
|
console.log("");
|
|
3029
|
-
const agentEmail = await
|
|
3242
|
+
const agentEmail = await consola24.prompt(
|
|
3030
3243
|
"Agent email (shown in browser after enrollment)",
|
|
3031
3244
|
{ type: "text", placeholder: `agent+${agentName}@...` }
|
|
3032
3245
|
).then((r) => {
|
|
@@ -3036,7 +3249,7 @@ var enrollCommand = defineCommand28({
|
|
|
3036
3249
|
if (!agentEmail) {
|
|
3037
3250
|
throw new CliError("Agent email is required to verify enrollment.");
|
|
3038
3251
|
}
|
|
3039
|
-
|
|
3252
|
+
consola24.start("Verifying enrollment...");
|
|
3040
3253
|
const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
|
|
3041
3254
|
saveAuth({
|
|
3042
3255
|
idp,
|
|
@@ -3048,18 +3261,18 @@ var enrollCommand = defineCommand28({
|
|
|
3048
3261
|
config.defaults = { ...config.defaults, idp };
|
|
3049
3262
|
config.agent = { key: keyPath, email: agentEmail };
|
|
3050
3263
|
saveConfig(config);
|
|
3051
|
-
|
|
3052
|
-
|
|
3264
|
+
consola24.success(`Agent enrolled as ${agentEmail}`);
|
|
3265
|
+
consola24.success("Config saved to ~/.config/apes/");
|
|
3053
3266
|
console.log("");
|
|
3054
|
-
|
|
3267
|
+
consola24.info("Verify with: apes whoami");
|
|
3055
3268
|
}
|
|
3056
3269
|
});
|
|
3057
3270
|
|
|
3058
3271
|
// src/commands/register-user.ts
|
|
3059
3272
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
3060
|
-
import { defineCommand as
|
|
3061
|
-
import
|
|
3062
|
-
var registerUserCommand =
|
|
3273
|
+
import { defineCommand as defineCommand30 } from "citty";
|
|
3274
|
+
import consola25 from "consola";
|
|
3275
|
+
var registerUserCommand = defineCommand30({
|
|
3063
3276
|
meta: {
|
|
3064
3277
|
name: "register-user",
|
|
3065
3278
|
description: "Register a sub-user with SSH key"
|
|
@@ -3114,15 +3327,15 @@ var registerUserCommand = defineCommand29({
|
|
|
3114
3327
|
...userType ? { type: userType } : {}
|
|
3115
3328
|
}
|
|
3116
3329
|
});
|
|
3117
|
-
|
|
3330
|
+
consola25.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
|
|
3118
3331
|
}
|
|
3119
3332
|
});
|
|
3120
3333
|
|
|
3121
3334
|
// src/commands/dns-check.ts
|
|
3122
|
-
import { defineCommand as
|
|
3123
|
-
import
|
|
3335
|
+
import { defineCommand as defineCommand31 } from "citty";
|
|
3336
|
+
import consola26 from "consola";
|
|
3124
3337
|
import { resolveDDISA as resolveDDISA2 } from "@openape/core";
|
|
3125
|
-
var dnsCheckCommand =
|
|
3338
|
+
var dnsCheckCommand = defineCommand31({
|
|
3126
3339
|
meta: {
|
|
3127
3340
|
name: "dns-check",
|
|
3128
3341
|
description: "Validate DDISA DNS TXT records for a domain"
|
|
@@ -3136,7 +3349,7 @@ var dnsCheckCommand = defineCommand30({
|
|
|
3136
3349
|
},
|
|
3137
3350
|
async run({ args }) {
|
|
3138
3351
|
const domain = args.domain;
|
|
3139
|
-
|
|
3352
|
+
consola26.start(`Checking _ddisa.${domain}...`);
|
|
3140
3353
|
try {
|
|
3141
3354
|
const result = await resolveDDISA2(domain);
|
|
3142
3355
|
if (!result) {
|
|
@@ -3145,7 +3358,7 @@ var dnsCheckCommand = defineCommand30({
|
|
|
3145
3358
|
console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
|
|
3146
3359
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
3147
3360
|
}
|
|
3148
|
-
|
|
3361
|
+
consola26.success(`_ddisa.${domain} \u2192 ${result.idp}`);
|
|
3149
3362
|
console.log("");
|
|
3150
3363
|
console.log(` Version: ${result.version || "ddisa1"}`);
|
|
3151
3364
|
console.log(` IdP URL: ${result.idp}`);
|
|
@@ -3154,14 +3367,14 @@ var dnsCheckCommand = defineCommand30({
|
|
|
3154
3367
|
if (result.priority !== void 0)
|
|
3155
3368
|
console.log(` Priority: ${result.priority}`);
|
|
3156
3369
|
console.log("");
|
|
3157
|
-
|
|
3370
|
+
consola26.start(`Verifying IdP at ${result.idp}...`);
|
|
3158
3371
|
const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
|
|
3159
3372
|
if (!discoResp.ok) {
|
|
3160
|
-
|
|
3373
|
+
consola26.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
|
|
3161
3374
|
return;
|
|
3162
3375
|
}
|
|
3163
3376
|
const disco = await discoResp.json();
|
|
3164
|
-
|
|
3377
|
+
consola26.success(`IdP is reachable`);
|
|
3165
3378
|
console.log(` Issuer: ${disco.issuer}`);
|
|
3166
3379
|
console.log(` DDISA: v${disco.ddisa_version || "?"}`);
|
|
3167
3380
|
if (disco.ddisa_auth_methods_supported) {
|
|
@@ -3179,7 +3392,7 @@ var dnsCheckCommand = defineCommand30({
|
|
|
3179
3392
|
// src/commands/health.ts
|
|
3180
3393
|
import { exec } from "child_process";
|
|
3181
3394
|
import { promisify } from "util";
|
|
3182
|
-
import { defineCommand as
|
|
3395
|
+
import { defineCommand as defineCommand32 } from "citty";
|
|
3183
3396
|
var execAsync = promisify(exec);
|
|
3184
3397
|
async function resolveApeShellPath() {
|
|
3185
3398
|
try {
|
|
@@ -3215,7 +3428,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
3215
3428
|
}
|
|
3216
3429
|
}
|
|
3217
3430
|
async function runHealth(args) {
|
|
3218
|
-
const version = true ? "0.
|
|
3431
|
+
const version = true ? "0.13.1" : "0.0.0";
|
|
3219
3432
|
const auth = loadAuth();
|
|
3220
3433
|
if (!auth) {
|
|
3221
3434
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -3278,7 +3491,7 @@ async function runHealth(args) {
|
|
|
3278
3491
|
throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
|
|
3279
3492
|
}
|
|
3280
3493
|
}
|
|
3281
|
-
var healthCommand =
|
|
3494
|
+
var healthCommand = defineCommand32({
|
|
3282
3495
|
meta: {
|
|
3283
3496
|
name: "health",
|
|
3284
3497
|
description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
|
|
@@ -3296,8 +3509,8 @@ var healthCommand = defineCommand31({
|
|
|
3296
3509
|
});
|
|
3297
3510
|
|
|
3298
3511
|
// src/commands/workflows.ts
|
|
3299
|
-
import { defineCommand as
|
|
3300
|
-
import
|
|
3512
|
+
import { defineCommand as defineCommand33 } from "citty";
|
|
3513
|
+
import consola27 from "consola";
|
|
3301
3514
|
|
|
3302
3515
|
// src/guides/index.ts
|
|
3303
3516
|
var guides = [
|
|
@@ -3347,7 +3560,7 @@ var guides = [
|
|
|
3347
3560
|
];
|
|
3348
3561
|
|
|
3349
3562
|
// src/commands/workflows.ts
|
|
3350
|
-
var workflowsCommand =
|
|
3563
|
+
var workflowsCommand = defineCommand33({
|
|
3351
3564
|
meta: {
|
|
3352
3565
|
name: "workflows",
|
|
3353
3566
|
description: "Discover workflow guides"
|
|
@@ -3368,7 +3581,7 @@ var workflowsCommand = defineCommand32({
|
|
|
3368
3581
|
if (args.id) {
|
|
3369
3582
|
const guide = guides.find((g) => g.id === String(args.id));
|
|
3370
3583
|
if (!guide) {
|
|
3371
|
-
|
|
3584
|
+
consola27.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
|
|
3372
3585
|
throw new CliError(`Guide not found: ${args.id}`);
|
|
3373
3586
|
}
|
|
3374
3587
|
if (args.json) {
|
|
@@ -3417,10 +3630,10 @@ if (shellRewrite) {
|
|
|
3417
3630
|
if (shellRewrite.action === "rewrite") {
|
|
3418
3631
|
process.argv = shellRewrite.argv;
|
|
3419
3632
|
} else if (shellRewrite.action === "version") {
|
|
3420
|
-
console.log(`ape-shell ${"0.
|
|
3633
|
+
console.log(`ape-shell ${"0.13.1"} (OpenApe DDISA shell wrapper)`);
|
|
3421
3634
|
process.exit(0);
|
|
3422
3635
|
} else if (shellRewrite.action === "help") {
|
|
3423
|
-
console.log(`ape-shell ${"0.
|
|
3636
|
+
console.log(`ape-shell ${"0.13.1"} \u2014 OpenApe DDISA shell wrapper`);
|
|
3424
3637
|
console.log("");
|
|
3425
3638
|
console.log("Usage:");
|
|
3426
3639
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -3444,7 +3657,7 @@ if (shellRewrite) {
|
|
|
3444
3657
|
}
|
|
3445
3658
|
}
|
|
3446
3659
|
var debug = process.argv.includes("--debug");
|
|
3447
|
-
var grantsCommand =
|
|
3660
|
+
var grantsCommand = defineCommand34({
|
|
3448
3661
|
meta: {
|
|
3449
3662
|
name: "grants",
|
|
3450
3663
|
description: "Grant management"
|
|
@@ -3465,7 +3678,7 @@ var grantsCommand = defineCommand33({
|
|
|
3465
3678
|
"delegation-revoke": delegationRevokeCommand
|
|
3466
3679
|
}
|
|
3467
3680
|
});
|
|
3468
|
-
var configCommand =
|
|
3681
|
+
var configCommand = defineCommand34({
|
|
3469
3682
|
meta: {
|
|
3470
3683
|
name: "config",
|
|
3471
3684
|
description: "Configuration management"
|
|
@@ -3475,10 +3688,10 @@ var configCommand = defineCommand33({
|
|
|
3475
3688
|
set: configSetCommand
|
|
3476
3689
|
}
|
|
3477
3690
|
});
|
|
3478
|
-
var main =
|
|
3691
|
+
var main = defineCommand34({
|
|
3479
3692
|
meta: {
|
|
3480
3693
|
name: "apes",
|
|
3481
|
-
version: "0.
|
|
3694
|
+
version: "0.13.1",
|
|
3482
3695
|
description: "Unified CLI for OpenApe"
|
|
3483
3696
|
},
|
|
3484
3697
|
subCommands: {
|
|
@@ -3493,6 +3706,7 @@ var main = defineCommand33({
|
|
|
3493
3706
|
grants: grantsCommand,
|
|
3494
3707
|
admin: adminCommand,
|
|
3495
3708
|
run: runCommand,
|
|
3709
|
+
proxy: proxyCommand,
|
|
3496
3710
|
explain: explainCommand,
|
|
3497
3711
|
adapter: adapterCommand,
|
|
3498
3712
|
config: configCommand,
|
|
@@ -3506,13 +3720,13 @@ runMain(main).catch((err) => {
|
|
|
3506
3720
|
process.exit(err.exitCode);
|
|
3507
3721
|
}
|
|
3508
3722
|
if (err instanceof CliError) {
|
|
3509
|
-
|
|
3723
|
+
consola28.error(err.message);
|
|
3510
3724
|
process.exit(err.exitCode);
|
|
3511
3725
|
}
|
|
3512
3726
|
if (debug) {
|
|
3513
|
-
|
|
3727
|
+
consola28.error(err);
|
|
3514
3728
|
} else {
|
|
3515
|
-
|
|
3729
|
+
consola28.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
|
|
3516
3730
|
}
|
|
3517
3731
|
process.exit(1);
|
|
3518
3732
|
});
|