@openape/apes 0.28.0 → 0.30.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";
|
|
@@ -2548,8 +2623,15 @@ except Exception: sys.exit(1)" 2>/dev/null || true)
|
|
|
2548
2623
|
try: print(json.load(open(os.path.expanduser('~/.config/apes/auth.json')))['idp'])
|
|
2549
2624
|
except Exception: sys.exit(1)" 2>/dev/null || true)
|
|
2550
2625
|
if [ -n "$agent_email" ] && [ -n "$agent_idp" ]; then
|
|
2551
|
-
|
|
2552
|
-
|
|
2626
|
+
# Capture full output so the failure mode is debuggable from logs
|
|
2627
|
+
# without needing an interactive grant approval. apes-login should
|
|
2628
|
+
# succeed with the SSH key under ~/.ssh/id_ed25519 written by spawn;
|
|
2629
|
+
# if it doesn't, the cached token carries us until expiry (~1h) and
|
|
2630
|
+
# the daemon will retry on the next launchd restart.
|
|
2631
|
+
login_output=$(apes login "$agent_email" --idp "$agent_idp" 2>&1) || {
|
|
2632
|
+
echo "warn: apes login failed for $agent_email; continuing with cached token" >&2
|
|
2633
|
+
echo "$login_output" | sed 's/^/ apes-login: /' >&2
|
|
2634
|
+
}
|
|
2553
2635
|
fi
|
|
2554
2636
|
fi
|
|
2555
2637
|
|
|
@@ -2597,7 +2679,7 @@ set +a
|
|
|
2597
2679
|
exec openape-chat-bridge
|
|
2598
2680
|
`;
|
|
2599
2681
|
}
|
|
2600
|
-
function buildBridgePlist(agentName, homeDir) {
|
|
2682
|
+
function buildBridgePlist(agentName, homeDir, ownerEmail) {
|
|
2601
2683
|
const startScript = `${homeDir}/Library/Application Support/openape/bridge/start.sh`;
|
|
2602
2684
|
const stdoutLog = `${homeDir}/Library/Logs/openape-chat-bridge.log`;
|
|
2603
2685
|
const stderrLog = `${homeDir}/Library/Logs/openape-chat-bridge.err.log`;
|
|
@@ -2632,6 +2714,8 @@ function buildBridgePlist(agentName, homeDir) {
|
|
|
2632
2714
|
<string>${homeDir}</string>
|
|
2633
2715
|
<key>PATH</key>
|
|
2634
2716
|
<string>${homeDir}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
|
2717
|
+
<key>OPENAPE_OWNER_EMAIL</key>
|
|
2718
|
+
<string>${ownerEmail}</string>
|
|
2635
2719
|
</dict>
|
|
2636
2720
|
</dict>
|
|
2637
2721
|
</plist>
|
|
@@ -2639,7 +2723,7 @@ function buildBridgePlist(agentName, homeDir) {
|
|
|
2639
2723
|
}
|
|
2640
2724
|
|
|
2641
2725
|
// src/commands/agents/spawn.ts
|
|
2642
|
-
var spawnAgentCommand =
|
|
2726
|
+
var spawnAgentCommand = defineCommand24({
|
|
2643
2727
|
meta: {
|
|
2644
2728
|
name: "spawn",
|
|
2645
2729
|
description: "Provision a local macOS agent end-to-end (OS user, keypair, IdP agent, Claude hook)"
|
|
@@ -2725,12 +2809,12 @@ and try again.`
|
|
|
2725
2809
|
const scratch = mkdtempSync2(join4(tmpdir2(), `apes-spawn-${name}-`));
|
|
2726
2810
|
const scriptPath = join4(scratch, "setup.sh");
|
|
2727
2811
|
try {
|
|
2728
|
-
|
|
2812
|
+
consola22.start(`Generating keypair for ${name}\u2026`);
|
|
2729
2813
|
const { privatePem, publicSshLine } = generateKeyPairInMemory();
|
|
2730
|
-
|
|
2814
|
+
consola22.start(`Registering agent at ${idp}\u2026`);
|
|
2731
2815
|
const registration = await registerAgentAtIdp({ name, publicKey: publicSshLine, idp });
|
|
2732
|
-
|
|
2733
|
-
|
|
2816
|
+
consola22.success(`Registered as ${registration.email}`);
|
|
2817
|
+
consola22.start("Issuing agent access token\u2026");
|
|
2734
2818
|
const { token, expiresIn } = await issueAgentToken({
|
|
2735
2819
|
idp,
|
|
2736
2820
|
agentEmail: registration.email,
|
|
@@ -2756,7 +2840,7 @@ and try again.`
|
|
|
2756
2840
|
return {
|
|
2757
2841
|
plistLabel: bridgePlistLabel(name),
|
|
2758
2842
|
plistPath: bridgePlistPath(name),
|
|
2759
|
-
plistContent: buildBridgePlist(name, homeDir),
|
|
2843
|
+
plistContent: buildBridgePlist(name, homeDir, auth.email),
|
|
2760
2844
|
startScript: buildBridgeStartScript(),
|
|
2761
2845
|
envFile: buildBridgeEnvFile(cfg)
|
|
2762
2846
|
};
|
|
@@ -2774,13 +2858,13 @@ and try again.`
|
|
|
2774
2858
|
bridge
|
|
2775
2859
|
});
|
|
2776
2860
|
writeFileSync3(scriptPath, script, { mode: 448 });
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2861
|
+
consola22.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
|
|
2862
|
+
consola22.info("You will be asked to approve the as=root grant in your DDISA inbox; this command blocks until you do.");
|
|
2863
|
+
execFileSync5(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], { stdio: "inherit" });
|
|
2864
|
+
consola22.success(`Agent ${name} spawned.`);
|
|
2781
2865
|
if (args.bridge) {
|
|
2782
|
-
|
|
2783
|
-
|
|
2866
|
+
consola22.info(`On first boot, the bridge will send you a contact request from ${registration.email}.`);
|
|
2867
|
+
consola22.info("Open chat.openape.ai and accept it to start chatting with the agent.");
|
|
2784
2868
|
}
|
|
2785
2869
|
console.log("");
|
|
2786
2870
|
console.log("Run as the agent with:");
|
|
@@ -2814,29 +2898,30 @@ async function resolveClaudeToken(opts) {
|
|
|
2814
2898
|
}
|
|
2815
2899
|
|
|
2816
2900
|
// src/commands/agents/index.ts
|
|
2817
|
-
var agentsCommand =
|
|
2901
|
+
var agentsCommand = defineCommand25({
|
|
2818
2902
|
meta: {
|
|
2819
2903
|
name: "agents",
|
|
2820
|
-
description: "Manage owned agents (register, spawn, list, destroy)"
|
|
2904
|
+
description: "Manage owned agents (register, spawn, list, destroy, allow)"
|
|
2821
2905
|
},
|
|
2822
2906
|
subCommands: {
|
|
2823
2907
|
register: registerAgentCommand,
|
|
2824
2908
|
spawn: spawnAgentCommand,
|
|
2825
2909
|
list: listAgentsCommand,
|
|
2826
|
-
destroy: destroyAgentCommand
|
|
2910
|
+
destroy: destroyAgentCommand,
|
|
2911
|
+
allow: allowAgentCommand
|
|
2827
2912
|
}
|
|
2828
2913
|
});
|
|
2829
2914
|
|
|
2830
2915
|
// src/commands/adapter/index.ts
|
|
2831
|
-
import { defineCommand as
|
|
2832
|
-
import
|
|
2833
|
-
var adapterCommand =
|
|
2916
|
+
import { defineCommand as defineCommand26 } from "citty";
|
|
2917
|
+
import consola23 from "consola";
|
|
2918
|
+
var adapterCommand = defineCommand26({
|
|
2834
2919
|
meta: {
|
|
2835
2920
|
name: "adapter",
|
|
2836
2921
|
description: "Manage CLI adapters"
|
|
2837
2922
|
},
|
|
2838
2923
|
subCommands: {
|
|
2839
|
-
list:
|
|
2924
|
+
list: defineCommand26({
|
|
2840
2925
|
meta: {
|
|
2841
2926
|
name: "list",
|
|
2842
2927
|
description: "List available adapters"
|
|
@@ -2867,7 +2952,7 @@ var adapterCommand = defineCommand25({
|
|
|
2867
2952
|
`);
|
|
2868
2953
|
return;
|
|
2869
2954
|
}
|
|
2870
|
-
|
|
2955
|
+
consola23.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
|
|
2871
2956
|
for (const a of index2.adapters) {
|
|
2872
2957
|
const installed = isInstalled(a.id, false) ? " [installed]" : "";
|
|
2873
2958
|
console.log(` ${a.id.padEnd(12)} ${a.name.padEnd(24)} ${a.category}${installed}`);
|
|
@@ -2889,7 +2974,7 @@ var adapterCommand = defineCommand25({
|
|
|
2889
2974
|
return;
|
|
2890
2975
|
}
|
|
2891
2976
|
if (local.length === 0) {
|
|
2892
|
-
|
|
2977
|
+
consola23.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
|
|
2893
2978
|
return;
|
|
2894
2979
|
}
|
|
2895
2980
|
for (const a of local) {
|
|
@@ -2897,7 +2982,7 @@ var adapterCommand = defineCommand25({
|
|
|
2897
2982
|
}
|
|
2898
2983
|
}
|
|
2899
2984
|
}),
|
|
2900
|
-
install:
|
|
2985
|
+
install: defineCommand26({
|
|
2901
2986
|
meta: {
|
|
2902
2987
|
name: "install",
|
|
2903
2988
|
description: "Install an adapter from the registry"
|
|
@@ -2926,24 +3011,24 @@ var adapterCommand = defineCommand25({
|
|
|
2926
3011
|
for (const id of ids) {
|
|
2927
3012
|
const entry = findAdapter(index, id);
|
|
2928
3013
|
if (!entry) {
|
|
2929
|
-
|
|
3014
|
+
consola23.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
|
|
2930
3015
|
continue;
|
|
2931
3016
|
}
|
|
2932
3017
|
const conflicts = findConflictingAdapters(entry.executable, id);
|
|
2933
3018
|
if (conflicts.length > 0) {
|
|
2934
3019
|
for (const c of conflicts) {
|
|
2935
|
-
|
|
2936
|
-
|
|
3020
|
+
consola23.warn(`Conflicting adapter found: ${c.path} (id: ${c.adapterId}, executable: ${c.executable})`);
|
|
3021
|
+
consola23.warn(` Remove it with: apes adapter remove ${c.adapterId}`);
|
|
2937
3022
|
}
|
|
2938
3023
|
}
|
|
2939
3024
|
const result = await installAdapter(entry, { local });
|
|
2940
3025
|
const verb = result.updated ? "Updated" : "Installed";
|
|
2941
|
-
|
|
2942
|
-
|
|
3026
|
+
consola23.success(`${verb} ${result.id} \u2192 ${result.path}`);
|
|
3027
|
+
consola23.info(`Digest: ${result.digest}`);
|
|
2943
3028
|
}
|
|
2944
3029
|
}
|
|
2945
3030
|
}),
|
|
2946
|
-
remove:
|
|
3031
|
+
remove: defineCommand26({
|
|
2947
3032
|
meta: {
|
|
2948
3033
|
name: "remove",
|
|
2949
3034
|
description: "Remove an installed adapter"
|
|
@@ -2966,9 +3051,9 @@ var adapterCommand = defineCommand25({
|
|
|
2966
3051
|
let failed = false;
|
|
2967
3052
|
for (const id of ids) {
|
|
2968
3053
|
if (removeAdapter(id, local)) {
|
|
2969
|
-
|
|
3054
|
+
consola23.success(`Removed adapter: ${id}`);
|
|
2970
3055
|
} else {
|
|
2971
|
-
|
|
3056
|
+
consola23.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
2972
3057
|
failed = true;
|
|
2973
3058
|
}
|
|
2974
3059
|
}
|
|
@@ -2976,7 +3061,7 @@ var adapterCommand = defineCommand25({
|
|
|
2976
3061
|
throw new CliError("Some adapters could not be removed");
|
|
2977
3062
|
}
|
|
2978
3063
|
}),
|
|
2979
|
-
info:
|
|
3064
|
+
info: defineCommand26({
|
|
2980
3065
|
meta: {
|
|
2981
3066
|
name: "info",
|
|
2982
3067
|
description: "Show detailed adapter information"
|
|
@@ -3018,7 +3103,7 @@ var adapterCommand = defineCommand25({
|
|
|
3018
3103
|
}
|
|
3019
3104
|
}
|
|
3020
3105
|
}),
|
|
3021
|
-
search:
|
|
3106
|
+
search: defineCommand26({
|
|
3022
3107
|
meta: {
|
|
3023
3108
|
name: "search",
|
|
3024
3109
|
description: "Search adapters in the registry"
|
|
@@ -3050,7 +3135,7 @@ var adapterCommand = defineCommand25({
|
|
|
3050
3135
|
return;
|
|
3051
3136
|
}
|
|
3052
3137
|
if (results.length === 0) {
|
|
3053
|
-
|
|
3138
|
+
consola23.info(`No adapters matching "${query}"`);
|
|
3054
3139
|
return;
|
|
3055
3140
|
}
|
|
3056
3141
|
for (const a of results) {
|
|
@@ -3059,7 +3144,7 @@ var adapterCommand = defineCommand25({
|
|
|
3059
3144
|
}
|
|
3060
3145
|
}
|
|
3061
3146
|
}),
|
|
3062
|
-
update:
|
|
3147
|
+
update: defineCommand26({
|
|
3063
3148
|
meta: {
|
|
3064
3149
|
name: "update",
|
|
3065
3150
|
description: "Update installed adapters"
|
|
@@ -3085,33 +3170,33 @@ var adapterCommand = defineCommand25({
|
|
|
3085
3170
|
const targetId = args.id ? String(args.id) : void 0;
|
|
3086
3171
|
const targets = targetId ? [targetId] : index.adapters.map((a) => a.id).filter((id) => isInstalled(id, false));
|
|
3087
3172
|
if (targets.length === 0) {
|
|
3088
|
-
|
|
3173
|
+
consola23.info("No adapters installed to update.");
|
|
3089
3174
|
return;
|
|
3090
3175
|
}
|
|
3091
3176
|
for (const id of targets) {
|
|
3092
3177
|
const entry = findAdapter(index, id);
|
|
3093
3178
|
if (!entry) {
|
|
3094
|
-
|
|
3179
|
+
consola23.warn(`${id}: not found in registry, skipping`);
|
|
3095
3180
|
continue;
|
|
3096
3181
|
}
|
|
3097
3182
|
const localDigest = getInstalledDigest(id, false);
|
|
3098
3183
|
if (localDigest === entry.digest) {
|
|
3099
|
-
|
|
3184
|
+
consola23.info(`${id}: already up to date`);
|
|
3100
3185
|
continue;
|
|
3101
3186
|
}
|
|
3102
3187
|
if (localDigest && !args.yes) {
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3188
|
+
consola23.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
|
|
3189
|
+
consola23.info(` Old: ${localDigest}`);
|
|
3190
|
+
consola23.info(` New: ${entry.digest}`);
|
|
3191
|
+
consola23.info(" Use --yes to confirm");
|
|
3107
3192
|
continue;
|
|
3108
3193
|
}
|
|
3109
3194
|
const result = await installAdapter(entry);
|
|
3110
|
-
|
|
3195
|
+
consola23.success(`Updated ${result.id} \u2192 ${result.path}`);
|
|
3111
3196
|
}
|
|
3112
3197
|
}
|
|
3113
3198
|
}),
|
|
3114
|
-
verify:
|
|
3199
|
+
verify: defineCommand26({
|
|
3115
3200
|
meta: {
|
|
3116
3201
|
name: "verify",
|
|
3117
3202
|
description: "Verify installed adapter against registry digest"
|
|
@@ -3144,7 +3229,7 @@ var adapterCommand = defineCommand25({
|
|
|
3144
3229
|
if (!localDigest)
|
|
3145
3230
|
throw new Error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
3146
3231
|
if (localDigest === entry.digest) {
|
|
3147
|
-
|
|
3232
|
+
consola23.success(`${id}: digest matches registry`);
|
|
3148
3233
|
} else {
|
|
3149
3234
|
console.log(` Local: ${localDigest}`);
|
|
3150
3235
|
console.log(` Registry: ${entry.digest}`);
|
|
@@ -3156,11 +3241,11 @@ var adapterCommand = defineCommand25({
|
|
|
3156
3241
|
});
|
|
3157
3242
|
|
|
3158
3243
|
// src/commands/run.ts
|
|
3159
|
-
import { execFileSync as
|
|
3244
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
3160
3245
|
import { hostname as hostname3 } from "os";
|
|
3161
3246
|
import { basename } from "path";
|
|
3162
|
-
import { defineCommand as
|
|
3163
|
-
import
|
|
3247
|
+
import { defineCommand as defineCommand27 } from "citty";
|
|
3248
|
+
import consola24 from "consola";
|
|
3164
3249
|
function shouldWaitForGrant(args) {
|
|
3165
3250
|
return args.wait === true || process.env.APE_WAIT === "1";
|
|
3166
3251
|
}
|
|
@@ -3197,7 +3282,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
3197
3282
|
const statusCmd = `apes grants status ${grant.id}`;
|
|
3198
3283
|
const executeCmd = `apes grants run ${grant.id}`;
|
|
3199
3284
|
if (mode === "human") {
|
|
3200
|
-
|
|
3285
|
+
consola24.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
|
|
3201
3286
|
console.log(` Approve in browser: ${approveUrl}`);
|
|
3202
3287
|
console.log(` Check status: ${statusCmd}`);
|
|
3203
3288
|
console.log(` Run after approval: ${executeCmd}`);
|
|
@@ -3207,7 +3292,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
3207
3292
|
return;
|
|
3208
3293
|
}
|
|
3209
3294
|
const maxMin = getPollMaxMinutes();
|
|
3210
|
-
|
|
3295
|
+
consola24.success(`Grant ${grant.id} created (pending approval)`);
|
|
3211
3296
|
console.log(` Approve: ${approveUrl}`);
|
|
3212
3297
|
console.log(` Status: ${statusCmd} [--json]`);
|
|
3213
3298
|
console.log(` Execute: ${executeCmd} --wait`);
|
|
@@ -3229,7 +3314,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
3229
3314
|
console.log(' Tip: Approve as "timed" or "always" in the browser to let this');
|
|
3230
3315
|
console.log(" grant be reused on subsequent invocations without re-approval.");
|
|
3231
3316
|
}
|
|
3232
|
-
var runCommand =
|
|
3317
|
+
var runCommand = defineCommand27({
|
|
3233
3318
|
meta: {
|
|
3234
3319
|
name: "run",
|
|
3235
3320
|
description: "Execute a grant-secured command"
|
|
@@ -3332,7 +3417,7 @@ async function runShellMode(command, args) {
|
|
|
3332
3417
|
}
|
|
3333
3418
|
} catch {
|
|
3334
3419
|
}
|
|
3335
|
-
|
|
3420
|
+
consola24.info(`Requesting ape-shell session grant on ${targetHost}`);
|
|
3336
3421
|
const grant = await apiFetch(grantsUrl, {
|
|
3337
3422
|
method: "POST",
|
|
3338
3423
|
body: {
|
|
@@ -3352,8 +3437,8 @@ async function runShellMode(command, args) {
|
|
|
3352
3437
|
host: targetHost
|
|
3353
3438
|
});
|
|
3354
3439
|
if (shouldWaitForGrant(args)) {
|
|
3355
|
-
|
|
3356
|
-
|
|
3440
|
+
consola24.info(`Grant requested: ${grant.id}`);
|
|
3441
|
+
consola24.info("Waiting for approval...");
|
|
3357
3442
|
const maxWait = 3e5;
|
|
3358
3443
|
const interval = 3e3;
|
|
3359
3444
|
const start = Date.now();
|
|
@@ -3384,13 +3469,13 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
3384
3469
|
try {
|
|
3385
3470
|
resolved = await resolveCommand(loaded, [normalizedExecutable, ...parsed.argv]);
|
|
3386
3471
|
} catch (err) {
|
|
3387
|
-
|
|
3472
|
+
consola24.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
|
|
3388
3473
|
return false;
|
|
3389
3474
|
}
|
|
3390
3475
|
try {
|
|
3391
3476
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
3392
3477
|
if (existingGrantId) {
|
|
3393
|
-
|
|
3478
|
+
consola24.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
|
|
3394
3479
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
3395
3480
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
3396
3481
|
return true;
|
|
@@ -3398,7 +3483,7 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
3398
3483
|
} catch {
|
|
3399
3484
|
}
|
|
3400
3485
|
const approval = args.approval ?? "once";
|
|
3401
|
-
|
|
3486
|
+
consola24.info(`Requesting grant for: ${resolved.detail.display}`);
|
|
3402
3487
|
const grant = await createShapesGrant(resolved, {
|
|
3403
3488
|
idp,
|
|
3404
3489
|
approval,
|
|
@@ -3406,8 +3491,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
3406
3491
|
});
|
|
3407
3492
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
3408
3493
|
const n = grant.similar_grants.similar_grants.length;
|
|
3409
|
-
|
|
3410
|
-
|
|
3494
|
+
consola24.info("");
|
|
3495
|
+
consola24.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
3411
3496
|
}
|
|
3412
3497
|
notifyGrantPending({
|
|
3413
3498
|
grantId: grant.id,
|
|
@@ -3417,8 +3502,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
3417
3502
|
host: args.host || hostname3()
|
|
3418
3503
|
});
|
|
3419
3504
|
if (shouldWaitForGrant(args)) {
|
|
3420
|
-
|
|
3421
|
-
|
|
3505
|
+
consola24.info(`Grant requested: ${grant.id}`);
|
|
3506
|
+
consola24.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
3422
3507
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
3423
3508
|
if (status !== "approved")
|
|
3424
3509
|
throw new CliError(`Grant ${status}`);
|
|
@@ -3434,7 +3519,7 @@ function execShellCommand(command) {
|
|
|
3434
3519
|
throw new CliError("No command to execute");
|
|
3435
3520
|
try {
|
|
3436
3521
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
3437
|
-
|
|
3522
|
+
execFileSync6(command[0], command.slice(1), {
|
|
3438
3523
|
stdio: "inherit",
|
|
3439
3524
|
env: inheritedEnv
|
|
3440
3525
|
});
|
|
@@ -3492,7 +3577,7 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
3492
3577
|
try {
|
|
3493
3578
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
3494
3579
|
if (existingGrantId) {
|
|
3495
|
-
|
|
3580
|
+
consola24.info(`Reusing existing grant: ${existingGrantId}`);
|
|
3496
3581
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
3497
3582
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
3498
3583
|
return;
|
|
@@ -3506,17 +3591,17 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
3506
3591
|
});
|
|
3507
3592
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
3508
3593
|
const n = grant.similar_grants.similar_grants.length;
|
|
3509
|
-
|
|
3510
|
-
|
|
3594
|
+
consola24.info("");
|
|
3595
|
+
consola24.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
3511
3596
|
if (grant.similar_grants.widened_details?.length) {
|
|
3512
3597
|
const wider = grant.similar_grants.widened_details.map((d) => d.permission).join(", ");
|
|
3513
|
-
|
|
3598
|
+
consola24.info(` Broader scope: ${wider}`);
|
|
3514
3599
|
}
|
|
3515
|
-
|
|
3600
|
+
consola24.info("");
|
|
3516
3601
|
}
|
|
3517
3602
|
if (shouldWaitForGrant(args)) {
|
|
3518
|
-
|
|
3519
|
-
|
|
3603
|
+
consola24.info(`Grant requested: ${grant.id}`);
|
|
3604
|
+
consola24.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
3520
3605
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
3521
3606
|
if (status !== "approved")
|
|
3522
3607
|
throw new Error(`Grant ${status}`);
|
|
@@ -3536,7 +3621,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3536
3621
|
const grantsUrl = await getGrantsEndpoint(idp);
|
|
3537
3622
|
const command = action.split(" ");
|
|
3538
3623
|
const targetHost = args.host || hostname3();
|
|
3539
|
-
|
|
3624
|
+
consola24.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
|
|
3540
3625
|
const grant = await apiFetch(grantsUrl, {
|
|
3541
3626
|
method: "POST",
|
|
3542
3627
|
body: {
|
|
@@ -3553,9 +3638,9 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3553
3638
|
printPendingGrantInfo(grant, idp);
|
|
3554
3639
|
throw new CliExit(getAsyncExitCode());
|
|
3555
3640
|
}
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3641
|
+
consola24.success(`Grant requested: ${grant.id}`);
|
|
3642
|
+
consola24.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
3643
|
+
consola24.info("Waiting for approval...");
|
|
3559
3644
|
const maxWait = 15 * 60 * 1e3;
|
|
3560
3645
|
const interval = 3e3;
|
|
3561
3646
|
const start = Date.now();
|
|
@@ -3563,7 +3648,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3563
3648
|
while (Date.now() - start < maxWait) {
|
|
3564
3649
|
const status = await apiFetch(`${grantsUrl}/${grant.id}`);
|
|
3565
3650
|
if (status.status === "approved") {
|
|
3566
|
-
|
|
3651
|
+
consola24.success("Grant approved!");
|
|
3567
3652
|
approved = true;
|
|
3568
3653
|
break;
|
|
3569
3654
|
}
|
|
@@ -3578,15 +3663,15 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3578
3663
|
`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
3664
|
);
|
|
3580
3665
|
}
|
|
3581
|
-
|
|
3666
|
+
consola24.info("Fetching grant token...");
|
|
3582
3667
|
const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, {
|
|
3583
3668
|
method: "POST"
|
|
3584
3669
|
});
|
|
3585
3670
|
if (audience === "escapes") {
|
|
3586
|
-
|
|
3671
|
+
consola24.info(`Executing: ${command.join(" ")}`);
|
|
3587
3672
|
try {
|
|
3588
3673
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
3589
|
-
|
|
3674
|
+
execFileSync6(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
|
|
3590
3675
|
stdio: "inherit",
|
|
3591
3676
|
env: inheritedEnv
|
|
3592
3677
|
});
|
|
@@ -3601,8 +3686,8 @@ async function runAudienceMode(audience, action, args) {
|
|
|
3601
3686
|
|
|
3602
3687
|
// src/commands/proxy.ts
|
|
3603
3688
|
import { spawn as spawn2 } from "child_process";
|
|
3604
|
-
import { defineCommand as
|
|
3605
|
-
import
|
|
3689
|
+
import { defineCommand as defineCommand28 } from "citty";
|
|
3690
|
+
import consola25 from "consola";
|
|
3606
3691
|
|
|
3607
3692
|
// src/proxy/config.ts
|
|
3608
3693
|
function buildDefaultProxyConfigToml(opts) {
|
|
@@ -3745,10 +3830,10 @@ function resolveProxyConfigOptions() {
|
|
|
3745
3830
|
77
|
|
3746
3831
|
);
|
|
3747
3832
|
}
|
|
3748
|
-
|
|
3833
|
+
consola25.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
|
|
3749
3834
|
return { agentEmail: auth.email, idpUrl: auth.idp, mediated: true };
|
|
3750
3835
|
}
|
|
3751
|
-
var proxyCommand =
|
|
3836
|
+
var proxyCommand = defineCommand28({
|
|
3752
3837
|
meta: {
|
|
3753
3838
|
name: "proxy",
|
|
3754
3839
|
description: "Run a command with HTTPS_PROXY routed through the OpenApe egress proxy."
|
|
@@ -3770,12 +3855,12 @@ var proxyCommand = defineCommand27({
|
|
|
3770
3855
|
let close = null;
|
|
3771
3856
|
if (reuseUrl) {
|
|
3772
3857
|
proxyUrl = reuseUrl;
|
|
3773
|
-
|
|
3858
|
+
consola25.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
|
|
3774
3859
|
} else {
|
|
3775
3860
|
const ephemeral = await startEphemeralProxy(buildDefaultProxyConfigToml(resolveProxyConfigOptions()));
|
|
3776
3861
|
proxyUrl = ephemeral.url;
|
|
3777
3862
|
close = ephemeral.close;
|
|
3778
|
-
|
|
3863
|
+
consola25.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
|
|
3779
3864
|
}
|
|
3780
3865
|
const noProxy = process.env.NO_PROXY ?? process.env.no_proxy ?? "127.0.0.1,localhost";
|
|
3781
3866
|
const childEnv = {
|
|
@@ -3807,7 +3892,7 @@ var proxyCommand = defineCommand27({
|
|
|
3807
3892
|
else resolveExit(code ?? 0);
|
|
3808
3893
|
});
|
|
3809
3894
|
child.once("error", (err) => {
|
|
3810
|
-
|
|
3895
|
+
consola25.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
|
|
3811
3896
|
resolveExit(127);
|
|
3812
3897
|
});
|
|
3813
3898
|
});
|
|
@@ -3821,8 +3906,8 @@ function signalNumber(signal) {
|
|
|
3821
3906
|
}
|
|
3822
3907
|
|
|
3823
3908
|
// src/commands/explain.ts
|
|
3824
|
-
import { defineCommand as
|
|
3825
|
-
var explainCommand =
|
|
3909
|
+
import { defineCommand as defineCommand29 } from "citty";
|
|
3910
|
+
var explainCommand = defineCommand29({
|
|
3826
3911
|
meta: {
|
|
3827
3912
|
name: "explain",
|
|
3828
3913
|
description: "Show what permission a command would need"
|
|
@@ -3860,9 +3945,9 @@ var explainCommand = defineCommand28({
|
|
|
3860
3945
|
});
|
|
3861
3946
|
|
|
3862
3947
|
// src/commands/config/get.ts
|
|
3863
|
-
import { defineCommand as
|
|
3864
|
-
import
|
|
3865
|
-
var configGetCommand =
|
|
3948
|
+
import { defineCommand as defineCommand30 } from "citty";
|
|
3949
|
+
import consola26 from "consola";
|
|
3950
|
+
var configGetCommand = defineCommand30({
|
|
3866
3951
|
meta: {
|
|
3867
3952
|
name: "get",
|
|
3868
3953
|
description: "Get a configuration value"
|
|
@@ -3882,7 +3967,7 @@ var configGetCommand = defineCommand29({
|
|
|
3882
3967
|
if (idp)
|
|
3883
3968
|
console.log(idp);
|
|
3884
3969
|
else
|
|
3885
|
-
|
|
3970
|
+
consola26.info("No IdP configured.");
|
|
3886
3971
|
break;
|
|
3887
3972
|
}
|
|
3888
3973
|
case "email": {
|
|
@@ -3890,7 +3975,7 @@ var configGetCommand = defineCommand29({
|
|
|
3890
3975
|
if (auth?.email)
|
|
3891
3976
|
console.log(auth.email);
|
|
3892
3977
|
else
|
|
3893
|
-
|
|
3978
|
+
consola26.info("Not logged in.");
|
|
3894
3979
|
break;
|
|
3895
3980
|
}
|
|
3896
3981
|
default: {
|
|
@@ -3903,7 +3988,7 @@ var configGetCommand = defineCommand29({
|
|
|
3903
3988
|
if (sectionObj && field in sectionObj) {
|
|
3904
3989
|
console.log(sectionObj[field]);
|
|
3905
3990
|
} else {
|
|
3906
|
-
|
|
3991
|
+
consola26.info(`Key "${key}" not set.`);
|
|
3907
3992
|
}
|
|
3908
3993
|
} else {
|
|
3909
3994
|
throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
|
|
@@ -3914,9 +3999,9 @@ var configGetCommand = defineCommand29({
|
|
|
3914
3999
|
});
|
|
3915
4000
|
|
|
3916
4001
|
// src/commands/config/set.ts
|
|
3917
|
-
import { defineCommand as
|
|
3918
|
-
import
|
|
3919
|
-
var configSetCommand =
|
|
4002
|
+
import { defineCommand as defineCommand31 } from "citty";
|
|
4003
|
+
import consola27 from "consola";
|
|
4004
|
+
var configSetCommand = defineCommand31({
|
|
3920
4005
|
meta: {
|
|
3921
4006
|
name: "set",
|
|
3922
4007
|
description: "Set a configuration value"
|
|
@@ -3952,12 +4037,12 @@ var configSetCommand = defineCommand30({
|
|
|
3952
4037
|
throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
|
|
3953
4038
|
}
|
|
3954
4039
|
saveConfig(config);
|
|
3955
|
-
|
|
4040
|
+
consola27.success(`Set ${key} = ${value}`);
|
|
3956
4041
|
}
|
|
3957
4042
|
});
|
|
3958
4043
|
|
|
3959
4044
|
// src/commands/fetch/index.ts
|
|
3960
|
-
import { defineCommand as
|
|
4045
|
+
import { defineCommand as defineCommand32 } from "citty";
|
|
3961
4046
|
async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
3962
4047
|
const token = getAuthToken();
|
|
3963
4048
|
if (!token) {
|
|
@@ -3993,13 +4078,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
|
3993
4078
|
throw new CliError(`HTTP ${response.status} ${response.statusText}`);
|
|
3994
4079
|
}
|
|
3995
4080
|
}
|
|
3996
|
-
var fetchCommand =
|
|
4081
|
+
var fetchCommand = defineCommand32({
|
|
3997
4082
|
meta: {
|
|
3998
4083
|
name: "fetch",
|
|
3999
4084
|
description: "Make authenticated HTTP requests"
|
|
4000
4085
|
},
|
|
4001
4086
|
subCommands: {
|
|
4002
|
-
get:
|
|
4087
|
+
get: defineCommand32({
|
|
4003
4088
|
meta: {
|
|
4004
4089
|
name: "get",
|
|
4005
4090
|
description: "GET request with auth token"
|
|
@@ -4025,7 +4110,7 @@ var fetchCommand = defineCommand31({
|
|
|
4025
4110
|
await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
|
|
4026
4111
|
}
|
|
4027
4112
|
}),
|
|
4028
|
-
post:
|
|
4113
|
+
post: defineCommand32({
|
|
4029
4114
|
meta: {
|
|
4030
4115
|
name: "post",
|
|
4031
4116
|
description: "POST request with auth token"
|
|
@@ -4064,8 +4149,8 @@ var fetchCommand = defineCommand31({
|
|
|
4064
4149
|
});
|
|
4065
4150
|
|
|
4066
4151
|
// src/commands/mcp/index.ts
|
|
4067
|
-
import { defineCommand as
|
|
4068
|
-
var mcpCommand =
|
|
4152
|
+
import { defineCommand as defineCommand33 } from "citty";
|
|
4153
|
+
var mcpCommand = defineCommand33({
|
|
4069
4154
|
meta: {
|
|
4070
4155
|
name: "mcp",
|
|
4071
4156
|
description: "Start MCP server for AI agents"
|
|
@@ -4088,7 +4173,7 @@ var mcpCommand = defineCommand32({
|
|
|
4088
4173
|
if (transport !== "stdio" && transport !== "sse") {
|
|
4089
4174
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
4090
4175
|
}
|
|
4091
|
-
const { startMcpServer } = await import("./server-
|
|
4176
|
+
const { startMcpServer } = await import("./server-43TJLWMB.js");
|
|
4092
4177
|
await startMcpServer(transport, port);
|
|
4093
4178
|
}
|
|
4094
4179
|
});
|
|
@@ -4096,10 +4181,10 @@ var mcpCommand = defineCommand32({
|
|
|
4096
4181
|
// src/commands/init/index.ts
|
|
4097
4182
|
import { existsSync as existsSync7, copyFileSync, writeFileSync as writeFileSync5 } from "fs";
|
|
4098
4183
|
import { randomBytes } from "crypto";
|
|
4099
|
-
import { execFileSync as
|
|
4184
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
4100
4185
|
import { join as join6 } from "path";
|
|
4101
|
-
import { defineCommand as
|
|
4102
|
-
import
|
|
4186
|
+
import { defineCommand as defineCommand34 } from "citty";
|
|
4187
|
+
import consola28 from "consola";
|
|
4103
4188
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
4104
4189
|
async function downloadTemplate(repo, targetDir) {
|
|
4105
4190
|
const { downloadTemplate: gigetDownload } = await import("giget");
|
|
@@ -4108,28 +4193,28 @@ async function downloadTemplate(repo, targetDir) {
|
|
|
4108
4193
|
function installDeps(dir) {
|
|
4109
4194
|
const hasLockFile = (name) => existsSync7(join6(dir, name));
|
|
4110
4195
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
4111
|
-
|
|
4196
|
+
execFileSync7("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
4112
4197
|
} else if (hasLockFile("bun.lockb")) {
|
|
4113
|
-
|
|
4198
|
+
execFileSync7("bun", ["install"], { cwd: dir, stdio: "inherit" });
|
|
4114
4199
|
} else {
|
|
4115
|
-
|
|
4200
|
+
execFileSync7("npm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
4116
4201
|
}
|
|
4117
4202
|
}
|
|
4118
4203
|
async function promptChoice(message, choices) {
|
|
4119
|
-
const result = await
|
|
4204
|
+
const result = await consola28.prompt(message, { type: "select", options: choices });
|
|
4120
4205
|
if (typeof result === "symbol") {
|
|
4121
4206
|
throw new CliExit(0);
|
|
4122
4207
|
}
|
|
4123
4208
|
return result;
|
|
4124
4209
|
}
|
|
4125
4210
|
async function promptText(message, defaultValue) {
|
|
4126
|
-
const result = await
|
|
4211
|
+
const result = await consola28.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
|
|
4127
4212
|
if (typeof result === "symbol") {
|
|
4128
4213
|
throw new CliExit(0);
|
|
4129
4214
|
}
|
|
4130
4215
|
return result || defaultValue || "";
|
|
4131
4216
|
}
|
|
4132
|
-
var initCommand =
|
|
4217
|
+
var initCommand = defineCommand34({
|
|
4133
4218
|
meta: {
|
|
4134
4219
|
name: "init",
|
|
4135
4220
|
description: "Scaffold a new OpenApe project"
|
|
@@ -4174,20 +4259,20 @@ async function initSP(targetDir) {
|
|
|
4174
4259
|
if (existsSync7(join6(dir, "package.json"))) {
|
|
4175
4260
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
4176
4261
|
}
|
|
4177
|
-
|
|
4262
|
+
consola28.start("Scaffolding SP starter...");
|
|
4178
4263
|
await downloadTemplate("openape-ai/openape-sp-starter", dir);
|
|
4179
|
-
|
|
4180
|
-
|
|
4264
|
+
consola28.success("Scaffolded from openape-sp-starter");
|
|
4265
|
+
consola28.start("Installing dependencies...");
|
|
4181
4266
|
installDeps(dir);
|
|
4182
|
-
|
|
4267
|
+
consola28.success("Dependencies installed");
|
|
4183
4268
|
const envExample = join6(dir, ".env.example");
|
|
4184
4269
|
const envFile = join6(dir, ".env");
|
|
4185
4270
|
if (existsSync7(envExample) && !existsSync7(envFile)) {
|
|
4186
4271
|
copyFileSync(envExample, envFile);
|
|
4187
|
-
|
|
4272
|
+
consola28.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
4188
4273
|
}
|
|
4189
4274
|
console.log("");
|
|
4190
|
-
|
|
4275
|
+
consola28.box([
|
|
4191
4276
|
`cd ${dir}`,
|
|
4192
4277
|
"npm run dev",
|
|
4193
4278
|
"",
|
|
@@ -4206,15 +4291,15 @@ async function initIdP(targetDir) {
|
|
|
4206
4291
|
"s3 (S3-compatible)"
|
|
4207
4292
|
]);
|
|
4208
4293
|
const adminEmail = await promptText("Admin email");
|
|
4209
|
-
|
|
4294
|
+
consola28.start("Scaffolding IdP starter...");
|
|
4210
4295
|
await downloadTemplate("openape-ai/openape-idp-starter", dir);
|
|
4211
|
-
|
|
4212
|
-
|
|
4296
|
+
consola28.success("Scaffolded from openape-idp-starter");
|
|
4297
|
+
consola28.start("Installing dependencies...");
|
|
4213
4298
|
installDeps(dir);
|
|
4214
|
-
|
|
4299
|
+
consola28.success("Dependencies installed");
|
|
4215
4300
|
const sessionSecret = randomBytes(32).toString("hex");
|
|
4216
4301
|
const managementToken = randomBytes(32).toString("hex");
|
|
4217
|
-
|
|
4302
|
+
consola28.success("Secrets generated");
|
|
4218
4303
|
const isLocalhost = domain === "localhost";
|
|
4219
4304
|
const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
|
|
4220
4305
|
const envContent = [
|
|
@@ -4230,9 +4315,9 @@ async function initIdP(targetDir) {
|
|
|
4230
4315
|
].join("\n");
|
|
4231
4316
|
writeFileSync5(join6(dir, ".env"), `${envContent}
|
|
4232
4317
|
`, { mode: 384 });
|
|
4233
|
-
|
|
4318
|
+
consola28.success(".env created");
|
|
4234
4319
|
console.log("");
|
|
4235
|
-
|
|
4320
|
+
consola28.box([
|
|
4236
4321
|
`cd ${dir}`,
|
|
4237
4322
|
"npm run dev",
|
|
4238
4323
|
"",
|
|
@@ -4252,8 +4337,8 @@ import { Buffer as Buffer5 } from "buffer";
|
|
|
4252
4337
|
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
4253
4338
|
import { execFile as execFile2 } from "child_process";
|
|
4254
4339
|
import { sign as sign2 } from "crypto";
|
|
4255
|
-
import { defineCommand as
|
|
4256
|
-
import
|
|
4340
|
+
import { defineCommand as defineCommand35 } from "citty";
|
|
4341
|
+
import consola29 from "consola";
|
|
4257
4342
|
var DEFAULT_IDP_URL2 = "https://id.openape.at";
|
|
4258
4343
|
var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
|
|
4259
4344
|
var POLL_INTERVAL = 3e3;
|
|
@@ -4296,7 +4381,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
4296
4381
|
}
|
|
4297
4382
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
4298
4383
|
}
|
|
4299
|
-
var enrollCommand =
|
|
4384
|
+
var enrollCommand = defineCommand35({
|
|
4300
4385
|
meta: {
|
|
4301
4386
|
name: "enroll",
|
|
4302
4387
|
description: "Enroll an agent with an Identity Provider"
|
|
@@ -4316,18 +4401,18 @@ var enrollCommand = defineCommand34({
|
|
|
4316
4401
|
}
|
|
4317
4402
|
},
|
|
4318
4403
|
async run({ args }) {
|
|
4319
|
-
const idp = args.idp || await
|
|
4404
|
+
const idp = args.idp || await consola29.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
|
|
4320
4405
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
4321
4406
|
return r;
|
|
4322
4407
|
}) || DEFAULT_IDP_URL2;
|
|
4323
|
-
const agentName = args.name || await
|
|
4408
|
+
const agentName = args.name || await consola29.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
|
|
4324
4409
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
4325
4410
|
return r;
|
|
4326
4411
|
});
|
|
4327
4412
|
if (!agentName) {
|
|
4328
4413
|
throw new CliError("Agent name is required.");
|
|
4329
4414
|
}
|
|
4330
|
-
const keyPath = args.key || await
|
|
4415
|
+
const keyPath = args.key || await consola29.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
|
|
4331
4416
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
4332
4417
|
return r;
|
|
4333
4418
|
}) || DEFAULT_KEY_PATH;
|
|
@@ -4335,19 +4420,19 @@ var enrollCommand = defineCommand34({
|
|
|
4335
4420
|
let publicKey;
|
|
4336
4421
|
if (existsSync8(resolvedKey)) {
|
|
4337
4422
|
publicKey = readPublicKey(resolvedKey);
|
|
4338
|
-
|
|
4423
|
+
consola29.success(`Using existing key ${keyPath}`);
|
|
4339
4424
|
} else {
|
|
4340
|
-
|
|
4425
|
+
consola29.start(`Generating Ed25519 key pair at ${keyPath}...`);
|
|
4341
4426
|
publicKey = generateAndSaveKey(keyPath);
|
|
4342
|
-
|
|
4427
|
+
consola29.success(`Key pair generated at ${keyPath}`);
|
|
4343
4428
|
}
|
|
4344
4429
|
const encodedKey = encodeURIComponent(publicKey);
|
|
4345
4430
|
const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
|
|
4346
|
-
|
|
4347
|
-
|
|
4431
|
+
consola29.info("Opening browser for enrollment...");
|
|
4432
|
+
consola29.info(`\u2192 ${idp}/enroll`);
|
|
4348
4433
|
openBrowser2(enrollUrl);
|
|
4349
4434
|
console.log("");
|
|
4350
|
-
const agentEmail = await
|
|
4435
|
+
const agentEmail = await consola29.prompt(
|
|
4351
4436
|
"Agent email (shown in browser after enrollment)",
|
|
4352
4437
|
{ type: "text", placeholder: `agent+${agentName}@...` }
|
|
4353
4438
|
).then((r) => {
|
|
@@ -4357,7 +4442,7 @@ var enrollCommand = defineCommand34({
|
|
|
4357
4442
|
if (!agentEmail) {
|
|
4358
4443
|
throw new CliError("Agent email is required to verify enrollment.");
|
|
4359
4444
|
}
|
|
4360
|
-
|
|
4445
|
+
consola29.start("Verifying enrollment...");
|
|
4361
4446
|
const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
|
|
4362
4447
|
saveAuth({
|
|
4363
4448
|
idp,
|
|
@@ -4369,18 +4454,18 @@ var enrollCommand = defineCommand34({
|
|
|
4369
4454
|
config.defaults = { ...config.defaults, idp };
|
|
4370
4455
|
config.agent = { key: keyPath, email: agentEmail };
|
|
4371
4456
|
saveConfig(config);
|
|
4372
|
-
|
|
4373
|
-
|
|
4457
|
+
consola29.success(`Agent enrolled as ${agentEmail}`);
|
|
4458
|
+
consola29.success("Config saved to ~/.config/apes/");
|
|
4374
4459
|
console.log("");
|
|
4375
|
-
|
|
4460
|
+
consola29.info("Verify with: apes whoami");
|
|
4376
4461
|
}
|
|
4377
4462
|
});
|
|
4378
4463
|
|
|
4379
4464
|
// src/commands/register-user.ts
|
|
4380
4465
|
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
4381
|
-
import { defineCommand as
|
|
4382
|
-
import
|
|
4383
|
-
var registerUserCommand =
|
|
4466
|
+
import { defineCommand as defineCommand36 } from "citty";
|
|
4467
|
+
import consola30 from "consola";
|
|
4468
|
+
var registerUserCommand = defineCommand36({
|
|
4384
4469
|
meta: {
|
|
4385
4470
|
name: "register-user",
|
|
4386
4471
|
description: "Register a sub-user with SSH key"
|
|
@@ -4435,18 +4520,18 @@ var registerUserCommand = defineCommand35({
|
|
|
4435
4520
|
...userType ? { type: userType } : {}
|
|
4436
4521
|
}
|
|
4437
4522
|
});
|
|
4438
|
-
|
|
4523
|
+
consola30.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
|
|
4439
4524
|
}
|
|
4440
4525
|
});
|
|
4441
4526
|
|
|
4442
4527
|
// src/commands/utils/index.ts
|
|
4443
|
-
import { defineCommand as
|
|
4528
|
+
import { defineCommand as defineCommand38 } from "citty";
|
|
4444
4529
|
|
|
4445
4530
|
// src/commands/utils/dig.ts
|
|
4446
|
-
import { defineCommand as
|
|
4447
|
-
import
|
|
4531
|
+
import { defineCommand as defineCommand37 } from "citty";
|
|
4532
|
+
import consola31 from "consola";
|
|
4448
4533
|
import { resolveDDISA as resolveDDISA2 } from "@openape/core";
|
|
4449
|
-
var digCommand =
|
|
4534
|
+
var digCommand = defineCommand37({
|
|
4450
4535
|
meta: {
|
|
4451
4536
|
name: "dig",
|
|
4452
4537
|
description: "Resolve DDISA IdP for a domain or email (admin/diag tool)"
|
|
@@ -4519,12 +4604,12 @@ var digCommand = defineCommand36({
|
|
|
4519
4604
|
console.log(` domain: ${domain}`);
|
|
4520
4605
|
console.log("");
|
|
4521
4606
|
if (!result.ddisa.found) {
|
|
4522
|
-
|
|
4607
|
+
consola31.warn(`No DDISA record at _ddisa.${domain}`);
|
|
4523
4608
|
if (result.hint) console.log(`
|
|
4524
4609
|
${result.hint}`);
|
|
4525
4610
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
4526
4611
|
}
|
|
4527
|
-
|
|
4612
|
+
consola31.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
|
|
4528
4613
|
console.log(` Version: ${result.ddisa.version || "ddisa1"}`);
|
|
4529
4614
|
console.log(` IdP URL: ${result.ddisa.idp}`);
|
|
4530
4615
|
if (result.ddisa.mode) console.log(` Mode: ${result.ddisa.mode}`);
|
|
@@ -4534,13 +4619,13 @@ ${result.hint}`);
|
|
|
4534
4619
|
return;
|
|
4535
4620
|
}
|
|
4536
4621
|
if (result.idpDiscovery.ok) {
|
|
4537
|
-
|
|
4622
|
+
consola31.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
|
|
4538
4623
|
if (result.idpDiscovery.issuer) console.log(` Issuer: ${result.idpDiscovery.issuer}`);
|
|
4539
4624
|
if (result.idpDiscovery.ddisaVersion) console.log(` DDISA: v${result.idpDiscovery.ddisaVersion}`);
|
|
4540
4625
|
if (result.idpDiscovery.authMethods?.length) console.log(` Auth: ${result.idpDiscovery.authMethods.join(", ")}`);
|
|
4541
4626
|
if (result.idpDiscovery.grantTypes?.length) console.log(` Grants: ${result.idpDiscovery.grantTypes.join(", ")}`);
|
|
4542
4627
|
} else {
|
|
4543
|
-
|
|
4628
|
+
consola31.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
|
|
4544
4629
|
if (result.hint) console.log(`
|
|
4545
4630
|
${result.hint}`);
|
|
4546
4631
|
throw new CliError(`IdP at ${result.ddisa.idp} not reachable`);
|
|
@@ -4549,7 +4634,7 @@ ${result.hint}`);
|
|
|
4549
4634
|
});
|
|
4550
4635
|
|
|
4551
4636
|
// src/commands/utils/index.ts
|
|
4552
|
-
var utilsCommand =
|
|
4637
|
+
var utilsCommand = defineCommand38({
|
|
4553
4638
|
meta: {
|
|
4554
4639
|
name: "utils",
|
|
4555
4640
|
description: "Admin/diagnostic utilities (dig, \u2026)"
|
|
@@ -4560,12 +4645,12 @@ var utilsCommand = defineCommand37({
|
|
|
4560
4645
|
});
|
|
4561
4646
|
|
|
4562
4647
|
// src/commands/sessions/index.ts
|
|
4563
|
-
import { defineCommand as
|
|
4648
|
+
import { defineCommand as defineCommand41 } from "citty";
|
|
4564
4649
|
|
|
4565
4650
|
// src/commands/sessions/list.ts
|
|
4566
|
-
import { defineCommand as
|
|
4567
|
-
import
|
|
4568
|
-
var sessionsListCommand =
|
|
4651
|
+
import { defineCommand as defineCommand39 } from "citty";
|
|
4652
|
+
import consola32 from "consola";
|
|
4653
|
+
var sessionsListCommand = defineCommand39({
|
|
4569
4654
|
meta: {
|
|
4570
4655
|
name: "list",
|
|
4571
4656
|
description: "List your active refresh-token families (one per logged-in device)."
|
|
@@ -4583,7 +4668,7 @@ var sessionsListCommand = defineCommand38({
|
|
|
4583
4668
|
return;
|
|
4584
4669
|
}
|
|
4585
4670
|
if (result.data.length === 0) {
|
|
4586
|
-
|
|
4671
|
+
consola32.info("No active sessions.");
|
|
4587
4672
|
return;
|
|
4588
4673
|
}
|
|
4589
4674
|
for (const f of result.data) {
|
|
@@ -4595,9 +4680,9 @@ var sessionsListCommand = defineCommand38({
|
|
|
4595
4680
|
});
|
|
4596
4681
|
|
|
4597
4682
|
// src/commands/sessions/remove.ts
|
|
4598
|
-
import { defineCommand as
|
|
4599
|
-
import
|
|
4600
|
-
var sessionsRemoveCommand =
|
|
4683
|
+
import { defineCommand as defineCommand40 } from "citty";
|
|
4684
|
+
import consola33 from "consola";
|
|
4685
|
+
var sessionsRemoveCommand = defineCommand40({
|
|
4601
4686
|
meta: {
|
|
4602
4687
|
name: "remove",
|
|
4603
4688
|
description: "Revoke one of your active refresh-token families by id."
|
|
@@ -4613,12 +4698,12 @@ var sessionsRemoveCommand = defineCommand39({
|
|
|
4613
4698
|
const id = String(args.familyId).trim();
|
|
4614
4699
|
if (!id) throw new CliError("familyId required");
|
|
4615
4700
|
await apiFetch(`/api/me/sessions/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
4616
|
-
|
|
4701
|
+
consola33.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
|
|
4617
4702
|
}
|
|
4618
4703
|
});
|
|
4619
4704
|
|
|
4620
4705
|
// src/commands/sessions/index.ts
|
|
4621
|
-
var sessionsCommand =
|
|
4706
|
+
var sessionsCommand = defineCommand41({
|
|
4622
4707
|
meta: {
|
|
4623
4708
|
name: "sessions",
|
|
4624
4709
|
description: "Manage your active refresh-token sessions across devices"
|
|
@@ -4630,10 +4715,10 @@ var sessionsCommand = defineCommand40({
|
|
|
4630
4715
|
});
|
|
4631
4716
|
|
|
4632
4717
|
// src/commands/dns-check.ts
|
|
4633
|
-
import { defineCommand as
|
|
4634
|
-
import
|
|
4718
|
+
import { defineCommand as defineCommand42 } from "citty";
|
|
4719
|
+
import consola34 from "consola";
|
|
4635
4720
|
import { resolveDDISA as resolveDDISA3 } from "@openape/core";
|
|
4636
|
-
var dnsCheckCommand =
|
|
4721
|
+
var dnsCheckCommand = defineCommand42({
|
|
4637
4722
|
meta: {
|
|
4638
4723
|
name: "dns-check",
|
|
4639
4724
|
description: "Validate DDISA DNS TXT records for a domain"
|
|
@@ -4647,7 +4732,7 @@ var dnsCheckCommand = defineCommand41({
|
|
|
4647
4732
|
},
|
|
4648
4733
|
async run({ args }) {
|
|
4649
4734
|
const domain = args.domain;
|
|
4650
|
-
|
|
4735
|
+
consola34.start(`Checking _ddisa.${domain}...`);
|
|
4651
4736
|
try {
|
|
4652
4737
|
const result = await resolveDDISA3(domain);
|
|
4653
4738
|
if (!result) {
|
|
@@ -4656,7 +4741,7 @@ var dnsCheckCommand = defineCommand41({
|
|
|
4656
4741
|
console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
|
|
4657
4742
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
4658
4743
|
}
|
|
4659
|
-
|
|
4744
|
+
consola34.success(`_ddisa.${domain} \u2192 ${result.idp}`);
|
|
4660
4745
|
console.log("");
|
|
4661
4746
|
console.log(` Version: ${result.version || "ddisa1"}`);
|
|
4662
4747
|
console.log(` IdP URL: ${result.idp}`);
|
|
@@ -4665,14 +4750,14 @@ var dnsCheckCommand = defineCommand41({
|
|
|
4665
4750
|
if (result.priority !== void 0)
|
|
4666
4751
|
console.log(` Priority: ${result.priority}`);
|
|
4667
4752
|
console.log("");
|
|
4668
|
-
|
|
4753
|
+
consola34.start(`Verifying IdP at ${result.idp}...`);
|
|
4669
4754
|
const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
|
|
4670
4755
|
if (!discoResp.ok) {
|
|
4671
|
-
|
|
4756
|
+
consola34.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
|
|
4672
4757
|
return;
|
|
4673
4758
|
}
|
|
4674
4759
|
const disco = await discoResp.json();
|
|
4675
|
-
|
|
4760
|
+
consola34.success(`IdP is reachable`);
|
|
4676
4761
|
console.log(` Issuer: ${disco.issuer}`);
|
|
4677
4762
|
console.log(` DDISA: v${disco.ddisa_version || "?"}`);
|
|
4678
4763
|
if (disco.ddisa_auth_methods_supported) {
|
|
@@ -4690,7 +4775,7 @@ var dnsCheckCommand = defineCommand41({
|
|
|
4690
4775
|
// src/commands/health.ts
|
|
4691
4776
|
import { exec } from "child_process";
|
|
4692
4777
|
import { promisify } from "util";
|
|
4693
|
-
import { defineCommand as
|
|
4778
|
+
import { defineCommand as defineCommand43 } from "citty";
|
|
4694
4779
|
var execAsync = promisify(exec);
|
|
4695
4780
|
async function resolveApeShellPath() {
|
|
4696
4781
|
try {
|
|
@@ -4726,7 +4811,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
4726
4811
|
}
|
|
4727
4812
|
}
|
|
4728
4813
|
async function runHealth(args) {
|
|
4729
|
-
const version = true ? "0.
|
|
4814
|
+
const version = true ? "0.30.0" : "0.0.0";
|
|
4730
4815
|
const auth = loadAuth();
|
|
4731
4816
|
if (!auth) {
|
|
4732
4817
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -4789,7 +4874,7 @@ async function runHealth(args) {
|
|
|
4789
4874
|
throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
|
|
4790
4875
|
}
|
|
4791
4876
|
}
|
|
4792
|
-
var healthCommand =
|
|
4877
|
+
var healthCommand = defineCommand43({
|
|
4793
4878
|
meta: {
|
|
4794
4879
|
name: "health",
|
|
4795
4880
|
description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
|
|
@@ -4807,8 +4892,8 @@ var healthCommand = defineCommand42({
|
|
|
4807
4892
|
});
|
|
4808
4893
|
|
|
4809
4894
|
// src/commands/workflows.ts
|
|
4810
|
-
import { defineCommand as
|
|
4811
|
-
import
|
|
4895
|
+
import { defineCommand as defineCommand44 } from "citty";
|
|
4896
|
+
import consola35 from "consola";
|
|
4812
4897
|
|
|
4813
4898
|
// src/guides/index.ts
|
|
4814
4899
|
var guides = [
|
|
@@ -4858,7 +4943,7 @@ var guides = [
|
|
|
4858
4943
|
];
|
|
4859
4944
|
|
|
4860
4945
|
// src/commands/workflows.ts
|
|
4861
|
-
var workflowsCommand =
|
|
4946
|
+
var workflowsCommand = defineCommand44({
|
|
4862
4947
|
meta: {
|
|
4863
4948
|
name: "workflows",
|
|
4864
4949
|
description: "Discover workflow guides"
|
|
@@ -4879,7 +4964,7 @@ var workflowsCommand = defineCommand43({
|
|
|
4879
4964
|
if (args.id) {
|
|
4880
4965
|
const guide = guides.find((g) => g.id === String(args.id));
|
|
4881
4966
|
if (!guide) {
|
|
4882
|
-
|
|
4967
|
+
consola35.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
|
|
4883
4968
|
throw new CliError(`Guide not found: ${args.id}`);
|
|
4884
4969
|
}
|
|
4885
4970
|
if (args.json) {
|
|
@@ -4922,7 +5007,7 @@ var workflowsCommand = defineCommand43({
|
|
|
4922
5007
|
import { existsSync as existsSync10, mkdirSync as mkdirSync2, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
4923
5008
|
import { homedir as homedir6 } from "os";
|
|
4924
5009
|
import { join as join7 } from "path";
|
|
4925
|
-
import
|
|
5010
|
+
import consola36 from "consola";
|
|
4926
5011
|
var PACKAGE_NAME = "@openape/apes";
|
|
4927
5012
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
4928
5013
|
var CACHE_FILE = join7(homedir6(), ".config", "apes", ".version-check.json");
|
|
@@ -4967,7 +5052,7 @@ async function fetchLatestVersion() {
|
|
|
4967
5052
|
}
|
|
4968
5053
|
function warnIfBehind(currentVersion, latest) {
|
|
4969
5054
|
if (compareSemver(currentVersion, latest) < 0) {
|
|
4970
|
-
|
|
5055
|
+
consola36.warn(
|
|
4971
5056
|
`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
5057
|
);
|
|
4973
5058
|
}
|
|
@@ -4999,10 +5084,10 @@ if (shellRewrite) {
|
|
|
4999
5084
|
if (shellRewrite.action === "rewrite") {
|
|
5000
5085
|
process.argv = shellRewrite.argv;
|
|
5001
5086
|
} else if (shellRewrite.action === "version") {
|
|
5002
|
-
console.log(`ape-shell ${"0.
|
|
5087
|
+
console.log(`ape-shell ${"0.30.0"} (OpenApe DDISA shell wrapper)`);
|
|
5003
5088
|
process.exit(0);
|
|
5004
5089
|
} else if (shellRewrite.action === "help") {
|
|
5005
|
-
console.log(`ape-shell ${"0.
|
|
5090
|
+
console.log(`ape-shell ${"0.30.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
5006
5091
|
console.log("");
|
|
5007
5092
|
console.log("Usage:");
|
|
5008
5093
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -5026,7 +5111,7 @@ if (shellRewrite) {
|
|
|
5026
5111
|
}
|
|
5027
5112
|
}
|
|
5028
5113
|
var debug = process.argv.includes("--debug");
|
|
5029
|
-
var grantsCommand =
|
|
5114
|
+
var grantsCommand = defineCommand45({
|
|
5030
5115
|
meta: {
|
|
5031
5116
|
name: "grants",
|
|
5032
5117
|
description: "Grant management"
|
|
@@ -5047,7 +5132,7 @@ var grantsCommand = defineCommand44({
|
|
|
5047
5132
|
"delegation-revoke": delegationRevokeCommand
|
|
5048
5133
|
}
|
|
5049
5134
|
});
|
|
5050
|
-
var configCommand =
|
|
5135
|
+
var configCommand = defineCommand45({
|
|
5051
5136
|
meta: {
|
|
5052
5137
|
name: "config",
|
|
5053
5138
|
description: "Configuration management"
|
|
@@ -5057,10 +5142,10 @@ var configCommand = defineCommand44({
|
|
|
5057
5142
|
set: configSetCommand
|
|
5058
5143
|
}
|
|
5059
5144
|
});
|
|
5060
|
-
var main =
|
|
5145
|
+
var main = defineCommand45({
|
|
5061
5146
|
meta: {
|
|
5062
5147
|
name: "apes",
|
|
5063
|
-
version: "0.
|
|
5148
|
+
version: "0.30.0",
|
|
5064
5149
|
description: "Unified CLI for OpenApe"
|
|
5065
5150
|
},
|
|
5066
5151
|
subCommands: {
|
|
@@ -5115,20 +5200,20 @@ async function maybeRefreshAuth() {
|
|
|
5115
5200
|
}
|
|
5116
5201
|
}
|
|
5117
5202
|
await maybeRefreshAuth();
|
|
5118
|
-
await maybeWarnStaleVersion("0.
|
|
5203
|
+
await maybeWarnStaleVersion("0.30.0").catch(() => {
|
|
5119
5204
|
});
|
|
5120
5205
|
runMain(main).catch((err) => {
|
|
5121
5206
|
if (err instanceof CliExit) {
|
|
5122
5207
|
process.exit(err.exitCode);
|
|
5123
5208
|
}
|
|
5124
5209
|
if (err instanceof CliError) {
|
|
5125
|
-
|
|
5210
|
+
consola37.error(err.message);
|
|
5126
5211
|
process.exit(err.exitCode);
|
|
5127
5212
|
}
|
|
5128
5213
|
if (debug) {
|
|
5129
|
-
|
|
5214
|
+
consola37.error(err);
|
|
5130
5215
|
} else {
|
|
5131
|
-
|
|
5216
|
+
consola37.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
|
|
5132
5217
|
}
|
|
5133
5218
|
process.exit(1);
|
|
5134
5219
|
});
|