@ken-jo/agent-connector 0.1.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.
Files changed (203) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +6 -0
  3. package/README.md +348 -0
  4. package/dist/amp-QSFH2V7Y.js +217 -0
  5. package/dist/amp-QSFH2V7Y.js.map +1 -0
  6. package/dist/amp-TULUPXXL.js +237 -0
  7. package/dist/amp-TULUPXXL.js.map +1 -0
  8. package/dist/antigravity-CX2YLSY7.js +17 -0
  9. package/dist/antigravity-CX2YLSY7.js.map +1 -0
  10. package/dist/antigravity-STHZWMP3.js +171 -0
  11. package/dist/antigravity-STHZWMP3.js.map +1 -0
  12. package/dist/antigravity-cli-P6HADOAO.js +121 -0
  13. package/dist/antigravity-cli-P6HADOAO.js.map +1 -0
  14. package/dist/antigravity-cli-YQDFVV4U.js +86 -0
  15. package/dist/antigravity-cli-YQDFVV4U.js.map +1 -0
  16. package/dist/chunk-54EMKTTX.js +191 -0
  17. package/dist/chunk-54EMKTTX.js.map +1 -0
  18. package/dist/chunk-7L6ITC4T.js +54 -0
  19. package/dist/chunk-7L6ITC4T.js.map +1 -0
  20. package/dist/chunk-7MSDGHJW.js +316 -0
  21. package/dist/chunk-7MSDGHJW.js.map +1 -0
  22. package/dist/chunk-BCHWFTV4.js +196 -0
  23. package/dist/chunk-BCHWFTV4.js.map +1 -0
  24. package/dist/chunk-DBQMX75U.js +36 -0
  25. package/dist/chunk-DBQMX75U.js.map +1 -0
  26. package/dist/chunk-EXLS7BSI.js +29 -0
  27. package/dist/chunk-EXLS7BSI.js.map +1 -0
  28. package/dist/chunk-JNM3TPLX.js +593 -0
  29. package/dist/chunk-JNM3TPLX.js.map +1 -0
  30. package/dist/chunk-JWNT5KW7.js +197 -0
  31. package/dist/chunk-JWNT5KW7.js.map +1 -0
  32. package/dist/chunk-KHO5WNTP.js +30 -0
  33. package/dist/chunk-KHO5WNTP.js.map +1 -0
  34. package/dist/chunk-LTT56GI3.js +155 -0
  35. package/dist/chunk-LTT56GI3.js.map +1 -0
  36. package/dist/chunk-MEH7GC7R.js +111 -0
  37. package/dist/chunk-MEH7GC7R.js.map +1 -0
  38. package/dist/chunk-MQPNU2CY.js +64 -0
  39. package/dist/chunk-MQPNU2CY.js.map +1 -0
  40. package/dist/chunk-OPXAP3AC.js +12 -0
  41. package/dist/chunk-OPXAP3AC.js.map +1 -0
  42. package/dist/chunk-RK6VBLXP.js +50 -0
  43. package/dist/chunk-RK6VBLXP.js.map +1 -0
  44. package/dist/chunk-TIIP3RG2.js +420 -0
  45. package/dist/chunk-TIIP3RG2.js.map +1 -0
  46. package/dist/chunk-TRKWUNO4.js +702 -0
  47. package/dist/chunk-TRKWUNO4.js.map +1 -0
  48. package/dist/chunk-TRQKHP7D.js +93 -0
  49. package/dist/chunk-TRQKHP7D.js.map +1 -0
  50. package/dist/chunk-WCETQWWK.js +59 -0
  51. package/dist/chunk-WCETQWWK.js.map +1 -0
  52. package/dist/chunk-WV63X7IK.js +357 -0
  53. package/dist/chunk-WV63X7IK.js.map +1 -0
  54. package/dist/chunk-XD7MY6HB.js +343 -0
  55. package/dist/chunk-XD7MY6HB.js.map +1 -0
  56. package/dist/chunk-XNAM7F35.js +276 -0
  57. package/dist/chunk-XNAM7F35.js.map +1 -0
  58. package/dist/chunk-XUCWLJY5.js +238 -0
  59. package/dist/chunk-XUCWLJY5.js.map +1 -0
  60. package/dist/chunk-YNZU6PAV.js +800 -0
  61. package/dist/chunk-YNZU6PAV.js.map +1 -0
  62. package/dist/chunk-YT43MUSJ.js +146 -0
  63. package/dist/chunk-YT43MUSJ.js.map +1 -0
  64. package/dist/claude-code-HKDV7T32.js +637 -0
  65. package/dist/claude-code-HKDV7T32.js.map +1 -0
  66. package/dist/claude-code-W74MNTAC.js +652 -0
  67. package/dist/claude-code-W74MNTAC.js.map +1 -0
  68. package/dist/cli/sdk.d.ts +54 -0
  69. package/dist/cli/sdk.js +82 -0
  70. package/dist/cli/sdk.js.map +1 -0
  71. package/dist/cli.d.ts +2 -0
  72. package/dist/cli.js +15 -0
  73. package/dist/cli.js.map +1 -0
  74. package/dist/codebuff-3PMZJJHP.js +307 -0
  75. package/dist/codebuff-3PMZJJHP.js.map +1 -0
  76. package/dist/codebuff-QX57FJDN.js +220 -0
  77. package/dist/codebuff-QX57FJDN.js.map +1 -0
  78. package/dist/codex-JFQTS6LU.js +593 -0
  79. package/dist/codex-JFQTS6LU.js.map +1 -0
  80. package/dist/codex-Q3ATRRX3.js +364 -0
  81. package/dist/codex-Q3ATRRX3.js.map +1 -0
  82. package/dist/copilot-cli-MTCGHZ2T.js +622 -0
  83. package/dist/copilot-cli-MTCGHZ2T.js.map +1 -0
  84. package/dist/copilot-cli-SJGIXVSD.js +369 -0
  85. package/dist/copilot-cli-SJGIXVSD.js.map +1 -0
  86. package/dist/crush-I7PK3FGI.js +360 -0
  87. package/dist/crush-I7PK3FGI.js.map +1 -0
  88. package/dist/crush-LN5QFFR2.js +183 -0
  89. package/dist/crush-LN5QFFR2.js.map +1 -0
  90. package/dist/cursor-4TMXKJOZ.js +603 -0
  91. package/dist/cursor-4TMXKJOZ.js.map +1 -0
  92. package/dist/cursor-QZ6MTO74.js +194 -0
  93. package/dist/cursor-QZ6MTO74.js.map +1 -0
  94. package/dist/detect-WIAGVYS4.js +68 -0
  95. package/dist/detect-WIAGVYS4.js.map +1 -0
  96. package/dist/doctor-EZW2K4NI.js +372 -0
  97. package/dist/doctor-EZW2K4NI.js.map +1 -0
  98. package/dist/droid-KN6VRMMT.js +424 -0
  99. package/dist/droid-KN6VRMMT.js.map +1 -0
  100. package/dist/droid-W5WF5XEX.js +224 -0
  101. package/dist/droid-W5WF5XEX.js.map +1 -0
  102. package/dist/gemini-cli-CIRW37TU.js +369 -0
  103. package/dist/gemini-cli-CIRW37TU.js.map +1 -0
  104. package/dist/gemini-cli-Y35FFK4M.js +705 -0
  105. package/dist/gemini-cli-Y35FFK4M.js.map +1 -0
  106. package/dist/goose-A3M5GODH.js +212 -0
  107. package/dist/goose-A3M5GODH.js.map +1 -0
  108. package/dist/goose-ZTGTSUFJ.js +480 -0
  109. package/dist/goose-ZTGTSUFJ.js.map +1 -0
  110. package/dist/hermes-H2KV44GK.js +470 -0
  111. package/dist/hermes-H2KV44GK.js.map +1 -0
  112. package/dist/hermes-ZYLMOFLZ.js +196 -0
  113. package/dist/hermes-ZYLMOFLZ.js.map +1 -0
  114. package/dist/hook-YVDILAMZ.js +75 -0
  115. package/dist/hook-YVDILAMZ.js.map +1 -0
  116. package/dist/index.d.ts +22 -0
  117. package/dist/index.js +10 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/install-HQRYZOQ2.js +60 -0
  120. package/dist/install-HQRYZOQ2.js.map +1 -0
  121. package/dist/jetbrains-copilot-HWA3DMH7.js +633 -0
  122. package/dist/jetbrains-copilot-HWA3DMH7.js.map +1 -0
  123. package/dist/kilo-NSWAVP6P.js +235 -0
  124. package/dist/kilo-NSWAVP6P.js.map +1 -0
  125. package/dist/kilo-QXJRCSLT.js +384 -0
  126. package/dist/kilo-QXJRCSLT.js.map +1 -0
  127. package/dist/kilo-cli-EAQTHXUW.js +587 -0
  128. package/dist/kilo-cli-EAQTHXUW.js.map +1 -0
  129. package/dist/kilo-cli-EVBKUODA.js +160 -0
  130. package/dist/kilo-cli-EVBKUODA.js.map +1 -0
  131. package/dist/kimi-EI3UM3ZV.js +155 -0
  132. package/dist/kimi-EI3UM3ZV.js.map +1 -0
  133. package/dist/kimi-GQ7VXNYT.js +423 -0
  134. package/dist/kimi-GQ7VXNYT.js.map +1 -0
  135. package/dist/kiro-UCLSLBW2.js +217 -0
  136. package/dist/kiro-UCLSLBW2.js.map +1 -0
  137. package/dist/kiro-VQTT6LO2.js +451 -0
  138. package/dist/kiro-VQTT6LO2.js.map +1 -0
  139. package/dist/leaderboard-K6ON3SWW.js +137 -0
  140. package/dist/leaderboard-K6ON3SWW.js.map +1 -0
  141. package/dist/mux-T2TV4CIQ.js +211 -0
  142. package/dist/mux-T2TV4CIQ.js.map +1 -0
  143. package/dist/mux-ZMLVAXOO.js +96 -0
  144. package/dist/mux-ZMLVAXOO.js.map +1 -0
  145. package/dist/omp-PB4VDKS6.js +586 -0
  146. package/dist/omp-PB4VDKS6.js.map +1 -0
  147. package/dist/openclaw-ETN2M63O.js +751 -0
  148. package/dist/openclaw-ETN2M63O.js.map +1 -0
  149. package/dist/openclaw-IYA7ASL6.js +150 -0
  150. package/dist/openclaw-IYA7ASL6.js.map +1 -0
  151. package/dist/opencode-FZ33JKUZ.js +734 -0
  152. package/dist/opencode-FZ33JKUZ.js.map +1 -0
  153. package/dist/opencode-HWT3RSMN.js +216 -0
  154. package/dist/opencode-HWT3RSMN.js.map +1 -0
  155. package/dist/package-DLOVE2E4.js +1132 -0
  156. package/dist/package-DLOVE2E4.js.map +1 -0
  157. package/dist/pi-CIU2QHT4.js +208 -0
  158. package/dist/pi-CIU2QHT4.js.map +1 -0
  159. package/dist/pi-UFX2OYFV.js +139 -0
  160. package/dist/pi-UFX2OYFV.js.map +1 -0
  161. package/dist/qwen-code-5POCNU6P.js +573 -0
  162. package/dist/qwen-code-5POCNU6P.js.map +1 -0
  163. package/dist/qwen-code-W7NUCDEN.js +134 -0
  164. package/dist/qwen-code-W7NUCDEN.js.map +1 -0
  165. package/dist/roo-code-IOIUXRDE.js +242 -0
  166. package/dist/roo-code-IOIUXRDE.js.map +1 -0
  167. package/dist/roo-code-ZLKH4A7N.js +229 -0
  168. package/dist/roo-code-ZLKH4A7N.js.map +1 -0
  169. package/dist/runtime/index.d.ts +157 -0
  170. package/dist/runtime/index.js +20 -0
  171. package/dist/runtime/index.js.map +1 -0
  172. package/dist/serve-HVWWY4B6.js +65 -0
  173. package/dist/serve-HVWWY4B6.js.map +1 -0
  174. package/dist/status-FE7TECZD.js +128 -0
  175. package/dist/status-FE7TECZD.js.map +1 -0
  176. package/dist/synthetic-UKR6SMGS.js +178 -0
  177. package/dist/synthetic-UKR6SMGS.js.map +1 -0
  178. package/dist/telemetry-36GESKQQ.js +349 -0
  179. package/dist/telemetry-36GESKQQ.js.map +1 -0
  180. package/dist/trae-JSNDZFKL.js +204 -0
  181. package/dist/trae-JSNDZFKL.js.map +1 -0
  182. package/dist/trae-PA26DPBW.js +157 -0
  183. package/dist/trae-PA26DPBW.js.map +1 -0
  184. package/dist/types-CYUB1OTr.d.ts +427 -0
  185. package/dist/uninstall-IGCKNOSF.js +72 -0
  186. package/dist/uninstall-IGCKNOSF.js.map +1 -0
  187. package/dist/upgrade-JV2VK242.js +104 -0
  188. package/dist/upgrade-JV2VK242.js.map +1 -0
  189. package/dist/usage-6ER6EMEY.js +324 -0
  190. package/dist/usage-6ER6EMEY.js.map +1 -0
  191. package/dist/usage-event-JKBI6XCF.js +48 -0
  192. package/dist/usage-event-JKBI6XCF.js.map +1 -0
  193. package/dist/vscode-copilot-CK3NO54M.js +715 -0
  194. package/dist/vscode-copilot-CK3NO54M.js.map +1 -0
  195. package/dist/warp-JNQA7PBU.js +126 -0
  196. package/dist/warp-JNQA7PBU.js.map +1 -0
  197. package/dist/warp-QNVDXOG4.js +199 -0
  198. package/dist/warp-QNVDXOG4.js.map +1 -0
  199. package/dist/zed-NNNX5MNT.js +272 -0
  200. package/dist/zed-NNNX5MNT.js.map +1 -0
  201. package/dist/zed-VRJKWYUR.js +209 -0
  202. package/dist/zed-VRJKWYUR.js.map +1 -0
  203. package/package.json +79 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/codex/index.ts"],"sourcesContent":["/**\n * adapters/codex — Codex CLI platform adapter for agent-connector.\n *\n * Codex CLI hook paradigm is \"json-stdio\": the host pipes a JSON payload to a\n * command on stdin and reads JSON/exit-code back — the same wire protocol as\n * Claude Code (PascalCase fields, `hookSpecificOutput` reply wrapper).\n *\n * Two native config files live under the Codex config dir\n * (`$CODEX_HOME` || `~/.codex`, mirrored to `<projectDir>/.codex` for project\n * scope):\n * - config.toml → `[mcp_servers.<id>]` MCP registration (TOML, NO native\n * interpolation, so env-refs are resolved to literals at install time).\n * - hooks.json → Claude-compatible hook registration ({ matcher, hooks }).\n *\n * Grounded in context-mode's proven Codex adapter (configs/codex/{config.toml,\n * hooks.json}, src/adapters/codex/*) — exact TOML MCP shape + hook JSON schema.\n *\n * Known Codex limitations (upstream): PreToolUse deny works but updatedInput is\n * not yet honored (openai/codex#18491); PostToolUse updatedMCPToolOutput is\n * parsed-but-unsupported — hence canModifyArgs / canModifyOutput are false.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport TOML from \"@iarna/toml\";\n\nimport type {\n ChangeRecord,\n CommandDef,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n SkillDef,\n SubagentDef,\n} from \"../../core/types.js\";\nimport { ensureDir } from \"../../core/paths.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport { writeTomlString } from \"../../core/toml.js\";\nimport {\n buildHomeBinHookCommand,\n buildServeWrapperCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\nimport { BaseAdapter } from \"../base.js\";\nimport type {\n HookReply,\n InstallContext,\n NormalizedEvent,\n} from \"../spi.js\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Native shapes\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Raw Codex hook payload (PascalCase event, snake_case fields — Claude-style). */\ninterface CodexHookInput {\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_response?: string;\n session_id?: string;\n cwd?: string;\n hook_event_name?: string;\n source?: string;\n prompt?: string;\n is_error?: boolean;\n stop_hook_active?: boolean;\n trigger?: string;\n message?: string;\n}\n\n/** One hook entry inside hooks.json (Claude-compatible). */\ninterface CodexHookEntry {\n matcher?: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\ninterface CodexHooksFile {\n hooks?: Record<string, CodexHookEntry[]>;\n [key: string]: unknown;\n}\n\n/** Rendered `[mcp_servers.<id>]` table — string env table, no interpolation. */\ninterface CodexMcpEntry {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\n\n/**\n * Codex hook events agent-connector registers, in the canonical → native order.\n * Codex uses the same PascalCase event names as Claude Code; the home-binary\n * hook command receives the lowercased event token.\n */\nconst CODEX_HOOK_EVENTS = [\n \"SessionStart\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PreCompact\",\n \"UserPromptSubmit\",\n \"Stop\",\n] as const;\n\ntype CodexHookEventName = (typeof CODEX_HOOK_EVENTS)[number];\n\n/**\n * PreToolUse matcher — canonical Codex tool names + bare MCP tool names +\n * external MCP catch-all literal. Charset-clean ([A-Za-z0-9_|] only) so Codex's\n * Rust `regex` exact-matcher short-circuits (no look-around, which Codex\n * rejects at boot). Copied from context-mode's proven matcher.\n */\nconst PRE_TOOL_USE_MATCHER =\n \"local_shell|shell|shell_command|exec_command|Bash|Shell|apply_patch|Edit|Write|grep_files|mcp__\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Adapter\n// ─────────────────────────────────────────────────────────────────────────\n\nexport class CodexAdapter extends BaseAdapter {\n readonly id: PlatformId = \"codex\";\n readonly name = \"Codex CLI\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: false,\n userPromptSubmit: true,\n stop: true,\n notification: false,\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: true,\n transports: [\"stdio\", \"http\"],\n // Content surfaces: Codex implements all three.\n // command → ~/.codex/prompts/<name>.md (md+frontmatter, USER SCOPE ONLY)\n // skill → <codexDir>/skills/<name>/SKILL.md (+ resources)\n // subagent → <codexDir>/agents/<name>.toml (TOML)\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: true,\n };\n\n // ── Detection ──────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = this.userConfigDir();\n const projDir = join(projectDir, \".codex\");\n const userCfg = join(userDir, \"config.toml\");\n const projCfg = join(projDir, \"config.toml\");\n\n const userInstalled = existsSync(userDir) || existsSync(userCfg);\n const projInstalled = existsSync(projDir) || existsSync(projCfg);\n const installed = userInstalled || projInstalled;\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projCfg : userCfg;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `Found Codex config dir (${scope})`\n : `No .codex config dir at ${userDir} or ${projDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ───────────────────────────────────────────────────────\n\n override getConfigDir(ctx: InstallContext): string {\n if (ctx.scope === \"project\") return join(ctx.projectDir, \".codex\");\n return this.userConfigDir();\n }\n\n override getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"config.toml\");\n }\n\n override getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"hooks.json\");\n }\n\n /** `$CODEX_HOME` || `~/.codex` for user scope. */\n private userConfigDir(): string {\n const env = process.env.CODEX_HOME;\n if (env && env.trim() !== \"\") {\n if (env.startsWith(\"~\")) {\n return join(homedir(), env.replace(/^~[/\\\\]?/, \"\"));\n }\n return env;\n }\n return join(homedir(), \".codex\");\n }\n\n // ── TOML config IO (override JSON helpers — config.toml is TOML) ─────────\n\n private readToml(path: string): Record<string, unknown> {\n if (!existsSync(path)) return {};\n try {\n return TOML.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n\n private writeToml(path: string, data: Record<string, unknown>, dryRun: boolean): void {\n if (dryRun) return;\n ensureDir(dirname(path));\n // @iarna/toml's stringify type wants its JsonMap; our object is structurally compatible.\n writeFileSync(path, TOML.stringify(data as never), \"utf8\");\n }\n\n // ── Install server (config.toml → [mcp_servers.<id>]) ───────────────────\n\n override installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n const server = this.effectiveServer(ctx);\n const path = this.getServerConfigPath(ctx);\n\n if (!server) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"no server declared\" }];\n }\n if (server.transport !== \"stdio\" || !server.command) {\n // Codex config.toml [mcp_servers] is stdio-only; remote transports skip here.\n return [\n {\n platform: this.id,\n action: \"skip\",\n path,\n detail: `transport \"${server.transport}\" not registrable in config.toml (stdio only)`,\n },\n ];\n }\n\n const entry = this.renderMcpEntry(ctx, server);\n\n const cfg = this.readToml(path);\n const bucket = this.tomlBucket(cfg, \"mcp_servers\");\n const before = JSON.stringify(bucket[connector.id]);\n const after = JSON.stringify(entry);\n\n let action: ChangeRecord[\"action\"];\n if (before === undefined) action = \"create\";\n else if (before === after) action = \"skip\";\n else action = \"update\";\n\n if (action !== \"skip\") {\n bucket[connector.id] = entry as unknown as Record<string, unknown>;\n this.writeToml(path, cfg, dryRun);\n }\n return [{ platform: this.id, action, path, detail: `mcp_servers.${connector.id}` }];\n }\n\n override uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n const path = this.getServerConfigPath(ctx);\n const cfg = this.readToml(path);\n const bucket = cfg[\"mcp_servers\"];\n if (\n !existsSync(path) ||\n typeof bucket !== \"object\" ||\n bucket === null ||\n !(connector.id in (bucket as Record<string, unknown>))\n ) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path,\n detail: `mcp_servers.${connector.id} absent`,\n },\n ];\n }\n delete (bucket as Record<string, unknown>)[connector.id];\n this.writeToml(path, cfg, dryRun);\n return [{ platform: this.id, action: \"remove\", path, detail: `mcp_servers.${connector.id}` }];\n }\n\n // ── Install hooks (hooks.json) ──────────────────────────────────────────\n\n override installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n const path = this.getHookConfigPath(ctx);\n const events = this.effectiveHookEvents(ctx);\n\n if (events.length === 0) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"no hooks declared\" }];\n }\n\n const file = this.readHooksFile(path);\n const hooks = (file.hooks ??= {});\n const changes: ChangeRecord[] = [];\n\n for (const event of events) {\n const desired = this.renderHookEntry(ctx, event);\n const list = Array.isArray(hooks[event]) ? hooks[event] : (hooks[event] = []);\n const idx = list.findIndex((e) => this.isOurEntry(ctx, event, e));\n if (idx < 0) {\n list.push(desired);\n changes.push({ platform: this.id, action: \"create\", path, detail: `hooks.${event}` });\n } else if (JSON.stringify(list[idx]) !== JSON.stringify(desired)) {\n list[idx] = desired;\n changes.push({ platform: this.id, action: \"update\", path, detail: `hooks.${event}` });\n } else {\n changes.push({ platform: this.id, action: \"skip\", path, detail: `hooks.${event}` });\n }\n }\n\n if (changes.some((c) => c.action !== \"skip\")) {\n this.writeJson(path, file, dryRun);\n }\n return changes;\n }\n\n override uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const path = this.getHookConfigPath(ctx);\n const file = this.readJson<CodexHooksFile>(path);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"no hooks.json\" }];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n for (const event of CODEX_HOOK_EVENTS) {\n const list = hooks[event];\n if (!Array.isArray(list)) continue;\n const kept = list.filter((e) => !this.isOurEntry(ctx, event, e));\n if (kept.length === list.length) continue;\n mutated = true;\n if (kept.length > 0) hooks[event] = kept;\n else delete hooks[event];\n changes.push({ platform: this.id, action: \"remove\", path, detail: `hooks.${event}` });\n }\n\n if (mutated) this.writeJson(path, file, ctx.dryRun);\n if (changes.length === 0) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"no agent-connector hooks present\" }];\n }\n return changes;\n }\n\n // ── Health checks (default doctor renders these) ────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const path = this.getServerConfigPath(ctx);\n const id = ctx.connector.id;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: config.toml exists`,\n check: () =>\n existsSync(path)\n ? { status: \"OK\", detail: path }\n : { status: \"FAIL\", detail: `not found: ${path}` },\n },\n {\n name: `${this.name}: mcp_servers.${id} registered`,\n check: () => {\n const cfg = this.readToml(path);\n const bucket = cfg[\"mcp_servers\"];\n const present =\n typeof bucket === \"object\" &&\n bucket !== null &&\n id in (bucket as Record<string, unknown>);\n return present\n ? { status: \"OK\", detail: `mcp_servers.${id}` }\n : { status: \"FAIL\", detail: `mcp_servers.${id} not found in ${path}` };\n },\n },\n ];\n\n // Content-surface checks: assert presence only for surfaces this connector\n // declares. Codex commands are user-scope only, so a project-scope install\n // won't have written them — only check command files in user scope.\n if (ctx.scope !== \"project\") {\n for (const cmd of ctx.connector.commands) {\n const p = this.commandPath(cmd.name);\n checks.push({\n name: `${this.name}: command ${cmd.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n }\n for (const skill of ctx.connector.skills) {\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const agent of ctx.connector.subagents) {\n const p = this.subagentPath(ctx, agent.name);\n checks.push({\n name: `${this.name}: subagent ${agent.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n return checks;\n }\n\n // ── Content surfaces: commands / skills / subagents ──────────────────────\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\n // skip) via writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"codex\"] per-surface false to skip.\n //\n // Native locations:\n // command → ~/.codex/prompts/<name>.md md+frontmatter(description,argument-hint)\n // USER SCOPE ONLY — project scope yields a single \"warn\".\n // skill → <codexDir>/skills/<name>/SKILL.md (+ resources)\n // subagent → <codexDir>/agents/<name>.toml TOML via writeTomlString\n\n /** Command files always live under the USER codex dir: ~/.codex/prompts. */\n private commandPath(name: string): string {\n return join(this.userConfigDir(), \"prompts\", `${name}.md`);\n }\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.getConfigDir(ctx), \"skills\", name);\n }\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.getConfigDir(ctx), \"agents\", `${name}.toml`);\n }\n\n // ── Commands (USER SCOPE ONLY) ───────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for codex\" }];\n }\n if (ctx.scope === \"project\") {\n return [{ platform: this.id, action: \"warn\", detail: \"codex commands are user-scope only\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.writeContentFile(this.commandPath(cmd.name), this.renderCommand(cmd), ctx.dryRun),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (ctx.scope === \"project\") {\n return [{ platform: this.id, action: \"warn\", detail: \"codex commands are user-scope only\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(cmd.name), ctx.dryRun),\n );\n }\n\n /** Render a command to md+frontmatter (description, argument-hint). */\n private renderCommand(cmd: CommandDef): string {\n const frontmatter: Record<string, unknown> = {};\n if (cmd.description !== undefined) frontmatter.description = cmd.description;\n if (cmd.argumentHint !== undefined) frontmatter[\"argument-hint\"] = cmd.argumentHint;\n if (cmd.extra) Object.assign(frontmatter, cmd.extra);\n return this.renderFrontmatterMd(frontmatter, cmd.prompt);\n }\n\n // ── Skills ───────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for codex\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n /**\n * Render a skill's SKILL.md: frontmatter (name, description + optional model,\n * allowed-tools, disable-model-invocation) + body. UNIFORM with every other\n * skill-supporting platform — only the parent dir differs.\n */\n private renderSkill(skill: SkillDef): string {\n const frontmatter: Record<string, unknown> = {\n name: skill.name,\n description: skill.description,\n };\n if (skill.model !== undefined) frontmatter.model = skill.model;\n const allow = skill.tools?.allow;\n if (allow && allow.length > 0) frontmatter[\"allowed-tools\"] = allow.join(\", \");\n if (skill.disableModelInvocation !== undefined) {\n frontmatter[\"disable-model-invocation\"] = skill.disableModelInvocation;\n }\n if (skill.extra) Object.assign(frontmatter, skill.extra);\n return this.renderFrontmatterMd(frontmatter, skill.body);\n }\n\n // ── Subagents (TOML) ─────────────────────────────────────────────────────\n\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.subagents === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for codex\" }];\n }\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.writeContentFile(this.subagentPath(ctx, agent.name), this.renderSubagent(agent), ctx.dryRun),\n );\n }\n\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\n );\n }\n\n /**\n * Render a subagent to a Codex agent TOML file:\n * { name, description, developer_instructions: prompt, model }.\n * model is omitted when undefined so Codex applies its default.\n */\n private renderSubagent(agent: SubagentDef): string {\n const table: Record<string, unknown> = {\n name: agent.name,\n description: agent.description,\n developer_instructions: agent.prompt,\n };\n if (agent.model !== undefined) table.model = agent.model;\n if (agent.extra) Object.assign(table, agent.extra);\n return writeTomlString(table);\n }\n\n // ── Runtime dispatch ────────────────────────────────────────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as CodexHookInput;\n const base = {\n hostPlatform: this.id,\n connectorId: \"\",\n sessionId: input.session_id ?? `pid-${process.ppid}`,\n projectDir: input.cwd ?? process.env.CODEX_PROJECT_DIR ?? process.cwd(),\n raw,\n };\n\n switch (event) {\n case \"PreToolUse\":\n return {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n case \"PostToolUse\":\n return {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n toolOutput: input.tool_response,\n isError: input.is_error ?? false,\n };\n case \"SessionStart\":\n return { ...base, source: this.normalizeSource(input.source) };\n case \"SessionEnd\":\n return { ...base, reason: input.message };\n case \"UserPromptSubmit\":\n return { ...base, prompt: input.prompt ?? \"\" };\n case \"PreCompact\":\n return { ...base, trigger: input.trigger === \"manual\" ? \"manual\" : \"auto\" };\n case \"Stop\":\n return { ...base, stopHookActive: input.stop_hook_active ?? false };\n case \"Notification\":\n return { ...base, message: input.message ?? \"\" };\n }\n }\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n // Codex (like Claude Code) reads a `hookSpecificOutput` JSON wrapper from\n // stdout; exit code 0 = allow. Fields the host cannot honor are dropped.\n if (response.decision === \"deny\") {\n // PreToolUse deny is honored; other events fail-open to allow.\n if (event === \"PreToolUse\") {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n },\n }),\n };\n }\n return { exitCode: 0 };\n }\n\n // Context injection: honored on SessionStart and PostToolUse (additionalContext).\n if (response.additionalContext && (event === \"SessionStart\" || event === \"PostToolUse\")) {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: event,\n additionalContext: response.additionalContext,\n },\n }),\n };\n }\n\n // \"allow\" / unsupported-on-Codex (modify, ask) → passthrough.\n return { exitCode: 0 };\n }\n\n // ── Internal helpers ────────────────────────────────────────────────────\n\n /** Resolve the per-platform server override into an effective ServerDef. */\n private effectiveServer(ctx: InstallContext): ServerDef | undefined {\n const override = ctx.connector.platforms[this.id]?.server;\n if (override === false) return undefined;\n const base = ctx.connector.server;\n if (!base) return undefined;\n return override ? { ...base, ...override } : base;\n }\n\n /** Which canonical hook events to register for Codex, honoring overrides. */\n private effectiveHookEvents(ctx: InstallContext): CodexHookEventName[] {\n const override = ctx.connector.platforms[this.id]?.hooks;\n if (override === false) return [];\n return CODEX_HOOK_EVENTS.filter((e) => ctx.connector.hookEvents.includes(e));\n }\n\n /**\n * Render the `[mcp_servers.<id>]` table. TOML has NO interpolation, so every\n * `${env:VAR}` is resolved to a literal at install time. The env table is a\n * plain string→string map. Honors the telemetry serve-wrapper.\n */\n private renderMcpEntry(ctx: InstallContext, server: ServerDef): CodexMcpEntry {\n let command = server.command as string;\n let args = [...(server.args ?? [])];\n\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(ctx.homeBinPath, ctx.connector.id, command, args, ctx.scope, this.id);\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Resolve env-refs to literals (TOML cannot interpolate).\n command = resolveEnvRefsDeep(command);\n args = resolveEnvRefsDeep(args);\n\n const entry: CodexMcpEntry = { command };\n if (args.length > 0) entry.args = args;\n\n if (server.env && Object.keys(server.env).length > 0) {\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.env))) {\n env[k] = String(v);\n }\n entry.env = env;\n }\n return entry;\n }\n\n /** Render one hooks.json entry pointing at the stable home binary. */\n private renderHookEntry(ctx: InstallContext, event: CodexHookEventName): CodexHookEntry {\n const command = buildHomeBinHookCommand(\n ctx.homeBinPath,\n \"codex\",\n event,\n ctx.connector.id,\n );\n const entry: CodexHookEntry = { hooks: [{ type: \"command\", command }] };\n if (event === \"PreToolUse\") entry.matcher = PRE_TOOL_USE_MATCHER;\n else entry.matcher = \"\";\n return entry;\n }\n\n /** Does this hooks.json entry belong to this connector (by home-bin command)? */\n private isOurEntry(ctx: InstallContext, event: CodexHookEventName, entry: CodexHookEntry): boolean {\n if (!entry || typeof entry !== \"object\" || !Array.isArray(entry.hooks)) return false;\n const ours = buildHomeBinHookCommand(ctx.homeBinPath, \"codex\", event, ctx.connector.id);\n const needle = ours.replace(/\\\\/g, \"/\");\n return entry.hooks.some((h) => (h.command ?? \"\").replace(/\\\\/g, \"/\") === needle);\n }\n\n private readHooksFile(path: string): CodexHooksFile {\n return this.readJson<CodexHooksFile>(path) ?? {};\n }\n\n /** Get-or-create a nested table inside a parsed TOML object. */\n private tomlBucket(cfg: Record<string, unknown>, key: string): Record<string, unknown> {\n const existing = cfg[key];\n if (existing && typeof existing === \"object\" && !Array.isArray(existing)) {\n return existing as Record<string, unknown>;\n }\n const fresh: Record<string, unknown> = {};\n cfg[key] = fresh;\n return fresh;\n }\n\n private normalizeSource(raw: string | undefined): \"startup\" | \"compact\" | \"resume\" | \"clear\" {\n switch (raw) {\n case \"compact\":\n return \"compact\";\n case \"resume\":\n return \"resume\";\n case \"clear\":\n return \"clear\";\n default:\n return \"startup\";\n }\n }\n}\n\nexport const adapter = new CodexAdapter();\nexport default adapter;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAsBA,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,eAAe;AACxB,SAAS,SAAS,YAAY;AAE9B,OAAO,UAAU;AA0EjB,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAUA,IAAM,uBACJ;AAMK,IAAM,eAAN,cAA2B,YAAY;AAAA,EACnC,KAAiB;AAAA,EACjB,OAAO;AAAA,EACP,WAAyB;AAAA,EAEzB,eAAqC;AAAA,IAC5C,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,MAAM;AAAA,IACN,cAAc;AAAA,IACd,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,IACzB,YAAY,CAAC,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,IAK5B,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,EACrB;AAAA;AAAA,EAIA,gBAAgB,YAAsC;AACpD,UAAM,UAAU,KAAK,cAAc;AACnC,UAAM,UAAU,KAAK,YAAY,QAAQ;AACzC,UAAM,UAAU,KAAK,SAAS,aAAa;AAC3C,UAAM,UAAU,KAAK,SAAS,aAAa;AAE3C,UAAM,gBAAgB,WAAW,OAAO,KAAK,WAAW,OAAO;AAC/D,UAAM,gBAAgB,WAAW,OAAO,KAAK,WAAW,OAAO;AAC/D,UAAM,YAAY,iBAAiB;AACnC,UAAM,QAAQ,iBAAiB,CAAC,gBAAgB,YAAY;AAC5D,UAAM,aAAa,UAAU,YAAY,UAAU;AAEnD,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX;AAAA,MACA,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ,YACJ,2BAA2B,KAAK,MAChC,2BAA2B,OAAO,OAAO,OAAO;AAAA,MACpD,YAAY,YAAY,SAAS;AAAA,IACnC;AAAA,EACF;AAAA;AAAA,EAIS,aAAa,KAA6B;AACjD,QAAI,IAAI,UAAU,UAAW,QAAO,KAAK,IAAI,YAAY,QAAQ;AACjE,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAES,oBAAoB,KAA6B;AACxD,WAAO,KAAK,KAAK,aAAa,GAAG,GAAG,aAAa;AAAA,EACnD;AAAA,EAES,kBAAkB,KAA6B;AACtD,WAAO,KAAK,KAAK,aAAa,GAAG,GAAG,YAAY;AAAA,EAClD;AAAA;AAAA,EAGQ,gBAAwB;AAC9B,UAAM,MAAM,QAAQ,IAAI;AACxB,QAAI,OAAO,IAAI,KAAK,MAAM,IAAI;AAC5B,UAAI,IAAI,WAAW,GAAG,GAAG;AACvB,eAAO,KAAK,QAAQ,GAAG,IAAI,QAAQ,YAAY,EAAE,CAAC;AAAA,MACpD;AACA,aAAO;AAAA,IACT;AACA,WAAO,KAAK,QAAQ,GAAG,QAAQ;AAAA,EACjC;AAAA;AAAA,EAIQ,SAAS,MAAuC;AACtD,QAAI,CAAC,WAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,QAAI;AACF,aAAO,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC;AAAA,IAC9C,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,UAAU,MAAc,MAA+B,QAAuB;AACpF,QAAI,OAAQ;AACZ,cAAU,QAAQ,IAAI,CAAC;AAEvB,kBAAc,MAAM,KAAK,UAAU,IAAa,GAAG,MAAM;AAAA,EAC3D;AAAA;AAAA,EAIS,cAAc,KAAqC;AAC1D,UAAM,EAAE,WAAW,OAAO,IAAI;AAC9B,UAAM,SAAS,KAAK,gBAAgB,GAAG;AACvC,UAAM,OAAO,KAAK,oBAAoB,GAAG;AAEzC,QAAI,CAAC,QAAQ;AACX,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,MAAM,QAAQ,qBAAqB,CAAC;AAAA,IACnF;AACA,QAAI,OAAO,cAAc,WAAW,CAAC,OAAO,SAAS;AAEnD,aAAO;AAAA,QACL;AAAA,UACE,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR;AAAA,UACA,QAAQ,cAAc,OAAO,SAAS;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,eAAe,KAAK,MAAM;AAE7C,UAAM,MAAM,KAAK,SAAS,IAAI;AAC9B,UAAM,SAAS,KAAK,WAAW,KAAK,aAAa;AACjD,UAAM,SAAS,KAAK,UAAU,OAAO,UAAU,EAAE,CAAC;AAClD,UAAM,QAAQ,KAAK,UAAU,KAAK;AAElC,QAAI;AACJ,QAAI,WAAW,OAAW,UAAS;AAAA,aAC1B,WAAW,MAAO,UAAS;AAAA,QAC/B,UAAS;AAEd,QAAI,WAAW,QAAQ;AACrB,aAAO,UAAU,EAAE,IAAI;AACvB,WAAK,UAAU,MAAM,KAAK,MAAM;AAAA,IAClC;AACA,WAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,MAAM,QAAQ,eAAe,UAAU,EAAE,GAAG,CAAC;AAAA,EACpF;AAAA,EAES,gBAAgB,KAAqC;AAC5D,UAAM,EAAE,WAAW,OAAO,IAAI;AAC9B,UAAM,OAAO,KAAK,oBAAoB,GAAG;AACzC,UAAM,MAAM,KAAK,SAAS,IAAI;AAC9B,UAAM,SAAS,IAAI,aAAa;AAChC,QACE,CAAC,WAAW,IAAI,KAChB,OAAO,WAAW,YAClB,WAAW,QACX,EAAE,UAAU,MAAO,SACnB;AACA,aAAO;AAAA,QACL;AAAA,UACE,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR;AAAA,UACA,QAAQ,eAAe,UAAU,EAAE;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AACA,WAAQ,OAAmC,UAAU,EAAE;AACvD,SAAK,UAAU,MAAM,KAAK,MAAM;AAChC,WAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,UAAU,MAAM,QAAQ,eAAe,UAAU,EAAE,GAAG,CAAC;AAAA,EAC9F;AAAA;AAAA,EAIS,aAAa,KAAqC;AACzD,UAAM,EAAE,WAAW,OAAO,IAAI;AAC9B,UAAM,OAAO,KAAK,kBAAkB,GAAG;AACvC,UAAM,SAAS,KAAK,oBAAoB,GAAG;AAE3C,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,MAAM,QAAQ,oBAAoB,CAAC;AAAA,IAClF;AAEA,UAAM,OAAO,KAAK,cAAc,IAAI;AACpC,UAAM,QAAS,KAAK,UAAU,CAAC;AAC/B,UAAM,UAA0B,CAAC;AAEjC,eAAW,SAAS,QAAQ;AAC1B,YAAM,UAAU,KAAK,gBAAgB,KAAK,KAAK;AAC/C,YAAM,OAAO,MAAM,QAAQ,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,IAAK,MAAM,KAAK,IAAI,CAAC;AAC3E,YAAM,MAAM,KAAK,UAAU,CAAC,MAAM,KAAK,WAAW,KAAK,OAAO,CAAC,CAAC;AAChE,UAAI,MAAM,GAAG;AACX,aAAK,KAAK,OAAO;AACjB,gBAAQ,KAAK,EAAE,UAAU,KAAK,IAAI,QAAQ,UAAU,MAAM,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,MACtF,WAAW,KAAK,UAAU,KAAK,GAAG,CAAC,MAAM,KAAK,UAAU,OAAO,GAAG;AAChE,aAAK,GAAG,IAAI;AACZ,gBAAQ,KAAK,EAAE,UAAU,KAAK,IAAI,QAAQ,UAAU,MAAM,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,MACtF,OAAO;AACL,gBAAQ,KAAK,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,MAAM,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,MACpF;AAAA,IACF;AAEA,QAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,GAAG;AAC5C,WAAK,UAAU,MAAM,MAAM,MAAM;AAAA,IACnC;AACA,WAAO;AAAA,EACT;AAAA,EAES,eAAe,KAAqC;AAC3D,UAAM,OAAO,KAAK,kBAAkB,GAAG;AACvC,UAAM,OAAO,KAAK,SAAyB,IAAI;AAC/C,UAAM,QAAQ,MAAM;AACpB,QAAI,CAAC,QAAQ,CAAC,OAAO;AACnB,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,MAAM,QAAQ,gBAAgB,CAAC;AAAA,IAC9E;AAEA,UAAM,UAA0B,CAAC;AACjC,QAAI,UAAU;AACd,eAAW,SAAS,mBAAmB;AACrC,YAAM,OAAO,MAAM,KAAK;AACxB,UAAI,CAAC,MAAM,QAAQ,IAAI,EAAG;AAC1B,YAAM,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,KAAK,WAAW,KAAK,OAAO,CAAC,CAAC;AAC/D,UAAI,KAAK,WAAW,KAAK,OAAQ;AACjC,gBAAU;AACV,UAAI,KAAK,SAAS,EAAG,OAAM,KAAK,IAAI;AAAA,UAC/B,QAAO,MAAM,KAAK;AACvB,cAAQ,KAAK,EAAE,UAAU,KAAK,IAAI,QAAQ,UAAU,MAAM,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,IACtF;AAEA,QAAI,QAAS,MAAK,UAAU,MAAM,MAAM,IAAI,MAAM;AAClD,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,MAAM,QAAQ,mCAAmC,CAAC;AAAA,IACjG;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAIS,gBAAgB,KAA6C;AACpE,UAAM,OAAO,KAAK,oBAAoB,GAAG;AACzC,UAAM,KAAK,IAAI,UAAU;AACzB,UAAM,SAAwB;AAAA,MAC5B;AAAA,QACE,MAAM,GAAG,KAAK,IAAI;AAAA,QAClB,OAAO,MACL,WAAW,IAAI,IACX,EAAE,QAAQ,MAAM,QAAQ,KAAK,IAC7B,EAAE,QAAQ,QAAQ,QAAQ,cAAc,IAAI,GAAG;AAAA,MACvD;AAAA,MACA;AAAA,QACE,MAAM,GAAG,KAAK,IAAI,iBAAiB,EAAE;AAAA,QACrC,OAAO,MAAM;AACX,gBAAM,MAAM,KAAK,SAAS,IAAI;AAC9B,gBAAM,SAAS,IAAI,aAAa;AAChC,gBAAM,UACJ,OAAO,WAAW,YAClB,WAAW,QACX,MAAO;AACT,iBAAO,UACH,EAAE,QAAQ,MAAM,QAAQ,eAAe,EAAE,GAAG,IAC5C,EAAE,QAAQ,QAAQ,QAAQ,eAAe,EAAE,iBAAiB,IAAI,GAAG;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AAKA,QAAI,IAAI,UAAU,WAAW;AAC3B,iBAAW,OAAO,IAAI,UAAU,UAAU;AACxC,cAAM,IAAI,KAAK,YAAY,IAAI,IAAI;AACnC,eAAO,KAAK;AAAA,UACV,MAAM,GAAG,KAAK,IAAI,aAAa,IAAI,IAAI;AAAA,UACvC,OAAO,MACL,WAAW,CAAC,IAAI,EAAE,QAAQ,MAAM,QAAQ,EAAE,IAAI,EAAE,QAAQ,QAAQ,QAAQ,cAAc,CAAC,GAAG;AAAA,QAC9F,CAAC;AAAA,MACH;AAAA,IACF;AACA,eAAW,SAAS,IAAI,UAAU,QAAQ;AACxC,YAAM,IAAI,KAAK,KAAK,SAAS,KAAK,MAAM,IAAI,GAAG,UAAU;AACzD,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,KAAK,IAAI,WAAW,MAAM,IAAI;AAAA,QACvC,OAAO,MACL,WAAW,CAAC,IAAI,EAAE,QAAQ,MAAM,QAAQ,EAAE,IAAI,EAAE,QAAQ,QAAQ,QAAQ,cAAc,CAAC,GAAG;AAAA,MAC9F,CAAC;AAAA,IACH;AACA,eAAW,SAAS,IAAI,UAAU,WAAW;AAC3C,YAAM,IAAI,KAAK,aAAa,KAAK,MAAM,IAAI;AAC3C,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,KAAK,IAAI,cAAc,MAAM,IAAI;AAAA,QAC1C,OAAO,MACL,WAAW,CAAC,IAAI,EAAE,QAAQ,MAAM,QAAQ,EAAE,IAAI,EAAE,QAAQ,QAAQ,QAAQ,cAAc,CAAC,GAAG;AAAA,MAC9F,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeQ,YAAY,MAAsB;AACxC,WAAO,KAAK,KAAK,cAAc,GAAG,WAAW,GAAG,IAAI,KAAK;AAAA,EAC3D;AAAA,EACQ,SAAS,KAAqB,MAAsB;AAC1D,WAAO,KAAK,KAAK,aAAa,GAAG,GAAG,UAAU,IAAI;AAAA,EACpD;AAAA,EACQ,aAAa,KAAqB,MAAsB;AAC9D,WAAO,KAAK,KAAK,aAAa,GAAG,GAAG,UAAU,GAAG,IAAI,OAAO;AAAA,EAC9D;AAAA;AAAA,EAIS,gBAAgB,KAAqC;AAC5D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,UAAU,KAAK,EAAE,GAAG,aAAa,OAAO;AACpD,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,8BAA8B,CAAC;AAAA,IACtF;AACA,QAAI,IAAI,UAAU,WAAW;AAC3B,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,qCAAqC,CAAC;AAAA,IAC7F;AACA,QAAI,UAAU,SAAS,WAAW,GAAG;AACnC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,iCAAiC,CAAC;AAAA,IACzF;AACA,WAAO,UAAU,SAAS;AAAA,MAAI,CAAC,QAC7B,KAAK,iBAAiB,KAAK,YAAY,IAAI,IAAI,GAAG,KAAK,cAAc,GAAG,GAAG,IAAI,MAAM;AAAA,IACvF;AAAA,EACF;AAAA,EAES,kBAAkB,KAAqC;AAC9D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,IAAI,UAAU,WAAW;AAC3B,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,qCAAqC,CAAC;AAAA,IAC7F;AACA,QAAI,UAAU,SAAS,WAAW,GAAG;AACnC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,iCAAiC,CAAC;AAAA,IACzF;AACA,WAAO,UAAU,SAAS;AAAA,MAAI,CAAC,QAC7B,KAAK,kBAAkB,KAAK,YAAY,IAAI,IAAI,GAAG,IAAI,MAAM;AAAA,IAC/D;AAAA,EACF;AAAA;AAAA,EAGQ,cAAc,KAAyB;AAC7C,UAAM,cAAuC,CAAC;AAC9C,QAAI,IAAI,gBAAgB,OAAW,aAAY,cAAc,IAAI;AACjE,QAAI,IAAI,iBAAiB,OAAW,aAAY,eAAe,IAAI,IAAI;AACvE,QAAI,IAAI,MAAO,QAAO,OAAO,aAAa,IAAI,KAAK;AACnD,WAAO,KAAK,oBAAoB,aAAa,IAAI,MAAM;AAAA,EACzD;AAAA;AAAA,EAIS,cAAc,KAAqC;AAC1D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,UAAU,KAAK,EAAE,GAAG,WAAW,OAAO;AAClD,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,4BAA4B,CAAC;AAAA,IACpF;AACA,QAAI,UAAU,OAAO,WAAW,GAAG;AACjC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AACA,UAAM,UAA0B,CAAC;AACjC,eAAW,SAAS,UAAU,QAAQ;AACpC,YAAM,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI;AACzC,cAAQ;AAAA,QACN,KAAK,iBAAiB,KAAK,KAAK,UAAU,GAAG,KAAK,YAAY,KAAK,GAAG,IAAI,MAAM;AAAA,MAClF;AAIA,iBAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,MAAM,aAAa,CAAC,CAAC,GAAG;AACnE,cAAM,SAAS,KAAK,cAAc,KAAK,GAAG;AAC1C,YAAI,WAAW,MAAM;AACnB,kBAAQ,KAAK;AAAA,YACX,UAAU,KAAK;AAAA,YACf,QAAQ;AAAA,YACR,QAAQ,mBAAmB,GAAG;AAAA,UAChC,CAAC;AACD;AAAA,QACF;AACA,gBAAQ,KAAK,KAAK,iBAAiB,QAAQ,UAAU,IAAI,MAAM,CAAC;AAAA,MAClE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAES,gBAAgB,KAAqC;AAC5D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,OAAO,WAAW,GAAG;AACjC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AACA,UAAM,UAA0B,CAAC;AACjC,eAAW,SAAS,UAAU,QAAQ;AACpC,YAAM,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI;AAGzC,cAAQ,KAAK,KAAK,kBAAkB,KAAK,KAAK,UAAU,GAAG,IAAI,MAAM,CAAC;AACtE,iBAAW,OAAO,OAAO,KAAK,MAAM,aAAa,CAAC,CAAC,GAAG;AACpD,cAAM,SAAS,KAAK,cAAc,KAAK,GAAG;AAC1C,YAAI,WAAW,KAAM;AACrB,gBAAQ,KAAK,KAAK,kBAAkB,QAAQ,IAAI,MAAM,CAAC;AAAA,MACzD;AAGA,cAAQ,KAAK,KAAK,iBAAiB,KAAK,IAAI,MAAM,CAAC;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAY,OAAyB;AAC3C,UAAM,cAAuC;AAAA,MAC3C,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM;AAAA,IACrB;AACA,QAAI,MAAM,UAAU,OAAW,aAAY,QAAQ,MAAM;AACzD,UAAM,QAAQ,MAAM,OAAO;AAC3B,QAAI,SAAS,MAAM,SAAS,EAAG,aAAY,eAAe,IAAI,MAAM,KAAK,IAAI;AAC7E,QAAI,MAAM,2BAA2B,QAAW;AAC9C,kBAAY,0BAA0B,IAAI,MAAM;AAAA,IAClD;AACA,QAAI,MAAM,MAAO,QAAO,OAAO,aAAa,MAAM,KAAK;AACvD,WAAO,KAAK,oBAAoB,aAAa,MAAM,IAAI;AAAA,EACzD;AAAA;AAAA,EAIS,iBAAiB,KAAqC;AAC7D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,UAAU,KAAK,EAAE,GAAG,cAAc,OAAO;AACrD,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AACA,QAAI,UAAU,UAAU,WAAW,GAAG;AACpC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,kCAAkC,CAAC;AAAA,IAC1F;AACA,WAAO,UAAU,UAAU;AAAA,MAAI,CAAC,UAC9B,KAAK,iBAAiB,KAAK,aAAa,KAAK,MAAM,IAAI,GAAG,KAAK,eAAe,KAAK,GAAG,IAAI,MAAM;AAAA,IAClG;AAAA,EACF;AAAA,EAES,mBAAmB,KAAqC;AAC/D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,UAAU,WAAW,GAAG;AACpC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,kCAAkC,CAAC;AAAA,IAC1F;AACA,WAAO,UAAU,UAAU;AAAA,MAAI,CAAC,UAC9B,KAAK,kBAAkB,KAAK,aAAa,KAAK,MAAM,IAAI,GAAG,IAAI,MAAM;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,OAA4B;AACjD,UAAM,QAAiC;AAAA,MACrC,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM;AAAA,MACnB,wBAAwB,MAAM;AAAA,IAChC;AACA,QAAI,MAAM,UAAU,OAAW,OAAM,QAAQ,MAAM;AACnD,QAAI,MAAM,MAAO,QAAO,OAAO,OAAO,MAAM,KAAK;AACjD,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AAAA;AAAA,EAIA,WAAW,OAAsB,KAA+B;AAC9D,UAAM,QAAS,OAAO,CAAC;AACvB,UAAM,OAAO;AAAA,MACX,cAAc,KAAK;AAAA,MACnB,aAAa;AAAA,MACb,WAAW,MAAM,cAAc,OAAO,QAAQ,IAAI;AAAA,MAClD,YAAY,MAAM,OAAO,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAAA,MACtE;AAAA,IACF;AAEA,YAAQ,OAAO;AAAA,MACb,KAAK;AACH,eAAO;AAAA,UACL,GAAG;AAAA,UACH,UAAU,MAAM,aAAa;AAAA,UAC7B,WAAW,MAAM,cAAc,CAAC;AAAA,QAClC;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,GAAG;AAAA,UACH,UAAU,MAAM,aAAa;AAAA,UAC7B,WAAW,MAAM,cAAc,CAAC;AAAA,UAChC,YAAY,MAAM;AAAA,UAClB,SAAS,MAAM,YAAY;AAAA,QAC7B;AAAA,MACF,KAAK;AACH,eAAO,EAAE,GAAG,MAAM,QAAQ,KAAK,gBAAgB,MAAM,MAAM,EAAE;AAAA,MAC/D,KAAK;AACH,eAAO,EAAE,GAAG,MAAM,QAAQ,MAAM,QAAQ;AAAA,MAC1C,KAAK;AACH,eAAO,EAAE,GAAG,MAAM,QAAQ,MAAM,UAAU,GAAG;AAAA,MAC/C,KAAK;AACH,eAAO,EAAE,GAAG,MAAM,SAAS,MAAM,YAAY,WAAW,WAAW,OAAO;AAAA,MAC5E,KAAK;AACH,eAAO,EAAE,GAAG,MAAM,gBAAgB,MAAM,oBAAoB,MAAM;AAAA,MACpE,KAAK;AACH,eAAO,EAAE,GAAG,MAAM,SAAS,MAAM,WAAW,GAAG;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,YAAY,OAAsB,UAAmC;AAGnE,QAAI,SAAS,aAAa,QAAQ;AAEhC,UAAI,UAAU,cAAc;AAC1B,eAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ,KAAK,UAAU;AAAA,YACrB,oBAAoB;AAAA,cAClB,eAAe;AAAA,cACf,oBAAoB;AAAA,cACpB,0BAA0B,SAAS,UAAU;AAAA,YAC/C;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AACA,aAAO,EAAE,UAAU,EAAE;AAAA,IACvB;AAGA,QAAI,SAAS,sBAAsB,UAAU,kBAAkB,UAAU,gBAAgB;AACvF,aAAO;AAAA,QACL,UAAU;AAAA,QACV,QAAQ,KAAK,UAAU;AAAA,UACrB,oBAAoB;AAAA,YAClB,eAAe;AAAA,YACf,mBAAmB,SAAS;AAAA,UAC9B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAGA,WAAO,EAAE,UAAU,EAAE;AAAA,EACvB;AAAA;AAAA;AAAA,EAKQ,gBAAgB,KAA4C;AAClE,UAAM,WAAW,IAAI,UAAU,UAAU,KAAK,EAAE,GAAG;AACnD,QAAI,aAAa,MAAO,QAAO;AAC/B,UAAM,OAAO,IAAI,UAAU;AAC3B,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO,WAAW,EAAE,GAAG,MAAM,GAAG,SAAS,IAAI;AAAA,EAC/C;AAAA;AAAA,EAGQ,oBAAoB,KAA2C;AACrE,UAAM,WAAW,IAAI,UAAU,UAAU,KAAK,EAAE,GAAG;AACnD,QAAI,aAAa,MAAO,QAAO,CAAC;AAChC,WAAO,kBAAkB,OAAO,CAAC,MAAM,IAAI,UAAU,WAAW,SAAS,CAAC,CAAC;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,KAAqB,QAAkC;AAC5E,QAAI,UAAU,OAAO;AACrB,QAAI,OAAO,CAAC,GAAI,OAAO,QAAQ,CAAC,CAAE;AAElC,QAAI,uBAAuB,QAAQ,IAAI,UAAU,SAAS,GAAG;AAC3D,YAAM,UAAU,yBAAyB,IAAI,aAAa,IAAI,UAAU,IAAI,SAAS,MAAM,IAAI,OAAO,KAAK,EAAE;AAC7G,gBAAU,QAAQ;AAClB,aAAO,QAAQ;AAAA,IACjB;AAGA,cAAU,mBAAmB,OAAO;AACpC,WAAO,mBAAmB,IAAI;AAE9B,UAAM,QAAuB,EAAE,QAAQ;AACvC,QAAI,KAAK,SAAS,EAAG,OAAM,OAAO;AAElC,QAAI,OAAO,OAAO,OAAO,KAAK,OAAO,GAAG,EAAE,SAAS,GAAG;AACpD,YAAM,MAA8B,CAAC;AACrC,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,mBAAmB,OAAO,GAAG,CAAC,GAAG;AACnE,YAAI,CAAC,IAAI,OAAO,CAAC;AAAA,MACnB;AACA,YAAM,MAAM;AAAA,IACd;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,gBAAgB,KAAqB,OAA2C;AACtF,UAAM,UAAU;AAAA,MACd,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA,IAAI,UAAU;AAAA,IAChB;AACA,UAAM,QAAwB,EAAE,OAAO,CAAC,EAAE,MAAM,WAAW,QAAQ,CAAC,EAAE;AACtE,QAAI,UAAU,aAAc,OAAM,UAAU;AAAA,QACvC,OAAM,UAAU;AACrB,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,WAAW,KAAqB,OAA2B,OAAgC;AACjG,QAAI,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM,KAAK,EAAG,QAAO;AAC/E,UAAM,OAAO,wBAAwB,IAAI,aAAa,SAAS,OAAO,IAAI,UAAU,EAAE;AACtF,UAAM,SAAS,KAAK,QAAQ,OAAO,GAAG;AACtC,WAAO,MAAM,MAAM,KAAK,CAAC,OAAO,EAAE,WAAW,IAAI,QAAQ,OAAO,GAAG,MAAM,MAAM;AAAA,EACjF;AAAA,EAEQ,cAAc,MAA8B;AAClD,WAAO,KAAK,SAAyB,IAAI,KAAK,CAAC;AAAA,EACjD;AAAA;AAAA,EAGQ,WAAW,KAA8B,KAAsC;AACrF,UAAM,WAAW,IAAI,GAAG;AACxB,QAAI,YAAY,OAAO,aAAa,YAAY,CAAC,MAAM,QAAQ,QAAQ,GAAG;AACxE,aAAO;AAAA,IACT;AACA,UAAM,QAAiC,CAAC;AACxC,QAAI,GAAG,IAAI;AACX,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,KAAqE;AAC3F,YAAQ,KAAK;AAAA,MACX,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AACF;AAEO,IAAM,UAAU,IAAI,aAAa;AACxC,IAAO,gBAAQ;","names":[]}
@@ -0,0 +1,364 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ fileMtimeMs,
4
+ readJsonlLines
5
+ } from "./chunk-RK6VBLXP.js";
6
+ import {
7
+ firstExistingRoot,
8
+ walkFiles
9
+ } from "./chunk-JWNT5KW7.js";
10
+ import {
11
+ emptyTokens,
12
+ inferProvider,
13
+ normalizeWorkspaceKey,
14
+ workspaceLabelFromKey
15
+ } from "./chunk-XD7MY6HB.js";
16
+
17
+ // src/usage/readers/codex.ts
18
+ import { basename } from "path";
19
+ var PLATFORM_ID = "codex";
20
+ var DEFAULT_MODEL = "unknown";
21
+ var DEFAULT_PROVIDER = "openai";
22
+ function toIntOr(v, fallback) {
23
+ const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : NaN;
24
+ if (!Number.isFinite(n)) return fallback;
25
+ return Math.trunc(n);
26
+ }
27
+ function totalsFromUsage(usage) {
28
+ const cached = Math.max(
29
+ toIntOr(usage.cached_input_tokens, 0),
30
+ toIntOr(usage.cache_read_input_tokens, 0)
31
+ );
32
+ return {
33
+ input: Math.max(0, toIntOr(usage.input_tokens, 0)),
34
+ output: Math.max(0, toIntOr(usage.output_tokens, 0)),
35
+ cached: Math.max(0, cached),
36
+ reasoning: Math.max(0, toIntOr(usage.reasoning_output_tokens, 0))
37
+ };
38
+ }
39
+ function totalsEqual(a, b) {
40
+ return a.input === b.input && a.output === b.output && a.cached === b.cached && a.reasoning === b.reasoning;
41
+ }
42
+ function deltaFrom(self, previous) {
43
+ if (self.input < previous.input || self.output < previous.output || self.cached < previous.cached || self.reasoning < previous.reasoning) {
44
+ return null;
45
+ }
46
+ return {
47
+ input: self.input - previous.input,
48
+ output: self.output - previous.output,
49
+ cached: self.cached - previous.cached,
50
+ reasoning: self.reasoning - previous.reasoning
51
+ };
52
+ }
53
+ function saturatingAdd(self, other) {
54
+ return {
55
+ input: self.input + other.input,
56
+ output: self.output + other.output,
57
+ cached: self.cached + other.cached,
58
+ reasoning: self.reasoning + other.reasoning
59
+ };
60
+ }
61
+ function totalsSum(t) {
62
+ return t.input + t.output + t.cached + t.reasoning;
63
+ }
64
+ function isWithin(self, baseline) {
65
+ return self.input <= baseline.input && self.output <= baseline.output && self.cached <= baseline.cached && self.reasoning <= baseline.reasoning;
66
+ }
67
+ function looksLikeStaleRegression(self, previous, last) {
68
+ const previousTotal = totalsSum(previous);
69
+ const currentTotal = totalsSum(self);
70
+ const lastTotal = totalsSum(last);
71
+ if (previousTotal <= 0 || currentTotal <= 0 || lastTotal <= 0) return false;
72
+ return currentTotal * 100 >= previousTotal * 98 || currentTotal + lastTotal * 2 >= previousTotal;
73
+ }
74
+ function intoTokens(t) {
75
+ const clampedCached = Math.max(0, Math.min(t.cached, t.input));
76
+ const tokens = emptyTokens();
77
+ tokens.input = Math.max(0, t.input - clampedCached);
78
+ tokens.output = Math.max(0, t.output);
79
+ tokens.cacheRead = clampedCached;
80
+ tokens.cacheWrite = 0;
81
+ tokens.reasoning = Math.max(0, t.reasoning);
82
+ return tokens;
83
+ }
84
+ function freshState() {
85
+ return {
86
+ currentModel: void 0,
87
+ previousTotals: void 0,
88
+ sessionIsHeadless: false,
89
+ sessionProvider: void 0,
90
+ sessionAgent: void 0,
91
+ sessionWorkspaceKey: void 0,
92
+ sessionWorkspaceLabel: void 0,
93
+ forkedChildWaitingForTurnContext: false,
94
+ forkedChildInheritedBaseline: void 0,
95
+ forkedChildInheritedReportedTotal: void 0
96
+ };
97
+ }
98
+ function flushPending(pending, out, model) {
99
+ for (const p of pending) {
100
+ p.record.modelId = model;
101
+ if (!p.usedFallbackTimestamp) {
102
+ p.record.dedupKey = codexDedupKey(p.ts, p.providerId, model, p.tokens);
103
+ }
104
+ out.push(p.record);
105
+ }
106
+ pending.length = 0;
107
+ }
108
+ function flushPendingAsUnknown(pending, out) {
109
+ if (pending.length === 0) return;
110
+ flushPending(pending, out, DEFAULT_MODEL);
111
+ }
112
+ function nonEmptyString(v) {
113
+ return typeof v === "string" && v !== "" ? v : void 0;
114
+ }
115
+ function sessionIdFromPath(path) {
116
+ const name = basename(path);
117
+ const dot = name.lastIndexOf(".");
118
+ const stem = dot > 0 ? name.slice(0, dot) : name;
119
+ return stem === "" ? "unknown" : stem;
120
+ }
121
+ function parseEntryTimestamp(v) {
122
+ if (typeof v !== "string" || v === "") return null;
123
+ const ms = Date.parse(v);
124
+ return Number.isNaN(ms) ? null : ms;
125
+ }
126
+ function extractModel(payload) {
127
+ return nonEmptyString(payload.model_info?.slug) ?? nonEmptyString(payload.model) ?? nonEmptyString(payload.model_name) ?? (payload.info ? extractModelFromInfo(payload.info) : void 0);
128
+ }
129
+ function extractModelFromInfo(info) {
130
+ return nonEmptyString(info.model) ?? nonEmptyString(info.model_name);
131
+ }
132
+ function sourceIsExec(source) {
133
+ return source === "exec";
134
+ }
135
+ function forkedFromIdFromSource(source) {
136
+ if (typeof source !== "object" || source === null) return void 0;
137
+ const sub = source.subagent;
138
+ if (typeof sub !== "object" || sub === null) return void 0;
139
+ const spawn = sub.thread_spawn;
140
+ if (typeof spawn !== "object" || spawn === null) return void 0;
141
+ const parent = spawn.parent_thread_id;
142
+ return nonEmptyString(parent);
143
+ }
144
+ function workspaceFromCwd(cwd) {
145
+ const normalized = normalizeWorkspaceKey(cwd);
146
+ if (normalized === void 0) return {};
147
+ for (let i = 0; i < normalized.length; i++) {
148
+ const c = normalized.charCodeAt(i);
149
+ if (c < 32 || c === 127) return {};
150
+ }
151
+ if (!looksLikeExplicitWorkspacePath(normalized)) return {};
152
+ const label = workspaceLabelFromKey(normalized);
153
+ if (label === void 0) return {};
154
+ return { key: normalized, label };
155
+ }
156
+ function looksLikeExplicitWorkspacePath(path) {
157
+ if (path.startsWith("//") || path.startsWith("/")) return true;
158
+ if (path.length >= 3) {
159
+ const c0 = path.charCodeAt(0);
160
+ const isAlpha = c0 >= 65 && c0 <= 90 || c0 >= 97 && c0 <= 122;
161
+ if (isAlpha && path[1] === ":" && path[2] === "/") return true;
162
+ }
163
+ return false;
164
+ }
165
+ function reportedTotalTokens(usage) {
166
+ const v = toIntOr(usage.total_tokens, NaN);
167
+ if (!Number.isFinite(v) || v < 0) return void 0;
168
+ return v;
169
+ }
170
+ function rememberForkedChildInheritedBaseline(state, info) {
171
+ const totalUsage = info.total_token_usage;
172
+ if (!totalUsage) return;
173
+ const totals = totalsFromUsage(totalUsage);
174
+ state.previousTotals = totals;
175
+ state.forkedChildInheritedBaseline = totals;
176
+ state.forkedChildInheritedReportedTotal = reportedTotalTokens(totalUsage);
177
+ }
178
+ function forkedChildShouldSkipInheritedSnapshot(state, totalUsage, totals) {
179
+ if (totalUsage && state.forkedChildInheritedReportedTotal !== void 0) {
180
+ const reported = reportedTotalTokens(totalUsage);
181
+ if (reported !== void 0 && reported <= state.forkedChildInheritedReportedTotal) {
182
+ return true;
183
+ }
184
+ }
185
+ if (totals !== void 0 && state.forkedChildInheritedBaseline !== void 0) {
186
+ return isWithin(totals, state.forkedChildInheritedBaseline);
187
+ }
188
+ return false;
189
+ }
190
+ function codexDedupKey(ts, provider, model, tokens) {
191
+ return `codex:token_count:${ts}:${provider}:${model}:${tokens.input}:${tokens.output}:${tokens.cacheRead}:${tokens.cacheWrite}:${tokens.reasoning}`;
192
+ }
193
+ function tokensAllZero(t) {
194
+ return t.input === 0 && t.output === 0 && t.cacheRead === 0 && t.reasoning === 0;
195
+ }
196
+ function parseCodexFile(path) {
197
+ const lines = readJsonlLines(path);
198
+ if (lines.length === 0) return [];
199
+ const sessionId = sessionIdFromPath(path);
200
+ const fallbackTs = fileMtimeMs(path);
201
+ const state = freshState();
202
+ const out = [];
203
+ const pending = [];
204
+ for (const raw of lines) {
205
+ if (typeof raw !== "object" || raw === null) continue;
206
+ const entry = raw;
207
+ const payload = entry.payload;
208
+ if (payload === void 0 || payload === null) continue;
209
+ const entryType = typeof entry.type === "string" ? entry.type : "";
210
+ const payloadType = typeof payload.type === "string" ? payload.type : void 0;
211
+ const isTokenCount = entryType === "event_msg" && payloadType === "token_count";
212
+ if (state.forkedChildWaitingForTurnContext) {
213
+ if (entryType === "turn_context") {
214
+ state.forkedChildWaitingForTurnContext = false;
215
+ state.currentModel = extractModel(payload);
216
+ } else {
217
+ if (isTokenCount && payload.info) {
218
+ rememberForkedChildInheritedBaseline(state, payload.info);
219
+ }
220
+ continue;
221
+ }
222
+ }
223
+ if (entryType === "session_meta") {
224
+ if (sourceIsExec(payload.source)) state.sessionIsHeadless = true;
225
+ const forkedFromId = nonEmptyString(payload.forked_from_id) ?? forkedFromIdFromSource(payload.source);
226
+ if (forkedFromId !== void 0) {
227
+ state.forkedChildWaitingForTurnContext = true;
228
+ state.forkedChildInheritedBaseline = void 0;
229
+ state.forkedChildInheritedReportedTotal = void 0;
230
+ }
231
+ const provider = nonEmptyString(payload.model_provider);
232
+ if (provider !== void 0) state.sessionProvider = provider;
233
+ const nickname = nonEmptyString(payload.agent_nickname);
234
+ if (nickname !== void 0) state.sessionAgent = nickname;
235
+ if (typeof payload.cwd === "string") {
236
+ const ws = workspaceFromCwd(payload.cwd);
237
+ state.sessionWorkspaceKey = ws.key;
238
+ state.sessionWorkspaceLabel = ws.label;
239
+ }
240
+ continue;
241
+ }
242
+ if (entryType === "turn_context") {
243
+ state.currentModel = extractModel(payload);
244
+ if (state.currentModel !== void 0) {
245
+ flushPending(pending, out, state.currentModel);
246
+ }
247
+ continue;
248
+ }
249
+ if (!isTokenCount) continue;
250
+ const info = payload.info;
251
+ if (info === void 0 || info === null) continue;
252
+ const payloadModel = extractModel(payload);
253
+ const infoModel = extractModelFromInfo(info);
254
+ const model = payloadModel ?? infoModel ?? state.currentModel;
255
+ if (model !== void 0) {
256
+ state.currentModel = model;
257
+ flushPending(pending, out, model);
258
+ }
259
+ const totalUsageRaw = info.total_token_usage ?? void 0;
260
+ const lastUsageRaw = info.last_token_usage ?? void 0;
261
+ const totalUsage = totalUsageRaw ? totalsFromUsage(totalUsageRaw) : void 0;
262
+ const lastUsage = lastUsageRaw ? totalsFromUsage(lastUsageRaw) : void 0;
263
+ if (forkedChildShouldSkipInheritedSnapshot(state, totalUsageRaw, totalUsage)) {
264
+ continue;
265
+ }
266
+ state.forkedChildInheritedBaseline = void 0;
267
+ state.forkedChildInheritedReportedTotal = void 0;
268
+ let tokensTotals;
269
+ let nextTotals;
270
+ const previous = state.previousTotals;
271
+ if (totalUsage !== void 0 && lastUsage !== void 0 && previous !== void 0) {
272
+ if (totalsEqual(totalUsage, previous)) continue;
273
+ if (deltaFrom(totalUsage, previous) === null && looksLikeStaleRegression(totalUsage, previous, lastUsage)) {
274
+ continue;
275
+ }
276
+ tokensTotals = lastUsage;
277
+ nextTotals = totalUsage;
278
+ } else if (totalUsage !== void 0 && lastUsage !== void 0 && previous === void 0) {
279
+ tokensTotals = lastUsage;
280
+ nextTotals = totalUsage;
281
+ } else if (totalUsage !== void 0 && lastUsage === void 0 && previous !== void 0) {
282
+ if (totalsEqual(totalUsage, previous)) continue;
283
+ const delta = deltaFrom(totalUsage, previous);
284
+ if (delta !== null) {
285
+ tokensTotals = delta;
286
+ nextTotals = totalUsage;
287
+ } else {
288
+ state.previousTotals = totalUsage;
289
+ continue;
290
+ }
291
+ } else if (totalUsage !== void 0 && lastUsage === void 0 && previous === void 0) {
292
+ tokensTotals = totalUsage;
293
+ nextTotals = totalUsage;
294
+ } else if (totalUsage === void 0 && lastUsage !== void 0 && previous !== void 0) {
295
+ tokensTotals = lastUsage;
296
+ nextTotals = saturatingAdd(previous, lastUsage);
297
+ } else if (totalUsage === void 0 && lastUsage !== void 0 && previous === void 0) {
298
+ tokensTotals = lastUsage;
299
+ nextTotals = void 0;
300
+ } else {
301
+ continue;
302
+ }
303
+ const tokens = intoTokens(tokensTotals);
304
+ if (tokensAllZero(tokens)) continue;
305
+ state.previousTotals = nextTotals;
306
+ const parsedTs = parseEntryTimestamp(entry.timestamp);
307
+ const ts = parsedTs ?? fallbackTs;
308
+ const modelId = model ?? DEFAULT_MODEL;
309
+ const providerId = state.sessionProvider ?? inferProvider(modelId) ?? DEFAULT_PROVIDER;
310
+ const agent = state.sessionIsHeadless ? "headless" : state.sessionAgent;
311
+ const record = {
312
+ platformId: PLATFORM_ID,
313
+ modelId,
314
+ providerId,
315
+ sessionId,
316
+ tokens,
317
+ ts,
318
+ messageCount: 1,
319
+ confidence: "host-reported"
320
+ };
321
+ if (state.sessionWorkspaceKey !== void 0) record.projectKey = state.sessionWorkspaceKey;
322
+ if (state.sessionWorkspaceLabel !== void 0) record.projectLabel = state.sessionWorkspaceLabel;
323
+ if (agent !== void 0) record.agent = agent;
324
+ if (model === void 0) {
325
+ pending.push({
326
+ record,
327
+ tokens,
328
+ providerId,
329
+ ts,
330
+ usedFallbackTimestamp: parsedTs === null
331
+ });
332
+ continue;
333
+ }
334
+ if (parsedTs !== null) {
335
+ record.dedupKey = codexDedupKey(ts, providerId, model, tokens);
336
+ }
337
+ out.push(record);
338
+ }
339
+ flushPendingAsUnknown(pending, out);
340
+ return out;
341
+ }
342
+ var codexReader = {
343
+ platformId: PLATFORM_ID,
344
+ kind: "local",
345
+ async read({ sinceMs }) {
346
+ const root = firstExistingRoot(PLATFORM_ID);
347
+ if (root === void 0) return [];
348
+ const files = walkFiles(root, (name) => name.endsWith(".jsonl") || name.endsWith(".json"));
349
+ const records = [];
350
+ for (const file of files) {
351
+ const rows = parseCodexFile(file);
352
+ for (const row of rows) {
353
+ if (sinceMs !== void 0 && row.ts < sinceMs) continue;
354
+ records.push(row);
355
+ }
356
+ }
357
+ return records;
358
+ }
359
+ };
360
+ var codex_default = codexReader;
361
+ export {
362
+ codex_default as default
363
+ };
364
+ //# sourceMappingURL=codex-Q3ATRRX3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/usage/readers/codex.ts"],"sourcesContent":["/**\n * usage/readers/codex — Codex CLI native session-log reader.\n *\n * Faithful port of tokscale sessions/codex.rs (the hard, stateful reader). Reads\n * ~/.codex/sessions/**\\/*.jsonl (and the rare *.json headless variants; the\n * rollout-*.jsonl files are just a subset of *.jsonl and need no special-casing).\n *\n * Codex logs a cumulative token snapshot on every `token_count` event, so naive\n * summing double-counts every turn. This reader reproduces codex.rs exactly:\n *\n * - The per-turn increment comes from `payload.info.last_token_usage`\n * (the DELTA source). `total_token_usage` is a mutable cumulative snapshot\n * (compaction / context-window capping rewrites it) used ONLY for dedup and\n * monotonicity / stale-regression checks — never as a direct delta source\n * unless `last_token_usage` is absent.\n * - State is tracked PER SESSION (per file): `previous_totals` is the last\n * accepted cumulative baseline; each new snapshot must advance past it.\n * - When the new total equals the previous baseline → skip (duplicate snapshot).\n * - When the total regresses but `looks_like_stale_regression` holds (a small\n * out-of-order dip that resumes from the true watermark next row) → skip,\n * so `last_token_usage` is not counted twice.\n * - Forked-child sessions replay parent token rows before their first\n * `turn_context`; those inherited snapshots are skipped until totals move\n * past the inherited baseline.\n *\n * Token mapping (CodexTotals::into_tokens): cached = min(cached, input); the\n * reported `input` already INCLUDES cached, so net input = input - cached\n * (clamped ≥ 0). cache_read = clamped cached, cache_write = 0, reasoning as-is.\n * `cached` itself is max(cached_input_tokens, cache_read_input_tokens).\n *\n * Model: model_info.slug > model > model_name > info.model > info.model_name,\n * falling back to the session's current_model (from turn_context). Provider:\n * session_meta.model_provider, else inferred from the model, else \"openai\".\n * Session id: the file stem. Project: session_meta.cwd, only when it looks like\n * an explicit absolute/UNC/drive path. Confidence is \"host-reported\".\n *\n * Dedup key (set only when the row had a real RFC3339 timestamp, matching\n * codex.rs which skips the key on the mtime fallback):\n * codex:token_count:<ts>:<provider>:<model>:<in>:<out>:<cacheRead>:<cacheWrite>:<reasoning>\n *\n * Fail-open: no root → []; unreadable/malformed file or line → skipped.\n */\n\nimport { basename } from \"node:path\";\n\nimport type { TokenBreakdown, UsageReader, UsageRecord } from \"../types.js\";\nimport { emptyTokens } from \"../aggregate.js\";\nimport { fileMtimeMs, readJsonlLines } from \"../jsonl.js\";\nimport { inferProvider, normalizeWorkspaceKey, workspaceLabelFromKey } from \"../normalize.js\";\nimport { firstExistingRoot, walkFiles } from \"../paths.js\";\n\nconst PLATFORM_ID = \"codex\" as const;\nconst DEFAULT_MODEL = \"unknown\";\nconst DEFAULT_PROVIDER = \"openai\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Wire shapes (everything optional / unknown — narrowed at use)\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface CodexTokenUsage {\n input_tokens?: unknown;\n output_tokens?: unknown;\n cached_input_tokens?: unknown;\n cache_read_input_tokens?: unknown;\n reasoning_output_tokens?: unknown;\n total_tokens?: unknown;\n}\n\ninterface CodexInfo {\n model?: unknown;\n model_name?: unknown;\n last_token_usage?: CodexTokenUsage | null;\n total_token_usage?: CodexTokenUsage | null;\n}\n\ninterface CodexModelInfo {\n slug?: unknown;\n}\n\ninterface CodexPayload {\n id?: unknown;\n forked_from_id?: unknown;\n type?: unknown;\n model?: unknown;\n model_name?: unknown;\n model_info?: CodexModelInfo | null;\n info?: CodexInfo | null;\n source?: unknown;\n cwd?: unknown;\n model_provider?: unknown;\n agent_nickname?: unknown;\n}\n\ninterface CodexEntry {\n type?: unknown;\n timestamp?: unknown;\n payload?: CodexPayload | null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// CodexTotals — the four cumulative dimensions + delta / regression logic\n// (port of the Rust CodexTotals struct).\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface CodexTotals {\n input: number;\n output: number;\n cached: number;\n reasoning: number;\n}\n\n/** Coerce an unknown to a non-negative integer (0 on absence/garbage). */\nfunction toNonNegInt(v: unknown): number {\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.trunc(n));\n}\n\n/** Read a possibly-missing i64-ish field as an integer (may be negative). */\nfunction toIntOr(v: unknown, fallback: number): number {\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\n if (!Number.isFinite(n)) return fallback;\n return Math.trunc(n);\n}\n\n/** CodexTotals::from_usage — clamp each field ≥ 0; cached = max of both fields. */\nfunction totalsFromUsage(usage: CodexTokenUsage): CodexTotals {\n const cached = Math.max(\n toIntOr(usage.cached_input_tokens, 0),\n toIntOr(usage.cache_read_input_tokens, 0),\n );\n return {\n input: Math.max(0, toIntOr(usage.input_tokens, 0)),\n output: Math.max(0, toIntOr(usage.output_tokens, 0)),\n cached: Math.max(0, cached),\n reasoning: Math.max(0, toIntOr(usage.reasoning_output_tokens, 0)),\n };\n}\n\nfunction totalsEqual(a: CodexTotals, b: CodexTotals): boolean {\n return a.input === b.input && a.output === b.output && a.cached === b.cached && a.reasoning === b.reasoning;\n}\n\n/** CodexTotals::delta_from — null when any dimension regressed. */\nfunction deltaFrom(self: CodexTotals, previous: CodexTotals): CodexTotals | null {\n if (\n self.input < previous.input ||\n self.output < previous.output ||\n self.cached < previous.cached ||\n self.reasoning < previous.reasoning\n ) {\n return null;\n }\n return {\n input: self.input - previous.input,\n output: self.output - previous.output,\n cached: self.cached - previous.cached,\n reasoning: self.reasoning - previous.reasoning,\n };\n}\n\n/** CodexTotals::saturating_add (plain add — values are well within Number range). */\nfunction saturatingAdd(self: CodexTotals, other: CodexTotals): CodexTotals {\n return {\n input: self.input + other.input,\n output: self.output + other.output,\n cached: self.cached + other.cached,\n reasoning: self.reasoning + other.reasoning,\n };\n}\n\nfunction totalsSum(t: CodexTotals): number {\n return t.input + t.output + t.cached + t.reasoning;\n}\n\n/** CodexTotals::is_within — every dimension ≤ baseline. */\nfunction isWithin(self: CodexTotals, baseline: CodexTotals): boolean {\n return (\n self.input <= baseline.input &&\n self.output <= baseline.output &&\n self.cached <= baseline.cached &&\n self.reasoning <= baseline.reasoning\n );\n}\n\n/**\n * CodexTotals::looks_like_stale_regression — some snapshots arrive slightly out\n * of order: the cumulative total dips by ~one recent increment then resumes from\n * the true higher watermark next row. Treat those as stale (skip) rather than a\n * hard reset, so last_token_usage is not counted twice.\n */\nfunction looksLikeStaleRegression(self: CodexTotals, previous: CodexTotals, last: CodexTotals): boolean {\n const previousTotal = totalsSum(previous);\n const currentTotal = totalsSum(self);\n const lastTotal = totalsSum(last);\n if (previousTotal <= 0 || currentTotal <= 0 || lastTotal <= 0) return false;\n return currentTotal * 100 >= previousTotal * 98 || currentTotal + lastTotal * 2 >= previousTotal;\n}\n\n/**\n * CodexTotals::into_tokens — clamp cached to ≤ input so malformed rows can't\n * inflate the total; net input = input - clamped_cached; cache_write = 0.\n */\nfunction intoTokens(t: CodexTotals): TokenBreakdown {\n const clampedCached = Math.max(0, Math.min(t.cached, t.input));\n const tokens = emptyTokens();\n tokens.input = Math.max(0, t.input - clampedCached);\n tokens.output = Math.max(0, t.output);\n tokens.cacheRead = clampedCached;\n tokens.cacheWrite = 0;\n tokens.reasoning = Math.max(0, t.reasoning);\n return tokens;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Per-file (per-session) parse state\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface CodexParseState {\n currentModel: string | undefined;\n previousTotals: CodexTotals | undefined;\n sessionIsHeadless: boolean;\n sessionProvider: string | undefined;\n sessionAgent: string | undefined;\n sessionWorkspaceKey: string | undefined;\n sessionWorkspaceLabel: string | undefined;\n forkedChildWaitingForTurnContext: boolean;\n forkedChildInheritedBaseline: CodexTotals | undefined;\n forkedChildInheritedReportedTotal: number | undefined;\n}\n\nfunction freshState(): CodexParseState {\n return {\n currentModel: undefined,\n previousTotals: undefined,\n sessionIsHeadless: false,\n sessionProvider: undefined,\n sessionAgent: undefined,\n sessionWorkspaceKey: undefined,\n sessionWorkspaceLabel: undefined,\n forkedChildWaitingForTurnContext: false,\n forkedChildInheritedBaseline: undefined,\n forkedChildInheritedReportedTotal: undefined,\n };\n}\n\n/**\n * A model-less token_count record buffered until a later turn resolves the\n * model (port of codex.rs `pending_model_messages`). codex.rs back-fills the\n * resolved model + dedup key onto these, and flushes any still-unresolved at EOF\n * as \"unknown\" — but STILL with a dedup key when the row had a real timestamp.\n * `usedFallbackTimestamp` mirrors `parsed_timestamp.is_none()`: when true the\n * dedup key is skipped on flush (the mtime fallback is not a stable identity).\n */\ninterface PendingCodexRecord {\n record: UsageRecord;\n tokens: TokenBreakdown;\n providerId: string;\n ts: number;\n usedFallbackTimestamp: boolean;\n}\n\n/**\n * Flush every buffered model-less record with a now-resolved model (port of\n * flush_pending_model_messages): back-fill modelId and — when the row carried a\n * real timestamp — the codex dedup key keyed on that model.\n */\nfunction flushPending(pending: PendingCodexRecord[], out: UsageRecord[], model: string): void {\n for (const p of pending) {\n p.record.modelId = model;\n if (!p.usedFallbackTimestamp) {\n p.record.dedupKey = codexDedupKey(p.ts, p.providerId, model, p.tokens);\n }\n out.push(p.record);\n }\n pending.length = 0;\n}\n\n/** Flush remaining buffered records as \"unknown\" (still keyed when timestamped). */\nfunction flushPendingAsUnknown(pending: PendingCodexRecord[], out: UsageRecord[]): void {\n if (pending.length === 0) return;\n flushPending(pending, out, DEFAULT_MODEL);\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction nonEmptyString(v: unknown): string | undefined {\n return typeof v === \"string\" && v !== \"\" ? v : undefined;\n}\n\n/** session id from path file stem (port of session_id_from_path). */\nfunction sessionIdFromPath(path: string): string {\n const name = basename(path);\n const dot = name.lastIndexOf(\".\");\n const stem = dot > 0 ? name.slice(0, dot) : name;\n return stem === \"\" ? \"unknown\" : stem;\n}\n\n/** Parse an RFC3339 timestamp to epoch ms, or null (port of parse_codex_entry_timestamp). */\nfunction parseEntryTimestamp(v: unknown): number | null {\n if (typeof v !== \"string\" || v === \"\") return null;\n const ms = Date.parse(v);\n return Number.isNaN(ms) ? null : ms;\n}\n\n/**\n * extract_model — model_info.slug > model > model_name > info.model >\n * info.model_name (first non-empty).\n */\nfunction extractModel(payload: CodexPayload): string | undefined {\n return (\n nonEmptyString(payload.model_info?.slug) ??\n nonEmptyString(payload.model) ??\n nonEmptyString(payload.model_name) ??\n (payload.info ? extractModelFromInfo(payload.info) : undefined)\n );\n}\n\n/** extract_model_from_info — info.model > info.model_name. */\nfunction extractModelFromInfo(info: CodexInfo): string | undefined {\n return nonEmptyString(info.model) ?? nonEmptyString(info.model_name);\n}\n\n/** codex_source_is_exec — session_meta.source === \"exec\" marks a headless run. */\nfunction sourceIsExec(source: unknown): boolean {\n return source === \"exec\";\n}\n\n/** forked_from_id_from_source — source.subagent.thread_spawn.parent_thread_id. */\nfunction forkedFromIdFromSource(source: unknown): string | undefined {\n if (typeof source !== \"object\" || source === null) return undefined;\n const sub = (source as Record<string, unknown>).subagent;\n if (typeof sub !== \"object\" || sub === null) return undefined;\n const spawn = (sub as Record<string, unknown>).thread_spawn;\n if (typeof spawn !== \"object\" || spawn === null) return undefined;\n const parent = (spawn as Record<string, unknown>).parent_thread_id;\n return nonEmptyString(parent);\n}\n\n/**\n * codex_workspace_from_cwd — normalize the cwd, but only accept it when it looks\n * like an explicit absolute/UNC/drive path AND yields a label.\n */\nfunction workspaceFromCwd(cwd: string): { key?: string; label?: string } {\n const normalized = normalizeWorkspaceKey(cwd);\n if (normalized === undefined) return {};\n // Reject control characters.\n for (let i = 0; i < normalized.length; i++) {\n const c = normalized.charCodeAt(i);\n if (c < 0x20 || c === 0x7f) return {};\n }\n if (!looksLikeExplicitWorkspacePath(normalized)) return {};\n const label = workspaceLabelFromKey(normalized);\n if (label === undefined) return {};\n return { key: normalized, label };\n}\n\n/** looks_like_explicit_workspace_path — leading `/` or `//`, or `X:/` drive. */\nfunction looksLikeExplicitWorkspacePath(path: string): boolean {\n if (path.startsWith(\"//\") || path.startsWith(\"/\")) return true;\n if (path.length >= 3) {\n const c0 = path.charCodeAt(0);\n const isAlpha = (c0 >= 0x41 && c0 <= 0x5a) || (c0 >= 0x61 && c0 <= 0x7a);\n if (isAlpha && path[1] === \":\" && path[2] === \"/\") return true;\n }\n return false;\n}\n\n/** reported_total_tokens — info.total_token_usage.total_tokens when ≥ 0. */\nfunction reportedTotalTokens(usage: CodexTokenUsage): number | undefined {\n const v = toIntOr(usage.total_tokens, NaN);\n if (!Number.isFinite(v) || v < 0) return undefined;\n return v;\n}\n\nfunction rememberForkedChildInheritedBaseline(state: CodexParseState, info: CodexInfo): void {\n const totalUsage = info.total_token_usage;\n if (!totalUsage) return;\n const totals = totalsFromUsage(totalUsage);\n state.previousTotals = totals;\n state.forkedChildInheritedBaseline = totals;\n state.forkedChildInheritedReportedTotal = reportedTotalTokens(totalUsage);\n}\n\nfunction forkedChildShouldSkipInheritedSnapshot(\n state: CodexParseState,\n totalUsage: CodexTokenUsage | null | undefined,\n totals: CodexTotals | undefined,\n): boolean {\n if (totalUsage && state.forkedChildInheritedReportedTotal !== undefined) {\n const reported = reportedTotalTokens(totalUsage);\n if (reported !== undefined && reported <= state.forkedChildInheritedReportedTotal) {\n return true;\n }\n }\n if (totals !== undefined && state.forkedChildInheritedBaseline !== undefined) {\n return isWithin(totals, state.forkedChildInheritedBaseline);\n }\n return false;\n}\n\n/** The codex:token_count dedup key (port of codex_token_count_dedup_key). */\nfunction codexDedupKey(\n ts: number,\n provider: string,\n model: string,\n tokens: TokenBreakdown,\n): string {\n return `codex:token_count:${ts}:${provider}:${model}:${tokens.input}:${tokens.output}:${tokens.cacheRead}:${tokens.cacheWrite}:${tokens.reasoning}`;\n}\n\nfunction tokensAllZero(t: TokenBreakdown): boolean {\n return t.input === 0 && t.output === 0 && t.cacheRead === 0 && t.reasoning === 0;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// File parse (port of parse_codex_reader, stateless single-pass)\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction parseCodexFile(path: string): UsageRecord[] {\n const lines = readJsonlLines(path);\n if (lines.length === 0) return [];\n\n const sessionId = sessionIdFromPath(path);\n const fallbackTs = fileMtimeMs(path);\n const state = freshState();\n const out: UsageRecord[] = [];\n // Model-less token_count rows are buffered here and back-filled once a later\n // turn resolves the model (else flushed as \"unknown\" WITH a dedup key at EOF).\n const pending: PendingCodexRecord[] = [];\n\n for (const raw of lines) {\n if (typeof raw !== \"object\" || raw === null) continue;\n const entry = raw as CodexEntry;\n const payload = entry.payload;\n if (payload === undefined || payload === null) continue;\n\n const entryType = typeof entry.type === \"string\" ? entry.type : \"\";\n const payloadType = typeof payload.type === \"string\" ? payload.type : undefined;\n const isTokenCount = entryType === \"event_msg\" && payloadType === \"token_count\";\n\n // ── Forked-child gate: replayed parent rows arrive before turn_context. ──\n if (state.forkedChildWaitingForTurnContext) {\n if (entryType === \"turn_context\") {\n state.forkedChildWaitingForTurnContext = false;\n state.currentModel = extractModel(payload);\n } else {\n if (isTokenCount && payload.info) {\n rememberForkedChildInheritedBaseline(state, payload.info);\n }\n continue;\n }\n }\n\n // ── session_meta: headless flag, fork detection, provider, cwd. ──\n if (entryType === \"session_meta\") {\n if (sourceIsExec(payload.source)) state.sessionIsHeadless = true;\n const forkedFromId =\n nonEmptyString(payload.forked_from_id) ?? forkedFromIdFromSource(payload.source);\n if (forkedFromId !== undefined) {\n state.forkedChildWaitingForTurnContext = true;\n state.forkedChildInheritedBaseline = undefined;\n state.forkedChildInheritedReportedTotal = undefined;\n }\n const provider = nonEmptyString(payload.model_provider);\n if (provider !== undefined) state.sessionProvider = provider;\n const nickname = nonEmptyString(payload.agent_nickname);\n if (nickname !== undefined) state.sessionAgent = nickname;\n if (typeof payload.cwd === \"string\") {\n const ws = workspaceFromCwd(payload.cwd);\n state.sessionWorkspaceKey = ws.key;\n state.sessionWorkspaceLabel = ws.label;\n }\n continue;\n }\n\n // ── turn_context: sets the current model for subsequent token rows. When\n // it resolves a model, flush any buffered model-less rows onto it. ──\n if (entryType === \"turn_context\") {\n state.currentModel = extractModel(payload);\n if (state.currentModel !== undefined) {\n flushPending(pending, out, state.currentModel);\n }\n continue;\n }\n\n if (!isTokenCount) continue;\n\n const info = payload.info;\n if (info === undefined || info === null) continue;\n\n // Resolve model: payload model > info model > current session model.\n const payloadModel = extractModel(payload);\n const infoModel = extractModelFromInfo(info);\n const model = payloadModel ?? infoModel ?? state.currentModel;\n if (model !== undefined) {\n state.currentModel = model;\n // A resolved model back-fills any earlier model-less rows (codex.rs flushes\n // pending_model_messages here before building the current record).\n flushPending(pending, out, model);\n }\n\n const totalUsageRaw = info.total_token_usage ?? undefined;\n const lastUsageRaw = info.last_token_usage ?? undefined;\n const totalUsage = totalUsageRaw ? totalsFromUsage(totalUsageRaw) : undefined;\n const lastUsage = lastUsageRaw ? totalsFromUsage(lastUsageRaw) : undefined;\n\n // Forked child may replay >1 parent token row after the first turn_context.\n if (forkedChildShouldSkipInheritedSnapshot(state, totalUsageRaw, totalUsage)) {\n continue;\n }\n state.forkedChildInheritedBaseline = undefined;\n state.forkedChildInheritedReportedTotal = undefined;\n\n // ── Delta selection (exact port of the Rust match arms). ──\n let tokensTotals: CodexTotals | undefined;\n let nextTotals: CodexTotals | undefined;\n const previous = state.previousTotals;\n\n if (totalUsage !== undefined && lastUsage !== undefined && previous !== undefined) {\n // Both present with previous baseline (standard path).\n if (totalsEqual(totalUsage, previous)) continue;\n if (deltaFrom(totalUsage, previous) === null && looksLikeStaleRegression(totalUsage, previous, lastUsage)) {\n continue;\n }\n tokensTotals = lastUsage;\n nextTotals = totalUsage;\n } else if (totalUsage !== undefined && lastUsage !== undefined && previous === undefined) {\n // Both present, first event — use last (not full total).\n tokensTotals = lastUsage;\n nextTotals = totalUsage;\n } else if (totalUsage !== undefined && lastUsage === undefined && previous !== undefined) {\n // Only total, have previous (defensive).\n if (totalsEqual(totalUsage, previous)) continue;\n const delta = deltaFrom(totalUsage, previous);\n if (delta !== null) {\n tokensTotals = delta;\n nextTotals = totalUsage;\n } else {\n state.previousTotals = totalUsage;\n continue;\n }\n } else if (totalUsage !== undefined && lastUsage === undefined && previous === undefined) {\n // Only total, first event, no last — legacy/degraded path.\n tokensTotals = totalUsage;\n nextTotals = totalUsage;\n } else if (totalUsage === undefined && lastUsage !== undefined && previous !== undefined) {\n // Only last, have previous.\n tokensTotals = lastUsage;\n nextTotals = saturatingAdd(previous, lastUsage);\n } else if (totalUsage === undefined && lastUsage !== undefined && previous === undefined) {\n // Only last, no previous.\n tokensTotals = lastUsage;\n nextTotals = undefined;\n } else {\n // Neither.\n continue;\n }\n\n const tokens = intoTokens(tokensTotals);\n\n // Skip zero-token snapshots WITHOUT advancing the baseline, so post-compaction\n // zeros don't inflate later deltas.\n if (tokensAllZero(tokens)) continue;\n\n state.previousTotals = nextTotals;\n\n const parsedTs = parseEntryTimestamp(entry.timestamp);\n const ts = parsedTs ?? fallbackTs;\n\n const modelId = model ?? DEFAULT_MODEL;\n const providerId = state.sessionProvider ?? inferProvider(modelId) ?? DEFAULT_PROVIDER;\n const agent = state.sessionIsHeadless ? \"headless\" : state.sessionAgent;\n\n const record: UsageRecord = {\n platformId: PLATFORM_ID,\n modelId,\n providerId,\n sessionId,\n tokens,\n ts,\n messageCount: 1,\n confidence: \"host-reported\",\n };\n if (state.sessionWorkspaceKey !== undefined) record.projectKey = state.sessionWorkspaceKey;\n if (state.sessionWorkspaceLabel !== undefined) record.projectLabel = state.sessionWorkspaceLabel;\n if (agent !== undefined) record.agent = agent;\n\n if (model === undefined) {\n // Model not yet resolved: buffer the record and defer modelId + dedupKey\n // until a later turn resolves the model (codex.rs pending_model_messages).\n // At EOF it flushes as \"unknown\" but STILL with a dedup key when the row\n // carried a real timestamp — so it can dedup against cross-source overlap.\n pending.push({\n record,\n tokens,\n providerId,\n ts,\n usedFallbackTimestamp: parsedTs === null,\n });\n continue;\n }\n\n // Dedup key only when a real timestamp was parsed (mtime fallback skips it,\n // matching codex.rs which sets the key only when parsed_timestamp.is_some()).\n if (parsedTs !== null) {\n record.dedupKey = codexDedupKey(ts, providerId, model, tokens);\n }\n out.push(record);\n }\n\n // EOF: any token_count rows whose model never resolved are emitted as\n // \"unknown\" — keeping a dedup key when their timestamp was real (codex.rs\n // flush_pending_model_messages_as_unknown at end of file).\n flushPendingAsUnknown(pending, out);\n\n return out;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Reader\n// ─────────────────────────────────────────────────────────────────────────\n\n/** The Codex CLI usage reader singleton. */\nconst codexReader: UsageReader = {\n platformId: PLATFORM_ID,\n kind: \"local\",\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\n const root = firstExistingRoot(PLATFORM_ID);\n if (root === undefined) return []; // no ~/.codex/sessions → fail-open\n\n // ~/.codex/sessions/**/*.jsonl (+ *.json headless). rollout-*.jsonl is a\n // subset of *.jsonl and is matched by the same predicate.\n const files = walkFiles(root, (name) => name.endsWith(\".jsonl\") || name.endsWith(\".json\"));\n\n const records: UsageRecord[] = [];\n for (const file of files) {\n const rows = parseCodexFile(file);\n for (const row of rows) {\n if (sinceMs !== undefined && row.ts < sinceMs) continue;\n records.push(row);\n }\n }\n return records;\n },\n};\n\nexport default codexReader;\n"],"mappings":"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","names":[]}