@openape/apes 0.20.0 → 0.21.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
|
@@ -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
|
`;
|
|
@@ -2268,7 +2291,7 @@ import { defineCommand as defineCommand23 } from "citty";
|
|
|
2268
2291
|
import consola21 from "consola";
|
|
2269
2292
|
|
|
2270
2293
|
// src/lib/keygen.ts
|
|
2271
|
-
import { Buffer as
|
|
2294
|
+
import { Buffer as Buffer4 } from "buffer";
|
|
2272
2295
|
import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
2273
2296
|
import { generateKeyPairSync } from "crypto";
|
|
2274
2297
|
import { homedir as homedir4 } from "os";
|
|
@@ -2278,11 +2301,11 @@ function resolveKeyPath(p) {
|
|
|
2278
2301
|
}
|
|
2279
2302
|
function buildSshEd25519Line(rawPub) {
|
|
2280
2303
|
const keyTypeStr = "ssh-ed25519";
|
|
2281
|
-
const keyTypeLen =
|
|
2304
|
+
const keyTypeLen = Buffer4.alloc(4);
|
|
2282
2305
|
keyTypeLen.writeUInt32BE(keyTypeStr.length);
|
|
2283
|
-
const pubKeyLen =
|
|
2306
|
+
const pubKeyLen = Buffer4.alloc(4);
|
|
2284
2307
|
pubKeyLen.writeUInt32BE(rawPub.length);
|
|
2285
|
-
const blob =
|
|
2308
|
+
const blob = Buffer4.concat([keyTypeLen, Buffer4.from(keyTypeStr), pubKeyLen, rawPub]);
|
|
2286
2309
|
return `ssh-ed25519 ${blob.toString("base64")}`;
|
|
2287
2310
|
}
|
|
2288
2311
|
function readPublicKey(keyPath) {
|
|
@@ -2293,7 +2316,7 @@ function readPublicKey(keyPath) {
|
|
|
2293
2316
|
const keyContent = readFileSync4(keyPath, "utf-8");
|
|
2294
2317
|
const privateKey = loadEd25519PrivateKey(keyContent);
|
|
2295
2318
|
const jwk = privateKey.export({ format: "jwk" });
|
|
2296
|
-
const pubBytes =
|
|
2319
|
+
const pubBytes = Buffer4.from(jwk.x, "base64url");
|
|
2297
2320
|
return buildSshEd25519Line(pubBytes);
|
|
2298
2321
|
}
|
|
2299
2322
|
function generateAndSaveKey(keyPath) {
|
|
@@ -2306,7 +2329,7 @@ function generateAndSaveKey(keyPath) {
|
|
|
2306
2329
|
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
2307
2330
|
writeFileSync2(resolved, privatePem, { mode: 384 });
|
|
2308
2331
|
const jwk = publicKey.export({ format: "jwk" });
|
|
2309
|
-
const pubBytes =
|
|
2332
|
+
const pubBytes = Buffer4.from(jwk.x, "base64url");
|
|
2310
2333
|
const pubKeyStr = buildSshEd25519Line(pubBytes);
|
|
2311
2334
|
writeFileSync2(`${resolved}.pub`, `${pubKeyStr}
|
|
2312
2335
|
`, { mode: 420 });
|
|
@@ -2316,7 +2339,7 @@ function generateKeyPairInMemory() {
|
|
|
2316
2339
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
2317
2340
|
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
2318
2341
|
const jwk = publicKey.export({ format: "jwk" });
|
|
2319
|
-
const pubBytes =
|
|
2342
|
+
const pubBytes = Buffer4.from(jwk.x, "base64url");
|
|
2320
2343
|
return {
|
|
2321
2344
|
privatePem,
|
|
2322
2345
|
publicSshLine: buildSshEd25519Line(pubBytes)
|
|
@@ -2342,6 +2365,14 @@ var spawnAgentCommand = defineCommand23({
|
|
|
2342
2365
|
"no-claude-hook": {
|
|
2343
2366
|
type: "boolean",
|
|
2344
2367
|
description: "Skip writing ~/.claude/settings.json + the Bash-rewrite hook"
|
|
2368
|
+
},
|
|
2369
|
+
"claude-token": {
|
|
2370
|
+
type: "string",
|
|
2371
|
+
description: "Claude Code OAuth token (sk-ant-oat01-\u2026) from `claude setup-token`. Visible to ps \u2014 prefer --claude-token-stdin in scripts."
|
|
2372
|
+
},
|
|
2373
|
+
"claude-token-stdin": {
|
|
2374
|
+
type: "boolean",
|
|
2375
|
+
description: "Read the Claude Code OAuth token from stdin (paranoid form of --claude-token)."
|
|
2345
2376
|
}
|
|
2346
2377
|
},
|
|
2347
2378
|
async run({ args }) {
|
|
@@ -2408,6 +2439,10 @@ and try again.`
|
|
|
2408
2439
|
expiresAt: Math.floor(Date.now() / 1e3) + expiresIn
|
|
2409
2440
|
});
|
|
2410
2441
|
const includeClaudeHook = !args["no-claude-hook"];
|
|
2442
|
+
const claudeOauthToken = await resolveClaudeToken({
|
|
2443
|
+
flag: typeof args["claude-token"] === "string" ? args["claude-token"] : void 0,
|
|
2444
|
+
fromStdin: !!args["claude-token-stdin"]
|
|
2445
|
+
});
|
|
2411
2446
|
const script = buildSpawnSetupScript({
|
|
2412
2447
|
name,
|
|
2413
2448
|
homeDir,
|
|
@@ -2416,7 +2451,8 @@ and try again.`
|
|
|
2416
2451
|
publicKeySshLine: publicSshLine,
|
|
2417
2452
|
authJson,
|
|
2418
2453
|
claudeSettingsJson: includeClaudeHook ? CLAUDE_SETTINGS_JSON : null,
|
|
2419
|
-
hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null
|
|
2454
|
+
hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null,
|
|
2455
|
+
claudeOauthToken
|
|
2420
2456
|
});
|
|
2421
2457
|
writeFileSync3(scriptPath, script, { mode: 448 });
|
|
2422
2458
|
consola21.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
|
|
@@ -2431,6 +2467,28 @@ and try again.`
|
|
|
2431
2467
|
}
|
|
2432
2468
|
}
|
|
2433
2469
|
});
|
|
2470
|
+
async function resolveClaudeToken(opts) {
|
|
2471
|
+
if (opts.flag && opts.fromStdin) {
|
|
2472
|
+
throw new CliError("Pass --claude-token OR --claude-token-stdin, not both.");
|
|
2473
|
+
}
|
|
2474
|
+
let raw = null;
|
|
2475
|
+
if (typeof opts.flag === "string") {
|
|
2476
|
+
raw = opts.flag.trim();
|
|
2477
|
+
} else if (opts.fromStdin) {
|
|
2478
|
+
const chunks = [];
|
|
2479
|
+
for await (const chunk of process.stdin) {
|
|
2480
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
2481
|
+
}
|
|
2482
|
+
raw = Buffer.concat(chunks).toString("utf-8").trim();
|
|
2483
|
+
}
|
|
2484
|
+
if (!raw) return null;
|
|
2485
|
+
if (!raw.startsWith("sk-ant-oat01-")) {
|
|
2486
|
+
throw new CliError(
|
|
2487
|
+
`Claude token doesn't look right (expected sk-ant-oat01-\u2026). Run \`claude setup-token\` and paste the resulting token.`
|
|
2488
|
+
);
|
|
2489
|
+
}
|
|
2490
|
+
return raw;
|
|
2491
|
+
}
|
|
2434
2492
|
|
|
2435
2493
|
// src/commands/agents/index.ts
|
|
2436
2494
|
var agentsCommand = defineCommand24({
|
|
@@ -3698,7 +3756,7 @@ var mcpCommand = defineCommand32({
|
|
|
3698
3756
|
if (transport !== "stdio" && transport !== "sse") {
|
|
3699
3757
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
3700
3758
|
}
|
|
3701
|
-
const { startMcpServer } = await import("./server-
|
|
3759
|
+
const { startMcpServer } = await import("./server-UWKEQDNM.js");
|
|
3702
3760
|
await startMcpServer(transport, port);
|
|
3703
3761
|
}
|
|
3704
3762
|
});
|
|
@@ -3858,7 +3916,7 @@ async function initIdP(targetDir) {
|
|
|
3858
3916
|
}
|
|
3859
3917
|
|
|
3860
3918
|
// src/commands/enroll.ts
|
|
3861
|
-
import { Buffer as
|
|
3919
|
+
import { Buffer as Buffer5 } from "buffer";
|
|
3862
3920
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
3863
3921
|
import { execFile as execFile2 } from "child_process";
|
|
3864
3922
|
import { sign as sign2 } from "crypto";
|
|
@@ -3889,7 +3947,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
3889
3947
|
});
|
|
3890
3948
|
if (challengeResp.ok) {
|
|
3891
3949
|
const { challenge } = await challengeResp.json();
|
|
3892
|
-
const signature = sign2(null,
|
|
3950
|
+
const signature = sign2(null, Buffer5.from(challenge), privateKey).toString("base64");
|
|
3893
3951
|
const authResp = await fetch(authenticateUrl, {
|
|
3894
3952
|
method: "POST",
|
|
3895
3953
|
headers: { "Content-Type": "application/json" },
|
|
@@ -4336,7 +4394,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
4336
4394
|
}
|
|
4337
4395
|
}
|
|
4338
4396
|
async function runHealth(args) {
|
|
4339
|
-
const version = true ? "0.
|
|
4397
|
+
const version = true ? "0.21.0" : "0.0.0";
|
|
4340
4398
|
const auth = loadAuth();
|
|
4341
4399
|
if (!auth) {
|
|
4342
4400
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -4538,10 +4596,10 @@ if (shellRewrite) {
|
|
|
4538
4596
|
if (shellRewrite.action === "rewrite") {
|
|
4539
4597
|
process.argv = shellRewrite.argv;
|
|
4540
4598
|
} else if (shellRewrite.action === "version") {
|
|
4541
|
-
console.log(`ape-shell ${"0.
|
|
4599
|
+
console.log(`ape-shell ${"0.21.0"} (OpenApe DDISA shell wrapper)`);
|
|
4542
4600
|
process.exit(0);
|
|
4543
4601
|
} else if (shellRewrite.action === "help") {
|
|
4544
|
-
console.log(`ape-shell ${"0.
|
|
4602
|
+
console.log(`ape-shell ${"0.21.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
4545
4603
|
console.log("");
|
|
4546
4604
|
console.log("Usage:");
|
|
4547
4605
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -4599,7 +4657,7 @@ var configCommand = defineCommand44({
|
|
|
4599
4657
|
var main = defineCommand44({
|
|
4600
4658
|
meta: {
|
|
4601
4659
|
name: "apes",
|
|
4602
|
-
version: "0.
|
|
4660
|
+
version: "0.21.0",
|
|
4603
4661
|
description: "Unified CLI for OpenApe"
|
|
4604
4662
|
},
|
|
4605
4663
|
subCommands: {
|