@openape/apes 1.28.3 → 1.28.5

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
@@ -2644,13 +2644,91 @@ var cleanupOrphansCommand = defineCommand23({
2644
2644
  });
2645
2645
 
2646
2646
  // src/commands/agents/code.ts
2647
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
2648
- import { homedir as homedir4 } from "os";
2649
- import { join as join2 } from "path";
2647
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
2648
+ import { homedir as homedir5 } from "os";
2649
+ import { join as join3 } from "path";
2650
2650
  import process2 from "process";
2651
2651
  import { defineCommand as defineCommand24 } from "citty";
2652
2652
  import { consola as consola21 } from "consola";
2653
2653
 
2654
+ // src/lib/agent-secrets-runtime.ts
2655
+ import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync3, watch } from "fs";
2656
+ import { homedir as homedir4 } from "os";
2657
+ import { join as join2 } from "path";
2658
+ import { openString } from "@openape/core";
2659
+ var CONFIG_DIR2 = join2(homedir4(), ".config", "openape");
2660
+ var SECRETS_DIR = join2(CONFIG_DIR2, "secrets.d");
2661
+ var X25519_KEY_PATH = join2(CONFIG_DIR2, "agent-x25519.key");
2662
+ var X25519_PUBKEY_PATH = `${X25519_KEY_PATH}.pub`;
2663
+ function envNameFromFile(file) {
2664
+ if (!file.endsWith(".blob")) return null;
2665
+ const env = file.slice(0, -".blob".length);
2666
+ return /^[A-Z][A-Z0-9_]*$/.test(env) ? env : null;
2667
+ }
2668
+ function readAgentEncryptionKey(keyPath = X25519_KEY_PATH) {
2669
+ if (!existsSync4(keyPath)) return null;
2670
+ const k = readFileSync3(keyPath, "utf8").trim();
2671
+ return k.length > 0 ? k : null;
2672
+ }
2673
+ function readAgentEncryptionPublicKey(pubPath = X25519_PUBKEY_PATH) {
2674
+ if (!existsSync4(pubPath)) return null;
2675
+ const k = readFileSync3(pubPath, "utf8").trim();
2676
+ return k.length > 0 ? k : null;
2677
+ }
2678
+ function materializeSecrets(opts = {}) {
2679
+ const dir = opts.dir ?? SECRETS_DIR;
2680
+ const env = opts.env ?? process.env;
2681
+ const log = opts.log ?? (() => {
2682
+ });
2683
+ const applied = [];
2684
+ const failed = [];
2685
+ const key = readAgentEncryptionKey(opts.keyPath);
2686
+ const files = key && existsSync4(dir) ? readdirSync(dir) : [];
2687
+ for (const file of files) {
2688
+ const name = envNameFromFile(file);
2689
+ if (!name) continue;
2690
+ try {
2691
+ const box = JSON.parse(readFileSync3(join2(dir, file), "utf8"));
2692
+ env[name] = openString(box, key);
2693
+ applied.push(name);
2694
+ } catch (e) {
2695
+ failed.push(file);
2696
+ log(`secrets: failed to open ${file}: ${e.message}`);
2697
+ }
2698
+ }
2699
+ const live = new Set(applied);
2700
+ for (const prev of opts.previouslyApplied ?? []) {
2701
+ if (!live.has(prev)) {
2702
+ delete env[prev];
2703
+ log(`secrets: revoked ${prev}`);
2704
+ }
2705
+ }
2706
+ return { applied, failed };
2707
+ }
2708
+ function startSecretsWatcher(opts = {}) {
2709
+ const dir = opts.dir ?? SECRETS_DIR;
2710
+ const log = opts.log ?? (() => {
2711
+ });
2712
+ let appliedNames = /* @__PURE__ */ new Set();
2713
+ const run = () => {
2714
+ const r = materializeSecrets({ ...opts, previouslyApplied: appliedNames });
2715
+ appliedNames = new Set(r.applied);
2716
+ };
2717
+ run();
2718
+ if (!existsSync4(dir)) return () => {
2719
+ };
2720
+ let timer = null;
2721
+ const watcher = watch(dir, () => {
2722
+ if (timer) clearTimeout(timer);
2723
+ timer = setTimeout(run, 150);
2724
+ });
2725
+ watcher.on("error", (err) => log(`secrets: watcher error: ${err.message}`));
2726
+ return () => {
2727
+ if (timer) clearTimeout(timer);
2728
+ watcher.close();
2729
+ };
2730
+ }
2731
+
2654
2732
  // src/lib/coding/issue-task.ts
2655
2733
  var DEFAULT_TEMPLATE = "{type}/issue-{number}-{slug}";
2656
2734
  var DEFAULT_TYPE = "fix";
@@ -3003,9 +3081,9 @@ var DEFAULT_PERSONA = [
3003
3081
  ].join(" ");
3004
3082
  function readLitellmConfig(model) {
3005
3083
  const env = {};
3006
- const envPath = join2(homedir4(), "litellm", ".env");
3007
- if (existsSync4(envPath)) {
3008
- for (const raw of readFileSync3(envPath, "utf8").split("\n")) {
3084
+ const envPath = join3(homedir5(), "litellm", ".env");
3085
+ if (existsSync5(envPath)) {
3086
+ for (const raw of readFileSync4(envPath, "utf8").split("\n")) {
3009
3087
  const line = raw.trim();
3010
3088
  const m = /^([A-Z_][A-Z0-9_]*)=(.*)$/.exec(line);
3011
3089
  if (m) env[m[1]] = m[2].trim().replace(/^["']|["']$/g, "");
@@ -3020,11 +3098,11 @@ function readLitellmConfig(model) {
3020
3098
  return { apiBase, apiKey, model: model || process2.env.APE_CHAT_BRIDGE_MODEL || "claude-haiku-4-5" };
3021
3099
  }
3022
3100
  function readPersona(file) {
3023
- if (file && existsSync4(file)) return readFileSync3(file, "utf8");
3024
- const agentJson = join2(homedir4(), ".openape", "agent", "agent.json");
3025
- if (existsSync4(agentJson)) {
3101
+ if (file && existsSync5(file)) return readFileSync4(file, "utf8");
3102
+ const agentJson = join3(homedir5(), ".openape", "agent", "agent.json");
3103
+ if (existsSync5(agentJson)) {
3026
3104
  try {
3027
- const p = JSON.parse(readFileSync3(agentJson, "utf8"));
3105
+ const p = JSON.parse(readFileSync4(agentJson, "utf8"));
3028
3106
  if (p.systemPrompt?.trim()) return p.systemPrompt;
3029
3107
  } catch {
3030
3108
  }
@@ -3056,6 +3134,11 @@ var codeAgentCommand = defineCommand24({
3056
3134
  async run({ args }) {
3057
3135
  const repo = args.repo;
3058
3136
  const forge = args.forge || detectForge(repo);
3137
+ try {
3138
+ const { applied } = materializeSecrets();
3139
+ if (applied.length > 0) consola21.info(`Capabilities available: ${applied.join(", ")}`);
3140
+ } catch {
3141
+ }
3059
3142
  const config = readLitellmConfig(args.model);
3060
3143
  const persona = readPersona(args["persona-file"]);
3061
3144
  const maxSteps = Number(args["max-steps"]) > 0 ? Number(args["max-steps"]) : 40;
@@ -3074,7 +3157,13 @@ var codeAgentCommand = defineCommand24({
3074
3157
  if (args["poll-label"]) {
3075
3158
  const slug = repo.replace(/^https:\/\/github\.com\//, "").replace(/\.git$/, "");
3076
3159
  const list = await runApeShell(`gh issue list --repo ${slug} --label '${args["poll-label"]}' --state open --json number --jq '.[].number'`);
3077
- refs.push(...list.stdout.split("\n").map((s) => s.trim()).filter(Boolean));
3160
+ if (list.exit_code !== 0) {
3161
+ throw new CliError2(`gh issue list failed (exit ${list.exit_code}): ${(list.stderr || list.stdout).slice(0, 300)}`);
3162
+ }
3163
+ if (list.stdout.trim() === "" && /gh auth login|GH_TOKEN/i.test(list.stderr)) {
3164
+ throw new CliError2("gh is not authenticated (no GH_TOKEN). The agent's GH_TOKEN capability is not materialized \u2014 bind it via the deploy/secrets flow.");
3165
+ }
3166
+ refs.push(...list.stdout.split("\n").map((s) => s.trim()).filter((s) => /^\d+$/.test(s)));
3078
3167
  if (refs.length === 0) {
3079
3168
  consola21.info("no open issues with that label");
3080
3169
  return;
@@ -3099,27 +3188,27 @@ ${result.reason}`);
3099
3188
  import { execFileSync as execFileSync6 } from "child_process";
3100
3189
  import { mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
3101
3190
  import { tmpdir, userInfo } from "os";
3102
- import { join as join4 } from "path";
3191
+ import { join as join5 } from "path";
3103
3192
  import { defineCommand as defineCommand25 } from "citty";
3104
3193
  import consola22 from "consola";
3105
3194
 
3106
3195
  // src/lib/nest-registry.ts
3107
- import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync4, writeFileSync } from "fs";
3108
- import { homedir as homedir5 } from "os";
3109
- import { join as join3 } from "path";
3196
+ import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync5, writeFileSync } from "fs";
3197
+ import { homedir as homedir6 } from "os";
3198
+ import { join as join4 } from "path";
3110
3199
  function resolveRegistryPath() {
3111
- if (existsSync5("/var/openape/nest/agents.json")) return "/var/openape/nest/agents.json";
3112
- if (existsSync5("/var/openape/nest")) return "/var/openape/nest/agents.json";
3113
- return join3(homedir5(), ".openape", "nest", "agents.json");
3200
+ if (existsSync6("/var/openape/nest/agents.json")) return "/var/openape/nest/agents.json";
3201
+ if (existsSync6("/var/openape/nest")) return "/var/openape/nest/agents.json";
3202
+ return join4(homedir6(), ".openape", "nest", "agents.json");
3114
3203
  }
3115
3204
  function emptyRegistry() {
3116
3205
  return { version: 1, agents: [] };
3117
3206
  }
3118
3207
  function readNestRegistry() {
3119
3208
  const path2 = resolveRegistryPath();
3120
- if (!existsSync5(path2)) return emptyRegistry();
3209
+ if (!existsSync6(path2)) return emptyRegistry();
3121
3210
  try {
3122
- const parsed = JSON.parse(readFileSync4(path2, "utf8"));
3211
+ const parsed = JSON.parse(readFileSync5(path2, "utf8"));
3123
3212
  if (parsed?.version !== 1 || !Array.isArray(parsed.agents)) return emptyRegistry();
3124
3213
  return parsed;
3125
3214
  } catch {
@@ -3348,8 +3437,8 @@ ${consequences.join("\n")}`);
3348
3437
  }
3349
3438
  }
3350
3439
  if (adminPassword) {
3351
- const scratch = mkdtempSync(join4(tmpdir(), `apes-destroy-${name}-`));
3352
- const scriptPath = join4(scratch, "teardown.sh");
3440
+ const scratch = mkdtempSync(join5(tmpdir(), `apes-destroy-${name}-`));
3441
+ const scriptPath = join5(scratch, "teardown.sh");
3353
3442
  try {
3354
3443
  const script = buildDestroyTeardownScript({ name, homeDir, adminUser });
3355
3444
  writeFileSync2(scriptPath, script, { mode: 448 });
@@ -3458,7 +3547,7 @@ var listAgentsCommand = defineCommand26({
3458
3547
  });
3459
3548
 
3460
3549
  // src/commands/agents/register.ts
3461
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
3550
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
3462
3551
  import { defineCommand as defineCommand27 } from "citty";
3463
3552
  import consola24 from "consola";
3464
3553
  var registerAgentCommand = defineCommand27({
@@ -3506,10 +3595,10 @@ var registerAgentCommand = defineCommand27({
3506
3595
  throw new CliError("Pass either --public-key or --public-key-file, not both.");
3507
3596
  }
3508
3597
  if (!publicKey && keyFile) {
3509
- if (!existsSync6(keyFile)) {
3598
+ if (!existsSync7(keyFile)) {
3510
3599
  throw new CliError(`Public-key file not found: ${keyFile}`);
3511
3600
  }
3512
- publicKey = readFileSync5(keyFile, "utf-8").trim();
3601
+ publicKey = readFileSync6(keyFile, "utf-8").trim();
3513
3602
  }
3514
3603
  if (!publicKey) {
3515
3604
  throw new CliError('Provide --public-key "<ssh-ed25519 line>" or --public-key-file <path>.');
@@ -3549,86 +3638,6 @@ import { homedir as homedir7 } from "os";
3549
3638
  import { join as join6 } from "path";
3550
3639
  import { defineCommand as defineCommand28 } from "citty";
3551
3640
  import consola25 from "consola";
3552
-
3553
- // src/lib/agent-secrets-runtime.ts
3554
- import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync6, watch } from "fs";
3555
- import { homedir as homedir6 } from "os";
3556
- import { join as join5 } from "path";
3557
- import { openString } from "@openape/core";
3558
- var CONFIG_DIR2 = join5(homedir6(), ".config", "openape");
3559
- var SECRETS_DIR = join5(CONFIG_DIR2, "secrets.d");
3560
- var X25519_KEY_PATH = join5(CONFIG_DIR2, "agent-x25519.key");
3561
- var X25519_PUBKEY_PATH = `${X25519_KEY_PATH}.pub`;
3562
- function envNameFromFile(file) {
3563
- if (!file.endsWith(".blob")) return null;
3564
- const env = file.slice(0, -".blob".length);
3565
- return /^[A-Z][A-Z0-9_]*$/.test(env) ? env : null;
3566
- }
3567
- function readAgentEncryptionKey(keyPath = X25519_KEY_PATH) {
3568
- if (!existsSync7(keyPath)) return null;
3569
- const k = readFileSync6(keyPath, "utf8").trim();
3570
- return k.length > 0 ? k : null;
3571
- }
3572
- function readAgentEncryptionPublicKey(pubPath = X25519_PUBKEY_PATH) {
3573
- if (!existsSync7(pubPath)) return null;
3574
- const k = readFileSync6(pubPath, "utf8").trim();
3575
- return k.length > 0 ? k : null;
3576
- }
3577
- function materializeSecrets(opts = {}) {
3578
- const dir = opts.dir ?? SECRETS_DIR;
3579
- const env = opts.env ?? process.env;
3580
- const log = opts.log ?? (() => {
3581
- });
3582
- const applied = [];
3583
- const failed = [];
3584
- const key = readAgentEncryptionKey(opts.keyPath);
3585
- const files = key && existsSync7(dir) ? readdirSync(dir) : [];
3586
- for (const file of files) {
3587
- const name = envNameFromFile(file);
3588
- if (!name) continue;
3589
- try {
3590
- const box = JSON.parse(readFileSync6(join5(dir, file), "utf8"));
3591
- env[name] = openString(box, key);
3592
- applied.push(name);
3593
- } catch (e) {
3594
- failed.push(file);
3595
- log(`secrets: failed to open ${file}: ${e.message}`);
3596
- }
3597
- }
3598
- const live = new Set(applied);
3599
- for (const prev of opts.previouslyApplied ?? []) {
3600
- if (!live.has(prev)) {
3601
- delete env[prev];
3602
- log(`secrets: revoked ${prev}`);
3603
- }
3604
- }
3605
- return { applied, failed };
3606
- }
3607
- function startSecretsWatcher(opts = {}) {
3608
- const dir = opts.dir ?? SECRETS_DIR;
3609
- const log = opts.log ?? (() => {
3610
- });
3611
- let appliedNames = /* @__PURE__ */ new Set();
3612
- const run = () => {
3613
- const r = materializeSecrets({ ...opts, previouslyApplied: appliedNames });
3614
- appliedNames = new Set(r.applied);
3615
- };
3616
- run();
3617
- if (!existsSync7(dir)) return () => {
3618
- };
3619
- let timer = null;
3620
- const watcher = watch(dir, () => {
3621
- if (timer) clearTimeout(timer);
3622
- timer = setTimeout(run, 150);
3623
- });
3624
- watcher.on("error", (err) => log(`secrets: watcher error: ${err.message}`));
3625
- return () => {
3626
- if (timer) clearTimeout(timer);
3627
- watcher.close();
3628
- };
3629
- }
3630
-
3631
- // src/commands/agents/run.ts
3632
3641
  var AUTH_PATH = join6(homedir7(), ".config", "apes", "auth.json");
3633
3642
  var TASK_CACHE_DIR = join6(homedir7(), ".openape", "agent", "tasks");
3634
3643
  function readAuth() {
@@ -5996,7 +6005,7 @@ async function runAdapterMode(command, rawArgs, args) {
5996
6005
  if (!idp)
5997
6006
  throw new Error("No IdP URL configured. Run `apes login` first or pass --idp.");
5998
6007
  if (args.as) {
5999
- await runAudienceMode("escapes", command.join(" "), args);
6008
+ await runAudienceMode("escapes", command.join(" "), args, command);
6000
6009
  return;
6001
6010
  }
6002
6011
  const adapterOpt = extractOption(rawArgs, "adapter");
@@ -6054,14 +6063,14 @@ async function runAdapterMode(command, rawArgs, args) {
6054
6063
  printPendingGrantInfo(grant, idp);
6055
6064
  throw new CliExit(getAsyncExitCode());
6056
6065
  }
6057
- async function runAudienceMode(audience, action, args) {
6066
+ async function runAudienceMode(audience, action, args, commandArgv) {
6058
6067
  const auth = loadAuth();
6059
6068
  if (!auth) {
6060
6069
  throw new CliError("Not logged in. Run `apes login` first.");
6061
6070
  }
6062
6071
  const idp = getIdpUrl(args.idp);
6063
6072
  const grantsUrl = await getGrantsEndpoint(idp);
6064
- const command = action.split(" ");
6073
+ const command = commandArgv ?? action.split(" ");
6065
6074
  const targetHost = args.host || hostname5();
6066
6075
  const runAs = resolveRunAsTarget(args.as ?? void 0);
6067
6076
  const reusableId = await findReusableAudienceGrant({
@@ -6729,7 +6738,7 @@ var mcpCommand = defineCommand52({
6729
6738
  if (transport !== "stdio" && transport !== "sse") {
6730
6739
  throw new Error('Transport must be "stdio" or "sse"');
6731
6740
  }
6732
- const { startMcpServer } = await import("./server-5N27B7F2.js");
6741
+ const { startMcpServer } = await import("./server-QQ6WQ244.js");
6733
6742
  await startMcpServer(transport, port);
6734
6743
  }
6735
6744
  });
@@ -7367,7 +7376,7 @@ async function bestEffortGrantCount(idp) {
7367
7376
  }
7368
7377
  }
7369
7378
  async function runHealth(args) {
7370
- const version = true ? "1.28.3" : "0.0.0";
7379
+ const version = true ? "1.28.5" : "0.0.0";
7371
7380
  const auth = loadAuth();
7372
7381
  if (!auth) {
7373
7382
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -7640,10 +7649,10 @@ if (shellRewrite) {
7640
7649
  if (shellRewrite.action === "rewrite") {
7641
7650
  process.argv = shellRewrite.argv;
7642
7651
  } else if (shellRewrite.action === "version") {
7643
- console.log(`ape-shell ${"1.28.3"} (OpenApe DDISA shell wrapper)`);
7652
+ console.log(`ape-shell ${"1.28.5"} (OpenApe DDISA shell wrapper)`);
7644
7653
  process.exit(0);
7645
7654
  } else if (shellRewrite.action === "help") {
7646
- console.log(`ape-shell ${"1.28.3"} \u2014 OpenApe DDISA shell wrapper`);
7655
+ console.log(`ape-shell ${"1.28.5"} \u2014 OpenApe DDISA shell wrapper`);
7647
7656
  console.log("");
7648
7657
  console.log("Usage:");
7649
7658
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -7701,7 +7710,7 @@ var configCommand = defineCommand64({
7701
7710
  var main = defineCommand64({
7702
7711
  meta: {
7703
7712
  name: "apes",
7704
- version: "1.28.3",
7713
+ version: "1.28.5",
7705
7714
  description: "Unified CLI for OpenApe"
7706
7715
  },
7707
7716
  subCommands: {
@@ -7759,7 +7768,7 @@ async function maybeRefreshAuth() {
7759
7768
  }
7760
7769
  }
7761
7770
  await maybeRefreshAuth();
7762
- await maybeWarnStaleVersion("1.28.3").catch(() => {
7771
+ await maybeWarnStaleVersion("1.28.5").catch(() => {
7763
7772
  });
7764
7773
  runMain(main).catch((err) => {
7765
7774
  if (err instanceof CliExit) {