skill-codex 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # skill-codex
2
2
 
3
- ![npm](https://img.shields.io/npm/v/skill-codex)
3
+ [![npm version](https://img.shields.io/npm/v/skill-codex)](https://www.npmjs.com/package/skill-codex)
4
+ [![npm downloads](https://img.shields.io/npm/dm/skill-codex)](https://www.npmjs.com/package/skill-codex)
4
5
  ![CI](https://github.com/Arystos/skill-codex/actions/workflows/ci.yml/badge.svg)
5
6
  ![Windows](https://img.shields.io/badge/Windows-0078D4?style=flat&logo=windows&logoColor=white)
6
7
  ![macOS](https://img.shields.io/badge/macOS-000000?style=flat&logo=apple&logoColor=white)
@@ -31,12 +32,14 @@ Claude Code and Codex CLI have different strengths. Claude excels at reasoning,
31
32
  ## Quick Start
32
33
 
33
34
  ```shell
34
- # 1. Install and configure everything in one command
35
+ # Option A: Run directly (no global install)
35
36
  npx skill-codex setup
36
37
 
37
- # 2. Restart Claude Code to load the MCP server
38
+ # Option B: Install globally, then setup
39
+ npm i -g skill-codex
40
+ skill-codex setup
38
41
 
39
- # 3. Use the commands in any project
42
+ # Restart Claude Code to load the MCP server, then use:
40
43
  /codex-review # Review uncommitted changes
41
44
  /codex-do "write tests" # Delegate a task to Codex
42
45
  /codex-consult "approach?" # Get a second opinion
@@ -115,7 +118,7 @@ Environment variables (all optional):
115
118
  | Auth expired | Advises `codex login`, no retry |
116
119
  | Network down | Retries 3x with exponential backoff |
117
120
  | Rate limited (429) | Retries with backoff + jitter |
118
- | Codex hangs | Killed after timeout (SIGTERM then SIGKILL) |
121
+ | Codex hangs | Killed after timeout (SIGTERM+SIGKILL on Unix, immediate kill on Windows) |
119
122
  | Concurrent runs | Lock file prevents conflicts (stale after 15min) |
120
123
  | Recursive calls | `SKILL_CODEX_DEPTH` limit prevents infinite loops |
121
124
  | Trivial changes | Smart filter skips auto-review |
package/dist/index.js CHANGED
@@ -184,7 +184,7 @@ async function checkAuth() {
184
184
  const child = execFile(
185
185
  binary,
186
186
  ["exec", "--sandbox", "read-only", "--skip-git-repo-check", "--ephemeral", "echo ok"],
187
- { timeout: 15e3 },
187
+ { timeout: 3e4, shell: process.platform === "win32" },
188
188
  (error, _stdout, stderr) => {
189
189
  if (!error) {
190
190
  authCachedAt = Date.now();
@@ -322,7 +322,7 @@ function checkGit(cwd) {
322
322
  async function runPreflight(options) {
323
323
  checkRecursion();
324
324
  await checkBinary();
325
- if (!options.skipAuth) {
325
+ if (!options.skipAuth && process.platform !== "win32") {
326
326
  await checkAuth();
327
327
  }
328
328
  let lockHandle = null;
@@ -399,10 +399,20 @@ function parseCodexOutput(raw) {
399
399
  }
400
400
  const lines = raw.split("\n").filter((line) => line.trim());
401
401
  const messages = [];
402
+ const activity = [];
402
403
  let resultContent = null;
404
+ let usage = null;
403
405
  for (const line of lines) {
404
406
  try {
405
407
  const parsed = JSON.parse(line);
408
+ if (parsed.type === "turn.completed" && parsed.usage) {
409
+ usage = {
410
+ input_tokens: parsed.usage.input_tokens ?? 0,
411
+ cached_input_tokens: parsed.usage.cached_input_tokens ?? 0,
412
+ output_tokens: parsed.usage.output_tokens ?? 0
413
+ };
414
+ continue;
415
+ }
406
416
  if (parsed.type === "result" && typeof parsed.content === "string") {
407
417
  resultContent = parsed.content;
408
418
  continue;
@@ -411,6 +421,21 @@ function parseCodexOutput(raw) {
411
421
  messages.push(parsed.content);
412
422
  continue;
413
423
  }
424
+ if (parsed.item?.type === "command_execution") {
425
+ const cmd = parsed.item;
426
+ const shortCmd = cmd.command?.length > 80 ? cmd.command.slice(0, 77) + "..." : cmd.command;
427
+ const statusIcon = cmd.status === "declined" ? "\u2718" : cmd.exit_code === 0 ? "\u2714" : cmd.exit_code !== null ? "\u2718" : "\u25B6";
428
+ const statusLabel = cmd.status === "declined" ? "blocked" : cmd.status === "in_progress" ? "running" : cmd.exit_code === 0 ? "ok" : `exit ${cmd.exit_code}`;
429
+ if (cmd.status !== "in_progress") {
430
+ activity.push({
431
+ type: "exec",
432
+ command: shortCmd,
433
+ icon: statusIcon,
434
+ status: statusLabel
435
+ });
436
+ }
437
+ continue;
438
+ }
414
439
  if (parsed.item?.type === "agent_message" && typeof parsed.item.text === "string") {
415
440
  messages.push(parsed.item.text);
416
441
  continue;
@@ -419,6 +444,24 @@ function parseCodexOutput(raw) {
419
444
  messages.push(parsed.text);
420
445
  continue;
421
446
  }
447
+ if (parsed.item?.type === "file_read") {
448
+ activity.push({
449
+ type: "read",
450
+ path: parsed.item.path || "file",
451
+ icon: "\u25B6",
452
+ status: "read"
453
+ });
454
+ continue;
455
+ }
456
+ if (parsed.item?.type === "file_write" || parsed.item?.type === "file_edit") {
457
+ activity.push({
458
+ type: "write",
459
+ path: parsed.item.path || "file",
460
+ icon: "\u270E",
461
+ status: "write"
462
+ });
463
+ continue;
464
+ }
422
465
  } catch {
423
466
  }
424
467
  }
@@ -438,6 +481,8 @@ function parseCodexOutput(raw) {
438
481
  }
439
482
  return {
440
483
  content: truncateResponse(agentMessage),
484
+ activity,
485
+ usage,
441
486
  raw
442
487
  };
443
488
  }
@@ -495,7 +540,7 @@ async function execCodex(params) {
495
540
  cwd: params.cwd,
496
541
  env,
497
542
  stdio: ["pipe", "pipe", "pipe"],
498
- shell: false,
543
+ shell: process.platform === "win32",
499
544
  windowsHide: true
500
545
  });
501
546
  const { clear: clearTimeout_, promise: timeoutPromise } = setupTimeout(child, timeoutMs);
@@ -602,6 +647,32 @@ function formatError(err) {
602
647
  }
603
648
  return `[skill-codex error] Unknown error: ${String(err)}`;
604
649
  }
650
+ function formatRichResponse(result, input, cwd) {
651
+ const lines = [];
652
+ const modeLabel = input.mode === "full-auto" ? "full-auto" : "read-only";
653
+ const metaParts = [modeLabel, cwd];
654
+ if (result.usage) {
655
+ const { input_tokens: inp, output_tokens: out, cached_input_tokens: cached } = result.usage;
656
+ metaParts.push(
657
+ `${inp} tok in${cached > 0 ? ` (${cached} cached)` : ""} \u2192 ${out} out`
658
+ );
659
+ }
660
+ lines.push(`[${metaParts.join(" \u2502 ")}]`);
661
+ if (result.activity.length > 0) {
662
+ for (const a of result.activity) {
663
+ if (a.type === "exec") {
664
+ lines.push(` ${a.icon} exec: ${a.command} (${a.status})`);
665
+ } else if (a.type === "read") {
666
+ lines.push(` \u25B6 read: ${a.path}`);
667
+ } else if (a.type === "write") {
668
+ lines.push(` \u270E write: ${a.path}`);
669
+ }
670
+ }
671
+ }
672
+ lines.push("");
673
+ lines.push(result.content);
674
+ return lines.join("\n");
675
+ }
605
676
  async function handleCodexExec(input, serverCwd) {
606
677
  const rawCwd = input.cwd ?? serverCwd;
607
678
  const cwd = path3.resolve(rawCwd);
@@ -626,8 +697,9 @@ async function handleCodexExec(input, serverCwd) {
626
697
  timeoutMs: input.timeoutMs
627
698
  })
628
699
  );
700
+ const formatted = formatRichResponse(result, input, cwd);
629
701
  return {
630
- content: [{ type: "text", text: result.content }]
702
+ content: [{ type: "text", text: formatted }]
631
703
  };
632
704
  } catch (err) {
633
705
  return {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/tools/codex-exec.ts","../src/errors/errors.ts","../src/config/constants.ts","../src/guards/check-recursion.ts","../src/guards/check-binary.ts","../src/guards/check-auth.ts","../src/lock/lock-file.ts","../src/guards/check-lock.ts","../src/guards/check-git.ts","../src/guards/preflight.ts","../src/runner/exec-runner.ts","../src/util/platform.ts","../src/runner/timeout.ts","../src/util/truncate.ts","../src/runner/output-parser.ts","../src/runner/retry.ts","../src/index.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { TOOL_NAME, TOOL_DESCRIPTION, inputSchema, handleCodexExec } from \"./tools/codex-exec.js\";\n\nexport function createServer(cwd: string): Server {\n const server = new Server(\n { name: \"skill-codex\", version: \"0.2.0\" },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: TOOL_NAME,\n description: TOOL_DESCRIPTION,\n inputSchema: {\n type: \"object\" as const,\n properties: {\n prompt: { type: \"string\", description: \"The task description for Codex\" },\n mode: {\n type: \"string\",\n enum: [\"exec\", \"full-auto\"],\n default: \"exec\",\n description: \"exec = read-only, full-auto = can write files\",\n },\n cwd: { type: \"string\", description: \"Working directory (defaults to server cwd)\" },\n timeoutMs: { type: \"number\", description: \"Override default timeout in milliseconds\" },\n requireGit: {\n type: \"boolean\",\n default: false,\n description: \"Fail if not inside a git repository\",\n },\n },\n required: [\"prompt\"],\n },\n },\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n if (request.params.name !== TOOL_NAME) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${request.params.name}` }],\n isError: true,\n };\n }\n\n const parsed = inputSchema.safeParse(request.params.arguments);\n if (!parsed.success) {\n return {\n content: [\n {\n type: \"text\",\n text: `Invalid input: ${parsed.error.issues.map((i) => i.message).join(\", \")}`,\n },\n ],\n isError: true,\n };\n }\n\n return handleCodexExec(parsed.data, cwd);\n });\n\n return server;\n}\n\nexport async function startServer(): Promise<void> {\n const cwd = process.cwd();\n const server = createServer(cwd);\n const transport = new StdioServerTransport();\n\n process.stderr.write(\"[skill-codex] MCP server starting...\\n\");\n\n await server.connect(transport);\n\n process.stderr.write(\"[skill-codex] MCP server connected via stdio\\n\");\n\n process.on(\"uncaughtException\", (err) => {\n process.stderr.write(`[skill-codex] Uncaught exception: ${err.message}\\n`);\n });\n\n process.on(\"unhandledRejection\", (reason) => {\n process.stderr.write(`[skill-codex] Unhandled rejection: ${String(reason)}\\n`);\n });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { runPreflight } from \"../guards/preflight.js\";\nimport { execCodex } from \"../runner/exec-runner.js\";\nimport { withRetry } from \"../runner/retry.js\";\nimport { BridgeError } from \"../errors/errors.js\";\n\nexport const TOOL_NAME = \"codex_exec\";\n\nexport const TOOL_DESCRIPTION =\n \"Execute a task using OpenAI Codex CLI. Use for code review, implementation tasks, or getting a second opinion. Codex output is a SUGGESTION — evaluate it critically before applying.\";\n\nexport const inputSchema = z.object({\n prompt: z.string().describe(\"The task description for Codex\"),\n mode: z\n .enum([\"exec\", \"full-auto\"])\n .default(\"exec\")\n .describe(\"exec = read-only with confirmation, full-auto = can write files\"),\n cwd: z.string().optional().describe(\"Working directory (defaults to server cwd)\"),\n timeoutMs: z.number().optional().describe(\"Override default timeout in milliseconds\"),\n requireGit: z.boolean().default(false).describe(\"Fail if not inside a git repository\"),\n});\n\nexport type CodexExecInput = z.infer<typeof inputSchema>;\n\nfunction formatError(err: unknown): string {\n if (err instanceof BridgeError) {\n return `[skill-codex error: ${err.code}] ${err.message}`;\n }\n if (err instanceof Error) {\n return `[skill-codex error] ${err.message}`;\n }\n return `[skill-codex error] Unknown error: ${String(err)}`;\n}\n\nexport async function handleCodexExec(\n input: CodexExecInput,\n serverCwd: string,\n): Promise<{ content: Array<{ type: \"text\"; text: string }>; isError?: boolean }> {\n const rawCwd = input.cwd ?? serverCwd;\n const cwd = path.resolve(rawCwd);\n\n // Validate cwd is an existing directory (prevent path traversal to arbitrary locations)\n if (!fs.existsSync(cwd) || !fs.statSync(cwd).isDirectory()) {\n return {\n content: [{ type: \"text\", text: `[skill-codex error: INVALID_CWD] cwd is not an existing directory: ${cwd}` }],\n isError: true,\n };\n }\n\n let lockRelease: (() => void) | null = null;\n\n try {\n const { lockHandle } = await runPreflight({\n cwd,\n requireGit: input.requireGit,\n });\n lockRelease = lockHandle?.release ?? null;\n\n const result = await withRetry(() =>\n execCodex({\n prompt: input.prompt,\n cwd,\n mode: input.mode,\n timeoutMs: input.timeoutMs,\n }),\n );\n\n return {\n content: [{ type: \"text\", text: result.content }],\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: formatError(err) }],\n isError: true,\n };\n } finally {\n lockRelease?.();\n }\n}\n","export class BridgeError extends Error {\n readonly code: string;\n readonly retryable: boolean;\n\n constructor(message: string, code: string, retryable: boolean) {\n super(message);\n this.name = \"BridgeError\";\n this.code = code;\n this.retryable = retryable;\n }\n}\n\nexport class CliNotFoundError extends BridgeError {\n constructor(binary: string = \"codex\") {\n super(\n `${binary} CLI not found on PATH. Install it with: npm i -g @openai/codex`,\n \"CLI_NOT_FOUND\",\n false,\n );\n this.name = \"CliNotFoundError\";\n }\n}\n\nexport class AuthExpiredError extends BridgeError {\n constructor() {\n super(\n \"Codex authentication expired or not found. Run `codex login` to re-authenticate.\",\n \"AUTH_EXPIRED\",\n false,\n );\n this.name = \"AuthExpiredError\";\n }\n}\n\nexport class RecursionLimitError extends BridgeError {\n constructor(depth: number, max: number) {\n super(\n `Maximum bridge nesting depth reached (${depth} >= ${max}). This prevents infinite recursion between Claude and Codex.`,\n \"RECURSION_LIMIT\",\n false,\n );\n this.name = \"RecursionLimitError\";\n }\n}\n\nexport class LockConflictError extends BridgeError {\n constructor(pid: number) {\n super(\n `Another skill-codex instance is running (PID ${pid}). Wait for it to finish or delete the lock file.`,\n \"LOCK_CONFLICT\",\n false,\n );\n this.name = \"LockConflictError\";\n }\n}\n\nexport class TimeoutError extends BridgeError {\n constructor(timeoutMs: number) {\n super(\n `Codex timed out after ${Math.round(timeoutMs / 1000)}s. Increase SKILL_CODEX_TIMEOUT_MS if needed.`,\n \"TIMEOUT\",\n true,\n );\n this.name = \"TimeoutError\";\n }\n}\n\nexport class RateLimitError extends BridgeError {\n constructor() {\n super(\n \"Codex rate limited (429). Will retry with backoff.\",\n \"RATE_LIMIT\",\n true,\n );\n this.name = \"RateLimitError\";\n }\n}\n\nexport class ServerError extends BridgeError {\n constructor(detail: string = \"\") {\n super(\n `Codex server error${detail ? `: ${detail}` : \"\"}. Will retry.`,\n \"SERVER_ERROR\",\n true,\n );\n this.name = \"ServerError\";\n }\n}\n\nexport class NetworkError extends BridgeError {\n constructor(detail: string = \"\") {\n super(\n `Network error connecting to Codex${detail ? `: ${detail}` : \"\"}. Check your connection.`,\n \"NETWORK_ERROR\",\n true,\n );\n this.name = \"NetworkError\";\n }\n}\n\nexport class EmptyOutputError extends BridgeError {\n constructor() {\n super(\n \"Codex returned empty output. This may be a transient issue.\",\n \"EMPTY_OUTPUT\",\n true,\n );\n this.name = \"EmptyOutputError\";\n }\n}\n\nexport class NotGitRepoError extends BridgeError {\n constructor(cwd: string) {\n super(\n `Not a git repository: ${cwd}. This operation requires a git repo.`,\n \"NOT_GIT_REPO\",\n false,\n );\n this.name = \"NotGitRepoError\";\n }\n}\n\nexport class ParseError extends BridgeError {\n constructor(detail: string = \"\") {\n super(\n `Failed to parse Codex output${detail ? `: ${detail}` : \"\"}. The Codex CLI format may have changed — please update skill-codex.`,\n \"PARSE_ERROR\",\n false,\n );\n this.name = \"ParseError\";\n }\n}\n","export const MAX_BRIDGE_DEPTH = 2;\nexport const BRIDGE_DEPTH_ENV = \"SKILL_CODEX_DEPTH\";\n\nexport const DEFAULT_TIMEOUT_MS = 600_000; // 10 minutes\nexport const TIMEOUT_ENV = \"SKILL_CODEX_TIMEOUT_MS\";\nexport const KILL_GRACE_MS = 5_000;\n\nexport const MAX_RETRIES = 3;\nexport const MAX_RETRIES_ENV = \"SKILL_CODEX_MAX_RETRIES\";\nexport const RETRY_DELAYS_MS = [1_000, 2_000, 4_000];\nexport const RETRY_CAP_MS = 10_000;\n\nexport const MAX_RESPONSE_CHARS = 80_000;\n\nexport const LOCK_STALE_MS = 900_000; // 15 minutes\nexport const LOCK_FILENAME = \".skill-codex.lock\";\n\nexport const TRIVIAL_DIFF_THRESHOLD = 5; // lines\nexport const DOCS_ONLY_EXTENSIONS = [\".md\", \".txt\", \".rst\", \".adoc\"];\nexport const SECURITY_PATH_KEYWORDS = [\"security\", \"auth\", \"crypto\", \"password\", \"secret\", \"token\"];\nexport const FORCE_REVIEW_LINES = 100;\nexport const FORCE_REVIEW_FILES = 3;\n\nexport const CONFIG_ONLY_FILES = [\".gitignore\", \".eslintrc\", \".prettierrc\", \".editorconfig\"];\n\nexport const DEBUG_ENV = \"SKILL_CODEX_DEBUG\";\n\nexport const TRANSIENT_PATTERNS = [\n \"rate limit\", \"too many requests\", \"429\",\n \"500\", \"502\", \"503\", \"504\",\n \"internal server error\", \"bad gateway\", \"service unavailable\", \"gateway timeout\",\n \"connection reset\", \"connection refused\",\n \"econnreset\", \"econnrefused\", \"etimedout\",\n \"network error\", \"fetch failed\", \"socket hang up\",\n] as const;\n\nexport const AUTH_ERROR_PATTERNS = [\n \"api key\", \"authentication\", \"unauthorized\", \"401\", \"auth\",\n] as const;\n","import { BRIDGE_DEPTH_ENV, MAX_BRIDGE_DEPTH } from \"../config/constants.js\";\nimport { RecursionLimitError } from \"../errors/errors.js\";\n\nexport function getCurrentDepth(): number {\n return parseInt(process.env[BRIDGE_DEPTH_ENV] ?? \"0\", 10);\n}\n\nexport function getNextDepth(): number {\n return getCurrentDepth() + 1;\n}\n\nexport function checkRecursion(): void {\n const depth = getCurrentDepth();\n if (depth >= MAX_BRIDGE_DEPTH) {\n throw new RecursionLimitError(depth, MAX_BRIDGE_DEPTH);\n }\n}\n","import which from \"which\";\nimport { CliNotFoundError } from \"../errors/errors.js\";\n\nexport interface BinaryCheckResult {\n readonly found: boolean;\n readonly path: string;\n}\n\nlet cachedBinaryPath: string | null = null;\n\nexport function getCachedBinaryPath(): string | null {\n return cachedBinaryPath;\n}\n\nexport function resetBinaryCache(): void {\n cachedBinaryPath = null;\n}\n\nexport async function checkBinary(\n binary: string = \"codex\",\n): Promise<BinaryCheckResult> {\n if (cachedBinaryPath !== null) {\n return { found: true, path: cachedBinaryPath };\n }\n\n try {\n const resolved = await which(binary);\n cachedBinaryPath = resolved;\n return { found: true, path: resolved };\n } catch {\n throw new CliNotFoundError(binary);\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { AuthExpiredError, NetworkError, CliNotFoundError } from \"../errors/errors.js\";\nimport { getCachedBinaryPath } from \"./check-binary.js\";\n\nconst AUTH_CACHE_TTL_MS = 60_000;\n\nlet authCachedAt: number | null = null;\n\nexport function resetAuthCache(): void {\n authCachedAt = null;\n}\n\nexport async function checkAuth(): Promise<void> {\n const now = Date.now();\n\n if (authCachedAt !== null && now - authCachedAt < AUTH_CACHE_TTL_MS) {\n return;\n }\n\n const binary = getCachedBinaryPath() ?? \"codex\";\n\n return new Promise((resolve, reject) => {\n const child = execFile(\n binary,\n [\"exec\", \"--sandbox\", \"read-only\", \"--skip-git-repo-check\", \"--ephemeral\", \"echo ok\"],\n { timeout: 15_000 },\n (error, _stdout, stderr) => {\n if (!error) {\n authCachedAt = Date.now();\n resolve();\n return;\n }\n\n const lower = (stderr ?? error.message ?? \"\").toLowerCase();\n\n // Distinguish error types instead of masking everything as auth\n if (error.code === \"ENOENT\" || (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n reject(new CliNotFoundError());\n return;\n }\n\n if (error.killed) {\n reject(new NetworkError(\"Auth check timed out — check your network connection\"));\n return;\n }\n\n if ([\"econnrefused\", \"econnreset\", \"etimedout\", \"network error\", \"fetch failed\"].some((p) => lower.includes(p))) {\n reject(new NetworkError(\"Network error during auth check\"));\n return;\n }\n\n // Default: treat as auth issue\n reject(new AuthExpiredError());\n },\n );\n child.stdin?.end();\n });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { LOCK_FILENAME, LOCK_STALE_MS } from \"../config/constants.js\";\nimport { LockConflictError } from \"../errors/errors.js\";\n\ninterface LockData {\n readonly pid: number;\n readonly timestamp: number;\n readonly hostname: string;\n}\n\nexport interface LockHandle {\n readonly release: () => void;\n}\n\nfunction getLockPath(cwd: string): string {\n return path.join(cwd, LOCK_FILENAME);\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isLockStale(data: LockData): boolean {\n const age = Date.now() - data.timestamp;\n if (age > LOCK_STALE_MS) return true;\n if (!isProcessAlive(data.pid)) return true;\n return false;\n}\n\nfunction tryRemoveStaleLock(lockPath: string): boolean {\n try {\n const raw = fs.readFileSync(lockPath, \"utf-8\");\n const data: LockData = JSON.parse(raw);\n if (isLockStale(data)) {\n fs.unlinkSync(lockPath);\n return true;\n }\n throw new LockConflictError(data.pid);\n } catch (err) {\n if (err instanceof LockConflictError) throw err;\n // File disappeared or is unreadable — try to acquire\n try { fs.unlinkSync(lockPath); } catch { /* ignore */ }\n return true;\n }\n}\n\nexport function acquireLock(cwd: string): LockHandle {\n const lockPath = getLockPath(cwd);\n const lockData: LockData = {\n pid: process.pid,\n timestamp: Date.now(),\n hostname: os.hostname(),\n };\n const content = JSON.stringify(lockData, null, 2);\n\n try {\n fs.writeFileSync(lockPath, content, { flag: \"wx\" });\n } catch (err: unknown) {\n const fsErr = err as NodeJS.ErrnoException;\n if (fsErr.code === \"EEXIST\") {\n tryRemoveStaleLock(lockPath);\n // Retry once after stale removal — wrap in try/catch for TOCTOU race\n try {\n fs.writeFileSync(lockPath, content, { flag: \"wx\" });\n } catch (retryErr: unknown) {\n const retryFsErr = retryErr as NodeJS.ErrnoException;\n if (retryFsErr.code === \"EEXIST\") {\n // Another process won the race\n throw new LockConflictError(0);\n }\n throw retryErr;\n }\n } else {\n throw err;\n }\n }\n\n // Signal handlers — stored for removal in release()\n const onExit = (): void => {\n try { fs.unlinkSync(lockPath); } catch { /* ignore */ }\n };\n\n process.on(\"exit\", onExit);\n process.on(\"SIGINT\", onExit);\n process.on(\"SIGTERM\", onExit);\n\n const release = (): void => {\n // Remove signal handlers first to prevent double-cleanup\n process.removeListener(\"exit\", onExit);\n process.removeListener(\"SIGINT\", onExit);\n process.removeListener(\"SIGTERM\", onExit);\n try { fs.unlinkSync(lockPath); } catch { /* ignore */ }\n };\n\n return { release };\n}\n","import { acquireLock, type LockHandle } from \"../lock/lock-file.js\";\n\nexport function checkLock(cwd: string): LockHandle {\n return acquireLock(cwd);\n}\n","import { execFileSync } from \"node:child_process\";\n\nexport interface GitCheckResult {\n readonly isGitRepo: boolean;\n}\n\nexport function checkGit(cwd: string): GitCheckResult {\n try {\n execFileSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n cwd,\n stdio: \"pipe\",\n timeout: 5_000,\n });\n return { isGitRepo: true };\n } catch {\n return { isGitRepo: false };\n }\n}\n","import type { LockHandle } from \"../lock/lock-file.js\";\nimport { NotGitRepoError } from \"../errors/errors.js\";\nimport { checkRecursion } from \"./check-recursion.js\";\nimport { checkBinary } from \"./check-binary.js\";\nimport { checkAuth } from \"./check-auth.js\";\nimport { checkLock } from \"./check-lock.js\";\nimport { checkGit } from \"./check-git.js\";\n\nexport interface PreflightOptions {\n readonly cwd: string;\n readonly requireGit: boolean;\n readonly skipAuth?: boolean;\n readonly skipLock?: boolean;\n}\n\nexport interface PreflightResult {\n readonly lockHandle: LockHandle | null;\n}\n\nexport async function runPreflight(\n options: PreflightOptions,\n): Promise<PreflightResult> {\n // Order: cheapest checks first (fail-fast)\n // 1. Recursion (env read — instant)\n checkRecursion();\n\n // 2. Binary exists (filesystem lookup)\n await checkBinary();\n\n // 3. Auth valid (spawns a quick process)\n if (!options.skipAuth) {\n await checkAuth();\n }\n\n // 4. Lock file (filesystem write)\n let lockHandle: LockHandle | null = null;\n if (!options.skipLock) {\n lockHandle = checkLock(options.cwd);\n }\n\n // 5. Git repo (if required)\n if (options.requireGit) {\n const { isGitRepo } = checkGit(options.cwd);\n if (!isGitRepo) {\n lockHandle?.release();\n throw new NotGitRepoError(options.cwd);\n }\n }\n\n return { lockHandle };\n}\n","import { spawn } from \"node:child_process\";\nimport { BRIDGE_DEPTH_ENV, DEFAULT_TIMEOUT_MS, TIMEOUT_ENV } from \"../config/constants.js\";\nimport { getNextDepth } from \"../guards/check-recursion.js\";\nimport { getCachedBinaryPath } from \"../guards/check-binary.js\";\nimport { setupTimeout } from \"./timeout.js\";\nimport { parseCodexOutput, type CodexResult } from \"./output-parser.js\";\nimport {\n BridgeError,\n CliNotFoundError,\n AuthExpiredError,\n RateLimitError,\n ServerError,\n NetworkError,\n} from \"../errors/errors.js\";\n\nexport interface ExecParams {\n readonly prompt: string;\n readonly cwd: string;\n readonly mode: \"exec\" | \"full-auto\";\n readonly timeoutMs?: number;\n}\n\nfunction getTimeout(override?: number): number {\n if (override !== undefined) return override;\n const envVal = process.env[TIMEOUT_ENV];\n if (envVal) {\n const parsed = parseInt(envVal, 10);\n if (!isNaN(parsed) && parsed > 0) return parsed;\n }\n return DEFAULT_TIMEOUT_MS;\n}\n\nfunction classifyError(exitCode: number, stderr: string): BridgeError {\n const lower = stderr.toLowerCase();\n\n // Check auth errors first but exclude generic \"auth\" in context\n if (lower.includes(\"unauthorized\") || lower.includes(\"401\") || lower.includes(\"api key\")) {\n return new AuthExpiredError();\n }\n if (lower.includes(\"rate limit\") || lower.includes(\"429\") || lower.includes(\"too many requests\")) {\n return new RateLimitError();\n }\n if ([\"500\", \"502\", \"503\", \"504\", \"internal server error\", \"bad gateway\", \"service unavailable\"].some((p) => lower.includes(p))) {\n return new ServerError(stderr.slice(0, 200));\n }\n if ([\"econnreset\", \"econnrefused\", \"etimedout\", \"network error\", \"fetch failed\", \"socket hang up\"].some((p) => lower.includes(p))) {\n return new NetworkError(stderr.slice(0, 200));\n }\n\n return new BridgeError(\n `Codex exited with code ${exitCode}: ${stderr.slice(0, 300)}`,\n \"EXEC_FAILED\",\n false,\n );\n}\n\nexport async function execCodex(params: ExecParams): Promise<CodexResult> {\n // Use cached binary path from checkBinary — throws if not found\n const codexPath = getCachedBinaryPath();\n if (codexPath === null) {\n throw new CliNotFoundError();\n }\n\n return new Promise((resolve, reject) => {\n const timeoutMs = getTimeout(params.timeoutMs);\n const args: string[] = [\"exec\", \"--json\", \"--skip-git-repo-check\"];\n\n if (params.mode === \"full-auto\") {\n args.push(\"--full-auto\");\n } else {\n args.push(\"--sandbox\", \"read-only\");\n }\n\n // Prompt passed via stdin to avoid shell injection — NOT as a positional arg\n const stdinPrompt = params.prompt;\n\n // Use \"-\" to tell codex to read prompt from stdin\n args.push(\"-\");\n\n const env = {\n ...process.env,\n [BRIDGE_DEPTH_ENV]: String(getNextDepth()),\n };\n\n // shell: false — codexPath is the resolved absolute path, no shell resolution needed\n const child = spawn(codexPath, args, {\n cwd: params.cwd,\n env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n shell: false,\n windowsHide: true,\n });\n\n const { clear: clearTimeout_, promise: timeoutPromise } = setupTimeout(child, timeoutMs);\n\n const stdoutChunks: Buffer[] = [];\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n stdoutChunks.push(chunk);\n });\n\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n\n // Write prompt via stdin then close — safe from shell injection\n child.stdin?.write(stdinPrompt);\n child.stdin?.end();\n\n const onClose = (exitCode: number | null): void => {\n clearTimeout_();\n const stdout = Buffer.concat(stdoutChunks).toString();\n\n if (exitCode === 0 || exitCode === null) {\n try {\n const result = parseCodexOutput(stdout);\n resolve(result);\n } catch (err) {\n reject(err);\n }\n return;\n }\n\n reject(classifyError(exitCode, stderr));\n };\n\n child.on(\"close\", onClose);\n\n child.on(\"error\", (err: NodeJS.ErrnoException) => {\n clearTimeout_();\n if (err.code === \"ENOENT\") {\n reject(new CliNotFoundError());\n } else {\n reject(new BridgeError(`Failed to spawn codex: ${err.message}`, \"SPAWN_ERROR\", false));\n }\n });\n\n // Race with timeout\n timeoutPromise.catch((err) => {\n reject(err);\n });\n });\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\n\nexport type Platform = \"win32\" | \"darwin\" | \"linux\";\n\nexport function getPlatform(): Platform {\n const p = os.platform();\n if (p === \"win32\" || p === \"darwin\" || p === \"linux\") return p;\n return \"linux\"; // default fallback for other unix-like\n}\n\nexport function isWindows(): boolean {\n return getPlatform() === \"win32\";\n}\n\nexport function normalizePath(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\nexport function getHomeDir(): string {\n return os.homedir();\n}\n\nexport function getClaudeDir(): string {\n return path.join(getHomeDir(), \".claude\");\n}\n\nexport function getTempDir(): string {\n return os.tmpdir();\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport { KILL_GRACE_MS } from \"../config/constants.js\";\nimport { TimeoutError } from \"../errors/errors.js\";\nimport { isWindows } from \"../util/platform.js\";\n\nexport function setupTimeout(\n child: ChildProcess,\n timeoutMs: number,\n): { clear: () => void; promise: Promise<never> } {\n let timer: ReturnType<typeof setTimeout> | null = null;\n let graceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const promise = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n if (isWindows()) {\n // On Windows, SIGTERM is silently ignored by Node.js — it maps to\n // TerminateProcess regardless of signal name. Call kill() with no\n // argument so the intent is explicit and no grace timer is needed.\n child.kill();\n } else {\n // Phase 1: graceful kill\n child.kill(\"SIGTERM\");\n\n // Phase 2: force kill after grace period\n graceTimer = setTimeout(() => {\n try {\n if (!child.killed) {\n child.kill(\"SIGKILL\");\n }\n } catch {\n // Process may already be gone — ignore\n }\n }, KILL_GRACE_MS);\n }\n\n reject(new TimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n const clear = (): void => {\n if (timer) clearTimeout(timer);\n if (graceTimer) clearTimeout(graceTimer);\n };\n\n return { clear, promise };\n}\n","import { MAX_RESPONSE_CHARS } from \"../config/constants.js\";\n\nexport function truncateResponse(\n text: string,\n maxChars: number = MAX_RESPONSE_CHARS,\n): string {\n if (text.length <= maxChars) return text;\n\n const omitted = text.length - maxChars;\n return (\n text.slice(0, maxChars) +\n `\\n\\n[Response truncated at ${maxChars} characters. ${omitted} characters omitted.]`\n );\n}\n","import { EmptyOutputError } from \"../errors/errors.js\";\nimport { truncateResponse } from \"../util/truncate.js\";\n\nexport interface CodexResult {\n readonly content: string;\n readonly raw: string;\n}\n\nexport function parseCodexOutput(raw: string): CodexResult {\n if (!raw.trim()) {\n throw new EmptyOutputError();\n }\n\n const lines = raw.split(\"\\n\").filter((line) => line.trim());\n const messages: string[] = [];\n let resultContent: string | null = null;\n\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line);\n\n // Handle result type — takes priority over all other messages\n if (parsed.type === \"result\" && typeof parsed.content === \"string\") {\n resultContent = parsed.content;\n continue;\n }\n\n // Handle standard event format\n if (parsed.type === \"message\" && typeof parsed.content === \"string\") {\n messages.push(parsed.content);\n continue;\n }\n\n // Handle nested item format (Codex JSONL)\n if (parsed.item?.type === \"agent_message\" && typeof parsed.item.text === \"string\") {\n messages.push(parsed.item.text);\n continue;\n }\n\n // Handle flat legacy format\n if (parsed.itemType === \"agent_message\" && typeof parsed.text === \"string\") {\n messages.push(parsed.text);\n continue;\n }\n } catch {\n // Non-JSON line — could be preamble or status output. Skip.\n }\n }\n\n let agentMessage: string;\n\n if (resultContent !== null) {\n agentMessage = resultContent;\n } else if (messages.length > 0) {\n agentMessage = messages.join(\"\\n\\n\");\n } else {\n // If no structured output found, use the raw text (minus any obvious preamble)\n const substantiveLines = lines.filter(\n (line) => !line.startsWith(\"OpenAI Codex\") && !line.startsWith(\"---\") && !line.startsWith(\"tokens used\"),\n );\n agentMessage = substantiveLines.join(\"\\n\").trim();\n }\n\n if (!agentMessage) {\n throw new EmptyOutputError();\n }\n\n return {\n content: truncateResponse(agentMessage),\n raw,\n };\n}\n","import { BridgeError } from \"../errors/errors.js\";\nimport { MAX_RETRIES, MAX_RETRIES_ENV, RETRY_DELAYS_MS, RETRY_CAP_MS } from \"../config/constants.js\";\n\nexport interface RetryOptions {\n readonly maxRetries?: number;\n readonly shouldRetry?: (err: Error) => boolean;\n}\n\nfunction getMaxRetries(override?: number): number {\n if (override !== undefined) return override;\n const envVal = process.env[MAX_RETRIES_ENV];\n if (envVal) {\n const parsed = parseInt(envVal, 10);\n if (!isNaN(parsed) && parsed >= 0) return parsed;\n }\n return MAX_RETRIES;\n}\n\nfunction getDelay(attempt: number): number {\n const base = RETRY_DELAYS_MS[attempt] ?? RETRY_CAP_MS;\n const capped = Math.min(base, RETRY_CAP_MS);\n // Add jitter: 50-150% of base delay\n const jitter = 0.5 + Math.random();\n return Math.round(capped * jitter);\n}\n\nfunction defaultShouldRetry(err: Error): boolean {\n return err instanceof BridgeError && err.retryable;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {},\n): Promise<T> {\n const maxRetries = getMaxRetries(options.maxRetries);\n const shouldRetry = options.shouldRetry ?? defaultShouldRetry;\n\n for (let attempt = 0; ; attempt++) {\n try {\n return await fn();\n } catch (err) {\n const isRetryable = err instanceof Error && shouldRetry(err);\n if (attempt < maxRetries && isRetryable) {\n const delay = getDelay(attempt);\n const errorName = err instanceof Error ? err.constructor.name : \"UnknownError\";\n process.stderr.write(\n `[skill-codex] ${errorName} (attempt ${attempt + 1}/${maxRetries}), retrying in ${delay}ms...\\n`,\n );\n await sleep(delay);\n continue;\n }\n throw err;\n }\n }\n}\n","import { startServer } from \"./server.js\";\n\nstartServer().catch((err) => {\n process.stderr.write(`[skill-codex] Fatal: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path","os","path","path","fs"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/tools/codex-exec.ts","../src/errors/errors.ts","../src/config/constants.ts","../src/guards/check-recursion.ts","../src/guards/check-binary.ts","../src/guards/check-auth.ts","../src/lock/lock-file.ts","../src/guards/check-lock.ts","../src/guards/check-git.ts","../src/guards/preflight.ts","../src/runner/exec-runner.ts","../src/util/platform.ts","../src/runner/timeout.ts","../src/util/truncate.ts","../src/runner/output-parser.ts","../src/runner/retry.ts","../src/index.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { TOOL_NAME, TOOL_DESCRIPTION, inputSchema, handleCodexExec } from \"./tools/codex-exec.js\";\n\nexport function createServer(cwd: string): Server {\n const server = new Server(\n { name: \"skill-codex\", version: \"0.2.0\" },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: TOOL_NAME,\n description: TOOL_DESCRIPTION,\n inputSchema: {\n type: \"object\" as const,\n properties: {\n prompt: { type: \"string\", description: \"The task description for Codex\" },\n mode: {\n type: \"string\",\n enum: [\"exec\", \"full-auto\"],\n default: \"exec\",\n description: \"exec = read-only, full-auto = can write files\",\n },\n cwd: { type: \"string\", description: \"Working directory (defaults to server cwd)\" },\n timeoutMs: { type: \"number\", description: \"Override default timeout in milliseconds\" },\n requireGit: {\n type: \"boolean\",\n default: false,\n description: \"Fail if not inside a git repository\",\n },\n },\n required: [\"prompt\"],\n },\n },\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n if (request.params.name !== TOOL_NAME) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${request.params.name}` }],\n isError: true,\n };\n }\n\n const parsed = inputSchema.safeParse(request.params.arguments);\n if (!parsed.success) {\n return {\n content: [\n {\n type: \"text\",\n text: `Invalid input: ${parsed.error.issues.map((i) => i.message).join(\", \")}`,\n },\n ],\n isError: true,\n };\n }\n\n return handleCodexExec(parsed.data, cwd);\n });\n\n return server;\n}\n\nexport async function startServer(): Promise<void> {\n const cwd = process.cwd();\n const server = createServer(cwd);\n const transport = new StdioServerTransport();\n\n process.stderr.write(\"[skill-codex] MCP server starting...\\n\");\n\n await server.connect(transport);\n\n process.stderr.write(\"[skill-codex] MCP server connected via stdio\\n\");\n\n process.on(\"uncaughtException\", (err) => {\n process.stderr.write(`[skill-codex] Uncaught exception: ${err.message}\\n`);\n });\n\n process.on(\"unhandledRejection\", (reason) => {\n process.stderr.write(`[skill-codex] Unhandled rejection: ${String(reason)}\\n`);\n });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { runPreflight } from \"../guards/preflight.js\";\nimport { execCodex } from \"../runner/exec-runner.js\";\nimport { withRetry } from \"../runner/retry.js\";\nimport { BridgeError } from \"../errors/errors.js\";\nimport type { CodexResult } from \"../runner/output-parser.js\";\n\nexport const TOOL_NAME = \"codex_exec\";\n\nexport const TOOL_DESCRIPTION =\n \"Execute a task using OpenAI Codex CLI. Use for code review, implementation tasks, or getting a second opinion. Codex output is a SUGGESTION — evaluate it critically before applying.\";\n\nexport const inputSchema = z.object({\n prompt: z.string().describe(\"The task description for Codex\"),\n mode: z\n .enum([\"exec\", \"full-auto\"])\n .default(\"exec\")\n .describe(\"exec = read-only with confirmation, full-auto = can write files\"),\n cwd: z.string().optional().describe(\"Working directory (defaults to server cwd)\"),\n timeoutMs: z.number().optional().describe(\"Override default timeout in milliseconds\"),\n requireGit: z.boolean().default(false).describe(\"Fail if not inside a git repository\"),\n});\n\nexport type CodexExecInput = z.infer<typeof inputSchema>;\n\nfunction formatError(err: unknown): string {\n if (err instanceof BridgeError) {\n return `[skill-codex error: ${err.code}] ${err.message}`;\n }\n if (err instanceof Error) {\n return `[skill-codex error] ${err.message}`;\n }\n return `[skill-codex error] Unknown error: ${String(err)}`;\n}\n\nfunction formatRichResponse(\n result: CodexResult,\n input: CodexExecInput,\n cwd: string,\n): string {\n const lines: string[] = [];\n\n const modeLabel = input.mode === \"full-auto\" ? \"full-auto\" : \"read-only\";\n const metaParts: string[] = [modeLabel, cwd];\n\n if (result.usage) {\n const { input_tokens: inp, output_tokens: out, cached_input_tokens: cached } = result.usage;\n metaParts.push(\n `${inp} tok in${cached > 0 ? ` (${cached} cached)` : \"\"} \\u2192 ${out} out`,\n );\n }\n\n lines.push(`[${metaParts.join(\" \\u2502 \")}]`);\n\n if (result.activity.length > 0) {\n for (const a of result.activity) {\n if (a.type === \"exec\") {\n lines.push(` ${a.icon} exec: ${a.command} (${a.status})`);\n } else if (a.type === \"read\") {\n lines.push(` \\u25B6 read: ${a.path}`);\n } else if (a.type === \"write\") {\n lines.push(` \\u270E write: ${a.path}`);\n }\n }\n }\n\n lines.push(\"\");\n lines.push(result.content);\n\n return lines.join(\"\\n\");\n}\n\nexport async function handleCodexExec(\n input: CodexExecInput,\n serverCwd: string,\n): Promise<{ content: Array<{ type: \"text\"; text: string }>; isError?: boolean }> {\n const rawCwd = input.cwd ?? serverCwd;\n const cwd = path.resolve(rawCwd);\n\n // Validate cwd is an existing directory (prevent path traversal to arbitrary locations)\n if (!fs.existsSync(cwd) || !fs.statSync(cwd).isDirectory()) {\n return {\n content: [{ type: \"text\", text: `[skill-codex error: INVALID_CWD] cwd is not an existing directory: ${cwd}` }],\n isError: true,\n };\n }\n\n let lockRelease: (() => void) | null = null;\n\n try {\n const { lockHandle } = await runPreflight({\n cwd,\n requireGit: input.requireGit,\n });\n lockRelease = lockHandle?.release ?? null;\n\n const result = await withRetry(() =>\n execCodex({\n prompt: input.prompt,\n cwd,\n mode: input.mode,\n timeoutMs: input.timeoutMs,\n }),\n );\n\n const formatted = formatRichResponse(result, input, cwd);\n return {\n content: [{ type: \"text\", text: formatted }],\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: formatError(err) }],\n isError: true,\n };\n } finally {\n lockRelease?.();\n }\n}\n","export class BridgeError extends Error {\n readonly code: string;\n readonly retryable: boolean;\n\n constructor(message: string, code: string, retryable: boolean) {\n super(message);\n this.name = \"BridgeError\";\n this.code = code;\n this.retryable = retryable;\n }\n}\n\nexport class CliNotFoundError extends BridgeError {\n constructor(binary: string = \"codex\") {\n super(\n `${binary} CLI not found on PATH. Install it with: npm i -g @openai/codex`,\n \"CLI_NOT_FOUND\",\n false,\n );\n this.name = \"CliNotFoundError\";\n }\n}\n\nexport class AuthExpiredError extends BridgeError {\n constructor() {\n super(\n \"Codex authentication expired or not found. Run `codex login` to re-authenticate.\",\n \"AUTH_EXPIRED\",\n false,\n );\n this.name = \"AuthExpiredError\";\n }\n}\n\nexport class RecursionLimitError extends BridgeError {\n constructor(depth: number, max: number) {\n super(\n `Maximum bridge nesting depth reached (${depth} >= ${max}). This prevents infinite recursion between Claude and Codex.`,\n \"RECURSION_LIMIT\",\n false,\n );\n this.name = \"RecursionLimitError\";\n }\n}\n\nexport class LockConflictError extends BridgeError {\n constructor(pid: number) {\n super(\n `Another skill-codex instance is running (PID ${pid}). Wait for it to finish or delete the lock file.`,\n \"LOCK_CONFLICT\",\n false,\n );\n this.name = \"LockConflictError\";\n }\n}\n\nexport class TimeoutError extends BridgeError {\n constructor(timeoutMs: number) {\n super(\n `Codex timed out after ${Math.round(timeoutMs / 1000)}s. Increase SKILL_CODEX_TIMEOUT_MS if needed.`,\n \"TIMEOUT\",\n true,\n );\n this.name = \"TimeoutError\";\n }\n}\n\nexport class RateLimitError extends BridgeError {\n constructor() {\n super(\n \"Codex rate limited (429). Will retry with backoff.\",\n \"RATE_LIMIT\",\n true,\n );\n this.name = \"RateLimitError\";\n }\n}\n\nexport class ServerError extends BridgeError {\n constructor(detail: string = \"\") {\n super(\n `Codex server error${detail ? `: ${detail}` : \"\"}. Will retry.`,\n \"SERVER_ERROR\",\n true,\n );\n this.name = \"ServerError\";\n }\n}\n\nexport class NetworkError extends BridgeError {\n constructor(detail: string = \"\") {\n super(\n `Network error connecting to Codex${detail ? `: ${detail}` : \"\"}. Check your connection.`,\n \"NETWORK_ERROR\",\n true,\n );\n this.name = \"NetworkError\";\n }\n}\n\nexport class EmptyOutputError extends BridgeError {\n constructor() {\n super(\n \"Codex returned empty output. This may be a transient issue.\",\n \"EMPTY_OUTPUT\",\n true,\n );\n this.name = \"EmptyOutputError\";\n }\n}\n\nexport class NotGitRepoError extends BridgeError {\n constructor(cwd: string) {\n super(\n `Not a git repository: ${cwd}. This operation requires a git repo.`,\n \"NOT_GIT_REPO\",\n false,\n );\n this.name = \"NotGitRepoError\";\n }\n}\n\nexport class ParseError extends BridgeError {\n constructor(detail: string = \"\") {\n super(\n `Failed to parse Codex output${detail ? `: ${detail}` : \"\"}. The Codex CLI format may have changed — please update skill-codex.`,\n \"PARSE_ERROR\",\n false,\n );\n this.name = \"ParseError\";\n }\n}\n","export const MAX_BRIDGE_DEPTH = 2;\nexport const BRIDGE_DEPTH_ENV = \"SKILL_CODEX_DEPTH\";\n\nexport const DEFAULT_TIMEOUT_MS = 600_000; // 10 minutes\nexport const TIMEOUT_ENV = \"SKILL_CODEX_TIMEOUT_MS\";\nexport const KILL_GRACE_MS = 5_000;\n\nexport const MAX_RETRIES = 3;\nexport const MAX_RETRIES_ENV = \"SKILL_CODEX_MAX_RETRIES\";\nexport const RETRY_DELAYS_MS = [1_000, 2_000, 4_000];\nexport const RETRY_CAP_MS = 10_000;\n\nexport const MAX_RESPONSE_CHARS = 80_000;\n\nexport const LOCK_STALE_MS = 900_000; // 15 minutes\nexport const LOCK_FILENAME = \".skill-codex.lock\";\n\nexport const TRIVIAL_DIFF_THRESHOLD = 5; // lines\nexport const DOCS_ONLY_EXTENSIONS = [\".md\", \".txt\", \".rst\", \".adoc\"];\nexport const SECURITY_PATH_KEYWORDS = [\"security\", \"auth\", \"crypto\", \"password\", \"secret\", \"token\"];\nexport const FORCE_REVIEW_LINES = 100;\nexport const FORCE_REVIEW_FILES = 3;\n\nexport const CONFIG_ONLY_FILES = [\".gitignore\", \".eslintrc\", \".prettierrc\", \".editorconfig\"];\n\nexport const DEBUG_ENV = \"SKILL_CODEX_DEBUG\";\n\nexport const TRANSIENT_PATTERNS = [\n \"rate limit\", \"too many requests\", \"429\",\n \"500\", \"502\", \"503\", \"504\",\n \"internal server error\", \"bad gateway\", \"service unavailable\", \"gateway timeout\",\n \"connection reset\", \"connection refused\",\n \"econnreset\", \"econnrefused\", \"etimedout\",\n \"network error\", \"fetch failed\", \"socket hang up\",\n] as const;\n\nexport const AUTH_ERROR_PATTERNS = [\n \"api key\", \"authentication\", \"unauthorized\", \"401\", \"auth\",\n] as const;\n","import { BRIDGE_DEPTH_ENV, MAX_BRIDGE_DEPTH } from \"../config/constants.js\";\nimport { RecursionLimitError } from \"../errors/errors.js\";\n\nexport function getCurrentDepth(): number {\n return parseInt(process.env[BRIDGE_DEPTH_ENV] ?? \"0\", 10);\n}\n\nexport function getNextDepth(): number {\n return getCurrentDepth() + 1;\n}\n\nexport function checkRecursion(): void {\n const depth = getCurrentDepth();\n if (depth >= MAX_BRIDGE_DEPTH) {\n throw new RecursionLimitError(depth, MAX_BRIDGE_DEPTH);\n }\n}\n","import which from \"which\";\nimport { CliNotFoundError } from \"../errors/errors.js\";\n\nexport interface BinaryCheckResult {\n readonly found: boolean;\n readonly path: string;\n}\n\nlet cachedBinaryPath: string | null = null;\n\nexport function getCachedBinaryPath(): string | null {\n return cachedBinaryPath;\n}\n\nexport function resetBinaryCache(): void {\n cachedBinaryPath = null;\n}\n\nexport async function checkBinary(\n binary: string = \"codex\",\n): Promise<BinaryCheckResult> {\n if (cachedBinaryPath !== null) {\n return { found: true, path: cachedBinaryPath };\n }\n\n try {\n const resolved = await which(binary);\n cachedBinaryPath = resolved;\n return { found: true, path: resolved };\n } catch {\n throw new CliNotFoundError(binary);\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { AuthExpiredError, NetworkError, CliNotFoundError } from \"../errors/errors.js\";\nimport { getCachedBinaryPath } from \"./check-binary.js\";\n\nconst AUTH_CACHE_TTL_MS = 60_000;\n\nlet authCachedAt: number | null = null;\n\nexport function resetAuthCache(): void {\n authCachedAt = null;\n}\n\nexport async function checkAuth(): Promise<void> {\n const now = Date.now();\n\n if (authCachedAt !== null && now - authCachedAt < AUTH_CACHE_TTL_MS) {\n return;\n }\n\n const binary = getCachedBinaryPath() ?? \"codex\";\n\n return new Promise((resolve, reject) => {\n const child = execFile(\n binary,\n [\"exec\", \"--sandbox\", \"read-only\", \"--skip-git-repo-check\", \"--ephemeral\", \"echo ok\"],\n { timeout: 30_000, shell: process.platform === \"win32\" },\n (error, _stdout, stderr) => {\n if (!error) {\n authCachedAt = Date.now();\n resolve();\n return;\n }\n\n const lower = (stderr ?? error.message ?? \"\").toLowerCase();\n\n // Distinguish error types instead of masking everything as auth\n if (error.code === \"ENOENT\" || (error as NodeJS.ErrnoException).code === \"ENOENT\") {\n reject(new CliNotFoundError());\n return;\n }\n\n if (error.killed) {\n reject(new NetworkError(\"Auth check timed out — check your network connection\"));\n return;\n }\n\n if ([\"econnrefused\", \"econnreset\", \"etimedout\", \"network error\", \"fetch failed\"].some((p) => lower.includes(p))) {\n reject(new NetworkError(\"Network error during auth check\"));\n return;\n }\n\n // Default: treat as auth issue\n reject(new AuthExpiredError());\n },\n );\n child.stdin?.end();\n });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { LOCK_FILENAME, LOCK_STALE_MS } from \"../config/constants.js\";\nimport { LockConflictError } from \"../errors/errors.js\";\n\ninterface LockData {\n readonly pid: number;\n readonly timestamp: number;\n readonly hostname: string;\n}\n\nexport interface LockHandle {\n readonly release: () => void;\n}\n\nfunction getLockPath(cwd: string): string {\n return path.join(cwd, LOCK_FILENAME);\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isLockStale(data: LockData): boolean {\n const age = Date.now() - data.timestamp;\n if (age > LOCK_STALE_MS) return true;\n if (!isProcessAlive(data.pid)) return true;\n return false;\n}\n\nfunction tryRemoveStaleLock(lockPath: string): boolean {\n try {\n const raw = fs.readFileSync(lockPath, \"utf-8\");\n const data: LockData = JSON.parse(raw);\n if (isLockStale(data)) {\n fs.unlinkSync(lockPath);\n return true;\n }\n throw new LockConflictError(data.pid);\n } catch (err) {\n if (err instanceof LockConflictError) throw err;\n // File disappeared or is unreadable — try to acquire\n try { fs.unlinkSync(lockPath); } catch { /* ignore */ }\n return true;\n }\n}\n\nexport function acquireLock(cwd: string): LockHandle {\n const lockPath = getLockPath(cwd);\n const lockData: LockData = {\n pid: process.pid,\n timestamp: Date.now(),\n hostname: os.hostname(),\n };\n const content = JSON.stringify(lockData, null, 2);\n\n try {\n fs.writeFileSync(lockPath, content, { flag: \"wx\" });\n } catch (err: unknown) {\n const fsErr = err as NodeJS.ErrnoException;\n if (fsErr.code === \"EEXIST\") {\n tryRemoveStaleLock(lockPath);\n // Retry once after stale removal — wrap in try/catch for TOCTOU race\n try {\n fs.writeFileSync(lockPath, content, { flag: \"wx\" });\n } catch (retryErr: unknown) {\n const retryFsErr = retryErr as NodeJS.ErrnoException;\n if (retryFsErr.code === \"EEXIST\") {\n // Another process won the race\n throw new LockConflictError(0);\n }\n throw retryErr;\n }\n } else {\n throw err;\n }\n }\n\n // Signal handlers — stored for removal in release()\n const onExit = (): void => {\n try { fs.unlinkSync(lockPath); } catch { /* ignore */ }\n };\n\n process.on(\"exit\", onExit);\n process.on(\"SIGINT\", onExit);\n process.on(\"SIGTERM\", onExit);\n\n const release = (): void => {\n // Remove signal handlers first to prevent double-cleanup\n process.removeListener(\"exit\", onExit);\n process.removeListener(\"SIGINT\", onExit);\n process.removeListener(\"SIGTERM\", onExit);\n try { fs.unlinkSync(lockPath); } catch { /* ignore */ }\n };\n\n return { release };\n}\n","import { acquireLock, type LockHandle } from \"../lock/lock-file.js\";\n\nexport function checkLock(cwd: string): LockHandle {\n return acquireLock(cwd);\n}\n","import { execFileSync } from \"node:child_process\";\n\nexport interface GitCheckResult {\n readonly isGitRepo: boolean;\n}\n\nexport function checkGit(cwd: string): GitCheckResult {\n try {\n execFileSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n cwd,\n stdio: \"pipe\",\n timeout: 5_000,\n });\n return { isGitRepo: true };\n } catch {\n return { isGitRepo: false };\n }\n}\n","import type { LockHandle } from \"../lock/lock-file.js\";\nimport { NotGitRepoError } from \"../errors/errors.js\";\nimport { checkRecursion } from \"./check-recursion.js\";\nimport { checkBinary } from \"./check-binary.js\";\nimport { checkAuth } from \"./check-auth.js\";\nimport { checkLock } from \"./check-lock.js\";\nimport { checkGit } from \"./check-git.js\";\n\nexport interface PreflightOptions {\n readonly cwd: string;\n readonly requireGit: boolean;\n readonly skipAuth?: boolean;\n readonly skipLock?: boolean;\n}\n\nexport interface PreflightResult {\n readonly lockHandle: LockHandle | null;\n}\n\nexport async function runPreflight(\n options: PreflightOptions,\n): Promise<PreflightResult> {\n // Order: cheapest checks first (fail-fast)\n // 1. Recursion (env read — instant)\n checkRecursion();\n\n // 2. Binary exists (filesystem lookup)\n await checkBinary();\n\n // 3. Auth valid (spawns a quick process)\n // Skipped on Windows: execFile auth check fails due to PowerShell profile\n // errors causing false AuthExpiredError. The real execCodex handles auth.\n if (!options.skipAuth && process.platform !== \"win32\") {\n await checkAuth();\n }\n\n // 4. Lock file (filesystem write)\n let lockHandle: LockHandle | null = null;\n if (!options.skipLock) {\n lockHandle = checkLock(options.cwd);\n }\n\n // 5. Git repo (if required)\n if (options.requireGit) {\n const { isGitRepo } = checkGit(options.cwd);\n if (!isGitRepo) {\n lockHandle?.release();\n throw new NotGitRepoError(options.cwd);\n }\n }\n\n return { lockHandle };\n}\n","import { spawn } from \"node:child_process\";\nimport { BRIDGE_DEPTH_ENV, DEFAULT_TIMEOUT_MS, TIMEOUT_ENV } from \"../config/constants.js\";\nimport { getNextDepth } from \"../guards/check-recursion.js\";\nimport { getCachedBinaryPath } from \"../guards/check-binary.js\";\nimport { setupTimeout } from \"./timeout.js\";\nimport { parseCodexOutput, type CodexResult } from \"./output-parser.js\";\nimport {\n BridgeError,\n CliNotFoundError,\n AuthExpiredError,\n RateLimitError,\n ServerError,\n NetworkError,\n} from \"../errors/errors.js\";\n\nexport interface ExecParams {\n readonly prompt: string;\n readonly cwd: string;\n readonly mode: \"exec\" | \"full-auto\";\n readonly timeoutMs?: number;\n}\n\nfunction getTimeout(override?: number): number {\n if (override !== undefined) return override;\n const envVal = process.env[TIMEOUT_ENV];\n if (envVal) {\n const parsed = parseInt(envVal, 10);\n if (!isNaN(parsed) && parsed > 0) return parsed;\n }\n return DEFAULT_TIMEOUT_MS;\n}\n\nfunction classifyError(exitCode: number, stderr: string): BridgeError {\n const lower = stderr.toLowerCase();\n\n // Check auth errors first but exclude generic \"auth\" in context\n if (lower.includes(\"unauthorized\") || lower.includes(\"401\") || lower.includes(\"api key\")) {\n return new AuthExpiredError();\n }\n if (lower.includes(\"rate limit\") || lower.includes(\"429\") || lower.includes(\"too many requests\")) {\n return new RateLimitError();\n }\n if ([\"500\", \"502\", \"503\", \"504\", \"internal server error\", \"bad gateway\", \"service unavailable\"].some((p) => lower.includes(p))) {\n return new ServerError(stderr.slice(0, 200));\n }\n if ([\"econnreset\", \"econnrefused\", \"etimedout\", \"network error\", \"fetch failed\", \"socket hang up\"].some((p) => lower.includes(p))) {\n return new NetworkError(stderr.slice(0, 200));\n }\n\n return new BridgeError(\n `Codex exited with code ${exitCode}: ${stderr.slice(0, 300)}`,\n \"EXEC_FAILED\",\n false,\n );\n}\n\nexport async function execCodex(params: ExecParams): Promise<CodexResult> {\n // Use cached binary path from checkBinary — throws if not found\n const codexPath = getCachedBinaryPath();\n if (codexPath === null) {\n throw new CliNotFoundError();\n }\n\n return new Promise((resolve, reject) => {\n const timeoutMs = getTimeout(params.timeoutMs);\n const args: string[] = [\"exec\", \"--json\", \"--skip-git-repo-check\"];\n\n if (params.mode === \"full-auto\") {\n args.push(\"--full-auto\");\n } else {\n args.push(\"--sandbox\", \"read-only\");\n }\n\n // Prompt passed via stdin to avoid shell injection — NOT as a positional arg\n const stdinPrompt = params.prompt;\n\n // Use \"-\" to tell codex to read prompt from stdin\n args.push(\"-\");\n\n const env = {\n ...process.env,\n [BRIDGE_DEPTH_ENV]: String(getNextDepth()),\n };\n\n // On Windows, npm-installed CLIs are .cmd shims that require a shell to execute.\n const child = spawn(codexPath, args, {\n cwd: params.cwd,\n env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n windowsHide: true,\n });\n\n const { clear: clearTimeout_, promise: timeoutPromise } = setupTimeout(child, timeoutMs);\n\n const stdoutChunks: Buffer[] = [];\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n stdoutChunks.push(chunk);\n });\n\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n\n // Write prompt via stdin then close — safe from shell injection\n child.stdin?.write(stdinPrompt);\n child.stdin?.end();\n\n const onClose = (exitCode: number | null): void => {\n clearTimeout_();\n const stdout = Buffer.concat(stdoutChunks).toString();\n\n if (exitCode === 0 || exitCode === null) {\n try {\n const result = parseCodexOutput(stdout);\n resolve(result);\n } catch (err) {\n reject(err);\n }\n return;\n }\n\n reject(classifyError(exitCode, stderr));\n };\n\n child.on(\"close\", onClose);\n\n child.on(\"error\", (err: NodeJS.ErrnoException) => {\n clearTimeout_();\n if (err.code === \"ENOENT\") {\n reject(new CliNotFoundError());\n } else {\n reject(new BridgeError(`Failed to spawn codex: ${err.message}`, \"SPAWN_ERROR\", false));\n }\n });\n\n // Race with timeout\n timeoutPromise.catch((err) => {\n reject(err);\n });\n });\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\n\nexport type Platform = \"win32\" | \"darwin\" | \"linux\";\n\nexport function getPlatform(): Platform {\n const p = os.platform();\n if (p === \"win32\" || p === \"darwin\" || p === \"linux\") return p;\n return \"linux\"; // default fallback for other unix-like\n}\n\nexport function isWindows(): boolean {\n return getPlatform() === \"win32\";\n}\n\nexport function normalizePath(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\nexport function getHomeDir(): string {\n return os.homedir();\n}\n\nexport function getClaudeDir(): string {\n return path.join(getHomeDir(), \".claude\");\n}\n\nexport function getTempDir(): string {\n return os.tmpdir();\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport { KILL_GRACE_MS } from \"../config/constants.js\";\nimport { TimeoutError } from \"../errors/errors.js\";\nimport { isWindows } from \"../util/platform.js\";\n\nexport function setupTimeout(\n child: ChildProcess,\n timeoutMs: number,\n): { clear: () => void; promise: Promise<never> } {\n let timer: ReturnType<typeof setTimeout> | null = null;\n let graceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const promise = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n if (isWindows()) {\n // On Windows, SIGTERM is silently ignored by Node.js — it maps to\n // TerminateProcess regardless of signal name. Call kill() with no\n // argument so the intent is explicit and no grace timer is needed.\n child.kill();\n } else {\n // Phase 1: graceful kill\n child.kill(\"SIGTERM\");\n\n // Phase 2: force kill after grace period\n graceTimer = setTimeout(() => {\n try {\n if (!child.killed) {\n child.kill(\"SIGKILL\");\n }\n } catch {\n // Process may already be gone — ignore\n }\n }, KILL_GRACE_MS);\n }\n\n reject(new TimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n const clear = (): void => {\n if (timer) clearTimeout(timer);\n if (graceTimer) clearTimeout(graceTimer);\n };\n\n return { clear, promise };\n}\n","import { MAX_RESPONSE_CHARS } from \"../config/constants.js\";\n\nexport function truncateResponse(\n text: string,\n maxChars: number = MAX_RESPONSE_CHARS,\n): string {\n if (text.length <= maxChars) return text;\n\n const omitted = text.length - maxChars;\n return (\n text.slice(0, maxChars) +\n `\\n\\n[Response truncated at ${maxChars} characters. ${omitted} characters omitted.]`\n );\n}\n","import { EmptyOutputError } from \"../errors/errors.js\";\nimport { truncateResponse } from \"../util/truncate.js\";\n\nexport interface ActivityEntry {\n readonly type: \"exec\" | \"read\" | \"write\";\n readonly command?: string;\n readonly path?: string;\n readonly icon: string;\n readonly status: string;\n}\n\nexport interface TokenUsage {\n readonly input_tokens: number;\n readonly cached_input_tokens: number;\n readonly output_tokens: number;\n}\n\nexport interface CodexResult {\n readonly content: string;\n readonly activity: ActivityEntry[];\n readonly usage: TokenUsage | null;\n readonly raw: string;\n}\n\nexport function parseCodexOutput(raw: string): CodexResult {\n if (!raw.trim()) {\n throw new EmptyOutputError();\n }\n\n const lines = raw.split(\"\\n\").filter((line) => line.trim());\n const messages: string[] = [];\n const activity: ActivityEntry[] = [];\n let resultContent: string | null = null;\n let usage: TokenUsage | null = null;\n\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line);\n\n // Extract token usage from turn.completed events\n if (parsed.type === \"turn.completed\" && parsed.usage) {\n usage = {\n input_tokens: parsed.usage.input_tokens ?? 0,\n cached_input_tokens: parsed.usage.cached_input_tokens ?? 0,\n output_tokens: parsed.usage.output_tokens ?? 0,\n };\n continue;\n }\n\n // Handle result type — takes priority over all other messages\n if (parsed.type === \"result\" && typeof parsed.content === \"string\") {\n resultContent = parsed.content;\n continue;\n }\n\n // Handle standard event format\n if (parsed.type === \"message\" && typeof parsed.content === \"string\") {\n messages.push(parsed.content);\n continue;\n }\n\n // Track command executions\n if (parsed.item?.type === \"command_execution\") {\n const cmd = parsed.item;\n const shortCmd =\n cmd.command?.length > 80\n ? cmd.command.slice(0, 77) + \"...\"\n : cmd.command;\n const statusIcon =\n cmd.status === \"declined\"\n ? \"\\u2718\"\n : cmd.exit_code === 0\n ? \"\\u2714\"\n : cmd.exit_code !== null\n ? \"\\u2718\"\n : \"\\u25B6\";\n const statusLabel =\n cmd.status === \"declined\"\n ? \"blocked\"\n : cmd.status === \"in_progress\"\n ? \"running\"\n : cmd.exit_code === 0\n ? \"ok\"\n : `exit ${cmd.exit_code}`;\n // Only record completed/declined events, not in_progress starts\n if (cmd.status !== \"in_progress\") {\n activity.push({\n type: \"exec\",\n command: shortCmd,\n icon: statusIcon,\n status: statusLabel,\n });\n }\n continue;\n }\n\n // Handle nested item format (Codex JSONL)\n if (parsed.item?.type === \"agent_message\" && typeof parsed.item.text === \"string\") {\n messages.push(parsed.item.text);\n continue;\n }\n\n // Handle flat legacy format\n if (parsed.itemType === \"agent_message\" && typeof parsed.text === \"string\") {\n messages.push(parsed.text);\n continue;\n }\n\n // Track file reads\n if (parsed.item?.type === \"file_read\") {\n activity.push({\n type: \"read\",\n path: parsed.item.path || \"file\",\n icon: \"\\u25B6\",\n status: \"read\",\n });\n continue;\n }\n\n // Track file writes/edits\n if (parsed.item?.type === \"file_write\" || parsed.item?.type === \"file_edit\") {\n activity.push({\n type: \"write\",\n path: parsed.item.path || \"file\",\n icon: \"\\u270E\",\n status: \"write\",\n });\n continue;\n }\n } catch {\n // Non-JSON line — could be preamble or status output. Skip.\n }\n }\n\n let agentMessage: string;\n\n if (resultContent !== null) {\n agentMessage = resultContent;\n } else if (messages.length > 0) {\n agentMessage = messages.join(\"\\n\\n\");\n } else {\n // If no structured output found, use the raw text (minus any obvious preamble)\n const substantiveLines = lines.filter(\n (line) =>\n !line.startsWith(\"OpenAI Codex\") &&\n !line.startsWith(\"---\") &&\n !line.startsWith(\"tokens used\"),\n );\n agentMessage = substantiveLines.join(\"\\n\").trim();\n }\n\n if (!agentMessage) {\n throw new EmptyOutputError();\n }\n\n return {\n content: truncateResponse(agentMessage),\n activity,\n usage,\n raw,\n };\n}\n","import { BridgeError } from \"../errors/errors.js\";\nimport { MAX_RETRIES, MAX_RETRIES_ENV, RETRY_DELAYS_MS, RETRY_CAP_MS } from \"../config/constants.js\";\n\nexport interface RetryOptions {\n readonly maxRetries?: number;\n readonly shouldRetry?: (err: Error) => boolean;\n}\n\nfunction getMaxRetries(override?: number): number {\n if (override !== undefined) return override;\n const envVal = process.env[MAX_RETRIES_ENV];\n if (envVal) {\n const parsed = parseInt(envVal, 10);\n if (!isNaN(parsed) && parsed >= 0) return parsed;\n }\n return MAX_RETRIES;\n}\n\nfunction getDelay(attempt: number): number {\n const base = RETRY_DELAYS_MS[attempt] ?? RETRY_CAP_MS;\n const capped = Math.min(base, RETRY_CAP_MS);\n // Add jitter: 50-150% of base delay\n const jitter = 0.5 + Math.random();\n return Math.round(capped * jitter);\n}\n\nfunction defaultShouldRetry(err: Error): boolean {\n return err instanceof BridgeError && err.retryable;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {},\n): Promise<T> {\n const maxRetries = getMaxRetries(options.maxRetries);\n const shouldRetry = options.shouldRetry ?? defaultShouldRetry;\n\n for (let attempt = 0; ; attempt++) {\n try {\n return await fn();\n } catch (err) {\n const isRetryable = err instanceof Error && shouldRetry(err);\n if (attempt < maxRetries && isRetryable) {\n const delay = getDelay(attempt);\n const errorName = err instanceof Error ? err.constructor.name : \"UnknownError\";\n process.stderr.write(\n `[skill-codex] ${errorName} (attempt ${attempt + 1}/${maxRetries}), retrying in ${delay}ms...\\n`,\n );\n await sleep(delay);\n continue;\n }\n throw err;\n }\n }\n}\n","import { startServer } from \"./server.js\";\n\nstartServer().catch((err) => {\n process.stderr.write(`[skill-codex] Fatal: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path","os","path","path","fs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-codex",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Cross-platform Claude Code skill that integrates OpenAI Codex CLI for code review, task delegation, and consultation via MCP",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,7 +12,7 @@
12
12
  }
13
13
  },
14
14
  "bin": {
15
- "skill-codex": "./dist/bin/skill-codex.js"
15
+ "skill-codex": "dist/bin/skill-codex.js"
16
16
  },
17
17
  "scripts": {
18
18
  "build": "tsup",