@openape/apes 0.12.5 → 0.13.0
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 +310 -103
- package/dist/cli.js.map +1 -1
- package/dist/{orchestrator-EHFFTEL5.js → orchestrator-PUAO57CY.js} +2 -2
- package/dist/orchestrator-PUAO57CY.js.map +1 -0
- package/dist/{server-4JMBRSDA.js → server-QGNNBQHT.js} +2 -2
- package/package.json +5 -5
- package/dist/orchestrator-EHFFTEL5.js.map +0 -1
- package/scripts/fix-node-pty-perms.mjs +0 -39
- /package/dist/{server-4JMBRSDA.js.map → server-QGNNBQHT.js.map} +0 -0
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,215 @@ 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 childEnv = {
|
|
2629
|
+
...process.env,
|
|
2630
|
+
HTTPS_PROXY: proxyUrl,
|
|
2631
|
+
HTTP_PROXY: proxyUrl,
|
|
2632
|
+
NO_PROXY: process.env.NO_PROXY ?? "127.0.0.1,localhost"
|
|
2633
|
+
};
|
|
2634
|
+
const exitCode = await new Promise((resolveExit) => {
|
|
2635
|
+
const child = spawn2(wrapped[0], wrapped.slice(1), {
|
|
2636
|
+
stdio: "inherit",
|
|
2637
|
+
env: childEnv
|
|
2638
|
+
});
|
|
2639
|
+
const forward = (sig) => () => child.kill(sig);
|
|
2640
|
+
const onSigint = forward("SIGINT");
|
|
2641
|
+
const onSigterm = forward("SIGTERM");
|
|
2642
|
+
process.on("SIGINT", onSigint);
|
|
2643
|
+
process.on("SIGTERM", onSigterm);
|
|
2644
|
+
child.once("exit", (code, signal) => {
|
|
2645
|
+
process.off("SIGINT", onSigint);
|
|
2646
|
+
process.off("SIGTERM", onSigterm);
|
|
2647
|
+
if (signal) resolveExit(128 + (signalNumber(signal) ?? 0));
|
|
2648
|
+
else resolveExit(code ?? 0);
|
|
2649
|
+
});
|
|
2650
|
+
child.once("error", (err) => {
|
|
2651
|
+
consola20.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
|
|
2652
|
+
resolveExit(127);
|
|
2653
|
+
});
|
|
2654
|
+
});
|
|
2655
|
+
if (close) await close();
|
|
2656
|
+
if (exitCode !== 0) throw new CliExit(exitCode);
|
|
2657
|
+
}
|
|
2658
|
+
});
|
|
2659
|
+
function signalNumber(signal) {
|
|
2660
|
+
const map = { SIGINT: 2, SIGTERM: 15, SIGHUP: 1, SIGQUIT: 3, SIGKILL: 9 };
|
|
2661
|
+
return map[signal];
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2664
|
+
// src/commands/explain.ts
|
|
2665
|
+
import { defineCommand as defineCommand23 } from "citty";
|
|
2666
|
+
var explainCommand = defineCommand23({
|
|
2461
2667
|
meta: {
|
|
2462
2668
|
name: "explain",
|
|
2463
2669
|
description: "Show what permission a command would need"
|
|
@@ -2495,9 +2701,9 @@ var explainCommand = defineCommand22({
|
|
|
2495
2701
|
});
|
|
2496
2702
|
|
|
2497
2703
|
// src/commands/config/get.ts
|
|
2498
|
-
import { defineCommand as
|
|
2499
|
-
import
|
|
2500
|
-
var configGetCommand =
|
|
2704
|
+
import { defineCommand as defineCommand24 } from "citty";
|
|
2705
|
+
import consola21 from "consola";
|
|
2706
|
+
var configGetCommand = defineCommand24({
|
|
2501
2707
|
meta: {
|
|
2502
2708
|
name: "get",
|
|
2503
2709
|
description: "Get a configuration value"
|
|
@@ -2517,7 +2723,7 @@ var configGetCommand = defineCommand23({
|
|
|
2517
2723
|
if (idp)
|
|
2518
2724
|
console.log(idp);
|
|
2519
2725
|
else
|
|
2520
|
-
|
|
2726
|
+
consola21.info("No IdP configured.");
|
|
2521
2727
|
break;
|
|
2522
2728
|
}
|
|
2523
2729
|
case "email": {
|
|
@@ -2525,7 +2731,7 @@ var configGetCommand = defineCommand23({
|
|
|
2525
2731
|
if (auth?.email)
|
|
2526
2732
|
console.log(auth.email);
|
|
2527
2733
|
else
|
|
2528
|
-
|
|
2734
|
+
consola21.info("Not logged in.");
|
|
2529
2735
|
break;
|
|
2530
2736
|
}
|
|
2531
2737
|
default: {
|
|
@@ -2538,7 +2744,7 @@ var configGetCommand = defineCommand23({
|
|
|
2538
2744
|
if (sectionObj && field in sectionObj) {
|
|
2539
2745
|
console.log(sectionObj[field]);
|
|
2540
2746
|
} else {
|
|
2541
|
-
|
|
2747
|
+
consola21.info(`Key "${key}" not set.`);
|
|
2542
2748
|
}
|
|
2543
2749
|
} else {
|
|
2544
2750
|
throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
|
|
@@ -2549,9 +2755,9 @@ var configGetCommand = defineCommand23({
|
|
|
2549
2755
|
});
|
|
2550
2756
|
|
|
2551
2757
|
// src/commands/config/set.ts
|
|
2552
|
-
import { defineCommand as
|
|
2553
|
-
import
|
|
2554
|
-
var configSetCommand =
|
|
2758
|
+
import { defineCommand as defineCommand25 } from "citty";
|
|
2759
|
+
import consola22 from "consola";
|
|
2760
|
+
var configSetCommand = defineCommand25({
|
|
2555
2761
|
meta: {
|
|
2556
2762
|
name: "set",
|
|
2557
2763
|
description: "Set a configuration value"
|
|
@@ -2587,12 +2793,12 @@ var configSetCommand = defineCommand24({
|
|
|
2587
2793
|
throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
|
|
2588
2794
|
}
|
|
2589
2795
|
saveConfig(config);
|
|
2590
|
-
|
|
2796
|
+
consola22.success(`Set ${key} = ${value}`);
|
|
2591
2797
|
}
|
|
2592
2798
|
});
|
|
2593
2799
|
|
|
2594
2800
|
// src/commands/fetch/index.ts
|
|
2595
|
-
import { defineCommand as
|
|
2801
|
+
import { defineCommand as defineCommand26 } from "citty";
|
|
2596
2802
|
async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
2597
2803
|
const token = getAuthToken();
|
|
2598
2804
|
if (!token) {
|
|
@@ -2628,13 +2834,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
|
2628
2834
|
throw new CliError(`HTTP ${response.status} ${response.statusText}`);
|
|
2629
2835
|
}
|
|
2630
2836
|
}
|
|
2631
|
-
var fetchCommand =
|
|
2837
|
+
var fetchCommand = defineCommand26({
|
|
2632
2838
|
meta: {
|
|
2633
2839
|
name: "fetch",
|
|
2634
2840
|
description: "Make authenticated HTTP requests"
|
|
2635
2841
|
},
|
|
2636
2842
|
subCommands: {
|
|
2637
|
-
get:
|
|
2843
|
+
get: defineCommand26({
|
|
2638
2844
|
meta: {
|
|
2639
2845
|
name: "get",
|
|
2640
2846
|
description: "GET request with auth token"
|
|
@@ -2660,7 +2866,7 @@ var fetchCommand = defineCommand25({
|
|
|
2660
2866
|
await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
|
|
2661
2867
|
}
|
|
2662
2868
|
}),
|
|
2663
|
-
post:
|
|
2869
|
+
post: defineCommand26({
|
|
2664
2870
|
meta: {
|
|
2665
2871
|
name: "post",
|
|
2666
2872
|
description: "POST request with auth token"
|
|
@@ -2699,8 +2905,8 @@ var fetchCommand = defineCommand25({
|
|
|
2699
2905
|
});
|
|
2700
2906
|
|
|
2701
2907
|
// src/commands/mcp/index.ts
|
|
2702
|
-
import { defineCommand as
|
|
2703
|
-
var mcpCommand =
|
|
2908
|
+
import { defineCommand as defineCommand27 } from "citty";
|
|
2909
|
+
var mcpCommand = defineCommand27({
|
|
2704
2910
|
meta: {
|
|
2705
2911
|
name: "mcp",
|
|
2706
2912
|
description: "Start MCP server for AI agents"
|
|
@@ -2723,25 +2929,25 @@ var mcpCommand = defineCommand26({
|
|
|
2723
2929
|
if (transport !== "stdio" && transport !== "sse") {
|
|
2724
2930
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
2725
2931
|
}
|
|
2726
|
-
const { startMcpServer } = await import("./server-
|
|
2932
|
+
const { startMcpServer } = await import("./server-QGNNBQHT.js");
|
|
2727
2933
|
await startMcpServer(transport, port);
|
|
2728
2934
|
}
|
|
2729
2935
|
});
|
|
2730
2936
|
|
|
2731
2937
|
// src/commands/init/index.ts
|
|
2732
|
-
import { existsSync as existsSync3, copyFileSync, writeFileSync } from "fs";
|
|
2938
|
+
import { existsSync as existsSync3, copyFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
2733
2939
|
import { randomBytes } from "crypto";
|
|
2734
2940
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
2735
|
-
import { join as
|
|
2736
|
-
import { defineCommand as
|
|
2737
|
-
import
|
|
2941
|
+
import { join as join4 } from "path";
|
|
2942
|
+
import { defineCommand as defineCommand28 } from "citty";
|
|
2943
|
+
import consola23 from "consola";
|
|
2738
2944
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
2739
2945
|
async function downloadTemplate(repo, targetDir) {
|
|
2740
2946
|
const { downloadTemplate: gigetDownload } = await import("giget");
|
|
2741
2947
|
await gigetDownload(`gh:${repo}`, { dir: targetDir, force: false });
|
|
2742
2948
|
}
|
|
2743
2949
|
function installDeps(dir) {
|
|
2744
|
-
const hasLockFile = (name) => existsSync3(
|
|
2950
|
+
const hasLockFile = (name) => existsSync3(join4(dir, name));
|
|
2745
2951
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
2746
2952
|
execFileSync3("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
2747
2953
|
} else if (hasLockFile("bun.lockb")) {
|
|
@@ -2751,20 +2957,20 @@ function installDeps(dir) {
|
|
|
2751
2957
|
}
|
|
2752
2958
|
}
|
|
2753
2959
|
async function promptChoice(message, choices) {
|
|
2754
|
-
const result = await
|
|
2960
|
+
const result = await consola23.prompt(message, { type: "select", options: choices });
|
|
2755
2961
|
if (typeof result === "symbol") {
|
|
2756
2962
|
throw new CliExit(0);
|
|
2757
2963
|
}
|
|
2758
2964
|
return result;
|
|
2759
2965
|
}
|
|
2760
2966
|
async function promptText(message, defaultValue) {
|
|
2761
|
-
const result = await
|
|
2967
|
+
const result = await consola23.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
|
|
2762
2968
|
if (typeof result === "symbol") {
|
|
2763
2969
|
throw new CliExit(0);
|
|
2764
2970
|
}
|
|
2765
2971
|
return result || defaultValue || "";
|
|
2766
2972
|
}
|
|
2767
|
-
var initCommand =
|
|
2973
|
+
var initCommand = defineCommand28({
|
|
2768
2974
|
meta: {
|
|
2769
2975
|
name: "init",
|
|
2770
2976
|
description: "Scaffold a new OpenApe project"
|
|
@@ -2806,23 +3012,23 @@ var initCommand = defineCommand27({
|
|
|
2806
3012
|
});
|
|
2807
3013
|
async function initSP(targetDir) {
|
|
2808
3014
|
const dir = targetDir || "my-app";
|
|
2809
|
-
if (existsSync3(
|
|
3015
|
+
if (existsSync3(join4(dir, "package.json"))) {
|
|
2810
3016
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
2811
3017
|
}
|
|
2812
|
-
|
|
3018
|
+
consola23.start("Scaffolding SP starter...");
|
|
2813
3019
|
await downloadTemplate("openape-ai/openape-sp-starter", dir);
|
|
2814
|
-
|
|
2815
|
-
|
|
3020
|
+
consola23.success("Scaffolded from openape-sp-starter");
|
|
3021
|
+
consola23.start("Installing dependencies...");
|
|
2816
3022
|
installDeps(dir);
|
|
2817
|
-
|
|
2818
|
-
const envExample =
|
|
2819
|
-
const envFile =
|
|
3023
|
+
consola23.success("Dependencies installed");
|
|
3024
|
+
const envExample = join4(dir, ".env.example");
|
|
3025
|
+
const envFile = join4(dir, ".env");
|
|
2820
3026
|
if (existsSync3(envExample) && !existsSync3(envFile)) {
|
|
2821
3027
|
copyFileSync(envExample, envFile);
|
|
2822
|
-
|
|
3028
|
+
consola23.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
2823
3029
|
}
|
|
2824
3030
|
console.log("");
|
|
2825
|
-
|
|
3031
|
+
consola23.box([
|
|
2826
3032
|
`cd ${dir}`,
|
|
2827
3033
|
"npm run dev",
|
|
2828
3034
|
"",
|
|
@@ -2831,7 +3037,7 @@ async function initSP(targetDir) {
|
|
|
2831
3037
|
}
|
|
2832
3038
|
async function initIdP(targetDir) {
|
|
2833
3039
|
const dir = targetDir || "my-idp";
|
|
2834
|
-
if (existsSync3(
|
|
3040
|
+
if (existsSync3(join4(dir, "package.json"))) {
|
|
2835
3041
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
2836
3042
|
}
|
|
2837
3043
|
const domain = await promptText("Domain for the IdP", "localhost");
|
|
@@ -2841,15 +3047,15 @@ async function initIdP(targetDir) {
|
|
|
2841
3047
|
"s3 (S3-compatible)"
|
|
2842
3048
|
]);
|
|
2843
3049
|
const adminEmail = await promptText("Admin email");
|
|
2844
|
-
|
|
3050
|
+
consola23.start("Scaffolding IdP starter...");
|
|
2845
3051
|
await downloadTemplate("openape-ai/openape-idp-starter", dir);
|
|
2846
|
-
|
|
2847
|
-
|
|
3052
|
+
consola23.success("Scaffolded from openape-idp-starter");
|
|
3053
|
+
consola23.start("Installing dependencies...");
|
|
2848
3054
|
installDeps(dir);
|
|
2849
|
-
|
|
3055
|
+
consola23.success("Dependencies installed");
|
|
2850
3056
|
const sessionSecret = randomBytes(32).toString("hex");
|
|
2851
3057
|
const managementToken = randomBytes(32).toString("hex");
|
|
2852
|
-
|
|
3058
|
+
consola23.success("Secrets generated");
|
|
2853
3059
|
const isLocalhost = domain === "localhost";
|
|
2854
3060
|
const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
|
|
2855
3061
|
const envContent = [
|
|
@@ -2863,11 +3069,11 @@ async function initIdP(targetDir) {
|
|
|
2863
3069
|
`NUXT_OPENAPE_RP_ID=${domain}`,
|
|
2864
3070
|
`NUXT_OPENAPE_RP_ORIGIN=${origin}`
|
|
2865
3071
|
].join("\n");
|
|
2866
|
-
|
|
3072
|
+
writeFileSync2(join4(dir, ".env"), `${envContent}
|
|
2867
3073
|
`, { mode: 384 });
|
|
2868
|
-
|
|
3074
|
+
consola23.success(".env created");
|
|
2869
3075
|
console.log("");
|
|
2870
|
-
|
|
3076
|
+
consola23.box([
|
|
2871
3077
|
`cd ${dir}`,
|
|
2872
3078
|
"npm run dev",
|
|
2873
3079
|
"",
|
|
@@ -2884,19 +3090,19 @@ async function initIdP(targetDir) {
|
|
|
2884
3090
|
|
|
2885
3091
|
// src/commands/enroll.ts
|
|
2886
3092
|
import { Buffer as Buffer2 } from "buffer";
|
|
2887
|
-
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as
|
|
3093
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync } from "fs";
|
|
2888
3094
|
import { execFile as execFile2 } from "child_process";
|
|
2889
3095
|
import { generateKeyPairSync, sign } from "crypto";
|
|
2890
|
-
import { dirname, resolve as
|
|
2891
|
-
import { homedir as
|
|
2892
|
-
import { defineCommand as
|
|
2893
|
-
import
|
|
3096
|
+
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
3097
|
+
import { homedir as homedir5 } from "os";
|
|
3098
|
+
import { defineCommand as defineCommand29 } from "citty";
|
|
3099
|
+
import consola24 from "consola";
|
|
2894
3100
|
var DEFAULT_IDP_URL2 = "https://id.openape.at";
|
|
2895
3101
|
var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
|
|
2896
3102
|
var POLL_INTERVAL = 3e3;
|
|
2897
3103
|
var POLL_TIMEOUT = 3e5;
|
|
2898
3104
|
function resolvePath2(p) {
|
|
2899
|
-
return
|
|
3105
|
+
return resolve3(p.replace(/^~/, homedir5()));
|
|
2900
3106
|
}
|
|
2901
3107
|
function openBrowser2(url) {
|
|
2902
3108
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
@@ -2922,13 +3128,13 @@ function readPublicKey(keyPath) {
|
|
|
2922
3128
|
}
|
|
2923
3129
|
function generateAndSaveKey(keyPath) {
|
|
2924
3130
|
const resolved = resolvePath2(keyPath);
|
|
2925
|
-
const dir =
|
|
3131
|
+
const dir = dirname2(resolved);
|
|
2926
3132
|
if (!existsSync4(dir)) {
|
|
2927
3133
|
mkdirSync(dir, { recursive: true });
|
|
2928
3134
|
}
|
|
2929
3135
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
2930
3136
|
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
2931
|
-
|
|
3137
|
+
writeFileSync3(resolved, privatePem, { mode: 384 });
|
|
2932
3138
|
const jwk = publicKey.export({ format: "jwk" });
|
|
2933
3139
|
const pubBytes = Buffer2.from(jwk.x, "base64url");
|
|
2934
3140
|
const keyTypeStr = "ssh-ed25519";
|
|
@@ -2938,7 +3144,7 @@ function generateAndSaveKey(keyPath) {
|
|
|
2938
3144
|
pubKeyLen.writeUInt32BE(pubBytes.length);
|
|
2939
3145
|
const blob = Buffer2.concat([keyTypeLen, Buffer2.from(keyTypeStr), pubKeyLen, pubBytes]);
|
|
2940
3146
|
const pubKeyStr = `ssh-ed25519 ${blob.toString("base64")}`;
|
|
2941
|
-
|
|
3147
|
+
writeFileSync3(`${resolved}.pub`, `${pubKeyStr}
|
|
2942
3148
|
`, { mode: 420 });
|
|
2943
3149
|
return pubKeyStr;
|
|
2944
3150
|
}
|
|
@@ -2971,11 +3177,11 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
2971
3177
|
}
|
|
2972
3178
|
} catch {
|
|
2973
3179
|
}
|
|
2974
|
-
await new Promise((
|
|
3180
|
+
await new Promise((resolve4) => setTimeout(resolve4, POLL_INTERVAL));
|
|
2975
3181
|
}
|
|
2976
3182
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
2977
3183
|
}
|
|
2978
|
-
var enrollCommand =
|
|
3184
|
+
var enrollCommand = defineCommand29({
|
|
2979
3185
|
meta: {
|
|
2980
3186
|
name: "enroll",
|
|
2981
3187
|
description: "Enroll an agent with an Identity Provider"
|
|
@@ -2995,18 +3201,18 @@ var enrollCommand = defineCommand28({
|
|
|
2995
3201
|
}
|
|
2996
3202
|
},
|
|
2997
3203
|
async run({ args }) {
|
|
2998
|
-
const idp = args.idp || await
|
|
3204
|
+
const idp = args.idp || await consola24.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
|
|
2999
3205
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
3000
3206
|
return r;
|
|
3001
3207
|
}) || DEFAULT_IDP_URL2;
|
|
3002
|
-
const agentName = args.name || await
|
|
3208
|
+
const agentName = args.name || await consola24.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
|
|
3003
3209
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
3004
3210
|
return r;
|
|
3005
3211
|
});
|
|
3006
3212
|
if (!agentName) {
|
|
3007
3213
|
throw new CliError("Agent name is required.");
|
|
3008
3214
|
}
|
|
3009
|
-
const keyPath = args.key || await
|
|
3215
|
+
const keyPath = args.key || await consola24.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
|
|
3010
3216
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
3011
3217
|
return r;
|
|
3012
3218
|
}) || DEFAULT_KEY_PATH;
|
|
@@ -3014,19 +3220,19 @@ var enrollCommand = defineCommand28({
|
|
|
3014
3220
|
let publicKey;
|
|
3015
3221
|
if (existsSync4(resolvedKey)) {
|
|
3016
3222
|
publicKey = readPublicKey(resolvedKey);
|
|
3017
|
-
|
|
3223
|
+
consola24.success(`Using existing key ${keyPath}`);
|
|
3018
3224
|
} else {
|
|
3019
|
-
|
|
3225
|
+
consola24.start(`Generating Ed25519 key pair at ${keyPath}...`);
|
|
3020
3226
|
publicKey = generateAndSaveKey(keyPath);
|
|
3021
|
-
|
|
3227
|
+
consola24.success(`Key pair generated at ${keyPath}`);
|
|
3022
3228
|
}
|
|
3023
3229
|
const encodedKey = encodeURIComponent(publicKey);
|
|
3024
3230
|
const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
|
|
3025
|
-
|
|
3026
|
-
|
|
3231
|
+
consola24.info("Opening browser for enrollment...");
|
|
3232
|
+
consola24.info(`\u2192 ${idp}/enroll`);
|
|
3027
3233
|
openBrowser2(enrollUrl);
|
|
3028
3234
|
console.log("");
|
|
3029
|
-
const agentEmail = await
|
|
3235
|
+
const agentEmail = await consola24.prompt(
|
|
3030
3236
|
"Agent email (shown in browser after enrollment)",
|
|
3031
3237
|
{ type: "text", placeholder: `agent+${agentName}@...` }
|
|
3032
3238
|
).then((r) => {
|
|
@@ -3036,7 +3242,7 @@ var enrollCommand = defineCommand28({
|
|
|
3036
3242
|
if (!agentEmail) {
|
|
3037
3243
|
throw new CliError("Agent email is required to verify enrollment.");
|
|
3038
3244
|
}
|
|
3039
|
-
|
|
3245
|
+
consola24.start("Verifying enrollment...");
|
|
3040
3246
|
const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
|
|
3041
3247
|
saveAuth({
|
|
3042
3248
|
idp,
|
|
@@ -3048,18 +3254,18 @@ var enrollCommand = defineCommand28({
|
|
|
3048
3254
|
config.defaults = { ...config.defaults, idp };
|
|
3049
3255
|
config.agent = { key: keyPath, email: agentEmail };
|
|
3050
3256
|
saveConfig(config);
|
|
3051
|
-
|
|
3052
|
-
|
|
3257
|
+
consola24.success(`Agent enrolled as ${agentEmail}`);
|
|
3258
|
+
consola24.success("Config saved to ~/.config/apes/");
|
|
3053
3259
|
console.log("");
|
|
3054
|
-
|
|
3260
|
+
consola24.info("Verify with: apes whoami");
|
|
3055
3261
|
}
|
|
3056
3262
|
});
|
|
3057
3263
|
|
|
3058
3264
|
// src/commands/register-user.ts
|
|
3059
3265
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
3060
|
-
import { defineCommand as
|
|
3061
|
-
import
|
|
3062
|
-
var registerUserCommand =
|
|
3266
|
+
import { defineCommand as defineCommand30 } from "citty";
|
|
3267
|
+
import consola25 from "consola";
|
|
3268
|
+
var registerUserCommand = defineCommand30({
|
|
3063
3269
|
meta: {
|
|
3064
3270
|
name: "register-user",
|
|
3065
3271
|
description: "Register a sub-user with SSH key"
|
|
@@ -3114,15 +3320,15 @@ var registerUserCommand = defineCommand29({
|
|
|
3114
3320
|
...userType ? { type: userType } : {}
|
|
3115
3321
|
}
|
|
3116
3322
|
});
|
|
3117
|
-
|
|
3323
|
+
consola25.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
|
|
3118
3324
|
}
|
|
3119
3325
|
});
|
|
3120
3326
|
|
|
3121
3327
|
// src/commands/dns-check.ts
|
|
3122
|
-
import { defineCommand as
|
|
3123
|
-
import
|
|
3328
|
+
import { defineCommand as defineCommand31 } from "citty";
|
|
3329
|
+
import consola26 from "consola";
|
|
3124
3330
|
import { resolveDDISA as resolveDDISA2 } from "@openape/core";
|
|
3125
|
-
var dnsCheckCommand =
|
|
3331
|
+
var dnsCheckCommand = defineCommand31({
|
|
3126
3332
|
meta: {
|
|
3127
3333
|
name: "dns-check",
|
|
3128
3334
|
description: "Validate DDISA DNS TXT records for a domain"
|
|
@@ -3136,7 +3342,7 @@ var dnsCheckCommand = defineCommand30({
|
|
|
3136
3342
|
},
|
|
3137
3343
|
async run({ args }) {
|
|
3138
3344
|
const domain = args.domain;
|
|
3139
|
-
|
|
3345
|
+
consola26.start(`Checking _ddisa.${domain}...`);
|
|
3140
3346
|
try {
|
|
3141
3347
|
const result = await resolveDDISA2(domain);
|
|
3142
3348
|
if (!result) {
|
|
@@ -3145,7 +3351,7 @@ var dnsCheckCommand = defineCommand30({
|
|
|
3145
3351
|
console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
|
|
3146
3352
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
3147
3353
|
}
|
|
3148
|
-
|
|
3354
|
+
consola26.success(`_ddisa.${domain} \u2192 ${result.idp}`);
|
|
3149
3355
|
console.log("");
|
|
3150
3356
|
console.log(` Version: ${result.version || "ddisa1"}`);
|
|
3151
3357
|
console.log(` IdP URL: ${result.idp}`);
|
|
@@ -3154,14 +3360,14 @@ var dnsCheckCommand = defineCommand30({
|
|
|
3154
3360
|
if (result.priority !== void 0)
|
|
3155
3361
|
console.log(` Priority: ${result.priority}`);
|
|
3156
3362
|
console.log("");
|
|
3157
|
-
|
|
3363
|
+
consola26.start(`Verifying IdP at ${result.idp}...`);
|
|
3158
3364
|
const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
|
|
3159
3365
|
if (!discoResp.ok) {
|
|
3160
|
-
|
|
3366
|
+
consola26.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
|
|
3161
3367
|
return;
|
|
3162
3368
|
}
|
|
3163
3369
|
const disco = await discoResp.json();
|
|
3164
|
-
|
|
3370
|
+
consola26.success(`IdP is reachable`);
|
|
3165
3371
|
console.log(` Issuer: ${disco.issuer}`);
|
|
3166
3372
|
console.log(` DDISA: v${disco.ddisa_version || "?"}`);
|
|
3167
3373
|
if (disco.ddisa_auth_methods_supported) {
|
|
@@ -3179,7 +3385,7 @@ var dnsCheckCommand = defineCommand30({
|
|
|
3179
3385
|
// src/commands/health.ts
|
|
3180
3386
|
import { exec } from "child_process";
|
|
3181
3387
|
import { promisify } from "util";
|
|
3182
|
-
import { defineCommand as
|
|
3388
|
+
import { defineCommand as defineCommand32 } from "citty";
|
|
3183
3389
|
var execAsync = promisify(exec);
|
|
3184
3390
|
async function resolveApeShellPath() {
|
|
3185
3391
|
try {
|
|
@@ -3215,7 +3421,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
3215
3421
|
}
|
|
3216
3422
|
}
|
|
3217
3423
|
async function runHealth(args) {
|
|
3218
|
-
const version = true ? "0.
|
|
3424
|
+
const version = true ? "0.13.0" : "0.0.0";
|
|
3219
3425
|
const auth = loadAuth();
|
|
3220
3426
|
if (!auth) {
|
|
3221
3427
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -3278,7 +3484,7 @@ async function runHealth(args) {
|
|
|
3278
3484
|
throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
|
|
3279
3485
|
}
|
|
3280
3486
|
}
|
|
3281
|
-
var healthCommand =
|
|
3487
|
+
var healthCommand = defineCommand32({
|
|
3282
3488
|
meta: {
|
|
3283
3489
|
name: "health",
|
|
3284
3490
|
description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
|
|
@@ -3296,8 +3502,8 @@ var healthCommand = defineCommand31({
|
|
|
3296
3502
|
});
|
|
3297
3503
|
|
|
3298
3504
|
// src/commands/workflows.ts
|
|
3299
|
-
import { defineCommand as
|
|
3300
|
-
import
|
|
3505
|
+
import { defineCommand as defineCommand33 } from "citty";
|
|
3506
|
+
import consola27 from "consola";
|
|
3301
3507
|
|
|
3302
3508
|
// src/guides/index.ts
|
|
3303
3509
|
var guides = [
|
|
@@ -3347,7 +3553,7 @@ var guides = [
|
|
|
3347
3553
|
];
|
|
3348
3554
|
|
|
3349
3555
|
// src/commands/workflows.ts
|
|
3350
|
-
var workflowsCommand =
|
|
3556
|
+
var workflowsCommand = defineCommand33({
|
|
3351
3557
|
meta: {
|
|
3352
3558
|
name: "workflows",
|
|
3353
3559
|
description: "Discover workflow guides"
|
|
@@ -3368,7 +3574,7 @@ var workflowsCommand = defineCommand32({
|
|
|
3368
3574
|
if (args.id) {
|
|
3369
3575
|
const guide = guides.find((g) => g.id === String(args.id));
|
|
3370
3576
|
if (!guide) {
|
|
3371
|
-
|
|
3577
|
+
consola27.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
|
|
3372
3578
|
throw new CliError(`Guide not found: ${args.id}`);
|
|
3373
3579
|
}
|
|
3374
3580
|
if (args.json) {
|
|
@@ -3417,10 +3623,10 @@ if (shellRewrite) {
|
|
|
3417
3623
|
if (shellRewrite.action === "rewrite") {
|
|
3418
3624
|
process.argv = shellRewrite.argv;
|
|
3419
3625
|
} else if (shellRewrite.action === "version") {
|
|
3420
|
-
console.log(`ape-shell ${"0.
|
|
3626
|
+
console.log(`ape-shell ${"0.13.0"} (OpenApe DDISA shell wrapper)`);
|
|
3421
3627
|
process.exit(0);
|
|
3422
3628
|
} else if (shellRewrite.action === "help") {
|
|
3423
|
-
console.log(`ape-shell ${"0.
|
|
3629
|
+
console.log(`ape-shell ${"0.13.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
3424
3630
|
console.log("");
|
|
3425
3631
|
console.log("Usage:");
|
|
3426
3632
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -3435,7 +3641,7 @@ if (shellRewrite) {
|
|
|
3435
3641
|
console.log(" --help, -h Show this help message");
|
|
3436
3642
|
process.exit(0);
|
|
3437
3643
|
} else if (shellRewrite.action === "interactive") {
|
|
3438
|
-
const { runInteractiveShell } = await import("./orchestrator-
|
|
3644
|
+
const { runInteractiveShell } = await import("./orchestrator-PUAO57CY.js");
|
|
3439
3645
|
await runInteractiveShell();
|
|
3440
3646
|
process.exit(0);
|
|
3441
3647
|
} else {
|
|
@@ -3444,7 +3650,7 @@ if (shellRewrite) {
|
|
|
3444
3650
|
}
|
|
3445
3651
|
}
|
|
3446
3652
|
var debug = process.argv.includes("--debug");
|
|
3447
|
-
var grantsCommand =
|
|
3653
|
+
var grantsCommand = defineCommand34({
|
|
3448
3654
|
meta: {
|
|
3449
3655
|
name: "grants",
|
|
3450
3656
|
description: "Grant management"
|
|
@@ -3465,7 +3671,7 @@ var grantsCommand = defineCommand33({
|
|
|
3465
3671
|
"delegation-revoke": delegationRevokeCommand
|
|
3466
3672
|
}
|
|
3467
3673
|
});
|
|
3468
|
-
var configCommand =
|
|
3674
|
+
var configCommand = defineCommand34({
|
|
3469
3675
|
meta: {
|
|
3470
3676
|
name: "config",
|
|
3471
3677
|
description: "Configuration management"
|
|
@@ -3475,10 +3681,10 @@ var configCommand = defineCommand33({
|
|
|
3475
3681
|
set: configSetCommand
|
|
3476
3682
|
}
|
|
3477
3683
|
});
|
|
3478
|
-
var main =
|
|
3684
|
+
var main = defineCommand34({
|
|
3479
3685
|
meta: {
|
|
3480
3686
|
name: "apes",
|
|
3481
|
-
version: "0.
|
|
3687
|
+
version: "0.13.0",
|
|
3482
3688
|
description: "Unified CLI for OpenApe"
|
|
3483
3689
|
},
|
|
3484
3690
|
subCommands: {
|
|
@@ -3493,6 +3699,7 @@ var main = defineCommand33({
|
|
|
3493
3699
|
grants: grantsCommand,
|
|
3494
3700
|
admin: adminCommand,
|
|
3495
3701
|
run: runCommand,
|
|
3702
|
+
proxy: proxyCommand,
|
|
3496
3703
|
explain: explainCommand,
|
|
3497
3704
|
adapter: adapterCommand,
|
|
3498
3705
|
config: configCommand,
|
|
@@ -3506,13 +3713,13 @@ runMain(main).catch((err) => {
|
|
|
3506
3713
|
process.exit(err.exitCode);
|
|
3507
3714
|
}
|
|
3508
3715
|
if (err instanceof CliError) {
|
|
3509
|
-
|
|
3716
|
+
consola28.error(err.message);
|
|
3510
3717
|
process.exit(err.exitCode);
|
|
3511
3718
|
}
|
|
3512
3719
|
if (debug) {
|
|
3513
|
-
|
|
3720
|
+
consola28.error(err);
|
|
3514
3721
|
} else {
|
|
3515
|
-
|
|
3722
|
+
consola28.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
|
|
3516
3723
|
}
|
|
3517
3724
|
process.exit(1);
|
|
3518
3725
|
});
|