@openape/apes 0.28.0 → 0.29.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
CHANGED
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
} from "./chunk-IDPV5SNB.js";
|
|
64
64
|
|
|
65
65
|
// src/cli.ts
|
|
66
|
-
import
|
|
66
|
+
import consola37 from "consola";
|
|
67
67
|
|
|
68
68
|
// src/ape-shell.ts
|
|
69
69
|
import path from "path";
|
|
@@ -93,7 +93,7 @@ function rewriteApeShellArgs(argv, argv0) {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// src/cli.ts
|
|
96
|
-
import { defineCommand as
|
|
96
|
+
import { defineCommand as defineCommand45, runMain } from "citty";
|
|
97
97
|
|
|
98
98
|
// src/commands/auth/login.ts
|
|
99
99
|
import { Buffer as Buffer2 } from "buffer";
|
|
@@ -1743,13 +1743,10 @@ var adminCommand = defineCommand19({
|
|
|
1743
1743
|
});
|
|
1744
1744
|
|
|
1745
1745
|
// src/commands/agents/index.ts
|
|
1746
|
-
import { defineCommand as
|
|
1746
|
+
import { defineCommand as defineCommand25 } from "citty";
|
|
1747
1747
|
|
|
1748
|
-
// src/commands/agents/
|
|
1748
|
+
// src/commands/agents/allow.ts
|
|
1749
1749
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
1750
|
-
import { mkdtempSync, rmSync, writeFileSync } from "fs";
|
|
1751
|
-
import { tmpdir, userInfo } from "os";
|
|
1752
|
-
import { join as join2 } from "path";
|
|
1753
1750
|
import { defineCommand as defineCommand20 } from "citty";
|
|
1754
1751
|
import consola18 from "consola";
|
|
1755
1752
|
|
|
@@ -2098,6 +2095,84 @@ function isShellRegistered(shellPath) {
|
|
|
2098
2095
|
return content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#")).includes(shellPath);
|
|
2099
2096
|
}
|
|
2100
2097
|
|
|
2098
|
+
// src/commands/agents/allow.ts
|
|
2099
|
+
var allowAgentCommand = defineCommand20({
|
|
2100
|
+
meta: {
|
|
2101
|
+
name: "allow",
|
|
2102
|
+
description: "Add a peer to the agent's contact-allowlist so the bridge auto-accepts that peer's contact request."
|
|
2103
|
+
},
|
|
2104
|
+
args: {
|
|
2105
|
+
agent: {
|
|
2106
|
+
type: "positional",
|
|
2107
|
+
required: true,
|
|
2108
|
+
description: "Agent name (the macOS short username spawn created)"
|
|
2109
|
+
},
|
|
2110
|
+
email: {
|
|
2111
|
+
type: "positional",
|
|
2112
|
+
required: true,
|
|
2113
|
+
description: "Peer email to allow (the address that will send the contact request)"
|
|
2114
|
+
}
|
|
2115
|
+
},
|
|
2116
|
+
async run({ args }) {
|
|
2117
|
+
const agent = args.agent;
|
|
2118
|
+
const email = args.email.trim().toLowerCase();
|
|
2119
|
+
if (!AGENT_NAME_REGEX.test(agent)) {
|
|
2120
|
+
throw new CliError(`Invalid agent name "${agent}".`);
|
|
2121
|
+
}
|
|
2122
|
+
if (!email.includes("@")) {
|
|
2123
|
+
throw new CliError(`Invalid email "${email}".`);
|
|
2124
|
+
}
|
|
2125
|
+
if (!isDarwin()) {
|
|
2126
|
+
throw new CliError("`apes agents allow` is currently macOS-only.");
|
|
2127
|
+
}
|
|
2128
|
+
if (!readMacOSUser(agent)) {
|
|
2129
|
+
throw new CliError(`No macOS user "${agent}" \u2014 has the agent been spawned?`);
|
|
2130
|
+
}
|
|
2131
|
+
const apes = whichBinary("apes");
|
|
2132
|
+
if (!apes) throw new CliError("`apes` not found on PATH.");
|
|
2133
|
+
const script = `set -eu
|
|
2134
|
+
mkdir -p "$HOME/.config/openape"
|
|
2135
|
+
F="$HOME/.config/openape/bridge-allowlist.json"
|
|
2136
|
+
EMAIL=${shQuote2(email)}
|
|
2137
|
+
python3 - "$F" "$EMAIL" <<'PY'
|
|
2138
|
+
import json, os, sys
|
|
2139
|
+
path, email = sys.argv[1], sys.argv[2].lower()
|
|
2140
|
+
data = {"emails": []}
|
|
2141
|
+
if os.path.exists(path):
|
|
2142
|
+
try:
|
|
2143
|
+
with open(path) as f:
|
|
2144
|
+
data = json.load(f)
|
|
2145
|
+
if not isinstance(data, dict) or not isinstance(data.get("emails"), list):
|
|
2146
|
+
data = {"emails": []}
|
|
2147
|
+
except Exception:
|
|
2148
|
+
data = {"emails": []}
|
|
2149
|
+
emails = {e.lower() for e in data["emails"] if isinstance(e, str)}
|
|
2150
|
+
emails.add(email)
|
|
2151
|
+
data["emails"] = sorted(emails)
|
|
2152
|
+
with open(path, "w") as f:
|
|
2153
|
+
json.dump(data, f, indent=2)
|
|
2154
|
+
f.write("\\n")
|
|
2155
|
+
print("ok")
|
|
2156
|
+
PY
|
|
2157
|
+
chmod 600 "$F"
|
|
2158
|
+
`;
|
|
2159
|
+
consola18.start(`Adding ${email} to ${agent}'s allowlist\u2026`);
|
|
2160
|
+
execFileSync3(apes, ["run", "--as", agent, "--wait", "--", "bash", "-c", script], { stdio: "inherit" });
|
|
2161
|
+
consola18.success(`${agent} will auto-accept future contact requests from ${email} (within ~30s of next bridge connect).`);
|
|
2162
|
+
}
|
|
2163
|
+
});
|
|
2164
|
+
function shQuote2(s) {
|
|
2165
|
+
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
// src/commands/agents/destroy.ts
|
|
2169
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
2170
|
+
import { mkdtempSync, rmSync, writeFileSync } from "fs";
|
|
2171
|
+
import { tmpdir, userInfo } from "os";
|
|
2172
|
+
import { join as join2 } from "path";
|
|
2173
|
+
import { defineCommand as defineCommand21 } from "citty";
|
|
2174
|
+
import consola19 from "consola";
|
|
2175
|
+
|
|
2101
2176
|
// src/lib/silent-password.ts
|
|
2102
2177
|
function readPasswordSilent(prompt) {
|
|
2103
2178
|
if (!process.stdin.isTTY) {
|
|
@@ -2153,7 +2228,7 @@ function readPasswordSilent(prompt) {
|
|
|
2153
2228
|
}
|
|
2154
2229
|
|
|
2155
2230
|
// src/commands/agents/destroy.ts
|
|
2156
|
-
var destroyAgentCommand =
|
|
2231
|
+
var destroyAgentCommand = defineCommand21({
|
|
2157
2232
|
meta: {
|
|
2158
2233
|
name: "destroy",
|
|
2159
2234
|
description: "Tear down an agent: remove macOS user, hard-delete IdP agent, drop all SSH keys"
|
|
@@ -2197,7 +2272,7 @@ var destroyAgentCommand = defineCommand20({
|
|
|
2197
2272
|
const idpExists = idpAgent !== void 0;
|
|
2198
2273
|
const osUserExists = !args["keep-os-user"] && isDarwin() && readMacOSUser(name) !== null;
|
|
2199
2274
|
if (!idpExists && !osUserExists) {
|
|
2200
|
-
|
|
2275
|
+
consola19.info(`Nothing to destroy: no IdP agent and no OS user named "${name}".`);
|
|
2201
2276
|
return;
|
|
2202
2277
|
}
|
|
2203
2278
|
if (!args.force) {
|
|
@@ -2206,14 +2281,14 @@ var destroyAgentCommand = defineCommand20({
|
|
|
2206
2281
|
if (idpExists) {
|
|
2207
2282
|
consequences.push(args.soft ? `\u2022 Deactivate IdP agent ${idpAgent.email} (PATCH isActive=false)` : `\u2022 Hard-delete IdP agent ${idpAgent.email} and all its SSH keys`);
|
|
2208
2283
|
}
|
|
2209
|
-
|
|
2284
|
+
consola19.warn(`About to destroy "${name}":
|
|
2210
2285
|
${consequences.join("\n")}`);
|
|
2211
2286
|
if (!process.stdin.isTTY) {
|
|
2212
2287
|
throw new CliError(
|
|
2213
2288
|
"No TTY available for the interactive confirmation. Re-run with --force to skip the prompt (this is the same flag CI uses)."
|
|
2214
2289
|
);
|
|
2215
2290
|
}
|
|
2216
|
-
const confirmed = await
|
|
2291
|
+
const confirmed = await consola19.prompt("Proceed?", { type: "confirm", initial: false });
|
|
2217
2292
|
if (typeof confirmed === "symbol" || !confirmed) {
|
|
2218
2293
|
throw new CliExit(0);
|
|
2219
2294
|
}
|
|
@@ -2222,13 +2297,13 @@ ${consequences.join("\n")}`);
|
|
|
2222
2297
|
const id = encodeURIComponent(idpAgent.email);
|
|
2223
2298
|
if (args.soft) {
|
|
2224
2299
|
await apiFetch(`/api/my-agents/${id}`, { method: "PATCH", body: { isActive: false }, idp });
|
|
2225
|
-
|
|
2300
|
+
consola19.success(`Deactivated IdP agent ${idpAgent.email}`);
|
|
2226
2301
|
} else {
|
|
2227
2302
|
await apiFetch(`/api/my-agents/${id}`, { method: "DELETE", idp });
|
|
2228
|
-
|
|
2303
|
+
consola19.success(`Deleted IdP agent ${idpAgent.email}`);
|
|
2229
2304
|
}
|
|
2230
2305
|
} else {
|
|
2231
|
-
|
|
2306
|
+
consola19.info("No IdP agent to remove (skipped).");
|
|
2232
2307
|
}
|
|
2233
2308
|
if (osUserExists) {
|
|
2234
2309
|
const sudo = whichBinary("sudo");
|
|
@@ -2242,8 +2317,8 @@ ${consequences.join("\n")}`);
|
|
|
2242
2317
|
try {
|
|
2243
2318
|
const script = buildDestroyTeardownScript({ name, homeDir: `/Users/${name}`, adminUser });
|
|
2244
2319
|
writeFileSync(scriptPath, script, { mode: 448 });
|
|
2245
|
-
|
|
2246
|
-
|
|
2320
|
+
consola19.start("Running teardown via sudo\u2026");
|
|
2321
|
+
execFileSync4(sudo, ["-S", "--prompt=", "--", "bash", scriptPath], {
|
|
2247
2322
|
input: `${adminPassword}
|
|
2248
2323
|
${adminPassword}
|
|
2249
2324
|
`,
|
|
@@ -2253,9 +2328,9 @@ ${adminPassword}
|
|
|
2253
2328
|
rmSync(scratch, { recursive: true, force: true });
|
|
2254
2329
|
}
|
|
2255
2330
|
} else if (!args["keep-os-user"] && isDarwin()) {
|
|
2256
|
-
|
|
2331
|
+
consola19.info("No macOS user to remove (skipped).");
|
|
2257
2332
|
}
|
|
2258
|
-
|
|
2333
|
+
consola19.success(`Destroyed ${name}.`);
|
|
2259
2334
|
}
|
|
2260
2335
|
});
|
|
2261
2336
|
async function collectAdminPassword(opts) {
|
|
@@ -2269,9 +2344,9 @@ async function collectAdminPassword(opts) {
|
|
|
2269
2344
|
}
|
|
2270
2345
|
|
|
2271
2346
|
// src/commands/agents/list.ts
|
|
2272
|
-
import { defineCommand as
|
|
2273
|
-
import
|
|
2274
|
-
var listAgentsCommand =
|
|
2347
|
+
import { defineCommand as defineCommand22 } from "citty";
|
|
2348
|
+
import consola20 from "consola";
|
|
2349
|
+
var listAgentsCommand = defineCommand22({
|
|
2275
2350
|
meta: {
|
|
2276
2351
|
name: "list",
|
|
2277
2352
|
description: "List agents owned by the current user, with local OS-user status"
|
|
@@ -2312,7 +2387,7 @@ var listAgentsCommand = defineCommand21({
|
|
|
2312
2387
|
return;
|
|
2313
2388
|
}
|
|
2314
2389
|
if (rows.length === 0) {
|
|
2315
|
-
|
|
2390
|
+
consola20.info(args["include-inactive"] ? "No agents found." : "No active agents found. Use --include-inactive to show deactivated.");
|
|
2316
2391
|
return;
|
|
2317
2392
|
}
|
|
2318
2393
|
const nameW = Math.max(4, ...rows.map((r) => r.name.length));
|
|
@@ -2331,9 +2406,9 @@ var listAgentsCommand = defineCommand21({
|
|
|
2331
2406
|
|
|
2332
2407
|
// src/commands/agents/register.ts
|
|
2333
2408
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
2334
|
-
import { defineCommand as
|
|
2335
|
-
import
|
|
2336
|
-
var registerAgentCommand =
|
|
2409
|
+
import { defineCommand as defineCommand23 } from "citty";
|
|
2410
|
+
import consola21 from "consola";
|
|
2411
|
+
var registerAgentCommand = defineCommand23({
|
|
2337
2412
|
meta: {
|
|
2338
2413
|
name: "register",
|
|
2339
2414
|
description: "Register an agent at the IdP using a supplied public key"
|
|
@@ -2403,7 +2478,7 @@ var registerAgentCommand = defineCommand22({
|
|
|
2403
2478
|
`);
|
|
2404
2479
|
return;
|
|
2405
2480
|
}
|
|
2406
|
-
|
|
2481
|
+
consola21.success("Agent registered.");
|
|
2407
2482
|
console.log(` Name: ${result.name}`);
|
|
2408
2483
|
console.log(` Email: ${result.email}`);
|
|
2409
2484
|
console.log(` IdP: ${idp}`);
|
|
@@ -2416,12 +2491,12 @@ var registerAgentCommand = defineCommand22({
|
|
|
2416
2491
|
});
|
|
2417
2492
|
|
|
2418
2493
|
// src/commands/agents/spawn.ts
|
|
2419
|
-
import { execFileSync as
|
|
2494
|
+
import { execFileSync as execFileSync5 } from "child_process";
|
|
2420
2495
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
2421
2496
|
import { tmpdir as tmpdir2 } from "os";
|
|
2422
2497
|
import { join as join4 } from "path";
|
|
2423
|
-
import { defineCommand as
|
|
2424
|
-
import
|
|
2498
|
+
import { defineCommand as defineCommand24 } from "citty";
|
|
2499
|
+
import consola22 from "consola";
|
|
2425
2500
|
|
|
2426
2501
|
// src/lib/keygen.ts
|
|
2427
2502
|
import { Buffer as Buffer4 } from "buffer";
|
|
@@ -2639,7 +2714,7 @@ function buildBridgePlist(agentName, homeDir) {
|
|
|
2639
2714
|
}
|
|
2640
2715
|
|
|
2641
2716
|
// src/commands/agents/spawn.ts
|
|
2642
|
-
var spawnAgentCommand =
|
|
2717
|
+
var spawnAgentCommand = defineCommand24({
|
|
2643
2718
|
meta: {
|
|
2644
2719
|
name: "spawn",
|
|
2645
2720
|
description: "Provision a local macOS agent end-to-end (OS user, keypair, IdP agent, Claude hook)"
|
|
@@ -2725,12 +2800,12 @@ and try again.`
|
|
|
2725
2800
|
const scratch = mkdtempSync2(join4(tmpdir2(), `apes-spawn-${name}-`));
|
|
2726
2801
|
const scriptPath = join4(scratch, "setup.sh");
|
|
2727
2802
|
try {
|
|
2728
|
-
|
|
2803
|
+
consola22.start(`Generating keypair for ${name}\u2026`);
|
|
2729
2804
|
const { privatePem, publicSshLine } = generateKeyPairInMemory();
|
|
2730
|
-
|
|
2805
|
+
consola22.start(`Registering agent at ${idp}\u2026`);
|
|
2731
2806
|
const registration = await registerAgentAtIdp({ name, publicKey: publicSshLine, idp });
|
|
2732
|
-
|
|
2733
|
-
|
|
2807
|
+
consola22.success(`Registered as ${registration.email}`);
|
|
2808
|
+
consola22.start("Issuing agent access token\u2026");
|
|
2734
2809
|
const { token, expiresIn } = await issueAgentToken({
|
|
2735
2810
|
idp,
|
|
2736
2811
|
agentEmail: registration.email,
|
|
@@ -2774,13 +2849,13 @@ and try again.`
|
|
|
2774
2849
|
bridge
|
|
2775
2850
|
});
|
|
2776
2851
|
writeFileSync3(scriptPath, script, { mode: 448 });
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2852
|
+
consola22.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
|
|
2853
|
+
consola22.info("You will be asked to approve the as=root grant in your DDISA inbox; this command blocks until you do.");
|
|
2854
|
+
execFileSync5(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], { stdio: "inherit" });
|
|
2855
|
+
consola22.success(`Agent ${name} spawned.`);
|
|
2781
2856
|
if (args.bridge) {
|
|
2782
|
-
|
|
2783
|
-
|
|
2857
|
+
consola22.info(`On first boot, the bridge will send you a contact request from ${registration.email}.`);
|
|
2858
|
+
consola22.info("Open chat.openape.ai and accept it to start chatting with the agent.");
|
|
2784
2859
|
}
|
|
2785
2860
|
console.log("");
|
|
2786
2861
|
console.log("Run as the agent with:");
|
|
@@ -2814,29 +2889,30 @@ async function resolveClaudeToken(opts) {
|
|
|
2814
2889
|
}
|
|
2815
2890
|
|
|
2816
2891
|
// src/commands/agents/index.ts
|
|
2817
|
-
var agentsCommand =
|
|
2892
|
+
var agentsCommand = defineCommand25({
|
|
2818
2893
|
meta: {
|
|
2819
2894
|
name: "agents",
|
|
2820
|
-
description: "Manage owned agents (register, spawn, list, destroy)"
|
|
2895
|
+
description: "Manage owned agents (register, spawn, list, destroy, allow)"
|
|
2821
2896
|
},
|
|
2822
2897
|
subCommands: {
|
|
2823
2898
|
register: registerAgentCommand,
|
|
2824
2899
|
spawn: spawnAgentCommand,
|
|
2825
2900
|
list: listAgentsCommand,
|
|
2826
|
-
destroy: destroyAgentCommand
|
|
2901
|
+
destroy: destroyAgentCommand,
|
|
2902
|
+
allow: allowAgentCommand
|
|
2827
2903
|
}
|
|
2828
2904
|
});
|
|
2829
2905
|
|
|
2830
2906
|
// src/commands/adapter/index.ts
|
|
2831
|
-
import { defineCommand as
|
|
2832
|
-
import
|
|
2833
|
-
var adapterCommand =
|
|
2907
|
+
import { defineCommand as defineCommand26 } from "citty";
|
|
2908
|
+
import consola23 from "consola";
|
|
2909
|
+
var adapterCommand = defineCommand26({
|
|
2834
2910
|
meta: {
|
|
2835
2911
|
name: "adapter",
|
|
2836
2912
|
description: "Manage CLI adapters"
|
|
2837
2913
|
},
|
|
2838
2914
|
subCommands: {
|
|
2839
|
-
list:
|
|
2915
|
+
list: defineCommand26({
|
|
2840
2916
|
meta: {
|
|
2841
2917
|
name: "list",
|
|
2842
2918
|
description: "List available adapters"
|
|
@@ -2867,7 +2943,7 @@ var adapterCommand = defineCommand25({
|
|
|
2867
2943
|
`);
|
|
2868
2944
|
return;
|
|
2869
2945
|
}
|
|
2870
|
-
|
|
2946
|
+
consola23.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
|
|
2871
2947
|
for (const a of index2.adapters) {
|
|
2872
2948
|
const installed = isInstalled(a.id, false) ? " [installed]" : "";
|
|
2873
2949
|
console.log(` ${a.id.padEnd(12)} ${a.name.padEnd(24)} ${a.category}${installed}`);
|
|
@@ -2889,7 +2965,7 @@ var adapterCommand = defineCommand25({
|
|
|
2889
2965
|
return;
|
|
2890
2966
|
}
|
|
2891
2967
|
if (local.length === 0) {
|
|
2892
|
-
|
|
2968
|
+
consola23.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
|
|
2893
2969
|
return;
|
|
2894
2970
|
}
|
|
2895
2971
|
for (const a of local) {
|
|
@@ -2897,7 +2973,7 @@ var adapterCommand = defineCommand25({
|
|
|
2897
2973
|
}
|
|
2898
2974
|
}
|
|
2899
2975
|
}),
|
|
2900
|
-
install:
|
|
2976
|
+
install: defineCommand26({
|
|
2901
2977
|
meta: {
|
|
2902
2978
|
name: "install",
|
|
2903
2979
|
description: "Install an adapter from the registry"
|
|
@@ -2926,24 +3002,24 @@ var adapterCommand = defineCommand25({
|
|
|
2926
3002
|
for (const id of ids) {
|
|
2927
3003
|
const entry = findAdapter(index, id);
|
|
2928
3004
|
if (!entry) {
|
|
2929
|
-
|
|
3005
|
+
consola23.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
|
|
2930
3006
|
continue;
|
|
2931
3007
|
}
|
|
2932
3008
|
const conflicts = findConflictingAdapters(entry.executable, id);
|
|
2933
3009
|
if (conflicts.length > 0) {
|
|
2934
3010
|
for (const c of conflicts) {
|
|
2935
|
-
|
|
2936
|
-
|
|
3011
|
+
consola23.warn(`Conflicting adapter found: ${c.path} (id: ${c.adapterId}, executable: ${c.executable})`);
|
|
3012
|
+
consola23.warn(` Remove it with: apes adapter remove ${c.adapterId}`);
|
|
2937
3013
|
}
|
|
2938
3014
|
}
|
|
2939
3015
|
const result = await installAdapter(entry, { local });
|
|
2940
3016
|
const verb = result.updated ? "Updated" : "Installed";
|
|
2941
|
-
|
|
2942
|
-
|
|
3017
|
+
consola23.success(`${verb} ${result.id} \u2192 ${result.path}`);
|
|
3018
|
+
consola23.info(`Digest: ${result.digest}`);
|
|
2943
3019
|
}
|
|
2944
3020
|
}
|
|
2945
3021
|
}),
|
|
2946
|
-
remove:
|
|
3022
|
+
remove: defineCommand26({
|
|
2947
3023
|
meta: {
|
|
2948
3024
|
name: "remove",
|
|
2949
3025
|
description: "Remove an installed adapter"
|
|
@@ -2966,9 +3042,9 @@ var adapterCommand = defineCommand25({
|
|
|
2966
3042
|
let failed = false;
|
|
2967
3043
|
for (const id of ids) {
|
|
2968
3044
|
if (removeAdapter(id, local)) {
|
|
2969
|
-
|
|
3045
|
+
consola23.success(`Removed adapter: ${id}`);
|
|
2970
3046
|
} else {
|
|
2971
|
-
|
|
3047
|
+
consola23.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
2972
3048
|
failed = true;
|
|
2973
3049
|
}
|
|
2974
3050
|
}
|
|
@@ -2976,7 +3052,7 @@ var adapterCommand = defineCommand25({
|
|
|
2976
3052
|
throw new CliError("Some adapters could not be removed");
|
|
2977
3053
|
}
|
|
2978
3054
|
}),
|
|
2979
|
-
info:
|
|
3055
|
+
info: defineCommand26({
|
|
2980
3056
|
meta: {
|
|
2981
3057
|
name: "info",
|
|
2982
3058
|
description: "Show detailed adapter information"
|
|
@@ -3018,7 +3094,7 @@ var adapterCommand = defineCommand25({
|
|
|
3018
3094
|
}
|
|
3019
3095
|
}
|
|
3020
3096
|
}),
|
|
3021
|
-
search:
|
|
3097
|
+
search: defineCommand26({
|
|
3022
3098
|
meta: {
|
|
3023
3099
|
name: "search",
|
|
3024
3100
|
description: "Search adapters in the registry"
|
|
@@ -3050,7 +3126,7 @@ var adapterCommand = defineCommand25({
|
|
|
3050
3126
|
return;
|
|
3051
3127
|
}
|
|
3052
3128
|
if (results.length === 0) {
|
|
3053
|
-
|
|
3129
|
+
consola23.info(`No adapters matching "${query}"`);
|
|
3054
3130
|
return;
|
|
3055
3131
|
}
|
|
3056
3132
|
for (const a of results) {
|
|
@@ -3059,7 +3135,7 @@ var adapterCommand = defineCommand25({
|
|
|
3059
3135
|
}
|
|
3060
3136
|
}
|
|
3061
3137
|
}),
|
|
3062
|
-
update:
|
|
3138
|
+
update: defineCommand26({
|
|
3063
3139
|
meta: {
|
|
3064
3140
|
name: "update",
|
|
3065
3141
|
description: "Update installed adapters"
|
|
@@ -3085,33 +3161,33 @@ var adapterCommand = defineCommand25({
|
|
|
3085
3161
|
const targetId = args.id ? String(args.id) : void 0;
|
|
3086
3162
|
const targets = targetId ? [targetId] : index.adapters.map((a) => a.id).filter((id) => isInstalled(id, false));
|
|
3087
3163
|
if (targets.length === 0) {
|
|
3088
|
-
|
|
3164
|
+
consola23.info("No adapters installed to update.");
|
|
3089
3165
|
return;
|
|
3090
3166
|
}
|
|
3091
3167
|
for (const id of targets) {
|
|
3092
3168
|
const entry = findAdapter(index, id);
|
|
3093
3169
|
if (!entry) {
|
|
3094
|
-
|
|
3170
|
+
consola23.warn(`${id}: not found in registry, skipping`);
|
|
3095
3171
|
continue;
|
|
3096
3172
|
}
|
|
3097
3173
|
const localDigest = getInstalledDigest(id, false);
|
|
3098
3174
|
if (localDigest === entry.digest) {
|
|
3099
|
-
|
|
3175
|
+
consola23.info(`${id}: already up to date`);
|
|
3100
3176
|
continue;
|
|
3101
3177
|
}
|
|
3102
3178
|
if (localDigest && !args.yes) {
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3179
|
+
consola23.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
|
|
3180
|
+
consola23.info(` Old: ${localDigest}`);
|
|
3181
|
+
consola23.info(` New: ${entry.digest}`);
|
|
3182
|
+
consola23.info(" Use --yes to confirm");
|
|
3107
3183
|
continue;
|
|
3108
3184
|
}
|
|
3109
3185
|
const result = await installAdapter(entry);
|
|
3110
|
-
|
|
3186
|
+
consola23.success(`Updated ${result.id} \u2192 ${result.path}`);
|
|
3111
3187
|
}
|
|
3112
3188
|
}
|
|
3113
3189
|
}),
|
|
3114
|
-
verify:
|
|
3190
|
+
verify: defineCommand26({
|
|
3115
3191
|
meta: {
|
|
3116
3192
|
name: "verify",
|
|
3117
3193
|
description: "Verify installed adapter against registry digest"
|
|
@@ -3144,7 +3220,7 @@ var adapterCommand = defineCommand25({
|
|
|
3144
3220
|
if (!localDigest)
|
|
3145
3221
|
throw new Error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
3146
3222
|
if (localDigest === entry.digest) {
|
|
3147
|
-
|
|
3223
|
+
consola23.success(`${id}: digest matches registry`);
|
|
3148
3224
|
} else {
|
|
3149
3225
|
console.log(` Local: ${localDigest}`);
|
|
3150
3226
|
console.log(` Registry: ${entry.digest}`);
|
|
@@ -3156,11 +3232,11 @@ var adapterCommand = defineCommand25({
|
|
|
3156
3232
|
});
|
|
3157
3233
|
|
|
3158
3234
|
// src/commands/run.ts
|
|
3159
|
-
import { execFileSync as
|
|
3235
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
3160
3236
|
import { hostname as hostname3 } from "os";
|
|
3161
3237
|
import { basename } from "path";
|
|
3162
|
-
import { defineCommand as
|
|
3163
|
-
import
|
|
3238
|
+
import { defineCommand as defineCommand27 } from "citty";
|
|
3239
|
+
import consola24 from "consola";
|
|
3164
3240
|
function shouldWaitForGrant(args) {
|
|
3165
3241
|
return args.wait === true || process.env.APE_WAIT === "1";
|
|
3166
3242
|
}
|
|
@@ -3197,7 +3273,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
3197
3273
|
const statusCmd = `apes grants status ${grant.id}`;
|
|
3198
3274
|
const executeCmd = `apes grants run ${grant.id}`;
|
|
3199
3275
|
if (mode === "human") {
|
|
3200
|
-
|
|
3276
|
+
consola24.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
|
|
3201
3277
|
console.log(` Approve in browser: ${approveUrl}`);
|
|
3202
3278
|
console.log(` Check status: ${statusCmd}`);
|
|
3203
3279
|
console.log(` Run after approval: ${executeCmd}`);
|
|
@@ -3207,7 +3283,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
3207
3283
|
return;
|
|
3208
3284
|
}
|
|
3209
3285
|
const maxMin = getPollMaxMinutes();
|
|
3210
|
-
|
|
3286
|
+
consola24.success(`Grant ${grant.id} created (pending approval)`);
|
|
3211
3287
|
console.log(` Approve: ${approveUrl}`);
|
|
3212
3288
|
console.log(` Status: ${statusCmd} [--json]`);
|
|
3213
3289
|
console.log(` Execute: ${executeCmd} --wait`);
|
|
@@ -3229,7 +3305,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
3229
3305
|
console.log(' Tip: Approve as "timed" or "always" in the browser to let this');
|
|
3230
3306
|
console.log(" grant be reused on subsequent invocations without re-approval.");
|
|
3231
3307
|
}
|
|
3232
|
-
var runCommand =
|
|
3308
|
+
var runCommand = defineCommand27({
|
|
3233
3309
|
meta: {
|
|
3234
3310
|
name: "run",
|
|
3235
3311
|
description: "Execute a grant-secured command"
|
|
@@ -3332,7 +3408,7 @@ async function runShellMode(command, args) {
|
|
|
3332
3408
|
}
|
|
3333
3409
|
} catch {
|
|
3334
3410
|
}
|
|
3335
|
-
|
|
3411
|
+
consola24.info(`Requesting ape-shell session grant on ${targetHost}`);
|
|
3336
3412
|
const grant = await apiFetch(grantsUrl, {
|
|
3337
3413
|
method: "POST",
|
|
3338
3414
|
body: {
|
|
@@ -3352,8 +3428,8 @@ async function runShellMode(command, args) {
|
|
|
3352
3428
|
host: targetHost
|
|
3353
3429
|
});
|
|
3354
3430
|
if (shouldWaitForGrant(args)) {
|
|
3355
|
-
|
|
3356
|
-
|
|
3431
|
+
consola24.info(`Grant requested: ${grant.id}`);
|
|
3432
|
+
consola24.info("Waiting for approval...");
|
|
3357
3433
|
const maxWait = 3e5;
|
|
3358
3434
|
const interval = 3e3;
|
|
3359
3435
|
const start = Date.now();
|
|
@@ -3384,13 +3460,13 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
3384
3460
|
try {
|
|
3385
3461
|
resolved = await resolveCommand(loaded, [normalizedExecutable, ...parsed.argv]);
|
|
3386
3462
|
} catch (err) {
|
|
3387
|
-
|
|
3463
|
+
consola24.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
|
|
3388
3464
|
return false;
|
|
3389
3465
|
}
|
|
3390
3466
|
try {
|
|
3391
3467
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
3392
3468
|
if (existingGrantId) {
|
|
3393
|
-
|
|
3469
|
+
consola24.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
|
|
3394
3470
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
3395
3471
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
3396
3472
|
return true;
|
|
@@ -3398,7 +3474,7 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
3398
3474
|
} catch {
|
|
3399
3475
|
}
|
|
3400
3476
|
const approval = args.approval ?? "once";
|
|
3401
|
-
|
|
3477
|
+
consola24.info(`Requesting grant for: ${resolved.detail.display}`);
|
|
3402
3478
|
const grant = await createShapesGrant(resolved, {
|
|
3403
3479
|
idp,
|
|
3404
3480
|
approval,
|
|
@@ -3406,8 +3482,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
3406
3482
|
});
|
|
3407
3483
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
3408
3484
|
const n = grant.similar_grants.similar_grants.length;
|
|
3409
|
-
|
|
3410
|
-
|
|
3485
|
+
consola24.info("");
|
|
3486
|
+
consola24.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
3411
3487
|
}
|
|
3412
3488
|
notifyGrantPending({
|
|
3413
3489
|
grantId: grant.id,
|
|
@@ -3417,8 +3493,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
3417
3493
|
host: args.host || hostname3()
|
|
3418
3494
|
});
|
|
3419
3495
|
if (shouldWaitForGrant(args)) {
|
|
3420
|
-
|
|
3421
|
-
|
|
3496
|
+
consola24.info(`Grant requested: ${grant.id}`);
|
|
3497
|
+
consola24.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
3422
3498
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
3423
3499
|
if (status !== "approved")
|
|
3424
3500
|
throw new CliError(`Grant ${status}`);
|
|
@@ -3434,7 +3510,7 @@ function execShellCommand(command) {
|
|
|
3434
3510
|
throw new CliError("No command to execute");
|
|
3435
3511
|
try {
|
|
3436
3512
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
3437
|
-
|
|
3513
|
+
execFileSync6(command[0], command.slice(1), {
|
|
3438
3514
|
stdio: "inherit",
|
|
3439
3515
|
env: inheritedEnv
|
|
3440
3516
|
});
|
|
@@ -3492,7 +3568,7 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
3492
3568
|
try {
|
|
3493
3569
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
3494
3570
|
if (existingGrantId) {
|
|
3495
|
-
|
|
3571
|
+
consola24.info(`Reusing existing grant: ${existingGrantId}`);
|
|
3496
3572
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
3497
3573
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
3498
3574
|
return;
|
|
@@ -3506,17 +3582,17 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
3506
3582
|
});
|
|
3507
3583
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
3508
3584
|
const n = grant.similar_grants.similar_grants.length;
|
|
3509
|
-
|
|
3510
|
-
|
|
3585
|
+
consola24.info("");
|
|
3586
|
+
consola24.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
3511
3587
|
if (grant.similar_grants.widened_details?.length) {
|
|
3512
3588
|
const wider = grant.similar_grants.widened_details.map((d) => d.permission).join(", ");
|
|
3513
|
-
|
|
3589
|
+
consola24.info(` Broader scope: ${wider}`);
|
|
3514
3590
|
}
|
|
3515
|
-
|
|
3591
|
+
consola24.info("");
|
|
3516
3592
|
}
|
|
3517
3593
|
if (shouldWaitForGrant(args)) {
|
|
3518
|
-
|
|
3519
|
-
|
|
3594
|
+
consola24.info(`Grant requested: ${grant.id}`);
|
|
3595
|
+
consola24.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
3520
3596
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
3521
3597
|
if (status !== "approved")
|
|
3522
3598
|
throw new Error(`Grant ${status}`);
|
|
@@ -3536,7 +3612,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3536
3612
|
const grantsUrl = await getGrantsEndpoint(idp);
|
|
3537
3613
|
const command = action.split(" ");
|
|
3538
3614
|
const targetHost = args.host || hostname3();
|
|
3539
|
-
|
|
3615
|
+
consola24.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
|
|
3540
3616
|
const grant = await apiFetch(grantsUrl, {
|
|
3541
3617
|
method: "POST",
|
|
3542
3618
|
body: {
|
|
@@ -3553,9 +3629,9 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3553
3629
|
printPendingGrantInfo(grant, idp);
|
|
3554
3630
|
throw new CliExit(getAsyncExitCode());
|
|
3555
3631
|
}
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3632
|
+
consola24.success(`Grant requested: ${grant.id}`);
|
|
3633
|
+
consola24.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
3634
|
+
consola24.info("Waiting for approval...");
|
|
3559
3635
|
const maxWait = 15 * 60 * 1e3;
|
|
3560
3636
|
const interval = 3e3;
|
|
3561
3637
|
const start = Date.now();
|
|
@@ -3563,7 +3639,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3563
3639
|
while (Date.now() - start < maxWait) {
|
|
3564
3640
|
const status = await apiFetch(`${grantsUrl}/${grant.id}`);
|
|
3565
3641
|
if (status.status === "approved") {
|
|
3566
|
-
|
|
3642
|
+
consola24.success("Grant approved!");
|
|
3567
3643
|
approved = true;
|
|
3568
3644
|
break;
|
|
3569
3645
|
}
|
|
@@ -3578,15 +3654,15 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3578
3654
|
`Grant approval timed out after ${minutes} min (still pending). Check your DDISA inbox at ${idp}/grant-approval?grant_id=${grant.id} \u2014 if approved later, re-run the same \`apes run\` command and it will reuse the grant.`
|
|
3579
3655
|
);
|
|
3580
3656
|
}
|
|
3581
|
-
|
|
3657
|
+
consola24.info("Fetching grant token...");
|
|
3582
3658
|
const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, {
|
|
3583
3659
|
method: "POST"
|
|
3584
3660
|
});
|
|
3585
3661
|
if (audience === "escapes") {
|
|
3586
|
-
|
|
3662
|
+
consola24.info(`Executing: ${command.join(" ")}`);
|
|
3587
3663
|
try {
|
|
3588
3664
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
3589
|
-
|
|
3665
|
+
execFileSync6(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
|
|
3590
3666
|
stdio: "inherit",
|
|
3591
3667
|
env: inheritedEnv
|
|
3592
3668
|
});
|
|
@@ -3601,8 +3677,8 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3601
3677
|
|
|
3602
3678
|
// src/commands/proxy.ts
|
|
3603
3679
|
import { spawn as spawn2 } from "child_process";
|
|
3604
|
-
import { defineCommand as
|
|
3605
|
-
import
|
|
3680
|
+
import { defineCommand as defineCommand28 } from "citty";
|
|
3681
|
+
import consola25 from "consola";
|
|
3606
3682
|
|
|
3607
3683
|
// src/proxy/config.ts
|
|
3608
3684
|
function buildDefaultProxyConfigToml(opts) {
|
|
@@ -3745,10 +3821,10 @@ function resolveProxyConfigOptions() {
|
|
|
3745
3821
|
77
|
|
3746
3822
|
);
|
|
3747
3823
|
}
|
|
3748
|
-
|
|
3824
|
+
consola25.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
|
|
3749
3825
|
return { agentEmail: auth.email, idpUrl: auth.idp, mediated: true };
|
|
3750
3826
|
}
|
|
3751
|
-
var proxyCommand =
|
|
3827
|
+
var proxyCommand = defineCommand28({
|
|
3752
3828
|
meta: {
|
|
3753
3829
|
name: "proxy",
|
|
3754
3830
|
description: "Run a command with HTTPS_PROXY routed through the OpenApe egress proxy."
|
|
@@ -3770,12 +3846,12 @@ var proxyCommand = defineCommand27({
|
|
|
3770
3846
|
let close = null;
|
|
3771
3847
|
if (reuseUrl) {
|
|
3772
3848
|
proxyUrl = reuseUrl;
|
|
3773
|
-
|
|
3849
|
+
consola25.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
|
|
3774
3850
|
} else {
|
|
3775
3851
|
const ephemeral = await startEphemeralProxy(buildDefaultProxyConfigToml(resolveProxyConfigOptions()));
|
|
3776
3852
|
proxyUrl = ephemeral.url;
|
|
3777
3853
|
close = ephemeral.close;
|
|
3778
|
-
|
|
3854
|
+
consola25.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
|
|
3779
3855
|
}
|
|
3780
3856
|
const noProxy = process.env.NO_PROXY ?? process.env.no_proxy ?? "127.0.0.1,localhost";
|
|
3781
3857
|
const childEnv = {
|
|
@@ -3807,7 +3883,7 @@ var proxyCommand = defineCommand27({
|
|
|
3807
3883
|
else resolveExit(code ?? 0);
|
|
3808
3884
|
});
|
|
3809
3885
|
child.once("error", (err) => {
|
|
3810
|
-
|
|
3886
|
+
consola25.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
|
|
3811
3887
|
resolveExit(127);
|
|
3812
3888
|
});
|
|
3813
3889
|
});
|
|
@@ -3821,8 +3897,8 @@ function signalNumber(signal) {
|
|
|
3821
3897
|
}
|
|
3822
3898
|
|
|
3823
3899
|
// src/commands/explain.ts
|
|
3824
|
-
import { defineCommand as
|
|
3825
|
-
var explainCommand =
|
|
3900
|
+
import { defineCommand as defineCommand29 } from "citty";
|
|
3901
|
+
var explainCommand = defineCommand29({
|
|
3826
3902
|
meta: {
|
|
3827
3903
|
name: "explain",
|
|
3828
3904
|
description: "Show what permission a command would need"
|
|
@@ -3860,9 +3936,9 @@ var explainCommand = defineCommand28({
|
|
|
3860
3936
|
});
|
|
3861
3937
|
|
|
3862
3938
|
// src/commands/config/get.ts
|
|
3863
|
-
import { defineCommand as
|
|
3864
|
-
import
|
|
3865
|
-
var configGetCommand =
|
|
3939
|
+
import { defineCommand as defineCommand30 } from "citty";
|
|
3940
|
+
import consola26 from "consola";
|
|
3941
|
+
var configGetCommand = defineCommand30({
|
|
3866
3942
|
meta: {
|
|
3867
3943
|
name: "get",
|
|
3868
3944
|
description: "Get a configuration value"
|
|
@@ -3882,7 +3958,7 @@ var configGetCommand = defineCommand29({
|
|
|
3882
3958
|
if (idp)
|
|
3883
3959
|
console.log(idp);
|
|
3884
3960
|
else
|
|
3885
|
-
|
|
3961
|
+
consola26.info("No IdP configured.");
|
|
3886
3962
|
break;
|
|
3887
3963
|
}
|
|
3888
3964
|
case "email": {
|
|
@@ -3890,7 +3966,7 @@ var configGetCommand = defineCommand29({
|
|
|
3890
3966
|
if (auth?.email)
|
|
3891
3967
|
console.log(auth.email);
|
|
3892
3968
|
else
|
|
3893
|
-
|
|
3969
|
+
consola26.info("Not logged in.");
|
|
3894
3970
|
break;
|
|
3895
3971
|
}
|
|
3896
3972
|
default: {
|
|
@@ -3903,7 +3979,7 @@ var configGetCommand = defineCommand29({
|
|
|
3903
3979
|
if (sectionObj && field in sectionObj) {
|
|
3904
3980
|
console.log(sectionObj[field]);
|
|
3905
3981
|
} else {
|
|
3906
|
-
|
|
3982
|
+
consola26.info(`Key "${key}" not set.`);
|
|
3907
3983
|
}
|
|
3908
3984
|
} else {
|
|
3909
3985
|
throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
|
|
@@ -3914,9 +3990,9 @@ var configGetCommand = defineCommand29({
|
|
|
3914
3990
|
});
|
|
3915
3991
|
|
|
3916
3992
|
// src/commands/config/set.ts
|
|
3917
|
-
import { defineCommand as
|
|
3918
|
-
import
|
|
3919
|
-
var configSetCommand =
|
|
3993
|
+
import { defineCommand as defineCommand31 } from "citty";
|
|
3994
|
+
import consola27 from "consola";
|
|
3995
|
+
var configSetCommand = defineCommand31({
|
|
3920
3996
|
meta: {
|
|
3921
3997
|
name: "set",
|
|
3922
3998
|
description: "Set a configuration value"
|
|
@@ -3952,12 +4028,12 @@ var configSetCommand = defineCommand30({
|
|
|
3952
4028
|
throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
|
|
3953
4029
|
}
|
|
3954
4030
|
saveConfig(config);
|
|
3955
|
-
|
|
4031
|
+
consola27.success(`Set ${key} = ${value}`);
|
|
3956
4032
|
}
|
|
3957
4033
|
});
|
|
3958
4034
|
|
|
3959
4035
|
// src/commands/fetch/index.ts
|
|
3960
|
-
import { defineCommand as
|
|
4036
|
+
import { defineCommand as defineCommand32 } from "citty";
|
|
3961
4037
|
async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
3962
4038
|
const token = getAuthToken();
|
|
3963
4039
|
if (!token) {
|
|
@@ -3993,13 +4069,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
|
3993
4069
|
throw new CliError(`HTTP ${response.status} ${response.statusText}`);
|
|
3994
4070
|
}
|
|
3995
4071
|
}
|
|
3996
|
-
var fetchCommand =
|
|
4072
|
+
var fetchCommand = defineCommand32({
|
|
3997
4073
|
meta: {
|
|
3998
4074
|
name: "fetch",
|
|
3999
4075
|
description: "Make authenticated HTTP requests"
|
|
4000
4076
|
},
|
|
4001
4077
|
subCommands: {
|
|
4002
|
-
get:
|
|
4078
|
+
get: defineCommand32({
|
|
4003
4079
|
meta: {
|
|
4004
4080
|
name: "get",
|
|
4005
4081
|
description: "GET request with auth token"
|
|
@@ -4025,7 +4101,7 @@ var fetchCommand = defineCommand31({
|
|
|
4025
4101
|
await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
|
|
4026
4102
|
}
|
|
4027
4103
|
}),
|
|
4028
|
-
post:
|
|
4104
|
+
post: defineCommand32({
|
|
4029
4105
|
meta: {
|
|
4030
4106
|
name: "post",
|
|
4031
4107
|
description: "POST request with auth token"
|
|
@@ -4064,8 +4140,8 @@ var fetchCommand = defineCommand31({
|
|
|
4064
4140
|
});
|
|
4065
4141
|
|
|
4066
4142
|
// src/commands/mcp/index.ts
|
|
4067
|
-
import { defineCommand as
|
|
4068
|
-
var mcpCommand =
|
|
4143
|
+
import { defineCommand as defineCommand33 } from "citty";
|
|
4144
|
+
var mcpCommand = defineCommand33({
|
|
4069
4145
|
meta: {
|
|
4070
4146
|
name: "mcp",
|
|
4071
4147
|
description: "Start MCP server for AI agents"
|
|
@@ -4088,7 +4164,7 @@ var mcpCommand = defineCommand32({
|
|
|
4088
4164
|
if (transport !== "stdio" && transport !== "sse") {
|
|
4089
4165
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
4090
4166
|
}
|
|
4091
|
-
const { startMcpServer } = await import("./server-
|
|
4167
|
+
const { startMcpServer } = await import("./server-QGV3ED6I.js");
|
|
4092
4168
|
await startMcpServer(transport, port);
|
|
4093
4169
|
}
|
|
4094
4170
|
});
|
|
@@ -4096,10 +4172,10 @@ var mcpCommand = defineCommand32({
|
|
|
4096
4172
|
// src/commands/init/index.ts
|
|
4097
4173
|
import { existsSync as existsSync7, copyFileSync, writeFileSync as writeFileSync5 } from "fs";
|
|
4098
4174
|
import { randomBytes } from "crypto";
|
|
4099
|
-
import { execFileSync as
|
|
4175
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
4100
4176
|
import { join as join6 } from "path";
|
|
4101
|
-
import { defineCommand as
|
|
4102
|
-
import
|
|
4177
|
+
import { defineCommand as defineCommand34 } from "citty";
|
|
4178
|
+
import consola28 from "consola";
|
|
4103
4179
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
4104
4180
|
async function downloadTemplate(repo, targetDir) {
|
|
4105
4181
|
const { downloadTemplate: gigetDownload } = await import("giget");
|
|
@@ -4108,28 +4184,28 @@ async function downloadTemplate(repo, targetDir) {
|
|
|
4108
4184
|
function installDeps(dir) {
|
|
4109
4185
|
const hasLockFile = (name) => existsSync7(join6(dir, name));
|
|
4110
4186
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
4111
|
-
|
|
4187
|
+
execFileSync7("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
4112
4188
|
} else if (hasLockFile("bun.lockb")) {
|
|
4113
|
-
|
|
4189
|
+
execFileSync7("bun", ["install"], { cwd: dir, stdio: "inherit" });
|
|
4114
4190
|
} else {
|
|
4115
|
-
|
|
4191
|
+
execFileSync7("npm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
4116
4192
|
}
|
|
4117
4193
|
}
|
|
4118
4194
|
async function promptChoice(message, choices) {
|
|
4119
|
-
const result = await
|
|
4195
|
+
const result = await consola28.prompt(message, { type: "select", options: choices });
|
|
4120
4196
|
if (typeof result === "symbol") {
|
|
4121
4197
|
throw new CliExit(0);
|
|
4122
4198
|
}
|
|
4123
4199
|
return result;
|
|
4124
4200
|
}
|
|
4125
4201
|
async function promptText(message, defaultValue) {
|
|
4126
|
-
const result = await
|
|
4202
|
+
const result = await consola28.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
|
|
4127
4203
|
if (typeof result === "symbol") {
|
|
4128
4204
|
throw new CliExit(0);
|
|
4129
4205
|
}
|
|
4130
4206
|
return result || defaultValue || "";
|
|
4131
4207
|
}
|
|
4132
|
-
var initCommand =
|
|
4208
|
+
var initCommand = defineCommand34({
|
|
4133
4209
|
meta: {
|
|
4134
4210
|
name: "init",
|
|
4135
4211
|
description: "Scaffold a new OpenApe project"
|
|
@@ -4174,20 +4250,20 @@ async function initSP(targetDir) {
|
|
|
4174
4250
|
if (existsSync7(join6(dir, "package.json"))) {
|
|
4175
4251
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
4176
4252
|
}
|
|
4177
|
-
|
|
4253
|
+
consola28.start("Scaffolding SP starter...");
|
|
4178
4254
|
await downloadTemplate("openape-ai/openape-sp-starter", dir);
|
|
4179
|
-
|
|
4180
|
-
|
|
4255
|
+
consola28.success("Scaffolded from openape-sp-starter");
|
|
4256
|
+
consola28.start("Installing dependencies...");
|
|
4181
4257
|
installDeps(dir);
|
|
4182
|
-
|
|
4258
|
+
consola28.success("Dependencies installed");
|
|
4183
4259
|
const envExample = join6(dir, ".env.example");
|
|
4184
4260
|
const envFile = join6(dir, ".env");
|
|
4185
4261
|
if (existsSync7(envExample) && !existsSync7(envFile)) {
|
|
4186
4262
|
copyFileSync(envExample, envFile);
|
|
4187
|
-
|
|
4263
|
+
consola28.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
4188
4264
|
}
|
|
4189
4265
|
console.log("");
|
|
4190
|
-
|
|
4266
|
+
consola28.box([
|
|
4191
4267
|
`cd ${dir}`,
|
|
4192
4268
|
"npm run dev",
|
|
4193
4269
|
"",
|
|
@@ -4206,15 +4282,15 @@ async function initIdP(targetDir) {
|
|
|
4206
4282
|
"s3 (S3-compatible)"
|
|
4207
4283
|
]);
|
|
4208
4284
|
const adminEmail = await promptText("Admin email");
|
|
4209
|
-
|
|
4285
|
+
consola28.start("Scaffolding IdP starter...");
|
|
4210
4286
|
await downloadTemplate("openape-ai/openape-idp-starter", dir);
|
|
4211
|
-
|
|
4212
|
-
|
|
4287
|
+
consola28.success("Scaffolded from openape-idp-starter");
|
|
4288
|
+
consola28.start("Installing dependencies...");
|
|
4213
4289
|
installDeps(dir);
|
|
4214
|
-
|
|
4290
|
+
consola28.success("Dependencies installed");
|
|
4215
4291
|
const sessionSecret = randomBytes(32).toString("hex");
|
|
4216
4292
|
const managementToken = randomBytes(32).toString("hex");
|
|
4217
|
-
|
|
4293
|
+
consola28.success("Secrets generated");
|
|
4218
4294
|
const isLocalhost = domain === "localhost";
|
|
4219
4295
|
const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
|
|
4220
4296
|
const envContent = [
|
|
@@ -4230,9 +4306,9 @@ async function initIdP(targetDir) {
|
|
|
4230
4306
|
].join("\n");
|
|
4231
4307
|
writeFileSync5(join6(dir, ".env"), `${envContent}
|
|
4232
4308
|
`, { mode: 384 });
|
|
4233
|
-
|
|
4309
|
+
consola28.success(".env created");
|
|
4234
4310
|
console.log("");
|
|
4235
|
-
|
|
4311
|
+
consola28.box([
|
|
4236
4312
|
`cd ${dir}`,
|
|
4237
4313
|
"npm run dev",
|
|
4238
4314
|
"",
|
|
@@ -4252,8 +4328,8 @@ import { Buffer as Buffer5 } from "buffer";
|
|
|
4252
4328
|
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
4253
4329
|
import { execFile as execFile2 } from "child_process";
|
|
4254
4330
|
import { sign as sign2 } from "crypto";
|
|
4255
|
-
import { defineCommand as
|
|
4256
|
-
import
|
|
4331
|
+
import { defineCommand as defineCommand35 } from "citty";
|
|
4332
|
+
import consola29 from "consola";
|
|
4257
4333
|
var DEFAULT_IDP_URL2 = "https://id.openape.at";
|
|
4258
4334
|
var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
|
|
4259
4335
|
var POLL_INTERVAL = 3e3;
|
|
@@ -4296,7 +4372,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
4296
4372
|
}
|
|
4297
4373
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
4298
4374
|
}
|
|
4299
|
-
var enrollCommand =
|
|
4375
|
+
var enrollCommand = defineCommand35({
|
|
4300
4376
|
meta: {
|
|
4301
4377
|
name: "enroll",
|
|
4302
4378
|
description: "Enroll an agent with an Identity Provider"
|
|
@@ -4316,18 +4392,18 @@ var enrollCommand = defineCommand34({
|
|
|
4316
4392
|
}
|
|
4317
4393
|
},
|
|
4318
4394
|
async run({ args }) {
|
|
4319
|
-
const idp = args.idp || await
|
|
4395
|
+
const idp = args.idp || await consola29.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
|
|
4320
4396
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
4321
4397
|
return r;
|
|
4322
4398
|
}) || DEFAULT_IDP_URL2;
|
|
4323
|
-
const agentName = args.name || await
|
|
4399
|
+
const agentName = args.name || await consola29.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
|
|
4324
4400
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
4325
4401
|
return r;
|
|
4326
4402
|
});
|
|
4327
4403
|
if (!agentName) {
|
|
4328
4404
|
throw new CliError("Agent name is required.");
|
|
4329
4405
|
}
|
|
4330
|
-
const keyPath = args.key || await
|
|
4406
|
+
const keyPath = args.key || await consola29.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
|
|
4331
4407
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
4332
4408
|
return r;
|
|
4333
4409
|
}) || DEFAULT_KEY_PATH;
|
|
@@ -4335,19 +4411,19 @@ var enrollCommand = defineCommand34({
|
|
|
4335
4411
|
let publicKey;
|
|
4336
4412
|
if (existsSync8(resolvedKey)) {
|
|
4337
4413
|
publicKey = readPublicKey(resolvedKey);
|
|
4338
|
-
|
|
4414
|
+
consola29.success(`Using existing key ${keyPath}`);
|
|
4339
4415
|
} else {
|
|
4340
|
-
|
|
4416
|
+
consola29.start(`Generating Ed25519 key pair at ${keyPath}...`);
|
|
4341
4417
|
publicKey = generateAndSaveKey(keyPath);
|
|
4342
|
-
|
|
4418
|
+
consola29.success(`Key pair generated at ${keyPath}`);
|
|
4343
4419
|
}
|
|
4344
4420
|
const encodedKey = encodeURIComponent(publicKey);
|
|
4345
4421
|
const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
|
|
4346
|
-
|
|
4347
|
-
|
|
4422
|
+
consola29.info("Opening browser for enrollment...");
|
|
4423
|
+
consola29.info(`\u2192 ${idp}/enroll`);
|
|
4348
4424
|
openBrowser2(enrollUrl);
|
|
4349
4425
|
console.log("");
|
|
4350
|
-
const agentEmail = await
|
|
4426
|
+
const agentEmail = await consola29.prompt(
|
|
4351
4427
|
"Agent email (shown in browser after enrollment)",
|
|
4352
4428
|
{ type: "text", placeholder: `agent+${agentName}@...` }
|
|
4353
4429
|
).then((r) => {
|
|
@@ -4357,7 +4433,7 @@ var enrollCommand = defineCommand34({
|
|
|
4357
4433
|
if (!agentEmail) {
|
|
4358
4434
|
throw new CliError("Agent email is required to verify enrollment.");
|
|
4359
4435
|
}
|
|
4360
|
-
|
|
4436
|
+
consola29.start("Verifying enrollment...");
|
|
4361
4437
|
const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
|
|
4362
4438
|
saveAuth({
|
|
4363
4439
|
idp,
|
|
@@ -4369,18 +4445,18 @@ var enrollCommand = defineCommand34({
|
|
|
4369
4445
|
config.defaults = { ...config.defaults, idp };
|
|
4370
4446
|
config.agent = { key: keyPath, email: agentEmail };
|
|
4371
4447
|
saveConfig(config);
|
|
4372
|
-
|
|
4373
|
-
|
|
4448
|
+
consola29.success(`Agent enrolled as ${agentEmail}`);
|
|
4449
|
+
consola29.success("Config saved to ~/.config/apes/");
|
|
4374
4450
|
console.log("");
|
|
4375
|
-
|
|
4451
|
+
consola29.info("Verify with: apes whoami");
|
|
4376
4452
|
}
|
|
4377
4453
|
});
|
|
4378
4454
|
|
|
4379
4455
|
// src/commands/register-user.ts
|
|
4380
4456
|
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
4381
|
-
import { defineCommand as
|
|
4382
|
-
import
|
|
4383
|
-
var registerUserCommand =
|
|
4457
|
+
import { defineCommand as defineCommand36 } from "citty";
|
|
4458
|
+
import consola30 from "consola";
|
|
4459
|
+
var registerUserCommand = defineCommand36({
|
|
4384
4460
|
meta: {
|
|
4385
4461
|
name: "register-user",
|
|
4386
4462
|
description: "Register a sub-user with SSH key"
|
|
@@ -4435,18 +4511,18 @@ var registerUserCommand = defineCommand35({
|
|
|
4435
4511
|
...userType ? { type: userType } : {}
|
|
4436
4512
|
}
|
|
4437
4513
|
});
|
|
4438
|
-
|
|
4514
|
+
consola30.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
|
|
4439
4515
|
}
|
|
4440
4516
|
});
|
|
4441
4517
|
|
|
4442
4518
|
// src/commands/utils/index.ts
|
|
4443
|
-
import { defineCommand as
|
|
4519
|
+
import { defineCommand as defineCommand38 } from "citty";
|
|
4444
4520
|
|
|
4445
4521
|
// src/commands/utils/dig.ts
|
|
4446
|
-
import { defineCommand as
|
|
4447
|
-
import
|
|
4522
|
+
import { defineCommand as defineCommand37 } from "citty";
|
|
4523
|
+
import consola31 from "consola";
|
|
4448
4524
|
import { resolveDDISA as resolveDDISA2 } from "@openape/core";
|
|
4449
|
-
var digCommand =
|
|
4525
|
+
var digCommand = defineCommand37({
|
|
4450
4526
|
meta: {
|
|
4451
4527
|
name: "dig",
|
|
4452
4528
|
description: "Resolve DDISA IdP for a domain or email (admin/diag tool)"
|
|
@@ -4519,12 +4595,12 @@ var digCommand = defineCommand36({
|
|
|
4519
4595
|
console.log(` domain: ${domain}`);
|
|
4520
4596
|
console.log("");
|
|
4521
4597
|
if (!result.ddisa.found) {
|
|
4522
|
-
|
|
4598
|
+
consola31.warn(`No DDISA record at _ddisa.${domain}`);
|
|
4523
4599
|
if (result.hint) console.log(`
|
|
4524
4600
|
${result.hint}`);
|
|
4525
4601
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
4526
4602
|
}
|
|
4527
|
-
|
|
4603
|
+
consola31.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
|
|
4528
4604
|
console.log(` Version: ${result.ddisa.version || "ddisa1"}`);
|
|
4529
4605
|
console.log(` IdP URL: ${result.ddisa.idp}`);
|
|
4530
4606
|
if (result.ddisa.mode) console.log(` Mode: ${result.ddisa.mode}`);
|
|
@@ -4534,13 +4610,13 @@ ${result.hint}`);
|
|
|
4534
4610
|
return;
|
|
4535
4611
|
}
|
|
4536
4612
|
if (result.idpDiscovery.ok) {
|
|
4537
|
-
|
|
4613
|
+
consola31.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
|
|
4538
4614
|
if (result.idpDiscovery.issuer) console.log(` Issuer: ${result.idpDiscovery.issuer}`);
|
|
4539
4615
|
if (result.idpDiscovery.ddisaVersion) console.log(` DDISA: v${result.idpDiscovery.ddisaVersion}`);
|
|
4540
4616
|
if (result.idpDiscovery.authMethods?.length) console.log(` Auth: ${result.idpDiscovery.authMethods.join(", ")}`);
|
|
4541
4617
|
if (result.idpDiscovery.grantTypes?.length) console.log(` Grants: ${result.idpDiscovery.grantTypes.join(", ")}`);
|
|
4542
4618
|
} else {
|
|
4543
|
-
|
|
4619
|
+
consola31.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
|
|
4544
4620
|
if (result.hint) console.log(`
|
|
4545
4621
|
${result.hint}`);
|
|
4546
4622
|
throw new CliError(`IdP at ${result.ddisa.idp} not reachable`);
|
|
@@ -4549,7 +4625,7 @@ ${result.hint}`);
|
|
|
4549
4625
|
});
|
|
4550
4626
|
|
|
4551
4627
|
// src/commands/utils/index.ts
|
|
4552
|
-
var utilsCommand =
|
|
4628
|
+
var utilsCommand = defineCommand38({
|
|
4553
4629
|
meta: {
|
|
4554
4630
|
name: "utils",
|
|
4555
4631
|
description: "Admin/diagnostic utilities (dig, \u2026)"
|
|
@@ -4560,12 +4636,12 @@ var utilsCommand = defineCommand37({
|
|
|
4560
4636
|
});
|
|
4561
4637
|
|
|
4562
4638
|
// src/commands/sessions/index.ts
|
|
4563
|
-
import { defineCommand as
|
|
4639
|
+
import { defineCommand as defineCommand41 } from "citty";
|
|
4564
4640
|
|
|
4565
4641
|
// src/commands/sessions/list.ts
|
|
4566
|
-
import { defineCommand as
|
|
4567
|
-
import
|
|
4568
|
-
var sessionsListCommand =
|
|
4642
|
+
import { defineCommand as defineCommand39 } from "citty";
|
|
4643
|
+
import consola32 from "consola";
|
|
4644
|
+
var sessionsListCommand = defineCommand39({
|
|
4569
4645
|
meta: {
|
|
4570
4646
|
name: "list",
|
|
4571
4647
|
description: "List your active refresh-token families (one per logged-in device)."
|
|
@@ -4583,7 +4659,7 @@ var sessionsListCommand = defineCommand38({
|
|
|
4583
4659
|
return;
|
|
4584
4660
|
}
|
|
4585
4661
|
if (result.data.length === 0) {
|
|
4586
|
-
|
|
4662
|
+
consola32.info("No active sessions.");
|
|
4587
4663
|
return;
|
|
4588
4664
|
}
|
|
4589
4665
|
for (const f of result.data) {
|
|
@@ -4595,9 +4671,9 @@ var sessionsListCommand = defineCommand38({
|
|
|
4595
4671
|
});
|
|
4596
4672
|
|
|
4597
4673
|
// src/commands/sessions/remove.ts
|
|
4598
|
-
import { defineCommand as
|
|
4599
|
-
import
|
|
4600
|
-
var sessionsRemoveCommand =
|
|
4674
|
+
import { defineCommand as defineCommand40 } from "citty";
|
|
4675
|
+
import consola33 from "consola";
|
|
4676
|
+
var sessionsRemoveCommand = defineCommand40({
|
|
4601
4677
|
meta: {
|
|
4602
4678
|
name: "remove",
|
|
4603
4679
|
description: "Revoke one of your active refresh-token families by id."
|
|
@@ -4613,12 +4689,12 @@ var sessionsRemoveCommand = defineCommand39({
|
|
|
4613
4689
|
const id = String(args.familyId).trim();
|
|
4614
4690
|
if (!id) throw new CliError("familyId required");
|
|
4615
4691
|
await apiFetch(`/api/me/sessions/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
4616
|
-
|
|
4692
|
+
consola33.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
|
|
4617
4693
|
}
|
|
4618
4694
|
});
|
|
4619
4695
|
|
|
4620
4696
|
// src/commands/sessions/index.ts
|
|
4621
|
-
var sessionsCommand =
|
|
4697
|
+
var sessionsCommand = defineCommand41({
|
|
4622
4698
|
meta: {
|
|
4623
4699
|
name: "sessions",
|
|
4624
4700
|
description: "Manage your active refresh-token sessions across devices"
|
|
@@ -4630,10 +4706,10 @@ var sessionsCommand = defineCommand40({
|
|
|
4630
4706
|
});
|
|
4631
4707
|
|
|
4632
4708
|
// src/commands/dns-check.ts
|
|
4633
|
-
import { defineCommand as
|
|
4634
|
-
import
|
|
4709
|
+
import { defineCommand as defineCommand42 } from "citty";
|
|
4710
|
+
import consola34 from "consola";
|
|
4635
4711
|
import { resolveDDISA as resolveDDISA3 } from "@openape/core";
|
|
4636
|
-
var dnsCheckCommand =
|
|
4712
|
+
var dnsCheckCommand = defineCommand42({
|
|
4637
4713
|
meta: {
|
|
4638
4714
|
name: "dns-check",
|
|
4639
4715
|
description: "Validate DDISA DNS TXT records for a domain"
|
|
@@ -4647,7 +4723,7 @@ var dnsCheckCommand = defineCommand41({
|
|
|
4647
4723
|
},
|
|
4648
4724
|
async run({ args }) {
|
|
4649
4725
|
const domain = args.domain;
|
|
4650
|
-
|
|
4726
|
+
consola34.start(`Checking _ddisa.${domain}...`);
|
|
4651
4727
|
try {
|
|
4652
4728
|
const result = await resolveDDISA3(domain);
|
|
4653
4729
|
if (!result) {
|
|
@@ -4656,7 +4732,7 @@ var dnsCheckCommand = defineCommand41({
|
|
|
4656
4732
|
console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
|
|
4657
4733
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
4658
4734
|
}
|
|
4659
|
-
|
|
4735
|
+
consola34.success(`_ddisa.${domain} \u2192 ${result.idp}`);
|
|
4660
4736
|
console.log("");
|
|
4661
4737
|
console.log(` Version: ${result.version || "ddisa1"}`);
|
|
4662
4738
|
console.log(` IdP URL: ${result.idp}`);
|
|
@@ -4665,14 +4741,14 @@ var dnsCheckCommand = defineCommand41({
|
|
|
4665
4741
|
if (result.priority !== void 0)
|
|
4666
4742
|
console.log(` Priority: ${result.priority}`);
|
|
4667
4743
|
console.log("");
|
|
4668
|
-
|
|
4744
|
+
consola34.start(`Verifying IdP at ${result.idp}...`);
|
|
4669
4745
|
const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
|
|
4670
4746
|
if (!discoResp.ok) {
|
|
4671
|
-
|
|
4747
|
+
consola34.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
|
|
4672
4748
|
return;
|
|
4673
4749
|
}
|
|
4674
4750
|
const disco = await discoResp.json();
|
|
4675
|
-
|
|
4751
|
+
consola34.success(`IdP is reachable`);
|
|
4676
4752
|
console.log(` Issuer: ${disco.issuer}`);
|
|
4677
4753
|
console.log(` DDISA: v${disco.ddisa_version || "?"}`);
|
|
4678
4754
|
if (disco.ddisa_auth_methods_supported) {
|
|
@@ -4690,7 +4766,7 @@ var dnsCheckCommand = defineCommand41({
|
|
|
4690
4766
|
// src/commands/health.ts
|
|
4691
4767
|
import { exec } from "child_process";
|
|
4692
4768
|
import { promisify } from "util";
|
|
4693
|
-
import { defineCommand as
|
|
4769
|
+
import { defineCommand as defineCommand43 } from "citty";
|
|
4694
4770
|
var execAsync = promisify(exec);
|
|
4695
4771
|
async function resolveApeShellPath() {
|
|
4696
4772
|
try {
|
|
@@ -4726,7 +4802,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
4726
4802
|
}
|
|
4727
4803
|
}
|
|
4728
4804
|
async function runHealth(args) {
|
|
4729
|
-
const version = true ? "0.
|
|
4805
|
+
const version = true ? "0.29.0" : "0.0.0";
|
|
4730
4806
|
const auth = loadAuth();
|
|
4731
4807
|
if (!auth) {
|
|
4732
4808
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -4789,7 +4865,7 @@ async function runHealth(args) {
|
|
|
4789
4865
|
throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
|
|
4790
4866
|
}
|
|
4791
4867
|
}
|
|
4792
|
-
var healthCommand =
|
|
4868
|
+
var healthCommand = defineCommand43({
|
|
4793
4869
|
meta: {
|
|
4794
4870
|
name: "health",
|
|
4795
4871
|
description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
|
|
@@ -4807,8 +4883,8 @@ var healthCommand = defineCommand42({
|
|
|
4807
4883
|
});
|
|
4808
4884
|
|
|
4809
4885
|
// src/commands/workflows.ts
|
|
4810
|
-
import { defineCommand as
|
|
4811
|
-
import
|
|
4886
|
+
import { defineCommand as defineCommand44 } from "citty";
|
|
4887
|
+
import consola35 from "consola";
|
|
4812
4888
|
|
|
4813
4889
|
// src/guides/index.ts
|
|
4814
4890
|
var guides = [
|
|
@@ -4858,7 +4934,7 @@ var guides = [
|
|
|
4858
4934
|
];
|
|
4859
4935
|
|
|
4860
4936
|
// src/commands/workflows.ts
|
|
4861
|
-
var workflowsCommand =
|
|
4937
|
+
var workflowsCommand = defineCommand44({
|
|
4862
4938
|
meta: {
|
|
4863
4939
|
name: "workflows",
|
|
4864
4940
|
description: "Discover workflow guides"
|
|
@@ -4879,7 +4955,7 @@ var workflowsCommand = defineCommand43({
|
|
|
4879
4955
|
if (args.id) {
|
|
4880
4956
|
const guide = guides.find((g) => g.id === String(args.id));
|
|
4881
4957
|
if (!guide) {
|
|
4882
|
-
|
|
4958
|
+
consola35.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
|
|
4883
4959
|
throw new CliError(`Guide not found: ${args.id}`);
|
|
4884
4960
|
}
|
|
4885
4961
|
if (args.json) {
|
|
@@ -4922,7 +4998,7 @@ var workflowsCommand = defineCommand43({
|
|
|
4922
4998
|
import { existsSync as existsSync10, mkdirSync as mkdirSync2, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
4923
4999
|
import { homedir as homedir6 } from "os";
|
|
4924
5000
|
import { join as join7 } from "path";
|
|
4925
|
-
import
|
|
5001
|
+
import consola36 from "consola";
|
|
4926
5002
|
var PACKAGE_NAME = "@openape/apes";
|
|
4927
5003
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
4928
5004
|
var CACHE_FILE = join7(homedir6(), ".config", "apes", ".version-check.json");
|
|
@@ -4967,7 +5043,7 @@ async function fetchLatestVersion() {
|
|
|
4967
5043
|
}
|
|
4968
5044
|
function warnIfBehind(currentVersion, latest) {
|
|
4969
5045
|
if (compareSemver(currentVersion, latest) < 0) {
|
|
4970
|
-
|
|
5046
|
+
consola36.warn(
|
|
4971
5047
|
`apes ${currentVersion} is behind latest @openape/apes@${latest}. Run \`npm i -g @openape/apes@latest\` to update. (Suppress with APES_NO_UPDATE_CHECK=1.)`
|
|
4972
5048
|
);
|
|
4973
5049
|
}
|
|
@@ -4999,10 +5075,10 @@ if (shellRewrite) {
|
|
|
4999
5075
|
if (shellRewrite.action === "rewrite") {
|
|
5000
5076
|
process.argv = shellRewrite.argv;
|
|
5001
5077
|
} else if (shellRewrite.action === "version") {
|
|
5002
|
-
console.log(`ape-shell ${"0.
|
|
5078
|
+
console.log(`ape-shell ${"0.29.0"} (OpenApe DDISA shell wrapper)`);
|
|
5003
5079
|
process.exit(0);
|
|
5004
5080
|
} else if (shellRewrite.action === "help") {
|
|
5005
|
-
console.log(`ape-shell ${"0.
|
|
5081
|
+
console.log(`ape-shell ${"0.29.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
5006
5082
|
console.log("");
|
|
5007
5083
|
console.log("Usage:");
|
|
5008
5084
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -5026,7 +5102,7 @@ if (shellRewrite) {
|
|
|
5026
5102
|
}
|
|
5027
5103
|
}
|
|
5028
5104
|
var debug = process.argv.includes("--debug");
|
|
5029
|
-
var grantsCommand =
|
|
5105
|
+
var grantsCommand = defineCommand45({
|
|
5030
5106
|
meta: {
|
|
5031
5107
|
name: "grants",
|
|
5032
5108
|
description: "Grant management"
|
|
@@ -5047,7 +5123,7 @@ var grantsCommand = defineCommand44({
|
|
|
5047
5123
|
"delegation-revoke": delegationRevokeCommand
|
|
5048
5124
|
}
|
|
5049
5125
|
});
|
|
5050
|
-
var configCommand =
|
|
5126
|
+
var configCommand = defineCommand45({
|
|
5051
5127
|
meta: {
|
|
5052
5128
|
name: "config",
|
|
5053
5129
|
description: "Configuration management"
|
|
@@ -5057,10 +5133,10 @@ var configCommand = defineCommand44({
|
|
|
5057
5133
|
set: configSetCommand
|
|
5058
5134
|
}
|
|
5059
5135
|
});
|
|
5060
|
-
var main =
|
|
5136
|
+
var main = defineCommand45({
|
|
5061
5137
|
meta: {
|
|
5062
5138
|
name: "apes",
|
|
5063
|
-
version: "0.
|
|
5139
|
+
version: "0.29.0",
|
|
5064
5140
|
description: "Unified CLI for OpenApe"
|
|
5065
5141
|
},
|
|
5066
5142
|
subCommands: {
|
|
@@ -5115,20 +5191,20 @@ async function maybeRefreshAuth() {
|
|
|
5115
5191
|
}
|
|
5116
5192
|
}
|
|
5117
5193
|
await maybeRefreshAuth();
|
|
5118
|
-
await maybeWarnStaleVersion("0.
|
|
5194
|
+
await maybeWarnStaleVersion("0.29.0").catch(() => {
|
|
5119
5195
|
});
|
|
5120
5196
|
runMain(main).catch((err) => {
|
|
5121
5197
|
if (err instanceof CliExit) {
|
|
5122
5198
|
process.exit(err.exitCode);
|
|
5123
5199
|
}
|
|
5124
5200
|
if (err instanceof CliError) {
|
|
5125
|
-
|
|
5201
|
+
consola37.error(err.message);
|
|
5126
5202
|
process.exit(err.exitCode);
|
|
5127
5203
|
}
|
|
5128
5204
|
if (debug) {
|
|
5129
|
-
|
|
5205
|
+
consola37.error(err);
|
|
5130
5206
|
} else {
|
|
5131
|
-
|
|
5207
|
+
consola37.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
|
|
5132
5208
|
}
|
|
5133
5209
|
process.exit(1);
|
|
5134
5210
|
});
|