@openape/apes 1.28.3 → 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
|
|
2648
|
-
import { homedir as
|
|
2649
|
-
import { join as
|
|
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 =
|
|
3007
|
-
if (
|
|
3008
|
-
for (const raw of
|
|
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 &&
|
|
3024
|
-
const agentJson =
|
|
3025
|
-
if (
|
|
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(
|
|
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
|
-
|
|
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
|
|
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
|
|
3108
|
-
import { homedir as
|
|
3109
|
-
import { join as
|
|
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 (
|
|
3112
|
-
if (
|
|
3113
|
-
return
|
|
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 (!
|
|
3209
|
+
if (!existsSync6(path2)) return emptyRegistry();
|
|
3121
3210
|
try {
|
|
3122
|
-
const parsed = JSON.parse(
|
|
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(
|
|
3352
|
-
const scriptPath =
|
|
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
|
|
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 (!
|
|
3598
|
+
if (!existsSync7(keyFile)) {
|
|
3510
3599
|
throw new CliError(`Public-key file not found: ${keyFile}`);
|
|
3511
3600
|
}
|
|
3512
|
-
publicKey =
|
|
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() {
|
|
@@ -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-
|
|
6741
|
+
const { startMcpServer } = await import("./server-3SP63EFF.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.
|
|
7379
|
+
const version = true ? "1.28.4" : "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.
|
|
7652
|
+
console.log(`ape-shell ${"1.28.4"} (OpenApe DDISA shell wrapper)`);
|
|
7644
7653
|
process.exit(0);
|
|
7645
7654
|
} else if (shellRewrite.action === "help") {
|
|
7646
|
-
console.log(`ape-shell ${"1.28.
|
|
7655
|
+
console.log(`ape-shell ${"1.28.4"} \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.
|
|
7713
|
+
version: "1.28.4",
|
|
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.
|
|
7771
|
+
await maybeWarnStaleVersion("1.28.4").catch(() => {
|
|
7763
7772
|
});
|
|
7764
7773
|
runMain(main).catch((err) => {
|
|
7765
7774
|
if (err instanceof CliExit) {
|