@jentrix/runner 0.5.12 → 0.5.14

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.
@@ -0,0 +1,7 @@
1
+ // lib/version.ts
2
+ var RUNNER_VERSION = "0.5.14";
3
+
4
+ export {
5
+ RUNNER_VERSION
6
+ };
7
+ //# sourceMappingURL=chunk-HN5DR7DX.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../lib/version.ts"],
4
- "sourcesContent": ["export const RUNNER_VERSION = \"0.5.12\";\n"],
4
+ "sourcesContent": ["export const RUNNER_VERSION = \"0.5.14\";\n"],
5
5
  "mappings": ";AAAO,IAAM,iBAAiB;",
6
6
  "names": []
7
7
  }
@@ -32,7 +32,10 @@ function errorCode(error) {
32
32
  }
33
33
  async function executableAt(path) {
34
34
  try {
35
- await fs.access(path, constants.X_OK);
35
+ await fs.access(
36
+ path,
37
+ process.platform === "win32" ? constants.F_OK : constants.X_OK
38
+ );
36
39
  return await fs.realpath(path);
37
40
  } catch {
38
41
  return null;
@@ -492,4 +495,4 @@ export {
492
495
  resolveExecutable,
493
496
  runFileBounded
494
497
  };
495
- //# sourceMappingURL=local-probes-24XPDSVY.js.map
498
+ //# sourceMappingURL=local-probes-373TWNQP.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../lib/local-probes.ts"],
4
+ "sourcesContent": ["import { execFile, spawn } from \"node:child_process\";\nimport { constants, promises as fs } from \"node:fs\";\nimport { delimiter, extname, isAbsolute, resolve } from \"node:path\";\n\nimport { query, type SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\n\nconst PROBE_TIMEOUT_MS = 25_000;\nconst OUTPUT_CAP_BYTES = 1024 * 1024;\nconst PROBE_SCRUBBED_ENV_KEYS = new Set([\n \"STACKS_TOKEN\",\n \"STACKS_RUNNER_TOKEN\",\n \"STACKS_PLANNER_TOKEN\",\n \"STACKS_REVIEWER_TOKEN\",\n \"STACKS_WEBHOOK_SECRET\",\n \"STACKS_BOOTSTRAP_TOKEN\",\n \"STACKS_CLAIM_URL\",\n \"STACKS_RUNNER_AUTH_STATE\",\n \"STACKS_WORKER_HEARTBEAT_TOKEN\",\n \"STACKS_RUNNER_ROLE_BINDINGS\",\n]);\n\nexport function providerProbeEnv(\n env: NodeJS.ProcessEnv,\n adapter?: \"claude\" | \"codex\",\n): NodeJS.ProcessEnv {\n return Object.fromEntries(\n Object.entries(env).filter(\n ([key, value]) =>\n value !== undefined &&\n !PROBE_SCRUBBED_ENV_KEYS.has(key) &&\n !(adapter === \"codex\" && key === \"ANTHROPIC_API_KEY\"),\n ),\n );\n}\n\nexport type LocalRuntimeStatus =\n | \"ready\"\n | \"missing\"\n | \"auth_required\"\n | \"installed_unverified\"\n | \"incompatible\"\n | \"timeout\"\n | \"failed\";\n\nexport interface LocalRuntimeProbe {\n adapterKey: \"claude\" | \"codex\";\n status: LocalRuntimeStatus;\n binaryPath: string | null;\n version: string | null;\n authMethod: \"subscription\" | \"api_key\" | \"unknown\";\n availableModels: Array<{ id: string; displayName?: string }>;\n selectedModel: string | null;\n capabilitySource: \"local_rpc\" | \"sdk_init\" | \"cli_status\" | \"none\";\n checkedAt: string;\n blocker: { code: string; message: string; nextCommand?: string } | null;\n}\n\nexport interface ReadOnlyCapabilityResult {\n authenticated: boolean;\n authMethod: LocalRuntimeProbe[\"authMethod\"];\n availableModels: LocalRuntimeProbe[\"availableModels\"];\n selectedModel: string | null;\n compatible?: boolean;\n}\n\nexport interface RunFileResult {\n code: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface LocalProbeDeps {\n env: NodeJS.ProcessEnv;\n now(): Date;\n resolveExecutable(\n name: \"claude\" | \"codex\",\n override?: string,\n ): Promise<string | null>;\n runFile(file: string, args: string[]): Promise<RunFileResult>;\n probeClaudeInit(file: string): Promise<ReadOnlyCapabilityResult>;\n probeCodexRpc(file: string): Promise<ReadOnlyCapabilityResult>;\n}\n\nexport interface LocalProbeOptions {\n claudePath?: string;\n codexPath?: string;\n}\n\nfunction probeError(code: string, message: string): Error {\n return Object.assign(new Error(message), { code });\n}\n\nfunction errorCode(error: unknown): string | null {\n return typeof error === \"object\" && error !== null && \"code\" in error\n ? String((error as { code: unknown }).code)\n : null;\n}\n\nasync function executableAt(path: string): Promise<string | null> {\n try {\n // STA-132 \u2014 Windows has no execute bit (npm ships .cmd shims), so X_OK\n // rejects valid installs there; existence is the honest probe.\n await fs.access(\n path,\n process.platform === \"win32\" ? constants.F_OK : constants.X_OK,\n );\n return await fs.realpath(path);\n } catch {\n return null;\n }\n}\n\nexport async function resolveExecutable(\n name: \"claude\" | \"codex\",\n override: string | undefined,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<string | null> {\n if (override) {\n if (!isAbsolute(override)) return null;\n return executableAt(override);\n }\n const extensions =\n process.platform === \"win32\"\n ? (env.PATHEXT ?? \".EXE;.CMD;.BAT\").split(\";\")\n : [\"\"];\n for (const dir of (env.PATH ?? \"\").split(delimiter)) {\n if (!dir) continue;\n for (const extension of extensions) {\n const candidate = resolve(\n dir,\n process.platform === \"win32\" && !extname(name)\n ? `${name}${extension.toLowerCase()}`\n : name,\n );\n const found = await executableAt(candidate);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport function runFileBounded(\n file: string,\n args: string[],\n env: NodeJS.ProcessEnv = process.env,\n): Promise<RunFileResult> {\n if (!isAbsolute(file)) {\n return Promise.reject(new Error(\"probe executable path must be absolute\"));\n }\n return new Promise((resolveResult, reject) => {\n execFile(\n file,\n args,\n {\n env,\n timeout: PROBE_TIMEOUT_MS,\n maxBuffer: OUTPUT_CAP_BYTES,\n windowsHide: true,\n },\n (error, stdout, stderr) => {\n if (error && (error.killed || errorCode(error) === \"ETIMEDOUT\")) {\n reject(probeError(\"PROBE_TIMEOUT\", \"local runtime probe timed out\"));\n return;\n }\n if (error && errorCode(error) === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\") {\n reject(new Error(\"local runtime probe exceeded its output limit\"));\n return;\n }\n resolveResult({\n code:\n typeof (error as { code?: unknown } | null)?.code === \"number\"\n ? Number((error as { code: number }).code)\n : 0,\n stdout: String(stdout).slice(0, OUTPUT_CAP_BYTES),\n stderr: String(stderr).slice(0, OUTPUT_CAP_BYTES),\n });\n },\n );\n });\n}\n\nfunction cleanModels(value: unknown): LocalRuntimeProbe[\"availableModels\"] {\n if (!Array.isArray(value)) return [];\n const out: LocalRuntimeProbe[\"availableModels\"] = [];\n const seen = new Set<string>();\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n const row = item as Record<string, unknown>;\n const id = [row.id, row.model, row.slug, row.value]\n .find((v): v is string => typeof v === \"string\" && v.trim().length > 0)\n ?.trim();\n if (!id || seen.has(id)) continue;\n seen.add(id);\n const displayName = [row.displayName, row.display_name, row.name].find(\n (v): v is string => typeof v === \"string\" && v.trim().length > 0,\n );\n out.push({\n id,\n ...(displayName ? { displayName: displayName.trim() } : {}),\n });\n }\n return out;\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nasync function waitForAbort(signal: AbortSignal): Promise<void> {\n if (signal.aborted) return;\n await new Promise<void>((resolveAbort) =>\n signal.addEventListener(\"abort\", () => resolveAbort(), { once: true }),\n );\n}\n\nexport async function probeClaudeInit(\n executablePath: string,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<ReadOnlyCapabilityResult> {\n const abort = new AbortController();\n const session = query({\n // A never-yielding prompt lets the SDK finish local initialization without\n // ever writing a user message or starting a provider request.\n prompt: (async function* (): AsyncGenerator<SDKUserMessage> {\n await waitForAbort(abort.signal);\n })(),\n options: {\n persistSession: false,\n pathToClaudeCodeExecutable: executablePath,\n abortController: abort,\n settingSources: [],\n allowedTools: [],\n mcpServers: {},\n strictMcpConfig: true,\n env: { ...env, ENABLE_CLAUDEAI_MCP_SERVERS: \"false\" },\n stderr: () => {},\n },\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n const init = await Promise.race([\n session.initializationResult(),\n new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(probeError(\"PROBE_TIMEOUT\", \"Claude probe timed out\")),\n PROBE_TIMEOUT_MS,\n );\n }),\n ]);\n const account = init.account;\n const authMethod = account?.apiKeySource\n ? \"api_key\"\n : account?.subscriptionType ||\n account?.tokenSource ||\n account?.apiProvider\n ? \"subscription\"\n : \"unknown\";\n const models = cleanModels(init.models);\n return {\n authenticated: authMethod !== \"unknown\",\n authMethod,\n availableModels: models,\n selectedModel: models[0]?.id ?? null,\n };\n } finally {\n clearTimeout(timer);\n abort.abort();\n session.close();\n }\n}\n\nexport function probeCodexRpc(\n executablePath: string,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<ReadOnlyCapabilityResult> {\n if (!isAbsolute(executablePath)) {\n return Promise.reject(new Error(\"probe executable path must be absolute\"));\n }\n return new Promise((resolveProbe, rejectProbe) => {\n const child = spawn(executablePath, [\"app-server\"], {\n env,\n shell: false,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n windowsHide: true,\n });\n let outputBytes = 0;\n let buffer = \"\";\n let nextId = 1;\n let settled = false;\n const pending = new Map<\n number,\n { resolve(value: unknown): void; reject(error: Error): void }\n >();\n const finish = (error?: Error, value?: ReadOnlyCapabilityResult) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n for (const waiter of pending.values()) {\n waiter.reject(error ?? new Error(\"Codex app server stopped\"));\n }\n pending.clear();\n child.stdin.end();\n if (!child.killed) child.kill(\"SIGTERM\");\n if (error) rejectProbe(error);\n else resolveProbe(value!);\n };\n const timer = setTimeout(\n () => finish(probeError(\"PROBE_TIMEOUT\", \"Codex probe timed out\")),\n PROBE_TIMEOUT_MS,\n );\n const request = (method: string, params: unknown): Promise<unknown> => {\n const id = nextId++;\n return new Promise((resolveRequest, rejectRequest) => {\n pending.set(id, { resolve: resolveRequest, reject: rejectRequest });\n child.stdin.write(\n `${JSON.stringify({ jsonrpc: \"2.0\", id, method, params })}\\n`,\n );\n });\n };\n const onBytes = (chunk: Buffer, protocol: boolean) => {\n outputBytes += chunk.byteLength;\n if (outputBytes > OUTPUT_CAP_BYTES) {\n finish(new Error(\"Codex probe exceeded its output limit\"));\n return;\n }\n if (!protocol) return;\n buffer += chunk.toString(\"utf8\");\n for (;;) {\n const newline = buffer.indexOf(\"\\n\");\n if (newline < 0) break;\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n if (!line) continue;\n try {\n const message = JSON.parse(line) as Record<string, unknown>;\n if (typeof message.id !== \"number\") continue;\n const waiter = pending.get(message.id);\n if (!waiter) continue;\n pending.delete(message.id);\n if (message.error)\n waiter.reject(new Error(\"Codex RPC method failed\"));\n else waiter.resolve(message.result);\n } catch {\n finish(new Error(\"Codex app server returned malformed JSON\"));\n }\n }\n };\n child.stdout.on(\"data\", (chunk: Buffer) => onBytes(chunk, true));\n child.stderr.on(\"data\", (chunk: Buffer) => onBytes(chunk, false));\n child.once(\"error\", (error) => finish(error));\n child.once(\"exit\", () => {\n if (!settled) finish(new Error(\"Codex app server exited during probe\"));\n });\n\n void (async () => {\n await request(\"initialize\", {\n clientInfo: {\n name: \"stacks_runner_probe\",\n title: \"Jentrix Runner\",\n version: \"1\",\n },\n capabilities: { experimentalApi: true },\n });\n child.stdin.write(\n `${JSON.stringify({ jsonrpc: \"2.0\", method: \"initialized\" })}\\n`,\n );\n const accountResult = record(await request(\"account/read\", {}));\n const account = record(accountResult?.account);\n if (!account && accountResult?.requiresOpenaiAuth === true) {\n finish(undefined, {\n authenticated: false,\n authMethod: \"unknown\",\n availableModels: [],\n selectedModel: null,\n });\n return;\n }\n const modelResult = record(await request(\"model/list\", {}));\n const models = cleanModels(modelResult?.data ?? modelResult?.models);\n const authType = String(account?.type ?? \"\").toLowerCase();\n finish(undefined, {\n authenticated: Boolean(account),\n authMethod: /api/.test(authType)\n ? \"api_key\"\n : account\n ? \"subscription\"\n : \"unknown\",\n availableModels: models,\n selectedModel:\n models.find((model) => {\n const source = Array.isArray(modelResult?.data)\n ? (modelResult!.data as Array<Record<string, unknown>>)\n : [];\n return source.some(\n (row) =>\n (row.id === model.id || row.model === model.id) &&\n (row.isDefault === true || row.is_default === true),\n );\n })?.id ?? null,\n });\n })().catch((error) =>\n finish(error instanceof Error ? error : new Error(String(error))),\n );\n });\n}\n\nfunction versionOf(output: string): string | null {\n return output.match(/\\b\\d+\\.\\d+(?:\\.\\d+)?(?:[-+][\\w.-]+)?\\b/)?.[0] ?? null;\n}\n\nfunction blocker(\n code: string,\n message: string,\n nextCommand?: string,\n): LocalRuntimeProbe[\"blocker\"] {\n return { code, message, ...(nextCommand ? { nextCommand } : {}) };\n}\n\nasync function cliAuthFallback(\n adapter: \"claude\" | \"codex\",\n file: string,\n runFile: LocalProbeDeps[\"runFile\"],\n): Promise<\"authenticated\" | \"required\" | \"unknown\"> {\n const args =\n adapter === \"claude\" ? [\"auth\", \"status\", \"--json\"] : [\"login\", \"status\"];\n try {\n const result = await runFile(file, args);\n const text = `${result.stdout}\\n${result.stderr}`.toLowerCase();\n if (\n /not logged|login required|authentication required|\"loggedin\"\\s*:\\s*false/.test(\n text,\n )\n ) {\n return \"required\";\n }\n if (\n result.code === 0 &&\n /logged in|authenticated|\"loggedin\"\\s*:\\s*true/.test(text)\n ) {\n return \"authenticated\";\n }\n return \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nasync function probeRuntime(\n adapterKey: \"claude\" | \"codex\",\n override: string | undefined,\n deps: LocalProbeDeps,\n): Promise<LocalRuntimeProbe> {\n const checkedAt = deps.now().toISOString();\n const nextCommand =\n adapterKey === \"claude\" ? \"claude auth login\" : \"codex login\";\n const binaryPath = await deps.resolveExecutable(adapterKey, override);\n const base = {\n adapterKey,\n binaryPath,\n version: null,\n authMethod: \"unknown\" as const,\n availableModels: [],\n selectedModel: null,\n capabilitySource: \"none\" as const,\n checkedAt,\n };\n if (!binaryPath) {\n return {\n ...base,\n status: \"missing\",\n blocker: blocker(\n \"BINARY_NOT_FOUND\",\n `${adapterKey === \"claude\" ? \"Claude Code\" : \"Codex\"} is not installed or the configured path is not executable.`,\n `Install ${adapterKey === \"claude\" ? \"Claude Code\" : \"Codex\"} manually, then run jentrix runner doctor`,\n ),\n };\n }\n let version: string | null = null;\n try {\n const result = await deps.runFile(binaryPath, [\"--version\"]);\n version = versionOf(`${result.stdout}\\n${result.stderr}`);\n if (result.code !== 0 || !version) {\n return {\n ...base,\n binaryPath,\n status: \"failed\",\n blocker: blocker(\n \"VERSION_PROBE_FAILED\",\n `The ${adapterKey} executable ran but did not report a usable version.`,\n `Update ${adapterKey} manually, then run jentrix runner doctor`,\n ),\n };\n }\n } catch (error) {\n return {\n ...base,\n binaryPath,\n status: errorCode(error) === \"PROBE_TIMEOUT\" ? \"timeout\" : \"failed\",\n blocker: blocker(\n errorCode(error) === \"PROBE_TIMEOUT\"\n ? \"VERSION_PROBE_FAILED\"\n : \"VERSION_PROBE_FAILED\",\n `The ${adapterKey} version probe ${errorCode(error) === \"PROBE_TIMEOUT\" ? \"timed out\" : \"failed\"}.`,\n \"jentrix runner doctor\",\n ),\n };\n }\n\n try {\n const evidence = await (adapterKey === \"claude\"\n ? deps.probeClaudeInit(binaryPath)\n : deps.probeCodexRpc(binaryPath));\n if (evidence.compatible === false) {\n return {\n ...base,\n binaryPath,\n version,\n status: \"incompatible\",\n blocker: blocker(\n \"RUNTIME_INCOMPATIBLE\",\n `The installed ${adapterKey} runtime lacks the required read-only capability protocol.`,\n `Update ${adapterKey} manually, then run jentrix runner doctor`,\n ),\n };\n }\n if (!evidence.authenticated) {\n return {\n ...base,\n binaryPath,\n version,\n status: \"auth_required\",\n capabilitySource: adapterKey === \"claude\" ? \"sdk_init\" : \"local_rpc\",\n blocker: blocker(\n \"AUTH_REQUIRED\",\n `The local ${adapterKey} login is absent or expired.`,\n nextCommand,\n ),\n };\n }\n if (evidence.availableModels.length === 0) {\n return {\n ...base,\n binaryPath,\n version,\n authMethod: evidence.authMethod,\n status: \"installed_unverified\",\n capabilitySource: adapterKey === \"claude\" ? \"sdk_init\" : \"local_rpc\",\n blocker: blocker(\n \"AUTH_UNVERIFIED\",\n `The local ${adapterKey} probe could not prove a usable model without making a model request.`,\n nextCommand,\n ),\n };\n }\n return {\n ...base,\n binaryPath,\n version,\n authMethod: evidence.authMethod,\n availableModels: evidence.availableModels,\n selectedModel: evidence.selectedModel,\n status: \"ready\",\n capabilitySource: adapterKey === \"claude\" ? \"sdk_init\" : \"local_rpc\",\n blocker: null,\n };\n } catch (error) {\n if (errorCode(error) === \"PROBE_TIMEOUT\") {\n return {\n ...base,\n binaryPath,\n version,\n status: \"timeout\",\n blocker: blocker(\n \"RUNTIME_INCOMPATIBLE\",\n `The ${adapterKey} read-only capability probe timed out.`,\n \"jentrix runner doctor\",\n ),\n };\n }\n const fallback = await cliAuthFallback(\n adapterKey,\n binaryPath,\n deps.runFile,\n );\n if (fallback === \"required\") {\n return {\n ...base,\n binaryPath,\n version,\n status: \"auth_required\",\n capabilitySource: \"cli_status\",\n blocker: blocker(\n \"AUTH_REQUIRED\",\n `The local ${adapterKey} login is absent or expired.`,\n nextCommand,\n ),\n };\n }\n return {\n ...base,\n binaryPath,\n version,\n status: \"installed_unverified\",\n capabilitySource: fallback === \"authenticated\" ? \"cli_status\" : \"none\",\n blocker: blocker(\n \"AUTH_UNVERIFIED\",\n `The installed ${adapterKey} version cannot prove readiness without a model request.`,\n nextCommand,\n ),\n };\n }\n}\n\nexport function defaultLocalProbeDeps(\n env: NodeJS.ProcessEnv = process.env,\n): LocalProbeDeps {\n const safeEnv = providerProbeEnv(env);\n return {\n env,\n now: () => new Date(),\n resolveExecutable: (name, override) =>\n resolveExecutable(name, override, env),\n runFile: (file, args) => runFileBounded(file, args, safeEnv),\n probeClaudeInit: (file) =>\n probeClaudeInit(file, providerProbeEnv(env, \"claude\")),\n probeCodexRpc: (file) =>\n probeCodexRpc(file, providerProbeEnv(env, \"codex\")),\n };\n}\n\nexport async function probeLocalRuntimes(\n options: LocalProbeOptions = {},\n deps: LocalProbeDeps = defaultLocalProbeDeps(),\n): Promise<LocalRuntimeProbe[]> {\n return Promise.all([\n probeRuntime(\"claude\", options.claudePath, deps),\n probeRuntime(\"codex\", options.codexPath, deps),\n ]);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,13 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  RUNNER_VERSION
4
- } from "./chunk-TWNBYXS6.js";
4
+ } from "./chunk-HN5DR7DX.js";
5
5
 
6
6
  // runner-cli.ts
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { spawn } from "node:child_process";
9
9
  import { realpathSync } from "node:fs";
10
+ import { homedir } from "node:os";
11
+ import { join } from "node:path";
10
12
  var RUNNER_PROTOCOL_VERSION = 1;
13
+ function sessionHookDir(provider, home = homedir()) {
14
+ return provider === "claude" || provider === "codex" ? join(home, ".config", "stacks", `${provider}-sessions`) : null;
15
+ }
11
16
  function runnerVersionEnvelope() {
12
17
  return {
13
18
  protocolVersion: RUNNER_PROTOCOL_VERSION,
@@ -46,7 +51,7 @@ function assertRunnerConfigCompatibility(config) {
46
51
  }
47
52
  }
48
53
  async function runConfiguredRunner(once) {
49
- const { probeLocalRuntimes } = await import("./local-probes-24XPDSVY.js");
54
+ const { probeLocalRuntimes } = await import("./local-probes-373TWNQP.js");
50
55
  const { readRunnerConfig, runnerConfigPath } = await import("./runner-config-THT646ZG.js");
51
56
  const { applyRunnerSetup } = await import("./runner-setup-JHWM6BYD.js");
52
57
  const configPath = runnerConfigPath();
@@ -182,7 +187,7 @@ async function main(args = process.argv.slice(2)) {
182
187
  return 0;
183
188
  }
184
189
  if (command === "probe" && args.includes("--json")) {
185
- const { probeLocalRuntimes } = await import("./local-probes-24XPDSVY.js");
190
+ const { probeLocalRuntimes } = await import("./local-probes-373TWNQP.js");
186
191
  const { runnerConfigPath, runnerConfigSummary } = await import("./runner-config-THT646ZG.js");
187
192
  const [runtimes, config] = await Promise.all([
188
193
  probeLocalRuntimes({
@@ -214,7 +219,7 @@ async function main(args = process.argv.slice(2)) {
214
219
  return runConfiguredRunner(args.includes("--once"));
215
220
  }
216
221
  if (command === "session-run" && (args.includes("--plan-stdin") || args.includes("--plan-file"))) {
217
- const { runSessionHost } = await import("./session-host-6VFDGKBT.js");
222
+ const { runSessionHost } = await import("./session-host-ELAJLLL4.js");
218
223
  let raw;
219
224
  const planFile = valueAfter(args, "--plan-file");
220
225
  if (planFile) {
@@ -242,15 +247,17 @@ async function main(args = process.argv.slice(2)) {
242
247
  }
243
248
  if (command === "session-hook") {
244
249
  const { appendHookEvent } = await import("./session-hook-log-KNO6C4BF.js");
245
- const dir = valueAfter(args, "--dir");
250
+ const dir = valueAfter(args, "--dir") ?? sessionHookDir(valueAfter(args, "--provider") ?? null);
246
251
  const event = valueAfter(args, "--event") ?? "unknown";
247
252
  if (!dir)
248
- throw new Error("RUNNER_CONFIG_INVALID: session-hook needs --dir");
253
+ throw new Error(
254
+ "RUNNER_CONFIG_INVALID: session-hook needs --provider claude|codex or --dir"
255
+ );
249
256
  appendHookEvent(dir, event, await readStdinCapped());
250
257
  return 0;
251
258
  }
252
259
  process.stderr.write(
253
- "usage: stacks-runner version --json | probe --json [--claude-path PATH] [--codex-path PATH] | setup-apply --plan-stdin | run [--once] | session-run --plan-stdin | session-hook --dir DIR --event NAME\n"
260
+ "usage: stacks-runner version --json | probe --json [--claude-path PATH] [--codex-path PATH] | setup-apply --plan-stdin | run [--once] | session-run --plan-stdin | session-hook (--provider claude|codex | --dir DIR) --event NAME\n"
254
261
  );
255
262
  return 2;
256
263
  }
@@ -283,6 +290,7 @@ export {
283
290
  main,
284
291
  runnerEnvironment,
285
292
  runnerVersionEnvelope,
293
+ sessionHookDir,
286
294
  terminationHandlers
287
295
  };
288
296
  //# sourceMappingURL=runner-cli.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../runner-cli.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\nimport { fileURLToPath } from \"node:url\";\nimport { spawn } from \"node:child_process\";\nimport { realpathSync } from \"node:fs\";\n\nimport type { RunnerConfig } from \"./lib/runner-config.js\";\nimport type { RunnerSetupApply } from \"./lib/runner-setup.js\";\nimport { RUNNER_VERSION } from \"./lib/version.js\";\n\n// ---------------------------------------------------------------------------\n// TYPE-ONLY above, and that is load-bearing (MVP separation P5).\n//\n// `probe`, `setup-apply` and `run` are the PLATFORM half of this binary: they\n// enroll a worker and poll for agent jobs, both of which are planes. The MVP\n// deployment uses only the session half (`session-run`, `session-hook`), and\n// `session-hook` in particular is invoked by a Claude Code lifecycle hook \u2014\n// several times per conversation, on the operator's critical path.\n//\n// Statically importing `local-probes` put `@anthropic-ai/claude-agent-sdk` at\n// the top of the built bundle, so EVERY invocation paid to load 4.5 MB of a\n// provider SDK the session half never touches: ~90ms per hook against a ~10ms\n// bare-node baseline. The three `await import(\u2026)` calls below move that cost\n// into the branches that actually need it.\n//\n// The dependency itself stays REQUIRED rather than optional. Making it\n// optional is the packaging half of this question and it breaks a platform\n// operator's `npm i -g` in a way this refactor should not decide silently \u2014\n// see `plans/mvp-separation-strategy.md` \u00A7 P5.\n// ---------------------------------------------------------------------------\n\nexport const RUNNER_PROTOCOL_VERSION = 1;\nexport { RUNNER_VERSION };\n\nexport function runnerVersionEnvelope() {\n return {\n protocolVersion: RUNNER_PROTOCOL_VERSION,\n runnerVersion: RUNNER_VERSION,\n };\n}\n\nexport function runnerEnvironment(\n config: RunnerConfig,\n configPath: string,\n once: boolean,\n base: NodeJS.ProcessEnv = process.env,\n): NodeJS.ProcessEnv {\n return {\n ...base,\n STACKS_BASE_URL: config.jentrixBaseUrl,\n STACKS_MCP_URL: config.mcpUrl,\n STACKS_RUNNER_MODE: \"self-hosted\",\n STACKS_BOOTSTRAP_TOKEN: config.bootstrapToken,\n STACKS_CLAIM_URL: config.claimUrl,\n STACKS_RUNNER_AUTH_STATE: `${configPath}.auth.json`,\n STACKS_WORKER_HEARTBEAT_TOKEN: config.heartbeatToken,\n STACKS_RUNNER_ROLE_BINDINGS: JSON.stringify(config.roleBindings),\n STACKS_RUNNER_HOST: \"127.0.0.1\",\n STACKS_CLAUDE_EXECUTABLE: config.executables.claude,\n STACKS_CODEX_EXECUTABLE: config.executables.codex,\n STACKS_POLL_MS: base.STACKS_POLL_MS ?? \"30000\",\n ...(once ? { STACKS_RUNNER_ONCE: \"1\" } : {}),\n };\n}\n\nexport function terminationHandlers(kill: (signal: NodeJS.Signals) => unknown) {\n return {\n interrupt: () => kill(\"SIGINT\"),\n terminate: () => kill(\"SIGTERM\"),\n };\n}\n\nexport function assertRunnerConfigCompatibility(config: RunnerConfig): void {\n if (config.protocolVersion !== RUNNER_PROTOCOL_VERSION) {\n throw new Error(\n `RUNNER_VERSION_MISMATCH: run: npm install --global @jentrix/cli@${RUNNER_VERSION} @jentrix/runner@${RUNNER_VERSION}`,\n );\n }\n}\n\nasync function runConfiguredRunner(once: boolean): Promise<number> {\n const { probeLocalRuntimes } = await import(\"./lib/local-probes.js\");\n const { readRunnerConfig, runnerConfigPath } = await import(\n \"./lib/runner-config.js\"\n );\n const { applyRunnerSetup } = await import(\"./lib/runner-setup.js\");\n const configPath = runnerConfigPath();\n let config: RunnerConfig;\n try {\n config = await readRunnerConfig(configPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n throw new Error(\"BOOTSTRAP_REQUIRED: run jentrix runner setup.\");\n }\n throw error;\n }\n assertRunnerConfigCompatibility(config);\n const runtimes = await probeLocalRuntimes({\n claudePath: config.executables.claude,\n codexPath: config.executables.codex,\n });\n const probes = new Map(\n runtimes.map((runtime) => [runtime.adapterKey, runtime]),\n );\n for (const binding of Object.values(config.roleBindings)) {\n const probe = probes.get(binding.runtimeAdapterKey);\n if (!probe || probe.status !== \"ready\") {\n throw new Error(\n `ROLE_PLAN_UNSATISFIED: ${binding.runtimeAdapterKey} is not ready for a configured role.`,\n );\n }\n if (\n probe.availableModels.length > 0 &&\n !probe.availableModels.some((model) => model.id === binding.model)\n ) {\n throw new Error(\n `ROLE_PLAN_UNSATISFIED: ${binding.runtimeAdapterKey} cannot run configured model ${binding.model}.`,\n );\n }\n }\n await applyRunnerSetup(\n {\n protocolVersion: config.protocolVersion,\n runnerVersion: config.runnerVersion,\n configPath,\n jentrixBaseUrl: config.jentrixBaseUrl,\n mcpUrl: config.mcpUrl,\n workspaceId: config.workspaceId,\n enrollment: null,\n bootstrap: { token: config.bootstrapToken, claimUrl: config.claimUrl },\n runtimes,\n roleBindings: config.roleBindings,\n attestationConnections: [\n ...new Map(\n Object.values(config.roleBindings)\n .filter((binding) => binding.requiresClaimCredential)\n .map((binding) => [\n binding.providerConnectionId,\n {\n connectionId: binding.providerConnectionId,\n runtimeAdapterKey: binding.runtimeAdapterKey,\n },\n ]),\n ).values(),\n ],\n },\n {\n postJson: (path, body) =>\n postSetupJson(config.jentrixBaseUrl, path, body),\n },\n );\n const workflowRunner = fileURLToPath(\n new URL(\"./workflow-runner.js\", import.meta.url),\n );\n const child = spawn(process.execPath, [workflowRunner], {\n env: runnerEnvironment(config, configPath, once),\n stdio: \"inherit\",\n });\n const { interrupt, terminate } = terminationHandlers((signal) =>\n child.kill(signal),\n );\n process.once(\"SIGINT\", interrupt);\n process.once(\"SIGTERM\", terminate);\n try {\n return await new Promise<number>((resolve, reject) => {\n child.once(\"error\", reject);\n child.once(\"exit\", (code, signal) => resolve(code ?? (signal ? 1 : 0)));\n });\n } finally {\n process.off(\"SIGINT\", interrupt);\n process.off(\"SIGTERM\", terminate);\n }\n}\n\nfunction valueAfter(args: string[], flag: string): string | undefined {\n const at = args.indexOf(flag);\n return at >= 0 ? args[at + 1] : undefined;\n}\n\nasync function readStdinCapped(cap = 2 * 1024 * 1024): Promise<string> {\n const chunks: Buffer[] = [];\n let bytes = 0;\n for await (const chunk of process.stdin) {\n const buffer = Buffer.from(chunk);\n bytes += buffer.byteLength;\n if (bytes > cap)\n throw new Error(\"runner setup input exceeded its size limit\");\n chunks.push(buffer);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nasync function postSetupJson(\n baseUrl: string,\n path: string,\n body: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const response = await fetch(new URL(path, baseUrl), {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(30_000),\n });\n if (!response.ok) {\n throw new Error(\n `${path} refused the runner request (HTTP ${response.status}).`,\n );\n }\n const value = await response.json();\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${path} returned malformed JSON.`);\n }\n return value as Record<string, unknown>;\n}\n\nexport async function main(\n args: string[] = process.argv.slice(2),\n): Promise<number> {\n const command = args[0];\n // F-2/AGE-933: the conventional spellings must work too \u2014 every other CLI\n // on the machine answers `--version`, so rejecting it reads as breakage.\n if (command === \"--version\" || command === \"-v\") {\n process.stdout.write(`${RUNNER_VERSION}\\n`);\n return 0;\n }\n if (command === \"version\") {\n if (args.includes(\"--json\")) {\n process.stdout.write(`${JSON.stringify(runnerVersionEnvelope())}\\n`);\n } else {\n process.stdout.write(`${RUNNER_VERSION}\\n`);\n }\n return 0;\n }\n if (command === \"probe\" && args.includes(\"--json\")) {\n const { probeLocalRuntimes } = await import(\"./lib/local-probes.js\");\n const { runnerConfigPath, runnerConfigSummary } = await import(\n \"./lib/runner-config.js\"\n );\n const [runtimes, config] = await Promise.all([\n probeLocalRuntimes({\n claudePath: valueAfter(args, \"--claude-path\"),\n codexPath: valueAfter(args, \"--codex-path\"),\n }),\n runnerConfigSummary(runnerConfigPath()),\n ]);\n process.stdout.write(\n `${JSON.stringify({ ...runnerVersionEnvelope(), runtimes, config })}\\n`,\n );\n return runtimes.some((runtime) => runtime.status === \"ready\") ? 0 : 1;\n }\n if (command === \"setup-apply\" && args.includes(\"--plan-stdin\")) {\n const { applyRunnerSetup } = await import(\"./lib/runner-setup.js\");\n const parsed = JSON.parse(await readStdinCapped()) as RunnerSetupApply;\n if (parsed.protocolVersion !== RUNNER_PROTOCOL_VERSION) {\n throw new Error(\"runner setup protocol version mismatch\");\n }\n const result = await applyRunnerSetup(parsed, {\n postJson: (path, body) =>\n postSetupJson(parsed.jentrixBaseUrl, path, body),\n });\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n return 0;\n }\n if (command === \"run\") {\n return runConfiguredRunner(args.includes(\"--once\"));\n }\n // M20.1: connected-session host. The plan (including the TRANSIENT human\n // bearer) arrives over stdin or a 0600 plan file that is unlinked on read \u2014\n // never argv, never persisted (AC4). The file form exists because a LAUNCH\n // keeps the TTY's stdin for the interactive provider.\n if (\n command === \"session-run\" &&\n (args.includes(\"--plan-stdin\") || args.includes(\"--plan-file\"))\n ) {\n const { runSessionHost } = await import(\"./lib/session-host.js\");\n let raw: string;\n const planFile = valueAfter(args, \"--plan-file\");\n if (planFile) {\n const { readFileSync, unlinkSync } = await import(\"node:fs\");\n raw = readFileSync(planFile, \"utf8\");\n try {\n unlinkSync(planFile);\n } catch {\n // best-effort \u2014 the file is 0600 and holds a short-lived bearer\n }\n } else {\n raw = await readStdinCapped();\n }\n const plan = JSON.parse(raw) as {\n protocolVersion?: number;\n provider?: string;\n };\n if (plan.protocolVersion !== RUNNER_PROTOCOL_VERSION) {\n throw new Error(\n \"RUNNER_VERSION_MISMATCH: session plan protocol mismatch\",\n );\n }\n if (plan.provider !== \"claude\" && plan.provider !== \"codex\") {\n throw new Error(\"RUNNER_CONFIG_INVALID: unknown session provider\");\n }\n return runSessionHost(\n plan as import(\"./lib/session-host.js\").SessionRunPlan,\n );\n }\n // M20.1 \u00A715.1: the hook forwarder Claude lifecycle hooks invoke. Argv holds\n // only the session DIRECTORY and event name; the payload rides stdin.\n if (command === \"session-hook\") {\n // The hook-log module, NOT `session-host` \u2014 appending a line must not load\n // the MCP client and both transcript mappers (P5).\n const { appendHookEvent } = await import(\"./lib/session-hook-log.js\");\n const dir = valueAfter(args, \"--dir\");\n const event = valueAfter(args, \"--event\") ?? \"unknown\";\n if (!dir)\n throw new Error(\"RUNNER_CONFIG_INVALID: session-hook needs --dir\");\n appendHookEvent(dir, event, await readStdinCapped());\n return 0;\n }\n process.stderr.write(\n \"usage: stacks-runner version --json | probe --json [--claude-path PATH] [--codex-path PATH] | setup-apply --plan-stdin | run [--once] | session-run --plan-stdin | session-hook --dir DIR --event NAME\\n\",\n );\n return 2;\n}\n\nfunction isEntrypoint(): boolean {\n try {\n return (\n realpathSync(process.argv[1] ?? \"\") ===\n realpathSync(fileURLToPath(import.meta.url))\n );\n } catch {\n return false;\n }\n}\n\nif (isEntrypoint()) {\n main().then(\n (code) => {\n process.exitCode = code;\n },\n (error) => {\n const message = error instanceof Error ? error.message : \"\";\n process.stderr.write(\n /^[A-Z][A-Z_]+: /.test(message)\n ? `${message}\\n`\n : \"RUNNER_CONFIG_INVALID: runner protocol failure\\n\",\n );\n process.exitCode = 2;\n },\n );\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["#!/usr/bin/env node\nimport { fileURLToPath } from \"node:url\";\nimport { spawn } from \"node:child_process\";\nimport { realpathSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport type { RunnerConfig } from \"./lib/runner-config.js\";\nimport type { RunnerSetupApply } from \"./lib/runner-setup.js\";\nimport { RUNNER_VERSION } from \"./lib/version.js\";\n\n// ---------------------------------------------------------------------------\n// TYPE-ONLY above, and that is load-bearing (MVP separation P5).\n//\n// `probe`, `setup-apply` and `run` are the PLATFORM half of this binary: they\n// enroll a worker and poll for agent jobs, both of which are planes. The MVP\n// deployment uses only the session half (`session-run`, `session-hook`), and\n// `session-hook` in particular is invoked by a Claude Code lifecycle hook \u2014\n// several times per conversation, on the operator's critical path.\n//\n// Statically importing `local-probes` put `@anthropic-ai/claude-agent-sdk` at\n// the top of the built bundle, so EVERY invocation paid to load 4.5 MB of a\n// provider SDK the session half never touches: ~90ms per hook against a ~10ms\n// bare-node baseline. The three `await import(\u2026)` calls below move that cost\n// into the branches that actually need it.\n//\n// The dependency itself stays REQUIRED rather than optional. Making it\n// optional is the packaging half of this question and it breaks a platform\n// operator's `npm i -g` in a way this refactor should not decide silently \u2014\n// see `plans/mvp-separation-strategy.md` \u00A7 P5.\n// ---------------------------------------------------------------------------\n\nexport const RUNNER_PROTOCOL_VERSION = 1;\nexport { RUNNER_VERSION };\n\n/**\n * STA-131 \u2014 the default hook-context dir per provider, resolved in code. A\n * `$HOME` literal on hook argv never expands on Windows (no POSIX shell), so\n * the plugins pass `--provider` and the path is built here, cross-platform.\n */\nexport function sessionHookDir(\n provider: string | null,\n home: string = homedir(),\n): string | null {\n return provider === \"claude\" || provider === \"codex\"\n ? join(home, \".config\", \"stacks\", `${provider}-sessions`)\n : null;\n}\n\nexport function runnerVersionEnvelope() {\n return {\n protocolVersion: RUNNER_PROTOCOL_VERSION,\n runnerVersion: RUNNER_VERSION,\n };\n}\n\nexport function runnerEnvironment(\n config: RunnerConfig,\n configPath: string,\n once: boolean,\n base: NodeJS.ProcessEnv = process.env,\n): NodeJS.ProcessEnv {\n return {\n ...base,\n STACKS_BASE_URL: config.jentrixBaseUrl,\n STACKS_MCP_URL: config.mcpUrl,\n STACKS_RUNNER_MODE: \"self-hosted\",\n STACKS_BOOTSTRAP_TOKEN: config.bootstrapToken,\n STACKS_CLAIM_URL: config.claimUrl,\n STACKS_RUNNER_AUTH_STATE: `${configPath}.auth.json`,\n STACKS_WORKER_HEARTBEAT_TOKEN: config.heartbeatToken,\n STACKS_RUNNER_ROLE_BINDINGS: JSON.stringify(config.roleBindings),\n STACKS_RUNNER_HOST: \"127.0.0.1\",\n STACKS_CLAUDE_EXECUTABLE: config.executables.claude,\n STACKS_CODEX_EXECUTABLE: config.executables.codex,\n STACKS_POLL_MS: base.STACKS_POLL_MS ?? \"30000\",\n ...(once ? { STACKS_RUNNER_ONCE: \"1\" } : {}),\n };\n}\n\nexport function terminationHandlers(kill: (signal: NodeJS.Signals) => unknown) {\n return {\n interrupt: () => kill(\"SIGINT\"),\n terminate: () => kill(\"SIGTERM\"),\n };\n}\n\nexport function assertRunnerConfigCompatibility(config: RunnerConfig): void {\n if (config.protocolVersion !== RUNNER_PROTOCOL_VERSION) {\n throw new Error(\n `RUNNER_VERSION_MISMATCH: run: npm install --global @jentrix/cli@${RUNNER_VERSION} @jentrix/runner@${RUNNER_VERSION}`,\n );\n }\n}\n\nasync function runConfiguredRunner(once: boolean): Promise<number> {\n const { probeLocalRuntimes } = await import(\"./lib/local-probes.js\");\n const { readRunnerConfig, runnerConfigPath } = await import(\n \"./lib/runner-config.js\"\n );\n const { applyRunnerSetup } = await import(\"./lib/runner-setup.js\");\n const configPath = runnerConfigPath();\n let config: RunnerConfig;\n try {\n config = await readRunnerConfig(configPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n throw new Error(\"BOOTSTRAP_REQUIRED: run jentrix runner setup.\");\n }\n throw error;\n }\n assertRunnerConfigCompatibility(config);\n const runtimes = await probeLocalRuntimes({\n claudePath: config.executables.claude,\n codexPath: config.executables.codex,\n });\n const probes = new Map(\n runtimes.map((runtime) => [runtime.adapterKey, runtime]),\n );\n for (const binding of Object.values(config.roleBindings)) {\n const probe = probes.get(binding.runtimeAdapterKey);\n if (!probe || probe.status !== \"ready\") {\n throw new Error(\n `ROLE_PLAN_UNSATISFIED: ${binding.runtimeAdapterKey} is not ready for a configured role.`,\n );\n }\n if (\n probe.availableModels.length > 0 &&\n !probe.availableModels.some((model) => model.id === binding.model)\n ) {\n throw new Error(\n `ROLE_PLAN_UNSATISFIED: ${binding.runtimeAdapterKey} cannot run configured model ${binding.model}.`,\n );\n }\n }\n await applyRunnerSetup(\n {\n protocolVersion: config.protocolVersion,\n runnerVersion: config.runnerVersion,\n configPath,\n jentrixBaseUrl: config.jentrixBaseUrl,\n mcpUrl: config.mcpUrl,\n workspaceId: config.workspaceId,\n enrollment: null,\n bootstrap: { token: config.bootstrapToken, claimUrl: config.claimUrl },\n runtimes,\n roleBindings: config.roleBindings,\n attestationConnections: [\n ...new Map(\n Object.values(config.roleBindings)\n .filter((binding) => binding.requiresClaimCredential)\n .map((binding) => [\n binding.providerConnectionId,\n {\n connectionId: binding.providerConnectionId,\n runtimeAdapterKey: binding.runtimeAdapterKey,\n },\n ]),\n ).values(),\n ],\n },\n {\n postJson: (path, body) =>\n postSetupJson(config.jentrixBaseUrl, path, body),\n },\n );\n const workflowRunner = fileURLToPath(\n new URL(\"./workflow-runner.js\", import.meta.url),\n );\n const child = spawn(process.execPath, [workflowRunner], {\n env: runnerEnvironment(config, configPath, once),\n stdio: \"inherit\",\n });\n const { interrupt, terminate } = terminationHandlers((signal) =>\n child.kill(signal),\n );\n process.once(\"SIGINT\", interrupt);\n process.once(\"SIGTERM\", terminate);\n try {\n return await new Promise<number>((resolve, reject) => {\n child.once(\"error\", reject);\n child.once(\"exit\", (code, signal) => resolve(code ?? (signal ? 1 : 0)));\n });\n } finally {\n process.off(\"SIGINT\", interrupt);\n process.off(\"SIGTERM\", terminate);\n }\n}\n\nfunction valueAfter(args: string[], flag: string): string | undefined {\n const at = args.indexOf(flag);\n return at >= 0 ? args[at + 1] : undefined;\n}\n\nasync function readStdinCapped(cap = 2 * 1024 * 1024): Promise<string> {\n const chunks: Buffer[] = [];\n let bytes = 0;\n for await (const chunk of process.stdin) {\n const buffer = Buffer.from(chunk);\n bytes += buffer.byteLength;\n if (bytes > cap)\n throw new Error(\"runner setup input exceeded its size limit\");\n chunks.push(buffer);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nasync function postSetupJson(\n baseUrl: string,\n path: string,\n body: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const response = await fetch(new URL(path, baseUrl), {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(30_000),\n });\n if (!response.ok) {\n throw new Error(\n `${path} refused the runner request (HTTP ${response.status}).`,\n );\n }\n const value = await response.json();\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${path} returned malformed JSON.`);\n }\n return value as Record<string, unknown>;\n}\n\nexport async function main(\n args: string[] = process.argv.slice(2),\n): Promise<number> {\n const command = args[0];\n // F-2/AGE-933: the conventional spellings must work too \u2014 every other CLI\n // on the machine answers `--version`, so rejecting it reads as breakage.\n if (command === \"--version\" || command === \"-v\") {\n process.stdout.write(`${RUNNER_VERSION}\\n`);\n return 0;\n }\n if (command === \"version\") {\n if (args.includes(\"--json\")) {\n process.stdout.write(`${JSON.stringify(runnerVersionEnvelope())}\\n`);\n } else {\n process.stdout.write(`${RUNNER_VERSION}\\n`);\n }\n return 0;\n }\n if (command === \"probe\" && args.includes(\"--json\")) {\n const { probeLocalRuntimes } = await import(\"./lib/local-probes.js\");\n const { runnerConfigPath, runnerConfigSummary } = await import(\n \"./lib/runner-config.js\"\n );\n const [runtimes, config] = await Promise.all([\n probeLocalRuntimes({\n claudePath: valueAfter(args, \"--claude-path\"),\n codexPath: valueAfter(args, \"--codex-path\"),\n }),\n runnerConfigSummary(runnerConfigPath()),\n ]);\n process.stdout.write(\n `${JSON.stringify({ ...runnerVersionEnvelope(), runtimes, config })}\\n`,\n );\n return runtimes.some((runtime) => runtime.status === \"ready\") ? 0 : 1;\n }\n if (command === \"setup-apply\" && args.includes(\"--plan-stdin\")) {\n const { applyRunnerSetup } = await import(\"./lib/runner-setup.js\");\n const parsed = JSON.parse(await readStdinCapped()) as RunnerSetupApply;\n if (parsed.protocolVersion !== RUNNER_PROTOCOL_VERSION) {\n throw new Error(\"runner setup protocol version mismatch\");\n }\n const result = await applyRunnerSetup(parsed, {\n postJson: (path, body) =>\n postSetupJson(parsed.jentrixBaseUrl, path, body),\n });\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n return 0;\n }\n if (command === \"run\") {\n return runConfiguredRunner(args.includes(\"--once\"));\n }\n // M20.1: connected-session host. The plan (including the TRANSIENT human\n // bearer) arrives over stdin or a 0600 plan file that is unlinked on read \u2014\n // never argv, never persisted (AC4). The file form exists because a LAUNCH\n // keeps the TTY's stdin for the interactive provider.\n if (\n command === \"session-run\" &&\n (args.includes(\"--plan-stdin\") || args.includes(\"--plan-file\"))\n ) {\n const { runSessionHost } = await import(\"./lib/session-host.js\");\n let raw: string;\n const planFile = valueAfter(args, \"--plan-file\");\n if (planFile) {\n const { readFileSync, unlinkSync } = await import(\"node:fs\");\n raw = readFileSync(planFile, \"utf8\");\n try {\n unlinkSync(planFile);\n } catch {\n // best-effort \u2014 the file is 0600 and holds a short-lived bearer\n }\n } else {\n raw = await readStdinCapped();\n }\n const plan = JSON.parse(raw) as {\n protocolVersion?: number;\n provider?: string;\n };\n if (plan.protocolVersion !== RUNNER_PROTOCOL_VERSION) {\n throw new Error(\n \"RUNNER_VERSION_MISMATCH: session plan protocol mismatch\",\n );\n }\n if (plan.provider !== \"claude\" && plan.provider !== \"codex\") {\n throw new Error(\"RUNNER_CONFIG_INVALID: unknown session provider\");\n }\n return runSessionHost(\n plan as import(\"./lib/session-host.js\").SessionRunPlan,\n );\n }\n // M20.1 \u00A715.1: the hook forwarder Claude lifecycle hooks invoke. Argv holds\n // only the session DIRECTORY and event name; the payload rides stdin.\n if (command === \"session-hook\") {\n // The hook-log module, NOT `session-host` \u2014 appending a line must not load\n // the MCP client and both transcript mappers (P5).\n const { appendHookEvent } = await import(\"./lib/session-hook-log.js\");\n // --dir stays as the explicit override (and keeps pre-0.5.13 plugin\n // copies working on unix); see sessionHookDir for why --provider exists.\n const dir =\n valueAfter(args, \"--dir\") ??\n sessionHookDir(valueAfter(args, \"--provider\") ?? null);\n const event = valueAfter(args, \"--event\") ?? \"unknown\";\n if (!dir)\n throw new Error(\n \"RUNNER_CONFIG_INVALID: session-hook needs --provider claude|codex or --dir\",\n );\n appendHookEvent(dir, event, await readStdinCapped());\n return 0;\n }\n process.stderr.write(\n \"usage: stacks-runner version --json | probe --json [--claude-path PATH] [--codex-path PATH] | setup-apply --plan-stdin | run [--once] | session-run --plan-stdin | session-hook (--provider claude|codex | --dir DIR) --event NAME\\n\",\n );\n return 2;\n}\n\nfunction isEntrypoint(): boolean {\n try {\n return (\n realpathSync(process.argv[1] ?? \"\") ===\n realpathSync(fileURLToPath(import.meta.url))\n );\n } catch {\n return false;\n }\n}\n\nif (isEntrypoint()) {\n main().then(\n (code) => {\n process.exitCode = code;\n },\n (error) => {\n const message = error instanceof Error ? error.message : \"\";\n process.stderr.write(\n /^[A-Z][A-Z_]+: /.test(message)\n ? `${message}\\n`\n : \"RUNNER_CONFIG_INVALID: runner protocol failure\\n\",\n );\n process.exitCode = 2;\n },\n );\n}\n"],
5
+ "mappings": ";;;;;;AACA,SAAS,qBAAqB;AAC9B,SAAS,aAAa;AACtB,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,YAAY;AA2Bd,IAAM,0BAA0B;AAQhC,SAAS,eACd,UACA,OAAe,QAAQ,GACR;AACf,SAAO,aAAa,YAAY,aAAa,UACzC,KAAK,MAAM,WAAW,UAAU,GAAG,QAAQ,WAAW,IACtD;AACN;AAEO,SAAS,wBAAwB;AACtC,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,eAAe;AAAA,EACjB;AACF;AAEO,SAAS,kBACd,QACA,YACA,MACA,OAA0B,QAAQ,KACf;AACnB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,iBAAiB,OAAO;AAAA,IACxB,gBAAgB,OAAO;AAAA,IACvB,oBAAoB;AAAA,IACpB,wBAAwB,OAAO;AAAA,IAC/B,kBAAkB,OAAO;AAAA,IACzB,0BAA0B,GAAG,UAAU;AAAA,IACvC,+BAA+B,OAAO;AAAA,IACtC,6BAA6B,KAAK,UAAU,OAAO,YAAY;AAAA,IAC/D,oBAAoB;AAAA,IACpB,0BAA0B,OAAO,YAAY;AAAA,IAC7C,yBAAyB,OAAO,YAAY;AAAA,IAC5C,gBAAgB,KAAK,kBAAkB;AAAA,IACvC,GAAI,OAAO,EAAE,oBAAoB,IAAI,IAAI,CAAC;AAAA,EAC5C;AACF;AAEO,SAAS,oBAAoB,MAA2C;AAC7E,SAAO;AAAA,IACL,WAAW,MAAM,KAAK,QAAQ;AAAA,IAC9B,WAAW,MAAM,KAAK,SAAS;AAAA,EACjC;AACF;AAEO,SAAS,gCAAgC,QAA4B;AAC1E,MAAI,OAAO,oBAAoB,yBAAyB;AACtD,UAAM,IAAI;AAAA,MACR,mEAAmE,cAAc,oBAAoB,cAAc;AAAA,IACrH;AAAA,EACF;AACF;AAEA,eAAe,oBAAoB,MAAgC;AACjE,QAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,4BAAuB;AACnE,QAAM,EAAE,kBAAkB,iBAAiB,IAAI,MAAM,OACnD,6BACF;AACA,QAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,4BAAuB;AACjE,QAAM,aAAa,iBAAiB;AACpC,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,iBAAiB,UAAU;AAAA,EAC5C,SAAS,OAAO;AACd,QAAK,OAAiC,SAAS,UAAU;AACvD,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AACA,UAAM;AAAA,EACR;AACA,kCAAgC,MAAM;AACtC,QAAM,WAAW,MAAM,mBAAmB;AAAA,IACxC,YAAY,OAAO,YAAY;AAAA,IAC/B,WAAW,OAAO,YAAY;AAAA,EAChC,CAAC;AACD,QAAM,SAAS,IAAI;AAAA,IACjB,SAAS,IAAI,CAAC,YAAY,CAAC,QAAQ,YAAY,OAAO,CAAC;AAAA,EACzD;AACA,aAAW,WAAW,OAAO,OAAO,OAAO,YAAY,GAAG;AACxD,UAAM,QAAQ,OAAO,IAAI,QAAQ,iBAAiB;AAClD,QAAI,CAAC,SAAS,MAAM,WAAW,SAAS;AACtC,YAAM,IAAI;AAAA,QACR,0BAA0B,QAAQ,iBAAiB;AAAA,MACrD;AAAA,IACF;AACA,QACE,MAAM,gBAAgB,SAAS,KAC/B,CAAC,MAAM,gBAAgB,KAAK,CAAC,UAAU,MAAM,OAAO,QAAQ,KAAK,GACjE;AACA,YAAM,IAAI;AAAA,QACR,0BAA0B,QAAQ,iBAAiB,gCAAgC,QAAQ,KAAK;AAAA,MAClG;AAAA,IACF;AAAA,EACF;AACA,QAAM;AAAA,IACJ;AAAA,MACE,iBAAiB,OAAO;AAAA,MACxB,eAAe,OAAO;AAAA,MACtB;AAAA,MACA,gBAAgB,OAAO;AAAA,MACvB,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO;AAAA,MACpB,YAAY;AAAA,MACZ,WAAW,EAAE,OAAO,OAAO,gBAAgB,UAAU,OAAO,SAAS;AAAA,MACrE;AAAA,MACA,cAAc,OAAO;AAAA,MACrB,wBAAwB;AAAA,QACtB,GAAG,IAAI;AAAA,UACL,OAAO,OAAO,OAAO,YAAY,EAC9B,OAAO,CAAC,YAAY,QAAQ,uBAAuB,EACnD,IAAI,CAAC,YAAY;AAAA,YAChB,QAAQ;AAAA,YACR;AAAA,cACE,cAAc,QAAQ;AAAA,cACtB,mBAAmB,QAAQ;AAAA,YAC7B;AAAA,UACF,CAAC;AAAA,QACL,EAAE,OAAO;AAAA,MACX;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU,CAAC,MAAM,SACf,cAAc,OAAO,gBAAgB,MAAM,IAAI;AAAA,IACnD;AAAA,EACF;AACA,QAAM,iBAAiB;AAAA,IACrB,IAAI,IAAI,wBAAwB,YAAY,GAAG;AAAA,EACjD;AACA,QAAM,QAAQ,MAAM,QAAQ,UAAU,CAAC,cAAc,GAAG;AAAA,IACtD,KAAK,kBAAkB,QAAQ,YAAY,IAAI;AAAA,IAC/C,OAAO;AAAA,EACT,CAAC;AACD,QAAM,EAAE,WAAW,UAAU,IAAI;AAAA,IAAoB,CAAC,WACpD,MAAM,KAAK,MAAM;AAAA,EACnB;AACA,UAAQ,KAAK,UAAU,SAAS;AAChC,UAAQ,KAAK,WAAW,SAAS;AACjC,MAAI;AACF,WAAO,MAAM,IAAI,QAAgB,CAAC,SAAS,WAAW;AACpD,YAAM,KAAK,SAAS,MAAM;AAC1B,YAAM,KAAK,QAAQ,CAAC,MAAM,WAAW,QAAQ,SAAS,SAAS,IAAI,EAAE,CAAC;AAAA,IACxE,CAAC;AAAA,EACH,UAAE;AACA,YAAQ,IAAI,UAAU,SAAS;AAC/B,YAAQ,IAAI,WAAW,SAAS;AAAA,EAClC;AACF;AAEA,SAAS,WAAW,MAAgB,MAAkC;AACpE,QAAM,KAAK,KAAK,QAAQ,IAAI;AAC5B,SAAO,MAAM,IAAI,KAAK,KAAK,CAAC,IAAI;AAClC;AAEA,eAAe,gBAAgB,MAAM,IAAI,OAAO,MAAuB;AACrE,QAAM,SAAmB,CAAC;AAC1B,MAAI,QAAQ;AACZ,mBAAiB,SAAS,QAAQ,OAAO;AACvC,UAAM,SAAS,OAAO,KAAK,KAAK;AAChC,aAAS,OAAO;AAChB,QAAI,QAAQ;AACV,YAAM,IAAI,MAAM,4CAA4C;AAC9D,WAAO,KAAK,MAAM;AAAA,EACpB;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM;AAC9C;AAEA,eAAe,cACb,SACA,MACA,MACkC;AAClC,QAAM,WAAW,MAAM,MAAM,IAAI,IAAI,MAAM,OAAO,GAAG;AAAA,IACnD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,IACzB,QAAQ,YAAY,QAAQ,GAAM;AAAA,EACpC,CAAC;AACD,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,GAAG,IAAI,qCAAqC,SAAS,MAAM;AAAA,IAC7D;AAAA,EACF;AACA,QAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,UAAM,IAAI,MAAM,GAAG,IAAI,2BAA2B;AAAA,EACpD;AACA,SAAO;AACT;AAEA,eAAsB,KACpB,OAAiB,QAAQ,KAAK,MAAM,CAAC,GACpB;AACjB,QAAM,UAAU,KAAK,CAAC;AAGtB,MAAI,YAAY,eAAe,YAAY,MAAM;AAC/C,YAAQ,OAAO,MAAM,GAAG,cAAc;AAAA,CAAI;AAC1C,WAAO;AAAA,EACT;AACA,MAAI,YAAY,WAAW;AACzB,QAAI,KAAK,SAAS,QAAQ,GAAG;AAC3B,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,sBAAsB,CAAC,CAAC;AAAA,CAAI;AAAA,IACrE,OAAO;AACL,cAAQ,OAAO,MAAM,GAAG,cAAc;AAAA,CAAI;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AACA,MAAI,YAAY,WAAW,KAAK,SAAS,QAAQ,GAAG;AAClD,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,4BAAuB;AACnE,UAAM,EAAE,kBAAkB,oBAAoB,IAAI,MAAM,OACtD,6BACF;AACA,UAAM,CAAC,UAAU,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC3C,mBAAmB;AAAA,QACjB,YAAY,WAAW,MAAM,eAAe;AAAA,QAC5C,WAAW,WAAW,MAAM,cAAc;AAAA,MAC5C,CAAC;AAAA,MACD,oBAAoB,iBAAiB,CAAC;AAAA,IACxC,CAAC;AACD,YAAQ,OAAO;AAAA,MACb,GAAG,KAAK,UAAU,EAAE,GAAG,sBAAsB,GAAG,UAAU,OAAO,CAAC,CAAC;AAAA;AAAA,IACrE;AACA,WAAO,SAAS,KAAK,CAAC,YAAY,QAAQ,WAAW,OAAO,IAAI,IAAI;AAAA,EACtE;AACA,MAAI,YAAY,iBAAiB,KAAK,SAAS,cAAc,GAAG;AAC9D,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,4BAAuB;AACjE,UAAM,SAAS,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACjD,QAAI,OAAO,oBAAoB,yBAAyB;AACtD,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AACA,UAAM,SAAS,MAAM,iBAAiB,QAAQ;AAAA,MAC5C,UAAU,CAAC,MAAM,SACf,cAAc,OAAO,gBAAgB,MAAM,IAAI;AAAA,IACnD,CAAC;AACD,YAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,CAAC;AAAA,CAAI;AAClD,WAAO;AAAA,EACT;AACA,MAAI,YAAY,OAAO;AACrB,WAAO,oBAAoB,KAAK,SAAS,QAAQ,CAAC;AAAA,EACpD;AAKA,MACE,YAAY,kBACX,KAAK,SAAS,cAAc,KAAK,KAAK,SAAS,aAAa,IAC7D;AACA,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,4BAAuB;AAC/D,QAAI;AACJ,UAAM,WAAW,WAAW,MAAM,aAAa;AAC/C,QAAI,UAAU;AACZ,YAAM,EAAE,cAAc,WAAW,IAAI,MAAM,OAAO,SAAS;AAC3D,YAAM,aAAa,UAAU,MAAM;AACnC,UAAI;AACF,mBAAW,QAAQ;AAAA,MACrB,QAAQ;AAAA,MAER;AAAA,IACF,OAAO;AACL,YAAM,MAAM,gBAAgB;AAAA,IAC9B;AACA,UAAM,OAAO,KAAK,MAAM,GAAG;AAI3B,QAAI,KAAK,oBAAoB,yBAAyB;AACpD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,QAAI,KAAK,aAAa,YAAY,KAAK,aAAa,SAAS;AAC3D,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AACA,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAGA,MAAI,YAAY,gBAAgB;AAG9B,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,gCAA2B;AAGpE,UAAM,MACJ,WAAW,MAAM,OAAO,KACxB,eAAe,WAAW,MAAM,YAAY,KAAK,IAAI;AACvD,UAAM,QAAQ,WAAW,MAAM,SAAS,KAAK;AAC7C,QAAI,CAAC;AACH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AACF,oBAAgB,KAAK,OAAO,MAAM,gBAAgB,CAAC;AACnD,WAAO;AAAA,EACT;AACA,UAAQ,OAAO;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAwB;AAC/B,MAAI;AACF,WACE,aAAa,QAAQ,KAAK,CAAC,KAAK,EAAE,MAClC,aAAa,cAAc,YAAY,GAAG,CAAC;AAAA,EAE/C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAI,aAAa,GAAG;AAClB,OAAK,EAAE;AAAA,IACL,CAAC,SAAS;AACR,cAAQ,WAAW;AAAA,IACrB;AAAA,IACA,CAAC,UAAU;AACT,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,cAAQ,OAAO;AAAA,QACb,kBAAkB,KAAK,OAAO,IAC1B,GAAG,OAAO;AAAA,IACV;AAAA,MACN;AACA,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RUNNER_VERSION
3
- } from "./chunk-TWNBYXS6.js";
3
+ } from "./chunk-HN5DR7DX.js";
4
4
  import {
5
5
  appendHookEvent,
6
6
  readHookLines,
@@ -2001,4 +2001,4 @@ export {
2001
2001
  safeParse,
2002
2002
  sessionCallTool
2003
2003
  };
2004
- //# sourceMappingURL=session-host-6VFDGKBT.js.map
2004
+ //# sourceMappingURL=session-host-ELAJLLL4.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RUNNER_VERSION
3
- } from "./chunk-TWNBYXS6.js";
3
+ } from "./chunk-HN5DR7DX.js";
4
4
 
5
5
  // workflow-runner.ts
6
6
  import { createHmac, timingSafeEqual } from "node:crypto";
@@ -6351,7 +6351,7 @@ function stampSchemaRevision() {
6351
6351
  process.env.STACKS_SCHEMA_REVISION = "20260906000000_session_review_taxonomy_gap_issue";
6352
6352
  }
6353
6353
  if (!process.env.STACKS_APP_REVISION && true) {
6354
- process.env.STACKS_APP_REVISION = "5461b4a8a34c60cd33713ad57a13f0e39267eee5";
6354
+ process.env.STACKS_APP_REVISION = "412549b403d4d97d4de43f117eb51acd9eed371a";
6355
6355
  }
6356
6356
  const resolved = resolveSchemaRevision(process.env, (p) => readdirSync(p));
6357
6357
  if (resolved.source === "migrations" && resolved.revision) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jentrix/runner",
3
- "version": "0.5.12",
3
+ "version": "0.5.14",
4
4
  "type": "module",
5
5
  "description": "The distributable self-hosted workflow runner for Jentrix.",
6
6
  "bin": {
@@ -1,7 +0,0 @@
1
- // lib/version.ts
2
- var RUNNER_VERSION = "0.5.12";
3
-
4
- export {
5
- RUNNER_VERSION
6
- };
7
- //# sourceMappingURL=chunk-TWNBYXS6.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../lib/local-probes.ts"],
4
- "sourcesContent": ["import { execFile, spawn } from \"node:child_process\";\nimport { constants, promises as fs } from \"node:fs\";\nimport { delimiter, extname, isAbsolute, resolve } from \"node:path\";\n\nimport { query, type SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\n\nconst PROBE_TIMEOUT_MS = 25_000;\nconst OUTPUT_CAP_BYTES = 1024 * 1024;\nconst PROBE_SCRUBBED_ENV_KEYS = new Set([\n \"STACKS_TOKEN\",\n \"STACKS_RUNNER_TOKEN\",\n \"STACKS_PLANNER_TOKEN\",\n \"STACKS_REVIEWER_TOKEN\",\n \"STACKS_WEBHOOK_SECRET\",\n \"STACKS_BOOTSTRAP_TOKEN\",\n \"STACKS_CLAIM_URL\",\n \"STACKS_RUNNER_AUTH_STATE\",\n \"STACKS_WORKER_HEARTBEAT_TOKEN\",\n \"STACKS_RUNNER_ROLE_BINDINGS\",\n]);\n\nexport function providerProbeEnv(\n env: NodeJS.ProcessEnv,\n adapter?: \"claude\" | \"codex\",\n): NodeJS.ProcessEnv {\n return Object.fromEntries(\n Object.entries(env).filter(\n ([key, value]) =>\n value !== undefined &&\n !PROBE_SCRUBBED_ENV_KEYS.has(key) &&\n !(adapter === \"codex\" && key === \"ANTHROPIC_API_KEY\"),\n ),\n );\n}\n\nexport type LocalRuntimeStatus =\n | \"ready\"\n | \"missing\"\n | \"auth_required\"\n | \"installed_unverified\"\n | \"incompatible\"\n | \"timeout\"\n | \"failed\";\n\nexport interface LocalRuntimeProbe {\n adapterKey: \"claude\" | \"codex\";\n status: LocalRuntimeStatus;\n binaryPath: string | null;\n version: string | null;\n authMethod: \"subscription\" | \"api_key\" | \"unknown\";\n availableModels: Array<{ id: string; displayName?: string }>;\n selectedModel: string | null;\n capabilitySource: \"local_rpc\" | \"sdk_init\" | \"cli_status\" | \"none\";\n checkedAt: string;\n blocker: { code: string; message: string; nextCommand?: string } | null;\n}\n\nexport interface ReadOnlyCapabilityResult {\n authenticated: boolean;\n authMethod: LocalRuntimeProbe[\"authMethod\"];\n availableModels: LocalRuntimeProbe[\"availableModels\"];\n selectedModel: string | null;\n compatible?: boolean;\n}\n\nexport interface RunFileResult {\n code: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface LocalProbeDeps {\n env: NodeJS.ProcessEnv;\n now(): Date;\n resolveExecutable(\n name: \"claude\" | \"codex\",\n override?: string,\n ): Promise<string | null>;\n runFile(file: string, args: string[]): Promise<RunFileResult>;\n probeClaudeInit(file: string): Promise<ReadOnlyCapabilityResult>;\n probeCodexRpc(file: string): Promise<ReadOnlyCapabilityResult>;\n}\n\nexport interface LocalProbeOptions {\n claudePath?: string;\n codexPath?: string;\n}\n\nfunction probeError(code: string, message: string): Error {\n return Object.assign(new Error(message), { code });\n}\n\nfunction errorCode(error: unknown): string | null {\n return typeof error === \"object\" && error !== null && \"code\" in error\n ? String((error as { code: unknown }).code)\n : null;\n}\n\nasync function executableAt(path: string): Promise<string | null> {\n try {\n await fs.access(path, constants.X_OK);\n return await fs.realpath(path);\n } catch {\n return null;\n }\n}\n\nexport async function resolveExecutable(\n name: \"claude\" | \"codex\",\n override: string | undefined,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<string | null> {\n if (override) {\n if (!isAbsolute(override)) return null;\n return executableAt(override);\n }\n const extensions =\n process.platform === \"win32\"\n ? (env.PATHEXT ?? \".EXE;.CMD;.BAT\").split(\";\")\n : [\"\"];\n for (const dir of (env.PATH ?? \"\").split(delimiter)) {\n if (!dir) continue;\n for (const extension of extensions) {\n const candidate = resolve(\n dir,\n process.platform === \"win32\" && !extname(name)\n ? `${name}${extension.toLowerCase()}`\n : name,\n );\n const found = await executableAt(candidate);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport function runFileBounded(\n file: string,\n args: string[],\n env: NodeJS.ProcessEnv = process.env,\n): Promise<RunFileResult> {\n if (!isAbsolute(file)) {\n return Promise.reject(new Error(\"probe executable path must be absolute\"));\n }\n return new Promise((resolveResult, reject) => {\n execFile(\n file,\n args,\n {\n env,\n timeout: PROBE_TIMEOUT_MS,\n maxBuffer: OUTPUT_CAP_BYTES,\n windowsHide: true,\n },\n (error, stdout, stderr) => {\n if (error && (error.killed || errorCode(error) === \"ETIMEDOUT\")) {\n reject(probeError(\"PROBE_TIMEOUT\", \"local runtime probe timed out\"));\n return;\n }\n if (error && errorCode(error) === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\") {\n reject(new Error(\"local runtime probe exceeded its output limit\"));\n return;\n }\n resolveResult({\n code:\n typeof (error as { code?: unknown } | null)?.code === \"number\"\n ? Number((error as { code: number }).code)\n : 0,\n stdout: String(stdout).slice(0, OUTPUT_CAP_BYTES),\n stderr: String(stderr).slice(0, OUTPUT_CAP_BYTES),\n });\n },\n );\n });\n}\n\nfunction cleanModels(value: unknown): LocalRuntimeProbe[\"availableModels\"] {\n if (!Array.isArray(value)) return [];\n const out: LocalRuntimeProbe[\"availableModels\"] = [];\n const seen = new Set<string>();\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n const row = item as Record<string, unknown>;\n const id = [row.id, row.model, row.slug, row.value]\n .find((v): v is string => typeof v === \"string\" && v.trim().length > 0)\n ?.trim();\n if (!id || seen.has(id)) continue;\n seen.add(id);\n const displayName = [row.displayName, row.display_name, row.name].find(\n (v): v is string => typeof v === \"string\" && v.trim().length > 0,\n );\n out.push({\n id,\n ...(displayName ? { displayName: displayName.trim() } : {}),\n });\n }\n return out;\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nasync function waitForAbort(signal: AbortSignal): Promise<void> {\n if (signal.aborted) return;\n await new Promise<void>((resolveAbort) =>\n signal.addEventListener(\"abort\", () => resolveAbort(), { once: true }),\n );\n}\n\nexport async function probeClaudeInit(\n executablePath: string,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<ReadOnlyCapabilityResult> {\n const abort = new AbortController();\n const session = query({\n // A never-yielding prompt lets the SDK finish local initialization without\n // ever writing a user message or starting a provider request.\n prompt: (async function* (): AsyncGenerator<SDKUserMessage> {\n await waitForAbort(abort.signal);\n })(),\n options: {\n persistSession: false,\n pathToClaudeCodeExecutable: executablePath,\n abortController: abort,\n settingSources: [],\n allowedTools: [],\n mcpServers: {},\n strictMcpConfig: true,\n env: { ...env, ENABLE_CLAUDEAI_MCP_SERVERS: \"false\" },\n stderr: () => {},\n },\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n const init = await Promise.race([\n session.initializationResult(),\n new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(probeError(\"PROBE_TIMEOUT\", \"Claude probe timed out\")),\n PROBE_TIMEOUT_MS,\n );\n }),\n ]);\n const account = init.account;\n const authMethod = account?.apiKeySource\n ? \"api_key\"\n : account?.subscriptionType ||\n account?.tokenSource ||\n account?.apiProvider\n ? \"subscription\"\n : \"unknown\";\n const models = cleanModels(init.models);\n return {\n authenticated: authMethod !== \"unknown\",\n authMethod,\n availableModels: models,\n selectedModel: models[0]?.id ?? null,\n };\n } finally {\n clearTimeout(timer);\n abort.abort();\n session.close();\n }\n}\n\nexport function probeCodexRpc(\n executablePath: string,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<ReadOnlyCapabilityResult> {\n if (!isAbsolute(executablePath)) {\n return Promise.reject(new Error(\"probe executable path must be absolute\"));\n }\n return new Promise((resolveProbe, rejectProbe) => {\n const child = spawn(executablePath, [\"app-server\"], {\n env,\n shell: false,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n windowsHide: true,\n });\n let outputBytes = 0;\n let buffer = \"\";\n let nextId = 1;\n let settled = false;\n const pending = new Map<\n number,\n { resolve(value: unknown): void; reject(error: Error): void }\n >();\n const finish = (error?: Error, value?: ReadOnlyCapabilityResult) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n for (const waiter of pending.values()) {\n waiter.reject(error ?? new Error(\"Codex app server stopped\"));\n }\n pending.clear();\n child.stdin.end();\n if (!child.killed) child.kill(\"SIGTERM\");\n if (error) rejectProbe(error);\n else resolveProbe(value!);\n };\n const timer = setTimeout(\n () => finish(probeError(\"PROBE_TIMEOUT\", \"Codex probe timed out\")),\n PROBE_TIMEOUT_MS,\n );\n const request = (method: string, params: unknown): Promise<unknown> => {\n const id = nextId++;\n return new Promise((resolveRequest, rejectRequest) => {\n pending.set(id, { resolve: resolveRequest, reject: rejectRequest });\n child.stdin.write(\n `${JSON.stringify({ jsonrpc: \"2.0\", id, method, params })}\\n`,\n );\n });\n };\n const onBytes = (chunk: Buffer, protocol: boolean) => {\n outputBytes += chunk.byteLength;\n if (outputBytes > OUTPUT_CAP_BYTES) {\n finish(new Error(\"Codex probe exceeded its output limit\"));\n return;\n }\n if (!protocol) return;\n buffer += chunk.toString(\"utf8\");\n for (;;) {\n const newline = buffer.indexOf(\"\\n\");\n if (newline < 0) break;\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n if (!line) continue;\n try {\n const message = JSON.parse(line) as Record<string, unknown>;\n if (typeof message.id !== \"number\") continue;\n const waiter = pending.get(message.id);\n if (!waiter) continue;\n pending.delete(message.id);\n if (message.error)\n waiter.reject(new Error(\"Codex RPC method failed\"));\n else waiter.resolve(message.result);\n } catch {\n finish(new Error(\"Codex app server returned malformed JSON\"));\n }\n }\n };\n child.stdout.on(\"data\", (chunk: Buffer) => onBytes(chunk, true));\n child.stderr.on(\"data\", (chunk: Buffer) => onBytes(chunk, false));\n child.once(\"error\", (error) => finish(error));\n child.once(\"exit\", () => {\n if (!settled) finish(new Error(\"Codex app server exited during probe\"));\n });\n\n void (async () => {\n await request(\"initialize\", {\n clientInfo: {\n name: \"stacks_runner_probe\",\n title: \"Jentrix Runner\",\n version: \"1\",\n },\n capabilities: { experimentalApi: true },\n });\n child.stdin.write(\n `${JSON.stringify({ jsonrpc: \"2.0\", method: \"initialized\" })}\\n`,\n );\n const accountResult = record(await request(\"account/read\", {}));\n const account = record(accountResult?.account);\n if (!account && accountResult?.requiresOpenaiAuth === true) {\n finish(undefined, {\n authenticated: false,\n authMethod: \"unknown\",\n availableModels: [],\n selectedModel: null,\n });\n return;\n }\n const modelResult = record(await request(\"model/list\", {}));\n const models = cleanModels(modelResult?.data ?? modelResult?.models);\n const authType = String(account?.type ?? \"\").toLowerCase();\n finish(undefined, {\n authenticated: Boolean(account),\n authMethod: /api/.test(authType)\n ? \"api_key\"\n : account\n ? \"subscription\"\n : \"unknown\",\n availableModels: models,\n selectedModel:\n models.find((model) => {\n const source = Array.isArray(modelResult?.data)\n ? (modelResult!.data as Array<Record<string, unknown>>)\n : [];\n return source.some(\n (row) =>\n (row.id === model.id || row.model === model.id) &&\n (row.isDefault === true || row.is_default === true),\n );\n })?.id ?? null,\n });\n })().catch((error) =>\n finish(error instanceof Error ? error : new Error(String(error))),\n );\n });\n}\n\nfunction versionOf(output: string): string | null {\n return output.match(/\\b\\d+\\.\\d+(?:\\.\\d+)?(?:[-+][\\w.-]+)?\\b/)?.[0] ?? null;\n}\n\nfunction blocker(\n code: string,\n message: string,\n nextCommand?: string,\n): LocalRuntimeProbe[\"blocker\"] {\n return { code, message, ...(nextCommand ? { nextCommand } : {}) };\n}\n\nasync function cliAuthFallback(\n adapter: \"claude\" | \"codex\",\n file: string,\n runFile: LocalProbeDeps[\"runFile\"],\n): Promise<\"authenticated\" | \"required\" | \"unknown\"> {\n const args =\n adapter === \"claude\" ? [\"auth\", \"status\", \"--json\"] : [\"login\", \"status\"];\n try {\n const result = await runFile(file, args);\n const text = `${result.stdout}\\n${result.stderr}`.toLowerCase();\n if (\n /not logged|login required|authentication required|\"loggedin\"\\s*:\\s*false/.test(\n text,\n )\n ) {\n return \"required\";\n }\n if (\n result.code === 0 &&\n /logged in|authenticated|\"loggedin\"\\s*:\\s*true/.test(text)\n ) {\n return \"authenticated\";\n }\n return \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nasync function probeRuntime(\n adapterKey: \"claude\" | \"codex\",\n override: string | undefined,\n deps: LocalProbeDeps,\n): Promise<LocalRuntimeProbe> {\n const checkedAt = deps.now().toISOString();\n const nextCommand =\n adapterKey === \"claude\" ? \"claude auth login\" : \"codex login\";\n const binaryPath = await deps.resolveExecutable(adapterKey, override);\n const base = {\n adapterKey,\n binaryPath,\n version: null,\n authMethod: \"unknown\" as const,\n availableModels: [],\n selectedModel: null,\n capabilitySource: \"none\" as const,\n checkedAt,\n };\n if (!binaryPath) {\n return {\n ...base,\n status: \"missing\",\n blocker: blocker(\n \"BINARY_NOT_FOUND\",\n `${adapterKey === \"claude\" ? \"Claude Code\" : \"Codex\"} is not installed or the configured path is not executable.`,\n `Install ${adapterKey === \"claude\" ? \"Claude Code\" : \"Codex\"} manually, then run jentrix runner doctor`,\n ),\n };\n }\n let version: string | null = null;\n try {\n const result = await deps.runFile(binaryPath, [\"--version\"]);\n version = versionOf(`${result.stdout}\\n${result.stderr}`);\n if (result.code !== 0 || !version) {\n return {\n ...base,\n binaryPath,\n status: \"failed\",\n blocker: blocker(\n \"VERSION_PROBE_FAILED\",\n `The ${adapterKey} executable ran but did not report a usable version.`,\n `Update ${adapterKey} manually, then run jentrix runner doctor`,\n ),\n };\n }\n } catch (error) {\n return {\n ...base,\n binaryPath,\n status: errorCode(error) === \"PROBE_TIMEOUT\" ? \"timeout\" : \"failed\",\n blocker: blocker(\n errorCode(error) === \"PROBE_TIMEOUT\"\n ? \"VERSION_PROBE_FAILED\"\n : \"VERSION_PROBE_FAILED\",\n `The ${adapterKey} version probe ${errorCode(error) === \"PROBE_TIMEOUT\" ? \"timed out\" : \"failed\"}.`,\n \"jentrix runner doctor\",\n ),\n };\n }\n\n try {\n const evidence = await (adapterKey === \"claude\"\n ? deps.probeClaudeInit(binaryPath)\n : deps.probeCodexRpc(binaryPath));\n if (evidence.compatible === false) {\n return {\n ...base,\n binaryPath,\n version,\n status: \"incompatible\",\n blocker: blocker(\n \"RUNTIME_INCOMPATIBLE\",\n `The installed ${adapterKey} runtime lacks the required read-only capability protocol.`,\n `Update ${adapterKey} manually, then run jentrix runner doctor`,\n ),\n };\n }\n if (!evidence.authenticated) {\n return {\n ...base,\n binaryPath,\n version,\n status: \"auth_required\",\n capabilitySource: adapterKey === \"claude\" ? \"sdk_init\" : \"local_rpc\",\n blocker: blocker(\n \"AUTH_REQUIRED\",\n `The local ${adapterKey} login is absent or expired.`,\n nextCommand,\n ),\n };\n }\n if (evidence.availableModels.length === 0) {\n return {\n ...base,\n binaryPath,\n version,\n authMethod: evidence.authMethod,\n status: \"installed_unverified\",\n capabilitySource: adapterKey === \"claude\" ? \"sdk_init\" : \"local_rpc\",\n blocker: blocker(\n \"AUTH_UNVERIFIED\",\n `The local ${adapterKey} probe could not prove a usable model without making a model request.`,\n nextCommand,\n ),\n };\n }\n return {\n ...base,\n binaryPath,\n version,\n authMethod: evidence.authMethod,\n availableModels: evidence.availableModels,\n selectedModel: evidence.selectedModel,\n status: \"ready\",\n capabilitySource: adapterKey === \"claude\" ? \"sdk_init\" : \"local_rpc\",\n blocker: null,\n };\n } catch (error) {\n if (errorCode(error) === \"PROBE_TIMEOUT\") {\n return {\n ...base,\n binaryPath,\n version,\n status: \"timeout\",\n blocker: blocker(\n \"RUNTIME_INCOMPATIBLE\",\n `The ${adapterKey} read-only capability probe timed out.`,\n \"jentrix runner doctor\",\n ),\n };\n }\n const fallback = await cliAuthFallback(\n adapterKey,\n binaryPath,\n deps.runFile,\n );\n if (fallback === \"required\") {\n return {\n ...base,\n binaryPath,\n version,\n status: \"auth_required\",\n capabilitySource: \"cli_status\",\n blocker: blocker(\n \"AUTH_REQUIRED\",\n `The local ${adapterKey} login is absent or expired.`,\n nextCommand,\n ),\n };\n }\n return {\n ...base,\n binaryPath,\n version,\n status: \"installed_unverified\",\n capabilitySource: fallback === \"authenticated\" ? \"cli_status\" : \"none\",\n blocker: blocker(\n \"AUTH_UNVERIFIED\",\n `The installed ${adapterKey} version cannot prove readiness without a model request.`,\n nextCommand,\n ),\n };\n }\n}\n\nexport function defaultLocalProbeDeps(\n env: NodeJS.ProcessEnv = process.env,\n): LocalProbeDeps {\n const safeEnv = providerProbeEnv(env);\n return {\n env,\n now: () => new Date(),\n resolveExecutable: (name, override) =>\n resolveExecutable(name, override, env),\n runFile: (file, args) => runFileBounded(file, args, safeEnv),\n probeClaudeInit: (file) =>\n probeClaudeInit(file, providerProbeEnv(env, \"claude\")),\n probeCodexRpc: (file) =>\n probeCodexRpc(file, providerProbeEnv(env, \"codex\")),\n };\n}\n\nexport async function probeLocalRuntimes(\n options: LocalProbeOptions = {},\n deps: LocalProbeDeps = defaultLocalProbeDeps(),\n): Promise<LocalRuntimeProbe[]> {\n return Promise.all([\n probeRuntime(\"claude\", options.claudePath, deps),\n probeRuntime(\"codex\", options.codexPath, deps),\n ]);\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }