@openape/apes 1.11.0 → 1.12.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
@@ -77,7 +77,7 @@ import {
77
77
  import "./chunk-7OCVIDC7.js";
78
78
 
79
79
  // src/cli.ts
80
- import consola51 from "consola";
80
+ import consola49 from "consola";
81
81
 
82
82
  // src/ape-shell.ts
83
83
  import path from "path";
@@ -107,7 +107,7 @@ function rewriteApeShellArgs(argv, argv0) {
107
107
  }
108
108
 
109
109
  // src/cli.ts
110
- import { defineCommand as defineCommand61, runMain } from "citty";
110
+ import { defineCommand as defineCommand60, runMain } from "citty";
111
111
 
112
112
  // src/commands/auth/login.ts
113
113
  import { Buffer as Buffer2 } from "buffer";
@@ -393,7 +393,7 @@ async function loginWithPKCE(idp) {
393
393
  consola2.success(`Logged in as ${payload.email || payload.sub}`);
394
394
  }
395
395
  async function loginWithKey(idp, keyPath, agentEmail) {
396
- const { readFileSync: readFileSync14 } = await import("fs");
396
+ const { readFileSync: readFileSync15 } = await import("fs");
397
397
  const { sign: sign3 } = await import("crypto");
398
398
  const { loadEd25519PrivateKey: loadEd25519PrivateKey2 } = await import("./ssh-key-6X3YZXSD.js");
399
399
  const challengeUrl = await getAgentChallengeEndpoint(idp);
@@ -406,7 +406,7 @@ async function loginWithKey(idp, keyPath, agentEmail) {
406
406
  throw new CliError(`Challenge failed: ${await challengeResp.text()}`);
407
407
  }
408
408
  const { challenge } = await challengeResp.json();
409
- const keyContent = readFileSync14(keyPath, "utf-8");
409
+ const keyContent = readFileSync15(keyPath, "utf-8");
410
410
  const privateKey = loadEd25519PrivateKey2(keyContent);
411
411
  const signature = sign3(null, Buffer2.from(challenge), privateKey).toString("base64");
412
412
  const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
@@ -2693,46 +2693,19 @@ function buildBridgeBlock(bridge) {
2693
2693
  return `
2694
2694
  mkdir -p "$HOME_DIR/Library/Application Support/openape/bridge" "$HOME_DIR/Library/Logs"
2695
2695
  cat > "$HOME_DIR/Library/Application Support/openape/bridge/.env" ${shHeredoc(bridge.envFile)}
2696
- cat > "$HOME_DIR/Library/Application Support/openape/bridge/start.sh" ${shHeredoc(bridge.startScript)}
2697
- chmod 755 "$HOME_DIR/Library/Application Support/openape/bridge/start.sh"
2698
2696
  chmod 600 "$HOME_DIR/Library/Application Support/openape/bridge/.env"
2699
-
2700
- # System-wide LaunchDaemon \u2014 root-owned, mode 644 (launchd refuses
2701
- # group/world-writable plists). UserName in the plist makes launchd run
2702
- # the binary as the agent, not root.
2703
- cat > ${shQuote(bridge.plistPath)} ${shHeredoc(bridge.plistContent)}
2704
- chown root:wheel ${shQuote(bridge.plistPath)}
2705
- chmod 644 ${shQuote(bridge.plistPath)}
2706
2697
  `;
2707
2698
  }
2708
- function buildBridgeBootstrapBlock(bridge, _name) {
2709
- if (!bridge) return "";
2710
- return `
2711
- launchctl bootout "system/${bridge.plistLabel}" 2>/dev/null || true
2712
- launchctl bootstrap system ${shQuote(bridge.plistPath)} || \\
2713
- echo "warn: bridge bootstrap into system domain failed; check ${bridge.plistPath}"
2714
- `;
2699
+ function buildBridgeBootstrapBlock(_bridge, _name) {
2700
+ return "";
2715
2701
  }
2716
- function buildTroopBlock(troop) {
2717
- if (!troop) return "";
2702
+ function buildTroopBlock(_troop) {
2718
2703
  return `
2719
- mkdir -p "$HOME_DIR/Library/LaunchAgents" "$HOME_DIR/Library/Logs" "$HOME_DIR/.openape/agent/tasks"
2720
- cat > ${shQuote(troop.plistPath)} ${shHeredoc(troop.plistContent)}
2721
- chown root:wheel ${shQuote(troop.plistPath)}
2722
- chmod 644 ${shQuote(troop.plistPath)}
2704
+ mkdir -p "$HOME_DIR/Library/Logs" "$HOME_DIR/.openape/agent/tasks"
2723
2705
  `;
2724
2706
  }
2725
- function buildTroopBootstrapBlock(troop, name) {
2726
- if (!troop) return "";
2727
- return `
2728
- # Bootstrap the troop sync launchd in the system domain. setup.sh runs
2729
- # as root via \`apes run --as root\`, so we have permission. Stale label
2730
- # is bootouted first to make re-spawn idempotent.
2731
- echo "==> Installing troop sync launchd as ${name}\u2026"
2732
- launchctl bootout "system/${troop.plistLabel}" 2>/dev/null || true
2733
- launchctl bootstrap system ${shQuote(troop.plistPath)} || \\
2734
- echo "warn: troop sync bootstrap failed; check ${troop.plistPath}"
2735
- `;
2707
+ function buildTroopBootstrapBlock(_troop, _name) {
2708
+ return "";
2736
2709
  }
2737
2710
  function buildDestroyTeardownScript(input) {
2738
2711
  const { name, homeDir, adminUser } = input;
@@ -4265,7 +4238,7 @@ var agentsCommand = defineCommand28({
4265
4238
  });
4266
4239
 
4267
4240
  // src/commands/nest/index.ts
4268
- import { defineCommand as defineCommand37 } from "citty";
4241
+ import { defineCommand as defineCommand36 } from "citty";
4269
4242
 
4270
4243
  // src/commands/nest/authorize.ts
4271
4244
  import { execFileSync as execFileSync8 } from "child_process";
@@ -4434,147 +4407,107 @@ var authorizeNestCommand = defineCommand30({
4434
4407
  });
4435
4408
 
4436
4409
  // src/commands/nest/destroy.ts
4437
- import process2 from "process";
4438
4410
  import { defineCommand as defineCommand31 } from "citty";
4439
- import consola28 from "consola";
4440
-
4441
- // src/lib/nest-grant-flow.ts
4442
- import { hostname as hostname5 } from "os";
4443
4411
  import consola27 from "consola";
4444
- var NEST_AUDIENCE = "nest";
4445
- async function requestNestGrant(opts) {
4446
- const auth = loadAuth();
4447
- if (!auth) {
4448
- throw new CliError("Not logged in. Run `apes login` first.");
4449
- }
4450
- const idp = getIdpUrl(opts.idp) ?? void 0;
4451
- if (!idp) {
4452
- throw new CliError("No IdP URL resolved. Pass --idp or run `apes login` first.");
4453
- }
4454
- const grantsUrl = await getGrantsEndpoint(idp);
4455
- const targetHost = opts.targetHost ?? hostname5();
4456
- const approval = opts.approval ?? "always";
4457
- const reusableId = await findReusableNestGrant({
4458
- grantsUrl,
4459
- requester: auth.email,
4460
- command: opts.command,
4461
- targetHost
4462
- });
4463
- if (reusableId) {
4464
- const { authz_jwt: authz_jwt2 } = await apiFetch(`${grantsUrl}/${reusableId}/token`, {
4465
- method: "POST"
4466
- });
4467
- return authz_jwt2;
4468
- }
4469
- consola27.info(`Requesting nest grant: ${opts.command.join(" ")}`);
4470
- const grant = await apiFetch(grantsUrl, {
4471
- method: "POST",
4472
- body: {
4473
- requester: auth.email,
4474
- target_host: targetHost,
4475
- audience: NEST_AUDIENCE,
4476
- grant_type: approval,
4477
- command: opts.command,
4478
- reason: opts.reason ?? opts.command.join(" ")
4479
- }
4480
- });
4481
- let approved = grant.status === "approved";
4482
- const maxWait = 15 * 60 * 1e3;
4483
- const interval = 3e3;
4484
- const start = Date.now();
4485
- while (!approved && Date.now() - start < maxWait) {
4486
- const status = await apiFetch(`${grantsUrl}/${grant.id}`);
4487
- if (status.status === "approved") {
4488
- approved = true;
4489
- break;
4490
- }
4491
- if (status.status === "denied" || status.status === "revoked") {
4492
- throw new CliError(`Grant ${status.status}.`);
4493
- }
4494
- if (!approved) {
4495
- consola27.info(`Waiting for approval: ${idp}/grant-approval?grant_id=${grant.id}`);
4496
- await new Promise((r3) => setTimeout(r3, interval));
4412
+
4413
+ // src/lib/nest-intent.ts
4414
+ import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync10, statSync as statSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
4415
+ import { homedir as homedir10 } from "os";
4416
+ import { join as join10 } from "path";
4417
+ import { randomUUID } from "crypto";
4418
+ var POLL_INTERVAL_MS = 200;
4419
+ var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
4420
+ function resolveIntentDir() {
4421
+ if (process.env.OPENAPE_NEST_INTENT_DIR) return process.env.OPENAPE_NEST_INTENT_DIR;
4422
+ if (existsSync12("/var/openape/nest/intents")) return "/var/openape/nest/intents";
4423
+ return join10(homedir10(), ".openape", "nest", "intents");
4424
+ }
4425
+ async function dispatchIntent(intent, opts = {}) {
4426
+ const id = randomUUID();
4427
+ const dir = resolveIntentDir();
4428
+ if (!existsSync12(dir)) {
4429
+ throw new CliError(`Nest intent dir does not exist: ${dir}
4430
+ Is the nest daemon running? Try \`ps aux | grep openape-nest\`.`);
4431
+ }
4432
+ const intentPath = join10(dir, `${id}.json`);
4433
+ const responsePath = join10(dir, `${id}.response`);
4434
+ const tmpPath = `${intentPath}.tmp`;
4435
+ writeFileSync6(tmpPath, `${JSON.stringify({ id, ...intent })}
4436
+ `, { mode: 432 });
4437
+ try {
4438
+ const fs = await import("fs");
4439
+ fs.renameSync(tmpPath, intentPath);
4440
+ } catch (err) {
4441
+ try {
4442
+ unlinkSync(tmpPath);
4443
+ } catch {
4497
4444
  }
4445
+ throw err;
4498
4446
  }
4499
- if (!approved) {
4500
- throw new CliError(
4501
- `Grant approval timed out after 15 min (still pending). Check your DDISA inbox at ${idp}/grant-approval?grant_id=${grant.id}.`
4502
- );
4447
+ const deadline = Date.now() + (opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
4448
+ while (Date.now() < deadline) {
4449
+ if (existsSync12(responsePath)) {
4450
+ let raw;
4451
+ try {
4452
+ const st = statSync2(responsePath);
4453
+ if (Date.now() - st.mtimeMs < 50) {
4454
+ await sleep(50);
4455
+ }
4456
+ raw = readFileSync10(responsePath, "utf8");
4457
+ } catch {
4458
+ await sleep(POLL_INTERVAL_MS);
4459
+ continue;
4460
+ }
4461
+ try {
4462
+ unlinkSync(responsePath);
4463
+ } catch {
4464
+ }
4465
+ let parsed;
4466
+ try {
4467
+ parsed = JSON.parse(raw);
4468
+ } catch (err) {
4469
+ throw new CliError(`malformed nest response: ${err instanceof Error ? err.message : String(err)}`);
4470
+ }
4471
+ if (!parsed.ok) {
4472
+ throw new CliError(`nest: ${parsed.error}`);
4473
+ }
4474
+ return parsed.result;
4475
+ }
4476
+ await sleep(POLL_INTERVAL_MS);
4503
4477
  }
4504
- const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, {
4505
- method: "POST"
4506
- });
4507
- return authz_jwt;
4508
- }
4509
- function nestBaseUrl(port) {
4510
- const p2 = port ?? Number(process.env.OPENAPE_NEST_PORT ?? 9091);
4511
- return `http://127.0.0.1:${p2}`;
4512
- }
4513
- async function findReusableNestGrant(opts) {
4514
4478
  try {
4515
- const grants = await apiFetch(
4516
- `${opts.grantsUrl}?requester=${encodeURIComponent(opts.requester)}&status=approved&limit=50`
4517
- );
4518
- const now = Math.floor(Date.now() / 1e3);
4519
- const match = grants.data.find((g) => {
4520
- const r3 = g.request;
4521
- if (r3.audience !== NEST_AUDIENCE) return false;
4522
- if (r3.target_host !== opts.targetHost) return false;
4523
- if (r3.grant_type === "once") return false;
4524
- if (r3.grant_type === "timed" && g.expires_at && g.expires_at <= now) return false;
4525
- const cmd = r3.command ?? [];
4526
- if (cmd.length !== opts.command.length) return false;
4527
- return cmd.every((c2, i) => c2 === opts.command[i]);
4528
- });
4529
- return match?.id ?? null;
4479
+ unlinkSync(intentPath);
4530
4480
  } catch {
4531
- return null;
4532
4481
  }
4482
+ throw new CliError(`nest intent timeout (${(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS) / 1e3}s) \u2014 Nest daemon may not be running or is stuck.`);
4483
+ }
4484
+ function sleep(ms) {
4485
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
4533
4486
  }
4534
4487
 
4535
4488
  // src/commands/nest/destroy.ts
4536
4489
  var destroyNestCommand = defineCommand31({
4537
4490
  meta: {
4538
4491
  name: "destroy",
4539
- description: "Tear down an agent on the local nest (removes macOS user, hard-deletes IdP record, drops bridge plist). Requires a DDISA `nest destroy <name>` grant."
4492
+ description: "Tear down an agent on the local nest. Drops an intent file the nest daemon picks up."
4540
4493
  },
4541
4494
  args: {
4542
- name: { type: "positional", required: true, description: "Agent name to destroy" },
4543
- port: { type: "string", description: "Override nest port (default: 9091)" }
4495
+ name: { type: "positional", required: true, description: "Agent name to destroy" }
4544
4496
  },
4545
4497
  async run({ args }) {
4546
4498
  const name = String(args.name);
4547
- const token = await requestNestGrant({ command: ["nest", "destroy", name] });
4548
- const base = nestBaseUrl(args.port ? Number(args.port) : void 0);
4549
- try {
4550
- const res = await fetch(`${base}/agents/${encodeURIComponent(name)}`, {
4551
- method: "DELETE",
4552
- headers: { Authorization: `Bearer ${token}` }
4553
- });
4554
- if (!res.ok) {
4555
- const text = await res.text().catch(() => "");
4556
- throw new CliError(`nest DELETE /agents/${name} failed: ${res.status} ${text}`);
4557
- }
4558
- } catch (err) {
4559
- const msg = err instanceof Error ? err.message : String(err);
4560
- if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) {
4561
- consola28.error(`Nest daemon is not running at ${base}`);
4562
- consola28.info(" Run: apes nest install");
4563
- process2.exit(2);
4564
- }
4565
- throw err;
4566
- }
4567
- consola28.success(`Destroyed ${name}`);
4499
+ await dispatchIntent({ action: "destroy", name });
4500
+ consola27.success(`Destroyed ${name}`);
4568
4501
  }
4569
4502
  });
4570
4503
 
4571
4504
  // src/commands/nest/install.ts
4572
4505
  import { execFileSync as execFileSync9 } from "child_process";
4573
- import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
4574
- import { homedir as homedir10, userInfo as userInfo2 } from "os";
4575
- import { dirname as dirname3, join as join10 } from "path";
4506
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
4507
+ import { homedir as homedir11, userInfo as userInfo2 } from "os";
4508
+ import { dirname as dirname3, join as join11 } from "path";
4576
4509
  import { defineCommand as defineCommand32 } from "citty";
4577
- import consola29 from "consola";
4510
+ import consola28 from "consola";
4578
4511
 
4579
4512
  // src/commands/nest/apes-agents-adapter.ts
4580
4513
  var APES_AGENTS_ADAPTER_TOML = `schema = "openape-shapes/v1"
@@ -4641,13 +4574,13 @@ resource_chain = ["agents:name={name}", "allowlist:email={peer_email}"]
4641
4574
  // src/commands/nest/install.ts
4642
4575
  var PLIST_LABEL = "ai.openape.nest";
4643
4576
  function plistPath() {
4644
- return join10(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
4577
+ return join11(homedir11(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
4645
4578
  }
4646
4579
  function escape2(s) {
4647
4580
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4648
4581
  }
4649
4582
  function buildPlist(args) {
4650
- const logsDir = join10(args.userHome, "Library", "Logs");
4583
+ const logsDir = join11(args.userHome, "Library", "Logs");
4651
4584
  return `<?xml version="1.0" encoding="UTF-8"?>
4652
4585
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4653
4586
  <plist version="1.0">
@@ -4682,40 +4615,40 @@ function buildPlist(args) {
4682
4615
  `;
4683
4616
  }
4684
4617
  function installAdapter2() {
4685
- const target = join10(homedir10(), ".openape", "shapes", "adapters", "apes-agents.toml");
4686
- mkdirSync4(dirname3(target), { recursive: true });
4618
+ const target = join11(homedir11(), ".openape", "shapes", "adapters", "apes-agents.toml");
4619
+ mkdirSync5(dirname3(target), { recursive: true });
4687
4620
  let existing = "";
4688
4621
  try {
4689
- existing = readFileSync10(target, "utf8");
4622
+ existing = readFileSync11(target, "utf8");
4690
4623
  } catch {
4691
4624
  }
4692
4625
  if (existing === APES_AGENTS_ADAPTER_TOML) return false;
4693
- writeFileSync6(target, APES_AGENTS_ADAPTER_TOML, { mode: 420 });
4694
- consola29.success(`Wrote shapes adapter ${target}`);
4626
+ writeFileSync7(target, APES_AGENTS_ADAPTER_TOML, { mode: 420 });
4627
+ consola28.success(`Wrote shapes adapter ${target}`);
4695
4628
  return true;
4696
4629
  }
4697
4630
  function writeBridgeModelDefault(model) {
4698
- const envDir = join10(homedir10(), "litellm");
4699
- const envFile = join10(envDir, ".env");
4700
- mkdirSync4(envDir, { recursive: true });
4631
+ const envDir = join11(homedir11(), "litellm");
4632
+ const envFile = join11(envDir, ".env");
4633
+ mkdirSync5(envDir, { recursive: true });
4701
4634
  let lines = [];
4702
- if (existsSync12(envFile)) {
4703
- lines = readFileSync10(envFile, "utf8").split("\n").filter((l) => !l.startsWith("APE_CHAT_BRIDGE_MODEL="));
4635
+ if (existsSync13(envFile)) {
4636
+ lines = readFileSync11(envFile, "utf8").split("\n").filter((l) => !l.startsWith("APE_CHAT_BRIDGE_MODEL="));
4704
4637
  }
4705
4638
  lines.push(`APE_CHAT_BRIDGE_MODEL=${model}`);
4706
4639
  while (lines.length > 0 && lines.at(-1).trim() === "") lines.pop();
4707
- writeFileSync6(envFile, `${lines.join("\n")}
4640
+ writeFileSync7(envFile, `${lines.join("\n")}
4708
4641
  `, { mode: 384 });
4709
4642
  }
4710
4643
  function findBinary(name) {
4711
4644
  for (const dir of [
4712
- join10(homedir10(), ".bun", "bin"),
4645
+ join11(homedir11(), ".bun", "bin"),
4713
4646
  "/opt/homebrew/bin",
4714
4647
  "/usr/local/bin",
4715
4648
  "/usr/bin"
4716
4649
  ]) {
4717
- const p2 = join10(dir, name);
4718
- if (existsSync12(p2)) return p2;
4650
+ const p2 = join11(dir, name);
4651
+ if (existsSync13(p2)) return p2;
4719
4652
  }
4720
4653
  throw new Error(`could not locate ${name} on PATH; install it first`);
4721
4654
  }
@@ -4735,35 +4668,35 @@ var installNestCommand = defineCommand32({
4735
4668
  }
4736
4669
  },
4737
4670
  async run({ args }) {
4738
- const homeDir = homedir10();
4671
+ const homeDir = homedir11();
4739
4672
  const port = Number(args.port ?? 9091);
4740
4673
  if (!Number.isInteger(port) || port < 1024 || port > 65535) {
4741
4674
  throw new Error(`invalid port ${port}`);
4742
4675
  }
4743
4676
  const nestBin = findBinary("openape-nest");
4744
4677
  const apesBin = findBinary("apes");
4745
- consola29.info(`Installing nest at ${plistPath()}`);
4746
- consola29.info(` nest binary: ${nestBin}`);
4747
- consola29.info(` apes binary: ${apesBin}`);
4748
- consola29.info(` HTTP port: ${port}`);
4678
+ consola28.info(`Installing nest at ${plistPath()}`);
4679
+ consola28.info(` nest binary: ${nestBin}`);
4680
+ consola28.info(` apes binary: ${apesBin}`);
4681
+ consola28.info(` HTTP port: ${port}`);
4749
4682
  if (typeof args["bridge-model"] === "string" && args["bridge-model"]) {
4750
4683
  writeBridgeModelDefault(args["bridge-model"]);
4751
- consola29.success(`Default bridge model set to ${args["bridge-model"]} (in ~/litellm/.env)`);
4684
+ consola28.success(`Default bridge model set to ${args["bridge-model"]} (in ~/litellm/.env)`);
4752
4685
  }
4753
4686
  installAdapter2();
4754
- mkdirSync4(join10(homeDir, "Library", "LaunchAgents"), { recursive: true });
4755
- mkdirSync4(NEST_DATA_DIR, { recursive: true });
4687
+ mkdirSync5(join11(homeDir, "Library", "LaunchAgents"), { recursive: true });
4688
+ mkdirSync5(NEST_DATA_DIR, { recursive: true });
4756
4689
  const desired = buildPlist({ nestBin, apesBin, userHome: homeDir, nestHome: NEST_DATA_DIR, port });
4757
4690
  let existing = "";
4758
4691
  try {
4759
- existing = readFileSync10(plistPath(), "utf8");
4692
+ existing = readFileSync11(plistPath(), "utf8");
4760
4693
  } catch {
4761
4694
  }
4762
4695
  if (existing !== desired) {
4763
- writeFileSync6(plistPath(), desired, { mode: 420 });
4764
- consola29.success("Wrote launchd plist");
4696
+ writeFileSync7(plistPath(), desired, { mode: 420 });
4697
+ consola28.success("Wrote launchd plist");
4765
4698
  } else {
4766
- consola29.info("plist already up to date");
4699
+ consola28.info("plist already up to date");
4767
4700
  }
4768
4701
  const uid = userInfo2().uid;
4769
4702
  try {
@@ -4771,208 +4704,116 @@ var installNestCommand = defineCommand32({
4771
4704
  } catch {
4772
4705
  }
4773
4706
  execFileSync9("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
4774
- consola29.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
4775
- consola29.info("");
4776
- consola29.info("Next steps for zero-prompt spawn \u2014 both one-time:");
4777
- consola29.info("");
4778
- consola29.info(" 1. apes nest enroll # register nest as DDISA agent (creates own auth.json)");
4779
- consola29.info(" 2. apes nest authorize # set YOLO-policy on the nest agent");
4780
- consola29.info("");
4781
- consola29.info("After that, every `POST http://127.0.0.1:9091/agents` runs without DDISA prompts.");
4707
+ consola28.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
4708
+ consola28.info("");
4709
+ consola28.info("Next steps for zero-prompt spawn \u2014 both one-time:");
4710
+ consola28.info("");
4711
+ consola28.info(" 1. apes nest enroll # register nest as DDISA agent (creates own auth.json)");
4712
+ consola28.info(" 2. apes nest authorize # set YOLO-policy on the nest agent");
4713
+ consola28.info("");
4714
+ consola28.info("After that, every `POST http://127.0.0.1:9091/agents` runs without DDISA prompts.");
4782
4715
  }
4783
4716
  });
4784
4717
 
4785
4718
  // src/commands/nest/list.ts
4786
- import process3 from "process";
4787
4719
  import { defineCommand as defineCommand33 } from "citty";
4788
- import consola30 from "consola";
4720
+ import consola29 from "consola";
4789
4721
  var listNestCommand = defineCommand33({
4790
4722
  meta: {
4791
4723
  name: "list",
4792
- description: "List agents registered with the local nest. Goes through DDISA grants \u2014 YOLO auto-approves under the standard nest policy."
4724
+ description: "List agents registered with the local nest. File-based intent."
4793
4725
  },
4794
4726
  args: {
4795
- port: { type: "string", description: "Override nest port (default: 9091)" },
4796
4727
  json: { type: "boolean", description: "JSON output for scripts" }
4797
4728
  },
4798
4729
  async run({ args }) {
4799
- const token = await requestNestGrant({ command: ["nest", "list"] });
4800
- const base = nestBaseUrl(args.port ? Number(args.port) : void 0);
4801
- let resp;
4802
- try {
4803
- const res = await fetch(`${base}/agents`, {
4804
- headers: { Authorization: `Bearer ${token}` }
4805
- });
4806
- if (!res.ok) {
4807
- const text = await res.text().catch(() => "");
4808
- throw new CliError(`nest GET /agents failed: ${res.status} ${text}`);
4809
- }
4810
- resp = await res.json();
4811
- } catch (err) {
4812
- const msg = err instanceof Error ? err.message : String(err);
4813
- if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) {
4814
- consola30.error(`Nest daemon is not running at ${base}`);
4815
- consola30.info(" Run: apes nest install");
4816
- process3.exit(2);
4817
- }
4818
- throw err;
4819
- }
4730
+ const result = await dispatchIntent({ action: "list" });
4820
4731
  if (args.json) {
4821
- console.log(JSON.stringify(resp, null, 2));
4732
+ console.log(JSON.stringify(result, null, 2));
4822
4733
  return;
4823
4734
  }
4824
- if (resp.agents.length === 0) {
4825
- consola30.info("(no agents registered with this nest)");
4735
+ if (result.agents.length === 0) {
4736
+ consola29.info("(no agents registered with this nest)");
4826
4737
  return;
4827
4738
  }
4828
- consola30.info(`${resp.agents.length} agent(s) registered with this nest:`);
4829
- for (const a of resp.agents) {
4739
+ consola29.info(`${result.agents.length} agent(s) registered with this nest:`);
4740
+ for (const a of result.agents) {
4830
4741
  const bridge = a.bridge ? " bridge=on" : "";
4831
- consola30.info(` ${a.name.padEnd(16)} uid=${String(a.uid).padEnd(5)} home=${a.home}${bridge}`);
4742
+ consola29.info(` ${a.name.padEnd(16)} uid=${String(a.uid).padEnd(5)} home=${a.home}${bridge}`);
4832
4743
  }
4833
4744
  }
4834
4745
  });
4835
4746
 
4836
4747
  // src/commands/nest/spawn.ts
4837
- import process4 from "process";
4838
4748
  import { defineCommand as defineCommand34 } from "citty";
4839
- import consola31 from "consola";
4749
+ import consola30 from "consola";
4840
4750
  var spawnNestCommand = defineCommand34({
4841
4751
  meta: {
4842
4752
  name: "spawn",
4843
- description: "Spawn a new agent on the local nest. Requires a DDISA `nest spawn <name>` grant \u2014 auto-approved by Patrick's policy on first use, reused on subsequent calls."
4753
+ description: "Spawn a new agent on the local nest. Drops an intent file the nest daemon picks up; UNIX permissions on the intents dir gate access."
4844
4754
  },
4845
4755
  args: {
4846
4756
  name: { type: "positional", required: true, description: "Agent name (lowercase, [a-z0-9-], max 24 chars)" },
4847
4757
  "no-bridge": { type: "boolean", description: "Skip installing the chat-bridge daemon (default: install it)" },
4848
4758
  "bridge-key": { type: "string", description: "Override LITELLM_API_KEY (default: read from ~/litellm/.env)" },
4849
4759
  "bridge-base-url": { type: "string", description: "Override LITELLM_BASE_URL (default: read from ~/litellm/.env)" },
4850
- "bridge-model": { type: "string", description: "Override APE_CHAT_BRIDGE_MODEL" },
4851
- "port": { type: "string", description: "Override nest port (default: 9091)" }
4760
+ "bridge-model": { type: "string", description: "Override APE_CHAT_BRIDGE_MODEL" }
4852
4761
  },
4853
4762
  async run({ args }) {
4854
4763
  const name = String(args.name);
4855
- const token = await requestNestGrant({ command: ["nest", "spawn"] });
4856
- const base = nestBaseUrl(args.port ? Number(args.port) : void 0);
4857
- const reqBody = {
4764
+ const intent = {
4765
+ action: "spawn",
4858
4766
  name,
4859
4767
  bridge: !args["no-bridge"]
4860
4768
  };
4861
- if (typeof args["bridge-key"] === "string") reqBody.bridgeKey = args["bridge-key"];
4862
- if (typeof args["bridge-base-url"] === "string") reqBody.bridgeBaseUrl = args["bridge-base-url"];
4863
- if (typeof args["bridge-model"] === "string") reqBody.bridgeModel = args["bridge-model"];
4864
- let resp;
4865
- try {
4866
- const res = await fetch(`${base}/agents`, {
4867
- method: "POST",
4868
- headers: {
4869
- "Authorization": `Bearer ${token}`,
4870
- "Content-Type": "application/json"
4871
- },
4872
- body: JSON.stringify(reqBody)
4873
- });
4874
- if (!res.ok) {
4875
- const text = await res.text().catch(() => "");
4876
- throw new CliError(`nest POST /agents failed: ${res.status} ${text}`);
4877
- }
4878
- resp = await res.json();
4879
- } catch (err) {
4880
- const msg = err instanceof Error ? err.message : String(err);
4881
- if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) {
4882
- consola31.error(`Nest daemon is not running at ${base}`);
4883
- consola31.info(" Run: apes nest install");
4884
- process4.exit(2);
4885
- }
4886
- throw err;
4887
- }
4888
- consola31.success(`Spawned ${resp.name} (uid=${resp.uid}, home=${resp.home})`);
4889
- }
4890
- });
4891
-
4892
- // src/commands/nest/status.ts
4893
- import process5 from "process";
4894
- import { defineCommand as defineCommand35 } from "citty";
4895
- import consola32 from "consola";
4896
- var statusNestCommand = defineCommand35({
4897
- meta: {
4898
- name: "status",
4899
- description: "Print health of the local nest-daemon (agents registered). Goes through DDISA grants."
4900
- },
4901
- args: {
4902
- port: { type: "string", description: "Override nest port (default: 9091)" },
4903
- json: { type: "boolean", description: "JSON output for scripts" }
4904
- },
4905
- async run({ args }) {
4906
- const token = await requestNestGrant({ command: ["nest", "status"] });
4907
- const base = nestBaseUrl(args.port ? Number(args.port) : void 0);
4908
- let status;
4909
- try {
4910
- const res = await fetch(`${base}/status`, {
4911
- headers: { Authorization: `Bearer ${token}` }
4912
- });
4913
- if (!res.ok) {
4914
- const text = await res.text().catch(() => "");
4915
- throw new CliError(`nest GET /status failed: ${res.status} ${text}`);
4916
- }
4917
- status = await res.json();
4918
- } catch (err) {
4919
- const msg = err instanceof Error ? err.message : String(err);
4920
- if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) {
4921
- consola32.error(`Nest daemon is not running at ${base}`);
4922
- consola32.info(" Run: apes nest install");
4923
- process5.exit(2);
4924
- }
4925
- throw err;
4926
- }
4927
- if (args.json) {
4928
- console.log(JSON.stringify(status, null, 2));
4929
- return;
4930
- }
4931
- consola32.info(`Nest at ${base} \u2014 ${status.agents} agent(s) registered`);
4769
+ if (typeof args["bridge-key"] === "string") intent.bridgeKey = args["bridge-key"];
4770
+ if (typeof args["bridge-base-url"] === "string") intent.bridgeBaseUrl = args["bridge-base-url"];
4771
+ if (typeof args["bridge-model"] === "string") intent.bridgeModel = args["bridge-model"];
4772
+ const result = await dispatchIntent(intent);
4773
+ consola30.success(`Spawned ${result.name} (uid=${result.uid}, home=${result.home})`);
4932
4774
  }
4933
4775
  });
4934
4776
 
4935
4777
  // src/commands/nest/uninstall.ts
4936
4778
  import { execFileSync as execFileSync10 } from "child_process";
4937
- import { existsSync as existsSync13, unlinkSync } from "fs";
4938
- import { homedir as homedir11, userInfo as userInfo3 } from "os";
4939
- import { join as join11 } from "path";
4940
- import { defineCommand as defineCommand36 } from "citty";
4941
- import consola33 from "consola";
4779
+ import { existsSync as existsSync14, unlinkSync as unlinkSync2 } from "fs";
4780
+ import { homedir as homedir12, userInfo as userInfo3 } from "os";
4781
+ import { join as join12 } from "path";
4782
+ import { defineCommand as defineCommand35 } from "citty";
4783
+ import consola31 from "consola";
4942
4784
  var PLIST_LABEL2 = "ai.openape.nest";
4943
- var uninstallNestCommand = defineCommand36({
4785
+ var uninstallNestCommand = defineCommand35({
4944
4786
  meta: {
4945
4787
  name: "uninstall",
4946
4788
  description: "Stop + remove the local nest-daemon (registry + agents preserved)"
4947
4789
  },
4948
4790
  async run() {
4949
4791
  const uid = userInfo3().uid;
4950
- const path2 = join11(homedir11(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
4792
+ const path2 = join12(homedir12(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
4951
4793
  try {
4952
4794
  execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
4953
- consola33.success("Nest daemon stopped");
4795
+ consola31.success("Nest daemon stopped");
4954
4796
  } catch {
4955
- consola33.info("Nest daemon was not loaded");
4797
+ consola31.info("Nest daemon was not loaded");
4956
4798
  }
4957
- if (existsSync13(path2)) {
4958
- unlinkSync(path2);
4959
- consola33.success(`Removed ${path2}`);
4799
+ if (existsSync14(path2)) {
4800
+ unlinkSync2(path2);
4801
+ consola31.success(`Removed ${path2}`);
4960
4802
  }
4961
- consola33.info("Registry at ~/.openape/nest/agents.json kept \u2014 re-run `apes nest install` to resume supervision.");
4803
+ consola31.info("Registry at ~/.openape/nest/agents.json kept \u2014 re-run `apes nest install` to resume supervision.");
4962
4804
  }
4963
4805
  });
4964
4806
 
4965
4807
  // src/commands/nest/index.ts
4966
- var nestCommand = defineCommand37({
4808
+ var nestCommand = defineCommand36({
4967
4809
  meta: {
4968
4810
  name: "nest",
4969
- description: "Manage the local Nest control-plane daemon. One-time setup: `install` (launchd) \u2192 `enroll` (own DDISA identity) \u2192 `authorize` (YOLO-policy). Day-to-day: `status` / `list` (read-only) and `spawn` / `destroy` (mutating) \u2014 every API call is gated by a DDISA grant audited at the IdP, YOLO-approved silently under the policy `apes nest authorize` sets up."
4811
+ description: "Manage the local Nest control-plane daemon. One-time setup: `install` \u2192 `enroll` \u2192 `authorize`. Day-to-day: `list` / `spawn` / `destroy`. As of Phase D the Nest is a long-running CLIENT \u2014 commands talk to it via filesystem intent files in $NEST_HOME/intents (mode 770, group _openape_nest) instead of HTTP."
4970
4812
  },
4971
4813
  subCommands: {
4972
4814
  install: installNestCommand,
4973
4815
  enroll: enrollNestCommand,
4974
4816
  authorize: authorizeNestCommand,
4975
- status: statusNestCommand,
4976
4817
  list: listNestCommand,
4977
4818
  spawn: spawnNestCommand,
4978
4819
  destroy: destroyNestCommand,
@@ -4981,12 +4822,12 @@ var nestCommand = defineCommand37({
4981
4822
  });
4982
4823
 
4983
4824
  // src/commands/yolo/index.ts
4984
- import { defineCommand as defineCommand41 } from "citty";
4825
+ import { defineCommand as defineCommand40 } from "citty";
4985
4826
 
4986
4827
  // src/commands/yolo/clear.ts
4987
- import { defineCommand as defineCommand38 } from "citty";
4988
- import consola34 from "consola";
4989
- var yoloClearCommand = defineCommand38({
4828
+ import { defineCommand as defineCommand37 } from "citty";
4829
+ import consola32 from "consola";
4830
+ var yoloClearCommand = defineCommand37({
4990
4831
  meta: {
4991
4832
  name: "clear",
4992
4833
  description: "Remove the YOLO-policy from a DDISA agent (subsequent grants need human approval)"
@@ -5015,15 +4856,15 @@ var yoloClearCommand = defineCommand38({
5015
4856
  const text = await res.text().catch(() => "");
5016
4857
  throw new CliError(`DELETE /yolo-policy failed (${res.status}): ${text}`);
5017
4858
  }
5018
- consola34.success(`YOLO-policy cleared on ${email}`);
4859
+ consola32.success(`YOLO-policy cleared on ${email}`);
5019
4860
  }
5020
4861
  });
5021
4862
 
5022
4863
  // src/commands/yolo/set.ts
5023
- import { defineCommand as defineCommand39 } from "citty";
5024
- import consola35 from "consola";
4864
+ import { defineCommand as defineCommand38 } from "citty";
4865
+ import consola33 from "consola";
5025
4866
  var VALID_MODES = ["allow-list", "deny-list"];
5026
- var yoloSetCommand = defineCommand39({
4867
+ var yoloSetCommand = defineCommand38({
5027
4868
  meta: {
5028
4869
  name: "set",
5029
4870
  description: "Write a YOLO-policy on a DDISA agent you own"
@@ -5071,12 +4912,12 @@ var yoloSetCommand = defineCommand39({
5071
4912
  const denyPatterns = parseList(args.deny);
5072
4913
  const denyRiskThreshold = args["deny-risk"] ?? null;
5073
4914
  const expiresAt = parseExpiresIn(args["expires-in"]);
5074
- consola35.info(`Setting YOLO-policy on ${email}`);
5075
- consola35.info(` mode: ${mode}`);
5076
- if (allowPatterns.length) consola35.info(` allow_patterns: ${allowPatterns.join(", ")}`);
5077
- if (denyPatterns.length) consola35.info(` deny_patterns: ${denyPatterns.join(", ")}`);
5078
- if (denyRiskThreshold) consola35.info(` deny_risk: ${denyRiskThreshold}`);
5079
- if (expiresAt) consola35.info(` expires_at: ${new Date(expiresAt * 1e3).toISOString()}`);
4915
+ consola33.info(`Setting YOLO-policy on ${email}`);
4916
+ consola33.info(` mode: ${mode}`);
4917
+ if (allowPatterns.length) consola33.info(` allow_patterns: ${allowPatterns.join(", ")}`);
4918
+ if (denyPatterns.length) consola33.info(` deny_patterns: ${denyPatterns.join(", ")}`);
4919
+ if (denyRiskThreshold) consola33.info(` deny_risk: ${denyRiskThreshold}`);
4920
+ if (expiresAt) consola33.info(` expires_at: ${new Date(expiresAt * 1e3).toISOString()}`);
5080
4921
  const url = `${idp}/api/users/${encodeURIComponent(email)}/yolo-policy`;
5081
4922
  const res = await fetch(url, {
5082
4923
  method: "PUT",
@@ -5096,7 +4937,7 @@ var yoloSetCommand = defineCommand39({
5096
4937
  const text = await res.text().catch(() => "");
5097
4938
  throw new CliError(`PUT /yolo-policy failed (${res.status}): ${text}`);
5098
4939
  }
5099
- consola35.success(`YOLO-policy applied to ${email}`);
4940
+ consola33.success(`YOLO-policy applied to ${email}`);
5100
4941
  }
5101
4942
  });
5102
4943
  function parseList(s) {
@@ -5114,9 +4955,9 @@ function parseExpiresIn(s) {
5114
4955
  }
5115
4956
 
5116
4957
  // src/commands/yolo/show.ts
5117
- import { defineCommand as defineCommand40 } from "citty";
5118
- import consola36 from "consola";
5119
- var yoloShowCommand = defineCommand40({
4958
+ import { defineCommand as defineCommand39 } from "citty";
4959
+ import consola34 from "consola";
4960
+ var yoloShowCommand = defineCommand39({
5120
4961
  meta: {
5121
4962
  name: "show",
5122
4963
  description: "Print the YOLO-policy currently set on a DDISA agent"
@@ -5153,17 +4994,17 @@ var yoloShowCommand = defineCommand40({
5153
4994
  console.log(JSON.stringify(policy, null, 2));
5154
4995
  return;
5155
4996
  }
5156
- consola36.info(`YOLO-policy for ${email}`);
5157
- consola36.info(` mode: ${policy.mode}`);
5158
- consola36.info(` allow_patterns: ${policy.allowPatterns.length ? policy.allowPatterns.join(", ") : "(none)"}`);
5159
- consola36.info(` deny_patterns: ${policy.denyPatterns.length ? policy.denyPatterns.join(", ") : "(none)"}`);
5160
- consola36.info(` deny_risk: ${policy.denyRiskThreshold ?? "(none)"}`);
5161
- consola36.info(` expires_at: ${policy.expiresAt ? new Date(policy.expiresAt * 1e3).toISOString() : "(never)"}`);
4997
+ consola34.info(`YOLO-policy for ${email}`);
4998
+ consola34.info(` mode: ${policy.mode}`);
4999
+ consola34.info(` allow_patterns: ${policy.allowPatterns.length ? policy.allowPatterns.join(", ") : "(none)"}`);
5000
+ consola34.info(` deny_patterns: ${policy.denyPatterns.length ? policy.denyPatterns.join(", ") : "(none)"}`);
5001
+ consola34.info(` deny_risk: ${policy.denyRiskThreshold ?? "(none)"}`);
5002
+ consola34.info(` expires_at: ${policy.expiresAt ? new Date(policy.expiresAt * 1e3).toISOString() : "(never)"}`);
5162
5003
  }
5163
5004
  });
5164
5005
 
5165
5006
  // src/commands/yolo/index.ts
5166
- var yoloCommand = defineCommand41({
5007
+ var yoloCommand = defineCommand40({
5167
5008
  meta: {
5168
5009
  name: "yolo",
5169
5010
  description: "Manage YOLO-policies on DDISA agents you own \u2014 auto-approve grant patterns at the IdP layer (allow-list) or block dangerous ones outright (deny-list)."
@@ -5176,15 +5017,15 @@ var yoloCommand = defineCommand41({
5176
5017
  });
5177
5018
 
5178
5019
  // src/commands/adapter/index.ts
5179
- import { defineCommand as defineCommand42 } from "citty";
5180
- import consola37 from "consola";
5181
- var adapterCommand = defineCommand42({
5020
+ import { defineCommand as defineCommand41 } from "citty";
5021
+ import consola35 from "consola";
5022
+ var adapterCommand = defineCommand41({
5182
5023
  meta: {
5183
5024
  name: "adapter",
5184
5025
  description: "Manage CLI adapters"
5185
5026
  },
5186
5027
  subCommands: {
5187
- list: defineCommand42({
5028
+ list: defineCommand41({
5188
5029
  meta: {
5189
5030
  name: "list",
5190
5031
  description: "List available adapters"
@@ -5215,7 +5056,7 @@ var adapterCommand = defineCommand42({
5215
5056
  `);
5216
5057
  return;
5217
5058
  }
5218
- consola37.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
5059
+ consola35.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
5219
5060
  for (const a of index2.adapters) {
5220
5061
  const installed = isInstalled(a.id, false) ? " [installed]" : "";
5221
5062
  console.log(` ${a.id.padEnd(12)} ${a.name.padEnd(24)} ${a.category}${installed}`);
@@ -5237,7 +5078,7 @@ var adapterCommand = defineCommand42({
5237
5078
  return;
5238
5079
  }
5239
5080
  if (local.length === 0) {
5240
- consola37.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
5081
+ consola35.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
5241
5082
  return;
5242
5083
  }
5243
5084
  for (const a of local) {
@@ -5245,7 +5086,7 @@ var adapterCommand = defineCommand42({
5245
5086
  }
5246
5087
  }
5247
5088
  }),
5248
- install: defineCommand42({
5089
+ install: defineCommand41({
5249
5090
  meta: {
5250
5091
  name: "install",
5251
5092
  description: "Install an adapter from the registry"
@@ -5274,24 +5115,24 @@ var adapterCommand = defineCommand42({
5274
5115
  for (const id of ids) {
5275
5116
  const entry = findAdapter(index, id);
5276
5117
  if (!entry) {
5277
- consola37.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
5118
+ consola35.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
5278
5119
  continue;
5279
5120
  }
5280
5121
  const conflicts = findConflictingAdapters(entry.executable, id);
5281
5122
  if (conflicts.length > 0) {
5282
5123
  for (const c2 of conflicts) {
5283
- consola37.warn(`Conflicting adapter found: ${c2.path} (id: ${c2.adapterId}, executable: ${c2.executable})`);
5284
- consola37.warn(` Remove it with: apes adapter remove ${c2.adapterId}`);
5124
+ consola35.warn(`Conflicting adapter found: ${c2.path} (id: ${c2.adapterId}, executable: ${c2.executable})`);
5125
+ consola35.warn(` Remove it with: apes adapter remove ${c2.adapterId}`);
5285
5126
  }
5286
5127
  }
5287
5128
  const result = await installAdapter(entry, { local });
5288
5129
  const verb = result.updated ? "Updated" : "Installed";
5289
- consola37.success(`${verb} ${result.id} \u2192 ${result.path}`);
5290
- consola37.info(`Digest: ${result.digest}`);
5130
+ consola35.success(`${verb} ${result.id} \u2192 ${result.path}`);
5131
+ consola35.info(`Digest: ${result.digest}`);
5291
5132
  }
5292
5133
  }
5293
5134
  }),
5294
- remove: defineCommand42({
5135
+ remove: defineCommand41({
5295
5136
  meta: {
5296
5137
  name: "remove",
5297
5138
  description: "Remove an installed adapter"
@@ -5314,9 +5155,9 @@ var adapterCommand = defineCommand42({
5314
5155
  let failed = false;
5315
5156
  for (const id of ids) {
5316
5157
  if (removeAdapter(id, local)) {
5317
- consola37.success(`Removed adapter: ${id}`);
5158
+ consola35.success(`Removed adapter: ${id}`);
5318
5159
  } else {
5319
- consola37.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
5160
+ consola35.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
5320
5161
  failed = true;
5321
5162
  }
5322
5163
  }
@@ -5324,7 +5165,7 @@ var adapterCommand = defineCommand42({
5324
5165
  throw new CliError("Some adapters could not be removed");
5325
5166
  }
5326
5167
  }),
5327
- info: defineCommand42({
5168
+ info: defineCommand41({
5328
5169
  meta: {
5329
5170
  name: "info",
5330
5171
  description: "Show detailed adapter information"
@@ -5366,7 +5207,7 @@ var adapterCommand = defineCommand42({
5366
5207
  }
5367
5208
  }
5368
5209
  }),
5369
- search: defineCommand42({
5210
+ search: defineCommand41({
5370
5211
  meta: {
5371
5212
  name: "search",
5372
5213
  description: "Search adapters in the registry"
@@ -5398,7 +5239,7 @@ var adapterCommand = defineCommand42({
5398
5239
  return;
5399
5240
  }
5400
5241
  if (results.length === 0) {
5401
- consola37.info(`No adapters matching "${query}"`);
5242
+ consola35.info(`No adapters matching "${query}"`);
5402
5243
  return;
5403
5244
  }
5404
5245
  for (const a of results) {
@@ -5407,7 +5248,7 @@ var adapterCommand = defineCommand42({
5407
5248
  }
5408
5249
  }
5409
5250
  }),
5410
- update: defineCommand42({
5251
+ update: defineCommand41({
5411
5252
  meta: {
5412
5253
  name: "update",
5413
5254
  description: "Update installed adapters"
@@ -5433,33 +5274,33 @@ var adapterCommand = defineCommand42({
5433
5274
  const targetId = args.id ? String(args.id) : void 0;
5434
5275
  const targets = targetId ? [targetId] : index.adapters.map((a) => a.id).filter((id) => isInstalled(id, false));
5435
5276
  if (targets.length === 0) {
5436
- consola37.info("No adapters installed to update.");
5277
+ consola35.info("No adapters installed to update.");
5437
5278
  return;
5438
5279
  }
5439
5280
  for (const id of targets) {
5440
5281
  const entry = findAdapter(index, id);
5441
5282
  if (!entry) {
5442
- consola37.warn(`${id}: not found in registry, skipping`);
5283
+ consola35.warn(`${id}: not found in registry, skipping`);
5443
5284
  continue;
5444
5285
  }
5445
5286
  const localDigest = getInstalledDigest(id, false);
5446
5287
  if (localDigest === entry.digest) {
5447
- consola37.info(`${id}: already up to date`);
5288
+ consola35.info(`${id}: already up to date`);
5448
5289
  continue;
5449
5290
  }
5450
5291
  if (localDigest && !args.yes) {
5451
- consola37.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
5452
- consola37.info(` Old: ${localDigest}`);
5453
- consola37.info(` New: ${entry.digest}`);
5454
- consola37.info(" Use --yes to confirm");
5292
+ consola35.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
5293
+ consola35.info(` Old: ${localDigest}`);
5294
+ consola35.info(` New: ${entry.digest}`);
5295
+ consola35.info(" Use --yes to confirm");
5455
5296
  continue;
5456
5297
  }
5457
5298
  const result = await installAdapter(entry);
5458
- consola37.success(`Updated ${result.id} \u2192 ${result.path}`);
5299
+ consola35.success(`Updated ${result.id} \u2192 ${result.path}`);
5459
5300
  }
5460
5301
  }
5461
5302
  }),
5462
- verify: defineCommand42({
5303
+ verify: defineCommand41({
5463
5304
  meta: {
5464
5305
  name: "verify",
5465
5306
  description: "Verify installed adapter against registry digest"
@@ -5492,7 +5333,7 @@ var adapterCommand = defineCommand42({
5492
5333
  if (!localDigest)
5493
5334
  throw new Error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
5494
5335
  if (localDigest === entry.digest) {
5495
- consola37.success(`${id}: digest matches registry`);
5336
+ consola35.success(`${id}: digest matches registry`);
5496
5337
  } else {
5497
5338
  console.log(` Local: ${localDigest}`);
5498
5339
  console.log(` Registry: ${entry.digest}`);
@@ -5505,10 +5346,10 @@ var adapterCommand = defineCommand42({
5505
5346
 
5506
5347
  // src/commands/run.ts
5507
5348
  import { execFileSync as execFileSync11 } from "child_process";
5508
- import { hostname as hostname6 } from "os";
5349
+ import { hostname as hostname5 } from "os";
5509
5350
  import { basename } from "path";
5510
- import { defineCommand as defineCommand43 } from "citty";
5511
- import consola38 from "consola";
5351
+ import { defineCommand as defineCommand42 } from "citty";
5352
+ import consola36 from "consola";
5512
5353
  function shouldWaitForGrant(args) {
5513
5354
  return args.wait === true || process.env.APE_WAIT === "1";
5514
5355
  }
@@ -5545,7 +5386,7 @@ function printPendingGrantInfo(grant, idp) {
5545
5386
  const statusCmd = `apes grants status ${grant.id}`;
5546
5387
  const executeCmd = `apes grants run ${grant.id}`;
5547
5388
  if (mode === "human") {
5548
- consola38.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
5389
+ consola36.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
5549
5390
  console.log(` Approve in browser: ${approveUrl}`);
5550
5391
  console.log(` Check status: ${statusCmd}`);
5551
5392
  console.log(` Run after approval: ${executeCmd}`);
@@ -5555,7 +5396,7 @@ function printPendingGrantInfo(grant, idp) {
5555
5396
  return;
5556
5397
  }
5557
5398
  const maxMin = getPollMaxMinutes();
5558
- consola38.success(`Grant ${grant.id} created (pending approval)`);
5399
+ consola36.success(`Grant ${grant.id} created (pending approval)`);
5559
5400
  console.log(` Approve: ${approveUrl}`);
5560
5401
  console.log(` Status: ${statusCmd} [--json]`);
5561
5402
  console.log(` Execute: ${executeCmd} --wait`);
@@ -5577,7 +5418,7 @@ function printPendingGrantInfo(grant, idp) {
5577
5418
  console.log(' Tip: Approve as "timed" or "always" in the browser to let this');
5578
5419
  console.log(" grant be reused on subsequent invocations without re-approval.");
5579
5420
  }
5580
- var runCommand = defineCommand43({
5421
+ var runCommand = defineCommand42({
5581
5422
  meta: {
5582
5423
  name: "run",
5583
5424
  description: "Execute a grant-secured command"
@@ -5666,7 +5507,7 @@ async function runShellMode(command, args) {
5666
5507
  const adapterHandled = await tryAdapterModeFromShell(command, idp, args);
5667
5508
  if (adapterHandled) return;
5668
5509
  const grantsUrl = await getGrantsEndpoint(idp);
5669
- const targetHost = args.host || hostname6();
5510
+ const targetHost = args.host || hostname5();
5670
5511
  try {
5671
5512
  const grants = await apiFetch(
5672
5513
  `${grantsUrl}?requester=${encodeURIComponent(auth.email)}&status=approved&limit=20`
@@ -5680,7 +5521,7 @@ async function runShellMode(command, args) {
5680
5521
  }
5681
5522
  } catch {
5682
5523
  }
5683
- consola38.info(`Requesting ape-shell session grant on ${targetHost}`);
5524
+ consola36.info(`Requesting ape-shell session grant on ${targetHost}`);
5684
5525
  const grant = await apiFetch(grantsUrl, {
5685
5526
  method: "POST",
5686
5527
  body: {
@@ -5700,8 +5541,8 @@ async function runShellMode(command, args) {
5700
5541
  host: targetHost
5701
5542
  });
5702
5543
  if (shouldWaitForGrant(args)) {
5703
- consola38.info(`Grant requested: ${grant.id}`);
5704
- consola38.info("Waiting for approval...");
5544
+ consola36.info(`Grant requested: ${grant.id}`);
5545
+ consola36.info("Waiting for approval...");
5705
5546
  const maxWait = 3e5;
5706
5547
  const interval = 3e3;
5707
5548
  const start = Date.now();
@@ -5732,13 +5573,13 @@ async function tryAdapterModeFromShell(command, idp, args) {
5732
5573
  try {
5733
5574
  resolved = await resolveCommand(loaded, [normalizedExecutable, ...parsed.argv]);
5734
5575
  } catch (err) {
5735
- consola38.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
5576
+ consola36.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
5736
5577
  return false;
5737
5578
  }
5738
5579
  try {
5739
5580
  const existingGrantId = await findExistingGrant(resolved, idp);
5740
5581
  if (existingGrantId) {
5741
- consola38.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
5582
+ consola36.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
5742
5583
  const token = await fetchGrantToken(idp, existingGrantId);
5743
5584
  await verifyAndExecute(token, resolved, existingGrantId);
5744
5585
  return true;
@@ -5746,7 +5587,7 @@ async function tryAdapterModeFromShell(command, idp, args) {
5746
5587
  } catch {
5747
5588
  }
5748
5589
  const approval = args.approval ?? "once";
5749
- consola38.info(`Requesting grant for: ${resolved.detail.display}`);
5590
+ consola36.info(`Requesting grant for: ${resolved.detail.display}`);
5750
5591
  const grant = await createShapesGrant(resolved, {
5751
5592
  idp,
5752
5593
  approval,
@@ -5754,19 +5595,19 @@ async function tryAdapterModeFromShell(command, idp, args) {
5754
5595
  });
5755
5596
  if (grant.similar_grants?.similar_grants?.length) {
5756
5597
  const n2 = grant.similar_grants.similar_grants.length;
5757
- consola38.info("");
5758
- consola38.info(` Similar grant(s) found (${n2}). Your approver can extend an existing grant to cover this request.`);
5598
+ consola36.info("");
5599
+ consola36.info(` Similar grant(s) found (${n2}). Your approver can extend an existing grant to cover this request.`);
5759
5600
  }
5760
5601
  notifyGrantPending({
5761
5602
  grantId: grant.id,
5762
5603
  approveUrl: `${idp}/grant-approval?grant_id=${grant.id}`,
5763
5604
  command: resolved.detail?.display || parsed?.raw || "unknown",
5764
5605
  audience: resolved.adapter?.cli?.audience ?? "shapes",
5765
- host: args.host || hostname6()
5606
+ host: args.host || hostname5()
5766
5607
  });
5767
5608
  if (shouldWaitForGrant(args)) {
5768
- consola38.info(`Grant requested: ${grant.id}`);
5769
- consola38.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
5609
+ consola36.info(`Grant requested: ${grant.id}`);
5610
+ consola36.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
5770
5611
  const status = await waitForGrantStatus(idp, grant.id);
5771
5612
  if (status !== "approved")
5772
5613
  throw new CliError(`Grant ${status}`);
@@ -5840,7 +5681,7 @@ async function runAdapterMode(command, rawArgs, args) {
5840
5681
  try {
5841
5682
  const existingGrantId = await findExistingGrant(resolved, idp);
5842
5683
  if (existingGrantId) {
5843
- consola38.info(`Reusing existing grant: ${existingGrantId}`);
5684
+ consola36.info(`Reusing existing grant: ${existingGrantId}`);
5844
5685
  const token = await fetchGrantToken(idp, existingGrantId);
5845
5686
  await verifyAndExecute(token, resolved, existingGrantId);
5846
5687
  return;
@@ -5854,17 +5695,17 @@ async function runAdapterMode(command, rawArgs, args) {
5854
5695
  });
5855
5696
  if (grant.similar_grants?.similar_grants?.length) {
5856
5697
  const n2 = grant.similar_grants.similar_grants.length;
5857
- consola38.info("");
5858
- consola38.info(` Similar grant(s) found (${n2}). Your approver can extend an existing grant to cover this request.`);
5698
+ consola36.info("");
5699
+ consola36.info(` Similar grant(s) found (${n2}). Your approver can extend an existing grant to cover this request.`);
5859
5700
  if (grant.similar_grants.widened_details?.length) {
5860
5701
  const wider = grant.similar_grants.widened_details.map((d) => d.permission).join(", ");
5861
- consola38.info(` Broader scope: ${wider}`);
5702
+ consola36.info(` Broader scope: ${wider}`);
5862
5703
  }
5863
- consola38.info("");
5704
+ consola36.info("");
5864
5705
  }
5865
5706
  if (shouldWaitForGrant(args)) {
5866
- consola38.info(`Grant requested: ${grant.id}`);
5867
- consola38.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
5707
+ consola36.info(`Grant requested: ${grant.id}`);
5708
+ consola36.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
5868
5709
  const status = await waitForGrantStatus(idp, grant.id);
5869
5710
  if (status !== "approved")
5870
5711
  throw new Error(`Grant ${status}`);
@@ -5883,8 +5724,8 @@ async function runAudienceMode(audience, action, args) {
5883
5724
  const idp = getIdpUrl(args.idp);
5884
5725
  const grantsUrl = await getGrantsEndpoint(idp);
5885
5726
  const command = action.split(" ");
5886
- const targetHost = args.host || hostname6();
5887
- consola38.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
5727
+ const targetHost = args.host || hostname5();
5728
+ consola36.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
5888
5729
  const grant = await apiFetch(grantsUrl, {
5889
5730
  method: "POST",
5890
5731
  body: {
@@ -5901,9 +5742,9 @@ async function runAudienceMode(audience, action, args) {
5901
5742
  printPendingGrantInfo(grant, idp);
5902
5743
  throw new CliExit(getAsyncExitCode());
5903
5744
  }
5904
- consola38.success(`Grant requested: ${grant.id}`);
5905
- consola38.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
5906
- consola38.info("Waiting for approval...");
5745
+ consola36.success(`Grant requested: ${grant.id}`);
5746
+ consola36.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
5747
+ consola36.info("Waiting for approval...");
5907
5748
  const maxWait = 15 * 60 * 1e3;
5908
5749
  const interval = 3e3;
5909
5750
  const start = Date.now();
@@ -5911,7 +5752,7 @@ async function runAudienceMode(audience, action, args) {
5911
5752
  while (Date.now() - start < maxWait) {
5912
5753
  const status = await apiFetch(`${grantsUrl}/${grant.id}`);
5913
5754
  if (status.status === "approved") {
5914
- consola38.success("Grant approved!");
5755
+ consola36.success("Grant approved!");
5915
5756
  approved = true;
5916
5757
  break;
5917
5758
  }
@@ -5926,12 +5767,12 @@ async function runAudienceMode(audience, action, args) {
5926
5767
  `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.`
5927
5768
  );
5928
5769
  }
5929
- consola38.info("Fetching grant token...");
5770
+ consola36.info("Fetching grant token...");
5930
5771
  const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, {
5931
5772
  method: "POST"
5932
5773
  });
5933
5774
  if (audience === "escapes") {
5934
- consola38.info(`Executing: ${command.join(" ")}`);
5775
+ consola36.info(`Executing: ${command.join(" ")}`);
5935
5776
  try {
5936
5777
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
5937
5778
  execFileSync11(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
@@ -5949,8 +5790,8 @@ async function runAudienceMode(audience, action, args) {
5949
5790
 
5950
5791
  // src/commands/proxy.ts
5951
5792
  import { spawn as spawn2 } from "child_process";
5952
- import { defineCommand as defineCommand44 } from "citty";
5953
- import consola39 from "consola";
5793
+ import { defineCommand as defineCommand43 } from "citty";
5794
+ import consola37 from "consola";
5954
5795
 
5955
5796
  // src/proxy/config.ts
5956
5797
  function buildDefaultProxyConfigToml(opts) {
@@ -5984,10 +5825,10 @@ note = "VPC-internal hostname suffix"
5984
5825
 
5985
5826
  // src/proxy/local-proxy.ts
5986
5827
  import { spawn } from "child_process";
5987
- import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
5828
+ import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
5988
5829
  import { createRequire } from "module";
5989
5830
  import { tmpdir as tmpdir3 } from "os";
5990
- import { dirname as dirname4, join as join12, resolve as resolve3 } from "path";
5831
+ import { dirname as dirname4, join as join13, resolve as resolve3 } from "path";
5991
5832
  var require2 = createRequire(import.meta.url);
5992
5833
  function findProxyBin() {
5993
5834
  const pkgPath = require2.resolve("@openape/proxy/package.json");
@@ -5999,9 +5840,9 @@ function findProxyBin() {
5999
5840
  return resolve3(dirname4(pkgPath), binRel);
6000
5841
  }
6001
5842
  async function startEphemeralProxy(configToml) {
6002
- const tmpDir = mkdtempSync3(join12(tmpdir3(), "openape-proxy-"));
6003
- const configPath = join12(tmpDir, "config.toml");
6004
- writeFileSync7(configPath, configToml, { mode: 384 });
5843
+ const tmpDir = mkdtempSync3(join13(tmpdir3(), "openape-proxy-"));
5844
+ const configPath = join13(tmpDir, "config.toml");
5845
+ writeFileSync8(configPath, configToml, { mode: 384 });
6005
5846
  const binPath = findProxyBin();
6006
5847
  const child = spawn(process.execPath, [binPath, "-c", configPath], {
6007
5848
  stdio: ["ignore", "pipe", "pipe"],
@@ -6093,10 +5934,10 @@ function resolveProxyConfigOptions() {
6093
5934
  77
6094
5935
  );
6095
5936
  }
6096
- consola39.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
5937
+ consola37.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
6097
5938
  return { agentEmail: auth.email, idpUrl: auth.idp, mediated: true };
6098
5939
  }
6099
- var proxyCommand = defineCommand44({
5940
+ var proxyCommand = defineCommand43({
6100
5941
  meta: {
6101
5942
  name: "proxy",
6102
5943
  description: "Run a command with HTTPS_PROXY routed through the OpenApe egress proxy."
@@ -6118,12 +5959,12 @@ var proxyCommand = defineCommand44({
6118
5959
  let close = null;
6119
5960
  if (reuseUrl) {
6120
5961
  proxyUrl = reuseUrl;
6121
- consola39.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
5962
+ consola37.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
6122
5963
  } else {
6123
5964
  const ephemeral = await startEphemeralProxy(buildDefaultProxyConfigToml(resolveProxyConfigOptions()));
6124
5965
  proxyUrl = ephemeral.url;
6125
5966
  close = ephemeral.close;
6126
- consola39.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
5967
+ consola37.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
6127
5968
  }
6128
5969
  const noProxy = process.env.NO_PROXY ?? process.env.no_proxy ?? "127.0.0.1,localhost";
6129
5970
  const childEnv = {
@@ -6155,7 +5996,7 @@ var proxyCommand = defineCommand44({
6155
5996
  else resolveExit(code ?? 0);
6156
5997
  });
6157
5998
  child.once("error", (err) => {
6158
- consola39.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
5999
+ consola37.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
6159
6000
  resolveExit(127);
6160
6001
  });
6161
6002
  });
@@ -6169,8 +6010,8 @@ function signalNumber(signal) {
6169
6010
  }
6170
6011
 
6171
6012
  // src/commands/explain.ts
6172
- import { defineCommand as defineCommand45 } from "citty";
6173
- var explainCommand = defineCommand45({
6013
+ import { defineCommand as defineCommand44 } from "citty";
6014
+ var explainCommand = defineCommand44({
6174
6015
  meta: {
6175
6016
  name: "explain",
6176
6017
  description: "Show what permission a command would need"
@@ -6208,9 +6049,9 @@ var explainCommand = defineCommand45({
6208
6049
  });
6209
6050
 
6210
6051
  // src/commands/config/get.ts
6211
- import { defineCommand as defineCommand46 } from "citty";
6212
- import consola40 from "consola";
6213
- var configGetCommand = defineCommand46({
6052
+ import { defineCommand as defineCommand45 } from "citty";
6053
+ import consola38 from "consola";
6054
+ var configGetCommand = defineCommand45({
6214
6055
  meta: {
6215
6056
  name: "get",
6216
6057
  description: "Get a configuration value"
@@ -6230,7 +6071,7 @@ var configGetCommand = defineCommand46({
6230
6071
  if (idp)
6231
6072
  console.log(idp);
6232
6073
  else
6233
- consola40.info("No IdP configured.");
6074
+ consola38.info("No IdP configured.");
6234
6075
  break;
6235
6076
  }
6236
6077
  case "email": {
@@ -6238,7 +6079,7 @@ var configGetCommand = defineCommand46({
6238
6079
  if (auth?.email)
6239
6080
  console.log(auth.email);
6240
6081
  else
6241
- consola40.info("Not logged in.");
6082
+ consola38.info("Not logged in.");
6242
6083
  break;
6243
6084
  }
6244
6085
  default: {
@@ -6251,7 +6092,7 @@ var configGetCommand = defineCommand46({
6251
6092
  if (sectionObj && field in sectionObj) {
6252
6093
  console.log(sectionObj[field]);
6253
6094
  } else {
6254
- consola40.info(`Key "${key}" not set.`);
6095
+ consola38.info(`Key "${key}" not set.`);
6255
6096
  }
6256
6097
  } else {
6257
6098
  throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
@@ -6262,9 +6103,9 @@ var configGetCommand = defineCommand46({
6262
6103
  });
6263
6104
 
6264
6105
  // src/commands/config/set.ts
6265
- import { defineCommand as defineCommand47 } from "citty";
6266
- import consola41 from "consola";
6267
- var configSetCommand = defineCommand47({
6106
+ import { defineCommand as defineCommand46 } from "citty";
6107
+ import consola39 from "consola";
6108
+ var configSetCommand = defineCommand46({
6268
6109
  meta: {
6269
6110
  name: "set",
6270
6111
  description: "Set a configuration value"
@@ -6300,12 +6141,12 @@ var configSetCommand = defineCommand47({
6300
6141
  throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
6301
6142
  }
6302
6143
  saveConfig(config);
6303
- consola41.success(`Set ${key} = ${value}`);
6144
+ consola39.success(`Set ${key} = ${value}`);
6304
6145
  }
6305
6146
  });
6306
6147
 
6307
6148
  // src/commands/fetch/index.ts
6308
- import { defineCommand as defineCommand48 } from "citty";
6149
+ import { defineCommand as defineCommand47 } from "citty";
6309
6150
  async function doRequest(method, url, body, contentType, raw, showHeaders) {
6310
6151
  const token = getAuthToken();
6311
6152
  if (!token) {
@@ -6341,13 +6182,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
6341
6182
  throw new CliError(`HTTP ${response.status} ${response.statusText}`);
6342
6183
  }
6343
6184
  }
6344
- var fetchCommand = defineCommand48({
6185
+ var fetchCommand = defineCommand47({
6345
6186
  meta: {
6346
6187
  name: "fetch",
6347
6188
  description: "Make authenticated HTTP requests"
6348
6189
  },
6349
6190
  subCommands: {
6350
- get: defineCommand48({
6191
+ get: defineCommand47({
6351
6192
  meta: {
6352
6193
  name: "get",
6353
6194
  description: "GET request with auth token"
@@ -6373,7 +6214,7 @@ var fetchCommand = defineCommand48({
6373
6214
  await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
6374
6215
  }
6375
6216
  }),
6376
- post: defineCommand48({
6217
+ post: defineCommand47({
6377
6218
  meta: {
6378
6219
  name: "post",
6379
6220
  description: "POST request with auth token"
@@ -6412,8 +6253,8 @@ var fetchCommand = defineCommand48({
6412
6253
  });
6413
6254
 
6414
6255
  // src/commands/mcp/index.ts
6415
- import { defineCommand as defineCommand49 } from "citty";
6416
- var mcpCommand = defineCommand49({
6256
+ import { defineCommand as defineCommand48 } from "citty";
6257
+ var mcpCommand = defineCommand48({
6417
6258
  meta: {
6418
6259
  name: "mcp",
6419
6260
  description: "Start MCP server for AI agents"
@@ -6436,25 +6277,25 @@ var mcpCommand = defineCommand49({
6436
6277
  if (transport !== "stdio" && transport !== "sse") {
6437
6278
  throw new Error('Transport must be "stdio" or "sse"');
6438
6279
  }
6439
- const { startMcpServer } = await import("./server-F3ALNNYS.js");
6280
+ const { startMcpServer } = await import("./server-TGGXHP4H.js");
6440
6281
  await startMcpServer(transport, port);
6441
6282
  }
6442
6283
  });
6443
6284
 
6444
6285
  // src/commands/init/index.ts
6445
- import { existsSync as existsSync14, copyFileSync, writeFileSync as writeFileSync8 } from "fs";
6286
+ import { existsSync as existsSync15, copyFileSync, writeFileSync as writeFileSync9 } from "fs";
6446
6287
  import { randomBytes } from "crypto";
6447
6288
  import { execFileSync as execFileSync12 } from "child_process";
6448
- import { join as join13 } from "path";
6449
- import { defineCommand as defineCommand50 } from "citty";
6450
- import consola42 from "consola";
6289
+ import { join as join14 } from "path";
6290
+ import { defineCommand as defineCommand49 } from "citty";
6291
+ import consola40 from "consola";
6451
6292
  var DEFAULT_IDP_URL = "https://id.openape.at";
6452
6293
  async function downloadTemplate(repo, targetDir) {
6453
6294
  const { downloadTemplate: gigetDownload } = await import("giget");
6454
6295
  await gigetDownload(`gh:${repo}`, { dir: targetDir, force: false });
6455
6296
  }
6456
6297
  function installDeps(dir) {
6457
- const hasLockFile = (name) => existsSync14(join13(dir, name));
6298
+ const hasLockFile = (name) => existsSync15(join14(dir, name));
6458
6299
  if (hasLockFile("pnpm-lock.yaml")) {
6459
6300
  execFileSync12("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
6460
6301
  } else if (hasLockFile("bun.lockb")) {
@@ -6464,20 +6305,20 @@ function installDeps(dir) {
6464
6305
  }
6465
6306
  }
6466
6307
  async function promptChoice(message, choices) {
6467
- const result = await consola42.prompt(message, { type: "select", options: choices });
6308
+ const result = await consola40.prompt(message, { type: "select", options: choices });
6468
6309
  if (typeof result === "symbol") {
6469
6310
  throw new CliExit(0);
6470
6311
  }
6471
6312
  return result;
6472
6313
  }
6473
6314
  async function promptText(message, defaultValue) {
6474
- const result = await consola42.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
6315
+ const result = await consola40.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
6475
6316
  if (typeof result === "symbol") {
6476
6317
  throw new CliExit(0);
6477
6318
  }
6478
6319
  return result || defaultValue || "";
6479
6320
  }
6480
- var initCommand = defineCommand50({
6321
+ var initCommand = defineCommand49({
6481
6322
  meta: {
6482
6323
  name: "init",
6483
6324
  description: "Scaffold a new OpenApe project"
@@ -6519,23 +6360,23 @@ var initCommand = defineCommand50({
6519
6360
  });
6520
6361
  async function initSP(targetDir) {
6521
6362
  const dir = targetDir || "my-app";
6522
- if (existsSync14(join13(dir, "package.json"))) {
6363
+ if (existsSync15(join14(dir, "package.json"))) {
6523
6364
  throw new CliError(`Directory "${dir}" already contains a project.`);
6524
6365
  }
6525
- consola42.start("Scaffolding SP starter...");
6366
+ consola40.start("Scaffolding SP starter...");
6526
6367
  await downloadTemplate("openape-ai/openape-sp-starter", dir);
6527
- consola42.success("Scaffolded from openape-sp-starter");
6528
- consola42.start("Installing dependencies...");
6368
+ consola40.success("Scaffolded from openape-sp-starter");
6369
+ consola40.start("Installing dependencies...");
6529
6370
  installDeps(dir);
6530
- consola42.success("Dependencies installed");
6531
- const envExample = join13(dir, ".env.example");
6532
- const envFile = join13(dir, ".env");
6533
- if (existsSync14(envExample) && !existsSync14(envFile)) {
6371
+ consola40.success("Dependencies installed");
6372
+ const envExample = join14(dir, ".env.example");
6373
+ const envFile = join14(dir, ".env");
6374
+ if (existsSync15(envExample) && !existsSync15(envFile)) {
6534
6375
  copyFileSync(envExample, envFile);
6535
- consola42.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
6376
+ consola40.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
6536
6377
  }
6537
6378
  console.log("");
6538
- consola42.box([
6379
+ consola40.box([
6539
6380
  `cd ${dir}`,
6540
6381
  "npm run dev",
6541
6382
  "",
@@ -6544,7 +6385,7 @@ async function initSP(targetDir) {
6544
6385
  }
6545
6386
  async function initIdP(targetDir) {
6546
6387
  const dir = targetDir || "my-idp";
6547
- if (existsSync14(join13(dir, "package.json"))) {
6388
+ if (existsSync15(join14(dir, "package.json"))) {
6548
6389
  throw new CliError(`Directory "${dir}" already contains a project.`);
6549
6390
  }
6550
6391
  const domain = await promptText("Domain for the IdP", "localhost");
@@ -6554,15 +6395,15 @@ async function initIdP(targetDir) {
6554
6395
  "s3 (S3-compatible)"
6555
6396
  ]);
6556
6397
  const adminEmail = await promptText("Admin email");
6557
- consola42.start("Scaffolding IdP starter...");
6398
+ consola40.start("Scaffolding IdP starter...");
6558
6399
  await downloadTemplate("openape-ai/openape-idp-starter", dir);
6559
- consola42.success("Scaffolded from openape-idp-starter");
6560
- consola42.start("Installing dependencies...");
6400
+ consola40.success("Scaffolded from openape-idp-starter");
6401
+ consola40.start("Installing dependencies...");
6561
6402
  installDeps(dir);
6562
- consola42.success("Dependencies installed");
6403
+ consola40.success("Dependencies installed");
6563
6404
  const sessionSecret = randomBytes(32).toString("hex");
6564
6405
  const managementToken = randomBytes(32).toString("hex");
6565
- consola42.success("Secrets generated");
6406
+ consola40.success("Secrets generated");
6566
6407
  const isLocalhost = domain === "localhost";
6567
6408
  const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
6568
6409
  const envContent = [
@@ -6576,11 +6417,11 @@ async function initIdP(targetDir) {
6576
6417
  `NUXT_OPENAPE_RP_ID=${domain}`,
6577
6418
  `NUXT_OPENAPE_RP_ORIGIN=${origin}`
6578
6419
  ].join("\n");
6579
- writeFileSync8(join13(dir, ".env"), `${envContent}
6420
+ writeFileSync9(join14(dir, ".env"), `${envContent}
6580
6421
  `, { mode: 384 });
6581
- consola42.success(".env created");
6422
+ consola40.success(".env created");
6582
6423
  console.log("");
6583
- consola42.box([
6424
+ consola40.box([
6584
6425
  `cd ${dir}`,
6585
6426
  "npm run dev",
6586
6427
  "",
@@ -6597,11 +6438,11 @@ async function initIdP(targetDir) {
6597
6438
 
6598
6439
  // src/commands/enroll.ts
6599
6440
  import { Buffer as Buffer5 } from "buffer";
6600
- import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
6441
+ import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
6601
6442
  import { execFile as execFile2 } from "child_process";
6602
6443
  import { sign as sign2 } from "crypto";
6603
- import { defineCommand as defineCommand51 } from "citty";
6604
- import consola43 from "consola";
6444
+ import { defineCommand as defineCommand50 } from "citty";
6445
+ import consola41 from "consola";
6605
6446
  var DEFAULT_IDP_URL2 = "https://id.openape.at";
6606
6447
  var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
6607
6448
  var POLL_INTERVAL = 3e3;
@@ -6613,7 +6454,7 @@ function openBrowser2(url) {
6613
6454
  }
6614
6455
  async function pollForEnrollment(idp, agentEmail, keyPath) {
6615
6456
  const resolvedKey = resolveKeyPath(keyPath);
6616
- const keyContent = readFileSync11(resolvedKey, "utf-8");
6457
+ const keyContent = readFileSync12(resolvedKey, "utf-8");
6617
6458
  const privateKey = loadEd25519PrivateKey(keyContent);
6618
6459
  const challengeUrl = await getAgentChallengeEndpoint(idp);
6619
6460
  const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
@@ -6644,7 +6485,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
6644
6485
  }
6645
6486
  throw new Error("Enrollment timed out. Please check the browser and try again.");
6646
6487
  }
6647
- var enrollCommand = defineCommand51({
6488
+ var enrollCommand = defineCommand50({
6648
6489
  meta: {
6649
6490
  name: "enroll",
6650
6491
  description: "Enroll an agent with an Identity Provider"
@@ -6664,38 +6505,38 @@ var enrollCommand = defineCommand51({
6664
6505
  }
6665
6506
  },
6666
6507
  async run({ args }) {
6667
- const idp = args.idp || await consola43.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r3) => {
6508
+ const idp = args.idp || await consola41.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r3) => {
6668
6509
  if (typeof r3 === "symbol") throw new CliExit(0);
6669
6510
  return r3;
6670
6511
  }) || DEFAULT_IDP_URL2;
6671
- const agentName = args.name || await consola43.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r3) => {
6512
+ const agentName = args.name || await consola41.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r3) => {
6672
6513
  if (typeof r3 === "symbol") throw new CliExit(0);
6673
6514
  return r3;
6674
6515
  });
6675
6516
  if (!agentName) {
6676
6517
  throw new CliError("Agent name is required.");
6677
6518
  }
6678
- const keyPath = args.key || await consola43.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r3) => {
6519
+ const keyPath = args.key || await consola41.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r3) => {
6679
6520
  if (typeof r3 === "symbol") throw new CliExit(0);
6680
6521
  return r3;
6681
6522
  }) || DEFAULT_KEY_PATH;
6682
6523
  const resolvedKey = resolveKeyPath(keyPath);
6683
6524
  let publicKey;
6684
- if (existsSync15(resolvedKey)) {
6525
+ if (existsSync16(resolvedKey)) {
6685
6526
  publicKey = readPublicKey(resolvedKey);
6686
- consola43.success(`Using existing key ${keyPath}`);
6527
+ consola41.success(`Using existing key ${keyPath}`);
6687
6528
  } else {
6688
- consola43.start(`Generating Ed25519 key pair at ${keyPath}...`);
6529
+ consola41.start(`Generating Ed25519 key pair at ${keyPath}...`);
6689
6530
  publicKey = generateAndSaveKey(keyPath);
6690
- consola43.success(`Key pair generated at ${keyPath}`);
6531
+ consola41.success(`Key pair generated at ${keyPath}`);
6691
6532
  }
6692
6533
  const encodedKey = encodeURIComponent(publicKey);
6693
6534
  const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
6694
- consola43.info("Opening browser for enrollment...");
6695
- consola43.info(`\u2192 ${idp}/enroll`);
6535
+ consola41.info("Opening browser for enrollment...");
6536
+ consola41.info(`\u2192 ${idp}/enroll`);
6696
6537
  openBrowser2(enrollUrl);
6697
6538
  console.log("");
6698
- const agentEmail = await consola43.prompt(
6539
+ const agentEmail = await consola41.prompt(
6699
6540
  "Agent email (shown in browser after enrollment)",
6700
6541
  { type: "text", placeholder: `agent+${agentName}@...` }
6701
6542
  ).then((r3) => {
@@ -6705,7 +6546,7 @@ var enrollCommand = defineCommand51({
6705
6546
  if (!agentEmail) {
6706
6547
  throw new CliError("Agent email is required to verify enrollment.");
6707
6548
  }
6708
- consola43.start("Verifying enrollment...");
6549
+ consola41.start("Verifying enrollment...");
6709
6550
  const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
6710
6551
  saveAuth({
6711
6552
  idp,
@@ -6717,18 +6558,18 @@ var enrollCommand = defineCommand51({
6717
6558
  config.defaults = { ...config.defaults, idp };
6718
6559
  config.agent = { key: keyPath, email: agentEmail };
6719
6560
  saveConfig(config);
6720
- consola43.success(`Agent enrolled as ${agentEmail}`);
6721
- consola43.success("Config saved to ~/.config/apes/");
6561
+ consola41.success(`Agent enrolled as ${agentEmail}`);
6562
+ consola41.success("Config saved to ~/.config/apes/");
6722
6563
  console.log("");
6723
- consola43.info("Verify with: apes whoami");
6564
+ consola41.info("Verify with: apes whoami");
6724
6565
  }
6725
6566
  });
6726
6567
 
6727
6568
  // src/commands/register-user.ts
6728
- import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
6729
- import { defineCommand as defineCommand52 } from "citty";
6730
- import consola44 from "consola";
6731
- var registerUserCommand = defineCommand52({
6569
+ import { existsSync as existsSync17, readFileSync as readFileSync13 } from "fs";
6570
+ import { defineCommand as defineCommand51 } from "citty";
6571
+ import consola42 from "consola";
6572
+ var registerUserCommand = defineCommand51({
6732
6573
  meta: {
6733
6574
  name: "register-user",
6734
6575
  description: "Register a sub-user with SSH key"
@@ -6764,8 +6605,8 @@ var registerUserCommand = defineCommand52({
6764
6605
  throw new CliError("No IdP URL configured. Run `apes login` first.");
6765
6606
  }
6766
6607
  let publicKey = args.key;
6767
- if (existsSync16(args.key)) {
6768
- publicKey = readFileSync12(args.key, "utf-8").trim();
6608
+ if (existsSync17(args.key)) {
6609
+ publicKey = readFileSync13(args.key, "utf-8").trim();
6769
6610
  }
6770
6611
  if (!publicKey.startsWith("ssh-ed25519 ")) {
6771
6612
  throw new CliError("Public key must be in ssh-ed25519 format.");
@@ -6783,18 +6624,18 @@ var registerUserCommand = defineCommand52({
6783
6624
  ...userType ? { type: userType } : {}
6784
6625
  }
6785
6626
  });
6786
- consola44.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
6627
+ consola42.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
6787
6628
  }
6788
6629
  });
6789
6630
 
6790
6631
  // src/commands/utils/index.ts
6791
- import { defineCommand as defineCommand54 } from "citty";
6632
+ import { defineCommand as defineCommand53 } from "citty";
6792
6633
 
6793
6634
  // src/commands/utils/dig.ts
6794
- import { defineCommand as defineCommand53 } from "citty";
6795
- import consola45 from "consola";
6635
+ import { defineCommand as defineCommand52 } from "citty";
6636
+ import consola43 from "consola";
6796
6637
  import { resolveDDISA as resolveDDISA2 } from "@openape/core";
6797
- var digCommand = defineCommand53({
6638
+ var digCommand = defineCommand52({
6798
6639
  meta: {
6799
6640
  name: "dig",
6800
6641
  description: "Resolve DDISA IdP for a domain or email (admin/diag tool)"
@@ -6867,12 +6708,12 @@ var digCommand = defineCommand53({
6867
6708
  console.log(` domain: ${domain}`);
6868
6709
  console.log("");
6869
6710
  if (!result.ddisa.found) {
6870
- consola45.warn(`No DDISA record at _ddisa.${domain}`);
6711
+ consola43.warn(`No DDISA record at _ddisa.${domain}`);
6871
6712
  if (result.hint) console.log(`
6872
6713
  ${result.hint}`);
6873
6714
  throw new CliError(`No DDISA record found for ${domain}`);
6874
6715
  }
6875
- consola45.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
6716
+ consola43.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
6876
6717
  console.log(` Version: ${result.ddisa.version || "ddisa1"}`);
6877
6718
  console.log(` IdP URL: ${result.ddisa.idp}`);
6878
6719
  if (result.ddisa.mode) console.log(` Mode: ${result.ddisa.mode}`);
@@ -6882,13 +6723,13 @@ ${result.hint}`);
6882
6723
  return;
6883
6724
  }
6884
6725
  if (result.idpDiscovery.ok) {
6885
- consola45.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
6726
+ consola43.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
6886
6727
  if (result.idpDiscovery.issuer) console.log(` Issuer: ${result.idpDiscovery.issuer}`);
6887
6728
  if (result.idpDiscovery.ddisaVersion) console.log(` DDISA: v${result.idpDiscovery.ddisaVersion}`);
6888
6729
  if (result.idpDiscovery.authMethods?.length) console.log(` Auth: ${result.idpDiscovery.authMethods.join(", ")}`);
6889
6730
  if (result.idpDiscovery.grantTypes?.length) console.log(` Grants: ${result.idpDiscovery.grantTypes.join(", ")}`);
6890
6731
  } else {
6891
- consola45.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
6732
+ consola43.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
6892
6733
  if (result.hint) console.log(`
6893
6734
  ${result.hint}`);
6894
6735
  throw new CliError(`IdP at ${result.ddisa.idp} not reachable`);
@@ -6897,7 +6738,7 @@ ${result.hint}`);
6897
6738
  });
6898
6739
 
6899
6740
  // src/commands/utils/index.ts
6900
- var utilsCommand = defineCommand54({
6741
+ var utilsCommand = defineCommand53({
6901
6742
  meta: {
6902
6743
  name: "utils",
6903
6744
  description: "Admin/diagnostic utilities (dig, \u2026)"
@@ -6908,12 +6749,12 @@ var utilsCommand = defineCommand54({
6908
6749
  });
6909
6750
 
6910
6751
  // src/commands/sessions/index.ts
6911
- import { defineCommand as defineCommand57 } from "citty";
6752
+ import { defineCommand as defineCommand56 } from "citty";
6912
6753
 
6913
6754
  // src/commands/sessions/list.ts
6914
- import { defineCommand as defineCommand55 } from "citty";
6915
- import consola46 from "consola";
6916
- var sessionsListCommand = defineCommand55({
6755
+ import { defineCommand as defineCommand54 } from "citty";
6756
+ import consola44 from "consola";
6757
+ var sessionsListCommand = defineCommand54({
6917
6758
  meta: {
6918
6759
  name: "list",
6919
6760
  description: "List your active refresh-token families (one per logged-in device)."
@@ -6931,7 +6772,7 @@ var sessionsListCommand = defineCommand55({
6931
6772
  return;
6932
6773
  }
6933
6774
  if (result.data.length === 0) {
6934
- consola46.info("No active sessions.");
6775
+ consola44.info("No active sessions.");
6935
6776
  return;
6936
6777
  }
6937
6778
  for (const f of result.data) {
@@ -6943,9 +6784,9 @@ var sessionsListCommand = defineCommand55({
6943
6784
  });
6944
6785
 
6945
6786
  // src/commands/sessions/remove.ts
6946
- import { defineCommand as defineCommand56 } from "citty";
6947
- import consola47 from "consola";
6948
- var sessionsRemoveCommand = defineCommand56({
6787
+ import { defineCommand as defineCommand55 } from "citty";
6788
+ import consola45 from "consola";
6789
+ var sessionsRemoveCommand = defineCommand55({
6949
6790
  meta: {
6950
6791
  name: "remove",
6951
6792
  description: "Revoke one of your active refresh-token families by id."
@@ -6961,12 +6802,12 @@ var sessionsRemoveCommand = defineCommand56({
6961
6802
  const id = String(args.familyId).trim();
6962
6803
  if (!id) throw new CliError("familyId required");
6963
6804
  await apiFetch(`/api/me/sessions/${encodeURIComponent(id)}`, { method: "DELETE" });
6964
- consola47.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
6805
+ consola45.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
6965
6806
  }
6966
6807
  });
6967
6808
 
6968
6809
  // src/commands/sessions/index.ts
6969
- var sessionsCommand = defineCommand57({
6810
+ var sessionsCommand = defineCommand56({
6970
6811
  meta: {
6971
6812
  name: "sessions",
6972
6813
  description: "Manage your active refresh-token sessions across devices"
@@ -6978,10 +6819,10 @@ var sessionsCommand = defineCommand57({
6978
6819
  });
6979
6820
 
6980
6821
  // src/commands/dns-check.ts
6981
- import { defineCommand as defineCommand58 } from "citty";
6982
- import consola48 from "consola";
6822
+ import { defineCommand as defineCommand57 } from "citty";
6823
+ import consola46 from "consola";
6983
6824
  import { resolveDDISA as resolveDDISA3 } from "@openape/core";
6984
- var dnsCheckCommand = defineCommand58({
6825
+ var dnsCheckCommand = defineCommand57({
6985
6826
  meta: {
6986
6827
  name: "dns-check",
6987
6828
  description: "Validate DDISA DNS TXT records for a domain"
@@ -6995,7 +6836,7 @@ var dnsCheckCommand = defineCommand58({
6995
6836
  },
6996
6837
  async run({ args }) {
6997
6838
  const domain = args.domain;
6998
- consola48.start(`Checking _ddisa.${domain}...`);
6839
+ consola46.start(`Checking _ddisa.${domain}...`);
6999
6840
  try {
7000
6841
  const result = await resolveDDISA3(domain);
7001
6842
  if (!result) {
@@ -7004,7 +6845,7 @@ var dnsCheckCommand = defineCommand58({
7004
6845
  console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
7005
6846
  throw new CliError(`No DDISA record found for ${domain}`);
7006
6847
  }
7007
- consola48.success(`_ddisa.${domain} \u2192 ${result.idp}`);
6848
+ consola46.success(`_ddisa.${domain} \u2192 ${result.idp}`);
7008
6849
  console.log("");
7009
6850
  console.log(` Version: ${result.version || "ddisa1"}`);
7010
6851
  console.log(` IdP URL: ${result.idp}`);
@@ -7013,14 +6854,14 @@ var dnsCheckCommand = defineCommand58({
7013
6854
  if (result.priority !== void 0)
7014
6855
  console.log(` Priority: ${result.priority}`);
7015
6856
  console.log("");
7016
- consola48.start(`Verifying IdP at ${result.idp}...`);
6857
+ consola46.start(`Verifying IdP at ${result.idp}...`);
7017
6858
  const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
7018
6859
  if (!discoResp.ok) {
7019
- consola48.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
6860
+ consola46.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
7020
6861
  return;
7021
6862
  }
7022
6863
  const disco = await discoResp.json();
7023
- consola48.success(`IdP is reachable`);
6864
+ consola46.success(`IdP is reachable`);
7024
6865
  console.log(` Issuer: ${disco.issuer}`);
7025
6866
  console.log(` DDISA: v${disco.ddisa_version || "?"}`);
7026
6867
  if (disco.ddisa_auth_methods_supported) {
@@ -7038,7 +6879,7 @@ var dnsCheckCommand = defineCommand58({
7038
6879
  // src/commands/health.ts
7039
6880
  import { exec } from "child_process";
7040
6881
  import { promisify } from "util";
7041
- import { defineCommand as defineCommand59 } from "citty";
6882
+ import { defineCommand as defineCommand58 } from "citty";
7042
6883
  var execAsync = promisify(exec);
7043
6884
  async function resolveApeShellPath() {
7044
6885
  try {
@@ -7074,7 +6915,7 @@ async function bestEffortGrantCount(idp) {
7074
6915
  }
7075
6916
  }
7076
6917
  async function runHealth(args) {
7077
- const version = true ? "1.11.0" : "0.0.0";
6918
+ const version = true ? "1.12.0" : "0.0.0";
7078
6919
  const auth = loadAuth();
7079
6920
  if (!auth) {
7080
6921
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -7137,7 +6978,7 @@ async function runHealth(args) {
7137
6978
  throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
7138
6979
  }
7139
6980
  }
7140
- var healthCommand = defineCommand59({
6981
+ var healthCommand = defineCommand58({
7141
6982
  meta: {
7142
6983
  name: "health",
7143
6984
  description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
@@ -7155,8 +6996,8 @@ var healthCommand = defineCommand59({
7155
6996
  });
7156
6997
 
7157
6998
  // src/commands/workflows.ts
7158
- import { defineCommand as defineCommand60 } from "citty";
7159
- import consola49 from "consola";
6999
+ import { defineCommand as defineCommand59 } from "citty";
7000
+ import consola47 from "consola";
7160
7001
 
7161
7002
  // src/guides/index.ts
7162
7003
  var guides = [
@@ -7206,7 +7047,7 @@ var guides = [
7206
7047
  ];
7207
7048
 
7208
7049
  // src/commands/workflows.ts
7209
- var workflowsCommand = defineCommand60({
7050
+ var workflowsCommand = defineCommand59({
7210
7051
  meta: {
7211
7052
  name: "workflows",
7212
7053
  description: "Discover workflow guides"
@@ -7227,7 +7068,7 @@ var workflowsCommand = defineCommand60({
7227
7068
  if (args.id) {
7228
7069
  const guide = guides.find((g) => g.id === String(args.id));
7229
7070
  if (!guide) {
7230
- consola49.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
7071
+ consola47.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
7231
7072
  throw new CliError(`Guide not found: ${args.id}`);
7232
7073
  }
7233
7074
  if (args.json) {
@@ -7267,26 +7108,26 @@ var workflowsCommand = defineCommand60({
7267
7108
  });
7268
7109
 
7269
7110
  // src/version-check.ts
7270
- import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
7271
- import { homedir as homedir12 } from "os";
7272
- import { join as join14 } from "path";
7273
- import consola50 from "consola";
7111
+ import { existsSync as existsSync18, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "fs";
7112
+ import { homedir as homedir13 } from "os";
7113
+ import { join as join15 } from "path";
7114
+ import consola48 from "consola";
7274
7115
  var PACKAGE_NAME = "@openape/apes";
7275
7116
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
7276
- var CACHE_FILE = join14(homedir12(), ".config", "apes", ".version-check.json");
7117
+ var CACHE_FILE = join15(homedir13(), ".config", "apes", ".version-check.json");
7277
7118
  function readCache() {
7278
- if (!existsSync17(CACHE_FILE)) return null;
7119
+ if (!existsSync18(CACHE_FILE)) return null;
7279
7120
  try {
7280
- return JSON.parse(readFileSync13(CACHE_FILE, "utf-8"));
7121
+ return JSON.parse(readFileSync14(CACHE_FILE, "utf-8"));
7281
7122
  } catch {
7282
7123
  return null;
7283
7124
  }
7284
7125
  }
7285
7126
  function writeCache(entry) {
7286
7127
  try {
7287
- const dir = join14(homedir12(), ".config", "apes");
7288
- if (!existsSync17(dir)) mkdirSync5(dir, { recursive: true, mode: 448 });
7289
- writeFileSync9(CACHE_FILE, JSON.stringify(entry), { mode: 384 });
7128
+ const dir = join15(homedir13(), ".config", "apes");
7129
+ if (!existsSync18(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
7130
+ writeFileSync10(CACHE_FILE, JSON.stringify(entry), { mode: 384 });
7290
7131
  } catch {
7291
7132
  }
7292
7133
  }
@@ -7315,7 +7156,7 @@ async function fetchLatestVersion() {
7315
7156
  }
7316
7157
  function warnIfBehind(currentVersion, latest) {
7317
7158
  if (compareSemver(currentVersion, latest) < 0) {
7318
- consola50.warn(
7159
+ consola48.warn(
7319
7160
  `apes ${currentVersion} is behind latest @openape/apes@${latest}. Run \`npm i -g @openape/apes@latest\` to update. (Suppress with APES_NO_UPDATE_CHECK=1.)`
7320
7161
  );
7321
7162
  }
@@ -7347,10 +7188,10 @@ if (shellRewrite) {
7347
7188
  if (shellRewrite.action === "rewrite") {
7348
7189
  process.argv = shellRewrite.argv;
7349
7190
  } else if (shellRewrite.action === "version") {
7350
- console.log(`ape-shell ${"1.11.0"} (OpenApe DDISA shell wrapper)`);
7191
+ console.log(`ape-shell ${"1.12.0"} (OpenApe DDISA shell wrapper)`);
7351
7192
  process.exit(0);
7352
7193
  } else if (shellRewrite.action === "help") {
7353
- console.log(`ape-shell ${"1.11.0"} \u2014 OpenApe DDISA shell wrapper`);
7194
+ console.log(`ape-shell ${"1.12.0"} \u2014 OpenApe DDISA shell wrapper`);
7354
7195
  console.log("");
7355
7196
  console.log("Usage:");
7356
7197
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -7374,7 +7215,7 @@ if (shellRewrite) {
7374
7215
  }
7375
7216
  }
7376
7217
  var debug = process.argv.includes("--debug");
7377
- var grantsCommand = defineCommand61({
7218
+ var grantsCommand = defineCommand60({
7378
7219
  meta: {
7379
7220
  name: "grants",
7380
7221
  description: "Grant management"
@@ -7395,7 +7236,7 @@ var grantsCommand = defineCommand61({
7395
7236
  "delegation-revoke": delegationRevokeCommand
7396
7237
  }
7397
7238
  });
7398
- var configCommand = defineCommand61({
7239
+ var configCommand = defineCommand60({
7399
7240
  meta: {
7400
7241
  name: "config",
7401
7242
  description: "Configuration management"
@@ -7405,10 +7246,10 @@ var configCommand = defineCommand61({
7405
7246
  set: configSetCommand
7406
7247
  }
7407
7248
  });
7408
- var main = defineCommand61({
7249
+ var main = defineCommand60({
7409
7250
  meta: {
7410
7251
  name: "apes",
7411
- version: "1.11.0",
7252
+ version: "1.12.0",
7412
7253
  description: "Unified CLI for OpenApe"
7413
7254
  },
7414
7255
  subCommands: {
@@ -7465,20 +7306,20 @@ async function maybeRefreshAuth() {
7465
7306
  }
7466
7307
  }
7467
7308
  await maybeRefreshAuth();
7468
- await maybeWarnStaleVersion("1.11.0").catch(() => {
7309
+ await maybeWarnStaleVersion("1.12.0").catch(() => {
7469
7310
  });
7470
7311
  runMain(main).catch((err) => {
7471
7312
  if (err instanceof CliExit) {
7472
7313
  process.exit(err.exitCode);
7473
7314
  }
7474
7315
  if (err instanceof CliError) {
7475
- consola51.error(err.message);
7316
+ consola49.error(err.message);
7476
7317
  process.exit(err.exitCode);
7477
7318
  }
7478
7319
  if (debug) {
7479
- consola51.error(err);
7320
+ consola49.error(err);
7480
7321
  } else {
7481
- consola51.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
7322
+ consola49.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
7482
7323
  }
7483
7324
  process.exit(1);
7484
7325
  });