@openape/apes 1.9.0 → 1.11.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
@@ -7,8 +7,11 @@ import {
7
7
  import {
8
8
  CliError,
9
9
  CliExit,
10
- parseDuration
11
- } from "./chunk-ZSJU7IXE.js";
10
+ RpcSessionMap,
11
+ parseDuration,
12
+ runLoop,
13
+ taskTools
14
+ } from "./chunk-TDSCDH5P.js";
12
15
  import {
13
16
  loadEd25519PrivateKey,
14
17
  readPublicKeyComment
@@ -317,7 +320,7 @@ async function loginWithPKCE(idp) {
317
320
  authUrl.searchParams.set("state", state);
318
321
  authUrl.searchParams.set("nonce", nonce);
319
322
  authUrl.searchParams.set("scope", "openid email profile offline_access");
320
- const code = await new Promise((resolve5, reject) => {
323
+ const code = await new Promise((resolve4, reject) => {
321
324
  const server = createServer((req, res) => {
322
325
  const url = new URL(req.url, `http://localhost:${CALLBACK_PORT}`);
323
326
  if (url.pathname === "/callback") {
@@ -334,7 +337,7 @@ async function loginWithPKCE(idp) {
334
337
  res.writeHead(200, { "Content-Type": "text/html" });
335
338
  res.end("<h1>Login successful!</h1><p>You can close this window.</p>");
336
339
  server.close();
337
- resolve5(authCode);
340
+ resolve4(authCode);
338
341
  return;
339
342
  }
340
343
  res.writeHead(400);
@@ -390,7 +393,7 @@ async function loginWithPKCE(idp) {
390
393
  consola2.success(`Logged in as ${payload.email || payload.sub}`);
391
394
  }
392
395
  async function loginWithKey(idp, keyPath, agentEmail) {
393
- const { readFileSync: readFileSync15 } = await import("fs");
396
+ const { readFileSync: readFileSync14 } = await import("fs");
394
397
  const { sign: sign3 } = await import("crypto");
395
398
  const { loadEd25519PrivateKey: loadEd25519PrivateKey2 } = await import("./ssh-key-6X3YZXSD.js");
396
399
  const challengeUrl = await getAgentChallengeEndpoint(idp);
@@ -403,7 +406,7 @@ async function loginWithKey(idp, keyPath, agentEmail) {
403
406
  throw new CliError(`Challenge failed: ${await challengeResp.text()}`);
404
407
  }
405
408
  const { challenge } = await challengeResp.json();
406
- const keyContent = readFileSync15(keyPath, "utf-8");
409
+ const keyContent = readFileSync14(keyPath, "utf-8");
407
410
  const privateKey = loadEd25519PrivateKey2(keyContent);
408
411
  const signature = sign3(null, Buffer2.from(challenge), privateKey).toString("base64");
409
412
  const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
@@ -895,7 +898,7 @@ async function waitForApproval2(grantsUrl, grantId) {
895
898
  if (grant.status === "revoked") {
896
899
  throw new CliError("Grant revoked.");
897
900
  }
898
- await new Promise((resolve5) => setTimeout(resolve5, interval));
901
+ await new Promise((resolve4) => setTimeout(resolve4, interval));
899
902
  }
900
903
  throw new CliError("Timed out waiting for approval.");
901
904
  }
@@ -2262,7 +2265,7 @@ function createFetch(globalOptions = {}) {
2262
2265
  if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) {
2263
2266
  const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0;
2264
2267
  if (retryDelay > 0) {
2265
- await new Promise((resolve5) => setTimeout(resolve5, retryDelay));
2268
+ await new Promise((resolve4) => setTimeout(resolve4, retryDelay));
2266
2269
  }
2267
2270
  return $fetchRaw(context.request, {
2268
2271
  ...context.options,
@@ -2702,23 +2705,9 @@ chown root:wheel ${shQuote(bridge.plistPath)}
2702
2705
  chmod 644 ${shQuote(bridge.plistPath)}
2703
2706
  `;
2704
2707
  }
2705
- function buildBridgeBootstrapBlock(bridge, name) {
2708
+ function buildBridgeBootstrapBlock(bridge, _name) {
2706
2709
  if (!bridge) return "";
2707
2710
  return `
2708
- echo "==> Installing bridge stack as ${name} via bun (one-time)\u2026"
2709
- su - ${shQuote(name)} -c '
2710
- set -euo pipefail
2711
- if ! command -v bun >/dev/null 2>&1 && [ ! -x "$HOME/.bun/bin/bun" ]; then
2712
- echo "==> bun not found \u2014 installing via official installer"
2713
- curl -fsSL https://bun.sh/install | bash
2714
- fi
2715
- export PATH="$HOME/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$HOME/.bun/install/global/bin"
2716
- bun add -g @openape/chat-bridge @openape/apes
2717
- '
2718
-
2719
- # Bootstrap into the system domain. Spawn already runs as root via
2720
- # \`apes run --as root\`, so we have permission. Stale label is bootouted
2721
- # first to make re-spawn idempotent.
2722
2711
  launchctl bootout "system/${bridge.plistLabel}" 2>/dev/null || true
2723
2712
  launchctl bootstrap system ${shQuote(bridge.plistPath)} || \\
2724
2713
  echo "warn: bridge bootstrap into system domain failed; check ${bridge.plistPath}"
@@ -3006,7 +2995,7 @@ function readPasswordSilent(prompt) {
3006
2995
  "No TTY available for the silent password prompt. Set APES_ADMIN_PASSWORD in the environment instead."
3007
2996
  ));
3008
2997
  }
3009
- return new Promise((resolve5, reject) => {
2998
+ return new Promise((resolve4, reject) => {
3010
2999
  process.stdout.write(prompt);
3011
3000
  const wasRaw = process.stdin.isRaw ?? false;
3012
3001
  process.stdin.setRawMode(true);
@@ -3021,7 +3010,7 @@ function readPasswordSilent(prompt) {
3021
3010
  if (ch === "\r" || ch === "\n") {
3022
3011
  cleanup();
3023
3012
  process.stdout.write("\n");
3024
- resolve5(buf);
3013
+ resolve4(buf);
3025
3014
  return;
3026
3015
  }
3027
3016
  if (code === 3) {
@@ -3317,481 +3306,12 @@ var registerAgentCommand = defineCommand23({
3317
3306
  });
3318
3307
 
3319
3308
  // src/commands/agents/run.ts
3320
- import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
3321
- import { homedir as homedir5 } from "os";
3309
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
3310
+ import { homedir as homedir4 } from "os";
3322
3311
  import { join as join3 } from "path";
3323
3312
  import { defineCommand as defineCommand24 } from "citty";
3324
3313
  import consola22 from "consola";
3325
3314
 
3326
- // src/lib/agent-tools/file.ts
3327
- import { mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
3328
- import { homedir as homedir4 } from "os";
3329
- import { dirname, normalize, resolve as resolve2 } from "path";
3330
- var MAX_BYTES = 1024 * 1024;
3331
- function jailPath(input) {
3332
- if (typeof input !== "string" || input === "") {
3333
- throw new Error("path must be a non-empty string");
3334
- }
3335
- const home = homedir4();
3336
- const candidate = input.startsWith("~/") ? resolve2(home, input.slice(2)) : input.startsWith("/") ? normalize(input) : resolve2(home, input);
3337
- if (candidate !== home && !candidate.startsWith(`${home}/`)) {
3338
- throw new Error(`path "${input}" resolves outside the agent's home`);
3339
- }
3340
- return candidate;
3341
- }
3342
- var fileTools = [
3343
- {
3344
- name: "file.read",
3345
- description: "Read a UTF-8 file from the agent's home directory ($HOME). Capped at 1MB. Path traversal blocked.",
3346
- parameters: {
3347
- type: "object",
3348
- properties: {
3349
- path: { type: "string", description: "Path relative to $HOME (or absolute under $HOME). `..` segments are rejected." }
3350
- },
3351
- required: ["path"]
3352
- },
3353
- execute: async (args) => {
3354
- const a = args;
3355
- const p2 = jailPath(a.path);
3356
- const content = readFileSync4(p2, "utf8");
3357
- if (Buffer.byteLength(content, "utf8") > MAX_BYTES) {
3358
- return { path: p2, truncated: true, content: content.slice(0, MAX_BYTES) };
3359
- }
3360
- return { path: p2, truncated: false, content };
3361
- }
3362
- },
3363
- {
3364
- name: "file.write",
3365
- description: "Write a UTF-8 file under the agent's home directory. Creates parent dirs as needed. 1MB max.",
3366
- parameters: {
3367
- type: "object",
3368
- properties: {
3369
- path: { type: "string", description: "Path relative to $HOME (or absolute under $HOME)." },
3370
- content: { type: "string", description: "File body. Existing files are overwritten." }
3371
- },
3372
- required: ["path", "content"]
3373
- },
3374
- execute: async (args) => {
3375
- const a = args;
3376
- if (typeof a.content !== "string") throw new Error("content must be a string");
3377
- if (Buffer.byteLength(a.content, "utf8") > MAX_BYTES) {
3378
- throw new Error(`content exceeds ${MAX_BYTES} byte cap`);
3379
- }
3380
- const p2 = jailPath(a.path);
3381
- mkdirSync(dirname(p2), { recursive: true });
3382
- writeFileSync2(p2, a.content, { encoding: "utf8" });
3383
- return { path: p2, bytes: Buffer.byteLength(a.content, "utf8") };
3384
- }
3385
- }
3386
- ];
3387
-
3388
- // src/lib/agent-tools/http.ts
3389
- var MAX_BYTES2 = 1024 * 1024;
3390
- var FORBIDDEN_HEADERS = /* @__PURE__ */ new Set([
3391
- "host",
3392
- "authorization",
3393
- "cookie",
3394
- "connection",
3395
- "transfer-encoding",
3396
- "upgrade",
3397
- "proxy-authorization"
3398
- ]);
3399
- function sanitizeHeaders(input) {
3400
- if (!input || typeof input !== "object") return {};
3401
- const out = {};
3402
- for (const [k, v] of Object.entries(input)) {
3403
- if (typeof v !== "string") continue;
3404
- if (FORBIDDEN_HEADERS.has(k.toLowerCase())) continue;
3405
- out[k] = v;
3406
- }
3407
- return out;
3408
- }
3409
- async function readCappedBody(res) {
3410
- const buf = new Uint8Array(MAX_BYTES2 + 1);
3411
- let written = 0;
3412
- const reader = res.body?.getReader();
3413
- if (!reader) return await res.text();
3414
- while (true) {
3415
- const { value, done } = await reader.read();
3416
- if (done) break;
3417
- if (written + value.byteLength > MAX_BYTES2) {
3418
- buf.set(value.subarray(0, MAX_BYTES2 - written), written);
3419
- written = MAX_BYTES2;
3420
- try {
3421
- await reader.cancel();
3422
- } catch {
3423
- }
3424
- break;
3425
- }
3426
- buf.set(value, written);
3427
- written += value.byteLength;
3428
- }
3429
- return new TextDecoder().decode(buf.subarray(0, written));
3430
- }
3431
- var httpTools = [
3432
- {
3433
- name: "http.get",
3434
- description: "GET an HTTPS URL and return the response body (capped at 1MB). Useful for reading public APIs, RSS feeds, web pages.",
3435
- parameters: {
3436
- type: "object",
3437
- properties: {
3438
- url: { type: "string", description: "Absolute HTTPS URL." },
3439
- headers: { type: "object", description: "Optional headers (Host, Authorization, Cookie are stripped)." }
3440
- },
3441
- required: ["url"]
3442
- },
3443
- execute: async (args) => {
3444
- const a = args;
3445
- if (typeof a.url !== "string" || !a.url.startsWith("http")) {
3446
- throw new Error("url must be an http(s) URL");
3447
- }
3448
- const res = await fetch(a.url, { method: "GET", headers: sanitizeHeaders(a.headers) });
3449
- const body = await readCappedBody(res);
3450
- return { status: res.status, headers: Object.fromEntries(res.headers), body };
3451
- }
3452
- },
3453
- {
3454
- name: "http.post",
3455
- description: "POST JSON to an HTTPS URL and return the response body (capped at 1MB).",
3456
- parameters: {
3457
- type: "object",
3458
- properties: {
3459
- url: { type: "string", description: "Absolute HTTPS URL." },
3460
- body: { description: "JSON-serialisable payload." },
3461
- headers: { type: "object", description: "Optional headers (Host, Authorization, Cookie are stripped)." }
3462
- },
3463
- required: ["url", "body"]
3464
- },
3465
- execute: async (args) => {
3466
- const a = args;
3467
- if (typeof a.url !== "string" || !a.url.startsWith("http")) {
3468
- throw new Error("url must be an http(s) URL");
3469
- }
3470
- const res = await fetch(a.url, {
3471
- method: "POST",
3472
- headers: { "content-type": "application/json", ...sanitizeHeaders(a.headers) },
3473
- body: JSON.stringify(a.body)
3474
- });
3475
- const body = await readCappedBody(res);
3476
- return { status: res.status, headers: Object.fromEntries(res.headers), body };
3477
- }
3478
- }
3479
- ];
3480
-
3481
- // src/lib/agent-tools/mail.ts
3482
- import { execFileSync as execFileSync5 } from "child_process";
3483
- function o365(args) {
3484
- try {
3485
- return execFileSync5("o365-cli", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
3486
- } catch (err) {
3487
- const e = err;
3488
- if (e.code === "ENOENT") {
3489
- throw new Error("o365-cli is not installed on this agent host");
3490
- }
3491
- const stderr = typeof e.stderr === "string" ? e.stderr : e.stderr?.toString("utf8");
3492
- throw new Error(`o365-cli failed: ${stderr ?? e.message ?? err}`);
3493
- }
3494
- }
3495
- var mailTools = [
3496
- {
3497
- name: "mail.list",
3498
- description: "List recent inbox messages via o365-cli. Optional `unread_only` and `limit`.",
3499
- parameters: {
3500
- type: "object",
3501
- properties: {
3502
- limit: { type: "integer", minimum: 1, maximum: 100, default: 20 },
3503
- unread_only: { type: "boolean", default: false }
3504
- },
3505
- required: []
3506
- },
3507
- execute: async (args) => {
3508
- const a = args ?? {};
3509
- const argv = ["mail", "list", "--json", "--limit", String(a.limit ?? 20)];
3510
- if (a.unread_only) argv.push("--unread");
3511
- const out = o365(argv);
3512
- try {
3513
- return JSON.parse(out);
3514
- } catch {
3515
- return { raw: out };
3516
- }
3517
- }
3518
- },
3519
- {
3520
- name: "mail.search",
3521
- description: "Search the inbox via o365-cli using a free-form query string.",
3522
- parameters: {
3523
- type: "object",
3524
- properties: {
3525
- q: { type: "string" },
3526
- limit: { type: "integer", minimum: 1, maximum: 100, default: 20 }
3527
- },
3528
- required: ["q"]
3529
- },
3530
- execute: async (args) => {
3531
- const a = args;
3532
- if (typeof a.q !== "string" || a.q.length === 0) throw new Error("q is required");
3533
- const argv = ["mail", "search", a.q, "--json", "--limit", String(a.limit ?? 20)];
3534
- const out = o365(argv);
3535
- try {
3536
- return JSON.parse(out);
3537
- } catch {
3538
- return { raw: out };
3539
- }
3540
- }
3541
- }
3542
- ];
3543
-
3544
- // src/lib/agent-tools/tasks.ts
3545
- import { execFileSync as execFileSync6 } from "child_process";
3546
- function ape(args) {
3547
- try {
3548
- return execFileSync6("ape-tasks", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
3549
- } catch (err) {
3550
- const e = err;
3551
- const stderr = typeof e.stderr === "string" ? e.stderr : e.stderr?.toString("utf8");
3552
- throw new Error(`ape-tasks failed: ${stderr ?? e.message ?? err}`);
3553
- }
3554
- }
3555
- var tasksTools = [
3556
- {
3557
- name: "tasks.list",
3558
- description: "List the owner's open ape-tasks (the user's personal task list at tasks.openape.ai).",
3559
- parameters: {
3560
- type: "object",
3561
- properties: {
3562
- status: { type: "string", enum: ["open", "doing", "done", "archived"] },
3563
- team_id: { type: "string" }
3564
- },
3565
- required: []
3566
- },
3567
- execute: async (args) => {
3568
- const a = args ?? {};
3569
- const argv = ["list", "--json"];
3570
- if (a.status) argv.push("--status", a.status);
3571
- if (a.team_id) argv.push("--team", a.team_id);
3572
- const out = ape(argv);
3573
- try {
3574
- return JSON.parse(out);
3575
- } catch {
3576
- return { raw: out };
3577
- }
3578
- }
3579
- },
3580
- {
3581
- name: "tasks.create",
3582
- description: "Create a new ape-task on the owner's task list at tasks.openape.ai.",
3583
- parameters: {
3584
- type: "object",
3585
- properties: {
3586
- title: { type: "string" },
3587
- notes: { type: "string" },
3588
- priority: { type: "string", enum: ["low", "med", "high"] },
3589
- due_at: { type: "string", description: "ISO date or +Nh/+Nd shorthand." }
3590
- },
3591
- required: ["title"]
3592
- },
3593
- execute: async (args) => {
3594
- const a = args;
3595
- const argv = ["new", "--title", a.title, "--json"];
3596
- if (a.notes) argv.push("--notes", a.notes);
3597
- if (a.priority) argv.push("--priority", a.priority);
3598
- if (a.due_at) argv.push("--due", a.due_at);
3599
- const out = ape(argv);
3600
- try {
3601
- return JSON.parse(out);
3602
- } catch {
3603
- return { raw: out };
3604
- }
3605
- }
3606
- }
3607
- ];
3608
-
3609
- // src/lib/agent-tools/time.ts
3610
- var timeTools = [
3611
- {
3612
- name: "time.now",
3613
- description: "Returns the current UTC date and time as ISO 8601 plus epoch seconds. No inputs.",
3614
- parameters: { type: "object", properties: {}, required: [] },
3615
- execute: async () => {
3616
- const now = /* @__PURE__ */ new Date();
3617
- return {
3618
- iso: now.toISOString(),
3619
- epoch_seconds: Math.floor(now.getTime() / 1e3),
3620
- timezone_offset_minutes: -now.getTimezoneOffset()
3621
- };
3622
- }
3623
- }
3624
- ];
3625
-
3626
- // src/lib/agent-tools/index.ts
3627
- var ALL_TOOLS = [
3628
- ...timeTools,
3629
- ...httpTools,
3630
- ...fileTools,
3631
- ...tasksTools,
3632
- ...mailTools
3633
- ];
3634
- var TOOLS = Object.fromEntries(
3635
- ALL_TOOLS.map((t) => [t.name, t])
3636
- );
3637
- function taskTools(names) {
3638
- const out = [];
3639
- const missing = [];
3640
- for (const name of names) {
3641
- const tool = TOOLS[name];
3642
- if (!tool) missing.push(name);
3643
- else out.push(tool);
3644
- }
3645
- if (missing.length > 0) {
3646
- throw new Error(`unknown tool(s): ${missing.join(", ")}`);
3647
- }
3648
- return out;
3649
- }
3650
- function asOpenAiTools(tools) {
3651
- return tools.map((t) => ({
3652
- type: "function",
3653
- function: { name: wireToolName(t.name), description: t.description, parameters: t.parameters }
3654
- }));
3655
- }
3656
- function wireToolName(local) {
3657
- return local.replace(/\./g, "_");
3658
- }
3659
- function localToolName(wire) {
3660
- for (const t of Object.values(TOOLS)) {
3661
- if (wireToolName(t.name) === wire) return t.name;
3662
- }
3663
- return wire;
3664
- }
3665
-
3666
- // src/lib/agent-runtime.ts
3667
- function previewJson(value, max = 500) {
3668
- let s;
3669
- try {
3670
- s = JSON.stringify(value);
3671
- } catch {
3672
- s = String(value);
3673
- }
3674
- return s.length > max ? `${s.slice(0, max)}\u2026` : s;
3675
- }
3676
- async function runLoop(opts) {
3677
- const fetchFn = opts.fetchImpl ?? fetch;
3678
- const trace = [];
3679
- const messages = [
3680
- { role: "system", content: opts.systemPrompt },
3681
- ...opts.history ?? [],
3682
- { role: "user", content: opts.userMessage }
3683
- ];
3684
- const tools = asOpenAiTools(opts.tools);
3685
- for (let step = 1; step <= opts.maxSteps; step++) {
3686
- const res = await fetchFn(`${opts.config.apiBase}/chat/completions`, {
3687
- method: "POST",
3688
- headers: {
3689
- "authorization": `Bearer ${opts.config.apiKey}`,
3690
- "content-type": "application/json"
3691
- },
3692
- body: JSON.stringify({
3693
- model: opts.config.model,
3694
- messages,
3695
- ...tools.length > 0 ? { tools, tool_choice: "auto" } : {}
3696
- })
3697
- });
3698
- if (!res.ok) {
3699
- const text = await res.text().catch(() => "");
3700
- throw new Error(`LiteLLM ${res.status}: ${text.slice(0, 500)}`);
3701
- }
3702
- const data = await res.json();
3703
- const choice = data.choices?.[0];
3704
- if (!choice) throw new Error("LiteLLM response had no choices");
3705
- const assistant = choice.message;
3706
- messages.push(assistant);
3707
- if (assistant.content) opts.handlers?.onTextDelta?.(assistant.content);
3708
- trace.push({
3709
- step,
3710
- type: "assistant",
3711
- preview: previewJson({ content: assistant.content, tool_calls: assistant.tool_calls?.length ?? 0 })
3712
- });
3713
- if (!assistant.tool_calls || assistant.tool_calls.length === 0) {
3714
- const result2 = {
3715
- status: "ok",
3716
- finalMessage: assistant.content,
3717
- stepCount: step,
3718
- trace
3719
- };
3720
- opts.handlers?.onDone?.(result2);
3721
- return result2;
3722
- }
3723
- for (const call of assistant.tool_calls) {
3724
- const wireName = call.function.name;
3725
- const localName = localToolName(wireName);
3726
- const tool = opts.tools.find((t) => t.name === localName);
3727
- let parsedArgs;
3728
- try {
3729
- parsedArgs = JSON.parse(call.function.arguments);
3730
- } catch {
3731
- parsedArgs = {};
3732
- }
3733
- opts.handlers?.onToolCall?.({ name: localName, args: parsedArgs });
3734
- trace.push({ step, type: "tool_call", tool: localName, preview: previewJson(parsedArgs) });
3735
- let result2;
3736
- let isError = false;
3737
- if (!tool) {
3738
- result2 = `unknown tool: ${localName}`;
3739
- isError = true;
3740
- } else {
3741
- try {
3742
- result2 = await tool.execute(parsedArgs);
3743
- } catch (err) {
3744
- result2 = err?.message ?? String(err);
3745
- isError = true;
3746
- }
3747
- }
3748
- if (isError) {
3749
- opts.handlers?.onToolError?.({ name: localName, error: String(result2) });
3750
- trace.push({ step, type: "tool_error", tool: localName, preview: previewJson(result2) });
3751
- } else {
3752
- opts.handlers?.onToolResult?.({ name: localName, result: result2 });
3753
- trace.push({ step, type: "tool_result", tool: localName, preview: previewJson(result2) });
3754
- }
3755
- messages.push({
3756
- role: "tool",
3757
- tool_call_id: call.id,
3758
- name: wireToolName(localName),
3759
- content: typeof result2 === "string" ? result2 : JSON.stringify(result2)
3760
- });
3761
- }
3762
- }
3763
- const result = {
3764
- status: "error",
3765
- finalMessage: `max_steps (${opts.maxSteps}) reached without completion`,
3766
- stepCount: opts.maxSteps,
3767
- trace
3768
- };
3769
- opts.handlers?.onDone?.(result);
3770
- return result;
3771
- }
3772
- var RPC_SESSION_TTL_MS = 60 * 60 * 1e3;
3773
- var RpcSessionMap = class {
3774
- sessions = /* @__PURE__ */ new Map();
3775
- get(id) {
3776
- const s = this.sessions.get(id);
3777
- if (s) s.lastTouched = Date.now();
3778
- return s;
3779
- }
3780
- put(id, s) {
3781
- s.lastTouched = Date.now();
3782
- this.sessions.set(id, s);
3783
- }
3784
- evictStale() {
3785
- const cutoff = Date.now() - RPC_SESSION_TTL_MS;
3786
- for (const [k, v] of this.sessions) {
3787
- if (v.lastTouched < cutoff) this.sessions.delete(k);
3788
- }
3789
- }
3790
- size() {
3791
- return this.sessions.size;
3792
- }
3793
- };
3794
-
3795
3315
  // src/lib/troop-client.ts
3796
3316
  var DEFAULT_TROOP_URL = "https://troop.openape.ai";
3797
3317
  var TroopClient = class {
@@ -3850,13 +3370,13 @@ function resolveTroopUrl(override) {
3850
3370
  }
3851
3371
 
3852
3372
  // src/commands/agents/run.ts
3853
- var AUTH_PATH = join3(homedir5(), ".config", "apes", "auth.json");
3854
- var TASK_CACHE_DIR = join3(homedir5(), ".openape", "agent", "tasks");
3373
+ var AUTH_PATH = join3(homedir4(), ".config", "apes", "auth.json");
3374
+ var TASK_CACHE_DIR = join3(homedir4(), ".openape", "agent", "tasks");
3855
3375
  function readAuth() {
3856
3376
  if (!existsSync5(AUTH_PATH)) {
3857
3377
  throw new CliError(`No agent auth found at ${AUTH_PATH}. Run \`apes agents spawn <name>\` first.`);
3858
3378
  }
3859
- const parsed = JSON.parse(readFileSync5(AUTH_PATH, "utf8"));
3379
+ const parsed = JSON.parse(readFileSync4(AUTH_PATH, "utf8"));
3860
3380
  if (!parsed.access_token) throw new CliError("auth.json missing access_token");
3861
3381
  return parsed;
3862
3382
  }
@@ -3896,22 +3416,22 @@ function readTaskSpec(taskId) {
3896
3416
  if (!existsSync5(path2)) {
3897
3417
  throw new CliError(`No cached task spec at ${path2}. Run \`apes agents sync\` first to pull the task list from troop.`);
3898
3418
  }
3899
- return JSON.parse(readFileSync5(path2, "utf8"));
3419
+ return JSON.parse(readFileSync4(path2, "utf8"));
3900
3420
  }
3901
- var AGENT_CONFIG_PATH = join3(homedir5(), ".openape", "agent", "agent.json");
3421
+ var AGENT_CONFIG_PATH = join3(homedir4(), ".openape", "agent", "agent.json");
3902
3422
  function readAgentConfig() {
3903
3423
  if (!existsSync5(AGENT_CONFIG_PATH)) return { systemPrompt: "" };
3904
3424
  try {
3905
- return JSON.parse(readFileSync5(AGENT_CONFIG_PATH, "utf8"));
3425
+ return JSON.parse(readFileSync4(AGENT_CONFIG_PATH, "utf8"));
3906
3426
  } catch {
3907
3427
  return { systemPrompt: "" };
3908
3428
  }
3909
3429
  }
3910
3430
  function readLitellmConfig(model) {
3911
- const envPath = join3(homedir5(), "litellm", ".env");
3431
+ const envPath = join3(homedir4(), "litellm", ".env");
3912
3432
  const env = {};
3913
3433
  if (existsSync5(envPath)) {
3914
- for (const line of readFileSync5(envPath, "utf8").split(/\r?\n/)) {
3434
+ for (const line of readFileSync4(envPath, "utf8").split(/\r?\n/)) {
3915
3435
  const m = line.match(/^([A-Z_]+)=(.*)$/);
3916
3436
  if (m) env[m[1]] = m[2].replace(/^["']|["']$/g, "");
3917
3437
  }
@@ -4016,17 +3536,17 @@ var runAgentCommand = defineCommand24({
4016
3536
  });
4017
3537
 
4018
3538
  // src/commands/agents/serve.ts
4019
- import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
4020
- import { homedir as homedir6 } from "os";
3539
+ import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
3540
+ import { homedir as homedir5 } from "os";
4021
3541
  import { join as join4 } from "path";
4022
3542
  import { createInterface } from "readline";
4023
3543
  import { defineCommand as defineCommand25 } from "citty";
4024
- var AUTH_PATH2 = join4(homedir6(), ".config", "apes", "auth.json");
3544
+ var AUTH_PATH2 = join4(homedir5(), ".config", "apes", "auth.json");
4025
3545
  function readLitellmConfig2(model) {
4026
- const envPath = join4(homedir6(), "litellm", ".env");
3546
+ const envPath = join4(homedir5(), "litellm", ".env");
4027
3547
  const env = {};
4028
3548
  if (existsSync6(envPath)) {
4029
- for (const line of readFileSync6(envPath, "utf8").split(/\r?\n/)) {
3549
+ for (const line of readFileSync5(envPath, "utf8").split(/\r?\n/)) {
4030
3550
  const m = line.match(/^([A-Z_]+)=(.*)$/);
4031
3551
  if (m) env[m[1]] = m[2].replace(/^["']|["']$/g, "");
4032
3552
  }
@@ -4060,7 +3580,7 @@ var serveAgentCommand = defineCommand25({
4060
3580
  }
4061
3581
  if (existsSync6(AUTH_PATH2)) {
4062
3582
  try {
4063
- JSON.parse(readFileSync6(AUTH_PATH2, "utf8"));
3583
+ JSON.parse(readFileSync5(AUTH_PATH2, "utf8"));
4064
3584
  } catch {
4065
3585
  }
4066
3586
  }
@@ -4135,8 +3655,8 @@ async function handleInbound(msg, sessions) {
4135
3655
  }
4136
3656
 
4137
3657
  // src/commands/agents/spawn.ts
4138
- import { execFileSync as execFileSync7 } from "child_process";
4139
- import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
3658
+ import { execFileSync as execFileSync6 } from "child_process";
3659
+ import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
4140
3660
  import { tmpdir as tmpdir2 } from "os";
4141
3661
  import { join as join6 } from "path";
4142
3662
  import { defineCommand as defineCommand26 } from "citty";
@@ -4152,7 +3672,8 @@ function escape(s) {
4152
3672
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4153
3673
  }
4154
3674
  function buildSyncPlist(input) {
4155
- const pathLine = ` <key>PATH</key><string>${escape(input.homeDir)}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
3675
+ const pathDirs = (input.hostBinDirs && input.hostBinDirs.length > 0 ? input.hostBinDirs : ["/opt/homebrew/bin", "/usr/local/bin"]).join(":");
3676
+ const pathLine = ` <key>PATH</key><string>${escape(pathDirs)}:/usr/bin:/bin</string>
4156
3677
  `;
4157
3678
  const agentUserLine = ` <key>AGENT_USER</key><string>${escape(input.userName)}</string>
4158
3679
  `;
@@ -4195,12 +3716,12 @@ ${envBlock} <key>StartInterval</key>
4195
3716
 
4196
3717
  // src/lib/keygen.ts
4197
3718
  import { Buffer as Buffer4 } from "buffer";
4198
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "fs";
3719
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
4199
3720
  import { generateKeyPairSync } from "crypto";
4200
- import { homedir as homedir7 } from "os";
4201
- import { dirname as dirname2, resolve as resolve3 } from "path";
3721
+ import { homedir as homedir6 } from "os";
3722
+ import { dirname, resolve as resolve2 } from "path";
4202
3723
  function resolveKeyPath(p2) {
4203
- return resolve3(p2.replace(/^~/, homedir7()));
3724
+ return resolve2(p2.replace(/^~/, homedir6()));
4204
3725
  }
4205
3726
  function buildSshEd25519Line(rawPub) {
4206
3727
  const keyTypeStr = "ssh-ed25519";
@@ -4214,9 +3735,9 @@ function buildSshEd25519Line(rawPub) {
4214
3735
  function readPublicKey(keyPath) {
4215
3736
  const pubPath = `${keyPath}.pub`;
4216
3737
  if (existsSync7(pubPath)) {
4217
- return readFileSync7(pubPath, "utf-8").trim();
3738
+ return readFileSync6(pubPath, "utf-8").trim();
4218
3739
  }
4219
- const keyContent = readFileSync7(keyPath, "utf-8");
3740
+ const keyContent = readFileSync6(keyPath, "utf-8");
4220
3741
  const privateKey = loadEd25519PrivateKey(keyContent);
4221
3742
  const jwk = privateKey.export({ format: "jwk" });
4222
3743
  const pubBytes = Buffer4.from(jwk.x, "base64url");
@@ -4224,17 +3745,17 @@ function readPublicKey(keyPath) {
4224
3745
  }
4225
3746
  function generateAndSaveKey(keyPath) {
4226
3747
  const resolved = resolveKeyPath(keyPath);
4227
- const dir = dirname2(resolved);
3748
+ const dir = dirname(resolved);
4228
3749
  if (!existsSync7(dir)) {
4229
- mkdirSync2(dir, { recursive: true });
3750
+ mkdirSync(dir, { recursive: true });
4230
3751
  }
4231
3752
  const { publicKey, privateKey } = generateKeyPairSync("ed25519");
4232
3753
  const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
4233
- writeFileSync3(resolved, privatePem, { mode: 384 });
3754
+ writeFileSync2(resolved, privatePem, { mode: 384 });
4234
3755
  const jwk = publicKey.export({ format: "jwk" });
4235
3756
  const pubBytes = Buffer4.from(jwk.x, "base64url");
4236
3757
  const pubKeyStr = buildSshEd25519Line(pubBytes);
4237
- writeFileSync3(`${resolved}.pub`, `${pubKeyStr}
3758
+ writeFileSync2(`${resolved}.pub`, `${pubKeyStr}
4238
3759
  `, { mode: 420 });
4239
3760
  return pubKeyStr;
4240
3761
  }
@@ -4250,14 +3771,15 @@ function generateKeyPairInMemory() {
4250
3771
  }
4251
3772
 
4252
3773
  // src/lib/llm-bridge.ts
4253
- import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
4254
- import { homedir as homedir8 } from "os";
4255
- import { join as join5 } from "path";
3774
+ import { execFileSync as execFileSync5 } from "child_process";
3775
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
3776
+ import { homedir as homedir7 } from "os";
3777
+ import { dirname as dirname2, join as join5 } from "path";
4256
3778
  var PLIST_LABEL_PREFIX = "eco.hofmann.apes.bridge";
4257
- function readLitellmEnv(envPath = join5(homedir8(), "litellm", ".env")) {
3779
+ function readLitellmEnv(envPath = join5(homedir7(), "litellm", ".env")) {
4258
3780
  if (!existsSync8(envPath)) return null;
4259
3781
  try {
4260
- const text = readFileSync8(envPath, "utf8");
3782
+ const text = readFileSync7(envPath, "utf8");
4261
3783
  const out = {};
4262
3784
  for (const line of text.split("\n")) {
4263
3785
  const trimmed = line.trim();
@@ -4287,6 +3809,25 @@ function resolveBridgeConfig(opts) {
4287
3809
  }
4288
3810
  return { baseUrl, apiKey, model };
4289
3811
  }
3812
+ function captureHostBinDirs() {
3813
+ const dirs = [];
3814
+ const seen = /* @__PURE__ */ new Set();
3815
+ for (const bin of ["node", "openape-chat-bridge", "apes"]) {
3816
+ let resolved;
3817
+ try {
3818
+ resolved = execFileSync5("/usr/bin/which", [bin], { encoding: "utf8" }).trim();
3819
+ } catch {
3820
+ const installCmd = bin === "openape-chat-bridge" ? "npm i -g @openape/chat-bridge" : bin === "apes" ? "npm i -g @openape/apes" : "install Node.js (e.g. brew install node)";
3821
+ throw new Error(`'${bin}' not found on host PATH. ${installCmd} before spawning agents \u2014 the bridge runtime resolves these at spawn time and bakes the dir into the agent's launchd plist.`);
3822
+ }
3823
+ const dir = dirname2(resolved);
3824
+ if (!seen.has(dir)) {
3825
+ seen.add(dir);
3826
+ dirs.push(dir);
3827
+ }
3828
+ }
3829
+ return dirs;
3830
+ }
4290
3831
  function bridgePlistLabel(agentName) {
4291
3832
  return `${PLIST_LABEL_PREFIX}.${agentName}`;
4292
3833
  }
@@ -4302,34 +3843,31 @@ LITELLM_BASE_URL=${cfg.baseUrl}
4302
3843
  LITELLM_API_KEY=${cfg.apiKey}
4303
3844
  ${modelLine}`;
4304
3845
  }
4305
- function buildBridgeStartScript() {
3846
+ function buildBridgeStartScript(hostBinDirs) {
3847
+ const pathLine = `export PATH="${hostBinDirs.join(":")}:/usr/bin:/bin"`;
4306
3848
  return `#!/usr/bin/env bash
4307
3849
  # Auto-generated by 'apes agents spawn --bridge'.
4308
- # Slim launcher \u2014 install stack lives in spawn, not here.
3850
+ # Slim launcher \u2014 bridge stack lives on the host, no per-agent install.
4309
3851
  set -euo pipefail
4310
3852
 
4311
- export PATH="$HOME/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
3853
+ ${pathLine}
4312
3854
 
4313
3855
  # Token refresh is in-process via @openape/cli-auth's challenge-response
4314
3856
  # path (auth.json.key_path -> ~/.ssh/id_ed25519). No "apes login" needed
4315
3857
  # at boot \u2014 keeping start.sh slim avoids the rate-limit dance the old
4316
3858
  # refresh hit when KeepAlive crash-restarted the daemon every 1h.
4317
3859
 
4318
- # M6 dropped the third-party LLM-runtime install + extension write
4319
- # that used to live here. The bridge now spawns
4320
- # \`apes agents serve --rpc\` directly (M8) which calls LiteLLM
4321
- # itself, so no third-party extension config is needed.
4322
-
4323
3860
  set -a
4324
3861
  . "$HOME/Library/Application Support/openape/bridge/.env"
4325
3862
  set +a
4326
3863
  exec openape-chat-bridge
4327
3864
  `;
4328
3865
  }
4329
- function buildBridgePlist(agentName, homeDir, ownerEmail) {
3866
+ function buildBridgePlist(agentName, homeDir, ownerEmail, hostBinDirs) {
4330
3867
  const startScript = `${homeDir}/Library/Application Support/openape/bridge/start.sh`;
4331
3868
  const stdoutLog = `${homeDir}/Library/Logs/openape-chat-bridge.log`;
4332
3869
  const stderrLog = `${homeDir}/Library/Logs/openape-chat-bridge.err.log`;
3870
+ const pathValue = `${hostBinDirs.join(":")}:/usr/bin:/bin`;
4333
3871
  return `<?xml version="1.0" encoding="UTF-8"?>
4334
3872
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4335
3873
  <plist version="1.0">
@@ -4360,7 +3898,7 @@ function buildBridgePlist(agentName, homeDir, ownerEmail) {
4360
3898
  <key>HOME</key>
4361
3899
  <string>${homeDir}</string>
4362
3900
  <key>PATH</key>
4363
- <string>${homeDir}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
3901
+ <string>${pathValue}</string>
4364
3902
  <key>OPENAPE_OWNER_EMAIL</key>
4365
3903
  <string>${ownerEmail}</string>
4366
3904
  </dict>
@@ -4498,20 +4036,22 @@ and try again.`
4498
4036
  cliBaseUrl: typeof args["bridge-base-url"] === "string" ? args["bridge-base-url"] : void 0,
4499
4037
  cliModel: typeof args["bridge-model"] === "string" ? args["bridge-model"] : void 0
4500
4038
  });
4039
+ const hostBinDirs = captureHostBinDirs();
4501
4040
  return {
4502
4041
  plistLabel: bridgePlistLabel(name),
4503
4042
  plistPath: bridgePlistPath(name),
4504
- plistContent: buildBridgePlist(name, homeDir, auth.email),
4505
- startScript: buildBridgeStartScript(),
4043
+ plistContent: buildBridgePlist(name, homeDir, auth.email, hostBinDirs),
4044
+ startScript: buildBridgeStartScript(hostBinDirs),
4506
4045
  envFile: buildBridgeEnvFile(cfg)
4507
4046
  };
4508
4047
  })() : null;
4509
4048
  const troopPlistLabel = `openape.troop.sync.${name}`;
4510
4049
  const troopPlistPath = `/Library/LaunchDaemons/${troopPlistLabel}.plist`;
4050
+ const troopBinDirs = bridge ? captureHostBinDirs() : captureHostBinDirs();
4511
4051
  const troop = {
4512
4052
  plistLabel: troopPlistLabel,
4513
4053
  plistPath: troopPlistPath,
4514
- plistContent: buildSyncPlist({ agentName: name, apesBin: apes, homeDir, userName: name })
4054
+ plistContent: buildSyncPlist({ agentName: name, apesBin: apes, homeDir, userName: name, hostBinDirs: troopBinDirs })
4515
4055
  };
4516
4056
  const script = buildSpawnSetupScript({
4517
4057
  name,
@@ -4526,10 +4066,10 @@ and try again.`
4526
4066
  bridge,
4527
4067
  troop
4528
4068
  });
4529
- writeFileSync4(scriptPath, script, { mode: 448 });
4069
+ writeFileSync3(scriptPath, script, { mode: 448 });
4530
4070
  consola23.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
4531
4071
  consola23.info("You will be asked to approve the as=root grant in your DDISA inbox; this command blocks until you do.");
4532
- execFileSync7(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], { stdio: "inherit" });
4072
+ execFileSync6(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], { stdio: "inherit" });
4533
4073
  consola23.success(`Agent ${name} spawned.`);
4534
4074
  consola23.info(`\u{1F517} Troop: https://troop.openape.ai/agents/${name}`);
4535
4075
  if (args.bridge) {
@@ -4568,18 +4108,18 @@ async function resolveClaudeToken(opts) {
4568
4108
  }
4569
4109
 
4570
4110
  // src/commands/agents/sync.ts
4571
- import { chownSync, existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync9, statSync, writeFileSync as writeFileSync5 } from "fs";
4572
- import { homedir as homedir9 } from "os";
4111
+ import { chownSync, existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as readFileSync8, statSync, writeFileSync as writeFileSync4 } from "fs";
4112
+ import { homedir as homedir8 } from "os";
4573
4113
  import { join as join7 } from "path";
4574
4114
  import { defineCommand as defineCommand27 } from "citty";
4575
4115
  import consola24 from "consola";
4576
4116
 
4577
4117
  // src/lib/macos-host.ts
4578
- import { execFileSync as execFileSync8 } from "child_process";
4118
+ import { execFileSync as execFileSync7 } from "child_process";
4579
4119
  import { hostname as hostname3 } from "os";
4580
4120
  function getHostId() {
4581
4121
  try {
4582
- const output = execFileSync8(
4122
+ const output = execFileSync7(
4583
4123
  "/usr/sbin/ioreg",
4584
4124
  ["-d2", "-c", "IOPlatformExpertDevice"],
4585
4125
  { encoding: "utf8", timeout: 2e3 }
@@ -4599,15 +4139,15 @@ function getHostname() {
4599
4139
  }
4600
4140
 
4601
4141
  // src/commands/agents/sync.ts
4602
- var AUTH_PATH3 = join7(homedir9(), ".config", "apes", "auth.json");
4603
- var TASK_CACHE_DIR2 = join7(homedir9(), ".openape", "agent", "tasks");
4142
+ var AUTH_PATH3 = join7(homedir8(), ".config", "apes", "auth.json");
4143
+ var TASK_CACHE_DIR2 = join7(homedir8(), ".openape", "agent", "tasks");
4604
4144
  function readAuthJson() {
4605
4145
  if (!existsSync9(AUTH_PATH3)) {
4606
4146
  throw new CliError(
4607
4147
  `No agent auth found at ${AUTH_PATH3}. Run \`apes agents spawn <name>\` to provision an agent first.`
4608
4148
  );
4609
4149
  }
4610
- const raw = readFileSync9(AUTH_PATH3, "utf8");
4150
+ const raw = readFileSync8(AUTH_PATH3, "utf8");
4611
4151
  let parsed;
4612
4152
  try {
4613
4153
  parsed = JSON.parse(raw);
@@ -4668,7 +4208,7 @@ var syncAgentCommand = defineCommand27({
4668
4208
  let agentGid = null;
4669
4209
  if (process.geteuid?.() === 0) {
4670
4210
  try {
4671
- const homeStat = statSync(homedir9());
4211
+ const homeStat = statSync(homedir8());
4672
4212
  agentUid = homeStat.uid;
4673
4213
  agentGid = homeStat.gid;
4674
4214
  } catch {
@@ -4682,23 +4222,23 @@ var syncAgentCommand = defineCommand27({
4682
4222
  }
4683
4223
  }
4684
4224
  }
4685
- const agentDir = join7(homedir9(), ".openape", "agent");
4686
- mkdirSync3(agentDir, { recursive: true });
4687
- chownToAgent(join7(homedir9(), ".openape"));
4225
+ const agentDir = join7(homedir8(), ".openape", "agent");
4226
+ mkdirSync2(agentDir, { recursive: true });
4227
+ chownToAgent(join7(homedir8(), ".openape"));
4688
4228
  chownToAgent(agentDir);
4689
4229
  const agentJsonPath = join7(agentDir, "agent.json");
4690
- writeFileSync5(
4230
+ writeFileSync4(
4691
4231
  agentJsonPath,
4692
4232
  `${JSON.stringify({ systemPrompt }, null, 2)}
4693
4233
  `,
4694
4234
  { mode: 384 }
4695
4235
  );
4696
4236
  chownToAgent(agentJsonPath);
4697
- mkdirSync3(TASK_CACHE_DIR2, { recursive: true });
4237
+ mkdirSync2(TASK_CACHE_DIR2, { recursive: true });
4698
4238
  chownToAgent(TASK_CACHE_DIR2);
4699
4239
  for (const task of tasks) {
4700
4240
  const path2 = join7(TASK_CACHE_DIR2, `${task.taskId}.json`);
4701
- writeFileSync5(path2, `${JSON.stringify(task, null, 2)}
4241
+ writeFileSync4(path2, `${JSON.stringify(task, null, 2)}
4702
4242
  `, { mode: 384 });
4703
4243
  chownToAgent(path2);
4704
4244
  }
@@ -4728,19 +4268,19 @@ var agentsCommand = defineCommand28({
4728
4268
  import { defineCommand as defineCommand37 } from "citty";
4729
4269
 
4730
4270
  // src/commands/nest/authorize.ts
4731
- import { execFileSync as execFileSync9 } from "child_process";
4732
- import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
4271
+ import { execFileSync as execFileSync8 } from "child_process";
4272
+ import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
4733
4273
  import { join as join9 } from "path";
4734
4274
  import { defineCommand as defineCommand30 } from "citty";
4735
4275
  import consola26 from "consola";
4736
4276
 
4737
4277
  // src/commands/nest/enroll.ts
4738
- import { hostname as hostname4, homedir as homedir10 } from "os";
4739
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, writeFileSync as writeFileSync6, chmodSync } from "fs";
4278
+ import { hostname as hostname4, homedir as homedir9 } from "os";
4279
+ import { existsSync as existsSync10, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5, chmodSync } from "fs";
4740
4280
  import { join as join8 } from "path";
4741
4281
  import { defineCommand as defineCommand29 } from "citty";
4742
4282
  import consola25 from "consola";
4743
- var NEST_DATA_DIR = join8(homedir10(), ".openape", "nest");
4283
+ var NEST_DATA_DIR = join8(homedir9(), ".openape", "nest");
4744
4284
  function nestAgentName() {
4745
4285
  const raw = hostname4().toLowerCase();
4746
4286
  const head = raw.split(".")[0] ?? raw;
@@ -4779,13 +4319,13 @@ var enrollNestCommand = defineCommand29({
4779
4319
  }
4780
4320
  const sshDir = join8(NEST_DATA_DIR, ".ssh");
4781
4321
  const configDir = join8(NEST_DATA_DIR, ".config", "apes");
4782
- mkdirSync4(sshDir, { recursive: true });
4783
- mkdirSync4(configDir, { recursive: true });
4322
+ mkdirSync3(sshDir, { recursive: true });
4323
+ mkdirSync3(configDir, { recursive: true });
4784
4324
  consola25.start(`Generating keypair for ${name}\u2026`);
4785
4325
  const { privatePem, publicSshLine } = generateKeyPairInMemory();
4786
- writeFileSync6(join8(sshDir, "id_ed25519"), `${privatePem.trimEnd()}
4326
+ writeFileSync5(join8(sshDir, "id_ed25519"), `${privatePem.trimEnd()}
4787
4327
  `, { mode: 384 });
4788
- writeFileSync6(join8(sshDir, "id_ed25519.pub"), `${publicSshLine}
4328
+ writeFileSync5(join8(sshDir, "id_ed25519.pub"), `${publicSshLine}
4789
4329
  `, { mode: 420 });
4790
4330
  chmodSync(sshDir, 448);
4791
4331
  consola25.start(`Registering nest at ${idp}\u2026`);
@@ -4805,7 +4345,7 @@ var enrollNestCommand = defineCommand29({
4805
4345
  keyPath: join8(sshDir, "id_ed25519"),
4806
4346
  ownerEmail: ownerAuth.email
4807
4347
  });
4808
- writeFileSync6(authPath, authJson, { mode: 384 });
4348
+ writeFileSync5(authPath, authJson, { mode: 384 });
4809
4349
  chmodSync(configDir, 448);
4810
4350
  consola25.success(`Nest enrolled \u2014 auth.json at ${authPath}`);
4811
4351
  consola25.info("");
@@ -4867,7 +4407,7 @@ var authorizeNestCommand = defineCommand30({
4867
4407
  if (!existsSync11(nestAuthPath)) {
4868
4408
  throw new CliError("Nest not enrolled. Run `apes nest enroll` first.");
4869
4409
  }
4870
- const nestAuth = JSON.parse(readFileSync10(nestAuthPath, "utf8"));
4410
+ const nestAuth = JSON.parse(readFileSync9(nestAuthPath, "utf8"));
4871
4411
  if (!nestAuth.email) throw new CliError(`${nestAuthPath} has no email`);
4872
4412
  const allow = args.allow ?? DEFAULT_ALLOW_PATTERNS.join(",");
4873
4413
  consola26.info(`Configuring YOLO-policy on ${nestAuth.email} via \`apes yolo set\`\u2026`);
@@ -4884,7 +4424,7 @@ var authorizeNestCommand = defineCommand30({
4884
4424
  cmdArgs.push("--expires-in", args["expires-in"]);
4885
4425
  }
4886
4426
  try {
4887
- execFileSync9("apes", cmdArgs, { stdio: "inherit" });
4427
+ execFileSync8("apes", cmdArgs, { stdio: "inherit" });
4888
4428
  } catch (err) {
4889
4429
  throw new CliError(err instanceof Error ? err.message : String(err));
4890
4430
  }
@@ -5029,9 +4569,9 @@ var destroyNestCommand = defineCommand31({
5029
4569
  });
5030
4570
 
5031
4571
  // src/commands/nest/install.ts
5032
- import { execFileSync as execFileSync10 } from "child_process";
5033
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
5034
- import { homedir as homedir11, userInfo as userInfo2 } from "os";
4572
+ 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";
5035
4575
  import { dirname as dirname3, join as join10 } from "path";
5036
4576
  import { defineCommand as defineCommand32 } from "citty";
5037
4577
  import consola29 from "consola";
@@ -5101,7 +4641,7 @@ resource_chain = ["agents:name={name}", "allowlist:email={peer_email}"]
5101
4641
  // src/commands/nest/install.ts
5102
4642
  var PLIST_LABEL = "ai.openape.nest";
5103
4643
  function plistPath() {
5104
- return join10(homedir11(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
4644
+ return join10(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
5105
4645
  }
5106
4646
  function escape2(s) {
5107
4647
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -5129,7 +4669,7 @@ function buildPlist(args) {
5129
4669
  <key>EnvironmentVariables</key>
5130
4670
  <dict>
5131
4671
  <key>HOME</key><string>${escape2(args.nestHome)}</string>
5132
- <key>PATH</key><string>${escape2(args.userHome)}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
4672
+ <key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
5133
4673
  <key>OPENAPE_NEST_PORT</key><string>${args.port}</string>
5134
4674
  <key>OPENAPE_APES_BIN</key><string>${escape2(args.apesBin)}</string>
5135
4675
  </dict>
@@ -5142,34 +4682,34 @@ function buildPlist(args) {
5142
4682
  `;
5143
4683
  }
5144
4684
  function installAdapter2() {
5145
- const target = join10(homedir11(), ".openape", "shapes", "adapters", "apes-agents.toml");
5146
- mkdirSync5(dirname3(target), { recursive: true });
4685
+ const target = join10(homedir10(), ".openape", "shapes", "adapters", "apes-agents.toml");
4686
+ mkdirSync4(dirname3(target), { recursive: true });
5147
4687
  let existing = "";
5148
4688
  try {
5149
- existing = readFileSync11(target, "utf8");
4689
+ existing = readFileSync10(target, "utf8");
5150
4690
  } catch {
5151
4691
  }
5152
4692
  if (existing === APES_AGENTS_ADAPTER_TOML) return false;
5153
- writeFileSync7(target, APES_AGENTS_ADAPTER_TOML, { mode: 420 });
4693
+ writeFileSync6(target, APES_AGENTS_ADAPTER_TOML, { mode: 420 });
5154
4694
  consola29.success(`Wrote shapes adapter ${target}`);
5155
4695
  return true;
5156
4696
  }
5157
4697
  function writeBridgeModelDefault(model) {
5158
- const envDir = join10(homedir11(), "litellm");
4698
+ const envDir = join10(homedir10(), "litellm");
5159
4699
  const envFile = join10(envDir, ".env");
5160
- mkdirSync5(envDir, { recursive: true });
4700
+ mkdirSync4(envDir, { recursive: true });
5161
4701
  let lines = [];
5162
4702
  if (existsSync12(envFile)) {
5163
- lines = readFileSync11(envFile, "utf8").split("\n").filter((l) => !l.startsWith("APE_CHAT_BRIDGE_MODEL="));
4703
+ lines = readFileSync10(envFile, "utf8").split("\n").filter((l) => !l.startsWith("APE_CHAT_BRIDGE_MODEL="));
5164
4704
  }
5165
4705
  lines.push(`APE_CHAT_BRIDGE_MODEL=${model}`);
5166
4706
  while (lines.length > 0 && lines.at(-1).trim() === "") lines.pop();
5167
- writeFileSync7(envFile, `${lines.join("\n")}
4707
+ writeFileSync6(envFile, `${lines.join("\n")}
5168
4708
  `, { mode: 384 });
5169
4709
  }
5170
4710
  function findBinary(name) {
5171
4711
  for (const dir of [
5172
- join10(homedir11(), ".bun", "bin"),
4712
+ join10(homedir10(), ".bun", "bin"),
5173
4713
  "/opt/homebrew/bin",
5174
4714
  "/usr/local/bin",
5175
4715
  "/usr/bin"
@@ -5195,7 +4735,7 @@ var installNestCommand = defineCommand32({
5195
4735
  }
5196
4736
  },
5197
4737
  async run({ args }) {
5198
- const homeDir = homedir11();
4738
+ const homeDir = homedir10();
5199
4739
  const port = Number(args.port ?? 9091);
5200
4740
  if (!Number.isInteger(port) || port < 1024 || port > 65535) {
5201
4741
  throw new Error(`invalid port ${port}`);
@@ -5211,26 +4751,26 @@ var installNestCommand = defineCommand32({
5211
4751
  consola29.success(`Default bridge model set to ${args["bridge-model"]} (in ~/litellm/.env)`);
5212
4752
  }
5213
4753
  installAdapter2();
5214
- mkdirSync5(join10(homeDir, "Library", "LaunchAgents"), { recursive: true });
5215
- mkdirSync5(NEST_DATA_DIR, { recursive: true });
4754
+ mkdirSync4(join10(homeDir, "Library", "LaunchAgents"), { recursive: true });
4755
+ mkdirSync4(NEST_DATA_DIR, { recursive: true });
5216
4756
  const desired = buildPlist({ nestBin, apesBin, userHome: homeDir, nestHome: NEST_DATA_DIR, port });
5217
4757
  let existing = "";
5218
4758
  try {
5219
- existing = readFileSync11(plistPath(), "utf8");
4759
+ existing = readFileSync10(plistPath(), "utf8");
5220
4760
  } catch {
5221
4761
  }
5222
4762
  if (existing !== desired) {
5223
- writeFileSync7(plistPath(), desired, { mode: 420 });
4763
+ writeFileSync6(plistPath(), desired, { mode: 420 });
5224
4764
  consola29.success("Wrote launchd plist");
5225
4765
  } else {
5226
4766
  consola29.info("plist already up to date");
5227
4767
  }
5228
4768
  const uid = userInfo2().uid;
5229
4769
  try {
5230
- execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
4770
+ execFileSync9("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
5231
4771
  } catch {
5232
4772
  }
5233
- execFileSync10("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
4773
+ execFileSync9("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
5234
4774
  consola29.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
5235
4775
  consola29.info("");
5236
4776
  consola29.info("Next steps for zero-prompt spawn \u2014 both one-time:");
@@ -5393,9 +4933,9 @@ var statusNestCommand = defineCommand35({
5393
4933
  });
5394
4934
 
5395
4935
  // src/commands/nest/uninstall.ts
5396
- import { execFileSync as execFileSync11 } from "child_process";
4936
+ import { execFileSync as execFileSync10 } from "child_process";
5397
4937
  import { existsSync as existsSync13, unlinkSync } from "fs";
5398
- import { homedir as homedir12, userInfo as userInfo3 } from "os";
4938
+ import { homedir as homedir11, userInfo as userInfo3 } from "os";
5399
4939
  import { join as join11 } from "path";
5400
4940
  import { defineCommand as defineCommand36 } from "citty";
5401
4941
  import consola33 from "consola";
@@ -5407,9 +4947,9 @@ var uninstallNestCommand = defineCommand36({
5407
4947
  },
5408
4948
  async run() {
5409
4949
  const uid = userInfo3().uid;
5410
- const path2 = join11(homedir12(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
4950
+ const path2 = join11(homedir11(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
5411
4951
  try {
5412
- execFileSync11("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
4952
+ execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
5413
4953
  consola33.success("Nest daemon stopped");
5414
4954
  } catch {
5415
4955
  consola33.info("Nest daemon was not loaded");
@@ -5964,7 +5504,7 @@ var adapterCommand = defineCommand42({
5964
5504
  });
5965
5505
 
5966
5506
  // src/commands/run.ts
5967
- import { execFileSync as execFileSync12 } from "child_process";
5507
+ import { execFileSync as execFileSync11 } from "child_process";
5968
5508
  import { hostname as hostname6 } from "os";
5969
5509
  import { basename } from "path";
5970
5510
  import { defineCommand as defineCommand43 } from "citty";
@@ -6242,7 +5782,7 @@ function execShellCommand(command) {
6242
5782
  throw new CliError("No command to execute");
6243
5783
  try {
6244
5784
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
6245
- execFileSync12(command[0], command.slice(1), {
5785
+ execFileSync11(command[0], command.slice(1), {
6246
5786
  stdio: "inherit",
6247
5787
  env: inheritedEnv
6248
5788
  });
@@ -6394,7 +5934,7 @@ async function runAudienceMode(audience, action, args) {
6394
5934
  consola38.info(`Executing: ${command.join(" ")}`);
6395
5935
  try {
6396
5936
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
6397
- execFileSync12(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
5937
+ execFileSync11(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
6398
5938
  stdio: "inherit",
6399
5939
  env: inheritedEnv
6400
5940
  });
@@ -6444,10 +5984,10 @@ note = "VPC-internal hostname suffix"
6444
5984
 
6445
5985
  // src/proxy/local-proxy.ts
6446
5986
  import { spawn } from "child_process";
6447
- import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
5987
+ import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
6448
5988
  import { createRequire } from "module";
6449
5989
  import { tmpdir as tmpdir3 } from "os";
6450
- import { dirname as dirname4, join as join12, resolve as resolve4 } from "path";
5990
+ import { dirname as dirname4, join as join12, resolve as resolve3 } from "path";
6451
5991
  var require2 = createRequire(import.meta.url);
6452
5992
  function findProxyBin() {
6453
5993
  const pkgPath = require2.resolve("@openape/proxy/package.json");
@@ -6456,12 +5996,12 @@ function findProxyBin() {
6456
5996
  if (!binRel) {
6457
5997
  throw new Error("@openape/proxy is missing the openape-proxy bin entry");
6458
5998
  }
6459
- return resolve4(dirname4(pkgPath), binRel);
5999
+ return resolve3(dirname4(pkgPath), binRel);
6460
6000
  }
6461
6001
  async function startEphemeralProxy(configToml) {
6462
6002
  const tmpDir = mkdtempSync3(join12(tmpdir3(), "openape-proxy-"));
6463
6003
  const configPath = join12(tmpDir, "config.toml");
6464
- writeFileSync8(configPath, configToml, { mode: 384 });
6004
+ writeFileSync7(configPath, configToml, { mode: 384 });
6465
6005
  const binPath = findProxyBin();
6466
6006
  const child = spawn(process.execPath, [binPath, "-c", configPath], {
6467
6007
  stdio: ["ignore", "pipe", "pipe"],
@@ -6896,15 +6436,15 @@ var mcpCommand = defineCommand49({
6896
6436
  if (transport !== "stdio" && transport !== "sse") {
6897
6437
  throw new Error('Transport must be "stdio" or "sse"');
6898
6438
  }
6899
- const { startMcpServer } = await import("./server-6WQYPDVO.js");
6439
+ const { startMcpServer } = await import("./server-F3ALNNYS.js");
6900
6440
  await startMcpServer(transport, port);
6901
6441
  }
6902
6442
  });
6903
6443
 
6904
6444
  // src/commands/init/index.ts
6905
- import { existsSync as existsSync14, copyFileSync, writeFileSync as writeFileSync9 } from "fs";
6445
+ import { existsSync as existsSync14, copyFileSync, writeFileSync as writeFileSync8 } from "fs";
6906
6446
  import { randomBytes } from "crypto";
6907
- import { execFileSync as execFileSync13 } from "child_process";
6447
+ import { execFileSync as execFileSync12 } from "child_process";
6908
6448
  import { join as join13 } from "path";
6909
6449
  import { defineCommand as defineCommand50 } from "citty";
6910
6450
  import consola42 from "consola";
@@ -6916,11 +6456,11 @@ async function downloadTemplate(repo, targetDir) {
6916
6456
  function installDeps(dir) {
6917
6457
  const hasLockFile = (name) => existsSync14(join13(dir, name));
6918
6458
  if (hasLockFile("pnpm-lock.yaml")) {
6919
- execFileSync13("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
6459
+ execFileSync12("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
6920
6460
  } else if (hasLockFile("bun.lockb")) {
6921
- execFileSync13("bun", ["install"], { cwd: dir, stdio: "inherit" });
6461
+ execFileSync12("bun", ["install"], { cwd: dir, stdio: "inherit" });
6922
6462
  } else {
6923
- execFileSync13("npm", ["install"], { cwd: dir, stdio: "inherit" });
6463
+ execFileSync12("npm", ["install"], { cwd: dir, stdio: "inherit" });
6924
6464
  }
6925
6465
  }
6926
6466
  async function promptChoice(message, choices) {
@@ -7036,7 +6576,7 @@ async function initIdP(targetDir) {
7036
6576
  `NUXT_OPENAPE_RP_ID=${domain}`,
7037
6577
  `NUXT_OPENAPE_RP_ORIGIN=${origin}`
7038
6578
  ].join("\n");
7039
- writeFileSync9(join13(dir, ".env"), `${envContent}
6579
+ writeFileSync8(join13(dir, ".env"), `${envContent}
7040
6580
  `, { mode: 384 });
7041
6581
  consola42.success(".env created");
7042
6582
  console.log("");
@@ -7057,7 +6597,7 @@ async function initIdP(targetDir) {
7057
6597
 
7058
6598
  // src/commands/enroll.ts
7059
6599
  import { Buffer as Buffer5 } from "buffer";
7060
- import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
6600
+ import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
7061
6601
  import { execFile as execFile2 } from "child_process";
7062
6602
  import { sign as sign2 } from "crypto";
7063
6603
  import { defineCommand as defineCommand51 } from "citty";
@@ -7073,7 +6613,7 @@ function openBrowser2(url) {
7073
6613
  }
7074
6614
  async function pollForEnrollment(idp, agentEmail, keyPath) {
7075
6615
  const resolvedKey = resolveKeyPath(keyPath);
7076
- const keyContent = readFileSync12(resolvedKey, "utf-8");
6616
+ const keyContent = readFileSync11(resolvedKey, "utf-8");
7077
6617
  const privateKey = loadEd25519PrivateKey(keyContent);
7078
6618
  const challengeUrl = await getAgentChallengeEndpoint(idp);
7079
6619
  const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
@@ -7100,7 +6640,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
7100
6640
  }
7101
6641
  } catch {
7102
6642
  }
7103
- await new Promise((resolve5) => setTimeout(resolve5, POLL_INTERVAL));
6643
+ await new Promise((resolve4) => setTimeout(resolve4, POLL_INTERVAL));
7104
6644
  }
7105
6645
  throw new Error("Enrollment timed out. Please check the browser and try again.");
7106
6646
  }
@@ -7185,7 +6725,7 @@ var enrollCommand = defineCommand51({
7185
6725
  });
7186
6726
 
7187
6727
  // src/commands/register-user.ts
7188
- import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
6728
+ import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
7189
6729
  import { defineCommand as defineCommand52 } from "citty";
7190
6730
  import consola44 from "consola";
7191
6731
  var registerUserCommand = defineCommand52({
@@ -7225,7 +6765,7 @@ var registerUserCommand = defineCommand52({
7225
6765
  }
7226
6766
  let publicKey = args.key;
7227
6767
  if (existsSync16(args.key)) {
7228
- publicKey = readFileSync13(args.key, "utf-8").trim();
6768
+ publicKey = readFileSync12(args.key, "utf-8").trim();
7229
6769
  }
7230
6770
  if (!publicKey.startsWith("ssh-ed25519 ")) {
7231
6771
  throw new CliError("Public key must be in ssh-ed25519 format.");
@@ -7534,7 +7074,7 @@ async function bestEffortGrantCount(idp) {
7534
7074
  }
7535
7075
  }
7536
7076
  async function runHealth(args) {
7537
- const version = true ? "1.9.0" : "0.0.0";
7077
+ const version = true ? "1.11.0" : "0.0.0";
7538
7078
  const auth = loadAuth();
7539
7079
  if (!auth) {
7540
7080
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -7727,26 +7267,26 @@ var workflowsCommand = defineCommand60({
7727
7267
  });
7728
7268
 
7729
7269
  // src/version-check.ts
7730
- import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "fs";
7731
- import { homedir as homedir13 } from "os";
7270
+ import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
7271
+ import { homedir as homedir12 } from "os";
7732
7272
  import { join as join14 } from "path";
7733
7273
  import consola50 from "consola";
7734
7274
  var PACKAGE_NAME = "@openape/apes";
7735
7275
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
7736
- var CACHE_FILE = join14(homedir13(), ".config", "apes", ".version-check.json");
7276
+ var CACHE_FILE = join14(homedir12(), ".config", "apes", ".version-check.json");
7737
7277
  function readCache() {
7738
7278
  if (!existsSync17(CACHE_FILE)) return null;
7739
7279
  try {
7740
- return JSON.parse(readFileSync14(CACHE_FILE, "utf-8"));
7280
+ return JSON.parse(readFileSync13(CACHE_FILE, "utf-8"));
7741
7281
  } catch {
7742
7282
  return null;
7743
7283
  }
7744
7284
  }
7745
7285
  function writeCache(entry) {
7746
7286
  try {
7747
- const dir = join14(homedir13(), ".config", "apes");
7748
- if (!existsSync17(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
7749
- writeFileSync10(CACHE_FILE, JSON.stringify(entry), { mode: 384 });
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 });
7750
7290
  } catch {
7751
7291
  }
7752
7292
  }
@@ -7807,10 +7347,10 @@ if (shellRewrite) {
7807
7347
  if (shellRewrite.action === "rewrite") {
7808
7348
  process.argv = shellRewrite.argv;
7809
7349
  } else if (shellRewrite.action === "version") {
7810
- console.log(`ape-shell ${"1.9.0"} (OpenApe DDISA shell wrapper)`);
7350
+ console.log(`ape-shell ${"1.11.0"} (OpenApe DDISA shell wrapper)`);
7811
7351
  process.exit(0);
7812
7352
  } else if (shellRewrite.action === "help") {
7813
- console.log(`ape-shell ${"1.9.0"} \u2014 OpenApe DDISA shell wrapper`);
7353
+ console.log(`ape-shell ${"1.11.0"} \u2014 OpenApe DDISA shell wrapper`);
7814
7354
  console.log("");
7815
7355
  console.log("Usage:");
7816
7356
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -7868,7 +7408,7 @@ var configCommand = defineCommand61({
7868
7408
  var main = defineCommand61({
7869
7409
  meta: {
7870
7410
  name: "apes",
7871
- version: "1.9.0",
7411
+ version: "1.11.0",
7872
7412
  description: "Unified CLI for OpenApe"
7873
7413
  },
7874
7414
  subCommands: {
@@ -7925,7 +7465,7 @@ async function maybeRefreshAuth() {
7925
7465
  }
7926
7466
  }
7927
7467
  await maybeRefreshAuth();
7928
- await maybeWarnStaleVersion("1.9.0").catch(() => {
7468
+ await maybeWarnStaleVersion("1.11.0").catch(() => {
7929
7469
  });
7930
7470
  runMain(main).catch((err) => {
7931
7471
  if (err instanceof CliExit) {