@openape/apes 0.22.1 → 0.23.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
|
@@ -379,7 +379,7 @@ async function loginWithPKCE(idp) {
|
|
|
379
379
|
consola2.success(`Logged in as ${payload.email || payload.sub}`);
|
|
380
380
|
}
|
|
381
381
|
async function loginWithKey(idp, keyPath, agentEmail) {
|
|
382
|
-
const { readFileSync:
|
|
382
|
+
const { readFileSync: readFileSync9 } = await import("fs");
|
|
383
383
|
const { sign: sign3 } = await import("crypto");
|
|
384
384
|
const { loadEd25519PrivateKey: loadEd25519PrivateKey2 } = await import("./ssh-key-YBNNG5K5.js");
|
|
385
385
|
const challengeUrl = await getAgentChallengeEndpoint(idp);
|
|
@@ -392,7 +392,7 @@ async function loginWithKey(idp, keyPath, agentEmail) {
|
|
|
392
392
|
throw new CliError(`Challenge failed: ${await challengeResp.text()}`);
|
|
393
393
|
}
|
|
394
394
|
const { challenge } = await challengeResp.json();
|
|
395
|
-
const keyContent =
|
|
395
|
+
const keyContent = readFileSync9(keyPath, "utf-8");
|
|
396
396
|
const privateKey = loadEd25519PrivateKey2(keyContent);
|
|
397
397
|
const signature = sign3(null, Buffer2.from(challenge), privateKey).toString("base64");
|
|
398
398
|
const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
|
|
@@ -1873,7 +1873,7 @@ mkdir -p "$HOME_DIR/.ssh" "$HOME_DIR/.config/apes"
|
|
|
1873
1873
|
cat > "$HOME_DIR/.ssh/id_ed25519" ${shHeredoc(privatePemForHeredoc.trimEnd())}
|
|
1874
1874
|
cat > "$HOME_DIR/.ssh/id_ed25519.pub" ${shHeredoc(`${input.publicKeySshLine}`)}
|
|
1875
1875
|
cat > "$HOME_DIR/.config/apes/auth.json" ${shHeredoc(input.authJson)}
|
|
1876
|
-
${claudeBlock}${claudeTokenBlock}
|
|
1876
|
+
${claudeBlock}${claudeTokenBlock}${buildBridgeBlock(input.bridge)}
|
|
1877
1877
|
chown -R "$NAME:staff" "$HOME_DIR"
|
|
1878
1878
|
chmod 700 "$HOME_DIR/.ssh"
|
|
1879
1879
|
chmod 700 "$HOME_DIR/.config"
|
|
@@ -1886,6 +1886,28 @@ if [ -f "$HOME_DIR/.config/openape/claude-token.env" ]; then
|
|
|
1886
1886
|
fi
|
|
1887
1887
|
|
|
1888
1888
|
echo "OK $NAME uid=$NEXT_UID home=$HOME_DIR"
|
|
1889
|
+
${buildBridgeBootstrapBlock(input.bridge)}`;
|
|
1890
|
+
}
|
|
1891
|
+
function buildBridgeBlock(bridge) {
|
|
1892
|
+
if (!bridge) return "";
|
|
1893
|
+
return `
|
|
1894
|
+
mkdir -p "$HOME_DIR/Library/LaunchAgents" "$HOME_DIR/Library/Application Support/openape/bridge" "$HOME_DIR/Library/Logs" "$HOME_DIR/.pi/agent"
|
|
1895
|
+
cat > "$HOME_DIR/.pi/agent/.env" ${shHeredoc(bridge.envFile)}
|
|
1896
|
+
cat > "$HOME_DIR/Library/Application Support/openape/bridge/start.sh" ${shHeredoc(bridge.startScript)}
|
|
1897
|
+
chmod 755 "$HOME_DIR/Library/Application Support/openape/bridge/start.sh"
|
|
1898
|
+
cat > "$HOME_DIR/Library/LaunchAgents/${bridge.plistLabel}.plist" ${shHeredoc(bridge.plistContent)}
|
|
1899
|
+
chmod 600 "$HOME_DIR/.pi/agent/.env"
|
|
1900
|
+
`;
|
|
1901
|
+
}
|
|
1902
|
+
function buildBridgeBootstrapBlock(bridge) {
|
|
1903
|
+
if (!bridge) return "";
|
|
1904
|
+
return `
|
|
1905
|
+
# Load the bridge launchd job into the agent's gui domain. Runs as root
|
|
1906
|
+
# from the spawn setup script so we target gui/<agent-uid> explicitly.
|
|
1907
|
+
# Failure here is non-fatal \u2014 the plist still lands and launchd will pick
|
|
1908
|
+
# it up next time the agent logs in.
|
|
1909
|
+
launchctl bootstrap "gui/$NEXT_UID" "$HOME_DIR/Library/LaunchAgents/${bridge.plistLabel}.plist" || \\
|
|
1910
|
+
echo "warn: bridge bootstrap failed for gui/$NEXT_UID; loads on next login"
|
|
1889
1911
|
`;
|
|
1890
1912
|
}
|
|
1891
1913
|
function buildDestroyTeardownScript(input) {
|
|
@@ -2329,7 +2351,7 @@ var registerAgentCommand = defineCommand22({
|
|
|
2329
2351
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
2330
2352
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
2331
2353
|
import { tmpdir as tmpdir2 } from "os";
|
|
2332
|
-
import { join as
|
|
2354
|
+
import { join as join4 } from "path";
|
|
2333
2355
|
import { defineCommand as defineCommand23 } from "citty";
|
|
2334
2356
|
import consola21 from "consola";
|
|
2335
2357
|
|
|
@@ -2389,6 +2411,103 @@ function generateKeyPairInMemory() {
|
|
|
2389
2411
|
};
|
|
2390
2412
|
}
|
|
2391
2413
|
|
|
2414
|
+
// src/lib/llm-bridge.ts
|
|
2415
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
2416
|
+
import { homedir as homedir5 } from "os";
|
|
2417
|
+
import { join as join3 } from "path";
|
|
2418
|
+
var BRIDGE_PLIST_LABEL = "eco.hofmann.apes.bridge";
|
|
2419
|
+
function readLitellmEnv(envPath = join3(homedir5(), "litellm", ".env")) {
|
|
2420
|
+
if (!existsSync6(envPath)) return null;
|
|
2421
|
+
try {
|
|
2422
|
+
const text = readFileSync5(envPath, "utf8");
|
|
2423
|
+
const out = {};
|
|
2424
|
+
for (const line of text.split("\n")) {
|
|
2425
|
+
const trimmed = line.trim();
|
|
2426
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
2427
|
+
const eq = trimmed.indexOf("=");
|
|
2428
|
+
if (eq < 0) continue;
|
|
2429
|
+
const key = trimmed.slice(0, eq).trim();
|
|
2430
|
+
const value = trimmed.slice(eq + 1).trim();
|
|
2431
|
+
if (key === "LITELLM_MASTER_KEY" || key === "LITELLM_API_KEY") out.apiKey = value;
|
|
2432
|
+
if (key === "LITELLM_BASE_URL") out.baseUrl = value;
|
|
2433
|
+
}
|
|
2434
|
+
return out;
|
|
2435
|
+
} catch {
|
|
2436
|
+
return null;
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
function resolveBridgeConfig(opts) {
|
|
2440
|
+
const env = readLitellmEnv(opts.envPath);
|
|
2441
|
+
const apiKey = opts.cliKey ?? env?.apiKey;
|
|
2442
|
+
const baseUrl = opts.cliBaseUrl ?? env?.baseUrl ?? "http://127.0.0.1:4000/v1";
|
|
2443
|
+
if (!apiKey) {
|
|
2444
|
+
throw new Error(
|
|
2445
|
+
"No LITELLM_API_KEY resolved. Pass --bridge-key sk-\u2026 or write LITELLM_MASTER_KEY into ~/litellm/.env first."
|
|
2446
|
+
);
|
|
2447
|
+
}
|
|
2448
|
+
return { baseUrl, apiKey };
|
|
2449
|
+
}
|
|
2450
|
+
function buildBridgeEnvFile(cfg) {
|
|
2451
|
+
return `# Auto-generated by 'apes agents spawn --bridge'.
|
|
2452
|
+
# Read by the chat-bridge daemon at boot to talk to the local LLM proxy.
|
|
2453
|
+
LITELLM_BASE_URL=${cfg.baseUrl}
|
|
2454
|
+
LITELLM_API_KEY=${cfg.apiKey}
|
|
2455
|
+
`;
|
|
2456
|
+
}
|
|
2457
|
+
function buildBridgeStartScript() {
|
|
2458
|
+
return `#!/usr/bin/env bash
|
|
2459
|
+
# Auto-generated by 'apes agents spawn --bridge'.
|
|
2460
|
+
# Idempotent installer + launcher. First boot installs @openape/chat-bridge
|
|
2461
|
+
# globally via bun (homebrew-provided); subsequent boots skip the install.
|
|
2462
|
+
set -euo pipefail
|
|
2463
|
+
export PATH="/opt/homebrew/bin:$HOME/.bun/bin:$PATH"
|
|
2464
|
+
if ! command -v openape-chat-bridge >/dev/null 2>&1; then
|
|
2465
|
+
bun add -g @openape/chat-bridge
|
|
2466
|
+
fi
|
|
2467
|
+
set -a
|
|
2468
|
+
. "$HOME/.pi/agent/.env"
|
|
2469
|
+
set +a
|
|
2470
|
+
exec openape-chat-bridge
|
|
2471
|
+
`;
|
|
2472
|
+
}
|
|
2473
|
+
function buildBridgePlist(homeDir) {
|
|
2474
|
+
const startScript = `${homeDir}/Library/Application Support/openape/bridge/start.sh`;
|
|
2475
|
+
const stdoutLog = `${homeDir}/Library/Logs/openape-chat-bridge.log`;
|
|
2476
|
+
const stderrLog = `${homeDir}/Library/Logs/openape-chat-bridge.err.log`;
|
|
2477
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
2478
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
2479
|
+
<plist version="1.0">
|
|
2480
|
+
<dict>
|
|
2481
|
+
<key>Label</key>
|
|
2482
|
+
<string>${BRIDGE_PLIST_LABEL}</string>
|
|
2483
|
+
<key>ProgramArguments</key>
|
|
2484
|
+
<array>
|
|
2485
|
+
<string>${startScript}</string>
|
|
2486
|
+
</array>
|
|
2487
|
+
<key>WorkingDirectory</key>
|
|
2488
|
+
<string>${homeDir}</string>
|
|
2489
|
+
<key>RunAtLoad</key>
|
|
2490
|
+
<true/>
|
|
2491
|
+
<key>KeepAlive</key>
|
|
2492
|
+
<true/>
|
|
2493
|
+
<key>ThrottleInterval</key>
|
|
2494
|
+
<integer>10</integer>
|
|
2495
|
+
<key>StandardOutPath</key>
|
|
2496
|
+
<string>${stdoutLog}</string>
|
|
2497
|
+
<key>StandardErrorPath</key>
|
|
2498
|
+
<string>${stderrLog}</string>
|
|
2499
|
+
<key>EnvironmentVariables</key>
|
|
2500
|
+
<dict>
|
|
2501
|
+
<key>HOME</key>
|
|
2502
|
+
<string>${homeDir}</string>
|
|
2503
|
+
<key>PATH</key>
|
|
2504
|
+
<string>/opt/homebrew/bin:/usr/bin:/bin</string>
|
|
2505
|
+
</dict>
|
|
2506
|
+
</dict>
|
|
2507
|
+
</plist>
|
|
2508
|
+
`;
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2392
2511
|
// src/commands/agents/spawn.ts
|
|
2393
2512
|
var spawnAgentCommand = defineCommand23({
|
|
2394
2513
|
meta: {
|
|
@@ -2416,6 +2535,18 @@ var spawnAgentCommand = defineCommand23({
|
|
|
2416
2535
|
"claude-token-stdin": {
|
|
2417
2536
|
type: "boolean",
|
|
2418
2537
|
description: "Read the Claude Code OAuth token from stdin (paranoid form of --claude-token)."
|
|
2538
|
+
},
|
|
2539
|
+
"bridge": {
|
|
2540
|
+
type: "boolean",
|
|
2541
|
+
description: "Install the openape-chat-bridge daemon for this agent: drops a launchd plist that runs `@openape/chat-bridge` so the agent answers chat.openape.ai messages. Reads LITELLM_API_KEY/BASE_URL defaults from ~/litellm/.env; override via --bridge-key / --bridge-base-url."
|
|
2542
|
+
},
|
|
2543
|
+
"bridge-key": {
|
|
2544
|
+
type: "string",
|
|
2545
|
+
description: "Override LITELLM_API_KEY for the bridge (default: read from ~/litellm/.env)."
|
|
2546
|
+
},
|
|
2547
|
+
"bridge-base-url": {
|
|
2548
|
+
type: "string",
|
|
2549
|
+
description: "Override LITELLM_BASE_URL for the bridge (default: read from ~/litellm/.env or http://127.0.0.1:4000/v1)."
|
|
2419
2550
|
}
|
|
2420
2551
|
},
|
|
2421
2552
|
async run({ args }) {
|
|
@@ -2461,8 +2592,8 @@ and try again.`
|
|
|
2461
2592
|
throw new CliError(`macOS user "${name}" already exists (uid=${existing.uid ?? "?"}). Refusing to overwrite.`);
|
|
2462
2593
|
}
|
|
2463
2594
|
const homeDir = `/Users/${name}`;
|
|
2464
|
-
const scratch = mkdtempSync2(
|
|
2465
|
-
const scriptPath =
|
|
2595
|
+
const scratch = mkdtempSync2(join4(tmpdir2(), `apes-spawn-${name}-`));
|
|
2596
|
+
const scriptPath = join4(scratch, "setup.sh");
|
|
2466
2597
|
try {
|
|
2467
2598
|
consola21.start(`Generating keypair for ${name}\u2026`);
|
|
2468
2599
|
const { privatePem, publicSshLine } = generateKeyPairInMemory();
|
|
@@ -2486,6 +2617,18 @@ and try again.`
|
|
|
2486
2617
|
flag: typeof args["claude-token"] === "string" ? args["claude-token"] : void 0,
|
|
2487
2618
|
fromStdin: !!args["claude-token-stdin"]
|
|
2488
2619
|
});
|
|
2620
|
+
const bridge = args.bridge ? (() => {
|
|
2621
|
+
const cfg = resolveBridgeConfig({
|
|
2622
|
+
cliKey: typeof args["bridge-key"] === "string" ? args["bridge-key"] : void 0,
|
|
2623
|
+
cliBaseUrl: typeof args["bridge-base-url"] === "string" ? args["bridge-base-url"] : void 0
|
|
2624
|
+
});
|
|
2625
|
+
return {
|
|
2626
|
+
plistLabel: BRIDGE_PLIST_LABEL,
|
|
2627
|
+
plistContent: buildBridgePlist(homeDir),
|
|
2628
|
+
startScript: buildBridgeStartScript(),
|
|
2629
|
+
envFile: buildBridgeEnvFile(cfg)
|
|
2630
|
+
};
|
|
2631
|
+
})() : null;
|
|
2489
2632
|
const script = buildSpawnSetupScript({
|
|
2490
2633
|
name,
|
|
2491
2634
|
homeDir,
|
|
@@ -2495,7 +2638,8 @@ and try again.`
|
|
|
2495
2638
|
authJson,
|
|
2496
2639
|
claudeSettingsJson: includeClaudeHook ? CLAUDE_SETTINGS_JSON : null,
|
|
2497
2640
|
hookScriptSource: includeClaudeHook ? BASH_VIA_APE_SHELL_HOOK_SOURCE : null,
|
|
2498
|
-
claudeOauthToken
|
|
2641
|
+
claudeOauthToken,
|
|
2642
|
+
bridge
|
|
2499
2643
|
});
|
|
2500
2644
|
writeFileSync3(scriptPath, script, { mode: 448 });
|
|
2501
2645
|
consola21.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
|
|
@@ -3359,7 +3503,7 @@ import { spawn } from "child_process";
|
|
|
3359
3503
|
import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
3360
3504
|
import { createRequire } from "module";
|
|
3361
3505
|
import { tmpdir as tmpdir3 } from "os";
|
|
3362
|
-
import { dirname as dirname2, join as
|
|
3506
|
+
import { dirname as dirname2, join as join5, resolve as resolve3 } from "path";
|
|
3363
3507
|
var require2 = createRequire(import.meta.url);
|
|
3364
3508
|
function findProxyBin() {
|
|
3365
3509
|
const pkgPath = require2.resolve("@openape/proxy/package.json");
|
|
@@ -3371,8 +3515,8 @@ function findProxyBin() {
|
|
|
3371
3515
|
return resolve3(dirname2(pkgPath), binRel);
|
|
3372
3516
|
}
|
|
3373
3517
|
async function startEphemeralProxy(configToml) {
|
|
3374
|
-
const tmpDir = mkdtempSync3(
|
|
3375
|
-
const configPath =
|
|
3518
|
+
const tmpDir = mkdtempSync3(join5(tmpdir3(), "openape-proxy-"));
|
|
3519
|
+
const configPath = join5(tmpDir, "config.toml");
|
|
3376
3520
|
writeFileSync4(configPath, configToml, { mode: 384 });
|
|
3377
3521
|
const binPath = findProxyBin();
|
|
3378
3522
|
const child = spawn(process.execPath, [binPath, "-c", configPath], {
|
|
@@ -3808,16 +3952,16 @@ var mcpCommand = defineCommand32({
|
|
|
3808
3952
|
if (transport !== "stdio" && transport !== "sse") {
|
|
3809
3953
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
3810
3954
|
}
|
|
3811
|
-
const { startMcpServer } = await import("./server-
|
|
3955
|
+
const { startMcpServer } = await import("./server-D5EQSCWF.js");
|
|
3812
3956
|
await startMcpServer(transport, port);
|
|
3813
3957
|
}
|
|
3814
3958
|
});
|
|
3815
3959
|
|
|
3816
3960
|
// src/commands/init/index.ts
|
|
3817
|
-
import { existsSync as
|
|
3961
|
+
import { existsSync as existsSync7, copyFileSync, writeFileSync as writeFileSync5 } from "fs";
|
|
3818
3962
|
import { randomBytes } from "crypto";
|
|
3819
3963
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
3820
|
-
import { join as
|
|
3964
|
+
import { join as join6 } from "path";
|
|
3821
3965
|
import { defineCommand as defineCommand33 } from "citty";
|
|
3822
3966
|
import consola27 from "consola";
|
|
3823
3967
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
@@ -3826,7 +3970,7 @@ async function downloadTemplate(repo, targetDir) {
|
|
|
3826
3970
|
await gigetDownload(`gh:${repo}`, { dir: targetDir, force: false });
|
|
3827
3971
|
}
|
|
3828
3972
|
function installDeps(dir) {
|
|
3829
|
-
const hasLockFile = (name) =>
|
|
3973
|
+
const hasLockFile = (name) => existsSync7(join6(dir, name));
|
|
3830
3974
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
3831
3975
|
execFileSync6("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
3832
3976
|
} else if (hasLockFile("bun.lockb")) {
|
|
@@ -3891,7 +4035,7 @@ var initCommand = defineCommand33({
|
|
|
3891
4035
|
});
|
|
3892
4036
|
async function initSP(targetDir) {
|
|
3893
4037
|
const dir = targetDir || "my-app";
|
|
3894
|
-
if (
|
|
4038
|
+
if (existsSync7(join6(dir, "package.json"))) {
|
|
3895
4039
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
3896
4040
|
}
|
|
3897
4041
|
consola27.start("Scaffolding SP starter...");
|
|
@@ -3900,9 +4044,9 @@ async function initSP(targetDir) {
|
|
|
3900
4044
|
consola27.start("Installing dependencies...");
|
|
3901
4045
|
installDeps(dir);
|
|
3902
4046
|
consola27.success("Dependencies installed");
|
|
3903
|
-
const envExample =
|
|
3904
|
-
const envFile =
|
|
3905
|
-
if (
|
|
4047
|
+
const envExample = join6(dir, ".env.example");
|
|
4048
|
+
const envFile = join6(dir, ".env");
|
|
4049
|
+
if (existsSync7(envExample) && !existsSync7(envFile)) {
|
|
3906
4050
|
copyFileSync(envExample, envFile);
|
|
3907
4051
|
consola27.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
3908
4052
|
}
|
|
@@ -3916,7 +4060,7 @@ async function initSP(targetDir) {
|
|
|
3916
4060
|
}
|
|
3917
4061
|
async function initIdP(targetDir) {
|
|
3918
4062
|
const dir = targetDir || "my-idp";
|
|
3919
|
-
if (
|
|
4063
|
+
if (existsSync7(join6(dir, "package.json"))) {
|
|
3920
4064
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
3921
4065
|
}
|
|
3922
4066
|
const domain = await promptText("Domain for the IdP", "localhost");
|
|
@@ -3948,7 +4092,7 @@ async function initIdP(targetDir) {
|
|
|
3948
4092
|
`NUXT_OPENAPE_RP_ID=${domain}`,
|
|
3949
4093
|
`NUXT_OPENAPE_RP_ORIGIN=${origin}`
|
|
3950
4094
|
].join("\n");
|
|
3951
|
-
writeFileSync5(
|
|
4095
|
+
writeFileSync5(join6(dir, ".env"), `${envContent}
|
|
3952
4096
|
`, { mode: 384 });
|
|
3953
4097
|
consola27.success(".env created");
|
|
3954
4098
|
console.log("");
|
|
@@ -3969,7 +4113,7 @@ async function initIdP(targetDir) {
|
|
|
3969
4113
|
|
|
3970
4114
|
// src/commands/enroll.ts
|
|
3971
4115
|
import { Buffer as Buffer5 } from "buffer";
|
|
3972
|
-
import { existsSync as
|
|
4116
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
3973
4117
|
import { execFile as execFile2 } from "child_process";
|
|
3974
4118
|
import { sign as sign2 } from "crypto";
|
|
3975
4119
|
import { defineCommand as defineCommand34 } from "citty";
|
|
@@ -3985,7 +4129,7 @@ function openBrowser2(url) {
|
|
|
3985
4129
|
}
|
|
3986
4130
|
async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
3987
4131
|
const resolvedKey = resolveKeyPath(keyPath);
|
|
3988
|
-
const keyContent =
|
|
4132
|
+
const keyContent = readFileSync6(resolvedKey, "utf-8");
|
|
3989
4133
|
const privateKey = loadEd25519PrivateKey(keyContent);
|
|
3990
4134
|
const challengeUrl = await getAgentChallengeEndpoint(idp);
|
|
3991
4135
|
const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
|
|
@@ -4053,7 +4197,7 @@ var enrollCommand = defineCommand34({
|
|
|
4053
4197
|
}) || DEFAULT_KEY_PATH;
|
|
4054
4198
|
const resolvedKey = resolveKeyPath(keyPath);
|
|
4055
4199
|
let publicKey;
|
|
4056
|
-
if (
|
|
4200
|
+
if (existsSync8(resolvedKey)) {
|
|
4057
4201
|
publicKey = readPublicKey(resolvedKey);
|
|
4058
4202
|
consola28.success(`Using existing key ${keyPath}`);
|
|
4059
4203
|
} else {
|
|
@@ -4097,7 +4241,7 @@ var enrollCommand = defineCommand34({
|
|
|
4097
4241
|
});
|
|
4098
4242
|
|
|
4099
4243
|
// src/commands/register-user.ts
|
|
4100
|
-
import { existsSync as
|
|
4244
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
4101
4245
|
import { defineCommand as defineCommand35 } from "citty";
|
|
4102
4246
|
import consola29 from "consola";
|
|
4103
4247
|
var registerUserCommand = defineCommand35({
|
|
@@ -4136,8 +4280,8 @@ var registerUserCommand = defineCommand35({
|
|
|
4136
4280
|
throw new CliError("No IdP URL configured. Run `apes login` first.");
|
|
4137
4281
|
}
|
|
4138
4282
|
let publicKey = args.key;
|
|
4139
|
-
if (
|
|
4140
|
-
publicKey =
|
|
4283
|
+
if (existsSync9(args.key)) {
|
|
4284
|
+
publicKey = readFileSync7(args.key, "utf-8").trim();
|
|
4141
4285
|
}
|
|
4142
4286
|
if (!publicKey.startsWith("ssh-ed25519 ")) {
|
|
4143
4287
|
throw new CliError("Public key must be in ssh-ed25519 format.");
|
|
@@ -4446,7 +4590,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
4446
4590
|
}
|
|
4447
4591
|
}
|
|
4448
4592
|
async function runHealth(args) {
|
|
4449
|
-
const version = true ? "0.
|
|
4593
|
+
const version = true ? "0.23.0" : "0.0.0";
|
|
4450
4594
|
const auth = loadAuth();
|
|
4451
4595
|
if (!auth) {
|
|
4452
4596
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -4639,25 +4783,25 @@ var workflowsCommand = defineCommand43({
|
|
|
4639
4783
|
});
|
|
4640
4784
|
|
|
4641
4785
|
// src/version-check.ts
|
|
4642
|
-
import { existsSync as
|
|
4643
|
-
import { homedir as
|
|
4644
|
-
import { join as
|
|
4786
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync2, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
4787
|
+
import { homedir as homedir6 } from "os";
|
|
4788
|
+
import { join as join7 } from "path";
|
|
4645
4789
|
import consola35 from "consola";
|
|
4646
4790
|
var PACKAGE_NAME = "@openape/apes";
|
|
4647
4791
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
4648
|
-
var CACHE_FILE =
|
|
4792
|
+
var CACHE_FILE = join7(homedir6(), ".config", "apes", ".version-check.json");
|
|
4649
4793
|
function readCache() {
|
|
4650
|
-
if (!
|
|
4794
|
+
if (!existsSync10(CACHE_FILE)) return null;
|
|
4651
4795
|
try {
|
|
4652
|
-
return JSON.parse(
|
|
4796
|
+
return JSON.parse(readFileSync8(CACHE_FILE, "utf-8"));
|
|
4653
4797
|
} catch {
|
|
4654
4798
|
return null;
|
|
4655
4799
|
}
|
|
4656
4800
|
}
|
|
4657
4801
|
function writeCache(entry) {
|
|
4658
4802
|
try {
|
|
4659
|
-
const dir =
|
|
4660
|
-
if (!
|
|
4803
|
+
const dir = join7(homedir6(), ".config", "apes");
|
|
4804
|
+
if (!existsSync10(dir)) mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
4661
4805
|
writeFileSync6(CACHE_FILE, JSON.stringify(entry), { mode: 384 });
|
|
4662
4806
|
} catch {
|
|
4663
4807
|
}
|
|
@@ -4719,10 +4863,10 @@ if (shellRewrite) {
|
|
|
4719
4863
|
if (shellRewrite.action === "rewrite") {
|
|
4720
4864
|
process.argv = shellRewrite.argv;
|
|
4721
4865
|
} else if (shellRewrite.action === "version") {
|
|
4722
|
-
console.log(`ape-shell ${"0.
|
|
4866
|
+
console.log(`ape-shell ${"0.23.0"} (OpenApe DDISA shell wrapper)`);
|
|
4723
4867
|
process.exit(0);
|
|
4724
4868
|
} else if (shellRewrite.action === "help") {
|
|
4725
|
-
console.log(`ape-shell ${"0.
|
|
4869
|
+
console.log(`ape-shell ${"0.23.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
4726
4870
|
console.log("");
|
|
4727
4871
|
console.log("Usage:");
|
|
4728
4872
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -4780,7 +4924,7 @@ var configCommand = defineCommand44({
|
|
|
4780
4924
|
var main = defineCommand44({
|
|
4781
4925
|
meta: {
|
|
4782
4926
|
name: "apes",
|
|
4783
|
-
version: "0.
|
|
4927
|
+
version: "0.23.0",
|
|
4784
4928
|
description: "Unified CLI for OpenApe"
|
|
4785
4929
|
},
|
|
4786
4930
|
subCommands: {
|
|
@@ -4835,7 +4979,7 @@ async function maybeRefreshAuth() {
|
|
|
4835
4979
|
}
|
|
4836
4980
|
}
|
|
4837
4981
|
await maybeRefreshAuth();
|
|
4838
|
-
await maybeWarnStaleVersion("0.
|
|
4982
|
+
await maybeWarnStaleVersion("0.23.0").catch(() => {
|
|
4839
4983
|
});
|
|
4840
4984
|
runMain(main).catch((err) => {
|
|
4841
4985
|
if (err instanceof CliExit) {
|