@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 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";
@@ -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
- apes login "$agent_email" --idp "$agent_idp" >/dev/null 2>&1 \\
2552
- || echo "warn: apes login failed for $agent_email; continuing with cached token"
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 = defineCommand23({
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
- consola21.start(`Generating keypair for ${name}\u2026`);
2812
+ consola22.start(`Generating keypair for ${name}\u2026`);
2729
2813
  const { privatePem, publicSshLine } = generateKeyPairInMemory();
2730
- consola21.start(`Registering agent at ${idp}\u2026`);
2814
+ consola22.start(`Registering agent at ${idp}\u2026`);
2731
2815
  const registration = await registerAgentAtIdp({ name, publicKey: publicSshLine, idp });
2732
- consola21.success(`Registered as ${registration.email}`);
2733
- consola21.start("Issuing agent access token\u2026");
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
- 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.`);
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
- 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.");
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 = defineCommand24({
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 defineCommand25 } from "citty";
2832
- import consola22 from "consola";
2833
- var adapterCommand = defineCommand25({
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: defineCommand25({
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
- consola22.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
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
- consola22.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
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: defineCommand25({
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
- consola22.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
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
- consola22.warn(`Conflicting adapter found: ${c.path} (id: ${c.adapterId}, executable: ${c.executable})`);
2936
- consola22.warn(` Remove it with: apes adapter remove ${c.adapterId}`);
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
- consola22.success(`${verb} ${result.id} \u2192 ${result.path}`);
2942
- consola22.info(`Digest: ${result.digest}`);
3026
+ consola23.success(`${verb} ${result.id} \u2192 ${result.path}`);
3027
+ consola23.info(`Digest: ${result.digest}`);
2943
3028
  }
2944
3029
  }
2945
3030
  }),
2946
- remove: defineCommand25({
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
- consola22.success(`Removed adapter: ${id}`);
3054
+ consola23.success(`Removed adapter: ${id}`);
2970
3055
  } else {
2971
- consola22.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
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: defineCommand25({
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: defineCommand25({
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
- consola22.info(`No adapters matching "${query}"`);
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: defineCommand25({
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
- consola22.info("No adapters installed to update.");
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
- consola22.warn(`${id}: not found in registry, skipping`);
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
- consola22.info(`${id}: already up to date`);
3184
+ consola23.info(`${id}: already up to date`);
3100
3185
  continue;
3101
3186
  }
3102
3187
  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");
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
- consola22.success(`Updated ${result.id} \u2192 ${result.path}`);
3195
+ consola23.success(`Updated ${result.id} \u2192 ${result.path}`);
3111
3196
  }
3112
3197
  }
3113
3198
  }),
3114
- verify: defineCommand25({
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
- consola22.success(`${id}: digest matches registry`);
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 execFileSync5 } from "child_process";
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 defineCommand26 } from "citty";
3163
- import consola23 from "consola";
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
- consola23.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
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
- consola23.success(`Grant ${grant.id} created (pending approval)`);
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 = defineCommand26({
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
- consola23.info(`Requesting ape-shell session grant on ${targetHost}`);
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
- consola23.info(`Grant requested: ${grant.id}`);
3356
- consola23.info("Waiting for approval...");
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
- consola23.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
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
- consola23.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
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
- consola23.info(`Requesting grant for: ${resolved.detail.display}`);
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
- consola23.info("");
3410
- consola23.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
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
- consola23.info(`Grant requested: ${grant.id}`);
3421
- consola23.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
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
- execFileSync5(command[0], command.slice(1), {
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
- consola23.info(`Reusing existing grant: ${existingGrantId}`);
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
- consola23.info("");
3510
- consola23.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
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
- consola23.info(` Broader scope: ${wider}`);
3598
+ consola24.info(` Broader scope: ${wider}`);
3514
3599
  }
3515
- consola23.info("");
3600
+ consola24.info("");
3516
3601
  }
3517
3602
  if (shouldWaitForGrant(args)) {
3518
- consola23.info(`Grant requested: ${grant.id}`);
3519
- consola23.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
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
- consola23.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
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
- consola23.success(`Grant requested: ${grant.id}`);
3557
- consola23.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
3558
- consola23.info("Waiting for approval...");
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
- consola23.success("Grant approved!");
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
- consola23.info("Fetching grant token...");
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
- consola23.info(`Executing: ${command.join(" ")}`);
3671
+ consola24.info(`Executing: ${command.join(" ")}`);
3587
3672
  try {
3588
3673
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
3589
- execFileSync5(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
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 defineCommand27 } from "citty";
3605
- import consola24 from "consola";
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
- consola24.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
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 = defineCommand27({
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
- consola24.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
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
- consola24.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
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
- consola24.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
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 defineCommand28 } from "citty";
3825
- var explainCommand = defineCommand28({
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 defineCommand29 } from "citty";
3864
- import consola25 from "consola";
3865
- var configGetCommand = defineCommand29({
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
- consola25.info("No IdP configured.");
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
- consola25.info("Not logged in.");
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
- consola25.info(`Key "${key}" not set.`);
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 defineCommand30 } from "citty";
3918
- import consola26 from "consola";
3919
- var configSetCommand = defineCommand30({
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
- consola26.success(`Set ${key} = ${value}`);
4040
+ consola27.success(`Set ${key} = ${value}`);
3956
4041
  }
3957
4042
  });
3958
4043
 
3959
4044
  // src/commands/fetch/index.ts
3960
- import { defineCommand as defineCommand31 } from "citty";
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 = defineCommand31({
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: defineCommand31({
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: defineCommand31({
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 defineCommand32 } from "citty";
4068
- var mcpCommand = defineCommand32({
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-GWZM6VS3.js");
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 execFileSync6 } from "child_process";
4184
+ import { execFileSync as execFileSync7 } from "child_process";
4100
4185
  import { join as join6 } from "path";
4101
- import { defineCommand as defineCommand33 } from "citty";
4102
- import consola27 from "consola";
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
- execFileSync6("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
4196
+ execFileSync7("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
4112
4197
  } else if (hasLockFile("bun.lockb")) {
4113
- execFileSync6("bun", ["install"], { cwd: dir, stdio: "inherit" });
4198
+ execFileSync7("bun", ["install"], { cwd: dir, stdio: "inherit" });
4114
4199
  } else {
4115
- execFileSync6("npm", ["install"], { cwd: dir, stdio: "inherit" });
4200
+ execFileSync7("npm", ["install"], { cwd: dir, stdio: "inherit" });
4116
4201
  }
4117
4202
  }
4118
4203
  async function promptChoice(message, choices) {
4119
- const result = await consola27.prompt(message, { type: "select", options: choices });
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 consola27.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
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 = defineCommand33({
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
- consola27.start("Scaffolding SP starter...");
4262
+ consola28.start("Scaffolding SP starter...");
4178
4263
  await downloadTemplate("openape-ai/openape-sp-starter", dir);
4179
- consola27.success("Scaffolded from openape-sp-starter");
4180
- consola27.start("Installing dependencies...");
4264
+ consola28.success("Scaffolded from openape-sp-starter");
4265
+ consola28.start("Installing dependencies...");
4181
4266
  installDeps(dir);
4182
- consola27.success("Dependencies installed");
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
- consola27.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
4272
+ consola28.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
4188
4273
  }
4189
4274
  console.log("");
4190
- consola27.box([
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
- consola27.start("Scaffolding IdP starter...");
4294
+ consola28.start("Scaffolding IdP starter...");
4210
4295
  await downloadTemplate("openape-ai/openape-idp-starter", dir);
4211
- consola27.success("Scaffolded from openape-idp-starter");
4212
- consola27.start("Installing dependencies...");
4296
+ consola28.success("Scaffolded from openape-idp-starter");
4297
+ consola28.start("Installing dependencies...");
4213
4298
  installDeps(dir);
4214
- consola27.success("Dependencies installed");
4299
+ consola28.success("Dependencies installed");
4215
4300
  const sessionSecret = randomBytes(32).toString("hex");
4216
4301
  const managementToken = randomBytes(32).toString("hex");
4217
- consola27.success("Secrets generated");
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
- consola27.success(".env created");
4318
+ consola28.success(".env created");
4234
4319
  console.log("");
4235
- consola27.box([
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 defineCommand34 } from "citty";
4256
- import consola28 from "consola";
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 = defineCommand34({
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 consola28.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
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 consola28.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
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 consola28.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
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
- consola28.success(`Using existing key ${keyPath}`);
4423
+ consola29.success(`Using existing key ${keyPath}`);
4339
4424
  } else {
4340
- consola28.start(`Generating Ed25519 key pair at ${keyPath}...`);
4425
+ consola29.start(`Generating Ed25519 key pair at ${keyPath}...`);
4341
4426
  publicKey = generateAndSaveKey(keyPath);
4342
- consola28.success(`Key pair generated at ${keyPath}`);
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
- consola28.info("Opening browser for enrollment...");
4347
- consola28.info(`\u2192 ${idp}/enroll`);
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 consola28.prompt(
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
- consola28.start("Verifying enrollment...");
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
- consola28.success(`Agent enrolled as ${agentEmail}`);
4373
- consola28.success("Config saved to ~/.config/apes/");
4457
+ consola29.success(`Agent enrolled as ${agentEmail}`);
4458
+ consola29.success("Config saved to ~/.config/apes/");
4374
4459
  console.log("");
4375
- consola28.info("Verify with: apes whoami");
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 defineCommand35 } from "citty";
4382
- import consola29 from "consola";
4383
- var registerUserCommand = defineCommand35({
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
- consola29.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
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 defineCommand37 } from "citty";
4528
+ import { defineCommand as defineCommand38 } from "citty";
4444
4529
 
4445
4530
  // src/commands/utils/dig.ts
4446
- import { defineCommand as defineCommand36 } from "citty";
4447
- import consola30 from "consola";
4531
+ import { defineCommand as defineCommand37 } from "citty";
4532
+ import consola31 from "consola";
4448
4533
  import { resolveDDISA as resolveDDISA2 } from "@openape/core";
4449
- var digCommand = defineCommand36({
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
- consola30.warn(`No DDISA record at _ddisa.${domain}`);
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
- consola30.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
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
- consola30.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
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
- consola30.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
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 = defineCommand37({
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 defineCommand40 } from "citty";
4648
+ import { defineCommand as defineCommand41 } from "citty";
4564
4649
 
4565
4650
  // src/commands/sessions/list.ts
4566
- import { defineCommand as defineCommand38 } from "citty";
4567
- import consola31 from "consola";
4568
- var sessionsListCommand = defineCommand38({
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
- consola31.info("No active sessions.");
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 defineCommand39 } from "citty";
4599
- import consola32 from "consola";
4600
- var sessionsRemoveCommand = defineCommand39({
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
- consola32.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
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 = defineCommand40({
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 defineCommand41 } from "citty";
4634
- import consola33 from "consola";
4718
+ import { defineCommand as defineCommand42 } from "citty";
4719
+ import consola34 from "consola";
4635
4720
  import { resolveDDISA as resolveDDISA3 } from "@openape/core";
4636
- var dnsCheckCommand = defineCommand41({
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
- consola33.start(`Checking _ddisa.${domain}...`);
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
- consola33.success(`_ddisa.${domain} \u2192 ${result.idp}`);
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
- consola33.start(`Verifying IdP at ${result.idp}...`);
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
- consola33.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
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
- consola33.success(`IdP is reachable`);
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 defineCommand42 } from "citty";
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.28.0" : "0.0.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 = defineCommand42({
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 defineCommand43 } from "citty";
4811
- import consola34 from "consola";
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 = defineCommand43({
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
- consola34.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
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 consola35 from "consola";
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
- consola35.warn(
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.28.0"} (OpenApe DDISA shell wrapper)`);
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.28.0"} \u2014 OpenApe DDISA shell wrapper`);
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 = defineCommand44({
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 = defineCommand44({
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 = defineCommand44({
5145
+ var main = defineCommand45({
5061
5146
  meta: {
5062
5147
  name: "apes",
5063
- version: "0.28.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.28.0").catch(() => {
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
- consola36.error(err.message);
5210
+ consola37.error(err.message);
5126
5211
  process.exit(err.exitCode);
5127
5212
  }
5128
5213
  if (debug) {
5129
- consola36.error(err);
5214
+ consola37.error(err);
5130
5215
  } else {
5131
- consola36.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
5216
+ consola37.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
5132
5217
  }
5133
5218
  process.exit(1);
5134
5219
  });