@openape/apes 0.9.2 → 0.9.4
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-6U2G75S6.js → auth-lock-6GGWZVOA.js} +2 -2
- package/dist/{chunk-UQ673USC.js → chunk-D3OMN7RV.js} +3 -3
- package/dist/{chunk-AZVY3X7Q.js → chunk-ILKZ5HGV.js} +1 -1
- package/dist/chunk-ILKZ5HGV.js.map +1 -0
- package/dist/{chunk-LSKHTHUY.js → chunk-ZHTLP2DD.js} +19 -3
- package/dist/chunk-ZHTLP2DD.js.map +1 -0
- package/dist/cli.js +96 -17
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +18 -0
- package/dist/index.js +2 -2
- package/dist/{orchestrator-GJ5V4XDT.js → orchestrator-5EZD7ZQE.js} +7 -13
- package/dist/orchestrator-5EZD7ZQE.js.map +1 -0
- package/dist/{server-UA3JNXXZ.js → server-ED5MMYT3.js} +4 -4
- package/package.json +3 -3
- package/dist/chunk-AZVY3X7Q.js.map +0 -1
- package/dist/chunk-LSKHTHUY.js.map +0 -1
- package/dist/orchestrator-GJ5V4XDT.js.map +0 -1
- /package/dist/{auth-lock-6U2G75S6.js.map → auth-lock-6GGWZVOA.js.map} +0 -0
- /package/dist/{chunk-UQ673USC.js.map → chunk-D3OMN7RV.js.map} +0 -0
- /package/dist/{server-UA3JNXXZ.js.map → server-ED5MMYT3.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CONFIG_DIR
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ILKZ5HGV.js";
|
|
5
5
|
|
|
6
6
|
// src/auth-lock.ts
|
|
7
7
|
import { open, rm, stat } from "fs/promises";
|
|
@@ -38,4 +38,4 @@ export {
|
|
|
38
38
|
acquireAuthLock,
|
|
39
39
|
releaseAuthLock
|
|
40
40
|
};
|
|
41
|
-
//# sourceMappingURL=auth-lock-
|
|
41
|
+
//# sourceMappingURL=auth-lock-6GGWZVOA.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
loadAuth,
|
|
6
6
|
loadConfig,
|
|
7
7
|
saveAuth
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ILKZ5HGV.js";
|
|
9
9
|
|
|
10
10
|
// src/http.ts
|
|
11
11
|
import consola from "consola";
|
|
@@ -104,7 +104,7 @@ async function refreshOAuthToken() {
|
|
|
104
104
|
const auth = loadAuth();
|
|
105
105
|
if (!auth?.refresh_token)
|
|
106
106
|
return null;
|
|
107
|
-
const { acquireAuthLock, releaseAuthLock } = await import("./auth-lock-
|
|
107
|
+
const { acquireAuthLock, releaseAuthLock } = await import("./auth-lock-6GGWZVOA.js");
|
|
108
108
|
const lock = await acquireAuthLock({ timeoutMs: 5e3 });
|
|
109
109
|
if (!lock) {
|
|
110
110
|
return getAuthToken();
|
|
@@ -1302,4 +1302,4 @@ export {
|
|
|
1302
1302
|
buildExactCommandGrantRequest,
|
|
1303
1303
|
buildStructuredCliGrantRequest
|
|
1304
1304
|
};
|
|
1305
|
-
//# sourceMappingURL=chunk-
|
|
1305
|
+
//# sourceMappingURL=chunk-D3OMN7RV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport interface AuthData {\n idp: string\n access_token: string\n refresh_token?: string\n email: string\n expires_at: number\n}\n\nexport interface ApesConfig {\n defaults?: {\n idp?: string\n approval?: string\n /**\n * Audience for the `apes run` async info block. `agent` (default)\n * emits verbose agent-facing instructions with a polling protocol;\n * `human` emits a short friendly block. Env var `APES_USER` wins.\n */\n user?: 'agent' | 'human'\n /**\n * Poll interval (seconds) embedded in the agent-mode instructions.\n * Default 10. Env var `APES_GRANT_POLL_INTERVAL` wins. Stored as a\n * string in TOML because the hand-rolled parser only handles quoted\n * values — casting to number happens at read time.\n */\n grant_poll_interval_seconds?: string\n /**\n * Maximum poll duration (minutes) embedded in the agent-mode\n * instructions. Default 5. Env var `APES_GRANT_POLL_MAX_MINUTES` wins.\n */\n grant_poll_max_minutes?: string\n }\n agent?: {\n key?: string\n email?: string\n }\n notifications?: {\n pending_command?: string\n }\n}\n\nconst CONFIG_DIR = join(homedir(), '.config', 'apes')\nconst AUTH_FILE = join(CONFIG_DIR, 'auth.json')\nconst CONFIG_FILE = join(CONFIG_DIR, 'config.toml')\n\nfunction ensureDir() {\n if (!existsSync(CONFIG_DIR)) {\n mkdirSync(CONFIG_DIR, { recursive: true })\n }\n}\n\nexport function loadAuth(): AuthData | null {\n if (!existsSync(AUTH_FILE))\n return null\n try {\n return JSON.parse(readFileSync(AUTH_FILE, 'utf-8'))\n }\n catch {\n return null\n }\n}\n\nexport function saveAuth(data: AuthData): void {\n ensureDir()\n writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2), { mode: 0o600 })\n}\n\nexport function clearAuth(): void {\n if (existsSync(AUTH_FILE)) {\n writeFileSync(AUTH_FILE, '', { mode: 0o600 })\n }\n // Also wipe the [agent] section from config.toml so logout disables\n // auto-refresh. Preserves [defaults] so the IdP URL stays configured.\n if (existsSync(CONFIG_FILE)) {\n const existing = loadConfig()\n if (existing.agent) {\n const { agent: _removed, ...rest } = existing\n saveConfig(rest)\n }\n }\n}\n\nexport function loadConfig(): ApesConfig {\n if (!existsSync(CONFIG_FILE))\n return {}\n try {\n return parseTOML(readFileSync(CONFIG_FILE, 'utf-8'))\n }\n catch {\n return {}\n }\n}\n\nfunction parseTOML(content: string): ApesConfig {\n const config: ApesConfig = {}\n let section = ''\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith('#'))\n continue\n\n const sectionMatch = trimmed.match(/^\\[(.+)\\]$/)\n if (sectionMatch) {\n section = sectionMatch[1]!\n continue\n }\n\n const kvMatch = trimmed.match(/^(\\w+)\\s*=\\s*\"(.+)\"$/)\n if (kvMatch) {\n const [, key, value] = kvMatch\n if (section === 'defaults') {\n config.defaults = config.defaults || {}\n ;(config.defaults as Record<string, string>)[key!] = value!\n }\n else if (section === 'agent') {\n config.agent = config.agent || {}\n ;(config.agent as Record<string, string>)[key!] = value!\n }\n else if (section === 'notifications') {\n config.notifications = config.notifications || {}\n ;(config.notifications as Record<string, string>)[key!] = value!\n }\n }\n }\n\n return config\n}\n\nexport function saveConfig(config: ApesConfig): void {\n ensureDir()\n const lines: string[] = []\n\n if (config.defaults) {\n lines.push('[defaults]')\n for (const [key, value] of Object.entries(config.defaults)) {\n if (value)\n lines.push(`${key} = \"${value}\"`)\n }\n lines.push('')\n }\n\n if (config.agent) {\n lines.push('[agent]')\n for (const [key, value] of Object.entries(config.agent)) {\n if (value)\n lines.push(`${key} = \"${value}\"`)\n }\n lines.push('')\n }\n\n if (config.notifications) {\n lines.push('[notifications]')\n for (const [key, value] of Object.entries(config.notifications)) {\n if (value)\n lines.push(`${key} = \"${value}\"`)\n }\n lines.push('')\n }\n\n writeFileSync(CONFIG_FILE, lines.join('\\n'), { mode: 0o600 })\n}\n\nexport function getIdpUrl(explicit?: string): string | null {\n if (explicit)\n return explicit\n if (process.env.APES_IDP)\n return process.env.APES_IDP\n\n const auth = loadAuth()\n if (auth?.idp)\n return auth.idp\n\n const config = loadConfig()\n if (config.defaults?.idp)\n return config.defaults.idp\n\n return null\n}\n\nexport function getAuthToken(): string | null {\n const auth = loadAuth()\n if (!auth)\n return null\n\n // Check expiry (with 30s buffer)\n if (auth.expires_at && Date.now() / 1000 > auth.expires_at - 30) {\n return null // expired\n }\n\n return auth.access_token\n}\n\nexport function getRequesterIdentity(): string | null {\n return loadAuth()?.email ?? null\n}\n\nexport { CONFIG_DIR, AUTH_FILE }\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ILKZ5HGV.js";
|
|
5
5
|
|
|
6
6
|
// src/notifications.ts
|
|
7
7
|
import { spawn } from "child_process";
|
|
@@ -44,7 +44,23 @@ function notifyGrantPending(info) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
// src/shell/apes-self-dispatch.ts
|
|
48
|
+
import { basename } from "path";
|
|
49
|
+
var APES_GATED_SUBCOMMANDS = /* @__PURE__ */ new Set(["run", "fetch", "mcp"]);
|
|
50
|
+
function isApesSelfDispatch(parsed) {
|
|
51
|
+
if (!parsed || parsed.isCompound)
|
|
52
|
+
return false;
|
|
53
|
+
const invokedName = basename(parsed.executable);
|
|
54
|
+
if (invokedName !== "apes" && invokedName !== "apes.js")
|
|
55
|
+
return false;
|
|
56
|
+
const subCommand = parsed.argv[0];
|
|
57
|
+
if (!subCommand)
|
|
58
|
+
return false;
|
|
59
|
+
return !APES_GATED_SUBCOMMANDS.has(subCommand);
|
|
60
|
+
}
|
|
61
|
+
|
|
47
62
|
export {
|
|
48
|
-
notifyGrantPending
|
|
63
|
+
notifyGrantPending,
|
|
64
|
+
isApesSelfDispatch
|
|
49
65
|
};
|
|
50
|
-
//# sourceMappingURL=chunk-
|
|
66
|
+
//# sourceMappingURL=chunk-ZHTLP2DD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/notifications.ts","../src/shell/apes-self-dispatch.ts"],"sourcesContent":["import { spawn } from 'node:child_process'\nimport consola from 'consola'\nimport { quote } from 'shell-quote'\nimport { loadConfig } from './config'\n\nexport interface PendingGrantInfo {\n grantId: string\n approveUrl: string\n command: string\n audience: string\n host: string\n}\n\n/**\n * Resolve the notification command for pending grants. Checks (in order):\n * 1. `APES_NOTIFY_PENDING_COMMAND` env var (highest priority — lets\n * parent programs like openclaw override per invocation)\n * 2. `[notifications] pending_command` in ~/.config/apes/config.toml\n *\n * Returns undefined if no notification command is configured.\n */\nfunction resolvePendingCommand(): string | undefined {\n if (process.env.APES_NOTIFY_PENDING_COMMAND)\n return process.env.APES_NOTIFY_PENDING_COMMAND\n\n const config = loadConfig()\n return config.notifications?.pending_command\n}\n\n/**\n * Escape a value for safe embedding inside a single-quoted shell string.\n * We use `shell-quote` to produce a safe literal, then strip the outer\n * quoting because the template substitution embeds the value inside the\n * user's command template which is itself passed to `sh -c`.\n */\nfunction shellEscape(value: string): string {\n // quote() wraps in single quotes and escapes internal single quotes\n // e.g. \"it's\" → \"'it'\\\\''s'\"\n // We return the raw escaped form so it's safe inside sh -c.\n return quote([value])\n}\n\n/**\n * Substitute template variables in the notification command.\n * All values are shell-escaped to prevent injection.\n */\nfunction renderTemplate(template: string, info: PendingGrantInfo): string {\n return template\n .replace(/\\{grant_id\\}/g, shellEscape(info.grantId))\n .replace(/\\{approve_url\\}/g, shellEscape(info.approveUrl))\n .replace(/\\{command\\}/g, shellEscape(info.command))\n .replace(/\\{audience\\}/g, shellEscape(info.audience))\n .replace(/\\{host\\}/g, shellEscape(info.host))\n}\n\n/**\n * Send a notification that a grant is awaiting human approval.\n *\n * This is **fire-and-forget**: the notification subprocess runs detached\n * and unref'd so it cannot block the grant flow. A 10-second timeout\n * kills it if it hangs (e.g. network issue reaching Telegram API).\n *\n * Only fires when a notification command is configured. Silently returns\n * if not — the grant flow must never depend on notifications.\n *\n * Only call this when the grant **actually requires waiting** (new grant\n * with pending status). Do NOT call when:\n * - An existing timed/always grant was reused (no human action needed)\n * - The grant was instantly approved (no waiting phase)\n */\nexport function notifyGrantPending(info: PendingGrantInfo): void {\n const template = resolvePendingCommand()\n if (!template)\n return\n\n const rendered = renderTemplate(template, info)\n\n try {\n const child = spawn('sh', ['-c', rendered], {\n detached: true,\n stdio: 'ignore',\n env: { ...process.env },\n })\n\n // Don't let the notification process keep the parent alive\n child.unref()\n\n // Kill after 10 seconds if it hasn't exited\n const timeout = setTimeout(() => {\n try {\n child.kill('SIGKILL')\n }\n catch {}\n }, 10_000)\n timeout.unref()\n\n child.on('exit', () => clearTimeout(timeout))\n }\n catch (err) {\n // Never let notification failure break the grant flow\n consola.debug('Notification command failed:', err)\n }\n}\n","import { basename } from 'node:path'\nimport type { ParsedShellCommand } from '../shapes/shell-parser.js'\n\n/**\n * Subset of `apes` subcommands that remain grant-gated even when invoked\n * as self-dispatches from inside an ape-shell context. These are the\n * three categories where the shell-grant layer adds real security value\n * that isn't duplicated by server-side auth gates or local-file-only\n * semantics:\n *\n * - `run` — spawns arbitrary executables, the core of the grant system\n * - `fetch` — forwards the bearer token to a user-specified URL\n * - `mcp` — binds a network port and serves a persistent API\n *\n * Every other `apes <subcmd>` either reads state, mutates the user's own\n * local config, or talks to the IdP through endpoints that are already\n * scoped by the auth token — gating them in the shell is redundant\n * friction, and under 0.9.0's async-default grant flow it actively\n * breaks `apes grants run <id>` via recursion (the polling call itself\n * creates a new grant, cascading indefinitely).\n *\n * This is the single source of truth shared by both dispatch paths:\n * - Interactive REPL: `shell/grant-dispatch.ts` → `requestGrantForShellLine`\n * - One-shot `ape-shell -c`: `commands/run.ts` → `runShellMode` (which\n * receives the bash-c-wrapped command after `rewriteApeShellArgs`\n * rewrites `ape-shell -c \"<cmd>\"` into `apes run --shell -- bash -c <cmd>`)\n *\n * Keep this list in sync with the blocklist snapshot test in\n * `shell-grant-dispatch.test.ts` — the tripwire that forces a review\n * decision whenever a new top-level apes subcommand is added.\n */\nexport const APES_GATED_SUBCOMMANDS = new Set(['run', 'fetch', 'mcp'])\n\n/**\n * Returns true if the parsed shell command is an `apes <subcmd>`\n * invocation that should bypass the grant flow entirely. Non-apes\n * binaries, compound lines (pipes, &&, etc.), and subcommands in\n * `APES_GATED_SUBCOMMANDS` all return false so they stay on the normal\n * grant path.\n *\n * The caller (either `requestGrantForShellLine` for the REPL path or\n * `runShellMode` for the one-shot path) is responsible for parsing the\n * input string and passing the resulting ParsedShellCommand here.\n */\nexport function isApesSelfDispatch(parsed: ParsedShellCommand | null | undefined): boolean {\n if (!parsed || parsed.isCompound)\n return false\n const invokedName = basename(parsed.executable)\n if (invokedName !== 'apes' && invokedName !== 'apes.js')\n return false\n const subCommand = parsed.argv[0]\n if (!subCommand)\n return false\n return !APES_GATED_SUBCOMMANDS.has(subCommand)\n}\n"],"mappings":";;;;;;AAAA,SAAS,aAAa;AACtB,OAAO,aAAa;AACpB,SAAS,aAAa;AAmBtB,SAAS,wBAA4C;AACnD,MAAI,QAAQ,IAAI;AACd,WAAO,QAAQ,IAAI;AAErB,QAAM,SAAS,WAAW;AAC1B,SAAO,OAAO,eAAe;AAC/B;AAQA,SAAS,YAAY,OAAuB;AAI1C,SAAO,MAAM,CAAC,KAAK,CAAC;AACtB;AAMA,SAAS,eAAe,UAAkB,MAAgC;AACxE,SAAO,SACJ,QAAQ,iBAAiB,YAAY,KAAK,OAAO,CAAC,EAClD,QAAQ,oBAAoB,YAAY,KAAK,UAAU,CAAC,EACxD,QAAQ,gBAAgB,YAAY,KAAK,OAAO,CAAC,EACjD,QAAQ,iBAAiB,YAAY,KAAK,QAAQ,CAAC,EACnD,QAAQ,aAAa,YAAY,KAAK,IAAI,CAAC;AAChD;AAiBO,SAAS,mBAAmB,MAA8B;AAC/D,QAAM,WAAW,sBAAsB;AACvC,MAAI,CAAC;AACH;AAEF,QAAM,WAAW,eAAe,UAAU,IAAI;AAE9C,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,CAAC,MAAM,QAAQ,GAAG;AAAA,MAC1C,UAAU;AAAA,MACV,OAAO;AAAA,MACP,KAAK,EAAE,GAAG,QAAQ,IAAI;AAAA,IACxB,CAAC;AAGD,UAAM,MAAM;AAGZ,UAAM,UAAU,WAAW,MAAM;AAC/B,UAAI;AACF,cAAM,KAAK,SAAS;AAAA,MACtB,QACM;AAAA,MAAC;AAAA,IACT,GAAG,GAAM;AACT,YAAQ,MAAM;AAEd,UAAM,GAAG,QAAQ,MAAM,aAAa,OAAO,CAAC;AAAA,EAC9C,SACO,KAAK;AAEV,YAAQ,MAAM,gCAAgC,GAAG;AAAA,EACnD;AACF;;;ACtGA,SAAS,gBAAgB;AA+BlB,IAAM,yBAAyB,oBAAI,IAAI,CAAC,OAAO,SAAS,KAAK,CAAC;AAa9D,SAAS,mBAAmB,QAAwD;AACzF,MAAI,CAAC,UAAU,OAAO;AACpB,WAAO;AACT,QAAM,cAAc,SAAS,OAAO,UAAU;AAC9C,MAAI,gBAAgB,UAAU,gBAAgB;AAC5C,WAAO;AACT,QAAM,aAAa,OAAO,KAAK,CAAC;AAChC,MAAI,CAAC;AACH,WAAO;AACT,SAAO,CAAC,uBAAuB,IAAI,UAAU;AAC/C;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -9,8 +9,9 @@ import {
|
|
|
9
9
|
readPublicKeyComment
|
|
10
10
|
} from "./chunk-ION3CWD5.js";
|
|
11
11
|
import {
|
|
12
|
+
isApesSelfDispatch,
|
|
12
13
|
notifyGrantPending
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ZHTLP2DD.js";
|
|
14
15
|
import {
|
|
15
16
|
ApiError,
|
|
16
17
|
apiFetch,
|
|
@@ -41,7 +42,7 @@ import {
|
|
|
41
42
|
searchAdapters,
|
|
42
43
|
verifyAndExecute,
|
|
43
44
|
waitForGrantStatus
|
|
44
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-D3OMN7RV.js";
|
|
45
46
|
import {
|
|
46
47
|
AUTH_FILE,
|
|
47
48
|
CONFIG_DIR,
|
|
@@ -52,7 +53,7 @@ import {
|
|
|
52
53
|
loadConfig,
|
|
53
54
|
saveAuth,
|
|
54
55
|
saveConfig
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-ILKZ5HGV.js";
|
|
56
57
|
|
|
57
58
|
// src/cli.ts
|
|
58
59
|
import consola27 from "consola";
|
|
@@ -1928,14 +1929,78 @@ import consola19 from "consola";
|
|
|
1928
1929
|
function shouldWaitForGrant(args) {
|
|
1929
1930
|
return args.wait === true || process.env.APE_WAIT === "1";
|
|
1930
1931
|
}
|
|
1932
|
+
function getUserMode() {
|
|
1933
|
+
const envValue = process.env.APES_USER;
|
|
1934
|
+
if (envValue === "human")
|
|
1935
|
+
return "human";
|
|
1936
|
+
if (envValue === "agent")
|
|
1937
|
+
return "agent";
|
|
1938
|
+
const cfg = loadConfig();
|
|
1939
|
+
if (cfg.defaults?.user === "human")
|
|
1940
|
+
return "human";
|
|
1941
|
+
return "agent";
|
|
1942
|
+
}
|
|
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
|
+
}
|
|
1931
1975
|
function printPendingGrantInfo(grant, idp) {
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1976
|
+
const mode = getUserMode();
|
|
1977
|
+
const approveUrl = `${idp}/grant-approval?grant_id=${grant.id}`;
|
|
1978
|
+
const statusCmd = `apes grants status ${grant.id}`;
|
|
1979
|
+
const executeCmd = `apes grants run ${grant.id}`;
|
|
1980
|
+
if (mode === "human") {
|
|
1981
|
+
consola19.success(`Grant ${grant.id} created \u2014 awaiting your approval`);
|
|
1982
|
+
console.log(` Approve in browser: ${approveUrl}`);
|
|
1983
|
+
console.log(` Check status: ${statusCmd}`);
|
|
1984
|
+
console.log(` Run after approval: ${executeCmd}`);
|
|
1985
|
+
console.log("");
|
|
1986
|
+
console.log(' Tip: Approve as "timed" or "always" in the browser to reuse');
|
|
1987
|
+
console.log(" this grant without re-approval on the next invocation.");
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
const pollSec = getPollIntervalSeconds();
|
|
1991
|
+
const maxMin = getPollMaxMinutes();
|
|
1992
|
+
consola19.success(`Grant ${grant.id} created (pending approval)`);
|
|
1993
|
+
console.log(` Approve: ${approveUrl}`);
|
|
1994
|
+
console.log(` Status: ${statusCmd} [--json]`);
|
|
1995
|
+
console.log(` Execute: ${executeCmd}`);
|
|
1936
1996
|
console.log("");
|
|
1937
|
-
console.log(
|
|
1938
|
-
console.log(
|
|
1997
|
+
console.log(` For agents: poll \`${statusCmd} --json\` every ${pollSec}s, wait up to ${maxMin} minutes.`);
|
|
1998
|
+
console.log(` When .status == "approved", run \`${executeCmd}\` to execute.`);
|
|
1999
|
+
console.log(` On "denied" or "revoked", stop and report to the user.`);
|
|
2000
|
+
console.log(` On timeout, stop and notify the user that approval has not happened.`);
|
|
2001
|
+
console.log("");
|
|
2002
|
+
console.log(' Tip: Approve as "timed" or "always" in the browser to let this');
|
|
2003
|
+
console.log(" grant be reused on subsequent invocations without re-approval.");
|
|
1939
2004
|
}
|
|
1940
2005
|
var runCommand = defineCommand21({
|
|
1941
2006
|
meta: {
|
|
@@ -2012,6 +2077,14 @@ async function runShellMode(command, args) {
|
|
|
2012
2077
|
const idp = getIdpUrl(args.idp);
|
|
2013
2078
|
if (!idp)
|
|
2014
2079
|
throw new CliError("No IdP URL configured. Run `apes login` first or pass --idp.");
|
|
2080
|
+
const innerLine = extractShellCommandString(command);
|
|
2081
|
+
if (innerLine) {
|
|
2082
|
+
const parsedInner = parseShellCommand(innerLine);
|
|
2083
|
+
if (isApesSelfDispatch(parsedInner)) {
|
|
2084
|
+
execShellCommand(command);
|
|
2085
|
+
return;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2015
2088
|
const adapterHandled = await tryAdapterModeFromShell(command, idp, args);
|
|
2016
2089
|
if (adapterHandled) return;
|
|
2017
2090
|
const grantsUrl = await getGrantsEndpoint(idp);
|
|
@@ -2129,7 +2202,11 @@ function execShellCommand(command) {
|
|
|
2129
2202
|
if (command.length === 0)
|
|
2130
2203
|
throw new CliError("No command to execute");
|
|
2131
2204
|
try {
|
|
2132
|
-
|
|
2205
|
+
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
2206
|
+
execFileSync2(command[0], command.slice(1), {
|
|
2207
|
+
stdio: "inherit",
|
|
2208
|
+
env: inheritedEnv
|
|
2209
|
+
});
|
|
2133
2210
|
} catch (err) {
|
|
2134
2211
|
const exitCode = err.status || 1;
|
|
2135
2212
|
throw new CliExit(exitCode);
|
|
@@ -2249,8 +2326,10 @@ async function runAudienceMode(audience, action, args) {
|
|
|
2249
2326
|
if (audience === "escapes") {
|
|
2250
2327
|
consola19.info(`Executing: ${command.join(" ")}`);
|
|
2251
2328
|
try {
|
|
2329
|
+
const { APES_SHELL_WRAPPER: _wrapperMarker, ...inheritedEnv } = process.env;
|
|
2252
2330
|
execFileSync2(args["escapes-path"] || "escapes", ["--grant", authz_jwt, "--", ...command], {
|
|
2253
|
-
stdio: "inherit"
|
|
2331
|
+
stdio: "inherit",
|
|
2332
|
+
env: inheritedEnv
|
|
2254
2333
|
});
|
|
2255
2334
|
} catch (err) {
|
|
2256
2335
|
const exitCode = err.status || 1;
|
|
@@ -2529,7 +2608,7 @@ var mcpCommand = defineCommand26({
|
|
|
2529
2608
|
if (transport !== "stdio" && transport !== "sse") {
|
|
2530
2609
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
2531
2610
|
}
|
|
2532
|
-
const { startMcpServer } = await import("./server-
|
|
2611
|
+
const { startMcpServer } = await import("./server-ED5MMYT3.js");
|
|
2533
2612
|
await startMcpServer(transport, port);
|
|
2534
2613
|
}
|
|
2535
2614
|
});
|
|
@@ -3021,7 +3100,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
3021
3100
|
}
|
|
3022
3101
|
}
|
|
3023
3102
|
async function runHealth(args) {
|
|
3024
|
-
const version = true ? "0.9.
|
|
3103
|
+
const version = true ? "0.9.4" : "0.0.0";
|
|
3025
3104
|
const auth = loadAuth();
|
|
3026
3105
|
if (!auth) {
|
|
3027
3106
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -3223,10 +3302,10 @@ if (shellRewrite) {
|
|
|
3223
3302
|
if (shellRewrite.action === "rewrite") {
|
|
3224
3303
|
process.argv = shellRewrite.argv;
|
|
3225
3304
|
} else if (shellRewrite.action === "version") {
|
|
3226
|
-
console.log(`ape-shell ${"0.9.
|
|
3305
|
+
console.log(`ape-shell ${"0.9.4"} (OpenApe DDISA shell wrapper)`);
|
|
3227
3306
|
process.exit(0);
|
|
3228
3307
|
} else if (shellRewrite.action === "help") {
|
|
3229
|
-
console.log(`ape-shell ${"0.9.
|
|
3308
|
+
console.log(`ape-shell ${"0.9.4"} \u2014 OpenApe DDISA shell wrapper`);
|
|
3230
3309
|
console.log("");
|
|
3231
3310
|
console.log("Usage:");
|
|
3232
3311
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -3241,7 +3320,7 @@ if (shellRewrite) {
|
|
|
3241
3320
|
console.log(" --help, -h Show this help message");
|
|
3242
3321
|
process.exit(0);
|
|
3243
3322
|
} else if (shellRewrite.action === "interactive") {
|
|
3244
|
-
const { runInteractiveShell } = await import("./orchestrator-
|
|
3323
|
+
const { runInteractiveShell } = await import("./orchestrator-5EZD7ZQE.js");
|
|
3245
3324
|
await runInteractiveShell();
|
|
3246
3325
|
process.exit(0);
|
|
3247
3326
|
} else {
|
|
@@ -3284,7 +3363,7 @@ var configCommand = defineCommand33({
|
|
|
3284
3363
|
var main = defineCommand33({
|
|
3285
3364
|
meta: {
|
|
3286
3365
|
name: "apes",
|
|
3287
|
-
version: "0.9.
|
|
3366
|
+
version: "0.9.4",
|
|
3288
3367
|
description: "Unified CLI for OpenApe"
|
|
3289
3368
|
},
|
|
3290
3369
|
subCommands: {
|