@openape/apes 1.6.0 → 1.7.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
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
} from "./chunk-OBF7IMQ2.js";
|
|
64
64
|
|
|
65
65
|
// src/cli.ts
|
|
66
|
-
import
|
|
66
|
+
import consola47 from "consola";
|
|
67
67
|
|
|
68
68
|
// src/ape-shell.ts
|
|
69
69
|
import path from "path";
|
|
@@ -93,7 +93,7 @@ function rewriteApeShellArgs(argv, argv0) {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// src/cli.ts
|
|
96
|
-
import { defineCommand as
|
|
96
|
+
import { defineCommand as defineCommand58, runMain } from "citty";
|
|
97
97
|
|
|
98
98
|
// src/commands/auth/login.ts
|
|
99
99
|
import { Buffer as Buffer2 } from "buffer";
|
|
@@ -3921,6 +3921,7 @@ var agentsCommand = defineCommand28({
|
|
|
3921
3921
|
import { defineCommand as defineCommand34 } from "citty";
|
|
3922
3922
|
|
|
3923
3923
|
// src/commands/nest/authorize.ts
|
|
3924
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
3924
3925
|
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
|
|
3925
3926
|
import { join as join9 } from "path";
|
|
3926
3927
|
import { defineCommand as defineCommand30 } from "citty";
|
|
@@ -4009,10 +4010,17 @@ var enrollNestCommand = defineCommand29({
|
|
|
4009
4010
|
|
|
4010
4011
|
// src/commands/nest/authorize.ts
|
|
4011
4012
|
var DEFAULT_ALLOW_PATTERNS = [
|
|
4012
|
-
//
|
|
4013
|
+
// Outer spawn-grant — what the nest's HTTP handler invokes.
|
|
4013
4014
|
"apes agents spawn *",
|
|
4014
4015
|
"apes agents destroy *",
|
|
4015
4016
|
"apes agents sync",
|
|
4017
|
+
// Inner setup.sh-grant — `apes agents spawn` itself shells out to
|
|
4018
|
+
// `apes run --as root --wait -- bash <tempdir>/setup.sh` to do the
|
|
4019
|
+
// dscl/launchctl/heredoc-write work. Path looks like
|
|
4020
|
+
// `bash /var/folders/.../apes-spawn-<name>-XXXX/setup.sh`. The narrow
|
|
4021
|
+
// glob below limits the auto-approval to that exact lifecycle path
|
|
4022
|
+
// — `bash *` would be unsafe.
|
|
4023
|
+
"bash *apes-spawn-*setup.sh",
|
|
4016
4024
|
// Bridge invocation the supervisor uses to keep agent processes
|
|
4017
4025
|
// running. Pattern is intentionally precise — not a generic
|
|
4018
4026
|
// `apes run --as *` wildcard — so a compromised nest can't pivot
|
|
@@ -4022,77 +4030,51 @@ var DEFAULT_ALLOW_PATTERNS = [
|
|
|
4022
4030
|
var authorizeNestCommand = defineCommand30({
|
|
4023
4031
|
meta: {
|
|
4024
4032
|
name: "authorize",
|
|
4025
|
-
description: "Set the YOLO-policy that lets the local nest spawn/destroy without per-call DDISA prompts"
|
|
4033
|
+
description: "Set the YOLO-policy that lets the local nest spawn/destroy without per-call DDISA prompts (wraps `apes yolo set`)"
|
|
4026
4034
|
},
|
|
4027
4035
|
args: {
|
|
4028
4036
|
"allow": {
|
|
4029
4037
|
type: "string",
|
|
4030
4038
|
description: "Override allow_patterns (comma-separated globs). Default: nest-managed agent lifecycle."
|
|
4031
4039
|
},
|
|
4032
|
-
"mode": {
|
|
4033
|
-
type: "string",
|
|
4034
|
-
description: "Policy mode (allow-list | deny-list). Default: allow-list \u2014 auto-approve only matched patterns."
|
|
4035
|
-
},
|
|
4036
4040
|
"expires-in": {
|
|
4037
4041
|
type: "string",
|
|
4038
4042
|
description: "Optional duration like 30d, 6h. Omit for no expiry."
|
|
4039
4043
|
}
|
|
4040
4044
|
},
|
|
4041
4045
|
async run({ args }) {
|
|
4042
|
-
const ownerAuth = loadAuth();
|
|
4043
|
-
if (!ownerAuth?.email || !ownerAuth.access_token) {
|
|
4044
|
-
throw new CliError("Run `apes login <email>` first \u2014 only the nest's owner can set its YOLO-policy.");
|
|
4045
|
-
}
|
|
4046
4046
|
const nestAuthPath = join9(NEST_DATA_DIR, ".config", "apes", "auth.json");
|
|
4047
4047
|
if (!existsSync11(nestAuthPath)) {
|
|
4048
4048
|
throw new CliError("Nest not enrolled. Run `apes nest enroll` first.");
|
|
4049
4049
|
}
|
|
4050
4050
|
const nestAuth = JSON.parse(readFileSync10(nestAuthPath, "utf8"));
|
|
4051
4051
|
if (!nestAuth.email) throw new CliError(`${nestAuthPath} has no email`);
|
|
4052
|
-
const
|
|
4053
|
-
|
|
4054
|
-
const
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
mode,
|
|
4071
|
-
allowPatterns,
|
|
4072
|
-
denyPatterns: [],
|
|
4073
|
-
expiresAt: expiresAt ?? null
|
|
4074
|
-
})
|
|
4075
|
-
});
|
|
4076
|
-
if (!res.ok) {
|
|
4077
|
-
const text = await res.text().catch(() => "");
|
|
4078
|
-
throw new CliError(`PUT /yolo-policy failed (${res.status}): ${text}`);
|
|
4052
|
+
const allow = args.allow ?? DEFAULT_ALLOW_PATTERNS.join(",");
|
|
4053
|
+
consola26.info(`Configuring YOLO-policy on ${nestAuth.email} via \`apes yolo set\`\u2026`);
|
|
4054
|
+
const cmdArgs = [
|
|
4055
|
+
"yolo",
|
|
4056
|
+
"set",
|
|
4057
|
+
nestAuth.email,
|
|
4058
|
+
"--mode",
|
|
4059
|
+
"allow-list",
|
|
4060
|
+
"--allow",
|
|
4061
|
+
allow
|
|
4062
|
+
];
|
|
4063
|
+
if (typeof args["expires-in"] === "string" && args["expires-in"]) {
|
|
4064
|
+
cmdArgs.push("--expires-in", args["expires-in"]);
|
|
4065
|
+
}
|
|
4066
|
+
try {
|
|
4067
|
+
execFileSync9("apes", cmdArgs, { stdio: "inherit" });
|
|
4068
|
+
} catch (err) {
|
|
4069
|
+
throw new CliError(err instanceof Error ? err.message : String(err));
|
|
4079
4070
|
}
|
|
4080
|
-
consola26.success("
|
|
4071
|
+
consola26.success("Nest-driven agent lifecycle is now zero-prompt.");
|
|
4081
4072
|
consola26.info("Test: apes agents spawn <name> via the nest API \u2192 no DDISA prompt.");
|
|
4082
4073
|
}
|
|
4083
4074
|
});
|
|
4084
|
-
function parseExpiresIn(s) {
|
|
4085
|
-
if (!s) return null;
|
|
4086
|
-
const m = s.match(/^(\d+)([hdw])$/);
|
|
4087
|
-
if (!m) throw new CliError(`Invalid --expires-in "${s}" \u2014 expected forms like 30d, 6h, 2w`);
|
|
4088
|
-
const n = Number(m[1]);
|
|
4089
|
-
const unit = m[2];
|
|
4090
|
-
const seconds = unit === "h" ? 3600 : unit === "d" ? 86400 : 7 * 86400;
|
|
4091
|
-
return Math.floor(Date.now() / 1e3) + n * seconds;
|
|
4092
|
-
}
|
|
4093
4075
|
|
|
4094
4076
|
// src/commands/nest/install.ts
|
|
4095
|
-
import { execFileSync as
|
|
4077
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
4096
4078
|
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
4097
4079
|
import { homedir as homedir11, userInfo as userInfo2 } from "os";
|
|
4098
4080
|
import { dirname as dirname3, join as join10 } from "path";
|
|
@@ -4269,10 +4251,10 @@ var installNestCommand = defineCommand31({
|
|
|
4269
4251
|
}
|
|
4270
4252
|
const uid = userInfo2().uid;
|
|
4271
4253
|
try {
|
|
4272
|
-
|
|
4254
|
+
execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
|
|
4273
4255
|
} catch {
|
|
4274
4256
|
}
|
|
4275
|
-
|
|
4257
|
+
execFileSync10("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
|
|
4276
4258
|
consola27.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
|
|
4277
4259
|
consola27.info("");
|
|
4278
4260
|
consola27.info("Next steps for zero-prompt spawn \u2014 both one-time:");
|
|
@@ -4339,7 +4321,7 @@ function humanDuration(sec) {
|
|
|
4339
4321
|
}
|
|
4340
4322
|
|
|
4341
4323
|
// src/commands/nest/uninstall.ts
|
|
4342
|
-
import { execFileSync as
|
|
4324
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
4343
4325
|
import { existsSync as existsSync13, unlinkSync } from "fs";
|
|
4344
4326
|
import { homedir as homedir12, userInfo as userInfo3 } from "os";
|
|
4345
4327
|
import { join as join11 } from "path";
|
|
@@ -4355,7 +4337,7 @@ var uninstallNestCommand = defineCommand33({
|
|
|
4355
4337
|
const uid = userInfo3().uid;
|
|
4356
4338
|
const path2 = join11(homedir12(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
|
|
4357
4339
|
try {
|
|
4358
|
-
|
|
4340
|
+
execFileSync11("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
|
|
4359
4341
|
consola29.success("Nest daemon stopped");
|
|
4360
4342
|
} catch {
|
|
4361
4343
|
consola29.info("Nest daemon was not loaded");
|
|
@@ -4383,16 +4365,211 @@ var nestCommand = defineCommand34({
|
|
|
4383
4365
|
}
|
|
4384
4366
|
});
|
|
4385
4367
|
|
|
4386
|
-
// src/commands/
|
|
4368
|
+
// src/commands/yolo/index.ts
|
|
4369
|
+
import { defineCommand as defineCommand38 } from "citty";
|
|
4370
|
+
|
|
4371
|
+
// src/commands/yolo/clear.ts
|
|
4387
4372
|
import { defineCommand as defineCommand35 } from "citty";
|
|
4388
4373
|
import consola30 from "consola";
|
|
4389
|
-
var
|
|
4374
|
+
var yoloClearCommand = defineCommand35({
|
|
4375
|
+
meta: {
|
|
4376
|
+
name: "clear",
|
|
4377
|
+
description: "Remove the YOLO-policy from a DDISA agent (subsequent grants need human approval)"
|
|
4378
|
+
},
|
|
4379
|
+
args: {
|
|
4380
|
+
email: {
|
|
4381
|
+
type: "positional",
|
|
4382
|
+
description: "Target agent email",
|
|
4383
|
+
required: true
|
|
4384
|
+
}
|
|
4385
|
+
},
|
|
4386
|
+
async run({ args }) {
|
|
4387
|
+
const ownerAuth = loadAuth();
|
|
4388
|
+
if (!ownerAuth?.access_token) {
|
|
4389
|
+
throw new CliError("Run `apes login <email>` first.");
|
|
4390
|
+
}
|
|
4391
|
+
const idp = getIdpUrl();
|
|
4392
|
+
if (!idp) throw new CliError("No IdP configured.");
|
|
4393
|
+
const email = args.email;
|
|
4394
|
+
const url = `${idp}/api/users/${encodeURIComponent(email)}/yolo-policy`;
|
|
4395
|
+
const res = await fetch(url, {
|
|
4396
|
+
method: "DELETE",
|
|
4397
|
+
headers: { Authorization: `Bearer ${ownerAuth.access_token}` }
|
|
4398
|
+
});
|
|
4399
|
+
if (!res.ok && res.status !== 404) {
|
|
4400
|
+
const text = await res.text().catch(() => "");
|
|
4401
|
+
throw new CliError(`DELETE /yolo-policy failed (${res.status}): ${text}`);
|
|
4402
|
+
}
|
|
4403
|
+
consola30.success(`YOLO-policy cleared on ${email}`);
|
|
4404
|
+
}
|
|
4405
|
+
});
|
|
4406
|
+
|
|
4407
|
+
// src/commands/yolo/set.ts
|
|
4408
|
+
import { defineCommand as defineCommand36 } from "citty";
|
|
4409
|
+
import consola31 from "consola";
|
|
4410
|
+
var VALID_MODES = ["allow-list", "deny-list"];
|
|
4411
|
+
var yoloSetCommand = defineCommand36({
|
|
4412
|
+
meta: {
|
|
4413
|
+
name: "set",
|
|
4414
|
+
description: "Write a YOLO-policy on a DDISA agent you own"
|
|
4415
|
+
},
|
|
4416
|
+
args: {
|
|
4417
|
+
"email": {
|
|
4418
|
+
type: "positional",
|
|
4419
|
+
description: "Target agent email (e.g. nest-mac-cb6bf26a+patrick+example_com@id.openape.ai)",
|
|
4420
|
+
required: true
|
|
4421
|
+
},
|
|
4422
|
+
"mode": {
|
|
4423
|
+
type: "string",
|
|
4424
|
+
description: "Policy mode (allow-list | deny-list)"
|
|
4425
|
+
},
|
|
4426
|
+
"allow": {
|
|
4427
|
+
type: "string",
|
|
4428
|
+
description: 'Allow patterns \u2014 comma-separated bash globs (e.g. "apes agents spawn *,apes agents sync")'
|
|
4429
|
+
},
|
|
4430
|
+
"deny": {
|
|
4431
|
+
type: "string",
|
|
4432
|
+
description: "Deny patterns \u2014 comma-separated bash globs"
|
|
4433
|
+
},
|
|
4434
|
+
"deny-risk": {
|
|
4435
|
+
type: "string",
|
|
4436
|
+
description: "Deny grants at this risk level or above (low|medium|high|critical)"
|
|
4437
|
+
},
|
|
4438
|
+
"expires-in": {
|
|
4439
|
+
type: "string",
|
|
4440
|
+
description: "Optional expiry like 30d, 6h, 2w. Omit for no expiry."
|
|
4441
|
+
}
|
|
4442
|
+
},
|
|
4443
|
+
async run({ args }) {
|
|
4444
|
+
const ownerAuth = loadAuth();
|
|
4445
|
+
if (!ownerAuth?.access_token) {
|
|
4446
|
+
throw new CliError("Run `apes login <email>` first.");
|
|
4447
|
+
}
|
|
4448
|
+
const idp = getIdpUrl();
|
|
4449
|
+
if (!idp) throw new CliError("No IdP configured.");
|
|
4450
|
+
const email = args.email;
|
|
4451
|
+
const mode = args.mode ?? "allow-list";
|
|
4452
|
+
if (!VALID_MODES.includes(mode)) {
|
|
4453
|
+
throw new CliError(`mode must be one of: ${VALID_MODES.join(", ")}`);
|
|
4454
|
+
}
|
|
4455
|
+
const allowPatterns = parseList(args.allow);
|
|
4456
|
+
const denyPatterns = parseList(args.deny);
|
|
4457
|
+
const denyRiskThreshold = args["deny-risk"] ?? null;
|
|
4458
|
+
const expiresAt = parseExpiresIn(args["expires-in"]);
|
|
4459
|
+
consola31.info(`Setting YOLO-policy on ${email}`);
|
|
4460
|
+
consola31.info(` mode: ${mode}`);
|
|
4461
|
+
if (allowPatterns.length) consola31.info(` allow_patterns: ${allowPatterns.join(", ")}`);
|
|
4462
|
+
if (denyPatterns.length) consola31.info(` deny_patterns: ${denyPatterns.join(", ")}`);
|
|
4463
|
+
if (denyRiskThreshold) consola31.info(` deny_risk: ${denyRiskThreshold}`);
|
|
4464
|
+
if (expiresAt) consola31.info(` expires_at: ${new Date(expiresAt * 1e3).toISOString()}`);
|
|
4465
|
+
const url = `${idp}/api/users/${encodeURIComponent(email)}/yolo-policy`;
|
|
4466
|
+
const res = await fetch(url, {
|
|
4467
|
+
method: "PUT",
|
|
4468
|
+
headers: {
|
|
4469
|
+
"Authorization": `Bearer ${ownerAuth.access_token}`,
|
|
4470
|
+
"Content-Type": "application/json"
|
|
4471
|
+
},
|
|
4472
|
+
body: JSON.stringify({
|
|
4473
|
+
mode,
|
|
4474
|
+
allowPatterns,
|
|
4475
|
+
denyPatterns,
|
|
4476
|
+
denyRiskThreshold,
|
|
4477
|
+
expiresAt: expiresAt ?? null
|
|
4478
|
+
})
|
|
4479
|
+
});
|
|
4480
|
+
if (!res.ok) {
|
|
4481
|
+
const text = await res.text().catch(() => "");
|
|
4482
|
+
throw new CliError(`PUT /yolo-policy failed (${res.status}): ${text}`);
|
|
4483
|
+
}
|
|
4484
|
+
consola31.success(`YOLO-policy applied to ${email}`);
|
|
4485
|
+
}
|
|
4486
|
+
});
|
|
4487
|
+
function parseList(s) {
|
|
4488
|
+
if (!s) return [];
|
|
4489
|
+
return s.split(",").map((p) => p.trim()).filter(Boolean);
|
|
4490
|
+
}
|
|
4491
|
+
function parseExpiresIn(s) {
|
|
4492
|
+
if (!s) return null;
|
|
4493
|
+
const m = s.match(/^(\d+)([hdw])$/);
|
|
4494
|
+
if (!m) throw new CliError(`Invalid --expires-in "${s}" \u2014 expected forms like 30d, 6h, 2w`);
|
|
4495
|
+
const n = Number(m[1]);
|
|
4496
|
+
const unit = m[2];
|
|
4497
|
+
const seconds = unit === "h" ? 3600 : unit === "d" ? 86400 : 7 * 86400;
|
|
4498
|
+
return Math.floor(Date.now() / 1e3) + n * seconds;
|
|
4499
|
+
}
|
|
4500
|
+
|
|
4501
|
+
// src/commands/yolo/show.ts
|
|
4502
|
+
import { defineCommand as defineCommand37 } from "citty";
|
|
4503
|
+
import consola32 from "consola";
|
|
4504
|
+
var yoloShowCommand = defineCommand37({
|
|
4505
|
+
meta: {
|
|
4506
|
+
name: "show",
|
|
4507
|
+
description: "Print the YOLO-policy currently set on a DDISA agent"
|
|
4508
|
+
},
|
|
4509
|
+
args: {
|
|
4510
|
+
email: {
|
|
4511
|
+
type: "positional",
|
|
4512
|
+
description: "Target agent email",
|
|
4513
|
+
required: true
|
|
4514
|
+
},
|
|
4515
|
+
json: {
|
|
4516
|
+
type: "boolean",
|
|
4517
|
+
description: "JSON output for scripts"
|
|
4518
|
+
}
|
|
4519
|
+
},
|
|
4520
|
+
async run({ args }) {
|
|
4521
|
+
const ownerAuth = loadAuth();
|
|
4522
|
+
if (!ownerAuth?.access_token) {
|
|
4523
|
+
throw new CliError("Run `apes login <email>` first.");
|
|
4524
|
+
}
|
|
4525
|
+
const idp = getIdpUrl();
|
|
4526
|
+
if (!idp) throw new CliError("No IdP configured.");
|
|
4527
|
+
const email = args.email;
|
|
4528
|
+
const url = `${idp}/api/users/${encodeURIComponent(email)}/yolo-policy`;
|
|
4529
|
+
const res = await fetch(url, {
|
|
4530
|
+
headers: { Authorization: `Bearer ${ownerAuth.access_token}` }
|
|
4531
|
+
});
|
|
4532
|
+
if (!res.ok) {
|
|
4533
|
+
const text = await res.text().catch(() => "");
|
|
4534
|
+
throw new CliError(`GET /yolo-policy failed (${res.status}): ${text}`);
|
|
4535
|
+
}
|
|
4536
|
+
const policy = await res.json();
|
|
4537
|
+
if (args.json) {
|
|
4538
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
4539
|
+
return;
|
|
4540
|
+
}
|
|
4541
|
+
consola32.info(`YOLO-policy for ${email}`);
|
|
4542
|
+
consola32.info(` mode: ${policy.mode}`);
|
|
4543
|
+
consola32.info(` allow_patterns: ${policy.allowPatterns.length ? policy.allowPatterns.join(", ") : "(none)"}`);
|
|
4544
|
+
consola32.info(` deny_patterns: ${policy.denyPatterns.length ? policy.denyPatterns.join(", ") : "(none)"}`);
|
|
4545
|
+
consola32.info(` deny_risk: ${policy.denyRiskThreshold ?? "(none)"}`);
|
|
4546
|
+
consola32.info(` expires_at: ${policy.expiresAt ? new Date(policy.expiresAt * 1e3).toISOString() : "(never)"}`);
|
|
4547
|
+
}
|
|
4548
|
+
});
|
|
4549
|
+
|
|
4550
|
+
// src/commands/yolo/index.ts
|
|
4551
|
+
var yoloCommand = defineCommand38({
|
|
4552
|
+
meta: {
|
|
4553
|
+
name: "yolo",
|
|
4554
|
+
description: "Manage YOLO-policies on DDISA agents you own \u2014 auto-approve grant patterns at the IdP layer (allow-list) or block dangerous ones outright (deny-list)."
|
|
4555
|
+
},
|
|
4556
|
+
subCommands: {
|
|
4557
|
+
set: yoloSetCommand,
|
|
4558
|
+
show: yoloShowCommand,
|
|
4559
|
+
clear: yoloClearCommand
|
|
4560
|
+
}
|
|
4561
|
+
});
|
|
4562
|
+
|
|
4563
|
+
// src/commands/adapter/index.ts
|
|
4564
|
+
import { defineCommand as defineCommand39 } from "citty";
|
|
4565
|
+
import consola33 from "consola";
|
|
4566
|
+
var adapterCommand = defineCommand39({
|
|
4390
4567
|
meta: {
|
|
4391
4568
|
name: "adapter",
|
|
4392
4569
|
description: "Manage CLI adapters"
|
|
4393
4570
|
},
|
|
4394
4571
|
subCommands: {
|
|
4395
|
-
list:
|
|
4572
|
+
list: defineCommand39({
|
|
4396
4573
|
meta: {
|
|
4397
4574
|
name: "list",
|
|
4398
4575
|
description: "List available adapters"
|
|
@@ -4423,7 +4600,7 @@ var adapterCommand = defineCommand35({
|
|
|
4423
4600
|
`);
|
|
4424
4601
|
return;
|
|
4425
4602
|
}
|
|
4426
|
-
|
|
4603
|
+
consola33.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
|
|
4427
4604
|
for (const a of index2.adapters) {
|
|
4428
4605
|
const installed = isInstalled(a.id, false) ? " [installed]" : "";
|
|
4429
4606
|
console.log(` ${a.id.padEnd(12)} ${a.name.padEnd(24)} ${a.category}${installed}`);
|
|
@@ -4445,7 +4622,7 @@ var adapterCommand = defineCommand35({
|
|
|
4445
4622
|
return;
|
|
4446
4623
|
}
|
|
4447
4624
|
if (local.length === 0) {
|
|
4448
|
-
|
|
4625
|
+
consola33.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
|
|
4449
4626
|
return;
|
|
4450
4627
|
}
|
|
4451
4628
|
for (const a of local) {
|
|
@@ -4453,7 +4630,7 @@ var adapterCommand = defineCommand35({
|
|
|
4453
4630
|
}
|
|
4454
4631
|
}
|
|
4455
4632
|
}),
|
|
4456
|
-
install:
|
|
4633
|
+
install: defineCommand39({
|
|
4457
4634
|
meta: {
|
|
4458
4635
|
name: "install",
|
|
4459
4636
|
description: "Install an adapter from the registry"
|
|
@@ -4482,24 +4659,24 @@ var adapterCommand = defineCommand35({
|
|
|
4482
4659
|
for (const id of ids) {
|
|
4483
4660
|
const entry = findAdapter(index, id);
|
|
4484
4661
|
if (!entry) {
|
|
4485
|
-
|
|
4662
|
+
consola33.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
|
|
4486
4663
|
continue;
|
|
4487
4664
|
}
|
|
4488
4665
|
const conflicts = findConflictingAdapters(entry.executable, id);
|
|
4489
4666
|
if (conflicts.length > 0) {
|
|
4490
4667
|
for (const c of conflicts) {
|
|
4491
|
-
|
|
4492
|
-
|
|
4668
|
+
consola33.warn(`Conflicting adapter found: ${c.path} (id: ${c.adapterId}, executable: ${c.executable})`);
|
|
4669
|
+
consola33.warn(` Remove it with: apes adapter remove ${c.adapterId}`);
|
|
4493
4670
|
}
|
|
4494
4671
|
}
|
|
4495
4672
|
const result = await installAdapter(entry, { local });
|
|
4496
4673
|
const verb = result.updated ? "Updated" : "Installed";
|
|
4497
|
-
|
|
4498
|
-
|
|
4674
|
+
consola33.success(`${verb} ${result.id} \u2192 ${result.path}`);
|
|
4675
|
+
consola33.info(`Digest: ${result.digest}`);
|
|
4499
4676
|
}
|
|
4500
4677
|
}
|
|
4501
4678
|
}),
|
|
4502
|
-
remove:
|
|
4679
|
+
remove: defineCommand39({
|
|
4503
4680
|
meta: {
|
|
4504
4681
|
name: "remove",
|
|
4505
4682
|
description: "Remove an installed adapter"
|
|
@@ -4522,9 +4699,9 @@ var adapterCommand = defineCommand35({
|
|
|
4522
4699
|
let failed = false;
|
|
4523
4700
|
for (const id of ids) {
|
|
4524
4701
|
if (removeAdapter(id, local)) {
|
|
4525
|
-
|
|
4702
|
+
consola33.success(`Removed adapter: ${id}`);
|
|
4526
4703
|
} else {
|
|
4527
|
-
|
|
4704
|
+
consola33.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
4528
4705
|
failed = true;
|
|
4529
4706
|
}
|
|
4530
4707
|
}
|
|
@@ -4532,7 +4709,7 @@ var adapterCommand = defineCommand35({
|
|
|
4532
4709
|
throw new CliError("Some adapters could not be removed");
|
|
4533
4710
|
}
|
|
4534
4711
|
}),
|
|
4535
|
-
info:
|
|
4712
|
+
info: defineCommand39({
|
|
4536
4713
|
meta: {
|
|
4537
4714
|
name: "info",
|
|
4538
4715
|
description: "Show detailed adapter information"
|
|
@@ -4574,7 +4751,7 @@ var adapterCommand = defineCommand35({
|
|
|
4574
4751
|
}
|
|
4575
4752
|
}
|
|
4576
4753
|
}),
|
|
4577
|
-
search:
|
|
4754
|
+
search: defineCommand39({
|
|
4578
4755
|
meta: {
|
|
4579
4756
|
name: "search",
|
|
4580
4757
|
description: "Search adapters in the registry"
|
|
@@ -4606,7 +4783,7 @@ var adapterCommand = defineCommand35({
|
|
|
4606
4783
|
return;
|
|
4607
4784
|
}
|
|
4608
4785
|
if (results.length === 0) {
|
|
4609
|
-
|
|
4786
|
+
consola33.info(`No adapters matching "${query}"`);
|
|
4610
4787
|
return;
|
|
4611
4788
|
}
|
|
4612
4789
|
for (const a of results) {
|
|
@@ -4615,7 +4792,7 @@ var adapterCommand = defineCommand35({
|
|
|
4615
4792
|
}
|
|
4616
4793
|
}
|
|
4617
4794
|
}),
|
|
4618
|
-
update:
|
|
4795
|
+
update: defineCommand39({
|
|
4619
4796
|
meta: {
|
|
4620
4797
|
name: "update",
|
|
4621
4798
|
description: "Update installed adapters"
|
|
@@ -4641,33 +4818,33 @@ var adapterCommand = defineCommand35({
|
|
|
4641
4818
|
const targetId = args.id ? String(args.id) : void 0;
|
|
4642
4819
|
const targets = targetId ? [targetId] : index.adapters.map((a) => a.id).filter((id) => isInstalled(id, false));
|
|
4643
4820
|
if (targets.length === 0) {
|
|
4644
|
-
|
|
4821
|
+
consola33.info("No adapters installed to update.");
|
|
4645
4822
|
return;
|
|
4646
4823
|
}
|
|
4647
4824
|
for (const id of targets) {
|
|
4648
4825
|
const entry = findAdapter(index, id);
|
|
4649
4826
|
if (!entry) {
|
|
4650
|
-
|
|
4827
|
+
consola33.warn(`${id}: not found in registry, skipping`);
|
|
4651
4828
|
continue;
|
|
4652
4829
|
}
|
|
4653
4830
|
const localDigest = getInstalledDigest(id, false);
|
|
4654
4831
|
if (localDigest === entry.digest) {
|
|
4655
|
-
|
|
4832
|
+
consola33.info(`${id}: already up to date`);
|
|
4656
4833
|
continue;
|
|
4657
4834
|
}
|
|
4658
4835
|
if (localDigest && !args.yes) {
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4836
|
+
consola33.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
|
|
4837
|
+
consola33.info(` Old: ${localDigest}`);
|
|
4838
|
+
consola33.info(` New: ${entry.digest}`);
|
|
4839
|
+
consola33.info(" Use --yes to confirm");
|
|
4663
4840
|
continue;
|
|
4664
4841
|
}
|
|
4665
4842
|
const result = await installAdapter(entry);
|
|
4666
|
-
|
|
4843
|
+
consola33.success(`Updated ${result.id} \u2192 ${result.path}`);
|
|
4667
4844
|
}
|
|
4668
4845
|
}
|
|
4669
4846
|
}),
|
|
4670
|
-
verify:
|
|
4847
|
+
verify: defineCommand39({
|
|
4671
4848
|
meta: {
|
|
4672
4849
|
name: "verify",
|
|
4673
4850
|
description: "Verify installed adapter against registry digest"
|
|
@@ -4700,7 +4877,7 @@ var adapterCommand = defineCommand35({
|
|
|
4700
4877
|
if (!localDigest)
|
|
4701
4878
|
throw new Error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
4702
4879
|
if (localDigest === entry.digest) {
|
|
4703
|
-
|
|
4880
|
+
consola33.success(`${id}: digest matches registry`);
|
|
4704
4881
|
} else {
|
|
4705
4882
|
console.log(` Local: ${localDigest}`);
|
|
4706
4883
|
console.log(` Registry: ${entry.digest}`);
|
|
@@ -4712,11 +4889,11 @@ var adapterCommand = defineCommand35({
|
|
|
4712
4889
|
});
|
|
4713
4890
|
|
|
4714
4891
|
// src/commands/run.ts
|
|
4715
|
-
import { execFileSync as
|
|
4892
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
4716
4893
|
import { hostname as hostname5 } from "os";
|
|
4717
4894
|
import { basename } from "path";
|
|
4718
|
-
import { defineCommand as
|
|
4719
|
-
import
|
|
4895
|
+
import { defineCommand as defineCommand40 } from "citty";
|
|
4896
|
+
import consola34 from "consola";
|
|
4720
4897
|
function shouldWaitForGrant(args) {
|
|
4721
4898
|
return args.wait === true || process.env.APE_WAIT === "1";
|
|
4722
4899
|
}
|
|
@@ -4753,7 +4930,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4753
4930
|
const statusCmd = `apes grants status ${grant.id}`;
|
|
4754
4931
|
const executeCmd = `apes grants run ${grant.id}`;
|
|
4755
4932
|
if (mode === "human") {
|
|
4756
|
-
|
|
4933
|
+
consola34.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
|
|
4757
4934
|
console.log(` Approve in browser: ${approveUrl}`);
|
|
4758
4935
|
console.log(` Check status: ${statusCmd}`);
|
|
4759
4936
|
console.log(` Run after approval: ${executeCmd}`);
|
|
@@ -4763,7 +4940,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4763
4940
|
return;
|
|
4764
4941
|
}
|
|
4765
4942
|
const maxMin = getPollMaxMinutes();
|
|
4766
|
-
|
|
4943
|
+
consola34.success(`Grant ${grant.id} created (pending approval)`);
|
|
4767
4944
|
console.log(` Approve: ${approveUrl}`);
|
|
4768
4945
|
console.log(` Status: ${statusCmd} [--json]`);
|
|
4769
4946
|
console.log(` Execute: ${executeCmd} --wait`);
|
|
@@ -4785,7 +4962,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4785
4962
|
console.log(' Tip: Approve as "timed" or "always" in the browser to let this');
|
|
4786
4963
|
console.log(" grant be reused on subsequent invocations without re-approval.");
|
|
4787
4964
|
}
|
|
4788
|
-
var runCommand =
|
|
4965
|
+
var runCommand = defineCommand40({
|
|
4789
4966
|
meta: {
|
|
4790
4967
|
name: "run",
|
|
4791
4968
|
description: "Execute a grant-secured command"
|
|
@@ -4888,7 +5065,7 @@ async function runShellMode(command, args) {
|
|
|
4888
5065
|
}
|
|
4889
5066
|
} catch {
|
|
4890
5067
|
}
|
|
4891
|
-
|
|
5068
|
+
consola34.info(`Requesting ape-shell session grant on ${targetHost}`);
|
|
4892
5069
|
const grant = await apiFetch(grantsUrl, {
|
|
4893
5070
|
method: "POST",
|
|
4894
5071
|
body: {
|
|
@@ -4908,8 +5085,8 @@ async function runShellMode(command, args) {
|
|
|
4908
5085
|
host: targetHost
|
|
4909
5086
|
});
|
|
4910
5087
|
if (shouldWaitForGrant(args)) {
|
|
4911
|
-
|
|
4912
|
-
|
|
5088
|
+
consola34.info(`Grant requested: ${grant.id}`);
|
|
5089
|
+
consola34.info("Waiting for approval...");
|
|
4913
5090
|
const maxWait = 3e5;
|
|
4914
5091
|
const interval = 3e3;
|
|
4915
5092
|
const start = Date.now();
|
|
@@ -4940,13 +5117,13 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4940
5117
|
try {
|
|
4941
5118
|
resolved = await resolveCommand(loaded, [normalizedExecutable, ...parsed.argv]);
|
|
4942
5119
|
} catch (err) {
|
|
4943
|
-
|
|
5120
|
+
consola34.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
|
|
4944
5121
|
return false;
|
|
4945
5122
|
}
|
|
4946
5123
|
try {
|
|
4947
5124
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
4948
5125
|
if (existingGrantId) {
|
|
4949
|
-
|
|
5126
|
+
consola34.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
|
|
4950
5127
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
4951
5128
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
4952
5129
|
return true;
|
|
@@ -4954,7 +5131,7 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4954
5131
|
} catch {
|
|
4955
5132
|
}
|
|
4956
5133
|
const approval = args.approval ?? "once";
|
|
4957
|
-
|
|
5134
|
+
consola34.info(`Requesting grant for: ${resolved.detail.display}`);
|
|
4958
5135
|
const grant = await createShapesGrant(resolved, {
|
|
4959
5136
|
idp,
|
|
4960
5137
|
approval,
|
|
@@ -4962,8 +5139,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4962
5139
|
});
|
|
4963
5140
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
4964
5141
|
const n = grant.similar_grants.similar_grants.length;
|
|
4965
|
-
|
|
4966
|
-
|
|
5142
|
+
consola34.info("");
|
|
5143
|
+
consola34.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
4967
5144
|
}
|
|
4968
5145
|
notifyGrantPending({
|
|
4969
5146
|
grantId: grant.id,
|
|
@@ -4973,8 +5150,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4973
5150
|
host: args.host || hostname5()
|
|
4974
5151
|
});
|
|
4975
5152
|
if (shouldWaitForGrant(args)) {
|
|
4976
|
-
|
|
4977
|
-
|
|
5153
|
+
consola34.info(`Grant requested: ${grant.id}`);
|
|
5154
|
+
consola34.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
4978
5155
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
4979
5156
|
if (status !== "approved")
|
|
4980
5157
|
throw new CliError(`Grant ${status}`);
|
|
@@ -4990,7 +5167,7 @@ function execShellCommand(command) {
|
|
|
4990
5167
|
throw new CliError("No command to execute");
|
|
4991
5168
|
try {
|
|
4992
5169
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
4993
|
-
|
|
5170
|
+
execFileSync12(command[0], command.slice(1), {
|
|
4994
5171
|
stdio: "inherit",
|
|
4995
5172
|
env: inheritedEnv
|
|
4996
5173
|
});
|
|
@@ -5048,7 +5225,7 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
5048
5225
|
try {
|
|
5049
5226
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
5050
5227
|
if (existingGrantId) {
|
|
5051
|
-
|
|
5228
|
+
consola34.info(`Reusing existing grant: ${existingGrantId}`);
|
|
5052
5229
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
5053
5230
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
5054
5231
|
return;
|
|
@@ -5062,17 +5239,17 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
5062
5239
|
});
|
|
5063
5240
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
5064
5241
|
const n = grant.similar_grants.similar_grants.length;
|
|
5065
|
-
|
|
5066
|
-
|
|
5242
|
+
consola34.info("");
|
|
5243
|
+
consola34.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
5067
5244
|
if (grant.similar_grants.widened_details?.length) {
|
|
5068
5245
|
const wider = grant.similar_grants.widened_details.map((d) => d.permission).join(", ");
|
|
5069
|
-
|
|
5246
|
+
consola34.info(` Broader scope: ${wider}`);
|
|
5070
5247
|
}
|
|
5071
|
-
|
|
5248
|
+
consola34.info("");
|
|
5072
5249
|
}
|
|
5073
5250
|
if (shouldWaitForGrant(args)) {
|
|
5074
|
-
|
|
5075
|
-
|
|
5251
|
+
consola34.info(`Grant requested: ${grant.id}`);
|
|
5252
|
+
consola34.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
5076
5253
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
5077
5254
|
if (status !== "approved")
|
|
5078
5255
|
throw new Error(`Grant ${status}`);
|
|
@@ -5092,7 +5269,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5092
5269
|
const grantsUrl = await getGrantsEndpoint(idp);
|
|
5093
5270
|
const command = action.split(" ");
|
|
5094
5271
|
const targetHost = args.host || hostname5();
|
|
5095
|
-
|
|
5272
|
+
consola34.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
|
|
5096
5273
|
const grant = await apiFetch(grantsUrl, {
|
|
5097
5274
|
method: "POST",
|
|
5098
5275
|
body: {
|
|
@@ -5109,9 +5286,9 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5109
5286
|
printPendingGrantInfo(grant, idp);
|
|
5110
5287
|
throw new CliExit(getAsyncExitCode());
|
|
5111
5288
|
}
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5289
|
+
consola34.success(`Grant requested: ${grant.id}`);
|
|
5290
|
+
consola34.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
5291
|
+
consola34.info("Waiting for approval...");
|
|
5115
5292
|
const maxWait = 15 * 60 * 1e3;
|
|
5116
5293
|
const interval = 3e3;
|
|
5117
5294
|
const start = Date.now();
|
|
@@ -5119,7 +5296,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5119
5296
|
while (Date.now() - start < maxWait) {
|
|
5120
5297
|
const status = await apiFetch(`${grantsUrl}/${grant.id}`);
|
|
5121
5298
|
if (status.status === "approved") {
|
|
5122
|
-
|
|
5299
|
+
consola34.success("Grant approved!");
|
|
5123
5300
|
approved = true;
|
|
5124
5301
|
break;
|
|
5125
5302
|
}
|
|
@@ -5134,15 +5311,15 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5134
5311
|
`Grant approval timed out after ${minutes} min (still pending). Check your DDISA inbox at ${idp}/grant-approval?grant_id=${grant.id} \u2014 if approved later, re-run the same \`apes run\` command and it will reuse the grant.`
|
|
5135
5312
|
);
|
|
5136
5313
|
}
|
|
5137
|
-
|
|
5314
|
+
consola34.info("Fetching grant token...");
|
|
5138
5315
|
const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, {
|
|
5139
5316
|
method: "POST"
|
|
5140
5317
|
});
|
|
5141
5318
|
if (audience === "escapes") {
|
|
5142
|
-
|
|
5319
|
+
consola34.info(`Executing: ${command.join(" ")}`);
|
|
5143
5320
|
try {
|
|
5144
5321
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
5145
|
-
|
|
5322
|
+
execFileSync12(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
|
|
5146
5323
|
stdio: "inherit",
|
|
5147
5324
|
env: inheritedEnv
|
|
5148
5325
|
});
|
|
@@ -5157,8 +5334,8 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5157
5334
|
|
|
5158
5335
|
// src/commands/proxy.ts
|
|
5159
5336
|
import { spawn as spawn2 } from "child_process";
|
|
5160
|
-
import { defineCommand as
|
|
5161
|
-
import
|
|
5337
|
+
import { defineCommand as defineCommand41 } from "citty";
|
|
5338
|
+
import consola35 from "consola";
|
|
5162
5339
|
|
|
5163
5340
|
// src/proxy/config.ts
|
|
5164
5341
|
function buildDefaultProxyConfigToml(opts) {
|
|
@@ -5301,10 +5478,10 @@ function resolveProxyConfigOptions() {
|
|
|
5301
5478
|
77
|
|
5302
5479
|
);
|
|
5303
5480
|
}
|
|
5304
|
-
|
|
5481
|
+
consola35.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
|
|
5305
5482
|
return { agentEmail: auth.email, idpUrl: auth.idp, mediated: true };
|
|
5306
5483
|
}
|
|
5307
|
-
var proxyCommand =
|
|
5484
|
+
var proxyCommand = defineCommand41({
|
|
5308
5485
|
meta: {
|
|
5309
5486
|
name: "proxy",
|
|
5310
5487
|
description: "Run a command with HTTPS_PROXY routed through the OpenApe egress proxy."
|
|
@@ -5326,12 +5503,12 @@ var proxyCommand = defineCommand37({
|
|
|
5326
5503
|
let close = null;
|
|
5327
5504
|
if (reuseUrl) {
|
|
5328
5505
|
proxyUrl = reuseUrl;
|
|
5329
|
-
|
|
5506
|
+
consola35.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
|
|
5330
5507
|
} else {
|
|
5331
5508
|
const ephemeral = await startEphemeralProxy(buildDefaultProxyConfigToml(resolveProxyConfigOptions()));
|
|
5332
5509
|
proxyUrl = ephemeral.url;
|
|
5333
5510
|
close = ephemeral.close;
|
|
5334
|
-
|
|
5511
|
+
consola35.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
|
|
5335
5512
|
}
|
|
5336
5513
|
const noProxy = process.env.NO_PROXY ?? process.env.no_proxy ?? "127.0.0.1,localhost";
|
|
5337
5514
|
const childEnv = {
|
|
@@ -5363,7 +5540,7 @@ var proxyCommand = defineCommand37({
|
|
|
5363
5540
|
else resolveExit(code ?? 0);
|
|
5364
5541
|
});
|
|
5365
5542
|
child.once("error", (err) => {
|
|
5366
|
-
|
|
5543
|
+
consola35.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
|
|
5367
5544
|
resolveExit(127);
|
|
5368
5545
|
});
|
|
5369
5546
|
});
|
|
@@ -5377,8 +5554,8 @@ function signalNumber(signal) {
|
|
|
5377
5554
|
}
|
|
5378
5555
|
|
|
5379
5556
|
// src/commands/explain.ts
|
|
5380
|
-
import { defineCommand as
|
|
5381
|
-
var explainCommand =
|
|
5557
|
+
import { defineCommand as defineCommand42 } from "citty";
|
|
5558
|
+
var explainCommand = defineCommand42({
|
|
5382
5559
|
meta: {
|
|
5383
5560
|
name: "explain",
|
|
5384
5561
|
description: "Show what permission a command would need"
|
|
@@ -5416,9 +5593,9 @@ var explainCommand = defineCommand38({
|
|
|
5416
5593
|
});
|
|
5417
5594
|
|
|
5418
5595
|
// src/commands/config/get.ts
|
|
5419
|
-
import { defineCommand as
|
|
5420
|
-
import
|
|
5421
|
-
var configGetCommand =
|
|
5596
|
+
import { defineCommand as defineCommand43 } from "citty";
|
|
5597
|
+
import consola36 from "consola";
|
|
5598
|
+
var configGetCommand = defineCommand43({
|
|
5422
5599
|
meta: {
|
|
5423
5600
|
name: "get",
|
|
5424
5601
|
description: "Get a configuration value"
|
|
@@ -5438,7 +5615,7 @@ var configGetCommand = defineCommand39({
|
|
|
5438
5615
|
if (idp)
|
|
5439
5616
|
console.log(idp);
|
|
5440
5617
|
else
|
|
5441
|
-
|
|
5618
|
+
consola36.info("No IdP configured.");
|
|
5442
5619
|
break;
|
|
5443
5620
|
}
|
|
5444
5621
|
case "email": {
|
|
@@ -5446,7 +5623,7 @@ var configGetCommand = defineCommand39({
|
|
|
5446
5623
|
if (auth?.email)
|
|
5447
5624
|
console.log(auth.email);
|
|
5448
5625
|
else
|
|
5449
|
-
|
|
5626
|
+
consola36.info("Not logged in.");
|
|
5450
5627
|
break;
|
|
5451
5628
|
}
|
|
5452
5629
|
default: {
|
|
@@ -5459,7 +5636,7 @@ var configGetCommand = defineCommand39({
|
|
|
5459
5636
|
if (sectionObj && field in sectionObj) {
|
|
5460
5637
|
console.log(sectionObj[field]);
|
|
5461
5638
|
} else {
|
|
5462
|
-
|
|
5639
|
+
consola36.info(`Key "${key}" not set.`);
|
|
5463
5640
|
}
|
|
5464
5641
|
} else {
|
|
5465
5642
|
throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
|
|
@@ -5470,9 +5647,9 @@ var configGetCommand = defineCommand39({
|
|
|
5470
5647
|
});
|
|
5471
5648
|
|
|
5472
5649
|
// src/commands/config/set.ts
|
|
5473
|
-
import { defineCommand as
|
|
5474
|
-
import
|
|
5475
|
-
var configSetCommand =
|
|
5650
|
+
import { defineCommand as defineCommand44 } from "citty";
|
|
5651
|
+
import consola37 from "consola";
|
|
5652
|
+
var configSetCommand = defineCommand44({
|
|
5476
5653
|
meta: {
|
|
5477
5654
|
name: "set",
|
|
5478
5655
|
description: "Set a configuration value"
|
|
@@ -5508,12 +5685,12 @@ var configSetCommand = defineCommand40({
|
|
|
5508
5685
|
throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
|
|
5509
5686
|
}
|
|
5510
5687
|
saveConfig(config);
|
|
5511
|
-
|
|
5688
|
+
consola37.success(`Set ${key} = ${value}`);
|
|
5512
5689
|
}
|
|
5513
5690
|
});
|
|
5514
5691
|
|
|
5515
5692
|
// src/commands/fetch/index.ts
|
|
5516
|
-
import { defineCommand as
|
|
5693
|
+
import { defineCommand as defineCommand45 } from "citty";
|
|
5517
5694
|
async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
5518
5695
|
const token = getAuthToken();
|
|
5519
5696
|
if (!token) {
|
|
@@ -5549,13 +5726,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
|
5549
5726
|
throw new CliError(`HTTP ${response.status} ${response.statusText}`);
|
|
5550
5727
|
}
|
|
5551
5728
|
}
|
|
5552
|
-
var fetchCommand =
|
|
5729
|
+
var fetchCommand = defineCommand45({
|
|
5553
5730
|
meta: {
|
|
5554
5731
|
name: "fetch",
|
|
5555
5732
|
description: "Make authenticated HTTP requests"
|
|
5556
5733
|
},
|
|
5557
5734
|
subCommands: {
|
|
5558
|
-
get:
|
|
5735
|
+
get: defineCommand45({
|
|
5559
5736
|
meta: {
|
|
5560
5737
|
name: "get",
|
|
5561
5738
|
description: "GET request with auth token"
|
|
@@ -5581,7 +5758,7 @@ var fetchCommand = defineCommand41({
|
|
|
5581
5758
|
await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
|
|
5582
5759
|
}
|
|
5583
5760
|
}),
|
|
5584
|
-
post:
|
|
5761
|
+
post: defineCommand45({
|
|
5585
5762
|
meta: {
|
|
5586
5763
|
name: "post",
|
|
5587
5764
|
description: "POST request with auth token"
|
|
@@ -5620,8 +5797,8 @@ var fetchCommand = defineCommand41({
|
|
|
5620
5797
|
});
|
|
5621
5798
|
|
|
5622
5799
|
// src/commands/mcp/index.ts
|
|
5623
|
-
import { defineCommand as
|
|
5624
|
-
var mcpCommand =
|
|
5800
|
+
import { defineCommand as defineCommand46 } from "citty";
|
|
5801
|
+
var mcpCommand = defineCommand46({
|
|
5625
5802
|
meta: {
|
|
5626
5803
|
name: "mcp",
|
|
5627
5804
|
description: "Start MCP server for AI agents"
|
|
@@ -5644,7 +5821,7 @@ var mcpCommand = defineCommand42({
|
|
|
5644
5821
|
if (transport !== "stdio" && transport !== "sse") {
|
|
5645
5822
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
5646
5823
|
}
|
|
5647
|
-
const { startMcpServer } = await import("./server-
|
|
5824
|
+
const { startMcpServer } = await import("./server-BSBIEKFK.js");
|
|
5648
5825
|
await startMcpServer(transport, port);
|
|
5649
5826
|
}
|
|
5650
5827
|
});
|
|
@@ -5652,10 +5829,10 @@ var mcpCommand = defineCommand42({
|
|
|
5652
5829
|
// src/commands/init/index.ts
|
|
5653
5830
|
import { existsSync as existsSync14, copyFileSync, writeFileSync as writeFileSync9 } from "fs";
|
|
5654
5831
|
import { randomBytes } from "crypto";
|
|
5655
|
-
import { execFileSync as
|
|
5832
|
+
import { execFileSync as execFileSync13 } from "child_process";
|
|
5656
5833
|
import { join as join13 } from "path";
|
|
5657
|
-
import { defineCommand as
|
|
5658
|
-
import
|
|
5834
|
+
import { defineCommand as defineCommand47 } from "citty";
|
|
5835
|
+
import consola38 from "consola";
|
|
5659
5836
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
5660
5837
|
async function downloadTemplate(repo, targetDir) {
|
|
5661
5838
|
const { downloadTemplate: gigetDownload } = await import("giget");
|
|
@@ -5664,28 +5841,28 @@ async function downloadTemplate(repo, targetDir) {
|
|
|
5664
5841
|
function installDeps(dir) {
|
|
5665
5842
|
const hasLockFile = (name) => existsSync14(join13(dir, name));
|
|
5666
5843
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
5667
|
-
|
|
5844
|
+
execFileSync13("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5668
5845
|
} else if (hasLockFile("bun.lockb")) {
|
|
5669
|
-
|
|
5846
|
+
execFileSync13("bun", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5670
5847
|
} else {
|
|
5671
|
-
|
|
5848
|
+
execFileSync13("npm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5672
5849
|
}
|
|
5673
5850
|
}
|
|
5674
5851
|
async function promptChoice(message, choices) {
|
|
5675
|
-
const result = await
|
|
5852
|
+
const result = await consola38.prompt(message, { type: "select", options: choices });
|
|
5676
5853
|
if (typeof result === "symbol") {
|
|
5677
5854
|
throw new CliExit(0);
|
|
5678
5855
|
}
|
|
5679
5856
|
return result;
|
|
5680
5857
|
}
|
|
5681
5858
|
async function promptText(message, defaultValue) {
|
|
5682
|
-
const result = await
|
|
5859
|
+
const result = await consola38.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
|
|
5683
5860
|
if (typeof result === "symbol") {
|
|
5684
5861
|
throw new CliExit(0);
|
|
5685
5862
|
}
|
|
5686
5863
|
return result || defaultValue || "";
|
|
5687
5864
|
}
|
|
5688
|
-
var initCommand =
|
|
5865
|
+
var initCommand = defineCommand47({
|
|
5689
5866
|
meta: {
|
|
5690
5867
|
name: "init",
|
|
5691
5868
|
description: "Scaffold a new OpenApe project"
|
|
@@ -5730,20 +5907,20 @@ async function initSP(targetDir) {
|
|
|
5730
5907
|
if (existsSync14(join13(dir, "package.json"))) {
|
|
5731
5908
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
5732
5909
|
}
|
|
5733
|
-
|
|
5910
|
+
consola38.start("Scaffolding SP starter...");
|
|
5734
5911
|
await downloadTemplate("openape-ai/openape-sp-starter", dir);
|
|
5735
|
-
|
|
5736
|
-
|
|
5912
|
+
consola38.success("Scaffolded from openape-sp-starter");
|
|
5913
|
+
consola38.start("Installing dependencies...");
|
|
5737
5914
|
installDeps(dir);
|
|
5738
|
-
|
|
5915
|
+
consola38.success("Dependencies installed");
|
|
5739
5916
|
const envExample = join13(dir, ".env.example");
|
|
5740
5917
|
const envFile = join13(dir, ".env");
|
|
5741
5918
|
if (existsSync14(envExample) && !existsSync14(envFile)) {
|
|
5742
5919
|
copyFileSync(envExample, envFile);
|
|
5743
|
-
|
|
5920
|
+
consola38.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
5744
5921
|
}
|
|
5745
5922
|
console.log("");
|
|
5746
|
-
|
|
5923
|
+
consola38.box([
|
|
5747
5924
|
`cd ${dir}`,
|
|
5748
5925
|
"npm run dev",
|
|
5749
5926
|
"",
|
|
@@ -5762,15 +5939,15 @@ async function initIdP(targetDir) {
|
|
|
5762
5939
|
"s3 (S3-compatible)"
|
|
5763
5940
|
]);
|
|
5764
5941
|
const adminEmail = await promptText("Admin email");
|
|
5765
|
-
|
|
5942
|
+
consola38.start("Scaffolding IdP starter...");
|
|
5766
5943
|
await downloadTemplate("openape-ai/openape-idp-starter", dir);
|
|
5767
|
-
|
|
5768
|
-
|
|
5944
|
+
consola38.success("Scaffolded from openape-idp-starter");
|
|
5945
|
+
consola38.start("Installing dependencies...");
|
|
5769
5946
|
installDeps(dir);
|
|
5770
|
-
|
|
5947
|
+
consola38.success("Dependencies installed");
|
|
5771
5948
|
const sessionSecret = randomBytes(32).toString("hex");
|
|
5772
5949
|
const managementToken = randomBytes(32).toString("hex");
|
|
5773
|
-
|
|
5950
|
+
consola38.success("Secrets generated");
|
|
5774
5951
|
const isLocalhost = domain === "localhost";
|
|
5775
5952
|
const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
|
|
5776
5953
|
const envContent = [
|
|
@@ -5786,9 +5963,9 @@ async function initIdP(targetDir) {
|
|
|
5786
5963
|
].join("\n");
|
|
5787
5964
|
writeFileSync9(join13(dir, ".env"), `${envContent}
|
|
5788
5965
|
`, { mode: 384 });
|
|
5789
|
-
|
|
5966
|
+
consola38.success(".env created");
|
|
5790
5967
|
console.log("");
|
|
5791
|
-
|
|
5968
|
+
consola38.box([
|
|
5792
5969
|
`cd ${dir}`,
|
|
5793
5970
|
"npm run dev",
|
|
5794
5971
|
"",
|
|
@@ -5808,8 +5985,8 @@ import { Buffer as Buffer5 } from "buffer";
|
|
|
5808
5985
|
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
|
|
5809
5986
|
import { execFile as execFile2 } from "child_process";
|
|
5810
5987
|
import { sign as sign2 } from "crypto";
|
|
5811
|
-
import { defineCommand as
|
|
5812
|
-
import
|
|
5988
|
+
import { defineCommand as defineCommand48 } from "citty";
|
|
5989
|
+
import consola39 from "consola";
|
|
5813
5990
|
var DEFAULT_IDP_URL2 = "https://id.openape.at";
|
|
5814
5991
|
var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
|
|
5815
5992
|
var POLL_INTERVAL = 3e3;
|
|
@@ -5852,7 +6029,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
5852
6029
|
}
|
|
5853
6030
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
5854
6031
|
}
|
|
5855
|
-
var enrollCommand =
|
|
6032
|
+
var enrollCommand = defineCommand48({
|
|
5856
6033
|
meta: {
|
|
5857
6034
|
name: "enroll",
|
|
5858
6035
|
description: "Enroll an agent with an Identity Provider"
|
|
@@ -5872,18 +6049,18 @@ var enrollCommand = defineCommand44({
|
|
|
5872
6049
|
}
|
|
5873
6050
|
},
|
|
5874
6051
|
async run({ args }) {
|
|
5875
|
-
const idp = args.idp || await
|
|
6052
|
+
const idp = args.idp || await consola39.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
|
|
5876
6053
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5877
6054
|
return r;
|
|
5878
6055
|
}) || DEFAULT_IDP_URL2;
|
|
5879
|
-
const agentName = args.name || await
|
|
6056
|
+
const agentName = args.name || await consola39.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
|
|
5880
6057
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5881
6058
|
return r;
|
|
5882
6059
|
});
|
|
5883
6060
|
if (!agentName) {
|
|
5884
6061
|
throw new CliError("Agent name is required.");
|
|
5885
6062
|
}
|
|
5886
|
-
const keyPath = args.key || await
|
|
6063
|
+
const keyPath = args.key || await consola39.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
|
|
5887
6064
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5888
6065
|
return r;
|
|
5889
6066
|
}) || DEFAULT_KEY_PATH;
|
|
@@ -5891,19 +6068,19 @@ var enrollCommand = defineCommand44({
|
|
|
5891
6068
|
let publicKey;
|
|
5892
6069
|
if (existsSync15(resolvedKey)) {
|
|
5893
6070
|
publicKey = readPublicKey(resolvedKey);
|
|
5894
|
-
|
|
6071
|
+
consola39.success(`Using existing key ${keyPath}`);
|
|
5895
6072
|
} else {
|
|
5896
|
-
|
|
6073
|
+
consola39.start(`Generating Ed25519 key pair at ${keyPath}...`);
|
|
5897
6074
|
publicKey = generateAndSaveKey(keyPath);
|
|
5898
|
-
|
|
6075
|
+
consola39.success(`Key pair generated at ${keyPath}`);
|
|
5899
6076
|
}
|
|
5900
6077
|
const encodedKey = encodeURIComponent(publicKey);
|
|
5901
6078
|
const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
|
|
5902
|
-
|
|
5903
|
-
|
|
6079
|
+
consola39.info("Opening browser for enrollment...");
|
|
6080
|
+
consola39.info(`\u2192 ${idp}/enroll`);
|
|
5904
6081
|
openBrowser2(enrollUrl);
|
|
5905
6082
|
console.log("");
|
|
5906
|
-
const agentEmail = await
|
|
6083
|
+
const agentEmail = await consola39.prompt(
|
|
5907
6084
|
"Agent email (shown in browser after enrollment)",
|
|
5908
6085
|
{ type: "text", placeholder: `agent+${agentName}@...` }
|
|
5909
6086
|
).then((r) => {
|
|
@@ -5913,7 +6090,7 @@ var enrollCommand = defineCommand44({
|
|
|
5913
6090
|
if (!agentEmail) {
|
|
5914
6091
|
throw new CliError("Agent email is required to verify enrollment.");
|
|
5915
6092
|
}
|
|
5916
|
-
|
|
6093
|
+
consola39.start("Verifying enrollment...");
|
|
5917
6094
|
const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
|
|
5918
6095
|
saveAuth({
|
|
5919
6096
|
idp,
|
|
@@ -5925,18 +6102,18 @@ var enrollCommand = defineCommand44({
|
|
|
5925
6102
|
config.defaults = { ...config.defaults, idp };
|
|
5926
6103
|
config.agent = { key: keyPath, email: agentEmail };
|
|
5927
6104
|
saveConfig(config);
|
|
5928
|
-
|
|
5929
|
-
|
|
6105
|
+
consola39.success(`Agent enrolled as ${agentEmail}`);
|
|
6106
|
+
consola39.success("Config saved to ~/.config/apes/");
|
|
5930
6107
|
console.log("");
|
|
5931
|
-
|
|
6108
|
+
consola39.info("Verify with: apes whoami");
|
|
5932
6109
|
}
|
|
5933
6110
|
});
|
|
5934
6111
|
|
|
5935
6112
|
// src/commands/register-user.ts
|
|
5936
6113
|
import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
|
|
5937
|
-
import { defineCommand as
|
|
5938
|
-
import
|
|
5939
|
-
var registerUserCommand =
|
|
6114
|
+
import { defineCommand as defineCommand49 } from "citty";
|
|
6115
|
+
import consola40 from "consola";
|
|
6116
|
+
var registerUserCommand = defineCommand49({
|
|
5940
6117
|
meta: {
|
|
5941
6118
|
name: "register-user",
|
|
5942
6119
|
description: "Register a sub-user with SSH key"
|
|
@@ -5991,18 +6168,18 @@ var registerUserCommand = defineCommand45({
|
|
|
5991
6168
|
...userType ? { type: userType } : {}
|
|
5992
6169
|
}
|
|
5993
6170
|
});
|
|
5994
|
-
|
|
6171
|
+
consola40.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
|
|
5995
6172
|
}
|
|
5996
6173
|
});
|
|
5997
6174
|
|
|
5998
6175
|
// src/commands/utils/index.ts
|
|
5999
|
-
import { defineCommand as
|
|
6176
|
+
import { defineCommand as defineCommand51 } from "citty";
|
|
6000
6177
|
|
|
6001
6178
|
// src/commands/utils/dig.ts
|
|
6002
|
-
import { defineCommand as
|
|
6003
|
-
import
|
|
6179
|
+
import { defineCommand as defineCommand50 } from "citty";
|
|
6180
|
+
import consola41 from "consola";
|
|
6004
6181
|
import { resolveDDISA as resolveDDISA2 } from "@openape/core";
|
|
6005
|
-
var digCommand =
|
|
6182
|
+
var digCommand = defineCommand50({
|
|
6006
6183
|
meta: {
|
|
6007
6184
|
name: "dig",
|
|
6008
6185
|
description: "Resolve DDISA IdP for a domain or email (admin/diag tool)"
|
|
@@ -6075,12 +6252,12 @@ var digCommand = defineCommand46({
|
|
|
6075
6252
|
console.log(` domain: ${domain}`);
|
|
6076
6253
|
console.log("");
|
|
6077
6254
|
if (!result.ddisa.found) {
|
|
6078
|
-
|
|
6255
|
+
consola41.warn(`No DDISA record at _ddisa.${domain}`);
|
|
6079
6256
|
if (result.hint) console.log(`
|
|
6080
6257
|
${result.hint}`);
|
|
6081
6258
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
6082
6259
|
}
|
|
6083
|
-
|
|
6260
|
+
consola41.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
|
|
6084
6261
|
console.log(` Version: ${result.ddisa.version || "ddisa1"}`);
|
|
6085
6262
|
console.log(` IdP URL: ${result.ddisa.idp}`);
|
|
6086
6263
|
if (result.ddisa.mode) console.log(` Mode: ${result.ddisa.mode}`);
|
|
@@ -6090,13 +6267,13 @@ ${result.hint}`);
|
|
|
6090
6267
|
return;
|
|
6091
6268
|
}
|
|
6092
6269
|
if (result.idpDiscovery.ok) {
|
|
6093
|
-
|
|
6270
|
+
consola41.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
|
|
6094
6271
|
if (result.idpDiscovery.issuer) console.log(` Issuer: ${result.idpDiscovery.issuer}`);
|
|
6095
6272
|
if (result.idpDiscovery.ddisaVersion) console.log(` DDISA: v${result.idpDiscovery.ddisaVersion}`);
|
|
6096
6273
|
if (result.idpDiscovery.authMethods?.length) console.log(` Auth: ${result.idpDiscovery.authMethods.join(", ")}`);
|
|
6097
6274
|
if (result.idpDiscovery.grantTypes?.length) console.log(` Grants: ${result.idpDiscovery.grantTypes.join(", ")}`);
|
|
6098
6275
|
} else {
|
|
6099
|
-
|
|
6276
|
+
consola41.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
|
|
6100
6277
|
if (result.hint) console.log(`
|
|
6101
6278
|
${result.hint}`);
|
|
6102
6279
|
throw new CliError(`IdP at ${result.ddisa.idp} not reachable`);
|
|
@@ -6105,7 +6282,7 @@ ${result.hint}`);
|
|
|
6105
6282
|
});
|
|
6106
6283
|
|
|
6107
6284
|
// src/commands/utils/index.ts
|
|
6108
|
-
var utilsCommand =
|
|
6285
|
+
var utilsCommand = defineCommand51({
|
|
6109
6286
|
meta: {
|
|
6110
6287
|
name: "utils",
|
|
6111
6288
|
description: "Admin/diagnostic utilities (dig, \u2026)"
|
|
@@ -6116,12 +6293,12 @@ var utilsCommand = defineCommand47({
|
|
|
6116
6293
|
});
|
|
6117
6294
|
|
|
6118
6295
|
// src/commands/sessions/index.ts
|
|
6119
|
-
import { defineCommand as
|
|
6296
|
+
import { defineCommand as defineCommand54 } from "citty";
|
|
6120
6297
|
|
|
6121
6298
|
// src/commands/sessions/list.ts
|
|
6122
|
-
import { defineCommand as
|
|
6123
|
-
import
|
|
6124
|
-
var sessionsListCommand =
|
|
6299
|
+
import { defineCommand as defineCommand52 } from "citty";
|
|
6300
|
+
import consola42 from "consola";
|
|
6301
|
+
var sessionsListCommand = defineCommand52({
|
|
6125
6302
|
meta: {
|
|
6126
6303
|
name: "list",
|
|
6127
6304
|
description: "List your active refresh-token families (one per logged-in device)."
|
|
@@ -6139,7 +6316,7 @@ var sessionsListCommand = defineCommand48({
|
|
|
6139
6316
|
return;
|
|
6140
6317
|
}
|
|
6141
6318
|
if (result.data.length === 0) {
|
|
6142
|
-
|
|
6319
|
+
consola42.info("No active sessions.");
|
|
6143
6320
|
return;
|
|
6144
6321
|
}
|
|
6145
6322
|
for (const f of result.data) {
|
|
@@ -6151,9 +6328,9 @@ var sessionsListCommand = defineCommand48({
|
|
|
6151
6328
|
});
|
|
6152
6329
|
|
|
6153
6330
|
// src/commands/sessions/remove.ts
|
|
6154
|
-
import { defineCommand as
|
|
6155
|
-
import
|
|
6156
|
-
var sessionsRemoveCommand =
|
|
6331
|
+
import { defineCommand as defineCommand53 } from "citty";
|
|
6332
|
+
import consola43 from "consola";
|
|
6333
|
+
var sessionsRemoveCommand = defineCommand53({
|
|
6157
6334
|
meta: {
|
|
6158
6335
|
name: "remove",
|
|
6159
6336
|
description: "Revoke one of your active refresh-token families by id."
|
|
@@ -6169,12 +6346,12 @@ var sessionsRemoveCommand = defineCommand49({
|
|
|
6169
6346
|
const id = String(args.familyId).trim();
|
|
6170
6347
|
if (!id) throw new CliError("familyId required");
|
|
6171
6348
|
await apiFetch(`/api/me/sessions/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
6172
|
-
|
|
6349
|
+
consola43.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
|
|
6173
6350
|
}
|
|
6174
6351
|
});
|
|
6175
6352
|
|
|
6176
6353
|
// src/commands/sessions/index.ts
|
|
6177
|
-
var sessionsCommand =
|
|
6354
|
+
var sessionsCommand = defineCommand54({
|
|
6178
6355
|
meta: {
|
|
6179
6356
|
name: "sessions",
|
|
6180
6357
|
description: "Manage your active refresh-token sessions across devices"
|
|
@@ -6186,10 +6363,10 @@ var sessionsCommand = defineCommand50({
|
|
|
6186
6363
|
});
|
|
6187
6364
|
|
|
6188
6365
|
// src/commands/dns-check.ts
|
|
6189
|
-
import { defineCommand as
|
|
6190
|
-
import
|
|
6366
|
+
import { defineCommand as defineCommand55 } from "citty";
|
|
6367
|
+
import consola44 from "consola";
|
|
6191
6368
|
import { resolveDDISA as resolveDDISA3 } from "@openape/core";
|
|
6192
|
-
var dnsCheckCommand =
|
|
6369
|
+
var dnsCheckCommand = defineCommand55({
|
|
6193
6370
|
meta: {
|
|
6194
6371
|
name: "dns-check",
|
|
6195
6372
|
description: "Validate DDISA DNS TXT records for a domain"
|
|
@@ -6203,7 +6380,7 @@ var dnsCheckCommand = defineCommand51({
|
|
|
6203
6380
|
},
|
|
6204
6381
|
async run({ args }) {
|
|
6205
6382
|
const domain = args.domain;
|
|
6206
|
-
|
|
6383
|
+
consola44.start(`Checking _ddisa.${domain}...`);
|
|
6207
6384
|
try {
|
|
6208
6385
|
const result = await resolveDDISA3(domain);
|
|
6209
6386
|
if (!result) {
|
|
@@ -6212,7 +6389,7 @@ var dnsCheckCommand = defineCommand51({
|
|
|
6212
6389
|
console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
|
|
6213
6390
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
6214
6391
|
}
|
|
6215
|
-
|
|
6392
|
+
consola44.success(`_ddisa.${domain} \u2192 ${result.idp}`);
|
|
6216
6393
|
console.log("");
|
|
6217
6394
|
console.log(` Version: ${result.version || "ddisa1"}`);
|
|
6218
6395
|
console.log(` IdP URL: ${result.idp}`);
|
|
@@ -6221,14 +6398,14 @@ var dnsCheckCommand = defineCommand51({
|
|
|
6221
6398
|
if (result.priority !== void 0)
|
|
6222
6399
|
console.log(` Priority: ${result.priority}`);
|
|
6223
6400
|
console.log("");
|
|
6224
|
-
|
|
6401
|
+
consola44.start(`Verifying IdP at ${result.idp}...`);
|
|
6225
6402
|
const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
|
|
6226
6403
|
if (!discoResp.ok) {
|
|
6227
|
-
|
|
6404
|
+
consola44.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
|
|
6228
6405
|
return;
|
|
6229
6406
|
}
|
|
6230
6407
|
const disco = await discoResp.json();
|
|
6231
|
-
|
|
6408
|
+
consola44.success(`IdP is reachable`);
|
|
6232
6409
|
console.log(` Issuer: ${disco.issuer}`);
|
|
6233
6410
|
console.log(` DDISA: v${disco.ddisa_version || "?"}`);
|
|
6234
6411
|
if (disco.ddisa_auth_methods_supported) {
|
|
@@ -6246,7 +6423,7 @@ var dnsCheckCommand = defineCommand51({
|
|
|
6246
6423
|
// src/commands/health.ts
|
|
6247
6424
|
import { exec } from "child_process";
|
|
6248
6425
|
import { promisify } from "util";
|
|
6249
|
-
import { defineCommand as
|
|
6426
|
+
import { defineCommand as defineCommand56 } from "citty";
|
|
6250
6427
|
var execAsync = promisify(exec);
|
|
6251
6428
|
async function resolveApeShellPath() {
|
|
6252
6429
|
try {
|
|
@@ -6282,7 +6459,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
6282
6459
|
}
|
|
6283
6460
|
}
|
|
6284
6461
|
async function runHealth(args) {
|
|
6285
|
-
const version = true ? "1.
|
|
6462
|
+
const version = true ? "1.7.0" : "0.0.0";
|
|
6286
6463
|
const auth = loadAuth();
|
|
6287
6464
|
if (!auth) {
|
|
6288
6465
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -6345,7 +6522,7 @@ async function runHealth(args) {
|
|
|
6345
6522
|
throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
|
|
6346
6523
|
}
|
|
6347
6524
|
}
|
|
6348
|
-
var healthCommand =
|
|
6525
|
+
var healthCommand = defineCommand56({
|
|
6349
6526
|
meta: {
|
|
6350
6527
|
name: "health",
|
|
6351
6528
|
description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
|
|
@@ -6363,8 +6540,8 @@ var healthCommand = defineCommand52({
|
|
|
6363
6540
|
});
|
|
6364
6541
|
|
|
6365
6542
|
// src/commands/workflows.ts
|
|
6366
|
-
import { defineCommand as
|
|
6367
|
-
import
|
|
6543
|
+
import { defineCommand as defineCommand57 } from "citty";
|
|
6544
|
+
import consola45 from "consola";
|
|
6368
6545
|
|
|
6369
6546
|
// src/guides/index.ts
|
|
6370
6547
|
var guides = [
|
|
@@ -6414,7 +6591,7 @@ var guides = [
|
|
|
6414
6591
|
];
|
|
6415
6592
|
|
|
6416
6593
|
// src/commands/workflows.ts
|
|
6417
|
-
var workflowsCommand =
|
|
6594
|
+
var workflowsCommand = defineCommand57({
|
|
6418
6595
|
meta: {
|
|
6419
6596
|
name: "workflows",
|
|
6420
6597
|
description: "Discover workflow guides"
|
|
@@ -6435,7 +6612,7 @@ var workflowsCommand = defineCommand53({
|
|
|
6435
6612
|
if (args.id) {
|
|
6436
6613
|
const guide = guides.find((g) => g.id === String(args.id));
|
|
6437
6614
|
if (!guide) {
|
|
6438
|
-
|
|
6615
|
+
consola45.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
|
|
6439
6616
|
throw new CliError(`Guide not found: ${args.id}`);
|
|
6440
6617
|
}
|
|
6441
6618
|
if (args.json) {
|
|
@@ -6478,7 +6655,7 @@ var workflowsCommand = defineCommand53({
|
|
|
6478
6655
|
import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "fs";
|
|
6479
6656
|
import { homedir as homedir13 } from "os";
|
|
6480
6657
|
import { join as join14 } from "path";
|
|
6481
|
-
import
|
|
6658
|
+
import consola46 from "consola";
|
|
6482
6659
|
var PACKAGE_NAME = "@openape/apes";
|
|
6483
6660
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
6484
6661
|
var CACHE_FILE = join14(homedir13(), ".config", "apes", ".version-check.json");
|
|
@@ -6523,7 +6700,7 @@ async function fetchLatestVersion() {
|
|
|
6523
6700
|
}
|
|
6524
6701
|
function warnIfBehind(currentVersion, latest) {
|
|
6525
6702
|
if (compareSemver(currentVersion, latest) < 0) {
|
|
6526
|
-
|
|
6703
|
+
consola46.warn(
|
|
6527
6704
|
`apes ${currentVersion} is behind latest @openape/apes@${latest}. Run \`npm i -g @openape/apes@latest\` to update. (Suppress with APES_NO_UPDATE_CHECK=1.)`
|
|
6528
6705
|
);
|
|
6529
6706
|
}
|
|
@@ -6555,10 +6732,10 @@ if (shellRewrite) {
|
|
|
6555
6732
|
if (shellRewrite.action === "rewrite") {
|
|
6556
6733
|
process.argv = shellRewrite.argv;
|
|
6557
6734
|
} else if (shellRewrite.action === "version") {
|
|
6558
|
-
console.log(`ape-shell ${"1.
|
|
6735
|
+
console.log(`ape-shell ${"1.7.0"} (OpenApe DDISA shell wrapper)`);
|
|
6559
6736
|
process.exit(0);
|
|
6560
6737
|
} else if (shellRewrite.action === "help") {
|
|
6561
|
-
console.log(`ape-shell ${"1.
|
|
6738
|
+
console.log(`ape-shell ${"1.7.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
6562
6739
|
console.log("");
|
|
6563
6740
|
console.log("Usage:");
|
|
6564
6741
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -6582,7 +6759,7 @@ if (shellRewrite) {
|
|
|
6582
6759
|
}
|
|
6583
6760
|
}
|
|
6584
6761
|
var debug = process.argv.includes("--debug");
|
|
6585
|
-
var grantsCommand =
|
|
6762
|
+
var grantsCommand = defineCommand58({
|
|
6586
6763
|
meta: {
|
|
6587
6764
|
name: "grants",
|
|
6588
6765
|
description: "Grant management"
|
|
@@ -6603,7 +6780,7 @@ var grantsCommand = defineCommand54({
|
|
|
6603
6780
|
"delegation-revoke": delegationRevokeCommand
|
|
6604
6781
|
}
|
|
6605
6782
|
});
|
|
6606
|
-
var configCommand =
|
|
6783
|
+
var configCommand = defineCommand58({
|
|
6607
6784
|
meta: {
|
|
6608
6785
|
name: "config",
|
|
6609
6786
|
description: "Configuration management"
|
|
@@ -6613,10 +6790,10 @@ var configCommand = defineCommand54({
|
|
|
6613
6790
|
set: configSetCommand
|
|
6614
6791
|
}
|
|
6615
6792
|
});
|
|
6616
|
-
var main =
|
|
6793
|
+
var main = defineCommand58({
|
|
6617
6794
|
meta: {
|
|
6618
6795
|
name: "apes",
|
|
6619
|
-
version: "1.
|
|
6796
|
+
version: "1.7.0",
|
|
6620
6797
|
description: "Unified CLI for OpenApe"
|
|
6621
6798
|
},
|
|
6622
6799
|
subCommands: {
|
|
@@ -6633,6 +6810,7 @@ var main = defineCommand54({
|
|
|
6633
6810
|
grants: grantsCommand,
|
|
6634
6811
|
agents: agentsCommand,
|
|
6635
6812
|
nest: nestCommand,
|
|
6813
|
+
yolo: yoloCommand,
|
|
6636
6814
|
admin: adminCommand,
|
|
6637
6815
|
run: runCommand,
|
|
6638
6816
|
proxy: proxyCommand,
|
|
@@ -6672,20 +6850,20 @@ async function maybeRefreshAuth() {
|
|
|
6672
6850
|
}
|
|
6673
6851
|
}
|
|
6674
6852
|
await maybeRefreshAuth();
|
|
6675
|
-
await maybeWarnStaleVersion("1.
|
|
6853
|
+
await maybeWarnStaleVersion("1.7.0").catch(() => {
|
|
6676
6854
|
});
|
|
6677
6855
|
runMain(main).catch((err) => {
|
|
6678
6856
|
if (err instanceof CliExit) {
|
|
6679
6857
|
process.exit(err.exitCode);
|
|
6680
6858
|
}
|
|
6681
6859
|
if (err instanceof CliError) {
|
|
6682
|
-
|
|
6860
|
+
consola47.error(err.message);
|
|
6683
6861
|
process.exit(err.exitCode);
|
|
6684
6862
|
}
|
|
6685
6863
|
if (debug) {
|
|
6686
|
-
|
|
6864
|
+
consola47.error(err);
|
|
6687
6865
|
} else {
|
|
6688
|
-
|
|
6866
|
+
consola47.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
|
|
6689
6867
|
}
|
|
6690
6868
|
process.exit(1);
|
|
6691
6869
|
});
|