@openape/apes 0.7.2 → 0.9.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/{auth-lock-SRUFWJC3.js → auth-lock-6U2G75S6.js} +2 -2
- package/dist/{chunk-TBYYREL6.js → chunk-AZVY3X7Q.js} +13 -1
- package/dist/chunk-AZVY3X7Q.js.map +1 -0
- package/dist/chunk-LSKHTHUY.js +50 -0
- package/dist/chunk-LSKHTHUY.js.map +1 -0
- package/dist/{chunk-B32ZQP5K.js → chunk-UQ673USC.js} +31 -6
- package/dist/chunk-UQ673USC.js.map +1 -0
- package/dist/cli.js +455 -207
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +2 -2
- package/dist/{orchestrator-JAMWD6DD.js → orchestrator-GPNL543L.js} +135 -7
- package/dist/orchestrator-GPNL543L.js.map +1 -0
- package/dist/{server-GPETT3ON.js → server-FFOPFICW.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-B32ZQP5K.js.map +0 -1
- package/dist/chunk-TBYYREL6.js.map +0 -1
- package/dist/orchestrator-JAMWD6DD.js.map +0 -1
- /package/dist/{auth-lock-SRUFWJC3.js.map → auth-lock-6U2G75S6.js.map} +0 -0
- /package/dist/{server-GPETT3ON.js.map → server-FFOPFICW.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,9 @@ import {
|
|
|
8
8
|
loadEd25519PrivateKey,
|
|
9
9
|
readPublicKeyComment
|
|
10
10
|
} from "./chunk-ION3CWD5.js";
|
|
11
|
+
import {
|
|
12
|
+
notifyGrantPending
|
|
13
|
+
} from "./chunk-LSKHTHUY.js";
|
|
11
14
|
import {
|
|
12
15
|
ApiError,
|
|
13
16
|
apiFetch,
|
|
@@ -34,11 +37,14 @@ import {
|
|
|
34
37
|
removeAdapter,
|
|
35
38
|
resolveCapabilityRequest,
|
|
36
39
|
resolveCommand,
|
|
40
|
+
resolveFromGrant,
|
|
37
41
|
searchAdapters,
|
|
38
42
|
verifyAndExecute,
|
|
39
43
|
waitForGrantStatus
|
|
40
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-UQ673USC.js";
|
|
41
45
|
import {
|
|
46
|
+
AUTH_FILE,
|
|
47
|
+
CONFIG_DIR,
|
|
42
48
|
clearAuth,
|
|
43
49
|
getAuthToken,
|
|
44
50
|
getIdpUrl,
|
|
@@ -46,10 +52,10 @@ import {
|
|
|
46
52
|
loadConfig,
|
|
47
53
|
saveAuth,
|
|
48
54
|
saveConfig
|
|
49
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-AZVY3X7Q.js";
|
|
50
56
|
|
|
51
57
|
// src/cli.ts
|
|
52
|
-
import
|
|
58
|
+
import consola27 from "consola";
|
|
53
59
|
|
|
54
60
|
// src/ape-shell.ts
|
|
55
61
|
import path from "path";
|
|
@@ -79,7 +85,7 @@ function rewriteApeShellArgs(argv, argv0) {
|
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
// src/cli.ts
|
|
82
|
-
import { defineCommand as
|
|
88
|
+
import { defineCommand as defineCommand33, runMain } from "citty";
|
|
83
89
|
|
|
84
90
|
// src/commands/auth/login.ts
|
|
85
91
|
import { Buffer } from "buffer";
|
|
@@ -1036,9 +1042,83 @@ var revokeCommand = defineCommand11({
|
|
|
1036
1042
|
}
|
|
1037
1043
|
});
|
|
1038
1044
|
|
|
1039
|
-
// src/commands/grants/
|
|
1045
|
+
// src/commands/grants/run.ts
|
|
1046
|
+
import { execFileSync } from "child_process";
|
|
1040
1047
|
import { defineCommand as defineCommand12 } from "citty";
|
|
1041
|
-
|
|
1048
|
+
import consola12 from "consola";
|
|
1049
|
+
var runGrantCommand = defineCommand12({
|
|
1050
|
+
meta: {
|
|
1051
|
+
name: "run",
|
|
1052
|
+
description: "Execute a previously-approved grant by ID"
|
|
1053
|
+
},
|
|
1054
|
+
args: {
|
|
1055
|
+
id: {
|
|
1056
|
+
type: "positional",
|
|
1057
|
+
description: "Grant ID",
|
|
1058
|
+
required: true
|
|
1059
|
+
},
|
|
1060
|
+
"escapes-path": {
|
|
1061
|
+
type: "string",
|
|
1062
|
+
description: "Path to escapes binary (audience=escapes only)",
|
|
1063
|
+
default: "escapes"
|
|
1064
|
+
}
|
|
1065
|
+
},
|
|
1066
|
+
async run({ args }) {
|
|
1067
|
+
const idp = getIdpUrl();
|
|
1068
|
+
if (!idp)
|
|
1069
|
+
throw new CliError("No IdP URL configured. Run `apes login` first or pass --idp.");
|
|
1070
|
+
const grantsUrl = await getGrantsEndpoint(idp);
|
|
1071
|
+
const grant = await apiFetch(`${grantsUrl}/${args.id}`);
|
|
1072
|
+
if (grant.status === "pending")
|
|
1073
|
+
throw new CliError(`Grant ${grant.id} is still pending. Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
1074
|
+
if (grant.status === "denied" || grant.status === "revoked")
|
|
1075
|
+
throw new CliError(`Grant ${grant.id} is ${grant.status}. Request a new one.`);
|
|
1076
|
+
if (grant.status === "used")
|
|
1077
|
+
throw new CliError(`Grant ${grant.id} has already been used. Request a new one (single-use grants cannot be re-executed).`);
|
|
1078
|
+
if (grant.status !== "approved")
|
|
1079
|
+
throw new CliError(`Grant ${grant.id} has unexpected status: ${grant.status}`);
|
|
1080
|
+
const audience = grant.request?.audience;
|
|
1081
|
+
const authDetails = grant.request?.authorization_details ?? [];
|
|
1082
|
+
const hasOpenApeCliDetail = authDetails.some((d) => d?.type === "openape_cli");
|
|
1083
|
+
const isShapesGrant = hasOpenApeCliDetail || audience === "shapes";
|
|
1084
|
+
if (isShapesGrant) {
|
|
1085
|
+
let resolved;
|
|
1086
|
+
try {
|
|
1087
|
+
resolved = await resolveFromGrant(grant);
|
|
1088
|
+
} catch (err) {
|
|
1089
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1090
|
+
throw new CliError(`Cannot re-resolve grant: ${msg}`);
|
|
1091
|
+
}
|
|
1092
|
+
const token = await fetchGrantToken(idp, grant.id);
|
|
1093
|
+
await verifyAndExecute(token, resolved);
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
if (audience === "escapes") {
|
|
1097
|
+
const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, { method: "POST" });
|
|
1098
|
+
const command = grant.request?.command ?? [];
|
|
1099
|
+
if (command.length === 0)
|
|
1100
|
+
throw new CliError(`Grant ${grant.id} has no command to execute.`);
|
|
1101
|
+
consola12.info(`Executing via escapes: ${command.join(" ")}`);
|
|
1102
|
+
try {
|
|
1103
|
+
execFileSync(args["escapes-path"], ["--grant", authz_jwt, "--", ...command], { stdio: "inherit" });
|
|
1104
|
+
} catch (err) {
|
|
1105
|
+
const exitCode = err.status || 1;
|
|
1106
|
+
throw new CliExit(exitCode);
|
|
1107
|
+
}
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
if (audience === "ape-shell") {
|
|
1111
|
+
throw new CliError(
|
|
1112
|
+
`Grant ${grant.id} is an ape-shell session grant and cannot be re-executed via \`apes grants run\`. Re-run the original command \u2014 if the grant was approved as timed/always, the REPL will reuse it automatically.`
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
throw new CliError(`Grant ${grant.id} has unsupported audience "${audience}" \u2014 no execution path available.`);
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
|
|
1119
|
+
// src/commands/grants/token.ts
|
|
1120
|
+
import { defineCommand as defineCommand13 } from "citty";
|
|
1121
|
+
var tokenCommand = defineCommand13({
|
|
1042
1122
|
meta: {
|
|
1043
1123
|
name: "token",
|
|
1044
1124
|
description: "Get grant token JWT"
|
|
@@ -1064,9 +1144,9 @@ var tokenCommand = defineCommand12({
|
|
|
1064
1144
|
});
|
|
1065
1145
|
|
|
1066
1146
|
// src/commands/grants/delegate.ts
|
|
1067
|
-
import { defineCommand as
|
|
1068
|
-
import
|
|
1069
|
-
var delegateCommand =
|
|
1147
|
+
import { defineCommand as defineCommand14 } from "citty";
|
|
1148
|
+
import consola13 from "consola";
|
|
1149
|
+
var delegateCommand = defineCommand14({
|
|
1070
1150
|
meta: {
|
|
1071
1151
|
name: "delegate",
|
|
1072
1152
|
description: "Create a delegation"
|
|
@@ -1118,7 +1198,7 @@ var delegateCommand = defineCommand13({
|
|
|
1118
1198
|
method: "POST",
|
|
1119
1199
|
body
|
|
1120
1200
|
});
|
|
1121
|
-
|
|
1201
|
+
consola13.success(`Delegation created: ${result.id}`);
|
|
1122
1202
|
console.log(` Delegate: ${args.to}`);
|
|
1123
1203
|
console.log(` Audience: ${args.at}`);
|
|
1124
1204
|
if (args.scopes)
|
|
@@ -1130,9 +1210,9 @@ var delegateCommand = defineCommand13({
|
|
|
1130
1210
|
});
|
|
1131
1211
|
|
|
1132
1212
|
// src/commands/grants/delegations.ts
|
|
1133
|
-
import { defineCommand as
|
|
1134
|
-
import
|
|
1135
|
-
var delegationsCommand =
|
|
1213
|
+
import { defineCommand as defineCommand15 } from "citty";
|
|
1214
|
+
import consola14 from "consola";
|
|
1215
|
+
var delegationsCommand = defineCommand15({
|
|
1136
1216
|
meta: {
|
|
1137
1217
|
name: "delegations",
|
|
1138
1218
|
description: "List delegations"
|
|
@@ -1154,7 +1234,7 @@ var delegationsCommand = defineCommand14({
|
|
|
1154
1234
|
return;
|
|
1155
1235
|
}
|
|
1156
1236
|
if (delegations.length === 0) {
|
|
1157
|
-
|
|
1237
|
+
consola14.info("No delegations found.");
|
|
1158
1238
|
return;
|
|
1159
1239
|
}
|
|
1160
1240
|
for (const d of delegations) {
|
|
@@ -1166,9 +1246,9 @@ var delegationsCommand = defineCommand14({
|
|
|
1166
1246
|
});
|
|
1167
1247
|
|
|
1168
1248
|
// src/commands/grants/delegation-revoke.ts
|
|
1169
|
-
import { defineCommand as
|
|
1170
|
-
import
|
|
1171
|
-
var delegationRevokeCommand =
|
|
1249
|
+
import { defineCommand as defineCommand16 } from "citty";
|
|
1250
|
+
import consola15 from "consola";
|
|
1251
|
+
var delegationRevokeCommand = defineCommand16({
|
|
1172
1252
|
meta: {
|
|
1173
1253
|
name: "delegation-revoke",
|
|
1174
1254
|
description: "Revoke a delegation"
|
|
@@ -1191,16 +1271,16 @@ var delegationRevokeCommand = defineCommand15({
|
|
|
1191
1271
|
`${delegationsUrl}/${id}`,
|
|
1192
1272
|
{ method: "DELETE" }
|
|
1193
1273
|
);
|
|
1194
|
-
|
|
1274
|
+
consola15.success(`Delegation ${result.id} revoked.`);
|
|
1195
1275
|
}
|
|
1196
1276
|
});
|
|
1197
1277
|
|
|
1198
1278
|
// src/commands/admin/index.ts
|
|
1199
|
-
import { defineCommand as
|
|
1279
|
+
import { defineCommand as defineCommand19 } from "citty";
|
|
1200
1280
|
|
|
1201
1281
|
// src/commands/admin/users.ts
|
|
1202
|
-
import { defineCommand as
|
|
1203
|
-
import
|
|
1282
|
+
import { defineCommand as defineCommand17 } from "citty";
|
|
1283
|
+
import consola16 from "consola";
|
|
1204
1284
|
function getManagementToken() {
|
|
1205
1285
|
const token = process.env.APES_MANAGEMENT_TOKEN;
|
|
1206
1286
|
if (!token) {
|
|
@@ -1208,7 +1288,7 @@ function getManagementToken() {
|
|
|
1208
1288
|
}
|
|
1209
1289
|
return token;
|
|
1210
1290
|
}
|
|
1211
|
-
var usersListCommand =
|
|
1291
|
+
var usersListCommand = defineCommand17({
|
|
1212
1292
|
meta: {
|
|
1213
1293
|
name: "list",
|
|
1214
1294
|
description: "List all users"
|
|
@@ -1250,7 +1330,7 @@ var usersListCommand = defineCommand16({
|
|
|
1250
1330
|
return;
|
|
1251
1331
|
}
|
|
1252
1332
|
if (result.data.length === 0) {
|
|
1253
|
-
|
|
1333
|
+
consola16.info("No users found.");
|
|
1254
1334
|
return;
|
|
1255
1335
|
}
|
|
1256
1336
|
for (const u of result.data) {
|
|
@@ -1259,11 +1339,11 @@ var usersListCommand = defineCommand16({
|
|
|
1259
1339
|
console.log(`${u.email} ${u.name}${owner}${active}`);
|
|
1260
1340
|
}
|
|
1261
1341
|
if (result.pagination.has_more) {
|
|
1262
|
-
|
|
1342
|
+
consola16.info(`More results available. Use --cursor="${result.pagination.cursor}" to see next page.`);
|
|
1263
1343
|
}
|
|
1264
1344
|
}
|
|
1265
1345
|
});
|
|
1266
|
-
var usersCreateCommand =
|
|
1346
|
+
var usersCreateCommand = defineCommand17({
|
|
1267
1347
|
meta: {
|
|
1268
1348
|
name: "create",
|
|
1269
1349
|
description: "Create a user"
|
|
@@ -1294,10 +1374,10 @@ var usersCreateCommand = defineCommand16({
|
|
|
1294
1374
|
token
|
|
1295
1375
|
}
|
|
1296
1376
|
);
|
|
1297
|
-
|
|
1377
|
+
consola16.success(`User created: ${result.email} (${result.name})`);
|
|
1298
1378
|
}
|
|
1299
1379
|
});
|
|
1300
|
-
var usersDeleteCommand =
|
|
1380
|
+
var usersDeleteCommand = defineCommand17({
|
|
1301
1381
|
meta: {
|
|
1302
1382
|
name: "delete",
|
|
1303
1383
|
description: "Delete a user"
|
|
@@ -1320,7 +1400,7 @@ var usersDeleteCommand = defineCommand16({
|
|
|
1320
1400
|
method: "DELETE",
|
|
1321
1401
|
token
|
|
1322
1402
|
});
|
|
1323
|
-
|
|
1403
|
+
consola16.success(`User deleted: ${email}`);
|
|
1324
1404
|
}
|
|
1325
1405
|
});
|
|
1326
1406
|
|
|
@@ -1328,8 +1408,8 @@ var usersDeleteCommand = defineCommand16({
|
|
|
1328
1408
|
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
1329
1409
|
import { resolve } from "path";
|
|
1330
1410
|
import { homedir as homedir3 } from "os";
|
|
1331
|
-
import { defineCommand as
|
|
1332
|
-
import
|
|
1411
|
+
import { defineCommand as defineCommand18 } from "citty";
|
|
1412
|
+
import consola17 from "consola";
|
|
1333
1413
|
function getManagementToken2() {
|
|
1334
1414
|
const token = process.env.APES_MANAGEMENT_TOKEN;
|
|
1335
1415
|
if (!token) {
|
|
@@ -1337,7 +1417,7 @@ function getManagementToken2() {
|
|
|
1337
1417
|
}
|
|
1338
1418
|
return token;
|
|
1339
1419
|
}
|
|
1340
|
-
var sshKeysListCommand =
|
|
1420
|
+
var sshKeysListCommand = defineCommand18({
|
|
1341
1421
|
meta: {
|
|
1342
1422
|
name: "list",
|
|
1343
1423
|
description: "List SSH keys for a user"
|
|
@@ -1370,7 +1450,7 @@ var sshKeysListCommand = defineCommand17({
|
|
|
1370
1450
|
return;
|
|
1371
1451
|
}
|
|
1372
1452
|
if (keys.length === 0) {
|
|
1373
|
-
|
|
1453
|
+
consola17.info(`No SSH keys found for ${email}.`);
|
|
1374
1454
|
return;
|
|
1375
1455
|
}
|
|
1376
1456
|
for (const k of keys) {
|
|
@@ -1378,7 +1458,7 @@ var sshKeysListCommand = defineCommand17({
|
|
|
1378
1458
|
}
|
|
1379
1459
|
}
|
|
1380
1460
|
});
|
|
1381
|
-
var sshKeysAddCommand =
|
|
1461
|
+
var sshKeysAddCommand = defineCommand18({
|
|
1382
1462
|
meta: {
|
|
1383
1463
|
name: "add",
|
|
1384
1464
|
description: "Add an SSH key for a user"
|
|
@@ -1422,10 +1502,10 @@ var sshKeysAddCommand = defineCommand17({
|
|
|
1422
1502
|
token
|
|
1423
1503
|
}
|
|
1424
1504
|
);
|
|
1425
|
-
|
|
1505
|
+
consola17.success(`SSH key added: ${result.keyId} (${result.name})`);
|
|
1426
1506
|
}
|
|
1427
1507
|
});
|
|
1428
|
-
var sshKeysDeleteCommand =
|
|
1508
|
+
var sshKeysDeleteCommand = defineCommand18({
|
|
1429
1509
|
meta: {
|
|
1430
1510
|
name: "delete",
|
|
1431
1511
|
description: "Delete an SSH key"
|
|
@@ -1456,12 +1536,12 @@ var sshKeysDeleteCommand = defineCommand17({
|
|
|
1456
1536
|
token
|
|
1457
1537
|
}
|
|
1458
1538
|
);
|
|
1459
|
-
|
|
1539
|
+
consola17.success(`SSH key deleted: ${keyId}`);
|
|
1460
1540
|
}
|
|
1461
1541
|
});
|
|
1462
1542
|
|
|
1463
1543
|
// src/commands/admin/index.ts
|
|
1464
|
-
var usersCommand =
|
|
1544
|
+
var usersCommand = defineCommand19({
|
|
1465
1545
|
meta: {
|
|
1466
1546
|
name: "users",
|
|
1467
1547
|
description: "Manage users"
|
|
@@ -1472,7 +1552,7 @@ var usersCommand = defineCommand18({
|
|
|
1472
1552
|
delete: usersDeleteCommand
|
|
1473
1553
|
}
|
|
1474
1554
|
});
|
|
1475
|
-
var sshKeysCommand =
|
|
1555
|
+
var sshKeysCommand = defineCommand19({
|
|
1476
1556
|
meta: {
|
|
1477
1557
|
name: "ssh-keys",
|
|
1478
1558
|
description: "Manage SSH keys"
|
|
@@ -1483,7 +1563,7 @@ var sshKeysCommand = defineCommand18({
|
|
|
1483
1563
|
delete: sshKeysDeleteCommand
|
|
1484
1564
|
}
|
|
1485
1565
|
});
|
|
1486
|
-
var adminCommand =
|
|
1566
|
+
var adminCommand = defineCommand19({
|
|
1487
1567
|
meta: {
|
|
1488
1568
|
name: "admin",
|
|
1489
1569
|
description: "Admin commands (requires APES_MANAGEMENT_TOKEN)"
|
|
@@ -1495,15 +1575,15 @@ var adminCommand = defineCommand18({
|
|
|
1495
1575
|
});
|
|
1496
1576
|
|
|
1497
1577
|
// src/commands/adapter/index.ts
|
|
1498
|
-
import { defineCommand as
|
|
1499
|
-
import
|
|
1500
|
-
var adapterCommand =
|
|
1578
|
+
import { defineCommand as defineCommand20 } from "citty";
|
|
1579
|
+
import consola18 from "consola";
|
|
1580
|
+
var adapterCommand = defineCommand20({
|
|
1501
1581
|
meta: {
|
|
1502
1582
|
name: "adapter",
|
|
1503
1583
|
description: "Manage CLI adapters"
|
|
1504
1584
|
},
|
|
1505
1585
|
subCommands: {
|
|
1506
|
-
list:
|
|
1586
|
+
list: defineCommand20({
|
|
1507
1587
|
meta: {
|
|
1508
1588
|
name: "list",
|
|
1509
1589
|
description: "List available adapters"
|
|
@@ -1534,7 +1614,7 @@ var adapterCommand = defineCommand19({
|
|
|
1534
1614
|
`);
|
|
1535
1615
|
return;
|
|
1536
1616
|
}
|
|
1537
|
-
|
|
1617
|
+
consola18.info(`Registry: ${index2.adapters.length} adapters (${index2.generated_at})`);
|
|
1538
1618
|
for (const a of index2.adapters) {
|
|
1539
1619
|
const installed = isInstalled(a.id, false) ? " [installed]" : "";
|
|
1540
1620
|
console.log(` ${a.id.padEnd(12)} ${a.name.padEnd(24)} ${a.category}${installed}`);
|
|
@@ -1556,7 +1636,7 @@ var adapterCommand = defineCommand19({
|
|
|
1556
1636
|
return;
|
|
1557
1637
|
}
|
|
1558
1638
|
if (local.length === 0) {
|
|
1559
|
-
|
|
1639
|
+
consola18.info("No adapters installed. Use `apes adapter list --remote` to see available adapters.");
|
|
1560
1640
|
return;
|
|
1561
1641
|
}
|
|
1562
1642
|
for (const a of local) {
|
|
@@ -1564,7 +1644,7 @@ var adapterCommand = defineCommand19({
|
|
|
1564
1644
|
}
|
|
1565
1645
|
}
|
|
1566
1646
|
}),
|
|
1567
|
-
install:
|
|
1647
|
+
install: defineCommand20({
|
|
1568
1648
|
meta: {
|
|
1569
1649
|
name: "install",
|
|
1570
1650
|
description: "Install an adapter from the registry"
|
|
@@ -1593,24 +1673,24 @@ var adapterCommand = defineCommand19({
|
|
|
1593
1673
|
for (const id of ids) {
|
|
1594
1674
|
const entry = findAdapter(index, id);
|
|
1595
1675
|
if (!entry) {
|
|
1596
|
-
|
|
1676
|
+
consola18.error(`Adapter "${id}" not found in registry. Use \`apes adapter search ${id}\` to search.`);
|
|
1597
1677
|
continue;
|
|
1598
1678
|
}
|
|
1599
1679
|
const conflicts = findConflictingAdapters(entry.executable, id);
|
|
1600
1680
|
if (conflicts.length > 0) {
|
|
1601
1681
|
for (const c of conflicts) {
|
|
1602
|
-
|
|
1603
|
-
|
|
1682
|
+
consola18.warn(`Conflicting adapter found: ${c.path} (id: ${c.adapterId}, executable: ${c.executable})`);
|
|
1683
|
+
consola18.warn(` Remove it with: apes adapter remove ${c.adapterId}`);
|
|
1604
1684
|
}
|
|
1605
1685
|
}
|
|
1606
1686
|
const result = await installAdapter(entry, { local });
|
|
1607
1687
|
const verb = result.updated ? "Updated" : "Installed";
|
|
1608
|
-
|
|
1609
|
-
|
|
1688
|
+
consola18.success(`${verb} ${result.id} \u2192 ${result.path}`);
|
|
1689
|
+
consola18.info(`Digest: ${result.digest}`);
|
|
1610
1690
|
}
|
|
1611
1691
|
}
|
|
1612
1692
|
}),
|
|
1613
|
-
remove:
|
|
1693
|
+
remove: defineCommand20({
|
|
1614
1694
|
meta: {
|
|
1615
1695
|
name: "remove",
|
|
1616
1696
|
description: "Remove an installed adapter"
|
|
@@ -1633,9 +1713,9 @@ var adapterCommand = defineCommand19({
|
|
|
1633
1713
|
let failed = false;
|
|
1634
1714
|
for (const id of ids) {
|
|
1635
1715
|
if (removeAdapter(id, local)) {
|
|
1636
|
-
|
|
1716
|
+
consola18.success(`Removed adapter: ${id}`);
|
|
1637
1717
|
} else {
|
|
1638
|
-
|
|
1718
|
+
consola18.error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
1639
1719
|
failed = true;
|
|
1640
1720
|
}
|
|
1641
1721
|
}
|
|
@@ -1643,7 +1723,7 @@ var adapterCommand = defineCommand19({
|
|
|
1643
1723
|
throw new CliError("Some adapters could not be removed");
|
|
1644
1724
|
}
|
|
1645
1725
|
}),
|
|
1646
|
-
info:
|
|
1726
|
+
info: defineCommand20({
|
|
1647
1727
|
meta: {
|
|
1648
1728
|
name: "info",
|
|
1649
1729
|
description: "Show detailed adapter information"
|
|
@@ -1685,7 +1765,7 @@ var adapterCommand = defineCommand19({
|
|
|
1685
1765
|
}
|
|
1686
1766
|
}
|
|
1687
1767
|
}),
|
|
1688
|
-
search:
|
|
1768
|
+
search: defineCommand20({
|
|
1689
1769
|
meta: {
|
|
1690
1770
|
name: "search",
|
|
1691
1771
|
description: "Search adapters in the registry"
|
|
@@ -1717,7 +1797,7 @@ var adapterCommand = defineCommand19({
|
|
|
1717
1797
|
return;
|
|
1718
1798
|
}
|
|
1719
1799
|
if (results.length === 0) {
|
|
1720
|
-
|
|
1800
|
+
consola18.info(`No adapters matching "${query}"`);
|
|
1721
1801
|
return;
|
|
1722
1802
|
}
|
|
1723
1803
|
for (const a of results) {
|
|
@@ -1726,7 +1806,7 @@ var adapterCommand = defineCommand19({
|
|
|
1726
1806
|
}
|
|
1727
1807
|
}
|
|
1728
1808
|
}),
|
|
1729
|
-
update:
|
|
1809
|
+
update: defineCommand20({
|
|
1730
1810
|
meta: {
|
|
1731
1811
|
name: "update",
|
|
1732
1812
|
description: "Update installed adapters"
|
|
@@ -1752,33 +1832,33 @@ var adapterCommand = defineCommand19({
|
|
|
1752
1832
|
const targetId = args.id ? String(args.id) : void 0;
|
|
1753
1833
|
const targets = targetId ? [targetId] : index.adapters.map((a) => a.id).filter((id) => isInstalled(id, false));
|
|
1754
1834
|
if (targets.length === 0) {
|
|
1755
|
-
|
|
1835
|
+
consola18.info("No adapters installed to update.");
|
|
1756
1836
|
return;
|
|
1757
1837
|
}
|
|
1758
1838
|
for (const id of targets) {
|
|
1759
1839
|
const entry = findAdapter(index, id);
|
|
1760
1840
|
if (!entry) {
|
|
1761
|
-
|
|
1841
|
+
consola18.warn(`${id}: not found in registry, skipping`);
|
|
1762
1842
|
continue;
|
|
1763
1843
|
}
|
|
1764
1844
|
const localDigest = getInstalledDigest(id, false);
|
|
1765
1845
|
if (localDigest === entry.digest) {
|
|
1766
|
-
|
|
1846
|
+
consola18.info(`${id}: already up to date`);
|
|
1767
1847
|
continue;
|
|
1768
1848
|
}
|
|
1769
1849
|
if (localDigest && !args.yes) {
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1850
|
+
consola18.warn(`${id}: digest will change \u2014 existing grants for this adapter will be invalidated`);
|
|
1851
|
+
consola18.info(` Old: ${localDigest}`);
|
|
1852
|
+
consola18.info(` New: ${entry.digest}`);
|
|
1853
|
+
consola18.info(" Use --yes to confirm");
|
|
1774
1854
|
continue;
|
|
1775
1855
|
}
|
|
1776
1856
|
const result = await installAdapter(entry);
|
|
1777
|
-
|
|
1857
|
+
consola18.success(`Updated ${result.id} \u2192 ${result.path}`);
|
|
1778
1858
|
}
|
|
1779
1859
|
}
|
|
1780
1860
|
}),
|
|
1781
|
-
verify:
|
|
1861
|
+
verify: defineCommand20({
|
|
1782
1862
|
meta: {
|
|
1783
1863
|
name: "verify",
|
|
1784
1864
|
description: "Verify installed adapter against registry digest"
|
|
@@ -1811,7 +1891,7 @@ var adapterCommand = defineCommand19({
|
|
|
1811
1891
|
if (!localDigest)
|
|
1812
1892
|
throw new Error(`Adapter "${id}" is not installed${local ? " locally" : ""}`);
|
|
1813
1893
|
if (localDigest === entry.digest) {
|
|
1814
|
-
|
|
1894
|
+
consola18.success(`${id}: digest matches registry`);
|
|
1815
1895
|
} else {
|
|
1816
1896
|
console.log(` Local: ${localDigest}`);
|
|
1817
1897
|
console.log(` Registry: ${entry.digest}`);
|
|
@@ -1823,12 +1903,24 @@ var adapterCommand = defineCommand19({
|
|
|
1823
1903
|
});
|
|
1824
1904
|
|
|
1825
1905
|
// src/commands/run.ts
|
|
1826
|
-
import { execFileSync } from "child_process";
|
|
1906
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
1827
1907
|
import { hostname as hostname3 } from "os";
|
|
1828
1908
|
import { basename } from "path";
|
|
1829
|
-
import { defineCommand as
|
|
1830
|
-
import
|
|
1831
|
-
|
|
1909
|
+
import { defineCommand as defineCommand21 } from "citty";
|
|
1910
|
+
import consola19 from "consola";
|
|
1911
|
+
function shouldWaitForGrant(args) {
|
|
1912
|
+
return args.wait === true || process.env.APE_WAIT === "1";
|
|
1913
|
+
}
|
|
1914
|
+
function printPendingGrantInfo(grant, idp) {
|
|
1915
|
+
consola19.success(`Grant ${grant.id} erstellt`);
|
|
1916
|
+
console.log(` Approve: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
1917
|
+
console.log(` Status: apes grants status ${grant.id}`);
|
|
1918
|
+
console.log(` Ausf\xFChren: apes grants run ${grant.id}`);
|
|
1919
|
+
console.log("");
|
|
1920
|
+
console.log(' Tipp: Im Browser "als timed/always approven" w\xE4hlen, um das');
|
|
1921
|
+
console.log(" Kommando ohne erneuten Approval wiederzuverwenden.");
|
|
1922
|
+
}
|
|
1923
|
+
var runCommand = defineCommand21({
|
|
1832
1924
|
meta: {
|
|
1833
1925
|
name: "run",
|
|
1834
1926
|
description: "Execute a grant-secured command"
|
|
@@ -1869,6 +1961,11 @@ var runCommand = defineCommand20({
|
|
|
1869
1961
|
description: "Shell mode: use session grant with audience ape-shell",
|
|
1870
1962
|
default: false
|
|
1871
1963
|
},
|
|
1964
|
+
"wait": {
|
|
1965
|
+
type: "boolean",
|
|
1966
|
+
description: "Block until grant is approved (default: async, print grant info and exit 0). Equivalent to APE_WAIT=1.",
|
|
1967
|
+
default: false
|
|
1968
|
+
},
|
|
1872
1969
|
"_": {
|
|
1873
1970
|
type: "positional",
|
|
1874
1971
|
description: "Command to execute (after --)",
|
|
@@ -1915,7 +2012,7 @@ async function runShellMode(command, args) {
|
|
|
1915
2012
|
}
|
|
1916
2013
|
} catch {
|
|
1917
2014
|
}
|
|
1918
|
-
|
|
2015
|
+
consola19.info(`Requesting ape-shell session grant on ${targetHost}`);
|
|
1919
2016
|
const grant = await apiFetch(grantsUrl, {
|
|
1920
2017
|
method: "POST",
|
|
1921
2018
|
body: {
|
|
@@ -1927,20 +2024,31 @@ async function runShellMode(command, args) {
|
|
|
1927
2024
|
reason: `Shell session: ${command.join(" ").slice(0, 100)}`
|
|
1928
2025
|
}
|
|
1929
2026
|
});
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
2027
|
+
notifyGrantPending({
|
|
2028
|
+
grantId: grant.id,
|
|
2029
|
+
approveUrl: `${idp}/grant-approval?grant_id=${grant.id}`,
|
|
2030
|
+
command: command.join(" ").slice(0, 200),
|
|
2031
|
+
audience: "ape-shell",
|
|
2032
|
+
host: targetHost
|
|
2033
|
+
});
|
|
2034
|
+
if (shouldWaitForGrant(args)) {
|
|
2035
|
+
consola19.info(`Grant requested: ${grant.id}`);
|
|
2036
|
+
consola19.info("Waiting for approval...");
|
|
2037
|
+
const maxWait = 3e5;
|
|
2038
|
+
const interval = 3e3;
|
|
2039
|
+
const start = Date.now();
|
|
2040
|
+
while (Date.now() - start < maxWait) {
|
|
2041
|
+
const status = await apiFetch(`${grantsUrl}/${grant.id}`);
|
|
2042
|
+
if (status.status === "approved")
|
|
2043
|
+
break;
|
|
2044
|
+
if (status.status === "denied" || status.status === "revoked")
|
|
2045
|
+
throw new CliError(`Grant ${status.status}.`);
|
|
2046
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
2047
|
+
}
|
|
2048
|
+
execShellCommand(command);
|
|
2049
|
+
return;
|
|
1942
2050
|
}
|
|
1943
|
-
|
|
2051
|
+
printPendingGrantInfo(grant, idp);
|
|
1944
2052
|
}
|
|
1945
2053
|
async function tryAdapterModeFromShell(command, idp, args) {
|
|
1946
2054
|
const cmdString = extractShellCommandString(command);
|
|
@@ -1955,45 +2063,56 @@ async function tryAdapterModeFromShell(command, idp, args) {
|
|
|
1955
2063
|
try {
|
|
1956
2064
|
resolved = await resolveCommand(loaded, [normalizedExecutable, ...parsed.argv]);
|
|
1957
2065
|
} catch (err) {
|
|
1958
|
-
|
|
2066
|
+
consola19.debug(`ape-shell: adapter resolve failed for "${parsed.raw}":`, err);
|
|
1959
2067
|
return false;
|
|
1960
2068
|
}
|
|
1961
2069
|
try {
|
|
1962
2070
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
1963
2071
|
if (existingGrantId) {
|
|
1964
|
-
|
|
1965
|
-
const
|
|
1966
|
-
await verifyAndExecute(
|
|
2072
|
+
consola19.info(`Reusing grant ${existingGrantId} for: ${resolved.detail.display}`);
|
|
2073
|
+
const token = await fetchGrantToken(idp, existingGrantId);
|
|
2074
|
+
await verifyAndExecute(token, resolved);
|
|
1967
2075
|
return true;
|
|
1968
2076
|
}
|
|
1969
2077
|
} catch {
|
|
1970
2078
|
}
|
|
1971
2079
|
const approval = args.approval ?? "once";
|
|
1972
|
-
|
|
2080
|
+
consola19.info(`Requesting grant for: ${resolved.detail.display}`);
|
|
1973
2081
|
const grant = await createShapesGrant(resolved, {
|
|
1974
2082
|
idp,
|
|
1975
2083
|
approval,
|
|
1976
2084
|
reason: args.reason || `ape-shell: ${resolved.detail.display}`
|
|
1977
2085
|
});
|
|
1978
|
-
consola18.info(`Grant requested: ${grant.id}`);
|
|
1979
|
-
consola18.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
1980
2086
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
1981
2087
|
const n = grant.similar_grants.similar_grants.length;
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
}
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
2088
|
+
consola19.info("");
|
|
2089
|
+
consola19.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
2090
|
+
}
|
|
2091
|
+
notifyGrantPending({
|
|
2092
|
+
grantId: grant.id,
|
|
2093
|
+
approveUrl: `${idp}/grant-approval?grant_id=${grant.id}`,
|
|
2094
|
+
command: resolved.detail?.display || parsed?.raw || "unknown",
|
|
2095
|
+
audience: resolved.adapter?.cli?.audience ?? "shapes",
|
|
2096
|
+
host: args.host || hostname3()
|
|
2097
|
+
});
|
|
2098
|
+
if (shouldWaitForGrant(args)) {
|
|
2099
|
+
consola19.info(`Grant requested: ${grant.id}`);
|
|
2100
|
+
consola19.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
2101
|
+
const status = await waitForGrantStatus(idp, grant.id);
|
|
2102
|
+
if (status !== "approved")
|
|
2103
|
+
throw new CliError(`Grant ${status}`);
|
|
2104
|
+
const token = await fetchGrantToken(idp, grant.id);
|
|
2105
|
+
await verifyAndExecute(token, resolved);
|
|
2106
|
+
return true;
|
|
2107
|
+
}
|
|
2108
|
+
printPendingGrantInfo(grant, idp);
|
|
1990
2109
|
return true;
|
|
1991
2110
|
}
|
|
1992
2111
|
function execShellCommand(command) {
|
|
1993
2112
|
if (command.length === 0)
|
|
1994
2113
|
throw new CliError("No command to execute");
|
|
1995
2114
|
try {
|
|
1996
|
-
|
|
2115
|
+
execFileSync2(command[0], command.slice(1), { stdio: "inherit" });
|
|
1997
2116
|
} catch (err) {
|
|
1998
2117
|
const exitCode = err.status || 1;
|
|
1999
2118
|
throw new CliExit(exitCode);
|
|
@@ -2030,9 +2149,9 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
2030
2149
|
try {
|
|
2031
2150
|
const existingGrantId = await findExistingGrant(resolved, idp);
|
|
2032
2151
|
if (existingGrantId) {
|
|
2033
|
-
|
|
2034
|
-
const
|
|
2035
|
-
await verifyAndExecute(
|
|
2152
|
+
consola19.info(`Reusing existing grant: ${existingGrantId}`);
|
|
2153
|
+
const token = await fetchGrantToken(idp, existingGrantId);
|
|
2154
|
+
await verifyAndExecute(token, resolved);
|
|
2036
2155
|
return;
|
|
2037
2156
|
}
|
|
2038
2157
|
} catch {
|
|
@@ -2042,23 +2161,27 @@ async function runAdapterMode(command, rawArgs, args) {
|
|
|
2042
2161
|
approval,
|
|
2043
2162
|
...args.reason ? { reason: args.reason } : {}
|
|
2044
2163
|
});
|
|
2045
|
-
consola18.info(`Grant requested: ${grant.id}`);
|
|
2046
|
-
consola18.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
2047
2164
|
if (grant.similar_grants?.similar_grants?.length) {
|
|
2048
2165
|
const n = grant.similar_grants.similar_grants.length;
|
|
2049
|
-
|
|
2050
|
-
|
|
2166
|
+
consola19.info("");
|
|
2167
|
+
consola19.info(` Similar grant(s) found (${n}). Your approver can extend an existing grant to cover this request.`);
|
|
2051
2168
|
if (grant.similar_grants.widened_details?.length) {
|
|
2052
2169
|
const wider = grant.similar_grants.widened_details.map((d) => d.permission).join(", ");
|
|
2053
|
-
|
|
2054
|
-
}
|
|
2055
|
-
|
|
2170
|
+
consola19.info(` Broader scope: ${wider}`);
|
|
2171
|
+
}
|
|
2172
|
+
consola19.info("");
|
|
2173
|
+
}
|
|
2174
|
+
if (shouldWaitForGrant(args)) {
|
|
2175
|
+
consola19.info(`Grant requested: ${grant.id}`);
|
|
2176
|
+
consola19.info(`Approve at: ${idp}/grant-approval?grant_id=${grant.id}`);
|
|
2177
|
+
const status = await waitForGrantStatus(idp, grant.id);
|
|
2178
|
+
if (status !== "approved")
|
|
2179
|
+
throw new Error(`Grant ${status}`);
|
|
2180
|
+
const token = await fetchGrantToken(idp, grant.id);
|
|
2181
|
+
await verifyAndExecute(token, resolved);
|
|
2182
|
+
return;
|
|
2056
2183
|
}
|
|
2057
|
-
|
|
2058
|
-
if (status !== "approved")
|
|
2059
|
-
throw new Error(`Grant ${status}`);
|
|
2060
|
-
const token = await fetchGrantToken(idp, grant.id);
|
|
2061
|
-
await verifyAndExecute(token, resolved);
|
|
2184
|
+
printPendingGrantInfo(grant, idp);
|
|
2062
2185
|
}
|
|
2063
2186
|
async function runAudienceMode(audience, action, args) {
|
|
2064
2187
|
const auth = loadAuth();
|
|
@@ -2069,7 +2192,7 @@ async function runAudienceMode(audience, action, args) {
|
|
|
2069
2192
|
const grantsUrl = await getGrantsEndpoint(idp);
|
|
2070
2193
|
const command = action.split(" ");
|
|
2071
2194
|
const targetHost = args.host || hostname3();
|
|
2072
|
-
|
|
2195
|
+
consola19.info(`Requesting ${audience} grant on ${targetHost}: ${command.join(" ")}`);
|
|
2073
2196
|
const grant = await apiFetch(grantsUrl, {
|
|
2074
2197
|
method: "POST",
|
|
2075
2198
|
body: {
|
|
@@ -2082,15 +2205,19 @@ async function runAudienceMode(audience, action, args) {
|
|
|
2082
2205
|
...args.as ? { run_as: args.as } : {}
|
|
2083
2206
|
}
|
|
2084
2207
|
});
|
|
2085
|
-
|
|
2086
|
-
|
|
2208
|
+
if (!shouldWaitForGrant(args)) {
|
|
2209
|
+
printPendingGrantInfo(grant, idp);
|
|
2210
|
+
return;
|
|
2211
|
+
}
|
|
2212
|
+
consola19.success(`Grant requested: ${grant.id}`);
|
|
2213
|
+
consola19.info("Waiting for approval...");
|
|
2087
2214
|
const maxWait = 3e5;
|
|
2088
2215
|
const interval = 3e3;
|
|
2089
2216
|
const start = Date.now();
|
|
2090
2217
|
while (Date.now() - start < maxWait) {
|
|
2091
2218
|
const status = await apiFetch(`${grantsUrl}/${grant.id}`);
|
|
2092
2219
|
if (status.status === "approved") {
|
|
2093
|
-
|
|
2220
|
+
consola19.success("Grant approved!");
|
|
2094
2221
|
break;
|
|
2095
2222
|
}
|
|
2096
2223
|
if (status.status === "denied" || status.status === "revoked") {
|
|
@@ -2098,14 +2225,14 @@ async function runAudienceMode(audience, action, args) {
|
|
|
2098
2225
|
}
|
|
2099
2226
|
await new Promise((r) => setTimeout(r, interval));
|
|
2100
2227
|
}
|
|
2101
|
-
|
|
2228
|
+
consola19.info("Fetching grant token...");
|
|
2102
2229
|
const { authz_jwt } = await apiFetch(`${grantsUrl}/${grant.id}/token`, {
|
|
2103
2230
|
method: "POST"
|
|
2104
2231
|
});
|
|
2105
2232
|
if (audience === "escapes") {
|
|
2106
|
-
|
|
2233
|
+
consola19.info(`Executing: ${command.join(" ")}`);
|
|
2107
2234
|
try {
|
|
2108
|
-
|
|
2235
|
+
execFileSync2(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
|
|
2109
2236
|
stdio: "inherit"
|
|
2110
2237
|
});
|
|
2111
2238
|
} catch (err) {
|
|
@@ -2118,8 +2245,8 @@ async function runAudienceMode(audience, action, args) {
|
|
|
2118
2245
|
}
|
|
2119
2246
|
|
|
2120
2247
|
// src/commands/explain.ts
|
|
2121
|
-
import { defineCommand as
|
|
2122
|
-
var explainCommand =
|
|
2248
|
+
import { defineCommand as defineCommand22 } from "citty";
|
|
2249
|
+
var explainCommand = defineCommand22({
|
|
2123
2250
|
meta: {
|
|
2124
2251
|
name: "explain",
|
|
2125
2252
|
description: "Show what permission a command would need"
|
|
@@ -2157,9 +2284,9 @@ var explainCommand = defineCommand21({
|
|
|
2157
2284
|
});
|
|
2158
2285
|
|
|
2159
2286
|
// src/commands/config/get.ts
|
|
2160
|
-
import { defineCommand as
|
|
2161
|
-
import
|
|
2162
|
-
var configGetCommand =
|
|
2287
|
+
import { defineCommand as defineCommand23 } from "citty";
|
|
2288
|
+
import consola20 from "consola";
|
|
2289
|
+
var configGetCommand = defineCommand23({
|
|
2163
2290
|
meta: {
|
|
2164
2291
|
name: "get",
|
|
2165
2292
|
description: "Get a configuration value"
|
|
@@ -2179,7 +2306,7 @@ var configGetCommand = defineCommand22({
|
|
|
2179
2306
|
if (idp)
|
|
2180
2307
|
console.log(idp);
|
|
2181
2308
|
else
|
|
2182
|
-
|
|
2309
|
+
consola20.info("No IdP configured.");
|
|
2183
2310
|
break;
|
|
2184
2311
|
}
|
|
2185
2312
|
case "email": {
|
|
@@ -2187,7 +2314,7 @@ var configGetCommand = defineCommand22({
|
|
|
2187
2314
|
if (auth?.email)
|
|
2188
2315
|
console.log(auth.email);
|
|
2189
2316
|
else
|
|
2190
|
-
|
|
2317
|
+
consola20.info("Not logged in.");
|
|
2191
2318
|
break;
|
|
2192
2319
|
}
|
|
2193
2320
|
default: {
|
|
@@ -2200,7 +2327,7 @@ var configGetCommand = defineCommand22({
|
|
|
2200
2327
|
if (sectionObj && field in sectionObj) {
|
|
2201
2328
|
console.log(sectionObj[field]);
|
|
2202
2329
|
} else {
|
|
2203
|
-
|
|
2330
|
+
consola20.info(`Key "${key}" not set.`);
|
|
2204
2331
|
}
|
|
2205
2332
|
} else {
|
|
2206
2333
|
throw new CliError(`Unknown key: "${key}". Use: idp, email, defaults.idp, defaults.approval, agent.key, agent.email`);
|
|
@@ -2211,9 +2338,9 @@ var configGetCommand = defineCommand22({
|
|
|
2211
2338
|
});
|
|
2212
2339
|
|
|
2213
2340
|
// src/commands/config/set.ts
|
|
2214
|
-
import { defineCommand as
|
|
2215
|
-
import
|
|
2216
|
-
var configSetCommand =
|
|
2341
|
+
import { defineCommand as defineCommand24 } from "citty";
|
|
2342
|
+
import consola21 from "consola";
|
|
2343
|
+
var configSetCommand = defineCommand24({
|
|
2217
2344
|
meta: {
|
|
2218
2345
|
name: "set",
|
|
2219
2346
|
description: "Set a configuration value"
|
|
@@ -2249,12 +2376,12 @@ var configSetCommand = defineCommand23({
|
|
|
2249
2376
|
throw new CliError(`Unknown section: "${section}". Use: defaults, agent`);
|
|
2250
2377
|
}
|
|
2251
2378
|
saveConfig(config);
|
|
2252
|
-
|
|
2379
|
+
consola21.success(`Set ${key} = ${value}`);
|
|
2253
2380
|
}
|
|
2254
2381
|
});
|
|
2255
2382
|
|
|
2256
2383
|
// src/commands/fetch/index.ts
|
|
2257
|
-
import { defineCommand as
|
|
2384
|
+
import { defineCommand as defineCommand25 } from "citty";
|
|
2258
2385
|
async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
2259
2386
|
const token = getAuthToken();
|
|
2260
2387
|
if (!token) {
|
|
@@ -2290,13 +2417,13 @@ async function doRequest(method, url, body, contentType, raw, showHeaders) {
|
|
|
2290
2417
|
throw new CliError(`HTTP ${response.status} ${response.statusText}`);
|
|
2291
2418
|
}
|
|
2292
2419
|
}
|
|
2293
|
-
var fetchCommand =
|
|
2420
|
+
var fetchCommand = defineCommand25({
|
|
2294
2421
|
meta: {
|
|
2295
2422
|
name: "fetch",
|
|
2296
2423
|
description: "Make authenticated HTTP requests"
|
|
2297
2424
|
},
|
|
2298
2425
|
subCommands: {
|
|
2299
|
-
get:
|
|
2426
|
+
get: defineCommand25({
|
|
2300
2427
|
meta: {
|
|
2301
2428
|
name: "get",
|
|
2302
2429
|
description: "GET request with auth token"
|
|
@@ -2322,7 +2449,7 @@ var fetchCommand = defineCommand24({
|
|
|
2322
2449
|
await doRequest("GET", String(args.url), void 0, "application/json", Boolean(args.raw), Boolean(args.headers));
|
|
2323
2450
|
}
|
|
2324
2451
|
}),
|
|
2325
|
-
post:
|
|
2452
|
+
post: defineCommand25({
|
|
2326
2453
|
meta: {
|
|
2327
2454
|
name: "post",
|
|
2328
2455
|
description: "POST request with auth token"
|
|
@@ -2361,8 +2488,8 @@ var fetchCommand = defineCommand24({
|
|
|
2361
2488
|
});
|
|
2362
2489
|
|
|
2363
2490
|
// src/commands/mcp/index.ts
|
|
2364
|
-
import { defineCommand as
|
|
2365
|
-
var mcpCommand =
|
|
2491
|
+
import { defineCommand as defineCommand26 } from "citty";
|
|
2492
|
+
var mcpCommand = defineCommand26({
|
|
2366
2493
|
meta: {
|
|
2367
2494
|
name: "mcp",
|
|
2368
2495
|
description: "Start MCP server for AI agents"
|
|
@@ -2385,7 +2512,7 @@ var mcpCommand = defineCommand25({
|
|
|
2385
2512
|
if (transport !== "stdio" && transport !== "sse") {
|
|
2386
2513
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
2387
2514
|
}
|
|
2388
|
-
const { startMcpServer } = await import("./server-
|
|
2515
|
+
const { startMcpServer } = await import("./server-FFOPFICW.js");
|
|
2389
2516
|
await startMcpServer(transport, port);
|
|
2390
2517
|
}
|
|
2391
2518
|
});
|
|
@@ -2393,10 +2520,10 @@ var mcpCommand = defineCommand25({
|
|
|
2393
2520
|
// src/commands/init/index.ts
|
|
2394
2521
|
import { existsSync as existsSync3, copyFileSync, writeFileSync } from "fs";
|
|
2395
2522
|
import { randomBytes } from "crypto";
|
|
2396
|
-
import { execFileSync as
|
|
2523
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
2397
2524
|
import { join as join2 } from "path";
|
|
2398
|
-
import { defineCommand as
|
|
2399
|
-
import
|
|
2525
|
+
import { defineCommand as defineCommand27 } from "citty";
|
|
2526
|
+
import consola22 from "consola";
|
|
2400
2527
|
var DEFAULT_IDP_URL = "https://id.openape.at";
|
|
2401
2528
|
async function downloadTemplate(repo, targetDir) {
|
|
2402
2529
|
const { downloadTemplate: gigetDownload } = await import("giget");
|
|
@@ -2405,28 +2532,28 @@ async function downloadTemplate(repo, targetDir) {
|
|
|
2405
2532
|
function installDeps(dir) {
|
|
2406
2533
|
const hasLockFile = (name) => existsSync3(join2(dir, name));
|
|
2407
2534
|
if (hasLockFile("pnpm-lock.yaml")) {
|
|
2408
|
-
|
|
2535
|
+
execFileSync3("pnpm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
2409
2536
|
} else if (hasLockFile("bun.lockb")) {
|
|
2410
|
-
|
|
2537
|
+
execFileSync3("bun", ["install"], { cwd: dir, stdio: "inherit" });
|
|
2411
2538
|
} else {
|
|
2412
|
-
|
|
2539
|
+
execFileSync3("npm", ["install"], { cwd: dir, stdio: "inherit" });
|
|
2413
2540
|
}
|
|
2414
2541
|
}
|
|
2415
2542
|
async function promptChoice(message, choices) {
|
|
2416
|
-
const result = await
|
|
2543
|
+
const result = await consola22.prompt(message, { type: "select", options: choices });
|
|
2417
2544
|
if (typeof result === "symbol") {
|
|
2418
2545
|
throw new CliExit(0);
|
|
2419
2546
|
}
|
|
2420
2547
|
return result;
|
|
2421
2548
|
}
|
|
2422
2549
|
async function promptText(message, defaultValue) {
|
|
2423
|
-
const result = await
|
|
2550
|
+
const result = await consola22.prompt(message, { type: "text", default: defaultValue, placeholder: defaultValue });
|
|
2424
2551
|
if (typeof result === "symbol") {
|
|
2425
2552
|
throw new CliExit(0);
|
|
2426
2553
|
}
|
|
2427
2554
|
return result || defaultValue || "";
|
|
2428
2555
|
}
|
|
2429
|
-
var initCommand =
|
|
2556
|
+
var initCommand = defineCommand27({
|
|
2430
2557
|
meta: {
|
|
2431
2558
|
name: "init",
|
|
2432
2559
|
description: "Scaffold a new OpenApe project"
|
|
@@ -2471,20 +2598,20 @@ async function initSP(targetDir) {
|
|
|
2471
2598
|
if (existsSync3(join2(dir, "package.json"))) {
|
|
2472
2599
|
throw new CliError(`Directory "${dir}" already contains a project.`);
|
|
2473
2600
|
}
|
|
2474
|
-
|
|
2601
|
+
consola22.start("Scaffolding SP starter...");
|
|
2475
2602
|
await downloadTemplate("openape-ai/openape-sp-starter", dir);
|
|
2476
|
-
|
|
2477
|
-
|
|
2603
|
+
consola22.success("Scaffolded from openape-sp-starter");
|
|
2604
|
+
consola22.start("Installing dependencies...");
|
|
2478
2605
|
installDeps(dir);
|
|
2479
|
-
|
|
2606
|
+
consola22.success("Dependencies installed");
|
|
2480
2607
|
const envExample = join2(dir, ".env.example");
|
|
2481
2608
|
const envFile = join2(dir, ".env");
|
|
2482
2609
|
if (existsSync3(envExample) && !existsSync3(envFile)) {
|
|
2483
2610
|
copyFileSync(envExample, envFile);
|
|
2484
|
-
|
|
2611
|
+
consola22.success(`\`.env\` created (using Free IdP at ${DEFAULT_IDP_URL})`);
|
|
2485
2612
|
}
|
|
2486
2613
|
console.log("");
|
|
2487
|
-
|
|
2614
|
+
consola22.box([
|
|
2488
2615
|
`cd ${dir}`,
|
|
2489
2616
|
"npm run dev",
|
|
2490
2617
|
"",
|
|
@@ -2503,15 +2630,15 @@ async function initIdP(targetDir) {
|
|
|
2503
2630
|
"s3 (S3-compatible)"
|
|
2504
2631
|
]);
|
|
2505
2632
|
const adminEmail = await promptText("Admin email");
|
|
2506
|
-
|
|
2633
|
+
consola22.start("Scaffolding IdP starter...");
|
|
2507
2634
|
await downloadTemplate("openape-ai/openape-idp-starter", dir);
|
|
2508
|
-
|
|
2509
|
-
|
|
2635
|
+
consola22.success("Scaffolded from openape-idp-starter");
|
|
2636
|
+
consola22.start("Installing dependencies...");
|
|
2510
2637
|
installDeps(dir);
|
|
2511
|
-
|
|
2638
|
+
consola22.success("Dependencies installed");
|
|
2512
2639
|
const sessionSecret = randomBytes(32).toString("hex");
|
|
2513
2640
|
const managementToken = randomBytes(32).toString("hex");
|
|
2514
|
-
|
|
2641
|
+
consola22.success("Secrets generated");
|
|
2515
2642
|
const isLocalhost = domain === "localhost";
|
|
2516
2643
|
const origin = isLocalhost ? "http://localhost:3000" : `https://${domain}`;
|
|
2517
2644
|
const envContent = [
|
|
@@ -2527,9 +2654,9 @@ async function initIdP(targetDir) {
|
|
|
2527
2654
|
].join("\n");
|
|
2528
2655
|
writeFileSync(join2(dir, ".env"), `${envContent}
|
|
2529
2656
|
`, { mode: 384 });
|
|
2530
|
-
|
|
2657
|
+
consola22.success(".env created");
|
|
2531
2658
|
console.log("");
|
|
2532
|
-
|
|
2659
|
+
consola22.box([
|
|
2533
2660
|
`cd ${dir}`,
|
|
2534
2661
|
"npm run dev",
|
|
2535
2662
|
"",
|
|
@@ -2551,8 +2678,8 @@ import { execFile as execFile2 } from "child_process";
|
|
|
2551
2678
|
import { generateKeyPairSync, sign } from "crypto";
|
|
2552
2679
|
import { dirname, resolve as resolve2 } from "path";
|
|
2553
2680
|
import { homedir as homedir4 } from "os";
|
|
2554
|
-
import { defineCommand as
|
|
2555
|
-
import
|
|
2681
|
+
import { defineCommand as defineCommand28 } from "citty";
|
|
2682
|
+
import consola23 from "consola";
|
|
2556
2683
|
var DEFAULT_IDP_URL2 = "https://id.openape.at";
|
|
2557
2684
|
var DEFAULT_KEY_PATH = "~/.ssh/id_ed25519";
|
|
2558
2685
|
var POLL_INTERVAL = 3e3;
|
|
@@ -2637,7 +2764,7 @@ async function pollForEnrollment(idp, agentEmail, keyPath) {
|
|
|
2637
2764
|
}
|
|
2638
2765
|
throw new Error("Enrollment timed out. Please check the browser and try again.");
|
|
2639
2766
|
}
|
|
2640
|
-
var enrollCommand =
|
|
2767
|
+
var enrollCommand = defineCommand28({
|
|
2641
2768
|
meta: {
|
|
2642
2769
|
name: "enroll",
|
|
2643
2770
|
description: "Enroll an agent with an Identity Provider"
|
|
@@ -2657,18 +2784,18 @@ var enrollCommand = defineCommand27({
|
|
|
2657
2784
|
}
|
|
2658
2785
|
},
|
|
2659
2786
|
async run({ args }) {
|
|
2660
|
-
const idp = args.idp || await
|
|
2787
|
+
const idp = args.idp || await consola23.prompt("IdP URL", { type: "text", default: DEFAULT_IDP_URL2, placeholder: DEFAULT_IDP_URL2 }).then((r) => {
|
|
2661
2788
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
2662
2789
|
return r;
|
|
2663
2790
|
}) || DEFAULT_IDP_URL2;
|
|
2664
|
-
const agentName = args.name || await
|
|
2791
|
+
const agentName = args.name || await consola23.prompt("Agent name", { type: "text", placeholder: "deploy-bot" }).then((r) => {
|
|
2665
2792
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
2666
2793
|
return r;
|
|
2667
2794
|
});
|
|
2668
2795
|
if (!agentName) {
|
|
2669
2796
|
throw new CliError("Agent name is required.");
|
|
2670
2797
|
}
|
|
2671
|
-
const keyPath = args.key || await
|
|
2798
|
+
const keyPath = args.key || await consola23.prompt("Ed25519 key", { type: "text", default: DEFAULT_KEY_PATH, placeholder: DEFAULT_KEY_PATH }).then((r) => {
|
|
2672
2799
|
if (typeof r === "symbol") throw new CliExit(0);
|
|
2673
2800
|
return r;
|
|
2674
2801
|
}) || DEFAULT_KEY_PATH;
|
|
@@ -2676,19 +2803,19 @@ var enrollCommand = defineCommand27({
|
|
|
2676
2803
|
let publicKey;
|
|
2677
2804
|
if (existsSync4(resolvedKey)) {
|
|
2678
2805
|
publicKey = readPublicKey(resolvedKey);
|
|
2679
|
-
|
|
2806
|
+
consola23.success(`Using existing key ${keyPath}`);
|
|
2680
2807
|
} else {
|
|
2681
|
-
|
|
2808
|
+
consola23.start(`Generating Ed25519 key pair at ${keyPath}...`);
|
|
2682
2809
|
publicKey = generateAndSaveKey(keyPath);
|
|
2683
|
-
|
|
2810
|
+
consola23.success(`Key pair generated at ${keyPath}`);
|
|
2684
2811
|
}
|
|
2685
2812
|
const encodedKey = encodeURIComponent(publicKey);
|
|
2686
2813
|
const enrollUrl = `${idp}/enroll?name=${encodeURIComponent(agentName)}&key=${encodedKey}`;
|
|
2687
|
-
|
|
2688
|
-
|
|
2814
|
+
consola23.info("Opening browser for enrollment...");
|
|
2815
|
+
consola23.info(`\u2192 ${idp}/enroll`);
|
|
2689
2816
|
openBrowser2(enrollUrl);
|
|
2690
2817
|
console.log("");
|
|
2691
|
-
const agentEmail = await
|
|
2818
|
+
const agentEmail = await consola23.prompt(
|
|
2692
2819
|
"Agent email (shown in browser after enrollment)",
|
|
2693
2820
|
{ type: "text", placeholder: `agent+${agentName}@...` }
|
|
2694
2821
|
).then((r) => {
|
|
@@ -2698,7 +2825,7 @@ var enrollCommand = defineCommand27({
|
|
|
2698
2825
|
if (!agentEmail) {
|
|
2699
2826
|
throw new CliError("Agent email is required to verify enrollment.");
|
|
2700
2827
|
}
|
|
2701
|
-
|
|
2828
|
+
consola23.start("Verifying enrollment...");
|
|
2702
2829
|
const { token, expiresIn } = await pollForEnrollment(idp, agentEmail, keyPath);
|
|
2703
2830
|
saveAuth({
|
|
2704
2831
|
idp,
|
|
@@ -2710,18 +2837,18 @@ var enrollCommand = defineCommand27({
|
|
|
2710
2837
|
config.defaults = { ...config.defaults, idp };
|
|
2711
2838
|
config.agent = { key: keyPath, email: agentEmail };
|
|
2712
2839
|
saveConfig(config);
|
|
2713
|
-
|
|
2714
|
-
|
|
2840
|
+
consola23.success(`Agent enrolled as ${agentEmail}`);
|
|
2841
|
+
consola23.success("Config saved to ~/.config/apes/");
|
|
2715
2842
|
console.log("");
|
|
2716
|
-
|
|
2843
|
+
consola23.info("Verify with: apes whoami");
|
|
2717
2844
|
}
|
|
2718
2845
|
});
|
|
2719
2846
|
|
|
2720
2847
|
// src/commands/register-user.ts
|
|
2721
2848
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
2722
|
-
import { defineCommand as
|
|
2723
|
-
import
|
|
2724
|
-
var registerUserCommand =
|
|
2849
|
+
import { defineCommand as defineCommand29 } from "citty";
|
|
2850
|
+
import consola24 from "consola";
|
|
2851
|
+
var registerUserCommand = defineCommand29({
|
|
2725
2852
|
meta: {
|
|
2726
2853
|
name: "register-user",
|
|
2727
2854
|
description: "Register a sub-user with SSH key"
|
|
@@ -2776,15 +2903,15 @@ var registerUserCommand = defineCommand28({
|
|
|
2776
2903
|
...userType ? { type: userType } : {}
|
|
2777
2904
|
}
|
|
2778
2905
|
});
|
|
2779
|
-
|
|
2906
|
+
consola24.success(`User registered: ${result.email} (type: ${result.type}, owner: ${result.owner})`);
|
|
2780
2907
|
}
|
|
2781
2908
|
});
|
|
2782
2909
|
|
|
2783
2910
|
// src/commands/dns-check.ts
|
|
2784
|
-
import { defineCommand as
|
|
2785
|
-
import
|
|
2911
|
+
import { defineCommand as defineCommand30 } from "citty";
|
|
2912
|
+
import consola25 from "consola";
|
|
2786
2913
|
import { resolveDDISA as resolveDDISA2 } from "@openape/core";
|
|
2787
|
-
var dnsCheckCommand =
|
|
2914
|
+
var dnsCheckCommand = defineCommand30({
|
|
2788
2915
|
meta: {
|
|
2789
2916
|
name: "dns-check",
|
|
2790
2917
|
description: "Validate DDISA DNS TXT records for a domain"
|
|
@@ -2798,7 +2925,7 @@ var dnsCheckCommand = defineCommand29({
|
|
|
2798
2925
|
},
|
|
2799
2926
|
async run({ args }) {
|
|
2800
2927
|
const domain = args.domain;
|
|
2801
|
-
|
|
2928
|
+
consola25.start(`Checking _ddisa.${domain}...`);
|
|
2802
2929
|
try {
|
|
2803
2930
|
const result = await resolveDDISA2(domain);
|
|
2804
2931
|
if (!result) {
|
|
@@ -2807,7 +2934,7 @@ var dnsCheckCommand = defineCommand29({
|
|
|
2807
2934
|
console.log(` _ddisa.${domain} TXT "v=ddisa1 idp=https://id.${domain}"`);
|
|
2808
2935
|
throw new CliError(`No DDISA record found for ${domain}`);
|
|
2809
2936
|
}
|
|
2810
|
-
|
|
2937
|
+
consola25.success(`_ddisa.${domain} \u2192 ${result.idp}`);
|
|
2811
2938
|
console.log("");
|
|
2812
2939
|
console.log(` Version: ${result.version || "ddisa1"}`);
|
|
2813
2940
|
console.log(` IdP URL: ${result.idp}`);
|
|
@@ -2816,14 +2943,14 @@ var dnsCheckCommand = defineCommand29({
|
|
|
2816
2943
|
if (result.priority !== void 0)
|
|
2817
2944
|
console.log(` Priority: ${result.priority}`);
|
|
2818
2945
|
console.log("");
|
|
2819
|
-
|
|
2946
|
+
consola25.start(`Verifying IdP at ${result.idp}...`);
|
|
2820
2947
|
const discoResp = await fetch(`${result.idp}/.well-known/openid-configuration`);
|
|
2821
2948
|
if (!discoResp.ok) {
|
|
2822
|
-
|
|
2949
|
+
consola25.warn(`IdP discovery failed (${discoResp.status}). Is the IdP running at ${result.idp}?`);
|
|
2823
2950
|
return;
|
|
2824
2951
|
}
|
|
2825
2952
|
const disco = await discoResp.json();
|
|
2826
|
-
|
|
2953
|
+
consola25.success(`IdP is reachable`);
|
|
2827
2954
|
console.log(` Issuer: ${disco.issuer}`);
|
|
2828
2955
|
console.log(` DDISA: v${disco.ddisa_version || "?"}`);
|
|
2829
2956
|
if (disco.ddisa_auth_methods_supported) {
|
|
@@ -2838,9 +2965,128 @@ var dnsCheckCommand = defineCommand29({
|
|
|
2838
2965
|
}
|
|
2839
2966
|
});
|
|
2840
2967
|
|
|
2968
|
+
// src/commands/health.ts
|
|
2969
|
+
import { exec } from "child_process";
|
|
2970
|
+
import { promisify } from "util";
|
|
2971
|
+
import { defineCommand as defineCommand31 } from "citty";
|
|
2972
|
+
var execAsync = promisify(exec);
|
|
2973
|
+
async function resolveApeShellPath() {
|
|
2974
|
+
try {
|
|
2975
|
+
const { stdout } = await execAsync("command -v ape-shell", { shell: "/bin/bash" });
|
|
2976
|
+
const trimmed = stdout.trim();
|
|
2977
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
2978
|
+
} catch {
|
|
2979
|
+
return null;
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
async function probeIdp(url) {
|
|
2983
|
+
const ctrl = new AbortController();
|
|
2984
|
+
const timeout = setTimeout(() => ctrl.abort(), 3e3);
|
|
2985
|
+
try {
|
|
2986
|
+
await fetch(url, { method: "GET", signal: ctrl.signal });
|
|
2987
|
+
return { reachable: true };
|
|
2988
|
+
} catch (err) {
|
|
2989
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2990
|
+
return { reachable: false, error: message };
|
|
2991
|
+
} finally {
|
|
2992
|
+
clearTimeout(timeout);
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
async function bestEffortGrantCount(idp) {
|
|
2996
|
+
try {
|
|
2997
|
+
const grantsUrl = await getGrantsEndpoint(idp);
|
|
2998
|
+
const res = await apiFetch(`${grantsUrl}?limit=1`);
|
|
2999
|
+
const count = Array.isArray(res?.data) ? res.data.length : 0;
|
|
3000
|
+
return { count };
|
|
3001
|
+
} catch (err) {
|
|
3002
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3003
|
+
return { error: message };
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
async function runHealth(args) {
|
|
3007
|
+
const version = true ? "0.9.0" : "0.0.0";
|
|
3008
|
+
const auth = loadAuth();
|
|
3009
|
+
if (!auth) {
|
|
3010
|
+
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
3011
|
+
}
|
|
3012
|
+
const isAgent = auth.email.includes("agent+");
|
|
3013
|
+
const expiresDate = new Date(auth.expires_at * 1e3);
|
|
3014
|
+
const isExpired = Date.now() / 1e3 > auth.expires_at;
|
|
3015
|
+
if (isExpired) {
|
|
3016
|
+
throw new CliError(`Token expired at ${expiresDate.toISOString()}. Run \`apes login\`.`, 1);
|
|
3017
|
+
}
|
|
3018
|
+
const idpProbe = await probeIdp(auth.idp);
|
|
3019
|
+
const grantInfo = await bestEffortGrantCount(auth.idp);
|
|
3020
|
+
const apeShellPath = await resolveApeShellPath();
|
|
3021
|
+
const report = {
|
|
3022
|
+
version,
|
|
3023
|
+
config: { dir: CONFIG_DIR },
|
|
3024
|
+
auth: {
|
|
3025
|
+
file: AUTH_FILE,
|
|
3026
|
+
present: true,
|
|
3027
|
+
email: auth.email,
|
|
3028
|
+
type: isAgent ? "agent" : "human",
|
|
3029
|
+
idp: auth.idp,
|
|
3030
|
+
expires_at_iso: expiresDate.toISOString(),
|
|
3031
|
+
expires_at_local: expiresDate.toLocaleString(),
|
|
3032
|
+
expired: false
|
|
3033
|
+
},
|
|
3034
|
+
idp: {
|
|
3035
|
+
url: auth.idp,
|
|
3036
|
+
reachable: idpProbe.reachable,
|
|
3037
|
+
..."error" in idpProbe ? { error: idpProbe.error } : {}
|
|
3038
|
+
},
|
|
3039
|
+
grants: "count" in grantInfo ? { count: grantInfo.count } : { error: grantInfo.error },
|
|
3040
|
+
ape_shell_binary: apeShellPath,
|
|
3041
|
+
ok: idpProbe.reachable
|
|
3042
|
+
};
|
|
3043
|
+
if (args.json) {
|
|
3044
|
+
console.log(JSON.stringify(report, null, 2));
|
|
3045
|
+
} else {
|
|
3046
|
+
console.log(`apes ${version}`);
|
|
3047
|
+
console.log("");
|
|
3048
|
+
console.log(`Config: ${CONFIG_DIR}`);
|
|
3049
|
+
console.log(`Auth: ${AUTH_FILE}`);
|
|
3050
|
+
console.log(` ${auth.email} (${isAgent ? "agent" : "human"})`);
|
|
3051
|
+
console.log(` IdP: ${auth.idp}`);
|
|
3052
|
+
console.log(` Token: valid until ${expiresDate.toISOString()} (local: ${expiresDate.toLocaleString()})`);
|
|
3053
|
+
console.log("");
|
|
3054
|
+
if (idpProbe.reachable) {
|
|
3055
|
+
console.log("IdP: reachable");
|
|
3056
|
+
} else {
|
|
3057
|
+
console.log(`IdP: <unreachable: ${idpProbe.error}>`);
|
|
3058
|
+
}
|
|
3059
|
+
if ("count" in grantInfo) {
|
|
3060
|
+
console.log(`Grants: ${grantInfo.count}`);
|
|
3061
|
+
} else {
|
|
3062
|
+
console.log(`Grants: <unreachable: ${grantInfo.error}>`);
|
|
3063
|
+
}
|
|
3064
|
+
console.log(`ape-shell: ${apeShellPath ?? "(not on PATH)"}`);
|
|
3065
|
+
}
|
|
3066
|
+
if (!idpProbe.reachable) {
|
|
3067
|
+
throw new CliError(`IdP ${auth.idp} unreachable: ${idpProbe.error}`, 1);
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
var healthCommand = defineCommand31({
|
|
3071
|
+
meta: {
|
|
3072
|
+
name: "health",
|
|
3073
|
+
description: "Report CLI diagnostic state (auth, IdP, grants, binaries)"
|
|
3074
|
+
},
|
|
3075
|
+
args: {
|
|
3076
|
+
json: {
|
|
3077
|
+
type: "boolean",
|
|
3078
|
+
description: "Emit a machine-readable JSON report",
|
|
3079
|
+
default: false
|
|
3080
|
+
}
|
|
3081
|
+
},
|
|
3082
|
+
async run({ args }) {
|
|
3083
|
+
await runHealth({ json: Boolean(args.json) });
|
|
3084
|
+
}
|
|
3085
|
+
});
|
|
3086
|
+
|
|
2841
3087
|
// src/commands/workflows.ts
|
|
2842
|
-
import { defineCommand as
|
|
2843
|
-
import
|
|
3088
|
+
import { defineCommand as defineCommand32 } from "citty";
|
|
3089
|
+
import consola26 from "consola";
|
|
2844
3090
|
|
|
2845
3091
|
// src/guides/index.ts
|
|
2846
3092
|
var guides = [
|
|
@@ -2890,7 +3136,7 @@ var guides = [
|
|
|
2890
3136
|
];
|
|
2891
3137
|
|
|
2892
3138
|
// src/commands/workflows.ts
|
|
2893
|
-
var workflowsCommand =
|
|
3139
|
+
var workflowsCommand = defineCommand32({
|
|
2894
3140
|
meta: {
|
|
2895
3141
|
name: "workflows",
|
|
2896
3142
|
description: "Discover workflow guides"
|
|
@@ -2911,7 +3157,7 @@ var workflowsCommand = defineCommand30({
|
|
|
2911
3157
|
if (args.id) {
|
|
2912
3158
|
const guide = guides.find((g) => g.id === String(args.id));
|
|
2913
3159
|
if (!guide) {
|
|
2914
|
-
|
|
3160
|
+
consola26.info(`Available: ${guides.map((g) => g.id).join(", ")}`);
|
|
2915
3161
|
throw new CliError(`Guide not found: ${args.id}`);
|
|
2916
3162
|
}
|
|
2917
3163
|
if (args.json) {
|
|
@@ -2960,10 +3206,10 @@ if (shellRewrite) {
|
|
|
2960
3206
|
if (shellRewrite.action === "rewrite") {
|
|
2961
3207
|
process.argv = shellRewrite.argv;
|
|
2962
3208
|
} else if (shellRewrite.action === "version") {
|
|
2963
|
-
console.log(`ape-shell ${"0.
|
|
3209
|
+
console.log(`ape-shell ${"0.9.0"} (OpenApe DDISA shell wrapper)`);
|
|
2964
3210
|
process.exit(0);
|
|
2965
3211
|
} else if (shellRewrite.action === "help") {
|
|
2966
|
-
console.log(`ape-shell ${"0.
|
|
3212
|
+
console.log(`ape-shell ${"0.9.0"} \u2014 OpenApe DDISA shell wrapper`);
|
|
2967
3213
|
console.log("");
|
|
2968
3214
|
console.log("Usage:");
|
|
2969
3215
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -2978,7 +3224,7 @@ if (shellRewrite) {
|
|
|
2978
3224
|
console.log(" --help, -h Show this help message");
|
|
2979
3225
|
process.exit(0);
|
|
2980
3226
|
} else if (shellRewrite.action === "interactive") {
|
|
2981
|
-
const { runInteractiveShell } = await import("./orchestrator-
|
|
3227
|
+
const { runInteractiveShell } = await import("./orchestrator-GPNL543L.js");
|
|
2982
3228
|
await runInteractiveShell();
|
|
2983
3229
|
process.exit(0);
|
|
2984
3230
|
} else {
|
|
@@ -2987,7 +3233,7 @@ if (shellRewrite) {
|
|
|
2987
3233
|
}
|
|
2988
3234
|
}
|
|
2989
3235
|
var debug = process.argv.includes("--debug");
|
|
2990
|
-
var grantsCommand =
|
|
3236
|
+
var grantsCommand = defineCommand33({
|
|
2991
3237
|
meta: {
|
|
2992
3238
|
name: "grants",
|
|
2993
3239
|
description: "Grant management"
|
|
@@ -3001,13 +3247,14 @@ var grantsCommand = defineCommand31({
|
|
|
3001
3247
|
approve: approveCommand,
|
|
3002
3248
|
deny: denyCommand,
|
|
3003
3249
|
revoke: revokeCommand,
|
|
3250
|
+
run: runGrantCommand,
|
|
3004
3251
|
token: tokenCommand,
|
|
3005
3252
|
delegate: delegateCommand,
|
|
3006
3253
|
delegations: delegationsCommand,
|
|
3007
3254
|
"delegation-revoke": delegationRevokeCommand
|
|
3008
3255
|
}
|
|
3009
3256
|
});
|
|
3010
|
-
var configCommand =
|
|
3257
|
+
var configCommand = defineCommand33({
|
|
3011
3258
|
meta: {
|
|
3012
3259
|
name: "config",
|
|
3013
3260
|
description: "Configuration management"
|
|
@@ -3017,10 +3264,10 @@ var configCommand = defineCommand31({
|
|
|
3017
3264
|
set: configSetCommand
|
|
3018
3265
|
}
|
|
3019
3266
|
});
|
|
3020
|
-
var main =
|
|
3267
|
+
var main = defineCommand33({
|
|
3021
3268
|
meta: {
|
|
3022
3269
|
name: "apes",
|
|
3023
|
-
version: "0.
|
|
3270
|
+
version: "0.9.0",
|
|
3024
3271
|
description: "Unified CLI for OpenApe"
|
|
3025
3272
|
},
|
|
3026
3273
|
subCommands: {
|
|
@@ -3031,6 +3278,7 @@ var main = defineCommand31({
|
|
|
3031
3278
|
login: loginCommand,
|
|
3032
3279
|
logout: logoutCommand,
|
|
3033
3280
|
whoami: whoamiCommand,
|
|
3281
|
+
health: healthCommand,
|
|
3034
3282
|
grants: grantsCommand,
|
|
3035
3283
|
admin: adminCommand,
|
|
3036
3284
|
run: runCommand,
|
|
@@ -3047,13 +3295,13 @@ runMain(main).catch((err) => {
|
|
|
3047
3295
|
process.exit(err.exitCode);
|
|
3048
3296
|
}
|
|
3049
3297
|
if (err instanceof CliError) {
|
|
3050
|
-
|
|
3298
|
+
consola27.error(err.message);
|
|
3051
3299
|
process.exit(err.exitCode);
|
|
3052
3300
|
}
|
|
3053
3301
|
if (debug) {
|
|
3054
|
-
|
|
3302
|
+
consola27.error(err);
|
|
3055
3303
|
} else {
|
|
3056
|
-
|
|
3304
|
+
consola27.error(err instanceof ApiError ? err.message : err instanceof Error ? err.message : String(err));
|
|
3057
3305
|
}
|
|
3058
3306
|
process.exit(1);
|
|
3059
3307
|
});
|