@openape/apes 1.28.2 → 1.28.4

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() {
@@ -5689,6 +5698,16 @@ function getUserMode() {
5689
5698
  return "human";
5690
5699
  return "agent";
5691
5700
  }
5701
+ var writeRealStdout = (s) => {
5702
+ process.stdout.write(s);
5703
+ };
5704
+ function routeDiagnosticsToStderrForWrappedAgentRun() {
5705
+ const original = process.stdout.write.bind(process.stdout);
5706
+ writeRealStdout = (s) => {
5707
+ original(s);
5708
+ };
5709
+ process.stdout.write = ((chunk, ...rest) => process.stderr.write(chunk, ...rest));
5710
+ }
5692
5711
  function getAsyncExitCode() {
5693
5712
  const envValue = process.env.APES_ASYNC_EXIT_CODE;
5694
5713
  if (envValue !== void 0 && envValue !== "") {
@@ -5797,6 +5816,9 @@ var runCommand = defineCommand46({
5797
5816
  },
5798
5817
  async run({ rawArgs, args }) {
5799
5818
  const wrappedCommand = extractWrappedCommand(rawArgs ?? []);
5819
+ if (wrappedCommand.length > 0 && getUserMode() === "agent") {
5820
+ routeDiagnosticsToStderrForWrappedAgentRun();
5821
+ }
5800
5822
  if (args.shell && wrappedCommand.length > 0) {
5801
5823
  await runShellMode(wrappedCommand, args);
5802
5824
  return;
@@ -6126,7 +6148,7 @@ function executeWithGrantToken(opts) {
6126
6148
  throw new CliExit(exitCode);
6127
6149
  }
6128
6150
  } else {
6129
- process.stdout.write(token);
6151
+ writeRealStdout(token);
6130
6152
  }
6131
6153
  }
6132
6154
  async function findReusableAudienceGrant(opts) {
@@ -6716,7 +6738,7 @@ var mcpCommand = defineCommand52({
6716
6738
  if (transport !== "stdio" && transport !== "sse") {
6717
6739
  throw new Error('Transport must be "stdio" or "sse"');
6718
6740
  }
6719
- const { startMcpServer } = await import("./server-WOOJEA67.js");
6741
+ const { startMcpServer } = await import("./server-3SP63EFF.js");
6720
6742
  await startMcpServer(transport, port);
6721
6743
  }
6722
6744
  });
@@ -7354,7 +7376,7 @@ async function bestEffortGrantCount(idp) {
7354
7376
  }
7355
7377
  }
7356
7378
  async function runHealth(args) {
7357
- const version = true ? "1.28.2" : "0.0.0";
7379
+ const version = true ? "1.28.4" : "0.0.0";
7358
7380
  const auth = loadAuth();
7359
7381
  if (!auth) {
7360
7382
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -7627,10 +7649,10 @@ if (shellRewrite) {
7627
7649
  if (shellRewrite.action === "rewrite") {
7628
7650
  process.argv = shellRewrite.argv;
7629
7651
  } else if (shellRewrite.action === "version") {
7630
- console.log(`ape-shell ${"1.28.2"} (OpenApe DDISA shell wrapper)`);
7652
+ console.log(`ape-shell ${"1.28.4"} (OpenApe DDISA shell wrapper)`);
7631
7653
  process.exit(0);
7632
7654
  } else if (shellRewrite.action === "help") {
7633
- console.log(`ape-shell ${"1.28.2"} \u2014 OpenApe DDISA shell wrapper`);
7655
+ console.log(`ape-shell ${"1.28.4"} \u2014 OpenApe DDISA shell wrapper`);
7634
7656
  console.log("");
7635
7657
  console.log("Usage:");
7636
7658
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -7688,7 +7710,7 @@ var configCommand = defineCommand64({
7688
7710
  var main = defineCommand64({
7689
7711
  meta: {
7690
7712
  name: "apes",
7691
- version: "1.28.2",
7713
+ version: "1.28.4",
7692
7714
  description: "Unified CLI for OpenApe"
7693
7715
  },
7694
7716
  subCommands: {
@@ -7746,7 +7768,7 @@ async function maybeRefreshAuth() {
7746
7768
  }
7747
7769
  }
7748
7770
  await maybeRefreshAuth();
7749
- await maybeWarnStaleVersion("1.28.2").catch(() => {
7771
+ await maybeWarnStaleVersion("1.28.4").catch(() => {
7750
7772
  });
7751
7773
  runMain(main).catch((err) => {
7752
7774
  if (err instanceof CliExit) {