@midscene/core 1.13.1 → 1.13.2-beta-20260923031905.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 (255) hide show
  1. package/dist/es/agent/task-builder.mjs +1 -1
  2. package/dist/es/agent/task-builder.mjs.map +1 -1
  3. package/dist/es/agent/tasks.mjs +4 -4
  4. package/dist/es/agent/tasks.mjs.map +1 -1
  5. package/dist/es/agent/utils.mjs +1 -1
  6. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs +2 -5
  7. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs.map +1 -1
  8. package/dist/es/ai-model/model-adapter/chat-completion.mjs +8 -11
  9. package/dist/es/ai-model/model-adapter/chat-completion.mjs.map +1 -1
  10. package/dist/es/ai-model/model-adapter/resolve.mjs +10 -0
  11. package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -1
  12. package/dist/es/ai-model/model-adapter/responses.mjs +38 -0
  13. package/dist/es/ai-model/model-adapter/responses.mjs.map +1 -0
  14. package/dist/es/ai-model/model-adapter/temperature-with-semantic-retry.mjs +7 -0
  15. package/dist/es/ai-model/model-adapter/temperature-with-semantic-retry.mjs.map +1 -0
  16. package/dist/es/ai-model/models/gpt.mjs +73 -9
  17. package/dist/es/ai-model/models/gpt.mjs.map +1 -1
  18. package/dist/es/ai-model/models/registry.mjs +2 -2
  19. package/dist/es/ai-model/models/registry.mjs.map +1 -1
  20. package/dist/es/ai-model/service-caller/call-ai.mjs +22 -13
  21. package/dist/es/ai-model/service-caller/call-ai.mjs.map +1 -1
  22. package/dist/es/ai-model/service-caller/codex/call-codex.mjs +10 -8
  23. package/dist/es/ai-model/service-caller/codex/call-codex.mjs.map +1 -1
  24. package/dist/es/ai-model/service-caller/codex/codex-app-server.mjs +29 -28
  25. package/dist/es/ai-model/service-caller/codex/codex-app-server.mjs.map +1 -1
  26. package/dist/es/ai-model/service-caller/index.mjs +1 -2
  27. package/dist/es/ai-model/service-caller/model-call.mjs +4 -4
  28. package/dist/es/ai-model/service-caller/model-call.mjs.map +1 -1
  29. package/dist/es/ai-model/service-caller/openai/call-openai.mjs +13 -8
  30. package/dist/es/ai-model/service-caller/openai/call-openai.mjs.map +1 -1
  31. package/dist/es/ai-model/service-caller/openai/chat-completion/chat-completion.mjs +11 -7
  32. package/dist/es/ai-model/service-caller/openai/chat-completion/chat-completion.mjs.map +1 -1
  33. package/dist/es/ai-model/service-caller/openai/chat-completion/non-stream.mjs +9 -9
  34. package/dist/es/ai-model/service-caller/openai/chat-completion/non-stream.mjs.map +1 -1
  35. package/dist/es/ai-model/service-caller/openai/chat-completion/stream.mjs +4 -8
  36. package/dist/es/ai-model/service-caller/openai/chat-completion/stream.mjs.map +1 -1
  37. package/dist/es/ai-model/service-caller/openai/chat-completion/utils.mjs +28 -1
  38. package/dist/es/ai-model/service-caller/openai/chat-completion/utils.mjs.map +1 -1
  39. package/dist/es/ai-model/service-caller/openai/openai-client.mjs +3 -3
  40. package/dist/es/ai-model/service-caller/openai/openai-client.mjs.map +1 -1
  41. package/dist/es/ai-model/service-caller/openai/responses/non-stream.mjs +21 -0
  42. package/dist/es/ai-model/service-caller/openai/responses/non-stream.mjs.map +1 -0
  43. package/dist/es/ai-model/service-caller/openai/responses/responses.mjs +57 -0
  44. package/dist/es/ai-model/service-caller/openai/responses/responses.mjs.map +1 -0
  45. package/dist/es/ai-model/service-caller/openai/responses/stream.mjs +56 -0
  46. package/dist/es/ai-model/service-caller/openai/responses/stream.mjs.map +1 -0
  47. package/dist/es/ai-model/service-caller/openai/responses/types.mjs +0 -0
  48. package/dist/es/ai-model/service-caller/openai/responses/utils.mjs +72 -0
  49. package/dist/es/ai-model/service-caller/openai/responses/utils.mjs.map +1 -0
  50. package/dist/es/ai-model/service-caller/semantic-retry.mjs.map +1 -1
  51. package/dist/es/ai-model/service-caller/utils.mjs +6 -25
  52. package/dist/es/ai-model/service-caller/utils.mjs.map +1 -1
  53. package/dist/es/ai-model/shared/multimodal-prompt.mjs +5 -8
  54. package/dist/es/ai-model/shared/multimodal-prompt.mjs.map +1 -1
  55. package/dist/es/ai-model/workflows/grounding/locate.mjs +6 -6
  56. package/dist/es/ai-model/workflows/grounding/locate.mjs.map +1 -1
  57. package/dist/es/ai-model/workflows/grounding/planning-action-locate.mjs +5 -5
  58. package/dist/es/ai-model/workflows/grounding/planning-action-locate.mjs.map +1 -1
  59. package/dist/es/ai-model/workflows/grounding/section-locate.mjs +5 -5
  60. package/dist/es/ai-model/workflows/grounding/section-locate.mjs.map +1 -1
  61. package/dist/es/ai-model/workflows/grounding/utils.mjs +4 -7
  62. package/dist/es/ai-model/workflows/grounding/utils.mjs.map +1 -1
  63. package/dist/es/ai-model/workflows/insight/extraction.mjs +9 -15
  64. package/dist/es/ai-model/workflows/insight/extraction.mjs.map +1 -1
  65. package/dist/es/ai-model/workflows/insight/order-sensitive.mjs.map +1 -1
  66. package/dist/es/ai-model/workflows/planning/conversation-history.mjs +17 -9
  67. package/dist/es/ai-model/workflows/planning/conversation-history.mjs.map +1 -1
  68. package/dist/es/ai-model/workflows/planning/custom-planning.mjs +11 -12
  69. package/dist/es/ai-model/workflows/planning/custom-planning.mjs.map +1 -1
  70. package/dist/es/ai-model/workflows/planning/standard-planning.mjs +24 -26
  71. package/dist/es/ai-model/workflows/planning/standard-planning.mjs.map +1 -1
  72. package/dist/es/ai-model/workflows/recorder-generation/common.mjs +2 -4
  73. package/dist/es/ai-model/workflows/recorder-generation/common.mjs.map +1 -1
  74. package/dist/es/ai-model/workflows/recorder-generation/markdown.mjs +3 -5
  75. package/dist/es/ai-model/workflows/recorder-generation/markdown.mjs.map +1 -1
  76. package/dist/es/ai-model/workflows/recorder-generation/metadata.mjs +2 -4
  77. package/dist/es/ai-model/workflows/recorder-generation/metadata.mjs.map +1 -1
  78. package/dist/es/ai-model/workflows/recorder-generation/playwright.mjs.map +1 -1
  79. package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs +2 -4
  80. package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs.map +1 -1
  81. package/dist/es/report-html-template.mjs +1 -1
  82. package/dist/es/service/index.mjs +17 -26
  83. package/dist/es/service/index.mjs.map +1 -1
  84. package/dist/es/types.mjs.map +1 -1
  85. package/dist/es/utils.mjs +1 -1
  86. package/dist/lib/agent/task-builder.js +1 -1
  87. package/dist/lib/agent/task-builder.js.map +1 -1
  88. package/dist/lib/agent/tasks.js +4 -4
  89. package/dist/lib/agent/tasks.js.map +1 -1
  90. package/dist/lib/agent/utils.js +1 -1
  91. package/dist/lib/ai-model/connectivity/run-connectivity-test.js +2 -5
  92. package/dist/lib/ai-model/connectivity/run-connectivity-test.js.map +1 -1
  93. package/dist/lib/ai-model/model-adapter/chat-completion.js +8 -11
  94. package/dist/lib/ai-model/model-adapter/chat-completion.js.map +1 -1
  95. package/dist/lib/ai-model/model-adapter/resolve.js +10 -0
  96. package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -1
  97. package/dist/lib/ai-model/model-adapter/responses.js +75 -0
  98. package/dist/lib/ai-model/model-adapter/responses.js.map +1 -0
  99. package/dist/lib/ai-model/model-adapter/temperature-with-semantic-retry.js +41 -0
  100. package/dist/lib/ai-model/model-adapter/temperature-with-semantic-retry.js.map +1 -0
  101. package/dist/lib/ai-model/models/gpt.js +73 -9
  102. package/dist/lib/ai-model/models/gpt.js.map +1 -1
  103. package/dist/lib/ai-model/models/registry.js +2 -2
  104. package/dist/lib/ai-model/models/registry.js.map +1 -1
  105. package/dist/lib/ai-model/service-caller/call-ai.js +22 -13
  106. package/dist/lib/ai-model/service-caller/call-ai.js.map +1 -1
  107. package/dist/lib/ai-model/service-caller/codex/call-codex.js +10 -8
  108. package/dist/lib/ai-model/service-caller/codex/call-codex.js.map +1 -1
  109. package/dist/lib/ai-model/service-caller/codex/codex-app-server.js +29 -28
  110. package/dist/lib/ai-model/service-caller/codex/codex-app-server.js.map +1 -1
  111. package/dist/lib/ai-model/service-caller/index.js +0 -4
  112. package/dist/lib/ai-model/service-caller/model-call.js +4 -4
  113. package/dist/lib/ai-model/service-caller/model-call.js.map +1 -1
  114. package/dist/lib/ai-model/service-caller/openai/call-openai.js +12 -7
  115. package/dist/lib/ai-model/service-caller/openai/call-openai.js.map +1 -1
  116. package/dist/lib/ai-model/service-caller/openai/chat-completion/chat-completion.js +10 -6
  117. package/dist/lib/ai-model/service-caller/openai/chat-completion/chat-completion.js.map +1 -1
  118. package/dist/lib/ai-model/service-caller/openai/chat-completion/non-stream.js +9 -9
  119. package/dist/lib/ai-model/service-caller/openai/chat-completion/non-stream.js.map +1 -1
  120. package/dist/lib/ai-model/service-caller/openai/chat-completion/stream.js +4 -8
  121. package/dist/lib/ai-model/service-caller/openai/chat-completion/stream.js.map +1 -1
  122. package/dist/lib/ai-model/service-caller/openai/chat-completion/utils.js +32 -2
  123. package/dist/lib/ai-model/service-caller/openai/chat-completion/utils.js.map +1 -1
  124. package/dist/lib/ai-model/service-caller/openai/openai-client.js +5 -5
  125. package/dist/lib/ai-model/service-caller/openai/openai-client.js.map +1 -1
  126. package/dist/lib/ai-model/service-caller/openai/responses/non-stream.js +55 -0
  127. package/dist/lib/ai-model/service-caller/openai/responses/non-stream.js.map +1 -0
  128. package/dist/lib/ai-model/service-caller/openai/responses/responses.js +94 -0
  129. package/dist/lib/ai-model/service-caller/openai/responses/responses.js.map +1 -0
  130. package/dist/lib/ai-model/service-caller/openai/responses/stream.js +90 -0
  131. package/dist/lib/ai-model/service-caller/openai/responses/stream.js.map +1 -0
  132. package/dist/lib/ai-model/service-caller/openai/responses/types.js +20 -0
  133. package/dist/lib/ai-model/service-caller/openai/responses/types.js.map +1 -0
  134. package/dist/lib/ai-model/service-caller/openai/responses/utils.js +112 -0
  135. package/dist/lib/ai-model/service-caller/openai/responses/utils.js.map +1 -0
  136. package/dist/lib/ai-model/service-caller/semantic-retry.js.map +1 -1
  137. package/dist/lib/ai-model/service-caller/utils.js +5 -27
  138. package/dist/lib/ai-model/service-caller/utils.js.map +1 -1
  139. package/dist/lib/ai-model/shared/multimodal-prompt.js +11 -14
  140. package/dist/lib/ai-model/shared/multimodal-prompt.js.map +1 -1
  141. package/dist/lib/ai-model/workflows/grounding/locate.js +6 -6
  142. package/dist/lib/ai-model/workflows/grounding/locate.js.map +1 -1
  143. package/dist/lib/ai-model/workflows/grounding/planning-action-locate.js +5 -5
  144. package/dist/lib/ai-model/workflows/grounding/planning-action-locate.js.map +1 -1
  145. package/dist/lib/ai-model/workflows/grounding/section-locate.js +5 -5
  146. package/dist/lib/ai-model/workflows/grounding/section-locate.js.map +1 -1
  147. package/dist/lib/ai-model/workflows/grounding/utils.js +3 -6
  148. package/dist/lib/ai-model/workflows/grounding/utils.js.map +1 -1
  149. package/dist/lib/ai-model/workflows/insight/extraction.js +8 -14
  150. package/dist/lib/ai-model/workflows/insight/extraction.js.map +1 -1
  151. package/dist/lib/ai-model/workflows/insight/order-sensitive.js.map +1 -1
  152. package/dist/lib/ai-model/workflows/planning/conversation-history.js +17 -9
  153. package/dist/lib/ai-model/workflows/planning/conversation-history.js.map +1 -1
  154. package/dist/lib/ai-model/workflows/planning/custom-planning.js +10 -11
  155. package/dist/lib/ai-model/workflows/planning/custom-planning.js.map +1 -1
  156. package/dist/lib/ai-model/workflows/planning/standard-planning.js +23 -25
  157. package/dist/lib/ai-model/workflows/planning/standard-planning.js.map +1 -1
  158. package/dist/lib/ai-model/workflows/recorder-generation/common.js +2 -4
  159. package/dist/lib/ai-model/workflows/recorder-generation/common.js.map +1 -1
  160. package/dist/lib/ai-model/workflows/recorder-generation/markdown.js +3 -5
  161. package/dist/lib/ai-model/workflows/recorder-generation/markdown.js.map +1 -1
  162. package/dist/lib/ai-model/workflows/recorder-generation/metadata.js +2 -4
  163. package/dist/lib/ai-model/workflows/recorder-generation/metadata.js.map +1 -1
  164. package/dist/lib/ai-model/workflows/recorder-generation/playwright.js.map +1 -1
  165. package/dist/lib/ai-model/workflows/recorder-generation/yaml.js +2 -4
  166. package/dist/lib/ai-model/workflows/recorder-generation/yaml.js.map +1 -1
  167. package/dist/lib/report-html-template.js +1 -1
  168. package/dist/lib/service/index.js +17 -26
  169. package/dist/lib/service/index.js.map +1 -1
  170. package/dist/lib/types.js.map +1 -1
  171. package/dist/lib/utils.js +1 -1
  172. package/dist/types/ai-model/connectivity/run-connectivity-test.d.ts.map +1 -1
  173. package/dist/types/ai-model/index.d.ts +1 -1
  174. package/dist/types/ai-model/index.d.ts.map +1 -1
  175. package/dist/types/ai-model/model-adapter/chat-completion.d.ts.map +1 -1
  176. package/dist/types/ai-model/model-adapter/resolve.d.ts +4 -1
  177. package/dist/types/ai-model/model-adapter/resolve.d.ts.map +1 -1
  178. package/dist/types/ai-model/model-adapter/responses.d.ts +4 -0
  179. package/dist/types/ai-model/model-adapter/responses.d.ts.map +1 -0
  180. package/dist/types/ai-model/model-adapter/temperature-with-semantic-retry.d.ts +6 -0
  181. package/dist/types/ai-model/model-adapter/temperature-with-semantic-retry.d.ts.map +1 -0
  182. package/dist/types/ai-model/model-adapter/types.d.ts +42 -13
  183. package/dist/types/ai-model/model-adapter/types.d.ts.map +1 -1
  184. package/dist/types/ai-model/models/gpt.d.ts +15 -3
  185. package/dist/types/ai-model/models/gpt.d.ts.map +1 -1
  186. package/dist/types/ai-model/models/registry.d.ts +14 -2
  187. package/dist/types/ai-model/models/registry.d.ts.map +1 -1
  188. package/dist/types/ai-model/service-caller/call-ai.d.ts +2 -2
  189. package/dist/types/ai-model/service-caller/call-ai.d.ts.map +1 -1
  190. package/dist/types/ai-model/service-caller/codex/call-codex.d.ts +4 -2
  191. package/dist/types/ai-model/service-caller/codex/call-codex.d.ts.map +1 -1
  192. package/dist/types/ai-model/service-caller/codex/codex-app-server.d.ts +5 -4
  193. package/dist/types/ai-model/service-caller/codex/codex-app-server.d.ts.map +1 -1
  194. package/dist/types/ai-model/service-caller/index.d.ts +0 -1
  195. package/dist/types/ai-model/service-caller/index.d.ts.map +1 -1
  196. package/dist/types/ai-model/service-caller/model-call.d.ts +6 -6
  197. package/dist/types/ai-model/service-caller/model-call.d.ts.map +1 -1
  198. package/dist/types/ai-model/service-caller/openai/call-openai.d.ts +9 -1
  199. package/dist/types/ai-model/service-caller/openai/call-openai.d.ts.map +1 -1
  200. package/dist/types/ai-model/service-caller/openai/chat-completion/chat-completion.d.ts +3 -4
  201. package/dist/types/ai-model/service-caller/openai/chat-completion/chat-completion.d.ts.map +1 -1
  202. package/dist/types/ai-model/service-caller/openai/chat-completion/non-stream.d.ts +1 -1
  203. package/dist/types/ai-model/service-caller/openai/chat-completion/non-stream.d.ts.map +1 -1
  204. package/dist/types/ai-model/service-caller/openai/chat-completion/stream.d.ts +1 -1
  205. package/dist/types/ai-model/service-caller/openai/chat-completion/stream.d.ts.map +1 -1
  206. package/dist/types/ai-model/service-caller/openai/chat-completion/types.d.ts +5 -5
  207. package/dist/types/ai-model/service-caller/openai/chat-completion/types.d.ts.map +1 -1
  208. package/dist/types/ai-model/service-caller/openai/chat-completion/utils.d.ts +5 -0
  209. package/dist/types/ai-model/service-caller/openai/chat-completion/utils.d.ts.map +1 -1
  210. package/dist/types/ai-model/service-caller/openai/openai-client.d.ts +2 -2
  211. package/dist/types/ai-model/service-caller/openai/openai-client.d.ts.map +1 -1
  212. package/dist/types/ai-model/service-caller/openai/responses/non-stream.d.ts +4 -0
  213. package/dist/types/ai-model/service-caller/openai/responses/non-stream.d.ts.map +1 -0
  214. package/dist/types/ai-model/service-caller/openai/responses/responses.d.ts +8 -0
  215. package/dist/types/ai-model/service-caller/openai/responses/responses.d.ts.map +1 -0
  216. package/dist/types/ai-model/service-caller/openai/responses/stream.d.ts +4 -0
  217. package/dist/types/ai-model/service-caller/openai/responses/stream.d.ts.map +1 -0
  218. package/dist/types/ai-model/service-caller/openai/responses/types.d.ts +8 -0
  219. package/dist/types/ai-model/service-caller/openai/responses/types.d.ts.map +1 -0
  220. package/dist/types/ai-model/service-caller/openai/responses/utils.d.ts +8 -0
  221. package/dist/types/ai-model/service-caller/openai/responses/utils.d.ts.map +1 -0
  222. package/dist/types/ai-model/service-caller/semantic-retry.d.ts +2 -2
  223. package/dist/types/ai-model/service-caller/semantic-retry.d.ts.map +1 -1
  224. package/dist/types/ai-model/service-caller/types.d.ts +35 -5
  225. package/dist/types/ai-model/service-caller/types.d.ts.map +1 -1
  226. package/dist/types/ai-model/service-caller/utils.d.ts +5 -9
  227. package/dist/types/ai-model/service-caller/utils.d.ts.map +1 -1
  228. package/dist/types/ai-model/shared/multimodal-prompt.d.ts +3 -3
  229. package/dist/types/ai-model/shared/multimodal-prompt.d.ts.map +1 -1
  230. package/dist/types/ai-model/workflows/grounding/planning-action-locate.d.ts.map +1 -1
  231. package/dist/types/ai-model/workflows/grounding/section-locate.d.ts +2 -1
  232. package/dist/types/ai-model/workflows/grounding/section-locate.d.ts.map +1 -1
  233. package/dist/types/ai-model/workflows/grounding/types.d.ts +3 -2
  234. package/dist/types/ai-model/workflows/grounding/types.d.ts.map +1 -1
  235. package/dist/types/ai-model/workflows/grounding/utils.d.ts +3 -3
  236. package/dist/types/ai-model/workflows/grounding/utils.d.ts.map +1 -1
  237. package/dist/types/ai-model/workflows/insight/extraction.d.ts +1 -1
  238. package/dist/types/ai-model/workflows/insight/extraction.d.ts.map +1 -1
  239. package/dist/types/ai-model/workflows/insight/order-sensitive.d.ts.map +1 -1
  240. package/dist/types/ai-model/workflows/planning/conversation-history.d.ts +10 -8
  241. package/dist/types/ai-model/workflows/planning/conversation-history.d.ts.map +1 -1
  242. package/dist/types/ai-model/workflows/planning/custom-planning.d.ts +2 -2
  243. package/dist/types/ai-model/workflows/planning/custom-planning.d.ts.map +1 -1
  244. package/dist/types/ai-model/workflows/planning/standard-planning.d.ts.map +1 -1
  245. package/dist/types/ai-model/workflows/recorder-generation/common.d.ts +2 -1
  246. package/dist/types/ai-model/workflows/recorder-generation/common.d.ts.map +1 -1
  247. package/dist/types/ai-model/workflows/recorder-generation/markdown.d.ts +2 -2
  248. package/dist/types/ai-model/workflows/recorder-generation/markdown.d.ts.map +1 -1
  249. package/dist/types/ai-model/workflows/recorder-generation/metadata.d.ts.map +1 -1
  250. package/dist/types/ai-model/workflows/recorder-generation/playwright.d.ts.map +1 -1
  251. package/dist/types/ai-model/workflows/recorder-generation/yaml.d.ts.map +1 -1
  252. package/dist/types/service/index.d.ts.map +1 -1
  253. package/dist/types/types.d.ts +11 -2
  254. package/dist/types/types.d.ts.map +1 -1
  255. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/codex/call-codex.mjs","sources":["../../../../../src/ai-model/service-caller/codex/call-codex.ts"],"sourcesContent":["import type { ModelCallContext, ModelCallResult } from '../types';\nimport { applyImageDetail } from '../utils';\nimport {\n type CodexAppServerRecordEvent,\n callAIWithCodexAppServer,\n} from './codex-app-server';\n\nexport const prepareCodexCall = ({\n messages,\n modelRuntime,\n options,\n}: Pick<ModelCallContext, 'messages' | 'modelRuntime' | 'options'>) => {\n const { config: modelConfig, adapter } = modelRuntime;\n const { config, imageDetail } = adapter.buildCodexAppServerParams({\n intent: modelConfig.intent,\n userConfig: {\n reasoningEnabled: modelConfig.reasoningEnabled,\n reasoningEffort: modelConfig.reasoningEffort,\n reasoningBudget: modelConfig.reasoningBudget,\n },\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n });\n const messagesWithImageDetail = applyImageDetail({ imageDetail, messages });\n return { messages: messagesWithImageDetail, requestParams: config };\n};\n\nexport const callCodex = async (\n { modelRuntime, options, recordEvent, requestSignal }: ModelCallContext,\n { messages, requestParams }: ReturnType<typeof prepareCodexCall>,\n): Promise<ModelCallResult> => {\n const { config: modelConfig } = modelRuntime;\n let protocolChunkSequence = 0;\n const codexStartTime = Date.now();\n const recordCodexEvent = recordEvent\n ? (event: CodexAppServerRecordEvent) => {\n if (event.type === 'chunk') {\n protocolChunkSequence += 1;\n recordEvent({\n ...event,\n attempt: 1,\n sequence: protocolChunkSequence,\n provider: 'codex-app-server',\n });\n return;\n }\n\n recordEvent({\n ...event,\n attempt: 1,\n provider: 'codex-app-server',\n });\n }\n : undefined;\n\n try {\n const codexResult = await callAIWithCodexAppServer(messages, modelConfig, {\n stream: options?.stream,\n onChunk: options?.onChunk,\n params: requestParams,\n abortSignal: requestSignal,\n onRecordEvent: recordCodexEvent,\n });\n requestSignal.throwIfAborted();\n const { protocolMetadata, usage: rawUsage, ...response } = codexResult;\n const timeCost = Date.now() - codexStartTime;\n recordEvent?.({\n type: 'response',\n attempt: 1,\n provider: 'codex-app-server',\n final: {\n content: response.content,\n reasoningContent: response.reasoning_content,\n usage: rawUsage,\n timeCost,\n protocol: protocolMetadata,\n },\n });\n return {\n ...response,\n rawUsage,\n timeCost,\n requestId: protocolMetadata.turnId,\n };\n } catch (error) {\n recordEvent?.({\n type: 'error',\n attempt: 1,\n provider: 'codex-app-server',\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : String(error),\n });\n throw error;\n }\n};\n"],"names":["prepareCodexCall","messages","modelRuntime","options","modelConfig","adapter","config","imageDetail","messagesWithImageDetail","applyImageDetail","callCodex","recordEvent","requestSignal","requestParams","protocolChunkSequence","codexStartTime","Date","recordCodexEvent","event","undefined","codexResult","callAIWithCodexAppServer","protocolMetadata","rawUsage","response","timeCost","error","Error","String"],"mappings":";;AAOO,MAAMA,mBAAmB,CAAC,EAC/BC,QAAQ,EACRC,YAAY,EACZC,OAAO,EACyD;IAChE,MAAM,EAAE,QAAQC,WAAW,EAAEC,OAAO,EAAE,GAAGH;IACzC,MAAM,EAAEI,MAAM,EAAEC,WAAW,EAAE,GAAGF,QAAQ,yBAAyB,CAAC;QAChE,QAAQD,YAAY,MAAM;QAC1B,YAAY;YACV,kBAAkBA,YAAY,gBAAgB;YAC9C,iBAAiBA,YAAY,eAAe;YAC5C,iBAAiBA,YAAY,eAAe;QAC9C;QACA,6BAA6BD,SAAS;IACxC;IACA,MAAMK,0BAA0BC,iBAAiB;QAAEF;QAAaN;IAAS;IACzE,OAAO;QAAE,UAAUO;QAAyB,eAAeF;IAAO;AACpE;AAEO,MAAMI,YAAY,OACvB,EAAER,YAAY,EAAEC,OAAO,EAAEQ,WAAW,EAAEC,aAAa,EAAoB,EACvE,EAAEX,QAAQ,EAAEY,aAAa,EAAuC;IAEhE,MAAM,EAAE,QAAQT,WAAW,EAAE,GAAGF;IAChC,IAAIY,wBAAwB;IAC5B,MAAMC,iBAAiBC,KAAK,GAAG;IAC/B,MAAMC,mBAAmBN,cACrB,CAACO;QACC,IAAIA,AAAe,YAAfA,MAAM,IAAI,EAAc;YAC1BJ,yBAAyB;YACzBH,YAAY;gBACV,GAAGO,KAAK;gBACR,SAAS;gBACT,UAAUJ;gBACV,UAAU;YACZ;YACA;QACF;QAEAH,YAAY;YACV,GAAGO,KAAK;YACR,SAAS;YACT,UAAU;QACZ;IACF,IACAC;IAEJ,IAAI;QACF,MAAMC,cAAc,MAAMC,yBAAyBpB,UAAUG,aAAa;YACxE,QAAQD,SAAS;YACjB,SAASA,SAAS;YAClB,QAAQU;YACR,aAAaD;YACb,eAAeK;QACjB;QACAL,cAAc,cAAc;QAC5B,MAAM,EAAEU,gBAAgB,EAAE,OAAOC,QAAQ,EAAE,GAAGC,UAAU,GAAGJ;QAC3D,MAAMK,WAAWT,KAAK,GAAG,KAAKD;QAC9BJ,cAAc;YACZ,MAAM;YACN,SAAS;YACT,UAAU;YACV,OAAO;gBACL,SAASa,SAAS,OAAO;gBACzB,kBAAkBA,SAAS,iBAAiB;gBAC5C,OAAOD;gBACPE;gBACA,UAAUH;YACZ;QACF;QACA,OAAO;YACL,GAAGE,QAAQ;YACXD;YACAE;YACA,WAAWH,iBAAiB,MAAM;QACpC;IACF,EAAE,OAAOI,OAAO;QACdf,cAAc;YACZ,MAAM;YACN,SAAS;YACT,UAAU;YACV,OACEe,iBAAiBC,QACb;gBACE,MAAMD,MAAM,IAAI;gBAChB,SAASA,MAAM,OAAO;gBACtB,OAAOA,MAAM,KAAK;YACpB,IACAE,OAAOF;QACf;QACA,MAAMA;IACR;AACF"}
1
+ {"version":3,"file":"ai-model/service-caller/codex/call-codex.mjs","sources":["../../../../../src/ai-model/service-caller/codex/call-codex.ts"],"sourcesContent":["import type { ResolveImageDetail } from '../../model-adapter/types';\nimport type { ModelCallContext, ModelCallResult } from '../types';\nimport {\n type CodexAppServerRecordEvent,\n callAIWithCodexAppServer,\n} from './codex-app-server';\n\nexport const prepareCodexCall = ({\n messages,\n modelRuntime,\n options,\n}: Pick<ModelCallContext, 'messages' | 'modelRuntime' | 'options'>) => {\n const { config: modelConfig, adapter } = modelRuntime;\n const { config } = adapter.buildCodexAppServerParams({\n intent: modelConfig.intent,\n userConfig: {\n reasoningEnabled: modelConfig.reasoningEnabled,\n reasoningEffort: modelConfig.reasoningEffort,\n reasoningBudget: modelConfig.reasoningBudget,\n },\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n });\n const resolveImageDetail: ResolveImageDetail = ({ imageDetail }) =>\n adapter.resolveImageDetail({\n imageDetail,\n intent: modelConfig.intent,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n });\n return { messages, resolveImageDetail, requestParams: config };\n};\n\nexport const callCodex = async (\n { modelRuntime, options, recordEvent, requestSignal }: ModelCallContext,\n {\n messages,\n resolveImageDetail,\n requestParams,\n }: ReturnType<typeof prepareCodexCall>,\n): Promise<ModelCallResult> => {\n const { config: modelConfig } = modelRuntime;\n let protocolChunkSequence = 0;\n const codexStartTime = Date.now();\n const recordCodexEvent = recordEvent\n ? (event: CodexAppServerRecordEvent) => {\n if (event.type === 'chunk') {\n protocolChunkSequence += 1;\n recordEvent({\n ...event,\n attempt: 1,\n sequence: protocolChunkSequence,\n provider: 'codex-app-server',\n });\n return;\n }\n\n recordEvent({\n ...event,\n attempt: 1,\n provider: 'codex-app-server',\n });\n }\n : undefined;\n\n try {\n const codexResult = await callAIWithCodexAppServer(messages, modelConfig, {\n stream: options?.stream,\n onChunk: options?.onChunk,\n params: requestParams,\n resolveImageDetail,\n abortSignal: requestSignal,\n onRecordEvent: recordCodexEvent,\n });\n requestSignal.throwIfAborted();\n const { protocolMetadata, usage: rawUsage, ...response } = codexResult;\n const timeCost = Date.now() - codexStartTime;\n recordEvent?.({\n type: 'response',\n attempt: 1,\n provider: 'codex-app-server',\n final: {\n content: response.content,\n reasoningContent: response.reasoning_content,\n usage: rawUsage,\n timeCost,\n protocol: protocolMetadata,\n },\n });\n return {\n ...response,\n rawUsage,\n timeCost,\n requestId: protocolMetadata.turnId,\n };\n } catch (error) {\n recordEvent?.({\n type: 'error',\n attempt: 1,\n provider: 'codex-app-server',\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : String(error),\n });\n throw error;\n }\n};\n"],"names":["prepareCodexCall","messages","modelRuntime","options","modelConfig","adapter","config","resolveImageDetail","imageDetail","callCodex","recordEvent","requestSignal","requestParams","protocolChunkSequence","codexStartTime","Date","recordCodexEvent","event","undefined","codexResult","callAIWithCodexAppServer","protocolMetadata","rawUsage","response","timeCost","error","Error","String"],"mappings":";AAOO,MAAMA,mBAAmB,CAAC,EAC/BC,QAAQ,EACRC,YAAY,EACZC,OAAO,EACyD;IAChE,MAAM,EAAE,QAAQC,WAAW,EAAEC,OAAO,EAAE,GAAGH;IACzC,MAAM,EAAEI,MAAM,EAAE,GAAGD,QAAQ,yBAAyB,CAAC;QACnD,QAAQD,YAAY,MAAM;QAC1B,YAAY;YACV,kBAAkBA,YAAY,gBAAgB;YAC9C,iBAAiBA,YAAY,eAAe;YAC5C,iBAAiBA,YAAY,eAAe;QAC9C;QACA,6BAA6BD,SAAS;IACxC;IACA,MAAMI,qBAAyC,CAAC,EAAEC,WAAW,EAAE,GAC7DH,QAAQ,kBAAkB,CAAC;YACzBG;YACA,QAAQJ,YAAY,MAAM;YAC1B,6BAA6BD,SAAS;QACxC;IACF,OAAO;QAAEF;QAAUM;QAAoB,eAAeD;IAAO;AAC/D;AAEO,MAAMG,YAAY,OACvB,EAAEP,YAAY,EAAEC,OAAO,EAAEO,WAAW,EAAEC,aAAa,EAAoB,EACvE,EACEV,QAAQ,EACRM,kBAAkB,EAClBK,aAAa,EACuB;IAEtC,MAAM,EAAE,QAAQR,WAAW,EAAE,GAAGF;IAChC,IAAIW,wBAAwB;IAC5B,MAAMC,iBAAiBC,KAAK,GAAG;IAC/B,MAAMC,mBAAmBN,cACrB,CAACO;QACC,IAAIA,AAAe,YAAfA,MAAM,IAAI,EAAc;YAC1BJ,yBAAyB;YACzBH,YAAY;gBACV,GAAGO,KAAK;gBACR,SAAS;gBACT,UAAUJ;gBACV,UAAU;YACZ;YACA;QACF;QAEAH,YAAY;YACV,GAAGO,KAAK;YACR,SAAS;YACT,UAAU;QACZ;IACF,IACAC;IAEJ,IAAI;QACF,MAAMC,cAAc,MAAMC,yBAAyBnB,UAAUG,aAAa;YACxE,QAAQD,SAAS;YACjB,SAASA,SAAS;YAClB,QAAQS;YACRL;YACA,aAAaI;YACb,eAAeK;QACjB;QACAL,cAAc,cAAc;QAC5B,MAAM,EAAEU,gBAAgB,EAAE,OAAOC,QAAQ,EAAE,GAAGC,UAAU,GAAGJ;QAC3D,MAAMK,WAAWT,KAAK,GAAG,KAAKD;QAC9BJ,cAAc;YACZ,MAAM;YACN,SAAS;YACT,UAAU;YACV,OAAO;gBACL,SAASa,SAAS,OAAO;gBACzB,kBAAkBA,SAAS,iBAAiB;gBAC5C,OAAOD;gBACPE;gBACA,UAAUH;YACZ;QACF;QACA,OAAO;YACL,GAAGE,QAAQ;YACXD;YACAE;YACA,WAAWH,iBAAiB,MAAM;QACpC;IACF,EAAE,OAAOI,OAAO;QACdf,cAAc;YACZ,MAAM;YACN,SAAS;YACT,UAAU;YACV,OACEe,iBAAiBC,QACb;gBACE,MAAMD,MAAM,IAAI;gBAChB,SAASA,MAAM,OAAO;gBACtB,OAAOA,MAAM,KAAK;YACpB,IACAE,OAAOF;QACf;QACA,MAAMA;IACR;AACF"}
@@ -52,7 +52,6 @@ const toNonEmptyString = (value)=>{
52
52
  const trimmed = value.trim();
53
53
  return trimmed || void 0;
54
54
  };
55
- const toCodexImageDetail = (value)=>'auto' === value || 'low' === value || 'high' === value || 'original' === value ? value : void 0;
56
55
  const normalizeCodexLocalImagePath = (imageUrl, platform = process.platform)=>{
57
56
  if (!imageUrl.startsWith('file://')) return imageUrl;
58
57
  try {
@@ -71,54 +70,54 @@ const normalizeCodexLocalImagePath = (imageUrl, platform = process.platform)=>{
71
70
  }
72
71
  };
73
72
  const extractTextFromMessage = (message)=>{
74
- const content = message.content;
73
+ const { content } = message;
75
74
  if ('string' == typeof content) return content;
76
- if (Array.isArray(content)) return content.map((part)=>{
77
- if (!part || 'object' != typeof part) return '';
78
- if ('text' === part.type && 'string' == typeof part.text) return part.text;
79
- if ('input_text' === part.type && 'string' == typeof part.text) return part.text;
80
- return '';
81
- }).filter(Boolean).join('\n');
82
- return '';
75
+ return content.map((part)=>'text' === part.type ? part.text : '').filter(Boolean).join('\n');
83
76
  };
84
- const extractImageInputs = (message)=>{
85
- const content = message.content;
77
+ const extractImageInputs = (message, resolveImageDetail)=>{
78
+ const { content } = message;
86
79
  if (!Array.isArray(content)) return [];
87
80
  const inputs = [];
88
81
  for (const part of content){
89
- if (!part || 'object' != typeof part) continue;
90
- const partType = String(part.type || '');
91
- const imageUrl = 'image_url' === partType ? toNonEmptyString(part.image_url?.url) : 'input_image' === partType ? toNonEmptyString(part.image_url || part.url) : void 0;
92
- const imageDetail = toCodexImageDetail('image_url' === partType ? part.image_url?.detail : part.detail);
82
+ if ('image' !== part.type) continue;
83
+ const imageUrl = toNonEmptyString(part.url);
84
+ const detail = resolveImageDetail({
85
+ imageDetail: part.detail
86
+ });
93
87
  if (imageUrl) {
94
88
  if (imageUrl.startsWith('/') || imageUrl.startsWith('./') || imageUrl.startsWith('../') || imageUrl.startsWith('file://')) {
95
89
  const path = imageUrl.startsWith('file://') ? normalizeCodexLocalImagePath(imageUrl) : imageUrl;
96
90
  inputs.push({
97
91
  type: 'localImage',
98
92
  path,
99
- ...imageDetail ? {
100
- detail: imageDetail
101
- } : {}
93
+ detail
102
94
  });
103
95
  continue;
104
96
  }
105
97
  inputs.push({
106
98
  type: 'image',
107
99
  url: imageUrl,
108
- ...imageDetail ? {
109
- detail: imageDetail
110
- } : {}
100
+ detail
111
101
  });
112
102
  }
113
103
  }
114
104
  return inputs;
115
105
  };
116
- const buildCodexTurnPayloadFromMessages = (messages)=>{
106
+ const buildCodexTurnPayloadFromMessages = (messages, resolveImageDetail)=>{
117
107
  const developerInstructionParts = [];
118
108
  const transcriptParts = [];
119
109
  const imageInputs = [];
120
- for (const message of messages){
121
- const role = String(message.role || 'user');
110
+ for (const entry of messages){
111
+ const message = (()=>{
112
+ if ('role' in entry) return entry;
113
+ if ('input-message' === entry.type) return entry.message;
114
+ if ('chat-completion' !== entry.output.type) throw new Error('Cannot replay Responses output in a Codex conversation');
115
+ return {
116
+ role: 'assistant',
117
+ content: entry.output.rawValue.content ?? ''
118
+ };
119
+ })();
120
+ const { role } = message;
122
121
  const text = extractTextFromMessage(message);
123
122
  if ('system' === role) {
124
123
  if (text.trim()) developerInstructionParts.push(text.trim());
@@ -127,7 +126,7 @@ const buildCodexTurnPayloadFromMessages = (messages)=>{
127
126
  const roleTag = role.toUpperCase();
128
127
  if (text.trim()) transcriptParts.push(`[${roleTag}]\n${text.trim()}`);
129
128
  else transcriptParts.push(`[${roleTag}]\n(no text content)`);
130
- if ('user' === role) imageInputs.push(...extractImageInputs(message));
129
+ if ('user' === role) imageInputs.push(...extractImageInputs(message, resolveImageDetail));
131
130
  }
132
131
  const fullTranscript = transcriptParts.join('\n\n');
133
132
  const transcriptText = (fullTranscript.length > CODEX_TEXT_INPUT_MAX_LENGTH ? fullTranscript.slice(-CODEX_TEXT_INPUT_MAX_LENGTH) : fullTranscript) || 'Please answer the latest user request.';
@@ -175,9 +174,9 @@ class CodexAppServerConnection {
175
174
  isClosed() {
176
175
  return this.closed;
177
176
  }
178
- async runTurn({ messages, modelConfig, stream, onChunk, params, abortSignal, onRecordEvent }) {
177
+ async runTurn({ messages, resolveImageDetail, modelConfig, stream, onChunk, params, abortSignal, onRecordEvent }) {
179
178
  const isStreaming = !!(stream && onChunk);
180
- const { developerInstructions, input } = buildCodexTurnPayloadFromMessages(messages);
179
+ const { developerInstructions, input } = buildCodexTurnPayloadFromMessages(messages, resolveImageDetail);
181
180
  let threadId;
182
181
  let turnId;
183
182
  let latestErrorMessage;
@@ -550,7 +549,7 @@ class CodexAppServerConnection {
550
549
  }
551
550
  }
552
551
  class CodexAppServerConnectionManager {
553
- async runTurn({ messages, modelConfig, stream, onChunk, params, abortSignal, onRecordEvent }) {
552
+ async runTurn({ messages, resolveImageDetail, modelConfig, stream, onChunk, params, abortSignal, onRecordEvent }) {
554
553
  return this.runner.run(async ()=>{
555
554
  abortSignal?.throwIfAborted();
556
555
  const connection = await this.getConnection();
@@ -558,6 +557,7 @@ class CodexAppServerConnectionManager {
558
557
  try {
559
558
  return await connection.runTurn({
560
559
  messages,
560
+ resolveImageDetail,
561
561
  modelConfig,
562
562
  stream,
563
563
  onChunk,
@@ -599,6 +599,7 @@ async function callAIWithCodexAppServer(messages, modelConfig, options) {
599
599
  return codexConnectionManager.runTurn({
600
600
  messages,
601
601
  modelConfig,
602
+ resolveImageDetail: options.resolveImageDetail,
602
603
  stream: options?.stream,
603
604
  onChunk: options?.onChunk,
604
605
  params: options?.params,
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/codex/codex-app-server.mjs","sources":["../../../../../src/ai-model/service-caller/codex/codex-app-server.ts"],"sourcesContent":["import type { CodeGenerationChunk, StreamingCallback } from '@/types';\nimport type { IModelConfig } from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport type OpenAI from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { CodexAppServerParamsResult } from '../../model-adapter/types';\n\nconst CODEX_PROVIDER_SCHEME = 'codex://';\nconst CODEX_INTERRUPT_TIMEOUT_MS = 5_000;\nconst CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS = 15 * 1000;\nconst CODEX_DEFAULT_CLEANUP_TIMEOUT_MS = 8 * 1000;\nconst CODEX_TEXT_INPUT_MAX_LENGTH = 256 * 1024;\n\nconst debugCodex = getDebug('ai:call:codex');\nconst warnCodex = getDebug('ai:call:codex', { console: true });\n\ntype JsonRpcRequest = {\n id: string | number;\n method: string;\n params?: unknown;\n};\n\ntype JsonRpcResponse = {\n id: string | number;\n result?: unknown;\n error?: {\n code?: number;\n message?: string;\n data?: unknown;\n };\n};\n\ntype JsonRpcNotification = {\n method: string;\n params?: Record<string, any>;\n};\n\ntype JsonRpcMessage = JsonRpcRequest | JsonRpcResponse | JsonRpcNotification;\n\ntype CodexTextInput = {\n type: 'text';\n text: string;\n text_elements: any[];\n};\n\n// Codex app-server v2 accepts `detail` on both image input variants:\n// https://github.com/openai/codex/blob/main/codex-rs/app-server-protocol/src/protocol/v2/turn.rs#L276-L329\n// Codex has also reported `original` as a supported value in production:\n// https://github.com/openai/codex/issues/24797\ntype CodexImageInput = {\n type: 'image';\n url: string;\n detail?: CodexImageDetail;\n};\n\ntype CodexLocalImageInput = {\n type: 'localImage';\n path: string;\n detail?: CodexImageDetail;\n};\n\ntype CodexTurnInput = CodexTextInput | CodexImageInput | CodexLocalImageInput;\n\ntype CodexImageDetail = 'auto' | 'low' | 'high' | 'original';\n\nexport type CodexAppServerRecordEvent = {\n type: 'request' | 'chunk';\n protocol: Record<string, unknown>;\n};\n\ntype CodexTurnResult = {\n content: string;\n reasoning_content?: string;\n usage?: OpenAI.CompletionUsage;\n isStreamed: boolean;\n protocolMetadata: {\n transport: 'json-rpc';\n threadId: string;\n turnId: string;\n turnStatus: string;\n };\n};\n\ntype CodexTurnStartResponse = {\n turn?: {\n id?: string;\n };\n};\n\ntype CodexThreadStartResponse = {\n thread?: {\n id?: string;\n };\n};\n\ntype CodexUsageNotification = {\n threadId?: string;\n turnId?: string;\n tokenUsage?: {\n total?: {\n totalTokens?: number;\n inputTokens?: number;\n cachedInputTokens?: number;\n outputTokens?: number;\n reasoningOutputTokens?: number;\n };\n last?: {\n totalTokens?: number;\n inputTokens?: number;\n cachedInputTokens?: number;\n outputTokens?: number;\n reasoningOutputTokens?: number;\n };\n };\n};\n\nclass SerializedRunner {\n private tail: Promise<void> = Promise.resolve();\n\n async run<T>(work: () => Promise<T>): Promise<T> {\n const previous = this.tail;\n let release!: () => void;\n this.tail = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n await previous;\n try {\n return await work();\n } finally {\n release();\n }\n }\n}\n\nexport const isCodexAppServerProvider = (baseURL?: string): boolean => {\n if (!baseURL) return false;\n return baseURL.trim().toLowerCase().startsWith(CODEX_PROVIDER_SCHEME);\n};\n\nconst isAbortError = (error: unknown): boolean => {\n if (!error) return false;\n if (error instanceof Error && error.name === 'AbortError') return true;\n const message =\n error instanceof Error ? error.message : String(error ?? 'unknown error');\n return /aborted|abort/i.test(message);\n};\n\nconst toNonEmptyString = (value: unknown): string | undefined => {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed || undefined;\n};\n\nconst toCodexImageDetail = (value: unknown): CodexImageDetail | undefined =>\n value === 'auto' ||\n value === 'low' ||\n value === 'high' ||\n value === 'original'\n ? value\n : undefined;\n\nexport const normalizeCodexLocalImagePath = (\n imageUrl: string,\n platform: NodeJS.Platform = process.platform,\n): string => {\n if (!imageUrl.startsWith('file://')) {\n return imageUrl;\n }\n\n try {\n const parsed = new URL(imageUrl);\n const pathname = decodeURIComponent(parsed.pathname);\n const host = parsed.hostname.toLowerCase();\n\n if (platform === 'win32') {\n const windowsPath = pathname\n .replace(/\\//g, '\\\\')\n .replace(/^\\\\([A-Za-z]:)/, '$1');\n\n if (host && host !== 'localhost') {\n return `\\\\\\\\${parsed.hostname}${windowsPath}`;\n }\n\n return windowsPath;\n }\n\n if (host && host !== 'localhost') {\n return `//${parsed.hostname}${pathname}`;\n }\n\n return pathname;\n } catch {\n return decodeURIComponent(imageUrl.slice('file://'.length));\n }\n};\n\nconst extractTextFromMessage = (\n message: ChatCompletionMessageParam,\n): string => {\n const content = (message as any).content;\n if (typeof content === 'string') {\n return content;\n }\n\n if (Array.isArray(content)) {\n return content\n .map((part) => {\n if (!part || typeof part !== 'object') return '';\n\n if (part.type === 'text' && typeof part.text === 'string') {\n return part.text;\n }\n\n if (part.type === 'input_text' && typeof part.text === 'string') {\n return part.text;\n }\n\n return '';\n })\n .filter(Boolean)\n .join('\\n');\n }\n\n return '';\n};\n\nconst extractImageInputs = (\n message: ChatCompletionMessageParam,\n): Array<CodexImageInput | CodexLocalImageInput> => {\n const content = (message as any).content;\n if (!Array.isArray(content)) return [];\n\n const inputs: Array<CodexImageInput | CodexLocalImageInput> = [];\n for (const part of content) {\n if (!part || typeof part !== 'object') continue;\n\n const partType = String(part.type || '');\n const imageUrl =\n partType === 'image_url'\n ? toNonEmptyString(part.image_url?.url)\n : partType === 'input_image'\n ? toNonEmptyString(part.image_url || part.url)\n : undefined;\n const imageDetail = toCodexImageDetail(\n partType === 'image_url' ? part.image_url?.detail : part.detail,\n );\n\n if (!imageUrl) continue;\n\n if (\n imageUrl.startsWith('/') ||\n imageUrl.startsWith('./') ||\n imageUrl.startsWith('../') ||\n imageUrl.startsWith('file://')\n ) {\n const path = imageUrl.startsWith('file://')\n ? normalizeCodexLocalImagePath(imageUrl)\n : imageUrl;\n\n inputs.push({\n type: 'localImage',\n path,\n ...(imageDetail ? { detail: imageDetail } : {}),\n });\n continue;\n }\n\n inputs.push({\n type: 'image',\n url: imageUrl,\n ...(imageDetail ? { detail: imageDetail } : {}),\n });\n }\n\n return inputs;\n};\n\nexport const buildCodexTurnPayloadFromMessages = (\n messages: ChatCompletionMessageParam[],\n): {\n developerInstructions?: string;\n input: CodexTurnInput[];\n} => {\n const developerInstructionParts: string[] = [];\n const transcriptParts: string[] = [];\n const imageInputs: Array<CodexImageInput | CodexLocalImageInput> = [];\n\n for (const message of messages) {\n const role = String((message as any).role || 'user');\n const text = extractTextFromMessage(message);\n\n if (role === 'system') {\n if (text.trim()) developerInstructionParts.push(text.trim());\n continue;\n }\n\n const roleTag = role.toUpperCase();\n if (text.trim()) {\n transcriptParts.push(`[${roleTag}]\\n${text.trim()}`);\n } else {\n transcriptParts.push(`[${roleTag}]\\n(no text content)`);\n }\n\n if (role === 'user') {\n imageInputs.push(...extractImageInputs(message));\n }\n }\n\n const fullTranscript = transcriptParts.join('\\n\\n');\n const transcriptText =\n (fullTranscript.length > CODEX_TEXT_INPUT_MAX_LENGTH\n ? fullTranscript.slice(-CODEX_TEXT_INPUT_MAX_LENGTH)\n : fullTranscript) || 'Please answer the latest user request.';\n\n const input: CodexTurnInput[] = [\n {\n type: 'text',\n text: transcriptText,\n text_elements: [],\n },\n ...imageInputs,\n ];\n\n const developerInstructions = developerInstructionParts.length\n ? developerInstructionParts.join('\\n\\n')\n : undefined;\n\n return {\n developerInstructions,\n input,\n };\n};\n\nclass CodexAppServerConnection {\n private child: any;\n private lineReader: any;\n private pendingMessages: JsonRpcMessage[] = [];\n private lineBuffer: string[] = [];\n private nextRequestId = 1;\n private closed = false;\n private lastExitCode: number | null = null;\n private processErrorMessage: string | null = null;\n private stderrBuffer = '';\n\n private constructor(child: any, lineReader: any) {\n this.child = child;\n this.lineReader = lineReader;\n }\n\n static async create(): Promise<CodexAppServerConnection> {\n if (ifInBrowser) {\n throw new Error(\n 'codex app-server provider is not supported in browser runtime',\n );\n }\n\n const childProcessModuleName = 'node:child_process';\n const readlineModuleName = 'node:readline';\n const { spawn } = await import(childProcessModuleName);\n const readline = await import(readlineModuleName);\n\n const child = spawn('codex', ['app-server'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n if (!child.stdin || !child.stdout || !child.stderr) {\n throw new Error('failed to start codex app-server: stdio unavailable');\n }\n\n const lineReader = readline.createInterface({\n input: child.stdout,\n crlfDelay: Number.POSITIVE_INFINITY,\n });\n const connection = new CodexAppServerConnection(child, lineReader);\n connection.detachFromEventLoop();\n connection.attachProcessListeners();\n await connection.initializeHandshake();\n\n return connection;\n }\n\n isClosed(): boolean {\n return this.closed;\n }\n\n async runTurn({\n messages,\n modelConfig,\n stream,\n onChunk,\n params,\n abortSignal,\n onRecordEvent,\n }: {\n messages: ChatCompletionMessageParam[];\n modelConfig: IModelConfig;\n stream?: boolean;\n onChunk?: StreamingCallback;\n params?: CodexAppServerParamsResult['config'];\n abortSignal?: AbortSignal;\n onRecordEvent?: (event: CodexAppServerRecordEvent) => void;\n }): Promise<CodexTurnResult> {\n const isStreaming = !!(stream && onChunk);\n\n const { developerInstructions, input } =\n buildCodexTurnPayloadFromMessages(messages);\n\n let threadId: string | undefined;\n let turnId: string | undefined;\n let latestErrorMessage: string | undefined;\n let accumulatedText = '';\n let accumulatedReasoning = '';\n let latestUsage: OpenAI.CompletionUsage | undefined;\n\n const emitChunk = ({\n content,\n reasoning,\n isComplete,\n usage,\n }: {\n content: string;\n reasoning: string;\n isComplete: boolean;\n usage?: OpenAI.CompletionUsage;\n }) => {\n if (!isStreaming || !onChunk) return;\n const chunk: CodeGenerationChunk = {\n content,\n reasoning_content: reasoning,\n accumulated: accumulatedText,\n isComplete,\n usage,\n };\n onChunk(chunk);\n };\n\n try {\n const threadStartParams = {\n model: modelConfig.modelName,\n cwd: process.cwd(),\n approvalPolicy: 'never',\n sandbox: 'read-only',\n ephemeral: true,\n experimentalRawEvents: false,\n persistExtendedHistory: false,\n developerInstructions: developerInstructions || null,\n };\n onRecordEvent?.({\n type: 'request',\n protocol: {\n direction: 'client',\n method: 'thread/start',\n params: threadStartParams,\n },\n });\n const threadStartResponse = await this.request<CodexThreadStartResponse>({\n method: 'thread/start',\n params: threadStartParams,\n abortSignal,\n });\n onRecordEvent?.({\n type: 'chunk',\n protocol: {\n direction: 'server',\n method: 'thread/start',\n result: threadStartResponse,\n },\n });\n\n threadId = threadStartResponse?.thread?.id;\n if (!threadId) {\n throw new Error('thread/start did not return a thread id');\n }\n\n const turnStartParams = {\n ...params,\n threadId,\n input,\n };\n onRecordEvent?.({\n type: 'request',\n protocol: {\n direction: 'client',\n method: 'turn/start',\n params: turnStartParams,\n },\n });\n const turnStartResponse = await this.request<CodexTurnStartResponse>({\n method: 'turn/start',\n params: turnStartParams,\n abortSignal,\n });\n onRecordEvent?.({\n type: 'chunk',\n protocol: {\n direction: 'server',\n method: 'turn/start',\n result: turnStartResponse,\n },\n });\n\n turnId = turnStartResponse?.turn?.id;\n if (!turnId) {\n throw new Error('turn/start did not return a turn id');\n }\n\n let turnStatus: string | undefined;\n while (!turnStatus) {\n const message = await this.nextMessage({ abortSignal });\n\n if (this.isResponseMessage(message)) {\n // No concurrent requests in adapter runtime.\n continue;\n }\n\n if (this.isRequestMessage(message)) {\n await this.respondToServerRequest(message);\n continue;\n }\n\n const notification = message as JsonRpcNotification;\n const method = notification.method;\n const params = notification.params || {};\n const belongsToCurrentTurn =\n params.threadId === threadId &&\n (params.turnId === turnId || params.turn?.id === turnId);\n\n if (belongsToCurrentTurn) {\n onRecordEvent?.({\n type: 'chunk',\n protocol: {\n direction: 'server',\n method,\n params,\n },\n });\n }\n\n if (method === 'error') {\n const messageText =\n params.error?.message ||\n params.message ||\n 'codex app-server reported turn error';\n latestErrorMessage = String(messageText);\n continue;\n }\n\n if (\n method === 'item/agentMessage/delta' &&\n params.threadId === threadId &&\n params.turnId === turnId\n ) {\n const delta = String(params.delta || '');\n if (delta) {\n accumulatedText += delta;\n emitChunk({\n content: delta,\n reasoning: '',\n isComplete: false,\n });\n }\n continue;\n }\n\n if (\n (method === 'item/reasoning/summaryTextDelta' ||\n method === 'item/reasoning/textDelta') &&\n params.threadId === threadId &&\n params.turnId === turnId\n ) {\n const delta = String(params.delta || '');\n if (delta) {\n accumulatedReasoning += delta;\n emitChunk({\n content: '',\n reasoning: delta,\n isComplete: false,\n });\n }\n continue;\n }\n\n if (\n method === 'item/completed' &&\n params.threadId === threadId &&\n params.turnId === turnId &&\n params.item?.type === 'agentMessage' &&\n typeof params.item?.text === 'string' &&\n !accumulatedText\n ) {\n accumulatedText = params.item.text;\n continue;\n }\n\n if (\n method === 'thread/tokenUsage/updated' &&\n params.threadId === threadId &&\n params.turnId === turnId\n ) {\n latestUsage = this.mapUsage(params as CodexUsageNotification);\n continue;\n }\n\n if (\n method === 'turn/completed' &&\n params.threadId === threadId &&\n params.turn?.id === turnId\n ) {\n turnStatus = String(params.turn.status || '');\n latestErrorMessage =\n params.turn?.error?.message || latestErrorMessage || undefined;\n break;\n }\n }\n\n if (turnStatus !== 'completed') {\n throw new Error(\n latestErrorMessage ||\n `codex turn finished with status \"${turnStatus || 'unknown'}\"`,\n );\n }\n\n if (isStreaming) {\n emitChunk({\n content: '',\n reasoning: '',\n isComplete: true,\n usage: latestUsage,\n });\n }\n\n return {\n content: accumulatedText,\n reasoning_content: accumulatedReasoning || undefined,\n usage: latestUsage,\n isStreamed: isStreaming,\n protocolMetadata: {\n transport: 'json-rpc',\n threadId,\n turnId,\n turnStatus,\n },\n };\n } catch (error) {\n if (isAbortError(error) && threadId && turnId) {\n await this.request({\n method: 'turn/interrupt',\n params: {\n threadId,\n turnId,\n },\n deadlineAt: Date.now() + CODEX_INTERRUPT_TIMEOUT_MS,\n }).catch(() => {});\n }\n throw error;\n } finally {\n if (threadId) {\n await this.request({\n method: 'thread/unsubscribe',\n params: { threadId },\n deadlineAt: Date.now() + CODEX_DEFAULT_CLEANUP_TIMEOUT_MS,\n }).catch((error) => {\n warnCodex(\n `failed to unsubscribe codex thread ${threadId}: ${String(error)}`,\n );\n });\n }\n }\n }\n\n async dispose(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n\n try {\n this.lineReader?.close?.();\n } catch {}\n\n try {\n this.child?.stdin?.end?.();\n } catch {}\n\n try {\n this.child?.kill?.();\n } catch {}\n }\n\n private attachProcessListeners() {\n this.lineReader.on('line', (line: string) => {\n this.lineBuffer.push(line);\n });\n\n this.child.stderr.on('data', (chunk: Buffer | string) => {\n const text = Buffer.isBuffer(chunk)\n ? chunk.toString('utf8')\n : String(chunk);\n this.stderrBuffer += text;\n if (this.stderrBuffer.length > 8192) {\n this.stderrBuffer = this.stderrBuffer.slice(-8192);\n }\n });\n\n this.child.on('exit', (code: number | null) => {\n this.closed = true;\n this.lastExitCode = code;\n });\n\n this.child.on('error', (error: Error) => {\n this.closed = true;\n this.processErrorMessage = error.message;\n });\n }\n\n /**\n * Keep codex process reusable but let short-lived callers exit naturally.\n * Without unref, one-shot scripts/tests that call AI once can hang.\n */\n private detachFromEventLoop() {\n this.child.unref?.();\n this.child.stdin?.unref?.();\n this.child.stdout?.unref?.();\n this.child.stderr?.unref?.();\n }\n\n private async initializeHandshake() {\n const deadlineAt = Date.now() + CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS;\n await this.request({\n method: 'initialize',\n params: {\n clientInfo: {\n name: 'midscene_codex_provider',\n title: 'Midscene Codex Provider',\n version: '1.0.0',\n },\n capabilities: {\n experimentalApi: false,\n },\n },\n deadlineAt,\n });\n await this.sendMessage({\n method: 'initialized',\n });\n }\n\n private mapUsage(\n usage: CodexUsageNotification,\n ): OpenAI.CompletionUsage | undefined {\n const tokenUsage = usage.tokenUsage;\n const picked = tokenUsage?.last || tokenUsage?.total;\n if (!picked) return undefined;\n\n return {\n prompt_tokens: picked.inputTokens ?? 0,\n completion_tokens: picked.outputTokens ?? 0,\n total_tokens: picked.totalTokens ?? 0,\n prompt_tokens_details: { cached_tokens: picked.cachedInputTokens ?? 0 },\n completion_tokens_details: {\n reasoning_tokens: picked.reasoningOutputTokens ?? 0,\n },\n } satisfies OpenAI.CompletionUsage;\n }\n\n private isRequestMessage(message: JsonRpcMessage): message is JsonRpcRequest {\n return (\n typeof (message as any)?.method === 'string' &&\n (message as any)?.id !== undefined\n );\n }\n\n private isResponseMessage(\n message: JsonRpcMessage,\n ): message is JsonRpcResponse {\n return (\n (message as any)?.id !== undefined &&\n ((message as any)?.result !== undefined ||\n (message as any)?.error !== undefined) &&\n typeof (message as any)?.method !== 'string'\n );\n }\n\n private async request<T = unknown>({\n method,\n params,\n deadlineAt,\n abortSignal,\n }: {\n method: string;\n params: unknown;\n deadlineAt?: number;\n abortSignal?: AbortSignal;\n }): Promise<T> {\n abortSignal?.throwIfAborted();\n const requestId = this.nextRequestId++;\n\n await this.sendMessage({\n id: requestId,\n method,\n params,\n });\n\n while (true) {\n const message = await this.nextMessage({\n deadlineAt,\n abortSignal,\n includePending: false,\n });\n\n if (this.isResponseMessage(message) && message.id === requestId) {\n if (message.error) {\n throw new Error(\n `codex app-server ${method} failed: ${\n message.error.message || 'unknown error'\n }`,\n );\n }\n return (message.result || {}) as T;\n }\n\n if (this.isRequestMessage(message)) {\n await this.respondToServerRequest(message);\n continue;\n }\n\n // Keep unmatched notifications/other responses for later stream handling.\n this.pendingMessages.push(message);\n }\n }\n\n private async respondToServerRequest(request: JsonRpcRequest): Promise<void> {\n const requestId = request.id;\n const method = request.method;\n\n let result: unknown = {};\n if (method === 'item/commandExecution/requestApproval') {\n result = { decision: 'decline' };\n } else if (method === 'item/fileChange/requestApproval') {\n result = { decision: 'decline' };\n } else if (method === 'mcpServer/elicitation/request') {\n result = { action: 'cancel', content: null };\n } else if (method === 'item/tool/requestUserInput') {\n result = { answers: [] };\n } else {\n await this.sendMessage({\n id: requestId,\n error: {\n code: -32601,\n message: `unsupported server request: ${method}`,\n },\n });\n return;\n }\n\n await this.sendMessage({\n id: requestId,\n result,\n });\n }\n\n private async nextMessage({\n deadlineAt,\n abortSignal,\n includePending = true,\n }: {\n deadlineAt?: number;\n abortSignal?: AbortSignal;\n includePending?: boolean;\n }): Promise<JsonRpcMessage> {\n if (includePending && this.pendingMessages.length) {\n return this.pendingMessages.shift() as JsonRpcMessage;\n }\n\n while (true) {\n if (abortSignal?.aborted) {\n throw new Error('codex app-server request aborted');\n }\n\n if (deadlineAt && Date.now() > deadlineAt) {\n throw new Error('codex app-server request timed out');\n }\n\n if (this.lineBuffer.length) {\n const line = this.lineBuffer.shift()!;\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let parsed: JsonRpcMessage;\n try {\n parsed = JSON.parse(trimmed);\n } catch (error) {\n warnCodex(\n `ignored non-JSON message from codex app-server: ${trimmed}`,\n );\n continue;\n }\n\n return parsed;\n }\n\n if (this.closed) {\n throw this.createClosedConnectionError();\n }\n\n await new Promise((resolve) => setTimeout(resolve, 20));\n }\n }\n\n private async sendMessage(payload: Record<string, unknown>): Promise<void> {\n if (this.closed) {\n throw this.createClosedConnectionError();\n }\n\n const line = JSON.stringify(payload);\n await new Promise<void>((resolve, reject) => {\n this.child.stdin.write(`${line}\\n`, (error: Error | null | undefined) => {\n if (error) {\n reject(\n new Error(\n `failed writing to codex app-server stdin: ${error.message}`,\n ),\n );\n return;\n }\n resolve();\n });\n });\n }\n\n private createClosedConnectionError(): Error {\n const stderr = this.stderrBuffer.trim();\n if (this.processErrorMessage) {\n return new Error(\n stderr\n ? `codex app-server process error: ${this.processErrorMessage}. stderr=${stderr}`\n : `codex app-server process error: ${this.processErrorMessage}`,\n );\n }\n\n return new Error(\n stderr\n ? `codex app-server connection closed (exitCode=${this.lastExitCode}). stderr=${stderr}`\n : `codex app-server connection closed (exitCode=${this.lastExitCode})`,\n );\n }\n}\n\nclass CodexAppServerConnectionManager {\n private connection: CodexAppServerConnection | null = null;\n private runner = new SerializedRunner();\n\n async runTurn({\n messages,\n modelConfig,\n stream,\n onChunk,\n params,\n abortSignal,\n onRecordEvent,\n }: {\n messages: ChatCompletionMessageParam[];\n modelConfig: IModelConfig;\n stream?: boolean;\n onChunk?: StreamingCallback;\n params?: CodexAppServerParamsResult['config'];\n abortSignal?: AbortSignal;\n onRecordEvent?: (event: CodexAppServerRecordEvent) => void;\n }): Promise<CodexTurnResult> {\n return this.runner.run(async () => {\n abortSignal?.throwIfAborted();\n const connection = await this.getConnection();\n abortSignal?.throwIfAborted();\n try {\n return await connection.runTurn({\n messages,\n modelConfig,\n stream,\n onChunk,\n params,\n abortSignal,\n onRecordEvent,\n });\n } catch (error) {\n if (connection.isClosed() || !isAbortError(error)) {\n await this.resetConnection();\n }\n throw error;\n }\n });\n }\n\n async shutdownForTests(): Promise<void> {\n await this.resetConnection();\n }\n\n private async getConnection(): Promise<CodexAppServerConnection> {\n if (!this.connection || this.connection.isClosed()) {\n this.connection = await CodexAppServerConnection.create();\n debugCodex('started long-lived codex app-server connection');\n }\n return this.connection;\n }\n\n private async resetConnection(): Promise<void> {\n if (!this.connection) return;\n const staleConnection = this.connection;\n this.connection = null;\n await staleConnection.dispose();\n debugCodex('reset codex app-server connection');\n }\n}\n\nconst codexConnectionManager = new CodexAppServerConnectionManager();\n\nexport async function callAIWithCodexAppServer(\n messages: ChatCompletionMessageParam[],\n modelConfig: IModelConfig,\n options?: {\n stream?: boolean;\n onChunk?: StreamingCallback;\n params?: CodexAppServerParamsResult['config'];\n abortSignal?: AbortSignal;\n onRecordEvent?: (event: CodexAppServerRecordEvent) => void;\n },\n): Promise<CodexTurnResult> {\n if (ifInBrowser) {\n throw new Error(\n 'codex app-server provider is not supported in browser runtime',\n );\n }\n\n return codexConnectionManager.runTurn({\n messages,\n modelConfig,\n stream: options?.stream,\n onChunk: options?.onChunk,\n params: options?.params,\n abortSignal: options?.abortSignal,\n onRecordEvent: options?.onRecordEvent,\n });\n}\n\nexport async function __shutdownCodexAppServerForTests() {\n await codexConnectionManager.shutdownForTests();\n}\n"],"names":["CODEX_PROVIDER_SCHEME","CODEX_INTERRUPT_TIMEOUT_MS","CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS","CODEX_DEFAULT_CLEANUP_TIMEOUT_MS","CODEX_TEXT_INPUT_MAX_LENGTH","debugCodex","getDebug","warnCodex","SerializedRunner","work","previous","release","Promise","resolve","isCodexAppServerProvider","baseURL","isAbortError","error","Error","message","String","toNonEmptyString","value","trimmed","undefined","toCodexImageDetail","normalizeCodexLocalImagePath","imageUrl","platform","process","parsed","URL","pathname","decodeURIComponent","host","windowsPath","extractTextFromMessage","content","Array","part","Boolean","extractImageInputs","inputs","partType","imageDetail","path","buildCodexTurnPayloadFromMessages","messages","developerInstructionParts","transcriptParts","imageInputs","role","text","roleTag","fullTranscript","transcriptText","input","developerInstructions","CodexAppServerConnection","ifInBrowser","childProcessModuleName","readlineModuleName","spawn","readline","child","lineReader","Number","connection","modelConfig","stream","onChunk","params","abortSignal","onRecordEvent","isStreaming","threadId","turnId","latestErrorMessage","accumulatedText","accumulatedReasoning","latestUsage","emitChunk","reasoning","isComplete","usage","chunk","threadStartParams","threadStartResponse","turnStartParams","turnStartResponse","turnStatus","notification","method","belongsToCurrentTurn","messageText","delta","Date","line","Buffer","code","deadlineAt","tokenUsage","picked","requestId","request","result","includePending","JSON","setTimeout","payload","reject","stderr","CodexAppServerConnectionManager","staleConnection","codexConnectionManager","callAIWithCodexAppServer","options","__shutdownCodexAppServerForTests"],"mappings":"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"}
1
+ {"version":3,"file":"ai-model/service-caller/codex/codex-app-server.mjs","sources":["../../../../../src/ai-model/service-caller/codex/codex-app-server.ts"],"sourcesContent":["import type { CodeGenerationChunk, StreamingCallback } from '@/types';\nimport type { IModelConfig } from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport type OpenAI from 'openai';\nimport type {\n CodexAppServerParamsResult,\n ResolveImageDetail,\n} from '../../model-adapter/types';\nimport type { ConversationMessage, ModelCallMessages } from '../types';\n\nconst CODEX_PROVIDER_SCHEME = 'codex://';\nconst CODEX_INTERRUPT_TIMEOUT_MS = 5_000;\nconst CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS = 15 * 1000;\nconst CODEX_DEFAULT_CLEANUP_TIMEOUT_MS = 8 * 1000;\nconst CODEX_TEXT_INPUT_MAX_LENGTH = 256 * 1024;\n\nconst debugCodex = getDebug('ai:call:codex');\nconst warnCodex = getDebug('ai:call:codex', { console: true });\n\ntype JsonRpcRequest = {\n id: string | number;\n method: string;\n params?: unknown;\n};\n\ntype JsonRpcResponse = {\n id: string | number;\n result?: unknown;\n error?: {\n code?: number;\n message?: string;\n data?: unknown;\n };\n};\n\ntype JsonRpcNotification = {\n method: string;\n params?: Record<string, any>;\n};\n\ntype JsonRpcMessage = JsonRpcRequest | JsonRpcResponse | JsonRpcNotification;\n\ntype CodexTextInput = {\n type: 'text';\n text: string;\n text_elements: any[];\n};\n\n// Codex app-server v2 accepts `detail` on both image input variants:\n// https://github.com/openai/codex/blob/main/codex-rs/app-server-protocol/src/protocol/v2/turn.rs#L276-L329\n// Codex has also reported `original` as a supported value in production:\n// https://github.com/openai/codex/issues/24797\ntype CodexImageInput = {\n type: 'image';\n url: string;\n detail?: CodexImageDetail;\n};\n\ntype CodexLocalImageInput = {\n type: 'localImage';\n path: string;\n detail?: CodexImageDetail;\n};\n\ntype CodexTurnInput = CodexTextInput | CodexImageInput | CodexLocalImageInput;\n\ntype CodexImageDetail = 'auto' | 'low' | 'high' | 'original';\n\nexport type CodexAppServerRecordEvent = {\n type: 'request' | 'chunk';\n protocol: Record<string, unknown>;\n};\n\ntype CodexTurnResult = {\n content: string;\n reasoning_content?: string;\n usage?: OpenAI.CompletionUsage;\n isStreamed: boolean;\n protocolMetadata: {\n transport: 'json-rpc';\n threadId: string;\n turnId: string;\n turnStatus: string;\n };\n};\n\ntype CodexTurnStartResponse = {\n turn?: {\n id?: string;\n };\n};\n\ntype CodexThreadStartResponse = {\n thread?: {\n id?: string;\n };\n};\n\ntype CodexUsageNotification = {\n threadId?: string;\n turnId?: string;\n tokenUsage?: {\n total?: {\n totalTokens?: number;\n inputTokens?: number;\n cachedInputTokens?: number;\n outputTokens?: number;\n reasoningOutputTokens?: number;\n };\n last?: {\n totalTokens?: number;\n inputTokens?: number;\n cachedInputTokens?: number;\n outputTokens?: number;\n reasoningOutputTokens?: number;\n };\n };\n};\n\nclass SerializedRunner {\n private tail: Promise<void> = Promise.resolve();\n\n async run<T>(work: () => Promise<T>): Promise<T> {\n const previous = this.tail;\n let release!: () => void;\n this.tail = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n await previous;\n try {\n return await work();\n } finally {\n release();\n }\n }\n}\n\nexport const isCodexAppServerProvider = (baseURL?: string): boolean => {\n if (!baseURL) return false;\n return baseURL.trim().toLowerCase().startsWith(CODEX_PROVIDER_SCHEME);\n};\n\nconst isAbortError = (error: unknown): boolean => {\n if (!error) return false;\n if (error instanceof Error && error.name === 'AbortError') return true;\n const message =\n error instanceof Error ? error.message : String(error ?? 'unknown error');\n return /aborted|abort/i.test(message);\n};\n\nconst toNonEmptyString = (value: unknown): string | undefined => {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed || undefined;\n};\n\nexport const normalizeCodexLocalImagePath = (\n imageUrl: string,\n platform: NodeJS.Platform = process.platform,\n): string => {\n if (!imageUrl.startsWith('file://')) {\n return imageUrl;\n }\n\n try {\n const parsed = new URL(imageUrl);\n const pathname = decodeURIComponent(parsed.pathname);\n const host = parsed.hostname.toLowerCase();\n\n if (platform === 'win32') {\n const windowsPath = pathname\n .replace(/\\//g, '\\\\')\n .replace(/^\\\\([A-Za-z]:)/, '$1');\n\n if (host && host !== 'localhost') {\n return `\\\\\\\\${parsed.hostname}${windowsPath}`;\n }\n\n return windowsPath;\n }\n\n if (host && host !== 'localhost') {\n return `//${parsed.hostname}${pathname}`;\n }\n\n return pathname;\n } catch {\n return decodeURIComponent(imageUrl.slice('file://'.length));\n }\n};\n\nconst extractTextFromMessage = (message: ConversationMessage): string => {\n const { content } = message;\n if (typeof content === 'string') {\n return content;\n }\n return content\n .map((part) => (part.type === 'text' ? part.text : ''))\n .filter(Boolean)\n .join('\\n');\n};\n\nconst extractImageInputs = (\n message: ConversationMessage,\n resolveImageDetail: ResolveImageDetail,\n): Array<CodexImageInput | CodexLocalImageInput> => {\n const { content } = message;\n if (!Array.isArray(content)) {\n return [];\n }\n\n const inputs: Array<CodexImageInput | CodexLocalImageInput> = [];\n for (const part of content) {\n if (part.type !== 'image') {\n continue;\n }\n const imageUrl = toNonEmptyString(part.url);\n const detail = resolveImageDetail({ imageDetail: part.detail });\n if (!imageUrl) {\n continue;\n }\n\n if (\n imageUrl.startsWith('/') ||\n imageUrl.startsWith('./') ||\n imageUrl.startsWith('../') ||\n imageUrl.startsWith('file://')\n ) {\n const path = imageUrl.startsWith('file://')\n ? normalizeCodexLocalImagePath(imageUrl)\n : imageUrl;\n\n inputs.push({\n type: 'localImage',\n path,\n detail,\n });\n continue;\n }\n\n inputs.push({\n type: 'image',\n url: imageUrl,\n detail,\n });\n }\n\n return inputs;\n};\n\nexport const buildCodexTurnPayloadFromMessages = (\n messages: ModelCallMessages,\n resolveImageDetail: ResolveImageDetail,\n): {\n developerInstructions?: string;\n input: CodexTurnInput[];\n} => {\n const developerInstructionParts: string[] = [];\n const transcriptParts: string[] = [];\n const imageInputs: Array<CodexImageInput | CodexLocalImageInput> = [];\n\n for (const entry of messages) {\n const message: ConversationMessage = (() => {\n if ('role' in entry) {\n return entry;\n }\n if (entry.type === 'input-message') {\n return entry.message;\n }\n if (entry.output.type !== 'chat-completion') {\n throw new Error(\n 'Cannot replay Responses output in a Codex conversation',\n );\n }\n return {\n role: 'assistant',\n content: entry.output.rawValue.content ?? '',\n };\n })();\n const { role } = message;\n const text = extractTextFromMessage(message);\n\n if (role === 'system') {\n if (text.trim()) developerInstructionParts.push(text.trim());\n continue;\n }\n\n const roleTag = role.toUpperCase();\n if (text.trim()) {\n transcriptParts.push(`[${roleTag}]\\n${text.trim()}`);\n } else {\n transcriptParts.push(`[${roleTag}]\\n(no text content)`);\n }\n\n if (role === 'user') {\n imageInputs.push(...extractImageInputs(message, resolveImageDetail));\n }\n }\n\n const fullTranscript = transcriptParts.join('\\n\\n');\n const transcriptText =\n (fullTranscript.length > CODEX_TEXT_INPUT_MAX_LENGTH\n ? fullTranscript.slice(-CODEX_TEXT_INPUT_MAX_LENGTH)\n : fullTranscript) || 'Please answer the latest user request.';\n\n const input: CodexTurnInput[] = [\n {\n type: 'text',\n text: transcriptText,\n text_elements: [],\n },\n ...imageInputs,\n ];\n\n const developerInstructions = developerInstructionParts.length\n ? developerInstructionParts.join('\\n\\n')\n : undefined;\n\n return {\n developerInstructions,\n input,\n };\n};\n\nclass CodexAppServerConnection {\n private child: any;\n private lineReader: any;\n private pendingMessages: JsonRpcMessage[] = [];\n private lineBuffer: string[] = [];\n private nextRequestId = 1;\n private closed = false;\n private lastExitCode: number | null = null;\n private processErrorMessage: string | null = null;\n private stderrBuffer = '';\n\n private constructor(child: any, lineReader: any) {\n this.child = child;\n this.lineReader = lineReader;\n }\n\n static async create(): Promise<CodexAppServerConnection> {\n if (ifInBrowser) {\n throw new Error(\n 'codex app-server provider is not supported in browser runtime',\n );\n }\n\n const childProcessModuleName = 'node:child_process';\n const readlineModuleName = 'node:readline';\n const { spawn } = await import(childProcessModuleName);\n const readline = await import(readlineModuleName);\n\n const child = spawn('codex', ['app-server'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n if (!child.stdin || !child.stdout || !child.stderr) {\n throw new Error('failed to start codex app-server: stdio unavailable');\n }\n\n const lineReader = readline.createInterface({\n input: child.stdout,\n crlfDelay: Number.POSITIVE_INFINITY,\n });\n const connection = new CodexAppServerConnection(child, lineReader);\n connection.detachFromEventLoop();\n connection.attachProcessListeners();\n await connection.initializeHandshake();\n\n return connection;\n }\n\n isClosed(): boolean {\n return this.closed;\n }\n\n async runTurn({\n messages,\n resolveImageDetail,\n modelConfig,\n stream,\n onChunk,\n params,\n abortSignal,\n onRecordEvent,\n }: {\n messages: ModelCallMessages;\n resolveImageDetail: ResolveImageDetail;\n modelConfig: IModelConfig;\n stream?: boolean;\n onChunk?: StreamingCallback;\n params?: CodexAppServerParamsResult['config'];\n abortSignal?: AbortSignal;\n onRecordEvent?: (event: CodexAppServerRecordEvent) => void;\n }): Promise<CodexTurnResult> {\n const isStreaming = !!(stream && onChunk);\n\n const { developerInstructions, input } = buildCodexTurnPayloadFromMessages(\n messages,\n resolveImageDetail,\n );\n\n let threadId: string | undefined;\n let turnId: string | undefined;\n let latestErrorMessage: string | undefined;\n let accumulatedText = '';\n let accumulatedReasoning = '';\n let latestUsage: OpenAI.CompletionUsage | undefined;\n\n const emitChunk = ({\n content,\n reasoning,\n isComplete,\n usage,\n }: {\n content: string;\n reasoning: string;\n isComplete: boolean;\n usage?: OpenAI.CompletionUsage;\n }) => {\n if (!isStreaming || !onChunk) return;\n const chunk: CodeGenerationChunk = {\n content,\n reasoning_content: reasoning,\n accumulated: accumulatedText,\n isComplete,\n usage,\n };\n onChunk(chunk);\n };\n\n try {\n const threadStartParams = {\n model: modelConfig.modelName,\n cwd: process.cwd(),\n approvalPolicy: 'never',\n sandbox: 'read-only',\n ephemeral: true,\n experimentalRawEvents: false,\n persistExtendedHistory: false,\n developerInstructions: developerInstructions || null,\n };\n onRecordEvent?.({\n type: 'request',\n protocol: {\n direction: 'client',\n method: 'thread/start',\n params: threadStartParams,\n },\n });\n const threadStartResponse = await this.request<CodexThreadStartResponse>({\n method: 'thread/start',\n params: threadStartParams,\n abortSignal,\n });\n onRecordEvent?.({\n type: 'chunk',\n protocol: {\n direction: 'server',\n method: 'thread/start',\n result: threadStartResponse,\n },\n });\n\n threadId = threadStartResponse?.thread?.id;\n if (!threadId) {\n throw new Error('thread/start did not return a thread id');\n }\n\n const turnStartParams = {\n ...params,\n threadId,\n input,\n };\n onRecordEvent?.({\n type: 'request',\n protocol: {\n direction: 'client',\n method: 'turn/start',\n params: turnStartParams,\n },\n });\n const turnStartResponse = await this.request<CodexTurnStartResponse>({\n method: 'turn/start',\n params: turnStartParams,\n abortSignal,\n });\n onRecordEvent?.({\n type: 'chunk',\n protocol: {\n direction: 'server',\n method: 'turn/start',\n result: turnStartResponse,\n },\n });\n\n turnId = turnStartResponse?.turn?.id;\n if (!turnId) {\n throw new Error('turn/start did not return a turn id');\n }\n\n let turnStatus: string | undefined;\n while (!turnStatus) {\n const message = await this.nextMessage({ abortSignal });\n\n if (this.isResponseMessage(message)) {\n // No concurrent requests in adapter runtime.\n continue;\n }\n\n if (this.isRequestMessage(message)) {\n await this.respondToServerRequest(message);\n continue;\n }\n\n const notification = message as JsonRpcNotification;\n const method = notification.method;\n const params = notification.params || {};\n const belongsToCurrentTurn =\n params.threadId === threadId &&\n (params.turnId === turnId || params.turn?.id === turnId);\n\n if (belongsToCurrentTurn) {\n onRecordEvent?.({\n type: 'chunk',\n protocol: {\n direction: 'server',\n method,\n params,\n },\n });\n }\n\n if (method === 'error') {\n const messageText =\n params.error?.message ||\n params.message ||\n 'codex app-server reported turn error';\n latestErrorMessage = String(messageText);\n continue;\n }\n\n if (\n method === 'item/agentMessage/delta' &&\n params.threadId === threadId &&\n params.turnId === turnId\n ) {\n const delta = String(params.delta || '');\n if (delta) {\n accumulatedText += delta;\n emitChunk({\n content: delta,\n reasoning: '',\n isComplete: false,\n });\n }\n continue;\n }\n\n if (\n (method === 'item/reasoning/summaryTextDelta' ||\n method === 'item/reasoning/textDelta') &&\n params.threadId === threadId &&\n params.turnId === turnId\n ) {\n const delta = String(params.delta || '');\n if (delta) {\n accumulatedReasoning += delta;\n emitChunk({\n content: '',\n reasoning: delta,\n isComplete: false,\n });\n }\n continue;\n }\n\n if (\n method === 'item/completed' &&\n params.threadId === threadId &&\n params.turnId === turnId &&\n params.item?.type === 'agentMessage' &&\n typeof params.item?.text === 'string' &&\n !accumulatedText\n ) {\n accumulatedText = params.item.text;\n continue;\n }\n\n if (\n method === 'thread/tokenUsage/updated' &&\n params.threadId === threadId &&\n params.turnId === turnId\n ) {\n latestUsage = this.mapUsage(params as CodexUsageNotification);\n continue;\n }\n\n if (\n method === 'turn/completed' &&\n params.threadId === threadId &&\n params.turn?.id === turnId\n ) {\n turnStatus = String(params.turn.status || '');\n latestErrorMessage =\n params.turn?.error?.message || latestErrorMessage || undefined;\n break;\n }\n }\n\n if (turnStatus !== 'completed') {\n throw new Error(\n latestErrorMessage ||\n `codex turn finished with status \"${turnStatus || 'unknown'}\"`,\n );\n }\n\n if (isStreaming) {\n emitChunk({\n content: '',\n reasoning: '',\n isComplete: true,\n usage: latestUsage,\n });\n }\n\n return {\n content: accumulatedText,\n reasoning_content: accumulatedReasoning || undefined,\n usage: latestUsage,\n isStreamed: isStreaming,\n protocolMetadata: {\n transport: 'json-rpc',\n threadId,\n turnId,\n turnStatus,\n },\n };\n } catch (error) {\n if (isAbortError(error) && threadId && turnId) {\n await this.request({\n method: 'turn/interrupt',\n params: {\n threadId,\n turnId,\n },\n deadlineAt: Date.now() + CODEX_INTERRUPT_TIMEOUT_MS,\n }).catch(() => {});\n }\n throw error;\n } finally {\n if (threadId) {\n await this.request({\n method: 'thread/unsubscribe',\n params: { threadId },\n deadlineAt: Date.now() + CODEX_DEFAULT_CLEANUP_TIMEOUT_MS,\n }).catch((error) => {\n warnCodex(\n `failed to unsubscribe codex thread ${threadId}: ${String(error)}`,\n );\n });\n }\n }\n }\n\n async dispose(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n\n try {\n this.lineReader?.close?.();\n } catch {}\n\n try {\n this.child?.stdin?.end?.();\n } catch {}\n\n try {\n this.child?.kill?.();\n } catch {}\n }\n\n private attachProcessListeners() {\n this.lineReader.on('line', (line: string) => {\n this.lineBuffer.push(line);\n });\n\n this.child.stderr.on('data', (chunk: Buffer | string) => {\n const text = Buffer.isBuffer(chunk)\n ? chunk.toString('utf8')\n : String(chunk);\n this.stderrBuffer += text;\n if (this.stderrBuffer.length > 8192) {\n this.stderrBuffer = this.stderrBuffer.slice(-8192);\n }\n });\n\n this.child.on('exit', (code: number | null) => {\n this.closed = true;\n this.lastExitCode = code;\n });\n\n this.child.on('error', (error: Error) => {\n this.closed = true;\n this.processErrorMessage = error.message;\n });\n }\n\n /**\n * Keep codex process reusable but let short-lived callers exit naturally.\n * Without unref, one-shot scripts/tests that call AI once can hang.\n */\n private detachFromEventLoop() {\n this.child.unref?.();\n this.child.stdin?.unref?.();\n this.child.stdout?.unref?.();\n this.child.stderr?.unref?.();\n }\n\n private async initializeHandshake() {\n const deadlineAt = Date.now() + CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS;\n await this.request({\n method: 'initialize',\n params: {\n clientInfo: {\n name: 'midscene_codex_provider',\n title: 'Midscene Codex Provider',\n version: '1.0.0',\n },\n capabilities: {\n experimentalApi: false,\n },\n },\n deadlineAt,\n });\n await this.sendMessage({\n method: 'initialized',\n });\n }\n\n private mapUsage(\n usage: CodexUsageNotification,\n ): OpenAI.CompletionUsage | undefined {\n const tokenUsage = usage.tokenUsage;\n const picked = tokenUsage?.last || tokenUsage?.total;\n if (!picked) return undefined;\n\n return {\n prompt_tokens: picked.inputTokens ?? 0,\n completion_tokens: picked.outputTokens ?? 0,\n total_tokens: picked.totalTokens ?? 0,\n prompt_tokens_details: { cached_tokens: picked.cachedInputTokens ?? 0 },\n completion_tokens_details: {\n reasoning_tokens: picked.reasoningOutputTokens ?? 0,\n },\n } satisfies OpenAI.CompletionUsage;\n }\n\n private isRequestMessage(message: JsonRpcMessage): message is JsonRpcRequest {\n return (\n typeof (message as any)?.method === 'string' &&\n (message as any)?.id !== undefined\n );\n }\n\n private isResponseMessage(\n message: JsonRpcMessage,\n ): message is JsonRpcResponse {\n return (\n (message as any)?.id !== undefined &&\n ((message as any)?.result !== undefined ||\n (message as any)?.error !== undefined) &&\n typeof (message as any)?.method !== 'string'\n );\n }\n\n private async request<T = unknown>({\n method,\n params,\n deadlineAt,\n abortSignal,\n }: {\n method: string;\n params: unknown;\n deadlineAt?: number;\n abortSignal?: AbortSignal;\n }): Promise<T> {\n abortSignal?.throwIfAborted();\n const requestId = this.nextRequestId++;\n\n await this.sendMessage({\n id: requestId,\n method,\n params,\n });\n\n while (true) {\n const message = await this.nextMessage({\n deadlineAt,\n abortSignal,\n includePending: false,\n });\n\n if (this.isResponseMessage(message) && message.id === requestId) {\n if (message.error) {\n throw new Error(\n `codex app-server ${method} failed: ${\n message.error.message || 'unknown error'\n }`,\n );\n }\n return (message.result || {}) as T;\n }\n\n if (this.isRequestMessage(message)) {\n await this.respondToServerRequest(message);\n continue;\n }\n\n // Keep unmatched notifications/other responses for later stream handling.\n this.pendingMessages.push(message);\n }\n }\n\n private async respondToServerRequest(request: JsonRpcRequest): Promise<void> {\n const requestId = request.id;\n const method = request.method;\n\n let result: unknown = {};\n if (method === 'item/commandExecution/requestApproval') {\n result = { decision: 'decline' };\n } else if (method === 'item/fileChange/requestApproval') {\n result = { decision: 'decline' };\n } else if (method === 'mcpServer/elicitation/request') {\n result = { action: 'cancel', content: null };\n } else if (method === 'item/tool/requestUserInput') {\n result = { answers: [] };\n } else {\n await this.sendMessage({\n id: requestId,\n error: {\n code: -32601,\n message: `unsupported server request: ${method}`,\n },\n });\n return;\n }\n\n await this.sendMessage({\n id: requestId,\n result,\n });\n }\n\n private async nextMessage({\n deadlineAt,\n abortSignal,\n includePending = true,\n }: {\n deadlineAt?: number;\n abortSignal?: AbortSignal;\n includePending?: boolean;\n }): Promise<JsonRpcMessage> {\n if (includePending && this.pendingMessages.length) {\n return this.pendingMessages.shift() as JsonRpcMessage;\n }\n\n while (true) {\n if (abortSignal?.aborted) {\n throw new Error('codex app-server request aborted');\n }\n\n if (deadlineAt && Date.now() > deadlineAt) {\n throw new Error('codex app-server request timed out');\n }\n\n if (this.lineBuffer.length) {\n const line = this.lineBuffer.shift()!;\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let parsed: JsonRpcMessage;\n try {\n parsed = JSON.parse(trimmed);\n } catch (error) {\n warnCodex(\n `ignored non-JSON message from codex app-server: ${trimmed}`,\n );\n continue;\n }\n\n return parsed;\n }\n\n if (this.closed) {\n throw this.createClosedConnectionError();\n }\n\n await new Promise((resolve) => setTimeout(resolve, 20));\n }\n }\n\n private async sendMessage(payload: Record<string, unknown>): Promise<void> {\n if (this.closed) {\n throw this.createClosedConnectionError();\n }\n\n const line = JSON.stringify(payload);\n await new Promise<void>((resolve, reject) => {\n this.child.stdin.write(`${line}\\n`, (error: Error | null | undefined) => {\n if (error) {\n reject(\n new Error(\n `failed writing to codex app-server stdin: ${error.message}`,\n ),\n );\n return;\n }\n resolve();\n });\n });\n }\n\n private createClosedConnectionError(): Error {\n const stderr = this.stderrBuffer.trim();\n if (this.processErrorMessage) {\n return new Error(\n stderr\n ? `codex app-server process error: ${this.processErrorMessage}. stderr=${stderr}`\n : `codex app-server process error: ${this.processErrorMessage}`,\n );\n }\n\n return new Error(\n stderr\n ? `codex app-server connection closed (exitCode=${this.lastExitCode}). stderr=${stderr}`\n : `codex app-server connection closed (exitCode=${this.lastExitCode})`,\n );\n }\n}\n\nclass CodexAppServerConnectionManager {\n private connection: CodexAppServerConnection | null = null;\n private runner = new SerializedRunner();\n\n async runTurn({\n messages,\n resolveImageDetail,\n modelConfig,\n stream,\n onChunk,\n params,\n abortSignal,\n onRecordEvent,\n }: {\n messages: ModelCallMessages;\n resolveImageDetail: ResolveImageDetail;\n modelConfig: IModelConfig;\n stream?: boolean;\n onChunk?: StreamingCallback;\n params?: CodexAppServerParamsResult['config'];\n abortSignal?: AbortSignal;\n onRecordEvent?: (event: CodexAppServerRecordEvent) => void;\n }): Promise<CodexTurnResult> {\n return this.runner.run(async () => {\n abortSignal?.throwIfAborted();\n const connection = await this.getConnection();\n abortSignal?.throwIfAborted();\n try {\n return await connection.runTurn({\n messages,\n resolveImageDetail,\n modelConfig,\n stream,\n onChunk,\n params,\n abortSignal,\n onRecordEvent,\n });\n } catch (error) {\n if (connection.isClosed() || !isAbortError(error)) {\n await this.resetConnection();\n }\n throw error;\n }\n });\n }\n\n async shutdownForTests(): Promise<void> {\n await this.resetConnection();\n }\n\n private async getConnection(): Promise<CodexAppServerConnection> {\n if (!this.connection || this.connection.isClosed()) {\n this.connection = await CodexAppServerConnection.create();\n debugCodex('started long-lived codex app-server connection');\n }\n return this.connection;\n }\n\n private async resetConnection(): Promise<void> {\n if (!this.connection) return;\n const staleConnection = this.connection;\n this.connection = null;\n await staleConnection.dispose();\n debugCodex('reset codex app-server connection');\n }\n}\n\nconst codexConnectionManager = new CodexAppServerConnectionManager();\n\nexport async function callAIWithCodexAppServer(\n messages: ModelCallMessages,\n modelConfig: IModelConfig,\n options: {\n resolveImageDetail: ResolveImageDetail;\n stream?: boolean;\n onChunk?: StreamingCallback;\n params?: CodexAppServerParamsResult['config'];\n abortSignal?: AbortSignal;\n onRecordEvent?: (event: CodexAppServerRecordEvent) => void;\n },\n): Promise<CodexTurnResult> {\n if (ifInBrowser) {\n throw new Error(\n 'codex app-server provider is not supported in browser runtime',\n );\n }\n\n return codexConnectionManager.runTurn({\n messages,\n modelConfig,\n resolveImageDetail: options.resolveImageDetail,\n stream: options?.stream,\n onChunk: options?.onChunk,\n params: options?.params,\n abortSignal: options?.abortSignal,\n onRecordEvent: options?.onRecordEvent,\n });\n}\n\nexport async function __shutdownCodexAppServerForTests() {\n await codexConnectionManager.shutdownForTests();\n}\n"],"names":["CODEX_PROVIDER_SCHEME","CODEX_INTERRUPT_TIMEOUT_MS","CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS","CODEX_DEFAULT_CLEANUP_TIMEOUT_MS","CODEX_TEXT_INPUT_MAX_LENGTH","debugCodex","getDebug","warnCodex","SerializedRunner","work","previous","release","Promise","resolve","isCodexAppServerProvider","baseURL","isAbortError","error","Error","message","String","toNonEmptyString","value","trimmed","undefined","normalizeCodexLocalImagePath","imageUrl","platform","process","parsed","URL","pathname","decodeURIComponent","host","windowsPath","extractTextFromMessage","content","part","Boolean","extractImageInputs","resolveImageDetail","Array","inputs","detail","path","buildCodexTurnPayloadFromMessages","messages","developerInstructionParts","transcriptParts","imageInputs","entry","role","text","roleTag","fullTranscript","transcriptText","input","developerInstructions","CodexAppServerConnection","ifInBrowser","childProcessModuleName","readlineModuleName","spawn","readline","child","lineReader","Number","connection","modelConfig","stream","onChunk","params","abortSignal","onRecordEvent","isStreaming","threadId","turnId","latestErrorMessage","accumulatedText","accumulatedReasoning","latestUsage","emitChunk","reasoning","isComplete","usage","chunk","threadStartParams","threadStartResponse","turnStartParams","turnStartResponse","turnStatus","notification","method","belongsToCurrentTurn","messageText","delta","Date","line","Buffer","code","deadlineAt","tokenUsage","picked","requestId","request","result","includePending","JSON","setTimeout","payload","reject","stderr","CodexAppServerConnectionManager","staleConnection","codexConnectionManager","callAIWithCodexAppServer","options","__shutdownCodexAppServerForTests"],"mappings":";;;;;;;;;;;;AAWA,MAAMA,wBAAwB;AAC9B,MAAMC,6BAA6B;AACnC,MAAMC,yCAAyC;AAC/C,MAAMC,mCAAmC;AACzC,MAAMC,8BAA8B;AAEpC,MAAMC,aAAaC,SAAS;AAC5B,MAAMC,YAAYD,SAAS,iBAAiB;IAAE,SAAS;AAAK;AAsG5D,MAAME;IAGJ,MAAM,IAAOC,IAAsB,EAAc;QAC/C,MAAMC,WAAW,IAAI,CAAC,IAAI;QAC1B,IAAIC;QACJ,IAAI,CAAC,IAAI,GAAG,IAAIC,QAAc,CAACC;YAC7BF,UAAUE;QACZ;QAEA,MAAMH;QACN,IAAI;YACF,OAAO,MAAMD;QACf,SAAU;YACRE;QACF;IACF;;QAfA,uBAAQ,QAAsBC,QAAQ,OAAO;;AAgB/C;AAEO,MAAME,2BAA2B,CAACC;IACvC,IAAI,CAACA,SAAS,OAAO;IACrB,OAAOA,QAAQ,IAAI,GAAG,WAAW,GAAG,UAAU,CAACf;AACjD;AAEA,MAAMgB,eAAe,CAACC;IACpB,IAAI,CAACA,OAAO,OAAO;IACnB,IAAIA,iBAAiBC,SAASD,AAAe,iBAAfA,MAAM,IAAI,EAAmB,OAAO;IAClE,MAAME,UACJF,iBAAiBC,QAAQD,MAAM,OAAO,GAAGG,OAAOH,SAAS;IAC3D,OAAO,iBAAiB,IAAI,CAACE;AAC/B;AAEA,MAAME,mBAAmB,CAACC;IACxB,IAAI,AAAiB,YAAjB,OAAOA,OAAoB;IAC/B,MAAMC,UAAUD,MAAM,IAAI;IAC1B,OAAOC,WAAWC;AACpB;AAEO,MAAMC,+BAA+B,CAC1CC,UACAC,WAA4BC,QAAQ,QAAQ;IAE5C,IAAI,CAACF,SAAS,UAAU,CAAC,YACvB,OAAOA;IAGT,IAAI;QACF,MAAMG,SAAS,IAAIC,IAAIJ;QACvB,MAAMK,WAAWC,mBAAmBH,OAAO,QAAQ;QACnD,MAAMI,OAAOJ,OAAO,QAAQ,CAAC,WAAW;QAExC,IAAIF,AAAa,YAAbA,UAAsB;YACxB,MAAMO,cAAcH,SACjB,OAAO,CAAC,OAAO,MACf,OAAO,CAAC,kBAAkB;YAE7B,IAAIE,QAAQA,AAAS,gBAATA,MACV,OAAO,CAAC,IAAI,EAAEJ,OAAO,QAAQ,GAAGK,aAAa;YAG/C,OAAOA;QACT;QAEA,IAAID,QAAQA,AAAS,gBAATA,MACV,OAAO,CAAC,EAAE,EAAEJ,OAAO,QAAQ,GAAGE,UAAU;QAG1C,OAAOA;IACT,EAAE,OAAM;QACN,OAAOC,mBAAmBN,SAAS,KAAK,CAAC;IAC3C;AACF;AAEA,MAAMS,yBAAyB,CAAChB;IAC9B,MAAM,EAAEiB,OAAO,EAAE,GAAGjB;IACpB,IAAI,AAAmB,YAAnB,OAAOiB,SACT,OAAOA;IAET,OAAOA,QACJ,GAAG,CAAC,CAACC,OAAUA,AAAc,WAAdA,KAAK,IAAI,GAAcA,KAAK,IAAI,GAAG,IAClD,MAAM,CAACC,SACP,IAAI,CAAC;AACV;AAEA,MAAMC,qBAAqB,CACzBpB,SACAqB;IAEA,MAAM,EAAEJ,OAAO,EAAE,GAAGjB;IACpB,IAAI,CAACsB,MAAM,OAAO,CAACL,UACjB,OAAO,EAAE;IAGX,MAAMM,SAAwD,EAAE;IAChE,KAAK,MAAML,QAAQD,QAAS;QAC1B,IAAIC,AAAc,YAAdA,KAAK,IAAI,EACX;QAEF,MAAMX,WAAWL,iBAAiBgB,KAAK,GAAG;QAC1C,MAAMM,SAASH,mBAAmB;YAAE,aAAaH,KAAK,MAAM;QAAC;QAC7D,IAAKX;YAIL,IACEA,SAAS,UAAU,CAAC,QACpBA,SAAS,UAAU,CAAC,SACpBA,SAAS,UAAU,CAAC,UACpBA,SAAS,UAAU,CAAC,YACpB;gBACA,MAAMkB,OAAOlB,SAAS,UAAU,CAAC,aAC7BD,6BAA6BC,YAC7BA;gBAEJgB,OAAO,IAAI,CAAC;oBACV,MAAM;oBACNE;oBACAD;gBACF;gBACA;YACF;YAEAD,OAAO,IAAI,CAAC;gBACV,MAAM;gBACN,KAAKhB;gBACLiB;YACF;;IACF;IAEA,OAAOD;AACT;AAEO,MAAMG,oCAAoC,CAC/CC,UACAN;IAKA,MAAMO,4BAAsC,EAAE;IAC9C,MAAMC,kBAA4B,EAAE;IACpC,MAAMC,cAA6D,EAAE;IAErE,KAAK,MAAMC,SAASJ,SAAU;QAC5B,MAAM3B,UAAgC,AAAC;YACrC,IAAI,UAAU+B,OACZ,OAAOA;YAET,IAAIA,AAAe,oBAAfA,MAAM,IAAI,EACZ,OAAOA,MAAM,OAAO;YAEtB,IAAIA,AAAsB,sBAAtBA,MAAM,MAAM,CAAC,IAAI,EACnB,MAAM,IAAIhC,MACR;YAGJ,OAAO;gBACL,MAAM;gBACN,SAASgC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI;YAC5C;QACF;QACA,MAAM,EAAEC,IAAI,EAAE,GAAGhC;QACjB,MAAMiC,OAAOjB,uBAAuBhB;QAEpC,IAAIgC,AAAS,aAATA,MAAmB;YACrB,IAAIC,KAAK,IAAI,IAAIL,0BAA0B,IAAI,CAACK,KAAK,IAAI;YACzD;QACF;QAEA,MAAMC,UAAUF,KAAK,WAAW;QAChC,IAAIC,KAAK,IAAI,IACXJ,gBAAgB,IAAI,CAAC,CAAC,CAAC,EAAEK,QAAQ,GAAG,EAAED,KAAK,IAAI,IAAI;aAEnDJ,gBAAgB,IAAI,CAAC,CAAC,CAAC,EAAEK,QAAQ,oBAAoB,CAAC;QAGxD,IAAIF,AAAS,WAATA,MACFF,YAAY,IAAI,IAAIV,mBAAmBpB,SAASqB;IAEpD;IAEA,MAAMc,iBAAiBN,gBAAgB,IAAI,CAAC;IAC5C,MAAMO,iBACHD,AAAAA,CAAAA,eAAe,MAAM,GAAGlD,8BACrBkD,eAAe,KAAK,CAAC,CAAClD,+BACtBkD,cAAa,KAAM;IAEzB,MAAME,QAA0B;QAC9B;YACE,MAAM;YACN,MAAMD;YACN,eAAe,EAAE;QACnB;WACGN;KACJ;IAED,MAAMQ,wBAAwBV,0BAA0B,MAAM,GAC1DA,0BAA0B,IAAI,CAAC,UAC/BvB;IAEJ,OAAO;QACLiC;QACAD;IACF;AACF;AAEA,MAAME;IAgBJ,aAAa,SAA4C;QACvD,IAAIC,aACF,MAAM,IAAIzC,MACR;QAIJ,MAAM0C,yBAAyB;QAC/B,MAAMC,qBAAqB;QAC3B,MAAM,EAAEC,KAAK,EAAE,GAAG,MAAM,MAAM,CAACF;QAC/B,MAAMG,WAAW,MAAM,MAAM,CAACF;QAE9B,MAAMG,QAAQF,MAAM,SAAS;YAAC;SAAa,EAAE;YAC3C,OAAO;gBAAC;gBAAQ;gBAAQ;aAAO;QACjC;QAEA,IAAI,CAACE,MAAM,KAAK,IAAI,CAACA,MAAM,MAAM,IAAI,CAACA,MAAM,MAAM,EAChD,MAAM,IAAI9C,MAAM;QAGlB,MAAM+C,aAAaF,SAAS,eAAe,CAAC;YAC1C,OAAOC,MAAM,MAAM;YACnB,WAAWE;QACb;QACA,MAAMC,aAAa,IAAIT,yBAAyBM,OAAOC;QACvDE,WAAW,mBAAmB;QAC9BA,WAAW,sBAAsB;QACjC,MAAMA,WAAW,mBAAmB;QAEpC,OAAOA;IACT;IAEA,WAAoB;QAClB,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,MAAM,QAAQ,EACZrB,QAAQ,EACRN,kBAAkB,EAClB4B,WAAW,EACXC,MAAM,EACNC,OAAO,EACPC,MAAM,EACNC,WAAW,EACXC,aAAa,EAUd,EAA4B;QAC3B,MAAMC,cAAc,CAAC,CAAEL,CAAAA,UAAUC,OAAM;QAEvC,MAAM,EAAEb,qBAAqB,EAAED,KAAK,EAAE,GAAGX,kCACvCC,UACAN;QAGF,IAAImC;QACJ,IAAIC;QACJ,IAAIC;QACJ,IAAIC,kBAAkB;QACtB,IAAIC,uBAAuB;QAC3B,IAAIC;QAEJ,MAAMC,YAAY,CAAC,EACjB7C,OAAO,EACP8C,SAAS,EACTC,UAAU,EACVC,KAAK,EAMN;YACC,IAAI,CAACV,eAAe,CAACJ,SAAS;YAC9B,MAAMe,QAA6B;gBACjCjD;gBACA,mBAAmB8C;gBACnB,aAAaJ;gBACbK;gBACAC;YACF;YACAd,QAAQe;QACV;QAEA,IAAI;YACF,MAAMC,oBAAoB;gBACxB,OAAOlB,YAAY,SAAS;gBAC5B,KAAKxC,QAAQ,GAAG;gBAChB,gBAAgB;gBAChB,SAAS;gBACT,WAAW;gBACX,uBAAuB;gBACvB,wBAAwB;gBACxB,uBAAuB6B,yBAAyB;YAClD;YACAgB,gBAAgB;gBACd,MAAM;gBACN,UAAU;oBACR,WAAW;oBACX,QAAQ;oBACR,QAAQa;gBACV;YACF;YACA,MAAMC,sBAAsB,MAAM,IAAI,CAAC,OAAO,CAA2B;gBACvE,QAAQ;gBACR,QAAQD;gBACRd;YACF;YACAC,gBAAgB;gBACd,MAAM;gBACN,UAAU;oBACR,WAAW;oBACX,QAAQ;oBACR,QAAQc;gBACV;YACF;YAEAZ,WAAWY,qBAAqB,QAAQ;YACxC,IAAI,CAACZ,UACH,MAAM,IAAIzD,MAAM;YAGlB,MAAMsE,kBAAkB;gBACtB,GAAGjB,MAAM;gBACTI;gBACAnB;YACF;YACAiB,gBAAgB;gBACd,MAAM;gBACN,UAAU;oBACR,WAAW;oBACX,QAAQ;oBACR,QAAQe;gBACV;YACF;YACA,MAAMC,oBAAoB,MAAM,IAAI,CAAC,OAAO,CAAyB;gBACnE,QAAQ;gBACR,QAAQD;gBACRhB;YACF;YACAC,gBAAgB;gBACd,MAAM;gBACN,UAAU;oBACR,WAAW;oBACX,QAAQ;oBACR,QAAQgB;gBACV;YACF;YAEAb,SAASa,mBAAmB,MAAM;YAClC,IAAI,CAACb,QACH,MAAM,IAAI1D,MAAM;YAGlB,IAAIwE;YACJ,MAAO,CAACA,WAAY;gBAClB,MAAMvE,UAAU,MAAM,IAAI,CAAC,WAAW,CAAC;oBAAEqD;gBAAY;gBAErD,IAAI,IAAI,CAAC,iBAAiB,CAACrD,UAEzB;gBAGF,IAAI,IAAI,CAAC,gBAAgB,CAACA,UAAU;oBAClC,MAAM,IAAI,CAAC,sBAAsB,CAACA;oBAClC;gBACF;gBAEA,MAAMwE,eAAexE;gBACrB,MAAMyE,SAASD,aAAa,MAAM;gBAClC,MAAMpB,SAASoB,aAAa,MAAM,IAAI,CAAC;gBACvC,MAAME,uBACJtB,OAAO,QAAQ,KAAKI,YACnBJ,CAAAA,OAAO,MAAM,KAAKK,UAAUL,OAAO,IAAI,EAAE,OAAOK,MAAK;gBAExD,IAAIiB,sBACFpB,gBAAgB;oBACd,MAAM;oBACN,UAAU;wBACR,WAAW;wBACXmB;wBACArB;oBACF;gBACF;gBAGF,IAAIqB,AAAW,YAAXA,QAAoB;oBACtB,MAAME,cACJvB,OAAO,KAAK,EAAE,WACdA,OAAO,OAAO,IACd;oBACFM,qBAAqBzD,OAAO0E;oBAC5B;gBACF;gBAEA,IACEF,AAAW,8BAAXA,UACArB,OAAO,QAAQ,KAAKI,YACpBJ,OAAO,MAAM,KAAKK,QAClB;oBACA,MAAMmB,QAAQ3E,OAAOmD,OAAO,KAAK,IAAI;oBACrC,IAAIwB,OAAO;wBACTjB,mBAAmBiB;wBACnBd,UAAU;4BACR,SAASc;4BACT,WAAW;4BACX,YAAY;wBACd;oBACF;oBACA;gBACF;gBAEA,IACGH,AAAAA,CAAAA,AAAW,sCAAXA,UACCA,AAAW,+BAAXA,MAAoC,KACtCrB,OAAO,QAAQ,KAAKI,YACpBJ,OAAO,MAAM,KAAKK,QAClB;oBACA,MAAMmB,QAAQ3E,OAAOmD,OAAO,KAAK,IAAI;oBACrC,IAAIwB,OAAO;wBACThB,wBAAwBgB;wBACxBd,UAAU;4BACR,SAAS;4BACT,WAAWc;4BACX,YAAY;wBACd;oBACF;oBACA;gBACF;gBAEA,IACEH,AAAW,qBAAXA,UACArB,OAAO,QAAQ,KAAKI,YACpBJ,OAAO,MAAM,KAAKK,UAClBL,OAAO,IAAI,EAAE,SAAS,kBACtB,AAA6B,YAA7B,OAAOA,OAAO,IAAI,EAAE,QACpB,CAACO,iBACD;oBACAA,kBAAkBP,OAAO,IAAI,CAAC,IAAI;oBAClC;gBACF;gBAEA,IACEqB,AAAW,gCAAXA,UACArB,OAAO,QAAQ,KAAKI,YACpBJ,OAAO,MAAM,KAAKK,QAClB;oBACAI,cAAc,IAAI,CAAC,QAAQ,CAACT;oBAC5B;gBACF;gBAEA,IACEqB,AAAW,qBAAXA,UACArB,OAAO,QAAQ,KAAKI,YACpBJ,OAAO,IAAI,EAAE,OAAOK,QACpB;oBACAc,aAAatE,OAAOmD,OAAO,IAAI,CAAC,MAAM,IAAI;oBAC1CM,qBACEN,OAAO,IAAI,EAAE,OAAO,WAAWM,sBAAsBrD;oBACvD;gBACF;YACF;YAEA,IAAIkE,AAAe,gBAAfA,YACF,MAAM,IAAIxE,MACR2D,sBACE,CAAC,iCAAiC,EAAEa,cAAc,UAAU,CAAC,CAAC;YAIpE,IAAIhB,aACFO,UAAU;gBACR,SAAS;gBACT,WAAW;gBACX,YAAY;gBACZ,OAAOD;YACT;YAGF,OAAO;gBACL,SAASF;gBACT,mBAAmBC,wBAAwBvD;gBAC3C,OAAOwD;gBACP,YAAYN;gBACZ,kBAAkB;oBAChB,WAAW;oBACXC;oBACAC;oBACAc;gBACF;YACF;QACF,EAAE,OAAOzE,OAAO;YACd,IAAID,aAAaC,UAAU0D,YAAYC,QACrC,MAAM,IAAI,CAAC,OAAO,CAAC;gBACjB,QAAQ;gBACR,QAAQ;oBACND;oBACAC;gBACF;gBACA,YAAYoB,KAAK,GAAG,KAAK/F;YAC3B,GAAG,KAAK,CAAC,KAAO;YAElB,MAAMgB;QACR,SAAU;YACR,IAAI0D,UACF,MAAM,IAAI,CAAC,OAAO,CAAC;gBACjB,QAAQ;gBACR,QAAQ;oBAAEA;gBAAS;gBACnB,YAAYqB,KAAK,GAAG,KAAK7F;YAC3B,GAAG,KAAK,CAAC,CAACc;gBACRV,UACE,CAAC,mCAAmC,EAAEoE,SAAS,EAAE,EAAEvD,OAAOH,QAAQ;YAEtE;QAEJ;IACF;IAEA,MAAM,UAAyB;QAC7B,IAAI,IAAI,CAAC,MAAM,EAAE;QACjB,IAAI,CAAC,MAAM,GAAG;QAEd,IAAI;YACF,IAAI,CAAC,UAAU,EAAE;QACnB,EAAE,OAAM,CAAC;QAET,IAAI;YACF,IAAI,CAAC,KAAK,EAAE,OAAO;QACrB,EAAE,OAAM,CAAC;QAET,IAAI;YACF,IAAI,CAAC,KAAK,EAAE;QACd,EAAE,OAAM,CAAC;IACX;IAEQ,yBAAyB;QAC/B,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,CAACgF;YAC1B,IAAI,CAAC,UAAU,CAAC,IAAI,CAACA;QACvB;QAEA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAACZ;YAC5B,MAAMjC,OAAO8C,OAAO,QAAQ,CAACb,SACzBA,MAAM,QAAQ,CAAC,UACfjE,OAAOiE;YACX,IAAI,CAAC,YAAY,IAAIjC;YACrB,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,MAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;QAEhD;QAEA,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC+C;YACrB,IAAI,CAAC,MAAM,GAAG;YACd,IAAI,CAAC,YAAY,GAAGA;QACtB;QAEA,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAClF;YACtB,IAAI,CAAC,MAAM,GAAG;YACd,IAAI,CAAC,mBAAmB,GAAGA,MAAM,OAAO;QAC1C;IACF;IAMQ,sBAAsB;QAC5B,IAAI,CAAC,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QAClB,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QACnB,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;IACrB;IAEA,MAAc,sBAAsB;QAClC,MAAMmF,aAAaJ,KAAK,GAAG,KAAK9F;QAChC,MAAM,IAAI,CAAC,OAAO,CAAC;YACjB,QAAQ;YACR,QAAQ;gBACN,YAAY;oBACV,MAAM;oBACN,OAAO;oBACP,SAAS;gBACX;gBACA,cAAc;oBACZ,iBAAiB;gBACnB;YACF;YACAkG;QACF;QACA,MAAM,IAAI,CAAC,WAAW,CAAC;YACrB,QAAQ;QACV;IACF;IAEQ,SACNhB,KAA6B,EACO;QACpC,MAAMiB,aAAajB,MAAM,UAAU;QACnC,MAAMkB,SAASD,YAAY,QAAQA,YAAY;QAC/C,IAAI,CAACC,QAAQ;QAEb,OAAO;YACL,eAAeA,OAAO,WAAW,IAAI;YACrC,mBAAmBA,OAAO,YAAY,IAAI;YAC1C,cAAcA,OAAO,WAAW,IAAI;YACpC,uBAAuB;gBAAE,eAAeA,OAAO,iBAAiB,IAAI;YAAE;YACtE,2BAA2B;gBACzB,kBAAkBA,OAAO,qBAAqB,IAAI;YACpD;QACF;IACF;IAEQ,iBAAiBnF,OAAuB,EAA6B;QAC3E,OACE,AAAoC,YAApC,OAAQA,SAAiB,UACxBA,SAAiB,OAAOK;IAE7B;IAEQ,kBACNL,OAAuB,EACK;QAC5B,OACGA,SAAiB,OAAOK,UACvBL,CAAAA,SAAiB,WAAWK,UAC3BL,SAAiB,UAAUK,MAAQ,KACtC,AAAoC,YAApC,OAAQL,SAAiB;IAE7B;IAEA,MAAc,QAAqB,EACjCyE,MAAM,EACNrB,MAAM,EACN6B,UAAU,EACV5B,WAAW,EAMZ,EAAc;QACbA,aAAa;QACb,MAAM+B,YAAY,IAAI,CAAC,aAAa;QAEpC,MAAM,IAAI,CAAC,WAAW,CAAC;YACrB,IAAIA;YACJX;YACArB;QACF;QAEA,MAAO,KAAM;YACX,MAAMpD,UAAU,MAAM,IAAI,CAAC,WAAW,CAAC;gBACrCiF;gBACA5B;gBACA,gBAAgB;YAClB;YAEA,IAAI,IAAI,CAAC,iBAAiB,CAACrD,YAAYA,QAAQ,EAAE,KAAKoF,WAAW;gBAC/D,IAAIpF,QAAQ,KAAK,EACf,MAAM,IAAID,MACR,CAAC,iBAAiB,EAAE0E,OAAO,SAAS,EAClCzE,QAAQ,KAAK,CAAC,OAAO,IAAI,iBACzB;gBAGN,OAAQA,QAAQ,MAAM,IAAI,CAAC;YAC7B;YAEA,IAAI,IAAI,CAAC,gBAAgB,CAACA,UAAU;gBAClC,MAAM,IAAI,CAAC,sBAAsB,CAACA;gBAClC;YACF;YAGA,IAAI,CAAC,eAAe,CAAC,IAAI,CAACA;QAC5B;IACF;IAEA,MAAc,uBAAuBqF,OAAuB,EAAiB;QAC3E,MAAMD,YAAYC,QAAQ,EAAE;QAC5B,MAAMZ,SAASY,QAAQ,MAAM;QAE7B,IAAIC,SAAkB,CAAC;QACvB,IAAIb,AAAW,4CAAXA,QACFa,SAAS;YAAE,UAAU;QAAU;aAC1B,IAAIb,AAAW,sCAAXA,QACTa,SAAS;YAAE,UAAU;QAAU;aAC1B,IAAIb,AAAW,oCAAXA,QACTa,SAAS;YAAE,QAAQ;YAAU,SAAS;QAAK;;YACtC,IAAIb,AAAW,iCAAXA,QAEJ,YACL,MAAM,IAAI,CAAC,WAAW,CAAC;gBACrB,IAAIW;gBACJ,OAAO;oBACL,MAAM;oBACN,SAAS,CAAC,4BAA4B,EAAEX,QAAQ;gBAClD;YACF;YARAa,SAAS;gBAAE,SAAS,EAAE;YAAC;;QAYzB,MAAM,IAAI,CAAC,WAAW,CAAC;YACrB,IAAIF;YACJE;QACF;IACF;IAEA,MAAc,YAAY,EACxBL,UAAU,EACV5B,WAAW,EACXkC,iBAAiB,IAAI,EAKtB,EAA2B;QAC1B,IAAIA,kBAAkB,IAAI,CAAC,eAAe,CAAC,MAAM,EAC/C,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK;QAGnC,MAAO,KAAM;YACX,IAAIlC,aAAa,SACf,MAAM,IAAItD,MAAM;YAGlB,IAAIkF,cAAcJ,KAAK,GAAG,KAAKI,YAC7B,MAAM,IAAIlF,MAAM;YAGlB,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;gBAC1B,MAAM+E,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK;gBAClC,MAAM1E,UAAU0E,KAAK,IAAI;gBACzB,IAAI,CAAC1E,SAAS;gBAEd,IAAIM;gBACJ,IAAI;oBACFA,SAAS8E,KAAK,KAAK,CAACpF;gBACtB,EAAE,OAAON,OAAO;oBACdV,UACE,CAAC,gDAAgD,EAAEgB,SAAS;oBAE9D;gBACF;gBAEA,OAAOM;YACT;YAEA,IAAI,IAAI,CAAC,MAAM,EACb,MAAM,IAAI,CAAC,2BAA2B;YAGxC,MAAM,IAAIjB,QAAQ,CAACC,UAAY+F,WAAW/F,SAAS;QACrD;IACF;IAEA,MAAc,YAAYgG,OAAgC,EAAiB;QACzE,IAAI,IAAI,CAAC,MAAM,EACb,MAAM,IAAI,CAAC,2BAA2B;QAGxC,MAAMZ,OAAOU,KAAK,SAAS,CAACE;QAC5B,MAAM,IAAIjG,QAAc,CAACC,SAASiG;YAChC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAGb,KAAK,EAAE,CAAC,EAAE,CAAChF;gBACnC,IAAIA,OAAO,YACT6F,OACE,IAAI5F,MACF,CAAC,0CAA0C,EAAED,MAAM,OAAO,EAAE;gBAKlEJ;YACF;QACF;IACF;IAEQ,8BAAqC;QAC3C,MAAMkG,SAAS,IAAI,CAAC,YAAY,CAAC,IAAI;QACrC,IAAI,IAAI,CAAC,mBAAmB,EAC1B,OAAO,IAAI7F,MACT6F,SACI,CAAC,gCAAgC,EAAE,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAEA,QAAQ,GAC/E,CAAC,gCAAgC,EAAE,IAAI,CAAC,mBAAmB,EAAE;QAIrE,OAAO,IAAI7F,MACT6F,SACI,CAAC,6CAA6C,EAAE,IAAI,CAAC,YAAY,CAAC,UAAU,EAAEA,QAAQ,GACtF,CAAC,6CAA6C,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;IAE5E;IA3lBA,YAAoB/C,KAAU,EAAEC,UAAe,CAAE;QAVjD,uBAAQ,SAAR;QACA,uBAAQ,cAAR;QACA,uBAAQ,mBAAoC,EAAE;QAC9C,uBAAQ,cAAuB,EAAE;QACjC,uBAAQ,iBAAgB;QACxB,uBAAQ,UAAS;QACjB,uBAAQ,gBAA8B;QACtC,uBAAQ,uBAAqC;QAC7C,uBAAQ,gBAAe;QAGrB,IAAI,CAAC,KAAK,GAAGD;QACb,IAAI,CAAC,UAAU,GAAGC;IACpB;AAylBF;AAEA,MAAM+C;IAIJ,MAAM,QAAQ,EACZlE,QAAQ,EACRN,kBAAkB,EAClB4B,WAAW,EACXC,MAAM,EACNC,OAAO,EACPC,MAAM,EACNC,WAAW,EACXC,aAAa,EAUd,EAA4B;QAC3B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;YACrBD,aAAa;YACb,MAAML,aAAa,MAAM,IAAI,CAAC,aAAa;YAC3CK,aAAa;YACb,IAAI;gBACF,OAAO,MAAML,WAAW,OAAO,CAAC;oBAC9BrB;oBACAN;oBACA4B;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;gBACF;YACF,EAAE,OAAOxD,OAAO;gBACd,IAAIkD,WAAW,QAAQ,MAAM,CAACnD,aAAaC,QACzC,MAAM,IAAI,CAAC,eAAe;gBAE5B,MAAMA;YACR;QACF;IACF;IAEA,MAAM,mBAAkC;QACtC,MAAM,IAAI,CAAC,eAAe;IAC5B;IAEA,MAAc,gBAAmD;QAC/D,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,IAAI;YAClD,IAAI,CAAC,UAAU,GAAG,MAAMyC,yBAAyB,MAAM;YACvDrD,WAAW;QACb;QACA,OAAO,IAAI,CAAC,UAAU;IACxB;IAEA,MAAc,kBAAiC;QAC7C,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;QACtB,MAAM4G,kBAAkB,IAAI,CAAC,UAAU;QACvC,IAAI,CAAC,UAAU,GAAG;QAClB,MAAMA,gBAAgB,OAAO;QAC7B5G,WAAW;IACb;;QAhEA,uBAAQ,cAA8C;QACtD,uBAAQ,UAAS,IAAIG;;AAgEvB;AAEA,MAAM0G,yBAAyB,IAAIF;AAE5B,eAAeG,yBACpBrE,QAA2B,EAC3BsB,WAAyB,EACzBgD,OAOC;IAED,IAAIzD,aACF,MAAM,IAAIzC,MACR;IAIJ,OAAOgG,uBAAuB,OAAO,CAAC;QACpCpE;QACAsB;QACA,oBAAoBgD,QAAQ,kBAAkB;QAC9C,QAAQA,SAAS;QACjB,SAASA,SAAS;QAClB,QAAQA,SAAS;QACjB,aAAaA,SAAS;QACtB,eAAeA,SAAS;IAC1B;AACF;AAEO,eAAeC;IACpB,MAAMH,uBAAuB,gBAAgB;AAC/C"}
@@ -1,6 +1,5 @@
1
1
  import { callAIWithObjectResponse, callAIWithStringResponse, parseAIObjectResponse } from "./model-call.mjs";
2
2
  import { callAI } from "./call-ai.mjs";
3
- import { createChatClient } from "./openai/openai-client.mjs";
4
3
  import { AIResponseParseError, INTERNAL_CALL_ID_FIELD } from "./utils.mjs";
5
4
  import { extractJSONFromCodeBlock, parseModelResponseJson } from "../shared/json.mjs";
6
- export { AIResponseParseError, INTERNAL_CALL_ID_FIELD, callAI, callAIWithObjectResponse, callAIWithStringResponse, createChatClient, extractJSONFromCodeBlock, parseAIObjectResponse, parseModelResponseJson };
5
+ export { AIResponseParseError, INTERNAL_CALL_ID_FIELD, callAI, callAIWithObjectResponse, callAIWithStringResponse, extractJSONFromCodeBlock, parseAIObjectResponse, parseModelResponseJson };
@@ -15,7 +15,7 @@ function parseAIObjectResponse(response, modelRuntime, jsonParserSource = 'gener
15
15
  contentString: response.content,
16
16
  usage: response.usage,
17
17
  reasoning_content: response.reasoning_content,
18
- rawChoiceMessage: response.rawChoiceMessage
18
+ rawAssistantOutput: response.rawAssistantOutput
19
19
  };
20
20
  }
21
21
  async function callAIWithObjectResponse(messages, modelRuntime, options) {
@@ -29,7 +29,7 @@ async function callAIWithObjectResponse(messages, modelRuntime, options) {
29
29
  parseResponse: (response)=>parseAIObjectResponse(response, modelRuntime, options?.jsonParserSource),
30
30
  toParseError: (error, response)=>{
31
31
  const errorMessage = error instanceof Error ? error.message : String(error);
32
- return new AIResponseParseError(errorMessage, response.content, response.usage, response.rawChoiceMessage, response.reasoning_content);
32
+ return new AIResponseParseError(errorMessage, response.content, response.usage, response.rawAssistantOutput, response.reasoning_content);
33
33
  },
34
34
  parseRetryTimes: options?.retryTimes ?? modelConfig.retryCount,
35
35
  parseRetryInterval: options?.retryInterval ?? modelConfig.retryInterval,
@@ -37,11 +37,11 @@ async function callAIWithObjectResponse(messages, modelRuntime, options) {
37
37
  });
38
38
  }
39
39
  async function callAIWithStringResponse(msgs, modelRuntime, options) {
40
- const { content, usage, rawChoiceMessage } = await callAI(msgs, modelRuntime, options);
40
+ const { content, usage, rawAssistantOutput } = await callAI(msgs, modelRuntime, options);
41
41
  return {
42
42
  content,
43
43
  usage,
44
- rawChoiceMessage
44
+ rawAssistantOutput
45
45
  };
46
46
  }
47
47
  export { callAIWithObjectResponse, callAIWithStringResponse, parseAIObjectResponse };
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/model-call.mjs","sources":["../../../../src/ai-model/service-caller/model-call.ts"],"sourcesContent":["import type { AIUsageInfo } from '@/types';\nimport { assert } from '@midscene/shared/utils';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { ModelRuntime } from '../models';\nimport { type JsonParserSource, assertJsonObject } from '../shared/json';\nimport { callAI } from './call-ai';\nimport {\n callAiAndParseWithRetry,\n withSemanticRetryFeedback,\n} from './semantic-retry';\nimport type { CallAIOptions } from './types';\nimport type { AIArgs } from './types';\nimport { AIResponseParseError } from './utils';\n\nexport type AIObjectResponse<T> = {\n // TODO: `content` is a misleading name here because this is already the parsed object response. Consider renaming it to `object` or `data`.\n content: T;\n contentString: string;\n usage?: AIUsageInfo;\n reasoning_content?: string;\n rawChoiceMessage?: unknown;\n};\n\nexport function parseAIObjectResponse<T>(\n response: Awaited<ReturnType<typeof callAI>>,\n modelRuntime: ModelRuntime,\n jsonParserSource: JsonParserSource = 'generic-object',\n): AIObjectResponse<T> {\n const { adapter } = modelRuntime;\n assert(response, 'empty response');\n const jsonContent = adapter.jsonParser(response.content, {\n source: jsonParserSource,\n });\n assertJsonObject(jsonContent);\n return {\n content: jsonContent as T,\n contentString: response.content,\n usage: response.usage,\n reasoning_content: response.reasoning_content,\n rawChoiceMessage: response.rawChoiceMessage,\n };\n}\n\nexport async function callAIWithObjectResponse<T>(\n messages: ChatCompletionMessageParam[],\n modelRuntime: ModelRuntime,\n options?: {\n abortSignal?: AbortSignal;\n jsonParserSource?: JsonParserSource;\n retryTimes?: number;\n retryInterval?: number;\n },\n): Promise<AIObjectResponse<T>> {\n const { config: modelConfig } = modelRuntime;\n return callAiAndParseWithRetry({\n callAi: (retryAttempt, previousParseError) =>\n callAI(\n withSemanticRetryFeedback(messages, previousParseError),\n modelRuntime,\n {\n abortSignal: options?.abortSignal,\n expectedJsonObjectResponse: true,\n semanticRetryAttempt: retryAttempt,\n },\n ),\n parseResponse: (response) =>\n parseAIObjectResponse<T>(\n response,\n modelRuntime,\n options?.jsonParserSource,\n ),\n toParseError: (error, response) => {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return new AIResponseParseError(\n errorMessage,\n response.content,\n response.usage,\n response.rawChoiceMessage,\n response.reasoning_content,\n );\n },\n parseRetryTimes: options?.retryTimes ?? modelConfig.retryCount,\n parseRetryInterval: options?.retryInterval ?? modelConfig.retryInterval,\n abortSignal: options?.abortSignal,\n });\n}\n\nexport async function callAIWithStringResponse(\n msgs: AIArgs,\n modelRuntime: ModelRuntime,\n options?: Pick<CallAIOptions, 'abortSignal' | 'requiresOriginalImageDetail'>,\n): Promise<{\n content: string;\n usage?: AIUsageInfo;\n rawChoiceMessage?: unknown;\n}> {\n const { content, usage, rawChoiceMessage } = await callAI(\n msgs,\n modelRuntime,\n options,\n );\n return { content, usage, rawChoiceMessage };\n}\n"],"names":["parseAIObjectResponse","response","modelRuntime","jsonParserSource","adapter","assert","jsonContent","assertJsonObject","callAIWithObjectResponse","messages","options","modelConfig","callAiAndParseWithRetry","retryAttempt","previousParseError","callAI","withSemanticRetryFeedback","error","errorMessage","Error","String","AIResponseParseError","callAIWithStringResponse","msgs","content","usage","rawChoiceMessage"],"mappings":";;;;;AAuBO,SAASA,sBACdC,QAA4C,EAC5CC,YAA0B,EAC1BC,mBAAqC,gBAAgB;IAErD,MAAM,EAAEC,OAAO,EAAE,GAAGF;IACpBG,OAAOJ,UAAU;IACjB,MAAMK,cAAcF,QAAQ,UAAU,CAACH,SAAS,OAAO,EAAE;QACvD,QAAQE;IACV;IACAI,iBAAiBD;IACjB,OAAO;QACL,SAASA;QACT,eAAeL,SAAS,OAAO;QAC/B,OAAOA,SAAS,KAAK;QACrB,mBAAmBA,SAAS,iBAAiB;QAC7C,kBAAkBA,SAAS,gBAAgB;IAC7C;AACF;AAEO,eAAeO,yBACpBC,QAAsC,EACtCP,YAA0B,EAC1BQ,OAKC;IAED,MAAM,EAAE,QAAQC,WAAW,EAAE,GAAGT;IAChC,OAAOU,wBAAwB;QAC7B,QAAQ,CAACC,cAAcC,qBACrBC,OACEC,0BAA0BP,UAAUK,qBACpCZ,cACA;gBACE,aAAaQ,SAAS;gBACtB,4BAA4B;gBAC5B,sBAAsBG;YACxB;QAEJ,eAAe,CAACZ,WACdD,sBACEC,UACAC,cACAQ,SAAS;QAEb,cAAc,CAACO,OAAOhB;YACpB,MAAMiB,eACJD,iBAAiBE,QAAQF,MAAM,OAAO,GAAGG,OAAOH;YAClD,OAAO,IAAII,qBACTH,cACAjB,SAAS,OAAO,EAChBA,SAAS,KAAK,EACdA,SAAS,gBAAgB,EACzBA,SAAS,iBAAiB;QAE9B;QACA,iBAAiBS,SAAS,cAAcC,YAAY,UAAU;QAC9D,oBAAoBD,SAAS,iBAAiBC,YAAY,aAAa;QACvE,aAAaD,SAAS;IACxB;AACF;AAEO,eAAeY,yBACpBC,IAAY,EACZrB,YAA0B,EAC1BQ,OAA4E;IAM5E,MAAM,EAAEc,OAAO,EAAEC,KAAK,EAAEC,gBAAgB,EAAE,GAAG,MAAMX,OACjDQ,MACArB,cACAQ;IAEF,OAAO;QAAEc;QAASC;QAAOC;IAAiB;AAC5C"}
1
+ {"version":3,"file":"ai-model/service-caller/model-call.mjs","sources":["../../../../src/ai-model/service-caller/model-call.ts"],"sourcesContent":["import type { RawAssistantOutput } from '@/types';\nimport type { AIUsageInfo } from '@/types';\nimport { assert } from '@midscene/shared/utils';\nimport type { ModelRuntime } from '../models';\nimport { type JsonParserSource, assertJsonObject } from '../shared/json';\nimport { callAI } from './call-ai';\nimport {\n callAiAndParseWithRetry,\n withSemanticRetryFeedback,\n} from './semantic-retry';\nimport type { CallAIOptions } from './types';\nimport type { ModelCallMessages } from './types';\nimport { AIResponseParseError } from './utils';\n\nexport type AIObjectResponse<T> = {\n // TODO: `content` is a misleading name here because this is already the parsed object response. Consider renaming it to `object` or `data`.\n content: T;\n contentString: string;\n usage?: AIUsageInfo;\n reasoning_content?: string;\n rawAssistantOutput?: RawAssistantOutput;\n};\n\nexport function parseAIObjectResponse<T>(\n response: Awaited<ReturnType<typeof callAI>>,\n modelRuntime: ModelRuntime,\n jsonParserSource: JsonParserSource = 'generic-object',\n): AIObjectResponse<T> {\n const { adapter } = modelRuntime;\n assert(response, 'empty response');\n const jsonContent = adapter.jsonParser(response.content, {\n source: jsonParserSource,\n });\n assertJsonObject(jsonContent);\n return {\n content: jsonContent as T,\n contentString: response.content,\n usage: response.usage,\n reasoning_content: response.reasoning_content,\n rawAssistantOutput: response.rawAssistantOutput,\n };\n}\n\nexport async function callAIWithObjectResponse<T>(\n messages: ModelCallMessages,\n modelRuntime: ModelRuntime,\n options?: {\n abortSignal?: AbortSignal;\n jsonParserSource?: JsonParserSource;\n retryTimes?: number;\n retryInterval?: number;\n },\n): Promise<AIObjectResponse<T>> {\n const { config: modelConfig } = modelRuntime;\n return callAiAndParseWithRetry({\n callAi: (retryAttempt, previousParseError) =>\n callAI(\n withSemanticRetryFeedback(messages, previousParseError),\n modelRuntime,\n {\n abortSignal: options?.abortSignal,\n expectedJsonObjectResponse: true,\n semanticRetryAttempt: retryAttempt,\n },\n ),\n parseResponse: (response) =>\n parseAIObjectResponse<T>(\n response,\n modelRuntime,\n options?.jsonParserSource,\n ),\n toParseError: (error, response) => {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return new AIResponseParseError(\n errorMessage,\n response.content,\n response.usage,\n response.rawAssistantOutput,\n response.reasoning_content,\n );\n },\n parseRetryTimes: options?.retryTimes ?? modelConfig.retryCount,\n parseRetryInterval: options?.retryInterval ?? modelConfig.retryInterval,\n abortSignal: options?.abortSignal,\n });\n}\n\nexport async function callAIWithStringResponse(\n msgs: ModelCallMessages,\n modelRuntime: ModelRuntime,\n options?: Pick<CallAIOptions, 'abortSignal' | 'requiresOriginalImageDetail'>,\n): Promise<{\n content: string;\n usage?: AIUsageInfo;\n rawAssistantOutput?: RawAssistantOutput;\n}> {\n const { content, usage, rawAssistantOutput } = await callAI(\n msgs,\n modelRuntime,\n options,\n );\n return { content, usage, rawAssistantOutput };\n}\n"],"names":["parseAIObjectResponse","response","modelRuntime","jsonParserSource","adapter","assert","jsonContent","assertJsonObject","callAIWithObjectResponse","messages","options","modelConfig","callAiAndParseWithRetry","retryAttempt","previousParseError","callAI","withSemanticRetryFeedback","error","errorMessage","Error","String","AIResponseParseError","callAIWithStringResponse","msgs","content","usage","rawAssistantOutput"],"mappings":";;;;;AAuBO,SAASA,sBACdC,QAA4C,EAC5CC,YAA0B,EAC1BC,mBAAqC,gBAAgB;IAErD,MAAM,EAAEC,OAAO,EAAE,GAAGF;IACpBG,OAAOJ,UAAU;IACjB,MAAMK,cAAcF,QAAQ,UAAU,CAACH,SAAS,OAAO,EAAE;QACvD,QAAQE;IACV;IACAI,iBAAiBD;IACjB,OAAO;QACL,SAASA;QACT,eAAeL,SAAS,OAAO;QAC/B,OAAOA,SAAS,KAAK;QACrB,mBAAmBA,SAAS,iBAAiB;QAC7C,oBAAoBA,SAAS,kBAAkB;IACjD;AACF;AAEO,eAAeO,yBACpBC,QAA2B,EAC3BP,YAA0B,EAC1BQ,OAKC;IAED,MAAM,EAAE,QAAQC,WAAW,EAAE,GAAGT;IAChC,OAAOU,wBAAwB;QAC7B,QAAQ,CAACC,cAAcC,qBACrBC,OACEC,0BAA0BP,UAAUK,qBACpCZ,cACA;gBACE,aAAaQ,SAAS;gBACtB,4BAA4B;gBAC5B,sBAAsBG;YACxB;QAEJ,eAAe,CAACZ,WACdD,sBACEC,UACAC,cACAQ,SAAS;QAEb,cAAc,CAACO,OAAOhB;YACpB,MAAMiB,eACJD,iBAAiBE,QAAQF,MAAM,OAAO,GAAGG,OAAOH;YAClD,OAAO,IAAII,qBACTH,cACAjB,SAAS,OAAO,EAChBA,SAAS,KAAK,EACdA,SAAS,kBAAkB,EAC3BA,SAAS,iBAAiB;QAE9B;QACA,iBAAiBS,SAAS,cAAcC,YAAY,UAAU;QAC9D,oBAAoBD,SAAS,iBAAiBC,YAAY,aAAa;QACvE,aAAaD,SAAS;IACxB;AACF;AAEO,eAAeY,yBACpBC,IAAuB,EACvBrB,YAA0B,EAC1BQ,OAA4E;IAM5E,MAAM,EAAEc,OAAO,EAAEC,KAAK,EAAEC,kBAAkB,EAAE,GAAG,MAAMX,OACnDQ,MACArB,cACAQ;IAEF,OAAO;QAAEc;QAASC;QAAOC;IAAmB;AAC9C"}
@@ -1,14 +1,15 @@
1
1
  import { getDebug } from "@midscene/shared/logger";
2
2
  import { AIResponseParseError } from "../utils.mjs";
3
3
  import { callChatCompletion } from "./chat-completion/chat-completion.mjs";
4
- import { createChatClient } from "./openai-client.mjs";
4
+ import { createClient } from "./openai-client.mjs";
5
5
  import { formatOpenAIAPIErrorDetails } from "./openai-request-context.mjs";
6
+ import { callResponses } from "./responses/responses.mjs";
6
7
  async function callOpenAI({ modelRuntime, options, executionId, recordEvent, requestSignal, effectiveTimeoutMs }, prepared) {
7
8
  const { config: modelConfig } = modelRuntime;
8
9
  const { modelName } = modelConfig;
9
- const { completion, openAIRequestContext } = await createChatClient({
10
+ const { openai, openAIRequestContext } = await createClient({
10
11
  modelConfig,
11
- proxyAgent: prepared.proxyAgent,
12
+ proxyAgent: prepared.input.proxyAgent,
12
13
  effectiveTimeoutMs,
13
14
  executionId,
14
15
  recordEvent
@@ -24,12 +25,16 @@ async function callOpenAI({ modelRuntime, options, executionId, recordEvent, req
24
25
  };
25
26
  try {
26
27
  const startTime = Date.now();
27
- const response = await callChatCompletion({
28
+ const response = 'responses' === prepared.protocol ? await callResponses({
28
29
  ...requestOptions,
29
- completion,
30
- modelRuntime,
31
- messages: prepared.messages,
32
- requestBodyParams: prepared.requestParams
30
+ responses: openai.responses,
31
+ requestBodyParams: prepared.input.requestParams
32
+ }, isStreaming) : await callChatCompletion({
33
+ ...requestOptions,
34
+ completion: openai.chat.completions,
35
+ requestBodyParams: prepared.input.requestParams,
36
+ extractContentAndReasoning: prepared.input.extractContentAndReasoning,
37
+ useReasoningAsContentFallback: prepared.input.useReasoningAsContentFallback
33
38
  }, isStreaming);
34
39
  const { reasoningContent, ...result } = response;
35
40
  requestSignal.throwIfAborted();
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/openai/call-openai.mjs","sources":["../../../../../src/ai-model/service-caller/openai/call-openai.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport type {\n ModelCallContext,\n ModelCallResult,\n OpenAIProtocolCallOptions,\n} from '../types';\nimport { AIResponseParseError } from '../utils';\nimport {\n callChatCompletion,\n type prepareChatCompletion,\n} from './chat-completion/chat-completion';\nimport { createChatClient } from './openai-client';\nimport { formatOpenAIAPIErrorDetails } from './openai-request-context';\n\nexport async function callOpenAI(\n {\n modelRuntime,\n options,\n executionId,\n recordEvent,\n requestSignal,\n effectiveTimeoutMs,\n }: ModelCallContext,\n prepared: Awaited<ReturnType<typeof prepareChatCompletion>>,\n): Promise<ModelCallResult> {\n const { config: modelConfig } = modelRuntime;\n const { modelName } = modelConfig;\n const { completion, openAIRequestContext } = await createChatClient({\n modelConfig,\n proxyAgent: prepared.proxyAgent,\n effectiveTimeoutMs,\n executionId,\n recordEvent,\n });\n const isStreaming = options?.stream === true;\n const debugCall = getDebug('ai:call');\n debugCall(\n `sending ${isStreaming ? 'streaming ' : ''}request to ${modelName}`,\n );\n const requestOptions: OpenAIProtocolCallOptions = {\n requestSignal,\n openAIRequestContext,\n onChunk: options?.onChunk,\n recordEvent,\n };\n try {\n const startTime = Date.now();\n const response = await callChatCompletion(\n {\n ...requestOptions,\n completion,\n modelRuntime,\n messages: prepared.messages,\n requestBodyParams: prepared.requestParams,\n },\n isStreaming,\n );\n const { reasoningContent, ...result } = response;\n requestSignal.throwIfAborted();\n const timeCost = Date.now() - startTime;\n debugCall(`response reasoning content: ${reasoningContent}`);\n debugCall(`response content: ${result.content}`);\n recordEvent?.({\n type: 'response',\n http: openAIRequestContext.httpResponse,\n final: {\n content: result.content,\n reasoningContent,\n usage: result.rawUsage,\n requestId: result.requestId,\n timeCost,\n responseModelName: result.responseModelName,\n },\n });\n return {\n ...result,\n reasoning_content: reasoningContent,\n isStreamed: isStreaming,\n timeCost,\n };\n } catch (error: any) {\n getDebug('ai:call', { console: true })('call AI error', error);\n if (error instanceof AIResponseParseError) {\n throw error;\n }\n throw new Error(\n `failed to call ${isStreaming ? 'streaming ' : ''}AI model service (${modelName}): ${error.message}${formatOpenAIAPIErrorDetails(error, openAIRequestContext)}\\nTrouble shooting: https://midscenejs.com/model-provider.html`,\n { cause: error },\n );\n }\n}\n"],"names":["callOpenAI","modelRuntime","options","executionId","recordEvent","requestSignal","effectiveTimeoutMs","prepared","modelConfig","modelName","completion","openAIRequestContext","createChatClient","isStreaming","debugCall","getDebug","requestOptions","startTime","Date","response","callChatCompletion","reasoningContent","result","timeCost","error","AIResponseParseError","Error","formatOpenAIAPIErrorDetails"],"mappings":";;;;;AAcO,eAAeA,WACpB,EACEC,YAAY,EACZC,OAAO,EACPC,WAAW,EACXC,WAAW,EACXC,aAAa,EACbC,kBAAkB,EACD,EACnBC,QAA2D;IAE3D,MAAM,EAAE,QAAQC,WAAW,EAAE,GAAGP;IAChC,MAAM,EAAEQ,SAAS,EAAE,GAAGD;IACtB,MAAM,EAAEE,UAAU,EAAEC,oBAAoB,EAAE,GAAG,MAAMC,iBAAiB;QAClEJ;QACA,YAAYD,SAAS,UAAU;QAC/BD;QACAH;QACAC;IACF;IACA,MAAMS,cAAcX,SAAS,WAAW;IACxC,MAAMY,YAAYC,SAAS;IAC3BD,UACE,CAAC,QAAQ,EAAED,cAAc,eAAe,GAAG,WAAW,EAAEJ,WAAW;IAErE,MAAMO,iBAA4C;QAChDX;QACAM;QACA,SAAST,SAAS;QAClBE;IACF;IACA,IAAI;QACF,MAAMa,YAAYC,KAAK,GAAG;QAC1B,MAAMC,WAAW,MAAMC,mBACrB;YACE,GAAGJ,cAAc;YACjBN;YACAT;YACA,UAAUM,SAAS,QAAQ;YAC3B,mBAAmBA,SAAS,aAAa;QAC3C,GACAM;QAEF,MAAM,EAAEQ,gBAAgB,EAAE,GAAGC,QAAQ,GAAGH;QACxCd,cAAc,cAAc;QAC5B,MAAMkB,WAAWL,KAAK,GAAG,KAAKD;QAC9BH,UAAU,CAAC,4BAA4B,EAAEO,kBAAkB;QAC3DP,UAAU,CAAC,kBAAkB,EAAEQ,OAAO,OAAO,EAAE;QAC/ClB,cAAc;YACZ,MAAM;YACN,MAAMO,qBAAqB,YAAY;YACvC,OAAO;gBACL,SAASW,OAAO,OAAO;gBACvBD;gBACA,OAAOC,OAAO,QAAQ;gBACtB,WAAWA,OAAO,SAAS;gBAC3BC;gBACA,mBAAmBD,OAAO,iBAAiB;YAC7C;QACF;QACA,OAAO;YACL,GAAGA,MAAM;YACT,mBAAmBD;YACnB,YAAYR;YACZU;QACF;IACF,EAAE,OAAOC,OAAY;QACnBT,SAAS,WAAW;YAAE,SAAS;QAAK,GAAG,iBAAiBS;QACxD,IAAIA,iBAAiBC,sBACnB,MAAMD;QAER,MAAM,IAAIE,MACR,CAAC,eAAe,EAAEb,cAAc,eAAe,GAAG,kBAAkB,EAAEJ,UAAU,GAAG,EAAEe,MAAM,OAAO,GAAGG,4BAA4BH,OAAOb,sBAAsB,8DAA8D,CAAC,EAC7N;YAAE,OAAOa;QAAM;IAEnB;AACF"}
1
+ {"version":3,"file":"ai-model/service-caller/openai/call-openai.mjs","sources":["../../../../../src/ai-model/service-caller/openai/call-openai.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport type { ModelCallContext, ModelCallResult } from '../types';\nimport { AIResponseParseError } from '../utils';\nimport {\n callChatCompletion,\n type prepareChatCompletion,\n} from './chat-completion/chat-completion';\nimport { createClient } from './openai-client';\nimport { formatOpenAIAPIErrorDetails } from './openai-request-context';\nimport { callResponses, type prepareResponses } from './responses/responses';\n\nexport type PreparedOpenAIInput =\n | {\n protocol: 'chat-completion';\n input: Awaited<ReturnType<typeof prepareChatCompletion>>;\n }\n | {\n protocol: 'responses';\n input: Awaited<ReturnType<typeof prepareResponses>>;\n };\n\nexport async function callOpenAI(\n {\n modelRuntime,\n options,\n executionId,\n recordEvent,\n requestSignal,\n effectiveTimeoutMs,\n }: ModelCallContext,\n prepared: PreparedOpenAIInput,\n): Promise<ModelCallResult> {\n const { config: modelConfig } = modelRuntime;\n const { modelName } = modelConfig;\n const { openai, openAIRequestContext } = await createClient({\n modelConfig,\n proxyAgent: prepared.input.proxyAgent,\n effectiveTimeoutMs,\n executionId,\n recordEvent,\n });\n const isStreaming = options?.stream === true;\n const debugCall = getDebug('ai:call');\n debugCall(\n `sending ${isStreaming ? 'streaming ' : ''}request to ${modelName}`,\n );\n const requestOptions = {\n requestSignal,\n openAIRequestContext,\n onChunk: options?.onChunk,\n recordEvent,\n };\n try {\n const startTime = Date.now();\n const response =\n prepared.protocol === 'responses'\n ? await callResponses(\n {\n ...requestOptions,\n responses: openai.responses,\n requestBodyParams: prepared.input.requestParams,\n },\n isStreaming,\n )\n : await callChatCompletion(\n {\n ...requestOptions,\n completion: openai.chat.completions,\n requestBodyParams: prepared.input.requestParams,\n extractContentAndReasoning:\n prepared.input.extractContentAndReasoning,\n useReasoningAsContentFallback:\n prepared.input.useReasoningAsContentFallback,\n },\n isStreaming,\n );\n const { reasoningContent, ...result } = response;\n requestSignal.throwIfAborted();\n const timeCost = Date.now() - startTime;\n debugCall(`response reasoning content: ${reasoningContent}`);\n debugCall(`response content: ${result.content}`);\n recordEvent?.({\n type: 'response',\n http: openAIRequestContext.httpResponse,\n final: {\n content: result.content,\n reasoningContent,\n usage: result.rawUsage,\n requestId: result.requestId,\n timeCost,\n responseModelName: result.responseModelName,\n },\n });\n return {\n ...result,\n reasoning_content: reasoningContent,\n isStreamed: isStreaming,\n timeCost,\n };\n } catch (error: any) {\n getDebug('ai:call', { console: true })('call AI error', error);\n if (error instanceof AIResponseParseError) {\n throw error;\n }\n throw new Error(\n `failed to call ${isStreaming ? 'streaming ' : ''}AI model service (${modelName}): ${error.message}${formatOpenAIAPIErrorDetails(error, openAIRequestContext)}\\nTrouble shooting: https://midscenejs.com/model-provider.html`,\n { cause: error },\n );\n }\n}\n"],"names":["callOpenAI","modelRuntime","options","executionId","recordEvent","requestSignal","effectiveTimeoutMs","prepared","modelConfig","modelName","openai","openAIRequestContext","createClient","isStreaming","debugCall","getDebug","requestOptions","startTime","Date","response","callResponses","callChatCompletion","reasoningContent","result","timeCost","error","AIResponseParseError","Error","formatOpenAIAPIErrorDetails"],"mappings":";;;;;;AAqBO,eAAeA,WACpB,EACEC,YAAY,EACZC,OAAO,EACPC,WAAW,EACXC,WAAW,EACXC,aAAa,EACbC,kBAAkB,EACD,EACnBC,QAA6B;IAE7B,MAAM,EAAE,QAAQC,WAAW,EAAE,GAAGP;IAChC,MAAM,EAAEQ,SAAS,EAAE,GAAGD;IACtB,MAAM,EAAEE,MAAM,EAAEC,oBAAoB,EAAE,GAAG,MAAMC,aAAa;QAC1DJ;QACA,YAAYD,SAAS,KAAK,CAAC,UAAU;QACrCD;QACAH;QACAC;IACF;IACA,MAAMS,cAAcX,SAAS,WAAW;IACxC,MAAMY,YAAYC,SAAS;IAC3BD,UACE,CAAC,QAAQ,EAAED,cAAc,eAAe,GAAG,WAAW,EAAEJ,WAAW;IAErE,MAAMO,iBAAiB;QACrBX;QACAM;QACA,SAAST,SAAS;QAClBE;IACF;IACA,IAAI;QACF,MAAMa,YAAYC,KAAK,GAAG;QAC1B,MAAMC,WACJZ,AAAsB,gBAAtBA,SAAS,QAAQ,GACb,MAAMa,cACJ;YACE,GAAGJ,cAAc;YACjB,WAAWN,OAAO,SAAS;YAC3B,mBAAmBH,SAAS,KAAK,CAAC,aAAa;QACjD,GACAM,eAEF,MAAMQ,mBACJ;YACE,GAAGL,cAAc;YACjB,YAAYN,OAAO,IAAI,CAAC,WAAW;YACnC,mBAAmBH,SAAS,KAAK,CAAC,aAAa;YAC/C,4BACEA,SAAS,KAAK,CAAC,0BAA0B;YAC3C,+BACEA,SAAS,KAAK,CAAC,6BAA6B;QAChD,GACAM;QAER,MAAM,EAAES,gBAAgB,EAAE,GAAGC,QAAQ,GAAGJ;QACxCd,cAAc,cAAc;QAC5B,MAAMmB,WAAWN,KAAK,GAAG,KAAKD;QAC9BH,UAAU,CAAC,4BAA4B,EAAEQ,kBAAkB;QAC3DR,UAAU,CAAC,kBAAkB,EAAES,OAAO,OAAO,EAAE;QAC/CnB,cAAc;YACZ,MAAM;YACN,MAAMO,qBAAqB,YAAY;YACvC,OAAO;gBACL,SAASY,OAAO,OAAO;gBACvBD;gBACA,OAAOC,OAAO,QAAQ;gBACtB,WAAWA,OAAO,SAAS;gBAC3BC;gBACA,mBAAmBD,OAAO,iBAAiB;YAC7C;QACF;QACA,OAAO;YACL,GAAGA,MAAM;YACT,mBAAmBD;YACnB,YAAYT;YACZW;QACF;IACF,EAAE,OAAOC,OAAY;QACnBV,SAAS,WAAW;YAAE,SAAS;QAAK,GAAG,iBAAiBU;QACxD,IAAIA,iBAAiBC,sBACnB,MAAMD;QAER,MAAM,IAAIE,MACR,CAAC,eAAe,EAAEd,cAAc,eAAe,GAAG,kBAAkB,EAAEJ,UAAU,GAAG,EAAEgB,MAAM,OAAO,GAAGG,4BAA4BH,OAAOd,sBAAsB,8DAA8D,CAAC,EAC7N;YAAE,OAAOc;QAAM;IAEnB;AACF"}
@@ -1,8 +1,9 @@
1
1
  import { getDebug } from "@midscene/shared/logger";
2
2
  import { createProxyAgentIfNeeded } from "../../proxy/index.mjs";
3
- import { applyImageDetail, stringifyForDebug } from "../../utils.mjs";
3
+ import { stringifyForDebug } from "../../utils.mjs";
4
4
  import { callChatCompletionNonStreaming } from "./non-stream.mjs";
5
5
  import { callChatCompletionStream } from "./stream.mjs";
6
+ import { toChatMessages } from "./utils.mjs";
6
7
  const prepareChatCompletion = async ({ messages, modelRuntime, options })=>{
7
8
  const debugCall = getDebug('ai:call');
8
9
  const { config: modelConfig, adapter } = modelRuntime;
@@ -23,22 +24,25 @@ const prepareChatCompletion = async ({ messages, modelRuntime, options })=>{
23
24
  debugCall(`adapter chat completion params: ${stringifyForDebug({
24
25
  config: adapterChatCompletionParams
25
26
  })}`);
27
+ const resolveImageDetail = ({ imageDetail })=>adapter.resolveImageDetail({
28
+ imageDetail,
29
+ intent: modelConfig.intent,
30
+ requiresOriginalImageDetail: options?.requiresOriginalImageDetail
31
+ });
26
32
  const requestBodyParams = {
33
+ model: modelConfig.modelName,
34
+ messages: toChatMessages(messages, resolveImageDetail),
27
35
  ...adapterChatCompletionParams,
28
36
  ...modelConfig.extraBody ?? {}
29
37
  };
30
- const imageDetail = adapter.chatCompletion.resolveImageDetail(modelCallInput);
31
- const messagesWithImageDetail = applyImageDetail({
32
- imageDetail,
33
- messages
34
- });
35
38
  const proxyAgent = await createProxyAgentIfNeeded({
36
39
  socksProxy: modelConfig.socksProxy,
37
40
  httpProxy: modelConfig.httpProxy
38
41
  });
39
42
  return {
40
- messages: messagesWithImageDetail,
41
43
  requestParams: requestBodyParams,
44
+ extractContentAndReasoning: adapter.chatCompletion.extractContentAndReasoning,
45
+ useReasoningAsContentFallback: adapter.chatCompletion.useReasoningAsContentFallback,
42
46
  proxyAgent
43
47
  };
44
48
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/openai/chat-completion/chat-completion.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/chat-completion.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport type { ChatCompletionCallInput } from '../../../model-adapter/types';\nimport { createProxyAgentIfNeeded } from '../../proxy';\nimport type { ModelCallContext, OpenAIProtocolCallResult } from '../../types';\nimport { applyImageDetail, stringifyForDebug } from '../../utils';\nimport { callChatCompletionNonStreaming } from './non-stream';\nimport { callChatCompletionStream } from './stream';\nimport type { ChatCompletionCallOptions } from './types';\n\nexport const prepareChatCompletion = async ({\n messages,\n modelRuntime,\n options,\n}: Pick<ModelCallContext, 'messages' | 'modelRuntime' | 'options'>) => {\n const debugCall = getDebug('ai:call');\n const { config: modelConfig, adapter } = modelRuntime;\n\n const modelCallInput: ChatCompletionCallInput = {\n intent: modelConfig.intent,\n userConfig: {\n temperature: modelConfig.temperature,\n reasoningEnabled: modelConfig.reasoningEnabled,\n reasoningEffort: modelConfig.reasoningEffort,\n reasoningBudget: modelConfig.reasoningBudget,\n responseFormat: modelConfig.responseFormat,\n },\n semanticRetryAttempt: options?.semanticRetryAttempt,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n expectedJsonObjectResponse: options?.expectedJsonObjectResponse,\n };\n\n const { config: adapterChatCompletionParams } =\n adapter.chatCompletion.buildChatCompletionParams(modelCallInput);\n\n debugCall(\n `adapter chat completion params: ${stringifyForDebug({\n config: adapterChatCompletionParams,\n })}`,\n );\n\n const requestBodyParams = {\n ...adapterChatCompletionParams,\n ...(modelConfig.extraBody ?? {}),\n };\n\n const imageDetail = adapter.chatCompletion.resolveImageDetail(modelCallInput);\n\n // Some adapters request original image detail to preserve screenshot\n // resolution for localization-sensitive tasks.\n const messagesWithImageDetail = applyImageDetail({ imageDetail, messages });\n\n const proxyAgent = await createProxyAgentIfNeeded({\n socksProxy: modelConfig.socksProxy,\n httpProxy: modelConfig.httpProxy,\n });\n\n return {\n messages: messagesWithImageDetail,\n requestParams: requestBodyParams,\n proxyAgent,\n };\n};\n\nexport function callChatCompletion(\n options: ChatCompletionCallOptions,\n stream: boolean,\n): Promise<OpenAIProtocolCallResult> {\n return stream\n ? callChatCompletionStream(options)\n : callChatCompletionNonStreaming(options);\n}\n"],"names":["prepareChatCompletion","messages","modelRuntime","options","debugCall","getDebug","modelConfig","adapter","modelCallInput","adapterChatCompletionParams","stringifyForDebug","requestBodyParams","imageDetail","messagesWithImageDetail","applyImageDetail","proxyAgent","createProxyAgentIfNeeded","callChatCompletion","stream","callChatCompletionStream","callChatCompletionNonStreaming"],"mappings":";;;;;AASO,MAAMA,wBAAwB,OAAO,EAC1CC,QAAQ,EACRC,YAAY,EACZC,OAAO,EACyD;IAChE,MAAMC,YAAYC,SAAS;IAC3B,MAAM,EAAE,QAAQC,WAAW,EAAEC,OAAO,EAAE,GAAGL;IAEzC,MAAMM,iBAA0C;QAC9C,QAAQF,YAAY,MAAM;QAC1B,YAAY;YACV,aAAaA,YAAY,WAAW;YACpC,kBAAkBA,YAAY,gBAAgB;YAC9C,iBAAiBA,YAAY,eAAe;YAC5C,iBAAiBA,YAAY,eAAe;YAC5C,gBAAgBA,YAAY,cAAc;QAC5C;QACA,sBAAsBH,SAAS;QAC/B,6BAA6BA,SAAS;QACtC,4BAA4BA,SAAS;IACvC;IAEA,MAAM,EAAE,QAAQM,2BAA2B,EAAE,GAC3CF,QAAQ,cAAc,CAAC,yBAAyB,CAACC;IAEnDJ,UACE,CAAC,gCAAgC,EAAEM,kBAAkB;QACnD,QAAQD;IACV,IAAI;IAGN,MAAME,oBAAoB;QACxB,GAAGF,2BAA2B;QAC9B,GAAIH,YAAY,SAAS,IAAI,CAAC,CAAC;IACjC;IAEA,MAAMM,cAAcL,QAAQ,cAAc,CAAC,kBAAkB,CAACC;IAI9D,MAAMK,0BAA0BC,iBAAiB;QAAEF;QAAaX;IAAS;IAEzE,MAAMc,aAAa,MAAMC,yBAAyB;QAChD,YAAYV,YAAY,UAAU;QAClC,WAAWA,YAAY,SAAS;IAClC;IAEA,OAAO;QACL,UAAUO;QACV,eAAeF;QACfI;IACF;AACF;AAEO,SAASE,mBACdd,OAAkC,EAClCe,MAAe;IAEf,OAAOA,SACHC,yBAAyBhB,WACzBiB,+BAA+BjB;AACrC"}
1
+ {"version":3,"file":"ai-model/service-caller/openai/chat-completion/chat-completion.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/chat-completion.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport type { ResolveImageDetail } from '../../../model-adapter/types';\nimport type { ModelRequestConfigInput } from '../../../model-adapter/types';\nimport { createProxyAgentIfNeeded } from '../../proxy';\nimport type { ModelCallContext, OpenAIProtocolCallResult } from '../../types';\nimport { stringifyForDebug } from '../../utils';\nimport { callChatCompletionNonStreaming } from './non-stream';\nimport { callChatCompletionStream } from './stream';\nimport type { ChatCompletionCallOptions } from './types';\nimport { toChatMessages } from './utils';\n\nexport const prepareChatCompletion = async ({\n messages,\n modelRuntime,\n options,\n}: Pick<ModelCallContext, 'messages' | 'modelRuntime' | 'options'>) => {\n const debugCall = getDebug('ai:call');\n const { config: modelConfig, adapter } = modelRuntime;\n\n const modelCallInput: ModelRequestConfigInput = {\n intent: modelConfig.intent,\n userConfig: {\n temperature: modelConfig.temperature,\n reasoningEnabled: modelConfig.reasoningEnabled,\n reasoningEffort: modelConfig.reasoningEffort,\n reasoningBudget: modelConfig.reasoningBudget,\n responseFormat: modelConfig.responseFormat,\n },\n semanticRetryAttempt: options?.semanticRetryAttempt,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n expectedJsonObjectResponse: options?.expectedJsonObjectResponse,\n };\n\n const { config: adapterChatCompletionParams } =\n adapter.chatCompletion.buildChatCompletionParams(modelCallInput);\n\n debugCall(\n `adapter chat completion params: ${stringifyForDebug({\n config: adapterChatCompletionParams,\n })}`,\n );\n\n const resolveImageDetail: ResolveImageDetail = ({ imageDetail }) =>\n adapter.resolveImageDetail({\n imageDetail,\n intent: modelConfig.intent,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n });\n\n const requestBodyParams: ChatCompletionCallOptions['requestBodyParams'] = {\n model: modelConfig.modelName,\n messages: toChatMessages(messages, resolveImageDetail),\n ...adapterChatCompletionParams,\n ...(modelConfig.extraBody ?? {}),\n };\n\n const proxyAgent = await createProxyAgentIfNeeded({\n socksProxy: modelConfig.socksProxy,\n httpProxy: modelConfig.httpProxy,\n });\n\n return {\n requestParams: requestBodyParams,\n extractContentAndReasoning:\n adapter.chatCompletion.extractContentAndReasoning,\n useReasoningAsContentFallback:\n adapter.chatCompletion.useReasoningAsContentFallback,\n proxyAgent,\n };\n};\n\nexport function callChatCompletion(\n options: ChatCompletionCallOptions,\n stream: boolean,\n): Promise<OpenAIProtocolCallResult> {\n return stream\n ? callChatCompletionStream(options)\n : callChatCompletionNonStreaming(options);\n}\n"],"names":["prepareChatCompletion","messages","modelRuntime","options","debugCall","getDebug","modelConfig","adapter","modelCallInput","adapterChatCompletionParams","stringifyForDebug","resolveImageDetail","imageDetail","requestBodyParams","toChatMessages","proxyAgent","createProxyAgentIfNeeded","callChatCompletion","stream","callChatCompletionStream","callChatCompletionNonStreaming"],"mappings":";;;;;;AAWO,MAAMA,wBAAwB,OAAO,EAC1CC,QAAQ,EACRC,YAAY,EACZC,OAAO,EACyD;IAChE,MAAMC,YAAYC,SAAS;IAC3B,MAAM,EAAE,QAAQC,WAAW,EAAEC,OAAO,EAAE,GAAGL;IAEzC,MAAMM,iBAA0C;QAC9C,QAAQF,YAAY,MAAM;QAC1B,YAAY;YACV,aAAaA,YAAY,WAAW;YACpC,kBAAkBA,YAAY,gBAAgB;YAC9C,iBAAiBA,YAAY,eAAe;YAC5C,iBAAiBA,YAAY,eAAe;YAC5C,gBAAgBA,YAAY,cAAc;QAC5C;QACA,sBAAsBH,SAAS;QAC/B,6BAA6BA,SAAS;QACtC,4BAA4BA,SAAS;IACvC;IAEA,MAAM,EAAE,QAAQM,2BAA2B,EAAE,GAC3CF,QAAQ,cAAc,CAAC,yBAAyB,CAACC;IAEnDJ,UACE,CAAC,gCAAgC,EAAEM,kBAAkB;QACnD,QAAQD;IACV,IAAI;IAGN,MAAME,qBAAyC,CAAC,EAAEC,WAAW,EAAE,GAC7DL,QAAQ,kBAAkB,CAAC;YACzBK;YACA,QAAQN,YAAY,MAAM;YAC1B,6BAA6BH,SAAS;QACxC;IAEF,MAAMU,oBAAoE;QACxE,OAAOP,YAAY,SAAS;QAC5B,UAAUQ,eAAeb,UAAUU;QACnC,GAAGF,2BAA2B;QAC9B,GAAIH,YAAY,SAAS,IAAI,CAAC,CAAC;IACjC;IAEA,MAAMS,aAAa,MAAMC,yBAAyB;QAChD,YAAYV,YAAY,UAAU;QAClC,WAAWA,YAAY,SAAS;IAClC;IAEA,OAAO;QACL,eAAeO;QACf,4BACEN,QAAQ,cAAc,CAAC,0BAA0B;QACnD,+BACEA,QAAQ,cAAc,CAAC,6BAA6B;QACtDQ;IACF;AACF;AAEO,SAASE,mBACdd,OAAkC,EAClCe,MAAe;IAEf,OAAOA,SACHC,yBAAyBhB,WACzBiB,+BAA+BjB;AACrC"}