@openape/apes 1.28.11 → 1.28.13
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/{chunk-4KPKANZT.js → chunk-NYJSBFLG.js} +7 -5
- package/dist/chunk-NYJSBFLG.js.map +1 -0
- package/dist/{chunk-DYSFQ26B.js → chunk-PEA2RDWK.js} +6 -153
- package/dist/chunk-PEA2RDWK.js.map +1 -0
- package/dist/{chunk-OOKB2IL2.js → chunk-ZEUSCNCH.js} +59 -9
- package/dist/chunk-ZEUSCNCH.js.map +1 -0
- package/dist/cli.js +625 -376
- package/dist/cli.js.map +1 -1
- package/dist/{http-6OKWT52Z.js → http-UPOTOYQV.js} +2 -2
- package/dist/index.d.ts +12 -0
- package/dist/index.js +3 -3
- package/dist/{orchestrator-CIDV7OGM.js → orchestrator-REICEX3F.js} +3 -3
- package/dist/{server-WB77GNKJ.js → server-JGX5FIDP.js} +4 -4
- package/package.json +6 -6
- package/dist/chunk-4KPKANZT.js.map +0 -1
- package/dist/chunk-DYSFQ26B.js.map +0 -1
- package/dist/chunk-OOKB2IL2.js.map +0 -1
- /package/dist/{http-6OKWT52Z.js.map → http-UPOTOYQV.js.map} +0 -0
- /package/dist/{orchestrator-CIDV7OGM.js.map → orchestrator-REICEX3F.js.map} +0 -0
- /package/dist/{server-WB77GNKJ.js.map → server-JGX5FIDP.js.map} +0 -0
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
getAgentChallengeEndpoint,
|
|
9
9
|
getDelegationsEndpoint,
|
|
10
10
|
getGrantsEndpoint
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NYJSBFLG.js";
|
|
12
12
|
import "./chunk-OBF7IMQ2.js";
|
|
13
13
|
export {
|
|
14
14
|
ApiError,
|
|
@@ -20,4 +20,4 @@ export {
|
|
|
20
20
|
getDelegationsEndpoint,
|
|
21
21
|
getGrantsEndpoint
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=http-
|
|
23
|
+
//# sourceMappingURL=http-UPOTOYQV.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -419,6 +419,18 @@ interface RunOptions {
|
|
|
419
419
|
history?: ChatMessage[];
|
|
420
420
|
handlers?: RunStreamHandlers;
|
|
421
421
|
fetchImpl?: typeof fetch;
|
|
422
|
+
/**
|
|
423
|
+
* Send `stream: true` to the LiteLLM proxy and aggregate the SSE
|
|
424
|
+
* chunks locally into a single non-stream response. Workaround for
|
|
425
|
+
* LiteLLM's chatgpt-OAuth provider whose non-stream `/v1/chat/
|
|
426
|
+
* completions` returns an empty body (the chatgpt upstream only
|
|
427
|
+
* emits content via the responses-API streaming path; the bridge
|
|
428
|
+
* back to chat/completions fails to aggregate). Streaming + local
|
|
429
|
+
* aggregation produces a correct response with every provider
|
|
430
|
+
* LiteLLM ships, so this flag is safe to enable globally — it
|
|
431
|
+
* defaults off only to keep existing JSON-fixture tests intact.
|
|
432
|
+
*/
|
|
433
|
+
streamAggregate?: boolean;
|
|
422
434
|
}
|
|
423
435
|
declare function runLoop(opts: RunOptions): Promise<RunResult>;
|
|
424
436
|
interface RpcSession {
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
runApeShell,
|
|
9
9
|
runLoop,
|
|
10
10
|
taskTools
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZEUSCNCH.js";
|
|
12
12
|
import {
|
|
13
13
|
appendAuditLog,
|
|
14
14
|
buildExactCommandGrantRequest,
|
|
@@ -36,12 +36,12 @@ import {
|
|
|
36
36
|
tryLoadAdapter,
|
|
37
37
|
verifyAndExecute,
|
|
38
38
|
waitForGrantStatus
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-PEA2RDWK.js";
|
|
40
40
|
import {
|
|
41
41
|
ApiError,
|
|
42
42
|
apiFetch,
|
|
43
43
|
discoverEndpoints
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-NYJSBFLG.js";
|
|
45
45
|
import {
|
|
46
46
|
clearAuth,
|
|
47
47
|
getAuthToken,
|
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
resolveCommand,
|
|
15
15
|
verifyAndConsume,
|
|
16
16
|
waitForGrantStatus
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-PEA2RDWK.js";
|
|
18
18
|
import {
|
|
19
19
|
apiFetch,
|
|
20
20
|
getGrantsEndpoint
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-NYJSBFLG.js";
|
|
22
22
|
import {
|
|
23
23
|
loadAuth
|
|
24
24
|
} from "./chunk-OBF7IMQ2.js";
|
|
@@ -777,4 +777,4 @@ async function runInteractiveShell() {
|
|
|
777
777
|
export {
|
|
778
778
|
runInteractiveShell
|
|
779
779
|
};
|
|
780
|
-
//# sourceMappingURL=orchestrator-
|
|
780
|
+
//# sourceMappingURL=orchestrator-REICEX3F.js.map
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
loadAdapter,
|
|
6
6
|
resolveCommand,
|
|
7
7
|
verifyAndExecute
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PEA2RDWK.js";
|
|
9
9
|
import {
|
|
10
10
|
apiFetch,
|
|
11
11
|
getGrantsEndpoint
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-NYJSBFLG.js";
|
|
13
13
|
import {
|
|
14
14
|
getAuthToken,
|
|
15
15
|
getIdpUrl,
|
|
@@ -303,7 +303,7 @@ function registerAdapterTools(server) {
|
|
|
303
303
|
async function startMcpServer(transport, port) {
|
|
304
304
|
const server = new McpServer({
|
|
305
305
|
name: "apes",
|
|
306
|
-
version: true ? "1.28.
|
|
306
|
+
version: true ? "1.28.13" : "0.1.0"
|
|
307
307
|
});
|
|
308
308
|
registerStaticTools(server);
|
|
309
309
|
registerAdapterTools(server);
|
|
@@ -331,4 +331,4 @@ async function startMcpServer(transport, port) {
|
|
|
331
331
|
export {
|
|
332
332
|
startMcpServer
|
|
333
333
|
};
|
|
334
|
-
//# sourceMappingURL=server-
|
|
334
|
+
//# sourceMappingURL=server-JGX5FIDP.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openape/apes",
|
|
3
|
-
"version": "1.28.
|
|
3
|
+
"version": "1.28.13",
|
|
4
4
|
"turbo": {
|
|
5
5
|
"tags": [
|
|
6
6
|
"publishable"
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"@lydell/node-pty": "1.2.0-beta.12",
|
|
32
32
|
"shell-quote": "^1.8.3",
|
|
33
33
|
"zod": "^4.3.6",
|
|
34
|
-
"@openape/
|
|
35
|
-
"@openape/proxy": "0.4.
|
|
36
|
-
"@openape/
|
|
37
|
-
"@openape/
|
|
34
|
+
"@openape/cli-auth": "0.5.0",
|
|
35
|
+
"@openape/proxy": "0.4.5",
|
|
36
|
+
"@openape/core": "0.17.1",
|
|
37
|
+
"@openape/grants": "0.12.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^25.3.5",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"tsup": "^8.5.1",
|
|
46
46
|
"typescript": "^5.8.2",
|
|
47
47
|
"vitest": "^4.1.7",
|
|
48
|
-
"@openape/server": "0.3.
|
|
48
|
+
"@openape/server": "0.3.13"
|
|
49
49
|
},
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"author": "Patrick Hofmann <phofmann@delta-mind.at>",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/http.ts"],"sourcesContent":["import consola from 'consola'\nimport { getAuthToken, getIdpUrl, loadAuth, loadConfig, saveAuth } from './config'\n\nconst debug = process.argv.includes('--debug')\n\nexport class ApiError extends Error {\n constructor(public statusCode: number, message: string, public problemDetails?: Record<string, unknown>) {\n super(message)\n this.name = 'ApiError'\n }\n}\n\n// OIDC Discovery cache (one-time per CLI invocation)\nconst _discoveryCache: Record<string, Record<string, unknown>> = {}\n\nexport async function discoverEndpoints(idpUrl: string): Promise<Record<string, unknown>> {\n if (_discoveryCache[idpUrl]) {\n return _discoveryCache[idpUrl]\n }\n\n try {\n const response = await fetch(`${idpUrl}/.well-known/openid-configuration`)\n if (response.ok) {\n const data = await response.json() as Record<string, unknown>\n _discoveryCache[idpUrl] = data\n return data\n }\n }\n catch {}\n\n // Return empty if discovery fails (graceful degradation)\n _discoveryCache[idpUrl] = {}\n return {}\n}\n\nexport async function getGrantsEndpoint(idpUrl: string): Promise<string> {\n const disco = await discoverEndpoints(idpUrl)\n return (disco.openape_grants_endpoint as string) || `${idpUrl}/api/grants`\n}\n\nexport async function getAgentChallengeEndpoint(idpUrl: string): Promise<string> {\n const disco = await discoverEndpoints(idpUrl)\n return (disco.ddisa_agent_challenge_endpoint as string) || `${idpUrl}/api/agent/challenge`\n}\n\nexport async function getAgentAuthenticateEndpoint(idpUrl: string): Promise<string> {\n const disco = await discoverEndpoints(idpUrl)\n return (disco.ddisa_agent_authenticate_endpoint as string) || `${idpUrl}/api/agent/authenticate`\n}\n\nexport async function getDelegationsEndpoint(idpUrl: string): Promise<string> {\n const disco = await discoverEndpoints(idpUrl)\n return (disco.openape_delegations_endpoint as string) || `${idpUrl}/api/delegations`\n}\n\n/**\n * Re-authenticate an agent using Ed25519 challenge-response.\n * Called automatically when the token is expired.\n */\nasync function refreshAgentToken(): Promise<string | null> {\n const auth = loadAuth()\n if (!auth)\n return null\n\n const config = loadConfig()\n const keyPath = config.agent?.key\n if (!keyPath)\n return null\n\n try {\n const { readFileSync } = await import('node:fs')\n const { sign } = await import('node:crypto')\n const { homedir } = await import('node:os')\n const { loadEd25519PrivateKey } = await import('./ssh-key.js')\n\n const resolved = keyPath.replace(/^~/, homedir())\n const keyContent = readFileSync(resolved, 'utf-8')\n const privateKey = loadEd25519PrivateKey(keyContent)\n\n const challengeUrl = await getAgentChallengeEndpoint(auth.idp)\n const challengeResp = await fetch(challengeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ agent_id: auth.email }),\n })\n\n if (!challengeResp.ok)\n return null\n\n const { challenge } = await challengeResp.json() as { challenge: string }\n const { Buffer } = await import('node:buffer')\n const signature = sign(null, Buffer.from(challenge), privateKey).toString('base64')\n\n const authenticateUrl = await getAgentAuthenticateEndpoint(auth.idp)\n const authResp = await fetch(authenticateUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ agent_id: auth.email, challenge, signature }),\n })\n\n if (!authResp.ok)\n return null\n\n const { token, expires_in } = await authResp.json() as { token: string, expires_in: number }\n\n saveAuth({\n ...auth,\n access_token: token,\n expires_at: Math.floor(Date.now() / 1000) + (expires_in || 3600),\n })\n\n if (debug) {\n consola.debug('Token refreshed via Ed25519 challenge-response')\n }\n\n return token\n }\n catch {\n return null\n }\n}\n\n/**\n * Refresh an OAuth2 access token using a stored refresh_token. Used for\n * PKCE/browser login sessions where no Ed25519 agent key is configured.\n *\n * Serialized via a file lock so concurrent apes/ape-shell invocations don't\n * both consume the same rotating refresh token (which would revoke the\n * entire family server-side).\n */\nasync function refreshOAuthToken(): Promise<string | null> {\n const auth = loadAuth()\n if (!auth?.refresh_token)\n return null\n\n const { acquireAuthLock, releaseAuthLock } = await import('./auth-lock.js')\n const lock = await acquireAuthLock({ timeoutMs: 5000 })\n if (!lock) {\n // Another process is refreshing. It should have updated auth.json by now;\n // re-read and return whatever fresh token is there (may still be null).\n return getAuthToken()\n }\n\n try {\n // Re-read auth.json inside the lock — another holder may already have\n // refreshed while we were waiting, in which case we reuse the new token.\n const latest = loadAuth()\n if (latest?.expires_at && Date.now() / 1000 < latest.expires_at - 30)\n return latest.access_token\n\n const activeRefreshToken = latest?.refresh_token ?? auth.refresh_token\n if (!activeRefreshToken)\n return null\n\n const disco = await discoverEndpoints(auth.idp)\n const tokenEndpoint = (disco.token_endpoint as string) || `${auth.idp}/token`\n\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: activeRefreshToken,\n })\n\n const resp = await fetch(tokenEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n })\n\n if (!resp.ok) {\n // Family may have been revoked server-side — clear refresh_token to\n // prevent an infinite retry loop on every subsequent apes invocation.\n if (resp.status === 400 || resp.status === 401) {\n const base = latest ?? auth\n saveAuth({ ...base, refresh_token: undefined })\n }\n return null\n }\n\n const tokens = await resp.json() as {\n access_token: string\n refresh_token?: string\n expires_in?: number\n }\n\n const base = latest ?? auth\n saveAuth({\n ...base,\n access_token: tokens.access_token,\n refresh_token: tokens.refresh_token ?? base.refresh_token,\n expires_at: Math.floor(Date.now() / 1000) + (tokens.expires_in || 300),\n })\n\n if (debug)\n consola.debug('Token refreshed via OAuth refresh_token')\n\n return tokens.access_token\n }\n finally {\n await releaseAuthLock(lock)\n }\n}\n\n/**\n * Refresh the local IdP token if it has expired. Used by every code path\n * that needs an access token — `apiFetch` for IdP-bound HTTP calls, plus\n * any pure-introspection command (`apes whoami`, `apes config get …`)\n * that previously only read local auth state and surfaced a stale\n * \"expired\" without attempting renewal.\n *\n * Returns the fresh access token on success, or null when no refresh\n * path is available (no agent key AND no refresh_token, or both refresh\n * attempts failed). Callers decide what to do with null — `apiFetch`\n * throws \"Not authenticated\", `whoami` falls back to the on-disk state.\n */\nexport async function ensureFreshToken(): Promise<string | null> {\n const cached = getAuthToken()\n if (cached) return cached\n\n // Auto-refresh: priority (1) ed25519 agent key, (2) OAuth refresh_token.\n // Agent-key first because it is concurrency-safe — every challenge is\n // independent server-side, so parallel ape-shell spawns don't race.\n const agentToken = await refreshAgentToken()\n if (agentToken) return agentToken\n const oauthToken = await refreshOAuthToken()\n return oauthToken ?? null\n}\n\nexport async function apiFetch<T = unknown>(\n path: string,\n options: {\n method?: string\n body?: unknown\n idp?: string\n token?: string\n } = {},\n): Promise<T> {\n const token = options.token ?? await ensureFreshToken()\n\n if (!token) {\n throw new Error('Not authenticated (token expired). Run `apes login` first.')\n }\n\n let url: string\n if (path.startsWith('http')) {\n url = path\n }\n else {\n const idp = options.idp || getIdpUrl()\n if (!idp) {\n throw new Error('No IdP URL configured. Run `apes login` first or pass --idp.')\n }\n url = `${idp}${path}`\n }\n const method = options.method || 'GET'\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n }\n\n if (debug) {\n consola.debug(`${method} ${url}`)\n consola.debug(`Token: ${token.substring(0, 20)}...${token.substring(token.length - 10)}`)\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n })\n\n if (debug) {\n consola.debug(`Response: ${response.status} ${response.statusText}`)\n }\n\n if (!response.ok) {\n const contentType = response.headers.get('content-type') || ''\n\n // Parse RFC 7807 Problem Details\n if (contentType.includes('application/problem+json') || contentType.includes('application/json')) {\n try {\n const problem = await response.json() as Record<string, unknown>\n const message = (problem.detail as string) || (problem.title as string) || (problem.statusMessage as string) || (problem.message as string) || `${response.status} ${response.statusText}`\n throw new ApiError(response.status, message, problem)\n }\n catch (e) {\n if (e instanceof ApiError)\n throw e\n }\n }\n\n const text = await response.text()\n throw new ApiError(response.status, text || `${response.status} ${response.statusText}`)\n }\n\n return response.json() as Promise<T>\n}\n"],"mappings":"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","names":["base"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shapes/adapters.ts","../src/shapes/toml.ts","../src/shapes/generic.ts","../src/shapes/audit.ts","../src/shapes/installer.ts","../src/shapes/registry.ts","../src/shapes/shell-parser.ts","../src/shapes/capabilities.ts","../src/shapes/parser.ts","../src/shapes/commands/explain.ts","../src/shapes/grants.ts","../src/shapes/config.ts","../src/shapes/http.ts","../src/audit/generic-log.ts","../src/shapes/request-builders.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, join } from 'node:path'\nimport type { LoadedAdapter, ResolvedCommand } from './types.js'\nimport { parseAdapterToml } from './toml.js'\nimport { buildGenericResolved } from './generic.js'\n\nfunction digest(content: string): string {\n return `SHA-256:${createHash('sha256').update(content).digest('hex')}`\n}\n\nfunction adapterDirs(): string[] {\n return [\n join(process.cwd(), '.openape', 'shapes', 'adapters'),\n join(homedir(), '.openape', 'shapes', 'adapters'),\n join('/etc', 'openape', 'shapes', 'adapters'),\n ]\n}\n\nfunction findByExecutable(executable: string): string | undefined {\n for (const dir of adapterDirs()) {\n if (!existsSync(dir))\n continue\n try {\n const files = readdirSync(dir).filter(f => f.endsWith('.toml'))\n for (const file of files) {\n const path = join(dir, file)\n const content = readFileSync(path, 'utf-8')\n const match = content.match(/^\\s*executable\\s*=\\s*\"([^\"]+)\"/m)\n if (match && match[1] === executable)\n return path\n }\n }\n catch {\n // directory not readable\n }\n }\n return undefined\n}\n\nexport function resolveAdapterPath(cliId: string, explicitPath?: string): string {\n if (explicitPath) {\n if (existsSync(explicitPath))\n return explicitPath\n throw new Error(`Adapter file not found: ${explicitPath}`)\n }\n\n // Try direct lookup by ID\n const candidates = adapterDirs().map(dir => join(dir, `${cliId}.toml`))\n const match = candidates.find(path => existsSync(path))\n if (match)\n return match\n\n // Fallback: scan for adapter with matching executable name\n const byExec = findByExecutable(cliId)\n if (byExec)\n return byExec\n\n throw new Error(`No adapter found for ${cliId}`)\n}\n\nexport function loadAdapter(cliId: string, explicitPath?: string): LoadedAdapter {\n const source = resolveAdapterPath(cliId, explicitPath)\n const content = readFileSync(source, 'utf-8')\n const adapter = parseAdapterToml(content)\n\n // Accept if either the adapter ID or the executable matches the requested cliId\n const idMatch = adapter.cli.id === cliId\n const fileMatch = basename(source) === `${cliId}.toml`\n const execMatch = adapter.cli.executable === cliId\n if (!idMatch && !fileMatch && !execMatch)\n throw new Error(`Adapter ${source} does not match requested CLI ${cliId}`)\n\n return {\n adapter,\n source,\n digest: digest(content),\n }\n}\n\n/**\n * Called by `run.ts` when `loadAdapter(cliId)` has already failed with\n * \"No adapter found\". If generic-fallback mode is enabled in config,\n * return a synthetic `ResolvedCommand` that bypasses the parser. If\n * disabled, re-throw the original error (restoring legacy behaviour).\n *\n * @param cliId The CLI that had no registered shape\n * @param fullArgv Argv to execute (including the executable itself)\n * @param opts `genericEnabled: true` → return synthetic resolved;\n * `false` → throw `\"No adapter found for <cliId>\"`.\n */\nexport async function resolveGenericOrReject(\n cliId: string,\n fullArgv: string[],\n opts: { genericEnabled: boolean },\n): Promise<ResolvedCommand> {\n if (!opts.genericEnabled)\n throw new Error(`No adapter found for ${cliId}`)\n return await buildGenericResolved(cliId, fullArgv)\n}\n\n/** Try to load an adapter locally, return null instead of throwing when not found. */\nexport function tryLoadAdapter(cliId: string, explicitPath?: string): LoadedAdapter | null {\n try {\n return loadAdapter(cliId, explicitPath)\n }\n catch {\n return null\n }\n}\n","import type { ShapesAdapter, ShapesOperation } from './types.js'\n\ninterface AdapterTomlFile {\n schema?: string\n cli?: ShapesAdapter['cli']\n operation?: ShapesOperation[]\n}\n\nfunction parseKeyValue(line: string): { key: string, value: string } | null {\n const eqIndex = line.indexOf('=')\n if (eqIndex === -1)\n return null\n const key = line.slice(0, eqIndex).trim()\n const value = line.slice(eqIndex + 1).trim()\n if (!key || !value)\n return null\n return { key, value }\n}\n\nfunction parseTomlValue(raw: string): unknown {\n const trimmed = raw.trim()\n\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"'))\n return trimmed.slice(1, -1)\n if (trimmed === 'true')\n return true\n if (trimmed === 'false')\n return false\n if (trimmed.startsWith('[') && trimmed.endsWith(']')) {\n const inner = trimmed.slice(1, -1).trim()\n if (!inner)\n return []\n return inner.split(',').map(value => value.trim().replace(/^\"|\"$/g, ''))\n }\n\n return trimmed\n}\n\nexport function parseAdapterToml(content: string): ShapesAdapter {\n const result: AdapterTomlFile = {}\n const operations: ShapesOperation[] = []\n let currentSection: 'root' | 'cli' | 'operation' = 'root'\n let currentEntry: Record<string, unknown> = {}\n\n const flushOperation = () => {\n if (currentSection === 'operation' && Object.keys(currentEntry).length > 0) {\n operations.push(currentEntry as unknown as ShapesOperation)\n currentEntry = {}\n }\n }\n\n for (const rawLine of content.split('\\n')) {\n const line = rawLine.trim()\n if (!line || line.startsWith('#'))\n continue\n\n if (line === '[cli]') {\n flushOperation()\n currentSection = 'cli'\n result.cli = {} as ShapesAdapter['cli']\n continue\n }\n\n if (line === '[[operation]]') {\n flushOperation()\n currentSection = 'operation'\n currentEntry = {}\n continue\n }\n\n const kv = parseKeyValue(line)\n if (!kv)\n continue\n\n const value = parseTomlValue(kv.value)\n if (currentSection === 'root') {\n ;(result as Record<string, unknown>)[kv.key] = value\n }\n else if (currentSection === 'cli') {\n ;(result.cli as Record<string, unknown>)[kv.key] = value\n }\n else {\n currentEntry[kv.key] = value\n }\n }\n\n flushOperation()\n result.operation = operations\n\n if (result.schema !== 'openape-shapes/v1') {\n throw new Error(`Unsupported adapter schema: ${result.schema ?? 'missing'}`)\n }\n if (!result.cli?.id || !result.cli.executable) {\n throw new Error('Adapter is missing cli.id or cli.executable')\n }\n if (!result.operation?.length) {\n throw new Error('Adapter must define at least one [[operation]] entry')\n }\n\n return {\n schema: result.schema,\n cli: {\n id: String(result.cli.id),\n executable: String(result.cli.executable),\n ...(result.cli.audience ? { audience: String(result.cli.audience) } : {}),\n ...(result.cli.version ? { version: String(result.cli.version) } : {}),\n },\n operations: result.operation.map((operation) => {\n if (!Array.isArray(operation.command) || operation.command.some(token => typeof token !== 'string')) {\n throw new Error(`Operation ${String(operation.id ?? '<unknown>')} is missing command[]`)\n }\n if (!Array.isArray(operation.resource_chain) || operation.resource_chain.some(token => typeof token !== 'string')) {\n throw new Error(`Operation ${String(operation.id ?? '<unknown>')} is missing resource_chain[]`)\n }\n if (typeof operation.id !== 'string' || typeof operation.display !== 'string' || typeof operation.action !== 'string') {\n throw new TypeError('Operation must define id, display, and action')\n }\n return {\n id: operation.id,\n command: operation.command as string[],\n ...(Array.isArray(operation.positionals) ? { positionals: operation.positionals as string[] } : {}),\n ...(Array.isArray(operation.required_options) ? { required_options: operation.required_options as string[] } : {}),\n display: operation.display,\n action: operation.action,\n risk: (operation.risk as ShapesOperation['risk']) || 'low',\n resource_chain: operation.resource_chain as string[],\n ...(operation.exact_command !== undefined ? { exact_command: Boolean(operation.exact_command) } : {}),\n }\n }),\n }\n}\n","import type { OpenApeCliAuthorizationDetail } from '@openape/core'\nimport { canonicalizeCliPermission, computeArgvHash } from '@openape/grants'\nimport type { LoadedAdapter, ResolvedCommand, ShapesAdapter } from './types.js'\n\n/**\n * The synthetic operation ID used for generic-fallback grants. Downstream\n * code (audit logging, UI banner) keys off this exact string.\n */\nexport const GENERIC_OPERATION_ID = '_generic.exec'\n\n/**\n * Schema version for synthetic adapters. Not persisted anywhere — exists\n * only so the in-memory adapter shape matches `ShapesAdapter`.\n */\nconst SYNTHETIC_SCHEMA = 'openape-shapes/v1'\n\n/**\n * Build a synthetic in-memory `LoadedAdapter` for a CLI that has no\n * registered shape. The adapter is marked with `synthetic: true` so\n * callers can branch on it if needed.\n *\n * NOTE: This does NOT produce a parser-matchable adapter. The generic\n * pipeline bypasses `resolveCommand()` entirely — see `buildGenericResolved()`.\n * This function exists for flow-control markers and tests.\n */\nexport function buildGenericAdapter(cliId: string): LoadedAdapter {\n const adapter: ShapesAdapter = {\n schema: SYNTHETIC_SCHEMA,\n cli: {\n id: cliId,\n executable: cliId,\n audience: 'shapes',\n version: 'synthetic',\n },\n operations: [],\n }\n return {\n adapter,\n source: '<synthetic>',\n digest: 'synthetic',\n synthetic: true,\n }\n}\n\n/**\n * Build a `ResolvedCommand` directly for a CLI that has no registered shape.\n *\n * Unlike the normal flow (loadAdapter → resolveCommand), the generic path\n * bypasses the parser entirely. Rationale:\n *\n * - `resolveCommand()` matches argv against declarative operation specs\n * via `matchOperation()`, which requires `positionals.length ===\n * operation.positionals.length`. A \"match-all\" spec (`command: []`,\n * `positionals: []`) would reject any non-empty argv.\n *\n * - Synthetic adapters have no declarative spec — we already know what\n * to execute. Running the parser is theatre.\n *\n * The returned `ResolvedCommand` has:\n * - `detail.operation_id === GENERIC_OPERATION_ID` — marker consumed by\n * the audit-log hook in `verifyAndExecute`.\n * - `detail.risk === 'high'` — forced.\n * - `detail.constraints.exact_command === true` — forced, binds the\n * grant to this exact argv via `argv_hash`.\n * - `resource_chain = [{resource: 'cli', selector: {name: cliId}},\n * {resource: 'argv', selector: {hash: <sha256>}}]`\n */\nexport async function buildGenericResolved(\n cliId: string,\n fullArgv: string[],\n): Promise<ResolvedCommand> {\n if (fullArgv.length === 0)\n throw new Error('buildGenericResolved: fullArgv must include the executable')\n const executable = fullArgv[0]!\n const commandArgv = fullArgv.slice(1)\n const argvHash = await computeArgvHash(fullArgv)\n\n const display = `Execute (unshaped): \\`${cliId} ${commandArgv.join(' ')}\\``\n\n const detail: OpenApeCliAuthorizationDetail = {\n type: 'openape_cli',\n cli_id: cliId,\n operation_id: GENERIC_OPERATION_ID,\n resource_chain: [\n { resource: 'cli', selector: { name: cliId } },\n { resource: 'argv', selector: { hash: argvHash } },\n ],\n action: 'exec',\n permission: '',\n display,\n risk: 'high',\n constraints: { exact_command: true },\n }\n detail.permission = canonicalizeCliPermission(detail)\n\n const adapter = buildGenericAdapter(cliId)\n\n return {\n adapter: adapter.adapter,\n source: adapter.source,\n digest: adapter.digest,\n executable,\n commandArgv,\n bindings: {},\n detail,\n executionContext: {\n argv: fullArgv,\n argv_hash: argvHash,\n adapter_id: cliId,\n adapter_version: SYNTHETIC_SCHEMA,\n adapter_digest: adapter.digest,\n resolved_executable: executable,\n context_bindings: {},\n },\n permission: detail.permission,\n }\n}\n\n/**\n * Type guard: does this `ResolvedCommand` come from the generic fallback path?\n */\nexport function isGenericResolved(resolved: ResolvedCommand): boolean {\n return resolved.detail.operation_id === GENERIC_OPERATION_ID\n}\n","import { appendFileSync, existsSync, mkdirSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\n/** Single audit log entry. Always includes a timestamp and an action string. */\nexport interface AuditEntry {\n action: string\n timestamp: number\n [key: string]: unknown\n}\n\nfunction auditPath(): string {\n return join(homedir(), '.config', 'apes', 'audit.jsonl')\n}\n\n/**\n * Append a single entry to the audit log at ~/.config/apes/audit.jsonl.\n * Failures are swallowed — the audit log should never break the actual flow.\n */\nexport function appendAuditLog(entry: { action: string, timestamp?: number } & Record<string, unknown>): void {\n const full: AuditEntry = {\n ...entry,\n action: entry.action,\n timestamp: entry.timestamp ?? Date.now(),\n }\n const path = auditPath()\n const dir = dirname(path)\n try {\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\n appendFileSync(path, `${JSON.stringify(full)}\\n`)\n }\n catch {\n // intentionally ignored — audit log must never break the flow\n }\n}\n","import { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport type { RegistryEntry } from './types.js'\n\nfunction adapterDir(local: boolean): string {\n const base = local ? process.cwd() : homedir()\n return join(base, '.openape', 'shapes', 'adapters')\n}\n\nfunction adapterPath(id: string, local: boolean): string {\n return join(adapterDir(local), `${id}.toml`)\n}\n\nfunction sha256(content: string): string {\n return `SHA-256:${createHash('sha256').update(content).digest('hex')}`\n}\n\nexport interface InstallResult {\n id: string\n path: string\n digest: string\n updated: boolean\n}\n\nexport async function installAdapter(entry: RegistryEntry, options: { local?: boolean } = {}): Promise<InstallResult> {\n const local = options.local ?? false\n const dest = adapterPath(entry.id, local)\n const dir = adapterDir(local)\n\n const response = await fetch(entry.download_url)\n if (!response.ok)\n throw new Error(`Failed to download adapter ${entry.id}: ${response.status} ${response.statusText}`)\n\n const content = await response.text()\n const digest = sha256(content)\n\n if (digest !== entry.digest)\n throw new Error(`Digest mismatch for ${entry.id}: expected ${entry.digest}, got ${digest}`)\n\n const updated = existsSync(dest)\n\n if (!existsSync(dir))\n mkdirSync(dir, { recursive: true })\n\n writeFileSync(dest, content)\n\n return { id: entry.id, path: dest, digest, updated }\n}\n\nexport function getInstalledDigest(id: string, local: boolean): string | null {\n const path = adapterPath(id, local)\n if (!existsSync(path))\n return null\n\n const content = readFileSync(path, 'utf-8')\n return sha256(content)\n}\n\nexport function isInstalled(id: string, local: boolean): boolean {\n return existsSync(adapterPath(id, local))\n}\n\nexport function getInstalledPath(id: string, local: boolean): string {\n return adapterPath(id, local)\n}\n\nexport function removeAdapter(id: string, local: boolean): boolean {\n const path = adapterPath(id, local)\n if (!existsSync(path))\n return false\n unlinkSync(path)\n return true\n}\n\nexport interface ConflictingAdapter {\n file: string\n path: string\n adapterId: string\n executable: string\n}\n\nexport function findConflictingAdapters(executable: string, excludeId: string): ConflictingAdapter[] {\n const conflicts: ConflictingAdapter[] = []\n const dirs = [\n join(process.cwd(), '.openape', 'shapes', 'adapters'),\n join(homedir(), '.openape', 'shapes', 'adapters'),\n ]\n\n for (const dir of dirs) {\n if (!existsSync(dir))\n continue\n try {\n for (const file of readdirSync(dir).filter(f => f.endsWith('.toml'))) {\n const path = join(dir, file)\n const content = readFileSync(path, 'utf-8')\n const execMatch = content.match(/^\\s*executable\\s*=\\s*\"([^\"]+)\"/m)\n const idMatch = content.match(/^\\s*id\\s*=\\s*\"([^\"]+)\"/m)\n if (execMatch?.[1] === executable && idMatch?.[1] !== excludeId) {\n conflicts.push({ file, path, adapterId: idMatch?.[1] ?? file, executable })\n }\n }\n }\n catch {\n // directory not readable\n }\n }\n\n return conflicts\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport type { RegistryEntry, RegistryIndex } from './types.js'\n\nconst REGISTRY_URL = process.env.SHAPES_REGISTRY_URL\n ?? 'https://raw.githubusercontent.com/openape-ai/shapes-registry/main/registry.json'\n\nconst CACHE_TTL_MS = 60 * 60 * 1000 // 1 hour\n\nfunction cacheDir(): string {\n return join(homedir(), '.openape', 'shapes', 'cache')\n}\n\nfunction cachePath(): string {\n return join(cacheDir(), 'registry.json')\n}\n\nfunction readCache(): RegistryIndex | null {\n const path = cachePath()\n if (!existsSync(path))\n return null\n\n try {\n const raw = readFileSync(path, 'utf-8')\n const stat = JSON.parse(raw) as RegistryIndex & { _cached_at?: number }\n if (stat._cached_at && Date.now() - stat._cached_at > CACHE_TTL_MS)\n return null\n return stat\n }\n catch {\n return null\n }\n}\n\nfunction writeCache(index: RegistryIndex): void {\n const dir = cacheDir()\n if (!existsSync(dir))\n mkdirSync(dir, { recursive: true })\n\n writeFileSync(cachePath(), JSON.stringify({ ...index, _cached_at: Date.now() }, null, 2))\n}\n\nexport async function fetchRegistry(forceRefresh = false): Promise<RegistryIndex> {\n if (!forceRefresh) {\n const cached = readCache()\n if (cached)\n return cached\n }\n\n const response = await fetch(REGISTRY_URL)\n if (!response.ok)\n throw new Error(`Failed to fetch registry: ${response.status} ${response.statusText}`)\n\n const index = await response.json() as RegistryIndex\n writeCache(index)\n return index\n}\n\nexport function searchAdapters(index: RegistryIndex, query: string): RegistryEntry[] {\n const q = query.toLowerCase()\n return index.adapters.filter(a =>\n a.id.includes(q)\n || a.name.toLowerCase().includes(q)\n || a.description.toLowerCase().includes(q)\n || a.tags.some(t => t.includes(q))\n || a.category.includes(q),\n )\n}\n\n/**\n * Look up a registry entry by its id or its executable field. This lets callers\n * pass either the registry id (\"o365\") or the binary name (\"o365-cli\"); most\n * adapters have id === executable, but the two can diverge.\n */\nexport function findAdapter(index: RegistryIndex, idOrExecutable: string): RegistryEntry | undefined {\n return index.adapters.find(\n a => a.id === idOrExecutable || a.executable === idOrExecutable,\n )\n}\n","import { basename } from 'node:path'\nimport consola from 'consola'\nimport { parse as shellParse } from 'shell-quote'\nimport { loadAdapter, tryLoadAdapter } from './adapters.js'\nimport { installAdapter } from './installer.js'\nimport { fetchRegistry, findAdapter } from './registry.js'\nimport { appendAuditLog } from './audit.js'\nimport type { LoadedAdapter } from './types.js'\n\n/** A parsed shell command string with the executable and its argv extracted. */\nexport interface ParsedShellCommand {\n /** The program to run (first token, e.g. \"rm\") */\n executable: string\n /** Remaining tokens after the executable (e.g. [\"-f\", \"/tmp/foo.txt\"]) */\n argv: string[]\n /**\n * true if the command contains compound operators (&&, ||, ;, |),\n * subshells ($(...)), or backticks. These cannot be safely handled\n * by the adapter mode and must fall back to the generic shell grant flow.\n */\n isCompound: boolean\n /** The original command string for display/logging */\n raw: string\n}\n\nconst COMPOUND_OPERATORS = new Set(['&&', '||', ';', '|', '&', '>', '>>', '<'])\n\ntype ShellQuoteToken = string | { op: string } | { comment: string } | { pattern: string }\n\n/**\n * Parse a shell command string like `rm /tmp/foo.txt` or `git commit -m \"hello\"` into\n * its executable and argv. Uses `shell-quote` to handle quoting correctly.\n *\n * Returns null for empty/whitespace-only input.\n */\nexport function parseShellCommand(raw: string): ParsedShellCommand | null {\n const trimmed = raw.trim()\n if (trimmed.length === 0) return null\n\n let tokens: ShellQuoteToken[]\n try {\n tokens = shellParse(trimmed) as ShellQuoteToken[]\n }\n catch {\n return null\n }\n\n // Detect compound operators and subshells\n const hasShellExpansion = /\\$\\(|`/.test(trimmed)\n const hasOperatorToken = tokens.some(t => typeof t === 'object' && t !== null && 'op' in t && COMPOUND_OPERATORS.has(t.op))\n const isCompound = hasShellExpansion || hasOperatorToken\n\n // Extract leading string tokens up to the first operator object\n const stringTokens: string[] = []\n for (const t of tokens) {\n if (typeof t === 'string') {\n stringTokens.push(t)\n }\n else {\n break\n }\n }\n\n if (stringTokens.length === 0) return null\n\n return {\n executable: stringTokens[0]!,\n argv: stringTokens.slice(1),\n isCompound,\n raw: trimmed,\n }\n}\n\n/**\n * Extract the command string from an `apes run --shell -- bash -c \"…\"` argv.\n * Returns null if the argv does not follow that shape.\n */\nexport function extractShellCommandString(command: string[]): string | null {\n if (command.length < 3) return null\n if (command[0] !== 'bash' && command[0] !== 'sh') return null\n if (command[1] !== '-c') return null\n // Everything after `-c` is the quoted command string\n return command.slice(2).join(' ')\n}\n\n/**\n * Load an adapter for the given CLI id. If the adapter is not installed locally,\n * try to fetch it from the shapes registry and auto-install it.\n *\n * Returns null when no adapter exists in either location, or when any step fails.\n * Failures are logged but never thrown — callers should fall back to the generic flow.\n */\nexport async function loadOrInstallAdapter(cliId: string): Promise<LoadedAdapter | null> {\n // Absolute or relative paths like `/usr/local/bin/o365-cli` must be reduced\n // to the binary name before any lookup — neither the local file scan nor the\n // registry knows how to match a path.\n const lookupId = basename(cliId)\n\n // 1. Try local\n const local = tryLoadAdapter(lookupId)\n if (local) return local\n\n // 2. Remote registry lookup + auto-install.\n // findAdapter matches both `id` and `executable`, so a bare binary name\n // like `o365-cli` resolves to a registry entry whose id is `o365`.\n try {\n const index = await fetchRegistry()\n const entry = findAdapter(index, lookupId)\n if (!entry) return null\n\n consola.info(`Installing shapes adapter for ${entry.id} from registry...`)\n await installAdapter(entry, { local: false })\n appendAuditLog({\n action: 'adapter-auto-install',\n cli_id: entry.id,\n digest: entry.digest,\n source: 'ape-shell',\n })\n\n // Adapters are installed under their registry `id` — always reload by id\n // even if the caller passed the executable name.\n return tryLoadAdapter(entry.id)\n }\n catch (err) {\n consola.debug(`ape-shell adapter auto-install failed for ${lookupId}:`, err)\n return null\n }\n}\n\n// Re-export loadAdapter so callers can import everything from one module\nexport { loadAdapter }\n","import type { OpenApeCliAuthorizationDetail, OpenApeCliResourceRef } from '@openape/core'\nimport { canonicalizeCliPermission } from '@openape/grants'\nimport type { LoadedAdapter, ResolvedCapability, ShapesOperation } from './types.js'\n\ninterface ParsedOperationChainEntry {\n resource: string\n selectorKeys: string[]\n}\n\nfunction parseOperationChainEntry(entry: string): ParsedOperationChainEntry {\n const [resource, selectorSpec = '*'] = entry.split(':', 2)\n if (!resource) {\n throw new Error(`Invalid resource chain entry: ${entry}`)\n }\n\n if (selectorSpec === '*') {\n return { resource, selectorKeys: [] }\n }\n\n const selectorKeys = selectorSpec.split(',')\n .map((segment) => {\n const [key] = segment.split('=', 2)\n if (!key)\n throw new Error(`Invalid selector segment: ${segment}`)\n return key\n })\n\n return { resource, selectorKeys }\n}\n\nfunction operationChain(operation: ShapesOperation): ParsedOperationChainEntry[] {\n return operation.resource_chain.map(parseOperationChainEntry)\n}\n\nfunction knownSelectorKeys(operations: ShapesOperation[], resource: string): string[] {\n const keys = new Set<string>()\n for (const operation of operations) {\n for (const entry of operationChain(operation)) {\n if (entry.resource !== resource)\n continue\n for (const key of entry.selectorKeys) {\n keys.add(key)\n }\n }\n }\n return Array.from(keys).sort()\n}\n\nfunction parseResourceSelector(raw: string): { resource: string, key: string, value: string } {\n const [lhs, value] = raw.split('=', 2)\n if (!lhs || !value) {\n throw new Error(`Invalid selector: ${raw}`)\n }\n\n const [resource, key] = lhs.split('.', 2)\n if (!resource || !key) {\n throw new Error(`Selectors must be in resource.key=value form: ${raw}`)\n }\n\n return { resource, key, value }\n}\n\nfunction formatSelector(selector?: Record<string, string>): string {\n if (!selector || Object.keys(selector).length === 0)\n return '*'\n return Object.entries(selector)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, value]) => `${key}=${value}`)\n .join(',')\n}\n\nfunction summarizeDetail(detail: OpenApeCliAuthorizationDetail): string {\n const chain = detail.resource_chain\n .map(resource => `${resource.resource}[${formatSelector(resource.selector)}]`)\n .join(' -> ')\n return `Allow ${detail.action} on ${detail.cli_id} ${chain}`\n}\n\nexport function resolveCapabilityRequest(\n loaded: LoadedAdapter,\n params: {\n resources: string[]\n selectors?: string[]\n actions: string[]\n },\n): ResolvedCapability {\n if (params.resources.length === 0) {\n throw new Error('At least one --resource is required')\n }\n if (params.actions.length === 0) {\n throw new Error('At least one --action is required')\n }\n\n const selectorMap = new Map<string, Record<string, string>>()\n for (const rawSelector of params.selectors ?? []) {\n const { resource, key, value } = parseResourceSelector(rawSelector)\n const current = selectorMap.get(resource) ?? {}\n current[key] = value\n selectorMap.set(resource, current)\n }\n\n const resource_chain: OpenApeCliResourceRef[] = params.resources.map((resource) => {\n const selector = selectorMap.get(resource)\n const knownKeys = knownSelectorKeys(loaded.adapter.operations, resource)\n if (selector) {\n for (const key of Object.keys(selector)) {\n if (!knownKeys.includes(key)) {\n throw new Error(`Unknown selector ${resource}.${key} for adapter ${loaded.adapter.cli.id}`)\n }\n }\n }\n return selector && Object.keys(selector).length > 0 ? { resource, selector } : { resource }\n })\n\n const requestedSequence = params.resources.join('\\0')\n const matchingOperations = loaded.adapter.operations.filter((operation) => {\n const sequence = operationChain(operation).map(entry => entry.resource).join('\\0')\n return sequence === requestedSequence || sequence.startsWith(`${requestedSequence}\\0`)\n })\n\n if (matchingOperations.length === 0) {\n throw new Error(`No adapter operation supports resource chain: ${params.resources.join(' -> ')}`)\n }\n\n const details = params.actions.map((action) => {\n const matchingActionOps = matchingOperations.filter(operation => operation.action === action)\n if (matchingActionOps.length === 0) {\n throw new Error(`Action ${action} is not valid for resource chain: ${params.resources.join(' -> ')}`)\n }\n\n const exact_command = matchingActionOps.every(operation => operation.exact_command === true)\n const risks = ['low', 'medium', 'high', 'critical'] as const\n const risk = matchingActionOps.reduce<typeof risks[number]>((current, operation) => {\n return risks.indexOf(operation.risk) > risks.indexOf(current) ? operation.risk : current\n }, 'low')\n\n const detail: OpenApeCliAuthorizationDetail = {\n type: 'openape_cli',\n cli_id: loaded.adapter.cli.id,\n operation_id: `capability.${action}`,\n resource_chain,\n action,\n permission: '',\n display: '',\n risk,\n ...(exact_command ? { constraints: { exact_command: true } } : {}),\n }\n detail.permission = canonicalizeCliPermission(detail)\n detail.display = summarizeDetail(detail)\n return detail\n })\n\n return {\n adapter: loaded.adapter,\n source: loaded.source,\n digest: loaded.digest,\n executable: loaded.adapter.cli.executable,\n details,\n executionContext: {\n adapter_id: loaded.adapter.cli.id,\n adapter_version: loaded.adapter.cli.version ?? loaded.adapter.schema,\n adapter_digest: loaded.digest,\n resolved_executable: loaded.adapter.cli.executable,\n context_bindings: Object.fromEntries(\n Array.from(selectorMap.entries()).flatMap(([resource, selector]) =>\n Object.entries(selector).map(([key, value]) => [`${resource}.${key}`, value] as const),\n ),\n ),\n },\n permissions: details.map(detail => detail.permission),\n summary: details.map(detail => detail.display).join('; '),\n }\n}\n","import type { OpenApeCliAuthorizationDetail, OpenApeCliResourceRef } from '@openape/core'\nimport { canonicalizeCliPermission, computeArgvHash } from '@openape/grants'\nimport type { LoadedAdapter, ResolvedCommand, ShapesOperation } from './types.js'\n\nfunction parseOptionArgs(tokens: string[], valueOptions?: string[]): { options: Record<string, string>, positionals: string[] } {\n const options: Record<string, string> = {}\n const positionals: string[] = []\n const takesValue = new Set(valueOptions ?? [])\n\n for (let index = 0; index < tokens.length; index += 1) {\n const token = tokens[index]!\n\n if (token.startsWith('--')) {\n // Long option: --name value or --name=value\n const stripped = token.slice(2)\n const eqIndex = stripped.indexOf('=')\n if (eqIndex >= 0) {\n options[stripped.slice(0, eqIndex)] = stripped.slice(eqIndex + 1)\n continue\n }\n\n const next = tokens[index + 1]\n if (next && !next.startsWith('-')) {\n options[stripped] = next\n index += 1\n continue\n }\n\n options[stripped] = 'true'\n }\n else if (token.startsWith('-') && token.length > 1 && !/^-\\d/.test(token)) {\n // Short option: -name value, -f value, or -l (boolean)\n const key = token.slice(1)\n\n if (key.length === 1 && !takesValue.has(key)) {\n // Single-char flag not in required_options → boolean\n options[key] = 'true'\n }\n else {\n // Multi-char option (-name) or known value option (-f) → consume next as value\n const next = tokens[index + 1]\n if (next && !next.startsWith('-')) {\n options[key] = next\n index += 1\n }\n else {\n options[key] = 'true'\n }\n }\n }\n else {\n positionals.push(token)\n }\n }\n\n return { options, positionals }\n}\n\nfunction resolveBindingToken(binding: string, bindings: Record<string, string>): string {\n const match = binding.match(/^\\{([^}|]+)(?:\\|([^}]+))?\\}$/)\n if (!match)\n return binding\n\n const [, name, transform] = match\n const value = bindings[name]\n if (!value)\n throw new Error(`Missing binding: ${name}`)\n if (!transform)\n return value\n\n if (transform === 'owner' || transform === 'name') {\n const [owner, repo] = value.split('/')\n if (!owner || !repo)\n throw new Error(`Binding ${name} must be in owner/name form`)\n return transform === 'owner' ? owner : repo\n }\n\n throw new Error(`Unsupported binding transform: ${transform}`)\n}\n\nfunction renderTemplate(template: string, bindings: Record<string, string>): string {\n return template.replace(/\\{([^}]+)\\}/g, (_, expression: string) => resolveBindingToken(`{${expression}}`, bindings))\n}\n\nfunction parseResourceChain(chain: string[], bindings: Record<string, string>): OpenApeCliResourceRef[] {\n return chain.map((entry) => {\n const [resource, selectorSpec = '*'] = entry.split(':', 2)\n if (!resource)\n throw new Error(`Invalid resource chain entry: ${entry}`)\n\n if (selectorSpec === '*') {\n return { resource }\n }\n\n const selector = Object.fromEntries(\n selectorSpec.split(',').map((segment) => {\n const [key, rawValue] = segment.split('=', 2)\n if (!key || !rawValue)\n throw new Error(`Invalid selector segment: ${segment}`)\n return [key, renderTemplate(rawValue, bindings)]\n }),\n )\n\n return { resource, selector }\n })\n}\n\nfunction matchOperation(operation: ShapesOperation, argv: string[]): Record<string, string> | null {\n if (argv.length < operation.command.length)\n return null\n\n const prefix = argv.slice(0, operation.command.length)\n if (prefix.join('\\0') !== operation.command.join('\\0'))\n return null\n\n const remainder = argv.slice(operation.command.length)\n const { options, positionals } = parseOptionArgs(remainder, operation.required_options)\n\n const expectedPositionals = operation.positionals ?? []\n if (positionals.length !== expectedPositionals.length)\n return null\n\n for (const option of operation.required_options ?? []) {\n if (!options[option])\n return null\n }\n\n const bindings: Record<string, string> = { ...options }\n for (let index = 0; index < expectedPositionals.length; index += 1) {\n const name = expectedPositionals[index]!\n const value = positionals[index]!\n if (name.startsWith('=')) {\n if (value !== name.slice(1))\n return null\n continue\n }\n bindings[name] = value\n }\n return bindings\n}\n\nfunction expandCombinedFlags(argv: string[]): string[] {\n return argv.flatMap((token) => {\n // Expand -rl into -r, -l (only single-letter combined flags)\n if (token.startsWith('-') && !token.startsWith('--') && token.length > 2 && /^-[a-z]+$/i.test(token)) {\n return Array.from(token.slice(1), c => `-${c}`)\n }\n return [token]\n })\n}\n\nfunction tryMatch(operations: ShapesOperation[], argv: string[]) {\n return operations.flatMap((operation) => {\n try {\n const bindings = matchOperation(operation, argv)\n return bindings ? [{ operation, bindings }] : []\n }\n catch {\n return []\n }\n })\n}\n\nexport async function resolveCommand(loaded: LoadedAdapter, fullArgv: string[]): Promise<ResolvedCommand> {\n const [executable, ...commandArgv] = fullArgv\n if (!executable) {\n throw new Error('Missing wrapped command')\n }\n if (executable !== loaded.adapter.cli.executable) {\n throw new Error(`Adapter ${loaded.adapter.cli.id} expects executable ${loaded.adapter.cli.executable}, got ${executable}`)\n }\n\n // Pass 1: exact match\n let matches = tryMatch(loaded.adapter.operations, commandArgv)\n\n // Pass 2: try with expanded combined flags (e.g. -rl → -r -l)\n if (matches.length === 0) {\n const expanded = expandCombinedFlags(commandArgv)\n if (expanded.length !== commandArgv.length) {\n matches = tryMatch(loaded.adapter.operations, expanded)\n }\n }\n\n if (matches.length === 0) {\n throw new Error(`No adapter operation matched: ${fullArgv.join(' ')}`)\n }\n if (matches.length > 1) {\n // Prefer the most specific match (longest command prefix)\n matches.sort((a, b) => b.operation.command.length - a.operation.command.length)\n matches = [matches[0]!]\n }\n\n const { operation, bindings } = matches[0]!\n const resource_chain = parseResourceChain(operation.resource_chain, bindings)\n const detail: OpenApeCliAuthorizationDetail = {\n type: 'openape_cli',\n cli_id: loaded.adapter.cli.id,\n operation_id: operation.id,\n resource_chain,\n action: operation.action,\n permission: '',\n display: renderTemplate(operation.display, bindings),\n risk: operation.risk,\n ...(operation.exact_command ? { constraints: { exact_command: true } } : {}),\n }\n detail.permission = canonicalizeCliPermission(detail)\n\n return {\n adapter: loaded.adapter,\n source: loaded.source,\n digest: loaded.digest,\n executable,\n commandArgv,\n bindings,\n detail,\n executionContext: {\n argv: fullArgv,\n argv_hash: await computeArgvHash(fullArgv),\n adapter_id: loaded.adapter.cli.id,\n adapter_version: loaded.adapter.cli.version ?? loaded.adapter.schema,\n adapter_digest: loaded.digest,\n resolved_executable: executable,\n context_bindings: bindings,\n },\n permission: detail.permission,\n }\n}\n","import { defineCommand } from 'citty'\nimport { loadAdapter } from '../adapters.js'\nimport { resolveCommand } from '../parser.js'\n\nexport const explainCommand = defineCommand({\n meta: {\n name: 'explain',\n description: 'Show what permission a wrapped command would need',\n },\n args: {\n adapter: {\n type: 'string',\n description: 'Explicit path to adapter TOML file',\n },\n _: {\n type: 'positional',\n description: 'Wrapped command (after --)',\n required: false,\n },\n },\n async run({ rawArgs }) {\n const command = extractWrappedCommand(rawArgs ?? [])\n if (command.length === 0)\n throw new Error('Missing wrapped command. Usage: shapes explain [--adapter <file>] -- <cli> ...')\n\n const adapterOpt = extractOption(rawArgs ?? [], 'adapter')\n const loaded = loadAdapter(command[0]!, adapterOpt)\n const resolved = await resolveCommand(loaded, command)\n\n process.stdout.write(`${JSON.stringify({\n adapter: resolved.adapter.cli.id,\n source: resolved.source,\n operation: resolved.detail.operation_id,\n display: resolved.detail.display,\n permission: resolved.permission,\n resource_chain: resolved.detail.resource_chain,\n exact_command: resolved.detail.constraints?.exact_command ?? false,\n adapter_digest: resolved.digest,\n }, null, 2)}\\n`)\n },\n})\n\nexport function extractWrappedCommand(args: string[]): string[] {\n const delimiter = args.indexOf('--')\n return delimiter >= 0 ? args.slice(delimiter + 1) : []\n}\n\nexport function extractOption(args: string[], name: string): string | undefined {\n const delimiter = args.indexOf('--')\n const optionArgs = delimiter >= 0 ? args.slice(0, delimiter) : args\n const index = optionArgs.indexOf(`--${name}`)\n if (index >= 0 && index + 1 < optionArgs.length)\n return optionArgs[index + 1]\n return undefined\n}\n","import type { OpenApeCliAuthorizationDetail, OpenApeGrant } from '@openape/core'\nimport { computeCmdHash } from '@openape/core'\nimport { cliAuthorizationDetailCovers, verifyAuthzJWT } from '@openape/grants'\nimport { execFileSync } from 'node:child_process'\nimport { hostname } from 'node:os'\nimport consola from 'consola'\nimport { getRequesterIdentity } from './config.js'\nimport { getGenericAuditLogPath } from '../config.js'\nimport { resolveCommand } from './parser.js'\nimport { loadOrInstallAdapter } from './shell-parser.js'\nimport type { ResolvedCommand } from './types.js'\nimport { apiFetch, discoverEndpoints, getGrantsEndpoint } from './http.js'\nimport { appendGenericCallLog } from '../audit/generic-log.js'\nimport { isGenericResolved } from './generic.js'\n\nfunction decodePayload(token: string): Record<string, unknown> {\n const [, payload] = token.split('.')\n if (!payload)\n throw new Error('Invalid JWT')\n return JSON.parse(Buffer.from(payload, 'base64url').toString('utf-8')) as Record<string, unknown>\n}\n\ninterface SimilarGrantsInfo {\n similar_grants: Array<{ grant: { id: string }, similar_detail_indices: number[] }>\n widened_details: Array<{ permission: string }>\n merged_details: Array<{ permission: string }>\n}\n\nexport async function createShapesGrant(\n resolved: ResolvedCommand,\n params: {\n idp: string\n approval: 'once' | 'timed' | 'always'\n reason?: string\n },\n): Promise<{ id: string, status: string, similar_grants?: SimilarGrantsInfo }> {\n const grantsEndpoint = await getGrantsEndpoint(params.idp)\n const requester = getRequesterIdentity()\n if (!requester) {\n throw new Error('No requester identity available. Run `apes login` first.')\n }\n return apiFetch<{ id: string, status: string, similar_grants?: SimilarGrantsInfo }>(grantsEndpoint, {\n method: 'POST',\n idp: params.idp,\n body: {\n requester,\n target_host: hostname(),\n audience: resolved.adapter.cli.audience ?? 'shapes',\n grant_type: params.approval,\n command: resolved.executionContext.argv,\n reason: params.reason ?? resolved.detail.display,\n permissions: [resolved.permission],\n authorization_details: [resolved.detail],\n execution_context: resolved.executionContext,\n },\n })\n}\n\nexport async function waitForGrantStatus(idp: string, grantId: string): Promise<'approved' | 'denied' | 'revoked'> {\n const grantsEndpoint = await getGrantsEndpoint(idp)\n const deadline = Date.now() + 300_000\n\n while (Date.now() < deadline) {\n const grant = await apiFetch<{ status: 'pending' | 'approved' | 'denied' | 'revoked' }>(`${grantsEndpoint}/${grantId}`, { idp })\n if (grant.status === 'approved' || grant.status === 'denied' || grant.status === 'revoked')\n return grant.status\n await new Promise(resolve => setTimeout(resolve, 3000))\n }\n\n throw new Error('Timed out waiting for grant approval')\n}\n\nexport async function fetchGrantToken(idp: string, grantId: string): Promise<string> {\n const grantsEndpoint = await getGrantsEndpoint(idp)\n const response = await apiFetch<{ authz_jwt: string }>(`${grantsEndpoint}/${grantId}/token`, {\n method: 'POST',\n idp,\n })\n return response.authz_jwt\n}\n\nfunction grantedCliDetails(claims: Record<string, unknown>): OpenApeCliAuthorizationDetail[] {\n const details = claims.authorization_details\n if (!Array.isArray(details))\n return []\n\n return details.filter((detail): detail is OpenApeCliAuthorizationDetail =>\n typeof detail === 'object'\n && detail !== null\n && (detail as Record<string, unknown>).type === 'openape_cli',\n )\n}\n\nfunction hasStructuredCliGrant(claims: Record<string, unknown>): boolean {\n return grantedCliDetails(claims).length > 0\n}\n\n/**\n * Verifies a grant token against the resolved command and marks the grant\n * as consumed on the IdP. Does NOT execute anything — callers that want\n * the one-shot behavior should use `verifyAndExecute`, callers that want\n * to run the command themselves (e.g. the interactive REPL piping through\n * a persistent bash pty) should call this and then do their own execution.\n *\n * Split out so the interactive shell can re-use the verify + consume path\n * without being forced into the `execFileSync`-based one-shot execution.\n */\nexport async function verifyAndConsume(token: string, resolved: ResolvedCommand): Promise<void> {\n const payload = decodePayload(token)\n const issuer = String(payload.iss ?? '')\n if (!issuer)\n throw new Error('Grant token is missing issuer')\n\n const discovery = await discoverEndpoints(issuer)\n const jwksUri = String(discovery.jwks_uri ?? `${issuer}/.well-known/jwks.json`)\n const result = await verifyAuthzJWT(token, {\n expectedIss: issuer,\n expectedAud: resolved.adapter.cli.audience ?? 'shapes',\n jwksUri,\n })\n\n if (!result.valid || !result.claims) {\n throw new Error(result.error ?? 'Grant verification failed')\n }\n\n const claims = result.claims\n const details = grantedCliDetails(claims as unknown as Record<string, unknown>)\n\n if (claims.execution_context?.adapter_digest && claims.execution_context.adapter_digest !== resolved.digest) {\n throw new Error('Adapter digest mismatch')\n }\n\n if (!hasStructuredCliGrant(claims as unknown as Record<string, unknown>)) {\n const argv = resolved.executionContext.argv\n if (!argv?.length) {\n throw new Error('Resolved command is missing argv')\n }\n const expectedCmdHash = await computeCmdHash(argv.join(' '))\n if (claims.command?.join('\\0') !== argv.join('\\0')) {\n throw new Error('Granted command does not match current argv')\n }\n if (claims.cmd_hash && claims.cmd_hash !== expectedCmdHash) {\n throw new Error('Granted command does not match current argv')\n }\n if (!claims.command?.length && !claims.cmd_hash) {\n throw new Error('Grant is not a structured CLI grant and is missing command binding')\n }\n }\n else {\n if (!details.some(detail => cliAuthorizationDetailCovers(detail, resolved.detail))) {\n throw new Error(`Grant does not cover required permission: ${resolved.permission}`)\n }\n\n const exactRequired = details.some(detail =>\n cliAuthorizationDetailCovers(detail, resolved.detail) && detail.constraints?.exact_command,\n )\n\n const isOnce = claims.grant_type === 'once' || claims.approval === 'once'\n const enforceArgvHash = exactRequired || (isOnce && !!claims.execution_context?.argv_hash)\n\n if (enforceArgvHash && claims.execution_context?.argv_hash !== resolved.executionContext.argv_hash) {\n throw new Error('Granted command does not match current argv')\n }\n }\n\n const grantsEndpoint = await getGrantsEndpoint(issuer)\n const consume = await fetch(`${grantsEndpoint}/${claims.grant_id}/consume`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })\n\n if (!consume.ok) {\n throw new Error(`Consume failed: ${consume.status} ${consume.statusText}`)\n }\n\n const consumeResult = await consume.json() as { error?: string }\n if (consumeResult.error) {\n throw new Error(`Grant rejected at consume step: ${consumeResult.error}`)\n }\n}\n\n/**\n * Execute a verified + consumed resolved command directly via execFileSync,\n * inheriting stdio so the caller's terminal is handed to the child. Used by\n * the one-shot `apes run --shell` path.\n */\nexport function executeResolvedViaExec(resolved: ResolvedCommand): void {\n consola.info(`Executing ${(resolved.executionContext.argv ?? [resolved.executable, ...resolved.commandArgv]).join(' ')}`)\n execFileSync(resolved.executable, resolved.commandArgv, { stdio: 'inherit' })\n}\n\n/**\n * One-shot verify + consume + execute. Preserves the legacy behavior of\n * the `apes run --shell` path so existing callers keep working unchanged.\n *\n * When `resolved` carries the generic-fallback operation id\n * (`_generic.exec`), a JSONL audit entry is appended to the generic-calls\n * log after the child process exits. `grantId` is needed to write the\n * entry — callers that know the grant id should pass it; if omitted, the\n * log entry is skipped (the audit hook is best-effort, not a hard gate).\n *\n * This is the central exec path for sync (`--wait`), async-default\n * (`apes grants run <id> --wait`), and REPL one-shot, so a hook here\n * covers all three flows without duplicating logic in each caller.\n */\nexport async function verifyAndExecute(\n token: string,\n resolved: ResolvedCommand,\n grantId?: string,\n): Promise<void> {\n await verifyAndConsume(token, resolved)\n\n const isGeneric = isGenericResolved(resolved)\n const start = Date.now()\n let exitCode = 0\n try {\n executeResolvedViaExec(resolved)\n }\n catch (err) {\n exitCode = (err as { status?: number })?.status ?? 1\n throw err\n }\n finally {\n if (isGeneric && grantId) {\n // Best-effort: swallow log errors so a broken audit file never\n // blocks a successful command.\n try {\n await appendGenericCallLog(\n {\n ts: new Date().toISOString(),\n cli: resolved.detail.cli_id,\n argv: resolved.executionContext.argv ?? [resolved.executable, ...resolved.commandArgv],\n argv_hash: resolved.executionContext.argv_hash ?? '',\n grant_id: grantId,\n exit_code: exitCode,\n duration_ms: Date.now() - start,\n },\n getGenericAuditLogPath(),\n )\n }\n catch (logErr) {\n consola.debug('Failed to append generic-call audit entry:', logErr)\n }\n }\n }\n}\n\n/**\n * Re-resolve a ResolvedCommand from a previously-created grant's recorded\n * request (argv + adapter digest). Used by `apes grants run <id>` to replay\n * an approved grant locally after the async approval step.\n *\n * Throws when the grant is missing argv, when the adapter cannot be loaded,\n * or when the locally installed adapter's digest no longer matches what the\n * grant was issued against.\n */\nexport async function resolveFromGrant(\n grant: {\n request: {\n command?: string[]\n execution_context?: { adapter_digest?: string, argv_hash?: string }\n authorization_details?: Array<{ type?: string, permission?: string }>\n }\n },\n): Promise<ResolvedCommand> {\n const argv = grant.request?.command\n if (!argv || argv.length === 0)\n throw new Error('Grant request is missing command argv')\n\n const executable = argv[0]\n const adapter = await loadOrInstallAdapter(executable)\n if (!adapter)\n throw new Error(`No shapes adapter found for ${executable}`)\n\n const resolved = await resolveCommand(adapter, argv)\n\n const grantDigest = grant.request.execution_context?.adapter_digest\n if (grantDigest && grantDigest !== resolved.digest) {\n throw new Error(\n `Adapter digest mismatch: grant was created against adapter ${grantDigest}, but local adapter is ${resolved.digest}. Reinstall or revert the adapter.`,\n )\n }\n\n return resolved\n}\n\nexport async function findExistingGrant(\n resolved: ResolvedCommand,\n idp: string,\n): Promise<string | null> {\n const grantsEndpoint = await getGrantsEndpoint(idp)\n const response = await apiFetch<{ data: OpenApeGrant[] }>(\n `${grantsEndpoint}?status=approved`,\n { idp },\n )\n\n const now = Math.floor(Date.now() / 1000)\n const expectedAudience = resolved.adapter.cli.audience ?? 'shapes'\n\n for (const grant of response.data) {\n const req = grant.request\n if (req.grant_type === 'once')\n continue\n if (req.grant_type === 'timed' && grant.expires_at && grant.expires_at <= now)\n continue\n if (req.audience !== expectedAudience)\n continue\n if (req.execution_context?.adapter_digest && req.execution_context.adapter_digest !== resolved.digest)\n continue\n\n const cliDetails = (req.authorization_details ?? []).filter(\n (d): d is OpenApeCliAuthorizationDetail => d.type === 'openape_cli',\n )\n\n if (cliDetails.length > 0) {\n if (cliDetails.some(detail => cliAuthorizationDetailCovers(detail, resolved.detail)))\n return grant.id\n }\n else if (req.permissions?.includes(resolved.permission)) {\n return grant.id\n }\n }\n\n return null\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\ninterface AuthData {\n idp: string\n access_token: string\n email: string\n expires_at: number\n}\n\nconst AUTH_FILE = join(homedir(), '.config', 'apes', 'auth.json')\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')) as AuthData\n }\n catch {\n return null\n }\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 if (process.env.SHAPES_IDP)\n return process.env.SHAPES_IDP\n return loadAuth()?.idp ?? null\n}\n\nexport function getAuthToken(): string | null {\n const auth = loadAuth()\n if (!auth)\n return null\n if (auth.expires_at && Date.now() / 1000 > auth.expires_at - 30)\n return null\n return auth.access_token\n}\n\nexport function getRequesterIdentity(): string | null {\n return loadAuth()?.email ?? null\n}\n","import { getAuthToken, getIdpUrl } from './config.js'\n\nexport async function discoverEndpoints(idpUrl: string): Promise<Record<string, unknown>> {\n const response = await fetch(`${idpUrl}/.well-known/openid-configuration`)\n if (!response.ok)\n return {}\n return response.json() as Promise<Record<string, unknown>>\n}\n\nexport async function getGrantsEndpoint(idpUrl: string): Promise<string> {\n const discovery = await discoverEndpoints(idpUrl)\n return String(discovery.openape_grants_endpoint ?? `${idpUrl}/api/grants`)\n}\n\nexport async function apiFetch<T>(\n path: string,\n options: {\n method?: string\n body?: unknown\n idp?: string\n token?: string\n } = {},\n): Promise<T> {\n const token = options.token ?? getAuthToken()\n if (!token)\n throw new Error('Not authenticated. Run `apes login` first.')\n\n const idp = options.idp ?? getIdpUrl()\n if (!path.startsWith('http') && !idp)\n throw new Error('No IdP URL configured. Use --idp or log in with apes.')\n\n const url = path.startsWith('http') ? path : `${idp}${path}`\n const response = await fetch(url, {\n method: options.method ?? 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n })\n\n if (!response.ok) {\n const text = await response.text()\n throw new Error(text || `${response.status} ${response.statusText}`)\n }\n\n return response.json() as Promise<T>\n}\n","import { mkdir, appendFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\n/**\n * A single successful generic-fallback execution entry.\n * Denied, timeout, and cancelled grants are NOT logged here — they are\n * captured by the IdP's server-side audit trail.\n */\nexport interface GenericCallLogEntry {\n /** ISO 8601 timestamp of execution completion */\n ts: string\n /** CLI id as requested by the user (e.g. \"kubectl\") */\n cli: string\n /** Full argv as executed, including the executable */\n argv: string[]\n /** SHA-256 of the argv — matches the `argv:hash` selector in resource_chain */\n argv_hash: string\n /** Grant that authorized this execution */\n grant_id: string\n /** Process exit code */\n exit_code: number\n /** Wall-clock duration from grant-approval to process exit, milliseconds */\n duration_ms: number\n}\n\n/**\n * Default audit log location. Lives under `~/.config/apes/` for consistency\n * with the rest of apes' client state (`config.toml`, `auth.json`, …).\n */\nexport function defaultGenericLogPath(): string {\n return join(homedir(), '.config', 'apes', 'generic-calls.log')\n}\n\n/**\n * Append a single generic-call entry to the audit log in JSONL format.\n * Creates the containing directory if needed.\n *\n * @param entry The call record to append\n * @param logPath Optional override (usually from `config.generic.audit_log`)\n */\nexport async function appendGenericCallLog(\n entry: GenericCallLogEntry,\n logPath?: string,\n): Promise<void> {\n const path = logPath ?? defaultGenericLogPath()\n await mkdir(dirname(path), { recursive: true })\n await appendFile(path, `${JSON.stringify(entry)}\\n`, 'utf-8')\n}\n","import { computeCmdHash } from '@openape/core'\nimport type { BuiltGrantRequest, GrantRequestOptions, ResolvedCapability, ResolvedCommand } from './types.js'\n\nexport async function buildExactCommandGrantRequest(\n command: string[],\n options: GrantRequestOptions & {\n audience: string\n },\n): Promise<BuiltGrantRequest> {\n return {\n request: {\n requester: options.requester,\n target_host: options.target_host,\n audience: options.audience,\n grant_type: options.grant_type,\n command,\n cmd_hash: await computeCmdHash(command.join(' ')),\n ...(options.reason ? { reason: options.reason } : {}),\n ...(options.run_as ? { run_as: options.run_as } : {}),\n },\n }\n}\n\nexport async function buildStructuredCliGrantRequest(\n resolved: ResolvedCommand | ResolvedCapability,\n options: GrantRequestOptions,\n): Promise<BuiltGrantRequest> {\n const details = 'detail' in resolved ? [resolved.detail] : resolved.details\n const permissions = 'permission' in resolved ? [resolved.permission] : resolved.permissions\n const command = 'executionContext' in resolved && resolved.executionContext.argv?.length\n ? resolved.executionContext.argv\n : undefined\n\n return {\n request: {\n requester: options.requester,\n target_host: options.target_host,\n audience: resolved.adapter.cli.audience ?? 'shapes',\n grant_type: options.grant_type,\n permissions,\n authorization_details: details,\n execution_context: resolved.executionContext,\n ...(command ? { command } : {}),\n ...(options.reason ? { reason: options.reason } : { reason: 'summary' in resolved ? resolved.summary : details[0]?.display }),\n ...(options.run_as ? { run_as: options.run_as } : {}),\n },\n }\n}\n"],"mappings":"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","names":["existsSync","homedir","join","createHash","existsSync","mkdirSync","readdirSync","readFileSync","homedir","join","digest","existsSync","join","homedir","readdirSync","readFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","join","basename","basename","canonicalizeCliPermission","canonicalizeCliPermission","computeArgvHash","consola","existsSync","readFileSync","homedir","join","homedir","dirname","join","consola","computeCmdHash"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/duration.ts","../src/lib/agent-tools/ape-shell-exec.ts","../src/lib/agent-tools/bash.ts","../src/lib/agent-tools/file.ts","../src/lib/coding/forge.ts","../src/lib/agent-tools/forge.ts","../src/lib/agent-tools/git-worktree.ts","../src/lib/agent-tools/http.ts","../src/lib/agent-tools/mail.ts","../src/lib/agent-tools/tasks.ts","../src/lib/agent-tools/time.ts","../src/lib/coding/verify.ts","../src/lib/agent-tools/verify.ts","../src/lib/agent-tools/index.ts","../src/lib/agent-runtime.ts"],"sourcesContent":["export class CliError extends Error {\n constructor(message: string, public exitCode: number = 1) {\n super(message)\n this.name = 'CliError'\n }\n}\n\nexport class CliExit extends Error {\n constructor(public exitCode: number = 0) {\n super('')\n this.name = 'CliExit'\n }\n}\n","/**\n * Parse a human-readable duration string into seconds.\n * Supported formats: 30s, 5m, 1h, 7d\n */\nexport function parseDuration(value: string): number {\n const match = value.match(/^(\\d+)\\s*([smhd])$/)\n if (!match) {\n throw new Error(`Invalid duration format: \"${value}\". Use e.g. 30m, 1h, 7d`)\n }\n const amount = Number.parseInt(match[1]!, 10)\n switch (match[2]) {\n case 's': return amount\n case 'm': return amount * 60\n case 'h': return amount * 3600\n case 'd': return amount * 86400\n default: throw new Error(`Unknown duration unit: ${match[2]}`)\n }\n}\n","import { spawn } from 'node:child_process'\n\n// Shared gated-exec path. Every shell command an agent tool runs goes\n// through `ape-shell -c <cmd>`, which rewrites to `apes run --shell --\n// bash -c …` — i.e. the DDISA grant cycle + shapes-adapter matching,\n// identical to what the human owner types interactively. APE_WAIT=1\n// forces the blocking path so the tool returns a result instead of\n// exiting 75 with grant-pending instructions.\n//\n// bash.ts and git-worktree.ts both build on this so the gating is\n// guaranteed in one place — no tool can shell out un-gated by reaching\n// for child_process directly.\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000\nconst MAX_STDIO_BYTES = 64 * 1024\nconst BIN = 'ape-shell'\n\nexport interface ApeShellResult {\n stdout: string\n stderr: string\n exit_code: number\n timed_out?: boolean\n error?: string\n hint?: string\n}\n\nfunction capStdio(s: string): string {\n const buf = Buffer.from(s, 'utf8')\n if (buf.byteLength <= MAX_STDIO_BYTES) return s\n return `${buf.subarray(0, MAX_STDIO_BYTES).toString('utf8')}\\n[truncated to ${MAX_STDIO_BYTES} bytes]`\n}\n\nexport function runApeShell(cmd: string, timeoutMs: number = DEFAULT_TIMEOUT_MS): Promise<ApeShellResult> {\n return new Promise<ApeShellResult>((resolveResult) => {\n const child = spawn(BIN, ['-c', cmd], {\n env: { ...process.env, APE_WAIT: '1' },\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n let stdout = ''\n let stderr = ''\n let timedOut = false\n let spawnError: Error | null = null\n\n child.stdout!.on('data', (chunk: Buffer) => { stdout += chunk.toString('utf8') })\n child.stderr!.on('data', (chunk: Buffer) => { stderr += chunk.toString('utf8') })\n child.on('error', (err) => { spawnError = err as Error })\n\n const timer = setTimeout(() => {\n timedOut = true\n child.kill('SIGTERM')\n // Force-kill if SIGTERM doesn't take in 5s — happens when the\n // child is wedged waiting on an upstream grant approval.\n setTimeout(() => {\n try { child.kill('SIGKILL') }\n catch { /* already dead */ }\n }, 5000)\n }, timeoutMs)\n\n child.on('close', (code) => {\n clearTimeout(timer)\n if (spawnError) {\n resolveResult({\n stdout: '',\n stderr: '',\n exit_code: -1,\n error: spawnError.message,\n hint: `Could not exec '${BIN}'. The agent host needs @openape/apes installed globally so ape-shell is on PATH.`,\n })\n return\n }\n resolveResult({\n stdout: capStdio(stdout),\n stderr: capStdio(stderr),\n exit_code: code ?? -1,\n ...(timedOut ? { timed_out: true } : {}),\n })\n })\n })\n}\n\nexport const DEFAULTS = { DEFAULT_TIMEOUT_MS }\n","import type { ToolDefinition } from './index'\nimport { DEFAULTS, runApeShell } from './ape-shell-exec'\n\nexport const bashTools: ToolDefinition[] = [\n {\n name: 'bash',\n description:\n 'Run a shell command on the agent host. Every invocation goes through the OpenApe DDISA grant cycle — auto-approved if the owner has a matching YOLO scope, otherwise the owner gets a push notification to approve. Runs as the agent\\'s macOS user, so file/network access is limited to what that user can see. Returns stdout, stderr, and exit code. For repeated command patterns ask the owner to set up a YOLO scope so approvals don\\'t pile up.',\n parameters: {\n type: 'object',\n properties: {\n cmd: {\n type: 'string',\n description: 'Shell command to run, e.g. `ls -la ~/Documents`, `git status`, `curl -fsSL https://example.com`. The whole string is passed to `bash -c`; quote internally as needed.',\n },\n timeout_ms: {\n type: 'number',\n description: 'Wall-clock cap for the whole approval-and-run cycle in milliseconds. Default 300000 (5 min). Approval waits count against this budget.',\n },\n },\n required: ['cmd'],\n },\n execute: async (args: unknown) => {\n const a = args as { cmd?: unknown, timeout_ms?: unknown }\n if (typeof a.cmd !== 'string' || a.cmd.trim() === '') {\n throw new Error('cmd must be a non-empty string')\n }\n const timeout = typeof a.timeout_ms === 'number' && a.timeout_ms > 0\n ? a.timeout_ms\n : DEFAULTS.DEFAULT_TIMEOUT_MS\n return await runApeShell(a.cmd, timeout)\n },\n },\n]\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, normalize, resolve } from 'node:path'\nimport type { ToolDefinition } from './index'\n\nconst MAX_BYTES = 1024 * 1024\n\n// All file ops are jailed inside the agent's $HOME. Path traversal\n// (`..`) is blocked by resolving the requested path against the home\n// dir and asserting the resolved path is still inside it.\nfunction jailPath(input: unknown): string {\n if (typeof input !== 'string' || input === '') {\n throw new Error('path must be a non-empty string')\n }\n const home = homedir()\n // Treat input as relative to home unless it starts with $HOME.\n const candidate = input.startsWith('~/')\n ? resolve(home, input.slice(2))\n : input.startsWith('/')\n ? normalize(input)\n : resolve(home, input)\n if (candidate !== home && !candidate.startsWith(`${home}/`)) {\n throw new Error(`path \"${input}\" resolves outside the agent's home`)\n }\n return candidate\n}\n\nexport const fileTools: ToolDefinition[] = [\n {\n name: 'file.read',\n description: 'Read a UTF-8 file from the agent\\'s home directory ($HOME). Capped at 1MB. Path traversal blocked.',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Path relative to $HOME (or absolute under $HOME). `..` segments are rejected.' },\n },\n required: ['path'],\n },\n execute: async (args: unknown) => {\n const a = args as { path: string }\n const p = jailPath(a.path)\n const content = readFileSync(p, 'utf8')\n if (Buffer.byteLength(content, 'utf8') > MAX_BYTES) {\n return { path: p, truncated: true, content: content.slice(0, MAX_BYTES) }\n }\n return { path: p, truncated: false, content }\n },\n },\n {\n name: 'file.write',\n description: 'Write a UTF-8 file under the agent\\'s home directory. Creates parent dirs as needed. 1MB max.',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Path relative to $HOME (or absolute under $HOME).' },\n content: { type: 'string', description: 'File body. Existing files are overwritten.' },\n },\n required: ['path', 'content'],\n },\n execute: async (args: unknown) => {\n const a = args as { path: string, content: string }\n if (typeof a.content !== 'string') throw new Error('content must be a string')\n if (Buffer.byteLength(a.content, 'utf8') > MAX_BYTES) {\n throw new Error(`content exceeds ${MAX_BYTES} byte cap`)\n }\n const p = jailPath(a.path)\n mkdirSync(dirname(p), { recursive: true })\n writeFileSync(p, a.content, { encoding: 'utf8' })\n return { path: p, bytes: Buffer.byteLength(a.content, 'utf8') }\n },\n },\n {\n name: 'file.edit',\n description: 'Replace an exact substring in a file under the agent\\'s home directory. Prefer this over file.write for edits — it touches only the changed region instead of rewriting the whole file. `old_string` must appear exactly once unless `replace_all` is true. Path traversal blocked, 1MB max.',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Path relative to $HOME (or absolute under $HOME).' },\n old_string: { type: 'string', description: 'Exact text to replace. Include enough surrounding context to be unique unless replace_all is set.' },\n new_string: { type: 'string', description: 'Replacement text. Must differ from old_string.' },\n replace_all: { type: 'boolean', description: 'Replace every occurrence instead of requiring a unique match. Default false.' },\n },\n required: ['path', 'old_string', 'new_string'],\n },\n execute: async (args: unknown) => {\n const a = args as { path?: unknown, old_string?: unknown, new_string?: unknown, replace_all?: unknown }\n if (typeof a.old_string !== 'string' || a.old_string === '') {\n throw new Error('old_string must be a non-empty string')\n }\n if (typeof a.new_string !== 'string') {\n throw new TypeError('new_string must be a string')\n }\n if (a.old_string === a.new_string) {\n throw new Error('old_string and new_string are identical — nothing to change')\n }\n const replaceAll = a.replace_all === true\n const p = jailPath(a.path)\n const before = readFileSync(p, 'utf8')\n\n const occurrences = before.split(a.old_string).length - 1\n if (occurrences === 0) {\n throw new Error('old_string not found in file')\n }\n if (occurrences > 1 && !replaceAll) {\n throw new Error(`old_string occurs ${occurrences} times — pass replace_all:true or add surrounding context to make it unique`)\n }\n\n const after = replaceAll\n ? before.split(a.old_string).join(a.new_string)\n : before.replace(a.old_string, a.new_string)\n\n if (Buffer.byteLength(after, 'utf8') > MAX_BYTES) {\n throw new Error(`result exceeds ${MAX_BYTES} byte cap`)\n }\n writeFileSync(p, after, { encoding: 'utf8' })\n return { path: p, replacements: replaceAll ? occurrences : 1 }\n },\n },\n]\n\nexport const _internal = { jailPath }\n","// Forge abstraction (M3): provider-agnostic PR/issue operations.\n//\n// Forges are NOT a closed enum baked into this library — that would lock\n// out anyone on Bitbucket / GitLab / Gitea / a self-hosted forge. They\n// are an open ADAPTER REGISTRY: GitHub (`gh`) and Azure DevOps (`az`)\n// ship built-in; anyone can `registerForge()` another (or load one from\n// recipe config). The actual CLIs are already shaped, so an adapter is\n// just \"how to recognise the remote + how to build the argv\" — the gated\n// ape-shell path executes it, no new gating machinery.\n//\n// Command-builders are pure (unit-tested). Free-text inputs (PR title/\n// body) are shell-escaped via `shq`; structured inputs (branch, pr id)\n// are charset-validated.\n\n// A forge id — 'github' / 'azure' built-in, or any registered adapter.\nexport type Forge = string\n\nconst BRANCH_RE = /^[\\w./-]{1,200}$/\nconst ID_RE = /^\\d{1,12}$/\n\n// POSIX-safe single-quote: wrap in '...' and replace any embedded\n// single quote with '\\'' . Makes arbitrary free text safe to pass\n// through `bash -c`.\nexport function shq(s: string): string {\n return `'${String(s).replace(/'/g, '\\'\\\\\\'\\'')}'`\n}\n\nexport function assertBranch(v: unknown): string {\n if (typeof v !== 'string' || !BRANCH_RE.test(v)) {\n throw new Error('branch must match ^[A-Za-z0-9._/-]{1,200}$')\n }\n return v\n}\n\nexport function assertId(v: unknown): string {\n if (typeof v !== 'string' && typeof v !== 'number') throw new Error('id required')\n const s = String(v)\n if (!ID_RE.test(s)) throw new Error('id must be a number')\n return s\n}\n\nexport interface PrCreateInput {\n forge: Forge\n title: string\n body: string\n head: string // source branch\n base?: string // target branch (default: repo default)\n}\n\nexport interface PrMergeInput {\n forge: Forge\n ref: string | number // GitHub: PR number or branch; others: PR/MR id\n auto?: boolean // arm \"merge when checks pass\" instead of immediate merge\n // Merge strategy is REPO policy, not ours. Only force squash when the\n // caller/recipe explicitly asks (squash:true); otherwise we add no\n // strategy flag and the forge/repo default applies.\n squash?: boolean\n deleteBranch?: boolean\n}\n\n// One forge's command vocabulary. Add a new forge by implementing this\n// and calling registerForge(). `matchesRemote` decides auto-detection.\nexport interface ForgeAdapter {\n id: string\n matchesRemote: (remoteUrl: string) => boolean\n prCreate: (input: PrCreateInput) => string\n prMerge: (input: PrMergeInput) => string\n prStatus: (ref: string | number) => string\n // `repo` is the target remote (URL or owner/name). Required for issue\n // lookups that run BEFORE the repo is cloned (e.g. the poll's\n // fetchIssue), where the CWD is not the repo — without it `gh issue\n // view` errors \"not a git repository\" / resolves the wrong repo.\n issueGet: (ref: string | number, repo?: string) => string\n}\n\n// --- Built-in adapters ---\n\nconst githubAdapter: ForgeAdapter = {\n id: 'github',\n matchesRemote: url => /github\\.com/i.test(url),\n prCreate: (i) => {\n const head = assertBranch(i.head)\n const parts = ['gh', 'pr', 'create', '--title', shq(i.title), '--body', shq(i.body), '--head', shq(head)]\n if (i.base !== undefined) parts.push('--base', shq(assertBranch(i.base)))\n return parts.join(' ')\n },\n prMerge: (i) => {\n const ref = String(i.ref)\n const refTok = ID_RE.test(ref) ? ref : assertBranch(ref)\n const parts = ['gh', 'pr', 'merge', shq(refTok)]\n if (i.squash === true) parts.push('--squash')\n if (i.auto) parts.push('--auto')\n if (i.deleteBranch) parts.push('--delete-branch')\n return parts.join(' ')\n },\n prStatus: (ref) => {\n const r = String(ref)\n const refTok = ID_RE.test(r) ? r : assertBranch(r)\n return `gh pr view ${shq(refTok)} --json state,mergeStateStatus,statusCheckRollup,reviewDecision`\n },\n issueGet: (ref, repo) => `gh issue view ${assertId(ref)}${repo ? ` --repo ${shq(repo)}` : ''} --json number,title,body,labels`,\n}\n\nconst azureAdapter: ForgeAdapter = {\n id: 'azure',\n matchesRemote: url => /dev\\.azure\\.com|visualstudio\\.com/i.test(url),\n prCreate: (i) => {\n const head = assertBranch(i.head)\n const parts = ['az', 'repos', 'pr', 'create', '--title', shq(i.title), '--description', shq(i.body), '--source-branch', shq(head)]\n if (i.base !== undefined) parts.push('--target-branch', shq(assertBranch(i.base)))\n return parts.join(' ')\n },\n prMerge: (i) => {\n const id = assertId(i.ref)\n const parts = ['az', 'repos', 'pr', 'update', '--id', id]\n if (i.auto) parts.push('--auto-complete', 'true')\n else parts.push('--status', 'completed')\n if (i.squash === true) parts.push('--merge-commit-message-style', 'squash')\n if (i.deleteBranch) parts.push('--delete-source-branch', 'true')\n return parts.join(' ')\n },\n prStatus: ref => `az repos pr show --id ${assertId(ref)}`,\n // Azure work items are org/project-scoped, not repo-scoped, so `repo`\n // doesn't apply here — the caller's `az` config (defaults.organization/\n // project) resolves it.\n issueGet: (ref, _repo) => `az boards work-item show --id ${assertId(ref)}`,\n}\n\n// --- Registry ---\n\nconst registry = new Map<string, ForgeAdapter>([\n [githubAdapter.id, githubAdapter],\n [azureAdapter.id, azureAdapter],\n])\n\n// Register (or override) a forge adapter — e.g. GitLab (`glab`), Gitea\n// (`tea`), Bitbucket, or a self-hosted forge. Recipes can ship adapters\n// so a team on any forge can use the coding agent.\nexport function registerForge(adapter: ForgeAdapter): void {\n registry.set(adapter.id, adapter)\n}\n\nexport function listForges(): string[] {\n return [...registry.keys()]\n}\n\nexport function getForge(id: string): ForgeAdapter {\n const a = registry.get(id)\n if (!a) {\n throw new Error(`unknown forge '${id}'. Registered: ${listForges().join(', ')}. Add one with registerForge().`)\n }\n return a\n}\n\n// Detect the forge from a git remote URL by asking each registered\n// adapter. Throws a helpful error (not a hard 2-provider rejection) so\n// the path to support a new forge is \"register an adapter\", not \"patch\n// this library\".\nexport function detectForge(remoteUrl: unknown): Forge {\n if (typeof remoteUrl !== 'string' || remoteUrl === '') {\n throw new Error('remote URL required to detect forge')\n }\n for (const a of registry.values()) {\n if (a.matchesRemote(remoteUrl)) return a.id\n }\n throw new Error(`no forge adapter matches remote: ${remoteUrl}. Registered: ${listForges().join(', ')}. Register one with registerForge() (e.g. GitLab/Bitbucket/Gitea).`)\n}\n\n// --- Public command builders (delegate to the resolved adapter) ---\n\nexport function buildPrCreate(input: PrCreateInput): string {\n return getForge(input.forge).prCreate(input)\n}\n\nexport function buildPrMerge(input: PrMergeInput): string {\n return getForge(input.forge).prMerge(input)\n}\n\nexport function buildPrStatus(forge: Forge, ref: string | number): string {\n return getForge(forge).prStatus(ref)\n}\n\nexport function buildIssueGet(forge: Forge, ref: string | number, repo?: string): string {\n return getForge(forge).issueGet(ref, repo)\n}\n\nexport const _internal = { shq, assertBranch, assertId, githubAdapter, azureAdapter, registry }\n","import type { ToolDefinition } from './index'\nimport type { Forge } from '../coding/forge'\nimport { runApeShell } from './ape-shell-exec'\nimport { buildIssueGet, buildPrCreate, buildPrMerge, buildPrStatus, detectForge } from '../coding/forge'\n\n// Resolve the forge from an explicit param or a remote URL. The\n// recipe/orchestration usually passes `forge` directly; `remote` is the\n// auto-detect fallback (git remote get-url origin). Any registered\n// adapter id is accepted (github/azure built-in, plus anything added via\n// registerForge) — getForge() validates downstream.\nfunction resolveForge(a: { forge?: unknown, remote?: unknown }): Forge {\n if (typeof a.forge === 'string' && a.forge !== '') return a.forge\n if (typeof a.remote === 'string') return detectForge(a.remote)\n throw new Error('provide a forge id (e.g. github, azure, or a registered adapter) or a remote URL to detect it')\n}\n\nconst forgeParam = { type: 'string', description: 'Target forge id (github, azure, or a registered adapter). Omit to auto-detect from `remote`.' }\nconst remoteParam = { type: 'string', description: 'git remote URL — used to auto-detect the forge when `forge` is omitted.' }\n\nexport const forgeTools: ToolDefinition[] = [\n {\n name: 'forge.pr.create',\n description: 'Open a pull request on GitHub (gh) or Azure DevOps (az). Gated via the DDISA grant cycle. Provider chosen by `forge` or auto-detected from `remote`.',\n parameters: {\n type: 'object',\n properties: {\n forge: forgeParam,\n remote: remoteParam,\n title: { type: 'string', description: 'PR title.' },\n body: { type: 'string', description: 'PR description / body.' },\n head: { type: 'string', description: 'Source branch.' },\n base: { type: 'string', description: 'Target branch. Omit for the repo default.' },\n },\n required: ['title', 'body', 'head'],\n },\n execute: async (args: unknown) => {\n const a = args as { forge?: unknown, remote?: unknown, title: string, body: string, head: string, base?: string }\n const cmd = buildPrCreate({ forge: resolveForge(a), title: a.title, body: a.body, head: a.head, base: a.base })\n return await runApeShell(cmd)\n },\n },\n {\n name: 'forge.pr.merge',\n description: 'Merge a PR — or with auto=true, arm \"merge when checks pass\" (gh --auto / az auto-complete) so the platform merges only on green CI. Gated. Never bypasses required checks (branch protection is the server-side gate).',\n parameters: {\n type: 'object',\n properties: {\n forge: forgeParam,\n remote: remoteParam,\n ref: { type: 'string', description: 'GitHub: PR number or branch. Azure: PR id.' },\n auto: { type: 'boolean', description: 'Arm merge-when-green instead of immediate merge. Recommended.' },\n squash: { type: 'boolean', description: 'Squash-merge. Default true.' },\n delete_branch: { type: 'boolean', description: 'Delete the source branch after merge.' },\n },\n required: ['ref'],\n },\n execute: async (args: unknown) => {\n const a = args as { forge?: unknown, remote?: unknown, ref: string, auto?: boolean, squash?: boolean, delete_branch?: boolean }\n const cmd = buildPrMerge({ forge: resolveForge(a), ref: a.ref, auto: a.auto, squash: a.squash, deleteBranch: a.delete_branch })\n return await runApeShell(cmd)\n },\n },\n {\n name: 'forge.pr.status',\n description: 'Fetch a PR\\'s state + checks + review decision. Gated (read).',\n parameters: {\n type: 'object',\n properties: { forge: forgeParam, remote: remoteParam, ref: { type: 'string', description: 'PR number/branch (GitHub) or id (Azure).' } },\n required: ['ref'],\n },\n execute: async (args: unknown) => {\n const a = args as { forge?: unknown, remote?: unknown, ref: string }\n return await runApeShell(buildPrStatus(resolveForge(a), a.ref))\n },\n },\n {\n name: 'forge.issue.get',\n description: 'Fetch an issue (GitHub) or work-item (Azure) — title, body, labels. Gated (read). Use to turn an assigned task into a coding run.',\n parameters: {\n type: 'object',\n properties: { forge: forgeParam, remote: remoteParam, ref: { type: 'string', description: 'Issue number (GitHub) or work-item id (Azure).' } },\n required: ['ref'],\n },\n execute: async (args: unknown) => {\n const a = args as { forge?: unknown, remote?: unknown, ref: string }\n // Pass the remote so the lookup works even when the CWD isn't the\n // target repo (e.g. before a clone).\n const repo = typeof a.remote === 'string' ? a.remote : undefined\n return await runApeShell(buildIssueGet(resolveForge(a), a.ref, repo))\n },\n },\n]\n","import { homedir } from 'node:os'\nimport { resolve } from 'node:path'\nimport process from 'node:process'\nimport type { ToolDefinition } from './index'\nimport { runApeShell } from './ape-shell-exec'\n\n// Worktree + clone roots. Default to ~/work and ~/repos but are\n// configurable per deployment via OPENAPE_CODING_WORK_DIR /\n// OPENAPE_CODING_REPOS_DIR (set by the recipe/nest). Must stay under\n// $HOME — the OS-confinement boundary the whole coding sandbox relies on.\nfunction jailedRoot(envVar: string, fallbackName: string): string {\n const home = homedir()\n const raw = process.env[envVar]\n const dir = raw ? resolve(raw) : resolve(home, fallbackName)\n if (dir !== home && !dir.startsWith(`${home}/`)) {\n throw new Error(`${envVar} (${dir}) must resolve inside the agent's home`)\n }\n return dir\n}\n\nfunction workRoot(): string {\n return jailedRoot('OPENAPE_CODING_WORK_DIR', 'work')\n}\n\nfunction reposRoot(): string {\n return jailedRoot('OPENAPE_CODING_REPOS_DIR', 'repos')\n}\n\n// Worktree lifecycle for the coding agent. All git invocations go\n// through the gated ape-shell path (runApeShell) — `git worktree add`\n// is a sandbox-leaving op, so it hits the DDISA grant / git-shape\n// matcher exactly like a terminal `apes run -- git …`.\n//\n// Layout (all under the agent's $HOME, OS-confined):\n// ~/repos/<base> cached bare-ish clone, one per repo\n// ~/work/<task_id> the per-task worktree the agent edits in\n//\n// Inputs are strictly validated + single-quoted before reaching the\n// shell. The charset rules reject quotes/metacharacters outright, so\n// the single-quoting can't be broken out of.\n\nconst TASK_ID_RE = /^[\\w.-]{1,64}$/\nconst BRANCH_RE = /^[\\w./-]{1,128}$/\n// Either an https/git remote URL, or a path (validated as jailed below).\nconst URL_RE = /^(?:https:\\/\\/|git@)[\\w@:/.-]{3,256}$/\n\nfunction assertTaskId(v: unknown): string {\n if (typeof v !== 'string' || !TASK_ID_RE.test(v)) {\n throw new Error('task_id must match ^[a-zA-Z0-9._-]{1,64}$')\n }\n return v\n}\n\nfunction assertBranch(v: unknown): string {\n if (typeof v !== 'string' || !BRANCH_RE.test(v)) {\n throw new Error('branch must match ^[A-Za-z0-9._/-]{1,128}$')\n }\n return v\n}\n\n// Resolve a repo reference to a base-clone dir + a clonable source.\n// URL → clone into ~/repos/<derived>. Local path → must be a git repo\n// already inside $HOME (jailed); used in place.\nexport function resolveRepo(repo: unknown): { source: string; baseDir: string; isUrl: boolean } {\n if (typeof repo !== 'string' || repo === '') {\n throw new Error('repo must be a non-empty string (URL or path under $HOME)')\n }\n const home = homedir()\n if (URL_RE.test(repo)) {\n const tail = repo.replace(/\\.git$/, '').replace(/[/:]+$/, '')\n const parts = tail.split(/[/:]/).filter(Boolean).slice(-2)\n const base = parts.join('-').replace(/[^\\w.-]/g, '')\n if (!base) throw new Error('could not derive a clone name from repo URL')\n return { source: repo, baseDir: resolve(reposRoot(), base), isUrl: true }\n }\n // Local path — jail under $HOME.\n const candidate = repo.startsWith('~/') ? resolve(home, repo.slice(2)) : resolve(home, repo)\n if (candidate !== home && !candidate.startsWith(`${home}/`)) {\n throw new Error(`repo path \"${repo}\" resolves outside the agent's home`)\n }\n return { source: candidate, baseDir: candidate, isUrl: false }\n}\n\nexport function worktreePathFor(taskId: string): string {\n return resolve(workRoot(), assertTaskId(taskId))\n}\n\nconst q = (s: string): string => `'${s}'` // safe: callers validate charset first\n\nexport function buildCreateCommand(repo: unknown, taskId: string, branch: string): string {\n const id = assertTaskId(taskId)\n const br = assertBranch(branch)\n const { source, baseDir, isUrl } = resolveRepo(repo)\n const wt = worktreePathFor(id)\n const clone = isUrl\n ? `if [ ! -d ${q(baseDir)}/.git ]; then git clone ${q(source)} ${q(baseDir)}; fi`\n : `test -d ${q(baseDir)}/.git`\n // A polling agent re-attempts the same issue (same task id → same branch\n // + worktree path) on every tick, so creation must be idempotent: tear\n // down any leftover worktree from a prior run, then add fresh with `-B`\n // (create-or-reset the branch). The cleanup group never fails the chain.\n const reset = [\n `git -C ${q(baseDir)} worktree remove --force ${q(wt)} 2>/dev/null || true`,\n `git -C ${q(baseDir)} worktree prune 2>/dev/null || true`,\n `rm -rf ${q(wt)} 2>/dev/null || true`,\n ].join('; ')\n // Non-interactive GitHub auth for the clone (shared by all its worktrees).\n // A spawned agent's git defaults to credential.helper=osxkeychain, which\n // hangs headless (no GUI) — so ANY `git push` the LLM runs itself would\n // block. Point credential.helper at $GH_TOKEN (read from the gated shell's\n // env at push time, never stored) so every git operation authenticates\n // without a prompt. GitHub-only; other forges keep their default helper.\n // First RESET the helper list (the empty value clears the inherited\n // osxkeychain helper — otherwise git still calls it on `store` and hangs\n // headless), then add ours that supplies $GH_TOKEN from the env.\n const ghAuth = /github\\.com/i.test(source)\n ? `git -C ${q(baseDir)} config credential.helper '' && git -C ${q(baseDir)} config --add credential.helper '!f() { echo username=x-access-token; echo \"password=$GH_TOKEN\"; }; f'`\n : 'true'\n return [\n `mkdir -p ${q(reposRoot())} ${q(workRoot())}`,\n clone,\n ghAuth,\n `git -C ${q(baseDir)} fetch --quiet || true`,\n `{ ${reset}; }`,\n `git -C ${q(baseDir)} worktree add -B ${q(br)} ${q(wt)}`,\n `echo ${q(wt)}`,\n ].join(' && ')\n}\n\nexport function buildRemoveCommand(repo: unknown, taskId: string): string {\n const id = assertTaskId(taskId)\n const { baseDir } = resolveRepo(repo)\n const wt = worktreePathFor(id)\n return `git -C ${q(baseDir)} worktree remove --force ${q(wt)} && git -C ${q(baseDir)} worktree prune`\n}\n\nexport function buildListCommand(): string {\n return `ls -1 ${q(workRoot())} 2>/dev/null || true`\n}\n\nexport const gitWorktreeTools: ToolDefinition[] = [\n {\n name: 'git.worktree',\n description: 'Manage isolated git worktrees for coding tasks. action=create clones the repo (cached under ~/repos) and adds a fresh worktree under ~/work/<task_id> on a new branch. action=remove tears it down. action=list shows current task worktrees. Git operations go through the DDISA grant cycle (git-shape).',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['create', 'remove', 'list'], description: 'create | remove | list' },\n repo: { type: 'string', description: 'For create/remove: git remote URL (https/git@) or a path under $HOME to an existing clone.' },\n task_id: { type: 'string', description: 'For create/remove: identifier for the worktree, ^[a-zA-Z0-9._-]{1,64}$. The worktree lands at ~/work/<task_id>.' },\n branch: { type: 'string', description: 'For create: new branch name, ^[A-Za-z0-9._/-]{1,128}$.' },\n },\n required: ['action'],\n },\n execute: async (args: unknown) => {\n const a = args as { action?: unknown, repo?: unknown, task_id?: unknown, branch?: unknown }\n let cmd: string\n if (a.action === 'create') {\n if (typeof a.branch !== 'string') throw new Error('branch is required for action=create')\n cmd = buildCreateCommand(a.repo, assertTaskId(a.task_id), a.branch)\n }\n else if (a.action === 'remove') {\n cmd = buildRemoveCommand(a.repo, assertTaskId(a.task_id))\n }\n else if (a.action === 'list') {\n cmd = buildListCommand()\n }\n else {\n throw new Error('action must be one of: create, remove, list')\n }\n const res = await runApeShell(cmd)\n return {\n action: a.action,\n ...(a.action !== 'list' ? { worktree: worktreePathFor(assertTaskId(a.task_id)) } : {}),\n stdout: res.stdout,\n stderr: res.stderr,\n exit_code: res.exit_code,\n ...(res.error ? { error: res.error, hint: res.hint } : {}),\n }\n },\n },\n]\n\nexport const _internal = { resolveRepo, worktreePathFor, buildCreateCommand, buildRemoveCommand, buildListCommand, assertTaskId, assertBranch }\n","import type { ToolDefinition } from './index'\n\nconst MAX_BYTES = 1024 * 1024\n// Headers we never let the model set: hop-by-hop ones, host (we\n// don't want to spoof another origin) and authorization (the model\n// would otherwise be a step away from \"fetch tasks.openape.ai with my\n// own JWT\" — that's a manual escalation path, not a tool the agent\n// gets out of the box).\nconst FORBIDDEN_HEADERS = new Set([\n 'host',\n 'authorization',\n 'cookie',\n 'connection',\n 'transfer-encoding',\n 'upgrade',\n 'proxy-authorization',\n])\n\nfunction sanitizeHeaders(input: unknown): Record<string, string> {\n if (!input || typeof input !== 'object') return {}\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(input as Record<string, unknown>)) {\n if (typeof v !== 'string') continue\n if (FORBIDDEN_HEADERS.has(k.toLowerCase())) continue\n out[k] = v\n }\n return out\n}\n\nasync function readCappedBody(res: Response): Promise<string> {\n const buf = new Uint8Array(MAX_BYTES + 1)\n let written = 0\n const reader = res.body?.getReader()\n if (!reader) return await res.text()\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n if (written + value.byteLength > MAX_BYTES) {\n buf.set(value.subarray(0, MAX_BYTES - written), written)\n written = MAX_BYTES\n try { await reader.cancel() }\n catch { /* ignore */ }\n break\n }\n buf.set(value, written)\n written += value.byteLength\n }\n return new TextDecoder().decode(buf.subarray(0, written))\n}\n\nexport const httpTools: ToolDefinition[] = [\n {\n name: 'http.get',\n description: 'GET an HTTPS URL and return the response body (capped at 1MB). Useful for reading public APIs, RSS feeds, web pages.',\n parameters: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'Absolute HTTPS URL.' },\n headers: { type: 'object', description: 'Optional headers (Host, Authorization, Cookie are stripped).' },\n },\n required: ['url'],\n },\n execute: async (args: unknown) => {\n const a = args as { url: string, headers?: unknown }\n if (typeof a.url !== 'string' || !a.url.startsWith('http')) {\n throw new Error('url must be an http(s) URL')\n }\n const res = await fetch(a.url, { method: 'GET', headers: sanitizeHeaders(a.headers) })\n const body = await readCappedBody(res)\n return { status: res.status, headers: Object.fromEntries(res.headers), body }\n },\n },\n {\n name: 'http.post',\n description: 'POST JSON to an HTTPS URL and return the response body (capped at 1MB).',\n parameters: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'Absolute HTTPS URL.' },\n body: { description: 'JSON-serialisable payload.' },\n headers: { type: 'object', description: 'Optional headers (Host, Authorization, Cookie are stripped).' },\n },\n required: ['url', 'body'],\n },\n execute: async (args: unknown) => {\n const a = args as { url: string, body: unknown, headers?: unknown }\n if (typeof a.url !== 'string' || !a.url.startsWith('http')) {\n throw new Error('url must be an http(s) URL')\n }\n const res = await fetch(a.url, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...sanitizeHeaders(a.headers) },\n body: JSON.stringify(a.body),\n })\n const body = await readCappedBody(res)\n return { status: res.status, headers: Object.fromEntries(res.headers), body }\n },\n },\n]\n","import { execFileSync } from 'node:child_process'\nimport type { ToolDefinition } from './index'\n\n// Shell out to o365-cli for read-only mail access. Same auth model\n// as ape-tasks: the agent's macOS user has o365-cli installed +\n// authenticated, agent runs as that user.\n\nfunction o365(args: string[]): string {\n try {\n return execFileSync('o365-cli', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] })\n }\n catch (err) {\n const e = err as { stderr?: Buffer | string, code?: string, message?: string }\n if (e.code === 'ENOENT') {\n throw new Error('o365-cli is not installed on this agent host')\n }\n const stderr = typeof e.stderr === 'string' ? e.stderr : e.stderr?.toString('utf8')\n throw new Error(`o365-cli failed: ${stderr ?? e.message ?? err}`)\n }\n}\n\nexport const mailTools: ToolDefinition[] = [\n {\n name: 'mail.list',\n description: 'List recent inbox messages via o365-cli. Optional `unread_only` and `limit`.',\n parameters: {\n type: 'object',\n properties: {\n limit: { type: 'integer', minimum: 1, maximum: 100, default: 20 },\n unread_only: { type: 'boolean', default: false },\n },\n required: [],\n },\n execute: async (args: unknown) => {\n const a = (args as { limit?: number, unread_only?: boolean }) ?? {}\n const argv = ['mail', 'list', '--json', '--limit', String(a.limit ?? 20)]\n if (a.unread_only) argv.push('--unread')\n const out = o365(argv)\n try { return JSON.parse(out) }\n catch { return { raw: out } }\n },\n },\n {\n name: 'mail.search',\n description: 'Search the inbox via o365-cli using a free-form query string.',\n parameters: {\n type: 'object',\n properties: {\n q: { type: 'string' },\n limit: { type: 'integer', minimum: 1, maximum: 100, default: 20 },\n },\n required: ['q'],\n },\n execute: async (args: unknown) => {\n const a = args as { q: string, limit?: number }\n if (typeof a.q !== 'string' || a.q.length === 0) throw new Error('q is required')\n const argv = ['mail', 'search', a.q, '--json', '--limit', String(a.limit ?? 20)]\n const out = o365(argv)\n try { return JSON.parse(out) }\n catch { return { raw: out } }\n },\n },\n]\n","import { execFileSync } from 'node:child_process'\nimport type { ToolDefinition } from './index'\n\n// Shell out to the user's `ape-tasks` CLI. The agent's macOS user\n// has its own ~/.config/apes/auth.json, so the CLI talks to\n// tasks.openape.ai as the agent's owner via the agent JWT (which\n// carries the owner-domain). For v1 we don't require a separate\n// agent identity for tasks — the tasks CLI authenticates with the\n// same auth.json the runtime uses.\n\nfunction ape(args: string[]): string {\n try {\n return execFileSync('ape-tasks', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] })\n }\n catch (err) {\n const e = err as { stderr?: Buffer | string, message?: string }\n const stderr = typeof e.stderr === 'string' ? e.stderr : e.stderr?.toString('utf8')\n throw new Error(`ape-tasks failed: ${stderr ?? e.message ?? err}`)\n }\n}\n\nexport const tasksTools: ToolDefinition[] = [\n {\n name: 'tasks.list',\n description: 'List the owner\\'s open ape-tasks (the user\\'s personal task list at tasks.openape.ai).',\n parameters: {\n type: 'object',\n properties: {\n status: { type: 'string', enum: ['open', 'doing', 'done', 'archived'] },\n team_id: { type: 'string' },\n },\n required: [],\n },\n execute: async (args: unknown) => {\n const a = (args as { status?: string, team_id?: string }) ?? {}\n const argv = ['list', '--json']\n if (a.status) argv.push('--status', a.status)\n if (a.team_id) argv.push('--team', a.team_id)\n const out = ape(argv)\n try { return JSON.parse(out) }\n catch { return { raw: out } }\n },\n },\n {\n name: 'tasks.create',\n description: 'Create a new ape-task on the owner\\'s task list at tasks.openape.ai.',\n parameters: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n notes: { type: 'string' },\n priority: { type: 'string', enum: ['low', 'med', 'high'] },\n due_at: { type: 'string', description: 'ISO date or +Nh/+Nd shorthand.' },\n },\n required: ['title'],\n },\n execute: async (args: unknown) => {\n const a = args as { title: string, notes?: string, priority?: string, due_at?: string }\n const argv = ['new', '--title', a.title, '--json']\n if (a.notes) argv.push('--notes', a.notes)\n if (a.priority) argv.push('--priority', a.priority)\n if (a.due_at) argv.push('--due', a.due_at)\n const out = ape(argv)\n try { return JSON.parse(out) }\n catch { return { raw: out } }\n },\n },\n]\n","import type { ToolDefinition } from './index'\n\nexport const timeTools: ToolDefinition[] = [\n {\n name: 'time.now',\n description: 'Returns the current UTC date and time as ISO 8601 plus epoch seconds. No inputs.',\n parameters: { type: 'object', properties: {}, required: [] },\n execute: async () => {\n const now = new Date()\n return {\n iso: now.toISOString(),\n epoch_seconds: Math.floor(now.getTime() / 1000),\n timezone_offset_minutes: -now.getTimezoneOffset(),\n }\n },\n },\n]\n","// Verification loop (M2). Runs the configured test/build command in a\n// worktree via the gated ape-shell path and reports pass/fail. This is\n// the local gate: the coding loop must NOT proceed to the PR/merge\n// phase on a non-zero exit. Branch protection is the second, server-\n// side gate.\n\nimport { runApeShell } from '../agent-tools/ape-shell-exec'\n\nexport interface VerifyResult {\n passed: boolean\n exit_code: number\n stdout: string\n stderr: string\n timed_out?: boolean\n}\n\nconst CWD_RE = /^[\\w./-]{1,256}$/\n\n// Run `command` in `cwd` (a worktree path). The command string is the\n// recipe-configured verify command (e.g. `pnpm test`). cwd is charset-\n// validated; both go through the gated path so the run is grant-scoped\n// exactly like a terminal invocation.\nexport async function runVerify(cwd: string, command: string, timeoutMs?: number): Promise<VerifyResult> {\n if (typeof cwd !== 'string' || !CWD_RE.test(cwd)) {\n throw new Error('cwd must match ^[A-Za-z0-9._/-]{1,256}$')\n }\n if (typeof command !== 'string' || command.trim() === '') {\n throw new Error('verify command must be a non-empty string')\n }\n // `cd <cwd> && <command>` — cwd validated above; command is the\n // operator-configured verify command (trusted recipe config, not\n // agent free-text).\n const res = await runApeShell(`cd '${cwd}' && ${command}`, timeoutMs)\n return {\n passed: res.exit_code === 0,\n exit_code: res.exit_code,\n stdout: res.stdout,\n stderr: res.stderr,\n ...(res.timed_out ? { timed_out: true } : {}),\n }\n}\n","import type { ToolDefinition } from './index'\nimport { runVerify } from '../coding/verify'\n\nexport const verifyTools: ToolDefinition[] = [\n {\n name: 'verify',\n description: 'Run the verification command (tests/build/lint) in a worktree and report pass/fail. The coding loop must NOT open or merge a PR when this fails. Runs through the DDISA grant cycle (same as bash). Returns { passed, exit_code, stdout, stderr }.',\n parameters: {\n type: 'object',\n properties: {\n cwd: { type: 'string', description: 'Worktree path to run in (e.g. ~/work/issue-42).' },\n command: { type: 'string', description: 'Verification command, e.g. `pnpm test` or `npm run build && npm test`.' },\n timeout_ms: { type: 'number', description: 'Wall-clock cap incl. approval wait. Default 300000.' },\n },\n required: ['cwd', 'command'],\n },\n execute: async (args: unknown) => {\n const a = args as { cwd?: unknown, command?: unknown, timeout_ms?: unknown }\n const timeout = typeof a.timeout_ms === 'number' && a.timeout_ms > 0 ? a.timeout_ms : undefined\n return await runVerify(a.cwd as string, a.command as string, timeout)\n },\n },\n]\n","// Built-in tool registry shipped with the apes binary. Each tool is\n// (a) an OpenAI tool-spec object (used as-is in the LiteLLM call's\n// `tools[]` parameter) and (b) an `execute` function called when the\n// model emits a `tool_calls` entry. Adding a new tool means\n// implementing it here AND adding an entry to\n// apps/openape-troop/server/tool-catalog.json so the SP validates\n// task specs against the same allowlist.\n//\n// The registry is keyed by string name (`time.now`, `http.get`, …).\n// `taskTools(spec.tools)` resolves a task's tool list to the slice of\n// the registry it can use. Unknown names abort the run before any\n// LLM call so the model can't invent a tool we haven't shipped.\n\nimport { bashTools } from './bash'\nimport { fileTools } from './file'\nimport { forgeTools } from './forge'\nimport { gitWorktreeTools } from './git-worktree'\nimport { httpTools } from './http'\nimport { mailTools } from './mail'\nimport { tasksTools } from './tasks'\nimport { timeTools } from './time'\nimport { verifyTools } from './verify'\n\nexport interface ToolDefinition {\n name: string\n description: string\n // OpenAI tool-spec shape: { type: 'object', properties: …, required: … }.\n // We don't constrain it further — the LLM's job to fill it in.\n parameters: Record<string, unknown>\n execute: (args: unknown) => Promise<unknown>\n}\n\nconst ALL_TOOLS: ToolDefinition[] = [\n ...timeTools,\n ...httpTools,\n ...fileTools,\n ...tasksTools,\n ...mailTools,\n ...bashTools,\n ...gitWorktreeTools,\n ...verifyTools,\n ...forgeTools,\n]\n\nexport const TOOLS: Record<string, ToolDefinition> = Object.fromEntries(\n ALL_TOOLS.map(t => [t.name, t]),\n)\n\n/**\n * Resolve a task spec's tool name list to ToolDefinitions. Throws on\n * unknown names — callers must surface that as a run-failure with a\n * clear \"unknown tool: foo\" final_message so the owner can see what\n * went wrong in the SP UI.\n */\nexport function taskTools(names: string[]): ToolDefinition[] {\n const out: ToolDefinition[] = []\n const missing: string[] = []\n for (const name of names) {\n const tool = TOOLS[name]\n if (!tool) missing.push(name)\n else out.push(tool)\n }\n if (missing.length > 0) {\n throw new Error(`unknown tool(s): ${missing.join(', ')}`)\n }\n return out\n}\n\n/**\n * Format the registry slice as the OpenAI `tools` param. Strips the\n * `execute` function — only the spec part goes to the LLM.\n *\n * Tool names get sent through `wireToolName()` because some upstreams\n * — notably ChatGPT's Responses API behind LiteLLM — enforce\n * `^[a-zA-Z0-9_-]+$` and reject our dotted catalog names like\n * `time.now`. Use `localToolName()` to map back when the model emits\n * a tool_call.\n */\nexport function asOpenAiTools(tools: ToolDefinition[]): { type: 'function', function: Omit<ToolDefinition, 'execute'> }[] {\n return tools.map(t => ({\n type: 'function' as const,\n function: { name: wireToolName(t.name), description: t.description, parameters: t.parameters },\n }))\n}\n\n/** Encode a local tool name (e.g. `time.now`) for the wire format. */\nexport function wireToolName(local: string): string {\n return local.replace(/\\./g, '_')\n}\n\n/**\n * Decode a tool name from the wire format back to its local form. The\n * encoding is `.` → `_`; we recover the original by looking for an\n * exact match in the catalog and only fall back to passing the name\n * through if no match is found (so unknown tool names still surface\n * as the obvious \"unknown tool\" error rather than silent rewrites).\n */\nexport function localToolName(wire: string): string {\n for (const t of Object.values(TOOLS)) {\n if (wireToolName(t.name) === wire) return t.name\n }\n return wire\n}\n","import { asOpenAiTools, localToolName, wireToolName } from './agent-tools'\nimport type { ToolDefinition } from './agent-tools'\n\n// Shared agent loop: send messages + tools to LiteLLM (OpenAI-\n// compatible chat-completions API), execute any tool_calls in the\n// response, append tool-result messages, loop until the model\n// returns a response with no tool_calls or we hit max_steps.\n//\n// Both `apes agents run` (cron) and `apes agents serve --rpc`\n// (chat-bridge subprocess) call into here so the LLM behaviour is\n// guaranteed identical between modes.\n\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant' | 'tool'\n content: string | null\n // Assistant message tool calls\n tool_calls?: Array<{\n id: string\n type: 'function'\n function: { name: string, arguments: string }\n }>\n // Tool message metadata\n tool_call_id?: string\n name?: string\n}\n\nexport interface RuntimeConfig {\n apiBase: string // LITELLM_BASE_URL (e.g. \"http://127.0.0.1:4000/v1\")\n apiKey: string // LITELLM_API_KEY (or LITELLM_MASTER_KEY)\n model: string\n}\n\nexport interface TraceEntry {\n step: number\n type: 'assistant' | 'tool_call' | 'tool_result' | 'tool_error'\n // Stripped down for trace: don't carry full bodies\n preview: string\n tool?: string\n}\n\nexport interface RunResult {\n status: 'ok' | 'error'\n finalMessage: string | null\n stepCount: number\n trace: TraceEntry[]\n}\n\nexport interface RunStreamHandlers {\n onTextDelta?: (delta: string) => void\n onToolCall?: (call: { name: string, args: unknown }) => void\n onToolResult?: (result: { name: string, result: unknown }) => void\n onToolError?: (err: { name: string, error: string }) => void\n onDone?: (result: RunResult) => void\n}\n\nexport interface RunOptions {\n config: RuntimeConfig\n systemPrompt: string\n userMessage: string\n tools: ToolDefinition[]\n maxSteps: number\n // Pre-existing message history for continued sessions (RPC mode).\n // The system prompt is always prepended, even if `history` is\n // non-empty — the SP-stored prompt is canonical. Defaults to []\n // (a fresh single-user-turn conversation).\n history?: ChatMessage[]\n handlers?: RunStreamHandlers\n // Test seam — replace fetch (we always use the global fetch in\n // production). Tests pass a mock that returns canned responses.\n fetchImpl?: typeof fetch\n}\n\ninterface OpenAIChoice {\n message: ChatMessage\n finish_reason?: string\n}\ninterface OpenAIChatResponse {\n choices: OpenAIChoice[]\n}\n\nfunction previewJson(value: unknown, max = 500): string {\n let s: string\n try { s = JSON.stringify(value) }\n catch { s = String(value) }\n return s.length > max ? `${s.slice(0, max)}…` : s\n}\n\nexport async function runLoop(opts: RunOptions): Promise<RunResult> {\n const fetchFn = opts.fetchImpl ?? fetch\n const trace: TraceEntry[] = []\n const messages: ChatMessage[] = [\n { role: 'system', content: opts.systemPrompt },\n ...(opts.history ?? []),\n { role: 'user', content: opts.userMessage },\n ]\n const tools = asOpenAiTools(opts.tools)\n\n for (let step = 1; step <= opts.maxSteps; step++) {\n const res = await fetchFn(`${opts.config.apiBase}/chat/completions`, {\n method: 'POST',\n headers: {\n 'authorization': `Bearer ${opts.config.apiKey}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n model: opts.config.model,\n messages,\n ...(tools.length > 0 ? { tools, tool_choice: 'auto' } : {}),\n }),\n })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`LiteLLM ${res.status}: ${text.slice(0, 500)}`)\n }\n const data = await res.json() as OpenAIChatResponse\n const choice = data.choices?.[0]\n if (!choice) throw new Error('LiteLLM response had no choices')\n\n const assistant = choice.message\n messages.push(assistant)\n if (assistant.content) opts.handlers?.onTextDelta?.(assistant.content)\n\n trace.push({\n step,\n type: 'assistant',\n preview: previewJson({ content: assistant.content, tool_calls: assistant.tool_calls?.length ?? 0 }),\n })\n\n if (!assistant.tool_calls || assistant.tool_calls.length === 0) {\n const result: RunResult = {\n status: 'ok',\n finalMessage: assistant.content,\n stepCount: step,\n trace,\n }\n opts.handlers?.onDone?.(result)\n return result\n }\n\n // Execute each tool call; the model sees the result on the next turn.\n // Wire-format names (`time_now`) get decoded to local catalog names\n // (`time.now`) for lookup + handler events; we send back the same\n // wire name in the tool message so the next request validates.\n for (const call of assistant.tool_calls) {\n const wireName = call.function.name\n const localName = localToolName(wireName)\n const tool = opts.tools.find(t => t.name === localName)\n let parsedArgs: unknown\n try { parsedArgs = JSON.parse(call.function.arguments) }\n catch { parsedArgs = {} }\n opts.handlers?.onToolCall?.({ name: localName, args: parsedArgs })\n trace.push({ step, type: 'tool_call', tool: localName, preview: previewJson(parsedArgs) })\n\n let result: unknown\n let isError = false\n if (!tool) {\n result = `unknown tool: ${localName}`\n isError = true\n }\n else {\n try {\n result = await tool.execute(parsedArgs)\n }\n catch (err) {\n result = (err as Error)?.message ?? String(err)\n isError = true\n }\n }\n\n if (isError) {\n opts.handlers?.onToolError?.({ name: localName, error: String(result) })\n trace.push({ step, type: 'tool_error', tool: localName, preview: previewJson(result) })\n }\n else {\n opts.handlers?.onToolResult?.({ name: localName, result })\n trace.push({ step, type: 'tool_result', tool: localName, preview: previewJson(result) })\n }\n\n messages.push({\n role: 'tool',\n tool_call_id: call.id,\n name: wireToolName(localName),\n content: typeof result === 'string' ? result : JSON.stringify(result),\n })\n }\n }\n\n // Loop fell through max_steps without a no-tool-calls reply.\n const result: RunResult = {\n status: 'error',\n finalMessage: `max_steps (${opts.maxSteps}) reached without completion`,\n stepCount: opts.maxSteps,\n trace,\n }\n opts.handlers?.onDone?.(result)\n return result\n}\n\nexport interface RpcSession {\n messages: ChatMessage[]\n systemPrompt: string\n tools: ToolDefinition[]\n maxSteps: number\n lastTouched: number\n}\n\nconst RPC_SESSION_TTL_MS = 60 * 60 * 1000\n\nexport class RpcSessionMap {\n private sessions = new Map<string, RpcSession>()\n\n get(id: string): RpcSession | undefined {\n const s = this.sessions.get(id)\n if (s) s.lastTouched = Date.now()\n return s\n }\n\n put(id: string, s: RpcSession): void {\n s.lastTouched = Date.now()\n this.sessions.set(id, s)\n }\n\n evictStale(): void {\n const cutoff = Date.now() - RPC_SESSION_TTL_MS\n for (const [k, v] of this.sessions) {\n if (v.lastTouched < cutoff) this.sessions.delete(k)\n }\n }\n\n size(): number {\n return this.sessions.size\n }\n}\n"],"mappings":"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","names":["homedir","resolve","process","homedir","process","resolve","BRANCH_RE","assertBranch","MAX_BYTES","execFileSync","result"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|