@openape/apes 1.6.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -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";
|
|
@@ -1832,6 +1832,12 @@ done
|
|
|
1832
1832
|
return `#!/bin/bash
|
|
1833
1833
|
set -euo pipefail
|
|
1834
1834
|
|
|
1835
|
+
# escapes-spawned scripts inherit a minimal PATH that doesn't include
|
|
1836
|
+
# /usr/sbin \u2014 which is where chown / dscl / pwpolicy live. Force a
|
|
1837
|
+
# wide PATH so the privileged setup commands resolve without absolute
|
|
1838
|
+
# paths everywhere.
|
|
1839
|
+
export PATH="/usr/sbin:/usr/bin:/bin:/sbin:/opt/homebrew/bin:/usr/local/bin"
|
|
1840
|
+
|
|
1835
1841
|
NAME=${shQuote(name)}
|
|
1836
1842
|
HOME_DIR=${shQuote(homeDir)}
|
|
1837
1843
|
SHELL_PATH=${shQuote(shellPath)}
|
|
@@ -3921,6 +3927,7 @@ var agentsCommand = defineCommand28({
|
|
|
3921
3927
|
import { defineCommand as defineCommand34 } from "citty";
|
|
3922
3928
|
|
|
3923
3929
|
// src/commands/nest/authorize.ts
|
|
3930
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
3924
3931
|
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
|
|
3925
3932
|
import { join as join9 } from "path";
|
|
3926
3933
|
import { defineCommand as defineCommand30 } from "citty";
|
|
@@ -4020,8 +4027,8 @@ var DEFAULT_ALLOW_PATTERNS = [
|
|
|
4020
4027
|
// glob below limits the auto-approval to that exact lifecycle path
|
|
4021
4028
|
// — `bash *` would be unsafe.
|
|
4022
4029
|
"bash *apes-spawn-*setup.sh",
|
|
4023
|
-
// Bridge invocation the
|
|
4024
|
-
//
|
|
4030
|
+
// Bridge invocation the supervisor uses to keep agent processes
|
|
4031
|
+
// running. Pattern is intentionally precise — not a generic
|
|
4025
4032
|
// `apes run --as *` wildcard — so a compromised nest can't pivot
|
|
4026
4033
|
// to running arbitrary commands as arbitrary users.
|
|
4027
4034
|
"apes run --as * -- openape-chat-bridge"
|
|
@@ -4029,77 +4036,51 @@ var DEFAULT_ALLOW_PATTERNS = [
|
|
|
4029
4036
|
var authorizeNestCommand = defineCommand30({
|
|
4030
4037
|
meta: {
|
|
4031
4038
|
name: "authorize",
|
|
4032
|
-
description: "Set the YOLO-policy that lets the local nest spawn/destroy without per-call DDISA prompts"
|
|
4039
|
+
description: "Set the YOLO-policy that lets the local nest spawn/destroy without per-call DDISA prompts (wraps `apes yolo set`)"
|
|
4033
4040
|
},
|
|
4034
4041
|
args: {
|
|
4035
4042
|
"allow": {
|
|
4036
4043
|
type: "string",
|
|
4037
4044
|
description: "Override allow_patterns (comma-separated globs). Default: nest-managed agent lifecycle."
|
|
4038
4045
|
},
|
|
4039
|
-
"mode": {
|
|
4040
|
-
type: "string",
|
|
4041
|
-
description: "Policy mode (allow-list | deny-list). Default: allow-list \u2014 auto-approve only matched patterns."
|
|
4042
|
-
},
|
|
4043
4046
|
"expires-in": {
|
|
4044
4047
|
type: "string",
|
|
4045
4048
|
description: "Optional duration like 30d, 6h. Omit for no expiry."
|
|
4046
4049
|
}
|
|
4047
4050
|
},
|
|
4048
4051
|
async run({ args }) {
|
|
4049
|
-
const ownerAuth = loadAuth();
|
|
4050
|
-
if (!ownerAuth?.email || !ownerAuth.access_token) {
|
|
4051
|
-
throw new CliError("Run `apes login <email>` first \u2014 only the nest's owner can set its YOLO-policy.");
|
|
4052
|
-
}
|
|
4053
4052
|
const nestAuthPath = join9(NEST_DATA_DIR, ".config", "apes", "auth.json");
|
|
4054
4053
|
if (!existsSync11(nestAuthPath)) {
|
|
4055
4054
|
throw new CliError("Nest not enrolled. Run `apes nest enroll` first.");
|
|
4056
4055
|
}
|
|
4057
4056
|
const nestAuth = JSON.parse(readFileSync10(nestAuthPath, "utf8"));
|
|
4058
4057
|
if (!nestAuth.email) throw new CliError(`${nestAuthPath} has no email`);
|
|
4059
|
-
const
|
|
4060
|
-
|
|
4061
|
-
const
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
mode,
|
|
4078
|
-
allowPatterns,
|
|
4079
|
-
denyPatterns: [],
|
|
4080
|
-
expiresAt: expiresAt ?? null
|
|
4081
|
-
})
|
|
4082
|
-
});
|
|
4083
|
-
if (!res.ok) {
|
|
4084
|
-
const text = await res.text().catch(() => "");
|
|
4085
|
-
throw new CliError(`PUT /yolo-policy failed (${res.status}): ${text}`);
|
|
4058
|
+
const allow = args.allow ?? DEFAULT_ALLOW_PATTERNS.join(",");
|
|
4059
|
+
consola26.info(`Configuring YOLO-policy on ${nestAuth.email} via \`apes yolo set\`\u2026`);
|
|
4060
|
+
const cmdArgs = [
|
|
4061
|
+
"yolo",
|
|
4062
|
+
"set",
|
|
4063
|
+
nestAuth.email,
|
|
4064
|
+
"--mode",
|
|
4065
|
+
"allow-list",
|
|
4066
|
+
"--allow",
|
|
4067
|
+
allow
|
|
4068
|
+
];
|
|
4069
|
+
if (typeof args["expires-in"] === "string" && args["expires-in"]) {
|
|
4070
|
+
cmdArgs.push("--expires-in", args["expires-in"]);
|
|
4071
|
+
}
|
|
4072
|
+
try {
|
|
4073
|
+
execFileSync9("apes", cmdArgs, { stdio: "inherit" });
|
|
4074
|
+
} catch (err) {
|
|
4075
|
+
throw new CliError(err instanceof Error ? err.message : String(err));
|
|
4086
4076
|
}
|
|
4087
|
-
consola26.success("
|
|
4077
|
+
consola26.success("Nest-driven agent lifecycle is now zero-prompt.");
|
|
4088
4078
|
consola26.info("Test: apes agents spawn <name> via the nest API \u2192 no DDISA prompt.");
|
|
4089
4079
|
}
|
|
4090
4080
|
});
|
|
4091
|
-
function parseExpiresIn(s) {
|
|
4092
|
-
if (!s) return null;
|
|
4093
|
-
const m = s.match(/^(\d+)([hdw])$/);
|
|
4094
|
-
if (!m) throw new CliError(`Invalid --expires-in "${s}" \u2014 expected forms like 30d, 6h, 2w`);
|
|
4095
|
-
const n = Number(m[1]);
|
|
4096
|
-
const unit = m[2];
|
|
4097
|
-
const seconds = unit === "h" ? 3600 : unit === "d" ? 86400 : 7 * 86400;
|
|
4098
|
-
return Math.floor(Date.now() / 1e3) + n * seconds;
|
|
4099
|
-
}
|
|
4100
4081
|
|
|
4101
4082
|
// src/commands/nest/install.ts
|
|
4102
|
-
import { execFileSync as
|
|
4083
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
4103
4084
|
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
4104
4085
|
import { homedir as homedir11, userInfo as userInfo2 } from "os";
|
|
4105
4086
|
import { dirname as dirname3, join as join10 } from "path";
|
|
@@ -4276,10 +4257,10 @@ var installNestCommand = defineCommand31({
|
|
|
4276
4257
|
}
|
|
4277
4258
|
const uid = userInfo2().uid;
|
|
4278
4259
|
try {
|
|
4279
|
-
|
|
4260
|
+
execFileSync10("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore" });
|
|
4280
4261
|
} catch {
|
|
4281
4262
|
}
|
|
4282
|
-
|
|
4263
|
+
execFileSync10("/bin/launchctl", ["bootstrap", `gui/${uid}`, plistPath()], { stdio: "inherit" });
|
|
4283
4264
|
consola27.success(`Nest daemon bootstrapped \u2014 http://127.0.0.1:${port}`);
|
|
4284
4265
|
consola27.info("");
|
|
4285
4266
|
consola27.info("Next steps for zero-prompt spawn \u2014 both one-time:");
|
|
@@ -4346,7 +4327,7 @@ function humanDuration(sec) {
|
|
|
4346
4327
|
}
|
|
4347
4328
|
|
|
4348
4329
|
// src/commands/nest/uninstall.ts
|
|
4349
|
-
import { execFileSync as
|
|
4330
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
4350
4331
|
import { existsSync as existsSync13, unlinkSync } from "fs";
|
|
4351
4332
|
import { homedir as homedir12, userInfo as userInfo3 } from "os";
|
|
4352
4333
|
import { join as join11 } from "path";
|
|
@@ -4362,7 +4343,7 @@ var uninstallNestCommand = defineCommand33({
|
|
|
4362
4343
|
const uid = userInfo3().uid;
|
|
4363
4344
|
const path2 = join11(homedir12(), "Library", "LaunchAgents", `${PLIST_LABEL2}.plist`);
|
|
4364
4345
|
try {
|
|
4365
|
-
|
|
4346
|
+
execFileSync11("/bin/launchctl", ["bootout", `gui/${uid}/${PLIST_LABEL2}`], { stdio: "ignore" });
|
|
4366
4347
|
consola29.success("Nest daemon stopped");
|
|
4367
4348
|
} catch {
|
|
4368
4349
|
consola29.info("Nest daemon was not loaded");
|
|
@@ -4390,16 +4371,211 @@ var nestCommand = defineCommand34({
|
|
|
4390
4371
|
}
|
|
4391
4372
|
});
|
|
4392
4373
|
|
|
4393
|
-
// src/commands/
|
|
4374
|
+
// src/commands/yolo/index.ts
|
|
4375
|
+
import { defineCommand as defineCommand38 } from "citty";
|
|
4376
|
+
|
|
4377
|
+
// src/commands/yolo/clear.ts
|
|
4394
4378
|
import { defineCommand as defineCommand35 } from "citty";
|
|
4395
4379
|
import consola30 from "consola";
|
|
4396
|
-
var
|
|
4380
|
+
var yoloClearCommand = defineCommand35({
|
|
4381
|
+
meta: {
|
|
4382
|
+
name: "clear",
|
|
4383
|
+
description: "Remove the YOLO-policy from a DDISA agent (subsequent grants need human approval)"
|
|
4384
|
+
},
|
|
4385
|
+
args: {
|
|
4386
|
+
email: {
|
|
4387
|
+
type: "positional",
|
|
4388
|
+
description: "Target agent email",
|
|
4389
|
+
required: true
|
|
4390
|
+
}
|
|
4391
|
+
},
|
|
4392
|
+
async run({ args }) {
|
|
4393
|
+
const ownerAuth = loadAuth();
|
|
4394
|
+
if (!ownerAuth?.access_token) {
|
|
4395
|
+
throw new CliError("Run `apes login <email>` first.");
|
|
4396
|
+
}
|
|
4397
|
+
const idp = getIdpUrl();
|
|
4398
|
+
if (!idp) throw new CliError("No IdP configured.");
|
|
4399
|
+
const email = args.email;
|
|
4400
|
+
const url = `${idp}/api/users/${encodeURIComponent(email)}/yolo-policy`;
|
|
4401
|
+
const res = await fetch(url, {
|
|
4402
|
+
method: "DELETE",
|
|
4403
|
+
headers: { Authorization: `Bearer ${ownerAuth.access_token}` }
|
|
4404
|
+
});
|
|
4405
|
+
if (!res.ok && res.status !== 404) {
|
|
4406
|
+
const text = await res.text().catch(() => "");
|
|
4407
|
+
throw new CliError(`DELETE /yolo-policy failed (${res.status}): ${text}`);
|
|
4408
|
+
}
|
|
4409
|
+
consola30.success(`YOLO-policy cleared on ${email}`);
|
|
4410
|
+
}
|
|
4411
|
+
});
|
|
4412
|
+
|
|
4413
|
+
// src/commands/yolo/set.ts
|
|
4414
|
+
import { defineCommand as defineCommand36 } from "citty";
|
|
4415
|
+
import consola31 from "consola";
|
|
4416
|
+
var VALID_MODES = ["allow-list", "deny-list"];
|
|
4417
|
+
var yoloSetCommand = defineCommand36({
|
|
4418
|
+
meta: {
|
|
4419
|
+
name: "set",
|
|
4420
|
+
description: "Write a YOLO-policy on a DDISA agent you own"
|
|
4421
|
+
},
|
|
4422
|
+
args: {
|
|
4423
|
+
"email": {
|
|
4424
|
+
type: "positional",
|
|
4425
|
+
description: "Target agent email (e.g. nest-mac-cb6bf26a+patrick+example_com@id.openape.ai)",
|
|
4426
|
+
required: true
|
|
4427
|
+
},
|
|
4428
|
+
"mode": {
|
|
4429
|
+
type: "string",
|
|
4430
|
+
description: "Policy mode (allow-list | deny-list)"
|
|
4431
|
+
},
|
|
4432
|
+
"allow": {
|
|
4433
|
+
type: "string",
|
|
4434
|
+
description: 'Allow patterns \u2014 comma-separated bash globs (e.g. "apes agents spawn *,apes agents sync")'
|
|
4435
|
+
},
|
|
4436
|
+
"deny": {
|
|
4437
|
+
type: "string",
|
|
4438
|
+
description: "Deny patterns \u2014 comma-separated bash globs"
|
|
4439
|
+
},
|
|
4440
|
+
"deny-risk": {
|
|
4441
|
+
type: "string",
|
|
4442
|
+
description: "Deny grants at this risk level or above (low|medium|high|critical)"
|
|
4443
|
+
},
|
|
4444
|
+
"expires-in": {
|
|
4445
|
+
type: "string",
|
|
4446
|
+
description: "Optional expiry like 30d, 6h, 2w. Omit for no expiry."
|
|
4447
|
+
}
|
|
4448
|
+
},
|
|
4449
|
+
async run({ args }) {
|
|
4450
|
+
const ownerAuth = loadAuth();
|
|
4451
|
+
if (!ownerAuth?.access_token) {
|
|
4452
|
+
throw new CliError("Run `apes login <email>` first.");
|
|
4453
|
+
}
|
|
4454
|
+
const idp = getIdpUrl();
|
|
4455
|
+
if (!idp) throw new CliError("No IdP configured.");
|
|
4456
|
+
const email = args.email;
|
|
4457
|
+
const mode = args.mode ?? "allow-list";
|
|
4458
|
+
if (!VALID_MODES.includes(mode)) {
|
|
4459
|
+
throw new CliError(`mode must be one of: ${VALID_MODES.join(", ")}`);
|
|
4460
|
+
}
|
|
4461
|
+
const allowPatterns = parseList(args.allow);
|
|
4462
|
+
const denyPatterns = parseList(args.deny);
|
|
4463
|
+
const denyRiskThreshold = args["deny-risk"] ?? null;
|
|
4464
|
+
const expiresAt = parseExpiresIn(args["expires-in"]);
|
|
4465
|
+
consola31.info(`Setting YOLO-policy on ${email}`);
|
|
4466
|
+
consola31.info(` mode: ${mode}`);
|
|
4467
|
+
if (allowPatterns.length) consola31.info(` allow_patterns: ${allowPatterns.join(", ")}`);
|
|
4468
|
+
if (denyPatterns.length) consola31.info(` deny_patterns: ${denyPatterns.join(", ")}`);
|
|
4469
|
+
if (denyRiskThreshold) consola31.info(` deny_risk: ${denyRiskThreshold}`);
|
|
4470
|
+
if (expiresAt) consola31.info(` expires_at: ${new Date(expiresAt * 1e3).toISOString()}`);
|
|
4471
|
+
const url = `${idp}/api/users/${encodeURIComponent(email)}/yolo-policy`;
|
|
4472
|
+
const res = await fetch(url, {
|
|
4473
|
+
method: "PUT",
|
|
4474
|
+
headers: {
|
|
4475
|
+
"Authorization": `Bearer ${ownerAuth.access_token}`,
|
|
4476
|
+
"Content-Type": "application/json"
|
|
4477
|
+
},
|
|
4478
|
+
body: JSON.stringify({
|
|
4479
|
+
mode,
|
|
4480
|
+
allowPatterns,
|
|
4481
|
+
denyPatterns,
|
|
4482
|
+
denyRiskThreshold,
|
|
4483
|
+
expiresAt: expiresAt ?? null
|
|
4484
|
+
})
|
|
4485
|
+
});
|
|
4486
|
+
if (!res.ok) {
|
|
4487
|
+
const text = await res.text().catch(() => "");
|
|
4488
|
+
throw new CliError(`PUT /yolo-policy failed (${res.status}): ${text}`);
|
|
4489
|
+
}
|
|
4490
|
+
consola31.success(`YOLO-policy applied to ${email}`);
|
|
4491
|
+
}
|
|
4492
|
+
});
|
|
4493
|
+
function parseList(s) {
|
|
4494
|
+
if (!s) return [];
|
|
4495
|
+
return s.split(",").map((p) => p.trim()).filter(Boolean);
|
|
4496
|
+
}
|
|
4497
|
+
function parseExpiresIn(s) {
|
|
4498
|
+
if (!s) return null;
|
|
4499
|
+
const m = s.match(/^(\d+)([hdw])$/);
|
|
4500
|
+
if (!m) throw new CliError(`Invalid --expires-in "${s}" \u2014 expected forms like 30d, 6h, 2w`);
|
|
4501
|
+
const n = Number(m[1]);
|
|
4502
|
+
const unit = m[2];
|
|
4503
|
+
const seconds = unit === "h" ? 3600 : unit === "d" ? 86400 : 7 * 86400;
|
|
4504
|
+
return Math.floor(Date.now() / 1e3) + n * seconds;
|
|
4505
|
+
}
|
|
4506
|
+
|
|
4507
|
+
// src/commands/yolo/show.ts
|
|
4508
|
+
import { defineCommand as defineCommand37 } from "citty";
|
|
4509
|
+
import consola32 from "consola";
|
|
4510
|
+
var yoloShowCommand = defineCommand37({
|
|
4511
|
+
meta: {
|
|
4512
|
+
name: "show",
|
|
4513
|
+
description: "Print the YOLO-policy currently set on a DDISA agent"
|
|
4514
|
+
},
|
|
4515
|
+
args: {
|
|
4516
|
+
email: {
|
|
4517
|
+
type: "positional",
|
|
4518
|
+
description: "Target agent email",
|
|
4519
|
+
required: true
|
|
4520
|
+
},
|
|
4521
|
+
json: {
|
|
4522
|
+
type: "boolean",
|
|
4523
|
+
description: "JSON output for scripts"
|
|
4524
|
+
}
|
|
4525
|
+
},
|
|
4526
|
+
async run({ args }) {
|
|
4527
|
+
const ownerAuth = loadAuth();
|
|
4528
|
+
if (!ownerAuth?.access_token) {
|
|
4529
|
+
throw new CliError("Run `apes login <email>` first.");
|
|
4530
|
+
}
|
|
4531
|
+
const idp = getIdpUrl();
|
|
4532
|
+
if (!idp) throw new CliError("No IdP configured.");
|
|
4533
|
+
const email = args.email;
|
|
4534
|
+
const url = `${idp}/api/users/${encodeURIComponent(email)}/yolo-policy`;
|
|
4535
|
+
const res = await fetch(url, {
|
|
4536
|
+
headers: { Authorization: `Bearer ${ownerAuth.access_token}` }
|
|
4537
|
+
});
|
|
4538
|
+
if (!res.ok) {
|
|
4539
|
+
const text = await res.text().catch(() => "");
|
|
4540
|
+
throw new CliError(`GET /yolo-policy failed (${res.status}): ${text}`);
|
|
4541
|
+
}
|
|
4542
|
+
const policy = await res.json();
|
|
4543
|
+
if (args.json) {
|
|
4544
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
4545
|
+
return;
|
|
4546
|
+
}
|
|
4547
|
+
consola32.info(`YOLO-policy for ${email}`);
|
|
4548
|
+
consola32.info(` mode: ${policy.mode}`);
|
|
4549
|
+
consola32.info(` allow_patterns: ${policy.allowPatterns.length ? policy.allowPatterns.join(", ") : "(none)"}`);
|
|
4550
|
+
consola32.info(` deny_patterns: ${policy.denyPatterns.length ? policy.denyPatterns.join(", ") : "(none)"}`);
|
|
4551
|
+
consola32.info(` deny_risk: ${policy.denyRiskThreshold ?? "(none)"}`);
|
|
4552
|
+
consola32.info(` expires_at: ${policy.expiresAt ? new Date(policy.expiresAt * 1e3).toISOString() : "(never)"}`);
|
|
4553
|
+
}
|
|
4554
|
+
});
|
|
4555
|
+
|
|
4556
|
+
// src/commands/yolo/index.ts
|
|
4557
|
+
var yoloCommand = defineCommand38({
|
|
4558
|
+
meta: {
|
|
4559
|
+
name: "yolo",
|
|
4560
|
+
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)."
|
|
4561
|
+
},
|
|
4562
|
+
subCommands: {
|
|
4563
|
+
set: yoloSetCommand,
|
|
4564
|
+
show: yoloShowCommand,
|
|
4565
|
+
clear: yoloClearCommand
|
|
4566
|
+
}
|
|
4567
|
+
});
|
|
4568
|
+
|
|
4569
|
+
// src/commands/adapter/index.ts
|
|
4570
|
+
import { defineCommand as defineCommand39 } from "citty";
|
|
4571
|
+
import consola33 from "consola";
|
|
4572
|
+
var adapterCommand = defineCommand39({
|
|
4397
4573
|
meta: {
|
|
4398
4574
|
name: "adapter",
|
|
4399
4575
|
description: "Manage CLI adapters"
|
|
4400
4576
|
},
|
|
4401
4577
|
subCommands: {
|
|
4402
|
-
list:
|
|
4578
|
+
list: defineCommand39({
|
|
4403
4579
|
meta: {
|
|
4404
4580
|
name: "list",
|
|
4405
4581
|
description: "List available adapters"
|
|
@@ -4430,7 +4606,7 @@ var adapterCommand = defineCommand35({
|
|
|
4430
4606
|
`);
|
|
4431
4607
|
return;
|
|
4432
4608
|
}
|
|
4433
|
-
|
|
4609
|
+
consola33.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
|
|
4434
4610
|
for (const a of index2.adapters) {
|
|
4435
4611
|
const installed = isInstalled(a.id, false) ? " [installed]" : "";
|
|
4436
4612
|
console.log(` ${a.id.padEnd(12)} ${a.name.padEnd(24)} ${a.category}${installed}`);
|
|
@@ -4452,7 +4628,7 @@ var adapterCommand = defineCommand35({
|
|
|
4452
4628
|
return;
|
|
4453
4629
|
}
|
|
4454
4630
|
if (local.length === 0) {
|
|
4455
|
-
|
|
4631
|
+
consola33.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
|
|
4456
4632
|
return;
|
|
4457
4633
|
}
|
|
4458
4634
|
for (const a of local) {
|
|
@@ -4460,7 +4636,7 @@ var adapterCommand = defineCommand35({
|
|
|
4460
4636
|
}
|
|
4461
4637
|
}
|
|
4462
4638
|
}),
|
|
4463
|
-
install:
|
|
4639
|
+
install: defineCommand39({
|
|
4464
4640
|
meta: {
|
|
4465
4641
|
name: "install",
|
|
4466
4642
|
description: "Install an adapter from the registry"
|
|
@@ -4489,24 +4665,24 @@ var adapterCommand = defineCommand35({
|
|
|
4489
4665
|
for (const id of ids) {
|
|
4490
4666
|
const entry = findAdapter(index, id);
|
|
4491
4667
|
if (!entry) {
|
|
4492
|
-
|
|
4668
|
+
consola33.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
|
|
4493
4669
|
continue;
|
|
4494
4670
|
}
|
|
4495
4671
|
const conflicts = findConflictingAdapters(entry.executable, id);
|
|
4496
4672
|
if (conflicts.length > 0) {
|
|
4497
4673
|
for (const c of conflicts) {
|
|
4498
|
-
|
|
4499
|
-
|
|
4674
|
+
consola33.warn(`Conflicting adapter found: ${c.path} (id: ${c.adapterId}, executable: ${c.executable})`);
|
|
4675
|
+
consola33.warn(` Remove it with: apes adapter remove ${c.adapterId}`);
|
|
4500
4676
|
}
|
|
4501
4677
|
}
|
|
4502
4678
|
const result = await installAdapter(entry, { local });
|
|
4503
4679
|
const verb = result.updated ? "Updated" : "Installed";
|
|
4504
|
-
|
|
4505
|
-
|
|
4680
|
+
consola33.success(`${verb} ${result.id} \u2192 ${result.path}`);
|
|
4681
|
+
consola33.info(`Digest: ${result.digest}`);
|
|
4506
4682
|
}
|
|
4507
4683
|
}
|
|
4508
4684
|
}),
|
|
4509
|
-
remove:
|
|
4685
|
+
remove: defineCommand39({
|
|
4510
4686
|
meta: {
|
|
4511
4687
|
name: "remove",
|
|
4512
4688
|
description: "Remove an installed adapter"
|
|
@@ -4529,9 +4705,9 @@ var adapterCommand = defineCommand35({
|
|
|
4529
4705
|
let failed = false;
|
|
4530
4706
|
for (const id of ids) {
|
|
4531
4707
|
if (removeAdapter(id, local)) {
|
|
4532
|
-
|
|
4708
|
+
consola33.success(`Removed adapter: ${id}`);
|
|
4533
4709
|
} else {
|
|
4534
|
-
|
|
4710
|
+
consola33.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
4535
4711
|
failed = true;
|
|
4536
4712
|
}
|
|
4537
4713
|
}
|
|
@@ -4539,7 +4715,7 @@ var adapterCommand = defineCommand35({
|
|
|
4539
4715
|
throw new CliError("Some adapters could not be removed");
|
|
4540
4716
|
}
|
|
4541
4717
|
}),
|
|
4542
|
-
info:
|
|
4718
|
+
info: defineCommand39({
|
|
4543
4719
|
meta: {
|
|
4544
4720
|
name: "info",
|
|
4545
4721
|
description: "Show detailed adapter information"
|
|
@@ -4581,7 +4757,7 @@ var adapterCommand = defineCommand35({
|
|
|
4581
4757
|
}
|
|
4582
4758
|
}
|
|
4583
4759
|
}),
|
|
4584
|
-
search:
|
|
4760
|
+
search: defineCommand39({
|
|
4585
4761
|
meta: {
|
|
4586
4762
|
name: "search",
|
|
4587
4763
|
description: "Search adapters in the registry"
|
|
@@ -4613,7 +4789,7 @@ var adapterCommand = defineCommand35({
|
|
|
4613
4789
|
return;
|
|
4614
4790
|
}
|
|
4615
4791
|
if (results.length === 0) {
|
|
4616
|
-
|
|
4792
|
+
consola33.info(`No adapters matching "${query}"`);
|
|
4617
4793
|
return;
|
|
4618
4794
|
}
|
|
4619
4795
|
for (const a of results) {
|
|
@@ -4622,7 +4798,7 @@ var adapterCommand = defineCommand35({
|
|
|
4622
4798
|
}
|
|
4623
4799
|
}
|
|
4624
4800
|
}),
|
|
4625
|
-
update:
|
|
4801
|
+
update: defineCommand39({
|
|
4626
4802
|
meta: {
|
|
4627
4803
|
name: "update",
|
|
4628
4804
|
description: "Update installed adapters"
|
|
@@ -4648,33 +4824,33 @@ var adapterCommand = defineCommand35({
|
|
|
4648
4824
|
const targetId = args.id ? String(args.id) : void 0;
|
|
4649
4825
|
const targets = targetId ? [targetId] : index.adapters.map((a) => a.id).filter((id) => isInstalled(id, false));
|
|
4650
4826
|
if (targets.length === 0) {
|
|
4651
|
-
|
|
4827
|
+
consola33.info("No adapters installed to update.");
|
|
4652
4828
|
return;
|
|
4653
4829
|
}
|
|
4654
4830
|
for (const id of targets) {
|
|
4655
4831
|
const entry = findAdapter(index, id);
|
|
4656
4832
|
if (!entry) {
|
|
4657
|
-
|
|
4833
|
+
consola33.warn(`${id}: not found in registry, skipping`);
|
|
4658
4834
|
continue;
|
|
4659
4835
|
}
|
|
4660
4836
|
const localDigest = getInstalledDigest(id, false);
|
|
4661
4837
|
if (localDigest === entry.digest) {
|
|
4662
|
-
|
|
4838
|
+
consola33.info(`${id}: already up to date`);
|
|
4663
4839
|
continue;
|
|
4664
4840
|
}
|
|
4665
4841
|
if (localDigest && !args.yes) {
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4842
|
+
consola33.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
|
|
4843
|
+
consola33.info(` Old: ${localDigest}`);
|
|
4844
|
+
consola33.info(` New: ${entry.digest}`);
|
|
4845
|
+
consola33.info(" Use --yes to confirm");
|
|
4670
4846
|
continue;
|
|
4671
4847
|
}
|
|
4672
4848
|
const result = await installAdapter(entry);
|
|
4673
|
-
|
|
4849
|
+
consola33.success(`Updated ${result.id} \u2192 ${result.path}`);
|
|
4674
4850
|
}
|
|
4675
4851
|
}
|
|
4676
4852
|
}),
|
|
4677
|
-
verify:
|
|
4853
|
+
verify: defineCommand39({
|
|
4678
4854
|
meta: {
|
|
4679
4855
|
name: "verify",
|
|
4680
4856
|
description: "Verify installed adapter against registry digest"
|
|
@@ -4707,7 +4883,7 @@ var adapterCommand = defineCommand35({
|
|
|
4707
4883
|
if (!localDigest)
|
|
4708
4884
|
throw new Error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
4709
4885
|
if (localDigest === entry.digest) {
|
|
4710
|
-
|
|
4886
|
+
consola33.success(`${id}: digest matches registry`);
|
|
4711
4887
|
} else {
|
|
4712
4888
|
console.log(` Local: ${localDigest}`);
|
|
4713
4889
|
console.log(` Registry: ${entry.digest}`);
|
|
@@ -4719,11 +4895,11 @@ var adapterCommand = defineCommand35({
|
|
|
4719
4895
|
});
|
|
4720
4896
|
|
|
4721
4897
|
// src/commands/run.ts
|
|
4722
|
-
import { execFileSync as
|
|
4898
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
4723
4899
|
import { hostname as hostname5 } from "os";
|
|
4724
4900
|
import { basename } from "path";
|
|
4725
|
-
import { defineCommand as
|
|
4726
|
-
import
|
|
4901
|
+
import { defineCommand as defineCommand40 } from "citty";
|
|
4902
|
+
import consola34 from "consola";
|
|
4727
4903
|
function shouldWaitForGrant(args) {
|
|
4728
4904
|
return args.wait === true || process.env.APE_WAIT === "1";
|
|
4729
4905
|
}
|
|
@@ -4760,7 +4936,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4760
4936
|
const statusCmd = `apes grants status ${grant.id}`;
|
|
4761
4937
|
const executeCmd = `apes grants run ${grant.id}`;
|
|
4762
4938
|
if (mode === "human") {
|
|
4763
|
-
|
|
4939
|
+
consola34.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
|
|
4764
4940
|
console.log(` Approve in browser: ${approveUrl}`);
|
|
4765
4941
|
console.log(` Check status: ${statusCmd}`);
|
|
4766
4942
|
console.log(` Run after approval: ${executeCmd}`);
|
|
@@ -4770,7 +4946,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4770
4946
|
return;
|
|
4771
4947
|
}
|
|
4772
4948
|
const maxMin = getPollMaxMinutes();
|
|
4773
|
-
|
|
4949
|
+
consola34.success(`Grant ${grant.id} created (pending approval)`);
|
|
4774
4950
|
console.log(` Approve: ${approveUrl}`);
|
|
4775
4951
|
console.log(` Status: ${statusCmd} [--json]`);
|
|
4776
4952
|
console.log(` Execute: ${executeCmd} --wait`);
|
|
@@ -4792,7 +4968,7 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
4792
4968
|
console.log(' Tip: Approve as "timed" or "always" in the browser to let this');
|
|
4793
4969
|
console.log(" grant be reused on subsequent invocations without re-approval.");
|
|
4794
4970
|
}
|
|
4795
|
-
var runCommand =
|
|
4971
|
+
var runCommand = defineCommand40({
|
|
4796
4972
|
meta: {
|
|
4797
4973
|
name: "run",
|
|
4798
4974
|
description: "Execute a grant-secured command"
|
|
@@ -4895,7 +5071,7 @@ async function runShellMode(command, args) {
|
|
|
4895
5071
|
}
|
|
4896
5072
|
} catch {
|
|
4897
5073
|
}
|
|
4898
|
-
|
|
5074
|
+
consola34.info(`Requesting ape-shell session grant on ${targetHost}`);
|
|
4899
5075
|
const grant = await apiFetch(grantsUrl, {
|
|
4900
5076
|
method: "POST",
|
|
4901
5077
|
body: {
|
|
@@ -4915,8 +5091,8 @@ async function runShellMode(command, args) {
|
|
|
4915
5091
|
host: targetHost
|
|
4916
5092
|
});
|
|
4917
5093
|
if (shouldWaitForGrant(args)) {
|
|
4918
|
-
|
|
4919
|
-
|
|
5094
|
+
consola34.info(`Grant requested: ${grant.id}`);
|
|
5095
|
+
consola34.info("Waiting for approval...");
|
|
4920
5096
|
const maxWait = 3e5;
|
|
4921
5097
|
const interval = 3e3;
|
|
4922
5098
|
const start = Date.now();
|
|
@@ -4947,13 +5123,13 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4947
5123
|
try {
|
|
4948
5124
|
resolved = await resolveCommand(loaded, [normalizedExecutable, ...parsed.argv]);
|
|
4949
5125
|
} catch (err) {
|
|
4950
|
-
|
|
5126
|
+
consola34.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
|
|
4951
5127
|
return false;
|
|
4952
5128
|
}
|
|
4953
5129
|
try {
|
|
4954
5130
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
4955
5131
|
if (existingGrantId) {
|
|
4956
|
-
|
|
5132
|
+
consola34.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
|
|
4957
5133
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
4958
5134
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
4959
5135
|
return true;
|
|
@@ -4961,7 +5137,7 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4961
5137
|
} catch {
|
|
4962
5138
|
}
|
|
4963
5139
|
const approval = args.approval ?? "once";
|
|
4964
|
-
|
|
5140
|
+
consola34.info(`Requesting grant for: ${resolved.detail.display}`);
|
|
4965
5141
|
const grant = await createShapesGrant(resolved, {
|
|
4966
5142
|
idp,
|
|
4967
5143
|
approval,
|
|
@@ -4969,8 +5145,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4969
5145
|
});
|
|
4970
5146
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
4971
5147
|
const n = grant.similar_grants.similar_grants.length;
|
|
4972
|
-
|
|
4973
|
-
|
|
5148
|
+
consola34.info("");
|
|
5149
|
+
consola34.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
4974
5150
|
}
|
|
4975
5151
|
notifyGrantPending({
|
|
4976
5152
|
grantId: grant.id,
|
|
@@ -4980,8 +5156,8 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
4980
5156
|
host: args.host || hostname5()
|
|
4981
5157
|
});
|
|
4982
5158
|
if (shouldWaitForGrant(args)) {
|
|
4983
|
-
|
|
4984
|
-
|
|
5159
|
+
consola34.info(`Grant requested: ${grant.id}`);
|
|
5160
|
+
consola34.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
4985
5161
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
4986
5162
|
if (status !== "approved")
|
|
4987
5163
|
throw new CliError(`Grant ${status}`);
|
|
@@ -4997,7 +5173,7 @@ function execShellCommand(command) {
|
|
|
4997
5173
|
throw new CliError("No command to execute");
|
|
4998
5174
|
try {
|
|
4999
5175
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
5000
|
-
|
|
5176
|
+
execFileSync12(command[0], command.slice(1), {
|
|
5001
5177
|
stdio: "inherit",
|
|
5002
5178
|
env: inheritedEnv
|
|
5003
5179
|
});
|
|
@@ -5055,7 +5231,7 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
5055
5231
|
try {
|
|
5056
5232
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
5057
5233
|
if (existingGrantId) {
|
|
5058
|
-
|
|
5234
|
+
consola34.info(`Reusing existing grant: ${existingGrantId}`);
|
|
5059
5235
|
const token = await fetchGrantToken(idp, existingGrantId);
|
|
5060
5236
|
await verifyAndExecute(token, resolved, existingGrantId);
|
|
5061
5237
|
return;
|
|
@@ -5069,17 +5245,17 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
5069
5245
|
});
|
|
5070
5246
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
5071
5247
|
const n = grant.similar_grants.similar_grants.length;
|
|
5072
|
-
|
|
5073
|
-
|
|
5248
|
+
consola34.info("");
|
|
5249
|
+
consola34.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
5074
5250
|
if (grant.similar_grants.widened_details?.length) {
|
|
5075
5251
|
const wider = grant.similar_grants.widened_details.map((d) => d.permission).join(", ");
|
|
5076
|
-
|
|
5252
|
+
consola34.info(` Broader scope: ${wider}`);
|
|
5077
5253
|
}
|
|
5078
|
-
|
|
5254
|
+
consola34.info("");
|
|
5079
5255
|
}
|
|
5080
5256
|
if (shouldWaitForGrant(args)) {
|
|
5081
|
-
|
|
5082
|
-
|
|
5257
|
+
consola34.info(`Grant requested: ${grant.id}`);
|
|
5258
|
+
consola34.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
5083
5259
|
const status = await waitForGrantStatus(idp, grant.id);
|
|
5084
5260
|
if (status !== "approved")
|
|
5085
5261
|
throw new Error(`Grant ${status}`);
|
|
@@ -5099,7 +5275,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5099
5275
|
const grantsUrl = await getGrantsEndpoint(idp);
|
|
5100
5276
|
const command = action.split(" ");
|
|
5101
5277
|
const targetHost = args.host || hostname5();
|
|
5102
|
-
|
|
5278
|
+
consola34.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
|
|
5103
5279
|
const grant = await apiFetch(grantsUrl, {
|
|
5104
5280
|
method: "POST",
|
|
5105
5281
|
body: {
|
|
@@ -5116,9 +5292,9 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5116
5292
|
printPendingGrantInfo(grant, idp);
|
|
5117
5293
|
throw new CliExit(getAsyncExitCode());
|
|
5118
5294
|
}
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5295
|
+
consola34.success(`Grant requested: ${grant.id}`);
|
|
5296
|
+
consola34.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
5297
|
+
consola34.info("Waiting for approval...");
|
|
5122
5298
|
const maxWait = 15 * 60 * 1e3;
|
|
5123
5299
|
const interval = 3e3;
|
|
5124
5300
|
const start = Date.now();
|
|
@@ -5126,7 +5302,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5126
5302
|
while (Date.now() - start < maxWait) {
|
|
5127
5303
|
const status = await apiFetch(`${grantsUrl}/${grant.id}`);
|
|
5128
5304
|
if (status.status === "approved") {
|
|
5129
|
-
|
|
5305
|
+
consola34.success("Grant approved!");
|
|
5130
5306
|
approved = true;
|
|
5131
5307
|
break;
|
|
5132
5308
|
}
|
|
@@ -5141,15 +5317,15 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5141
5317
|
`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.`
|
|
5142
5318
|
);
|
|
5143
5319
|
}
|
|
5144
|
-
|
|
5320
|
+
consola34.info("Fetching grant token...");
|
|
5145
5321
|
const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, {
|
|
5146
5322
|
method: "POST"
|
|
5147
5323
|
});
|
|
5148
5324
|
if (audience === "escapes") {
|
|
5149
|
-
|
|
5325
|
+
consola34.info(`Executing: ${command.join(" ")}`);
|
|
5150
5326
|
try {
|
|
5151
5327
|
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
5152
|
-
|
|
5328
|
+
execFileSync12(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
|
|
5153
5329
|
stdio: "inherit",
|
|
5154
5330
|
env: inheritedEnv
|
|
5155
5331
|
});
|
|
@@ -5164,8 +5340,8 @@ async function runAudienceMode(audience, action, args) {
|
|
|
5164
5340
|
|
|
5165
5341
|
// src/commands/proxy.ts
|
|
5166
5342
|
import { spawn as spawn2 } from "child_process";
|
|
5167
|
-
import { defineCommand as
|
|
5168
|
-
import
|
|
5343
|
+
import { defineCommand as defineCommand41 } from "citty";
|
|
5344
|
+
import consola35 from "consola";
|
|
5169
5345
|
|
|
5170
5346
|
// src/proxy/config.ts
|
|
5171
5347
|
function buildDefaultProxyConfigToml(opts) {
|
|
@@ -5308,10 +5484,10 @@ function resolveProxyConfigOptions() {
|
|
|
5308
5484
|
77
|
|
5309
5485
|
);
|
|
5310
5486
|
}
|
|
5311
|
-
|
|
5487
|
+
consola35.info(`[apes proxy] IdP-mediated mode \u2014 agent=${auth.email}, idp=${auth.idp}`);
|
|
5312
5488
|
return { agentEmail: auth.email, idpUrl: auth.idp, mediated: true };
|
|
5313
5489
|
}
|
|
5314
|
-
var proxyCommand =
|
|
5490
|
+
var proxyCommand = defineCommand41({
|
|
5315
5491
|
meta: {
|
|
5316
5492
|
name: "proxy",
|
|
5317
5493
|
description: "Run a command with HTTPS_PROXY routed through the OpenApe egress proxy."
|
|
@@ -5333,12 +5509,12 @@ var proxyCommand = defineCommand37({
|
|
|
5333
5509
|
let close = null;
|
|
5334
5510
|
if (reuseUrl) {
|
|
5335
5511
|
proxyUrl = reuseUrl;
|
|
5336
|
-
|
|
5512
|
+
consola35.info(`[apes proxy] reusing existing proxy at ${proxyUrl}`);
|
|
5337
5513
|
} else {
|
|
5338
5514
|
const ephemeral = await startEphemeralProxy(buildDefaultProxyConfigToml(resolveProxyConfigOptions()));
|
|
5339
5515
|
proxyUrl = ephemeral.url;
|
|
5340
5516
|
close = ephemeral.close;
|
|
5341
|
-
|
|
5517
|
+
consola35.info(`[apes proxy] started ephemeral proxy at ${proxyUrl}`);
|
|
5342
5518
|
}
|
|
5343
5519
|
const noProxy = process.env.NO_PROXY ?? process.env.no_proxy ?? "127.0.0.1,localhost";
|
|
5344
5520
|
const childEnv = {
|
|
@@ -5370,7 +5546,7 @@ var proxyCommand = defineCommand37({
|
|
|
5370
5546
|
else resolveExit(code ?? 0);
|
|
5371
5547
|
});
|
|
5372
5548
|
child.once("error", (err) => {
|
|
5373
|
-
|
|
5549
|
+
consola35.error(`[apes proxy] failed to spawn '${wrapped[0]}':`, err.message);
|
|
5374
5550
|
resolveExit(127);
|
|
5375
5551
|
});
|
|
5376
5552
|
});
|
|
@@ -5384,8 +5560,8 @@ function signalNumber(signal) {
|
|
|
5384
5560
|
}
|
|
5385
5561
|
|
|
5386
5562
|
// src/commands/explain.ts
|
|
5387
|
-
import { defineCommand as
|
|
5388
|
-
var explainCommand =
|
|
5563
|
+
import { defineCommand as defineCommand42 } from "citty";
|
|
5564
|
+
var explainCommand = defineCommand42({
|
|
5389
5565
|
meta: {
|
|
5390
5566
|
name: "explain",
|
|
5391
5567
|
description: "Show what permission a command would need"
|
|
@@ -5423,9 +5599,9 @@ var explainCommand = defineCommand38({
|
|
|
5423
5599
|
});
|
|
5424
5600
|
|
|
5425
5601
|
// src/commands/config/get.ts
|
|
5426
|
-
import { defineCommand as
|
|
5427
|
-
import
|
|
5428
|
-
var configGetCommand =
|
|
5602
|
+
import { defineCommand as defineCommand43 } from "citty";
|
|
5603
|
+
import consola36 from "consola";
|
|
5604
|
+
var configGetCommand = defineCommand43({
|
|
5429
5605
|
meta: {
|
|
5430
5606
|
name: "get",
|
|
5431
5607
|
description: "Get a configuration value"
|
|
@@ -5445,7 +5621,7 @@ var configGetCommand = defineCommand39({
|
|
|
5445
5621
|
if (idp)
|
|
5446
5622
|
console.log(idp);
|
|
5447
5623
|
else
|
|
5448
|
-
|
|
5624
|
+
consola36.info("No IdP configured.");
|
|
5449
5625
|
break;
|
|
5450
5626
|
}
|
|
5451
5627
|
case "email": {
|
|
@@ -5453,7 +5629,7 @@ var configGetCommand = defineCommand39({
|
|
|
5453
5629
|
if (auth?.email)
|
|
5454
5630
|
console.log(auth.email);
|
|
5455
5631
|
else
|
|
5456
|
-
|
|
5632
|
+
consola36.info("Not logged in.");
|
|
5457
5633
|
break;
|
|
5458
5634
|
}
|
|
5459
5635
|
default: {
|
|
@@ -5466,7 +5642,7 @@ var configGetCommand = defineCommand39({
|
|
|
5466
5642
|
if (sectionObj && field in sectionObj) {
|
|
5467
5643
|
console.log(sectionObj[field]);
|
|
5468
5644
|
} else {
|
|
5469
|
-
|
|
5645
|
+
consola36.info(`Key "${key}" not set.`);
|
|
5470
5646
|
}
|
|
5471
5647
|
} else {
|
|
5472
5648
|
throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
|
|
@@ -5477,9 +5653,9 @@ var configGetCommand = defineCommand39({
|
|
|
5477
5653
|
});
|
|
5478
5654
|
|
|
5479
5655
|
// src/commands/config/set.ts
|
|
5480
|
-
import { defineCommand as
|
|
5481
|
-
import
|
|
5482
|
-
var configSetCommand =
|
|
5656
|
+
import { defineCommand as defineCommand44 } from "citty";
|
|
5657
|
+
import consola37 from "consola";
|
|
5658
|
+
var configSetCommand = defineCommand44({
|
|
5483
5659
|
meta: {
|
|
5484
5660
|
name: "set",
|
|
5485
5661
|
description: "Set a configuration value"
|
|
@@ -5515,12 +5691,12 @@ var configSetCommand = defineCommand40({
|
|
|
5515
5691
|
throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
|
|
5516
5692
|
}
|
|
5517
5693
|
saveConfig(config);
|
|
5518
|
-
|
|
5694
|
+
consola37.success(`Set ${key} = ${value}`);
|
|
5519
5695
|
}
|
|
5520
5696
|
});
|
|
5521
5697
|
|
|
5522
5698
|
// src/commands/fetch/index.ts
|
|
5523
|
-
import { defineCommand as
|
|
5699
|
+
import { defineCommand as defineCommand45 } from "citty";
|
|
5524
5700
|
async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
5525
5701
|
const token = getAuthToken();
|
|
5526
5702
|
if (!token) {
|
|
@@ -5556,13 +5732,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
|
5556
5732
|
throw new CliError(`HTTP ${response.status} ${response.statusText}`);
|
|
5557
5733
|
}
|
|
5558
5734
|
}
|
|
5559
|
-
var fetchCommand =
|
|
5735
|
+
var fetchCommand = defineCommand45({
|
|
5560
5736
|
meta: {
|
|
5561
5737
|
name: "fetch",
|
|
5562
5738
|
description: "Make authenticated HTTP requests"
|
|
5563
5739
|
},
|
|
5564
5740
|
subCommands: {
|
|
5565
|
-
get:
|
|
5741
|
+
get: defineCommand45({
|
|
5566
5742
|
meta: {
|
|
5567
5743
|
name: "get",
|
|
5568
5744
|
description: "GET request with auth token"
|
|
@@ -5588,7 +5764,7 @@ var fetchCommand = defineCommand41({
|
|
|
5588
5764
|
await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
|
|
5589
5765
|
}
|
|
5590
5766
|
}),
|
|
5591
|
-
post:
|
|
5767
|
+
post: defineCommand45({
|
|
5592
5768
|
meta: {
|
|
5593
5769
|
name: "post",
|
|
5594
5770
|
description: "POST request with auth token"
|
|
@@ -5627,8 +5803,8 @@ var fetchCommand = defineCommand41({
|
|
|
5627
5803
|
});
|
|
5628
5804
|
|
|
5629
5805
|
// src/commands/mcp/index.ts
|
|
5630
|
-
import { defineCommand as
|
|
5631
|
-
var mcpCommand =
|
|
5806
|
+
import { defineCommand as defineCommand46 } from "citty";
|
|
5807
|
+
var mcpCommand = defineCommand46({
|
|
5632
5808
|
meta: {
|
|
5633
5809
|
name: "mcp",
|
|
5634
5810
|
description: "Start MCP server for AI agents"
|
|
@@ -5651,7 +5827,7 @@ var mcpCommand = defineCommand42({
|
|
|
5651
5827
|
if (transport !== "stdio" && transport !== "sse") {
|
|
5652
5828
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
5653
5829
|
}
|
|
5654
|
-
const { startMcpServer } = await import("./server-
|
|
5830
|
+
const { startMcpServer } = await import("./server-JBBJXDDS.js");
|
|
5655
5831
|
await startMcpServer(transport, port);
|
|
5656
5832
|
}
|
|
5657
5833
|
});
|
|
@@ -5659,10 +5835,10 @@ var mcpCommand = defineCommand42({
|
|
|
5659
5835
|
// src/commands/init/index.ts
|
|
5660
5836
|
import { existsSync as existsSync14, copyFileSync, writeFileSync as writeFileSync9 } from "fs";
|
|
5661
5837
|
import { randomBytes } from "crypto";
|
|
5662
|
-
import { execFileSync as
|
|
5838
|
+
import { execFileSync as execFileSync13 } from "child_process";
|
|
5663
5839
|
import { join as join13 } from "path";
|
|
5664
|
-
import { defineCommand as
|
|
5665
|
-
import
|
|
5840
|
+
import { defineCommand as defineCommand47 } from "citty";
|
|
5841
|
+
import consola38 from "consola";
|
|
5666
5842
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
5667
5843
|
async function downloadTemplate(repo, targetDir) {
|
|
5668
5844
|
const { downloadTemplate: gigetDownload } = await import("giget");
|
|
@@ -5671,28 +5847,28 @@ async function downloadTemplate(repo, targetDir) {
|
|
|
5671
5847
|
function installDeps(dir) {
|
|
5672
5848
|
const hasLockFile = (name) => existsSync14(join13(dir, name));
|
|
5673
5849
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
5674
|
-
|
|
5850
|
+
execFileSync13("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5675
5851
|
} else if (hasLockFile("bun.lockb")) {
|
|
5676
|
-
|
|
5852
|
+
execFileSync13("bun", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5677
5853
|
} else {
|
|
5678
|
-
|
|
5854
|
+
execFileSync13("npm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
5679
5855
|
}
|
|
5680
5856
|
}
|
|
5681
5857
|
async function promptChoice(message, choices) {
|
|
5682
|
-
const result = await
|
|
5858
|
+
const result = await consola38.prompt(message, { type: "select", options: choices });
|
|
5683
5859
|
if (typeof result === "symbol") {
|
|
5684
5860
|
throw new CliExit(0);
|
|
5685
5861
|
}
|
|
5686
5862
|
return result;
|
|
5687
5863
|
}
|
|
5688
5864
|
async function promptText(message, defaultValue) {
|
|
5689
|
-
const result = await
|
|
5865
|
+
const result = await consola38.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
|
|
5690
5866
|
if (typeof result === "symbol") {
|
|
5691
5867
|
throw new CliExit(0);
|
|
5692
5868
|
}
|
|
5693
5869
|
return result || defaultValue || "";
|
|
5694
5870
|
}
|
|
5695
|
-
var initCommand =
|
|
5871
|
+
var initCommand = defineCommand47({
|
|
5696
5872
|
meta: {
|
|
5697
5873
|
name: "init",
|
|
5698
5874
|
description: "Scaffold a new OpenApe project"
|
|
@@ -5737,20 +5913,20 @@ async function initSP(targetDir) {
|
|
|
5737
5913
|
if (existsSync14(join13(dir, "package.json"))) {
|
|
5738
5914
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
5739
5915
|
}
|
|
5740
|
-
|
|
5916
|
+
consola38.start("Scaffolding SP starter...");
|
|
5741
5917
|
await downloadTemplate("openape-ai/openape-sp-starter", dir);
|
|
5742
|
-
|
|
5743
|
-
|
|
5918
|
+
consola38.success("Scaffolded from openape-sp-starter");
|
|
5919
|
+
consola38.start("Installing dependencies...");
|
|
5744
5920
|
installDeps(dir);
|
|
5745
|
-
|
|
5921
|
+
consola38.success("Dependencies installed");
|
|
5746
5922
|
const envExample = join13(dir, ".env.example");
|
|
5747
5923
|
const envFile = join13(dir, ".env");
|
|
5748
5924
|
if (existsSync14(envExample) && !existsSync14(envFile)) {
|
|
5749
5925
|
copyFileSync(envExample, envFile);
|
|
5750
|
-
|
|
5926
|
+
consola38.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
5751
5927
|
}
|
|
5752
5928
|
console.log("");
|
|
5753
|
-
|
|
5929
|
+
consola38.box([
|
|
5754
5930
|
`cd ${dir}`,
|
|
5755
5931
|
"npm run dev",
|
|
5756
5932
|
"",
|
|
@@ -5769,15 +5945,15 @@ async function initIdP(targetDir) {
|
|
|
5769
5945
|
"s3 (S3-compatible)"
|
|
5770
5946
|
]);
|
|
5771
5947
|
const adminEmail = await promptText("Admin email");
|
|
5772
|
-
|
|
5948
|
+
consola38.start("Scaffolding IdP starter...");
|
|
5773
5949
|
await downloadTemplate("openape-ai/openape-idp-starter", dir);
|
|
5774
|
-
|
|
5775
|
-
|
|
5950
|
+
consola38.success("Scaffolded from openape-idp-starter");
|
|
5951
|
+
consola38.start("Installing dependencies...");
|
|
5776
5952
|
installDeps(dir);
|
|
5777
|
-
|
|
5953
|
+
consola38.success("Dependencies installed");
|
|
5778
5954
|
const sessionSecret = randomBytes(32).toString("hex");
|
|
5779
5955
|
const managementToken = randomBytes(32).toString("hex");
|
|
5780
|
-
|
|
5956
|
+
consola38.success("Secrets generated");
|
|
5781
5957
|
const isLocalhost = domain === "localhost";
|
|
5782
5958
|
const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
|
|
5783
5959
|
const envContent = [
|
|
@@ -5793,9 +5969,9 @@ async function initIdP(targetDir) {
|
|
|
5793
5969
|
].join("\n");
|
|
5794
5970
|
writeFileSync9(join13(dir, ".env"), `${envContent}
|
|
5795
5971
|
`, { mode: 384 });
|
|
5796
|
-
|
|
5972
|
+
consola38.success(".env created");
|
|
5797
5973
|
console.log("");
|
|
5798
|
-
|
|
5974
|
+
consola38.box([
|
|
5799
5975
|
`cd ${dir}`,
|
|
5800
5976
|
"npm run dev",
|
|
5801
5977
|
"",
|
|
@@ -5815,8 +5991,8 @@ import { Buffer as Buffer5 } from "buffer";
|
|
|
5815
5991
|
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
|
|
5816
5992
|
import { execFile as execFile2 } from "child_process";
|
|
5817
5993
|
import { sign as sign2 } from "crypto";
|
|
5818
|
-
import { defineCommand as
|
|
5819
|
-
import
|
|
5994
|
+
import { defineCommand as defineCommand48 } from "citty";
|
|
5995
|
+
import consola39 from "consola";
|
|
5820
5996
|
var DEFAULT_IDP_URL2 = "https://id.openape.at";
|
|
5821
5997
|
var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
|
|
5822
5998
|
var POLL_INTERVAL = 3e3;
|
|
@@ -5859,7 +6035,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
5859
6035
|
}
|
|
5860
6036
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
5861
6037
|
}
|
|
5862
|
-
var enrollCommand =
|
|
6038
|
+
var enrollCommand = defineCommand48({
|
|
5863
6039
|
meta: {
|
|
5864
6040
|
name: "enroll",
|
|
5865
6041
|
description: "Enroll an agent with an Identity Provider"
|
|
@@ -5879,18 +6055,18 @@ var enrollCommand = defineCommand44({
|
|
|
5879
6055
|
}
|
|
5880
6056
|
},
|
|
5881
6057
|
async run({ args }) {
|
|
5882
|
-
const idp = args.idp || await
|
|
6058
|
+
const idp = args.idp || await consola39.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
|
|
5883
6059
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5884
6060
|
return r;
|
|
5885
6061
|
}) || DEFAULT_IDP_URL2;
|
|
5886
|
-
const agentName = args.name || await
|
|
6062
|
+
const agentName = args.name || await consola39.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
|
|
5887
6063
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5888
6064
|
return r;
|
|
5889
6065
|
});
|
|
5890
6066
|
if (!agentName) {
|
|
5891
6067
|
throw new CliError("Agent name is required.");
|
|
5892
6068
|
}
|
|
5893
|
-
const keyPath = args.key || await
|
|
6069
|
+
const keyPath = args.key || await consola39.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
|
|
5894
6070
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
5895
6071
|
return r;
|
|
5896
6072
|
}) || DEFAULT_KEY_PATH;
|
|
@@ -5898,19 +6074,19 @@ var enrollCommand = defineCommand44({
|
|
|
5898
6074
|
let publicKey;
|
|
5899
6075
|
if (existsSync15(resolvedKey)) {
|
|
5900
6076
|
publicKey = readPublicKey(resolvedKey);
|
|
5901
|
-
|
|
6077
|
+
consola39.success(`Using existing key ${keyPath}`);
|
|
5902
6078
|
} else {
|
|
5903
|
-
|
|
6079
|
+
consola39.start(`Generating Ed25519 key pair at ${keyPath}...`);
|
|
5904
6080
|
publicKey = generateAndSaveKey(keyPath);
|
|
5905
|
-
|
|
6081
|
+
consola39.success(`Key pair generated at ${keyPath}`);
|
|
5906
6082
|
}
|
|
5907
6083
|
const encodedKey = encodeURIComponent(publicKey);
|
|
5908
6084
|
const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
|
|
5909
|
-
|
|
5910
|
-
|
|
6085
|
+
consola39.info("Opening browser for enrollment...");
|
|
6086
|
+
consola39.info(`\u2192 ${idp}/enroll`);
|
|
5911
6087
|
openBrowser2(enrollUrl);
|
|
5912
6088
|
console.log("");
|
|
5913
|
-
const agentEmail = await
|
|
6089
|
+
const agentEmail = await consola39.prompt(
|
|
5914
6090
|
"Agent email (shown in browser after enrollment)",
|
|
5915
6091
|
{ type: "text", placeholder: `agent+${agentName}@...` }
|
|
5916
6092
|
).then((r) => {
|
|
@@ -5920,7 +6096,7 @@ var enrollCommand = defineCommand44({
|
|
|
5920
6096
|
if (!agentEmail) {
|
|
5921
6097
|
throw new CliError("Agent email is required to verify enrollment.");
|
|
5922
6098
|
}
|
|
5923
|
-
|
|
6099
|
+
consola39.start("Verifying enrollment...");
|
|
5924
6100
|
const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
|
|
5925
6101
|
saveAuth({
|
|
5926
6102
|
idp,
|
|
@@ -5932,18 +6108,18 @@ var enrollCommand = defineCommand44({
|
|
|
5932
6108
|
config.defaults = { ...config.defaults, idp };
|
|
5933
6109
|
config.agent = { key: keyPath, email: agentEmail };
|
|
5934
6110
|
saveConfig(config);
|
|
5935
|
-
|
|
5936
|
-
|
|
6111
|
+
consola39.success(`Agent enrolled as ${agentEmail}`);
|
|
6112
|
+
consola39.success("Config saved to ~/.config/apes/");
|
|
5937
6113
|
console.log("");
|
|
5938
|
-
|
|
6114
|
+
consola39.info("Verify with: apes whoami");
|
|
5939
6115
|
}
|
|
5940
6116
|
});
|
|
5941
6117
|
|
|
5942
6118
|
// src/commands/register-user.ts
|
|
5943
6119
|
import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
|
|
5944
|
-
import { defineCommand as
|
|
5945
|
-
import
|
|
5946
|
-
var registerUserCommand =
|
|
6120
|
+
import { defineCommand as defineCommand49 } from "citty";
|
|
6121
|
+
import consola40 from "consola";
|
|
6122
|
+
var registerUserCommand = defineCommand49({
|
|
5947
6123
|
meta: {
|
|
5948
6124
|
name: "register-user",
|
|
5949
6125
|
description: "Register a sub-user with SSH key"
|
|
@@ -5998,18 +6174,18 @@ var registerUserCommand = defineCommand45({
|
|
|
5998
6174
|
...userType ? { type: userType } : {}
|
|
5999
6175
|
}
|
|
6000
6176
|
});
|
|
6001
|
-
|
|
6177
|
+
consola40.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
|
|
6002
6178
|
}
|
|
6003
6179
|
});
|
|
6004
6180
|
|
|
6005
6181
|
// src/commands/utils/index.ts
|
|
6006
|
-
import { defineCommand as
|
|
6182
|
+
import { defineCommand as defineCommand51 } from "citty";
|
|
6007
6183
|
|
|
6008
6184
|
// src/commands/utils/dig.ts
|
|
6009
|
-
import { defineCommand as
|
|
6010
|
-
import
|
|
6185
|
+
import { defineCommand as defineCommand50 } from "citty";
|
|
6186
|
+
import consola41 from "consola";
|
|
6011
6187
|
import { resolveDDISA as resolveDDISA2 } from "@openape/core";
|
|
6012
|
-
var digCommand =
|
|
6188
|
+
var digCommand = defineCommand50({
|
|
6013
6189
|
meta: {
|
|
6014
6190
|
name: "dig",
|
|
6015
6191
|
description: "Resolve DDISA IdP for a domain or email (admin/diag tool)"
|
|
@@ -6082,12 +6258,12 @@ var digCommand = defineCommand46({
|
|
|
6082
6258
|
console.log(` domain: ${domain}`);
|
|
6083
6259
|
console.log("");
|
|
6084
6260
|
if (!result.ddisa.found) {
|
|
6085
|
-
|
|
6261
|
+
consola41.warn(`No DDISA record at _ddisa.${domain}`);
|
|
6086
6262
|
if (result.hint) console.log(`
|
|
6087
6263
|
${result.hint}`);
|
|
6088
6264
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
6089
6265
|
}
|
|
6090
|
-
|
|
6266
|
+
consola41.success(`_ddisa.${domain} \u2192 ${result.ddisa.idp}`);
|
|
6091
6267
|
console.log(` Version: ${result.ddisa.version || "ddisa1"}`);
|
|
6092
6268
|
console.log(` IdP URL: ${result.ddisa.idp}`);
|
|
6093
6269
|
if (result.ddisa.mode) console.log(` Mode: ${result.ddisa.mode}`);
|
|
@@ -6097,13 +6273,13 @@ ${result.hint}`);
|
|
|
6097
6273
|
return;
|
|
6098
6274
|
}
|
|
6099
6275
|
if (result.idpDiscovery.ok) {
|
|
6100
|
-
|
|
6276
|
+
consola41.success(`IdP reachable (${result.idpDiscovery.status ?? 200})`);
|
|
6101
6277
|
if (result.idpDiscovery.issuer) console.log(` Issuer: ${result.idpDiscovery.issuer}`);
|
|
6102
6278
|
if (result.idpDiscovery.ddisaVersion) console.log(` DDISA: v${result.idpDiscovery.ddisaVersion}`);
|
|
6103
6279
|
if (result.idpDiscovery.authMethods?.length) console.log(` Auth: ${result.idpDiscovery.authMethods.join(", ")}`);
|
|
6104
6280
|
if (result.idpDiscovery.grantTypes?.length) console.log(` Grants: ${result.idpDiscovery.grantTypes.join(", ")}`);
|
|
6105
6281
|
} else {
|
|
6106
|
-
|
|
6282
|
+
consola41.warn(`IdP discovery failed${result.idpDiscovery.status ? ` (HTTP ${result.idpDiscovery.status})` : ""}`);
|
|
6107
6283
|
if (result.hint) console.log(`
|
|
6108
6284
|
${result.hint}`);
|
|
6109
6285
|
throw new CliError(`IdP at ${result.ddisa.idp} not reachable`);
|
|
@@ -6112,7 +6288,7 @@ ${result.hint}`);
|
|
|
6112
6288
|
});
|
|
6113
6289
|
|
|
6114
6290
|
// src/commands/utils/index.ts
|
|
6115
|
-
var utilsCommand =
|
|
6291
|
+
var utilsCommand = defineCommand51({
|
|
6116
6292
|
meta: {
|
|
6117
6293
|
name: "utils",
|
|
6118
6294
|
description: "Admin/diagnostic utilities (dig, \u2026)"
|
|
@@ -6123,12 +6299,12 @@ var utilsCommand = defineCommand47({
|
|
|
6123
6299
|
});
|
|
6124
6300
|
|
|
6125
6301
|
// src/commands/sessions/index.ts
|
|
6126
|
-
import { defineCommand as
|
|
6302
|
+
import { defineCommand as defineCommand54 } from "citty";
|
|
6127
6303
|
|
|
6128
6304
|
// src/commands/sessions/list.ts
|
|
6129
|
-
import { defineCommand as
|
|
6130
|
-
import
|
|
6131
|
-
var sessionsListCommand =
|
|
6305
|
+
import { defineCommand as defineCommand52 } from "citty";
|
|
6306
|
+
import consola42 from "consola";
|
|
6307
|
+
var sessionsListCommand = defineCommand52({
|
|
6132
6308
|
meta: {
|
|
6133
6309
|
name: "list",
|
|
6134
6310
|
description: "List your active refresh-token families (one per logged-in device)."
|
|
@@ -6146,7 +6322,7 @@ var sessionsListCommand = defineCommand48({
|
|
|
6146
6322
|
return;
|
|
6147
6323
|
}
|
|
6148
6324
|
if (result.data.length === 0) {
|
|
6149
|
-
|
|
6325
|
+
consola42.info("No active sessions.");
|
|
6150
6326
|
return;
|
|
6151
6327
|
}
|
|
6152
6328
|
for (const f of result.data) {
|
|
@@ -6158,9 +6334,9 @@ var sessionsListCommand = defineCommand48({
|
|
|
6158
6334
|
});
|
|
6159
6335
|
|
|
6160
6336
|
// src/commands/sessions/remove.ts
|
|
6161
|
-
import { defineCommand as
|
|
6162
|
-
import
|
|
6163
|
-
var sessionsRemoveCommand =
|
|
6337
|
+
import { defineCommand as defineCommand53 } from "citty";
|
|
6338
|
+
import consola43 from "consola";
|
|
6339
|
+
var sessionsRemoveCommand = defineCommand53({
|
|
6164
6340
|
meta: {
|
|
6165
6341
|
name: "remove",
|
|
6166
6342
|
description: "Revoke one of your active refresh-token families by id."
|
|
@@ -6176,12 +6352,12 @@ var sessionsRemoveCommand = defineCommand49({
|
|
|
6176
6352
|
const id = String(args.familyId).trim();
|
|
6177
6353
|
if (!id) throw new CliError("familyId required");
|
|
6178
6354
|
await apiFetch(`/api/me/sessions/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
6179
|
-
|
|
6355
|
+
consola43.success(`Session ${id} revoked. The device using it will need to \`apes login\` again on its next refresh.`);
|
|
6180
6356
|
}
|
|
6181
6357
|
});
|
|
6182
6358
|
|
|
6183
6359
|
// src/commands/sessions/index.ts
|
|
6184
|
-
var sessionsCommand =
|
|
6360
|
+
var sessionsCommand = defineCommand54({
|
|
6185
6361
|
meta: {
|
|
6186
6362
|
name: "sessions",
|
|
6187
6363
|
description: "Manage your active refresh-token sessions across devices"
|
|
@@ -6193,10 +6369,10 @@ var sessionsCommand = defineCommand50({
|
|
|
6193
6369
|
});
|
|
6194
6370
|
|
|
6195
6371
|
// src/commands/dns-check.ts
|
|
6196
|
-
import { defineCommand as
|
|
6197
|
-
import
|
|
6372
|
+
import { defineCommand as defineCommand55 } from "citty";
|
|
6373
|
+
import consola44 from "consola";
|
|
6198
6374
|
import { resolveDDISA as resolveDDISA3 } from "@openape/core";
|
|
6199
|
-
var dnsCheckCommand =
|
|
6375
|
+
var dnsCheckCommand = defineCommand55({
|
|
6200
6376
|
meta: {
|
|
6201
6377
|
name: "dns-check",
|
|
6202
6378
|
description: "Validate DDISA DNS TXT records for a domain"
|
|
@@ -6210,7 +6386,7 @@ var dnsCheckCommand = defineCommand51({
|
|
|
6210
6386
|
},
|
|
6211
6387
|
async run({ args }) {
|
|
6212
6388
|
const domain = args.domain;
|
|
6213
|
-
|
|
6389
|
+
consola44.start(`Checking _ddisa.${domain}...`);
|
|
6214
6390
|
try {
|
|
6215
6391
|
const result = await resolveDDISA3(domain);
|
|
6216
6392
|
if (!result) {
|
|
@@ -6219,7 +6395,7 @@ var dnsCheckCommand = defineCommand51({
|
|
|
6219
6395
|
console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
|
|
6220
6396
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
6221
6397
|
}
|
|
6222
|
-
|
|
6398
|
+
consola44.success(`_ddisa.${domain} \u2192 ${result.idp}`);
|
|
6223
6399
|
console.log("");
|
|
6224
6400
|
console.log(` Version: ${result.version || "ddisa1"}`);
|
|
6225
6401
|
console.log(` IdP URL: ${result.idp}`);
|
|
@@ -6228,14 +6404,14 @@ var dnsCheckCommand = defineCommand51({
|
|
|
6228
6404
|
if (result.priority !== void 0)
|
|
6229
6405
|
console.log(` Priority: ${result.priority}`);
|
|
6230
6406
|
console.log("");
|
|
6231
|
-
|
|
6407
|
+
consola44.start(`Verifying IdP at ${result.idp}...`);
|
|
6232
6408
|
const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
|
|
6233
6409
|
if (!discoResp.ok) {
|
|
6234
|
-
|
|
6410
|
+
consola44.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
|
|
6235
6411
|
return;
|
|
6236
6412
|
}
|
|
6237
6413
|
const disco = await discoResp.json();
|
|
6238
|
-
|
|
6414
|
+
consola44.success(`IdP is reachable`);
|
|
6239
6415
|
console.log(` Issuer: ${disco.issuer}`);
|
|
6240
6416
|
console.log(` DDISA: v${disco.ddisa_version || "?"}`);
|
|
6241
6417
|
if (disco.ddisa_auth_methods_supported) {
|
|
@@ -6253,7 +6429,7 @@ var dnsCheckCommand = defineCommand51({
|
|
|
6253
6429
|
// src/commands/health.ts
|
|
6254
6430
|
import { exec } from "child_process";
|
|
6255
6431
|
import { promisify } from "util";
|
|
6256
|
-
import { defineCommand as
|
|
6432
|
+
import { defineCommand as defineCommand56 } from "citty";
|
|
6257
6433
|
var execAsync = promisify(exec);
|
|
6258
6434
|
async function resolveApeShellPath() {
|
|
6259
6435
|
try {
|
|
@@ -6289,7 +6465,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
6289
6465
|
}
|
|
6290
6466
|
}
|
|
6291
6467
|
async function runHealth(args) {
|
|
6292
|
-
const version = true ? "1.
|
|
6468
|
+
const version = true ? "1.7.1" : "0.0.0";
|
|
6293
6469
|
const auth = loadAuth();
|
|
6294
6470
|
if (!auth) {
|
|
6295
6471
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -6352,7 +6528,7 @@ async function runHealth(args) {
|
|
|
6352
6528
|
throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
|
|
6353
6529
|
}
|
|
6354
6530
|
}
|
|
6355
|
-
var healthCommand =
|
|
6531
|
+
var healthCommand = defineCommand56({
|
|
6356
6532
|
meta: {
|
|
6357
6533
|
name: "health",
|
|
6358
6534
|
description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
|
|
@@ -6370,8 +6546,8 @@ var healthCommand = defineCommand52({
|
|
|
6370
6546
|
});
|
|
6371
6547
|
|
|
6372
6548
|
// src/commands/workflows.ts
|
|
6373
|
-
import { defineCommand as
|
|
6374
|
-
import
|
|
6549
|
+
import { defineCommand as defineCommand57 } from "citty";
|
|
6550
|
+
import consola45 from "consola";
|
|
6375
6551
|
|
|
6376
6552
|
// src/guides/index.ts
|
|
6377
6553
|
var guides = [
|
|
@@ -6421,7 +6597,7 @@ var guides = [
|
|
|
6421
6597
|
];
|
|
6422
6598
|
|
|
6423
6599
|
// src/commands/workflows.ts
|
|
6424
|
-
var workflowsCommand =
|
|
6600
|
+
var workflowsCommand = defineCommand57({
|
|
6425
6601
|
meta: {
|
|
6426
6602
|
name: "workflows",
|
|
6427
6603
|
description: "Discover workflow guides"
|
|
@@ -6442,7 +6618,7 @@ var workflowsCommand = defineCommand53({
|
|
|
6442
6618
|
if (args.id) {
|
|
6443
6619
|
const guide = guides.find((g) => g.id === String(args.id));
|
|
6444
6620
|
if (!guide) {
|
|
6445
|
-
|
|
6621
|
+
consola45.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
|
|
6446
6622
|
throw new CliError(`Guide not found: ${args.id}`);
|
|
6447
6623
|
}
|
|
6448
6624
|
if (args.json) {
|
|
@@ -6485,7 +6661,7 @@ var workflowsCommand = defineCommand53({
|
|
|
6485
6661
|
import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "fs";
|
|
6486
6662
|
import { homedir as homedir13 } from "os";
|
|
6487
6663
|
import { join as join14 } from "path";
|
|
6488
|
-
import
|
|
6664
|
+
import consola46 from "consola";
|
|
6489
6665
|
var PACKAGE_NAME = "@openape/apes";
|
|
6490
6666
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
6491
6667
|
var CACHE_FILE = join14(homedir13(), ".config", "apes", ".version-check.json");
|
|
@@ -6530,7 +6706,7 @@ async function fetchLatestVersion() {
|
|
|
6530
6706
|
}
|
|
6531
6707
|
function warnIfBehind(currentVersion, latest) {
|
|
6532
6708
|
if (compareSemver(currentVersion, latest) < 0) {
|
|
6533
|
-
|
|
6709
|
+
consola46.warn(
|
|
6534
6710
|
`apes ${currentVersion} is behind latest @openape/apes@${latest}. Run \`npm i -g @openape/apes@latest\` to update. (Suppress with APES_NO_UPDATE_CHECK=1.)`
|
|
6535
6711
|
);
|
|
6536
6712
|
}
|
|
@@ -6562,10 +6738,10 @@ if (shellRewrite) {
|
|
|
6562
6738
|
if (shellRewrite.action === "rewrite") {
|
|
6563
6739
|
process.argv = shellRewrite.argv;
|
|
6564
6740
|
} else if (shellRewrite.action === "version") {
|
|
6565
|
-
console.log(`ape-shell ${"1.
|
|
6741
|
+
console.log(`ape-shell ${"1.7.1"} (OpenApe DDISA shell wrapper)`);
|
|
6566
6742
|
process.exit(0);
|
|
6567
6743
|
} else if (shellRewrite.action === "help") {
|
|
6568
|
-
console.log(`ape-shell ${"1.
|
|
6744
|
+
console.log(`ape-shell ${"1.7.1"} \u2014 OpenApe DDISA shell wrapper`);
|
|
6569
6745
|
console.log("");
|
|
6570
6746
|
console.log("Usage:");
|
|
6571
6747
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -6589,7 +6765,7 @@ if (shellRewrite) {
|
|
|
6589
6765
|
}
|
|
6590
6766
|
}
|
|
6591
6767
|
var debug = process.argv.includes("--debug");
|
|
6592
|
-
var grantsCommand =
|
|
6768
|
+
var grantsCommand = defineCommand58({
|
|
6593
6769
|
meta: {
|
|
6594
6770
|
name: "grants",
|
|
6595
6771
|
description: "Grant management"
|
|
@@ -6610,7 +6786,7 @@ var grantsCommand = defineCommand54({
|
|
|
6610
6786
|
"delegation-revoke": delegationRevokeCommand
|
|
6611
6787
|
}
|
|
6612
6788
|
});
|
|
6613
|
-
var configCommand =
|
|
6789
|
+
var configCommand = defineCommand58({
|
|
6614
6790
|
meta: {
|
|
6615
6791
|
name: "config",
|
|
6616
6792
|
description: "Configuration management"
|
|
@@ -6620,10 +6796,10 @@ var configCommand = defineCommand54({
|
|
|
6620
6796
|
set: configSetCommand
|
|
6621
6797
|
}
|
|
6622
6798
|
});
|
|
6623
|
-
var main =
|
|
6799
|
+
var main = defineCommand58({
|
|
6624
6800
|
meta: {
|
|
6625
6801
|
name: "apes",
|
|
6626
|
-
version: "1.
|
|
6802
|
+
version: "1.7.1",
|
|
6627
6803
|
description: "Unified CLI for OpenApe"
|
|
6628
6804
|
},
|
|
6629
6805
|
subCommands: {
|
|
@@ -6640,6 +6816,7 @@ var main = defineCommand54({
|
|
|
6640
6816
|
grants: grantsCommand,
|
|
6641
6817
|
agents: agentsCommand,
|
|
6642
6818
|
nest: nestCommand,
|
|
6819
|
+
yolo: yoloCommand,
|
|
6643
6820
|
admin: adminCommand,
|
|
6644
6821
|
run: runCommand,
|
|
6645
6822
|
proxy: proxyCommand,
|
|
@@ -6679,20 +6856,20 @@ async function maybeRefreshAuth() {
|
|
|
6679
6856
|
}
|
|
6680
6857
|
}
|
|
6681
6858
|
await maybeRefreshAuth();
|
|
6682
|
-
await maybeWarnStaleVersion("1.
|
|
6859
|
+
await maybeWarnStaleVersion("1.7.1").catch(() => {
|
|
6683
6860
|
});
|
|
6684
6861
|
runMain(main).catch((err) => {
|
|
6685
6862
|
if (err instanceof CliExit) {
|
|
6686
6863
|
process.exit(err.exitCode);
|
|
6687
6864
|
}
|
|
6688
6865
|
if (err instanceof CliError) {
|
|
6689
|
-
|
|
6866
|
+
consola47.error(err.message);
|
|
6690
6867
|
process.exit(err.exitCode);
|
|
6691
6868
|
}
|
|
6692
6869
|
if (debug) {
|
|
6693
|
-
|
|
6870
|
+
consola47.error(err);
|
|
6694
6871
|
} else {
|
|
6695
|
-
|
|
6872
|
+
consola47.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
|
|
6696
6873
|
}
|
|
6697
6874
|
process.exit(1);
|
|
6698
6875
|
});
|