@openape/apes 1.13.0 → 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("");
@@ -4360,10 +4439,11 @@ var DEFAULT_ALLOW_PATTERNS = [
4360
4439
  // wrapped invocation.
4361
4440
  "openape-chat-bridge",
4362
4441
  // Phase E: per-agent pm2 management. The Nest shells out
4363
- // `apes run --as <agent> -- pm2 startOrReload /var/openape/nest/agents/<agent>/ecosystem.config.js`
4364
- // and `apes run --as <agent> -- pm2 delete openape-bridge-<agent>`.
4365
- // Inner-command (post-unwrap) targets:
4366
- "pm2 startOrReload *",
4442
+ // `apes run --as <agent> -- bash /var/openape/agents/<agent>/start.sh`
4443
+ // (the start.sh sets HOME/PM2_HOME and redirects pm2's stdio so the
4444
+ // god-daemon detach doesn't block our exec parent), plus
4445
+ // `apes run --as <agent> -- pm2 delete openape-bridge-<agent>` for teardown.
4446
+ "bash /var/openape/agents/*/start.sh",
4367
4447
  "pm2 delete openape-bridge-*",
4368
4448
  "pm2 jlist"
4369
4449
  ];
@@ -4383,11 +4463,11 @@ var authorizeNestCommand = defineCommand30({
4383
4463
  }
4384
4464
  },
4385
4465
  async run({ args }) {
4386
- const nestAuthPath = join9(NEST_DATA_DIR, ".config", "apes", "auth.json");
4387
- if (!existsSync11(nestAuthPath)) {
4466
+ const nestAuthPath = join10(NEST_DATA_DIR, ".config", "apes", "auth.json");
4467
+ if (!existsSync12(nestAuthPath)) {
4388
4468
  throw new CliError("Nest not enrolled. Run `apes nest enroll` first.");
4389
4469
  }
4390
- const nestAuth = JSON.parse(readFileSync9(nestAuthPath, "utf8"));
4470
+ const nestAuth = JSON.parse(readFileSync10(nestAuthPath, "utf8"));
4391
4471
  if (!nestAuth.email) throw new CliError(`${nestAuthPath} has no email`);
4392
4472
  const allow = args.allow ?? DEFAULT_ALLOW_PATTERNS.join(",");
4393
4473
  consola26.info(`Configuring YOLO-policy on ${nestAuth.email} via \`apes yolo set\`\u2026`);
@@ -4414,102 +4494,31 @@ var authorizeNestCommand = defineCommand30({
4414
4494
  });
4415
4495
 
4416
4496
  // src/commands/nest/destroy.ts
4497
+ import { execFileSync as execFileSync9 } from "child_process";
4417
4498
  import { defineCommand as defineCommand31 } from "citty";
4418
4499
  import consola27 from "consola";
4419
-
4420
- // src/lib/nest-intent.ts
4421
- import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync10, statSync as statSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
4422
- import { homedir as homedir10 } from "os";
4423
- import { join as join10 } from "path";
4424
- import { randomUUID } from "crypto";
4425
- var POLL_INTERVAL_MS = 200;
4426
- var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
4427
- function resolveIntentDir() {
4428
- if (process.env.OPENAPE_NEST_INTENT_DIR) return process.env.OPENAPE_NEST_INTENT_DIR;
4429
- if (existsSync12("/var/openape/nest/intents")) return "/var/openape/nest/intents";
4430
- return join10(homedir10(), ".openape", "nest", "intents");
4431
- }
4432
- async function dispatchIntent(intent, opts = {}) {
4433
- const id = randomUUID();
4434
- const dir = resolveIntentDir();
4435
- if (!existsSync12(dir)) {
4436
- throw new CliError(`Nest intent dir does not exist: ${dir}
4437
- Is the nest daemon running? Try \`ps aux | grep openape-nest\`.`);
4438
- }
4439
- const intentPath = join10(dir, `${id}.json`);
4440
- const responsePath = join10(dir, `${id}.response`);
4441
- const tmpPath = `${intentPath}.tmp`;
4442
- writeFileSync6(tmpPath, `${JSON.stringify({ id, ...intent })}
4443
- `, { mode: 432 });
4444
- try {
4445
- const fs = await import("fs");
4446
- fs.renameSync(tmpPath, intentPath);
4447
- } catch (err) {
4448
- try {
4449
- unlinkSync(tmpPath);
4450
- } catch {
4451
- }
4452
- throw err;
4453
- }
4454
- const deadline = Date.now() + (opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
4455
- while (Date.now() < deadline) {
4456
- if (existsSync12(responsePath)) {
4457
- let raw;
4458
- try {
4459
- const st = statSync2(responsePath);
4460
- if (Date.now() - st.mtimeMs < 50) {
4461
- await sleep(50);
4462
- }
4463
- raw = readFileSync10(responsePath, "utf8");
4464
- } catch {
4465
- await sleep(POLL_INTERVAL_MS);
4466
- continue;
4467
- }
4468
- try {
4469
- unlinkSync(responsePath);
4470
- } catch {
4471
- }
4472
- let parsed;
4473
- try {
4474
- parsed = JSON.parse(raw);
4475
- } catch (err) {
4476
- throw new CliError(`malformed nest response: ${err instanceof Error ? err.message : String(err)}`);
4477
- }
4478
- if (!parsed.ok) {
4479
- throw new CliError(`nest: ${parsed.error}`);
4480
- }
4481
- return parsed.result;
4482
- }
4483
- await sleep(POLL_INTERVAL_MS);
4484
- }
4485
- try {
4486
- unlinkSync(intentPath);
4487
- } catch {
4488
- }
4489
- throw new CliError(`nest intent timeout (${(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS) / 1e3}s) \u2014 Nest daemon may not be running or is stuck.`);
4490
- }
4491
- function sleep(ms) {
4492
- return new Promise((resolve4) => setTimeout(resolve4, ms));
4493
- }
4494
-
4495
- // src/commands/nest/destroy.ts
4496
4500
  var destroyNestCommand = defineCommand31({
4497
4501
  meta: {
4498
4502
  name: "destroy",
4499
- 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."
4500
4504
  },
4501
4505
  args: {
4502
4506
  name: { type: "positional", required: true, description: "Agent name to destroy" }
4503
4507
  },
4504
4508
  async run({ args }) {
4505
4509
  const name = String(args.name);
4506
- await dispatchIntent({ action: "destroy", name });
4507
- 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
+ }
4508
4517
  }
4509
4518
  });
4510
4519
 
4511
4520
  // src/commands/nest/install.ts
4512
- import { execFileSync as execFileSync9 } from "child_process";
4521
+ import { execFileSync as execFileSync10 } from "child_process";
4513
4522
  import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
4514
4523
  import { homedir as homedir11, userInfo as userInfo2 } from "os";
4515
4524
  import { dirname as dirname3, join as join11 } from "path";
@@ -4707,10 +4716,10 @@ var installNestCommand = defineCommand32({
4707
4716
  }
4708
4717
  const uid = userInfo2().uid;
4709
4718
  try {
4710
- execFileSync9("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
4719
+ execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
4711
4720
  } catch {
4712
4721
  }
4713
- execFileSync9("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
4722
+ execFileSync10("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
4714
4723
  consola28.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
4715
4724
  consola28.info("");
4716
4725
  consola28.info("Next steps for zero-prompt spawn \u2014 both one-time:");
@@ -4728,23 +4737,23 @@ import consola29 from "consola";
4728
4737
  var listNestCommand = defineCommand33({
4729
4738
  meta: {
4730
4739
  name: "list",
4731
- 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."
4732
4741
  },
4733
4742
  args: {
4734
4743
  json: { type: "boolean", description: "JSON output for scripts" }
4735
4744
  },
4736
4745
  async run({ args }) {
4737
- const result = await dispatchIntent({ action: "list" });
4746
+ const reg = readNestRegistry();
4738
4747
  if (args.json) {
4739
- console.log(JSON.stringify(result, null, 2));
4748
+ console.log(JSON.stringify(reg, null, 2));
4740
4749
  return;
4741
4750
  }
4742
- if (result.agents.length === 0) {
4751
+ if (reg.agents.length === 0) {
4743
4752
  consola29.info("(no agents registered with this nest)");
4744
4753
  return;
4745
4754
  }
4746
- consola29.info(`${result.agents.length} agent(s) registered with this nest:`);
4747
- 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) {
4748
4757
  const bridge = a.bridge ? " bridge=on" : "";
4749
4758
  consola29.info(` ${a.name.padEnd(16)} uid=${String(a.uid).padEnd(5)} home=${a.home}${bridge}`);
4750
4759
  }
@@ -4752,38 +4761,51 @@ var listNestCommand = defineCommand33({
4752
4761
  });
4753
4762
 
4754
4763
  // src/commands/nest/spawn.ts
4764
+ import { execFileSync as execFileSync11 } from "child_process";
4755
4765
  import { defineCommand as defineCommand34 } from "citty";
4756
4766
  import consola30 from "consola";
4757
4767
  var spawnNestCommand = defineCommand34({
4758
4768
  meta: {
4759
4769
  name: "spawn",
4760
- 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."
4761
4771
  },
4762
4772
  args: {
4763
4773
  name: { type: "positional", required: true, description: "Agent name (lowercase, [a-z0-9-], max 24 chars)" },
4764
4774
  "no-bridge": { type: "boolean", description: "Skip installing the chat-bridge daemon (default: install it)" },
4765
4775
  "bridge-key": { type: "string", description: "Override LITELLM_API_KEY (default: read from ~/litellm/.env)" },
4766
- "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" },
4767
4777
  "bridge-model": { type: "string", description: "Override APE_CHAT_BRIDGE_MODEL" }
4768
4778
  },
4769
4779
  async run({ args }) {
4770
4780
  const name = String(args.name);
4771
- const intent = {
4772
- action: "spawn",
4773
- name,
4774
- bridge: !args["no-bridge"]
4775
- };
4776
- if (typeof args["bridge-key"] === "string") intent.bridgeKey = args["bridge-key"];
4777
- if (typeof args["bridge-base-url"] === "string") intent.bridgeBaseUrl = args["bridge-base-url"];
4778
- if (typeof args["bridge-model"] === "string") intent.bridgeModel = args["bridge-model"];
4779
- const result = await dispatchIntent(intent);
4780
- 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
+ }
4781
4803
  }
4782
4804
  });
4783
4805
 
4784
4806
  // src/commands/nest/uninstall.ts
4785
- import { execFileSync as execFileSync10 } from "child_process";
4786
- 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";
4787
4809
  import { homedir as homedir12, userInfo as userInfo3 } from "os";
4788
4810
  import { join as join12 } from "path";
4789
4811
  import { defineCommand as defineCommand35 } from "citty";
@@ -4798,13 +4820,13 @@ var uninstallNestCommand = defineCommand35({
4798
4820
  const uid = userInfo3().uid;
4799
4821
  const path2 = join12(homedir12(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
4800
4822
  try {
4801
- execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
4823
+ execFileSync12("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
4802
4824
  consola31.success("Nest daemon stopped");
4803
4825
  } catch {
4804
4826
  consola31.info("Nest daemon was not loaded");
4805
4827
  }
4806
4828
  if (existsSync14(path2)) {
4807
- unlinkSync2(path2);
4829
+ unlinkSync(path2);
4808
4830
  consola31.success(`Removed ${path2}`);
4809
4831
  }
4810
4832
  consola31.info("Registry at ~/.openape/nest/agents.json kept \u2014 re-run `apes nest install` to resume supervision.");
@@ -5352,7 +5374,7 @@ var adapterCommand = defineCommand41({
5352
5374
  });
5353
5375
 
5354
5376
  // src/commands/run.ts
5355
- import { execFileSync as execFileSync11 } from "child_process";
5377
+ import { execFileSync as execFileSync13 } from "child_process";
5356
5378
  import { hostname as hostname5 } from "os";
5357
5379
  import { basename } from "path";
5358
5380
  import { defineCommand as defineCommand42 } from "citty";
@@ -5630,7 +5652,7 @@ function execShellCommand(command) {
5630
5652
  throw new CliError("No command to execute");
5631
5653
  try {
5632
5654
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
5633
- execFileSync11(command[0], command.slice(1), {
5655
+ execFileSync13(command[0], command.slice(1), {
5634
5656
  stdio: "inherit",
5635
5657
  env: inheritedEnv
5636
5658
  });
@@ -5782,7 +5804,7 @@ async function runAudienceMode(audience, action, args) {
5782
5804
  consola36.info(`Executing: ${command.join(" ")}`);
5783
5805
  try {
5784
5806
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
5785
- execFileSync11(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
5807
+ execFileSync13(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
5786
5808
  stdio: "inherit",
5787
5809
  env: inheritedEnv
5788
5810
  });
@@ -6284,7 +6306,7 @@ var mcpCommand = defineCommand48({
6284
6306
  if (transport !== "stdio" && transport !== "sse") {
6285
6307
  throw new Error('Transport must be "stdio" or "sse"');
6286
6308
  }
6287
- const { startMcpServer } = await import("./server-HYDAVEQI.js");
6309
+ const { startMcpServer } = await import("./server-P2XXAHS5.js");
6288
6310
  await startMcpServer(transport, port);
6289
6311
  }
6290
6312
  });
@@ -6292,7 +6314,7 @@ var mcpCommand = defineCommand48({
6292
6314
  // src/commands/init/index.ts
6293
6315
  import { existsSync as existsSync15, copyFileSync, writeFileSync as writeFileSync9 } from "fs";
6294
6316
  import { randomBytes } from "crypto";
6295
- import { execFileSync as execFileSync12 } from "child_process";
6317
+ import { execFileSync as execFileSync14 } from "child_process";
6296
6318
  import { join as join14 } from "path";
6297
6319
  import { defineCommand as defineCommand49 } from "citty";
6298
6320
  import consola40 from "consola";
@@ -6304,11 +6326,11 @@ async function downloadTemplate(repo, targetDir) {
6304
6326
  function installDeps(dir) {
6305
6327
  const hasLockFile = (name) => existsSync15(join14(dir, name));
6306
6328
  if (hasLockFile("pnpm-lock.yaml")) {
6307
- execFileSync12("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
6329
+ execFileSync14("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
6308
6330
  } else if (hasLockFile("bun.lockb")) {
6309
- execFileSync12("bun", ["install"], { cwd: dir, stdio: "inherit" });
6331
+ execFileSync14("bun", ["install"], { cwd: dir, stdio: "inherit" });
6310
6332
  } else {
6311
- execFileSync12("npm", ["install"], { cwd: dir, stdio: "inherit" });
6333
+ execFileSync14("npm", ["install"], { cwd: dir, stdio: "inherit" });
6312
6334
  }
6313
6335
  }
6314
6336
  async function promptChoice(message, choices) {
@@ -6922,7 +6944,7 @@ async function bestEffortGrantCount(idp) {
6922
6944
  }
6923
6945
  }
6924
6946
  async function runHealth(args) {
6925
- const version = true ? "1.13.0" : "0.0.0";
6947
+ const version = true ? "1.14.0" : "0.0.0";
6926
6948
  const auth = loadAuth();
6927
6949
  if (!auth) {
6928
6950
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -7195,10 +7217,10 @@ if (shellRewrite) {
7195
7217
  if (shellRewrite.action === "rewrite") {
7196
7218
  process.argv = shellRewrite.argv;
7197
7219
  } else if (shellRewrite.action === "version") {
7198
- console.log(`ape-shell ${"1.13.0"} (OpenApe DDISA shell wrapper)`);
7220
+ console.log(`ape-shell ${"1.14.0"} (OpenApe DDISA shell wrapper)`);
7199
7221
  process.exit(0);
7200
7222
  } else if (shellRewrite.action === "help") {
7201
- console.log(`ape-shell ${"1.13.0"} \u2014 OpenApe DDISA shell wrapper`);
7223
+ console.log(`ape-shell ${"1.14.0"} \u2014 OpenApe DDISA shell wrapper`);
7202
7224
  console.log("");
7203
7225
  console.log("Usage:");
7204
7226
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -7256,7 +7278,7 @@ var configCommand = defineCommand60({
7256
7278
  var main = defineCommand60({
7257
7279
  meta: {
7258
7280
  name: "apes",
7259
- version: "1.13.0",
7281
+ version: "1.14.0",
7260
7282
  description: "Unified CLI for OpenApe"
7261
7283
  },
7262
7284
  subCommands: {
@@ -7313,7 +7335,7 @@ async function maybeRefreshAuth() {
7313
7335
  }
7314
7336
  }
7315
7337
  await maybeRefreshAuth();
7316
- await maybeWarnStaleVersion("1.13.0").catch(() => {
7338
+ await maybeWarnStaleVersion("1.14.0").catch(() => {
7317
7339
  });
7318
7340
  runMain(main).catch((err) => {
7319
7341
  if (err instanceof CliExit) {