@openape/apes 0.9.4 → 0.10.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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CONFIG_DIR
4
- } from "./chunk-ILKZ5HGV.js";
4
+ } from "./chunk-6JSOSD7R.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-6GGWZVOA.js.map
41
+ //# sourceMappingURL=auth-lock-O7BTENTJ.js.map
@@ -142,4 +142,4 @@ export {
142
142
  getAuthToken,
143
143
  getRequesterIdentity
144
144
  };
145
- //# sourceMappingURL=chunk-ILKZ5HGV.js.map
145
+ //# sourceMappingURL=chunk-6JSOSD7R.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 * Exit code emitted by `apes run` / `ape-shell -c` when the async\n * default path creates a pending grant. Default `75` (`EX_TEMPFAIL`\n * from sysexits.h — \"temporary failure, retry later\"). Set to `0`\n * to restore the pre-0.10.0 exit-0 behaviour. Env var\n * `APES_ASYNC_EXIT_CODE` wins. Valid range 0–255.\n */\n async_exit_code?: 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-ILKZ5HGV.js";
4
+ } from "./chunk-6JSOSD7R.js";
5
5
 
6
6
  // src/notifications.ts
7
7
  import { spawn } from "child_process";
@@ -63,4 +63,4 @@ export {
63
63
  notifyGrantPending,
64
64
  isApesSelfDispatch
65
65
  };
66
- //# sourceMappingURL=chunk-ZHTLP2DD.js.map
66
+ //# sourceMappingURL=chunk-EAXBC4KC.js.map
@@ -5,7 +5,7 @@ import {
5
5
  loadAuth,
6
6
  loadConfig,
7
7
  saveAuth
8
- } from "./chunk-ILKZ5HGV.js";
8
+ } from "./chunk-6JSOSD7R.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-6GGWZVOA.js");
107
+ const { acquireAuthLock, releaseAuthLock } = await import("./auth-lock-O7BTENTJ.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-D3OMN7RV.js.map
1305
+ //# sourceMappingURL=chunk-U4CI2RBO.js.map
package/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  isApesSelfDispatch,
13
13
  notifyGrantPending
14
- } from "./chunk-ZHTLP2DD.js";
14
+ } from "./chunk-EAXBC4KC.js";
15
15
  import {
16
16
  ApiError,
17
17
  apiFetch,
@@ -42,7 +42,7 @@ import {
42
42
  searchAdapters,
43
43
  verifyAndExecute,
44
44
  waitForGrantStatus
45
- } from "./chunk-D3OMN7RV.js";
45
+ } from "./chunk-U4CI2RBO.js";
46
46
  import {
47
47
  AUTH_FILE,
48
48
  CONFIG_DIR,
@@ -53,7 +53,7 @@ import {
53
53
  loadConfig,
54
54
  saveAuth,
55
55
  saveConfig
56
- } from "./chunk-ILKZ5HGV.js";
56
+ } from "./chunk-6JSOSD7R.js";
57
57
 
58
58
  // src/cli.ts
59
59
  import consola27 from "consola";
@@ -1972,6 +1972,22 @@ function getPollMaxMinutes() {
1972
1972
  }
1973
1973
  return 5;
1974
1974
  }
1975
+ function getAsyncExitCode() {
1976
+ const envValue = process.env.APES_ASYNC_EXIT_CODE;
1977
+ if (envValue !== void 0 && envValue !== "") {
1978
+ const n = Number(envValue);
1979
+ if (Number.isFinite(n) && n >= 0 && n <= 255)
1980
+ return Math.floor(n);
1981
+ }
1982
+ const cfg = loadConfig();
1983
+ const cfgValue = cfg.defaults?.async_exit_code;
1984
+ if (cfgValue !== void 0 && cfgValue !== "") {
1985
+ const n = Number(cfgValue);
1986
+ if (Number.isFinite(n) && n >= 0 && n <= 255)
1987
+ return Math.floor(n);
1988
+ }
1989
+ return 75;
1990
+ }
1975
1991
  function printPendingGrantInfo(grant, idp) {
1976
1992
  const mode = getUserMode();
1977
1993
  const approveUrl = `${idp}/grant-approval?grant_id=${grant.id}`;
@@ -2139,6 +2155,7 @@ async function runShellMode(command, args) {
2139
2155
  return;
2140
2156
  }
2141
2157
  printPendingGrantInfo(grant, idp);
2158
+ throw new CliExit(getAsyncExitCode());
2142
2159
  }
2143
2160
  async function tryAdapterModeFromShell(command, idp, args) {
2144
2161
  const cmdString = extractShellCommandString(command);
@@ -2196,7 +2213,7 @@ async function tryAdapterModeFromShell(command, idp, args) {
2196
2213
  return true;
2197
2214
  }
2198
2215
  printPendingGrantInfo(grant, idp);
2199
- return true;
2216
+ throw new CliExit(getAsyncExitCode());
2200
2217
  }
2201
2218
  function execShellCommand(command) {
2202
2219
  if (command.length === 0)
@@ -2276,6 +2293,7 @@ async function runAdapterMode(command, rawArgs, args) {
2276
2293
  return;
2277
2294
  }
2278
2295
  printPendingGrantInfo(grant, idp);
2296
+ throw new CliExit(getAsyncExitCode());
2279
2297
  }
2280
2298
  async function runAudienceMode(audience, action, args) {
2281
2299
  const auth = loadAuth();
@@ -2301,7 +2319,7 @@ async function runAudienceMode(audience, action, args) {
2301
2319
  });
2302
2320
  if (!shouldWaitForGrant(args)) {
2303
2321
  printPendingGrantInfo(grant, idp);
2304
- return;
2322
+ throw new CliExit(getAsyncExitCode());
2305
2323
  }
2306
2324
  consola19.success(`Grant requested: ${grant.id}`);
2307
2325
  consola19.info("Waiting for approval...");
@@ -2608,7 +2626,7 @@ var mcpCommand = defineCommand26({
2608
2626
  if (transport !== "stdio" && transport !== "sse") {
2609
2627
  throw new Error('Transport must be "stdio" or "sse"');
2610
2628
  }
2611
- const { startMcpServer } = await import("./server-ED5MMYT3.js");
2629
+ const { startMcpServer } = await import("./server-N3DPYYBL.js");
2612
2630
  await startMcpServer(transport, port);
2613
2631
  }
2614
2632
  });
@@ -3100,7 +3118,7 @@ async function bestEffortGrantCount(idp) {
3100
3118
  }
3101
3119
  }
3102
3120
  async function runHealth(args) {
3103
- const version = true ? "0.9.4" : "0.0.0";
3121
+ const version = true ? "0.10.0" : "0.0.0";
3104
3122
  const auth = loadAuth();
3105
3123
  if (!auth) {
3106
3124
  throw new CliError("Not logged in. Run `apes login` first.", 1);
@@ -3302,10 +3320,10 @@ if (shellRewrite) {
3302
3320
  if (shellRewrite.action === "rewrite") {
3303
3321
  process.argv = shellRewrite.argv;
3304
3322
  } else if (shellRewrite.action === "version") {
3305
- console.log(`ape-shell ${"0.9.4"} (OpenApe DDISA shell wrapper)`);
3323
+ console.log(`ape-shell ${"0.10.0"} (OpenApe DDISA shell wrapper)`);
3306
3324
  process.exit(0);
3307
3325
  } else if (shellRewrite.action === "help") {
3308
- console.log(`ape-shell ${"0.9.4"} \u2014 OpenApe DDISA shell wrapper`);
3326
+ console.log(`ape-shell ${"0.10.0"} \u2014 OpenApe DDISA shell wrapper`);
3309
3327
  console.log("");
3310
3328
  console.log("Usage:");
3311
3329
  console.log(" ape-shell Start interactive grant-mediated REPL");
@@ -3320,7 +3338,7 @@ if (shellRewrite) {
3320
3338
  console.log(" --help, -h Show this help message");
3321
3339
  process.exit(0);
3322
3340
  } else if (shellRewrite.action === "interactive") {
3323
- const { runInteractiveShell } = await import("./orchestrator-5EZD7ZQE.js");
3341
+ const { runInteractiveShell } = await import("./orchestrator-QL3AT67U.js");
3324
3342
  await runInteractiveShell();
3325
3343
  process.exit(0);
3326
3344
  } else {
@@ -3363,7 +3381,7 @@ var configCommand = defineCommand33({
3363
3381
  var main = defineCommand33({
3364
3382
  meta: {
3365
3383
  name: "apes",
3366
- version: "0.9.4",
3384
+ version: "0.10.0",
3367
3385
  description: "Unified CLI for OpenApe"
3368
3386
  },
3369
3387
  subCommands: {