@openape/apes 1.10.0 → 1.11.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/chunk-TDSCDH5P.js +518 -0
- package/dist/chunk-TDSCDH5P.js.map +1 -0
- package/dist/cli.js +133 -599
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +89 -1
- package/dist/index.js +10 -2
- package/dist/{server-AZOEKT55.js → server-F3ALNNYS.js} +2 -2
- package/package.json +3 -3
- package/dist/chunk-ZSJU7IXE.js +0 -45
- package/dist/chunk-ZSJU7IXE.js.map +0 -1
- /package/dist/{server-AZOEKT55.js.map → server-F3ALNNYS.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -7,8 +7,11 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
CliError,
|
|
9
9
|
CliExit,
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
RpcSessionMap,
|
|
11
|
+
parseDuration,
|
|
12
|
+
runLoop,
|
|
13
|
+
taskTools
|
|
14
|
+
} from "./chunk-TDSCDH5P.js";
|
|
12
15
|
import {
|
|
13
16
|
loadEd25519PrivateKey,
|
|
14
17
|
readPublicKeyComment
|
|
@@ -317,7 +320,7 @@ async function loginWithPKCE(idp) {
|
|
|
317
320
|
authUrl.searchParams.set("state", state);
|
|
318
321
|
authUrl.searchParams.set("nonce", nonce);
|
|
319
322
|
authUrl.searchParams.set("scope", "openid email profile offline_access");
|
|
320
|
-
const code = await new Promise((
|
|
323
|
+
const code = await new Promise((resolve4, reject) => {
|
|
321
324
|
const server = createServer((req, res) => {
|
|
322
325
|
const url = new URL(req.url, `http://localhost:${CALLBACK_PORT}`);
|
|
323
326
|
if (url.pathname === "/callback") {
|
|
@@ -334,7 +337,7 @@ async function loginWithPKCE(idp) {
|
|
|
334
337
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
335
338
|
res.end("<h1>Login successful!</h1><p>You can close this window.</p>");
|
|
336
339
|
server.close();
|
|
337
|
-
|
|
340
|
+
resolve4(authCode);
|
|
338
341
|
return;
|
|
339
342
|
}
|
|
340
343
|
res.writeHead(400);
|
|
@@ -390,7 +393,7 @@ async function loginWithPKCE(idp) {
|
|
|
390
393
|
consola2.success(`Logged in as ${payload.email || payload.sub}`);
|
|
391
394
|
}
|
|
392
395
|
async function loginWithKey(idp, keyPath, agentEmail) {
|
|
393
|
-
const { readFileSync:
|
|
396
|
+
const { readFileSync: readFileSync14 } = await import("fs");
|
|
394
397
|
const { sign: sign3 } = await import("crypto");
|
|
395
398
|
const { loadEd25519PrivateKey: loadEd25519PrivateKey2 } = await import("./ssh-key-6X3YZXSD.js");
|
|
396
399
|
const challengeUrl = await getAgentChallengeEndpoint(idp);
|
|
@@ -403,7 +406,7 @@ async function loginWithKey(idp, keyPath, agentEmail) {
|
|
|
403
406
|
throw new CliError(`Challenge failed: ${await challengeResp.text()}`);
|
|
404
407
|
}
|
|
405
408
|
const { challenge } = await challengeResp.json();
|
|
406
|
-
const keyContent =
|
|
409
|
+
const keyContent = readFileSync14(keyPath, "utf-8");
|
|
407
410
|
const privateKey = loadEd25519PrivateKey2(keyContent);
|
|
408
411
|
const signature = sign3(null, Buffer2.from(challenge), privateKey).toString("base64");
|
|
409
412
|
const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
|
|
@@ -895,7 +898,7 @@ async function waitForApproval2(grantsUrl, grantId) {
|
|
|
895
898
|
if (grant.status === "revoked") {
|
|
896
899
|
throw new CliError("Grant revoked.");
|
|
897
900
|
}
|
|
898
|
-
await new Promise((
|
|
901
|
+
await new Promise((resolve4) => setTimeout(resolve4, interval));
|
|
899
902
|
}
|
|
900
903
|
throw new CliError("Timed out waiting for approval.");
|
|
901
904
|
}
|
|
@@ -2262,7 +2265,7 @@ function createFetch(globalOptions = {}) {
|
|
|
2262
2265
|
if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) {
|
|
2263
2266
|
const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0;
|
|
2264
2267
|
if (retryDelay > 0) {
|
|
2265
|
-
await new Promise((
|
|
2268
|
+
await new Promise((resolve4) => setTimeout(resolve4, retryDelay));
|
|
2266
2269
|
}
|
|
2267
2270
|
return $fetchRaw(context.request, {
|
|
2268
2271
|
...context.options,
|
|
@@ -2992,7 +2995,7 @@ function readPasswordSilent(prompt) {
|
|
|
2992
2995
|
"No TTY available for the silent password prompt. Set APES_ADMIN_PASSWORD in the environment instead."
|
|
2993
2996
|
));
|
|
2994
2997
|
}
|
|
2995
|
-
return new Promise((
|
|
2998
|
+
return new Promise((resolve4, reject) => {
|
|
2996
2999
|
process.stdout.write(prompt);
|
|
2997
3000
|
const wasRaw = process.stdin.isRaw ?? false;
|
|
2998
3001
|
process.stdin.setRawMode(true);
|
|
@@ -3007,7 +3010,7 @@ function readPasswordSilent(prompt) {
|
|
|
3007
3010
|
if (ch === "\r" || ch === "\n") {
|
|
3008
3011
|
cleanup();
|
|
3009
3012
|
process.stdout.write("\n");
|
|
3010
|
-
|
|
3013
|
+
resolve4(buf);
|
|
3011
3014
|
return;
|
|
3012
3015
|
}
|
|
3013
3016
|
if (code === 3) {
|
|
@@ -3303,481 +3306,12 @@ var registerAgentCommand = defineCommand23({
|
|
|
3303
3306
|
});
|
|
3304
3307
|
|
|
3305
3308
|
// src/commands/agents/run.ts
|
|
3306
|
-
import { existsSync as existsSync5, readFileSync as
|
|
3307
|
-
import { homedir as
|
|
3309
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
3310
|
+
import { homedir as homedir4 } from "os";
|
|
3308
3311
|
import { join as join3 } from "path";
|
|
3309
3312
|
import { defineCommand as defineCommand24 } from "citty";
|
|
3310
3313
|
import consola22 from "consola";
|
|
3311
3314
|
|
|
3312
|
-
// src/lib/agent-tools/file.ts
|
|
3313
|
-
import { mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
3314
|
-
import { homedir as homedir4 } from "os";
|
|
3315
|
-
import { dirname, normalize, resolve as resolve2 } from "path";
|
|
3316
|
-
var MAX_BYTES = 1024 * 1024;
|
|
3317
|
-
function jailPath(input) {
|
|
3318
|
-
if (typeof input !== "string" || input === "") {
|
|
3319
|
-
throw new Error("path must be a non-empty string");
|
|
3320
|
-
}
|
|
3321
|
-
const home = homedir4();
|
|
3322
|
-
const candidate = input.startsWith("~/") ? resolve2(home, input.slice(2)) : input.startsWith("/") ? normalize(input) : resolve2(home, input);
|
|
3323
|
-
if (candidate !== home && !candidate.startsWith(`${home}/`)) {
|
|
3324
|
-
throw new Error(`path "${input}" resolves outside the agent's home`);
|
|
3325
|
-
}
|
|
3326
|
-
return candidate;
|
|
3327
|
-
}
|
|
3328
|
-
var fileTools = [
|
|
3329
|
-
{
|
|
3330
|
-
name: "file.read",
|
|
3331
|
-
description: "Read a UTF-8 file from the agent's home directory ($HOME). Capped at 1MB. Path traversal blocked.",
|
|
3332
|
-
parameters: {
|
|
3333
|
-
type: "object",
|
|
3334
|
-
properties: {
|
|
3335
|
-
path: { type: "string", description: "Path relative to $HOME (or absolute under $HOME). `..` segments are rejected." }
|
|
3336
|
-
},
|
|
3337
|
-
required: ["path"]
|
|
3338
|
-
},
|
|
3339
|
-
execute: async (args) => {
|
|
3340
|
-
const a = args;
|
|
3341
|
-
const p2 = jailPath(a.path);
|
|
3342
|
-
const content = readFileSync4(p2, "utf8");
|
|
3343
|
-
if (Buffer.byteLength(content, "utf8") > MAX_BYTES) {
|
|
3344
|
-
return { path: p2, truncated: true, content: content.slice(0, MAX_BYTES) };
|
|
3345
|
-
}
|
|
3346
|
-
return { path: p2, truncated: false, content };
|
|
3347
|
-
}
|
|
3348
|
-
},
|
|
3349
|
-
{
|
|
3350
|
-
name: "file.write",
|
|
3351
|
-
description: "Write a UTF-8 file under the agent's home directory. Creates parent dirs as needed. 1MB max.",
|
|
3352
|
-
parameters: {
|
|
3353
|
-
type: "object",
|
|
3354
|
-
properties: {
|
|
3355
|
-
path: { type: "string", description: "Path relative to $HOME (or absolute under $HOME)." },
|
|
3356
|
-
content: { type: "string", description: "File body. Existing files are overwritten." }
|
|
3357
|
-
},
|
|
3358
|
-
required: ["path", "content"]
|
|
3359
|
-
},
|
|
3360
|
-
execute: async (args) => {
|
|
3361
|
-
const a = args;
|
|
3362
|
-
if (typeof a.content !== "string") throw new Error("content must be a string");
|
|
3363
|
-
if (Buffer.byteLength(a.content, "utf8") > MAX_BYTES) {
|
|
3364
|
-
throw new Error(`content exceeds ${MAX_BYTES} byte cap`);
|
|
3365
|
-
}
|
|
3366
|
-
const p2 = jailPath(a.path);
|
|
3367
|
-
mkdirSync(dirname(p2), { recursive: true });
|
|
3368
|
-
writeFileSync2(p2, a.content, { encoding: "utf8" });
|
|
3369
|
-
return { path: p2, bytes: Buffer.byteLength(a.content, "utf8") };
|
|
3370
|
-
}
|
|
3371
|
-
}
|
|
3372
|
-
];
|
|
3373
|
-
|
|
3374
|
-
// src/lib/agent-tools/http.ts
|
|
3375
|
-
var MAX_BYTES2 = 1024 * 1024;
|
|
3376
|
-
var FORBIDDEN_HEADERS = /* @__PURE__ */ new Set([
|
|
3377
|
-
"host",
|
|
3378
|
-
"authorization",
|
|
3379
|
-
"cookie",
|
|
3380
|
-
"connection",
|
|
3381
|
-
"transfer-encoding",
|
|
3382
|
-
"upgrade",
|
|
3383
|
-
"proxy-authorization"
|
|
3384
|
-
]);
|
|
3385
|
-
function sanitizeHeaders(input) {
|
|
3386
|
-
if (!input || typeof input !== "object") return {};
|
|
3387
|
-
const out = {};
|
|
3388
|
-
for (const [k, v] of Object.entries(input)) {
|
|
3389
|
-
if (typeof v !== "string") continue;
|
|
3390
|
-
if (FORBIDDEN_HEADERS.has(k.toLowerCase())) continue;
|
|
3391
|
-
out[k] = v;
|
|
3392
|
-
}
|
|
3393
|
-
return out;
|
|
3394
|
-
}
|
|
3395
|
-
async function readCappedBody(res) {
|
|
3396
|
-
const buf = new Uint8Array(MAX_BYTES2 + 1);
|
|
3397
|
-
let written = 0;
|
|
3398
|
-
const reader = res.body?.getReader();
|
|
3399
|
-
if (!reader) return await res.text();
|
|
3400
|
-
while (true) {
|
|
3401
|
-
const { value, done } = await reader.read();
|
|
3402
|
-
if (done) break;
|
|
3403
|
-
if (written + value.byteLength > MAX_BYTES2) {
|
|
3404
|
-
buf.set(value.subarray(0, MAX_BYTES2 - written), written);
|
|
3405
|
-
written = MAX_BYTES2;
|
|
3406
|
-
try {
|
|
3407
|
-
await reader.cancel();
|
|
3408
|
-
} catch {
|
|
3409
|
-
}
|
|
3410
|
-
break;
|
|
3411
|
-
}
|
|
3412
|
-
buf.set(value, written);
|
|
3413
|
-
written += value.byteLength;
|
|
3414
|
-
}
|
|
3415
|
-
return new TextDecoder().decode(buf.subarray(0, written));
|
|
3416
|
-
}
|
|
3417
|
-
var httpTools = [
|
|
3418
|
-
{
|
|
3419
|
-
name: "http.get",
|
|
3420
|
-
description: "GET an HTTPS URL and return the response body (capped at 1MB). Useful for reading public APIs, RSS feeds, web pages.",
|
|
3421
|
-
parameters: {
|
|
3422
|
-
type: "object",
|
|
3423
|
-
properties: {
|
|
3424
|
-
url: { type: "string", description: "Absolute HTTPS URL." },
|
|
3425
|
-
headers: { type: "object", description: "Optional headers (Host, Authorization, Cookie are stripped)." }
|
|
3426
|
-
},
|
|
3427
|
-
required: ["url"]
|
|
3428
|
-
},
|
|
3429
|
-
execute: async (args) => {
|
|
3430
|
-
const a = args;
|
|
3431
|
-
if (typeof a.url !== "string" || !a.url.startsWith("http")) {
|
|
3432
|
-
throw new Error("url must be an http(s) URL");
|
|
3433
|
-
}
|
|
3434
|
-
const res = await fetch(a.url, { method: "GET", headers: sanitizeHeaders(a.headers) });
|
|
3435
|
-
const body = await readCappedBody(res);
|
|
3436
|
-
return { status: res.status, headers: Object.fromEntries(res.headers), body };
|
|
3437
|
-
}
|
|
3438
|
-
},
|
|
3439
|
-
{
|
|
3440
|
-
name: "http.post",
|
|
3441
|
-
description: "POST JSON to an HTTPS URL and return the response body (capped at 1MB).",
|
|
3442
|
-
parameters: {
|
|
3443
|
-
type: "object",
|
|
3444
|
-
properties: {
|
|
3445
|
-
url: { type: "string", description: "Absolute HTTPS URL." },
|
|
3446
|
-
body: { description: "JSON-serialisable payload." },
|
|
3447
|
-
headers: { type: "object", description: "Optional headers (Host, Authorization, Cookie are stripped)." }
|
|
3448
|
-
},
|
|
3449
|
-
required: ["url", "body"]
|
|
3450
|
-
},
|
|
3451
|
-
execute: async (args) => {
|
|
3452
|
-
const a = args;
|
|
3453
|
-
if (typeof a.url !== "string" || !a.url.startsWith("http")) {
|
|
3454
|
-
throw new Error("url must be an http(s) URL");
|
|
3455
|
-
}
|
|
3456
|
-
const res = await fetch(a.url, {
|
|
3457
|
-
method: "POST",
|
|
3458
|
-
headers: { "content-type": "application/json", ...sanitizeHeaders(a.headers) },
|
|
3459
|
-
body: JSON.stringify(a.body)
|
|
3460
|
-
});
|
|
3461
|
-
const body = await readCappedBody(res);
|
|
3462
|
-
return { status: res.status, headers: Object.fromEntries(res.headers), body };
|
|
3463
|
-
}
|
|
3464
|
-
}
|
|
3465
|
-
];
|
|
3466
|
-
|
|
3467
|
-
// src/lib/agent-tools/mail.ts
|
|
3468
|
-
import { execFileSync as execFileSync5 } from "child_process";
|
|
3469
|
-
function o365(args) {
|
|
3470
|
-
try {
|
|
3471
|
-
return execFileSync5("o365-cli", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
3472
|
-
} catch (err) {
|
|
3473
|
-
const e = err;
|
|
3474
|
-
if (e.code === "ENOENT") {
|
|
3475
|
-
throw new Error("o365-cli is not installed on this agent host");
|
|
3476
|
-
}
|
|
3477
|
-
const stderr = typeof e.stderr === "string" ? e.stderr : e.stderr?.toString("utf8");
|
|
3478
|
-
throw new Error(`o365-cli failed: ${stderr ?? e.message ?? err}`);
|
|
3479
|
-
}
|
|
3480
|
-
}
|
|
3481
|
-
var mailTools = [
|
|
3482
|
-
{
|
|
3483
|
-
name: "mail.list",
|
|
3484
|
-
description: "List recent inbox messages via o365-cli. Optional `unread_only` and `limit`.",
|
|
3485
|
-
parameters: {
|
|
3486
|
-
type: "object",
|
|
3487
|
-
properties: {
|
|
3488
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 20 },
|
|
3489
|
-
unread_only: { type: "boolean", default: false }
|
|
3490
|
-
},
|
|
3491
|
-
required: []
|
|
3492
|
-
},
|
|
3493
|
-
execute: async (args) => {
|
|
3494
|
-
const a = args ?? {};
|
|
3495
|
-
const argv = ["mail", "list", "--json", "--limit", String(a.limit ?? 20)];
|
|
3496
|
-
if (a.unread_only) argv.push("--unread");
|
|
3497
|
-
const out = o365(argv);
|
|
3498
|
-
try {
|
|
3499
|
-
return JSON.parse(out);
|
|
3500
|
-
} catch {
|
|
3501
|
-
return { raw: out };
|
|
3502
|
-
}
|
|
3503
|
-
}
|
|
3504
|
-
},
|
|
3505
|
-
{
|
|
3506
|
-
name: "mail.search",
|
|
3507
|
-
description: "Search the inbox via o365-cli using a free-form query string.",
|
|
3508
|
-
parameters: {
|
|
3509
|
-
type: "object",
|
|
3510
|
-
properties: {
|
|
3511
|
-
q: { type: "string" },
|
|
3512
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 20 }
|
|
3513
|
-
},
|
|
3514
|
-
required: ["q"]
|
|
3515
|
-
},
|
|
3516
|
-
execute: async (args) => {
|
|
3517
|
-
const a = args;
|
|
3518
|
-
if (typeof a.q !== "string" || a.q.length === 0) throw new Error("q is required");
|
|
3519
|
-
const argv = ["mail", "search", a.q, "--json", "--limit", String(a.limit ?? 20)];
|
|
3520
|
-
const out = o365(argv);
|
|
3521
|
-
try {
|
|
3522
|
-
return JSON.parse(out);
|
|
3523
|
-
} catch {
|
|
3524
|
-
return { raw: out };
|
|
3525
|
-
}
|
|
3526
|
-
}
|
|
3527
|
-
}
|
|
3528
|
-
];
|
|
3529
|
-
|
|
3530
|
-
// src/lib/agent-tools/tasks.ts
|
|
3531
|
-
import { execFileSync as execFileSync6 } from "child_process";
|
|
3532
|
-
function ape(args) {
|
|
3533
|
-
try {
|
|
3534
|
-
return execFileSync6("ape-tasks", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
3535
|
-
} catch (err) {
|
|
3536
|
-
const e = err;
|
|
3537
|
-
const stderr = typeof e.stderr === "string" ? e.stderr : e.stderr?.toString("utf8");
|
|
3538
|
-
throw new Error(`ape-tasks failed: ${stderr ?? e.message ?? err}`);
|
|
3539
|
-
}
|
|
3540
|
-
}
|
|
3541
|
-
var tasksTools = [
|
|
3542
|
-
{
|
|
3543
|
-
name: "tasks.list",
|
|
3544
|
-
description: "List the owner's open ape-tasks (the user's personal task list at tasks.openape.ai).",
|
|
3545
|
-
parameters: {
|
|
3546
|
-
type: "object",
|
|
3547
|
-
properties: {
|
|
3548
|
-
status: { type: "string", enum: ["open", "doing", "done", "archived"] },
|
|
3549
|
-
team_id: { type: "string" }
|
|
3550
|
-
},
|
|
3551
|
-
required: []
|
|
3552
|
-
},
|
|
3553
|
-
execute: async (args) => {
|
|
3554
|
-
const a = args ?? {};
|
|
3555
|
-
const argv = ["list", "--json"];
|
|
3556
|
-
if (a.status) argv.push("--status", a.status);
|
|
3557
|
-
if (a.team_id) argv.push("--team", a.team_id);
|
|
3558
|
-
const out = ape(argv);
|
|
3559
|
-
try {
|
|
3560
|
-
return JSON.parse(out);
|
|
3561
|
-
} catch {
|
|
3562
|
-
return { raw: out };
|
|
3563
|
-
}
|
|
3564
|
-
}
|
|
3565
|
-
},
|
|
3566
|
-
{
|
|
3567
|
-
name: "tasks.create",
|
|
3568
|
-
description: "Create a new ape-task on the owner's task list at tasks.openape.ai.",
|
|
3569
|
-
parameters: {
|
|
3570
|
-
type: "object",
|
|
3571
|
-
properties: {
|
|
3572
|
-
title: { type: "string" },
|
|
3573
|
-
notes: { type: "string" },
|
|
3574
|
-
priority: { type: "string", enum: ["low", "med", "high"] },
|
|
3575
|
-
due_at: { type: "string", description: "ISO date or +Nh/+Nd shorthand." }
|
|
3576
|
-
},
|
|
3577
|
-
required: ["title"]
|
|
3578
|
-
},
|
|
3579
|
-
execute: async (args) => {
|
|
3580
|
-
const a = args;
|
|
3581
|
-
const argv = ["new", "--title", a.title, "--json"];
|
|
3582
|
-
if (a.notes) argv.push("--notes", a.notes);
|
|
3583
|
-
if (a.priority) argv.push("--priority", a.priority);
|
|
3584
|
-
if (a.due_at) argv.push("--due", a.due_at);
|
|
3585
|
-
const out = ape(argv);
|
|
3586
|
-
try {
|
|
3587
|
-
return JSON.parse(out);
|
|
3588
|
-
} catch {
|
|
3589
|
-
return { raw: out };
|
|
3590
|
-
}
|
|
3591
|
-
}
|
|
3592
|
-
}
|
|
3593
|
-
];
|
|
3594
|
-
|
|
3595
|
-
// src/lib/agent-tools/time.ts
|
|
3596
|
-
var timeTools = [
|
|
3597
|
-
{
|
|
3598
|
-
name: "time.now",
|
|
3599
|
-
description: "Returns the current UTC date and time as ISO 8601 plus epoch seconds. No inputs.",
|
|
3600
|
-
parameters: { type: "object", properties: {}, required: [] },
|
|
3601
|
-
execute: async () => {
|
|
3602
|
-
const now = /* @__PURE__ */ new Date();
|
|
3603
|
-
return {
|
|
3604
|
-
iso: now.toISOString(),
|
|
3605
|
-
epoch_seconds: Math.floor(now.getTime() / 1e3),
|
|
3606
|
-
timezone_offset_minutes: -now.getTimezoneOffset()
|
|
3607
|
-
};
|
|
3608
|
-
}
|
|
3609
|
-
}
|
|
3610
|
-
];
|
|
3611
|
-
|
|
3612
|
-
// src/lib/agent-tools/index.ts
|
|
3613
|
-
var ALL_TOOLS = [
|
|
3614
|
-
...timeTools,
|
|
3615
|
-
...httpTools,
|
|
3616
|
-
...fileTools,
|
|
3617
|
-
...tasksTools,
|
|
3618
|
-
...mailTools
|
|
3619
|
-
];
|
|
3620
|
-
var TOOLS = Object.fromEntries(
|
|
3621
|
-
ALL_TOOLS.map((t) => [t.name, t])
|
|
3622
|
-
);
|
|
3623
|
-
function taskTools(names) {
|
|
3624
|
-
const out = [];
|
|
3625
|
-
const missing = [];
|
|
3626
|
-
for (const name of names) {
|
|
3627
|
-
const tool = TOOLS[name];
|
|
3628
|
-
if (!tool) missing.push(name);
|
|
3629
|
-
else out.push(tool);
|
|
3630
|
-
}
|
|
3631
|
-
if (missing.length > 0) {
|
|
3632
|
-
throw new Error(`unknown tool(s): ${missing.join(", ")}`);
|
|
3633
|
-
}
|
|
3634
|
-
return out;
|
|
3635
|
-
}
|
|
3636
|
-
function asOpenAiTools(tools) {
|
|
3637
|
-
return tools.map((t) => ({
|
|
3638
|
-
type: "function",
|
|
3639
|
-
function: { name: wireToolName(t.name), description: t.description, parameters: t.parameters }
|
|
3640
|
-
}));
|
|
3641
|
-
}
|
|
3642
|
-
function wireToolName(local) {
|
|
3643
|
-
return local.replace(/\./g, "_");
|
|
3644
|
-
}
|
|
3645
|
-
function localToolName(wire) {
|
|
3646
|
-
for (const t of Object.values(TOOLS)) {
|
|
3647
|
-
if (wireToolName(t.name) === wire) return t.name;
|
|
3648
|
-
}
|
|
3649
|
-
return wire;
|
|
3650
|
-
}
|
|
3651
|
-
|
|
3652
|
-
// src/lib/agent-runtime.ts
|
|
3653
|
-
function previewJson(value, max = 500) {
|
|
3654
|
-
let s;
|
|
3655
|
-
try {
|
|
3656
|
-
s = JSON.stringify(value);
|
|
3657
|
-
} catch {
|
|
3658
|
-
s = String(value);
|
|
3659
|
-
}
|
|
3660
|
-
return s.length > max ? `${s.slice(0, max)}\u2026` : s;
|
|
3661
|
-
}
|
|
3662
|
-
async function runLoop(opts) {
|
|
3663
|
-
const fetchFn = opts.fetchImpl ?? fetch;
|
|
3664
|
-
const trace = [];
|
|
3665
|
-
const messages = [
|
|
3666
|
-
{ role: "system", content: opts.systemPrompt },
|
|
3667
|
-
...opts.history ?? [],
|
|
3668
|
-
{ role: "user", content: opts.userMessage }
|
|
3669
|
-
];
|
|
3670
|
-
const tools = asOpenAiTools(opts.tools);
|
|
3671
|
-
for (let step = 1; step <= opts.maxSteps; step++) {
|
|
3672
|
-
const res = await fetchFn(`${opts.config.apiBase}/chat/completions`, {
|
|
3673
|
-
method: "POST",
|
|
3674
|
-
headers: {
|
|
3675
|
-
"authorization": `Bearer ${opts.config.apiKey}`,
|
|
3676
|
-
"content-type": "application/json"
|
|
3677
|
-
},
|
|
3678
|
-
body: JSON.stringify({
|
|
3679
|
-
model: opts.config.model,
|
|
3680
|
-
messages,
|
|
3681
|
-
...tools.length > 0 ? { tools, tool_choice: "auto" } : {}
|
|
3682
|
-
})
|
|
3683
|
-
});
|
|
3684
|
-
if (!res.ok) {
|
|
3685
|
-
const text = await res.text().catch(() => "");
|
|
3686
|
-
throw new Error(`LiteLLM ${res.status}: ${text.slice(0, 500)}`);
|
|
3687
|
-
}
|
|
3688
|
-
const data = await res.json();
|
|
3689
|
-
const choice = data.choices?.[0];
|
|
3690
|
-
if (!choice) throw new Error("LiteLLM response had no choices");
|
|
3691
|
-
const assistant = choice.message;
|
|
3692
|
-
messages.push(assistant);
|
|
3693
|
-
if (assistant.content) opts.handlers?.onTextDelta?.(assistant.content);
|
|
3694
|
-
trace.push({
|
|
3695
|
-
step,
|
|
3696
|
-
type: "assistant",
|
|
3697
|
-
preview: previewJson({ content: assistant.content, tool_calls: assistant.tool_calls?.length ?? 0 })
|
|
3698
|
-
});
|
|
3699
|
-
if (!assistant.tool_calls || assistant.tool_calls.length === 0) {
|
|
3700
|
-
const result2 = {
|
|
3701
|
-
status: "ok",
|
|
3702
|
-
finalMessage: assistant.content,
|
|
3703
|
-
stepCount: step,
|
|
3704
|
-
trace
|
|
3705
|
-
};
|
|
3706
|
-
opts.handlers?.onDone?.(result2);
|
|
3707
|
-
return result2;
|
|
3708
|
-
}
|
|
3709
|
-
for (const call of assistant.tool_calls) {
|
|
3710
|
-
const wireName = call.function.name;
|
|
3711
|
-
const localName = localToolName(wireName);
|
|
3712
|
-
const tool = opts.tools.find((t) => t.name === localName);
|
|
3713
|
-
let parsedArgs;
|
|
3714
|
-
try {
|
|
3715
|
-
parsedArgs = JSON.parse(call.function.arguments);
|
|
3716
|
-
} catch {
|
|
3717
|
-
parsedArgs = {};
|
|
3718
|
-
}
|
|
3719
|
-
opts.handlers?.onToolCall?.({ name: localName, args: parsedArgs });
|
|
3720
|
-
trace.push({ step, type: "tool_call", tool: localName, preview: previewJson(parsedArgs) });
|
|
3721
|
-
let result2;
|
|
3722
|
-
let isError = false;
|
|
3723
|
-
if (!tool) {
|
|
3724
|
-
result2 = `unknown tool: ${localName}`;
|
|
3725
|
-
isError = true;
|
|
3726
|
-
} else {
|
|
3727
|
-
try {
|
|
3728
|
-
result2 = await tool.execute(parsedArgs);
|
|
3729
|
-
} catch (err) {
|
|
3730
|
-
result2 = err?.message ?? String(err);
|
|
3731
|
-
isError = true;
|
|
3732
|
-
}
|
|
3733
|
-
}
|
|
3734
|
-
if (isError) {
|
|
3735
|
-
opts.handlers?.onToolError?.({ name: localName, error: String(result2) });
|
|
3736
|
-
trace.push({ step, type: "tool_error", tool: localName, preview: previewJson(result2) });
|
|
3737
|
-
} else {
|
|
3738
|
-
opts.handlers?.onToolResult?.({ name: localName, result: result2 });
|
|
3739
|
-
trace.push({ step, type: "tool_result", tool: localName, preview: previewJson(result2) });
|
|
3740
|
-
}
|
|
3741
|
-
messages.push({
|
|
3742
|
-
role: "tool",
|
|
3743
|
-
tool_call_id: call.id,
|
|
3744
|
-
name: wireToolName(localName),
|
|
3745
|
-
content: typeof result2 === "string" ? result2 : JSON.stringify(result2)
|
|
3746
|
-
});
|
|
3747
|
-
}
|
|
3748
|
-
}
|
|
3749
|
-
const result = {
|
|
3750
|
-
status: "error",
|
|
3751
|
-
finalMessage: `max_steps (${opts.maxSteps}) reached without completion`,
|
|
3752
|
-
stepCount: opts.maxSteps,
|
|
3753
|
-
trace
|
|
3754
|
-
};
|
|
3755
|
-
opts.handlers?.onDone?.(result);
|
|
3756
|
-
return result;
|
|
3757
|
-
}
|
|
3758
|
-
var RPC_SESSION_TTL_MS = 60 * 60 * 1e3;
|
|
3759
|
-
var RpcSessionMap = class {
|
|
3760
|
-
sessions = /* @__PURE__ */ new Map();
|
|
3761
|
-
get(id) {
|
|
3762
|
-
const s = this.sessions.get(id);
|
|
3763
|
-
if (s) s.lastTouched = Date.now();
|
|
3764
|
-
return s;
|
|
3765
|
-
}
|
|
3766
|
-
put(id, s) {
|
|
3767
|
-
s.lastTouched = Date.now();
|
|
3768
|
-
this.sessions.set(id, s);
|
|
3769
|
-
}
|
|
3770
|
-
evictStale() {
|
|
3771
|
-
const cutoff = Date.now() - RPC_SESSION_TTL_MS;
|
|
3772
|
-
for (const [k, v] of this.sessions) {
|
|
3773
|
-
if (v.lastTouched < cutoff) this.sessions.delete(k);
|
|
3774
|
-
}
|
|
3775
|
-
}
|
|
3776
|
-
size() {
|
|
3777
|
-
return this.sessions.size;
|
|
3778
|
-
}
|
|
3779
|
-
};
|
|
3780
|
-
|
|
3781
3315
|
// src/lib/troop-client.ts
|
|
3782
3316
|
var DEFAULT_TROOP_URL = "https://troop.openape.ai";
|
|
3783
3317
|
var TroopClient = class {
|
|
@@ -3836,13 +3370,13 @@ function resolveTroopUrl(override) {
|
|
|
3836
3370
|
}
|
|
3837
3371
|
|
|
3838
3372
|
// src/commands/agents/run.ts
|
|
3839
|
-
var AUTH_PATH = join3(
|
|
3840
|
-
var TASK_CACHE_DIR = join3(
|
|
3373
|
+
var AUTH_PATH = join3(homedir4(), ".config", "apes", "auth.json");
|
|
3374
|
+
var TASK_CACHE_DIR = join3(homedir4(), ".openape", "agent", "tasks");
|
|
3841
3375
|
function readAuth() {
|
|
3842
3376
|
if (!existsSync5(AUTH_PATH)) {
|
|
3843
3377
|
throw new CliError(`No agent auth found at ${AUTH_PATH}. Run \`apes agents spawn <name>\` first.`);
|
|
3844
3378
|
}
|
|
3845
|
-
const parsed = JSON.parse(
|
|
3379
|
+
const parsed = JSON.parse(readFileSync4(AUTH_PATH, "utf8"));
|
|
3846
3380
|
if (!parsed.access_token) throw new CliError("auth.json missing access_token");
|
|
3847
3381
|
return parsed;
|
|
3848
3382
|
}
|
|
@@ -3882,22 +3416,22 @@ function readTaskSpec(taskId) {
|
|
|
3882
3416
|
if (!existsSync5(path2)) {
|
|
3883
3417
|
throw new CliError(`No cached task spec at ${path2}. Run \`apes agents sync\` first to pull the task list from troop.`);
|
|
3884
3418
|
}
|
|
3885
|
-
return JSON.parse(
|
|
3419
|
+
return JSON.parse(readFileSync4(path2, "utf8"));
|
|
3886
3420
|
}
|
|
3887
|
-
var AGENT_CONFIG_PATH = join3(
|
|
3421
|
+
var AGENT_CONFIG_PATH = join3(homedir4(), ".openape", "agent", "agent.json");
|
|
3888
3422
|
function readAgentConfig() {
|
|
3889
3423
|
if (!existsSync5(AGENT_CONFIG_PATH)) return { systemPrompt: "" };
|
|
3890
3424
|
try {
|
|
3891
|
-
return JSON.parse(
|
|
3425
|
+
return JSON.parse(readFileSync4(AGENT_CONFIG_PATH, "utf8"));
|
|
3892
3426
|
} catch {
|
|
3893
3427
|
return { systemPrompt: "" };
|
|
3894
3428
|
}
|
|
3895
3429
|
}
|
|
3896
3430
|
function readLitellmConfig(model) {
|
|
3897
|
-
const envPath = join3(
|
|
3431
|
+
const envPath = join3(homedir4(), "litellm", ".env");
|
|
3898
3432
|
const env = {};
|
|
3899
3433
|
if (existsSync5(envPath)) {
|
|
3900
|
-
for (const line of
|
|
3434
|
+
for (const line of readFileSync4(envPath, "utf8").split(/\r?\n/)) {
|
|
3901
3435
|
const m = line.match(/^([A-Z_]+)=(.*)$/);
|
|
3902
3436
|
if (m) env[m[1]] = m[2].replace(/^["']|["']$/g, "");
|
|
3903
3437
|
}
|
|
@@ -4002,17 +3536,17 @@ var runAgentCommand = defineCommand24({
|
|
|
4002
3536
|
});
|
|
4003
3537
|
|
|
4004
3538
|
// src/commands/agents/serve.ts
|
|
4005
|
-
import { existsSync as existsSync6, readFileSync as
|
|
4006
|
-
import { homedir as
|
|
3539
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
3540
|
+
import { homedir as homedir5 } from "os";
|
|
4007
3541
|
import { join as join4 } from "path";
|
|
4008
3542
|
import { createInterface } from "readline";
|
|
4009
3543
|
import { defineCommand as defineCommand25 } from "citty";
|
|
4010
|
-
var AUTH_PATH2 = join4(
|
|
3544
|
+
var AUTH_PATH2 = join4(homedir5(), ".config", "apes", "auth.json");
|
|
4011
3545
|
function readLitellmConfig2(model) {
|
|
4012
|
-
const envPath = join4(
|
|
3546
|
+
const envPath = join4(homedir5(), "litellm", ".env");
|
|
4013
3547
|
const env = {};
|
|
4014
3548
|
if (existsSync6(envPath)) {
|
|
4015
|
-
for (const line of
|
|
3549
|
+
for (const line of readFileSync5(envPath, "utf8").split(/\r?\n/)) {
|
|
4016
3550
|
const m = line.match(/^([A-Z_]+)=(.*)$/);
|
|
4017
3551
|
if (m) env[m[1]] = m[2].replace(/^["']|["']$/g, "");
|
|
4018
3552
|
}
|
|
@@ -4046,7 +3580,7 @@ var serveAgentCommand = defineCommand25({
|
|
|
4046
3580
|
}
|
|
4047
3581
|
if (existsSync6(AUTH_PATH2)) {
|
|
4048
3582
|
try {
|
|
4049
|
-
JSON.parse(
|
|
3583
|
+
JSON.parse(readFileSync5(AUTH_PATH2, "utf8"));
|
|
4050
3584
|
} catch {
|
|
4051
3585
|
}
|
|
4052
3586
|
}
|
|
@@ -4121,8 +3655,8 @@ async function handleInbound(msg, sessions) {
|
|
|
4121
3655
|
}
|
|
4122
3656
|
|
|
4123
3657
|
// src/commands/agents/spawn.ts
|
|
4124
|
-
import { execFileSync as
|
|
4125
|
-
import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as
|
|
3658
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
3659
|
+
import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
4126
3660
|
import { tmpdir as tmpdir2 } from "os";
|
|
4127
3661
|
import { join as join6 } from "path";
|
|
4128
3662
|
import { defineCommand as defineCommand26 } from "citty";
|
|
@@ -4182,12 +3716,12 @@ ${envBlock} <key>StartInterval</key>
|
|
|
4182
3716
|
|
|
4183
3717
|
// src/lib/keygen.ts
|
|
4184
3718
|
import { Buffer as Buffer4 } from "buffer";
|
|
4185
|
-
import { existsSync as existsSync7, mkdirSync
|
|
3719
|
+
import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
|
|
4186
3720
|
import { generateKeyPairSync } from "crypto";
|
|
4187
|
-
import { homedir as
|
|
4188
|
-
import { dirname
|
|
3721
|
+
import { homedir as homedir6 } from "os";
|
|
3722
|
+
import { dirname, resolve as resolve2 } from "path";
|
|
4189
3723
|
function resolveKeyPath(p2) {
|
|
4190
|
-
return
|
|
3724
|
+
return resolve2(p2.replace(/^~/, homedir6()));
|
|
4191
3725
|
}
|
|
4192
3726
|
function buildSshEd25519Line(rawPub) {
|
|
4193
3727
|
const keyTypeStr = "ssh-ed25519";
|
|
@@ -4201,9 +3735,9 @@ function buildSshEd25519Line(rawPub) {
|
|
|
4201
3735
|
function readPublicKey(keyPath) {
|
|
4202
3736
|
const pubPath = `${keyPath}.pub`;
|
|
4203
3737
|
if (existsSync7(pubPath)) {
|
|
4204
|
-
return
|
|
3738
|
+
return readFileSync6(pubPath, "utf-8").trim();
|
|
4205
3739
|
}
|
|
4206
|
-
const keyContent =
|
|
3740
|
+
const keyContent = readFileSync6(keyPath, "utf-8");
|
|
4207
3741
|
const privateKey = loadEd25519PrivateKey(keyContent);
|
|
4208
3742
|
const jwk = privateKey.export({ format: "jwk" });
|
|
4209
3743
|
const pubBytes = Buffer4.from(jwk.x, "base64url");
|
|
@@ -4211,17 +3745,17 @@ function readPublicKey(keyPath) {
|
|
|
4211
3745
|
}
|
|
4212
3746
|
function generateAndSaveKey(keyPath) {
|
|
4213
3747
|
const resolved = resolveKeyPath(keyPath);
|
|
4214
|
-
const dir =
|
|
3748
|
+
const dir = dirname(resolved);
|
|
4215
3749
|
if (!existsSync7(dir)) {
|
|
4216
|
-
|
|
3750
|
+
mkdirSync(dir, { recursive: true });
|
|
4217
3751
|
}
|
|
4218
3752
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
4219
3753
|
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
4220
|
-
|
|
3754
|
+
writeFileSync2(resolved, privatePem, { mode: 384 });
|
|
4221
3755
|
const jwk = publicKey.export({ format: "jwk" });
|
|
4222
3756
|
const pubBytes = Buffer4.from(jwk.x, "base64url");
|
|
4223
3757
|
const pubKeyStr = buildSshEd25519Line(pubBytes);
|
|
4224
|
-
|
|
3758
|
+
writeFileSync2(`${resolved}.pub`, `${pubKeyStr}
|
|
4225
3759
|
`, { mode: 420 });
|
|
4226
3760
|
return pubKeyStr;
|
|
4227
3761
|
}
|
|
@@ -4237,15 +3771,15 @@ function generateKeyPairInMemory() {
|
|
|
4237
3771
|
}
|
|
4238
3772
|
|
|
4239
3773
|
// src/lib/llm-bridge.ts
|
|
4240
|
-
import { execFileSync as
|
|
4241
|
-
import { existsSync as existsSync8, readFileSync as
|
|
4242
|
-
import { homedir as
|
|
4243
|
-
import { dirname as
|
|
3774
|
+
import { execFileSync as execFileSync5 } from "child_process";
|
|
3775
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
|
|
3776
|
+
import { homedir as homedir7 } from "os";
|
|
3777
|
+
import { dirname as dirname2, join as join5 } from "path";
|
|
4244
3778
|
var PLIST_LABEL_PREFIX = "eco.hofmann.apes.bridge";
|
|
4245
|
-
function readLitellmEnv(envPath = join5(
|
|
3779
|
+
function readLitellmEnv(envPath = join5(homedir7(), "litellm", ".env")) {
|
|
4246
3780
|
if (!existsSync8(envPath)) return null;
|
|
4247
3781
|
try {
|
|
4248
|
-
const text =
|
|
3782
|
+
const text = readFileSync7(envPath, "utf8");
|
|
4249
3783
|
const out = {};
|
|
4250
3784
|
for (const line of text.split("\n")) {
|
|
4251
3785
|
const trimmed = line.trim();
|
|
@@ -4281,12 +3815,12 @@ function captureHostBinDirs() {
|
|
|
4281
3815
|
for (const bin of ["node", "openape-chat-bridge", "apes"]) {
|
|
4282
3816
|
let resolved;
|
|
4283
3817
|
try {
|
|
4284
|
-
resolved =
|
|
3818
|
+
resolved = execFileSync5("/usr/bin/which", [bin], { encoding: "utf8" }).trim();
|
|
4285
3819
|
} catch {
|
|
4286
3820
|
const installCmd = bin === "openape-chat-bridge" ? "npm i -g @openape/chat-bridge" : bin === "apes" ? "npm i -g @openape/apes" : "install Node.js (e.g. brew install node)";
|
|
4287
3821
|
throw new Error(`'${bin}' not found on host PATH. ${installCmd} before spawning agents \u2014 the bridge runtime resolves these at spawn time and bakes the dir into the agent's launchd plist.`);
|
|
4288
3822
|
}
|
|
4289
|
-
const dir =
|
|
3823
|
+
const dir = dirname2(resolved);
|
|
4290
3824
|
if (!seen.has(dir)) {
|
|
4291
3825
|
seen.add(dir);
|
|
4292
3826
|
dirs.push(dir);
|
|
@@ -4532,10 +4066,10 @@ and try again.`
|
|
|
4532
4066
|
bridge,
|
|
4533
4067
|
troop
|
|
4534
4068
|
});
|
|
4535
|
-
|
|
4069
|
+
writeFileSync3(scriptPath, script, { mode: 448 });
|
|
4536
4070
|
consola23.start("Running privileged setup as root via `apes run --as root --wait`\u2026");
|
|
4537
4071
|
consola23.info("You will be asked to approve the as=root grant in your DDISA inbox; this command blocks until you do.");
|
|
4538
|
-
|
|
4072
|
+
execFileSync6(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], { stdio: "inherit" });
|
|
4539
4073
|
consola23.success(`Agent ${name} spawned.`);
|
|
4540
4074
|
consola23.info(`\u{1F517} Troop: https://troop.openape.ai/agents/${name}`);
|
|
4541
4075
|
if (args.bridge) {
|
|
@@ -4574,18 +4108,18 @@ async function resolveClaudeToken(opts) {
|
|
|
4574
4108
|
}
|
|
4575
4109
|
|
|
4576
4110
|
// src/commands/agents/sync.ts
|
|
4577
|
-
import { chownSync, existsSync as existsSync9, mkdirSync as
|
|
4578
|
-
import { homedir as
|
|
4111
|
+
import { chownSync, existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as readFileSync8, statSync, writeFileSync as writeFileSync4 } from "fs";
|
|
4112
|
+
import { homedir as homedir8 } from "os";
|
|
4579
4113
|
import { join as join7 } from "path";
|
|
4580
4114
|
import { defineCommand as defineCommand27 } from "citty";
|
|
4581
4115
|
import consola24 from "consola";
|
|
4582
4116
|
|
|
4583
4117
|
// src/lib/macos-host.ts
|
|
4584
|
-
import { execFileSync as
|
|
4118
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
4585
4119
|
import { hostname as hostname3 } from "os";
|
|
4586
4120
|
function getHostId() {
|
|
4587
4121
|
try {
|
|
4588
|
-
const output =
|
|
4122
|
+
const output = execFileSync7(
|
|
4589
4123
|
"/usr/sbin/ioreg",
|
|
4590
4124
|
["-d2", "-c", "IOPlatformExpertDevice"],
|
|
4591
4125
|
{ encoding: "utf8", timeout: 2e3 }
|
|
@@ -4605,15 +4139,15 @@ function getHostname() {
|
|
|
4605
4139
|
}
|
|
4606
4140
|
|
|
4607
4141
|
// src/commands/agents/sync.ts
|
|
4608
|
-
var AUTH_PATH3 = join7(
|
|
4609
|
-
var TASK_CACHE_DIR2 = join7(
|
|
4142
|
+
var AUTH_PATH3 = join7(homedir8(), ".config", "apes", "auth.json");
|
|
4143
|
+
var TASK_CACHE_DIR2 = join7(homedir8(), ".openape", "agent", "tasks");
|
|
4610
4144
|
function readAuthJson() {
|
|
4611
4145
|
if (!existsSync9(AUTH_PATH3)) {
|
|
4612
4146
|
throw new CliError(
|
|
4613
4147
|
`No agent auth found at ${AUTH_PATH3}. Run \`apes agents spawn <name>\` to provision an agent first.`
|
|
4614
4148
|
);
|
|
4615
4149
|
}
|
|
4616
|
-
const raw =
|
|
4150
|
+
const raw = readFileSync8(AUTH_PATH3, "utf8");
|
|
4617
4151
|
let parsed;
|
|
4618
4152
|
try {
|
|
4619
4153
|
parsed = JSON.parse(raw);
|
|
@@ -4674,7 +4208,7 @@ var syncAgentCommand = defineCommand27({
|
|
|
4674
4208
|
let agentGid = null;
|
|
4675
4209
|
if (process.geteuid?.() === 0) {
|
|
4676
4210
|
try {
|
|
4677
|
-
const homeStat = statSync(
|
|
4211
|
+
const homeStat = statSync(homedir8());
|
|
4678
4212
|
agentUid = homeStat.uid;
|
|
4679
4213
|
agentGid = homeStat.gid;
|
|
4680
4214
|
} catch {
|
|
@@ -4688,23 +4222,23 @@ var syncAgentCommand = defineCommand27({
|
|
|
4688
4222
|
}
|
|
4689
4223
|
}
|
|
4690
4224
|
}
|
|
4691
|
-
const agentDir = join7(
|
|
4692
|
-
|
|
4693
|
-
chownToAgent(join7(
|
|
4225
|
+
const agentDir = join7(homedir8(), ".openape", "agent");
|
|
4226
|
+
mkdirSync2(agentDir, { recursive: true });
|
|
4227
|
+
chownToAgent(join7(homedir8(), ".openape"));
|
|
4694
4228
|
chownToAgent(agentDir);
|
|
4695
4229
|
const agentJsonPath = join7(agentDir, "agent.json");
|
|
4696
|
-
|
|
4230
|
+
writeFileSync4(
|
|
4697
4231
|
agentJsonPath,
|
|
4698
4232
|
`${JSON.stringify({ systemPrompt }, null, 2)}
|
|
4699
4233
|
`,
|
|
4700
4234
|
{ mode: 384 }
|
|
4701
4235
|
);
|
|
4702
4236
|
chownToAgent(agentJsonPath);
|
|
4703
|
-
|
|
4237
|
+
mkdirSync2(TASK_CACHE_DIR2, { recursive: true });
|
|
4704
4238
|
chownToAgent(TASK_CACHE_DIR2);
|
|
4705
4239
|
for (const task of tasks) {
|
|
4706
4240
|
const path2 = join7(TASK_CACHE_DIR2, `${task.taskId}.json`);
|
|
4707
|
-
|
|
4241
|
+
writeFileSync4(path2, `${JSON.stringify(task, null, 2)}
|
|
4708
4242
|
`, { mode: 384 });
|
|
4709
4243
|
chownToAgent(path2);
|
|
4710
4244
|
}
|
|
@@ -4734,19 +4268,19 @@ var agentsCommand = defineCommand28({
|
|
|
4734
4268
|
import { defineCommand as defineCommand37 } from "citty";
|
|
4735
4269
|
|
|
4736
4270
|
// src/commands/nest/authorize.ts
|
|
4737
|
-
import { execFileSync as
|
|
4738
|
-
import { existsSync as existsSync11, readFileSync as
|
|
4271
|
+
import { execFileSync as execFileSync8 } from "child_process";
|
|
4272
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
|
|
4739
4273
|
import { join as join9 } from "path";
|
|
4740
4274
|
import { defineCommand as defineCommand30 } from "citty";
|
|
4741
4275
|
import consola26 from "consola";
|
|
4742
4276
|
|
|
4743
4277
|
// src/commands/nest/enroll.ts
|
|
4744
|
-
import { hostname as hostname4, homedir as
|
|
4745
|
-
import { existsSync as existsSync10, mkdirSync as
|
|
4278
|
+
import { hostname as hostname4, homedir as homedir9 } from "os";
|
|
4279
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5, chmodSync } from "fs";
|
|
4746
4280
|
import { join as join8 } from "path";
|
|
4747
4281
|
import { defineCommand as defineCommand29 } from "citty";
|
|
4748
4282
|
import consola25 from "consola";
|
|
4749
|
-
var NEST_DATA_DIR = join8(
|
|
4283
|
+
var NEST_DATA_DIR = join8(homedir9(), ".openape", "nest");
|
|
4750
4284
|
function nestAgentName() {
|
|
4751
4285
|
const raw = hostname4().toLowerCase();
|
|
4752
4286
|
const head = raw.split(".")[0] ?? raw;
|
|
@@ -4785,13 +4319,13 @@ var enrollNestCommand = defineCommand29({
|
|
|
4785
4319
|
}
|
|
4786
4320
|
const sshDir = join8(NEST_DATA_DIR, ".ssh");
|
|
4787
4321
|
const configDir = join8(NEST_DATA_DIR, ".config", "apes");
|
|
4788
|
-
|
|
4789
|
-
|
|
4322
|
+
mkdirSync3(sshDir, { recursive: true });
|
|
4323
|
+
mkdirSync3(configDir, { recursive: true });
|
|
4790
4324
|
consola25.start(`Generating keypair for ${name}\u2026`);
|
|
4791
4325
|
const { privatePem, publicSshLine } = generateKeyPairInMemory();
|
|
4792
|
-
|
|
4326
|
+
writeFileSync5(join8(sshDir, "id_ed25519"), `${privatePem.trimEnd()}
|
|
4793
4327
|
`, { mode: 384 });
|
|
4794
|
-
|
|
4328
|
+
writeFileSync5(join8(sshDir, "id_ed25519.pub"), `${publicSshLine}
|
|
4795
4329
|
`, { mode: 420 });
|
|
4796
4330
|
chmodSync(sshDir, 448);
|
|
4797
4331
|
consola25.start(`Registering nest at ${idp}\u2026`);
|
|
@@ -4811,7 +4345,7 @@ var enrollNestCommand = defineCommand29({
|
|
|
4811
4345
|
keyPath: join8(sshDir, "id_ed25519"),
|
|
4812
4346
|
ownerEmail: ownerAuth.email
|
|
4813
4347
|
});
|
|
4814
|
-
|
|
4348
|
+
writeFileSync5(authPath, authJson, { mode: 384 });
|
|
4815
4349
|
chmodSync(configDir, 448);
|
|
4816
4350
|
consola25.success(`Nest enrolled \u2014 auth.json at ${authPath}`);
|
|
4817
4351
|
consola25.info("");
|
|
@@ -4873,7 +4407,7 @@ var authorizeNestCommand = defineCommand30({
|
|
|
4873
4407
|
if (!existsSync11(nestAuthPath)) {
|
|
4874
4408
|
throw new CliError("Nest not enrolled. Run `apes nest enroll` first.");
|
|
4875
4409
|
}
|
|
4876
|
-
const nestAuth = JSON.parse(
|
|
4410
|
+
const nestAuth = JSON.parse(readFileSync9(nestAuthPath, "utf8"));
|
|
4877
4411
|
if (!nestAuth.email) throw new CliError(`${nestAuthPath} has no email`);
|
|
4878
4412
|
const allow = args.allow ?? DEFAULT_ALLOW_PATTERNS.join(",");
|
|
4879
4413
|
consola26.info(`Configuring YOLO-policy on ${nestAuth.email} via \`apes yolo set\`\u2026`);
|
|
@@ -4890,7 +4424,7 @@ var authorizeNestCommand = defineCommand30({
|
|
|
4890
4424
|
cmdArgs.push("--expires-in", args["expires-in"]);
|
|
4891
4425
|
}
|
|
4892
4426
|
try {
|
|
4893
|
-
|
|
4427
|
+
execFileSync8("apes", cmdArgs, { stdio: "inherit" });
|
|
4894
4428
|
} catch (err) {
|
|
4895
4429
|
throw new CliError(err instanceof Error ? err.message : String(err));
|
|
4896
4430
|
}
|
|
@@ -5035,10 +4569,10 @@ var destroyNestCommand = defineCommand31({
|
|
|
5035
4569
|
});
|
|
5036
4570
|
|
|
5037
4571
|
// src/commands/nest/install.ts
|
|
5038
|
-
import { execFileSync as
|
|
5039
|
-
import { existsSync as existsSync12, mkdirSync as
|
|
5040
|
-
import { homedir as
|
|
5041
|
-
import { dirname as
|
|
4572
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
4573
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
4574
|
+
import { homedir as homedir10, userInfo as userInfo2 } from "os";
|
|
4575
|
+
import { dirname as dirname3, join as join10 } from "path";
|
|
5042
4576
|
import { defineCommand as defineCommand32 } from "citty";
|
|
5043
4577
|
import consola29 from "consola";
|
|
5044
4578
|
|
|
@@ -5107,7 +4641,7 @@ resource_chain = ["agents:name={name}", "allowlist:email={peer_email}"]
|
|
|
5107
4641
|
// src/commands/nest/install.ts
|
|
5108
4642
|
var PLIST_LABEL = "ai.openape.nest";
|
|
5109
4643
|
function plistPath() {
|
|
5110
|
-
return join10(
|
|
4644
|
+
return join10(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
5111
4645
|
}
|
|
5112
4646
|
function escape2(s) {
|
|
5113
4647
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -5148,34 +4682,34 @@ function buildPlist(args) {
|
|
|
5148
4682
|
`;
|
|
5149
4683
|
}
|
|
5150
4684
|
function installAdapter2() {
|
|
5151
|
-
const target = join10(
|
|
5152
|
-
|
|
4685
|
+
const target = join10(homedir10(), ".openape", "shapes", "adapters", "apes-agents.toml");
|
|
4686
|
+
mkdirSync4(dirname3(target), { recursive: true });
|
|
5153
4687
|
let existing = "";
|
|
5154
4688
|
try {
|
|
5155
|
-
existing =
|
|
4689
|
+
existing = readFileSync10(target, "utf8");
|
|
5156
4690
|
} catch {
|
|
5157
4691
|
}
|
|
5158
4692
|
if (existing === APES_AGENTS_ADAPTER_TOML) return false;
|
|
5159
|
-
|
|
4693
|
+
writeFileSync6(target, APES_AGENTS_ADAPTER_TOML, { mode: 420 });
|
|
5160
4694
|
consola29.success(`Wrote shapes adapter ${target}`);
|
|
5161
4695
|
return true;
|
|
5162
4696
|
}
|
|
5163
4697
|
function writeBridgeModelDefault(model) {
|
|
5164
|
-
const envDir = join10(
|
|
4698
|
+
const envDir = join10(homedir10(), "litellm");
|
|
5165
4699
|
const envFile = join10(envDir, ".env");
|
|
5166
|
-
|
|
4700
|
+
mkdirSync4(envDir, { recursive: true });
|
|
5167
4701
|
let lines = [];
|
|
5168
4702
|
if (existsSync12(envFile)) {
|
|
5169
|
-
lines =
|
|
4703
|
+
lines = readFileSync10(envFile, "utf8").split("\n").filter((l) => !l.startsWith("APE_CHAT_BRIDGE_MODEL="));
|
|
5170
4704
|
}
|
|
5171
4705
|
lines.push(`APE_CHAT_BRIDGE_MODEL=${model}`);
|
|
5172
4706
|
while (lines.length > 0 && lines.at(-1).trim() === "") lines.pop();
|
|
5173
|
-
|
|
4707
|
+
writeFileSync6(envFile, `${lines.join("\n")}
|
|
5174
4708
|
`, { mode: 384 });
|
|
5175
4709
|
}
|
|
5176
4710
|
function findBinary(name) {
|
|
5177
4711
|
for (const dir of [
|
|
5178
|
-
join10(
|
|
4712
|
+
join10(homedir10(), ".bun", "bin"),
|
|
5179
4713
|
"/opt/homebrew/bin",
|
|
5180
4714
|
"/usr/local/bin",
|
|
5181
4715
|
"/usr/bin"
|
|
@@ -5201,7 +4735,7 @@ var installNestCommand = defineCommand32({
|
|
|
5201
4735
|
}
|
|
5202
4736
|
},
|
|
5203
4737
|
async run({ args }) {
|
|
5204
|
-
const homeDir =
|
|
4738
|
+
const homeDir = homedir10();
|
|
5205
4739
|
const port = Number(args.port ?? 9091);
|
|
5206
4740
|
if (!Number.isInteger(port) || port < 1024 || port > 65535) {
|
|
5207
4741
|
throw new Error(`invalid port ${port}`);
|
|
@@ -5217,26 +4751,26 @@ var installNestCommand = defineCommand32({
|
|
|
5217
4751
|
consola29.success(`Default bridge model set to ${args["bridge-model"]} (in ~/litellm/.env)`);
|
|
5218
4752
|
}
|
|
5219
4753
|
installAdapter2();
|
|
5220
|
-
|
|
5221
|
-
|
|
4754
|
+
mkdirSync4(join10(homeDir, "Library", "LaunchAgents"), { recursive: true });
|
|
4755
|
+
mkdirSync4(NEST_DATA_DIR, { recursive: true });
|
|
5222
4756
|
const desired = buildPlist({ nestBin, apesBin, userHome: homeDir, nestHome: NEST_DATA_DIR, port });
|
|
5223
4757
|
let existing = "";
|
|
5224
4758
|
try {
|
|
5225
|
-
existing =
|
|
4759
|
+
existing = readFileSync10(plistPath(), "utf8");
|
|
5226
4760
|
} catch {
|
|
5227
4761
|
}
|
|
5228
4762
|
if (existing !== desired) {
|
|
5229
|
-
|
|
4763
|
+
writeFileSync6(plistPath(), desired, { mode: 420 });
|
|
5230
4764
|
consola29.success("Wrote launchd plist");
|
|
5231
4765
|
} else {
|
|
5232
4766
|
consola29.info("plist already up to date");
|
|
5233
4767
|
}
|
|
5234
4768
|
const uid = userInfo2().uid;
|
|
5235
4769
|
try {
|
|
5236
|
-
|
|
4770
|
+
execFileSync9("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
|
|
5237
4771
|
} catch {
|
|
5238
4772
|
}
|
|
5239
|
-
|
|
4773
|
+
execFileSync9("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
|
|
5240
4774
|
consola29.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
|
|
5241
4775
|
consola29.info("");
|
|
5242
4776
|
consola29.info("Next steps for zero-prompt spawn \u2014 both one-time:");
|
|
@@ -5399,9 +4933,9 @@ var statusNestCommand = defineCommand35({
|
|
|
5399
4933
|
});
|
|
5400
4934
|
|
|
5401
4935
|
// src/commands/nest/uninstall.ts
|
|
5402
|
-
import { execFileSync as
|
|
4936
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
5403
4937
|
import { existsSync as existsSync13, unlinkSync } from "fs";
|
|
5404
|
-
import { homedir as
|
|
4938
|
+
import { homedir as homedir11, userInfo as userInfo3 } from "os";
|
|
5405
4939
|
import { join as join11 } from "path";
|
|
5406
4940
|
import { defineCommand as defineCommand36 } from "citty";
|
|
5407
4941
|
import consola33 from "consola";
|
|
@@ -5413,9 +4947,9 @@ var uninstallNestCommand = defineCommand36({
|
|
|
5413
4947
|
},
|
|
5414
4948
|
async run() {
|
|
5415
4949
|
const uid = userInfo3().uid;
|
|
5416
|
-
const path2 = join11(
|
|
4950
|
+
const path2 = join11(homedir11(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
|
|
5417
4951
|
try {
|
|
5418
|
-
|
|
4952
|
+
execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
|
|
5419
4953
|
consola33.success("Nest daemon stopped");
|
|
5420
4954
|
} catch {
|
|
5421
4955
|
consola33.info("Nest daemon was not loaded");
|
|
@@ -5970,7 +5504,7 @@ var adapterCommand = defineCommand42({
|
|
|
5970
5504
|
});
|
|
5971
5505
|
|
|
5972
5506
|
// src/commands/run.ts
|
|
5973
|
-
import { execFileSync as
|
|
5507
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
5974
5508
|
import { hostname as hostname6 } from "os";
|
|
5975
5509
|
import { basename } from "path";
|
|
5976
5510
|
import { defineCommand as defineCommand43 } from "citty";
|
|
@@ -6248,7 +5782,7 @@ function execShellCommand(command) {
|
|
|
6248
5782
|
throw new CliError("No command to execute");
|
|
6249
5783
|
try {
|
|
6250
5784
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
6251
|
-
|
|
5785
|
+
execFileSync11(command[0], command.slice(1), {
|
|
6252
5786
|
stdio: "inherit",
|
|
6253
5787
|
env: inheritedEnv
|
|
6254
5788
|
});
|
|
@@ -6400,7 +5934,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
6400
5934
|
consola38.info(`Executing: ${command.join(" ")}`);
|
|
6401
5935
|
try {
|
|
6402
5936
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
6403
|
-
|
|
5937
|
+
execFileSync11(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
|
|
6404
5938
|
stdio: "inherit",
|
|
6405
5939
|
env: inheritedEnv
|
|
6406
5940
|
});
|
|
@@ -6450,10 +5984,10 @@ note = "VPC-internal hostname suffix"
|
|
|
6450
5984
|
|
|
6451
5985
|
// src/proxy/local-proxy.ts
|
|
6452
5986
|
import { spawn } from "child_process";
|
|
6453
|
-
import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as
|
|
5987
|
+
import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
|
|
6454
5988
|
import { createRequire } from "module";
|
|
6455
5989
|
import { tmpdir as tmpdir3 } from "os";
|
|
6456
|
-
import { dirname as
|
|
5990
|
+
import { dirname as dirname4, join as join12, resolve as resolve3 } from "path";
|
|
6457
5991
|
var require2 = createRequire(import.meta.url);
|
|
6458
5992
|
function findProxyBin() {
|
|
6459
5993
|
const pkgPath = require2.resolve("@openape/proxy/package.json");
|
|
@@ -6462,12 +5996,12 @@ function findProxyBin() {
|
|
|
6462
5996
|
if (!binRel) {
|
|
6463
5997
|
throw new Error("@openape/proxy is missing the openape-proxy bin entry");
|
|
6464
5998
|
}
|
|
6465
|
-
return
|
|
5999
|
+
return resolve3(dirname4(pkgPath), binRel);
|
|
6466
6000
|
}
|
|
6467
6001
|
async function startEphemeralProxy(configToml) {
|
|
6468
6002
|
const tmpDir = mkdtempSync3(join12(tmpdir3(), "openape-proxy-"));
|
|
6469
6003
|
const configPath = join12(tmpDir, "config.toml");
|
|
6470
|
-
|
|
6004
|
+
writeFileSync7(configPath, configToml, { mode: 384 });
|
|
6471
6005
|
const binPath = findProxyBin();
|
|
6472
6006
|
const child = spawn(process.execPath, [binPath, "-c", configPath], {
|
|
6473
6007
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -6902,15 +6436,15 @@ var mcpCommand = defineCommand49({
|
|
|
6902
6436
|
if (transport !== "stdio" && transport !== "sse") {
|
|
6903
6437
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
6904
6438
|
}
|
|
6905
|
-
const { startMcpServer } = await import("./server-
|
|
6439
|
+
const { startMcpServer } = await import("./server-F3ALNNYS.js");
|
|
6906
6440
|
await startMcpServer(transport, port);
|
|
6907
6441
|
}
|
|
6908
6442
|
});
|
|
6909
6443
|
|
|
6910
6444
|
// src/commands/init/index.ts
|
|
6911
|
-
import { existsSync as existsSync14, copyFileSync, writeFileSync as
|
|
6445
|
+
import { existsSync as existsSync14, copyFileSync, writeFileSync as writeFileSync8 } from "fs";
|
|
6912
6446
|
import { randomBytes } from "crypto";
|
|
6913
|
-
import { execFileSync as
|
|
6447
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
6914
6448
|
import { join as join13 } from "path";
|
|
6915
6449
|
import { defineCommand as defineCommand50 } from "citty";
|
|
6916
6450
|
import consola42 from "consola";
|
|
@@ -6922,11 +6456,11 @@ async function downloadTemplate(repo, targetDir) {
|
|
|
6922
6456
|
function installDeps(dir) {
|
|
6923
6457
|
const hasLockFile = (name) => existsSync14(join13(dir, name));
|
|
6924
6458
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
6925
|
-
|
|
6459
|
+
execFileSync12("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
6926
6460
|
} else if (hasLockFile("bun.lockb")) {
|
|
6927
|
-
|
|
6461
|
+
execFileSync12("bun", ["install"], { cwd: dir, stdio: "inherit" });
|
|
6928
6462
|
} else {
|
|
6929
|
-
|
|
6463
|
+
execFileSync12("npm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
6930
6464
|
}
|
|
6931
6465
|
}
|
|
6932
6466
|
async function promptChoice(message, choices) {
|
|
@@ -7042,7 +6576,7 @@ async function initIdP(targetDir) {
|
|
|
7042
6576
|
`NUXT_OPENAPE_RP_ID=${domain}`,
|
|
7043
6577
|
`NUXT_OPENAPE_RP_ORIGIN=${origin}`
|
|
7044
6578
|
].join("\n");
|
|
7045
|
-
|
|
6579
|
+
writeFileSync8(join13(dir, ".env"), `${envContent}
|
|
7046
6580
|
`, { mode: 384 });
|
|
7047
6581
|
consola42.success(".env created");
|
|
7048
6582
|
console.log("");
|
|
@@ -7063,7 +6597,7 @@ async function initIdP(targetDir) {
|
|
|
7063
6597
|
|
|
7064
6598
|
// src/commands/enroll.ts
|
|
7065
6599
|
import { Buffer as Buffer5 } from "buffer";
|
|
7066
|
-
import { existsSync as existsSync15, readFileSync as
|
|
6600
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
|
|
7067
6601
|
import { execFile as execFile2 } from "child_process";
|
|
7068
6602
|
import { sign as sign2 } from "crypto";
|
|
7069
6603
|
import { defineCommand as defineCommand51 } from "citty";
|
|
@@ -7079,7 +6613,7 @@ function openBrowser2(url) {
|
|
|
7079
6613
|
}
|
|
7080
6614
|
async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
7081
6615
|
const resolvedKey = resolveKeyPath(keyPath);
|
|
7082
|
-
const keyContent =
|
|
6616
|
+
const keyContent = readFileSync11(resolvedKey, "utf-8");
|
|
7083
6617
|
const privateKey = loadEd25519PrivateKey(keyContent);
|
|
7084
6618
|
const challengeUrl = await getAgentChallengeEndpoint(idp);
|
|
7085
6619
|
const authenticateUrl = await getAgentAuthenticateEndpoint(idp);
|
|
@@ -7106,7 +6640,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
7106
6640
|
}
|
|
7107
6641
|
} catch {
|
|
7108
6642
|
}
|
|
7109
|
-
await new Promise((
|
|
6643
|
+
await new Promise((resolve4) => setTimeout(resolve4, POLL_INTERVAL));
|
|
7110
6644
|
}
|
|
7111
6645
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
7112
6646
|
}
|
|
@@ -7191,7 +6725,7 @@ var enrollCommand = defineCommand51({
|
|
|
7191
6725
|
});
|
|
7192
6726
|
|
|
7193
6727
|
// src/commands/register-user.ts
|
|
7194
|
-
import { existsSync as existsSync16, readFileSync as
|
|
6728
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
|
|
7195
6729
|
import { defineCommand as defineCommand52 } from "citty";
|
|
7196
6730
|
import consola44 from "consola";
|
|
7197
6731
|
var registerUserCommand = defineCommand52({
|
|
@@ -7231,7 +6765,7 @@ var registerUserCommand = defineCommand52({
|
|
|
7231
6765
|
}
|
|
7232
6766
|
let publicKey = args.key;
|
|
7233
6767
|
if (existsSync16(args.key)) {
|
|
7234
|
-
publicKey =
|
|
6768
|
+
publicKey = readFileSync12(args.key, "utf-8").trim();
|
|
7235
6769
|
}
|
|
7236
6770
|
if (!publicKey.startsWith("ssh-ed25519 ")) {
|
|
7237
6771
|
throw new CliError("Public key must be in ssh-ed25519 format.");
|
|
@@ -7540,7 +7074,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
7540
7074
|
}
|
|
7541
7075
|
}
|
|
7542
7076
|
async function runHealth(args) {
|
|
7543
|
-
const version = true ? "1.
|
|
7077
|
+
const version = true ? "1.11.0" : "0.0.0";
|
|
7544
7078
|
const auth = loadAuth();
|
|
7545
7079
|
if (!auth) {
|
|
7546
7080
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -7733,26 +7267,26 @@ var workflowsCommand = defineCommand60({
|
|
|
7733
7267
|
});
|
|
7734
7268
|
|
|
7735
7269
|
// src/version-check.ts
|
|
7736
|
-
import { existsSync as existsSync17, mkdirSync as
|
|
7737
|
-
import { homedir as
|
|
7270
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
|
|
7271
|
+
import { homedir as homedir12 } from "os";
|
|
7738
7272
|
import { join as join14 } from "path";
|
|
7739
7273
|
import consola50 from "consola";
|
|
7740
7274
|
var PACKAGE_NAME = "@openape/apes";
|
|
7741
7275
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
7742
|
-
var CACHE_FILE = join14(
|
|
7276
|
+
var CACHE_FILE = join14(homedir12(), ".config", "apes", ".version-check.json");
|
|
7743
7277
|
function readCache() {
|
|
7744
7278
|
if (!existsSync17(CACHE_FILE)) return null;
|
|
7745
7279
|
try {
|
|
7746
|
-
return JSON.parse(
|
|
7280
|
+
return JSON.parse(readFileSync13(CACHE_FILE, "utf-8"));
|
|
7747
7281
|
} catch {
|
|
7748
7282
|
return null;
|
|
7749
7283
|
}
|
|
7750
7284
|
}
|
|
7751
7285
|
function writeCache(entry) {
|
|
7752
7286
|
try {
|
|
7753
|
-
const dir = join14(
|
|
7754
|
-
if (!existsSync17(dir))
|
|
7755
|
-
|
|
7287
|
+
const dir = join14(homedir12(), ".config", "apes");
|
|
7288
|
+
if (!existsSync17(dir)) mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
7289
|
+
writeFileSync9(CACHE_FILE, JSON.stringify(entry), { mode: 384 });
|
|
7756
7290
|
} catch {
|
|
7757
7291
|
}
|
|
7758
7292
|
}
|
|
@@ -7813,10 +7347,10 @@ if (shellRewrite) {
|
|
|
7813
7347
|
if (shellRewrite.action === "rewrite") {
|
|
7814
7348
|
process.argv = shellRewrite.argv;
|
|
7815
7349
|
} else if (shellRewrite.action === "version") {
|
|
7816
|
-
console.log(`ape-shell ${"1.
|
|
7350
|
+
console.log(`ape-shell ${"1.11.0"} (OpenApe DDISA shell wrapper)`);
|
|
7817
7351
|
process.exit(0);
|
|
7818
7352
|
} else if (shellRewrite.action === "help") {
|
|
7819
|
-
console.log(`ape-shell ${"1.
|
|
7353
|
+
console.log(`ape-shell ${"1.11.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
7820
7354
|
console.log("");
|
|
7821
7355
|
console.log("Usage:");
|
|
7822
7356
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -7874,7 +7408,7 @@ var configCommand = defineCommand61({
|
|
|
7874
7408
|
var main = defineCommand61({
|
|
7875
7409
|
meta: {
|
|
7876
7410
|
name: "apes",
|
|
7877
|
-
version: "1.
|
|
7411
|
+
version: "1.11.0",
|
|
7878
7412
|
description: "Unified CLI for OpenApe"
|
|
7879
7413
|
},
|
|
7880
7414
|
subCommands: {
|
|
@@ -7931,7 +7465,7 @@ async function maybeRefreshAuth() {
|
|
|
7931
7465
|
}
|
|
7932
7466
|
}
|
|
7933
7467
|
await maybeRefreshAuth();
|
|
7934
|
-
await maybeWarnStaleVersion("1.
|
|
7468
|
+
await maybeWarnStaleVersion("1.11.0").catch(() => {
|
|
7935
7469
|
});
|
|
7936
7470
|
runMain(main).catch((err) => {
|
|
7937
7471
|
if (err instanceof CliExit) {
|