@openape/apes 1.13.1 → 1.14.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
@@ -2955,12 +2955,61 @@ function shQuote2(s) {
2955
2955
 
2956
2956
  // src/commands/agents/destroy.ts
2957
2957
  import { execFileSync as execFileSync4 } from "child_process";
2958
- import { mkdtempSync, rmSync, writeFileSync } from "fs";
2958
+ import { mkdtempSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
2959
2959
  import { tmpdir, userInfo } from "os";
2960
- import { join as join2 } from "path";
2960
+ import { join as join3 } from "path";
2961
2961
  import { defineCommand as defineCommand21 } from "citty";
2962
2962
  import consola19 from "consola";
2963
2963
 
2964
+ // src/lib/nest-registry.ts
2965
+ import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "fs";
2966
+ import { homedir as homedir4 } from "os";
2967
+ import { join as join2 } from "path";
2968
+ function resolveRegistryPath() {
2969
+ if (existsSync4("/var/openape/nest/agents.json")) return "/var/openape/nest/agents.json";
2970
+ if (existsSync4("/var/openape/nest")) return "/var/openape/nest/agents.json";
2971
+ return join2(homedir4(), ".openape", "nest", "agents.json");
2972
+ }
2973
+ function emptyRegistry() {
2974
+ return { version: 1, agents: [] };
2975
+ }
2976
+ function readNestRegistry() {
2977
+ const path2 = resolveRegistryPath();
2978
+ if (!existsSync4(path2)) return emptyRegistry();
2979
+ try {
2980
+ const parsed = JSON.parse(readFileSync3(path2, "utf8"));
2981
+ if (parsed?.version !== 1 || !Array.isArray(parsed.agents)) return emptyRegistry();
2982
+ return parsed;
2983
+ } catch {
2984
+ return emptyRegistry();
2985
+ }
2986
+ }
2987
+ function writeNestRegistry(reg) {
2988
+ const path2 = resolveRegistryPath();
2989
+ const dir = path2.replace(/\/agents\.json$/, "");
2990
+ try {
2991
+ mkdirSync(dir, { recursive: true });
2992
+ } catch {
2993
+ }
2994
+ writeFileSync(path2, `${JSON.stringify(reg, null, 2)}
2995
+ `, { mode: 432 });
2996
+ }
2997
+ function upsertNestAgent(entry) {
2998
+ const reg = readNestRegistry();
2999
+ const existing = reg.agents.findIndex((a) => a.name === entry.name);
3000
+ if (existing >= 0) reg.agents[existing] = entry;
3001
+ else reg.agents.push(entry);
3002
+ writeNestRegistry(reg);
3003
+ }
3004
+ function removeNestAgent(name) {
3005
+ const reg = readNestRegistry();
3006
+ const before = reg.agents.length;
3007
+ reg.agents = reg.agents.filter((a) => a.name !== name);
3008
+ if (reg.agents.length === before) return false;
3009
+ writeNestRegistry(reg);
3010
+ return true;
3011
+ }
3012
+
2964
3013
  // src/lib/silent-password.ts
2965
3014
  function readPasswordSilent(prompt) {
2966
3015
  if (!process.stdin.isTTY) {
@@ -3100,11 +3149,11 @@ ${consequences.join("\n")}`);
3100
3149
  }
3101
3150
  const adminUser = userInfo().username;
3102
3151
  const adminPassword = await collectAdminPassword({ adminUser });
3103
- const scratch = mkdtempSync(join2(tmpdir(), `apes-destroy-${name}-`));
3104
- const scriptPath = join2(scratch, "teardown.sh");
3152
+ const scratch = mkdtempSync(join3(tmpdir(), `apes-destroy-${name}-`));
3153
+ const scriptPath = join3(scratch, "teardown.sh");
3105
3154
  try {
3106
3155
  const script = buildDestroyTeardownScript({ name, homeDir: `/Users/${name}`, adminUser });
3107
- writeFileSync(scriptPath, script, { mode: 448 });
3156
+ writeFileSync2(scriptPath, script, { mode: 448 });
3108
3157
  consola19.start("Running teardown via sudo\u2026");
3109
3158
  execFileSync4(sudo, ["-S", "--prompt=", "--", "bash", scriptPath], {
3110
3159
  input: `${adminPassword}
@@ -3118,6 +3167,11 @@ ${adminPassword}
3118
3167
  } else if (!args["keep-os-user"] && isDarwin()) {
3119
3168
  consola19.info("No macOS user to remove (skipped).");
3120
3169
  }
3170
+ try {
3171
+ removeNestAgent(name);
3172
+ } catch (err) {
3173
+ consola19.warn(`Could not update nest registry: ${err instanceof Error ? err.message : String(err)}`);
3174
+ }
3121
3175
  consola19.success(`Destroyed ${name}.`);
3122
3176
  }
3123
3177
  });
@@ -3193,7 +3247,7 @@ var listAgentsCommand = defineCommand22({
3193
3247
  });
3194
3248
 
3195
3249
  // src/commands/agents/register.ts
3196
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
3250
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
3197
3251
  import { defineCommand as defineCommand23 } from "citty";
3198
3252
  import consola21 from "consola";
3199
3253
  var registerAgentCommand = defineCommand23({
@@ -3241,10 +3295,10 @@ var registerAgentCommand = defineCommand23({
3241
3295
  throw new CliError("Pass either --public-key or --public-key-file, not both.");
3242
3296
  }
3243
3297
  if (!publicKey && keyFile) {
3244
- if (!existsSync4(keyFile)) {
3298
+ if (!existsSync5(keyFile)) {
3245
3299
  throw new CliError(`Public-key file not found: ${keyFile}`);
3246
3300
  }
3247
- publicKey = readFileSync3(keyFile, "utf-8").trim();
3301
+ publicKey = readFileSync4(keyFile, "utf-8").trim();
3248
3302
  }
3249
3303
  if (!publicKey) {
3250
3304
  throw new CliError('Provide --public-key "<ssh-ed25519 line>" or --public-key-file <path>.');
@@ -3279,9 +3333,9 @@ var registerAgentCommand = defineCommand23({
3279
3333
  });
3280
3334
 
3281
3335
  // src/commands/agents/run.ts
3282
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
3283
- import { homedir as homedir4 } from "os";
3284
- import { join as join3 } from "path";
3336
+ import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
3337
+ import { homedir as homedir5 } from "os";
3338
+ import { join as join4 } from "path";
3285
3339
  import { defineCommand as defineCommand24 } from "citty";
3286
3340
  import consola22 from "consola";
3287
3341
 
@@ -3343,13 +3397,13 @@ function resolveTroopUrl(override) {
3343
3397
  }
3344
3398
 
3345
3399
  // src/commands/agents/run.ts
3346
- var AUTH_PATH = join3(homedir4(), ".config", "apes", "auth.json");
3347
- var TASK_CACHE_DIR = join3(homedir4(), ".openape", "agent", "tasks");
3400
+ var AUTH_PATH = join4(homedir5(), ".config", "apes", "auth.json");
3401
+ var TASK_CACHE_DIR = join4(homedir5(), ".openape", "agent", "tasks");
3348
3402
  function readAuth() {
3349
- if (!existsSync5(AUTH_PATH)) {
3403
+ if (!existsSync6(AUTH_PATH)) {
3350
3404
  throw new CliError(`No agent auth found at ${AUTH_PATH}. Run \`apes agents spawn <name>\` first.`);
3351
3405
  }
3352
- const parsed = JSON.parse(readFileSync4(AUTH_PATH, "utf8"));
3406
+ const parsed = JSON.parse(readFileSync5(AUTH_PATH, "utf8"));
3353
3407
  if (!parsed.access_token) throw new CliError("auth.json missing access_token");
3354
3408
  return parsed;
3355
3409
  }
@@ -3385,26 +3439,26 @@ ${msg}`.slice(0, 9e3);
3385
3439
  }
3386
3440
  }
3387
3441
  function readTaskSpec(taskId) {
3388
- const path2 = join3(TASK_CACHE_DIR, `${taskId}.json`);
3389
- if (!existsSync5(path2)) {
3442
+ const path2 = join4(TASK_CACHE_DIR, `${taskId}.json`);
3443
+ if (!existsSync6(path2)) {
3390
3444
  throw new CliError(`No cached task spec at ${path2}. Run \`apes agents sync\` first to pull the task list from troop.`);
3391
3445
  }
3392
- return JSON.parse(readFileSync4(path2, "utf8"));
3446
+ return JSON.parse(readFileSync5(path2, "utf8"));
3393
3447
  }
3394
- var AGENT_CONFIG_PATH = join3(homedir4(), ".openape", "agent", "agent.json");
3448
+ var AGENT_CONFIG_PATH = join4(homedir5(), ".openape", "agent", "agent.json");
3395
3449
  function readAgentConfig() {
3396
- if (!existsSync5(AGENT_CONFIG_PATH)) return { systemPrompt: "" };
3450
+ if (!existsSync6(AGENT_CONFIG_PATH)) return { systemPrompt: "" };
3397
3451
  try {
3398
- return JSON.parse(readFileSync4(AGENT_CONFIG_PATH, "utf8"));
3452
+ return JSON.parse(readFileSync5(AGENT_CONFIG_PATH, "utf8"));
3399
3453
  } catch {
3400
3454
  return { systemPrompt: "" };
3401
3455
  }
3402
3456
  }
3403
3457
  function readLitellmConfig(model) {
3404
- const envPath = join3(homedir4(), "litellm", ".env");
3458
+ const envPath = join4(homedir5(), "litellm", ".env");
3405
3459
  const env = {};
3406
- if (existsSync5(envPath)) {
3407
- for (const line of readFileSync4(envPath, "utf8").split(/\r?\n/)) {
3460
+ if (existsSync6(envPath)) {
3461
+ for (const line of readFileSync5(envPath, "utf8").split(/\r?\n/)) {
3408
3462
  const m = line.match(/^([A-Z_]+)=(.*)$/);
3409
3463
  if (m) env[m[1]] = m[2].replace(/^["']|["']$/g, "");
3410
3464
  }
@@ -3509,17 +3563,17 @@ var runAgentCommand = defineCommand24({
3509
3563
  });
3510
3564
 
3511
3565
  // src/commands/agents/serve.ts
3512
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
3513
- import { homedir as homedir5 } from "os";
3514
- import { join as join4 } from "path";
3566
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
3567
+ import { homedir as homedir6 } from "os";
3568
+ import { join as join5 } from "path";
3515
3569
  import { createInterface } from "readline";
3516
3570
  import { defineCommand as defineCommand25 } from "citty";
3517
- var AUTH_PATH2 = join4(homedir5(), ".config", "apes", "auth.json");
3571
+ var AUTH_PATH2 = join5(homedir6(), ".config", "apes", "auth.json");
3518
3572
  function readLitellmConfig2(model) {
3519
- const envPath = join4(homedir5(), "litellm", ".env");
3573
+ const envPath = join5(homedir6(), "litellm", ".env");
3520
3574
  const env = {};
3521
- if (existsSync6(envPath)) {
3522
- for (const line of readFileSync5(envPath, "utf8").split(/\r?\n/)) {
3575
+ if (existsSync7(envPath)) {
3576
+ for (const line of readFileSync6(envPath, "utf8").split(/\r?\n/)) {
3523
3577
  const m = line.match(/^([A-Z_]+)=(.*)$/);
3524
3578
  if (m) env[m[1]] = m[2].replace(/^["']|["']$/g, "");
3525
3579
  }
@@ -3551,9 +3605,9 @@ var serveAgentCommand = defineCommand25({
3551
3605
  if (!args.rpc) {
3552
3606
  throw new CliError("apes agents serve currently only supports --rpc mode");
3553
3607
  }
3554
- if (existsSync6(AUTH_PATH2)) {
3608
+ if (existsSync7(AUTH_PATH2)) {
3555
3609
  try {
3556
- JSON.parse(readFileSync5(AUTH_PATH2, "utf8"));
3610
+ JSON.parse(readFileSync6(AUTH_PATH2, "utf8"));
3557
3611
  } catch {
3558
3612
  }
3559
3613
  }
@@ -3629,9 +3683,9 @@ async function handleInbound(msg, sessions) {
3629
3683
 
3630
3684
  // src/commands/agents/spawn.ts
3631
3685
  import { execFileSync as execFileSync6 } from "child_process";
3632
- import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
3686
+ import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
3633
3687
  import { tmpdir as tmpdir2 } from "os";
3634
- import { join as join6 } from "path";
3688
+ import { join as join7 } from "path";
3635
3689
  import { defineCommand as defineCommand26 } from "citty";
3636
3690
  import consola23 from "consola";
3637
3691
 
@@ -3689,12 +3743,12 @@ ${envBlock} <key>StartInterval</key>
3689
3743
 
3690
3744
  // src/lib/keygen.ts
3691
3745
  import { Buffer as Buffer4 } from "buffer";
3692
- import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
3746
+ import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "fs";
3693
3747
  import { generateKeyPairSync } from "crypto";
3694
- import { homedir as homedir6 } from "os";
3748
+ import { homedir as homedir7 } from "os";
3695
3749
  import { dirname, resolve as resolve2 } from "path";
3696
3750
  function resolveKeyPath(p2) {
3697
- return resolve2(p2.replace(/^~/, homedir6()));
3751
+ return resolve2(p2.replace(/^~/, homedir7()));
3698
3752
  }
3699
3753
  function buildSshEd25519Line(rawPub) {
3700
3754
  const keyTypeStr = "ssh-ed25519";
@@ -3707,10 +3761,10 @@ function buildSshEd25519Line(rawPub) {
3707
3761
  }
3708
3762
  function readPublicKey(keyPath) {
3709
3763
  const pubPath = `${keyPath}.pub`;
3710
- if (existsSync7(pubPath)) {
3711
- return readFileSync6(pubPath, "utf-8").trim();
3764
+ if (existsSync8(pubPath)) {
3765
+ return readFileSync7(pubPath, "utf-8").trim();
3712
3766
  }
3713
- const keyContent = readFileSync6(keyPath, "utf-8");
3767
+ const keyContent = readFileSync7(keyPath, "utf-8");
3714
3768
  const privateKey = loadEd25519PrivateKey(keyContent);
3715
3769
  const jwk = privateKey.export({ format: "jwk" });
3716
3770
  const pubBytes = Buffer4.from(jwk.x, "base64url");
@@ -3719,16 +3773,16 @@ function readPublicKey(keyPath) {
3719
3773
  function generateAndSaveKey(keyPath) {
3720
3774
  const resolved = resolveKeyPath(keyPath);
3721
3775
  const dir = dirname(resolved);
3722
- if (!existsSync7(dir)) {
3723
- mkdirSync(dir, { recursive: true });
3776
+ if (!existsSync8(dir)) {
3777
+ mkdirSync2(dir, { recursive: true });
3724
3778
  }
3725
3779
  const { publicKey, privateKey } = generateKeyPairSync("ed25519");
3726
3780
  const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
3727
- writeFileSync2(resolved, privatePem, { mode: 384 });
3781
+ writeFileSync3(resolved, privatePem, { mode: 384 });
3728
3782
  const jwk = publicKey.export({ format: "jwk" });
3729
3783
  const pubBytes = Buffer4.from(jwk.x, "base64url");
3730
3784
  const pubKeyStr = buildSshEd25519Line(pubBytes);
3731
- writeFileSync2(`${resolved}.pub`, `${pubKeyStr}
3785
+ writeFileSync3(`${resolved}.pub`, `${pubKeyStr}
3732
3786
  `, { mode: 420 });
3733
3787
  return pubKeyStr;
3734
3788
  }
@@ -3745,14 +3799,14 @@ function generateKeyPairInMemory() {
3745
3799
 
3746
3800
  // src/lib/llm-bridge.ts
3747
3801
  import { execFileSync as execFileSync5 } from "child_process";
3748
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
3749
- import { homedir as homedir7 } from "os";
3750
- import { dirname as dirname2, join as join5 } from "path";
3802
+ import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
3803
+ import { homedir as homedir8 } from "os";
3804
+ import { dirname as dirname2, join as join6 } from "path";
3751
3805
  var PLIST_LABEL_PREFIX = "eco.hofmann.apes.bridge";
3752
- function readLitellmEnv(envPath = join5(homedir7(), "litellm", ".env")) {
3753
- if (!existsSync8(envPath)) return null;
3806
+ function readLitellmEnv(envPath = join6(homedir8(), "litellm", ".env")) {
3807
+ if (!existsSync9(envPath)) return null;
3754
3808
  try {
3755
- const text = readFileSync7(envPath, "utf8");
3809
+ const text = readFileSync8(envPath, "utf8");
3756
3810
  const out = {};
3757
3811
  for (const line of text.split("\n")) {
3758
3812
  const trimmed = line.trim();
@@ -3881,6 +3935,14 @@ function buildBridgePlist(agentName, homeDir, ownerEmail, hostBinDirs) {
3881
3935
  }
3882
3936
 
3883
3937
  // src/commands/agents/spawn.ts
3938
+ function readMacOSUidOrNull(name) {
3939
+ try {
3940
+ const u = readMacOSUser(name);
3941
+ return u?.uid ?? null;
3942
+ } catch {
3943
+ return null;
3944
+ }
3945
+ }
3884
3946
  var spawnAgentCommand = defineCommand26({
3885
3947
  meta: {
3886
3948
  name: "spawn",
@@ -3968,8 +4030,8 @@ and try again.`
3968
4030
  throw new CliError(`macOS user "${name}" already exists (uid=${existing.uid ?? "?"}). Refusing to overwrite.`);
3969
4031
  }
3970
4032
  const homeDir = `/Users/${name}`;
3971
- const scratch = mkdtempSync2(join6(tmpdir2(), `apes-spawn-${name}-`));
3972
- const scriptPath = join6(scratch, "setup.sh");
4033
+ const scratch = mkdtempSync2(join7(tmpdir2(), `apes-spawn-${name}-`));
4034
+ const scriptPath = join7(scratch, "setup.sh");
3973
4035
  try {
3974
4036
  consola23.start(`Generating keypair for ${name}\u2026`);
3975
4037
  const { privatePem, publicSshLine } = generateKeyPairInMemory();
@@ -4039,10 +4101,27 @@ and try again.`
4039
4101
  bridge,
4040
4102
  troop
4041
4103
  });
4042
- writeFileSync3(scriptPath, script, { mode: 448 });
4104
+ writeFileSync4(scriptPath, script, { mode: 448 });
4043
4105
  consola23.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
4044
4106
  consola23.info("You will be asked to approve the as=root grant in your DDISA inbox; this command blocks until you do.");
4045
4107
  execFileSync6(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], { stdio: "inherit" });
4108
+ try {
4109
+ const uid = readMacOSUidOrNull(name);
4110
+ upsertNestAgent({
4111
+ name,
4112
+ uid: uid ?? -1,
4113
+ home: homeDir,
4114
+ email: registration.email,
4115
+ registeredAt: Math.floor(Date.now() / 1e3),
4116
+ bridge: args.bridge ? {
4117
+ baseUrl: typeof args["bridge-base-url"] === "string" ? args["bridge-base-url"] : void 0,
4118
+ apiKey: typeof args["bridge-key"] === "string" ? args["bridge-key"] : void 0,
4119
+ model: typeof args["bridge-model"] === "string" ? args["bridge-model"] : void 0
4120
+ } : void 0
4121
+ });
4122
+ } catch (err) {
4123
+ consola23.warn(`Could not write to nest registry: ${err instanceof Error ? err.message : String(err)}`);
4124
+ }
4046
4125
  consola23.success(`Agent ${name} spawned.`);
4047
4126
  consola23.info(`\u{1F517} Troop: https://troop.openape.ai/agents/${name}`);
4048
4127
  if (args.bridge) {
@@ -4081,9 +4160,9 @@ async function resolveClaudeToken(opts) {
4081
4160
  }
4082
4161
 
4083
4162
  // src/commands/agents/sync.ts
4084
- import { chownSync, existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as readFileSync8, statSync, writeFileSync as writeFileSync4 } from "fs";
4085
- import { homedir as homedir8 } from "os";
4086
- import { join as join7 } from "path";
4163
+ import { chownSync, existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync9, statSync, writeFileSync as writeFileSync5 } from "fs";
4164
+ import { homedir as homedir9 } from "os";
4165
+ import { join as join8 } from "path";
4087
4166
  import { defineCommand as defineCommand27 } from "citty";
4088
4167
  import consola24 from "consola";
4089
4168
 
@@ -4112,15 +4191,15 @@ function getHostname() {
4112
4191
  }
4113
4192
 
4114
4193
  // src/commands/agents/sync.ts
4115
- var AUTH_PATH3 = join7(homedir8(), ".config", "apes", "auth.json");
4116
- var TASK_CACHE_DIR2 = join7(homedir8(), ".openape", "agent", "tasks");
4194
+ var AUTH_PATH3 = join8(homedir9(), ".config", "apes", "auth.json");
4195
+ var TASK_CACHE_DIR2 = join8(homedir9(), ".openape", "agent", "tasks");
4117
4196
  function readAuthJson() {
4118
- if (!existsSync9(AUTH_PATH3)) {
4197
+ if (!existsSync10(AUTH_PATH3)) {
4119
4198
  throw new CliError(
4120
4199
  `No agent auth found at ${AUTH_PATH3}. Run \`apes agents spawn <name>\` to provision an agent first.`
4121
4200
  );
4122
4201
  }
4123
- const raw = readFileSync8(AUTH_PATH3, "utf8");
4202
+ const raw = readFileSync9(AUTH_PATH3, "utf8");
4124
4203
  let parsed;
4125
4204
  try {
4126
4205
  parsed = JSON.parse(raw);
@@ -4181,7 +4260,7 @@ var syncAgentCommand = defineCommand27({
4181
4260
  let agentGid = null;
4182
4261
  if (process.geteuid?.() === 0) {
4183
4262
  try {
4184
- const homeStat = statSync(homedir8());
4263
+ const homeStat = statSync(homedir9());
4185
4264
  agentUid = homeStat.uid;
4186
4265
  agentGid = homeStat.gid;
4187
4266
  } catch {
@@ -4195,23 +4274,23 @@ var syncAgentCommand = defineCommand27({
4195
4274
  }
4196
4275
  }
4197
4276
  }
4198
- const agentDir = join7(homedir8(), ".openape", "agent");
4199
- mkdirSync2(agentDir, { recursive: true });
4200
- chownToAgent(join7(homedir8(), ".openape"));
4277
+ const agentDir = join8(homedir9(), ".openape", "agent");
4278
+ mkdirSync3(agentDir, { recursive: true });
4279
+ chownToAgent(join8(homedir9(), ".openape"));
4201
4280
  chownToAgent(agentDir);
4202
- const agentJsonPath = join7(agentDir, "agent.json");
4203
- writeFileSync4(
4281
+ const agentJsonPath = join8(agentDir, "agent.json");
4282
+ writeFileSync5(
4204
4283
  agentJsonPath,
4205
4284
  `${JSON.stringify({ systemPrompt }, null, 2)}
4206
4285
  `,
4207
4286
  { mode: 384 }
4208
4287
  );
4209
4288
  chownToAgent(agentJsonPath);
4210
- mkdirSync2(TASK_CACHE_DIR2, { recursive: true });
4289
+ mkdirSync3(TASK_CACHE_DIR2, { recursive: true });
4211
4290
  chownToAgent(TASK_CACHE_DIR2);
4212
4291
  for (const task of tasks) {
4213
- const path2 = join7(TASK_CACHE_DIR2, `${task.taskId}.json`);
4214
- writeFileSync4(path2, `${JSON.stringify(task, null, 2)}
4292
+ const path2 = join8(TASK_CACHE_DIR2, `${task.taskId}.json`);
4293
+ writeFileSync5(path2, `${JSON.stringify(task, null, 2)}
4215
4294
  `, { mode: 384 });
4216
4295
  chownToAgent(path2);
4217
4296
  }
@@ -4242,18 +4321,18 @@ import { defineCommand as defineCommand36 } from "citty";
4242
4321
 
4243
4322
  // src/commands/nest/authorize.ts
4244
4323
  import { execFileSync as execFileSync8 } from "child_process";
4245
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
4246
- import { join as join9 } from "path";
4324
+ import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
4325
+ import { join as join10 } from "path";
4247
4326
  import { defineCommand as defineCommand30 } from "citty";
4248
4327
  import consola26 from "consola";
4249
4328
 
4250
4329
  // src/commands/nest/enroll.ts
4251
- import { hostname as hostname4, homedir as homedir9 } from "os";
4252
- import { existsSync as existsSync10, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5, chmodSync } from "fs";
4253
- import { join as join8 } from "path";
4330
+ import { hostname as hostname4, homedir as homedir10 } from "os";
4331
+ import { existsSync as existsSync11, mkdirSync as mkdirSync4, writeFileSync as writeFileSync6, chmodSync } from "fs";
4332
+ import { join as join9 } from "path";
4254
4333
  import { defineCommand as defineCommand29 } from "citty";
4255
4334
  import consola25 from "consola";
4256
- var NEST_DATA_DIR = join8(homedir9(), ".openape", "nest");
4335
+ var NEST_DATA_DIR = join9(homedir10(), ".openape", "nest");
4257
4336
  function nestAgentName() {
4258
4337
  const raw = hostname4().toLowerCase();
4259
4338
  const head = raw.split(".")[0] ?? raw;
@@ -4286,19 +4365,19 @@ var enrollNestCommand = defineCommand29({
4286
4365
  throw new CliError("Run `apes login <email>` first \u2014 nest enroll attaches the new identity to your owner account.");
4287
4366
  }
4288
4367
  const name = args.name || nestAgentName();
4289
- const authPath = join8(NEST_DATA_DIR, ".config", "apes", "auth.json");
4290
- if (existsSync10(authPath) && !args.force) {
4368
+ const authPath = join9(NEST_DATA_DIR, ".config", "apes", "auth.json");
4369
+ if (existsSync11(authPath) && !args.force) {
4291
4370
  throw new CliError(`Nest already enrolled at ${authPath}. Pass --force to re-enroll.`);
4292
4371
  }
4293
- const sshDir = join8(NEST_DATA_DIR, ".ssh");
4294
- const configDir = join8(NEST_DATA_DIR, ".config", "apes");
4295
- mkdirSync3(sshDir, { recursive: true });
4296
- mkdirSync3(configDir, { recursive: true });
4372
+ const sshDir = join9(NEST_DATA_DIR, ".ssh");
4373
+ const configDir = join9(NEST_DATA_DIR, ".config", "apes");
4374
+ mkdirSync4(sshDir, { recursive: true });
4375
+ mkdirSync4(configDir, { recursive: true });
4297
4376
  consola25.start(`Generating keypair for ${name}\u2026`);
4298
4377
  const { privatePem, publicSshLine } = generateKeyPairInMemory();
4299
- writeFileSync5(join8(sshDir, "id_ed25519"), `${privatePem.trimEnd()}
4378
+ writeFileSync6(join9(sshDir, "id_ed25519"), `${privatePem.trimEnd()}
4300
4379
  `, { mode: 384 });
4301
- writeFileSync5(join8(sshDir, "id_ed25519.pub"), `${publicSshLine}
4380
+ writeFileSync6(join9(sshDir, "id_ed25519.pub"), `${publicSshLine}
4302
4381
  `, { mode: 420 });
4303
4382
  chmodSync(sshDir, 448);
4304
4383
  consola25.start(`Registering nest at ${idp}\u2026`);
@@ -4315,10 +4394,10 @@ var enrollNestCommand = defineCommand29({
4315
4394
  accessToken: token,
4316
4395
  email: registration.email,
4317
4396
  expiresAt: Math.floor(Date.now() / 1e3) + expiresIn,
4318
- keyPath: join8(sshDir, "id_ed25519"),
4397
+ keyPath: join9(sshDir, "id_ed25519"),
4319
4398
  ownerEmail: ownerAuth.email
4320
4399
  });
4321
- writeFileSync5(authPath, authJson, { mode: 384 });
4400
+ writeFileSync6(authPath, authJson, { mode: 384 });
4322
4401
  chmodSync(configDir, 448);
4323
4402
  consola25.success(`Nest enrolled \u2014 auth.json at ${authPath}`);
4324
4403
  consola25.info("");
@@ -4384,11 +4463,11 @@ var authorizeNestCommand = defineCommand30({
4384
4463
  }
4385
4464
  },
4386
4465
  async run({ args }) {
4387
- const nestAuthPath = join9(NEST_DATA_DIR, ".config", "apes", "auth.json");
4388
- if (!existsSync11(nestAuthPath)) {
4466
+ const nestAuthPath = join10(NEST_DATA_DIR, ".config", "apes", "auth.json");
4467
+ if (!existsSync12(nestAuthPath)) {
4389
4468
  throw new CliError("Nest not enrolled. Run `apes nest enroll` first.");
4390
4469
  }
4391
- const nestAuth = JSON.parse(readFileSync9(nestAuthPath, "utf8"));
4470
+ const nestAuth = JSON.parse(readFileSync10(nestAuthPath, "utf8"));
4392
4471
  if (!nestAuth.email) throw new CliError(`${nestAuthPath} has no email`);
4393
4472
  const allow = args.allow ?? DEFAULT_ALLOW_PATTERNS.join(",");
4394
4473
  consola26.info(`Configuring YOLO-policy on ${nestAuth.email} via \`apes yolo set\`\u2026`);
@@ -4415,102 +4494,31 @@ var authorizeNestCommand = defineCommand30({
4415
4494
  });
4416
4495
 
4417
4496
  // src/commands/nest/destroy.ts
4497
+ import { execFileSync as execFileSync9 } from "child_process";
4418
4498
  import { defineCommand as defineCommand31 } from "citty";
4419
4499
  import consola27 from "consola";
4420
-
4421
- // src/lib/nest-intent.ts
4422
- import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync10, statSync as statSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
4423
- import { homedir as homedir10 } from "os";
4424
- import { join as join10 } from "path";
4425
- import { randomUUID } from "crypto";
4426
- var POLL_INTERVAL_MS = 200;
4427
- var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
4428
- function resolveIntentDir() {
4429
- if (process.env.OPENAPE_NEST_INTENT_DIR) return process.env.OPENAPE_NEST_INTENT_DIR;
4430
- if (existsSync12("/var/openape/nest/intents")) return "/var/openape/nest/intents";
4431
- return join10(homedir10(), ".openape", "nest", "intents");
4432
- }
4433
- async function dispatchIntent(intent, opts = {}) {
4434
- const id = randomUUID();
4435
- const dir = resolveIntentDir();
4436
- if (!existsSync12(dir)) {
4437
- throw new CliError(`Nest intent dir does not exist: ${dir}
4438
- Is the nest daemon running? Try \`ps aux | grep openape-nest\`.`);
4439
- }
4440
- const intentPath = join10(dir, `${id}.json`);
4441
- const responsePath = join10(dir, `${id}.response`);
4442
- const tmpPath = `${intentPath}.tmp`;
4443
- writeFileSync6(tmpPath, `${JSON.stringify({ id, ...intent })}
4444
- `, { mode: 432 });
4445
- try {
4446
- const fs = await import("fs");
4447
- fs.renameSync(tmpPath, intentPath);
4448
- } catch (err) {
4449
- try {
4450
- unlinkSync(tmpPath);
4451
- } catch {
4452
- }
4453
- throw err;
4454
- }
4455
- const deadline = Date.now() + (opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
4456
- while (Date.now() < deadline) {
4457
- if (existsSync12(responsePath)) {
4458
- let raw;
4459
- try {
4460
- const st = statSync2(responsePath);
4461
- if (Date.now() - st.mtimeMs < 50) {
4462
- await sleep(50);
4463
- }
4464
- raw = readFileSync10(responsePath, "utf8");
4465
- } catch {
4466
- await sleep(POLL_INTERVAL_MS);
4467
- continue;
4468
- }
4469
- try {
4470
- unlinkSync(responsePath);
4471
- } catch {
4472
- }
4473
- let parsed;
4474
- try {
4475
- parsed = JSON.parse(raw);
4476
- } catch (err) {
4477
- throw new CliError(`malformed nest response: ${err instanceof Error ? err.message : String(err)}`);
4478
- }
4479
- if (!parsed.ok) {
4480
- throw new CliError(`nest: ${parsed.error}`);
4481
- }
4482
- return parsed.result;
4483
- }
4484
- await sleep(POLL_INTERVAL_MS);
4485
- }
4486
- try {
4487
- unlinkSync(intentPath);
4488
- } catch {
4489
- }
4490
- throw new CliError(`nest intent timeout (${(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS) / 1e3}s) \u2014 Nest daemon may not be running or is stuck.`);
4491
- }
4492
- function sleep(ms) {
4493
- return new Promise((resolve4) => setTimeout(resolve4, ms));
4494
- }
4495
-
4496
- // src/commands/nest/destroy.ts
4497
4500
  var destroyNestCommand = defineCommand31({
4498
4501
  meta: {
4499
4502
  name: "destroy",
4500
- description: "Tear down an agent on the local nest. Drops an intent file the nest daemon picks up."
4503
+ description: "Destroy a local agent. Wraps `apes run --as root -- apes agents destroy <name>`; the Nest watches its registry and pm2-deletes the bridge automatically."
4501
4504
  },
4502
4505
  args: {
4503
4506
  name: { type: "positional", required: true, description: "Agent name to destroy" }
4504
4507
  },
4505
4508
  async run({ args }) {
4506
4509
  const name = String(args.name);
4507
- await dispatchIntent({ action: "destroy", name });
4508
- consola27.success(`Destroyed ${name}`);
4510
+ try {
4511
+ execFileSync9("apes", ["run", "--as", "root", "--wait", "--", "apes", "agents", "destroy", name, "--force"], { stdio: "inherit" });
4512
+ consola27.success(`Nest will tear down ${name}'s pm2 process on its next reconcile (\u22642s).`);
4513
+ } catch (err) {
4514
+ const status = err.status ?? 1;
4515
+ throw new CliExit(status);
4516
+ }
4509
4517
  }
4510
4518
  });
4511
4519
 
4512
4520
  // src/commands/nest/install.ts
4513
- import { execFileSync as execFileSync9 } from "child_process";
4521
+ import { execFileSync as execFileSync10 } from "child_process";
4514
4522
  import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
4515
4523
  import { homedir as homedir11, userInfo as userInfo2 } from "os";
4516
4524
  import { dirname as dirname3, join as join11 } from "path";
@@ -4708,10 +4716,10 @@ var installNestCommand = defineCommand32({
4708
4716
  }
4709
4717
  const uid = userInfo2().uid;
4710
4718
  try {
4711
- execFileSync9("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
4719
+ execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
4712
4720
  } catch {
4713
4721
  }
4714
- execFileSync9("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
4722
+ execFileSync10("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
4715
4723
  consola28.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
4716
4724
  consola28.info("");
4717
4725
  consola28.info("Next steps for zero-prompt spawn \u2014 both one-time:");
@@ -4729,23 +4737,23 @@ import consola29 from "consola";
4729
4737
  var listNestCommand = defineCommand33({
4730
4738
  meta: {
4731
4739
  name: "list",
4732
- description: "List agents registered with the local nest. File-based intent."
4740
+ description: "List agents registered with the local nest. Reads /var/openape/nest/agents.json directly."
4733
4741
  },
4734
4742
  args: {
4735
4743
  json: { type: "boolean", description: "JSON output for scripts" }
4736
4744
  },
4737
4745
  async run({ args }) {
4738
- const result = await dispatchIntent({ action: "list" });
4746
+ const reg = readNestRegistry();
4739
4747
  if (args.json) {
4740
- console.log(JSON.stringify(result, null, 2));
4748
+ console.log(JSON.stringify(reg, null, 2));
4741
4749
  return;
4742
4750
  }
4743
- if (result.agents.length === 0) {
4751
+ if (reg.agents.length === 0) {
4744
4752
  consola29.info("(no agents registered with this nest)");
4745
4753
  return;
4746
4754
  }
4747
- consola29.info(`${result.agents.length} agent(s) registered with this nest:`);
4748
- for (const a of result.agents) {
4755
+ consola29.info(`${reg.agents.length} agent(s) registered with this nest:`);
4756
+ for (const a of reg.agents) {
4749
4757
  const bridge = a.bridge ? " bridge=on" : "";
4750
4758
  consola29.info(` ${a.name.padEnd(16)} uid=${String(a.uid).padEnd(5)} home=${a.home}${bridge}`);
4751
4759
  }
@@ -4753,38 +4761,51 @@ var listNestCommand = defineCommand33({
4753
4761
  });
4754
4762
 
4755
4763
  // src/commands/nest/spawn.ts
4764
+ import { execFileSync as execFileSync11 } from "child_process";
4756
4765
  import { defineCommand as defineCommand34 } from "citty";
4757
4766
  import consola30 from "consola";
4758
4767
  var spawnNestCommand = defineCommand34({
4759
4768
  meta: {
4760
4769
  name: "spawn",
4761
- 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."
4770
+ description: "Spawn a new agent locally. Wraps `apes run --as root -- apes agents spawn <name>`; the Nest watches its registry and starts the bridge in pm2 automatically."
4762
4771
  },
4763
4772
  args: {
4764
4773
  name: { type: "positional", required: true, description: "Agent name (lowercase, [a-z0-9-], max 24 chars)" },
4765
4774
  "no-bridge": { type: "boolean", description: "Skip installing the chat-bridge daemon (default: install it)" },
4766
4775
  "bridge-key": { type: "string", description: "Override LITELLM_API_KEY (default: read from ~/litellm/.env)" },
4767
- "bridge-base-url": { type: "string", description: "Override LITELLM_BASE_URL (default: read from ~/litellm/.env)" },
4776
+ "bridge-base-url": { type: "string", description: "Override LITELLM_BASE_URL" },
4768
4777
  "bridge-model": { type: "string", description: "Override APE_CHAT_BRIDGE_MODEL" }
4769
4778
  },
4770
4779
  async run({ args }) {
4771
4780
  const name = String(args.name);
4772
- const intent = {
4773
- action: "spawn",
4774
- name,
4775
- bridge: !args["no-bridge"]
4776
- };
4777
- if (typeof args["bridge-key"] === "string") intent.bridgeKey = args["bridge-key"];
4778
- if (typeof args["bridge-base-url"] === "string") intent.bridgeBaseUrl = args["bridge-base-url"];
4779
- if (typeof args["bridge-model"] === "string") intent.bridgeModel = args["bridge-model"];
4780
- const result = await dispatchIntent(intent);
4781
- consola30.success(`Spawned ${result.name} (uid=${result.uid}, home=${result.home})`);
4781
+ const apesArgs = [
4782
+ "run",
4783
+ "--as",
4784
+ "root",
4785
+ "--wait",
4786
+ "--",
4787
+ "apes",
4788
+ "agents",
4789
+ "spawn",
4790
+ name
4791
+ ];
4792
+ if (!args["no-bridge"]) apesArgs.push("--bridge");
4793
+ if (typeof args["bridge-key"] === "string") apesArgs.push("--bridge-key", args["bridge-key"]);
4794
+ if (typeof args["bridge-base-url"] === "string") apesArgs.push("--bridge-base-url", args["bridge-base-url"]);
4795
+ if (typeof args["bridge-model"] === "string") apesArgs.push("--bridge-model", args["bridge-model"]);
4796
+ try {
4797
+ execFileSync11("apes", apesArgs, { stdio: "inherit" });
4798
+ consola30.success(`Nest will pick up ${name} on its next reconcile (\u22642s).`);
4799
+ } catch (err) {
4800
+ const status = err.status ?? 1;
4801
+ throw new CliExit(status);
4802
+ }
4782
4803
  }
4783
4804
  });
4784
4805
 
4785
4806
  // src/commands/nest/uninstall.ts
4786
- import { execFileSync as execFileSync10 } from "child_process";
4787
- import { existsSync as existsSync14, unlinkSync as unlinkSync2 } from "fs";
4807
+ import { execFileSync as execFileSync12 } from "child_process";
4808
+ import { existsSync as existsSync14, unlinkSync } from "fs";
4788
4809
  import { homedir as homedir12, userInfo as userInfo3 } from "os";
4789
4810
  import { join as join12 } from "path";
4790
4811
  import { defineCommand as defineCommand35 } from "citty";
@@ -4799,13 +4820,13 @@ var uninstallNestCommand = defineCommand35({
4799
4820
  const uid = userInfo3().uid;
4800
4821
  const path2 = join12(homedir12(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
4801
4822
  try {
4802
- execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
4823
+ execFileSync12("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
4803
4824
  consola31.success("Nest daemon stopped");
4804
4825
  } catch {
4805
4826
  consola31.info("Nest daemon was not loaded");
4806
4827
  }
4807
4828
  if (existsSync14(path2)) {
4808
- unlinkSync2(path2);
4829
+ unlinkSync(path2);
4809
4830
  consola31.success(`Removed ${path2}`);
4810
4831
  }
4811
4832
  consola31.info("Registry at ~/.openape/nest/agents.json kept \u2014 re-run `apes nest install` to resume supervision.");
@@ -5353,7 +5374,7 @@ var adapterCommand = defineCommand41({
5353
5374
  });
5354
5375
 
5355
5376
  // src/commands/run.ts
5356
- import { execFileSync as execFileSync11 } from "child_process";
5377
+ import { execFileSync as execFileSync13 } from "child_process";
5357
5378
  import { hostname as hostname5 } from "os";
5358
5379
  import { basename } from "path";
5359
5380
  import { defineCommand as defineCommand42 } from "citty";
@@ -5631,7 +5652,7 @@ function execShellCommand(command) {
5631
5652
  throw new CliError("No command to execute");
5632
5653
  try {
5633
5654
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
5634
- execFileSync11(command[0], command.slice(1), {
5655
+ execFileSync13(command[0], command.slice(1), {
5635
5656
  stdio: "inherit",
5636
5657
  env: inheritedEnv
5637
5658
  });
@@ -5783,7 +5804,7 @@ async function runAudienceMode(audience, action, args) {
5783
5804
  consola36.info(`Executing: ${command.join(" ")}`);
5784
5805
  try {
5785
5806
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
5786
- execFileSync11(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
5807
+ execFileSync13(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
5787
5808
  stdio: "inherit",
5788
5809
  env: inheritedEnv
5789
5810
  });
@@ -6285,7 +6306,7 @@ var mcpCommand = defineCommand48({
6285
6306
  if (transport !== "stdio" && transport !== "sse") {
6286
6307
  throw new Error('Transport must be "stdio" or "sse"');
6287
6308
  }
6288
- const { startMcpServer } = await import("./server-5LHDHGDG.js");
6309
+ const { startMcpServer } = await import("./server-P2XXAHS5.js");
6289
6310
  await startMcpServer(transport, port);
6290
6311
  }
6291
6312
  });
@@ -6293,7 +6314,7 @@ var mcpCommand = defineCommand48({
6293
6314
  // src/commands/init/index.ts
6294
6315
  import { existsSync as existsSync15, copyFileSync, writeFileSync as writeFileSync9 } from "fs";
6295
6316
  import { randomBytes } from "crypto";
6296
- import { execFileSync as execFileSync12 } from "child_process";
6317
+ import { execFileSync as execFileSync14 } from "child_process";
6297
6318
  import { join as join14 } from "path";
6298
6319
  import { defineCommand as defineCommand49 } from "citty";
6299
6320
  import consola40 from "consola";
@@ -6305,11 +6326,11 @@ async function downloadTemplate(repo, targetDir) {
6305
6326
  function installDeps(dir) {
6306
6327
  const hasLockFile = (name) => existsSync15(join14(dir, name));
6307
6328
  if (hasLockFile("pnpm-lock.yaml")) {
6308
- execFileSync12("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
6329
+ execFileSync14("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
6309
6330
  } else if (hasLockFile("bun.lockb")) {
6310
- execFileSync12("bun", ["install"], { cwd: dir, stdio: "inherit" });
6331
+ execFileSync14("bun", ["install"], { cwd: dir, stdio: "inherit" });
6311
6332
  } else {
6312
- execFileSync12("npm", ["install"], { cwd: dir, stdio: "inherit" });
6333
+ execFileSync14("npm", ["install"], { cwd: dir, stdio: "inherit" });
6313
6334
  }
6314
6335
  }
6315
6336
  async function promptChoice(message, choices) {
@@ -6923,7 +6944,7 @@ async function bestEffortGrantCount(idp) {
6923
6944
  }
6924
6945
  }
6925
6946
  async function runHealth(args) {
6926
- const version = true ? "1.13.1" : "0.0.0";
6947
+ const version = true ? "1.14.0" : "0.0.0";
6927
6948
  const auth = loadAuth();
6928
6949
  if (!auth) {
6929
6950
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -7196,10 +7217,10 @@ if (shellRewrite) {
7196
7217
  if (shellRewrite.action === "rewrite") {
7197
7218
  process.argv = shellRewrite.argv;
7198
7219
  } else if (shellRewrite.action === "version") {
7199
- console.log(`ape-shell ${"1.13.1"} (OpenApe DDISA shell wrapper)`);
7220
+ console.log(`ape-shell ${"1.14.0"} (OpenApe DDISA shell wrapper)`);
7200
7221
  process.exit(0);
7201
7222
  } else if (shellRewrite.action === "help") {
7202
- console.log(`ape-shell ${"1.13.1"} \u2014 OpenApe DDISA shell wrapper`);
7223
+ console.log(`ape-shell ${"1.14.0"} \u2014 OpenApe DDISA shell wrapper`);
7203
7224
  console.log("");
7204
7225
  console.log("Usage:");
7205
7226
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -7257,7 +7278,7 @@ var configCommand = defineCommand60({
7257
7278
  var main = defineCommand60({
7258
7279
  meta: {
7259
7280
  name: "apes",
7260
- version: "1.13.1",
7281
+ version: "1.14.0",
7261
7282
  description: "Unified CLI for OpenApe"
7262
7283
  },
7263
7284
  subCommands: {
@@ -7314,7 +7335,7 @@ async function maybeRefreshAuth() {
7314
7335
  }
7315
7336
  }
7316
7337
  await maybeRefreshAuth();
7317
- await maybeWarnStaleVersion("1.13.1").catch(() => {
7338
+ await maybeWarnStaleVersion("1.14.0").catch(() => {
7318
7339
  });
7319
7340
  runMain(main).catch((err) => {
7320
7341
  if (err instanceof CliExit) {