@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,11 +1,8 @@
1
1
  import { AIResponseParseError, hasUsableText } from "../../utils.mjs";
2
2
  import { resolveContentWithReasoningFallback } from "./utils.mjs";
3
- const callChatCompletionNonStreaming = async ({ completion, openAIRequestContext, modelRuntime, messages, requestBodyParams, requestSignal })=>{
4
- const { config: { modelName }, adapter } = modelRuntime;
3
+ const callChatCompletionNonStreaming = async ({ completion, openAIRequestContext, extractContentAndReasoning, useReasoningAsContentFallback, requestBodyParams, requestSignal })=>{
5
4
  requestSignal.throwIfAborted();
6
5
  const result = await completion.create({
7
- model: modelName,
8
- messages,
9
6
  ...requestBodyParams,
10
7
  stream: false
11
8
  }, {
@@ -14,19 +11,22 @@ const callChatCompletionNonStreaming = async ({ completion, openAIRequestContext
14
11
  requestSignal.throwIfAborted();
15
12
  const requestId = result._request_id ?? openAIRequestContext.responseRequestId?.requestId;
16
13
  if (!result.choices) throw new Error(`invalid response from LLM service: ${JSON.stringify(result)}`);
17
- const rawChoiceMessage = result.choices[0].message;
18
- const parsedMessage = adapter.chatCompletion.extractContentAndReasoning(result.choices[0].message);
14
+ const rawAssistantOutput = {
15
+ type: 'chat-completion',
16
+ rawValue: result.choices[0].message
17
+ };
18
+ const parsedMessage = extractContentAndReasoning(result.choices[0].message);
19
19
  const reasoningContent = parsedMessage.reasoning_content;
20
20
  const content = resolveContentWithReasoningFallback({
21
21
  content: parsedMessage.content,
22
22
  reasoningContent,
23
- useReasoningAsContentFallback: adapter.chatCompletion.useReasoningAsContentFallback
23
+ useReasoningAsContentFallback
24
24
  });
25
- if (!hasUsableText(content)) throw new AIResponseParseError('empty content from AI model', content || '', void 0, rawChoiceMessage);
25
+ if (!hasUsableText(content)) throw new AIResponseParseError('empty content from AI model', content || '', void 0, rawAssistantOutput);
26
26
  return {
27
27
  content,
28
28
  reasoningContent,
29
- rawChoiceMessage,
29
+ rawAssistantOutput,
30
30
  rawUsage: result.usage,
31
31
  requestId,
32
32
  responseModelName: result.model
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/openai/chat-completion/non-stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/non-stream.ts"],"sourcesContent":["import type { OpenAIProtocolCallResult } from '../../types';\nimport { AIResponseParseError, hasUsableText } from '../../utils';\nimport type { ChatCompletionCallOptions } from './types';\nimport { resolveContentWithReasoningFallback } from './utils';\n\nexport const callChatCompletionNonStreaming = async ({\n completion,\n openAIRequestContext,\n modelRuntime,\n messages,\n requestBodyParams,\n requestSignal,\n}: ChatCompletionCallOptions): Promise<OpenAIProtocolCallResult> => {\n const {\n config: { modelName },\n adapter,\n } = modelRuntime;\n requestSignal.throwIfAborted();\n const result = await completion.create(\n {\n model: modelName,\n messages,\n ...requestBodyParams,\n stream: false,\n },\n { signal: requestSignal },\n );\n\n requestSignal.throwIfAborted();\n\n const requestId =\n result._request_id ?? openAIRequestContext.responseRequestId?.requestId;\n\n if (!result.choices) {\n throw new Error(\n `invalid response from LLM service: ${JSON.stringify(result)}`,\n );\n }\n\n const rawChoiceMessage = result.choices[0].message;\n const parsedMessage = adapter.chatCompletion.extractContentAndReasoning(\n result.choices[0].message,\n );\n const reasoningContent = parsedMessage.reasoning_content;\n const content = resolveContentWithReasoningFallback({\n content: parsedMessage.content,\n reasoningContent,\n useReasoningAsContentFallback:\n adapter.chatCompletion.useReasoningAsContentFallback,\n });\n\n if (!hasUsableText(content)) {\n throw new AIResponseParseError(\n 'empty content from AI model',\n content || '',\n undefined,\n rawChoiceMessage,\n );\n }\n\n return {\n content,\n reasoningContent,\n rawChoiceMessage,\n rawUsage: result.usage,\n requestId,\n responseModelName: result.model,\n };\n};\n"],"names":["callChatCompletionNonStreaming","completion","openAIRequestContext","modelRuntime","messages","requestBodyParams","requestSignal","modelName","adapter","result","requestId","Error","JSON","rawChoiceMessage","parsedMessage","reasoningContent","content","resolveContentWithReasoningFallback","hasUsableText","AIResponseParseError","undefined"],"mappings":";;AAKO,MAAMA,iCAAiC,OAAO,EACnDC,UAAU,EACVC,oBAAoB,EACpBC,YAAY,EACZC,QAAQ,EACRC,iBAAiB,EACjBC,aAAa,EACa;IAC1B,MAAM,EACJ,QAAQ,EAAEC,SAAS,EAAE,EACrBC,OAAO,EACR,GAAGL;IACJG,cAAc,cAAc;IAC5B,MAAMG,SAAS,MAAMR,WAAW,MAAM,CACpC;QACE,OAAOM;QACPH;QACA,GAAGC,iBAAiB;QACpB,QAAQ;IACV,GACA;QAAE,QAAQC;IAAc;IAG1BA,cAAc,cAAc;IAE5B,MAAMI,YACJD,OAAO,WAAW,IAAIP,qBAAqB,iBAAiB,EAAE;IAEhE,IAAI,CAACO,OAAO,OAAO,EACjB,MAAM,IAAIE,MACR,CAAC,mCAAmC,EAAEC,KAAK,SAAS,CAACH,SAAS;IAIlE,MAAMI,mBAAmBJ,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO;IAClD,MAAMK,gBAAgBN,QAAQ,cAAc,CAAC,0BAA0B,CACrEC,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO;IAE3B,MAAMM,mBAAmBD,cAAc,iBAAiB;IACxD,MAAME,UAAUC,oCAAoC;QAClD,SAASH,cAAc,OAAO;QAC9BC;QACA,+BACEP,QAAQ,cAAc,CAAC,6BAA6B;IACxD;IAEA,IAAI,CAACU,cAAcF,UACjB,MAAM,IAAIG,qBACR,+BACAH,WAAW,IACXI,QACAP;IAIJ,OAAO;QACLG;QACAD;QACAF;QACA,UAAUJ,OAAO,KAAK;QACtBC;QACA,mBAAmBD,OAAO,KAAK;IACjC;AACF"}
1
+ {"version":3,"file":"ai-model/service-caller/openai/chat-completion/non-stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/non-stream.ts"],"sourcesContent":["import type { RawAssistantOutput } from '@/types';\nimport type { OpenAIProtocolCallResult } from '../../types';\nimport { AIResponseParseError, hasUsableText } from '../../utils';\nimport type { ChatCompletionCallOptions } from './types';\nimport { resolveContentWithReasoningFallback } from './utils';\n\nexport const callChatCompletionNonStreaming = async ({\n completion,\n openAIRequestContext,\n extractContentAndReasoning,\n useReasoningAsContentFallback,\n requestBodyParams,\n requestSignal,\n}: ChatCompletionCallOptions): Promise<OpenAIProtocolCallResult> => {\n requestSignal.throwIfAborted();\n const result = await completion.create(\n {\n ...requestBodyParams,\n stream: false,\n },\n { signal: requestSignal },\n );\n\n requestSignal.throwIfAborted();\n\n const requestId =\n result._request_id ?? openAIRequestContext.responseRequestId?.requestId;\n\n if (!result.choices) {\n throw new Error(\n `invalid response from LLM service: ${JSON.stringify(result)}`,\n );\n }\n\n const rawAssistantOutput: RawAssistantOutput = {\n type: 'chat-completion',\n rawValue: result.choices[0].message,\n };\n const parsedMessage = extractContentAndReasoning(result.choices[0].message);\n const reasoningContent = parsedMessage.reasoning_content;\n const content = resolveContentWithReasoningFallback({\n content: parsedMessage.content,\n reasoningContent,\n useReasoningAsContentFallback,\n });\n\n if (!hasUsableText(content)) {\n throw new AIResponseParseError(\n 'empty content from AI model',\n content || '',\n undefined,\n rawAssistantOutput,\n );\n }\n\n return {\n content,\n reasoningContent,\n rawAssistantOutput,\n rawUsage: result.usage,\n requestId,\n responseModelName: result.model,\n };\n};\n"],"names":["callChatCompletionNonStreaming","completion","openAIRequestContext","extractContentAndReasoning","useReasoningAsContentFallback","requestBodyParams","requestSignal","result","requestId","Error","JSON","rawAssistantOutput","parsedMessage","reasoningContent","content","resolveContentWithReasoningFallback","hasUsableText","AIResponseParseError","undefined"],"mappings":";;AAMO,MAAMA,iCAAiC,OAAO,EACnDC,UAAU,EACVC,oBAAoB,EACpBC,0BAA0B,EAC1BC,6BAA6B,EAC7BC,iBAAiB,EACjBC,aAAa,EACa;IAC1BA,cAAc,cAAc;IAC5B,MAAMC,SAAS,MAAMN,WAAW,MAAM,CACpC;QACE,GAAGI,iBAAiB;QACpB,QAAQ;IACV,GACA;QAAE,QAAQC;IAAc;IAG1BA,cAAc,cAAc;IAE5B,MAAME,YACJD,OAAO,WAAW,IAAIL,qBAAqB,iBAAiB,EAAE;IAEhE,IAAI,CAACK,OAAO,OAAO,EACjB,MAAM,IAAIE,MACR,CAAC,mCAAmC,EAAEC,KAAK,SAAS,CAACH,SAAS;IAIlE,MAAMI,qBAAyC;QAC7C,MAAM;QACN,UAAUJ,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO;IACrC;IACA,MAAMK,gBAAgBT,2BAA2BI,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO;IAC1E,MAAMM,mBAAmBD,cAAc,iBAAiB;IACxD,MAAME,UAAUC,oCAAoC;QAClD,SAASH,cAAc,OAAO;QAC9BC;QACAT;IACF;IAEA,IAAI,CAACY,cAAcF,UACjB,MAAM,IAAIG,qBACR,+BACAH,WAAW,IACXI,QACAP;IAIJ,OAAO;QACLG;QACAD;QACAF;QACA,UAAUJ,OAAO,KAAK;QACtBC;QACA,mBAAmBD,OAAO,KAAK;IACjC;AACF"}
@@ -1,17 +1,13 @@
1
1
  import { assert } from "@midscene/shared/utils";
2
2
  import { resolveContentWithReasoningFallback } from "./utils.mjs";
3
- const callChatCompletionStream = async ({ completion, openAIRequestContext, modelRuntime, messages, requestBodyParams, requestSignal, onChunk, recordEvent })=>{
3
+ const callChatCompletionStream = async ({ completion, openAIRequestContext, extractContentAndReasoning, useReasoningAsContentFallback, requestBodyParams, requestSignal, onChunk, recordEvent })=>{
4
4
  assert('function' == typeof onChunk, 'onChunk is required when stream is true');
5
- const { adapter } = modelRuntime;
6
- const { modelName } = modelRuntime.config;
7
5
  let accumulated = '';
8
6
  let accumulatedReasoning = '';
9
7
  let usage;
10
8
  let responseModelName;
11
9
  requestSignal.throwIfAborted();
12
10
  const stream = await completion.create({
13
- model: modelName,
14
- messages,
15
11
  ...requestBodyParams,
16
12
  stream: true,
17
13
  stream_options: {
@@ -32,7 +28,7 @@ const callChatCompletionStream = async ({ completion, openAIRequestContext, mode
32
28
  sequence: chunkSequence,
33
29
  chunk
34
30
  });
35
- const parsedChunk = adapter.chatCompletion.extractContentAndReasoning(chunk.choices?.[0]?.delta);
31
+ const parsedChunk = extractContentAndReasoning(chunk.choices?.[0]?.delta);
36
32
  const content = parsedChunk.content || '';
37
33
  const reasoning_content = parsedChunk.reasoning_content || '';
38
34
  if (chunk.usage) usage = chunk.usage;
@@ -53,7 +49,7 @@ const callChatCompletionStream = async ({ completion, openAIRequestContext, mode
53
49
  const finalAccumulated = resolveContentWithReasoningFallback({
54
50
  content: accumulated,
55
51
  reasoningContent: accumulatedReasoning,
56
- useReasoningAsContentFallback: adapter.chatCompletion.useReasoningAsContentFallback
52
+ useReasoningAsContentFallback
57
53
  });
58
54
  accumulated = finalAccumulated || '';
59
55
  const finalChunk = {
@@ -67,7 +63,7 @@ const callChatCompletionStream = async ({ completion, openAIRequestContext, mode
67
63
  return {
68
64
  content: accumulated,
69
65
  reasoningContent: accumulatedReasoning,
70
- rawChoiceMessage: void 0,
66
+ rawAssistantOutput: void 0,
71
67
  rawUsage: usage,
72
68
  requestId,
73
69
  responseModelName
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/openai/chat-completion/stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/stream.ts"],"sourcesContent":["import type { CodeGenerationChunk } from '@/types';\nimport { assert } from '@midscene/shared/utils';\nimport type OpenAI from 'openai';\nimport type { Stream } from 'openai/streaming';\nimport type { OpenAIProtocolCallResult } from '../../types';\nimport type { ChatCompletionCallOptions } from './types';\nimport { resolveContentWithReasoningFallback } from './utils';\n\nexport const callChatCompletionStream = async ({\n completion,\n openAIRequestContext,\n modelRuntime,\n messages,\n requestBodyParams,\n requestSignal,\n onChunk,\n recordEvent,\n}: ChatCompletionCallOptions): Promise<OpenAIProtocolCallResult> => {\n assert(\n typeof onChunk === 'function',\n 'onChunk is required when stream is true',\n );\n const { adapter } = modelRuntime;\n const { modelName } = modelRuntime.config;\n let accumulated = '';\n let accumulatedReasoning = '';\n let usage: OpenAI.CompletionUsage | undefined;\n let responseModelName: string | undefined;\n requestSignal.throwIfAborted();\n const stream = (await completion.create(\n {\n model: modelName,\n messages,\n ...requestBodyParams,\n stream: true,\n stream_options: {\n ...(requestBodyParams.stream_options as\n | Record<string, unknown>\n | undefined),\n include_usage: true,\n },\n },\n {\n stream: true,\n signal: requestSignal,\n },\n )) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk> & {\n _request_id?: string | null;\n };\n\n const requestId =\n stream._request_id ?? openAIRequestContext.responseRequestId?.requestId;\n\n let chunkSequence = 0;\n for await (const chunk of stream) {\n requestSignal.throwIfAborted();\n chunkSequence += 1;\n recordEvent?.({\n type: 'chunk',\n sequence: chunkSequence,\n chunk,\n });\n const parsedChunk = adapter.chatCompletion.extractContentAndReasoning(\n chunk.choices?.[0]?.delta,\n );\n const content = parsedChunk.content || '';\n const reasoning_content = parsedChunk.reasoning_content || '';\n\n // Check for usage info in any chunk (OpenAI provides usage in separate chunks)\n if (chunk.usage) {\n usage = chunk.usage;\n }\n if (chunk.model) {\n responseModelName = chunk.model;\n }\n\n if (content || reasoning_content) {\n accumulated += content;\n accumulatedReasoning += reasoning_content;\n const chunkData: CodeGenerationChunk = {\n content,\n reasoning_content,\n accumulated,\n isComplete: false,\n usage: undefined,\n };\n onChunk(chunkData);\n }\n }\n\n const finalAccumulated = resolveContentWithReasoningFallback({\n content: accumulated,\n reasoningContent: accumulatedReasoning,\n useReasoningAsContentFallback:\n adapter.chatCompletion.useReasoningAsContentFallback,\n });\n accumulated = finalAccumulated || '';\n\n // Send final chunk\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage,\n };\n onChunk(finalChunk);\n return {\n content: accumulated,\n reasoningContent: accumulatedReasoning,\n rawChoiceMessage: undefined,\n rawUsage: usage,\n requestId,\n responseModelName,\n };\n};\n"],"names":["callChatCompletionStream","completion","openAIRequestContext","modelRuntime","messages","requestBodyParams","requestSignal","onChunk","recordEvent","assert","adapter","modelName","accumulated","accumulatedReasoning","usage","responseModelName","stream","requestId","chunkSequence","chunk","parsedChunk","content","reasoning_content","chunkData","undefined","finalAccumulated","resolveContentWithReasoningFallback","finalChunk"],"mappings":";;AAQO,MAAMA,2BAA2B,OAAO,EAC7CC,UAAU,EACVC,oBAAoB,EACpBC,YAAY,EACZC,QAAQ,EACRC,iBAAiB,EACjBC,aAAa,EACbC,OAAO,EACPC,WAAW,EACe;IAC1BC,OACE,AAAmB,cAAnB,OAAOF,SACP;IAEF,MAAM,EAAEG,OAAO,EAAE,GAAGP;IACpB,MAAM,EAAEQ,SAAS,EAAE,GAAGR,aAAa,MAAM;IACzC,IAAIS,cAAc;IAClB,IAAIC,uBAAuB;IAC3B,IAAIC;IACJ,IAAIC;IACJT,cAAc,cAAc;IAC5B,MAAMU,SAAU,MAAMf,WAAW,MAAM,CACrC;QACE,OAAOU;QACPP;QACA,GAAGC,iBAAiB;QACpB,QAAQ;QACR,gBAAgB;YACd,GAAIA,kBAAkB,cAAc;YAGpC,eAAe;QACjB;IACF,GACA;QACE,QAAQ;QACR,QAAQC;IACV;IAKF,MAAMW,YACJD,OAAO,WAAW,IAAId,qBAAqB,iBAAiB,EAAE;IAEhE,IAAIgB,gBAAgB;IACpB,WAAW,MAAMC,SAASH,OAAQ;QAChCV,cAAc,cAAc;QAC5BY,iBAAiB;QACjBV,cAAc;YACZ,MAAM;YACN,UAAUU;YACVC;QACF;QACA,MAAMC,cAAcV,QAAQ,cAAc,CAAC,0BAA0B,CACnES,MAAM,OAAO,EAAE,CAAC,EAAE,EAAE;QAEtB,MAAME,UAAUD,YAAY,OAAO,IAAI;QACvC,MAAME,oBAAoBF,YAAY,iBAAiB,IAAI;QAG3D,IAAID,MAAM,KAAK,EACbL,QAAQK,MAAM,KAAK;QAErB,IAAIA,MAAM,KAAK,EACbJ,oBAAoBI,MAAM,KAAK;QAGjC,IAAIE,WAAWC,mBAAmB;YAChCV,eAAeS;YACfR,wBAAwBS;YACxB,MAAMC,YAAiC;gBACrCF;gBACAC;gBACAV;gBACA,YAAY;gBACZ,OAAOY;YACT;YACAjB,QAAQgB;QACV;IACF;IAEA,MAAME,mBAAmBC,oCAAoC;QAC3D,SAASd;QACT,kBAAkBC;QAClB,+BACEH,QAAQ,cAAc,CAAC,6BAA6B;IACxD;IACAE,cAAca,oBAAoB;IAGlC,MAAME,aAAkC;QACtC,SAAS;QACTf;QACA,mBAAmB;QACnB,YAAY;QACZE;IACF;IACAP,QAAQoB;IACR,OAAO;QACL,SAASf;QACT,kBAAkBC;QAClB,kBAAkBW;QAClB,UAAUV;QACVG;QACAF;IACF;AACF"}
1
+ {"version":3,"file":"ai-model/service-caller/openai/chat-completion/stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/stream.ts"],"sourcesContent":["import type { CodeGenerationChunk } from '@/types';\nimport { assert } from '@midscene/shared/utils';\nimport type OpenAI from 'openai';\nimport type { Stream } from 'openai/streaming';\nimport type { OpenAIProtocolCallResult } from '../../types';\nimport type { ChatCompletionCallOptions } from './types';\nimport { resolveContentWithReasoningFallback } from './utils';\n\nexport const callChatCompletionStream = async ({\n completion,\n openAIRequestContext,\n extractContentAndReasoning,\n useReasoningAsContentFallback,\n requestBodyParams,\n requestSignal,\n onChunk,\n recordEvent,\n}: ChatCompletionCallOptions): Promise<OpenAIProtocolCallResult> => {\n assert(\n typeof onChunk === 'function',\n 'onChunk is required when stream is true',\n );\n let accumulated = '';\n let accumulatedReasoning = '';\n let usage: OpenAI.CompletionUsage | undefined;\n let responseModelName: string | undefined;\n requestSignal.throwIfAborted();\n const stream = (await completion.create(\n {\n ...requestBodyParams,\n stream: true,\n stream_options: {\n ...requestBodyParams.stream_options,\n include_usage: true,\n },\n },\n {\n stream: true,\n signal: requestSignal,\n },\n )) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk> & {\n _request_id?: string | null;\n };\n\n const requestId =\n stream._request_id ?? openAIRequestContext.responseRequestId?.requestId;\n\n let chunkSequence = 0;\n for await (const chunk of stream) {\n requestSignal.throwIfAborted();\n chunkSequence += 1;\n recordEvent?.({\n type: 'chunk',\n sequence: chunkSequence,\n chunk,\n });\n const parsedChunk = extractContentAndReasoning(chunk.choices?.[0]?.delta);\n const content = parsedChunk.content || '';\n const reasoning_content = parsedChunk.reasoning_content || '';\n\n // Check for usage info in any chunk (OpenAI provides usage in separate chunks)\n if (chunk.usage) {\n usage = chunk.usage;\n }\n if (chunk.model) {\n responseModelName = chunk.model;\n }\n\n if (content || reasoning_content) {\n accumulated += content;\n accumulatedReasoning += reasoning_content;\n const chunkData: CodeGenerationChunk = {\n content,\n reasoning_content,\n accumulated,\n isComplete: false,\n usage: undefined,\n };\n onChunk(chunkData);\n }\n }\n\n const finalAccumulated = resolveContentWithReasoningFallback({\n content: accumulated,\n reasoningContent: accumulatedReasoning,\n useReasoningAsContentFallback,\n });\n accumulated = finalAccumulated || '';\n\n // Send final chunk\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage,\n };\n onChunk(finalChunk);\n return {\n content: accumulated,\n reasoningContent: accumulatedReasoning,\n rawAssistantOutput: undefined,\n rawUsage: usage,\n requestId,\n responseModelName,\n };\n};\n"],"names":["callChatCompletionStream","completion","openAIRequestContext","extractContentAndReasoning","useReasoningAsContentFallback","requestBodyParams","requestSignal","onChunk","recordEvent","assert","accumulated","accumulatedReasoning","usage","responseModelName","stream","requestId","chunkSequence","chunk","parsedChunk","content","reasoning_content","chunkData","undefined","finalAccumulated","resolveContentWithReasoningFallback","finalChunk"],"mappings":";;AAQO,MAAMA,2BAA2B,OAAO,EAC7CC,UAAU,EACVC,oBAAoB,EACpBC,0BAA0B,EAC1BC,6BAA6B,EAC7BC,iBAAiB,EACjBC,aAAa,EACbC,OAAO,EACPC,WAAW,EACe;IAC1BC,OACE,AAAmB,cAAnB,OAAOF,SACP;IAEF,IAAIG,cAAc;IAClB,IAAIC,uBAAuB;IAC3B,IAAIC;IACJ,IAAIC;IACJP,cAAc,cAAc;IAC5B,MAAMQ,SAAU,MAAMb,WAAW,MAAM,CACrC;QACE,GAAGI,iBAAiB;QACpB,QAAQ;QACR,gBAAgB;YACd,GAAGA,kBAAkB,cAAc;YACnC,eAAe;QACjB;IACF,GACA;QACE,QAAQ;QACR,QAAQC;IACV;IAKF,MAAMS,YACJD,OAAO,WAAW,IAAIZ,qBAAqB,iBAAiB,EAAE;IAEhE,IAAIc,gBAAgB;IACpB,WAAW,MAAMC,SAASH,OAAQ;QAChCR,cAAc,cAAc;QAC5BU,iBAAiB;QACjBR,cAAc;YACZ,MAAM;YACN,UAAUQ;YACVC;QACF;QACA,MAAMC,cAAcf,2BAA2Bc,MAAM,OAAO,EAAE,CAAC,EAAE,EAAE;QACnE,MAAME,UAAUD,YAAY,OAAO,IAAI;QACvC,MAAME,oBAAoBF,YAAY,iBAAiB,IAAI;QAG3D,IAAID,MAAM,KAAK,EACbL,QAAQK,MAAM,KAAK;QAErB,IAAIA,MAAM,KAAK,EACbJ,oBAAoBI,MAAM,KAAK;QAGjC,IAAIE,WAAWC,mBAAmB;YAChCV,eAAeS;YACfR,wBAAwBS;YACxB,MAAMC,YAAiC;gBACrCF;gBACAC;gBACAV;gBACA,YAAY;gBACZ,OAAOY;YACT;YACAf,QAAQc;QACV;IACF;IAEA,MAAME,mBAAmBC,oCAAoC;QAC3D,SAASd;QACT,kBAAkBC;QAClBP;IACF;IACAM,cAAca,oBAAoB;IAGlC,MAAME,aAAkC;QACtC,SAAS;QACTf;QACA,mBAAmB;QACnB,YAAY;QACZE;IACF;IACAL,QAAQkB;IACR,OAAO;QACL,SAASf;QACT,kBAAkBC;QAClB,oBAAoBW;QACpB,UAAUV;QACVG;QACAF;IACF;AACF"}
@@ -10,6 +10,33 @@ const resolveContentWithReasoningFallback = ({ content, reasoningContent, useRea
10
10
  }
11
11
  return content;
12
12
  };
13
- export { resolveContentWithReasoningFallback };
13
+ function toChatMessages(messages, resolveImageDetail) {
14
+ return messages.map((entry)=>{
15
+ if ('type' in entry && 'model-output' === entry.type) {
16
+ if ('chat-completion' !== entry.output.type) throw new Error('Cannot replay Responses output in a Chat Completions conversation');
17
+ return entry.output.rawValue;
18
+ }
19
+ const message = 'role' in entry ? entry : entry.message;
20
+ return {
21
+ role: message.role,
22
+ content: 'string' == typeof message.content ? message.content : message.content.map((part)=>{
23
+ if ('text' === part.type) return {
24
+ type: 'text',
25
+ text: part.text
26
+ };
27
+ return {
28
+ type: 'image_url',
29
+ image_url: {
30
+ url: part.url,
31
+ detail: resolveImageDetail({
32
+ imageDetail: part.detail
33
+ })
34
+ }
35
+ };
36
+ })
37
+ };
38
+ });
39
+ }
40
+ export { resolveContentWithReasoningFallback, toChatMessages };
14
41
 
15
42
  //# sourceMappingURL=utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/openai/chat-completion/utils.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/utils.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { hasUsableText } from '../../utils';\n\nexport const resolveContentWithReasoningFallback = ({\n content,\n reasoningContent,\n useReasoningAsContentFallback,\n}: {\n content: string | undefined;\n reasoningContent: string;\n useReasoningAsContentFallback: boolean;\n}): string | undefined => {\n if (\n !hasUsableText(content) &&\n useReasoningAsContentFallback &&\n hasUsableText(reasoningContent)\n ) {\n const warnCall = getDebug('ai:call', { console: true });\n warnCall('empty content from AI model, using reasoning content');\n return reasoningContent;\n }\n\n return content;\n};\n"],"names":["resolveContentWithReasoningFallback","content","reasoningContent","useReasoningAsContentFallback","hasUsableText","warnCall","getDebug"],"mappings":";;AAGO,MAAMA,sCAAsC,CAAC,EAClDC,OAAO,EACPC,gBAAgB,EAChBC,6BAA6B,EAK9B;IACC,IACE,CAACC,cAAcH,YACfE,iCACAC,cAAcF,mBACd;QACA,MAAMG,WAAWC,SAAS,WAAW;YAAE,SAAS;QAAK;QACrDD,SAAS;QACT,OAAOH;IACT;IAEA,OAAOD;AACT"}
1
+ {"version":3,"file":"ai-model/service-caller/openai/chat-completion/utils.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/utils.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { ResolveImageDetail } from '../../../model-adapter/types';\nimport type { ModelCallMessages } from '../../types';\nimport { hasUsableText } from '../../utils';\n\nexport const resolveContentWithReasoningFallback = ({\n content,\n reasoningContent,\n useReasoningAsContentFallback,\n}: {\n content: string | undefined;\n reasoningContent: string;\n useReasoningAsContentFallback: boolean;\n}): string | undefined => {\n if (\n !hasUsableText(content) &&\n useReasoningAsContentFallback &&\n hasUsableText(reasoningContent)\n ) {\n const warnCall = getDebug('ai:call', { console: true });\n warnCall('empty content from AI model, using reasoning content');\n return reasoningContent;\n }\n\n return content;\n};\n\n/** Chat Completions cannot replay Responses output items as messages. */\nexport function toChatMessages(\n messages: ModelCallMessages,\n resolveImageDetail: ResolveImageDetail,\n): ChatCompletionMessageParam[] {\n // The installed SDK does not yet include the supported `original` image detail.\n return messages.map((entry) => {\n if ('type' in entry && entry.type === 'model-output') {\n if (entry.output.type !== 'chat-completion') {\n throw new Error(\n 'Cannot replay Responses output in a Chat Completions conversation',\n );\n }\n return entry.output.rawValue;\n }\n const message = 'role' in entry ? entry : entry.message;\n return {\n role: message.role,\n content:\n typeof message.content === 'string'\n ? message.content\n : message.content.map((part) => {\n if (part.type === 'text') {\n return { type: 'text', text: part.text };\n }\n return {\n type: 'image_url',\n image_url: {\n url: part.url,\n detail: resolveImageDetail({ imageDetail: part.detail }),\n },\n };\n }),\n };\n }) as ChatCompletionMessageParam[];\n}\n"],"names":["resolveContentWithReasoningFallback","content","reasoningContent","useReasoningAsContentFallback","hasUsableText","warnCall","getDebug","toChatMessages","messages","resolveImageDetail","entry","Error","message","part"],"mappings":";;AAMO,MAAMA,sCAAsC,CAAC,EAClDC,OAAO,EACPC,gBAAgB,EAChBC,6BAA6B,EAK9B;IACC,IACE,CAACC,cAAcH,YACfE,iCACAC,cAAcF,mBACd;QACA,MAAMG,WAAWC,SAAS,WAAW;YAAE,SAAS;QAAK;QACrDD,SAAS;QACT,OAAOH;IACT;IAEA,OAAOD;AACT;AAGO,SAASM,eACdC,QAA2B,EAC3BC,kBAAsC;IAGtC,OAAOD,SAAS,GAAG,CAAC,CAACE;QACnB,IAAI,UAAUA,SAASA,AAAe,mBAAfA,MAAM,IAAI,EAAqB;YACpD,IAAIA,AAAsB,sBAAtBA,MAAM,MAAM,CAAC,IAAI,EACnB,MAAM,IAAIC,MACR;YAGJ,OAAOD,MAAM,MAAM,CAAC,QAAQ;QAC9B;QACA,MAAME,UAAU,UAAUF,QAAQA,QAAQA,MAAM,OAAO;QACvD,OAAO;YACL,MAAME,QAAQ,IAAI;YAClB,SACE,AAA2B,YAA3B,OAAOA,QAAQ,OAAO,GAClBA,QAAQ,OAAO,GACfA,QAAQ,OAAO,CAAC,GAAG,CAAC,CAACC;gBACnB,IAAIA,AAAc,WAAdA,KAAK,IAAI,EACX,OAAO;oBAAE,MAAM;oBAAQ,MAAMA,KAAK,IAAI;gBAAC;gBAEzC,OAAO;oBACL,MAAM;oBACN,WAAW;wBACT,KAAKA,KAAK,GAAG;wBACb,QAAQJ,mBAAmB;4BAAE,aAAaI,KAAK,MAAM;wBAAC;oBACxD;gBACF;YACF;QACR;IACF;AACF"}
@@ -51,7 +51,7 @@ const createAndWrapClient = async ({ openaiBaseURL, openaiApiKey, openaiExtraCon
51
51
  }
52
52
  return openai;
53
53
  };
54
- async function createChatClient({ modelConfig, proxyAgent, effectiveTimeoutMs, executionId, recordEvent }) {
54
+ async function createClient({ modelConfig, proxyAgent, effectiveTimeoutMs, executionId, recordEvent }) {
55
55
  const { openaiBaseURL, openaiApiKey, openaiExtraConfig, createOpenAIClient } = modelConfig;
56
56
  const openAIRequestContext = {
57
57
  recordEvent
@@ -67,10 +67,10 @@ async function createChatClient({ modelConfig, proxyAgent, effectiveTimeoutMs, e
67
67
  openAIRequestContext
68
68
  });
69
69
  return {
70
- completion: openai.chat.completions,
70
+ openai,
71
71
  openAIRequestContext
72
72
  };
73
73
  }
74
- export { createChatClient };
74
+ export { createClient };
75
75
 
76
76
  //# sourceMappingURL=openai-client.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/openai/openai-client.mjs","sources":["../../../../../src/ai-model/service-caller/openai/openai-client.ts"],"sourcesContent":["import {\n type IModelConfig,\n MIDSCENE_LANGFUSE_DEBUG,\n MIDSCENE_LANGSMITH_DEBUG,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport OpenAI from 'openai';\nimport { getVersion } from '../../../utils';\nimport type { createProxyAgentIfNeeded } from '../proxy';\nimport {\n type OpenAIRequestContext,\n wrapOpenAICompatibleFetch,\n} from './openai-request-context';\n\nconst createAndWrapClient = async ({\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n createOpenAIClient,\n effectiveTimeoutMs,\n proxyAgent,\n executionId,\n openAIRequestContext,\n}: {\n openaiBaseURL: IModelConfig['openaiBaseURL'];\n openaiApiKey: IModelConfig['openaiApiKey'];\n openaiExtraConfig: IModelConfig['openaiExtraConfig'];\n createOpenAIClient: IModelConfig['createOpenAIClient'];\n effectiveTimeoutMs: number | null;\n proxyAgent: Awaited<ReturnType<typeof createProxyAgentIfNeeded>>;\n executionId: string;\n openAIRequestContext: OpenAIRequestContext;\n}): Promise<OpenAI> => {\n const warnClient = getDebug('ai:call', { console: true });\n\n const openAIOptions = {\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n // Use fetchOptions.dispatcher for fetch-based SDK instead of httpAgent\n // Note: Type assertion needed due to undici version mismatch between dependencies\n ...(proxyAgent ? { fetchOptions: { dispatcher: proxyAgent as any } } : {}),\n ...openaiExtraConfig,\n // Midscene exposes this setting through MIDSCENE_*_INIT_CONFIG_JSON, so\n // defaultHeaders is expected to be a plain JSON object rather than another\n // HeadersLike representation supported by the OpenAI SDK.\n defaultHeaders: {\n ...(openaiExtraConfig?.defaultHeaders as\n | Record<string, string>\n | undefined),\n // These Midscene-owned headers intentionally override user-supplied\n // headers with the same names.\n 'x-midscene-version': getVersion(),\n 'x-midscene-execution-id': executionId,\n },\n fetch: wrapOpenAICompatibleFetch(openAIRequestContext),\n // Midscene handles request retries in callAI(), so disable SDK-level retries\n // to avoid duplicate attempts and duplicated backoff latency.\n maxRetries: 0,\n // Disabling the Midscene hard timeout leaves the SDK timeout at its\n // configured value or default; it does not disable SDK/network timeouts.\n ...(effectiveTimeoutMs !== null ? { timeout: effectiveTimeoutMs } : {}),\n dangerouslyAllowBrowser: true,\n };\n\n const baseOpenAI = new OpenAI(openAIOptions);\n\n let openai: OpenAI = baseOpenAI;\n\n // LangSmith wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langsmith wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langsmithModule = 'langsmith/wrappers';\n const { wrapOpenAI } = await import(langsmithModule);\n openai = wrapOpenAI(openai);\n }\n\n // Langfuse wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGFUSE_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langfuse is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langfuse wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langfuseModule = '@langfuse/openai';\n const { observeOpenAI } = await import(langfuseModule);\n openai = observeOpenAI(openai);\n }\n\n if (createOpenAIClient) {\n const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);\n\n if (wrappedClient) {\n openai = wrappedClient as OpenAI;\n }\n }\n\n return openai;\n};\n\nexport async function createChatClient({\n modelConfig,\n proxyAgent,\n effectiveTimeoutMs,\n executionId,\n recordEvent,\n}: {\n modelConfig: IModelConfig;\n proxyAgent: Awaited<ReturnType<typeof createProxyAgentIfNeeded>>;\n effectiveTimeoutMs: number | null;\n executionId: string;\n recordEvent?: (event: Record<string, unknown>) => void;\n}): Promise<{\n completion: OpenAI.Chat.Completions;\n openAIRequestContext: OpenAIRequestContext;\n}> {\n const { openaiBaseURL, openaiApiKey, openaiExtraConfig, createOpenAIClient } =\n modelConfig;\n\n const openAIRequestContext: OpenAIRequestContext = {\n recordEvent,\n };\n\n const openai = await createAndWrapClient({\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n createOpenAIClient,\n effectiveTimeoutMs,\n proxyAgent,\n executionId,\n openAIRequestContext,\n });\n\n return {\n completion: openai.chat.completions,\n openAIRequestContext,\n };\n}\n"],"names":["createAndWrapClient","openaiBaseURL","openaiApiKey","openaiExtraConfig","createOpenAIClient","effectiveTimeoutMs","proxyAgent","executionId","openAIRequestContext","warnClient","getDebug","openAIOptions","getVersion","wrapOpenAICompatibleFetch","baseOpenAI","OpenAI","openai","globalConfigManager","MIDSCENE_LANGSMITH_DEBUG","ifInBrowser","Error","langsmithModule","wrapOpenAI","MIDSCENE_LANGFUSE_DEBUG","langfuseModule","observeOpenAI","wrappedClient","createChatClient","modelConfig","recordEvent"],"mappings":";;;;;;AAgBA,MAAMA,sBAAsB,OAAO,EACjCC,aAAa,EACbC,YAAY,EACZC,iBAAiB,EACjBC,kBAAkB,EAClBC,kBAAkB,EAClBC,UAAU,EACVC,WAAW,EACXC,oBAAoB,EAUrB;IACC,MAAMC,aAAaC,SAAS,WAAW;QAAE,SAAS;IAAK;IAEvD,MAAMC,gBAAgB;QACpB,SAASV;QACT,QAAQC;QAGR,GAAII,aAAa;YAAE,cAAc;gBAAE,YAAYA;YAAkB;QAAE,IAAI,CAAC,CAAC;QACzE,GAAGH,iBAAiB;QAIpB,gBAAgB;YACd,GAAIA,mBAAmB,cAAc;YAKrC,sBAAsBS;YACtB,2BAA2BL;QAC7B;QACA,OAAOM,0BAA0BL;QAGjC,YAAY;QAGZ,GAAIH,AAAuB,SAAvBA,qBAA8B;YAAE,SAASA;QAAmB,IAAI,CAAC,CAAC;QACtE,yBAAyB;IAC3B;IAEA,MAAMS,aAAa,IAAIC,SAAOJ;IAE9B,IAAIK,SAAiBF;IAGrB,IACEE,UACAC,oBAAoB,qBAAqB,CAACC,2BAC1C;QACA,IAAIC,aACF,MAAM,IAAIC,MAAM;QAElBX,WAAW;QAEX,MAAMY,kBAAkB;QACxB,MAAM,EAAEC,UAAU,EAAE,GAAG,MAAM,MAAM,CAACD;QACpCL,SAASM,WAAWN;IACtB;IAGA,IACEA,UACAC,oBAAoB,qBAAqB,CAACM,0BAC1C;QACA,IAAIJ,aACF,MAAM,IAAIC,MAAM;QAElBX,WAAW;QAEX,MAAMe,iBAAiB;QACvB,MAAM,EAAEC,aAAa,EAAE,GAAG,MAAM,MAAM,CAACD;QACvCR,SAASS,cAAcT;IACzB;IAEA,IAAIZ,oBAAoB;QACtB,MAAMsB,gBAAgB,MAAMtB,mBAAmBU,YAAYH;QAE3D,IAAIe,eACFV,SAASU;IAEb;IAEA,OAAOV;AACT;AAEO,eAAeW,iBAAiB,EACrCC,WAAW,EACXtB,UAAU,EACVD,kBAAkB,EAClBE,WAAW,EACXsB,WAAW,EAOZ;IAIC,MAAM,EAAE5B,aAAa,EAAEC,YAAY,EAAEC,iBAAiB,EAAEC,kBAAkB,EAAE,GAC1EwB;IAEF,MAAMpB,uBAA6C;QACjDqB;IACF;IAEA,MAAMb,SAAS,MAAMhB,oBAAoB;QACvCC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;IACF;IAEA,OAAO;QACL,YAAYQ,OAAO,IAAI,CAAC,WAAW;QACnCR;IACF;AACF"}
1
+ {"version":3,"file":"ai-model/service-caller/openai/openai-client.mjs","sources":["../../../../../src/ai-model/service-caller/openai/openai-client.ts"],"sourcesContent":["import {\n type IModelConfig,\n MIDSCENE_LANGFUSE_DEBUG,\n MIDSCENE_LANGSMITH_DEBUG,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport OpenAI from 'openai';\nimport { getVersion } from '../../../utils';\nimport type { createProxyAgentIfNeeded } from '../proxy';\nimport {\n type OpenAIRequestContext,\n wrapOpenAICompatibleFetch,\n} from './openai-request-context';\n\nconst createAndWrapClient = async ({\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n createOpenAIClient,\n effectiveTimeoutMs,\n proxyAgent,\n executionId,\n openAIRequestContext,\n}: {\n openaiBaseURL: IModelConfig['openaiBaseURL'];\n openaiApiKey: IModelConfig['openaiApiKey'];\n openaiExtraConfig: IModelConfig['openaiExtraConfig'];\n createOpenAIClient: IModelConfig['createOpenAIClient'];\n effectiveTimeoutMs: number | null;\n proxyAgent: Awaited<ReturnType<typeof createProxyAgentIfNeeded>>;\n executionId: string;\n openAIRequestContext: OpenAIRequestContext;\n}): Promise<OpenAI> => {\n const warnClient = getDebug('ai:call', { console: true });\n\n const openAIOptions = {\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n // Use fetchOptions.dispatcher for fetch-based SDK instead of httpAgent\n // Note: Type assertion needed due to undici version mismatch between dependencies\n ...(proxyAgent ? { fetchOptions: { dispatcher: proxyAgent as any } } : {}),\n ...openaiExtraConfig,\n // Midscene exposes this setting through MIDSCENE_*_INIT_CONFIG_JSON, so\n // defaultHeaders is expected to be a plain JSON object rather than another\n // HeadersLike representation supported by the OpenAI SDK.\n defaultHeaders: {\n ...(openaiExtraConfig?.defaultHeaders as\n | Record<string, string>\n | undefined),\n // These Midscene-owned headers intentionally override user-supplied\n // headers with the same names.\n 'x-midscene-version': getVersion(),\n 'x-midscene-execution-id': executionId,\n },\n fetch: wrapOpenAICompatibleFetch(openAIRequestContext),\n // Midscene handles request retries in callAI(), so disable SDK-level retries\n // to avoid duplicate attempts and duplicated backoff latency.\n maxRetries: 0,\n // Disabling the Midscene hard timeout leaves the SDK timeout at its\n // configured value or default; it does not disable SDK/network timeouts.\n ...(effectiveTimeoutMs !== null ? { timeout: effectiveTimeoutMs } : {}),\n dangerouslyAllowBrowser: true,\n };\n\n const baseOpenAI = new OpenAI(openAIOptions);\n\n let openai: OpenAI = baseOpenAI;\n\n // LangSmith wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langsmith wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langsmithModule = 'langsmith/wrappers';\n const { wrapOpenAI } = await import(langsmithModule);\n openai = wrapOpenAI(openai);\n }\n\n // Langfuse wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGFUSE_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langfuse is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langfuse wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langfuseModule = '@langfuse/openai';\n const { observeOpenAI } = await import(langfuseModule);\n openai = observeOpenAI(openai);\n }\n\n if (createOpenAIClient) {\n const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);\n\n if (wrappedClient) {\n openai = wrappedClient as OpenAI;\n }\n }\n\n return openai;\n};\n\nexport async function createClient({\n modelConfig,\n proxyAgent,\n effectiveTimeoutMs,\n executionId,\n recordEvent,\n}: {\n modelConfig: IModelConfig;\n proxyAgent: Awaited<ReturnType<typeof createProxyAgentIfNeeded>>;\n effectiveTimeoutMs: number | null;\n executionId: string;\n recordEvent?: (event: Record<string, unknown>) => void;\n}): Promise<{\n openai: OpenAI;\n openAIRequestContext: OpenAIRequestContext;\n}> {\n const { openaiBaseURL, openaiApiKey, openaiExtraConfig, createOpenAIClient } =\n modelConfig;\n\n const openAIRequestContext: OpenAIRequestContext = {\n recordEvent,\n };\n\n const openai = await createAndWrapClient({\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n createOpenAIClient,\n effectiveTimeoutMs,\n proxyAgent,\n executionId,\n openAIRequestContext,\n });\n\n return {\n openai,\n openAIRequestContext,\n };\n}\n"],"names":["createAndWrapClient","openaiBaseURL","openaiApiKey","openaiExtraConfig","createOpenAIClient","effectiveTimeoutMs","proxyAgent","executionId","openAIRequestContext","warnClient","getDebug","openAIOptions","getVersion","wrapOpenAICompatibleFetch","baseOpenAI","OpenAI","openai","globalConfigManager","MIDSCENE_LANGSMITH_DEBUG","ifInBrowser","Error","langsmithModule","wrapOpenAI","MIDSCENE_LANGFUSE_DEBUG","langfuseModule","observeOpenAI","wrappedClient","createClient","modelConfig","recordEvent"],"mappings":";;;;;;AAgBA,MAAMA,sBAAsB,OAAO,EACjCC,aAAa,EACbC,YAAY,EACZC,iBAAiB,EACjBC,kBAAkB,EAClBC,kBAAkB,EAClBC,UAAU,EACVC,WAAW,EACXC,oBAAoB,EAUrB;IACC,MAAMC,aAAaC,SAAS,WAAW;QAAE,SAAS;IAAK;IAEvD,MAAMC,gBAAgB;QACpB,SAASV;QACT,QAAQC;QAGR,GAAII,aAAa;YAAE,cAAc;gBAAE,YAAYA;YAAkB;QAAE,IAAI,CAAC,CAAC;QACzE,GAAGH,iBAAiB;QAIpB,gBAAgB;YACd,GAAIA,mBAAmB,cAAc;YAKrC,sBAAsBS;YACtB,2BAA2BL;QAC7B;QACA,OAAOM,0BAA0BL;QAGjC,YAAY;QAGZ,GAAIH,AAAuB,SAAvBA,qBAA8B;YAAE,SAASA;QAAmB,IAAI,CAAC,CAAC;QACtE,yBAAyB;IAC3B;IAEA,MAAMS,aAAa,IAAIC,SAAOJ;IAE9B,IAAIK,SAAiBF;IAGrB,IACEE,UACAC,oBAAoB,qBAAqB,CAACC,2BAC1C;QACA,IAAIC,aACF,MAAM,IAAIC,MAAM;QAElBX,WAAW;QAEX,MAAMY,kBAAkB;QACxB,MAAM,EAAEC,UAAU,EAAE,GAAG,MAAM,MAAM,CAACD;QACpCL,SAASM,WAAWN;IACtB;IAGA,IACEA,UACAC,oBAAoB,qBAAqB,CAACM,0BAC1C;QACA,IAAIJ,aACF,MAAM,IAAIC,MAAM;QAElBX,WAAW;QAEX,MAAMe,iBAAiB;QACvB,MAAM,EAAEC,aAAa,EAAE,GAAG,MAAM,MAAM,CAACD;QACvCR,SAASS,cAAcT;IACzB;IAEA,IAAIZ,oBAAoB;QACtB,MAAMsB,gBAAgB,MAAMtB,mBAAmBU,YAAYH;QAE3D,IAAIe,eACFV,SAASU;IAEb;IAEA,OAAOV;AACT;AAEO,eAAeW,aAAa,EACjCC,WAAW,EACXtB,UAAU,EACVD,kBAAkB,EAClBE,WAAW,EACXsB,WAAW,EAOZ;IAIC,MAAM,EAAE5B,aAAa,EAAEC,YAAY,EAAEC,iBAAiB,EAAEC,kBAAkB,EAAE,GAC1EwB;IAEF,MAAMpB,uBAA6C;QACjDqB;IACF;IAEA,MAAMb,SAAS,MAAMhB,oBAAoB;QACvCC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;IACF;IAEA,OAAO;QACLQ;QACAR;IACF;AACF"}
@@ -0,0 +1,21 @@
1
+ import { AIResponseParseError, hasUsableText } from "../../utils.mjs";
2
+ import { parseResponse } from "./utils.mjs";
3
+ async function callResponsesNonStreaming({ responses, requestBodyParams, requestSignal, openAIRequestContext }) {
4
+ requestSignal.throwIfAborted();
5
+ const response = await responses.create({
6
+ ...requestBodyParams,
7
+ stream: false
8
+ }, {
9
+ signal: requestSignal
10
+ });
11
+ requestSignal.throwIfAborted();
12
+ const result = parseResponse(response);
13
+ if (!hasUsableText(result.content)) throw new AIResponseParseError('empty content from AI model', result.content, void 0, result.rawAssistantOutput);
14
+ return {
15
+ ...result,
16
+ requestId: response._request_id ?? openAIRequestContext.responseRequestId?.requestId
17
+ };
18
+ }
19
+ export { callResponsesNonStreaming };
20
+
21
+ //# sourceMappingURL=non-stream.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-model/service-caller/openai/responses/non-stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/responses/non-stream.ts"],"sourcesContent":["import type { OpenAIProtocolCallResult } from '../../types';\nimport { AIResponseParseError, hasUsableText } from '../../utils';\nimport type { ResponsesCallOptions } from './types';\nimport { parseResponse } from './utils';\n\nexport async function callResponsesNonStreaming({\n responses,\n requestBodyParams,\n requestSignal,\n openAIRequestContext,\n}: ResponsesCallOptions): Promise<OpenAIProtocolCallResult> {\n requestSignal.throwIfAborted();\n const response = await responses.create(\n { ...requestBodyParams, stream: false },\n { signal: requestSignal },\n );\n requestSignal.throwIfAborted();\n const result = parseResponse(response);\n if (!hasUsableText(result.content)) {\n throw new AIResponseParseError(\n 'empty content from AI model',\n result.content,\n undefined,\n result.rawAssistantOutput,\n );\n }\n return {\n ...result,\n requestId:\n response._request_id ?? openAIRequestContext.responseRequestId?.requestId,\n };\n}\n"],"names":["callResponsesNonStreaming","responses","requestBodyParams","requestSignal","openAIRequestContext","response","result","parseResponse","hasUsableText","AIResponseParseError","undefined"],"mappings":";;AAKO,eAAeA,0BAA0B,EAC9CC,SAAS,EACTC,iBAAiB,EACjBC,aAAa,EACbC,oBAAoB,EACC;IACrBD,cAAc,cAAc;IAC5B,MAAME,WAAW,MAAMJ,UAAU,MAAM,CACrC;QAAE,GAAGC,iBAAiB;QAAE,QAAQ;IAAM,GACtC;QAAE,QAAQC;IAAc;IAE1BA,cAAc,cAAc;IAC5B,MAAMG,SAASC,cAAcF;IAC7B,IAAI,CAACG,cAAcF,OAAO,OAAO,GAC/B,MAAM,IAAIG,qBACR,+BACAH,OAAO,OAAO,EACdI,QACAJ,OAAO,kBAAkB;IAG7B,OAAO;QACL,GAAGA,MAAM;QACT,WACED,SAAS,WAAW,IAAID,qBAAqB,iBAAiB,EAAE;IACpE;AACF"}
@@ -0,0 +1,57 @@
1
+ import { getDebug } from "@midscene/shared/logger";
2
+ import { createProxyAgentIfNeeded } from "../../proxy/index.mjs";
3
+ import { stringifyForDebug } from "../../utils.mjs";
4
+ import { callResponsesNonStreaming } from "./non-stream.mjs";
5
+ import { callResponsesStream } from "./stream.mjs";
6
+ import { toResponsesInput } from "./utils.mjs";
7
+ async function prepareResponses({ messages, modelRuntime, options }) {
8
+ const debugCall = getDebug('ai:call');
9
+ const { config: modelConfig, adapter } = modelRuntime;
10
+ const modelCallInput = {
11
+ intent: modelConfig.intent,
12
+ userConfig: {
13
+ temperature: modelConfig.temperature,
14
+ reasoningEnabled: modelConfig.reasoningEnabled,
15
+ reasoningEffort: modelConfig.reasoningEffort,
16
+ reasoningBudget: modelConfig.reasoningBudget,
17
+ responseFormat: modelConfig.responseFormat
18
+ },
19
+ semanticRetryAttempt: options?.semanticRetryAttempt,
20
+ requiresOriginalImageDetail: options?.requiresOriginalImageDetail,
21
+ expectedJsonObjectResponse: options?.expectedJsonObjectResponse
22
+ };
23
+ const { config } = adapter.responses.buildResponsesParams(modelCallInput);
24
+ debugCall(`adapter responses params: ${stringifyForDebug({
25
+ config
26
+ })}`);
27
+ const resolveImageDetail = ({ imageDetail })=>adapter.resolveImageDetail({
28
+ imageDetail,
29
+ intent: modelConfig.intent,
30
+ requiresOriginalImageDetail: options?.requiresOriginalImageDetail
31
+ });
32
+ const requestParams = {
33
+ ...config,
34
+ ...modelConfig.extraBody
35
+ };
36
+ if (true === requestParams.background) throw new Error('Responses background mode is not supported');
37
+ const requestBodyParams = {
38
+ store: false,
39
+ ...requestParams,
40
+ model: modelConfig.modelName,
41
+ input: toResponsesInput(messages, resolveImageDetail)
42
+ };
43
+ const proxyAgent = await createProxyAgentIfNeeded({
44
+ socksProxy: modelConfig.socksProxy,
45
+ httpProxy: modelConfig.httpProxy
46
+ });
47
+ return {
48
+ requestParams: requestBodyParams,
49
+ proxyAgent
50
+ };
51
+ }
52
+ function callResponses(options, stream) {
53
+ return stream ? callResponsesStream(options) : callResponsesNonStreaming(options);
54
+ }
55
+ export { callResponses, prepareResponses };
56
+
57
+ //# sourceMappingURL=responses.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-model/service-caller/openai/responses/responses.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/responses/responses.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 { callResponsesNonStreaming } from './non-stream';\nimport { callResponsesStream } from './stream';\nimport type { ResponsesCallOptions } from './types';\nimport { toResponsesInput } from './utils';\n\nexport async function prepareResponses({\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 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 const { config } = adapter.responses.buildResponsesParams(modelCallInput);\n debugCall(`adapter responses params: ${stringifyForDebug({ config })}`);\n const resolveImageDetail: ResolveImageDetail = ({ imageDetail }) =>\n adapter.resolveImageDetail({\n imageDetail,\n intent: modelConfig.intent,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n });\n const requestParams = { ...config, ...modelConfig.extraBody };\n if (requestParams.background === true) {\n throw new Error('Responses background mode is not supported');\n }\n const requestBodyParams: ResponsesCallOptions['requestBodyParams'] = {\n store: false,\n ...requestParams,\n model: modelConfig.modelName,\n input: toResponsesInput(messages, resolveImageDetail),\n };\n const proxyAgent = await createProxyAgentIfNeeded({\n socksProxy: modelConfig.socksProxy,\n httpProxy: modelConfig.httpProxy,\n });\n return {\n requestParams: requestBodyParams,\n proxyAgent,\n };\n}\n\nexport function callResponses(\n options: ResponsesCallOptions,\n stream: boolean,\n): Promise<OpenAIProtocolCallResult> {\n return stream\n ? callResponsesStream(options)\n : callResponsesNonStreaming(options);\n}\n"],"names":["prepareResponses","messages","modelRuntime","options","debugCall","getDebug","modelConfig","adapter","modelCallInput","config","stringifyForDebug","resolveImageDetail","imageDetail","requestParams","Error","requestBodyParams","toResponsesInput","proxyAgent","createProxyAgentIfNeeded","callResponses","stream","callResponsesStream","callResponsesNonStreaming"],"mappings":";;;;;;AAWO,eAAeA,iBAAiB,EACrCC,QAAQ,EACRC,YAAY,EACZC,OAAO,EACyD;IAChE,MAAMC,YAAYC,SAAS;IAC3B,MAAM,EAAE,QAAQC,WAAW,EAAEC,OAAO,EAAE,GAAGL;IACzC,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;IACA,MAAM,EAAEM,MAAM,EAAE,GAAGF,QAAQ,SAAS,CAAC,oBAAoB,CAACC;IAC1DJ,UAAU,CAAC,0BAA0B,EAAEM,kBAAkB;QAAED;IAAO,IAAI;IACtE,MAAME,qBAAyC,CAAC,EAAEC,WAAW,EAAE,GAC7DL,QAAQ,kBAAkB,CAAC;YACzBK;YACA,QAAQN,YAAY,MAAM;YAC1B,6BAA6BH,SAAS;QACxC;IACF,MAAMU,gBAAgB;QAAE,GAAGJ,MAAM;QAAE,GAAGH,YAAY,SAAS;IAAC;IAC5D,IAAIO,AAA6B,SAA7BA,cAAc,UAAU,EAC1B,MAAM,IAAIC,MAAM;IAElB,MAAMC,oBAA+D;QACnE,OAAO;QACP,GAAGF,aAAa;QAChB,OAAOP,YAAY,SAAS;QAC5B,OAAOU,iBAAiBf,UAAUU;IACpC;IACA,MAAMM,aAAa,MAAMC,yBAAyB;QAChD,YAAYZ,YAAY,UAAU;QAClC,WAAWA,YAAY,SAAS;IAClC;IACA,OAAO;QACL,eAAeS;QACfE;IACF;AACF;AAEO,SAASE,cACdhB,OAA6B,EAC7BiB,MAAe;IAEf,OAAOA,SACHC,oBAAoBlB,WACpBmB,0BAA0BnB;AAChC"}
@@ -0,0 +1,56 @@
1
+ import { assert } from "@midscene/shared/utils";
2
+ import { AIResponseParseError, hasUsableText } from "../../utils.mjs";
3
+ import { parseResponse } from "./utils.mjs";
4
+ async function callResponsesStream({ responses, requestBodyParams, requestSignal, openAIRequestContext, onChunk, recordEvent }) {
5
+ assert('function' == typeof onChunk, 'onChunk is required when stream is true');
6
+ requestSignal.throwIfAborted();
7
+ const { data: stream, request_id: requestId } = await responses.create({
8
+ ...requestBodyParams,
9
+ stream: true
10
+ }, {
11
+ signal: requestSignal
12
+ }).withResponse();
13
+ let accumulated = '';
14
+ let finalResponse;
15
+ let sequence = 0;
16
+ for await (const event of stream){
17
+ requestSignal.throwIfAborted();
18
+ recordEvent?.({
19
+ type: 'chunk',
20
+ sequence: ++sequence,
21
+ chunk: event
22
+ });
23
+ if ('error' === event.type) throw new Error(event.message);
24
+ if ('response.failed' === event.type || 'response.incomplete' === event.type) parseResponse(event.response);
25
+ if ('response.completed' === event.type) finalResponse = event.response;
26
+ const content = 'response.output_text.delta' === event.type ? event.delta : '';
27
+ const reasoningContent = 'response.reasoning_summary_text.delta' === event.type || 'response.reasoning_text.delta' === event.type ? event.delta : '';
28
+ if (content || reasoningContent) {
29
+ accumulated += content;
30
+ onChunk({
31
+ content,
32
+ reasoning_content: reasoningContent,
33
+ accumulated,
34
+ isComplete: false
35
+ });
36
+ }
37
+ }
38
+ requestSignal.throwIfAborted();
39
+ assert(finalResponse, 'Responses stream ended without a completed response');
40
+ const result = parseResponse(finalResponse);
41
+ if (!hasUsableText(result.content)) throw new AIResponseParseError('empty content from AI model', result.content, void 0, result.rawAssistantOutput);
42
+ onChunk({
43
+ content: '',
44
+ reasoning_content: '',
45
+ accumulated: result.content,
46
+ isComplete: true,
47
+ usage: result.rawUsage
48
+ });
49
+ return {
50
+ ...result,
51
+ requestId: requestId ?? openAIRequestContext.responseRequestId?.requestId
52
+ };
53
+ }
54
+ export { callResponsesStream };
55
+
56
+ //# sourceMappingURL=stream.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-model/service-caller/openai/responses/stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/responses/stream.ts"],"sourcesContent":["import { assert } from '@midscene/shared/utils';\nimport type { Response } from 'openai/resources/responses/responses';\nimport type { OpenAIProtocolCallResult } from '../../types';\nimport { AIResponseParseError, hasUsableText } from '../../utils';\nimport type { ResponsesCallOptions } from './types';\nimport { parseResponse } from './utils';\n\nexport async function callResponsesStream({\n responses,\n requestBodyParams,\n requestSignal,\n openAIRequestContext,\n onChunk,\n recordEvent,\n}: ResponsesCallOptions): Promise<OpenAIProtocolCallResult> {\n assert(\n typeof onChunk === 'function',\n 'onChunk is required when stream is true',\n );\n requestSignal.throwIfAborted();\n const { data: stream, request_id: requestId } = await responses\n .create({ ...requestBodyParams, stream: true }, { signal: requestSignal })\n .withResponse();\n let accumulated = '';\n let finalResponse: Response | undefined;\n let sequence = 0;\n for await (const event of stream) {\n requestSignal.throwIfAborted();\n recordEvent?.({ type: 'chunk', sequence: ++sequence, chunk: event });\n if (event.type === 'error') {\n throw new Error(event.message);\n }\n if (\n event.type === 'response.failed' ||\n event.type === 'response.incomplete'\n ) {\n parseResponse(event.response);\n }\n if (event.type === 'response.completed') {\n finalResponse = event.response;\n }\n const content =\n event.type === 'response.output_text.delta' ? event.delta : '';\n const reasoningContent =\n event.type === 'response.reasoning_summary_text.delta' ||\n event.type === 'response.reasoning_text.delta'\n ? event.delta\n : '';\n if (content || reasoningContent) {\n accumulated += content;\n onChunk({\n content,\n reasoning_content: reasoningContent,\n accumulated,\n isComplete: false,\n });\n }\n }\n requestSignal.throwIfAborted();\n assert(finalResponse, 'Responses stream ended without a completed response');\n const result = parseResponse(finalResponse);\n if (!hasUsableText(result.content)) {\n throw new AIResponseParseError(\n 'empty content from AI model',\n result.content,\n undefined,\n result.rawAssistantOutput,\n );\n }\n onChunk({\n content: '',\n reasoning_content: '',\n accumulated: result.content,\n isComplete: true,\n usage: result.rawUsage,\n });\n return {\n ...result,\n requestId: requestId ?? openAIRequestContext.responseRequestId?.requestId,\n };\n}\n"],"names":["callResponsesStream","responses","requestBodyParams","requestSignal","openAIRequestContext","onChunk","recordEvent","assert","stream","requestId","accumulated","finalResponse","sequence","event","Error","parseResponse","content","reasoningContent","result","hasUsableText","AIResponseParseError","undefined"],"mappings":";;;AAOO,eAAeA,oBAAoB,EACxCC,SAAS,EACTC,iBAAiB,EACjBC,aAAa,EACbC,oBAAoB,EACpBC,OAAO,EACPC,WAAW,EACU;IACrBC,OACE,AAAmB,cAAnB,OAAOF,SACP;IAEFF,cAAc,cAAc;IAC5B,MAAM,EAAE,MAAMK,MAAM,EAAE,YAAYC,SAAS,EAAE,GAAG,MAAMR,UACnD,MAAM,CAAC;QAAE,GAAGC,iBAAiB;QAAE,QAAQ;IAAK,GAAG;QAAE,QAAQC;IAAc,GACvE,YAAY;IACf,IAAIO,cAAc;IAClB,IAAIC;IACJ,IAAIC,WAAW;IACf,WAAW,MAAMC,SAASL,OAAQ;QAChCL,cAAc,cAAc;QAC5BG,cAAc;YAAE,MAAM;YAAS,UAAU,EAAEM;YAAU,OAAOC;QAAM;QAClE,IAAIA,AAAe,YAAfA,MAAM,IAAI,EACZ,MAAM,IAAIC,MAAMD,MAAM,OAAO;QAE/B,IACEA,AAAe,sBAAfA,MAAM,IAAI,IACVA,AAAe,0BAAfA,MAAM,IAAI,EAEVE,cAAcF,MAAM,QAAQ;QAE9B,IAAIA,AAAe,yBAAfA,MAAM,IAAI,EACZF,gBAAgBE,MAAM,QAAQ;QAEhC,MAAMG,UACJH,AAAe,iCAAfA,MAAM,IAAI,GAAoCA,MAAM,KAAK,GAAG;QAC9D,MAAMI,mBACJJ,AAAe,4CAAfA,MAAM,IAAI,IACVA,AAAe,oCAAfA,MAAM,IAAI,GACNA,MAAM,KAAK,GACX;QACN,IAAIG,WAAWC,kBAAkB;YAC/BP,eAAeM;YACfX,QAAQ;gBACNW;gBACA,mBAAmBC;gBACnBP;gBACA,YAAY;YACd;QACF;IACF;IACAP,cAAc,cAAc;IAC5BI,OAAOI,eAAe;IACtB,MAAMO,SAASH,cAAcJ;IAC7B,IAAI,CAACQ,cAAcD,OAAO,OAAO,GAC/B,MAAM,IAAIE,qBACR,+BACAF,OAAO,OAAO,EACdG,QACAH,OAAO,kBAAkB;IAG7Bb,QAAQ;QACN,SAAS;QACT,mBAAmB;QACnB,aAAaa,OAAO,OAAO;QAC3B,YAAY;QACZ,OAAOA,OAAO,QAAQ;IACxB;IACA,OAAO;QACL,GAAGA,MAAM;QACT,WAAWT,aAAaL,qBAAqB,iBAAiB,EAAE;IAClE;AACF"}
@@ -0,0 +1,72 @@
1
+ function toResponsesInput(messages, resolveImageDetail) {
2
+ return messages.flatMap((entry)=>{
3
+ if ('type' in entry && 'model-output' === entry.type) {
4
+ if ('responses' !== entry.output.type) throw new Error('Cannot replay Chat Completions output in a Responses conversation');
5
+ return entry.output.rawValue;
6
+ }
7
+ const message = 'role' in entry ? entry : entry.message;
8
+ if ('string' == typeof message.content) return [
9
+ {
10
+ role: message.role,
11
+ content: message.content
12
+ }
13
+ ];
14
+ if ('assistant' === message.role) return [
15
+ {
16
+ role: message.role,
17
+ content: message.content.map((part)=>part.text).join('')
18
+ }
19
+ ];
20
+ return [
21
+ {
22
+ role: message.role,
23
+ content: message.content.map((part)=>{
24
+ if ('text' === part.type) return {
25
+ type: 'input_text',
26
+ text: part.text
27
+ };
28
+ return {
29
+ type: 'input_image',
30
+ image_url: part.url,
31
+ detail: resolveImageDetail({
32
+ imageDetail: part.detail
33
+ })
34
+ };
35
+ })
36
+ }
37
+ ];
38
+ });
39
+ }
40
+ function mapResponsesUsage(usage) {
41
+ if (!usage) return;
42
+ return {
43
+ prompt_tokens: usage.input_tokens,
44
+ completion_tokens: usage.output_tokens,
45
+ total_tokens: usage.total_tokens,
46
+ prompt_tokens_details: usage.input_tokens_details,
47
+ completion_tokens_details: usage.output_tokens_details
48
+ };
49
+ }
50
+ function parseResponse(response) {
51
+ if ('completed' !== response.status) throw new Error(`Responses request ${response.status}: ${response.error?.message ?? response.incomplete_details?.reason ?? 'response did not complete'}`);
52
+ const content = response.output.flatMap((item)=>'message' === item.type ? item.content.flatMap((part)=>'output_text' === part.type ? [
53
+ part.text
54
+ ] : []) : []).join('');
55
+ const reasoningContent = response.output.flatMap((item)=>{
56
+ if ('reasoning' !== item.type) return [];
57
+ return (item.content?.length ? item.content : item.summary).map((part)=>part.text);
58
+ }).join('');
59
+ return {
60
+ content,
61
+ reasoningContent,
62
+ rawAssistantOutput: {
63
+ type: 'responses',
64
+ rawValue: response.output
65
+ },
66
+ rawUsage: mapResponsesUsage(response.usage),
67
+ responseModelName: response.model
68
+ };
69
+ }
70
+ export { mapResponsesUsage, parseResponse, toResponsesInput };
71
+
72
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-model/service-caller/openai/responses/utils.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/responses/utils.ts"],"sourcesContent":["import type OpenAI from 'openai';\nimport type {\n Response,\n ResponseInput,\n ResponseInputImage,\n ResponseUsage,\n} from 'openai/resources/responses/responses';\nimport type { ResolveImageDetail } from '../../../model-adapter/types';\nimport type { ModelCallMessages, OpenAIProtocolCallResult } from '../../types';\n\nexport function toResponsesInput(\n messages: ModelCallMessages,\n resolveImageDetail: ResolveImageDetail,\n): ResponseInput {\n return messages.flatMap((entry): ResponseInput => {\n if ('type' in entry && entry.type === 'model-output') {\n if (entry.output.type !== 'responses') {\n throw new Error(\n 'Cannot replay Chat Completions output in a Responses conversation',\n );\n }\n return entry.output.rawValue;\n }\n const message = 'role' in entry ? entry : entry.message;\n if (typeof message.content === 'string') {\n return [{ role: message.role, content: message.content }];\n }\n if (message.role === 'assistant') {\n return [\n {\n role: message.role,\n content: message.content.map((part) => part.text).join(''),\n },\n ];\n }\n return [\n {\n role: message.role,\n content: message.content.map((part) => {\n if (part.type === 'text') {\n return { type: 'input_text' as const, text: part.text };\n }\n return {\n type: 'input_image' as const,\n image_url: part.url,\n // The installed SDK does not yet type `original`.\n detail: resolveImageDetail({\n imageDetail: part.detail,\n }) as ResponseInputImage['detail'],\n };\n }),\n },\n ];\n });\n}\n\nexport function mapResponsesUsage(\n usage: ResponseUsage | undefined,\n): OpenAI.CompletionUsage | undefined {\n if (!usage) {\n return undefined;\n }\n return {\n prompt_tokens: usage.input_tokens,\n completion_tokens: usage.output_tokens,\n total_tokens: usage.total_tokens,\n prompt_tokens_details: usage.input_tokens_details,\n completion_tokens_details: usage.output_tokens_details,\n };\n}\n\nexport function parseResponse(response: Response): OpenAIProtocolCallResult {\n if (response.status !== 'completed') {\n throw new Error(\n `Responses request ${response.status}: ${response.error?.message ?? response.incomplete_details?.reason ?? 'response did not complete'}`,\n );\n }\n const content = response.output\n .flatMap((item) =>\n item.type === 'message'\n ? item.content.flatMap((part) =>\n part.type === 'output_text' ? [part.text] : [],\n )\n : [],\n )\n .join('');\n const reasoningContent = response.output\n .flatMap((item) => {\n if (item.type !== 'reasoning') {\n return [];\n }\n return (item.content?.length ? item.content : item.summary).map(\n (part) => part.text,\n );\n })\n .join('');\n return {\n content,\n reasoningContent,\n rawAssistantOutput: { type: 'responses', rawValue: response.output },\n rawUsage: mapResponsesUsage(response.usage),\n responseModelName: response.model,\n };\n}\n"],"names":["toResponsesInput","messages","resolveImageDetail","entry","Error","message","part","mapResponsesUsage","usage","parseResponse","response","content","item","reasoningContent"],"mappings":"AAUO,SAASA,iBACdC,QAA2B,EAC3BC,kBAAsC;IAEtC,OAAOD,SAAS,OAAO,CAAC,CAACE;QACvB,IAAI,UAAUA,SAASA,AAAe,mBAAfA,MAAM,IAAI,EAAqB;YACpD,IAAIA,AAAsB,gBAAtBA,MAAM,MAAM,CAAC,IAAI,EACnB,MAAM,IAAIC,MACR;YAGJ,OAAOD,MAAM,MAAM,CAAC,QAAQ;QAC9B;QACA,MAAME,UAAU,UAAUF,QAAQA,QAAQA,MAAM,OAAO;QACvD,IAAI,AAA2B,YAA3B,OAAOE,QAAQ,OAAO,EACxB,OAAO;YAAC;gBAAE,MAAMA,QAAQ,IAAI;gBAAE,SAASA,QAAQ,OAAO;YAAC;SAAE;QAE3D,IAAIA,AAAiB,gBAAjBA,QAAQ,IAAI,EACd,OAAO;YACL;gBACE,MAAMA,QAAQ,IAAI;gBAClB,SAASA,QAAQ,OAAO,CAAC,GAAG,CAAC,CAACC,OAASA,KAAK,IAAI,EAAE,IAAI,CAAC;YACzD;SACD;QAEH,OAAO;YACL;gBACE,MAAMD,QAAQ,IAAI;gBAClB,SAASA,QAAQ,OAAO,CAAC,GAAG,CAAC,CAACC;oBAC5B,IAAIA,AAAc,WAAdA,KAAK,IAAI,EACX,OAAO;wBAAE,MAAM;wBAAuB,MAAMA,KAAK,IAAI;oBAAC;oBAExD,OAAO;wBACL,MAAM;wBACN,WAAWA,KAAK,GAAG;wBAEnB,QAAQJ,mBAAmB;4BACzB,aAAaI,KAAK,MAAM;wBAC1B;oBACF;gBACF;YACF;SACD;IACH;AACF;AAEO,SAASC,kBACdC,KAAgC;IAEhC,IAAI,CAACA,OACH;IAEF,OAAO;QACL,eAAeA,MAAM,YAAY;QACjC,mBAAmBA,MAAM,aAAa;QACtC,cAAcA,MAAM,YAAY;QAChC,uBAAuBA,MAAM,oBAAoB;QACjD,2BAA2BA,MAAM,qBAAqB;IACxD;AACF;AAEO,SAASC,cAAcC,QAAkB;IAC9C,IAAIA,AAAoB,gBAApBA,SAAS,MAAM,EACjB,MAAM,IAAIN,MACR,CAAC,kBAAkB,EAAEM,SAAS,MAAM,CAAC,EAAE,EAAEA,SAAS,KAAK,EAAE,WAAWA,SAAS,kBAAkB,EAAE,UAAU,6BAA6B;IAG5I,MAAMC,UAAUD,SAAS,MAAM,CAC5B,OAAO,CAAC,CAACE,OACRA,AAAc,cAAdA,KAAK,IAAI,GACLA,KAAK,OAAO,CAAC,OAAO,CAAC,CAACN,OACpBA,AAAc,kBAAdA,KAAK,IAAI,GAAqB;gBAACA,KAAK,IAAI;aAAC,GAAG,EAAE,IAEhD,EAAE,EAEP,IAAI,CAAC;IACR,MAAMO,mBAAmBH,SAAS,MAAM,CACrC,OAAO,CAAC,CAACE;QACR,IAAIA,AAAc,gBAAdA,KAAK,IAAI,EACX,OAAO,EAAE;QAEX,OAAQA,AAAAA,CAAAA,KAAK,OAAO,EAAE,SAASA,KAAK,OAAO,GAAGA,KAAK,OAAM,EAAG,GAAG,CAC7D,CAACN,OAASA,KAAK,IAAI;IAEvB,GACC,IAAI,CAAC;IACR,OAAO;QACLK;QACAE;QACA,oBAAoB;YAAE,MAAM;YAAa,UAAUH,SAAS,MAAM;QAAC;QACnE,UAAUH,kBAAkBG,SAAS,KAAK;QAC1C,mBAAmBA,SAAS,KAAK;IACnC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/semantic-retry.mjs","sources":["../../../../src/ai-model/service-caller/semantic-retry.ts"],"sourcesContent":["import type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport { waitForRetry } from './request-timeout';\n\nexport function withSemanticRetryFeedback(\n messages: ChatCompletionMessageParam[],\n previousParseError?: unknown,\n): ChatCompletionMessageParam[] {\n if (!previousParseError) return messages;\n\n const errorMessage =\n previousParseError instanceof Error\n ? previousParseError.message\n : String(previousParseError);\n\n return [\n ...messages,\n {\n role: 'user',\n content: `The previous response was invalid:\\n${errorMessage}\\n\\nPlease avoid the validation error above in this response.`,\n },\n ];\n}\n\nexport type CallAiAndParseWithRetryOptions<Response, Parsed> = {\n /** Sends a single model request. Request errors are always propagated as-is. */\n /**\n * `retryAttempt` is local to this retry loop: 0 for the initial request,\n * then incremented after each parsing failure.\n */\n callAi: (\n retryAttempt: number,\n previousParseError?: unknown,\n ) => Promise<Response>;\n /** Parses a successful model response. Only failures from this callback retry. */\n parseResponse: (response: Response) => Parsed | Promise<Parsed>;\n /** Converts the final parsing failure into the caller's domain error. */\n toParseError: (error: unknown, response: Response) => Error;\n /** Number of additional model requests after a parsing failure. Defaults to 0. */\n parseRetryTimes?: number;\n /** Delay in milliseconds before retrying a parsing failure. Defaults to 0. */\n parseRetryInterval?: number;\n abortSignal?: AbortSignal;\n /** Runs immediately before a parsing failure triggers another model request. */\n onParseRetry?: (error: unknown, response: Response) => void;\n};\n\n/**\n * Calls AI and parses its response, retrying only when the response cannot be\n * structurally parsed.\n *\n * Errors thrown by callAi() intentionally bypass this retry mechanism and are\n * propagated as-is. Only a successful callAi() response that fails the\n * parseResponse() callback triggers another model request.\n */\nexport async function callAiAndParseWithRetry<Response, Parsed>({\n callAi,\n parseResponse,\n toParseError,\n parseRetryTimes = 0,\n parseRetryInterval = 0,\n abortSignal,\n onParseRetry,\n}: CallAiAndParseWithRetryOptions<Response, Parsed>): Promise<Parsed> {\n const normalizedRetryTimes = Number.isFinite(parseRetryTimes)\n ? Math.max(0, Math.floor(parseRetryTimes))\n : 0;\n const normalizedRetryInterval = Number.isFinite(parseRetryInterval)\n ? Math.max(0, parseRetryInterval)\n : 0;\n\n const callAndParseOnce = async (\n remainingRetries: number,\n retryAttempt: number,\n previousParseError?: unknown,\n ): Promise<Parsed> => {\n abortSignal?.throwIfAborted();\n const response = await callAi(retryAttempt, previousParseError);\n\n try {\n const parsed = await parseResponse(response);\n abortSignal?.throwIfAborted();\n return parsed;\n } catch (error) {\n abortSignal?.throwIfAborted();\n if (remainingRetries > 0) {\n onParseRetry?.(error, response);\n if (normalizedRetryInterval > 0) {\n await waitForRetry(normalizedRetryInterval, abortSignal);\n }\n abortSignal?.throwIfAborted();\n return callAndParseOnce(remainingRetries - 1, retryAttempt + 1, error);\n }\n throw toParseError(error, response);\n }\n };\n\n return callAndParseOnce(normalizedRetryTimes, 0);\n}\n"],"names":["withSemanticRetryFeedback","messages","previousParseError","errorMessage","Error","String","callAiAndParseWithRetry","callAi","parseResponse","toParseError","parseRetryTimes","parseRetryInterval","abortSignal","onParseRetry","normalizedRetryTimes","Number","Math","normalizedRetryInterval","callAndParseOnce","remainingRetries","retryAttempt","response","parsed","error","waitForRetry"],"mappings":";AAGO,SAASA,0BACdC,QAAsC,EACtCC,kBAA4B;IAE5B,IAAI,CAACA,oBAAoB,OAAOD;IAEhC,MAAME,eACJD,8BAA8BE,QAC1BF,mBAAmB,OAAO,GAC1BG,OAAOH;IAEb,OAAO;WACFD;QACH;YACE,MAAM;YACN,SAAS,CAAC,oCAAoC,EAAEE,aAAa,6DAA6D,CAAC;QAC7H;KACD;AACH;AAiCO,eAAeG,wBAA0C,EAC9DC,MAAM,EACNC,aAAa,EACbC,YAAY,EACZC,kBAAkB,CAAC,EACnBC,qBAAqB,CAAC,EACtBC,WAAW,EACXC,YAAY,EACqC;IACjD,MAAMC,uBAAuBC,OAAO,QAAQ,CAACL,mBACzCM,KAAK,GAAG,CAAC,GAAGA,KAAK,KAAK,CAACN,oBACvB;IACJ,MAAMO,0BAA0BF,OAAO,QAAQ,CAACJ,sBAC5CK,KAAK,GAAG,CAAC,GAAGL,sBACZ;IAEJ,MAAMO,mBAAmB,OACvBC,kBACAC,cACAlB;QAEAU,aAAa;QACb,MAAMS,WAAW,MAAMd,OAAOa,cAAclB;QAE5C,IAAI;YACF,MAAMoB,SAAS,MAAMd,cAAca;YACnCT,aAAa;YACb,OAAOU;QACT,EAAE,OAAOC,OAAO;YACdX,aAAa;YACb,IAAIO,mBAAmB,GAAG;gBACxBN,eAAeU,OAAOF;gBACtB,IAAIJ,0BAA0B,GAC5B,MAAMO,aAAaP,yBAAyBL;gBAE9CA,aAAa;gBACb,OAAOM,iBAAiBC,mBAAmB,GAAGC,eAAe,GAAGG;YAClE;YACA,MAAMd,aAAac,OAAOF;QAC5B;IACF;IAEA,OAAOH,iBAAiBJ,sBAAsB;AAChD"}
1
+ {"version":3,"file":"ai-model/service-caller/semantic-retry.mjs","sources":["../../../../src/ai-model/service-caller/semantic-retry.ts"],"sourcesContent":["import { waitForRetry } from './request-timeout';\nimport type { ModelCallMessages } from './types';\n\nexport function withSemanticRetryFeedback(\n messages: ModelCallMessages,\n previousParseError?: unknown,\n): ModelCallMessages {\n if (!previousParseError) return messages;\n\n const errorMessage =\n previousParseError instanceof Error\n ? previousParseError.message\n : String(previousParseError);\n\n return [\n ...messages,\n {\n role: 'user',\n content: `The previous response was invalid:\\n${errorMessage}\\n\\nPlease avoid the validation error above in this response.`,\n },\n ];\n}\n\nexport type CallAiAndParseWithRetryOptions<Response, Parsed> = {\n /** Sends a single model request. Request errors are always propagated as-is. */\n /**\n * `retryAttempt` is local to this retry loop: 0 for the initial request,\n * then incremented after each parsing failure.\n */\n callAi: (\n retryAttempt: number,\n previousParseError?: unknown,\n ) => Promise<Response>;\n /** Parses a successful model response. Only failures from this callback retry. */\n parseResponse: (response: Response) => Parsed | Promise<Parsed>;\n /** Converts the final parsing failure into the caller's domain error. */\n toParseError: (error: unknown, response: Response) => Error;\n /** Number of additional model requests after a parsing failure. Defaults to 0. */\n parseRetryTimes?: number;\n /** Delay in milliseconds before retrying a parsing failure. Defaults to 0. */\n parseRetryInterval?: number;\n abortSignal?: AbortSignal;\n /** Runs immediately before a parsing failure triggers another model request. */\n onParseRetry?: (error: unknown, response: Response) => void;\n};\n\n/**\n * Calls AI and parses its response, retrying only when the response cannot be\n * structurally parsed.\n *\n * Errors thrown by callAi() intentionally bypass this retry mechanism and are\n * propagated as-is. Only a successful callAi() response that fails the\n * parseResponse() callback triggers another model request.\n */\nexport async function callAiAndParseWithRetry<Response, Parsed>({\n callAi,\n parseResponse,\n toParseError,\n parseRetryTimes = 0,\n parseRetryInterval = 0,\n abortSignal,\n onParseRetry,\n}: CallAiAndParseWithRetryOptions<Response, Parsed>): Promise<Parsed> {\n const normalizedRetryTimes = Number.isFinite(parseRetryTimes)\n ? Math.max(0, Math.floor(parseRetryTimes))\n : 0;\n const normalizedRetryInterval = Number.isFinite(parseRetryInterval)\n ? Math.max(0, parseRetryInterval)\n : 0;\n\n const callAndParseOnce = async (\n remainingRetries: number,\n retryAttempt: number,\n previousParseError?: unknown,\n ): Promise<Parsed> => {\n abortSignal?.throwIfAborted();\n const response = await callAi(retryAttempt, previousParseError);\n\n try {\n const parsed = await parseResponse(response);\n abortSignal?.throwIfAborted();\n return parsed;\n } catch (error) {\n abortSignal?.throwIfAborted();\n if (remainingRetries > 0) {\n onParseRetry?.(error, response);\n if (normalizedRetryInterval > 0) {\n await waitForRetry(normalizedRetryInterval, abortSignal);\n }\n abortSignal?.throwIfAborted();\n return callAndParseOnce(remainingRetries - 1, retryAttempt + 1, error);\n }\n throw toParseError(error, response);\n }\n };\n\n return callAndParseOnce(normalizedRetryTimes, 0);\n}\n"],"names":["withSemanticRetryFeedback","messages","previousParseError","errorMessage","Error","String","callAiAndParseWithRetry","callAi","parseResponse","toParseError","parseRetryTimes","parseRetryInterval","abortSignal","onParseRetry","normalizedRetryTimes","Number","Math","normalizedRetryInterval","callAndParseOnce","remainingRetries","retryAttempt","response","parsed","error","waitForRetry"],"mappings":";AAGO,SAASA,0BACdC,QAA2B,EAC3BC,kBAA4B;IAE5B,IAAI,CAACA,oBAAoB,OAAOD;IAEhC,MAAME,eACJD,8BAA8BE,QAC1BF,mBAAmB,OAAO,GAC1BG,OAAOH;IAEb,OAAO;WACFD;QACH;YACE,MAAM;YACN,SAAS,CAAC,oCAAoC,EAAEE,aAAa,6DAA6D,CAAC;QAC7H;KACD;AACH;AAiCO,eAAeG,wBAA0C,EAC9DC,MAAM,EACNC,aAAa,EACbC,YAAY,EACZC,kBAAkB,CAAC,EACnBC,qBAAqB,CAAC,EACtBC,WAAW,EACXC,YAAY,EACqC;IACjD,MAAMC,uBAAuBC,OAAO,QAAQ,CAACL,mBACzCM,KAAK,GAAG,CAAC,GAAGA,KAAK,KAAK,CAACN,oBACvB;IACJ,MAAMO,0BAA0BF,OAAO,QAAQ,CAACJ,sBAC5CK,KAAK,GAAG,CAAC,GAAGL,sBACZ;IAEJ,MAAMO,mBAAmB,OACvBC,kBACAC,cACAlB;QAEAU,aAAa;QACb,MAAMS,WAAW,MAAMd,OAAOa,cAAclB;QAE5C,IAAI;YACF,MAAMoB,SAAS,MAAMd,cAAca;YACnCT,aAAa;YACb,OAAOU;QACT,EAAE,OAAOC,OAAO;YACdX,aAAa;YACb,IAAIO,mBAAmB,GAAG;gBACxBN,eAAeU,OAAOF;gBACtB,IAAIJ,0BAA0B,GAC5B,MAAMO,aAAaP,yBAAyBL;gBAE9CA,aAAa;gBACb,OAAOM,iBAAiBC,mBAAmB,GAAGC,eAAe,GAAGG;YAClE;YACA,MAAMd,aAAac,OAAOF;QAC5B;IACF;IAEA,OAAOH,iBAAiBJ,sBAAsB;AAChD"}
@@ -9,12 +9,12 @@ function _define_property(obj, key, value) {
9
9
  return obj;
10
10
  }
11
11
  class AIResponseParseError extends Error {
12
- constructor(message, rawResponse, usage, rawChoiceMessage, reasoningContent){
13
- super(message), _define_property(this, "usage", void 0), _define_property(this, "rawResponse", void 0), _define_property(this, "rawChoiceMessage", void 0), _define_property(this, "reasoningContent", void 0);
12
+ constructor(message, rawResponse, usage, rawAssistantOutput, reasoningContent){
13
+ super(message), _define_property(this, "usage", void 0), _define_property(this, "rawResponse", void 0), _define_property(this, "rawAssistantOutput", void 0), _define_property(this, "reasoningContent", void 0);
14
14
  this.name = 'AIResponseParseError';
15
15
  this.rawResponse = rawResponse;
16
16
  this.usage = usage;
17
- this.rawChoiceMessage = rawChoiceMessage;
17
+ this.rawAssistantOutput = rawAssistantOutput;
18
18
  this.reasoningContent = reasoningContent;
19
19
  }
20
20
  }
@@ -53,11 +53,12 @@ function appendAIRequestFailureSummary(error, attemptErrors, maxAttempts) {
53
53
  error.message = `${error.message}\nPrevious AI call attempt errors:\n${details}`;
54
54
  return error;
55
55
  }
56
- const buildUsageInfo = ({ usageData, requestId, timeCost, totalTimeCost, retryCount, modelName, modelDescription, responseModelName, slot, internalCallId })=>{
56
+ const buildUsageInfo = ({ apiType, usageData, requestId, timeCost, totalTimeCost, retryCount, modelName, modelDescription, responseModelName, slot, internalCallId })=>{
57
57
  if (!usageData) return;
58
58
  const cachedInputTokens = usageData?.prompt_tokens_details?.cached_tokens;
59
59
  return {
60
60
  ...usageData,
61
+ api_type: apiType,
61
62
  prompt_tokens: usageData.prompt_tokens ?? 0,
62
63
  completion_tokens: usageData.completion_tokens ?? 0,
63
64
  total_tokens: usageData.total_tokens ?? 0,
@@ -74,27 +75,7 @@ const buildUsageInfo = ({ usageData, requestId, timeCost, totalTimeCost, retryCo
74
75
  [INTERNAL_CALL_ID_FIELD]: internalCallId
75
76
  };
76
77
  };
77
- const applyImageDetail = ({ imageDetail, messages })=>{
78
- if (!imageDetail) return messages;
79
- return messages.map((msg)=>{
80
- if (!Array.isArray(msg.content)) return msg;
81
- const content = msg.content.map((part)=>{
82
- if (part && 'image_url' === part.type && part.image_url?.url) return {
83
- ...part,
84
- image_url: {
85
- ...part.image_url,
86
- detail: imageDetail
87
- }
88
- };
89
- return part;
90
- });
91
- return {
92
- ...msg,
93
- content
94
- };
95
- });
96
- };
97
78
  const hasUsableText = (value)=>'string' == typeof value && value.trim().length > 0;
98
- export { AIResponseParseError, INTERNAL_CALL_ID_FIELD, appendAIRequestFailureSummary, applyImageDetail, buildUsageInfo, hasUsableText, nextInternalCallId, normalizeRetryCount, stringifyForDebug, toError };
79
+ export { AIResponseParseError, INTERNAL_CALL_ID_FIELD, appendAIRequestFailureSummary, buildUsageInfo, hasUsableText, nextInternalCallId, normalizeRetryCount, stringifyForDebug, toError };
99
80
 
100
81
  //# sourceMappingURL=utils.mjs.map