@seawork/server 1.0.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 (682) hide show
  1. package/.env.example +23 -0
  2. package/README.md +107 -0
  3. package/dist/scripts/dev-runner.js +27 -0
  4. package/dist/scripts/dev-runner.js.map +1 -0
  5. package/dist/scripts/mcp-stdio-socket-bridge-cli.mjs +62 -0
  6. package/dist/scripts/supervisor-entrypoint.js +123 -0
  7. package/dist/scripts/supervisor-entrypoint.js.map +1 -0
  8. package/dist/scripts/supervisor.js +148 -0
  9. package/dist/scripts/supervisor.js.map +1 -0
  10. package/dist/server/client/daemon-client-relay-e2ee-transport.d.ts +8 -0
  11. package/dist/server/client/daemon-client-relay-e2ee-transport.d.ts.map +1 -0
  12. package/dist/server/client/daemon-client-relay-e2ee-transport.js +161 -0
  13. package/dist/server/client/daemon-client-relay-e2ee-transport.js.map +1 -0
  14. package/dist/server/client/daemon-client-transport-types.d.ts +34 -0
  15. package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -0
  16. package/dist/server/client/daemon-client-transport-types.js +2 -0
  17. package/dist/server/client/daemon-client-transport-types.js.map +1 -0
  18. package/dist/server/client/daemon-client-transport-utils.d.ts +9 -0
  19. package/dist/server/client/daemon-client-transport-utils.d.ts.map +1 -0
  20. package/dist/server/client/daemon-client-transport-utils.js +121 -0
  21. package/dist/server/client/daemon-client-transport-utils.js.map +1 -0
  22. package/dist/server/client/daemon-client-transport.d.ts +5 -0
  23. package/dist/server/client/daemon-client-transport.d.ts.map +1 -0
  24. package/dist/server/client/daemon-client-transport.js +4 -0
  25. package/dist/server/client/daemon-client-transport.js.map +1 -0
  26. package/dist/server/client/daemon-client-websocket-transport.d.ts +7 -0
  27. package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -0
  28. package/dist/server/client/daemon-client-websocket-transport.js +119 -0
  29. package/dist/server/client/daemon-client-websocket-transport.js.map +1 -0
  30. package/dist/server/client/daemon-client.d.ts +697 -0
  31. package/dist/server/client/daemon-client.d.ts.map +1 -0
  32. package/dist/server/client/daemon-client.js +2885 -0
  33. package/dist/server/client/daemon-client.js.map +1 -0
  34. package/dist/server/server/agent/activity-curator.d.ts +8 -0
  35. package/dist/server/server/agent/activity-curator.d.ts.map +1 -0
  36. package/dist/server/server/agent/activity-curator.js +243 -0
  37. package/dist/server/server/agent/activity-curator.js.map +1 -0
  38. package/dist/server/server/agent/agent-management-mcp.d.ts +41 -0
  39. package/dist/server/server/agent/agent-management-mcp.d.ts.map +1 -0
  40. package/dist/server/server/agent/agent-management-mcp.js +767 -0
  41. package/dist/server/server/agent/agent-management-mcp.js.map +1 -0
  42. package/dist/server/server/agent/agent-manager.d.ts +287 -0
  43. package/dist/server/server/agent/agent-manager.d.ts.map +1 -0
  44. package/dist/server/server/agent/agent-manager.js +1956 -0
  45. package/dist/server/server/agent/agent-manager.js.map +1 -0
  46. package/dist/server/server/agent/agent-metadata-generator.d.ts +29 -0
  47. package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -0
  48. package/dist/server/server/agent/agent-metadata-generator.js +161 -0
  49. package/dist/server/server/agent/agent-metadata-generator.js.map +1 -0
  50. package/dist/server/server/agent/agent-projections.d.ts +17 -0
  51. package/dist/server/server/agent/agent-projections.d.ts.map +1 -0
  52. package/dist/server/server/agent/agent-projections.js +280 -0
  53. package/dist/server/server/agent/agent-projections.js.map +1 -0
  54. package/dist/server/server/agent/agent-response-loop.d.ts +60 -0
  55. package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -0
  56. package/dist/server/server/agent/agent-response-loop.js +304 -0
  57. package/dist/server/server/agent/agent-response-loop.js.map +1 -0
  58. package/dist/server/server/agent/agent-sdk-types.d.ts +470 -0
  59. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -0
  60. package/dist/server/server/agent/agent-sdk-types.js +12 -0
  61. package/dist/server/server/agent/agent-sdk-types.js.map +1 -0
  62. package/dist/server/server/agent/agent-storage.d.ts +336 -0
  63. package/dist/server/server/agent/agent-storage.d.ts.map +1 -0
  64. package/dist/server/server/agent/agent-storage.js +304 -0
  65. package/dist/server/server/agent/agent-storage.js.map +1 -0
  66. package/dist/server/server/agent/agent-title-limits.d.ts +3 -0
  67. package/dist/server/server/agent/agent-title-limits.d.ts.map +1 -0
  68. package/dist/server/server/agent/agent-title-limits.js +3 -0
  69. package/dist/server/server/agent/agent-title-limits.js.map +1 -0
  70. package/dist/server/server/agent/audio-utils.d.ts +3 -0
  71. package/dist/server/server/agent/audio-utils.d.ts.map +1 -0
  72. package/dist/server/server/agent/audio-utils.js +19 -0
  73. package/dist/server/server/agent/audio-utils.js.map +1 -0
  74. package/dist/server/server/agent/dictation-debug.d.ts +13 -0
  75. package/dist/server/server/agent/dictation-debug.d.ts.map +1 -0
  76. package/dist/server/server/agent/dictation-debug.js +50 -0
  77. package/dist/server/server/agent/dictation-debug.js.map +1 -0
  78. package/dist/server/server/agent/llm-openai.d.ts +7 -0
  79. package/dist/server/server/agent/llm-openai.d.ts.map +1 -0
  80. package/dist/server/server/agent/llm-openai.js +8 -0
  81. package/dist/server/server/agent/llm-openai.js.map +1 -0
  82. package/dist/server/server/agent/mcp-server.d.ts +33 -0
  83. package/dist/server/server/agent/mcp-server.d.ts.map +1 -0
  84. package/dist/server/server/agent/mcp-server.js +1279 -0
  85. package/dist/server/server/agent/mcp-server.js.map +1 -0
  86. package/dist/server/server/agent/mcp-shared.d.ts +251 -0
  87. package/dist/server/server/agent/mcp-shared.d.ts.map +1 -0
  88. package/dist/server/server/agent/mcp-shared.js +242 -0
  89. package/dist/server/server/agent/mcp-shared.js.map +1 -0
  90. package/dist/server/server/agent/model-resolver.d.ts +11 -0
  91. package/dist/server/server/agent/model-resolver.d.ts.map +1 -0
  92. package/dist/server/server/agent/model-resolver.js +21 -0
  93. package/dist/server/server/agent/model-resolver.js.map +1 -0
  94. package/dist/server/server/agent/orchestrator-instructions.d.ts +7 -0
  95. package/dist/server/server/agent/orchestrator-instructions.d.ts.map +1 -0
  96. package/dist/server/server/agent/orchestrator-instructions.js +51 -0
  97. package/dist/server/server/agent/orchestrator-instructions.js.map +1 -0
  98. package/dist/server/server/agent/orchestrator.d.ts +12 -0
  99. package/dist/server/server/agent/orchestrator.d.ts.map +1 -0
  100. package/dist/server/server/agent/orchestrator.js +12 -0
  101. package/dist/server/server/agent/orchestrator.js.map +1 -0
  102. package/dist/server/server/agent/pcm16-resampler.d.ts +14 -0
  103. package/dist/server/server/agent/pcm16-resampler.d.ts.map +1 -0
  104. package/dist/server/server/agent/pcm16-resampler.js +63 -0
  105. package/dist/server/server/agent/pcm16-resampler.js.map +1 -0
  106. package/dist/server/server/agent/provider-launch-config.d.ts +138 -0
  107. package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -0
  108. package/dist/server/server/agent/provider-launch-config.js +80 -0
  109. package/dist/server/server/agent/provider-launch-config.js.map +1 -0
  110. package/dist/server/server/agent/provider-manifest.d.ts +29 -0
  111. package/dist/server/server/agent/provider-manifest.d.ts.map +1 -0
  112. package/dist/server/server/agent/provider-manifest.js +157 -0
  113. package/dist/server/server/agent/provider-manifest.js.map +1 -0
  114. package/dist/server/server/agent/provider-registry.d.ts +19 -0
  115. package/dist/server/server/agent/provider-registry.d.ts.map +1 -0
  116. package/dist/server/server/agent/provider-registry.js +58 -0
  117. package/dist/server/server/agent/provider-registry.js.map +1 -0
  118. package/dist/server/server/agent/provider-snapshot-manager.d.ts +27 -0
  119. package/dist/server/server/agent/provider-snapshot-manager.d.ts.map +1 -0
  120. package/dist/server/server/agent/provider-snapshot-manager.js +181 -0
  121. package/dist/server/server/agent/provider-snapshot-manager.js.map +1 -0
  122. package/dist/server/server/agent/providers/acp-agent.d.ts +202 -0
  123. package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -0
  124. package/dist/server/server/agent/providers/acp-agent.js +1650 -0
  125. package/dist/server/server/agent/providers/acp-agent.js.map +1 -0
  126. package/dist/server/server/agent/providers/claude/claude-models.d.ts +8 -0
  127. package/dist/server/server/agent/providers/claude/claude-models.d.ts.map +1 -0
  128. package/dist/server/server/agent/providers/claude/claude-models.js +63 -0
  129. package/dist/server/server/agent/providers/claude/claude-models.js.map +1 -0
  130. package/dist/server/server/agent/providers/claude/partial-json.d.ts +5 -0
  131. package/dist/server/server/agent/providers/claude/partial-json.d.ts.map +1 -0
  132. package/dist/server/server/agent/providers/claude/partial-json.js +306 -0
  133. package/dist/server/server/agent/providers/claude/partial-json.js.map +1 -0
  134. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts +20 -0
  135. package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts.map +1 -0
  136. package/dist/server/server/agent/providers/claude/sidechain-tracker.js +230 -0
  137. package/dist/server/server/agent/providers/claude/sidechain-tracker.js.map +1 -0
  138. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +55 -0
  139. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts.map +1 -0
  140. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js +267 -0
  141. package/dist/server/server/agent/providers/claude/task-notification-tool-call.js.map +1 -0
  142. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts +3 -0
  143. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts.map +1 -0
  144. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +121 -0
  145. package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -0
  146. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +16 -0
  147. package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -0
  148. package/dist/server/server/agent/providers/claude/tool-call-mapper.js +252 -0
  149. package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -0
  150. package/dist/server/server/agent/providers/claude-agent.d.ts +44 -0
  151. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -0
  152. package/dist/server/server/agent/providers/claude-agent.js +3452 -0
  153. package/dist/server/server/agent/providers/claude-agent.js.map +1 -0
  154. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +12 -0
  155. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts.map +1 -0
  156. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js +104 -0
  157. package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js.map +1 -0
  158. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +15 -0
  159. package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -0
  160. package/dist/server/server/agent/providers/codex/tool-call-mapper.js +762 -0
  161. package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -0
  162. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +200 -0
  163. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -0
  164. package/dist/server/server/agent/providers/codex-app-server-agent.js +3474 -0
  165. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -0
  166. package/dist/server/server/agent/providers/codex-feature-definitions.d.ts +11 -0
  167. package/dist/server/server/agent/providers/codex-feature-definitions.d.ts.map +1 -0
  168. package/dist/server/server/agent/providers/codex-feature-definitions.js +45 -0
  169. package/dist/server/server/agent/providers/codex-feature-definitions.js.map +1 -0
  170. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts +9 -0
  171. package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -0
  172. package/dist/server/server/agent/providers/codex-rollout-timeline.js +544 -0
  173. package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -0
  174. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +16 -0
  175. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts.map +1 -0
  176. package/dist/server/server/agent/providers/copilot-acp-agent.js +95 -0
  177. package/dist/server/server/agent/providers/copilot-acp-agent.js.map +1 -0
  178. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +17 -0
  179. package/dist/server/server/agent/providers/diagnostic-utils.d.ts.map +1 -0
  180. package/dist/server/server/agent/providers/diagnostic-utils.js +56 -0
  181. package/dist/server/server/agent/providers/diagnostic-utils.js.map +1 -0
  182. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +3 -0
  183. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -0
  184. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +39 -0
  185. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -0
  186. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +13 -0
  187. package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -0
  188. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +144 -0
  189. package/dist/server/server/agent/providers/opencode/tool-call-mapper.js.map +1 -0
  190. package/dist/server/server/agent/providers/opencode-agent.d.ts +121 -0
  191. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -0
  192. package/dist/server/server/agent/providers/opencode-agent.js +1649 -0
  193. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -0
  194. package/dist/server/server/agent/providers/pi-acp-agent.d.ts +28 -0
  195. package/dist/server/server/agent/providers/pi-acp-agent.d.ts.map +1 -0
  196. package/dist/server/server/agent/providers/pi-acp-agent.js +302 -0
  197. package/dist/server/server/agent/providers/pi-acp-agent.js.map +1 -0
  198. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.d.ts +3 -0
  199. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.d.ts.map +1 -0
  200. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js +57 -0
  201. package/dist/server/server/agent/providers/test-utils/session-stream-adapter.js.map +1 -0
  202. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +1745 -0
  203. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -0
  204. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +686 -0
  205. package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -0
  206. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +18 -0
  207. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -0
  208. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +115 -0
  209. package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -0
  210. package/dist/server/server/agent/recordings-debug.d.ts +3 -0
  211. package/dist/server/server/agent/recordings-debug.d.ts.map +1 -0
  212. package/dist/server/server/agent/recordings-debug.js +19 -0
  213. package/dist/server/server/agent/recordings-debug.js.map +1 -0
  214. package/dist/server/server/agent/stt-debug.d.ts +10 -0
  215. package/dist/server/server/agent/stt-debug.d.ts.map +1 -0
  216. package/dist/server/server/agent/stt-debug.js +33 -0
  217. package/dist/server/server/agent/stt-debug.js.map +1 -0
  218. package/dist/server/server/agent/stt-manager.d.ts +33 -0
  219. package/dist/server/server/agent/stt-manager.d.ts.map +1 -0
  220. package/dist/server/server/agent/stt-manager.js +232 -0
  221. package/dist/server/server/agent/stt-manager.js.map +1 -0
  222. package/dist/server/server/agent/timeline-append.d.ts +10 -0
  223. package/dist/server/server/agent/timeline-append.d.ts.map +1 -0
  224. package/dist/server/server/agent/timeline-append.js +27 -0
  225. package/dist/server/server/agent/timeline-append.js.map +1 -0
  226. package/dist/server/server/agent/timeline-projection.d.ts +39 -0
  227. package/dist/server/server/agent/timeline-projection.d.ts.map +1 -0
  228. package/dist/server/server/agent/timeline-projection.js +215 -0
  229. package/dist/server/server/agent/timeline-projection.js.map +1 -0
  230. package/dist/server/server/agent/tool-name-normalization.d.ts +9 -0
  231. package/dist/server/server/agent/tool-name-normalization.d.ts.map +1 -0
  232. package/dist/server/server/agent/tool-name-normalization.js +82 -0
  233. package/dist/server/server/agent/tool-name-normalization.js.map +1 -0
  234. package/dist/server/server/agent/tts-debug.d.ts +8 -0
  235. package/dist/server/server/agent/tts-debug.d.ts.map +1 -0
  236. package/dist/server/server/agent/tts-debug.js +24 -0
  237. package/dist/server/server/agent/tts-debug.js.map +1 -0
  238. package/dist/server/server/agent/tts-manager.d.ts +41 -0
  239. package/dist/server/server/agent/tts-manager.d.ts.map +1 -0
  240. package/dist/server/server/agent/tts-manager.js +374 -0
  241. package/dist/server/server/agent/tts-manager.js.map +1 -0
  242. package/dist/server/server/agent/wait-for-agent-tracker.d.ts +15 -0
  243. package/dist/server/server/agent/wait-for-agent-tracker.d.ts.map +1 -0
  244. package/dist/server/server/agent/wait-for-agent-tracker.js +53 -0
  245. package/dist/server/server/agent/wait-for-agent-tracker.js.map +1 -0
  246. package/dist/server/server/agent-attention-policy.d.ts +20 -0
  247. package/dist/server/server/agent-attention-policy.d.ts.map +1 -0
  248. package/dist/server/server/agent-attention-policy.js +40 -0
  249. package/dist/server/server/agent-attention-policy.js.map +1 -0
  250. package/dist/server/server/allowed-hosts.d.ts +13 -0
  251. package/dist/server/server/allowed-hosts.d.ts.map +1 -0
  252. package/dist/server/server/allowed-hosts.js +94 -0
  253. package/dist/server/server/allowed-hosts.js.map +1 -0
  254. package/dist/server/server/bootstrap.d.ts +74 -0
  255. package/dist/server/server/bootstrap.d.ts.map +1 -0
  256. package/dist/server/server/bootstrap.js +537 -0
  257. package/dist/server/server/bootstrap.js.map +1 -0
  258. package/dist/server/server/chat/chat-mentions.d.ts +31 -0
  259. package/dist/server/server/chat/chat-mentions.d.ts.map +1 -0
  260. package/dist/server/server/chat/chat-mentions.js +71 -0
  261. package/dist/server/server/chat/chat-mentions.js.map +1 -0
  262. package/dist/server/server/chat/chat-rpc-schemas.d.ts +728 -0
  263. package/dist/server/server/chat/chat-rpc-schemas.d.ts.map +1 -0
  264. package/dist/server/server/chat/chat-rpc-schemas.js +103 -0
  265. package/dist/server/server/chat/chat-rpc-schemas.js.map +1 -0
  266. package/dist/server/server/chat/chat-service.d.ts +74 -0
  267. package/dist/server/server/chat/chat-service.d.ts.map +1 -0
  268. package/dist/server/server/chat/chat-service.js +330 -0
  269. package/dist/server/server/chat/chat-service.js.map +1 -0
  270. package/dist/server/server/chat/chat-types.d.ts +75 -0
  271. package/dist/server/server/chat/chat-types.d.ts.map +1 -0
  272. package/dist/server/server/chat/chat-types.js +22 -0
  273. package/dist/server/server/chat/chat-types.js.map +1 -0
  274. package/dist/server/server/checkout-diff-manager.d.ts +45 -0
  275. package/dist/server/server/checkout-diff-manager.d.ts.map +1 -0
  276. package/dist/server/server/checkout-diff-manager.js +374 -0
  277. package/dist/server/server/checkout-diff-manager.js.map +1 -0
  278. package/dist/server/server/checkout-git-utils.d.ts +9 -0
  279. package/dist/server/server/checkout-git-utils.d.ts.map +1 -0
  280. package/dist/server/server/checkout-git-utils.js +37 -0
  281. package/dist/server/server/checkout-git-utils.js.map +1 -0
  282. package/dist/server/server/client-message-id.d.ts +3 -0
  283. package/dist/server/server/client-message-id.d.ts.map +1 -0
  284. package/dist/server/server/client-message-id.js +12 -0
  285. package/dist/server/server/client-message-id.js.map +1 -0
  286. package/dist/server/server/config.d.ts +14 -0
  287. package/dist/server/server/config.d.ts.map +1 -0
  288. package/dist/server/server/config.js +96 -0
  289. package/dist/server/server/config.js.map +1 -0
  290. package/dist/server/server/connection-offer.d.ts +19 -0
  291. package/dist/server/server/connection-offer.d.ts.map +1 -0
  292. package/dist/server/server/connection-offer.js +59 -0
  293. package/dist/server/server/connection-offer.js.map +1 -0
  294. package/dist/server/server/daemon-config-store.d.ts +23 -0
  295. package/dist/server/server/daemon-config-store.d.ts.map +1 -0
  296. package/dist/server/server/daemon-config-store.js +114 -0
  297. package/dist/server/server/daemon-config-store.js.map +1 -0
  298. package/dist/server/server/daemon-keypair.d.ts +8 -0
  299. package/dist/server/server/daemon-keypair.d.ts.map +1 -0
  300. package/dist/server/server/daemon-keypair.js +40 -0
  301. package/dist/server/server/daemon-keypair.js.map +1 -0
  302. package/dist/server/server/daemon-version.d.ts +5 -0
  303. package/dist/server/server/daemon-version.d.ts.map +1 -0
  304. package/dist/server/server/daemon-version.js +22 -0
  305. package/dist/server/server/daemon-version.js.map +1 -0
  306. package/dist/server/server/dictation/dictation-stream-manager.d.ts +85 -0
  307. package/dist/server/server/dictation/dictation-stream-manager.d.ts.map +1 -0
  308. package/dist/server/server/dictation/dictation-stream-manager.js +571 -0
  309. package/dist/server/server/dictation/dictation-stream-manager.js.map +1 -0
  310. package/dist/server/server/editor-targets.d.ts +18 -0
  311. package/dist/server/server/editor-targets.d.ts.map +1 -0
  312. package/dist/server/server/editor-targets.js +113 -0
  313. package/dist/server/server/editor-targets.js.map +1 -0
  314. package/dist/server/server/exports.d.ts +19 -0
  315. package/dist/server/server/exports.d.ts.map +1 -0
  316. package/dist/server/server/exports.js +21 -0
  317. package/dist/server/server/exports.js.map +1 -0
  318. package/dist/server/server/file-download/token-store.d.ts +24 -0
  319. package/dist/server/server/file-download/token-store.d.ts.map +1 -0
  320. package/dist/server/server/file-download/token-store.js +40 -0
  321. package/dist/server/server/file-download/token-store.js.map +1 -0
  322. package/dist/server/server/file-explorer/service.d.ts +41 -0
  323. package/dist/server/server/file-explorer/service.d.ts.map +1 -0
  324. package/dist/server/server/file-explorer/service.js +194 -0
  325. package/dist/server/server/file-explorer/service.js.map +1 -0
  326. package/dist/server/server/index.d.ts +2 -0
  327. package/dist/server/server/index.d.ts.map +1 -0
  328. package/dist/server/server/index.js +176 -0
  329. package/dist/server/server/index.js.map +1 -0
  330. package/dist/server/server/json-utils.d.ts +11 -0
  331. package/dist/server/server/json-utils.d.ts.map +1 -0
  332. package/dist/server/server/json-utils.js +45 -0
  333. package/dist/server/server/json-utils.js.map +1 -0
  334. package/dist/server/server/logger.d.ts +33 -0
  335. package/dist/server/server/logger.d.ts.map +1 -0
  336. package/dist/server/server/logger.js +195 -0
  337. package/dist/server/server/logger.js.map +1 -0
  338. package/dist/server/server/loop/rpc-schemas.d.ts +2937 -0
  339. package/dist/server/server/loop/rpc-schemas.d.ts.map +1 -0
  340. package/dist/server/server/loop/rpc-schemas.js +159 -0
  341. package/dist/server/server/loop/rpc-schemas.js.map +1 -0
  342. package/dist/server/server/loop-service.d.ts +520 -0
  343. package/dist/server/server/loop-service.d.ts.map +1 -0
  344. package/dist/server/server/loop-service.js +739 -0
  345. package/dist/server/server/loop-service.js.map +1 -0
  346. package/dist/server/server/messages.d.ts +9 -0
  347. package/dist/server/server/messages.d.ts.map +1 -0
  348. package/dist/server/server/messages.js +29 -0
  349. package/dist/server/server/messages.js.map +1 -0
  350. package/dist/server/server/package-version.d.ts +13 -0
  351. package/dist/server/server/package-version.d.ts.map +1 -0
  352. package/dist/server/server/package-version.js +46 -0
  353. package/dist/server/server/package-version.js.map +1 -0
  354. package/dist/server/server/pairing-offer.d.ts +16 -0
  355. package/dist/server/server/pairing-offer.d.ts.map +1 -0
  356. package/dist/server/server/pairing-offer.js +45 -0
  357. package/dist/server/server/pairing-offer.js.map +1 -0
  358. package/dist/server/server/pairing-qr.d.ts +7 -0
  359. package/dist/server/server/pairing-qr.d.ts.map +1 -0
  360. package/dist/server/server/pairing-qr.js +45 -0
  361. package/dist/server/server/pairing-qr.js.map +1 -0
  362. package/dist/server/server/path-utils.d.ts +3 -0
  363. package/dist/server/server/path-utils.d.ts.map +1 -0
  364. package/dist/server/server/path-utils.js +20 -0
  365. package/dist/server/server/path-utils.js.map +1 -0
  366. package/dist/server/server/persisted-config.d.ts +625 -0
  367. package/dist/server/server/persisted-config.d.ts.map +1 -0
  368. package/dist/server/server/persisted-config.js +265 -0
  369. package/dist/server/server/persisted-config.js.map +1 -0
  370. package/dist/server/server/persistence-hooks.d.ts +24 -0
  371. package/dist/server/server/persistence-hooks.d.ts.map +1 -0
  372. package/dist/server/server/persistence-hooks.js +60 -0
  373. package/dist/server/server/persistence-hooks.js.map +1 -0
  374. package/dist/server/server/pid-lock.d.ts +29 -0
  375. package/dist/server/server/pid-lock.d.ts.map +1 -0
  376. package/dist/server/server/pid-lock.js +148 -0
  377. package/dist/server/server/pid-lock.js.map +1 -0
  378. package/dist/server/server/push/push-service.d.ts +22 -0
  379. package/dist/server/server/push/push-service.d.ts.map +1 -0
  380. package/dist/server/server/push/push-service.js +69 -0
  381. package/dist/server/server/push/push-service.js.map +1 -0
  382. package/dist/server/server/push/token-store.d.ts +18 -0
  383. package/dist/server/server/push/token-store.d.ts.map +1 -0
  384. package/dist/server/server/push/token-store.js +70 -0
  385. package/dist/server/server/push/token-store.js.map +1 -0
  386. package/dist/server/server/relay-transport.d.ts +23 -0
  387. package/dist/server/server/relay-transport.d.ts.map +1 -0
  388. package/dist/server/server/relay-transport.js +461 -0
  389. package/dist/server/server/relay-transport.js.map +1 -0
  390. package/dist/server/server/schedule/cron.d.ts +4 -0
  391. package/dist/server/server/schedule/cron.d.ts.map +1 -0
  392. package/dist/server/server/schedule/cron.js +103 -0
  393. package/dist/server/server/schedule/cron.js.map +1 -0
  394. package/dist/server/server/schedule/rpc-schemas.d.ts +2773 -0
  395. package/dist/server/server/schedule/rpc-schemas.d.ts.map +1 -0
  396. package/dist/server/server/schedule/rpc-schemas.js +112 -0
  397. package/dist/server/server/schedule/rpc-schemas.js.map +1 -0
  398. package/dist/server/server/schedule/service.d.ts +39 -0
  399. package/dist/server/server/schedule/service.d.ts.map +1 -0
  400. package/dist/server/server/schedule/service.js +410 -0
  401. package/dist/server/server/schedule/service.js.map +1 -0
  402. package/dist/server/server/schedule/store.d.ts +13 -0
  403. package/dist/server/server/schedule/store.d.ts.map +1 -0
  404. package/dist/server/server/schedule/store.js +56 -0
  405. package/dist/server/server/schedule/store.js.map +1 -0
  406. package/dist/server/server/schedule/types.d.ts +710 -0
  407. package/dist/server/server/schedule/types.d.ts.map +1 -0
  408. package/dist/server/server/schedule/types.js +73 -0
  409. package/dist/server/server/schedule/types.js.map +1 -0
  410. package/dist/server/server/seawork-home.d.ts +2 -0
  411. package/dist/server/server/seawork-home.d.ts.map +1 -0
  412. package/dist/server/server/seawork-home.js +19 -0
  413. package/dist/server/server/seawork-home.js.map +1 -0
  414. package/dist/server/server/server-id.d.ts +17 -0
  415. package/dist/server/server/server-id.d.ts.map +1 -0
  416. package/dist/server/server/server-id.js +63 -0
  417. package/dist/server/server/server-id.js.map +1 -0
  418. package/dist/server/server/session.d.ts +510 -0
  419. package/dist/server/server/session.d.ts.map +1 -0
  420. package/dist/server/server/session.js +6414 -0
  421. package/dist/server/server/session.js.map +1 -0
  422. package/dist/server/server/speech/audio.d.ts +10 -0
  423. package/dist/server/server/speech/audio.d.ts.map +1 -0
  424. package/dist/server/server/speech/audio.js +101 -0
  425. package/dist/server/server/speech/audio.js.map +1 -0
  426. package/dist/server/server/speech/provider-resolver.d.ts +3 -0
  427. package/dist/server/server/speech/provider-resolver.d.ts.map +1 -0
  428. package/dist/server/server/speech/provider-resolver.js +7 -0
  429. package/dist/server/server/speech/provider-resolver.js.map +1 -0
  430. package/dist/server/server/speech/providers/local/config.d.ts +25 -0
  431. package/dist/server/server/speech/providers/local/config.d.ts.map +1 -0
  432. package/dist/server/server/speech/providers/local/config.js +74 -0
  433. package/dist/server/server/speech/providers/local/config.js.map +1 -0
  434. package/dist/server/server/speech/providers/local/models.d.ts +11 -0
  435. package/dist/server/server/speech/providers/local/models.d.ts.map +1 -0
  436. package/dist/server/server/speech/providers/local/models.js +17 -0
  437. package/dist/server/server/speech/providers/local/models.js.map +1 -0
  438. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts +24 -0
  439. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts.map +1 -0
  440. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js +436 -0
  441. package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js.map +1 -0
  442. package/dist/server/server/speech/providers/local/runtime.d.ts +31 -0
  443. package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -0
  444. package/dist/server/server/speech/providers/local/runtime.js +247 -0
  445. package/dist/server/server/speech/providers/local/runtime.js.map +1 -0
  446. package/dist/server/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
  447. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +117 -0
  448. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts.map +1 -0
  449. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +166 -0
  450. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js.map +1 -0
  451. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +15 -0
  452. package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts.map +1 -0
  453. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +165 -0
  454. package/dist/server/server/speech/providers/local/sherpa/model-downloader.js.map +1 -0
  455. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +28 -0
  456. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts.map +1 -0
  457. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +73 -0
  458. package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js.map +1 -0
  459. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts +37 -0
  460. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts.map +1 -0
  461. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js +84 -0
  462. package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -0
  463. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts +7 -0
  464. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts.map +1 -0
  465. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.js +11 -0
  466. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.js.map +1 -0
  467. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +9 -0
  468. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts.map +1 -0
  469. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +102 -0
  470. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -0
  471. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts +28 -0
  472. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts.map +1 -0
  473. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +135 -0
  474. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js.map +1 -0
  475. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +21 -0
  476. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts.map +1 -0
  477. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +131 -0
  478. package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js.map +1 -0
  479. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.d.ts +23 -0
  480. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.d.ts.map +1 -0
  481. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js +110 -0
  482. package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -0
  483. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts +18 -0
  484. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.d.ts.map +1 -0
  485. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
  486. package/dist/server/server/speech/providers/local/sherpa/sherpa-runtime-env.js.map +1 -0
  487. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts +23 -0
  488. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts.map +1 -0
  489. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js +138 -0
  490. package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js.map +1 -0
  491. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +21 -0
  492. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts.map +1 -0
  493. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +108 -0
  494. package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -0
  495. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts +19 -0
  496. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts.map +1 -0
  497. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js +49 -0
  498. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js.map +1 -0
  499. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts +38 -0
  500. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts.map +1 -0
  501. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js +176 -0
  502. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js.map +1 -0
  503. package/dist/server/server/speech/providers/openai/config.d.ts +22 -0
  504. package/dist/server/server/speech/providers/openai/config.d.ts.map +1 -0
  505. package/dist/server/server/speech/providers/openai/config.js +80 -0
  506. package/dist/server/server/speech/providers/openai/config.js.map +1 -0
  507. package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts +42 -0
  508. package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts.map +1 -0
  509. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +168 -0
  510. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js.map +1 -0
  511. package/dist/server/server/speech/providers/openai/runtime.d.ts +29 -0
  512. package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -0
  513. package/dist/server/server/speech/providers/openai/runtime.js +112 -0
  514. package/dist/server/server/speech/providers/openai/runtime.js.map +1 -0
  515. package/dist/server/server/speech/providers/openai/stt.d.ts +22 -0
  516. package/dist/server/server/speech/providers/openai/stt.d.ts.map +1 -0
  517. package/dist/server/server/speech/providers/openai/stt.js +206 -0
  518. package/dist/server/server/speech/providers/openai/stt.js.map +1 -0
  519. package/dist/server/server/speech/providers/openai/tts.d.ts +18 -0
  520. package/dist/server/server/speech/providers/openai/tts.d.ts.map +1 -0
  521. package/dist/server/server/speech/providers/openai/tts.js +46 -0
  522. package/dist/server/server/speech/providers/openai/tts.js.map +1 -0
  523. package/dist/server/server/speech/speech-config-resolver.d.ts +11 -0
  524. package/dist/server/server/speech/speech-config-resolver.d.ts.map +1 -0
  525. package/dist/server/server/speech/speech-config-resolver.js +104 -0
  526. package/dist/server/server/speech/speech-config-resolver.js.map +1 -0
  527. package/dist/server/server/speech/speech-provider.d.ts +59 -0
  528. package/dist/server/server/speech/speech-provider.d.ts.map +1 -0
  529. package/dist/server/server/speech/speech-provider.js +2 -0
  530. package/dist/server/server/speech/speech-provider.js.map +1 -0
  531. package/dist/server/server/speech/speech-runtime.d.ts +43 -0
  532. package/dist/server/server/speech/speech-runtime.d.ts.map +1 -0
  533. package/dist/server/server/speech/speech-runtime.js +560 -0
  534. package/dist/server/server/speech/speech-runtime.js.map +1 -0
  535. package/dist/server/server/speech/speech-types.d.ts +24 -0
  536. package/dist/server/server/speech/speech-types.d.ts.map +1 -0
  537. package/dist/server/server/speech/speech-types.js +8 -0
  538. package/dist/server/server/speech/speech-types.js.map +1 -0
  539. package/dist/server/server/speech/turn-detection-provider.d.ts +23 -0
  540. package/dist/server/server/speech/turn-detection-provider.d.ts.map +1 -0
  541. package/dist/server/server/speech/turn-detection-provider.js +2 -0
  542. package/dist/server/server/speech/turn-detection-provider.js.map +1 -0
  543. package/dist/server/server/types.d.ts +5 -0
  544. package/dist/server/server/types.d.ts.map +1 -0
  545. package/dist/server/server/types.js +3 -0
  546. package/dist/server/server/types.js.map +1 -0
  547. package/dist/server/server/utils/diff-highlighter.d.ts +60 -0
  548. package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -0
  549. package/dist/server/server/utils/diff-highlighter.js +257 -0
  550. package/dist/server/server/utils/diff-highlighter.js.map +1 -0
  551. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.d.ts +16 -0
  552. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.d.ts.map +1 -0
  553. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.js +35 -0
  554. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.js.map +1 -0
  555. package/dist/server/server/voice/voice-turn-controller.d.ts +34 -0
  556. package/dist/server/server/voice/voice-turn-controller.d.ts.map +1 -0
  557. package/dist/server/server/voice/voice-turn-controller.js +160 -0
  558. package/dist/server/server/voice/voice-turn-controller.js.map +1 -0
  559. package/dist/server/server/voice-config.d.ts +15 -0
  560. package/dist/server/server/voice-config.d.ts.map +1 -0
  561. package/dist/server/server/voice-config.js +54 -0
  562. package/dist/server/server/voice-config.js.map +1 -0
  563. package/dist/server/server/voice-permission-policy.d.ts +4 -0
  564. package/dist/server/server/voice-permission-policy.d.ts.map +1 -0
  565. package/dist/server/server/voice-permission-policy.js +13 -0
  566. package/dist/server/server/voice-permission-policy.js.map +1 -0
  567. package/dist/server/server/voice-types.d.ts +12 -0
  568. package/dist/server/server/voice-types.d.ts.map +1 -0
  569. package/dist/server/server/voice-types.js +2 -0
  570. package/dist/server/server/voice-types.js.map +1 -0
  571. package/dist/server/server/websocket-server.d.ts +122 -0
  572. package/dist/server/server/websocket-server.d.ts.map +1 -0
  573. package/dist/server/server/websocket-server.js +1092 -0
  574. package/dist/server/server/websocket-server.js.map +1 -0
  575. package/dist/server/server/workspace-git-service.d.ts +108 -0
  576. package/dist/server/server/workspace-git-service.d.ts.map +1 -0
  577. package/dist/server/server/workspace-git-service.js +404 -0
  578. package/dist/server/server/workspace-git-service.js.map +1 -0
  579. package/dist/server/server/workspace-registry-bootstrap.d.ts +11 -0
  580. package/dist/server/server/workspace-registry-bootstrap.d.ts.map +1 -0
  581. package/dist/server/server/workspace-registry-bootstrap.js +100 -0
  582. package/dist/server/server/workspace-registry-bootstrap.js.map +1 -0
  583. package/dist/server/server/workspace-registry-model.d.ts +33 -0
  584. package/dist/server/server/workspace-registry-model.d.ts.map +1 -0
  585. package/dist/server/server/workspace-registry-model.js +167 -0
  586. package/dist/server/server/workspace-registry-model.js.map +1 -0
  587. package/dist/server/server/workspace-registry.d.ts +130 -0
  588. package/dist/server/server/workspace-registry.d.ts.map +1 -0
  589. package/dist/server/server/workspace-registry.js +151 -0
  590. package/dist/server/server/workspace-registry.js.map +1 -0
  591. package/dist/server/server/worktree-bootstrap.d.ts +29 -0
  592. package/dist/server/server/worktree-bootstrap.d.ts.map +1 -0
  593. package/dist/server/server/worktree-bootstrap.js +508 -0
  594. package/dist/server/server/worktree-bootstrap.js.map +1 -0
  595. package/dist/server/server/worktree-session.d.ts +131 -0
  596. package/dist/server/server/worktree-session.d.ts.map +1 -0
  597. package/dist/server/server/worktree-session.js +487 -0
  598. package/dist/server/server/worktree-session.js.map +1 -0
  599. package/dist/server/shared/agent-attention-notification.d.ts +40 -0
  600. package/dist/server/shared/agent-attention-notification.d.ts.map +1 -0
  601. package/dist/server/shared/agent-attention-notification.js +130 -0
  602. package/dist/server/shared/agent-attention-notification.js.map +1 -0
  603. package/dist/server/shared/agent-lifecycle.d.ts +3 -0
  604. package/dist/server/shared/agent-lifecycle.d.ts.map +1 -0
  605. package/dist/server/shared/agent-lifecycle.js +8 -0
  606. package/dist/server/shared/agent-lifecycle.js.map +1 -0
  607. package/dist/server/shared/connection-offer.d.ts +62 -0
  608. package/dist/server/shared/connection-offer.d.ts.map +1 -0
  609. package/dist/server/shared/connection-offer.js +17 -0
  610. package/dist/server/shared/connection-offer.js.map +1 -0
  611. package/dist/server/shared/daemon-endpoints.d.ts +28 -0
  612. package/dist/server/shared/daemon-endpoints.d.ts.map +1 -0
  613. package/dist/server/shared/daemon-endpoints.js +122 -0
  614. package/dist/server/shared/daemon-endpoints.js.map +1 -0
  615. package/dist/server/shared/literal-union.d.ts +2 -0
  616. package/dist/server/shared/literal-union.d.ts.map +1 -0
  617. package/dist/server/shared/literal-union.js +2 -0
  618. package/dist/server/shared/literal-union.js.map +1 -0
  619. package/dist/server/shared/messages.d.ts +81816 -0
  620. package/dist/server/shared/messages.d.ts.map +1 -0
  621. package/dist/server/shared/messages.js +2553 -0
  622. package/dist/server/shared/messages.js.map +1 -0
  623. package/dist/server/shared/path-utils.d.ts +2 -0
  624. package/dist/server/shared/path-utils.d.ts.map +1 -0
  625. package/dist/server/shared/path-utils.js +16 -0
  626. package/dist/server/shared/path-utils.js.map +1 -0
  627. package/dist/server/shared/terminal-stream-protocol.d.ts +36 -0
  628. package/dist/server/shared/terminal-stream-protocol.d.ts.map +1 -0
  629. package/dist/server/shared/terminal-stream-protocol.js +99 -0
  630. package/dist/server/shared/terminal-stream-protocol.js.map +1 -0
  631. package/dist/server/shared/tool-call-display.d.ts +11 -0
  632. package/dist/server/shared/tool-call-display.d.ts.map +1 -0
  633. package/dist/server/shared/tool-call-display.js +133 -0
  634. package/dist/server/shared/tool-call-display.js.map +1 -0
  635. package/dist/server/terminal/terminal-manager.d.ts +30 -0
  636. package/dist/server/terminal/terminal-manager.d.ts.map +1 -0
  637. package/dist/server/terminal/terminal-manager.js +136 -0
  638. package/dist/server/terminal/terminal-manager.js.map +1 -0
  639. package/dist/server/terminal/terminal.d.ts +68 -0
  640. package/dist/server/terminal/terminal.d.ts.map +1 -0
  641. package/dist/server/terminal/terminal.js +384 -0
  642. package/dist/server/terminal/terminal.js.map +1 -0
  643. package/dist/server/utils/checkout-git.d.ts +180 -0
  644. package/dist/server/utils/checkout-git.d.ts.map +1 -0
  645. package/dist/server/utils/checkout-git.js +1621 -0
  646. package/dist/server/utils/checkout-git.js.map +1 -0
  647. package/dist/server/utils/directory-suggestions.d.ts +24 -0
  648. package/dist/server/utils/directory-suggestions.d.ts.map +1 -0
  649. package/dist/server/utils/directory-suggestions.js +671 -0
  650. package/dist/server/utils/directory-suggestions.js.map +1 -0
  651. package/dist/server/utils/executable.d.ts +33 -0
  652. package/dist/server/utils/executable.d.ts.map +1 -0
  653. package/dist/server/utils/executable.js +134 -0
  654. package/dist/server/utils/executable.js.map +1 -0
  655. package/dist/server/utils/path.d.ts +5 -0
  656. package/dist/server/utils/path.d.ts.map +1 -0
  657. package/dist/server/utils/path.js +15 -0
  658. package/dist/server/utils/path.js.map +1 -0
  659. package/dist/server/utils/project-icon.d.ts +39 -0
  660. package/dist/server/utils/project-icon.d.ts.map +1 -0
  661. package/dist/server/utils/project-icon.js +389 -0
  662. package/dist/server/utils/project-icon.js.map +1 -0
  663. package/dist/server/utils/spawn.d.ts +13 -0
  664. package/dist/server/utils/spawn.d.ts.map +1 -0
  665. package/dist/server/utils/spawn.js +33 -0
  666. package/dist/server/utils/spawn.js.map +1 -0
  667. package/dist/server/utils/worktree-metadata.d.ts +47 -0
  668. package/dist/server/utils/worktree-metadata.d.ts.map +1 -0
  669. package/dist/server/utils/worktree-metadata.js +116 -0
  670. package/dist/server/utils/worktree-metadata.js.map +1 -0
  671. package/dist/server/utils/worktree.d.ts +144 -0
  672. package/dist/server/utils/worktree.d.ts.map +1 -0
  673. package/dist/server/utils/worktree.js +745 -0
  674. package/dist/server/utils/worktree.js.map +1 -0
  675. package/dist/src/server/pid-lock.js +148 -0
  676. package/dist/src/server/pid-lock.js.map +1 -0
  677. package/dist/src/server/seawork-home.js +19 -0
  678. package/dist/src/server/seawork-home.js.map +1 -0
  679. package/dist/src/server/speech/providers/local/sherpa/sherpa-runtime-env.js +84 -0
  680. package/dist/src/server/speech/providers/local/sherpa/sherpa-runtime-env.js.map +1 -0
  681. package/package.json +117 -0
  682. package/src/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
@@ -0,0 +1,3474 @@
1
+ import { execSync } from "node:child_process";
2
+ import { randomUUID } from "node:crypto";
3
+ import { existsSync } from "node:fs";
4
+ import fs from "node:fs/promises";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ import readline from "node:readline";
8
+ import { z } from "zod";
9
+ import { loadCodexPersistedTimeline } from "./codex-rollout-timeline.js";
10
+ import { mapCodexRolloutToolCall, mapCodexToolCallFromThreadItem, } from "./codex/tool-call-mapper.js";
11
+ import { applyProviderEnv, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
12
+ import { findExecutable } from "../../../utils/executable.js";
13
+ import { spawnProcess } from "../../../utils/spawn.js";
14
+ import { extractCodexTerminalSessionId, nonEmptyString } from "./tool-call-mapper-utils.js";
15
+ import { buildCodexFeatures, codexModelSupportsFastMode } from "./codex-feature-definitions.js";
16
+ import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, resolveBinaryVersion, toDiagnosticErrorMessage, } from "./diagnostic-utils.js";
17
+ const DEFAULT_TIMEOUT_MS = 14 * 24 * 60 * 60 * 1000;
18
+ const TURN_START_TIMEOUT_MS = 90 * 1000;
19
+ const CODEX_PROVIDER = "codex";
20
+ const CODEX_IMAGE_ATTACHMENT_DIR = "seawork-attachments";
21
+ const CODEX_PLAN_IMPLEMENTATION_PROMPT_PREFIX = "The user approved the plan. Implement it now. Do not restate or revise the plan unless blocked.";
22
+ const CODEX_APP_SERVER_CAPABILITIES = {
23
+ supportsStreaming: true,
24
+ supportsSessionPersistence: true,
25
+ supportsDynamicModes: false,
26
+ supportsMcpServers: true,
27
+ supportsReasoningStream: true,
28
+ supportsToolInvocations: true,
29
+ };
30
+ const CODEX_MODES = [
31
+ {
32
+ id: "auto",
33
+ label: "Default Permissions",
34
+ description: "Edit files and run commands with Codex's default approval flow.",
35
+ },
36
+ {
37
+ id: "full-access",
38
+ label: "Full Access",
39
+ description: "Edit files, run commands, and access the network without additional prompts.",
40
+ },
41
+ ];
42
+ const DEFAULT_CODEX_MODE_ID = "auto";
43
+ const MODE_PRESETS = {
44
+ "read-only": {
45
+ approvalPolicy: "on-request",
46
+ sandbox: "read-only",
47
+ },
48
+ auto: {
49
+ approvalPolicy: "on-request",
50
+ sandbox: "workspace-write",
51
+ },
52
+ "full-access": {
53
+ approvalPolicy: "never",
54
+ sandbox: "danger-full-access",
55
+ networkAccess: true,
56
+ },
57
+ };
58
+ function validateCodexMode(modeId) {
59
+ if (!(modeId in MODE_PRESETS)) {
60
+ const validModes = Object.keys(MODE_PRESETS).join(", ");
61
+ throw new Error(`Invalid Codex mode "${modeId}". Valid modes are: ${validModes}`);
62
+ }
63
+ }
64
+ function normalizeCodexThinkingOptionId(thinkingOptionId) {
65
+ if (typeof thinkingOptionId !== "string") {
66
+ return undefined;
67
+ }
68
+ const normalized = thinkingOptionId.trim();
69
+ if (!normalized || normalized === "default") {
70
+ return undefined;
71
+ }
72
+ return normalized;
73
+ }
74
+ function normalizeCodexModelId(modelId) {
75
+ if (typeof modelId !== "string") {
76
+ return undefined;
77
+ }
78
+ const normalized = modelId.trim();
79
+ if (!normalized) {
80
+ return undefined;
81
+ }
82
+ return normalized;
83
+ }
84
+ function normalizeCodexModelLabel(displayName) {
85
+ return displayName.replace(/\bgpt\b/gi, "GPT");
86
+ }
87
+ function isSchemaRecord(value) {
88
+ return typeof value === "object" && value !== null && !Array.isArray(value);
89
+ }
90
+ function isObjectSchemaNode(schema) {
91
+ const type = schema.type;
92
+ return (isSchemaRecord(schema.properties) ||
93
+ type === "object" ||
94
+ (Array.isArray(type) && type.includes("object")));
95
+ }
96
+ function normalizeCodexOutputSchemaNode(schema, path) {
97
+ if (Array.isArray(schema)) {
98
+ return schema.map((entry, index) => normalizeCodexOutputSchemaNode(entry, `${path}[${index}]`));
99
+ }
100
+ if (!isSchemaRecord(schema)) {
101
+ return schema;
102
+ }
103
+ const normalized = {};
104
+ for (const [key, value] of Object.entries(schema)) {
105
+ normalized[key] = normalizeCodexOutputSchemaNode(value, `${path}.${key}`);
106
+ }
107
+ if (!isObjectSchemaNode(normalized)) {
108
+ return normalized;
109
+ }
110
+ if (normalized.additionalProperties === undefined) {
111
+ normalized.additionalProperties = false;
112
+ }
113
+ else if (normalized.additionalProperties !== false) {
114
+ throw new Error(`Codex structured outputs require ${path} to set additionalProperties to false for object schemas.`);
115
+ }
116
+ const properties = isSchemaRecord(normalized.properties) ? normalized.properties : null;
117
+ if (!properties) {
118
+ return normalized;
119
+ }
120
+ const propertyKeys = Object.keys(properties);
121
+ const existingRequired = Array.isArray(normalized.required)
122
+ ? normalized.required.filter((entry) => typeof entry === "string")
123
+ : [];
124
+ normalized.required = Array.from(new Set([...existingRequired, ...propertyKeys]));
125
+ return normalized;
126
+ }
127
+ function normalizeCodexOutputSchema(schema) {
128
+ if (!isSchemaRecord(schema)) {
129
+ throw new Error("Codex structured outputs require a JSON object schema.");
130
+ }
131
+ const normalized = normalizeCodexOutputSchemaNode(schema, "$");
132
+ if (!isSchemaRecord(normalized) || !isObjectSchemaNode(normalized)) {
133
+ throw new Error("Codex structured outputs require a root object schema.");
134
+ }
135
+ return normalized;
136
+ }
137
+ function mergeCodexConfiguredDefaults(primary, fallback) {
138
+ return {
139
+ model: primary.model ?? fallback.model,
140
+ thinkingOptionId: primary.thinkingOptionId ?? fallback.thinkingOptionId,
141
+ };
142
+ }
143
+ async function resolveCodexBinary() {
144
+ const found = await findExecutable("codex");
145
+ if (found) {
146
+ return found;
147
+ }
148
+ throw new Error("Codex binary not found. Install the Codex CLI (https://github.com/openai/codex) and ensure it is available in your shell PATH.");
149
+ }
150
+ async function resolveCodexLaunchPrefix(runtimeSettings) {
151
+ return resolveProviderCommandPrefix(runtimeSettings?.command, resolveCodexBinary);
152
+ }
153
+ function resolveCodexHomeDir() {
154
+ return process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
155
+ }
156
+ function tokenizeCommandArgs(args) {
157
+ const tokens = [];
158
+ let current = "";
159
+ let quote = null;
160
+ for (let i = 0; i < args.length; i += 1) {
161
+ const ch = args[i];
162
+ if (quote) {
163
+ if (ch === quote) {
164
+ quote = null;
165
+ continue;
166
+ }
167
+ if (ch === "\\" && i + 1 < args.length) {
168
+ const next = args[i + 1];
169
+ if (next === quote || next === "\\" || next === "n" || next === "t") {
170
+ i += 1;
171
+ current += next === "n" ? "\n" : next === "t" ? "\t" : next;
172
+ continue;
173
+ }
174
+ }
175
+ current += ch;
176
+ continue;
177
+ }
178
+ if (ch === "'" || ch === '"') {
179
+ quote = ch;
180
+ continue;
181
+ }
182
+ if (/\s/.test(ch)) {
183
+ if (current) {
184
+ tokens.push(current);
185
+ current = "";
186
+ }
187
+ continue;
188
+ }
189
+ current += ch;
190
+ }
191
+ if (current) {
192
+ tokens.push(current);
193
+ }
194
+ return tokens;
195
+ }
196
+ function parseFrontMatter(markdown) {
197
+ const lines = markdown.split("\n");
198
+ if (lines[0]?.trim() !== "---") {
199
+ return { frontMatter: {}, body: markdown };
200
+ }
201
+ let end = -1;
202
+ for (let i = 1; i < lines.length; i += 1) {
203
+ if (lines[i]?.trim() === "---") {
204
+ end = i;
205
+ break;
206
+ }
207
+ }
208
+ if (end === -1) {
209
+ return { frontMatter: {}, body: markdown };
210
+ }
211
+ const metaLines = lines.slice(1, end);
212
+ const body = lines.slice(end + 1).join("\n");
213
+ const frontMatter = {};
214
+ for (const line of metaLines) {
215
+ const trimmed = line.trim();
216
+ if (!trimmed || trimmed.startsWith("#")) {
217
+ continue;
218
+ }
219
+ const idx = trimmed.indexOf(":");
220
+ if (idx <= 0) {
221
+ continue;
222
+ }
223
+ const key = trimmed.slice(0, idx).trim();
224
+ let value = trimmed.slice(idx + 1).trim();
225
+ value = value.replace(/^['"]/, "").replace(/['"]$/, "");
226
+ if (key && value) {
227
+ frontMatter[key] = value;
228
+ }
229
+ }
230
+ return { frontMatter, body };
231
+ }
232
+ async function listCodexCustomPrompts() {
233
+ const codexHome = resolveCodexHomeDir();
234
+ const promptsDir = path.join(codexHome, "prompts");
235
+ let entries;
236
+ try {
237
+ entries = await fs.readdir(promptsDir, { withFileTypes: true });
238
+ }
239
+ catch {
240
+ return [];
241
+ }
242
+ const commands = [];
243
+ for (const entry of entries) {
244
+ if (!entry.isFile()) {
245
+ continue;
246
+ }
247
+ if (!entry.name.endsWith(".md")) {
248
+ continue;
249
+ }
250
+ const name = entry.name.slice(0, -".md".length);
251
+ if (!name) {
252
+ continue;
253
+ }
254
+ const fullPath = path.join(promptsDir, entry.name);
255
+ let content;
256
+ try {
257
+ content = await fs.readFile(fullPath, "utf8");
258
+ }
259
+ catch {
260
+ continue;
261
+ }
262
+ const parsed = parseFrontMatter(content);
263
+ const description = parsed.frontMatter["description"] ?? "Custom prompt";
264
+ const argumentHint = parsed.frontMatter["argument-hint"] ?? parsed.frontMatter["argument_hint"] ?? "";
265
+ commands.push({
266
+ name: `prompts:${name}`,
267
+ description,
268
+ argumentHint,
269
+ });
270
+ }
271
+ return commands.sort((a, b) => a.name.localeCompare(b.name));
272
+ }
273
+ async function listCodexSkills(cwd) {
274
+ const candidates = [];
275
+ candidates.push(path.join(cwd, ".codex", "skills"));
276
+ const repoRoot = (() => {
277
+ try {
278
+ const output = execSync("git rev-parse --show-toplevel", {
279
+ cwd,
280
+ encoding: "utf8",
281
+ stdio: ["ignore", "pipe", "ignore"],
282
+ });
283
+ const trimmed = output.trim();
284
+ return trimmed ? trimmed : null;
285
+ }
286
+ catch {
287
+ return null;
288
+ }
289
+ })();
290
+ if (repoRoot) {
291
+ candidates.push(path.join(path.dirname(cwd), ".codex", "skills"));
292
+ candidates.push(path.join(repoRoot, ".codex", "skills"));
293
+ }
294
+ candidates.push(path.join(resolveCodexHomeDir(), "skills"));
295
+ const commandsByName = new Map();
296
+ for (const dir of candidates) {
297
+ let entries;
298
+ try {
299
+ entries = await fs.readdir(dir, { withFileTypes: true });
300
+ }
301
+ catch {
302
+ continue;
303
+ }
304
+ for (const entry of entries) {
305
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) {
306
+ continue;
307
+ }
308
+ const skillDir = path.join(dir, entry.name);
309
+ const skillPath = path.join(skillDir, "SKILL.md");
310
+ let content;
311
+ try {
312
+ content = await fs.readFile(skillPath, "utf8");
313
+ }
314
+ catch {
315
+ continue;
316
+ }
317
+ const { frontMatter } = parseFrontMatter(content);
318
+ const name = frontMatter["name"];
319
+ const description = frontMatter["description"];
320
+ if (!name || !description) {
321
+ continue;
322
+ }
323
+ if (!commandsByName.has(name)) {
324
+ commandsByName.set(name, {
325
+ name,
326
+ description,
327
+ argumentHint: "",
328
+ });
329
+ }
330
+ }
331
+ }
332
+ return Array.from(commandsByName.values()).sort((a, b) => a.name.localeCompare(b.name));
333
+ }
334
+ function escapeRegExp(value) {
335
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
336
+ }
337
+ function expandCodexCustomPrompt(template, args) {
338
+ const trimmedArgs = args ? args.trim() : "";
339
+ const tokens = trimmedArgs ? tokenizeCommandArgs(trimmedArgs) : [];
340
+ const named = {};
341
+ const positional = [];
342
+ for (const token of tokens) {
343
+ const idx = token.indexOf("=");
344
+ if (idx > 0) {
345
+ const key = token.slice(0, idx);
346
+ const value = token.slice(idx + 1);
347
+ if (key) {
348
+ named[key] = value;
349
+ continue;
350
+ }
351
+ }
352
+ positional.push(token);
353
+ }
354
+ const dollarPlaceholder = "__CODEX_DOLLAR_PLACEHOLDER__";
355
+ let out = template.split("$$").join(dollarPlaceholder);
356
+ out = out.split("$ARGUMENTS").join(trimmedArgs);
357
+ for (let i = 1; i <= 9; i += 1) {
358
+ const value = positional[i - 1] ?? "";
359
+ out = out.split(`$${i}`).join(value);
360
+ }
361
+ const namedKeys = Object.keys(named).sort((a, b) => b.length - a.length);
362
+ for (const key of namedKeys) {
363
+ const value = named[key] ?? "";
364
+ const re = new RegExp(`\\$${escapeRegExp(key)}\\b`, "g");
365
+ out = out.replace(re, value);
366
+ }
367
+ out = out.split(dollarPlaceholder).join("$");
368
+ return out;
369
+ }
370
+ function toCodexMcpConfig(config) {
371
+ switch (config.type) {
372
+ case "stdio":
373
+ return {
374
+ command: config.command,
375
+ args: config.args,
376
+ env: config.env,
377
+ };
378
+ case "http":
379
+ return {
380
+ url: config.url,
381
+ http_headers: config.headers,
382
+ };
383
+ case "sse":
384
+ return {
385
+ url: config.url,
386
+ http_headers: config.headers,
387
+ };
388
+ }
389
+ }
390
+ class CodexAppServerClient {
391
+ constructor(child, logger) {
392
+ this.child = child;
393
+ this.logger = logger;
394
+ this.pending = new Map();
395
+ this.requestHandlers = new Map();
396
+ this.notificationHandler = null;
397
+ this.nextId = 1;
398
+ this.disposed = false;
399
+ this.stderrBuffer = "";
400
+ this.resolveExitPromise = null;
401
+ this.rl = readline.createInterface({ input: child.stdout });
402
+ this.exitPromise = new Promise((resolve) => {
403
+ this.resolveExitPromise = resolve;
404
+ });
405
+ this.rl.on("line", (line) => this.handleLine(line));
406
+ child.stderr.on("data", (chunk) => {
407
+ this.stderrBuffer += chunk.toString();
408
+ if (this.stderrBuffer.length > 8192) {
409
+ this.stderrBuffer = this.stderrBuffer.slice(-8192);
410
+ }
411
+ });
412
+ child.on("error", (err) => {
413
+ this.logger.error({ err }, "Codex app-server child process error");
414
+ for (const pending of this.pending.values()) {
415
+ clearTimeout(pending.timer);
416
+ pending.reject(err);
417
+ }
418
+ this.pending.clear();
419
+ this.disposed = true;
420
+ this.resolveExitPromise?.();
421
+ this.resolveExitPromise = null;
422
+ });
423
+ child.on("exit", (code, signal) => {
424
+ const message = code === 0 && !signal
425
+ ? "Codex app-server exited"
426
+ : `Codex app-server exited with code ${code ?? "null"} and signal ${signal ?? "null"}`;
427
+ const error = new Error(`${message}\n${this.stderrBuffer}`.trim());
428
+ for (const pending of this.pending.values()) {
429
+ clearTimeout(pending.timer);
430
+ pending.reject(error);
431
+ }
432
+ this.pending.clear();
433
+ this.disposed = true;
434
+ this.resolveExitPromise?.();
435
+ this.resolveExitPromise = null;
436
+ });
437
+ }
438
+ setNotificationHandler(handler) {
439
+ this.notificationHandler = handler;
440
+ }
441
+ setRequestHandler(method, handler) {
442
+ this.requestHandlers.set(method, handler);
443
+ }
444
+ request(method, params, timeoutMs = DEFAULT_TIMEOUT_MS) {
445
+ if (this.disposed) {
446
+ return Promise.reject(new Error("Codex app-server client is closed"));
447
+ }
448
+ const id = this.nextId++;
449
+ const payload = { id, method, params };
450
+ const serialized = JSON.stringify(payload);
451
+ this.child.stdin.write(`${serialized}\n`);
452
+ return new Promise((resolve, reject) => {
453
+ const timer = setTimeout(() => {
454
+ this.pending.delete(id);
455
+ reject(new Error(`Codex app-server request timed out for ${method}`));
456
+ }, timeoutMs);
457
+ this.pending.set(id, { resolve, reject, timer });
458
+ });
459
+ }
460
+ notify(method, params) {
461
+ if (this.disposed) {
462
+ return;
463
+ }
464
+ const payload = { method, params };
465
+ this.child.stdin.write(`${JSON.stringify(payload)}\n`);
466
+ }
467
+ writeJsonRpcResponse(response) {
468
+ if (this.disposed || this.child.stdin.destroyed || !this.child.stdin.writable) {
469
+ return;
470
+ }
471
+ try {
472
+ this.child.stdin.write(`${JSON.stringify(response)}\n`);
473
+ }
474
+ catch (error) {
475
+ this.logger.debug({ error }, "Failed to write Codex app-server JSON-RPC response");
476
+ }
477
+ }
478
+ async dispose() {
479
+ if (this.disposed)
480
+ return;
481
+ this.disposed = true;
482
+ this.rl.close();
483
+ try {
484
+ this.child.stdin.end();
485
+ }
486
+ catch {
487
+ // ignore
488
+ }
489
+ terminateChildProcessTree(this.child);
490
+ await this.exitPromise;
491
+ }
492
+ async handleLine(line) {
493
+ if (!line.trim())
494
+ return;
495
+ let msg;
496
+ try {
497
+ msg = JSON.parse(line);
498
+ }
499
+ catch (error) {
500
+ this.logger.warn({ error, line }, "Failed to parse Codex app-server JSON");
501
+ return;
502
+ }
503
+ if (typeof msg.id === "number") {
504
+ const id = msg.id;
505
+ if (msg.result !== undefined || msg.error) {
506
+ const pending = this.pending.get(id);
507
+ if (!pending)
508
+ return;
509
+ clearTimeout(pending.timer);
510
+ this.pending.delete(id);
511
+ if (msg.error) {
512
+ pending.reject(new Error(msg.error?.message ?? "Unknown error"));
513
+ }
514
+ else {
515
+ pending.resolve(msg.result);
516
+ }
517
+ return;
518
+ }
519
+ // Server-initiated request
520
+ if (typeof msg.method === "string") {
521
+ const request = msg;
522
+ const handler = this.requestHandlers.get(request.method);
523
+ try {
524
+ const result = handler ? await handler(request.params) : {};
525
+ this.writeJsonRpcResponse({ id: request.id, result });
526
+ }
527
+ catch (error) {
528
+ this.writeJsonRpcResponse({
529
+ id: request.id,
530
+ error: { message: error instanceof Error ? error.message : String(error) },
531
+ });
532
+ }
533
+ return;
534
+ }
535
+ }
536
+ if (typeof msg.method === "string") {
537
+ const notification = msg;
538
+ this.notificationHandler?.(notification.method, notification.params);
539
+ }
540
+ }
541
+ }
542
+ function terminateChildProcessTree(child) {
543
+ if (child.killed) {
544
+ return;
545
+ }
546
+ if (process.platform !== "win32" && typeof child.pid === "number" && child.pid > 0) {
547
+ try {
548
+ process.kill(-child.pid, "SIGTERM");
549
+ return;
550
+ }
551
+ catch {
552
+ // Fall back to the direct child when no separate process group exists.
553
+ }
554
+ }
555
+ try {
556
+ child.kill("SIGTERM");
557
+ }
558
+ catch {
559
+ // ignore
560
+ }
561
+ }
562
+ function toAgentUsage(tokenUsage) {
563
+ if (!tokenUsage || typeof tokenUsage !== "object")
564
+ return undefined;
565
+ const usage = tokenUsage;
566
+ const contextWindowMaxTokens = typeof usage.model_context_window === "number" &&
567
+ Number.isFinite(usage.model_context_window) &&
568
+ usage.model_context_window > 0
569
+ ? usage.model_context_window
570
+ : typeof usage.modelContextWindow === "number" &&
571
+ Number.isFinite(usage.modelContextWindow) &&
572
+ usage.modelContextWindow > 0
573
+ ? usage.modelContextWindow
574
+ : undefined;
575
+ const contextWindowUsedTokens = typeof usage.last?.total_tokens === "number" &&
576
+ Number.isFinite(usage.last.total_tokens) &&
577
+ usage.last.total_tokens > 0
578
+ ? usage.last.total_tokens
579
+ : typeof usage.last?.totalTokens === "number" &&
580
+ Number.isFinite(usage.last.totalTokens) &&
581
+ usage.last.totalTokens > 0
582
+ ? usage.last.totalTokens
583
+ : undefined;
584
+ return {
585
+ inputTokens: usage.last?.inputTokens,
586
+ cachedInputTokens: usage.last?.cachedInputTokens,
587
+ outputTokens: usage.last?.outputTokens,
588
+ ...(contextWindowMaxTokens !== undefined ? { contextWindowMaxTokens } : {}),
589
+ ...(contextWindowUsedTokens !== undefined ? { contextWindowUsedTokens } : {}),
590
+ };
591
+ }
592
+ function extractUserText(content) {
593
+ if (!Array.isArray(content))
594
+ return null;
595
+ const parts = [];
596
+ for (const item of content) {
597
+ if (item && typeof item === "object") {
598
+ const obj = item;
599
+ if (obj.type === "text" && typeof obj.text === "string") {
600
+ parts.push(obj.text);
601
+ }
602
+ }
603
+ }
604
+ return parts.length > 0 ? parts.join("\n") : null;
605
+ }
606
+ function normalizePlanMarkdown(text) {
607
+ return text
608
+ .split("\n")
609
+ .map((line) => line.replace(/\s+$/, ""))
610
+ .join("\n")
611
+ .trim();
612
+ }
613
+ function planStepsToMarkdown(steps) {
614
+ const lines = steps
615
+ .map((entry) => entry.step.trim())
616
+ .filter((step) => step.length > 0)
617
+ .map((step) => {
618
+ if (/^(#{1,6}\s|[-*+]\s|\d+\.\s)/.test(step)) {
619
+ return step;
620
+ }
621
+ return `- ${step}`;
622
+ });
623
+ return normalizePlanMarkdown(lines.join("\n"));
624
+ }
625
+ function mapCodexPlanToToolCall(params) {
626
+ const text = normalizePlanMarkdown(params.text);
627
+ if (!text) {
628
+ return null;
629
+ }
630
+ return {
631
+ type: "tool_call",
632
+ callId: params.callId,
633
+ name: "plan",
634
+ status: "completed",
635
+ error: null,
636
+ detail: {
637
+ type: "plan",
638
+ text,
639
+ },
640
+ };
641
+ }
642
+ function buildPlanPermissionActions(options) {
643
+ const actions = [
644
+ {
645
+ id: "reject",
646
+ label: "Reject",
647
+ behavior: "deny",
648
+ variant: "danger",
649
+ intent: "dismiss",
650
+ },
651
+ {
652
+ id: "implement",
653
+ label: "Implement",
654
+ behavior: "allow",
655
+ variant: "primary",
656
+ intent: "implement",
657
+ },
658
+ ];
659
+ if (options?.includeResumeAction && options.resumeLabel) {
660
+ actions.push({
661
+ id: "implement_resume",
662
+ label: options.resumeLabel,
663
+ behavior: "allow",
664
+ variant: "secondary",
665
+ intent: "implement_resume",
666
+ });
667
+ }
668
+ return actions;
669
+ }
670
+ function buildCodexPlanImplementationPrompt(planText) {
671
+ const normalizedPlan = normalizePlanMarkdown(planText);
672
+ if (!normalizedPlan) {
673
+ return `${CODEX_PLAN_IMPLEMENTATION_PROMPT_PREFIX} Make the required code changes and verify them.`;
674
+ }
675
+ return [
676
+ CODEX_PLAN_IMPLEMENTATION_PROMPT_PREFIX,
677
+ "Approved plan:",
678
+ normalizedPlan,
679
+ "Carry out the work, make the necessary code changes, and verify the result.",
680
+ ].join("\n\n");
681
+ }
682
+ function normalizeCodexQuestionPrompts(raw) {
683
+ if (!Array.isArray(raw)) {
684
+ return [];
685
+ }
686
+ const questions = [];
687
+ for (const item of raw) {
688
+ if (!item || typeof item !== "object") {
689
+ continue;
690
+ }
691
+ const record = item;
692
+ const id = nonEmptyString(record.id);
693
+ const header = nonEmptyString(record.header);
694
+ const question = nonEmptyString(record.question);
695
+ if (!id || !header || !question) {
696
+ continue;
697
+ }
698
+ const options = Array.isArray(record.options)
699
+ ? record.options.flatMap((option) => {
700
+ if (!option || typeof option !== "object") {
701
+ return [];
702
+ }
703
+ const optionRecord = option;
704
+ const label = nonEmptyString(optionRecord.label);
705
+ if (!label) {
706
+ return [];
707
+ }
708
+ return [
709
+ {
710
+ label,
711
+ ...(typeof optionRecord.description === "string" &&
712
+ optionRecord.description.trim().length > 0
713
+ ? { description: optionRecord.description }
714
+ : {}),
715
+ },
716
+ ];
717
+ })
718
+ : [];
719
+ questions.push({
720
+ id,
721
+ header,
722
+ question,
723
+ options,
724
+ ...(record.multiSelect === true ? { multiSelect: true } : {}),
725
+ ...(record.isOther === true ? { isOther: true } : {}),
726
+ ...(record.isSecret === true ? { isSecret: true } : {}),
727
+ });
728
+ }
729
+ return questions;
730
+ }
731
+ function formatCodexQuestionPrompts(questions) {
732
+ return questions
733
+ .map((question) => {
734
+ const lines = [`${question.header}: ${question.question}`];
735
+ if (question.options.length > 0) {
736
+ lines.push(`Options: ${question.options.map((option) => option.label).join(", ")}`);
737
+ }
738
+ return lines.join("\n");
739
+ })
740
+ .join("\n\n")
741
+ .trim();
742
+ }
743
+ function mapCodexQuestionRequestToToolCall(params) {
744
+ const formattedQuestions = formatCodexQuestionPrompts(params.questions);
745
+ const formattedAnswers = params.answers && Object.keys(params.answers).length > 0
746
+ ? Object.entries(params.answers)
747
+ .map(([id, values]) => `${id}: ${values.join(", ")}`)
748
+ .join("\n")
749
+ : null;
750
+ const detailText = params.status === "completed" && formattedAnswers
751
+ ? [formattedQuestions, "Answers:", formattedAnswers].filter(Boolean).join("\n\n")
752
+ : formattedQuestions;
753
+ const base = {
754
+ type: "tool_call",
755
+ callId: params.callId,
756
+ name: "request_user_input",
757
+ detail: {
758
+ type: "plain_text",
759
+ text: detailText,
760
+ icon: "brain",
761
+ },
762
+ metadata: {
763
+ questions: params.questions,
764
+ ...(params.answers ? { answers: params.answers } : {}),
765
+ },
766
+ };
767
+ if (params.status === "failed") {
768
+ return {
769
+ ...base,
770
+ status: "failed",
771
+ error: params.error ?? { message: "Question dismissed" },
772
+ };
773
+ }
774
+ if (params.status === "canceled") {
775
+ return {
776
+ ...base,
777
+ status: "canceled",
778
+ error: null,
779
+ };
780
+ }
781
+ if (params.status === "running") {
782
+ return {
783
+ ...base,
784
+ status: "running",
785
+ error: null,
786
+ };
787
+ }
788
+ return {
789
+ ...base,
790
+ status: "completed",
791
+ error: null,
792
+ };
793
+ }
794
+ function mapCodexQuestionResponseByHeader(params) {
795
+ if (params.response.behavior !== "allow") {
796
+ return null;
797
+ }
798
+ const answersRecord = params.response.updatedInput && typeof params.response.updatedInput === "object"
799
+ ? params.response.updatedInput.answers
800
+ : undefined;
801
+ if (!answersRecord || typeof answersRecord !== "object") {
802
+ return null;
803
+ }
804
+ const answers = {};
805
+ for (const question of params.questions) {
806
+ const rawAnswer = answersRecord[question.header];
807
+ if (typeof rawAnswer !== "string") {
808
+ continue;
809
+ }
810
+ const normalizedAnswer = rawAnswer.trim();
811
+ if (!normalizedAnswer) {
812
+ continue;
813
+ }
814
+ const values = question.multiSelect
815
+ ? normalizedAnswer
816
+ .split(",")
817
+ .map((entry) => entry.trim())
818
+ .filter((entry) => entry.length > 0)
819
+ : [normalizedAnswer];
820
+ if (values.length > 0) {
821
+ answers[question.id] = { answers: values };
822
+ }
823
+ }
824
+ return Object.keys(answers).length > 0 ? answers : null;
825
+ }
826
+ function extractPatchLikeText(value) {
827
+ if (!value || typeof value !== "object") {
828
+ return undefined;
829
+ }
830
+ const record = value;
831
+ const candidates = [
832
+ record.diff,
833
+ record.patch,
834
+ record.unified_diff,
835
+ record.unifiedDiff,
836
+ record.content,
837
+ record.newString,
838
+ ];
839
+ for (const candidate of candidates) {
840
+ if (typeof candidate === "string" && candidate.length > 0) {
841
+ return candidate;
842
+ }
843
+ }
844
+ return undefined;
845
+ }
846
+ function normalizeCodexThreadItemType(rawType) {
847
+ if (!rawType) {
848
+ return rawType;
849
+ }
850
+ switch (rawType) {
851
+ case "UserMessage":
852
+ return "userMessage";
853
+ case "AgentMessage":
854
+ return "agentMessage";
855
+ case "Reasoning":
856
+ return "reasoning";
857
+ case "Plan":
858
+ return "plan";
859
+ case "CommandExecution":
860
+ return "commandExecution";
861
+ case "FileChange":
862
+ return "fileChange";
863
+ case "McpToolCall":
864
+ return "mcpToolCall";
865
+ case "WebSearch":
866
+ return "webSearch";
867
+ default:
868
+ return rawType;
869
+ }
870
+ }
871
+ function normalizeCodexCommandValue(value) {
872
+ if (typeof value === "string") {
873
+ const trimmed = value.trim();
874
+ if (!trimmed.length) {
875
+ return null;
876
+ }
877
+ const wrapperMatch = trimmed.match(/^(?:\/bin\/)?(?:zsh|bash|sh)\s+-(?:lc|c)\s+([\s\S]+)$/);
878
+ if (!wrapperMatch) {
879
+ return trimmed;
880
+ }
881
+ const candidate = wrapperMatch[1]?.trim() ?? "";
882
+ if (!candidate.length) {
883
+ return trimmed;
884
+ }
885
+ if ((candidate.startsWith('"') && candidate.endsWith('"')) ||
886
+ (candidate.startsWith("'") && candidate.endsWith("'"))) {
887
+ return candidate.slice(1, -1);
888
+ }
889
+ return candidate;
890
+ }
891
+ if (!Array.isArray(value)) {
892
+ return null;
893
+ }
894
+ const parts = value
895
+ .filter((entry) => typeof entry === "string")
896
+ .map((entry) => entry.trim())
897
+ .filter((entry) => entry.length > 0);
898
+ if (parts.length === 0) {
899
+ return null;
900
+ }
901
+ if (parts.length >= 3 && (parts[1] === "-lc" || parts[1] === "-c")) {
902
+ return parts[2] ?? parts;
903
+ }
904
+ return parts;
905
+ }
906
+ function parseCodexPatchChanges(changes) {
907
+ const resolvePathFromRecord = (record) => {
908
+ const directPath = (typeof record.path === "string" && record.path.trim().length > 0
909
+ ? record.path.trim()
910
+ : "") ||
911
+ (typeof record.file_path === "string" && record.file_path.trim().length > 0
912
+ ? record.file_path.trim()
913
+ : "") ||
914
+ (typeof record.filePath === "string" && record.filePath.trim().length > 0
915
+ ? record.filePath.trim()
916
+ : "");
917
+ return directPath;
918
+ };
919
+ if (!changes || typeof changes !== "object") {
920
+ return [];
921
+ }
922
+ if (Array.isArray(changes)) {
923
+ return changes
924
+ .map((entry) => {
925
+ if (!entry || typeof entry !== "object") {
926
+ return null;
927
+ }
928
+ const record = entry;
929
+ const pathValue = resolvePathFromRecord(record);
930
+ if (!pathValue) {
931
+ return null;
932
+ }
933
+ return {
934
+ path: pathValue,
935
+ kind: (typeof record.kind === "string" && record.kind) ||
936
+ (typeof record.type === "string" && record.type) ||
937
+ undefined,
938
+ content: extractPatchLikeText(record),
939
+ };
940
+ })
941
+ .filter((entry) => entry !== null);
942
+ }
943
+ const recordChanges = changes;
944
+ const directPathValue = resolvePathFromRecord(recordChanges);
945
+ if (directPathValue) {
946
+ return [
947
+ {
948
+ path: directPathValue,
949
+ kind: (typeof recordChanges.kind === "string" && recordChanges.kind) ||
950
+ (typeof recordChanges.type === "string" && recordChanges.type) ||
951
+ undefined,
952
+ content: extractPatchLikeText(recordChanges),
953
+ },
954
+ ];
955
+ }
956
+ return Object.entries(recordChanges)
957
+ .map(([path, value]) => {
958
+ const normalizedPath = path.trim();
959
+ if (!normalizedPath) {
960
+ return null;
961
+ }
962
+ return {
963
+ path: normalizedPath,
964
+ kind: value &&
965
+ typeof value === "object" &&
966
+ typeof value.type === "string"
967
+ ? (value.type ?? undefined)
968
+ : undefined,
969
+ content: extractPatchLikeText(value),
970
+ };
971
+ })
972
+ .filter((entry) => entry !== null);
973
+ }
974
+ function codexPatchTextFields(text) {
975
+ if (typeof text !== "string") {
976
+ return {};
977
+ }
978
+ const normalized = text.trimStart();
979
+ const looksLikeUnifiedDiff = normalized.startsWith("diff --git") ||
980
+ normalized.startsWith("@@") ||
981
+ normalized.startsWith("--- ") ||
982
+ normalized.startsWith("+++ ");
983
+ return looksLikeUnifiedDiff ? { patch: text } : { content: text };
984
+ }
985
+ function toRunningToolCall(item) {
986
+ return {
987
+ ...item,
988
+ status: "running",
989
+ error: null,
990
+ };
991
+ }
992
+ function isEditToolCallWithoutContent(item) {
993
+ if (item.type !== "tool_call") {
994
+ return false;
995
+ }
996
+ if (item.detail.type !== "edit") {
997
+ return false;
998
+ }
999
+ const hasDiff = typeof item.detail.unifiedDiff === "string" && item.detail.unifiedDiff.trim().length > 0;
1000
+ const hasNewString = typeof item.detail.newString === "string" && item.detail.newString.trim().length > 0;
1001
+ return !hasDiff && !hasNewString;
1002
+ }
1003
+ function decodeCodexOutputDeltaChunk(chunk) {
1004
+ const trimmed = chunk.trim();
1005
+ if (trimmed.length === 0) {
1006
+ return chunk;
1007
+ }
1008
+ if (!/^[A-Za-z0-9+/=]+$/.test(trimmed) || trimmed.length % 4 !== 0) {
1009
+ return chunk;
1010
+ }
1011
+ try {
1012
+ const decoded = Buffer.from(trimmed, "base64").toString("utf8");
1013
+ if (decoded.length === 0) {
1014
+ return chunk;
1015
+ }
1016
+ const normalizedInput = trimmed.replace(/=+$/, "");
1017
+ const normalizedRoundTrip = Buffer.from(decoded, "utf8").toString("base64").replace(/=+$/, "");
1018
+ return normalizedRoundTrip === normalizedInput ? decoded : chunk;
1019
+ }
1020
+ catch {
1021
+ return chunk;
1022
+ }
1023
+ }
1024
+ function mapCodexExecNotificationToToolCall(params) {
1025
+ const command = normalizeCodexCommandValue(params.command);
1026
+ if (!command) {
1027
+ return null;
1028
+ }
1029
+ const isFailure = params.running
1030
+ ? false
1031
+ : params.success === false || (typeof params.exitCode === "number" && params.exitCode !== 0);
1032
+ const output = params.running
1033
+ ? null
1034
+ : {
1035
+ command,
1036
+ ...(params.output !== null && params.output !== undefined ? { output: params.output } : {}),
1037
+ ...(params.exitCode !== null && params.exitCode !== undefined
1038
+ ? { exitCode: params.exitCode }
1039
+ : {}),
1040
+ };
1041
+ const mapped = mapCodexRolloutToolCall({
1042
+ callId: params.callId ?? null,
1043
+ name: "shell",
1044
+ input: {
1045
+ command,
1046
+ ...(params.cwd ? { cwd: params.cwd } : {}),
1047
+ },
1048
+ output,
1049
+ error: isFailure ? { message: params.stderr?.trim() || "Command failed" } : null,
1050
+ cwd: params.cwd ?? null,
1051
+ });
1052
+ if (!mapped) {
1053
+ return null;
1054
+ }
1055
+ return params.running ? toRunningToolCall(mapped) : mapped;
1056
+ }
1057
+ function mapCodexPatchNotificationToToolCall(params) {
1058
+ const files = parseCodexPatchChanges(params.changes);
1059
+ const firstPath = files[0]?.path;
1060
+ const firstPatchText = files
1061
+ .map((file) => file.content?.trim())
1062
+ .find((value) => typeof value === "string" && value.length > 0);
1063
+ const patchText = firstPatchText;
1064
+ const patchFields = codexPatchTextFields(patchText);
1065
+ const mapped = mapCodexRolloutToolCall({
1066
+ callId: params.callId ?? null,
1067
+ name: "apply_patch",
1068
+ input: firstPath
1069
+ ? {
1070
+ path: firstPath,
1071
+ ...patchFields,
1072
+ files: files.map((file) => ({ path: file.path, kind: file.kind })),
1073
+ }
1074
+ : {
1075
+ changes: params.changes ?? null,
1076
+ ...patchFields,
1077
+ },
1078
+ output: params.running
1079
+ ? null
1080
+ : {
1081
+ ...(files.length > 0
1082
+ ? {
1083
+ files: files.map((file) => ({
1084
+ path: file.path,
1085
+ ...(file.kind ? { kind: file.kind } : {}),
1086
+ ...codexPatchTextFields(file.content ?? patchText),
1087
+ })),
1088
+ }
1089
+ : {}),
1090
+ ...(params.stdout ? { stdout: params.stdout } : {}),
1091
+ ...(params.stderr ? { stderr: params.stderr } : {}),
1092
+ ...(params.success !== null && params.success !== undefined
1093
+ ? { success: params.success }
1094
+ : {}),
1095
+ },
1096
+ error: params.running || params.success !== false
1097
+ ? null
1098
+ : { message: params.stderr?.trim() || "Patch apply failed" },
1099
+ cwd: params.cwd ?? null,
1100
+ });
1101
+ if (!mapped) {
1102
+ return null;
1103
+ }
1104
+ return params.running ? toRunningToolCall(mapped) : mapped;
1105
+ }
1106
+ function mapCodexTerminalInteractionToToolCall(params) {
1107
+ const processId = nonEmptyString(params.processId ?? undefined);
1108
+ const callId = processId
1109
+ ? `terminal-session-${processId}`
1110
+ : (nonEmptyString(params.fallbackCallId ?? undefined) ?? "terminal-interaction");
1111
+ const label = nonEmptyString(params.command ?? undefined);
1112
+ return {
1113
+ type: "tool_call",
1114
+ callId,
1115
+ name: "terminal",
1116
+ status: "completed",
1117
+ error: null,
1118
+ detail: {
1119
+ type: "plain_text",
1120
+ ...(label ? { label } : {}),
1121
+ icon: "square_terminal",
1122
+ },
1123
+ ...(processId ? { metadata: { processId } } : {}),
1124
+ };
1125
+ }
1126
+ function threadItemToTimeline(item, options) {
1127
+ if (!item || typeof item !== "object")
1128
+ return null;
1129
+ const includeUserMessage = options?.includeUserMessage ?? true;
1130
+ const cwd = options?.cwd ?? null;
1131
+ const normalizedType = normalizeCodexThreadItemType(typeof item.type === "string" ? item.type : undefined);
1132
+ const normalizedItem = normalizedType && normalizedType !== item.type
1133
+ ? { ...item, type: normalizedType }
1134
+ : item;
1135
+ switch (normalizedType) {
1136
+ case "userMessage": {
1137
+ if (!includeUserMessage) {
1138
+ return null;
1139
+ }
1140
+ const text = extractUserText(normalizedItem.content) ?? "";
1141
+ return { type: "user_message", text };
1142
+ }
1143
+ case "agentMessage": {
1144
+ return { type: "assistant_message", text: normalizedItem.text ?? "" };
1145
+ }
1146
+ case "plan": {
1147
+ return mapCodexPlanToToolCall({
1148
+ callId: nonEmptyString(normalizedItem.id ?? normalizedItem.itemId ?? undefined) ??
1149
+ `plan:${normalizePlanMarkdown(normalizedItem.text ?? "")}`,
1150
+ text: normalizedItem.text ?? "",
1151
+ });
1152
+ }
1153
+ case "reasoning": {
1154
+ const summary = Array.isArray(normalizedItem.summary)
1155
+ ? normalizedItem.summary.join("\n")
1156
+ : "";
1157
+ const content = Array.isArray(normalizedItem.content)
1158
+ ? normalizedItem.content.join("\n")
1159
+ : "";
1160
+ const text = summary || content;
1161
+ return text ? { type: "reasoning", text } : null;
1162
+ }
1163
+ case "commandExecution":
1164
+ case "fileChange":
1165
+ case "mcpToolCall":
1166
+ case "webSearch":
1167
+ return mapCodexToolCallFromThreadItem(normalizedItem, { cwd });
1168
+ default:
1169
+ return null;
1170
+ }
1171
+ }
1172
+ function toSandboxPolicy(type, networkAccess) {
1173
+ switch (type) {
1174
+ case "read-only":
1175
+ return { type: "readOnly" };
1176
+ case "workspace-write":
1177
+ return { type: "workspaceWrite", networkAccess: networkAccess ?? false };
1178
+ case "danger-full-access":
1179
+ return { type: "dangerFullAccess" };
1180
+ default:
1181
+ return { type: "workspaceWrite", networkAccess: networkAccess ?? false };
1182
+ }
1183
+ }
1184
+ function getImageExtension(mimeType) {
1185
+ switch (mimeType) {
1186
+ case "image/jpeg":
1187
+ return "jpg";
1188
+ case "image/png":
1189
+ return "png";
1190
+ case "image/webp":
1191
+ return "webp";
1192
+ case "image/gif":
1193
+ return "gif";
1194
+ case "image/bmp":
1195
+ return "bmp";
1196
+ case "image/tiff":
1197
+ return "tiff";
1198
+ default:
1199
+ return "bin";
1200
+ }
1201
+ }
1202
+ function normalizeImageData(mimeType, data) {
1203
+ if (data.startsWith("data:")) {
1204
+ const match = data.match(/^data:([^;]+);base64,(.*)$/);
1205
+ if (match) {
1206
+ return { mimeType: match[1], data: match[2] };
1207
+ }
1208
+ }
1209
+ return { mimeType, data };
1210
+ }
1211
+ const ThreadStartedNotificationSchema = z
1212
+ .object({
1213
+ thread: z.object({ id: z.string() }).passthrough(),
1214
+ })
1215
+ .passthrough();
1216
+ const TurnStartedNotificationSchema = z
1217
+ .object({
1218
+ turn: z.object({ id: z.string() }).passthrough(),
1219
+ })
1220
+ .passthrough();
1221
+ const TurnCompletedNotificationSchema = z
1222
+ .object({
1223
+ turn: z
1224
+ .object({
1225
+ status: z.string(),
1226
+ error: z
1227
+ .object({
1228
+ message: z.string().optional(),
1229
+ })
1230
+ .passthrough()
1231
+ .nullable()
1232
+ .optional(),
1233
+ })
1234
+ .passthrough(),
1235
+ })
1236
+ .passthrough();
1237
+ const TurnPlanUpdatedNotificationSchema = z
1238
+ .object({
1239
+ plan: z.array(z
1240
+ .object({
1241
+ step: z.string().optional(),
1242
+ status: z.string().optional(),
1243
+ })
1244
+ .passthrough()),
1245
+ })
1246
+ .passthrough();
1247
+ const TurnDiffUpdatedNotificationSchema = z
1248
+ .object({
1249
+ diff: z.string(),
1250
+ })
1251
+ .passthrough();
1252
+ const ThreadTokenUsageUpdatedNotificationSchema = z
1253
+ .object({
1254
+ tokenUsage: z.unknown(),
1255
+ })
1256
+ .passthrough();
1257
+ const ItemTextDeltaNotificationSchema = z
1258
+ .object({
1259
+ itemId: z.string(),
1260
+ delta: z.string(),
1261
+ })
1262
+ .passthrough();
1263
+ const ItemLifecycleNotificationSchema = z
1264
+ .object({
1265
+ item: z
1266
+ .object({
1267
+ id: z.string().optional(),
1268
+ type: z.string().optional(),
1269
+ })
1270
+ .passthrough(),
1271
+ })
1272
+ .passthrough();
1273
+ const CodexEventTurnAbortedNotificationSchema = z
1274
+ .object({
1275
+ msg: z
1276
+ .object({
1277
+ type: z.literal("turn_aborted"),
1278
+ reason: z.string().optional(),
1279
+ })
1280
+ .passthrough(),
1281
+ })
1282
+ .passthrough();
1283
+ const CodexEventTaskCompleteNotificationSchema = z
1284
+ .object({
1285
+ msg: z
1286
+ .object({
1287
+ type: z.literal("task_complete"),
1288
+ })
1289
+ .passthrough(),
1290
+ })
1291
+ .passthrough();
1292
+ const CodexEventItemLifecycleNotificationSchema = z
1293
+ .object({
1294
+ msg: z
1295
+ .object({
1296
+ type: z.enum(["item_started", "item_completed"]),
1297
+ item: z
1298
+ .object({
1299
+ id: z.string().optional(),
1300
+ type: z.string().optional(),
1301
+ })
1302
+ .passthrough(),
1303
+ })
1304
+ .passthrough(),
1305
+ })
1306
+ .passthrough();
1307
+ const CodexEventExecCommandBeginNotificationSchema = z
1308
+ .object({
1309
+ msg: z
1310
+ .object({
1311
+ type: z.literal("exec_command_begin"),
1312
+ call_id: z.string().optional(),
1313
+ command: z.unknown().optional(),
1314
+ cwd: z.string().optional(),
1315
+ })
1316
+ .passthrough(),
1317
+ })
1318
+ .passthrough();
1319
+ const CodexEventExecCommandEndNotificationSchema = z
1320
+ .object({
1321
+ msg: z
1322
+ .object({
1323
+ type: z.literal("exec_command_end"),
1324
+ call_id: z.string().optional(),
1325
+ command: z.unknown().optional(),
1326
+ cwd: z.string().optional(),
1327
+ stdout: z.string().optional(),
1328
+ stderr: z.string().optional(),
1329
+ aggregated_output: z.string().optional(),
1330
+ aggregatedOutput: z.string().optional(),
1331
+ formatted_output: z.string().optional(),
1332
+ exit_code: z.number().nullable().optional(),
1333
+ exitCode: z.number().nullable().optional(),
1334
+ success: z.boolean().optional(),
1335
+ })
1336
+ .passthrough(),
1337
+ })
1338
+ .passthrough();
1339
+ const CodexEventExecCommandOutputDeltaNotificationSchema = z
1340
+ .object({
1341
+ msg: z
1342
+ .object({
1343
+ type: z.literal("exec_command_output_delta"),
1344
+ call_id: z.string().optional(),
1345
+ stream: z.string().optional(),
1346
+ chunk: z.string().optional(),
1347
+ delta: z.string().optional(),
1348
+ })
1349
+ .passthrough(),
1350
+ })
1351
+ .passthrough();
1352
+ const CodexEventTerminalInteractionNotificationSchema = z
1353
+ .object({
1354
+ msg: z
1355
+ .object({
1356
+ type: z.literal("terminal_interaction"),
1357
+ call_id: z.string().optional(),
1358
+ process_id: z.union([z.string(), z.number()]).optional(),
1359
+ stdin: z.string().optional(),
1360
+ })
1361
+ .passthrough(),
1362
+ })
1363
+ .passthrough();
1364
+ const ItemCommandExecutionTerminalInteractionNotificationSchema = z
1365
+ .object({
1366
+ itemId: z.string().optional(),
1367
+ processId: z.union([z.string(), z.number()]).optional(),
1368
+ stdin: z.string().optional(),
1369
+ })
1370
+ .passthrough();
1371
+ const CodexEventPatchApplyBeginNotificationSchema = z
1372
+ .object({
1373
+ msg: z
1374
+ .object({
1375
+ type: z.literal("patch_apply_begin"),
1376
+ call_id: z.string().optional(),
1377
+ changes: z.unknown().optional(),
1378
+ })
1379
+ .passthrough(),
1380
+ })
1381
+ .passthrough();
1382
+ const CodexEventPatchApplyEndNotificationSchema = z
1383
+ .object({
1384
+ msg: z
1385
+ .object({
1386
+ type: z.literal("patch_apply_end"),
1387
+ call_id: z.string().optional(),
1388
+ changes: z.unknown().optional(),
1389
+ stdout: z.string().optional(),
1390
+ stderr: z.string().optional(),
1391
+ success: z.boolean().optional(),
1392
+ })
1393
+ .passthrough(),
1394
+ })
1395
+ .passthrough();
1396
+ const ItemFileChangeOutputDeltaNotificationSchema = z
1397
+ .object({
1398
+ itemId: z.string(),
1399
+ delta: z.string().optional(),
1400
+ chunk: z.string().optional(),
1401
+ })
1402
+ .passthrough();
1403
+ const CodexEventTurnDiffNotificationSchema = z
1404
+ .object({
1405
+ msg: z
1406
+ .object({
1407
+ type: z.literal("turn_diff"),
1408
+ unified_diff: z.string().optional(),
1409
+ diff: z.string().optional(),
1410
+ })
1411
+ .passthrough(),
1412
+ })
1413
+ .passthrough();
1414
+ const CodexNotificationSchema = z.union([
1415
+ z
1416
+ .object({ method: z.literal("thread/started"), params: ThreadStartedNotificationSchema })
1417
+ .transform(({ params }) => ({
1418
+ kind: "thread_started",
1419
+ threadId: params.thread.id,
1420
+ })),
1421
+ z.object({ method: z.literal("thread/started"), params: z.unknown() }).transform(({ method, params }) => ({
1422
+ kind: "invalid_payload",
1423
+ method,
1424
+ params,
1425
+ })),
1426
+ z
1427
+ .object({ method: z.literal("turn/started"), params: TurnStartedNotificationSchema })
1428
+ .transform(({ params }) => ({ kind: "turn_started", turnId: params.turn.id })),
1429
+ z.object({ method: z.literal("turn/started"), params: z.unknown() }).transform(({ method, params }) => ({
1430
+ kind: "invalid_payload",
1431
+ method,
1432
+ params,
1433
+ })),
1434
+ z
1435
+ .object({ method: z.literal("turn/completed"), params: TurnCompletedNotificationSchema })
1436
+ .transform(({ params }) => ({
1437
+ kind: "turn_completed",
1438
+ status: params.turn.status,
1439
+ errorMessage: params.turn.error?.message ?? null,
1440
+ })),
1441
+ z.object({ method: z.literal("turn/completed"), params: z.unknown() }).transform(({ method, params }) => ({
1442
+ kind: "invalid_payload",
1443
+ method,
1444
+ params,
1445
+ })),
1446
+ z
1447
+ .object({ method: z.literal("turn/plan/updated"), params: TurnPlanUpdatedNotificationSchema })
1448
+ .transform(({ params }) => ({
1449
+ kind: "plan_updated",
1450
+ plan: params.plan.map((entry) => ({
1451
+ step: entry.step ?? null,
1452
+ status: entry.status ?? null,
1453
+ })),
1454
+ })),
1455
+ z.object({ method: z.literal("turn/plan/updated"), params: z.unknown() }).transform(({ method, params }) => ({
1456
+ kind: "invalid_payload",
1457
+ method,
1458
+ params,
1459
+ })),
1460
+ z
1461
+ .object({ method: z.literal("turn/diff/updated"), params: TurnDiffUpdatedNotificationSchema })
1462
+ .transform(({ params }) => ({ kind: "diff_updated", diff: params.diff })),
1463
+ z.object({ method: z.literal("turn/diff/updated"), params: z.unknown() }).transform(({ method, params }) => ({
1464
+ kind: "invalid_payload",
1465
+ method,
1466
+ params,
1467
+ })),
1468
+ z
1469
+ .object({
1470
+ method: z.literal("thread/tokenUsage/updated"),
1471
+ params: ThreadTokenUsageUpdatedNotificationSchema,
1472
+ })
1473
+ .transform(({ params }) => ({
1474
+ kind: "token_usage_updated",
1475
+ tokenUsage: params.tokenUsage,
1476
+ })),
1477
+ z.object({ method: z.literal("thread/tokenUsage/updated"), params: z.unknown() }).transform(({ method, params }) => ({
1478
+ kind: "invalid_payload",
1479
+ method,
1480
+ params,
1481
+ })),
1482
+ z
1483
+ .object({
1484
+ method: z.literal("item/agentMessage/delta"),
1485
+ params: ItemTextDeltaNotificationSchema,
1486
+ })
1487
+ .transform(({ params }) => ({
1488
+ kind: "agent_message_delta",
1489
+ itemId: params.itemId,
1490
+ delta: params.delta,
1491
+ })),
1492
+ z.object({ method: z.literal("item/agentMessage/delta"), params: z.unknown() }).transform(({ method, params }) => ({
1493
+ kind: "invalid_payload",
1494
+ method,
1495
+ params,
1496
+ })),
1497
+ z
1498
+ .object({
1499
+ method: z.literal("item/reasoning/summaryTextDelta"),
1500
+ params: ItemTextDeltaNotificationSchema,
1501
+ })
1502
+ .transform(({ params }) => ({
1503
+ kind: "reasoning_delta",
1504
+ itemId: params.itemId,
1505
+ delta: params.delta,
1506
+ })),
1507
+ z.object({ method: z.literal("item/reasoning/summaryTextDelta"), params: z.unknown() }).transform(({ method, params }) => ({
1508
+ kind: "invalid_payload",
1509
+ method,
1510
+ params,
1511
+ })),
1512
+ z
1513
+ .object({ method: z.literal("item/completed"), params: ItemLifecycleNotificationSchema })
1514
+ .transform(({ params }) => ({
1515
+ kind: "item_completed",
1516
+ source: "item",
1517
+ item: params.item,
1518
+ })),
1519
+ z.object({ method: z.literal("item/completed"), params: z.unknown() }).transform(({ method, params }) => ({
1520
+ kind: "invalid_payload",
1521
+ method,
1522
+ params,
1523
+ })),
1524
+ z
1525
+ .object({ method: z.literal("item/started"), params: ItemLifecycleNotificationSchema })
1526
+ .transform(({ params }) => ({
1527
+ kind: "item_started",
1528
+ source: "item",
1529
+ item: params.item,
1530
+ })),
1531
+ z.object({ method: z.literal("item/started"), params: z.unknown() }).transform(({ method, params }) => ({
1532
+ kind: "invalid_payload",
1533
+ method,
1534
+ params,
1535
+ })),
1536
+ z
1537
+ .object({
1538
+ method: z.literal("codex/event/item_started"),
1539
+ params: CodexEventItemLifecycleNotificationSchema,
1540
+ })
1541
+ .transform(({ params }) => ({
1542
+ kind: "item_started",
1543
+ source: "codex_event",
1544
+ item: params.msg.item,
1545
+ })),
1546
+ z.object({ method: z.literal("codex/event/item_started"), params: z.unknown() }).transform(({ method, params }) => ({
1547
+ kind: "invalid_payload",
1548
+ method,
1549
+ params,
1550
+ })),
1551
+ z
1552
+ .object({
1553
+ method: z.literal("codex/event/item_completed"),
1554
+ params: CodexEventItemLifecycleNotificationSchema,
1555
+ })
1556
+ .transform(({ params }) => ({
1557
+ kind: "item_completed",
1558
+ source: "codex_event",
1559
+ item: params.msg.item,
1560
+ })),
1561
+ z.object({ method: z.literal("codex/event/item_completed"), params: z.unknown() }).transform(({ method, params }) => ({
1562
+ kind: "invalid_payload",
1563
+ method,
1564
+ params,
1565
+ })),
1566
+ z
1567
+ .object({
1568
+ method: z.literal("codex/event/exec_command_begin"),
1569
+ params: CodexEventExecCommandBeginNotificationSchema,
1570
+ })
1571
+ .transform(({ params }) => ({
1572
+ kind: "exec_command_started",
1573
+ callId: params.msg.call_id ?? null,
1574
+ command: params.msg.command ?? null,
1575
+ cwd: params.msg.cwd ?? null,
1576
+ })),
1577
+ z.object({ method: z.literal("codex/event/exec_command_begin"), params: z.unknown() }).transform(({ method, params }) => ({
1578
+ kind: "invalid_payload",
1579
+ method,
1580
+ params,
1581
+ })),
1582
+ z
1583
+ .object({
1584
+ method: z.literal("codex/event/exec_command_end"),
1585
+ params: CodexEventExecCommandEndNotificationSchema,
1586
+ })
1587
+ .transform(({ params }) => ({
1588
+ kind: "exec_command_completed",
1589
+ callId: params.msg.call_id ?? null,
1590
+ command: params.msg.command ?? null,
1591
+ cwd: params.msg.cwd ?? null,
1592
+ output: params.msg.aggregated_output ??
1593
+ params.msg.aggregatedOutput ??
1594
+ params.msg.formatted_output ??
1595
+ params.msg.stdout ??
1596
+ null,
1597
+ exitCode: params.msg.exit_code ?? params.msg.exitCode ?? null,
1598
+ success: params.msg.success ?? null,
1599
+ stderr: params.msg.stderr ?? null,
1600
+ })),
1601
+ z.object({ method: z.literal("codex/event/exec_command_end"), params: z.unknown() }).transform(({ method, params }) => ({
1602
+ kind: "invalid_payload",
1603
+ method,
1604
+ params,
1605
+ })),
1606
+ z
1607
+ .object({
1608
+ method: z.literal("codex/event/exec_command_output_delta"),
1609
+ params: CodexEventExecCommandOutputDeltaNotificationSchema,
1610
+ })
1611
+ .transform(({ params }) => ({
1612
+ kind: "exec_command_output_delta",
1613
+ callId: params.msg.call_id ?? null,
1614
+ stream: params.msg.stream ?? null,
1615
+ chunk: params.msg.chunk ?? params.msg.delta ?? null,
1616
+ })),
1617
+ z
1618
+ .object({
1619
+ method: z.literal("codex/event/exec_command_output_delta"),
1620
+ params: z.unknown(),
1621
+ })
1622
+ .transform(({ method, params }) => ({
1623
+ kind: "invalid_payload",
1624
+ method,
1625
+ params,
1626
+ })),
1627
+ z
1628
+ .object({
1629
+ method: z.literal("codex/event/terminal_interaction"),
1630
+ params: CodexEventTerminalInteractionNotificationSchema,
1631
+ })
1632
+ .transform(({ params }) => ({
1633
+ kind: "terminal_interaction",
1634
+ source: "codex_event",
1635
+ callId: params.msg.call_id ?? null,
1636
+ processId: typeof params.msg.process_id === "number"
1637
+ ? String(params.msg.process_id)
1638
+ : (params.msg.process_id ?? null),
1639
+ stdin: params.msg.stdin ?? null,
1640
+ })),
1641
+ z
1642
+ .object({ method: z.literal("codex/event/terminal_interaction"), params: z.unknown() })
1643
+ .transform(({ method, params }) => ({
1644
+ kind: "invalid_payload",
1645
+ method,
1646
+ params,
1647
+ })),
1648
+ z
1649
+ .object({
1650
+ method: z.literal("item/commandExecution/terminalInteraction"),
1651
+ params: ItemCommandExecutionTerminalInteractionNotificationSchema,
1652
+ })
1653
+ .transform(({ params }) => ({
1654
+ kind: "terminal_interaction",
1655
+ source: "item",
1656
+ callId: params.itemId ?? null,
1657
+ processId: typeof params.processId === "number"
1658
+ ? String(params.processId)
1659
+ : (params.processId ?? null),
1660
+ stdin: params.stdin ?? null,
1661
+ })),
1662
+ z
1663
+ .object({
1664
+ method: z.literal("item/commandExecution/terminalInteraction"),
1665
+ params: z.unknown(),
1666
+ })
1667
+ .transform(({ method, params }) => ({
1668
+ kind: "invalid_payload",
1669
+ method,
1670
+ params,
1671
+ })),
1672
+ z
1673
+ .object({
1674
+ method: z.literal("codex/event/patch_apply_begin"),
1675
+ params: CodexEventPatchApplyBeginNotificationSchema,
1676
+ })
1677
+ .transform(({ params }) => ({
1678
+ kind: "patch_apply_started",
1679
+ callId: params.msg.call_id ?? null,
1680
+ changes: params.msg.changes ?? null,
1681
+ })),
1682
+ z.object({ method: z.literal("codex/event/patch_apply_begin"), params: z.unknown() }).transform(({ method, params }) => ({
1683
+ kind: "invalid_payload",
1684
+ method,
1685
+ params,
1686
+ })),
1687
+ z
1688
+ .object({
1689
+ method: z.literal("codex/event/patch_apply_end"),
1690
+ params: CodexEventPatchApplyEndNotificationSchema,
1691
+ })
1692
+ .transform(({ params }) => ({
1693
+ kind: "patch_apply_completed",
1694
+ callId: params.msg.call_id ?? null,
1695
+ changes: params.msg.changes ?? null,
1696
+ stdout: params.msg.stdout ?? null,
1697
+ stderr: params.msg.stderr ?? null,
1698
+ success: params.msg.success ?? null,
1699
+ })),
1700
+ z.object({ method: z.literal("codex/event/patch_apply_end"), params: z.unknown() }).transform(({ method, params }) => ({
1701
+ kind: "invalid_payload",
1702
+ method,
1703
+ params,
1704
+ })),
1705
+ z
1706
+ .object({
1707
+ method: z.literal("item/fileChange/outputDelta"),
1708
+ params: ItemFileChangeOutputDeltaNotificationSchema,
1709
+ })
1710
+ .transform(({ params }) => ({
1711
+ kind: "file_change_output_delta",
1712
+ itemId: params.itemId,
1713
+ delta: params.delta ?? params.chunk ?? null,
1714
+ })),
1715
+ z.object({ method: z.literal("item/fileChange/outputDelta"), params: z.unknown() }).transform(({ method, params }) => ({
1716
+ kind: "invalid_payload",
1717
+ method,
1718
+ params,
1719
+ })),
1720
+ z
1721
+ .object({
1722
+ method: z.literal("codex/event/turn_diff"),
1723
+ params: CodexEventTurnDiffNotificationSchema,
1724
+ })
1725
+ .transform(({ params }) => ({
1726
+ kind: "diff_updated",
1727
+ diff: params.msg.unified_diff ?? params.msg.diff ?? "",
1728
+ })),
1729
+ z.object({ method: z.literal("codex/event/turn_diff"), params: z.unknown() }).transform(({ method, params }) => ({
1730
+ kind: "invalid_payload",
1731
+ method,
1732
+ params,
1733
+ })),
1734
+ z
1735
+ .object({
1736
+ method: z.literal("codex/event/turn_aborted"),
1737
+ params: CodexEventTurnAbortedNotificationSchema,
1738
+ })
1739
+ .transform(() => ({
1740
+ kind: "turn_completed",
1741
+ status: "interrupted",
1742
+ errorMessage: null,
1743
+ })),
1744
+ z.object({ method: z.literal("codex/event/turn_aborted"), params: z.unknown() }).transform(({ method, params }) => ({
1745
+ kind: "invalid_payload",
1746
+ method,
1747
+ params,
1748
+ })),
1749
+ z
1750
+ .object({
1751
+ method: z.literal("codex/event/task_complete"),
1752
+ params: CodexEventTaskCompleteNotificationSchema,
1753
+ })
1754
+ .transform(() => ({
1755
+ kind: "turn_completed",
1756
+ status: "completed",
1757
+ errorMessage: null,
1758
+ })),
1759
+ z.object({ method: z.literal("codex/event/task_complete"), params: z.unknown() }).transform(({ method, params }) => ({
1760
+ kind: "invalid_payload",
1761
+ method,
1762
+ params,
1763
+ })),
1764
+ z
1765
+ .object({ method: z.string(), params: z.unknown() })
1766
+ .transform(({ method, params }) => ({ kind: "unknown_method", method, params })),
1767
+ ]);
1768
+ async function writeImageAttachment(mimeType, data) {
1769
+ const attachmentsDir = path.join(os.tmpdir(), CODEX_IMAGE_ATTACHMENT_DIR);
1770
+ await fs.mkdir(attachmentsDir, { recursive: true });
1771
+ const normalized = normalizeImageData(mimeType, data);
1772
+ const extension = getImageExtension(normalized.mimeType);
1773
+ const filename = `${randomUUID()}.${extension}`;
1774
+ const filePath = path.join(attachmentsDir, filename);
1775
+ await fs.writeFile(filePath, Buffer.from(normalized.data, "base64"));
1776
+ return filePath;
1777
+ }
1778
+ async function readCodexConfiguredDefaults(client, logger) {
1779
+ let savedConfigDefaults = {};
1780
+ try {
1781
+ const response = (await client.request("getUserSavedConfig", {}));
1782
+ savedConfigDefaults = {
1783
+ model: normalizeCodexModelId(response?.config?.model),
1784
+ thinkingOptionId: normalizeCodexThinkingOptionId(response?.config?.modelReasoningEffort ?? null),
1785
+ };
1786
+ }
1787
+ catch (error) {
1788
+ logger.debug({ error }, "Failed to read Codex saved config defaults");
1789
+ }
1790
+ if (savedConfigDefaults.model && savedConfigDefaults.thinkingOptionId) {
1791
+ return savedConfigDefaults;
1792
+ }
1793
+ let configReadDefaults = {};
1794
+ try {
1795
+ const response = (await client.request("config/read", {}));
1796
+ configReadDefaults = {
1797
+ model: normalizeCodexModelId(response?.config?.model),
1798
+ thinkingOptionId: normalizeCodexThinkingOptionId(response?.config?.model_reasoning_effort ?? null),
1799
+ };
1800
+ }
1801
+ catch (error) {
1802
+ logger.debug({ error }, "Failed to read Codex config defaults");
1803
+ }
1804
+ return mergeCodexConfiguredDefaults(savedConfigDefaults, configReadDefaults);
1805
+ }
1806
+ export async function codexAppServerTurnInputFromPrompt(prompt, logger) {
1807
+ if (typeof prompt === "string") {
1808
+ return [{ type: "text", text: prompt }];
1809
+ }
1810
+ const blocks = prompt;
1811
+ const output = [];
1812
+ for (const block of blocks) {
1813
+ if (!block || typeof block !== "object") {
1814
+ output.push(block);
1815
+ continue;
1816
+ }
1817
+ const record = block;
1818
+ if (record.type === "image" &&
1819
+ typeof record.mimeType === "string" &&
1820
+ typeof record.data === "string") {
1821
+ try {
1822
+ const filePath = await writeImageAttachment(record.mimeType, record.data);
1823
+ output.push({ type: "localImage", path: filePath });
1824
+ }
1825
+ catch (error) {
1826
+ const message = error instanceof Error ? error.message : String(error);
1827
+ logger.warn({ message }, "Failed to write Codex image attachment");
1828
+ output.push({
1829
+ type: "text",
1830
+ text: `User attached image (failed to write temp file): ${message}`,
1831
+ });
1832
+ }
1833
+ continue;
1834
+ }
1835
+ output.push(block);
1836
+ }
1837
+ return output;
1838
+ }
1839
+ function buildCodexAppServerEnv(runtimeSettings, launchEnv) {
1840
+ const env = applyProviderEnv(process.env, runtimeSettings);
1841
+ if (!launchEnv) {
1842
+ return env;
1843
+ }
1844
+ return {
1845
+ ...env,
1846
+ ...launchEnv,
1847
+ };
1848
+ }
1849
+ function buildCodexAppServerInitializeParams() {
1850
+ return {
1851
+ clientInfo: {
1852
+ name: "seawork",
1853
+ title: "Seawork",
1854
+ version: "0.0.0",
1855
+ },
1856
+ capabilities: {
1857
+ experimentalApi: true,
1858
+ },
1859
+ };
1860
+ }
1861
+ class CodexAppServerAgentSession {
1862
+ constructor(config, resumeHandle, logger, spawnAppServer) {
1863
+ this.resumeHandle = resumeHandle;
1864
+ this.spawnAppServer = spawnAppServer;
1865
+ this.provider = CODEX_PROVIDER;
1866
+ this.capabilities = CODEX_APP_SERVER_CAPABILITIES;
1867
+ this.currentThreadId = null;
1868
+ this.currentTurnId = null;
1869
+ this.client = null;
1870
+ this.subscribers = new Set();
1871
+ this.nextTurnOrdinal = 0;
1872
+ this.activeForegroundTurnId = null;
1873
+ this.cachedRuntimeInfo = null;
1874
+ this.serviceTier = null;
1875
+ this.planModeEnabled = false;
1876
+ this.historyPending = false;
1877
+ this.persistedHistory = [];
1878
+ this.pendingPermissions = new Map();
1879
+ this.pendingPermissionHandlers = new Map();
1880
+ this.resolvedPermissionRequests = new Set();
1881
+ this.pendingAgentMessages = new Map();
1882
+ this.pendingReasoning = new Map();
1883
+ this.pendingCommandOutputDeltas = new Map();
1884
+ this.pendingFileChangeOutputDeltas = new Map();
1885
+ this.terminalCommandByProcessId = new Map();
1886
+ this.pendingUnlabeledTerminalInteractions = new Set();
1887
+ this.emittedTerminalInteractionKeys = new Set();
1888
+ this.emittedExecCommandStartedCallIds = new Set();
1889
+ this.emittedExecCommandCompletedCallIds = new Set();
1890
+ this.emittedItemStartedIds = new Set();
1891
+ this.emittedItemCompletedIds = new Set();
1892
+ this.warnedUnknownNotificationMethods = new Set();
1893
+ this.warnedInvalidNotificationPayloads = new Set();
1894
+ this.warnedIncompleteEditToolCallIds = new Set();
1895
+ this.latestPlanResult = null;
1896
+ this.connected = false;
1897
+ this.collaborationModes = [];
1898
+ this.resolvedCollaborationMode = null;
1899
+ this.cachedSkills = [];
1900
+ this.logger = logger.child({ module: "agent", provider: CODEX_PROVIDER });
1901
+ if (config.modeId === undefined) {
1902
+ throw new Error("Codex agent requires modeId to be specified");
1903
+ }
1904
+ validateCodexMode(config.modeId);
1905
+ this.currentMode = config.modeId;
1906
+ this.config = config;
1907
+ this.config.thinkingOptionId = normalizeCodexThinkingOptionId(this.config.thinkingOptionId);
1908
+ if (this.config.featureValues?.fast_mode) {
1909
+ this.serviceTier = "fast";
1910
+ }
1911
+ if (this.config.featureValues?.plan_mode) {
1912
+ this.planModeEnabled = true;
1913
+ }
1914
+ if (this.resumeHandle?.sessionId) {
1915
+ this.currentThreadId = this.resumeHandle.sessionId;
1916
+ this.historyPending = true;
1917
+ }
1918
+ }
1919
+ get id() {
1920
+ return this.currentThreadId;
1921
+ }
1922
+ get features() {
1923
+ return buildCodexFeatures({
1924
+ modelId: this.config.model,
1925
+ fastModeEnabled: this.serviceTier === "fast",
1926
+ planModeEnabled: this.planModeEnabled,
1927
+ planModeAvailable: this.hasPlanCollaborationMode(),
1928
+ });
1929
+ }
1930
+ async connect() {
1931
+ if (this.connected)
1932
+ return;
1933
+ const child = await this.spawnAppServer();
1934
+ this.client = new CodexAppServerClient(child, this.logger);
1935
+ this.client.setNotificationHandler((method, params) => this.handleNotification(method, params));
1936
+ this.registerRequestHandlers();
1937
+ await this.client.request("initialize", buildCodexAppServerInitializeParams());
1938
+ this.client.notify("initialized", {});
1939
+ await this.loadCollaborationModes();
1940
+ await this.loadSkills();
1941
+ if (this.currentThreadId) {
1942
+ await this.loadPersistedHistory();
1943
+ await this.ensureThreadLoaded();
1944
+ }
1945
+ this.connected = true;
1946
+ }
1947
+ async loadCollaborationModes() {
1948
+ if (!this.client)
1949
+ return;
1950
+ try {
1951
+ const response = (await this.client.request("collaborationMode/list", {}));
1952
+ const data = Array.isArray(response?.data) ? response.data : [];
1953
+ this.collaborationModes = data.map((entry) => ({
1954
+ name: String(entry.name ?? ""),
1955
+ mode: entry.mode ?? null,
1956
+ model: entry.model ?? null,
1957
+ reasoning_effort: entry.reasoning_effort ?? null,
1958
+ developer_instructions: entry.developer_instructions ?? null,
1959
+ }));
1960
+ }
1961
+ catch (error) {
1962
+ this.logger.trace({ error }, "Failed to load collaboration modes");
1963
+ this.collaborationModes = [];
1964
+ }
1965
+ this.refreshResolvedCollaborationMode();
1966
+ }
1967
+ async loadSkills() {
1968
+ if (!this.client)
1969
+ return;
1970
+ try {
1971
+ const response = (await this.client.request("skills/list", {
1972
+ cwd: [this.config.cwd],
1973
+ }));
1974
+ const entries = Array.isArray(response?.data) ? response.data : [];
1975
+ const skills = [];
1976
+ for (const entry of entries) {
1977
+ const list = Array.isArray(entry.skills) ? entry.skills : [];
1978
+ for (const skill of list) {
1979
+ if (!skill?.name || !skill?.path)
1980
+ continue;
1981
+ skills.push({
1982
+ name: skill.name,
1983
+ description: skill.description ?? skill.shortDescription ?? "Skill",
1984
+ path: skill.path,
1985
+ });
1986
+ }
1987
+ }
1988
+ this.cachedSkills = skills;
1989
+ }
1990
+ catch (error) {
1991
+ this.logger.trace({ error }, "Failed to load skills list");
1992
+ this.cachedSkills = [];
1993
+ }
1994
+ }
1995
+ findCollaborationMode(target) {
1996
+ if (this.collaborationModes.length === 0)
1997
+ return null;
1998
+ const findByName = (predicate) => this.collaborationModes.find((entry) => predicate(entry.name.toLowerCase()));
1999
+ if (target === "plan") {
2000
+ return findByName((name) => name.includes("plan") || name.includes("read")) ?? null;
2001
+ }
2002
+ return (findByName((name) => name.includes("auto") || name.includes("code")) ??
2003
+ this.collaborationModes.find((entry) => {
2004
+ const name = entry.name.toLowerCase();
2005
+ return !name.includes("plan") && !name.includes("read");
2006
+ }) ??
2007
+ this.collaborationModes[0] ??
2008
+ null);
2009
+ }
2010
+ hasPlanCollaborationMode() {
2011
+ return this.findCollaborationMode("plan") !== null;
2012
+ }
2013
+ resolveCollaborationMode() {
2014
+ const match = this.findCollaborationMode(this.planModeEnabled ? "plan" : "code");
2015
+ if (!match)
2016
+ return null;
2017
+ const settings = {};
2018
+ if (match.model)
2019
+ settings.model = match.model;
2020
+ if (match.reasoning_effort)
2021
+ settings.reasoning_effort = match.reasoning_effort;
2022
+ const developerInstructions = [
2023
+ match.developer_instructions?.trim(),
2024
+ this.config.systemPrompt?.trim(),
2025
+ ]
2026
+ .filter((entry) => typeof entry === "string" && entry.length > 0)
2027
+ .join("\n\n");
2028
+ if (developerInstructions)
2029
+ settings.developer_instructions = developerInstructions;
2030
+ if (this.config.model)
2031
+ settings.model = this.config.model;
2032
+ const thinkingOptionId = normalizeCodexThinkingOptionId(this.config.thinkingOptionId);
2033
+ if (thinkingOptionId)
2034
+ settings.reasoning_effort = thinkingOptionId;
2035
+ return { mode: match.mode ?? "code", settings, name: match.name };
2036
+ }
2037
+ refreshResolvedCollaborationMode() {
2038
+ this.resolvedCollaborationMode = this.resolveCollaborationMode();
2039
+ }
2040
+ applyFeatureValue(featureId, value) {
2041
+ this.config.featureValues = {
2042
+ ...(this.config.featureValues ?? {}),
2043
+ [featureId]: value,
2044
+ };
2045
+ if (featureId === "fast_mode") {
2046
+ this.serviceTier = value ? "fast" : null;
2047
+ this.cachedRuntimeInfo = null;
2048
+ return;
2049
+ }
2050
+ this.planModeEnabled = value;
2051
+ this.refreshResolvedCollaborationMode();
2052
+ this.cachedRuntimeInfo = null;
2053
+ }
2054
+ rememberPlanResult(item) {
2055
+ if (item.detail.type !== "plan") {
2056
+ return;
2057
+ }
2058
+ this.latestPlanResult = {
2059
+ callId: item.callId,
2060
+ text: item.detail.text,
2061
+ turnId: this.currentTurnId,
2062
+ };
2063
+ }
2064
+ emitSyntheticPlanApprovalRequest(planText) {
2065
+ const requestId = `permission-${randomUUID()}`;
2066
+ const request = {
2067
+ id: requestId,
2068
+ provider: CODEX_PROVIDER,
2069
+ name: "CodexPlanApproval",
2070
+ kind: "plan",
2071
+ title: "Plan",
2072
+ description: "Review the proposed plan before implementation starts.",
2073
+ input: { plan: planText },
2074
+ actions: buildPlanPermissionActions(),
2075
+ metadata: {
2076
+ planText,
2077
+ source: "codex_plan_approval",
2078
+ },
2079
+ };
2080
+ this.pendingPermissions.set(requestId, request);
2081
+ this.pendingPermissionHandlers.set(requestId, {
2082
+ resolve: () => undefined,
2083
+ kind: "plan",
2084
+ planText,
2085
+ });
2086
+ this.emitEvent({ type: "permission_requested", provider: CODEX_PROVIDER, request });
2087
+ }
2088
+ /**
2089
+ * Prepare the session for plan implementation by disabling plan/fast mode
2090
+ * and returning the implementation prompt. The caller is responsible for
2091
+ * starting the turn through the normal streamAgent path.
2092
+ */
2093
+ preparePlanImplementation(params) {
2094
+ const planText = typeof params.planText === "string" ? normalizePlanMarkdown(params.planText) : "";
2095
+ this.applyFeatureValue("plan_mode", false);
2096
+ this.applyFeatureValue("fast_mode", false);
2097
+ return buildCodexPlanImplementationPrompt(planText);
2098
+ }
2099
+ registerRequestHandlers() {
2100
+ if (!this.client)
2101
+ return;
2102
+ this.client.setRequestHandler("item/commandExecution/requestApproval", (params) => this.handleCommandApprovalRequest(params));
2103
+ this.client.setRequestHandler("item/fileChange/requestApproval", (params) => this.handleFileChangeApprovalRequest(params));
2104
+ this.client.setRequestHandler("item/tool/requestUserInput", (params) => this.handleToolApprovalRequest(params));
2105
+ // Keep the legacy method name for older Codex builds.
2106
+ this.client.setRequestHandler("tool/requestUserInput", (params) => this.handleToolApprovalRequest(params));
2107
+ }
2108
+ async loadPersistedHistory() {
2109
+ if (!this.client || !this.currentThreadId)
2110
+ return;
2111
+ try {
2112
+ let rolloutTimeline = [];
2113
+ try {
2114
+ rolloutTimeline = await loadCodexPersistedTimeline(this.currentThreadId, undefined, this.logger);
2115
+ }
2116
+ catch {
2117
+ rolloutTimeline = [];
2118
+ }
2119
+ const response = (await this.client.request("thread/read", {
2120
+ threadId: this.currentThreadId,
2121
+ includeTurns: true,
2122
+ }));
2123
+ const thread = response?.thread;
2124
+ const threadTimeline = [];
2125
+ if (thread && Array.isArray(thread.turns)) {
2126
+ for (const turn of thread.turns) {
2127
+ const items = Array.isArray(turn.items) ? turn.items : [];
2128
+ for (const item of items) {
2129
+ const timelineItem = threadItemToTimeline(item, {
2130
+ cwd: this.config.cwd ?? null,
2131
+ });
2132
+ if (timelineItem) {
2133
+ if (timelineItem.type === "tool_call") {
2134
+ this.warnOnIncompleteEditToolCall(timelineItem, "thread_read", item);
2135
+ }
2136
+ threadTimeline.push(timelineItem);
2137
+ }
2138
+ }
2139
+ }
2140
+ }
2141
+ const timeline = rolloutTimeline.length > 0 ? rolloutTimeline : threadTimeline;
2142
+ if (timeline.length > 0) {
2143
+ this.persistedHistory = timeline;
2144
+ this.historyPending = true;
2145
+ }
2146
+ }
2147
+ catch (error) {
2148
+ this.logger.warn({ error }, "Failed to load Codex thread history");
2149
+ }
2150
+ }
2151
+ async ensureThreadLoaded() {
2152
+ if (!this.client || !this.currentThreadId)
2153
+ return;
2154
+ try {
2155
+ const loaded = (await this.client.request("thread/loaded/list", {}));
2156
+ const ids = Array.isArray(loaded?.data) ? loaded.data : [];
2157
+ if (ids.includes(this.currentThreadId)) {
2158
+ return;
2159
+ }
2160
+ const params = { threadId: this.currentThreadId };
2161
+ if (this.config.systemPrompt?.trim()) {
2162
+ params.developerInstructions = this.config.systemPrompt.trim();
2163
+ }
2164
+ const codexConfig = this.buildCodexInnerConfig();
2165
+ if (codexConfig) {
2166
+ params.config = codexConfig;
2167
+ }
2168
+ await this.client.request("thread/resume", params);
2169
+ }
2170
+ catch (error) {
2171
+ this.logger.warn({ error }, "Failed to resume Codex thread, starting new thread");
2172
+ this.currentThreadId = null;
2173
+ await this.ensureThread();
2174
+ }
2175
+ }
2176
+ parseSlashCommandInput(text) {
2177
+ const trimmed = text.trim();
2178
+ if (!trimmed.startsWith("/") || trimmed.length <= 1) {
2179
+ return null;
2180
+ }
2181
+ const withoutPrefix = trimmed.slice(1);
2182
+ const firstWhitespaceIdx = withoutPrefix.search(/\s/);
2183
+ const commandName = firstWhitespaceIdx === -1 ? withoutPrefix : withoutPrefix.slice(0, firstWhitespaceIdx);
2184
+ if (!commandName || commandName.includes("/")) {
2185
+ return null;
2186
+ }
2187
+ const rawArgs = firstWhitespaceIdx === -1 ? "" : withoutPrefix.slice(firstWhitespaceIdx + 1).trim();
2188
+ return rawArgs.length > 0 ? { commandName, args: rawArgs } : { commandName };
2189
+ }
2190
+ async resolveSlashCommandInvocation(prompt) {
2191
+ if (typeof prompt !== "string") {
2192
+ return null;
2193
+ }
2194
+ const parsed = this.parseSlashCommandInput(prompt);
2195
+ if (!parsed) {
2196
+ return null;
2197
+ }
2198
+ try {
2199
+ const commands = await this.listCommands();
2200
+ return commands.some((command) => command.name === parsed.commandName) ? parsed : null;
2201
+ }
2202
+ catch (error) {
2203
+ this.logger.warn({ err: error, commandName: parsed.commandName }, "Failed to resolve slash command; falling back to plain prompt input");
2204
+ return null;
2205
+ }
2206
+ }
2207
+ async buildCommandPromptInput(commandName, args) {
2208
+ if (commandName.startsWith("prompts:")) {
2209
+ const promptName = commandName.slice("prompts:".length);
2210
+ const codexHome = resolveCodexHomeDir();
2211
+ const promptPath = path.join(codexHome, "prompts", `${promptName}.md`);
2212
+ const raw = await fs.readFile(promptPath, "utf8");
2213
+ const parsed = parseFrontMatter(raw);
2214
+ return expandCodexCustomPrompt(parsed.body, args);
2215
+ }
2216
+ if (!this.connected) {
2217
+ await this.connect();
2218
+ }
2219
+ else {
2220
+ await this.loadSkills();
2221
+ }
2222
+ const skill = this.cachedSkills.find((entry) => entry.name === commandName);
2223
+ if (skill) {
2224
+ const input = [
2225
+ { type: "skill", name: skill.name, path: skill.path },
2226
+ ];
2227
+ if (args && args.trim().length > 0) {
2228
+ input.push({ type: "text", text: args.trim() });
2229
+ }
2230
+ else {
2231
+ input.push({ type: "text", text: `$${skill.name}` });
2232
+ }
2233
+ return input;
2234
+ }
2235
+ return args ? `$${commandName} ${args}` : `$${commandName}`;
2236
+ }
2237
+ async run(prompt, options) {
2238
+ const timeline = [];
2239
+ let finalText = "";
2240
+ let usage;
2241
+ let turnId = null;
2242
+ const bufferedEvents = [];
2243
+ let settled = false;
2244
+ let resolveCompletion;
2245
+ let rejectCompletion;
2246
+ const processEvent = (event) => {
2247
+ if (settled) {
2248
+ return;
2249
+ }
2250
+ const eventTurnId = event.turnId;
2251
+ if (turnId && eventTurnId && eventTurnId !== turnId) {
2252
+ return;
2253
+ }
2254
+ if (event.type === "timeline") {
2255
+ timeline.push(event.item);
2256
+ if (event.item.type === "assistant_message") {
2257
+ finalText = event.item.text;
2258
+ }
2259
+ else if (event.item.type === "tool_call" && event.item.detail.type === "plan") {
2260
+ finalText = event.item.detail.text;
2261
+ }
2262
+ return;
2263
+ }
2264
+ if (event.type === "turn_completed") {
2265
+ usage = event.usage;
2266
+ settled = true;
2267
+ resolveCompletion();
2268
+ return;
2269
+ }
2270
+ if (event.type === "turn_failed") {
2271
+ settled = true;
2272
+ rejectCompletion(new Error(event.error));
2273
+ return;
2274
+ }
2275
+ if (event.type === "turn_canceled") {
2276
+ settled = true;
2277
+ resolveCompletion();
2278
+ }
2279
+ };
2280
+ const completion = new Promise((resolve, reject) => {
2281
+ resolveCompletion = resolve;
2282
+ rejectCompletion = reject;
2283
+ });
2284
+ const unsubscribe = this.subscribe((event) => {
2285
+ if (!turnId) {
2286
+ bufferedEvents.push(event);
2287
+ return;
2288
+ }
2289
+ processEvent(event);
2290
+ });
2291
+ try {
2292
+ const result = await this.startTurn(prompt, options);
2293
+ turnId = result.turnId;
2294
+ for (const event of bufferedEvents) {
2295
+ processEvent(event);
2296
+ }
2297
+ if (!settled) {
2298
+ await completion;
2299
+ }
2300
+ }
2301
+ finally {
2302
+ unsubscribe();
2303
+ }
2304
+ const info = await this.getRuntimeInfo();
2305
+ return {
2306
+ sessionId: info.sessionId ?? "",
2307
+ finalText,
2308
+ usage,
2309
+ timeline,
2310
+ };
2311
+ }
2312
+ async startTurn(prompt, options) {
2313
+ if (this.activeForegroundTurnId) {
2314
+ throw new Error("A foreground turn is already active");
2315
+ }
2316
+ await this.connect();
2317
+ if (!this.client) {
2318
+ throw new Error("Codex client not initialized");
2319
+ }
2320
+ const slashCommand = await this.resolveSlashCommandInvocation(prompt);
2321
+ const effectivePrompt = slashCommand
2322
+ ? await this.buildCommandPromptInput(slashCommand.commandName, slashCommand.args)
2323
+ : prompt;
2324
+ if (this.currentThreadId) {
2325
+ await this.ensureThreadLoaded();
2326
+ }
2327
+ else {
2328
+ await this.ensureThread();
2329
+ }
2330
+ const input = await this.buildUserInput(effectivePrompt);
2331
+ const preset = MODE_PRESETS[this.currentMode] ?? MODE_PRESETS[DEFAULT_CODEX_MODE_ID];
2332
+ const approvalPolicy = this.config.approvalPolicy ?? preset.approvalPolicy;
2333
+ const sandboxPolicyType = this.config.sandboxMode ?? preset.sandbox;
2334
+ const params = {
2335
+ threadId: this.currentThreadId,
2336
+ input,
2337
+ approvalPolicy,
2338
+ sandboxPolicy: toSandboxPolicy(sandboxPolicyType, typeof this.config.networkAccess === "boolean"
2339
+ ? this.config.networkAccess
2340
+ : preset.networkAccess),
2341
+ };
2342
+ if (this.config.model) {
2343
+ params.model = this.config.model;
2344
+ }
2345
+ const thinkingOptionId = normalizeCodexThinkingOptionId(this.config.thinkingOptionId);
2346
+ if (thinkingOptionId) {
2347
+ params.effort = thinkingOptionId;
2348
+ }
2349
+ if (this.serviceTier) {
2350
+ params.serviceTier = this.serviceTier;
2351
+ }
2352
+ if (this.resolvedCollaborationMode) {
2353
+ params.collaborationMode = {
2354
+ mode: this.resolvedCollaborationMode.mode,
2355
+ settings: this.resolvedCollaborationMode.settings,
2356
+ };
2357
+ }
2358
+ if (this.config.cwd) {
2359
+ params.cwd = this.config.cwd;
2360
+ }
2361
+ if (options?.outputSchema) {
2362
+ params.outputSchema = normalizeCodexOutputSchema(options.outputSchema);
2363
+ }
2364
+ if (this.config.systemPrompt?.trim()) {
2365
+ params.developerInstructions = this.config.systemPrompt.trim();
2366
+ }
2367
+ const codexConfig = this.buildCodexInnerConfig();
2368
+ if (codexConfig) {
2369
+ params.config = codexConfig;
2370
+ }
2371
+ const turnId = this.createTurnId();
2372
+ this.activeForegroundTurnId = turnId;
2373
+ try {
2374
+ await this.client.request("turn/start", params, TURN_START_TIMEOUT_MS);
2375
+ }
2376
+ catch (error) {
2377
+ this.activeForegroundTurnId = null;
2378
+ throw error;
2379
+ }
2380
+ return { turnId };
2381
+ }
2382
+ subscribe(callback) {
2383
+ this.subscribers.add(callback);
2384
+ return () => {
2385
+ this.subscribers.delete(callback);
2386
+ };
2387
+ }
2388
+ async *streamHistory() {
2389
+ if (!this.historyPending || this.persistedHistory.length === 0) {
2390
+ return;
2391
+ }
2392
+ const history = this.persistedHistory;
2393
+ this.persistedHistory = [];
2394
+ this.historyPending = false;
2395
+ for (const item of history) {
2396
+ yield { type: "timeline", provider: CODEX_PROVIDER, item };
2397
+ }
2398
+ }
2399
+ async getRuntimeInfo() {
2400
+ if (this.cachedRuntimeInfo)
2401
+ return { ...this.cachedRuntimeInfo };
2402
+ if (!this.connected) {
2403
+ await this.connect();
2404
+ }
2405
+ if (!this.currentThreadId) {
2406
+ await this.ensureThread();
2407
+ }
2408
+ const info = {
2409
+ provider: CODEX_PROVIDER,
2410
+ sessionId: this.currentThreadId,
2411
+ model: this.config.model ?? null,
2412
+ thinkingOptionId: normalizeCodexThinkingOptionId(this.config.thinkingOptionId) ?? null,
2413
+ modeId: this.currentMode ?? null,
2414
+ extra: this.resolvedCollaborationMode
2415
+ ? { collaborationMode: this.resolvedCollaborationMode.name }
2416
+ : undefined,
2417
+ };
2418
+ this.cachedRuntimeInfo = info;
2419
+ return { ...info };
2420
+ }
2421
+ async getAvailableModes() {
2422
+ return CODEX_MODES;
2423
+ }
2424
+ async getCurrentMode() {
2425
+ return this.currentMode ?? null;
2426
+ }
2427
+ async setMode(modeId) {
2428
+ validateCodexMode(modeId);
2429
+ this.currentMode = modeId;
2430
+ this.cachedRuntimeInfo = null;
2431
+ }
2432
+ async setModel(modelId) {
2433
+ this.config.model = modelId ?? undefined;
2434
+ if (!codexModelSupportsFastMode(this.config.model)) {
2435
+ this.serviceTier = null;
2436
+ }
2437
+ this.refreshResolvedCollaborationMode();
2438
+ this.cachedRuntimeInfo = null;
2439
+ }
2440
+ async setThinkingOption(thinkingOptionId) {
2441
+ this.config.thinkingOptionId = normalizeCodexThinkingOptionId(thinkingOptionId);
2442
+ this.refreshResolvedCollaborationMode();
2443
+ this.cachedRuntimeInfo = null;
2444
+ }
2445
+ async setFeature(featureId, value) {
2446
+ if (featureId === "fast_mode") {
2447
+ this.applyFeatureValue("fast_mode", Boolean(value));
2448
+ return;
2449
+ }
2450
+ if (featureId === "plan_mode") {
2451
+ this.applyFeatureValue("plan_mode", Boolean(value));
2452
+ return;
2453
+ }
2454
+ throw new Error(`Unknown Codex feature: ${featureId}`);
2455
+ }
2456
+ getPendingPermissions() {
2457
+ return Array.from(this.pendingPermissions.values());
2458
+ }
2459
+ async respondToPermission(requestId, response) {
2460
+ const pending = this.pendingPermissionHandlers.get(requestId);
2461
+ if (!pending) {
2462
+ throw new Error(`No pending Codex app-server permission request with id '${requestId}'`);
2463
+ }
2464
+ const pendingRequest = this.pendingPermissions.get(requestId) ?? null;
2465
+ if (pending.kind === "plan") {
2466
+ let followUpPrompt;
2467
+ if (response.behavior === "allow") {
2468
+ followUpPrompt = this.preparePlanImplementation({
2469
+ planText: pending.planText ?? pendingRequest?.metadata?.planText,
2470
+ });
2471
+ }
2472
+ this.pendingPermissionHandlers.delete(requestId);
2473
+ this.pendingPermissions.delete(requestId);
2474
+ this.resolvedPermissionRequests.add(requestId);
2475
+ this.emitEvent({
2476
+ type: "permission_resolved",
2477
+ provider: CODEX_PROVIDER,
2478
+ requestId,
2479
+ resolution: response,
2480
+ });
2481
+ if (followUpPrompt) {
2482
+ return { followUpPrompt };
2483
+ }
2484
+ return;
2485
+ }
2486
+ this.pendingPermissionHandlers.delete(requestId);
2487
+ this.pendingPermissions.delete(requestId);
2488
+ this.resolvedPermissionRequests.add(requestId);
2489
+ if (response.behavior === "deny" && pendingRequest?.kind === "tool") {
2490
+ const fallbackName = pendingRequest.name === "CodexBash"
2491
+ ? "shell"
2492
+ : pendingRequest.name === "CodexFileChange"
2493
+ ? "apply_patch"
2494
+ : pendingRequest.name;
2495
+ this.emitEvent({
2496
+ type: "timeline",
2497
+ provider: CODEX_PROVIDER,
2498
+ item: {
2499
+ type: "tool_call",
2500
+ callId: requestId,
2501
+ name: fallbackName,
2502
+ status: "failed",
2503
+ error: { message: response.message ?? "Permission denied" },
2504
+ detail: pendingRequest.detail ?? {
2505
+ type: "unknown",
2506
+ input: pendingRequest.input ?? null,
2507
+ output: null,
2508
+ },
2509
+ metadata: {
2510
+ permissionRequestId: requestId,
2511
+ denied: true,
2512
+ },
2513
+ },
2514
+ });
2515
+ }
2516
+ this.emitEvent({
2517
+ type: "permission_resolved",
2518
+ provider: CODEX_PROVIDER,
2519
+ requestId,
2520
+ resolution: response,
2521
+ });
2522
+ if (pending.kind === "command") {
2523
+ const decision = response.behavior === "allow" ? "accept" : response.interrupt ? "cancel" : "decline";
2524
+ pending.resolve({ decision });
2525
+ return;
2526
+ }
2527
+ if (pending.kind === "file") {
2528
+ const decision = response.behavior === "allow" ? "accept" : response.interrupt ? "cancel" : "decline";
2529
+ pending.resolve({ decision });
2530
+ return;
2531
+ }
2532
+ const questions = pending.questions ?? [];
2533
+ const itemId = typeof pendingRequest?.metadata?.itemId === "string"
2534
+ ? pendingRequest.metadata.itemId
2535
+ : requestId;
2536
+ if (response.behavior === "allow") {
2537
+ const mappedAnswers = mapCodexQuestionResponseByHeader({
2538
+ questions,
2539
+ response,
2540
+ });
2541
+ const answers = mappedAnswers ??
2542
+ Object.fromEntries(questions
2543
+ .map((question) => {
2544
+ const fallback = question.options[0]?.label?.trim();
2545
+ return fallback ? [question.id, { answers: [fallback] }] : null;
2546
+ })
2547
+ .filter((entry) => entry !== null));
2548
+ this.emitEvent({
2549
+ type: "timeline",
2550
+ provider: CODEX_PROVIDER,
2551
+ item: mapCodexQuestionRequestToToolCall({
2552
+ callId: itemId,
2553
+ questions,
2554
+ status: "completed",
2555
+ answers: Object.fromEntries(Object.entries(answers).map(([id, value]) => [id, value.answers])),
2556
+ }),
2557
+ });
2558
+ pending.resolve({ answers });
2559
+ return;
2560
+ }
2561
+ this.emitEvent({
2562
+ type: "timeline",
2563
+ provider: CODEX_PROVIDER,
2564
+ item: mapCodexQuestionRequestToToolCall({
2565
+ callId: itemId,
2566
+ questions,
2567
+ status: response.interrupt ? "canceled" : "failed",
2568
+ error: { message: response.message ?? "Question dismissed" },
2569
+ }),
2570
+ });
2571
+ pending.resolve({ answers: {} });
2572
+ }
2573
+ describePersistence() {
2574
+ if (!this.currentThreadId)
2575
+ return null;
2576
+ const thinkingOptionId = normalizeCodexThinkingOptionId(this.config.thinkingOptionId) ?? null;
2577
+ return {
2578
+ provider: CODEX_PROVIDER,
2579
+ sessionId: this.currentThreadId,
2580
+ nativeHandle: this.currentThreadId,
2581
+ metadata: {
2582
+ provider: CODEX_PROVIDER,
2583
+ cwd: this.config.cwd,
2584
+ title: this.config.title ?? null,
2585
+ threadId: this.currentThreadId,
2586
+ modeId: this.currentMode,
2587
+ model: this.config.model ?? null,
2588
+ thinkingOptionId,
2589
+ extra: this.config.extra,
2590
+ systemPrompt: this.config.systemPrompt,
2591
+ mcpServers: this.config.mcpServers,
2592
+ },
2593
+ };
2594
+ }
2595
+ async interrupt() {
2596
+ if (!this.client || !this.currentThreadId || !this.currentTurnId)
2597
+ return;
2598
+ try {
2599
+ await this.client.request("turn/interrupt", {
2600
+ threadId: this.currentThreadId,
2601
+ turnId: this.currentTurnId,
2602
+ });
2603
+ }
2604
+ catch (error) {
2605
+ this.logger.warn({ error }, "Failed to interrupt Codex turn");
2606
+ }
2607
+ }
2608
+ async close() {
2609
+ for (const pending of this.pendingPermissionHandlers.values()) {
2610
+ pending.resolve({ decision: "cancel" });
2611
+ }
2612
+ this.pendingPermissionHandlers.clear();
2613
+ this.pendingPermissions.clear();
2614
+ this.resolvedPermissionRequests.clear();
2615
+ this.subscribers.clear();
2616
+ this.activeForegroundTurnId = null;
2617
+ if (this.client) {
2618
+ await this.client.dispose();
2619
+ }
2620
+ this.client = null;
2621
+ this.connected = false;
2622
+ this.currentThreadId = null;
2623
+ this.currentTurnId = null;
2624
+ }
2625
+ async listCommands() {
2626
+ const prompts = await listCodexCustomPrompts();
2627
+ if (!this.connected) {
2628
+ await this.connect();
2629
+ }
2630
+ else {
2631
+ await this.loadSkills();
2632
+ }
2633
+ const appServerSkills = this.cachedSkills.map((skill) => ({
2634
+ name: skill.name,
2635
+ description: skill.description,
2636
+ argumentHint: "",
2637
+ }));
2638
+ const fallbackSkills = appServerSkills.length === 0 ? await listCodexSkills(this.config.cwd) : [];
2639
+ return [...appServerSkills, ...fallbackSkills, ...prompts].sort((a, b) => a.name.localeCompare(b.name));
2640
+ }
2641
+ async ensureThread() {
2642
+ if (!this.client)
2643
+ return;
2644
+ if (this.currentThreadId)
2645
+ return;
2646
+ // Resolve model + thinking defaults when omitted.
2647
+ let configuredDefaults = {};
2648
+ let model = this.config.model;
2649
+ let thinkingOptionId = normalizeCodexThinkingOptionId(this.config.thinkingOptionId);
2650
+ if (!model || !thinkingOptionId) {
2651
+ configuredDefaults = await readCodexConfiguredDefaults(this.client, this.logger);
2652
+ }
2653
+ if (!model) {
2654
+ model = configuredDefaults.model;
2655
+ }
2656
+ if (!thinkingOptionId) {
2657
+ thinkingOptionId = configuredDefaults.thinkingOptionId;
2658
+ }
2659
+ if (!model || !thinkingOptionId) {
2660
+ const modelResponse = (await this.client.request("model/list", {}));
2661
+ const models = modelResponse?.data ?? [];
2662
+ const defaultModel = models.find((m) => m.isDefault) ?? models[0];
2663
+ if (!defaultModel) {
2664
+ throw new Error("No models available from Codex app-server");
2665
+ }
2666
+ const selectedModel = (model ? models.find((candidate) => candidate.id === model) : undefined) ?? defaultModel;
2667
+ if (!model) {
2668
+ model = selectedModel.id;
2669
+ }
2670
+ if (!thinkingOptionId) {
2671
+ thinkingOptionId = normalizeCodexThinkingOptionId(selectedModel.defaultReasoningEffort);
2672
+ }
2673
+ }
2674
+ this.config.model = model;
2675
+ this.config.thinkingOptionId = thinkingOptionId;
2676
+ const preset = MODE_PRESETS[this.currentMode] ?? MODE_PRESETS[DEFAULT_CODEX_MODE_ID];
2677
+ const approvalPolicy = this.config.approvalPolicy ?? preset.approvalPolicy;
2678
+ const sandbox = this.config.sandboxMode ?? preset.sandbox;
2679
+ const innerConfig = this.buildCodexInnerConfig();
2680
+ const response = (await this.client.request("thread/start", {
2681
+ model,
2682
+ cwd: this.config.cwd ?? null,
2683
+ approvalPolicy,
2684
+ sandbox,
2685
+ ...(this.config.systemPrompt?.trim()
2686
+ ? { developerInstructions: this.config.systemPrompt.trim() }
2687
+ : {}),
2688
+ ...(innerConfig ? { config: innerConfig } : {}),
2689
+ }));
2690
+ const threadId = response?.thread?.id;
2691
+ if (!threadId) {
2692
+ throw new Error("Codex app-server did not return thread id");
2693
+ }
2694
+ this.currentThreadId = threadId;
2695
+ }
2696
+ buildCodexInnerConfig() {
2697
+ const innerConfig = {};
2698
+ if (this.config.mcpServers) {
2699
+ const mcpServers = {};
2700
+ for (const [name, serverConfig] of Object.entries(this.config.mcpServers)) {
2701
+ mcpServers[name] = toCodexMcpConfig(serverConfig);
2702
+ }
2703
+ innerConfig.mcp_servers = mcpServers;
2704
+ }
2705
+ if (this.config.extra?.codex) {
2706
+ Object.assign(innerConfig, this.config.extra.codex);
2707
+ }
2708
+ return Object.keys(innerConfig).length > 0 ? innerConfig : null;
2709
+ }
2710
+ async buildUserInput(prompt) {
2711
+ if (typeof prompt === "string") {
2712
+ return [{ type: "text", text: prompt }];
2713
+ }
2714
+ const blocks = prompt;
2715
+ return await codexAppServerTurnInputFromPrompt(blocks, this.logger);
2716
+ }
2717
+ emitEvent(event) {
2718
+ if (event.type === "timeline") {
2719
+ if (event.item.type === "assistant_message") {
2720
+ this.pendingAgentMessages.clear();
2721
+ }
2722
+ }
2723
+ this.notifySubscribers(event);
2724
+ }
2725
+ notifySubscribers(event) {
2726
+ const turnId = this.activeForegroundTurnId;
2727
+ const tagged = turnId ? { ...event, turnId } : event;
2728
+ for (const callback of this.subscribers) {
2729
+ try {
2730
+ callback(tagged);
2731
+ }
2732
+ catch (error) {
2733
+ this.logger.warn({ err: error }, "Subscriber callback threw");
2734
+ }
2735
+ }
2736
+ }
2737
+ createTurnId() {
2738
+ return `codex-turn-${this.nextTurnOrdinal++}`;
2739
+ }
2740
+ handleNotification(method, params) {
2741
+ const parsed = CodexNotificationSchema.parse({ method, params });
2742
+ if (parsed.kind === "thread_started") {
2743
+ this.currentThreadId = parsed.threadId;
2744
+ this.emitEvent({
2745
+ type: "thread_started",
2746
+ provider: CODEX_PROVIDER,
2747
+ sessionId: parsed.threadId,
2748
+ });
2749
+ return;
2750
+ }
2751
+ if (parsed.kind === "turn_started") {
2752
+ this.currentTurnId = parsed.turnId;
2753
+ this.latestPlanResult = null;
2754
+ this.emittedItemStartedIds.clear();
2755
+ this.emittedItemCompletedIds.clear();
2756
+ this.emittedExecCommandStartedCallIds.clear();
2757
+ this.emittedExecCommandCompletedCallIds.clear();
2758
+ this.pendingCommandOutputDeltas.clear();
2759
+ this.pendingFileChangeOutputDeltas.clear();
2760
+ this.warnedIncompleteEditToolCallIds.clear();
2761
+ this.emitEvent({ type: "turn_started", provider: CODEX_PROVIDER });
2762
+ return;
2763
+ }
2764
+ if (parsed.kind === "turn_completed") {
2765
+ if (parsed.status === "failed") {
2766
+ this.emitEvent({
2767
+ type: "turn_failed",
2768
+ provider: CODEX_PROVIDER,
2769
+ error: parsed.errorMessage ?? "Codex turn failed",
2770
+ });
2771
+ }
2772
+ else if (parsed.status === "interrupted") {
2773
+ this.emitEvent({ type: "turn_canceled", provider: CODEX_PROVIDER, reason: "interrupted" });
2774
+ }
2775
+ else {
2776
+ if (this.planModeEnabled && this.latestPlanResult?.text) {
2777
+ this.emitSyntheticPlanApprovalRequest(this.latestPlanResult.text);
2778
+ }
2779
+ this.emitEvent({
2780
+ type: "turn_completed",
2781
+ provider: CODEX_PROVIDER,
2782
+ usage: this.latestUsage,
2783
+ });
2784
+ }
2785
+ this.activeForegroundTurnId = null;
2786
+ this.latestPlanResult = null;
2787
+ this.emittedItemStartedIds.clear();
2788
+ this.emittedItemCompletedIds.clear();
2789
+ this.emittedExecCommandStartedCallIds.clear();
2790
+ this.emittedExecCommandCompletedCallIds.clear();
2791
+ this.pendingCommandOutputDeltas.clear();
2792
+ this.pendingFileChangeOutputDeltas.clear();
2793
+ this.warnedIncompleteEditToolCallIds.clear();
2794
+ return;
2795
+ }
2796
+ if (parsed.kind === "plan_updated") {
2797
+ const timelineItem = mapCodexPlanToToolCall({
2798
+ callId: `plan:${this.currentTurnId ?? this.currentThreadId ?? "current"}`,
2799
+ text: planStepsToMarkdown(parsed.plan.map((entry) => ({
2800
+ step: entry.step ?? "",
2801
+ status: entry.status ?? "pending",
2802
+ }))),
2803
+ });
2804
+ if (timelineItem) {
2805
+ this.rememberPlanResult(timelineItem);
2806
+ this.emitEvent({
2807
+ type: "timeline",
2808
+ provider: CODEX_PROVIDER,
2809
+ item: timelineItem,
2810
+ });
2811
+ }
2812
+ return;
2813
+ }
2814
+ if (parsed.kind === "diff_updated") {
2815
+ // NOTE: Codex app-server emits frequent `turn/diff/updated` notifications
2816
+ // containing a full accumulated unified diff for the *entire turn*.
2817
+ // This is not a concrete file-change tool call; it is progress telemetry.
2818
+ // We intentionally do NOT store every diff update in the timeline.
2819
+ return;
2820
+ }
2821
+ if (parsed.kind === "token_usage_updated") {
2822
+ this.latestUsage = toAgentUsage(parsed.tokenUsage);
2823
+ if (this.latestUsage) {
2824
+ this.notifySubscribers({
2825
+ type: "usage_updated",
2826
+ provider: CODEX_PROVIDER,
2827
+ usage: this.latestUsage,
2828
+ });
2829
+ }
2830
+ return;
2831
+ }
2832
+ if (parsed.kind === "agent_message_delta") {
2833
+ const prev = this.pendingAgentMessages.get(parsed.itemId) ?? "";
2834
+ this.pendingAgentMessages.set(parsed.itemId, prev + parsed.delta);
2835
+ return;
2836
+ }
2837
+ if (parsed.kind === "reasoning_delta") {
2838
+ const prev = this.pendingReasoning.get(parsed.itemId) ?? [];
2839
+ prev.push(parsed.delta);
2840
+ this.pendingReasoning.set(parsed.itemId, prev);
2841
+ return;
2842
+ }
2843
+ if (parsed.kind === "exec_command_output_delta") {
2844
+ this.appendOutputDeltaChunk(this.pendingCommandOutputDeltas, parsed.callId, parsed.chunk, {
2845
+ decodeBase64: true,
2846
+ });
2847
+ return;
2848
+ }
2849
+ if (parsed.kind === "file_change_output_delta") {
2850
+ this.appendOutputDeltaChunk(this.pendingFileChangeOutputDeltas, parsed.itemId, parsed.delta);
2851
+ return;
2852
+ }
2853
+ if (parsed.kind === "exec_command_started") {
2854
+ if (parsed.callId) {
2855
+ this.emittedExecCommandStartedCallIds.add(parsed.callId);
2856
+ this.pendingCommandOutputDeltas.delete(parsed.callId);
2857
+ }
2858
+ const timelineItem = mapCodexExecNotificationToToolCall({
2859
+ callId: parsed.callId,
2860
+ command: parsed.command,
2861
+ cwd: parsed.cwd ?? this.config.cwd ?? null,
2862
+ running: true,
2863
+ });
2864
+ if (timelineItem) {
2865
+ this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
2866
+ }
2867
+ return;
2868
+ }
2869
+ if (parsed.kind === "exec_command_completed") {
2870
+ const bufferedOutput = this.consumeOutputDelta(this.pendingCommandOutputDeltas, parsed.callId);
2871
+ const resolvedOutput = parsed.output ?? bufferedOutput;
2872
+ this.rememberTerminalProcessForCommand(parsed.command, resolvedOutput);
2873
+ const timelineItem = mapCodexExecNotificationToToolCall({
2874
+ callId: parsed.callId,
2875
+ command: parsed.command,
2876
+ cwd: parsed.cwd ?? this.config.cwd ?? null,
2877
+ output: resolvedOutput,
2878
+ exitCode: parsed.exitCode,
2879
+ success: parsed.success,
2880
+ stderr: parsed.stderr,
2881
+ running: false,
2882
+ });
2883
+ if (timelineItem) {
2884
+ this.emittedExecCommandCompletedCallIds.add(timelineItem.callId);
2885
+ this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
2886
+ }
2887
+ return;
2888
+ }
2889
+ if (parsed.kind === "terminal_interaction") {
2890
+ const interactionKey = [parsed.processId ?? "", parsed.stdin ?? ""].join("\u0000");
2891
+ if (!this.shouldEmitTerminalInteractionKey(interactionKey)) {
2892
+ return;
2893
+ }
2894
+ const command = (parsed.processId ? this.terminalCommandByProcessId.get(parsed.processId) : undefined) ??
2895
+ null;
2896
+ if (!command && parsed.processId) {
2897
+ this.pendingUnlabeledTerminalInteractions.add(parsed.processId);
2898
+ }
2899
+ const timelineItem = mapCodexTerminalInteractionToToolCall({
2900
+ processId: parsed.processId,
2901
+ fallbackCallId: parsed.callId,
2902
+ command,
2903
+ });
2904
+ this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
2905
+ return;
2906
+ }
2907
+ if (parsed.kind === "patch_apply_started") {
2908
+ if (parsed.callId) {
2909
+ this.pendingFileChangeOutputDeltas.delete(parsed.callId);
2910
+ }
2911
+ const timelineItem = mapCodexPatchNotificationToToolCall({
2912
+ callId: parsed.callId,
2913
+ changes: parsed.changes,
2914
+ cwd: this.config.cwd ?? null,
2915
+ running: true,
2916
+ });
2917
+ if (timelineItem) {
2918
+ this.warnOnIncompleteEditToolCall(timelineItem, "patch_apply_started", {
2919
+ callId: parsed.callId,
2920
+ changes: parsed.changes,
2921
+ });
2922
+ this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
2923
+ }
2924
+ return;
2925
+ }
2926
+ if (parsed.kind === "patch_apply_completed") {
2927
+ const bufferedOutput = this.consumeOutputDelta(this.pendingFileChangeOutputDeltas, parsed.callId);
2928
+ const timelineItem = mapCodexPatchNotificationToToolCall({
2929
+ callId: parsed.callId,
2930
+ changes: parsed.changes,
2931
+ cwd: this.config.cwd ?? null,
2932
+ stdout: parsed.stdout ?? bufferedOutput,
2933
+ stderr: parsed.stderr,
2934
+ success: parsed.success,
2935
+ running: false,
2936
+ });
2937
+ if (timelineItem) {
2938
+ this.warnOnIncompleteEditToolCall(timelineItem, "patch_apply_completed", {
2939
+ callId: parsed.callId,
2940
+ changes: parsed.changes,
2941
+ stdout: parsed.stdout,
2942
+ });
2943
+ this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
2944
+ }
2945
+ return;
2946
+ }
2947
+ if (parsed.kind === "item_completed") {
2948
+ // Codex emits mirrored lifecycle notifications via both `codex/event/item_*`
2949
+ // and canonical `item/*`. We render only the canonical channel to avoid
2950
+ // duplicated assistant/reasoning rows.
2951
+ if (parsed.source === "codex_event") {
2952
+ return;
2953
+ }
2954
+ const timelineItem = threadItemToTimeline(parsed.item, {
2955
+ includeUserMessage: false,
2956
+ cwd: this.config.cwd ?? null,
2957
+ });
2958
+ if (timelineItem) {
2959
+ const normalizedItemType = normalizeCodexThreadItemType(typeof parsed.item.type === "string" ? parsed.item.type : undefined);
2960
+ const itemId = parsed.item.id;
2961
+ // For commandExecution items, codex/event/exec_command_* is authoritative.
2962
+ // Keep item/completed as fallback only when no exec_command completion was seen.
2963
+ if (timelineItem.type === "tool_call" && normalizedItemType === "commandExecution") {
2964
+ const callId = timelineItem.callId || itemId;
2965
+ if (callId && this.emittedExecCommandCompletedCallIds.has(callId)) {
2966
+ return;
2967
+ }
2968
+ }
2969
+ if (itemId && this.emittedItemCompletedIds.has(itemId)) {
2970
+ return;
2971
+ }
2972
+ if (timelineItem.type === "assistant_message" && itemId) {
2973
+ const buffered = this.pendingAgentMessages.get(itemId);
2974
+ if (buffered && buffered.length > 0) {
2975
+ timelineItem.text = buffered;
2976
+ }
2977
+ }
2978
+ if (timelineItem.type === "reasoning" && itemId) {
2979
+ const buffered = this.pendingReasoning.get(itemId);
2980
+ if (buffered && buffered.length > 0) {
2981
+ timelineItem.text = buffered.join("");
2982
+ }
2983
+ }
2984
+ if (timelineItem.type === "tool_call") {
2985
+ if (timelineItem.detail.type === "plan") {
2986
+ this.rememberPlanResult(timelineItem);
2987
+ }
2988
+ this.warnOnIncompleteEditToolCall(timelineItem, "item_completed", parsed.item);
2989
+ }
2990
+ this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
2991
+ if (itemId) {
2992
+ this.emittedItemCompletedIds.add(itemId);
2993
+ this.emittedItemStartedIds.delete(itemId);
2994
+ this.pendingCommandOutputDeltas.delete(itemId);
2995
+ this.pendingFileChangeOutputDeltas.delete(itemId);
2996
+ }
2997
+ }
2998
+ return;
2999
+ }
3000
+ if (parsed.kind === "item_started") {
3001
+ if (parsed.source === "codex_event") {
3002
+ return;
3003
+ }
3004
+ const timelineItem = threadItemToTimeline(parsed.item, {
3005
+ includeUserMessage: false,
3006
+ cwd: this.config.cwd ?? null,
3007
+ });
3008
+ if (timelineItem && timelineItem.type === "tool_call") {
3009
+ const normalizedItemType = normalizeCodexThreadItemType(typeof parsed.item.type === "string" ? parsed.item.type : undefined);
3010
+ const itemId = parsed.item.id;
3011
+ if (normalizedItemType === "commandExecution") {
3012
+ const callId = timelineItem.callId || itemId;
3013
+ if (callId && this.emittedExecCommandStartedCallIds.has(callId)) {
3014
+ return;
3015
+ }
3016
+ }
3017
+ if (itemId && this.emittedItemStartedIds.has(itemId)) {
3018
+ return;
3019
+ }
3020
+ this.warnOnIncompleteEditToolCall(timelineItem, "item_started", parsed.item);
3021
+ this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
3022
+ if (itemId) {
3023
+ this.emittedItemStartedIds.add(itemId);
3024
+ this.pendingCommandOutputDeltas.delete(itemId);
3025
+ this.pendingFileChangeOutputDeltas.delete(itemId);
3026
+ }
3027
+ }
3028
+ return;
3029
+ }
3030
+ if (parsed.kind === "invalid_payload") {
3031
+ this.warnInvalidNotificationPayload(parsed.method, parsed.params);
3032
+ return;
3033
+ }
3034
+ this.warnUnknownNotificationMethod(parsed.method, parsed.params);
3035
+ }
3036
+ warnUnknownNotificationMethod(method, params) {
3037
+ if (this.warnedUnknownNotificationMethods.has(method)) {
3038
+ return;
3039
+ }
3040
+ this.warnedUnknownNotificationMethods.add(method);
3041
+ this.logger.trace({ method, params }, "Unhandled Codex app-server notification method");
3042
+ }
3043
+ warnInvalidNotificationPayload(method, params) {
3044
+ const key = method;
3045
+ if (this.warnedInvalidNotificationPayloads.has(key)) {
3046
+ return;
3047
+ }
3048
+ this.warnedInvalidNotificationPayloads.add(key);
3049
+ this.logger.warn({ method, params }, "Invalid Codex app-server notification payload");
3050
+ }
3051
+ appendOutputDeltaChunk(store, id, chunk, options) {
3052
+ if (!id || !chunk) {
3053
+ return;
3054
+ }
3055
+ const normalized = options?.decodeBase64 ? decodeCodexOutputDeltaChunk(chunk) : chunk;
3056
+ if (!normalized.length) {
3057
+ return;
3058
+ }
3059
+ const prev = store.get(id) ?? [];
3060
+ prev.push(normalized);
3061
+ store.set(id, prev);
3062
+ }
3063
+ consumeOutputDelta(store, id) {
3064
+ if (!id) {
3065
+ return null;
3066
+ }
3067
+ const buffered = store.get(id);
3068
+ if (!buffered || buffered.length === 0) {
3069
+ return null;
3070
+ }
3071
+ store.delete(id);
3072
+ return buffered.join("");
3073
+ }
3074
+ rememberTerminalProcessForCommand(command, output) {
3075
+ const normalizedCommand = normalizeCodexCommandValue(command);
3076
+ if (!normalizedCommand) {
3077
+ return;
3078
+ }
3079
+ const displayCommand = typeof normalizedCommand === "string"
3080
+ ? normalizedCommand
3081
+ : normalizedCommand.join(" ").trim();
3082
+ if (!displayCommand) {
3083
+ return;
3084
+ }
3085
+ const processId = extractCodexTerminalSessionId(output ?? undefined);
3086
+ if (!processId) {
3087
+ return;
3088
+ }
3089
+ this.terminalCommandByProcessId.set(processId, displayCommand);
3090
+ if (!this.pendingUnlabeledTerminalInteractions.has(processId)) {
3091
+ return;
3092
+ }
3093
+ this.pendingUnlabeledTerminalInteractions.delete(processId);
3094
+ this.emitEvent({
3095
+ type: "timeline",
3096
+ provider: CODEX_PROVIDER,
3097
+ item: mapCodexTerminalInteractionToToolCall({
3098
+ processId,
3099
+ command: displayCommand,
3100
+ }),
3101
+ });
3102
+ }
3103
+ shouldEmitTerminalInteractionKey(key) {
3104
+ if (this.emittedTerminalInteractionKeys.has(key)) {
3105
+ return false;
3106
+ }
3107
+ this.emittedTerminalInteractionKeys.add(key);
3108
+ return true;
3109
+ }
3110
+ warnOnIncompleteEditToolCall(item, source, payload) {
3111
+ if (!isEditToolCallWithoutContent(item)) {
3112
+ return;
3113
+ }
3114
+ const warnKey = `${source}:${item.callId}`;
3115
+ if (this.warnedIncompleteEditToolCallIds.has(warnKey)) {
3116
+ return;
3117
+ }
3118
+ this.warnedIncompleteEditToolCallIds.add(warnKey);
3119
+ this.logger.warn({
3120
+ source,
3121
+ callId: item.callId,
3122
+ status: item.status,
3123
+ name: item.name,
3124
+ detail: item.detail,
3125
+ payload,
3126
+ }, "Codex edit tool call is missing diff/content fields");
3127
+ }
3128
+ handleCommandApprovalRequest(params) {
3129
+ const parsed = params;
3130
+ const commandPreview = mapCodexExecNotificationToToolCall({
3131
+ callId: parsed.itemId,
3132
+ command: parsed.command,
3133
+ cwd: parsed.cwd ?? this.config.cwd ?? null,
3134
+ running: true,
3135
+ });
3136
+ const requestId = `permission-${parsed.itemId}`;
3137
+ const title = parsed.command ? `Run command: ${parsed.command}` : "Run command";
3138
+ const request = {
3139
+ id: requestId,
3140
+ provider: CODEX_PROVIDER,
3141
+ name: "CodexBash",
3142
+ kind: "tool",
3143
+ title,
3144
+ description: parsed.reason ?? undefined,
3145
+ input: {
3146
+ command: parsed.command ?? undefined,
3147
+ cwd: parsed.cwd ?? undefined,
3148
+ },
3149
+ detail: commandPreview?.detail ?? {
3150
+ type: "unknown",
3151
+ input: {
3152
+ command: parsed.command ?? null,
3153
+ cwd: parsed.cwd ?? null,
3154
+ },
3155
+ output: null,
3156
+ },
3157
+ metadata: {
3158
+ itemId: parsed.itemId,
3159
+ threadId: parsed.threadId,
3160
+ turnId: parsed.turnId,
3161
+ },
3162
+ };
3163
+ this.pendingPermissions.set(requestId, request);
3164
+ this.emitEvent({ type: "permission_requested", provider: CODEX_PROVIDER, request });
3165
+ return new Promise((resolve) => {
3166
+ this.pendingPermissionHandlers.set(requestId, { resolve, kind: "command" });
3167
+ });
3168
+ }
3169
+ handleFileChangeApprovalRequest(params) {
3170
+ const parsed = params;
3171
+ const requestId = `permission-${parsed.itemId}`;
3172
+ const request = {
3173
+ id: requestId,
3174
+ provider: CODEX_PROVIDER,
3175
+ name: "CodexFileChange",
3176
+ kind: "tool",
3177
+ title: "Apply file changes",
3178
+ description: parsed.reason ?? undefined,
3179
+ detail: {
3180
+ type: "unknown",
3181
+ input: {
3182
+ reason: parsed.reason ?? null,
3183
+ },
3184
+ output: null,
3185
+ },
3186
+ metadata: {
3187
+ itemId: parsed.itemId,
3188
+ threadId: parsed.threadId,
3189
+ turnId: parsed.turnId,
3190
+ },
3191
+ };
3192
+ this.pendingPermissions.set(requestId, request);
3193
+ this.emitEvent({ type: "permission_requested", provider: CODEX_PROVIDER, request });
3194
+ return new Promise((resolve) => {
3195
+ this.pendingPermissionHandlers.set(requestId, { resolve, kind: "file" });
3196
+ });
3197
+ }
3198
+ handleToolApprovalRequest(params) {
3199
+ const parsed = params;
3200
+ const requestId = `permission-${parsed.itemId}`;
3201
+ const questions = normalizeCodexQuestionPrompts(parsed.questions);
3202
+ const request = {
3203
+ id: requestId,
3204
+ provider: CODEX_PROVIDER,
3205
+ name: "request_user_input",
3206
+ kind: "question",
3207
+ title: "Question",
3208
+ description: undefined,
3209
+ detail: {
3210
+ type: "plain_text",
3211
+ text: formatCodexQuestionPrompts(questions),
3212
+ icon: "brain",
3213
+ },
3214
+ input: { questions },
3215
+ metadata: {
3216
+ itemId: parsed.itemId,
3217
+ threadId: parsed.threadId,
3218
+ turnId: parsed.turnId,
3219
+ questions,
3220
+ },
3221
+ };
3222
+ this.pendingPermissions.set(requestId, request);
3223
+ this.emitEvent({
3224
+ type: "timeline",
3225
+ provider: CODEX_PROVIDER,
3226
+ item: mapCodexQuestionRequestToToolCall({
3227
+ callId: parsed.itemId,
3228
+ questions,
3229
+ status: "running",
3230
+ }),
3231
+ });
3232
+ this.emitEvent({ type: "permission_requested", provider: CODEX_PROVIDER, request });
3233
+ return new Promise((resolve) => {
3234
+ this.pendingPermissionHandlers.set(requestId, {
3235
+ resolve,
3236
+ kind: "question",
3237
+ questions,
3238
+ });
3239
+ });
3240
+ }
3241
+ }
3242
+ export class CodexAppServerAgentClient {
3243
+ constructor(logger, runtimeSettings) {
3244
+ this.logger = logger;
3245
+ this.runtimeSettings = runtimeSettings;
3246
+ this.provider = CODEX_PROVIDER;
3247
+ this.capabilities = CODEX_APP_SERVER_CAPABILITIES;
3248
+ }
3249
+ async spawnAppServer(launchEnv) {
3250
+ const launchPrefix = await resolveCodexLaunchPrefix(this.runtimeSettings);
3251
+ this.logger.trace({
3252
+ launchPrefix,
3253
+ }, "Spawning Codex app server");
3254
+ return spawnProcess(launchPrefix.command, [...launchPrefix.args, "app-server"], {
3255
+ detached: process.platform !== "win32",
3256
+ stdio: ["pipe", "pipe", "pipe"],
3257
+ env: buildCodexAppServerEnv(this.runtimeSettings, launchEnv),
3258
+ });
3259
+ }
3260
+ async createSession(config, launchContext) {
3261
+ const sessionConfig = { ...config, provider: CODEX_PROVIDER };
3262
+ const session = new CodexAppServerAgentSession(sessionConfig, null, this.logger, () => this.spawnAppServer(launchContext?.env));
3263
+ await session.connect();
3264
+ return session;
3265
+ }
3266
+ async resumeSession(handle, overrides, launchContext) {
3267
+ const storedConfig = (handle.metadata ?? {});
3268
+ const merged = {
3269
+ ...storedConfig,
3270
+ ...overrides,
3271
+ provider: CODEX_PROVIDER,
3272
+ cwd: overrides?.cwd ?? storedConfig.cwd ?? process.cwd(),
3273
+ };
3274
+ const session = new CodexAppServerAgentSession(merged, handle, this.logger, () => this.spawnAppServer(launchContext?.env));
3275
+ await session.connect();
3276
+ return session;
3277
+ }
3278
+ async listPersistedAgents(options) {
3279
+ const child = await this.spawnAppServer();
3280
+ const client = new CodexAppServerClient(child, this.logger);
3281
+ try {
3282
+ await client.request("initialize", buildCodexAppServerInitializeParams());
3283
+ client.notify("initialized", {});
3284
+ const limit = options?.limit ?? 20;
3285
+ const response = (await client.request("thread/list", { limit }));
3286
+ const threads = Array.isArray(response?.data) ? response.data : [];
3287
+ const descriptors = [];
3288
+ for (const thread of threads.slice(0, limit)) {
3289
+ const threadId = thread.id;
3290
+ const cwd = thread.cwd ?? process.cwd();
3291
+ const title = thread.preview ?? null;
3292
+ let timeline = [];
3293
+ try {
3294
+ const rolloutTimeline = await loadCodexPersistedTimeline(threadId, undefined, this.logger);
3295
+ const read = (await client.request("thread/read", {
3296
+ threadId,
3297
+ includeTurns: true,
3298
+ }));
3299
+ const turns = read.thread?.turns ?? [];
3300
+ const itemsFromThreadRead = [];
3301
+ for (const turn of turns) {
3302
+ for (const item of turn.items ?? []) {
3303
+ const timelineItem = threadItemToTimeline(item, { cwd });
3304
+ if (timelineItem)
3305
+ itemsFromThreadRead.push(timelineItem);
3306
+ }
3307
+ }
3308
+ timeline = rolloutTimeline.length > 0 ? rolloutTimeline : itemsFromThreadRead;
3309
+ }
3310
+ catch {
3311
+ timeline = [];
3312
+ }
3313
+ descriptors.push({
3314
+ provider: CODEX_PROVIDER,
3315
+ sessionId: threadId,
3316
+ cwd,
3317
+ title,
3318
+ lastActivityAt: new Date((thread.updatedAt ?? thread.createdAt ?? 0) * 1000),
3319
+ persistence: {
3320
+ provider: CODEX_PROVIDER,
3321
+ sessionId: threadId,
3322
+ nativeHandle: threadId,
3323
+ metadata: {
3324
+ provider: CODEX_PROVIDER,
3325
+ cwd,
3326
+ title,
3327
+ threadId,
3328
+ },
3329
+ },
3330
+ timeline,
3331
+ });
3332
+ }
3333
+ return descriptors;
3334
+ }
3335
+ finally {
3336
+ await client.dispose();
3337
+ }
3338
+ }
3339
+ async listModels(_options) {
3340
+ const child = await this.spawnAppServer();
3341
+ const client = new CodexAppServerClient(child, this.logger);
3342
+ try {
3343
+ await client.request("initialize", buildCodexAppServerInitializeParams());
3344
+ client.notify("initialized", {});
3345
+ const response = (await client.request("model/list", {}));
3346
+ const models = Array.isArray(response?.data) ? response.data : [];
3347
+ const configuredDefaults = await readCodexConfiguredDefaults(client, this.logger);
3348
+ const configuredDefaultModelId = configuredDefaults.model;
3349
+ const configuredDefaultThinkingOptionId = configuredDefaults.thinkingOptionId;
3350
+ const hasConfiguredDefaultModel = typeof configuredDefaultModelId === "string"
3351
+ ? models.some((model) => model?.id === configuredDefaultModelId)
3352
+ : false;
3353
+ return models.map((model) => {
3354
+ const defaultReasoningEffort = normalizeCodexThinkingOptionId(typeof model.defaultReasoningEffort === "string" ? model.defaultReasoningEffort : null);
3355
+ const resolvedDefaultReasoningEffort = configuredDefaultThinkingOptionId ?? defaultReasoningEffort;
3356
+ const thinkingById = new Map();
3357
+ if (Array.isArray(model.supportedReasoningEfforts)) {
3358
+ for (const entry of model.supportedReasoningEfforts) {
3359
+ const id = normalizeCodexThinkingOptionId(typeof entry?.reasoningEffort === "string" ? entry.reasoningEffort : null);
3360
+ if (!id)
3361
+ continue;
3362
+ const description = typeof entry?.description === "string" && entry.description.trim().length > 0
3363
+ ? entry.description
3364
+ : undefined;
3365
+ thinkingById.set(id, { id, label: id, description });
3366
+ }
3367
+ }
3368
+ if (resolvedDefaultReasoningEffort && !thinkingById.has(resolvedDefaultReasoningEffort)) {
3369
+ thinkingById.set(resolvedDefaultReasoningEffort, {
3370
+ id: resolvedDefaultReasoningEffort,
3371
+ label: resolvedDefaultReasoningEffort,
3372
+ description: configuredDefaultThinkingOptionId === resolvedDefaultReasoningEffort
3373
+ ? "Configured default reasoning effort"
3374
+ : "Model default reasoning effort",
3375
+ });
3376
+ }
3377
+ const thinkingOptions = Array.from(thinkingById.values()).map((option) => ({
3378
+ ...option,
3379
+ isDefault: option.id === resolvedDefaultReasoningEffort,
3380
+ }));
3381
+ const defaultThinkingOptionId = resolvedDefaultReasoningEffort ??
3382
+ thinkingOptions.find((option) => option.isDefault)?.id ??
3383
+ thinkingOptions[0]?.id;
3384
+ const isDefaultModel = hasConfiguredDefaultModel
3385
+ ? model.id === configuredDefaultModelId
3386
+ : model.isDefault;
3387
+ return {
3388
+ provider: CODEX_PROVIDER,
3389
+ id: model.id,
3390
+ label: normalizeCodexModelLabel(model.displayName),
3391
+ description: model.description,
3392
+ isDefault: isDefaultModel,
3393
+ thinkingOptions: thinkingOptions.length > 0 ? thinkingOptions : undefined,
3394
+ defaultThinkingOptionId,
3395
+ metadata: {
3396
+ model: model.model,
3397
+ defaultReasoningEffort: model.defaultReasoningEffort,
3398
+ supportedReasoningEfforts: model.supportedReasoningEfforts,
3399
+ },
3400
+ };
3401
+ });
3402
+ }
3403
+ finally {
3404
+ await client.dispose();
3405
+ }
3406
+ }
3407
+ async isAvailable() {
3408
+ const command = this.runtimeSettings?.command;
3409
+ if (command?.mode === "replace") {
3410
+ return existsSync(command.argv[0]);
3411
+ }
3412
+ return true;
3413
+ }
3414
+ async getDiagnostic() {
3415
+ try {
3416
+ const available = await this.isAvailable();
3417
+ const resolvedBinary = await findExecutable("codex");
3418
+ const entries = [
3419
+ {
3420
+ label: "Binary",
3421
+ value: resolvedBinary ?? "not found",
3422
+ },
3423
+ {
3424
+ label: "Version",
3425
+ value: resolvedBinary ? await resolveBinaryVersion(resolvedBinary) : "unknown",
3426
+ },
3427
+ ];
3428
+ let status = formatDiagnosticStatus(available);
3429
+ if (!available) {
3430
+ entries.push({ label: "Models", value: "Not checked" });
3431
+ }
3432
+ else {
3433
+ try {
3434
+ const models = await this.listModels();
3435
+ entries.push({ label: "Models", value: String(models.length) });
3436
+ }
3437
+ catch (error) {
3438
+ entries.push({
3439
+ label: "Models",
3440
+ value: `Error - ${toDiagnosticErrorMessage(error)}`,
3441
+ });
3442
+ status = formatDiagnosticStatus(available, {
3443
+ source: "model fetch",
3444
+ cause: error,
3445
+ });
3446
+ }
3447
+ }
3448
+ entries.push({ label: "Status", value: status });
3449
+ return {
3450
+ diagnostic: formatProviderDiagnostic("Codex", entries),
3451
+ };
3452
+ }
3453
+ catch (error) {
3454
+ return {
3455
+ diagnostic: formatProviderDiagnosticError("Codex", error),
3456
+ };
3457
+ }
3458
+ }
3459
+ }
3460
+ export const __codexAppServerInternals = {
3461
+ buildCodexAppServerEnv,
3462
+ codexModelSupportsFastMode,
3463
+ CodexAppServerAgentSession,
3464
+ formatCodexQuestionPrompts,
3465
+ mapCodexQuestionRequestToToolCall,
3466
+ mapCodexPatchNotificationToToolCall,
3467
+ planStepsToMarkdown,
3468
+ mapCodexPlanToToolCall,
3469
+ normalizeCodexOutputSchema,
3470
+ normalizeCodexQuestionPrompts,
3471
+ toAgentUsage,
3472
+ threadItemToTimeline,
3473
+ };
3474
+ //# sourceMappingURL=codex-app-server-agent.js.map