@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,4 +1,4 @@
1
- const defaultImageDetail = (_input)=>void 0;
1
+ import { getTemperatureWithSemanticRetry } from "./temperature-with-semantic-retry.mjs";
2
2
  const defaultChatCompletionParams = ({ midsceneDefaults, userConfig })=>({
3
3
  config: {
4
4
  temperature: userConfig.temperature ?? midsceneDefaults.temperature
@@ -31,7 +31,6 @@ function resolveExtractContentAndReasoning(chatCompletion) {
31
31
  }
32
32
  function resolveChatCompletion(chatCompletion) {
33
33
  const buildChatCompletionParams = chatCompletion?.buildChatCompletionParams ?? defaultChatCompletionParams;
34
- const resolveImageDetail = chatCompletion?.resolveImageDetail ?? defaultImageDetail;
35
34
  const unsupportedUserConfig = chatCompletion?.unsupportedUserConfig ?? [];
36
35
  const extractContentAndReasoning = resolveExtractContentAndReasoning(chatCompletion);
37
36
  const useReasoningAsContentFallback = chatCompletion?.useReasoningAsContentFallback ?? false;
@@ -45,20 +44,18 @@ function resolveChatCompletion(chatCompletion) {
45
44
  midsceneDefaults: midsceneChatCompletionDefaults
46
45
  };
47
46
  const params = buildChatCompletionParams(context);
48
- const retryAttempt = input.semanticRetryAttempt ?? 0;
49
- if (retryAttempt > 0 && input.userConfig?.temperature === void 0 && 0 === params.config.temperature) return {
47
+ return {
48
+ ...params,
50
49
  config: {
51
50
  ...params.config,
52
- temperature: 0.2
51
+ temperature: getTemperatureWithSemanticRetry({
52
+ temperature: params.config.temperature,
53
+ userTemperature: input.userConfig?.temperature,
54
+ semanticRetryAttempt: input.semanticRetryAttempt
55
+ })
53
56
  }
54
57
  };
55
- return params;
56
58
  },
57
- resolveImageDetail: (input)=>resolveImageDetail({
58
- ...input,
59
- userConfig: input.userConfig ?? {},
60
- midsceneDefaults: midsceneChatCompletionDefaults
61
- }),
62
59
  extractContentAndReasoning,
63
60
  useReasoningAsContentFallback,
64
61
  replayRawAssistantMessage
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/model-adapter/chat-completion.mjs","sources":["../../../../src/ai-model/model-adapter/chat-completion.ts"],"sourcesContent":["import type {\n ChatCompletionAdapter,\n ChatCompletionCallContext,\n ExtractContentAndReasoning,\n MidsceneChatCompletionDefaults,\n ModelAdapterDefinition,\n} from './types';\n\nconst defaultImageDetail = (_input: unknown) => undefined;\n\nconst defaultChatCompletionParams = ({\n midsceneDefaults,\n userConfig,\n}: ChatCompletionCallContext) => ({\n config: {\n temperature: userConfig.temperature ?? midsceneDefaults.temperature,\n },\n});\n\nconst midsceneChatCompletionDefaults: MidsceneChatCompletionDefaults = {\n temperature: 0,\n};\n\nfunction createDefaultExtractContentAndReasoning(\n reasoningContentKeys: string[],\n): ExtractContentAndReasoning {\n return (message) => {\n if (!message) {\n return {\n content: '',\n reasoning_content: '',\n };\n }\n\n const messageRecord = message as Record<string, unknown>;\n const rawReasoning = reasoningContentKeys\n .map((key) => messageRecord[key])\n .find((value) => typeof value === 'string');\n const messageReasoning =\n typeof rawReasoning === 'string' ? rawReasoning : '';\n\n return {\n content: typeof message.content === 'string' ? message.content : '',\n reasoning_content: messageReasoning,\n };\n };\n}\n\nfunction resolveExtractContentAndReasoning(\n chatCompletion: ModelAdapterDefinition['chatCompletion'],\n): ExtractContentAndReasoning {\n const messageExtraction = chatCompletion?.messageExtraction;\n if (messageExtraction?.kind === 'custom') {\n return messageExtraction.extractContentAndReasoning;\n }\n\n return createDefaultExtractContentAndReasoning(\n messageExtraction?.reasoningContentKeys ?? ['reasoning_content'],\n );\n}\n\nexport function resolveChatCompletion(\n chatCompletion: ModelAdapterDefinition['chatCompletion'],\n): ChatCompletionAdapter {\n const buildChatCompletionParams =\n chatCompletion?.buildChatCompletionParams ?? defaultChatCompletionParams;\n const resolveImageDetail =\n chatCompletion?.resolveImageDetail ?? defaultImageDetail;\n const unsupportedUserConfig = chatCompletion?.unsupportedUserConfig ?? [];\n const extractContentAndReasoning =\n resolveExtractContentAndReasoning(chatCompletion);\n const useReasoningAsContentFallback =\n chatCompletion?.useReasoningAsContentFallback ?? false;\n const replayRawAssistantMessage =\n chatCompletion?.replayRawAssistantMessage ?? false;\n\n return {\n unsupportedUserConfig,\n buildChatCompletionParams: (input) => {\n const context = {\n ...input,\n userConfig: input.userConfig ?? {},\n midsceneDefaults: midsceneChatCompletionDefaults,\n };\n const params = buildChatCompletionParams(context);\n const retryAttempt = input.semanticRetryAttempt ?? 0;\n // Only perturb the default deterministic request after a semantic parse\n // failure: preserve an explicit user temperature, and avoid adding a\n // temperature to adapters whose normal parameters do not include one.\n if (\n retryAttempt > 0 &&\n input.userConfig?.temperature === undefined &&\n params.config.temperature === 0\n ) {\n return {\n config: {\n ...params.config,\n temperature: 0.2,\n },\n };\n }\n return params;\n },\n resolveImageDetail: (input) =>\n resolveImageDetail({\n ...input,\n userConfig: input.userConfig ?? {},\n midsceneDefaults: midsceneChatCompletionDefaults,\n }),\n extractContentAndReasoning,\n useReasoningAsContentFallback,\n replayRawAssistantMessage,\n };\n}\n"],"names":["defaultImageDetail","_input","undefined","defaultChatCompletionParams","midsceneDefaults","userConfig","midsceneChatCompletionDefaults","createDefaultExtractContentAndReasoning","reasoningContentKeys","message","messageRecord","rawReasoning","key","value","messageReasoning","resolveExtractContentAndReasoning","chatCompletion","messageExtraction","resolveChatCompletion","buildChatCompletionParams","resolveImageDetail","unsupportedUserConfig","extractContentAndReasoning","useReasoningAsContentFallback","replayRawAssistantMessage","input","context","params","retryAttempt"],"mappings":"AAQA,MAAMA,qBAAqB,CAACC,SAAoBC;AAEhD,MAAMC,8BAA8B,CAAC,EACnCC,gBAAgB,EAChBC,UAAU,EACgB,GAAM;QAChC,QAAQ;YACN,aAAaA,WAAW,WAAW,IAAID,iBAAiB,WAAW;QACrE;IACF;AAEA,MAAME,iCAAiE;IACrE,aAAa;AACf;AAEA,SAASC,wCACPC,oBAA8B;IAE9B,OAAO,CAACC;QACN,IAAI,CAACA,SACH,OAAO;YACL,SAAS;YACT,mBAAmB;QACrB;QAGF,MAAMC,gBAAgBD;QACtB,MAAME,eAAeH,qBAClB,GAAG,CAAC,CAACI,MAAQF,aAAa,CAACE,IAAI,EAC/B,IAAI,CAAC,CAACC,QAAU,AAAiB,YAAjB,OAAOA;QAC1B,MAAMC,mBACJ,AAAwB,YAAxB,OAAOH,eAA4BA,eAAe;QAEpD,OAAO;YACL,SAAS,AAA2B,YAA3B,OAAOF,QAAQ,OAAO,GAAgBA,QAAQ,OAAO,GAAG;YACjE,mBAAmBK;QACrB;IACF;AACF;AAEA,SAASC,kCACPC,cAAwD;IAExD,MAAMC,oBAAoBD,gBAAgB;IAC1C,IAAIC,mBAAmB,SAAS,UAC9B,OAAOA,kBAAkB,0BAA0B;IAGrD,OAAOV,wCACLU,mBAAmB,wBAAwB;QAAC;KAAoB;AAEpE;AAEO,SAASC,sBACdF,cAAwD;IAExD,MAAMG,4BACJH,gBAAgB,6BAA6Bb;IAC/C,MAAMiB,qBACJJ,gBAAgB,sBAAsBhB;IACxC,MAAMqB,wBAAwBL,gBAAgB,yBAAyB,EAAE;IACzE,MAAMM,6BACJP,kCAAkCC;IACpC,MAAMO,gCACJP,gBAAgB,iCAAiC;IACnD,MAAMQ,4BACJR,gBAAgB,6BAA6B;IAE/C,OAAO;QACLK;QACA,2BAA2B,CAACI;YAC1B,MAAMC,UAAU;gBACd,GAAGD,KAAK;gBACR,YAAYA,MAAM,UAAU,IAAI,CAAC;gBACjC,kBAAkBnB;YACpB;YACA,MAAMqB,SAASR,0BAA0BO;YACzC,MAAME,eAAeH,MAAM,oBAAoB,IAAI;YAInD,IACEG,eAAe,KACfH,MAAM,UAAU,EAAE,gBAAgBvB,UAClCyB,AAA8B,MAA9BA,OAAO,MAAM,CAAC,WAAW,EAEzB,OAAO;gBACL,QAAQ;oBACN,GAAGA,OAAO,MAAM;oBAChB,aAAa;gBACf;YACF;YAEF,OAAOA;QACT;QACA,oBAAoB,CAACF,QACnBL,mBAAmB;gBACjB,GAAGK,KAAK;gBACR,YAAYA,MAAM,UAAU,IAAI,CAAC;gBACjC,kBAAkBnB;YACpB;QACFgB;QACAC;QACAC;IACF;AACF"}
1
+ {"version":3,"file":"ai-model/model-adapter/chat-completion.mjs","sources":["../../../../src/ai-model/model-adapter/chat-completion.ts"],"sourcesContent":["import { getTemperatureWithSemanticRetry } from './temperature-with-semantic-retry';\nimport type {\n ChatCompletionAdapter,\n ChatCompletionCallContext,\n ExtractContentAndReasoning,\n MidsceneChatCompletionDefaults,\n ModelAdapterDefinition,\n} from './types';\n\nconst defaultChatCompletionParams = ({\n midsceneDefaults,\n userConfig,\n}: ChatCompletionCallContext) => ({\n config: {\n temperature: userConfig.temperature ?? midsceneDefaults.temperature,\n },\n});\n\nconst midsceneChatCompletionDefaults: MidsceneChatCompletionDefaults = {\n temperature: 0,\n};\n\nfunction createDefaultExtractContentAndReasoning(\n reasoningContentKeys: string[],\n): ExtractContentAndReasoning {\n return (message) => {\n if (!message) {\n return {\n content: '',\n reasoning_content: '',\n };\n }\n\n const messageRecord = message as Record<string, unknown>;\n const rawReasoning = reasoningContentKeys\n .map((key) => messageRecord[key])\n .find((value) => typeof value === 'string');\n const messageReasoning =\n typeof rawReasoning === 'string' ? rawReasoning : '';\n\n return {\n content: typeof message.content === 'string' ? message.content : '',\n reasoning_content: messageReasoning,\n };\n };\n}\n\nfunction resolveExtractContentAndReasoning(\n chatCompletion: ModelAdapterDefinition['chatCompletion'],\n): ExtractContentAndReasoning {\n const messageExtraction = chatCompletion?.messageExtraction;\n if (messageExtraction?.kind === 'custom') {\n return messageExtraction.extractContentAndReasoning;\n }\n\n return createDefaultExtractContentAndReasoning(\n messageExtraction?.reasoningContentKeys ?? ['reasoning_content'],\n );\n}\n\nexport function resolveChatCompletion(\n chatCompletion: ModelAdapterDefinition['chatCompletion'],\n): ChatCompletionAdapter {\n const buildChatCompletionParams =\n chatCompletion?.buildChatCompletionParams ?? defaultChatCompletionParams;\n const unsupportedUserConfig = chatCompletion?.unsupportedUserConfig ?? [];\n const extractContentAndReasoning =\n resolveExtractContentAndReasoning(chatCompletion);\n const useReasoningAsContentFallback =\n chatCompletion?.useReasoningAsContentFallback ?? false;\n const replayRawAssistantMessage =\n chatCompletion?.replayRawAssistantMessage ?? false;\n\n return {\n unsupportedUserConfig,\n buildChatCompletionParams: (input) => {\n const context = {\n ...input,\n userConfig: input.userConfig ?? {},\n midsceneDefaults: midsceneChatCompletionDefaults,\n };\n const params = buildChatCompletionParams(context);\n return {\n ...params,\n config: {\n ...params.config,\n temperature: getTemperatureWithSemanticRetry({\n temperature: params.config.temperature,\n userTemperature: input.userConfig?.temperature,\n semanticRetryAttempt: input.semanticRetryAttempt,\n }),\n },\n };\n },\n extractContentAndReasoning,\n useReasoningAsContentFallback,\n replayRawAssistantMessage,\n };\n}\n"],"names":["defaultChatCompletionParams","midsceneDefaults","userConfig","midsceneChatCompletionDefaults","createDefaultExtractContentAndReasoning","reasoningContentKeys","message","messageRecord","rawReasoning","key","value","messageReasoning","resolveExtractContentAndReasoning","chatCompletion","messageExtraction","resolveChatCompletion","buildChatCompletionParams","unsupportedUserConfig","extractContentAndReasoning","useReasoningAsContentFallback","replayRawAssistantMessage","input","context","params","getTemperatureWithSemanticRetry"],"mappings":";AASA,MAAMA,8BAA8B,CAAC,EACnCC,gBAAgB,EAChBC,UAAU,EACgB,GAAM;QAChC,QAAQ;YACN,aAAaA,WAAW,WAAW,IAAID,iBAAiB,WAAW;QACrE;IACF;AAEA,MAAME,iCAAiE;IACrE,aAAa;AACf;AAEA,SAASC,wCACPC,oBAA8B;IAE9B,OAAO,CAACC;QACN,IAAI,CAACA,SACH,OAAO;YACL,SAAS;YACT,mBAAmB;QACrB;QAGF,MAAMC,gBAAgBD;QACtB,MAAME,eAAeH,qBAClB,GAAG,CAAC,CAACI,MAAQF,aAAa,CAACE,IAAI,EAC/B,IAAI,CAAC,CAACC,QAAU,AAAiB,YAAjB,OAAOA;QAC1B,MAAMC,mBACJ,AAAwB,YAAxB,OAAOH,eAA4BA,eAAe;QAEpD,OAAO;YACL,SAAS,AAA2B,YAA3B,OAAOF,QAAQ,OAAO,GAAgBA,QAAQ,OAAO,GAAG;YACjE,mBAAmBK;QACrB;IACF;AACF;AAEA,SAASC,kCACPC,cAAwD;IAExD,MAAMC,oBAAoBD,gBAAgB;IAC1C,IAAIC,mBAAmB,SAAS,UAC9B,OAAOA,kBAAkB,0BAA0B;IAGrD,OAAOV,wCACLU,mBAAmB,wBAAwB;QAAC;KAAoB;AAEpE;AAEO,SAASC,sBACdF,cAAwD;IAExD,MAAMG,4BACJH,gBAAgB,6BAA6Bb;IAC/C,MAAMiB,wBAAwBJ,gBAAgB,yBAAyB,EAAE;IACzE,MAAMK,6BACJN,kCAAkCC;IACpC,MAAMM,gCACJN,gBAAgB,iCAAiC;IACnD,MAAMO,4BACJP,gBAAgB,6BAA6B;IAE/C,OAAO;QACLI;QACA,2BAA2B,CAACI;YAC1B,MAAMC,UAAU;gBACd,GAAGD,KAAK;gBACR,YAAYA,MAAM,UAAU,IAAI,CAAC;gBACjC,kBAAkBlB;YACpB;YACA,MAAMoB,SAASP,0BAA0BM;YACzC,OAAO;gBACL,GAAGC,MAAM;gBACT,QAAQ;oBACN,GAAGA,OAAO,MAAM;oBAChB,aAAaC,gCAAgC;wBAC3C,aAAaD,OAAO,MAAM,CAAC,WAAW;wBACtC,iBAAiBF,MAAM,UAAU,EAAE;wBACnC,sBAAsBA,MAAM,oBAAoB;oBAClD;gBACF;YACF;QACF;QACAH;QACAC;QACAC;IACF;AACF"}
@@ -4,6 +4,7 @@ import { buildDefaultCodexAppServerParams } from "./codex-app-server.mjs";
4
4
  import { resolveInsight } from "./insight.mjs";
5
5
  import { resolveLocate } from "./locate.mjs";
6
6
  import { resolveCustomPlanningDefinition, resolvePlanning } from "./planning.mjs";
7
+ import { resolveResponses } from "./responses.mjs";
7
8
  function _define_property(obj, key, value) {
8
9
  if (key in obj) Object.defineProperty(obj, key, {
9
10
  value: value,
@@ -14,6 +15,7 @@ function _define_property(obj, key, value) {
14
15
  else obj[key] = value;
15
16
  return obj;
16
17
  }
18
+ const defaultImageDetail = ({ imageDetail })=>imageDetail ?? 'high';
17
19
  function resolveJsonParser(jsonParser) {
18
20
  if (!jsonParser || 'lenient-json' === jsonParser) return parseModelResponseJson;
19
21
  if ('function' == typeof jsonParser) return jsonParser;
@@ -26,16 +28,24 @@ function resolveImagePreprocess(imagePreprocess) {
26
28
  }
27
29
  class ResolvedModelAdapter {
28
30
  constructor(config, modelFamily){
31
+ _define_property(this, "supportedApiTypes", void 0);
29
32
  _define_property(this, "jsonParser", void 0);
30
33
  _define_property(this, "chatCompletion", void 0);
34
+ _define_property(this, "resolveImageDetail", void 0);
35
+ _define_property(this, "responses", void 0);
31
36
  _define_property(this, "buildCodexAppServerParams", void 0);
32
37
  _define_property(this, "acceptBbox2dAlias", void 0);
33
38
  _define_property(this, "imagePreprocess", void 0);
34
39
  _define_property(this, "insight", void 0);
35
40
  _define_property(this, "planning", void 0);
36
41
  _define_property(this, "locate", void 0);
42
+ this.supportedApiTypes = config.supportedApiTypes ?? [
43
+ 'chat-completion'
44
+ ];
37
45
  this.jsonParser = resolveJsonParser(config.jsonParser);
38
46
  this.chatCompletion = resolveChatCompletion(config.chatCompletion);
47
+ this.resolveImageDetail = config.resolveImageDetail ?? defaultImageDetail;
48
+ this.responses = resolveResponses(config.responses);
39
49
  this.buildCodexAppServerParams = config.buildCodexAppServerParams ?? buildDefaultCodexAppServerParams;
40
50
  this.acceptBbox2dAlias = config.acceptBbox2dAlias ?? false;
41
51
  this.imagePreprocess = resolveImagePreprocess(config.imagePreprocess);
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/model-adapter/resolve.mjs","sources":["../../../../src/ai-model/model-adapter/resolve.ts"],"sourcesContent":["import { parseModelResponseJson } from '../shared/json';\nimport { resolveChatCompletion } from './chat-completion';\nimport { buildDefaultCodexAppServerParams } from './codex-app-server';\nimport { resolveInsight } from './insight';\nimport type { InsightAdapter } from './insight-protocol';\nimport { resolveLocate } from './locate';\nimport { resolveCustomPlanningDefinition, resolvePlanning } from './planning';\nimport type {\n BuildCodexAppServerParams,\n ChatCompletionAdapter,\n ImagePreprocessPolicy,\n JsonParser,\n LocateAdapter,\n ModelAdapter,\n ModelAdapterDefinition,\n PlanningAdapter,\n} from './types';\n\nfunction resolveJsonParser(\n jsonParser: ModelAdapterDefinition['jsonParser'],\n): JsonParser {\n if (!jsonParser || jsonParser === 'lenient-json') {\n return parseModelResponseJson;\n }\n\n if (typeof jsonParser === 'function') {\n return jsonParser;\n }\n\n throw new Error(`Unknown json parser preset: ${jsonParser}`);\n}\n\nfunction resolveImagePreprocess(\n imagePreprocess: ModelAdapterDefinition['imagePreprocess'],\n): ImagePreprocessPolicy {\n return {\n padBlockSize: imagePreprocess?.padBlockSize,\n };\n}\n\nexport class ResolvedModelAdapter implements ModelAdapter {\n readonly jsonParser: JsonParser;\n readonly chatCompletion: ChatCompletionAdapter;\n readonly buildCodexAppServerParams: BuildCodexAppServerParams;\n readonly acceptBbox2dAlias: boolean;\n readonly imagePreprocess: ImagePreprocessPolicy;\n readonly insight: InsightAdapter;\n readonly planning: PlanningAdapter;\n readonly locate: LocateAdapter;\n\n constructor(config: ModelAdapterDefinition, modelFamily: string) {\n this.jsonParser = resolveJsonParser(config.jsonParser);\n this.chatCompletion = resolveChatCompletion(config.chatCompletion);\n this.buildCodexAppServerParams =\n config.buildCodexAppServerParams ?? buildDefaultCodexAppServerParams;\n this.acceptBbox2dAlias = config.acceptBbox2dAlias ?? false;\n this.imagePreprocess = resolveImagePreprocess(config.imagePreprocess);\n this.insight = resolveInsight(config.insight, {\n jsonParser: this.jsonParser,\n });\n const customPlanner =\n config.planning?.kind === 'custom' ? config.planning.planner : undefined;\n const resolvedCustomPlanner = customPlanner\n ? resolveCustomPlanningDefinition(customPlanner)\n : undefined;\n this.locate = resolveLocate(\n config.locate,\n resolvedCustomPlanner,\n {\n jsonParser: this.jsonParser,\n },\n this.acceptBbox2dAlias,\n );\n this.planning = resolvePlanning(\n config.planning,\n resolvedCustomPlanner,\n { jsonParser: this.jsonParser },\n this.locate.kind === 'standard'\n ? this.locate.element.resultCodec\n : undefined,\n );\n }\n}\n"],"names":["resolveJsonParser","jsonParser","parseModelResponseJson","Error","resolveImagePreprocess","imagePreprocess","ResolvedModelAdapter","config","modelFamily","resolveChatCompletion","buildDefaultCodexAppServerParams","resolveInsight","customPlanner","undefined","resolvedCustomPlanner","resolveCustomPlanningDefinition","resolveLocate","resolvePlanning"],"mappings":";;;;;;;;;;;;;;;;AAkBA,SAASA,kBACPC,UAAgD;IAEhD,IAAI,CAACA,cAAcA,AAAe,mBAAfA,YACjB,OAAOC;IAGT,IAAI,AAAsB,cAAtB,OAAOD,YACT,OAAOA;IAGT,MAAM,IAAIE,MAAM,CAAC,4BAA4B,EAAEF,YAAY;AAC7D;AAEA,SAASG,uBACPC,eAA0D;IAE1D,OAAO;QACL,cAAcA,iBAAiB;IACjC;AACF;AAEO,MAAMC;IAUX,YAAYC,MAA8B,EAAEC,WAAmB,CAAE;QATjE,uBAAS,cAAT;QACA,uBAAS,kBAAT;QACA,uBAAS,6BAAT;QACA,uBAAS,qBAAT;QACA,uBAAS,mBAAT;QACA,uBAAS,WAAT;QACA,uBAAS,YAAT;QACA,uBAAS,UAAT;QAGE,IAAI,CAAC,UAAU,GAAGR,kBAAkBO,OAAO,UAAU;QACrD,IAAI,CAAC,cAAc,GAAGE,sBAAsBF,OAAO,cAAc;QACjE,IAAI,CAAC,yBAAyB,GAC5BA,OAAO,yBAAyB,IAAIG;QACtC,IAAI,CAAC,iBAAiB,GAAGH,OAAO,iBAAiB,IAAI;QACrD,IAAI,CAAC,eAAe,GAAGH,uBAAuBG,OAAO,eAAe;QACpE,IAAI,CAAC,OAAO,GAAGI,eAAeJ,OAAO,OAAO,EAAE;YAC5C,YAAY,IAAI,CAAC,UAAU;QAC7B;QACA,MAAMK,gBACJL,OAAO,QAAQ,EAAE,SAAS,WAAWA,OAAO,QAAQ,CAAC,OAAO,GAAGM;QACjE,MAAMC,wBAAwBF,gBAC1BG,gCAAgCH,iBAChCC;QACJ,IAAI,CAAC,MAAM,GAAGG,cACZT,OAAO,MAAM,EACbO,uBACA;YACE,YAAY,IAAI,CAAC,UAAU;QAC7B,GACA,IAAI,CAAC,iBAAiB;QAExB,IAAI,CAAC,QAAQ,GAAGG,gBACdV,OAAO,QAAQ,EACfO,uBACA;YAAE,YAAY,IAAI,CAAC,UAAU;QAAC,GAC9B,AAAqB,eAArB,IAAI,CAAC,MAAM,CAAC,IAAI,GACZ,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,GAC/BD;IAER;AACF"}
1
+ {"version":3,"file":"ai-model/model-adapter/resolve.mjs","sources":["../../../../src/ai-model/model-adapter/resolve.ts"],"sourcesContent":["import { parseModelResponseJson } from '../shared/json';\nimport { resolveChatCompletion } from './chat-completion';\nimport { buildDefaultCodexAppServerParams } from './codex-app-server';\nimport { resolveInsight } from './insight';\nimport type { InsightAdapter } from './insight-protocol';\nimport { resolveLocate } from './locate';\nimport { resolveCustomPlanningDefinition, resolvePlanning } from './planning';\nimport { resolveResponses } from './responses';\nimport type {\n BuildCodexAppServerParams,\n ChatCompletionAdapter,\n ImagePreprocessPolicy,\n JsonParser,\n LocateAdapter,\n ModelAdapter,\n ModelAdapterDefinition,\n PlanningAdapter,\n ResolveImageDetail,\n ResponsesAdapter,\n} from './types';\n\nconst defaultImageDetail: ResolveImageDetail = ({ imageDetail }) =>\n imageDetail ?? 'high';\n\nfunction resolveJsonParser(\n jsonParser: ModelAdapterDefinition['jsonParser'],\n): JsonParser {\n if (!jsonParser || jsonParser === 'lenient-json') {\n return parseModelResponseJson;\n }\n\n if (typeof jsonParser === 'function') {\n return jsonParser;\n }\n\n throw new Error(`Unknown json parser preset: ${jsonParser}`);\n}\n\nfunction resolveImagePreprocess(\n imagePreprocess: ModelAdapterDefinition['imagePreprocess'],\n): ImagePreprocessPolicy {\n return {\n padBlockSize: imagePreprocess?.padBlockSize,\n };\n}\n\nexport class ResolvedModelAdapter implements ModelAdapter {\n readonly supportedApiTypes: ModelAdapter['supportedApiTypes'];\n readonly jsonParser: JsonParser;\n readonly chatCompletion: ChatCompletionAdapter;\n readonly resolveImageDetail: ResolveImageDetail;\n readonly responses: ResponsesAdapter;\n readonly buildCodexAppServerParams: BuildCodexAppServerParams;\n readonly acceptBbox2dAlias: boolean;\n readonly imagePreprocess: ImagePreprocessPolicy;\n readonly insight: InsightAdapter;\n readonly planning: PlanningAdapter;\n readonly locate: LocateAdapter;\n\n constructor(config: ModelAdapterDefinition, modelFamily: string) {\n this.supportedApiTypes = config.supportedApiTypes ?? ['chat-completion'];\n this.jsonParser = resolveJsonParser(config.jsonParser);\n this.chatCompletion = resolveChatCompletion(config.chatCompletion);\n this.resolveImageDetail = config.resolveImageDetail ?? defaultImageDetail;\n this.responses = resolveResponses(config.responses);\n this.buildCodexAppServerParams =\n config.buildCodexAppServerParams ?? buildDefaultCodexAppServerParams;\n this.acceptBbox2dAlias = config.acceptBbox2dAlias ?? false;\n this.imagePreprocess = resolveImagePreprocess(config.imagePreprocess);\n this.insight = resolveInsight(config.insight, {\n jsonParser: this.jsonParser,\n });\n const customPlanner =\n config.planning?.kind === 'custom' ? config.planning.planner : undefined;\n const resolvedCustomPlanner = customPlanner\n ? resolveCustomPlanningDefinition(customPlanner)\n : undefined;\n this.locate = resolveLocate(\n config.locate,\n resolvedCustomPlanner,\n {\n jsonParser: this.jsonParser,\n },\n this.acceptBbox2dAlias,\n );\n this.planning = resolvePlanning(\n config.planning,\n resolvedCustomPlanner,\n { jsonParser: this.jsonParser },\n this.locate.kind === 'standard'\n ? this.locate.element.resultCodec\n : undefined,\n );\n }\n}\n"],"names":["defaultImageDetail","imageDetail","resolveJsonParser","jsonParser","parseModelResponseJson","Error","resolveImagePreprocess","imagePreprocess","ResolvedModelAdapter","config","modelFamily","resolveChatCompletion","resolveResponses","buildDefaultCodexAppServerParams","resolveInsight","customPlanner","undefined","resolvedCustomPlanner","resolveCustomPlanningDefinition","resolveLocate","resolvePlanning"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,MAAMA,qBAAyC,CAAC,EAAEC,WAAW,EAAE,GAC7DA,eAAe;AAEjB,SAASC,kBACPC,UAAgD;IAEhD,IAAI,CAACA,cAAcA,AAAe,mBAAfA,YACjB,OAAOC;IAGT,IAAI,AAAsB,cAAtB,OAAOD,YACT,OAAOA;IAGT,MAAM,IAAIE,MAAM,CAAC,4BAA4B,EAAEF,YAAY;AAC7D;AAEA,SAASG,uBACPC,eAA0D;IAE1D,OAAO;QACL,cAAcA,iBAAiB;IACjC;AACF;AAEO,MAAMC;IAaX,YAAYC,MAA8B,EAAEC,WAAmB,CAAE;QAZjE,uBAAS,qBAAT;QACA,uBAAS,cAAT;QACA,uBAAS,kBAAT;QACA,uBAAS,sBAAT;QACA,uBAAS,aAAT;QACA,uBAAS,6BAAT;QACA,uBAAS,qBAAT;QACA,uBAAS,mBAAT;QACA,uBAAS,WAAT;QACA,uBAAS,YAAT;QACA,uBAAS,UAAT;QAGE,IAAI,CAAC,iBAAiB,GAAGD,OAAO,iBAAiB,IAAI;YAAC;SAAkB;QACxE,IAAI,CAAC,UAAU,GAAGP,kBAAkBO,OAAO,UAAU;QACrD,IAAI,CAAC,cAAc,GAAGE,sBAAsBF,OAAO,cAAc;QACjE,IAAI,CAAC,kBAAkB,GAAGA,OAAO,kBAAkB,IAAIT;QACvD,IAAI,CAAC,SAAS,GAAGY,iBAAiBH,OAAO,SAAS;QAClD,IAAI,CAAC,yBAAyB,GAC5BA,OAAO,yBAAyB,IAAII;QACtC,IAAI,CAAC,iBAAiB,GAAGJ,OAAO,iBAAiB,IAAI;QACrD,IAAI,CAAC,eAAe,GAAGH,uBAAuBG,OAAO,eAAe;QACpE,IAAI,CAAC,OAAO,GAAGK,eAAeL,OAAO,OAAO,EAAE;YAC5C,YAAY,IAAI,CAAC,UAAU;QAC7B;QACA,MAAMM,gBACJN,OAAO,QAAQ,EAAE,SAAS,WAAWA,OAAO,QAAQ,CAAC,OAAO,GAAGO;QACjE,MAAMC,wBAAwBF,gBAC1BG,gCAAgCH,iBAChCC;QACJ,IAAI,CAAC,MAAM,GAAGG,cACZV,OAAO,MAAM,EACbQ,uBACA;YACE,YAAY,IAAI,CAAC,UAAU;QAC7B,GACA,IAAI,CAAC,iBAAiB;QAExB,IAAI,CAAC,QAAQ,GAAGG,gBACdX,OAAO,QAAQ,EACfQ,uBACA;YAAE,YAAY,IAAI,CAAC,UAAU;QAAC,GAC9B,AAAqB,eAArB,IAAI,CAAC,MAAM,CAAC,IAAI,GACZ,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,GAC/BD;IAER;AACF"}
@@ -0,0 +1,38 @@
1
+ import { getTemperatureWithSemanticRetry } from "./temperature-with-semantic-retry.mjs";
2
+ const midsceneResponsesDefaults = {
3
+ temperature: 0
4
+ };
5
+ const buildDefaultResponsesParams = ({ midsceneDefaults, userConfig })=>({
6
+ config: {
7
+ temperature: userConfig.temperature ?? midsceneDefaults.temperature
8
+ }
9
+ });
10
+ function resolveResponses(responses) {
11
+ const buildResponsesParams = responses?.buildResponsesParams ?? buildDefaultResponsesParams;
12
+ return {
13
+ replayRawAssistantOutput: responses?.replayRawAssistantOutput ?? false,
14
+ unsupportedUserConfig: responses?.unsupportedUserConfig ?? [],
15
+ buildResponsesParams: (input)=>{
16
+ const context = {
17
+ ...input,
18
+ userConfig: input.userConfig ?? {},
19
+ midsceneDefaults: midsceneResponsesDefaults
20
+ };
21
+ const params = buildResponsesParams(context);
22
+ return {
23
+ ...params,
24
+ config: {
25
+ ...params.config,
26
+ temperature: getTemperatureWithSemanticRetry({
27
+ temperature: params.config.temperature,
28
+ userTemperature: input.userConfig?.temperature,
29
+ semanticRetryAttempt: input.semanticRetryAttempt
30
+ })
31
+ }
32
+ };
33
+ }
34
+ };
35
+ }
36
+ export { buildDefaultResponsesParams, resolveResponses };
37
+
38
+ //# sourceMappingURL=responses.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-model/model-adapter/responses.mjs","sources":["../../../../src/ai-model/model-adapter/responses.ts"],"sourcesContent":["import { getTemperatureWithSemanticRetry } from './temperature-with-semantic-retry';\nimport type {\n BuildResponsesParams,\n MidsceneResponsesDefaults,\n ModelAdapterDefinition,\n ResponsesAdapter,\n} from './types';\n\nconst midsceneResponsesDefaults: MidsceneResponsesDefaults = {\n temperature: 0,\n};\n\nexport const buildDefaultResponsesParams: BuildResponsesParams = ({\n midsceneDefaults,\n userConfig,\n}) => ({\n config: {\n temperature: userConfig.temperature ?? midsceneDefaults.temperature,\n },\n});\n\nexport function resolveResponses(\n responses: ModelAdapterDefinition['responses'],\n): ResponsesAdapter {\n const buildResponsesParams =\n responses?.buildResponsesParams ?? buildDefaultResponsesParams;\n return {\n replayRawAssistantOutput: responses?.replayRawAssistantOutput ?? false,\n unsupportedUserConfig: responses?.unsupportedUserConfig ?? [],\n buildResponsesParams: (input) => {\n const context = {\n ...input,\n userConfig: input.userConfig ?? {},\n midsceneDefaults: midsceneResponsesDefaults,\n };\n const params = buildResponsesParams(context);\n return {\n ...params,\n config: {\n ...params.config,\n temperature: getTemperatureWithSemanticRetry({\n temperature: params.config.temperature,\n userTemperature: input.userConfig?.temperature,\n semanticRetryAttempt: input.semanticRetryAttempt,\n }),\n },\n };\n },\n };\n}\n"],"names":["midsceneResponsesDefaults","buildDefaultResponsesParams","midsceneDefaults","userConfig","resolveResponses","responses","buildResponsesParams","input","context","params","getTemperatureWithSemanticRetry"],"mappings":";AAQA,MAAMA,4BAAuD;IAC3D,aAAa;AACf;AAEO,MAAMC,8BAAoD,CAAC,EAChEC,gBAAgB,EAChBC,UAAU,EACX,GAAM;QACL,QAAQ;YACN,aAAaA,WAAW,WAAW,IAAID,iBAAiB,WAAW;QACrE;IACF;AAEO,SAASE,iBACdC,SAA8C;IAE9C,MAAMC,uBACJD,WAAW,wBAAwBJ;IACrC,OAAO;QACL,0BAA0BI,WAAW,4BAA4B;QACjE,uBAAuBA,WAAW,yBAAyB,EAAE;QAC7D,sBAAsB,CAACE;YACrB,MAAMC,UAAU;gBACd,GAAGD,KAAK;gBACR,YAAYA,MAAM,UAAU,IAAI,CAAC;gBACjC,kBAAkBP;YACpB;YACA,MAAMS,SAASH,qBAAqBE;YACpC,OAAO;gBACL,GAAGC,MAAM;gBACT,QAAQ;oBACN,GAAGA,OAAO,MAAM;oBAChB,aAAaC,gCAAgC;wBAC3C,aAAaD,OAAO,MAAM,CAAC,WAAW;wBACtC,iBAAiBF,MAAM,UAAU,EAAE;wBACnC,sBAAsBA,MAAM,oBAAoB;oBAClD;gBACF;YACF;QACF;IACF;AACF"}
@@ -0,0 +1,7 @@
1
+ function getTemperatureWithSemanticRetry({ temperature, userTemperature, semanticRetryAttempt = 0 }) {
2
+ if (semanticRetryAttempt > 0 && void 0 === userTemperature && 0 === temperature) return 0.2;
3
+ return temperature;
4
+ }
5
+ export { getTemperatureWithSemanticRetry };
6
+
7
+ //# sourceMappingURL=temperature-with-semantic-retry.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-model/model-adapter/temperature-with-semantic-retry.mjs","sources":["../../../../src/ai-model/model-adapter/temperature-with-semantic-retry.ts"],"sourcesContent":["export function getTemperatureWithSemanticRetry<T>({\n temperature,\n userTemperature,\n semanticRetryAttempt = 0,\n}: {\n temperature: T;\n userTemperature?: number;\n semanticRetryAttempt?: number;\n}): T | number {\n // Only perturb the default deterministic request after a semantic parse\n // failure: preserve an explicit user temperature, and avoid adding a\n // temperature to adapters whose normal parameters do not include one.\n if (\n semanticRetryAttempt > 0 &&\n userTemperature === undefined &&\n temperature === 0\n ) {\n return 0.2;\n }\n return temperature;\n}\n"],"names":["getTemperatureWithSemanticRetry","temperature","userTemperature","semanticRetryAttempt","undefined"],"mappings":"AAAO,SAASA,gCAAmC,EACjDC,WAAW,EACXC,eAAe,EACfC,uBAAuB,CAAC,EAKzB;IAIC,IACEA,uBAAuB,KACvBD,AAAoBE,WAApBF,mBACAD,AAAgB,MAAhBA,aAEA,OAAO;IAET,OAAOA;AACT"}
@@ -1,5 +1,5 @@
1
1
  import { isLocateIntent } from "./utils/intent.mjs";
2
- const originalImageDetailForDefaultIntent = (input)=>isLocateIntent(input.intent) || input.requiresOriginalImageDetail ? 'original' : void 0;
2
+ const originalImageDetailForDefaultIntent = (input)=>isLocateIntent(input.intent) || input.requiresOriginalImageDetail ? 'original' : input.imageDetail ?? 'high';
3
3
  const resolveGpt5ReasoningEffort = ({ reasoningEnabled, reasoningEffort })=>{
4
4
  if ('default' === reasoningEnabled) return;
5
5
  return true === reasoningEnabled ? reasoningEffort ?? 'medium' : 'none';
@@ -11,15 +11,56 @@ const resolveGpt6ReasoningEffort = ({ reasoningEnabled, reasoningEffort })=>{
11
11
  const buildGpt5CodexAppServerParams = (input)=>({
12
12
  config: {
13
13
  effort: resolveGpt5ReasoningEffort(input.userConfig ?? {})
14
- },
15
- imageDetail: originalImageDetailForDefaultIntent(input)
14
+ }
16
15
  });
17
16
  const buildGpt6CodexAppServerParams = (input)=>({
18
17
  config: {
19
18
  effort: resolveGpt6ReasoningEffort(input.userConfig ?? {})
20
- },
21
- imageDetail: originalImageDetailForDefaultIntent(input)
19
+ }
22
20
  });
21
+ const buildGpt5ResponsesParams = (input)=>{
22
+ const { midsceneDefaults, userConfig, expectedJsonObjectResponse } = input;
23
+ const commonOverrideConfig = {};
24
+ if (void 0 !== userConfig.temperature) commonOverrideConfig.temperature = userConfig.temperature;
25
+ if ('none' !== userConfig.responseFormat && expectedJsonObjectResponse) commonOverrideConfig.text = {
26
+ format: {
27
+ type: 'json_object'
28
+ }
29
+ };
30
+ const effectiveReasoningEffort = resolveGpt5ReasoningEffort(userConfig);
31
+ return {
32
+ config: {
33
+ ...midsceneDefaults,
34
+ ...commonOverrideConfig,
35
+ reasoning: {
36
+ effort: effectiveReasoningEffort,
37
+ context: 'current_turn'
38
+ }
39
+ }
40
+ };
41
+ };
42
+ const buildGpt6ResponsesParams = (input)=>{
43
+ const { midsceneDefaults, userConfig, expectedJsonObjectResponse } = input;
44
+ const { responseFormat } = userConfig;
45
+ const commonOverrideConfig = {};
46
+ commonOverrideConfig.temperature = void 0;
47
+ if ('none' !== responseFormat && expectedJsonObjectResponse) commonOverrideConfig.text = {
48
+ format: {
49
+ type: 'json_object'
50
+ }
51
+ };
52
+ const effectiveReasoningEffort = resolveGpt6ReasoningEffort(userConfig);
53
+ return {
54
+ config: {
55
+ ...midsceneDefaults,
56
+ ...commonOverrideConfig,
57
+ reasoning: {
58
+ effort: effectiveReasoningEffort,
59
+ context: 'current_turn'
60
+ }
61
+ }
62
+ };
63
+ };
23
64
  const buildGpt5ChatCompletionParams = (input)=>{
24
65
  const { midsceneDefaults, userConfig } = input;
25
66
  const commonOverrideConfig = {};
@@ -55,13 +96,24 @@ const buildGpt6ChatCompletionParams = (input)=>{
55
96
  };
56
97
  const gptAdapters = {
57
98
  'gpt-5': {
99
+ supportedApiTypes: [
100
+ 'chat-completion',
101
+ 'responses'
102
+ ],
103
+ resolveImageDetail: originalImageDetailForDefaultIntent,
104
+ responses: {
105
+ replayRawAssistantOutput: false,
106
+ unsupportedUserConfig: [
107
+ 'reasoningBudget'
108
+ ],
109
+ buildResponsesParams: buildGpt5ResponsesParams
110
+ },
58
111
  buildCodexAppServerParams: buildGpt5CodexAppServerParams,
59
112
  chatCompletion: {
60
113
  unsupportedUserConfig: [
61
114
  'reasoningBudget'
62
115
  ],
63
- buildChatCompletionParams: buildGpt5ChatCompletionParams,
64
- resolveImageDetail: originalImageDetailForDefaultIntent
116
+ buildChatCompletionParams: buildGpt5ChatCompletionParams
65
117
  },
66
118
  locate: {
67
119
  element: {
@@ -75,14 +127,26 @@ const gptAdapters = {
75
127
  }
76
128
  },
77
129
  'gpt-6': {
130
+ supportedApiTypes: [
131
+ 'chat-completion',
132
+ 'responses'
133
+ ],
134
+ resolveImageDetail: originalImageDetailForDefaultIntent,
135
+ responses: {
136
+ replayRawAssistantOutput: false,
137
+ unsupportedUserConfig: [
138
+ 'temperature',
139
+ 'reasoningBudget'
140
+ ],
141
+ buildResponsesParams: buildGpt6ResponsesParams
142
+ },
78
143
  buildCodexAppServerParams: buildGpt6CodexAppServerParams,
79
144
  chatCompletion: {
80
145
  unsupportedUserConfig: [
81
146
  'temperature',
82
147
  'reasoningBudget'
83
148
  ],
84
- buildChatCompletionParams: buildGpt6ChatCompletionParams,
85
- resolveImageDetail: originalImageDetailForDefaultIntent
149
+ buildChatCompletionParams: buildGpt6ChatCompletionParams
86
150
  },
87
151
  locate: {
88
152
  element: {
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/models/gpt.mjs","sources":["../../../../src/ai-model/models/gpt.ts"],"sourcesContent":["import type { TModelFamily } from '@midscene/shared/env';\nimport type {\n ChatCompletionCallContext,\n ChatCompletionParamsResult,\n CodexAppServerCallInput,\n CodexAppServerParamsResult,\n ImageDetail,\n ModelAdapterDefinition,\n ReasoningInput,\n} from '../model-adapter/types';\nimport { isLocateIntent } from './utils/intent';\n\nconst originalImageDetailForDefaultIntent = (\n input: Pick<\n CodexAppServerCallInput,\n 'intent' | 'requiresOriginalImageDetail'\n >,\n): ImageDetail | undefined =>\n isLocateIntent(input.intent) || input.requiresOriginalImageDetail\n ? 'original'\n : undefined;\n\nconst resolveGpt5ReasoningEffort = ({\n reasoningEnabled,\n reasoningEffort,\n}: ReasoningInput): string | undefined => {\n if (reasoningEnabled === 'default') return undefined;\n return reasoningEnabled === true ? (reasoningEffort ?? 'medium') : 'none';\n};\n\n// Astra cannot disable reasoning; use its lowest effort when disabled.\nconst resolveGpt6ReasoningEffort = ({\n reasoningEnabled,\n reasoningEffort,\n}: ReasoningInput): string | undefined => {\n if (reasoningEnabled === 'default') return undefined;\n return reasoningEnabled === true ? (reasoningEffort ?? 'medium') : 'low';\n};\n\nconst buildGpt5CodexAppServerParams = (\n input: CodexAppServerCallInput,\n): CodexAppServerParamsResult => ({\n config: { effort: resolveGpt5ReasoningEffort(input.userConfig ?? {}) },\n imageDetail: originalImageDetailForDefaultIntent(input),\n});\n\nconst buildGpt6CodexAppServerParams = (\n input: CodexAppServerCallInput,\n): CodexAppServerParamsResult => ({\n config: { effort: resolveGpt6ReasoningEffort(input.userConfig ?? {}) },\n imageDetail: originalImageDetailForDefaultIntent(input),\n});\n\nconst buildGpt5ChatCompletionParams = (\n input: ChatCompletionCallContext,\n): ChatCompletionParamsResult => {\n const { midsceneDefaults, userConfig } = input;\n const commonOverrideConfig: Record<string, unknown> = {};\n\n if (userConfig.temperature !== undefined) {\n commonOverrideConfig.temperature = userConfig.temperature;\n }\n\n // OpenAI Chat Completions JSON mode:\n // https://platform.openai.com/docs/guides/structured-outputs?api-mode=chat#json-mode\n if (\n input.userConfig.responseFormat !== 'none' &&\n input.expectedJsonObjectResponse\n ) {\n commonOverrideConfig.response_format = { type: 'json_object' };\n }\n\n const effectiveReasoningEffort = resolveGpt5ReasoningEffort(userConfig);\n\n return {\n config: {\n ...midsceneDefaults,\n ...commonOverrideConfig,\n reasoning_effort: effectiveReasoningEffort,\n },\n };\n};\n\nconst buildGpt6ChatCompletionParams = (\n input: ChatCompletionCallContext,\n): ChatCompletionParamsResult => {\n const { midsceneDefaults, userConfig, expectedJsonObjectResponse } = input;\n const { responseFormat } = userConfig;\n const commonOverrideConfig: Record<string, unknown> = {};\n // GPT-6 does not support temperature; omit it from the serialized request.\n commonOverrideConfig.temperature = undefined;\n if (responseFormat !== 'none' && expectedJsonObjectResponse) {\n commonOverrideConfig.response_format = { type: 'json_object' };\n }\n\n const effectiveReasoningEffort = resolveGpt6ReasoningEffort(userConfig);\n\n return {\n config: {\n ...midsceneDefaults,\n ...commonOverrideConfig,\n reasoning_effort: effectiveReasoningEffort,\n },\n };\n};\n\nexport const gptAdapters = {\n 'gpt-5': {\n buildCodexAppServerParams: buildGpt5CodexAppServerParams,\n chatCompletion: {\n unsupportedUserConfig: ['reasoningBudget'],\n buildChatCompletionParams: buildGpt5ChatCompletionParams,\n resolveImageDetail: originalImageDetailForDefaultIntent,\n },\n locate: {\n element: {\n resultFormat: {\n coordinates: { shape: 'bbox', order: 'xy' },\n },\n },\n },\n },\n 'gpt-6': {\n buildCodexAppServerParams: buildGpt6CodexAppServerParams,\n chatCompletion: {\n unsupportedUserConfig: ['temperature', 'reasoningBudget'],\n buildChatCompletionParams: buildGpt6ChatCompletionParams,\n resolveImageDetail: originalImageDetailForDefaultIntent,\n },\n locate: {\n element: {\n resultFormat: {\n coordinates: { shape: 'bbox', order: 'xy' },\n },\n },\n },\n },\n} satisfies Pick<\n Record<TModelFamily, ModelAdapterDefinition>,\n 'gpt-5' | 'gpt-6'\n>;\n"],"names":["originalImageDetailForDefaultIntent","input","isLocateIntent","undefined","resolveGpt5ReasoningEffort","reasoningEnabled","reasoningEffort","resolveGpt6ReasoningEffort","buildGpt5CodexAppServerParams","buildGpt6CodexAppServerParams","buildGpt5ChatCompletionParams","midsceneDefaults","userConfig","commonOverrideConfig","effectiveReasoningEffort","buildGpt6ChatCompletionParams","expectedJsonObjectResponse","responseFormat","gptAdapters"],"mappings":";AAYA,MAAMA,sCAAsC,CAC1CC,QAKAC,eAAeD,MAAM,MAAM,KAAKA,MAAM,2BAA2B,GAC7D,aACAE;AAEN,MAAMC,6BAA6B,CAAC,EAClCC,gBAAgB,EAChBC,eAAe,EACA;IACf,IAAID,AAAqB,cAArBA,kBAAgC;IACpC,OAAOA,AAAqB,SAArBA,mBAA6BC,mBAAmB,WAAY;AACrE;AAGA,MAAMC,6BAA6B,CAAC,EAClCF,gBAAgB,EAChBC,eAAe,EACA;IACf,IAAID,AAAqB,cAArBA,kBAAgC;IACpC,OAAOA,AAAqB,SAArBA,mBAA6BC,mBAAmB,WAAY;AACrE;AAEA,MAAME,gCAAgC,CACpCP,QACgC;QAChC,QAAQ;YAAE,QAAQG,2BAA2BH,MAAM,UAAU,IAAI,CAAC;QAAG;QACrE,aAAaD,oCAAoCC;IACnD;AAEA,MAAMQ,gCAAgC,CACpCR,QACgC;QAChC,QAAQ;YAAE,QAAQM,2BAA2BN,MAAM,UAAU,IAAI,CAAC;QAAG;QACrE,aAAaD,oCAAoCC;IACnD;AAEA,MAAMS,gCAAgC,CACpCT;IAEA,MAAM,EAAEU,gBAAgB,EAAEC,UAAU,EAAE,GAAGX;IACzC,MAAMY,uBAAgD,CAAC;IAEvD,IAAID,AAA2BT,WAA3BS,WAAW,WAAW,EACxBC,qBAAqB,WAAW,GAAGD,WAAW,WAAW;IAK3D,IACEX,AAAoC,WAApCA,MAAM,UAAU,CAAC,cAAc,IAC/BA,MAAM,0BAA0B,EAEhCY,qBAAqB,eAAe,GAAG;QAAE,MAAM;IAAc;IAG/D,MAAMC,2BAA2BV,2BAA2BQ;IAE5D,OAAO;QACL,QAAQ;YACN,GAAGD,gBAAgB;YACnB,GAAGE,oBAAoB;YACvB,kBAAkBC;QACpB;IACF;AACF;AAEA,MAAMC,gCAAgC,CACpCd;IAEA,MAAM,EAAEU,gBAAgB,EAAEC,UAAU,EAAEI,0BAA0B,EAAE,GAAGf;IACrE,MAAM,EAAEgB,cAAc,EAAE,GAAGL;IAC3B,MAAMC,uBAAgD,CAAC;IAEvDA,qBAAqB,WAAW,GAAGV;IACnC,IAAIc,AAAmB,WAAnBA,kBAA6BD,4BAC/BH,qBAAqB,eAAe,GAAG;QAAE,MAAM;IAAc;IAG/D,MAAMC,2BAA2BP,2BAA2BK;IAE5D,OAAO;QACL,QAAQ;YACN,GAAGD,gBAAgB;YACnB,GAAGE,oBAAoB;YACvB,kBAAkBC;QACpB;IACF;AACF;AAEO,MAAMI,cAAc;IACzB,SAAS;QACP,2BAA2BV;QAC3B,gBAAgB;YACd,uBAAuB;gBAAC;aAAkB;YAC1C,2BAA2BE;YAC3B,oBAAoBV;QACtB;QACA,QAAQ;YACN,SAAS;gBACP,cAAc;oBACZ,aAAa;wBAAE,OAAO;wBAAQ,OAAO;oBAAK;gBAC5C;YACF;QACF;IACF;IACA,SAAS;QACP,2BAA2BS;QAC3B,gBAAgB;YACd,uBAAuB;gBAAC;gBAAe;aAAkB;YACzD,2BAA2BM;YAC3B,oBAAoBf;QACtB;QACA,QAAQ;YACN,SAAS;gBACP,cAAc;oBACZ,aAAa;wBAAE,OAAO;wBAAQ,OAAO;oBAAK;gBAC5C;YACF;QACF;IACF;AACF"}
1
+ {"version":3,"file":"ai-model/models/gpt.mjs","sources":["../../../../src/ai-model/models/gpt.ts"],"sourcesContent":["import type { TModelFamily } from '@midscene/shared/env';\nimport type {\n BuildResponsesParams,\n ChatCompletionCallContext,\n ChatCompletionParamsResult,\n CodexAppServerCallInput,\n CodexAppServerParamsResult,\n ModelAdapterDefinition,\n ReasoningInput,\n ResolveImageDetail,\n} from '../model-adapter/types';\nimport { isLocateIntent } from './utils/intent';\n\nconst originalImageDetailForDefaultIntent: ResolveImageDetail = (input) =>\n isLocateIntent(input.intent) || input.requiresOriginalImageDetail\n ? 'original'\n : (input.imageDetail ?? 'high');\n\nconst resolveGpt5ReasoningEffort = ({\n reasoningEnabled,\n reasoningEffort,\n}: ReasoningInput): string | undefined => {\n if (reasoningEnabled === 'default') return undefined;\n return reasoningEnabled === true ? (reasoningEffort ?? 'medium') : 'none';\n};\n\n// Astra cannot disable reasoning; use its lowest effort when disabled.\nconst resolveGpt6ReasoningEffort = ({\n reasoningEnabled,\n reasoningEffort,\n}: ReasoningInput): string | undefined => {\n if (reasoningEnabled === 'default') return undefined;\n return reasoningEnabled === true ? (reasoningEffort ?? 'medium') : 'low';\n};\n\nconst buildGpt5CodexAppServerParams = (\n input: CodexAppServerCallInput,\n): CodexAppServerParamsResult => ({\n config: { effort: resolveGpt5ReasoningEffort(input.userConfig ?? {}) },\n});\n\nconst buildGpt6CodexAppServerParams = (\n input: CodexAppServerCallInput,\n): CodexAppServerParamsResult => ({\n config: { effort: resolveGpt6ReasoningEffort(input.userConfig ?? {}) },\n});\n\nconst buildGpt5ResponsesParams: BuildResponsesParams = (input) => {\n const { midsceneDefaults, userConfig, expectedJsonObjectResponse } = input;\n const commonOverrideConfig: Record<string, unknown> = {};\n\n if (userConfig.temperature !== undefined) {\n commonOverrideConfig.temperature = userConfig.temperature;\n }\n\n if (userConfig.responseFormat !== 'none' && expectedJsonObjectResponse) {\n commonOverrideConfig.text = { format: { type: 'json_object' } };\n }\n\n const effectiveReasoningEffort = resolveGpt5ReasoningEffort(userConfig);\n\n return {\n config: {\n ...midsceneDefaults,\n ...commonOverrideConfig,\n // Use current-turn reasoning only. Switching to all_turns requires\n // responses.replayRawAssistantOutput to preserve reasoning history.\n reasoning: { effort: effectiveReasoningEffort, context: 'current_turn' },\n },\n };\n};\n\nconst buildGpt6ResponsesParams: BuildResponsesParams = (input) => {\n const { midsceneDefaults, userConfig, expectedJsonObjectResponse } = input;\n const { responseFormat } = userConfig;\n const commonOverrideConfig: Record<string, unknown> = {};\n // GPT-6 does not support temperature; omit it from the serialized request.\n commonOverrideConfig.temperature = undefined;\n if (responseFormat !== 'none' && expectedJsonObjectResponse) {\n commonOverrideConfig.text = { format: { type: 'json_object' } };\n }\n\n const effectiveReasoningEffort = resolveGpt6ReasoningEffort(userConfig);\n\n return {\n config: {\n ...midsceneDefaults,\n ...commonOverrideConfig,\n // Use current-turn reasoning only. Switching to all_turns requires\n // responses.replayRawAssistantOutput to preserve reasoning history.\n reasoning: { effort: effectiveReasoningEffort, context: 'current_turn' },\n },\n };\n};\n\nconst buildGpt5ChatCompletionParams = (\n input: ChatCompletionCallContext,\n): ChatCompletionParamsResult => {\n const { midsceneDefaults, userConfig } = input;\n const commonOverrideConfig: Record<string, unknown> = {};\n\n if (userConfig.temperature !== undefined) {\n commonOverrideConfig.temperature = userConfig.temperature;\n }\n\n // OpenAI Chat Completions JSON mode:\n // https://platform.openai.com/docs/guides/structured-outputs?api-mode=chat#json-mode\n if (\n input.userConfig.responseFormat !== 'none' &&\n input.expectedJsonObjectResponse\n ) {\n commonOverrideConfig.response_format = { type: 'json_object' };\n }\n\n const effectiveReasoningEffort = resolveGpt5ReasoningEffort(userConfig);\n\n return {\n config: {\n ...midsceneDefaults,\n ...commonOverrideConfig,\n reasoning_effort: effectiveReasoningEffort,\n },\n };\n};\n\nconst buildGpt6ChatCompletionParams = (\n input: ChatCompletionCallContext,\n): ChatCompletionParamsResult => {\n const { midsceneDefaults, userConfig, expectedJsonObjectResponse } = input;\n const { responseFormat } = userConfig;\n const commonOverrideConfig: Record<string, unknown> = {};\n // GPT-6 does not support temperature; omit it from the serialized request.\n commonOverrideConfig.temperature = undefined;\n if (responseFormat !== 'none' && expectedJsonObjectResponse) {\n commonOverrideConfig.response_format = { type: 'json_object' };\n }\n\n const effectiveReasoningEffort = resolveGpt6ReasoningEffort(userConfig);\n\n return {\n config: {\n ...midsceneDefaults,\n ...commonOverrideConfig,\n reasoning_effort: effectiveReasoningEffort,\n },\n };\n};\n\nexport const gptAdapters = {\n 'gpt-5': {\n supportedApiTypes: ['chat-completion', 'responses'],\n resolveImageDetail: originalImageDetailForDefaultIntent,\n responses: {\n replayRawAssistantOutput: false,\n unsupportedUserConfig: ['reasoningBudget'],\n buildResponsesParams: buildGpt5ResponsesParams,\n },\n buildCodexAppServerParams: buildGpt5CodexAppServerParams,\n chatCompletion: {\n unsupportedUserConfig: ['reasoningBudget'],\n buildChatCompletionParams: buildGpt5ChatCompletionParams,\n },\n locate: {\n element: {\n resultFormat: {\n coordinates: { shape: 'bbox', order: 'xy' },\n },\n },\n },\n },\n 'gpt-6': {\n supportedApiTypes: ['chat-completion', 'responses'],\n resolveImageDetail: originalImageDetailForDefaultIntent,\n responses: {\n replayRawAssistantOutput: false,\n unsupportedUserConfig: ['temperature', 'reasoningBudget'],\n buildResponsesParams: buildGpt6ResponsesParams,\n },\n buildCodexAppServerParams: buildGpt6CodexAppServerParams,\n chatCompletion: {\n unsupportedUserConfig: ['temperature', 'reasoningBudget'],\n buildChatCompletionParams: buildGpt6ChatCompletionParams,\n },\n locate: {\n element: {\n resultFormat: {\n coordinates: { shape: 'bbox', order: 'xy' },\n },\n },\n },\n },\n} satisfies Pick<\n Record<TModelFamily, ModelAdapterDefinition>,\n 'gpt-5' | 'gpt-6'\n>;\n"],"names":["originalImageDetailForDefaultIntent","input","isLocateIntent","resolveGpt5ReasoningEffort","reasoningEnabled","reasoningEffort","resolveGpt6ReasoningEffort","buildGpt5CodexAppServerParams","buildGpt6CodexAppServerParams","buildGpt5ResponsesParams","midsceneDefaults","userConfig","expectedJsonObjectResponse","commonOverrideConfig","undefined","effectiveReasoningEffort","buildGpt6ResponsesParams","responseFormat","buildGpt5ChatCompletionParams","buildGpt6ChatCompletionParams","gptAdapters"],"mappings":"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"}
@@ -26,8 +26,8 @@ const MODEL_ADAPTER_CONFIGS = {
26
26
  const modelAdapterCache = new Map();
27
27
  const debugModelAdapter = getDebug('ai:model-adapter');
28
28
  function debugAdapterUnsupportedUserConfig(modelFamily, adapter) {
29
- if (0 === adapter.chatCompletion.unsupportedUserConfig.length) return;
30
- debugModelAdapter(`model adapter "${modelFamily}" unsupportedUserConfig: ${JSON.stringify(adapter.chatCompletion.unsupportedUserConfig)}`);
29
+ if (adapter.chatCompletion.unsupportedUserConfig.length > 0) debugModelAdapter(`model adapter "${modelFamily}" (chat-completion) unsupportedUserConfig: ${JSON.stringify(adapter.chatCompletion.unsupportedUserConfig)}`);
30
+ if (adapter.responses.unsupportedUserConfig.length > 0) debugModelAdapter(`model adapter "${modelFamily}" (responses) unsupportedUserConfig: ${JSON.stringify(adapter.responses.unsupportedUserConfig)}`);
31
31
  }
32
32
  function getModelAdapter(modelFamily) {
33
33
  const cacheKey = modelFamily ?? 'default';
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/models/registry.mjs","sources":["../../../../src/ai-model/models/registry.ts"],"sourcesContent":["import type { IModelConfig, TModelFamily } from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ResolvedModelAdapter } from '../model-adapter/resolve';\nimport type {\n ModelAdapter,\n ModelAdapterDefinition,\n ModelRuntime,\n} from '../model-adapter/types';\nimport { autoGlmAdapters } from './auto-glm/adapter';\nimport { deepSeekAdapters } from './deepseek/adapter';\nimport { defaultOpenAICompatibleAdapterConfig } from './default';\nimport { doubaoAdapters } from './doubao';\nimport { geminiAdapters } from './gemini';\nimport { glmAdapters } from './glm';\nimport { gptAdapters } from './gpt';\nimport { kimiAdapters } from './kimi';\nimport { mimoAdapters } from './mimo';\nimport { qwenAdapters } from './qwen';\nimport { uiTarsAdapters } from './ui-tars/adapter';\n\nexport const MODEL_ADAPTER_CONFIGS = {\n ...qwenAdapters,\n ...deepSeekAdapters,\n ...doubaoAdapters,\n ...geminiAdapters,\n ...uiTarsAdapters,\n ...glmAdapters,\n ...autoGlmAdapters,\n ...gptAdapters,\n ...kimiAdapters,\n ...mimoAdapters,\n} satisfies Record<TModelFamily, ModelAdapterDefinition>;\n\ntype ModelAdapterCacheKey = TModelFamily | 'default';\n\nconst modelAdapterCache = new Map<ModelAdapterCacheKey, ModelAdapter>();\nconst debugModelAdapter = getDebug('ai:model-adapter');\n\nfunction debugAdapterUnsupportedUserConfig(\n modelFamily: ModelAdapterCacheKey,\n adapter: ModelAdapter,\n): void {\n if (adapter.chatCompletion.unsupportedUserConfig.length === 0) {\n return;\n }\n\n debugModelAdapter(\n `model adapter \"${modelFamily}\" unsupportedUserConfig: ${JSON.stringify(\n adapter.chatCompletion.unsupportedUserConfig,\n )}`,\n );\n}\n\nexport function getModelAdapter(modelFamily?: TModelFamily): ModelAdapter {\n const cacheKey: ModelAdapterCacheKey = modelFamily ?? 'default';\n let adapter = modelAdapterCache.get(cacheKey);\n if (adapter) {\n return adapter;\n }\n\n const config = modelFamily\n ? MODEL_ADAPTER_CONFIGS[modelFamily]\n : defaultOpenAICompatibleAdapterConfig;\n if (!config) {\n throw new Error(\n `No model adapter registered for modelFamily: ${modelFamily}`,\n );\n }\n\n adapter = new ResolvedModelAdapter(config, cacheKey);\n modelAdapterCache.set(cacheKey, adapter);\n debugAdapterUnsupportedUserConfig(cacheKey, adapter);\n\n return adapter;\n}\n\nexport function getModelRuntime(config: IModelConfig): ModelRuntime {\n return {\n config,\n adapter: getModelAdapter(config.modelFamily),\n };\n}\n"],"names":["MODEL_ADAPTER_CONFIGS","qwenAdapters","deepSeekAdapters","doubaoAdapters","geminiAdapters","uiTarsAdapters","glmAdapters","autoGlmAdapters","gptAdapters","kimiAdapters","mimoAdapters","modelAdapterCache","Map","debugModelAdapter","getDebug","debugAdapterUnsupportedUserConfig","modelFamily","adapter","JSON","getModelAdapter","cacheKey","config","defaultOpenAICompatibleAdapterConfig","Error","ResolvedModelAdapter","getModelRuntime"],"mappings":";;;;;;;;;;;;;AAoBO,MAAMA,wBAAwB;IACnC,GAAGC,YAAY;IACf,GAAGC,gBAAgB;IACnB,GAAGC,cAAc;IACjB,GAAGC,cAAc;IACjB,GAAGC,cAAc;IACjB,GAAGC,WAAW;IACd,GAAGC,eAAe;IAClB,GAAGC,WAAW;IACd,GAAGC,YAAY;IACf,GAAGC,YAAY;AACjB;AAIA,MAAMC,oBAAoB,IAAIC;AAC9B,MAAMC,oBAAoBC,SAAS;AAEnC,SAASC,kCACPC,WAAiC,EACjCC,OAAqB;IAErB,IAAIA,AAAwD,MAAxDA,QAAQ,cAAc,CAAC,qBAAqB,CAAC,MAAM,EACrD;IAGFJ,kBACE,CAAC,eAAe,EAAEG,YAAY,yBAAyB,EAAEE,KAAK,SAAS,CACrED,QAAQ,cAAc,CAAC,qBAAqB,GAC3C;AAEP;AAEO,SAASE,gBAAgBH,WAA0B;IACxD,MAAMI,WAAiCJ,eAAe;IACtD,IAAIC,UAAUN,kBAAkB,GAAG,CAACS;IACpC,IAAIH,SACF,OAAOA;IAGT,MAAMI,SAASL,cACXhB,qBAAqB,CAACgB,YAAY,GAClCM;IACJ,IAAI,CAACD,QACH,MAAM,IAAIE,MACR,CAAC,6CAA6C,EAAEP,aAAa;IAIjEC,UAAU,IAAIO,qBAAqBH,QAAQD;IAC3CT,kBAAkB,GAAG,CAACS,UAAUH;IAChCF,kCAAkCK,UAAUH;IAE5C,OAAOA;AACT;AAEO,SAASQ,gBAAgBJ,MAAoB;IAClD,OAAO;QACLA;QACA,SAASF,gBAAgBE,OAAO,WAAW;IAC7C;AACF"}
1
+ {"version":3,"file":"ai-model/models/registry.mjs","sources":["../../../../src/ai-model/models/registry.ts"],"sourcesContent":["import type { IModelConfig, TModelFamily } from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ResolvedModelAdapter } from '../model-adapter/resolve';\nimport type {\n ModelAdapter,\n ModelAdapterDefinition,\n ModelRuntime,\n} from '../model-adapter/types';\nimport { autoGlmAdapters } from './auto-glm/adapter';\nimport { deepSeekAdapters } from './deepseek/adapter';\nimport { defaultOpenAICompatibleAdapterConfig } from './default';\nimport { doubaoAdapters } from './doubao';\nimport { geminiAdapters } from './gemini';\nimport { glmAdapters } from './glm';\nimport { gptAdapters } from './gpt';\nimport { kimiAdapters } from './kimi';\nimport { mimoAdapters } from './mimo';\nimport { qwenAdapters } from './qwen';\nimport { uiTarsAdapters } from './ui-tars/adapter';\n\nexport const MODEL_ADAPTER_CONFIGS = {\n ...qwenAdapters,\n ...deepSeekAdapters,\n ...doubaoAdapters,\n ...geminiAdapters,\n ...uiTarsAdapters,\n ...glmAdapters,\n ...autoGlmAdapters,\n ...gptAdapters,\n ...kimiAdapters,\n ...mimoAdapters,\n} satisfies Record<TModelFamily, ModelAdapterDefinition>;\n\ntype ModelAdapterCacheKey = TModelFamily | 'default';\n\nconst modelAdapterCache = new Map<ModelAdapterCacheKey, ModelAdapter>();\nconst debugModelAdapter = getDebug('ai:model-adapter');\n\nfunction debugAdapterUnsupportedUserConfig(\n modelFamily: ModelAdapterCacheKey,\n adapter: ModelAdapter,\n): void {\n if (adapter.chatCompletion.unsupportedUserConfig.length > 0) {\n debugModelAdapter(\n `model adapter \"${modelFamily}\" (chat-completion) unsupportedUserConfig: ${JSON.stringify(adapter.chatCompletion.unsupportedUserConfig)}`,\n );\n }\n if (adapter.responses.unsupportedUserConfig.length > 0) {\n debugModelAdapter(\n `model adapter \"${modelFamily}\" (responses) unsupportedUserConfig: ${JSON.stringify(adapter.responses.unsupportedUserConfig)}`,\n );\n }\n}\n\nexport function getModelAdapter(modelFamily?: TModelFamily): ModelAdapter {\n const cacheKey: ModelAdapterCacheKey = modelFamily ?? 'default';\n let adapter = modelAdapterCache.get(cacheKey);\n if (adapter) {\n return adapter;\n }\n\n const config = modelFamily\n ? MODEL_ADAPTER_CONFIGS[modelFamily]\n : defaultOpenAICompatibleAdapterConfig;\n if (!config) {\n throw new Error(\n `No model adapter registered for modelFamily: ${modelFamily}`,\n );\n }\n\n adapter = new ResolvedModelAdapter(config, cacheKey);\n modelAdapterCache.set(cacheKey, adapter);\n debugAdapterUnsupportedUserConfig(cacheKey, adapter);\n\n return adapter;\n}\n\nexport function getModelRuntime(config: IModelConfig): ModelRuntime {\n return {\n config,\n adapter: getModelAdapter(config.modelFamily),\n };\n}\n"],"names":["MODEL_ADAPTER_CONFIGS","qwenAdapters","deepSeekAdapters","doubaoAdapters","geminiAdapters","uiTarsAdapters","glmAdapters","autoGlmAdapters","gptAdapters","kimiAdapters","mimoAdapters","modelAdapterCache","Map","debugModelAdapter","getDebug","debugAdapterUnsupportedUserConfig","modelFamily","adapter","JSON","getModelAdapter","cacheKey","config","defaultOpenAICompatibleAdapterConfig","Error","ResolvedModelAdapter","getModelRuntime"],"mappings":";;;;;;;;;;;;;AAoBO,MAAMA,wBAAwB;IACnC,GAAGC,YAAY;IACf,GAAGC,gBAAgB;IACnB,GAAGC,cAAc;IACjB,GAAGC,cAAc;IACjB,GAAGC,cAAc;IACjB,GAAGC,WAAW;IACd,GAAGC,eAAe;IAClB,GAAGC,WAAW;IACd,GAAGC,YAAY;IACf,GAAGC,YAAY;AACjB;AAIA,MAAMC,oBAAoB,IAAIC;AAC9B,MAAMC,oBAAoBC,SAAS;AAEnC,SAASC,kCACPC,WAAiC,EACjCC,OAAqB;IAErB,IAAIA,QAAQ,cAAc,CAAC,qBAAqB,CAAC,MAAM,GAAG,GACxDJ,kBACE,CAAC,eAAe,EAAEG,YAAY,2CAA2C,EAAEE,KAAK,SAAS,CAACD,QAAQ,cAAc,CAAC,qBAAqB,GAAG;IAG7I,IAAIA,QAAQ,SAAS,CAAC,qBAAqB,CAAC,MAAM,GAAG,GACnDJ,kBACE,CAAC,eAAe,EAAEG,YAAY,qCAAqC,EAAEE,KAAK,SAAS,CAACD,QAAQ,SAAS,CAAC,qBAAqB,GAAG;AAGpI;AAEO,SAASE,gBAAgBH,WAA0B;IACxD,MAAMI,WAAiCJ,eAAe;IACtD,IAAIC,UAAUN,kBAAkB,GAAG,CAACS;IACpC,IAAIH,SACF,OAAOA;IAGT,MAAMI,SAASL,cACXhB,qBAAqB,CAACgB,YAAY,GAClCM;IACJ,IAAI,CAACD,QACH,MAAM,IAAIE,MACR,CAAC,6CAA6C,EAAEP,aAAa;IAIjEC,UAAU,IAAIO,qBAAqBH,QAAQD;IAC3CT,kBAAkB,GAAG,CAACS,UAAUH;IAChCF,kCAAkCK,UAAUH;IAE5C,OAAOA;AACT;AAEO,SAASQ,gBAAgBJ,MAAoB;IAClD,OAAO;QACLA;QACA,SAASF,gBAAgBE,OAAO,WAAW;IAC7C;AACF"}
@@ -5,6 +5,7 @@ import { isCodexAppServerProvider } from "./codex/codex-app-server.mjs";
5
5
  import { isModelCallRecordingEnabled, recordModelCallEvent } from "./model-call-recorder.mjs";
6
6
  import { callOpenAI } from "./openai/call-openai.mjs";
7
7
  import { prepareChatCompletion } from "./openai/chat-completion/chat-completion.mjs";
8
+ import { prepareResponses } from "./openai/responses/responses.mjs";
8
9
  import { buildRequestAbortSignal, resolveEffectiveTimeoutMs, runWithAbortSignal, waitForRetry } from "./request-timeout.mjs";
9
10
  import { appendAIRequestFailureSummary, buildUsageInfo, nextInternalCallId, normalizeRetryCount, toError } from "./utils.mjs";
10
11
  function _define_property(obj, key, value) {
@@ -17,6 +18,7 @@ function _define_property(obj, key, value) {
17
18
  else obj[key] = value;
18
19
  return obj;
19
20
  }
21
+ const DEFAULT_MODEL_API_TYPE = 'chat-completion';
20
22
  async function callAI(messages, modelRuntime, options) {
21
23
  options?.abortSignal?.throwIfAborted();
22
24
  const isStreaming = options?.stream === true;
@@ -24,21 +26,27 @@ async function callAI(messages, modelRuntime, options) {
24
26
  const executionId = modelRuntime.executionId ?? `unscoped-${uuid()}`;
25
27
  const internalCallId = nextInternalCallId();
26
28
  const { config: modelConfig } = modelRuntime;
27
- const prepare = async ()=>isCodexAppServerProvider(modelConfig.openaiBaseURL) ? {
29
+ const prepare = async ()=>{
30
+ const input = {
31
+ messages,
32
+ modelRuntime,
33
+ options
34
+ };
35
+ if (isCodexAppServerProvider(modelConfig.openaiBaseURL)) return {
28
36
  protocol: 'codex',
29
- input: prepareCodexCall({
30
- messages,
31
- modelRuntime,
32
- options
33
- })
34
- } : {
37
+ input: prepareCodexCall(input)
38
+ };
39
+ const apiType = modelConfig.apiType ?? DEFAULT_MODEL_API_TYPE;
40
+ assert(modelRuntime.adapter.supportedApiTypes.includes(apiType), `Model adapter "${modelConfig.modelFamily ?? 'default'}" does not support API type "${apiType}"`);
41
+ if ('responses' === apiType) return {
42
+ protocol: 'responses',
43
+ input: await prepareResponses(input)
44
+ };
45
+ return {
35
46
  protocol: 'chat-completion',
36
- input: await prepareChatCompletion({
37
- messages,
38
- modelRuntime,
39
- options
40
- })
47
+ input: await prepareChatCompletion(input)
41
48
  };
49
+ };
42
50
  const prepared = options?.abortSignal ? await runWithAbortSignal(options.abortSignal, prepare) : await prepare();
43
51
  const result = await callModelWithRetry({
44
52
  messages,
@@ -50,6 +58,7 @@ async function callAI(messages, modelRuntime, options) {
50
58
  });
51
59
  const { rawUsage, timeCost, totalTimeCost, retryCount, requestId, responseModelName, ...response } = result;
52
60
  const usage = buildUsageInfo({
61
+ apiType: prepared.protocol,
53
62
  usageData: rawUsage,
54
63
  timeCost,
55
64
  totalTimeCost,
@@ -145,7 +154,7 @@ async function callModelOnce({ messages, modelRuntime, options, executionId, int
145
154
  } : options
146
155
  };
147
156
  try {
148
- return await runWithAbortSignal(requestSignal, ()=>'codex' === prepared.protocol ? callCodex(context, prepared.input) : callOpenAI(context, prepared.input));
157
+ return await runWithAbortSignal(requestSignal, ()=>'codex' === prepared.protocol ? callCodex(context, prepared.input) : callOpenAI(context, prepared));
149
158
  } catch (error) {
150
159
  options?.abortSignal?.throwIfAborted();
151
160
  const lastError = toError(error);
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/call-ai.mjs","sources":["../../../../src/ai-model/service-caller/call-ai.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { assert, uuid } from '@midscene/shared/utils';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { ModelRuntime } from '../models';\nimport { callCodex, prepareCodexCall } from './codex/call-codex';\nimport { isCodexAppServerProvider } from './codex/codex-app-server';\nimport {\n isModelCallRecordingEnabled,\n recordModelCallEvent,\n} from './model-call-recorder';\nimport { callOpenAI } from './openai/call-openai';\nimport { prepareChatCompletion } from './openai/chat-completion/chat-completion';\nimport {\n buildRequestAbortSignal,\n resolveEffectiveTimeoutMs,\n runWithAbortSignal,\n waitForRetry,\n} from './request-timeout';\nimport type {\n AICallResult,\n CallAIOptions,\n ModelCallContext,\n ModelCallResult,\n} from './types';\nimport {\n appendAIRequestFailureSummary,\n buildUsageInfo,\n nextInternalCallId,\n normalizeRetryCount,\n toError,\n} from './utils';\n\nexport async function callAI(\n messages: ChatCompletionMessageParam[],\n modelRuntime: ModelRuntime,\n options?: CallAIOptions,\n): Promise<AICallResult> {\n options?.abortSignal?.throwIfAborted();\n const isStreaming = options?.stream === true;\n if (isStreaming) {\n assert(\n typeof options?.onChunk === 'function',\n 'onChunk is required when stream is true',\n );\n }\n\n // Low-level callers without a TaskRunner still need a stable ID for the\n // lifetime of this model call (including its network retries).\n const executionId = modelRuntime.executionId ?? `unscoped-${uuid()}`;\n\n // Stable internal ID for this call, used by the agent to deduplicate usage\n // across the onUsage callback and the task-dump-based collectUsageMetrics()\n // path when the provider does not return a request_id.\n const internalCallId = nextInternalCallId();\n\n const { config: modelConfig } = modelRuntime;\n\n const prepare = async (): Promise<PreparedModelInput> =>\n isCodexAppServerProvider(modelConfig.openaiBaseURL)\n ? {\n protocol: 'codex',\n input: prepareCodexCall({ messages, modelRuntime, options }),\n }\n : {\n protocol: 'chat-completion',\n input: await prepareChatCompletion({\n messages,\n modelRuntime,\n options,\n }),\n };\n\n const prepared = options?.abortSignal\n ? await runWithAbortSignal(options.abortSignal, prepare)\n : await prepare();\n\n const result = await callModelWithRetry({\n messages,\n modelRuntime,\n options,\n executionId,\n internalCallId,\n prepared,\n });\n\n const {\n rawUsage,\n timeCost,\n totalTimeCost,\n retryCount,\n requestId,\n responseModelName,\n ...response\n } = result;\n\n const usage = buildUsageInfo({\n usageData: rawUsage,\n timeCost,\n totalTimeCost,\n retryCount,\n requestId,\n responseModelName,\n modelName: modelConfig.modelName,\n modelDescription: modelConfig.modelDescription,\n slot: modelConfig.slot,\n internalCallId,\n });\n\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n debugProfileStats(\n `model, ${modelConfig.modelName}, mode, ${modelConfig.modelFamily || 'default'}, streaming, ${response.isStreamed}, prompt-tokens, ${usage?.prompt_tokens ?? ''}, completion-tokens, ${usage?.completion_tokens ?? ''}, total-tokens, ${usage?.total_tokens ?? ''}, cached-input, ${usage?.cached_input ?? ''}, cost-ms, ${timeCost ?? ''}, requestId, ${requestId ?? ''}, slot, ${modelConfig.slot}, configured-temperature, ${modelConfig.temperature ?? ''}`,\n );\n debugProfileDetail(`model usage detail: ${JSON.stringify(usage)}`);\n\n if (usage && modelRuntime.onUsage) {\n modelRuntime.onUsage(usage);\n }\n return { ...response, usage };\n}\n\ntype PreparedModelInput =\n | { protocol: 'codex'; input: ReturnType<typeof prepareCodexCall> }\n | {\n protocol: 'chat-completion';\n input: Awaited<ReturnType<typeof prepareChatCompletion>>;\n };\n\ntype ModelCallInput = {\n messages: ChatCompletionMessageParam[];\n modelRuntime: ModelRuntime;\n options?: CallAIOptions;\n executionId: string;\n internalCallId: string;\n prepared: PreparedModelInput;\n};\n\n/** Carries the original failure across the retry boundary without replaying output. */\nclass NonRetryableModelCallError extends Error {\n readonly cause: Error;\n\n constructor(cause: Error) {\n super(cause.message, { cause });\n this.cause = cause;\n }\n}\n\nasync function callModelWithRetry(\n input: ModelCallInput,\n): Promise<ModelCallResult & { totalTimeCost: number; retryCount: number }> {\n const startTime = Date.now();\n const {\n modelRuntime: { config },\n options,\n } = input;\n const maxAttempts = normalizeRetryCount(config.retryCount) + 1;\n const retryInterval = config.retryInterval ?? 2000;\n const attemptErrors: Array<{ attempt: number; error: unknown }> = [];\n\n for (let attempt = 1; ; attempt++) {\n options?.abortSignal?.throwIfAborted();\n try {\n const result = await callModelOnce(input, attempt);\n return {\n ...result,\n totalTimeCost: Date.now() - startTime,\n retryCount: attempt - 1,\n };\n } catch (error) {\n options?.abortSignal?.throwIfAborted();\n if (error instanceof NonRetryableModelCallError) {\n throw error.cause;\n }\n const lastError = toError(error);\n attemptErrors.push({ attempt, error: lastError });\n if (attempt === maxAttempts) {\n throw appendAIRequestFailureSummary(\n lastError,\n attemptErrors,\n maxAttempts,\n );\n }\n getDebug('ai:call', { console: true })(\n `AI call failed (attempt ${attempt}/${maxAttempts}), retrying in ${retryInterval}ms... Error: ${lastError.message}`,\n );\n }\n await waitForRetry(retryInterval, options?.abortSignal);\n }\n}\n\nasync function callModelOnce(\n {\n messages,\n modelRuntime,\n options,\n executionId,\n internalCallId,\n prepared,\n }: ModelCallInput,\n attempt: number,\n): Promise<ModelCallResult> {\n const { config: modelConfig } = modelRuntime;\n const recordEvent = isModelCallRecordingEnabled()\n ? (event: Record<string, unknown>) => {\n void recordModelCallEvent({\n executionId,\n callId: internalCallId,\n semanticRetryAttempt: options?.semanticRetryAttempt,\n slot: modelConfig.slot,\n intent: modelConfig.intent,\n modelFamily: modelConfig.modelFamily,\n ...event,\n attempt,\n });\n }\n : undefined;\n const effectiveTimeoutMs = resolveEffectiveTimeoutMs(modelConfig.timeout);\n const { signal: requestSignal, cleanup } = buildRequestAbortSignal(\n effectiveTimeoutMs,\n options?.abortSignal,\n );\n let deliveredChunk = false;\n const onChunk = options?.onChunk;\n const context: ModelCallContext = {\n messages,\n modelRuntime,\n executionId,\n recordEvent,\n requestSignal,\n effectiveTimeoutMs,\n options: onChunk\n ? {\n ...options,\n onChunk: (chunk) => {\n requestSignal.throwIfAborted();\n deliveredChunk = true;\n onChunk(chunk);\n },\n }\n : options,\n };\n try {\n return await runWithAbortSignal(requestSignal, () =>\n prepared.protocol === 'codex'\n ? callCodex(context, prepared.input)\n : callOpenAI(context, prepared.input),\n );\n } catch (error) {\n options?.abortSignal?.throwIfAborted();\n const lastError = toError(error);\n if (deliveredChunk) {\n throw new NonRetryableModelCallError(lastError);\n }\n throw lastError;\n } finally {\n cleanup();\n }\n}\n"],"names":["callAI","messages","modelRuntime","options","isStreaming","assert","executionId","uuid","internalCallId","nextInternalCallId","modelConfig","prepare","isCodexAppServerProvider","prepareCodexCall","prepareChatCompletion","prepared","runWithAbortSignal","result","callModelWithRetry","rawUsage","timeCost","totalTimeCost","retryCount","requestId","responseModelName","response","usage","buildUsageInfo","debugProfileStats","getDebug","debugProfileDetail","JSON","NonRetryableModelCallError","Error","cause","input","startTime","Date","config","maxAttempts","normalizeRetryCount","retryInterval","attemptErrors","attempt","callModelOnce","error","lastError","toError","appendAIRequestFailureSummary","waitForRetry","recordEvent","isModelCallRecordingEnabled","event","recordModelCallEvent","undefined","effectiveTimeoutMs","resolveEffectiveTimeoutMs","requestSignal","cleanup","buildRequestAbortSignal","deliveredChunk","onChunk","context","chunk","callCodex","callOpenAI"],"mappings":"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"}
1
+ {"version":3,"file":"ai-model/service-caller/call-ai.mjs","sources":["../../../../src/ai-model/service-caller/call-ai.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { assert, uuid } from '@midscene/shared/utils';\nimport type { ModelRuntime } from '../models';\nimport { callCodex, prepareCodexCall } from './codex/call-codex';\nimport { isCodexAppServerProvider } from './codex/codex-app-server';\nimport {\n isModelCallRecordingEnabled,\n recordModelCallEvent,\n} from './model-call-recorder';\nimport { type PreparedOpenAIInput, callOpenAI } from './openai/call-openai';\nimport { prepareChatCompletion } from './openai/chat-completion/chat-completion';\nimport { prepareResponses } from './openai/responses/responses';\nimport {\n buildRequestAbortSignal,\n resolveEffectiveTimeoutMs,\n runWithAbortSignal,\n waitForRetry,\n} from './request-timeout';\nimport type { ModelCallMessages } from './types';\nimport type {\n AICallResult,\n CallAIOptions,\n ModelCallContext,\n ModelCallResult,\n} from './types';\nimport {\n appendAIRequestFailureSummary,\n buildUsageInfo,\n nextInternalCallId,\n normalizeRetryCount,\n toError,\n} from './utils';\n\nconst DEFAULT_MODEL_API_TYPE = 'chat-completion';\n\nexport async function callAI(\n messages: ModelCallMessages,\n modelRuntime: ModelRuntime,\n options?: CallAIOptions,\n): Promise<AICallResult> {\n options?.abortSignal?.throwIfAborted();\n const isStreaming = options?.stream === true;\n if (isStreaming) {\n assert(\n typeof options?.onChunk === 'function',\n 'onChunk is required when stream is true',\n );\n }\n\n // Low-level callers without a TaskRunner still need a stable ID for the\n // lifetime of this model call (including its network retries).\n const executionId = modelRuntime.executionId ?? `unscoped-${uuid()}`;\n\n // Stable internal ID for this call, used by the agent to deduplicate usage\n // across the onUsage callback and the task-dump-based collectUsageMetrics()\n // path when the provider does not return a request_id.\n const internalCallId = nextInternalCallId();\n\n const { config: modelConfig } = modelRuntime;\n\n const prepare = async (): Promise<PreparedModelInput> => {\n const input = { messages, modelRuntime, options };\n if (isCodexAppServerProvider(modelConfig.openaiBaseURL)) {\n return { protocol: 'codex', input: prepareCodexCall(input) };\n }\n const apiType = modelConfig.apiType ?? DEFAULT_MODEL_API_TYPE;\n\n assert(\n modelRuntime.adapter.supportedApiTypes.includes(apiType),\n `Model adapter \"${modelConfig.modelFamily ?? 'default'}\" does not support API type \"${apiType}\"`,\n );\n if (apiType === 'responses') {\n return { protocol: 'responses', input: await prepareResponses(input) };\n }\n return {\n protocol: 'chat-completion',\n input: await prepareChatCompletion(input),\n };\n };\n\n const prepared = options?.abortSignal\n ? await runWithAbortSignal(options.abortSignal, prepare)\n : await prepare();\n\n const result = await callModelWithRetry({\n messages,\n modelRuntime,\n options,\n executionId,\n internalCallId,\n prepared,\n });\n\n const {\n rawUsage,\n timeCost,\n totalTimeCost,\n retryCount,\n requestId,\n responseModelName,\n ...response\n } = result;\n\n const usage = buildUsageInfo({\n apiType: prepared.protocol,\n usageData: rawUsage,\n timeCost,\n totalTimeCost,\n retryCount,\n requestId,\n responseModelName,\n modelName: modelConfig.modelName,\n modelDescription: modelConfig.modelDescription,\n slot: modelConfig.slot,\n internalCallId,\n });\n\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n debugProfileStats(\n `model, ${modelConfig.modelName}, mode, ${modelConfig.modelFamily || 'default'}, streaming, ${response.isStreamed}, prompt-tokens, ${usage?.prompt_tokens ?? ''}, completion-tokens, ${usage?.completion_tokens ?? ''}, total-tokens, ${usage?.total_tokens ?? ''}, cached-input, ${usage?.cached_input ?? ''}, cost-ms, ${timeCost ?? ''}, requestId, ${requestId ?? ''}, slot, ${modelConfig.slot}, configured-temperature, ${modelConfig.temperature ?? ''}`,\n );\n debugProfileDetail(`model usage detail: ${JSON.stringify(usage)}`);\n\n if (usage && modelRuntime.onUsage) {\n modelRuntime.onUsage(usage);\n }\n return { ...response, usage };\n}\n\ntype PreparedModelInput =\n | { protocol: 'codex'; input: ReturnType<typeof prepareCodexCall> }\n | PreparedOpenAIInput;\n\ntype ModelCallInput = {\n messages: ModelCallMessages;\n modelRuntime: ModelRuntime;\n options?: CallAIOptions;\n executionId: string;\n internalCallId: string;\n prepared: PreparedModelInput;\n};\n\n/** Carries the original failure across the retry boundary without replaying output. */\nclass NonRetryableModelCallError extends Error {\n readonly cause: Error;\n\n constructor(cause: Error) {\n super(cause.message, { cause });\n this.cause = cause;\n }\n}\n\nasync function callModelWithRetry(\n input: ModelCallInput,\n): Promise<ModelCallResult & { totalTimeCost: number; retryCount: number }> {\n const startTime = Date.now();\n const {\n modelRuntime: { config },\n options,\n } = input;\n const maxAttempts = normalizeRetryCount(config.retryCount) + 1;\n const retryInterval = config.retryInterval ?? 2000;\n const attemptErrors: Array<{ attempt: number; error: unknown }> = [];\n\n for (let attempt = 1; ; attempt++) {\n options?.abortSignal?.throwIfAborted();\n try {\n const result = await callModelOnce(input, attempt);\n return {\n ...result,\n totalTimeCost: Date.now() - startTime,\n retryCount: attempt - 1,\n };\n } catch (error) {\n options?.abortSignal?.throwIfAborted();\n if (error instanceof NonRetryableModelCallError) {\n throw error.cause;\n }\n const lastError = toError(error);\n attemptErrors.push({ attempt, error: lastError });\n if (attempt === maxAttempts) {\n throw appendAIRequestFailureSummary(\n lastError,\n attemptErrors,\n maxAttempts,\n );\n }\n getDebug('ai:call', { console: true })(\n `AI call failed (attempt ${attempt}/${maxAttempts}), retrying in ${retryInterval}ms... Error: ${lastError.message}`,\n );\n }\n await waitForRetry(retryInterval, options?.abortSignal);\n }\n}\n\nasync function callModelOnce(\n {\n messages,\n modelRuntime,\n options,\n executionId,\n internalCallId,\n prepared,\n }: ModelCallInput,\n attempt: number,\n): Promise<ModelCallResult> {\n const { config: modelConfig } = modelRuntime;\n const recordEvent = isModelCallRecordingEnabled()\n ? (event: Record<string, unknown>) => {\n void recordModelCallEvent({\n executionId,\n callId: internalCallId,\n semanticRetryAttempt: options?.semanticRetryAttempt,\n slot: modelConfig.slot,\n intent: modelConfig.intent,\n modelFamily: modelConfig.modelFamily,\n ...event,\n attempt,\n });\n }\n : undefined;\n const effectiveTimeoutMs = resolveEffectiveTimeoutMs(modelConfig.timeout);\n const { signal: requestSignal, cleanup } = buildRequestAbortSignal(\n effectiveTimeoutMs,\n options?.abortSignal,\n );\n let deliveredChunk = false;\n const onChunk = options?.onChunk;\n const context: ModelCallContext = {\n messages,\n modelRuntime,\n executionId,\n recordEvent,\n requestSignal,\n effectiveTimeoutMs,\n options: onChunk\n ? {\n ...options,\n onChunk: (chunk) => {\n requestSignal.throwIfAborted();\n deliveredChunk = true;\n onChunk(chunk);\n },\n }\n : options,\n };\n try {\n return await runWithAbortSignal(requestSignal, () =>\n prepared.protocol === 'codex'\n ? callCodex(context, prepared.input)\n : callOpenAI(context, prepared),\n );\n } catch (error) {\n options?.abortSignal?.throwIfAborted();\n const lastError = toError(error);\n if (deliveredChunk) {\n throw new NonRetryableModelCallError(lastError);\n }\n throw lastError;\n } finally {\n cleanup();\n }\n}\n"],"names":["DEFAULT_MODEL_API_TYPE","callAI","messages","modelRuntime","options","isStreaming","assert","executionId","uuid","internalCallId","nextInternalCallId","modelConfig","prepare","input","isCodexAppServerProvider","prepareCodexCall","apiType","prepareResponses","prepareChatCompletion","prepared","runWithAbortSignal","result","callModelWithRetry","rawUsage","timeCost","totalTimeCost","retryCount","requestId","responseModelName","response","usage","buildUsageInfo","debugProfileStats","getDebug","debugProfileDetail","JSON","NonRetryableModelCallError","Error","cause","startTime","Date","config","maxAttempts","normalizeRetryCount","retryInterval","attemptErrors","attempt","callModelOnce","error","lastError","toError","appendAIRequestFailureSummary","waitForRetry","recordEvent","isModelCallRecordingEnabled","event","recordModelCallEvent","undefined","effectiveTimeoutMs","resolveEffectiveTimeoutMs","requestSignal","cleanup","buildRequestAbortSignal","deliveredChunk","onChunk","context","chunk","callCodex","callOpenAI"],"mappings":"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"}
@@ -1,8 +1,7 @@
1
- import { applyImageDetail } from "../utils.mjs";
2
1
  import { callAIWithCodexAppServer } from "./codex-app-server.mjs";
3
2
  const prepareCodexCall = ({ messages, modelRuntime, options })=>{
4
3
  const { config: modelConfig, adapter } = modelRuntime;
5
- const { config, imageDetail } = adapter.buildCodexAppServerParams({
4
+ const { config } = adapter.buildCodexAppServerParams({
6
5
  intent: modelConfig.intent,
7
6
  userConfig: {
8
7
  reasoningEnabled: modelConfig.reasoningEnabled,
@@ -11,16 +10,18 @@ const prepareCodexCall = ({ messages, modelRuntime, options })=>{
11
10
  },
12
11
  requiresOriginalImageDetail: options?.requiresOriginalImageDetail
13
12
  });
14
- const messagesWithImageDetail = applyImageDetail({
15
- imageDetail,
16
- messages
17
- });
13
+ const resolveImageDetail = ({ imageDetail })=>adapter.resolveImageDetail({
14
+ imageDetail,
15
+ intent: modelConfig.intent,
16
+ requiresOriginalImageDetail: options?.requiresOriginalImageDetail
17
+ });
18
18
  return {
19
- messages: messagesWithImageDetail,
19
+ messages,
20
+ resolveImageDetail,
20
21
  requestParams: config
21
22
  };
22
23
  };
23
- const callCodex = async ({ modelRuntime, options, recordEvent, requestSignal }, { messages, requestParams })=>{
24
+ const callCodex = async ({ modelRuntime, options, recordEvent, requestSignal }, { messages, resolveImageDetail, requestParams })=>{
24
25
  const { config: modelConfig } = modelRuntime;
25
26
  let protocolChunkSequence = 0;
26
27
  const codexStartTime = Date.now();
@@ -46,6 +47,7 @@ const callCodex = async ({ modelRuntime, options, recordEvent, requestSignal },
46
47
  stream: options?.stream,
47
48
  onChunk: options?.onChunk,
48
49
  params: requestParams,
50
+ resolveImageDetail,
49
51
  abortSignal: requestSignal,
50
52
  onRecordEvent: recordCodexEvent
51
53
  });