@openape/apes 1.2.0 → 1.3.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
@@ -379,7 +379,7 @@ async function loginWithPKCE(idp) {
379
379
  consola2.success(`Logged in as ${payload.email || payload.sub}`);
380
380
  }
381
381
  async function loginWithKey(idp, keyPath, agentEmail) {
382
- const { readFileSync: readFileSync14 } = await import("fs");
382
+ const { readFileSync: readFileSync13 } = await import("fs");
383
383
  const { sign: sign3 } = await import("crypto");
384
384
  const { loadEd25519PrivateKey: loadEd25519PrivateKey2 } = await import("./ssh-key-YBNNG5K5.js");
385
385
  const challengeUrl = await getAgentChallengeEndpoint(idp);
@@ -392,7 +392,7 @@ async function loginWithKey(idp, keyPath, agentEmail) {
392
392
  throw new CliError(`Challenge failed: ${await challengeResp.text()}`);
393
393
  }
394
394
  const { challenge } = await challengeResp.json();
395
- const keyContent = readFileSync14(keyPath, "utf-8");
395
+ const keyContent = readFileSync13(keyPath, "utf-8");
396
396
  const privateKey = loadEd25519PrivateKey2(keyContent);
397
397
  const signature = sign3(null, Buffer2.from(challenge), privateKey).toString("base64");
398
398
  const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
@@ -3343,16 +3343,18 @@ function escape(s) {
3343
3343
  }
3344
3344
  function buildSyncPlist(input) {
3345
3345
  const pathLine = ` <key>PATH</key><string>${escape(input.homeDir)}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
3346
+ `;
3347
+ const agentUserLine = ` <key>AGENT_USER</key><string>${escape(input.userName)}</string>
3346
3348
  `;
3347
3349
  const envBlock = input.troopUrl ? ` <key>EnvironmentVariables</key>
3348
3350
  <dict>
3349
3351
  <key>HOME</key><string>${escape(input.homeDir)}</string>
3350
- ${pathLine} <key>OPENAPE_TROOP_URL</key><string>${escape(input.troopUrl)}</string>
3352
+ ${pathLine}${agentUserLine} <key>OPENAPE_TROOP_URL</key><string>${escape(input.troopUrl)}</string>
3351
3353
  </dict>
3352
3354
  ` : ` <key>EnvironmentVariables</key>
3353
3355
  <dict>
3354
3356
  <key>HOME</key><string>${escape(input.homeDir)}</string>
3355
- ${pathLine} </dict>
3357
+ ${pathLine}${agentUserLine} </dict>
3356
3358
  `;
3357
3359
  return `<?xml version="1.0" encoding="UTF-8"?>
3358
3360
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -3360,8 +3362,6 @@ ${pathLine} </dict>
3360
3362
  <dict>
3361
3363
  <key>Label</key>
3362
3364
  <string>${escape(syncPlistLabel(input.agentName))}</string>
3363
- <key>UserName</key>
3364
- <string>${escape(input.userName)}</string>
3365
3365
  <key>ProgramArguments</key>
3366
3366
  <array>
3367
3367
  <string>${escape(input.apesBin)}</string>
@@ -3750,205 +3750,18 @@ async function resolveClaudeToken(opts) {
3750
3750
  }
3751
3751
 
3752
3752
  // src/commands/agents/sync.ts
3753
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
3754
- import { homedir as homedir10 } from "os";
3755
- import { join as join8 } from "path";
3753
+ import { chownSync, existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync9, statSync, writeFileSync as writeFileSync5 } from "fs";
3754
+ import { homedir as homedir9 } from "os";
3755
+ import { join as join7 } from "path";
3756
3756
  import { defineCommand as defineCommand27 } from "citty";
3757
3757
  import consola24 from "consola";
3758
3758
 
3759
- // src/lib/launchd-reconcile.ts
3760
- import { execFileSync as execFileSync8 } from "child_process";
3761
- import { mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync9, unlinkSync, writeFileSync as writeFileSync5 } from "fs";
3762
- import { homedir as homedir9, userInfo as userInfo2 } from "os";
3763
- import { join as join7 } from "path";
3764
- var PLIST_PREFIX = "openape.troop.";
3765
- function plistDir() {
3766
- return join7(homedir9(), "Library", "LaunchAgents");
3767
- }
3768
- function plistPath(agentName, taskId) {
3769
- return join7(plistDir(), `${PLIST_PREFIX}${agentName}.${taskId}.plist`);
3770
- }
3771
- function plistLabel(agentName, taskId) {
3772
- return `${PLIST_PREFIX}${agentName}.${taskId}`;
3773
- }
3774
- function fieldValues(token, range) {
3775
- const [min, max] = range;
3776
- if (token === "*") return null;
3777
- if (token.startsWith("*/")) {
3778
- const step = Number(token.slice(2));
3779
- if (!Number.isInteger(step) || step < 1) return [];
3780
- const values = [];
3781
- for (let i = min; i <= max; i++) {
3782
- if (i % step === 0) values.push(i);
3783
- }
3784
- return values;
3785
- }
3786
- const n = Number(token);
3787
- return Number.isInteger(n) ? [n] : [];
3788
- }
3789
- function cronToSchedule(expr) {
3790
- const parts = expr.trim().split(/\s+/);
3791
- if (parts.length !== 5) return [];
3792
- const [m, h, dom, mo, dow] = parts;
3793
- const minutes = fieldValues(m, [0, 59]);
3794
- const hours = fieldValues(h, [0, 23]);
3795
- const doms = fieldValues(dom, [1, 31]);
3796
- const months = fieldValues(mo, [1, 12]);
3797
- const dows = fieldValues(dow, [0, 7]);
3798
- const slots = [];
3799
- const minList = minutes ?? [null];
3800
- const hourList = hours ?? [null];
3801
- const domList = doms ?? [null];
3802
- const monthList = months ?? [null];
3803
- const dowList = dows ?? [null];
3804
- for (const M of minList) {
3805
- for (const H of hourList) {
3806
- for (const D of domList) {
3807
- for (const Mo of monthList) {
3808
- for (const W of dowList) {
3809
- const slot = {};
3810
- if (M !== null) slot.Minute = M;
3811
- if (H !== null) slot.Hour = H;
3812
- if (D !== null) slot.Day = D;
3813
- if (Mo !== null) slot.Month = Mo;
3814
- if (W !== null) slot.Weekday = W === 7 ? 0 : W;
3815
- slots.push(slot);
3816
- }
3817
- }
3818
- }
3819
- }
3820
- }
3821
- return slots;
3822
- }
3823
- function escape2(s) {
3824
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
3825
- }
3826
- function plistBody(input) {
3827
- const calendarBlocks = input.schedule.map((slot) => {
3828
- const lines = [];
3829
- if (slot.Minute !== void 0) lines.push(` <key>Minute</key><integer>${slot.Minute}</integer>`);
3830
- if (slot.Hour !== void 0) lines.push(` <key>Hour</key><integer>${slot.Hour}</integer>`);
3831
- if (slot.Day !== void 0) lines.push(` <key>Day</key><integer>${slot.Day}</integer>`);
3832
- if (slot.Month !== void 0) lines.push(` <key>Month</key><integer>${slot.Month}</integer>`);
3833
- if (slot.Weekday !== void 0) lines.push(` <key>Weekday</key><integer>${slot.Weekday}</integer>`);
3834
- return ` <dict>
3835
- ${lines.join("\n")}
3836
- </dict>`;
3837
- }).join("\n");
3838
- const calendarKey = input.schedule.length === 1 ? ` <key>StartCalendarInterval</key>
3839
- <dict>
3840
- ${calendarBlocks.replace(/^ {4}/gm, " ").replace(/^ {2}<dict>\n|\n {2}<\/dict>$/g, "")}
3841
- </dict>` : ` <key>StartCalendarInterval</key>
3842
- <array>
3843
- ${calendarBlocks}
3844
- </array>`;
3845
- return `<?xml version="1.0" encoding="UTF-8"?>
3846
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3847
- <plist version="1.0">
3848
- <dict>
3849
- <key>Label</key>
3850
- <string>${escape2(input.label)}</string>
3851
- <key>ProgramArguments</key>
3852
- <array>
3853
- <string>${escape2(input.apesBin)}</string>
3854
- <string>agents</string>
3855
- <string>run</string>
3856
- <string>${escape2(input.taskId)}</string>
3857
- </array>
3858
- <key>WorkingDirectory</key>
3859
- <string>${escape2(input.homeDir)}</string>
3860
- <key>EnvironmentVariables</key>
3861
- <dict>
3862
- <key>HOME</key>
3863
- <string>${escape2(input.homeDir)}</string>
3864
- </dict>
3865
- ${calendarKey}
3866
- <key>StandardOutPath</key>
3867
- <string>${escape2(input.homeDir)}/Library/Logs/openape-troop-${escape2(input.taskId)}.log</string>
3868
- <key>StandardErrorPath</key>
3869
- <string>${escape2(input.homeDir)}/Library/Logs/openape-troop-${escape2(input.taskId)}.log</string>
3870
- </dict>
3871
- </plist>
3872
- `;
3873
- }
3874
- function buildPlistContent(args) {
3875
- return plistBody({
3876
- label: plistLabel(args.agentName, args.task.taskId),
3877
- apesBin: args.apesBin,
3878
- taskId: args.task.taskId,
3879
- schedule: cronToSchedule(args.task.cron),
3880
- homeDir: args.homeDir
3881
- });
3882
- }
3883
- function uid() {
3884
- return userInfo2().uid;
3885
- }
3886
- function bootstrap(label, path2) {
3887
- try {
3888
- execFileSync8("/bin/launchctl", ["bootout", `gui/${uid()}/${label}`], { stdio: "ignore" });
3889
- } catch {
3890
- }
3891
- execFileSync8("/bin/launchctl", ["bootstrap", `gui/${uid()}`, path2], { stdio: "ignore" });
3892
- }
3893
- function bootout(label) {
3894
- try {
3895
- execFileSync8("/bin/launchctl", ["bootout", `gui/${uid()}/${label}`], { stdio: "ignore" });
3896
- } catch {
3897
- }
3898
- }
3899
- function reconcile(input) {
3900
- mkdirSync3(plistDir(), { recursive: true });
3901
- const present = readdirSync(plistDir()).filter((f) => f.startsWith(`${PLIST_PREFIX}${input.agentName}.`) && f.endsWith(".plist"));
3902
- const presentTaskIds = new Set(
3903
- present.map((f) => f.slice(`${PLIST_PREFIX}${input.agentName}.`.length, -".plist".length))
3904
- );
3905
- const desiredById = new Map(input.desired.map((t) => [t.taskId, t]));
3906
- const result = { added: [], updated: [], removed: [], unchanged: [] };
3907
- for (const taskId of presentTaskIds) {
3908
- if (!desiredById.has(taskId)) {
3909
- const path2 = plistPath(input.agentName, taskId);
3910
- bootout(plistLabel(input.agentName, taskId));
3911
- try {
3912
- unlinkSync(path2);
3913
- } catch {
3914
- }
3915
- result.removed.push(taskId);
3916
- }
3917
- }
3918
- for (const task of input.desired) {
3919
- const path2 = plistPath(input.agentName, task.taskId);
3920
- const desiredContent = buildPlistContent({
3921
- agentName: input.agentName,
3922
- apesBin: input.apesBin,
3923
- homeDir: input.homeDir,
3924
- task
3925
- });
3926
- let existingContent = "";
3927
- try {
3928
- existingContent = readFileSync9(path2, "utf8");
3929
- } catch {
3930
- }
3931
- if (existingContent === desiredContent) {
3932
- if (task.enabled) bootstrap(plistLabel(input.agentName, task.taskId), path2);
3933
- else bootout(plistLabel(input.agentName, task.taskId));
3934
- result.unchanged.push(task.taskId);
3935
- continue;
3936
- }
3937
- writeFileSync5(path2, desiredContent, { mode: 420 });
3938
- if (task.enabled) bootstrap(plistLabel(input.agentName, task.taskId), path2);
3939
- else bootout(plistLabel(input.agentName, task.taskId));
3940
- if (presentTaskIds.has(task.taskId)) result.updated.push(task.taskId);
3941
- else result.added.push(task.taskId);
3942
- }
3943
- return result;
3944
- }
3945
-
3946
3759
  // src/lib/macos-host.ts
3947
- import { execFileSync as execFileSync9 } from "child_process";
3760
+ import { execFileSync as execFileSync8 } from "child_process";
3948
3761
  import { hostname as hostname3 } from "os";
3949
3762
  function getHostId() {
3950
3763
  try {
3951
- const output = execFileSync9(
3764
+ const output = execFileSync8(
3952
3765
  "/usr/sbin/ioreg",
3953
3766
  ["-d2", "-c", "IOPlatformExpertDevice"],
3954
3767
  { encoding: "utf8", timeout: 2e3 }
@@ -3968,15 +3781,15 @@ function getHostname() {
3968
3781
  }
3969
3782
 
3970
3783
  // src/commands/agents/sync.ts
3971
- var AUTH_PATH3 = join8(homedir10(), ".config", "apes", "auth.json");
3972
- var TASK_CACHE_DIR2 = join8(homedir10(), ".openape", "agent", "tasks");
3784
+ var AUTH_PATH3 = join7(homedir9(), ".config", "apes", "auth.json");
3785
+ var TASK_CACHE_DIR2 = join7(homedir9(), ".openape", "agent", "tasks");
3973
3786
  function readAuthJson() {
3974
3787
  if (!existsSync9(AUTH_PATH3)) {
3975
3788
  throw new CliError(
3976
3789
  `No agent auth found at ${AUTH_PATH3}. Run \`apes agents spawn <name>\` to provision an agent first.`
3977
3790
  );
3978
3791
  }
3979
- const raw = readFileSync10(AUTH_PATH3, "utf8");
3792
+ const raw = readFileSync9(AUTH_PATH3, "utf8");
3980
3793
  let parsed;
3981
3794
  try {
3982
3795
  parsed = JSON.parse(raw);
@@ -4000,14 +3813,6 @@ function agentNameFromEmail(email) {
4000
3813
  }
4001
3814
  return before.slice(0, dashIdx);
4002
3815
  }
4003
- function findApesBin() {
4004
- const argv1 = process.argv[1];
4005
- if (argv1 && existsSync9(argv1)) return argv1;
4006
- for (const candidate of ["/opt/homebrew/bin/apes", "/usr/local/bin/apes"]) {
4007
- if (existsSync9(candidate)) return candidate;
4008
- }
4009
- throw new CliError("Could not locate the apes binary path for launchd. Set APES_BIN env var to point at it.");
4010
- }
4011
3816
  var syncAgentCommand = defineCommand27({
4012
3817
  meta: {
4013
3818
  name: "sync",
@@ -4041,31 +3846,44 @@ var syncAgentCommand = defineCommand27({
4041
3846
  consola24.info(sync.first_sync ? "\u2713 first sync \u2014 agent registered" : "\u2713 presence updated");
4042
3847
  const { system_prompt: systemPrompt, tasks } = await client.listTasks();
4043
3848
  consola24.info(`Pulled ${tasks.length} task${tasks.length === 1 ? "" : "s"}`);
4044
- const agentDir = join8(homedir10(), ".openape", "agent");
4045
- mkdirSync4(agentDir, { recursive: true });
4046
- writeFileSync6(
4047
- join8(agentDir, "agent.json"),
3849
+ let agentUid = null;
3850
+ let agentGid = null;
3851
+ if (process.geteuid?.() === 0) {
3852
+ try {
3853
+ const homeStat = statSync(homedir9());
3854
+ agentUid = homeStat.uid;
3855
+ agentGid = homeStat.gid;
3856
+ } catch {
3857
+ }
3858
+ }
3859
+ function chownToAgent(path2) {
3860
+ if (agentUid !== null && agentGid !== null) {
3861
+ try {
3862
+ chownSync(path2, agentUid, agentGid);
3863
+ } catch {
3864
+ }
3865
+ }
3866
+ }
3867
+ const agentDir = join7(homedir9(), ".openape", "agent");
3868
+ mkdirSync3(agentDir, { recursive: true });
3869
+ chownToAgent(join7(homedir9(), ".openape"));
3870
+ chownToAgent(agentDir);
3871
+ const agentJsonPath = join7(agentDir, "agent.json");
3872
+ writeFileSync5(
3873
+ agentJsonPath,
4048
3874
  `${JSON.stringify({ systemPrompt }, null, 2)}
4049
3875
  `,
4050
3876
  { mode: 384 }
4051
3877
  );
4052
- mkdirSync4(TASK_CACHE_DIR2, { recursive: true });
3878
+ chownToAgent(agentJsonPath);
3879
+ mkdirSync3(TASK_CACHE_DIR2, { recursive: true });
3880
+ chownToAgent(TASK_CACHE_DIR2);
4053
3881
  for (const task of tasks) {
4054
- const path2 = join8(TASK_CACHE_DIR2, `${task.taskId}.json`);
4055
- writeFileSync6(path2, `${JSON.stringify(task, null, 2)}
3882
+ const path2 = join7(TASK_CACHE_DIR2, `${task.taskId}.json`);
3883
+ writeFileSync5(path2, `${JSON.stringify(task, null, 2)}
4056
3884
  `, { mode: 384 });
3885
+ chownToAgent(path2);
4057
3886
  }
4058
- const apesBin = findApesBin();
4059
- const result = reconcile({
4060
- agentName,
4061
- apesBin,
4062
- homeDir: homedir10(),
4063
- desired: tasks
4064
- });
4065
- if (result.added.length) consola24.success(`launchd: added ${result.added.join(", ")}`);
4066
- if (result.updated.length) consola24.success(`launchd: updated ${result.updated.join(", ")}`);
4067
- if (result.removed.length) consola24.warn(`launchd: removed ${result.removed.join(", ")}`);
4068
- if (result.unchanged.length) consola24.info(`launchd: ${result.unchanged.length} unchanged`);
4069
3887
  consola24.success("Sync complete.");
4070
3888
  }
4071
3889
  });
@@ -4417,7 +4235,7 @@ var adapterCommand = defineCommand29({
4417
4235
  });
4418
4236
 
4419
4237
  // src/commands/run.ts
4420
- import { execFileSync as execFileSync10 } from "child_process";
4238
+ import { execFileSync as execFileSync9 } from "child_process";
4421
4239
  import { hostname as hostname4 } from "os";
4422
4240
  import { basename } from "path";
4423
4241
  import { defineCommand as defineCommand30 } from "citty";
@@ -4695,7 +4513,7 @@ function execShellCommand(command) {
4695
4513
  throw new CliError("No command to execute");
4696
4514
  try {
4697
4515
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
4698
- execFileSync10(command[0], command.slice(1), {
4516
+ execFileSync9(command[0], command.slice(1), {
4699
4517
  stdio: "inherit",
4700
4518
  env: inheritedEnv
4701
4519
  });
@@ -4847,7 +4665,7 @@ async function runAudienceMode(audience, action, args) {
4847
4665
  consola26.info(`Executing: ${command.join(" ")}`);
4848
4666
  try {
4849
4667
  const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
4850
- execFileSync10(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
4668
+ execFileSync9(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
4851
4669
  stdio: "inherit",
4852
4670
  env: inheritedEnv
4853
4671
  });
@@ -4897,10 +4715,10 @@ note = "VPC-internal hostname suffix"
4897
4715
 
4898
4716
  // src/proxy/local-proxy.ts
4899
4717
  import { spawn } from "child_process";
4900
- import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
4718
+ import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
4901
4719
  import { createRequire } from "module";
4902
4720
  import { tmpdir as tmpdir3 } from "os";
4903
- import { dirname as dirname3, join as join9, resolve as resolve4 } from "path";
4721
+ import { dirname as dirname3, join as join8, resolve as resolve4 } from "path";
4904
4722
  var require2 = createRequire(import.meta.url);
4905
4723
  function findProxyBin() {
4906
4724
  const pkgPath = require2.resolve("@openape/proxy/package.json");
@@ -4912,9 +4730,9 @@ function findProxyBin() {
4912
4730
  return resolve4(dirname3(pkgPath), binRel);
4913
4731
  }
4914
4732
  async function startEphemeralProxy(configToml) {
4915
- const tmpDir = mkdtempSync3(join9(tmpdir3(), "openape-proxy-"));
4916
- const configPath = join9(tmpDir, "config.toml");
4917
- writeFileSync7(configPath, configToml, { mode: 384 });
4733
+ const tmpDir = mkdtempSync3(join8(tmpdir3(), "openape-proxy-"));
4734
+ const configPath = join8(tmpDir, "config.toml");
4735
+ writeFileSync6(configPath, configToml, { mode: 384 });
4918
4736
  const binPath = findProxyBin();
4919
4737
  const child = spawn(process.execPath, [binPath, "-c", configPath], {
4920
4738
  stdio: ["ignore", "pipe", "pipe"],
@@ -5349,16 +5167,16 @@ var mcpCommand = defineCommand36({
5349
5167
  if (transport !== "stdio" && transport !== "sse") {
5350
5168
  throw new Error('Transport must be "stdio" or "sse"');
5351
5169
  }
5352
- const { startMcpServer } = await import("./server-6OLIVAHI.js");
5170
+ const { startMcpServer } = await import("./server-W5ZP3FWK.js");
5353
5171
  await startMcpServer(transport, port);
5354
5172
  }
5355
5173
  });
5356
5174
 
5357
5175
  // src/commands/init/index.ts
5358
- import { existsSync as existsSync10, copyFileSync, writeFileSync as writeFileSync8 } from "fs";
5176
+ import { existsSync as existsSync10, copyFileSync, writeFileSync as writeFileSync7 } from "fs";
5359
5177
  import { randomBytes } from "crypto";
5360
- import { execFileSync as execFileSync11 } from "child_process";
5361
- import { join as join10 } from "path";
5178
+ import { execFileSync as execFileSync10 } from "child_process";
5179
+ import { join as join9 } from "path";
5362
5180
  import { defineCommand as defineCommand37 } from "citty";
5363
5181
  import consola30 from "consola";
5364
5182
  var DEFAULT_IDP_URL = "https://id.openape.at";
@@ -5367,13 +5185,13 @@ async function downloadTemplate(repo, targetDir) {
5367
5185
  await gigetDownload(`gh:${repo}`, { dir: targetDir, force: false });
5368
5186
  }
5369
5187
  function installDeps(dir) {
5370
- const hasLockFile = (name) => existsSync10(join10(dir, name));
5188
+ const hasLockFile = (name) => existsSync10(join9(dir, name));
5371
5189
  if (hasLockFile("pnpm-lock.yaml")) {
5372
- execFileSync11("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
5190
+ execFileSync10("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
5373
5191
  } else if (hasLockFile("bun.lockb")) {
5374
- execFileSync11("bun", ["install"], { cwd: dir, stdio: "inherit" });
5192
+ execFileSync10("bun", ["install"], { cwd: dir, stdio: "inherit" });
5375
5193
  } else {
5376
- execFileSync11("npm", ["install"], { cwd: dir, stdio: "inherit" });
5194
+ execFileSync10("npm", ["install"], { cwd: dir, stdio: "inherit" });
5377
5195
  }
5378
5196
  }
5379
5197
  async function promptChoice(message, choices) {
@@ -5432,7 +5250,7 @@ var initCommand = defineCommand37({
5432
5250
  });
5433
5251
  async function initSP(targetDir) {
5434
5252
  const dir = targetDir || "my-app";
5435
- if (existsSync10(join10(dir, "package.json"))) {
5253
+ if (existsSync10(join9(dir, "package.json"))) {
5436
5254
  throw new CliError(`Directory "${dir}" already contains a project.`);
5437
5255
  }
5438
5256
  consola30.start("Scaffolding SP starter...");
@@ -5441,8 +5259,8 @@ async function initSP(targetDir) {
5441
5259
  consola30.start("Installing dependencies...");
5442
5260
  installDeps(dir);
5443
5261
  consola30.success("Dependencies installed");
5444
- const envExample = join10(dir, ".env.example");
5445
- const envFile = join10(dir, ".env");
5262
+ const envExample = join9(dir, ".env.example");
5263
+ const envFile = join9(dir, ".env");
5446
5264
  if (existsSync10(envExample) && !existsSync10(envFile)) {
5447
5265
  copyFileSync(envExample, envFile);
5448
5266
  consola30.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
@@ -5457,7 +5275,7 @@ async function initSP(targetDir) {
5457
5275
  }
5458
5276
  async function initIdP(targetDir) {
5459
5277
  const dir = targetDir || "my-idp";
5460
- if (existsSync10(join10(dir, "package.json"))) {
5278
+ if (existsSync10(join9(dir, "package.json"))) {
5461
5279
  throw new CliError(`Directory "${dir}" already contains a project.`);
5462
5280
  }
5463
5281
  const domain = await promptText("Domain for the IdP", "localhost");
@@ -5489,7 +5307,7 @@ async function initIdP(targetDir) {
5489
5307
  `NUXT_OPENAPE_RP_ID=${domain}`,
5490
5308
  `NUXT_OPENAPE_RP_ORIGIN=${origin}`
5491
5309
  ].join("\n");
5492
- writeFileSync8(join10(dir, ".env"), `${envContent}
5310
+ writeFileSync7(join9(dir, ".env"), `${envContent}
5493
5311
  `, { mode: 384 });
5494
5312
  consola30.success(".env created");
5495
5313
  console.log("");
@@ -5510,7 +5328,7 @@ async function initIdP(targetDir) {
5510
5328
 
5511
5329
  // src/commands/enroll.ts
5512
5330
  import { Buffer as Buffer5 } from "buffer";
5513
- import { existsSync as existsSync11, readFileSync as readFileSync11 } from "fs";
5331
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
5514
5332
  import { execFile as execFile2 } from "child_process";
5515
5333
  import { sign as sign2 } from "crypto";
5516
5334
  import { defineCommand as defineCommand38 } from "citty";
@@ -5526,7 +5344,7 @@ function openBrowser2(url) {
5526
5344
  }
5527
5345
  async function pollForEnrollment(idp, agentEmail, keyPath) {
5528
5346
  const resolvedKey = resolveKeyPath(keyPath);
5529
- const keyContent = readFileSync11(resolvedKey, "utf-8");
5347
+ const keyContent = readFileSync10(resolvedKey, "utf-8");
5530
5348
  const privateKey = loadEd25519PrivateKey(keyContent);
5531
5349
  const challengeUrl = await getAgentChallengeEndpoint(idp);
5532
5350
  const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
@@ -5638,7 +5456,7 @@ var enrollCommand = defineCommand38({
5638
5456
  });
5639
5457
 
5640
5458
  // src/commands/register-user.ts
5641
- import { existsSync as existsSync12, readFileSync as readFileSync12 } from "fs";
5459
+ import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
5642
5460
  import { defineCommand as defineCommand39 } from "citty";
5643
5461
  import consola32 from "consola";
5644
5462
  var registerUserCommand = defineCommand39({
@@ -5678,7 +5496,7 @@ var registerUserCommand = defineCommand39({
5678
5496
  }
5679
5497
  let publicKey = args.key;
5680
5498
  if (existsSync12(args.key)) {
5681
- publicKey = readFileSync12(args.key, "utf-8").trim();
5499
+ publicKey = readFileSync11(args.key, "utf-8").trim();
5682
5500
  }
5683
5501
  if (!publicKey.startsWith("ssh-ed25519 ")) {
5684
5502
  throw new CliError("Public key must be in ssh-ed25519 format.");
@@ -5987,7 +5805,7 @@ async function bestEffortGrantCount(idp) {
5987
5805
  }
5988
5806
  }
5989
5807
  async function runHealth(args) {
5990
- const version = true ? "1.2.0" : "0.0.0";
5808
+ const version = true ? "1.3.0" : "0.0.0";
5991
5809
  const auth = loadAuth();
5992
5810
  if (!auth) {
5993
5811
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -6180,26 +5998,26 @@ var workflowsCommand = defineCommand47({
6180
5998
  });
6181
5999
 
6182
6000
  // src/version-check.ts
6183
- import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
6184
- import { homedir as homedir11 } from "os";
6185
- import { join as join11 } from "path";
6001
+ import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "fs";
6002
+ import { homedir as homedir10 } from "os";
6003
+ import { join as join10 } from "path";
6186
6004
  import consola38 from "consola";
6187
6005
  var PACKAGE_NAME = "@openape/apes";
6188
6006
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
6189
- var CACHE_FILE = join11(homedir11(), ".config", "apes", ".version-check.json");
6007
+ var CACHE_FILE = join10(homedir10(), ".config", "apes", ".version-check.json");
6190
6008
  function readCache() {
6191
6009
  if (!existsSync13(CACHE_FILE)) return null;
6192
6010
  try {
6193
- return JSON.parse(readFileSync13(CACHE_FILE, "utf-8"));
6011
+ return JSON.parse(readFileSync12(CACHE_FILE, "utf-8"));
6194
6012
  } catch {
6195
6013
  return null;
6196
6014
  }
6197
6015
  }
6198
6016
  function writeCache(entry) {
6199
6017
  try {
6200
- const dir = join11(homedir11(), ".config", "apes");
6201
- if (!existsSync13(dir)) mkdirSync5(dir, { recursive: true, mode: 448 });
6202
- writeFileSync9(CACHE_FILE, JSON.stringify(entry), { mode: 384 });
6018
+ const dir = join10(homedir10(), ".config", "apes");
6019
+ if (!existsSync13(dir)) mkdirSync4(dir, { recursive: true, mode: 448 });
6020
+ writeFileSync8(CACHE_FILE, JSON.stringify(entry), { mode: 384 });
6203
6021
  } catch {
6204
6022
  }
6205
6023
  }
@@ -6260,10 +6078,10 @@ if (shellRewrite) {
6260
6078
  if (shellRewrite.action === "rewrite") {
6261
6079
  process.argv = shellRewrite.argv;
6262
6080
  } else if (shellRewrite.action === "version") {
6263
- console.log(`ape-shell ${"1.2.0"} (OpenApe DDISA shell wrapper)`);
6081
+ console.log(`ape-shell ${"1.3.0"} (OpenApe DDISA shell wrapper)`);
6264
6082
  process.exit(0);
6265
6083
  } else if (shellRewrite.action === "help") {
6266
- console.log(`ape-shell ${"1.2.0"} \u2014 OpenApe DDISA shell wrapper`);
6084
+ console.log(`ape-shell ${"1.3.0"} \u2014 OpenApe DDISA shell wrapper`);
6267
6085
  console.log("");
6268
6086
  console.log("Usage:");
6269
6087
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -6321,7 +6139,7 @@ var configCommand = defineCommand48({
6321
6139
  var main = defineCommand48({
6322
6140
  meta: {
6323
6141
  name: "apes",
6324
- version: "1.2.0",
6142
+ version: "1.3.0",
6325
6143
  description: "Unified CLI for OpenApe"
6326
6144
  },
6327
6145
  subCommands: {
@@ -6376,7 +6194,7 @@ async function maybeRefreshAuth() {
6376
6194
  }
6377
6195
  }
6378
6196
  await maybeRefreshAuth();
6379
- await maybeWarnStaleVersion("1.2.0").catch(() => {
6197
+ await maybeWarnStaleVersion("1.3.0").catch(() => {
6380
6198
  });
6381
6199
  runMain(main).catch((err) => {
6382
6200
  if (err instanceof CliExit) {