@openape/apes 0.20.0 → 0.21.1
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
|
@@ -96,7 +96,7 @@ function rewriteApeShellArgs(argv, argv0) {
|
|
|
96
96
|
import { defineCommand as defineCommand44, runMain } from "citty";
|
|
97
97
|
|
|
98
98
|
// src/commands/auth/login.ts
|
|
99
|
-
import { Buffer } from "buffer";
|
|
99
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
100
100
|
import { execFile } from "child_process";
|
|
101
101
|
import { createServer } from "http";
|
|
102
102
|
import { homedir as homedir2 } from "os";
|
|
@@ -394,7 +394,7 @@ async function loginWithKey(idp, keyPath, agentEmail) {
|
|
|
394
394
|
const { challenge } = await challengeResp.json();
|
|
395
395
|
const keyContent = readFileSync7(keyPath, "utf-8");
|
|
396
396
|
const privateKey = loadEd25519PrivateKey2(keyContent);
|
|
397
|
-
const signature = sign3(null,
|
|
397
|
+
const signature = sign3(null, Buffer2.from(challenge), privateKey).toString("base64");
|
|
398
398
|
const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
|
|
399
399
|
const authResp = await fetch(authenticateUrl, {
|
|
400
400
|
method: "POST",
|
|
@@ -1754,7 +1754,7 @@ import { defineCommand as defineCommand20 } from "citty";
|
|
|
1754
1754
|
import consola18 from "consola";
|
|
1755
1755
|
|
|
1756
1756
|
// src/lib/agent-bootstrap.ts
|
|
1757
|
-
import { Buffer as
|
|
1757
|
+
import { Buffer as Buffer3 } from "buffer";
|
|
1758
1758
|
import { createPrivateKey, sign } from "crypto";
|
|
1759
1759
|
var AGENT_NAME_REGEX = /^[a-z][a-z0-9-]{0,23}$/;
|
|
1760
1760
|
var SSH_ED25519_PREFIX = "ssh-ed25519 ";
|
|
@@ -1779,7 +1779,7 @@ async function issueAgentToken(input) {
|
|
|
1779
1779
|
throw new Error(`Challenge failed (${challengeResp.status}): ${text}`);
|
|
1780
1780
|
}
|
|
1781
1781
|
const { challenge } = await challengeResp.json();
|
|
1782
|
-
const signature = sign(null,
|
|
1782
|
+
const signature = sign(null, Buffer3.from(challenge), privateKey).toString("base64");
|
|
1783
1783
|
const authenticateUrl = await getAgentAuthenticateEndpoint(input.idp);
|
|
1784
1784
|
const authResp = await fetch(authenticateUrl, {
|
|
1785
1785
|
method: "POST",
|
|
@@ -1811,6 +1811,25 @@ mkdir -p "$HOME_DIR/.claude/hooks"
|
|
|
1811
1811
|
cat > "$HOME_DIR/.claude/settings.json" ${shHeredoc(input.claudeSettingsJson)}
|
|
1812
1812
|
cat > "$HOME_DIR/.claude/hooks/bash-via-ape-shell.sh" ${shHeredoc(input.hookScriptSource)}
|
|
1813
1813
|
chmod 755 "$HOME_DIR/.claude/hooks/bash-via-ape-shell.sh"
|
|
1814
|
+
` : "";
|
|
1815
|
+
const claudeTokenBlock = input.claudeOauthToken ? `
|
|
1816
|
+
mkdir -p "$HOME_DIR/.config/openape"
|
|
1817
|
+
cat > "$HOME_DIR/.config/openape/claude-token.env" ${shHeredoc(`# Auto-generated by 'apes agents spawn'. chmod 600 \u2014 contains a long-lived
|
|
1818
|
+
# Claude Code OAuth token. Rotate by editing this file in place; the
|
|
1819
|
+
# .zshenv / .profile source-lines below will pick it up automatically.
|
|
1820
|
+
export CLAUDE_CODE_OAUTH_TOKEN=${shQuote(input.claudeOauthToken)}
|
|
1821
|
+
`)}
|
|
1822
|
+
SOURCE_LINE='[ -f "$HOME/.config/openape/claude-token.env" ] && . "$HOME/.config/openape/claude-token.env"'
|
|
1823
|
+
for f in "$HOME_DIR/.zshenv" "$HOME_DIR/.profile"; do
|
|
1824
|
+
touch "$f"
|
|
1825
|
+
if ! grep -qF 'config/openape/claude-token.env' "$f" 2>/dev/null; then
|
|
1826
|
+
{
|
|
1827
|
+
echo ''
|
|
1828
|
+
echo '# OpenApe: load Claude Code OAuth token (added by apes agents spawn)'
|
|
1829
|
+
echo "$SOURCE_LINE"
|
|
1830
|
+
} >> "$f"
|
|
1831
|
+
fi
|
|
1832
|
+
done
|
|
1814
1833
|
` : "";
|
|
1815
1834
|
return `#!/bin/bash
|
|
1816
1835
|
set -euo pipefail
|
|
@@ -1854,13 +1873,17 @@ mkdir -p "$HOME_DIR/.ssh" "$HOME_DIR/.config/apes"
|
|
|
1854
1873
|
cat > "$HOME_DIR/.ssh/id_ed25519" ${shHeredoc(privatePemForHeredoc.trimEnd())}
|
|
1855
1874
|
cat > "$HOME_DIR/.ssh/id_ed25519.pub" ${shHeredoc(`${input.publicKeySshLine}`)}
|
|
1856
1875
|
cat > "$HOME_DIR/.config/apes/auth.json" ${shHeredoc(input.authJson)}
|
|
1857
|
-
${claudeBlock}
|
|
1876
|
+
${claudeBlock}${claudeTokenBlock}
|
|
1858
1877
|
chown -R "$NAME:staff" "$HOME_DIR"
|
|
1859
1878
|
chmod 700 "$HOME_DIR/.ssh"
|
|
1860
1879
|
chmod 700 "$HOME_DIR/.config"
|
|
1861
1880
|
chmod 600 "$HOME_DIR/.ssh/id_ed25519"
|
|
1862
1881
|
chmod 644 "$HOME_DIR/.ssh/id_ed25519.pub"
|
|
1863
1882
|
chmod 600 "$HOME_DIR/.config/apes/auth.json"
|
|
1883
|
+
if [ -f "$HOME_DIR/.config/openape/claude-token.env" ]; then
|
|
1884
|
+
chmod 700 "$HOME_DIR/.config/openape"
|
|
1885
|
+
chmod 600 "$HOME_DIR/.config/openape/claude-token.env"
|
|
1886
|
+
fi
|
|
1864
1887
|
|
|
1865
1888
|
echo "OK $NAME uid=$NEXT_UID home=$HOME_DIR"
|
|
1866
1889
|
`;
|
|
@@ -2068,6 +2091,11 @@ var destroyAgentCommand = defineCommand20({
|
|
|
2068
2091
|
}
|
|
2069
2092
|
consola18.warn(`About to destroy "${name}":
|
|
2070
2093
|
${consequences.join("\n")}`);
|
|
2094
|
+
if (!process.stdin.isTTY) {
|
|
2095
|
+
throw new CliError(
|
|
2096
|
+
"No TTY available for the interactive confirmation. Re-run with --force to skip the prompt (this is the same flag CI uses)."
|
|
2097
|
+
);
|
|
2098
|
+
}
|
|
2071
2099
|
const confirmed = await consola18.prompt("Proceed?", { type: "confirm", initial: false });
|
|
2072
2100
|
if (typeof confirmed === "symbol" || !confirmed) {
|
|
2073
2101
|
throw new CliExit(0);
|
|
@@ -2268,7 +2296,7 @@ import { defineCommand as defineCommand23 } from "citty";
|
|
|
2268
2296
|
import consola21 from "consola";
|
|
2269
2297
|
|
|
2270
2298
|
// src/lib/keygen.ts
|
|
2271
|
-
import { Buffer as
|
|
2299
|
+
import { Buffer as Buffer4 } from "buffer";
|
|
2272
2300
|
import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
2273
2301
|
import { generateKeyPairSync } from "crypto";
|
|
2274
2302
|
import { homedir as homedir4 } from "os";
|
|
@@ -2278,11 +2306,11 @@ function resolveKeyPath(p) {
|
|
|
2278
2306
|
}
|
|
2279
2307
|
function buildSshEd25519Line(rawPub) {
|
|
2280
2308
|
const keyTypeStr = "ssh-ed25519";
|
|
2281
|
-
const keyTypeLen =
|
|
2309
|
+
const keyTypeLen = Buffer4.alloc(4);
|
|
2282
2310
|
keyTypeLen.writeUInt32BE(keyTypeStr.length);
|
|
2283
|
-
const pubKeyLen =
|
|
2311
|
+
const pubKeyLen = Buffer4.alloc(4);
|
|
2284
2312
|
pubKeyLen.writeUInt32BE(rawPub.length);
|
|
2285
|
-
const blob =
|
|
2313
|
+
const blob = Buffer4.concat([keyTypeLen, Buffer4.from(keyTypeStr), pubKeyLen, rawPub]);
|
|
2286
2314
|
return `ssh-ed25519 ${blob.toString("base64")}`;
|
|
2287
2315
|
}
|
|
2288
2316
|
function readPublicKey(keyPath) {
|
|
@@ -2293,7 +2321,7 @@ function readPublicKey(keyPath) {
|
|
|
2293
2321
|
const keyContent = readFileSync4(keyPath, "utf-8");
|
|
2294
2322
|
const privateKey = loadEd25519PrivateKey(keyContent);
|
|
2295
2323
|
const jwk = privateKey.export({ format: "jwk" });
|
|
2296
|
-
const pubBytes =
|
|
2324
|
+
const pubBytes = Buffer4.from(jwk.x, "base64url");
|
|
2297
2325
|
return buildSshEd25519Line(pubBytes);
|
|
2298
2326
|
}
|
|
2299
2327
|
function generateAndSaveKey(keyPath) {
|
|
@@ -2306,7 +2334,7 @@ function generateAndSaveKey(keyPath) {
|
|
|
2306
2334
|
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
2307
2335
|
writeFileSync2(resolved, privatePem, { mode: 384 });
|
|
2308
2336
|
const jwk = publicKey.export({ format: "jwk" });
|
|
2309
|
-
const pubBytes =
|
|
2337
|
+
const pubBytes = Buffer4.from(jwk.x, "base64url");
|
|
2310
2338
|
const pubKeyStr = buildSshEd25519Line(pubBytes);
|
|
2311
2339
|
writeFileSync2(`${resolved}.pub`, `${pubKeyStr}
|
|
2312
2340
|
`, { mode: 420 });
|
|
@@ -2316,7 +2344,7 @@ function generateKeyPairInMemory() {
|
|
|
2316
2344
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
2317
2345
|
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
2318
2346
|
const jwk = publicKey.export({ format: "jwk" });
|
|
2319
|
-
const pubBytes =
|
|
2347
|
+
const pubBytes = Buffer4.from(jwk.x, "base64url");
|
|
2320
2348
|
return {
|
|
2321
2349
|
privatePem,
|
|
2322
2350
|
publicSshLine: buildSshEd25519Line(pubBytes)
|
|
@@ -2342,6 +2370,14 @@ var spawnAgentCommand = defineCommand23({
|
|
|
2342
2370
|
"no-claude-hook": {
|
|
2343
2371
|
type: "boolean",
|
|
2344
2372
|
description: "Skip writing ~/.claude/settings.json + the Bash-rewrite hook"
|
|
2373
|
+
},
|
|
2374
|
+
"claude-token": {
|
|
2375
|
+
type: "string",
|
|
2376
|
+
description: "Claude Code OAuth token (sk-ant-oat01-\u2026) from `claude setup-token`. Visible to ps \u2014 prefer --claude-token-stdin in scripts."
|
|
2377
|
+
},
|
|
2378
|
+
"claude-token-stdin": {
|
|
2379
|
+
type: "boolean",
|
|
2380
|
+
description: "Read the Claude Code OAuth token from stdin (paranoid form of --claude-token)."
|
|
2345
2381
|
}
|
|
2346
2382
|
},
|
|
2347
2383
|
async run({ args }) {
|
|
@@ -2408,6 +2444,10 @@ and try again.`
|
|
|
2408
2444
|
expiresAt: Math.floor(Date.now() / 1e3) + expiresIn
|
|
2409
2445
|
});
|
|
2410
2446
|
const includeClaudeHook = !args["no-claude-hook"];
|
|
2447
|
+
const claudeOauthToken = await resolveClaudeToken({
|
|
2448
|
+
flag: typeof args["claude-token"] === "string" ? args["claude-token"] : void 0,
|
|
2449
|
+
fromStdin: !!args["claude-token-stdin"]
|
|
2450
|
+
});
|
|
2411
2451
|
const script = buildSpawnSetupScript({
|
|
2412
2452
|
name,
|
|
2413
2453
|
homeDir,
|
|
@@ -2416,7 +2456,8 @@ and try again.`
|
|
|
2416
2456
|
publicKeySshLine: publicSshLine,
|
|
2417
2457
|
authJson,
|
|
2418
2458
|
claudeSettingsJson: includeClaudeHook ? CLAUDE_SETTINGS_JSON : null,
|
|
2419
|
-
hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null
|
|
2459
|
+
hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null,
|
|
2460
|
+
claudeOauthToken
|
|
2420
2461
|
});
|
|
2421
2462
|
writeFileSync3(scriptPath, script, { mode: 448 });
|
|
2422
2463
|
consola21.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
|
|
@@ -2431,6 +2472,28 @@ and try again.`
|
|
|
2431
2472
|
}
|
|
2432
2473
|
}
|
|
2433
2474
|
});
|
|
2475
|
+
async function resolveClaudeToken(opts) {
|
|
2476
|
+
if (opts.flag && opts.fromStdin) {
|
|
2477
|
+
throw new CliError("Pass --claude-token OR --claude-token-stdin, not both.");
|
|
2478
|
+
}
|
|
2479
|
+
let raw = null;
|
|
2480
|
+
if (typeof opts.flag === "string") {
|
|
2481
|
+
raw = opts.flag.trim();
|
|
2482
|
+
} else if (opts.fromStdin) {
|
|
2483
|
+
const chunks = [];
|
|
2484
|
+
for await (const chunk of process.stdin) {
|
|
2485
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
2486
|
+
}
|
|
2487
|
+
raw = Buffer.concat(chunks).toString("utf-8").trim();
|
|
2488
|
+
}
|
|
2489
|
+
if (!raw) return null;
|
|
2490
|
+
if (!raw.startsWith("sk-ant-oat01-")) {
|
|
2491
|
+
throw new CliError(
|
|
2492
|
+
`Claude token doesn't look right (expected sk-ant-oat01-\u2026). Run \`claude setup-token\` and paste the resulting token.`
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
return raw;
|
|
2496
|
+
}
|
|
2434
2497
|
|
|
2435
2498
|
// src/commands/agents/index.ts
|
|
2436
2499
|
var agentsCommand = defineCommand24({
|
|
@@ -3698,7 +3761,7 @@ var mcpCommand = defineCommand32({
|
|
|
3698
3761
|
if (transport !== "stdio" && transport !== "sse") {
|
|
3699
3762
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
3700
3763
|
}
|
|
3701
|
-
const { startMcpServer } = await import("./server-
|
|
3764
|
+
const { startMcpServer } = await import("./server-3KAKSSMI.js");
|
|
3702
3765
|
await startMcpServer(transport, port);
|
|
3703
3766
|
}
|
|
3704
3767
|
});
|
|
@@ -3858,7 +3921,7 @@ async function initIdP(targetDir) {
|
|
|
3858
3921
|
}
|
|
3859
3922
|
|
|
3860
3923
|
// src/commands/enroll.ts
|
|
3861
|
-
import { Buffer as
|
|
3924
|
+
import { Buffer as Buffer5 } from "buffer";
|
|
3862
3925
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
3863
3926
|
import { execFile as execFile2 } from "child_process";
|
|
3864
3927
|
import { sign as sign2 } from "crypto";
|
|
@@ -3889,7 +3952,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
3889
3952
|
});
|
|
3890
3953
|
if (challengeResp.ok) {
|
|
3891
3954
|
const { challenge } = await challengeResp.json();
|
|
3892
|
-
const signature = sign2(null,
|
|
3955
|
+
const signature = sign2(null, Buffer5.from(challenge), privateKey).toString("base64");
|
|
3893
3956
|
const authResp = await fetch(authenticateUrl, {
|
|
3894
3957
|
method: "POST",
|
|
3895
3958
|
headers: { "Content-Type": "application/json" },
|
|
@@ -4336,7 +4399,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
4336
4399
|
}
|
|
4337
4400
|
}
|
|
4338
4401
|
async function runHealth(args) {
|
|
4339
|
-
const version = true ? "0.
|
|
4402
|
+
const version = true ? "0.21.1" : "0.0.0";
|
|
4340
4403
|
const auth = loadAuth();
|
|
4341
4404
|
if (!auth) {
|
|
4342
4405
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -4538,10 +4601,10 @@ if (shellRewrite) {
|
|
|
4538
4601
|
if (shellRewrite.action === "rewrite") {
|
|
4539
4602
|
process.argv = shellRewrite.argv;
|
|
4540
4603
|
} else if (shellRewrite.action === "version") {
|
|
4541
|
-
console.log(`ape-shell ${"0.
|
|
4604
|
+
console.log(`ape-shell ${"0.21.1"} (OpenApe DDISA shell wrapper)`);
|
|
4542
4605
|
process.exit(0);
|
|
4543
4606
|
} else if (shellRewrite.action === "help") {
|
|
4544
|
-
console.log(`ape-shell ${"0.
|
|
4607
|
+
console.log(`ape-shell ${"0.21.1"} \u2014 OpenApe DDISA shell wrapper`);
|
|
4545
4608
|
console.log("");
|
|
4546
4609
|
console.log("Usage:");
|
|
4547
4610
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -4599,7 +4662,7 @@ var configCommand = defineCommand44({
|
|
|
4599
4662
|
var main = defineCommand44({
|
|
4600
4663
|
meta: {
|
|
4601
4664
|
name: "apes",
|
|
4602
|
-
version: "0.
|
|
4665
|
+
version: "0.21.1",
|
|
4603
4666
|
description: "Unified CLI for OpenApe"
|
|
4604
4667
|
},
|
|
4605
4668
|
subCommands: {
|