@openape/apes 0.10.0 → 0.10.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
|
@@ -1064,6 +1064,59 @@ var revokeCommand = defineCommand11({
|
|
|
1064
1064
|
import { execFileSync } from "child_process";
|
|
1065
1065
|
import { defineCommand as defineCommand12 } from "citty";
|
|
1066
1066
|
import consola12 from "consola";
|
|
1067
|
+
|
|
1068
|
+
// src/grant-poll.ts
|
|
1069
|
+
function getPollIntervalSeconds() {
|
|
1070
|
+
const envValue = process.env.APES_GRANT_POLL_INTERVAL;
|
|
1071
|
+
if (envValue) {
|
|
1072
|
+
const n = Number(envValue);
|
|
1073
|
+
if (Number.isFinite(n) && n > 0)
|
|
1074
|
+
return Math.floor(n);
|
|
1075
|
+
}
|
|
1076
|
+
const cfg = loadConfig();
|
|
1077
|
+
const cfgValue = cfg.defaults?.grant_poll_interval_seconds;
|
|
1078
|
+
if (cfgValue) {
|
|
1079
|
+
const n = Number(cfgValue);
|
|
1080
|
+
if (Number.isFinite(n) && n > 0)
|
|
1081
|
+
return Math.floor(n);
|
|
1082
|
+
}
|
|
1083
|
+
return 10;
|
|
1084
|
+
}
|
|
1085
|
+
function getPollMaxMinutes() {
|
|
1086
|
+
const envValue = process.env.APES_GRANT_POLL_MAX_MINUTES;
|
|
1087
|
+
if (envValue) {
|
|
1088
|
+
const n = Number(envValue);
|
|
1089
|
+
if (Number.isFinite(n) && n > 0)
|
|
1090
|
+
return Math.floor(n);
|
|
1091
|
+
}
|
|
1092
|
+
const cfg = loadConfig();
|
|
1093
|
+
const cfgValue = cfg.defaults?.grant_poll_max_minutes;
|
|
1094
|
+
if (cfgValue) {
|
|
1095
|
+
const n = Number(cfgValue);
|
|
1096
|
+
if (Number.isFinite(n) && n > 0)
|
|
1097
|
+
return Math.floor(n);
|
|
1098
|
+
}
|
|
1099
|
+
return 5;
|
|
1100
|
+
}
|
|
1101
|
+
async function pollGrantUntilResolved(idp, grantId) {
|
|
1102
|
+
const grantsEndpoint = await getGrantsEndpoint(idp);
|
|
1103
|
+
const intervalSec = getPollIntervalSeconds();
|
|
1104
|
+
const maxMinutes = getPollMaxMinutes();
|
|
1105
|
+
const maxMs = maxMinutes * 6e4;
|
|
1106
|
+
const intervalMs = intervalSec * 1e3;
|
|
1107
|
+
const start = Date.now();
|
|
1108
|
+
while (Date.now() - start < maxMs) {
|
|
1109
|
+
const grant = await apiFetch(`${grantsEndpoint}/${grantId}`);
|
|
1110
|
+
if (grant.status === "approved")
|
|
1111
|
+
return { kind: "approved" };
|
|
1112
|
+
if (grant.status === "denied" || grant.status === "revoked" || grant.status === "used")
|
|
1113
|
+
return { kind: "terminal", status: grant.status };
|
|
1114
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
1115
|
+
}
|
|
1116
|
+
return { kind: "timeout" };
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// src/commands/grants/run.ts
|
|
1067
1120
|
var runGrantCommand = defineCommand12({
|
|
1068
1121
|
meta: {
|
|
1069
1122
|
name: "run",
|
|
@@ -1079,6 +1132,11 @@ var runGrantCommand = defineCommand12({
|
|
|
1079
1132
|
type: "string",
|
|
1080
1133
|
description: "Path to escapes binary (audience=escapes only)",
|
|
1081
1134
|
default: "escapes"
|
|
1135
|
+
},
|
|
1136
|
+
wait: {
|
|
1137
|
+
type: "boolean",
|
|
1138
|
+
description: "If the grant is pending, block and poll until approved (or denied/revoked/used/timeout). Reuses APES_GRANT_POLL_INTERVAL / APES_GRANT_POLL_MAX_MINUTES knobs.",
|
|
1139
|
+
default: false
|
|
1082
1140
|
}
|
|
1083
1141
|
},
|
|
1084
1142
|
async run({ args }) {
|
|
@@ -1086,9 +1144,29 @@ var runGrantCommand = defineCommand12({
|
|
|
1086
1144
|
if (!idp)
|
|
1087
1145
|
throw new CliError("No IdP URL configured. Run `apes login` first or pass --idp.");
|
|
1088
1146
|
const grantsUrl = await getGrantsEndpoint(idp);
|
|
1089
|
-
|
|
1090
|
-
if (grant.status === "pending")
|
|
1091
|
-
|
|
1147
|
+
let grant = await apiFetch(`${grantsUrl}/${args.id}`);
|
|
1148
|
+
if (grant.status === "pending") {
|
|
1149
|
+
if (!args.wait) {
|
|
1150
|
+
throw new CliError(
|
|
1151
|
+
`Grant ${grant.id} is still pending. Approve at: ${idp}/grant-approval?grant_id=${grant.id}`
|
|
1152
|
+
);
|
|
1153
|
+
}
|
|
1154
|
+
const maxMinutes = getPollMaxMinutes();
|
|
1155
|
+
consola12.info(`Waiting for grant ${grant.id} approval (up to ${maxMinutes} minute${maxMinutes === 1 ? "" : "s"})...`);
|
|
1156
|
+
const outcome = await pollGrantUntilResolved(idp, grant.id);
|
|
1157
|
+
if (outcome.kind === "timeout") {
|
|
1158
|
+
throw new CliError(
|
|
1159
|
+
`Grant ${grant.id} approval timed out after ${maxMinutes} minute${maxMinutes === 1 ? "" : "s"}. Re-run after approval, or extend the timeout via APES_GRANT_POLL_MAX_MINUTES.`
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
if (outcome.kind === "terminal") {
|
|
1163
|
+
throw new CliError(
|
|
1164
|
+
`Grant ${grant.id} resolved to ${outcome.status}. Request a new one.`
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
grant = await apiFetch(`${grantsUrl}/${args.id}`);
|
|
1168
|
+
consola12.info(`Grant ${grant.id} approved \u2014 continuing`);
|
|
1169
|
+
}
|
|
1092
1170
|
if (grant.status === "denied" || grant.status === "revoked")
|
|
1093
1171
|
throw new CliError(`Grant ${grant.id} is ${grant.status}. Request a new one.`);
|
|
1094
1172
|
if (grant.status === "used")
|
|
@@ -1940,38 +2018,6 @@ function getUserMode() {
|
|
|
1940
2018
|
return "human";
|
|
1941
2019
|
return "agent";
|
|
1942
2020
|
}
|
|
1943
|
-
function getPollIntervalSeconds() {
|
|
1944
|
-
const envValue = process.env.APES_GRANT_POLL_INTERVAL;
|
|
1945
|
-
if (envValue) {
|
|
1946
|
-
const n = Number(envValue);
|
|
1947
|
-
if (Number.isFinite(n) && n > 0)
|
|
1948
|
-
return Math.floor(n);
|
|
1949
|
-
}
|
|
1950
|
-
const cfg = loadConfig();
|
|
1951
|
-
const cfgValue = cfg.defaults?.grant_poll_interval_seconds;
|
|
1952
|
-
if (cfgValue) {
|
|
1953
|
-
const n = Number(cfgValue);
|
|
1954
|
-
if (Number.isFinite(n) && n > 0)
|
|
1955
|
-
return Math.floor(n);
|
|
1956
|
-
}
|
|
1957
|
-
return 10;
|
|
1958
|
-
}
|
|
1959
|
-
function getPollMaxMinutes() {
|
|
1960
|
-
const envValue = process.env.APES_GRANT_POLL_MAX_MINUTES;
|
|
1961
|
-
if (envValue) {
|
|
1962
|
-
const n = Number(envValue);
|
|
1963
|
-
if (Number.isFinite(n) && n > 0)
|
|
1964
|
-
return Math.floor(n);
|
|
1965
|
-
}
|
|
1966
|
-
const cfg = loadConfig();
|
|
1967
|
-
const cfgValue = cfg.defaults?.grant_poll_max_minutes;
|
|
1968
|
-
if (cfgValue) {
|
|
1969
|
-
const n = Number(cfgValue);
|
|
1970
|
-
if (Number.isFinite(n) && n > 0)
|
|
1971
|
-
return Math.floor(n);
|
|
1972
|
-
}
|
|
1973
|
-
return 5;
|
|
1974
|
-
}
|
|
1975
2021
|
function getAsyncExitCode() {
|
|
1976
2022
|
const envValue = process.env.APES_ASYNC_EXIT_CODE;
|
|
1977
2023
|
if (envValue !== void 0 && envValue !== "") {
|
|
@@ -2003,17 +2049,25 @@ function printPendingGrantInfo(grant, idp) {
|
|
|
2003
2049
|
console.log(" this grant without re-approval on the next invocation.");
|
|
2004
2050
|
return;
|
|
2005
2051
|
}
|
|
2006
|
-
const pollSec = getPollIntervalSeconds();
|
|
2007
2052
|
const maxMin = getPollMaxMinutes();
|
|
2008
2053
|
consola19.success(`Grant ${grant.id} created (pending approval)`);
|
|
2009
2054
|
console.log(` Approve: ${approveUrl}`);
|
|
2010
2055
|
console.log(` Status: ${statusCmd} [--json]`);
|
|
2011
|
-
console.log(` Execute: ${executeCmd}`);
|
|
2056
|
+
console.log(` Execute: ${executeCmd} --wait`);
|
|
2057
|
+
console.log("");
|
|
2058
|
+
console.log(" For agents:");
|
|
2059
|
+
console.log(` 1. Tell the user about the pending grant and the approve URL above.`);
|
|
2060
|
+
console.log(` 2. Run \`${executeCmd} --wait\`. This blocks up to ${maxMin} minutes`);
|
|
2061
|
+
console.log(` until the user approves (or denies/timeout) and then executes`);
|
|
2062
|
+
console.log(` the command in a single step. The CLI handles the polling loop`);
|
|
2063
|
+
console.log(` internally \u2014 you do not need to poll the status yourself.`);
|
|
2064
|
+
console.log(` 3. Exit 0 means approved + executed; stdout is the command output.`);
|
|
2065
|
+
console.log(` Exit 75 (pending) only appears if you accidentally call this`);
|
|
2066
|
+
console.log(` without --wait. Any other non-zero exit means denied, revoked,`);
|
|
2067
|
+
console.log(` used, or timeout \u2014 report the reason to the user.`);
|
|
2012
2068
|
console.log("");
|
|
2013
|
-
console.log(
|
|
2014
|
-
console.log(
|
|
2015
|
-
console.log(` On "denied" or "revoked", stop and report to the user.`);
|
|
2016
|
-
console.log(` On timeout, stop and notify the user that approval has not happened.`);
|
|
2069
|
+
console.log(' Note: exit code 75 (EX_TEMPFAIL) from this command means "pending,');
|
|
2070
|
+
console.log(' retry later" \u2014 do not abort your workflow, follow the steps above.');
|
|
2017
2071
|
console.log("");
|
|
2018
2072
|
console.log(' Tip: Approve as "timed" or "always" in the browser to let this');
|
|
2019
2073
|
console.log(" grant be reused on subsequent invocations without re-approval.");
|
|
@@ -2626,7 +2680,7 @@ var mcpCommand = defineCommand26({
|
|
|
2626
2680
|
if (transport !== "stdio" && transport !== "sse") {
|
|
2627
2681
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
2628
2682
|
}
|
|
2629
|
-
const { startMcpServer } = await import("./server-
|
|
2683
|
+
const { startMcpServer } = await import("./server-GTATJDYX.js");
|
|
2630
2684
|
await startMcpServer(transport, port);
|
|
2631
2685
|
}
|
|
2632
2686
|
});
|
|
@@ -3118,7 +3172,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
3118
3172
|
}
|
|
3119
3173
|
}
|
|
3120
3174
|
async function runHealth(args) {
|
|
3121
|
-
const version = true ? "0.10.
|
|
3175
|
+
const version = true ? "0.10.1" : "0.0.0";
|
|
3122
3176
|
const auth = loadAuth();
|
|
3123
3177
|
if (!auth) {
|
|
3124
3178
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -3320,10 +3374,10 @@ if (shellRewrite) {
|
|
|
3320
3374
|
if (shellRewrite.action === "rewrite") {
|
|
3321
3375
|
process.argv = shellRewrite.argv;
|
|
3322
3376
|
} else if (shellRewrite.action === "version") {
|
|
3323
|
-
console.log(`ape-shell ${"0.10.
|
|
3377
|
+
console.log(`ape-shell ${"0.10.1"} (OpenApe DDISA shell wrapper)`);
|
|
3324
3378
|
process.exit(0);
|
|
3325
3379
|
} else if (shellRewrite.action === "help") {
|
|
3326
|
-
console.log(`ape-shell ${"0.10.
|
|
3380
|
+
console.log(`ape-shell ${"0.10.1"} \u2014 OpenApe DDISA shell wrapper`);
|
|
3327
3381
|
console.log("");
|
|
3328
3382
|
console.log("Usage:");
|
|
3329
3383
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -3381,7 +3435,7 @@ var configCommand = defineCommand33({
|
|
|
3381
3435
|
var main = defineCommand33({
|
|
3382
3436
|
meta: {
|
|
3383
3437
|
name: "apes",
|
|
3384
|
-
version: "0.10.
|
|
3438
|
+
version: "0.10.1",
|
|
3385
3439
|
description: "Unified CLI for OpenApe"
|
|
3386
3440
|
},
|
|
3387
3441
|
subCommands: {
|