@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 consola36 from "consola";
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 defineCommand44, runMain } from "citty";
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 defineCommand24 } from "citty";
1746
+ import { defineCommand as defineCommand25 } from "citty";
1747
1747
 
1748
- // src/commands/agents/destroy.ts
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 = defineCommand20({
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
- consola18.info(`Nothing to destroy: no IdP agent and no OS user named "${name}".`);
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
- consola18.warn(`About to destroy "${name}":
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 consola18.prompt("Proceed?", { type: "confirm", initial: false });
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
- consola18.success(`Deactivated IdP agent ${idpAgent.email}`);
2300
+ consola19.success(`Deactivated IdP agent ${idpAgent.email}`);
2226
2301
  } else {
2227
2302
  await apiFetch(`/api/my-agents/${id}`, { method: "DELETE", idp });
2228
- consola18.success(`Deleted IdP agent ${idpAgent.email}`);
2303
+ consola19.success(`Deleted IdP agent ${idpAgent.email}`);
2229
2304
  }
2230
2305
  } else {
2231
- consola18.info("No IdP agent to remove (skipped).");
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
- consola18.start("Running teardown via sudo\u2026");
2246
- execFileSync3(sudo, ["-S", "--prompt=", "--", "bash", scriptPath], {
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
- consola18.info("No macOS user to remove (skipped).");
2331
+ consola19.info("No macOS user to remove (skipped).");
2257
2332
  }
2258
- consola18.success(`Destroyed ${name}.`);
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 defineCommand21 } from "citty";
2273
- import consola19 from "consola";
2274
- var listAgentsCommand = defineCommand21({
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
- consola19.info(args["include-inactive"] ? "No agents found." : "No active agents found. Use --include-inactive to show deactivated.");
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 defineCommand22 } from "citty";
2335
- import consola20 from "consola";
2336
- var registerAgentCommand = defineCommand22({
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
- consola20.success("Agent registered.");
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 execFileSync4 } from "child_process";
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 defineCommand23 } from "citty";
2424
- import consola21 from "consola";
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 = defineCommand23({
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
- consola21.start(`Generating keypair for ${name}\u2026`);
2803
+ consola22.start(`Generating keypair for ${name}\u2026`);
2729
2804
  const { privatePem, publicSshLine } = generateKeyPairInMemory();
2730
- consola21.start(`Registering agent at ${idp}\u2026`);
2805
+ consola22.start(`Registering agent at ${idp}\u2026`);
2731
2806
  const registration = await registerAgentAtIdp({ name, publicKey: publicSshLine, idp });
2732
- consola21.success(`Registered as ${registration.email}`);
2733
- consola21.start("Issuing agent access token\u2026");
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
- consola21.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
2778
- consola21.info("You will be asked to approve the as=root grant in your DDISA inbox; this command blocks until you do.");
2779
- execFileSync4(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], { stdio: "inherit" });
2780
- consola21.success(`Agent ${name} spawned.`);
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
- consola21.info(`On first boot, the bridge will send you a contact request from ${registration.email}.`);
2783
- consola21.info("Open chat.openape.ai and accept it to start chatting with the agent.");
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 = defineCommand24({
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 defineCommand25 } from "citty";
2832
- import consola22 from "consola";
2833
- var adapterCommand = defineCommand25({
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: defineCommand25({
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
- consola22.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
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
- consola22.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
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: defineCommand25({
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
- consola22.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
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
- consola22.warn(`Conflicting adapter found: ${c.path} (id: ${c.adapterId}, executable: ${c.executable})`);
2936
- consola22.warn(` Remove it with: apes adapter remove ${c.adapterId}`);
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
- consola22.success(`${verb} ${result.id} \u2192 ${result.path}`);
2942
- consola22.info(`Digest: ${result.digest}`);
3017
+ consola23.success(`${verb} ${result.id} \u2192 ${result.path}`);
3018
+ consola23.info(`Digest: ${result.digest}`);
2943
3019
  }
2944
3020
  }
2945
3021
  }),
2946
- remove: defineCommand25({
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
- consola22.success(`Removed adapter: ${id}`);
3045
+ consola23.success(`Removed adapter: ${id}`);
2970
3046
  } else {
2971
- consola22.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
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: defineCommand25({
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: defineCommand25({
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
- consola22.info(`No adapters matching "${query}"`);
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: defineCommand25({
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
- consola22.info("No adapters installed to update.");
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
- consola22.warn(`${id}: not found in registry, skipping`);
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
- consola22.info(`${id}: already up to date`);
3175
+ consola23.info(`${id}: already up to date`);
3100
3176
  continue;
3101
3177
  }
3102
3178
  if (localDigest && !args.yes) {
3103
- consola22.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
3104
- consola22.info(` Old: ${localDigest}`);
3105
- consola22.info(` New: ${entry.digest}`);
3106
- consola22.info(" Use --yes to confirm");
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
- consola22.success(`Updated ${result.id} \u2192 ${result.path}`);
3186
+ consola23.success(`Updated ${result.id} \u2192 ${result.path}`);
3111
3187
  }
3112
3188
  }
3113
3189
  }),
3114
- verify: defineCommand25({
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
- consola22.success(`${id}: digest matches registry`);
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 execFileSync5 } from "child_process";
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 defineCommand26 } from "citty";
3163
- import consola23 from "consola";
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
- consola23.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
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
- consola23.success(`Grant ${grant.id} created (pending approval)`);
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 = defineCommand26({
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
- consola23.info(`Requesting ape-shell session grant on ${targetHost}`);
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
- consola23.info(`Grant requested: ${grant.id}`);
3356
- consola23.info("Waiting for approval...");
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
- consola23.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
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
- consola23.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
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
- consola23.info(`Requesting grant for: ${resolved.detail.display}`);
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
- consola23.info("");
3410
- consola23.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
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
- consola23.info(`Grant requested: ${grant.id}`);
3421
- consola23.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
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
- execFileSync5(command[0], command.slice(1), {
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
- consola23.info(`Reusing existing grant: ${existingGrantId}`);
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
- consola23.info("");
3510
- consola23.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
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
- consola23.info(` Broader scope: ${wider}`);
3589
+ consola24.info(` Broader scope: ${wider}`);
3514
3590
  }
3515
- consola23.info("");
3591
+ consola24.info("");
3516
3592
  }
3517
3593
  if (shouldWaitForGrant(args)) {
3518
- consola23.info(`Grant requested: ${grant.id}`);
3519
- consola23.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
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
- consola23.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
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
- consola23.success(`Grant requested: ${grant.id}`);
3557
- consola23.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
3558
- consola23.info("Waiting for approval...");
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
- consola23.success("Grant approved!");
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
- consola23.info("Fetching grant token...");
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
- consola23.info(`Executing: ${command.join(" ")}`);
3662
+ consola24.info(`Executing: ${command.join(" ")}`);
3587
3663
  try {
3588
3664
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
3589
- execFileSync5(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
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 defineCommand27 } from "citty";
3605
- import consola24 from "consola";
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
- consola24.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
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 = defineCommand27({
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
- consola24.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
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
- consola24.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
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
- consola24.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
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 defineCommand28 } from "citty";
3825
- var explainCommand = defineCommand28({
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 defineCommand29 } from "citty";
3864
- import consola25 from "consola";
3865
- var configGetCommand = defineCommand29({
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
- consola25.info("No IdP configured.");
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
- consola25.info("Not logged in.");
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
- consola25.info(`Key "${key}" not set.`);
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 defineCommand30 } from "citty";
3918
- import consola26 from "consola";
3919
- var configSetCommand = defineCommand30({
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
- consola26.success(`Set ${key} = ${value}`);
4031
+ consola27.success(`Set ${key} = ${value}`);
3956
4032
  }
3957
4033
  });
3958
4034
 
3959
4035
  // src/commands/fetch/index.ts
3960
- import { defineCommand as defineCommand31 } from "citty";
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 = defineCommand31({
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: defineCommand31({
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: defineCommand31({
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 defineCommand32 } from "citty";
4068
- var mcpCommand = defineCommand32({
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-GWZM6VS3.js");
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 execFileSync6 } from "child_process";
4175
+ import { execFileSync as execFileSync7 } from "child_process";
4100
4176
  import { join as join6 } from "path";
4101
- import { defineCommand as defineCommand33 } from "citty";
4102
- import consola27 from "consola";
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
- execFileSync6("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
4187
+ execFileSync7("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
4112
4188
  } else if (hasLockFile("bun.lockb")) {
4113
- execFileSync6("bun", ["install"], { cwd: dir, stdio: "inherit" });
4189
+ execFileSync7("bun", ["install"], { cwd: dir, stdio: "inherit" });
4114
4190
  } else {
4115
- execFileSync6("npm", ["install"], { cwd: dir, stdio: "inherit" });
4191
+ execFileSync7("npm", ["install"], { cwd: dir, stdio: "inherit" });
4116
4192
  }
4117
4193
  }
4118
4194
  async function promptChoice(message, choices) {
4119
- const result = await consola27.prompt(message, { type: "select", options: choices });
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 consola27.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
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 = defineCommand33({
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
- consola27.start("Scaffolding SP starter...");
4253
+ consola28.start("Scaffolding SP starter...");
4178
4254
  await downloadTemplate("openape-ai/openape-sp-starter", dir);
4179
- consola27.success("Scaffolded from openape-sp-starter");
4180
- consola27.start("Installing dependencies...");
4255
+ consola28.success("Scaffolded from openape-sp-starter");
4256
+ consola28.start("Installing dependencies...");
4181
4257
  installDeps(dir);
4182
- consola27.success("Dependencies installed");
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
- consola27.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
4263
+ consola28.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
4188
4264
  }
4189
4265
  console.log("");
4190
- consola27.box([
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
- consola27.start("Scaffolding IdP starter...");
4285
+ consola28.start("Scaffolding IdP starter...");
4210
4286
  await downloadTemplate("openape-ai/openape-idp-starter", dir);
4211
- consola27.success("Scaffolded from openape-idp-starter");
4212
- consola27.start("Installing dependencies...");
4287
+ consola28.success("Scaffolded from openape-idp-starter");
4288
+ consola28.start("Installing dependencies...");
4213
4289
  installDeps(dir);
4214
- consola27.success("Dependencies installed");
4290
+ consola28.success("Dependencies installed");
4215
4291
  const sessionSecret = randomBytes(32).toString("hex");
4216
4292
  const managementToken = randomBytes(32).toString("hex");
4217
- consola27.success("Secrets generated");
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
- consola27.success(".env created");
4309
+ consola28.success(".env created");
4234
4310
  console.log("");
4235
- consola27.box([
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 defineCommand34 } from "citty";
4256
- import consola28 from "consola";
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 = defineCommand34({
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 consola28.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
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 consola28.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
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 consola28.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
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
- consola28.success(`Using existing key ${keyPath}`);
4414
+ consola29.success(`Using existing key ${keyPath}`);
4339
4415
  } else {
4340
- consola28.start(`Generating Ed25519 key pair at ${keyPath}...`);
4416
+ consola29.start(`Generating Ed25519 key pair at ${keyPath}...`);
4341
4417
  publicKey = generateAndSaveKey(keyPath);
4342
- consola28.success(`Key pair generated at ${keyPath}`);
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
- consola28.info("Opening browser for enrollment...");
4347
- consola28.info(`\u2192 ${idp}/enroll`);
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 consola28.prompt(
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
- consola28.start("Verifying enrollment...");
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
- consola28.success(`Agent enrolled as ${agentEmail}`);
4373
- consola28.success("Config saved to ~/.config/apes/");
4448
+ consola29.success(`Agent enrolled as ${agentEmail}`);
4449
+ consola29.success("Config saved to ~/.config/apes/");
4374
4450
  console.log("");
4375
- consola28.info("Verify with: apes whoami");
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 defineCommand35 } from "citty";
4382
- import consola29 from "consola";
4383
- var registerUserCommand = defineCommand35({
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
- consola29.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
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 defineCommand37 } from "citty";
4519
+ import { defineCommand as defineCommand38 } from "citty";
4444
4520
 
4445
4521
  // src/commands/utils/dig.ts
4446
- import { defineCommand as defineCommand36 } from "citty";
4447
- import consola30 from "consola";
4522
+ import { defineCommand as defineCommand37 } from "citty";
4523
+ import consola31 from "consola";
4448
4524
  import { resolveDDISA as resolveDDISA2 } from "@openape/core";
4449
- var digCommand = defineCommand36({
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
- consola30.warn(`No DDISA record at _ddisa.${domain}`);
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
- consola30.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
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
- consola30.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
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
- consola30.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
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 = defineCommand37({
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 defineCommand40 } from "citty";
4639
+ import { defineCommand as defineCommand41 } from "citty";
4564
4640
 
4565
4641
  // src/commands/sessions/list.ts
4566
- import { defineCommand as defineCommand38 } from "citty";
4567
- import consola31 from "consola";
4568
- var sessionsListCommand = defineCommand38({
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
- consola31.info("No active sessions.");
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 defineCommand39 } from "citty";
4599
- import consola32 from "consola";
4600
- var sessionsRemoveCommand = defineCommand39({
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
- consola32.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
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 = defineCommand40({
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 defineCommand41 } from "citty";
4634
- import consola33 from "consola";
4709
+ import { defineCommand as defineCommand42 } from "citty";
4710
+ import consola34 from "consola";
4635
4711
  import { resolveDDISA as resolveDDISA3 } from "@openape/core";
4636
- var dnsCheckCommand = defineCommand41({
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
- consola33.start(`Checking _ddisa.${domain}...`);
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
- consola33.success(`_ddisa.${domain} \u2192 ${result.idp}`);
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
- consola33.start(`Verifying IdP at ${result.idp}...`);
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
- consola33.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
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
- consola33.success(`IdP is reachable`);
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 defineCommand42 } from "citty";
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.28.0" : "0.0.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 = defineCommand42({
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 defineCommand43 } from "citty";
4811
- import consola34 from "consola";
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 = defineCommand43({
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
- consola34.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
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 consola35 from "consola";
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
- consola35.warn(
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.28.0"} (OpenApe DDISA shell wrapper)`);
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.28.0"} \u2014 OpenApe DDISA shell wrapper`);
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 = defineCommand44({
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 = defineCommand44({
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 = defineCommand44({
5136
+ var main = defineCommand45({
5061
5137
  meta: {
5062
5138
  name: "apes",
5063
- version: "0.28.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.28.0").catch(() => {
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
- consola36.error(err.message);
5201
+ consola37.error(err.message);
5126
5202
  process.exit(err.exitCode);
5127
5203
  }
5128
5204
  if (debug) {
5129
- consola36.error(err);
5205
+ consola37.error(err);
5130
5206
  } else {
5131
- consola36.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
5207
+ consola37.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
5132
5208
  }
5133
5209
  process.exit(1);
5134
5210
  });