@midscene/core 1.13.4-beta-20260928072823.0 → 1.14.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 (300) 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/default-locate-protocol.mjs +7 -8
  11. package/dist/es/ai-model/model-adapter/default-locate-protocol.mjs.map +1 -1
  12. package/dist/es/ai-model/model-adapter/locate.mjs +3 -7
  13. package/dist/es/ai-model/model-adapter/locate.mjs.map +1 -1
  14. package/dist/es/ai-model/model-adapter/resolve.mjs +11 -3
  15. package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -1
  16. package/dist/es/ai-model/model-adapter/responses.mjs +38 -0
  17. package/dist/es/ai-model/model-adapter/responses.mjs.map +1 -0
  18. package/dist/es/ai-model/model-adapter/temperature-with-semantic-retry.mjs +7 -0
  19. package/dist/es/ai-model/model-adapter/temperature-with-semantic-retry.mjs.map +1 -0
  20. package/dist/es/ai-model/models/gpt.mjs +73 -9
  21. package/dist/es/ai-model/models/gpt.mjs.map +1 -1
  22. package/dist/es/ai-model/models/qwen.mjs +8 -2
  23. package/dist/es/ai-model/models/qwen.mjs.map +1 -1
  24. package/dist/es/ai-model/models/registry.mjs +2 -2
  25. package/dist/es/ai-model/models/registry.mjs.map +1 -1
  26. package/dist/es/ai-model/service-caller/call-ai.mjs +22 -13
  27. package/dist/es/ai-model/service-caller/call-ai.mjs.map +1 -1
  28. package/dist/es/ai-model/service-caller/codex/call-codex.mjs +10 -8
  29. package/dist/es/ai-model/service-caller/codex/call-codex.mjs.map +1 -1
  30. package/dist/es/ai-model/service-caller/codex/codex-app-server.mjs +29 -28
  31. package/dist/es/ai-model/service-caller/codex/codex-app-server.mjs.map +1 -1
  32. package/dist/es/ai-model/service-caller/index.mjs +1 -2
  33. package/dist/es/ai-model/service-caller/model-call.mjs +4 -4
  34. package/dist/es/ai-model/service-caller/model-call.mjs.map +1 -1
  35. package/dist/es/ai-model/service-caller/openai/call-openai.mjs +18 -8
  36. package/dist/es/ai-model/service-caller/openai/call-openai.mjs.map +1 -1
  37. package/dist/es/ai-model/service-caller/openai/chat-completion/chat-completion.mjs +11 -7
  38. package/dist/es/ai-model/service-caller/openai/chat-completion/chat-completion.mjs.map +1 -1
  39. package/dist/es/ai-model/service-caller/openai/chat-completion/non-stream.mjs +9 -9
  40. package/dist/es/ai-model/service-caller/openai/chat-completion/non-stream.mjs.map +1 -1
  41. package/dist/es/ai-model/service-caller/openai/chat-completion/stream.mjs +4 -8
  42. package/dist/es/ai-model/service-caller/openai/chat-completion/stream.mjs.map +1 -1
  43. package/dist/es/ai-model/service-caller/openai/chat-completion/utils.mjs +28 -1
  44. package/dist/es/ai-model/service-caller/openai/chat-completion/utils.mjs.map +1 -1
  45. package/dist/es/ai-model/service-caller/openai/openai-client.mjs +3 -3
  46. package/dist/es/ai-model/service-caller/openai/openai-client.mjs.map +1 -1
  47. package/dist/es/ai-model/service-caller/openai/responses/non-stream.mjs +21 -0
  48. package/dist/es/ai-model/service-caller/openai/responses/non-stream.mjs.map +1 -0
  49. package/dist/es/ai-model/service-caller/openai/responses/responses.mjs +57 -0
  50. package/dist/es/ai-model/service-caller/openai/responses/responses.mjs.map +1 -0
  51. package/dist/es/ai-model/service-caller/openai/responses/stream.mjs +56 -0
  52. package/dist/es/ai-model/service-caller/openai/responses/stream.mjs.map +1 -0
  53. package/dist/es/ai-model/service-caller/openai/responses/types.mjs +0 -0
  54. package/dist/es/ai-model/service-caller/openai/responses/utils.mjs +72 -0
  55. package/dist/es/ai-model/service-caller/openai/responses/utils.mjs.map +1 -0
  56. package/dist/es/ai-model/service-caller/semantic-retry.mjs.map +1 -1
  57. package/dist/es/ai-model/service-caller/utils.mjs +6 -25
  58. package/dist/es/ai-model/service-caller/utils.mjs.map +1 -1
  59. package/dist/es/ai-model/shared/model-locate-result/factory.mjs +4 -1
  60. package/dist/es/ai-model/shared/model-locate-result/factory.mjs.map +1 -1
  61. package/dist/es/ai-model/shared/model-locate-result/prompt-spec.mjs +3 -2
  62. package/dist/es/ai-model/shared/model-locate-result/prompt-spec.mjs.map +1 -1
  63. package/dist/es/ai-model/shared/model-locate-result/result-field.mjs +13 -0
  64. package/dist/es/ai-model/shared/model-locate-result/result-field.mjs.map +1 -0
  65. package/dist/es/ai-model/shared/model-locate-result/types.mjs.map +1 -1
  66. package/dist/es/ai-model/shared/multimodal-prompt.mjs +5 -8
  67. package/dist/es/ai-model/shared/multimodal-prompt.mjs.map +1 -1
  68. package/dist/es/ai-model/workflows/grounding/locate.mjs +6 -6
  69. package/dist/es/ai-model/workflows/grounding/locate.mjs.map +1 -1
  70. package/dist/es/ai-model/workflows/grounding/planning-action-locate.mjs +5 -5
  71. package/dist/es/ai-model/workflows/grounding/planning-action-locate.mjs.map +1 -1
  72. package/dist/es/ai-model/workflows/grounding/section-locate.mjs +5 -5
  73. package/dist/es/ai-model/workflows/grounding/section-locate.mjs.map +1 -1
  74. package/dist/es/ai-model/workflows/grounding/utils.mjs +4 -7
  75. package/dist/es/ai-model/workflows/grounding/utils.mjs.map +1 -1
  76. package/dist/es/ai-model/workflows/insight/extraction.mjs +9 -15
  77. package/dist/es/ai-model/workflows/insight/extraction.mjs.map +1 -1
  78. package/dist/es/ai-model/workflows/insight/order-sensitive.mjs.map +1 -1
  79. package/dist/es/ai-model/workflows/planning/conversation-history.mjs +17 -9
  80. package/dist/es/ai-model/workflows/planning/conversation-history.mjs.map +1 -1
  81. package/dist/es/ai-model/workflows/planning/custom-planning.mjs +12 -14
  82. package/dist/es/ai-model/workflows/planning/custom-planning.mjs.map +1 -1
  83. package/dist/es/ai-model/workflows/planning/locate-normalization.mjs +5 -9
  84. package/dist/es/ai-model/workflows/planning/locate-normalization.mjs.map +1 -1
  85. package/dist/es/ai-model/workflows/planning/standard-planning.mjs +25 -28
  86. package/dist/es/ai-model/workflows/planning/standard-planning.mjs.map +1 -1
  87. package/dist/es/ai-model/workflows/recorder-generation/common.mjs +2 -4
  88. package/dist/es/ai-model/workflows/recorder-generation/common.mjs.map +1 -1
  89. package/dist/es/ai-model/workflows/recorder-generation/markdown.mjs +3 -5
  90. package/dist/es/ai-model/workflows/recorder-generation/markdown.mjs.map +1 -1
  91. package/dist/es/ai-model/workflows/recorder-generation/metadata.mjs +2 -4
  92. package/dist/es/ai-model/workflows/recorder-generation/metadata.mjs.map +1 -1
  93. package/dist/es/ai-model/workflows/recorder-generation/playwright.mjs.map +1 -1
  94. package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs +2 -4
  95. package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs.map +1 -1
  96. package/dist/es/report-html-template.mjs +1 -1
  97. package/dist/es/service/index.mjs +17 -26
  98. package/dist/es/service/index.mjs.map +1 -1
  99. package/dist/es/types.mjs.map +1 -1
  100. package/dist/es/utils.mjs +1 -1
  101. package/dist/lib/agent/task-builder.js +1 -1
  102. package/dist/lib/agent/task-builder.js.map +1 -1
  103. package/dist/lib/agent/tasks.js +4 -4
  104. package/dist/lib/agent/tasks.js.map +1 -1
  105. package/dist/lib/agent/utils.js +1 -1
  106. package/dist/lib/ai-model/connectivity/run-connectivity-test.js +2 -5
  107. package/dist/lib/ai-model/connectivity/run-connectivity-test.js.map +1 -1
  108. package/dist/lib/ai-model/model-adapter/chat-completion.js +8 -11
  109. package/dist/lib/ai-model/model-adapter/chat-completion.js.map +1 -1
  110. package/dist/lib/ai-model/model-adapter/default-locate-protocol.js +7 -8
  111. package/dist/lib/ai-model/model-adapter/default-locate-protocol.js.map +1 -1
  112. package/dist/lib/ai-model/model-adapter/locate.js +3 -7
  113. package/dist/lib/ai-model/model-adapter/locate.js.map +1 -1
  114. package/dist/lib/ai-model/model-adapter/resolve.js +11 -3
  115. package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -1
  116. package/dist/lib/ai-model/model-adapter/responses.js +75 -0
  117. package/dist/lib/ai-model/model-adapter/responses.js.map +1 -0
  118. package/dist/lib/ai-model/model-adapter/temperature-with-semantic-retry.js +41 -0
  119. package/dist/lib/ai-model/model-adapter/temperature-with-semantic-retry.js.map +1 -0
  120. package/dist/lib/ai-model/models/gpt.js +73 -9
  121. package/dist/lib/ai-model/models/gpt.js.map +1 -1
  122. package/dist/lib/ai-model/models/qwen.js +8 -2
  123. package/dist/lib/ai-model/models/qwen.js.map +1 -1
  124. package/dist/lib/ai-model/models/registry.js +2 -2
  125. package/dist/lib/ai-model/models/registry.js.map +1 -1
  126. package/dist/lib/ai-model/service-caller/call-ai.js +22 -13
  127. package/dist/lib/ai-model/service-caller/call-ai.js.map +1 -1
  128. package/dist/lib/ai-model/service-caller/codex/call-codex.js +10 -8
  129. package/dist/lib/ai-model/service-caller/codex/call-codex.js.map +1 -1
  130. package/dist/lib/ai-model/service-caller/codex/codex-app-server.js +29 -28
  131. package/dist/lib/ai-model/service-caller/codex/codex-app-server.js.map +1 -1
  132. package/dist/lib/ai-model/service-caller/index.js +0 -4
  133. package/dist/lib/ai-model/service-caller/model-call.js +4 -4
  134. package/dist/lib/ai-model/service-caller/model-call.js.map +1 -1
  135. package/dist/lib/ai-model/service-caller/openai/call-openai.js +17 -7
  136. package/dist/lib/ai-model/service-caller/openai/call-openai.js.map +1 -1
  137. package/dist/lib/ai-model/service-caller/openai/chat-completion/chat-completion.js +10 -6
  138. package/dist/lib/ai-model/service-caller/openai/chat-completion/chat-completion.js.map +1 -1
  139. package/dist/lib/ai-model/service-caller/openai/chat-completion/non-stream.js +9 -9
  140. package/dist/lib/ai-model/service-caller/openai/chat-completion/non-stream.js.map +1 -1
  141. package/dist/lib/ai-model/service-caller/openai/chat-completion/stream.js +4 -8
  142. package/dist/lib/ai-model/service-caller/openai/chat-completion/stream.js.map +1 -1
  143. package/dist/lib/ai-model/service-caller/openai/chat-completion/utils.js +32 -2
  144. package/dist/lib/ai-model/service-caller/openai/chat-completion/utils.js.map +1 -1
  145. package/dist/lib/ai-model/service-caller/openai/openai-client.js +5 -5
  146. package/dist/lib/ai-model/service-caller/openai/openai-client.js.map +1 -1
  147. package/dist/lib/ai-model/service-caller/openai/responses/non-stream.js +55 -0
  148. package/dist/lib/ai-model/service-caller/openai/responses/non-stream.js.map +1 -0
  149. package/dist/lib/ai-model/service-caller/openai/responses/responses.js +94 -0
  150. package/dist/lib/ai-model/service-caller/openai/responses/responses.js.map +1 -0
  151. package/dist/lib/ai-model/service-caller/openai/responses/stream.js +90 -0
  152. package/dist/lib/ai-model/service-caller/openai/responses/stream.js.map +1 -0
  153. package/dist/lib/ai-model/service-caller/openai/responses/types.js +20 -0
  154. package/dist/lib/ai-model/service-caller/openai/responses/types.js.map +1 -0
  155. package/dist/lib/ai-model/service-caller/openai/responses/utils.js +112 -0
  156. package/dist/lib/ai-model/service-caller/openai/responses/utils.js.map +1 -0
  157. package/dist/lib/ai-model/service-caller/semantic-retry.js.map +1 -1
  158. package/dist/lib/ai-model/service-caller/utils.js +5 -27
  159. package/dist/lib/ai-model/service-caller/utils.js.map +1 -1
  160. package/dist/lib/ai-model/shared/model-locate-result/factory.js +4 -1
  161. package/dist/lib/ai-model/shared/model-locate-result/factory.js.map +1 -1
  162. package/dist/lib/ai-model/shared/model-locate-result/prompt-spec.js +3 -2
  163. package/dist/lib/ai-model/shared/model-locate-result/prompt-spec.js.map +1 -1
  164. package/dist/lib/ai-model/shared/model-locate-result/result-field.js +50 -0
  165. package/dist/lib/ai-model/shared/model-locate-result/result-field.js.map +1 -0
  166. package/dist/lib/ai-model/shared/model-locate-result/types.js.map +1 -1
  167. package/dist/lib/ai-model/shared/multimodal-prompt.js +11 -14
  168. package/dist/lib/ai-model/shared/multimodal-prompt.js.map +1 -1
  169. package/dist/lib/ai-model/workflows/grounding/locate.js +6 -6
  170. package/dist/lib/ai-model/workflows/grounding/locate.js.map +1 -1
  171. package/dist/lib/ai-model/workflows/grounding/planning-action-locate.js +5 -5
  172. package/dist/lib/ai-model/workflows/grounding/planning-action-locate.js.map +1 -1
  173. package/dist/lib/ai-model/workflows/grounding/section-locate.js +5 -5
  174. package/dist/lib/ai-model/workflows/grounding/section-locate.js.map +1 -1
  175. package/dist/lib/ai-model/workflows/grounding/utils.js +3 -6
  176. package/dist/lib/ai-model/workflows/grounding/utils.js.map +1 -1
  177. package/dist/lib/ai-model/workflows/insight/extraction.js +8 -14
  178. package/dist/lib/ai-model/workflows/insight/extraction.js.map +1 -1
  179. package/dist/lib/ai-model/workflows/insight/order-sensitive.js.map +1 -1
  180. package/dist/lib/ai-model/workflows/planning/conversation-history.js +17 -9
  181. package/dist/lib/ai-model/workflows/planning/conversation-history.js.map +1 -1
  182. package/dist/lib/ai-model/workflows/planning/custom-planning.js +11 -13
  183. package/dist/lib/ai-model/workflows/planning/custom-planning.js.map +1 -1
  184. package/dist/lib/ai-model/workflows/planning/locate-normalization.js +5 -9
  185. package/dist/lib/ai-model/workflows/planning/locate-normalization.js.map +1 -1
  186. package/dist/lib/ai-model/workflows/planning/standard-planning.js +24 -27
  187. package/dist/lib/ai-model/workflows/planning/standard-planning.js.map +1 -1
  188. package/dist/lib/ai-model/workflows/recorder-generation/common.js +2 -4
  189. package/dist/lib/ai-model/workflows/recorder-generation/common.js.map +1 -1
  190. package/dist/lib/ai-model/workflows/recorder-generation/markdown.js +3 -5
  191. package/dist/lib/ai-model/workflows/recorder-generation/markdown.js.map +1 -1
  192. package/dist/lib/ai-model/workflows/recorder-generation/metadata.js +2 -4
  193. package/dist/lib/ai-model/workflows/recorder-generation/metadata.js.map +1 -1
  194. package/dist/lib/ai-model/workflows/recorder-generation/playwright.js.map +1 -1
  195. package/dist/lib/ai-model/workflows/recorder-generation/yaml.js +2 -4
  196. package/dist/lib/ai-model/workflows/recorder-generation/yaml.js.map +1 -1
  197. package/dist/lib/report-html-template.js +1 -1
  198. package/dist/lib/service/index.js +17 -26
  199. package/dist/lib/service/index.js.map +1 -1
  200. package/dist/lib/types.js.map +1 -1
  201. package/dist/lib/utils.js +1 -1
  202. package/dist/types/ai-model/connectivity/run-connectivity-test.d.ts.map +1 -1
  203. package/dist/types/ai-model/index.d.ts +1 -1
  204. package/dist/types/ai-model/index.d.ts.map +1 -1
  205. package/dist/types/ai-model/model-adapter/chat-completion.d.ts.map +1 -1
  206. package/dist/types/ai-model/model-adapter/default-locate-protocol.d.ts +2 -6
  207. package/dist/types/ai-model/model-adapter/default-locate-protocol.d.ts.map +1 -1
  208. package/dist/types/ai-model/model-adapter/locate.d.ts +1 -1
  209. package/dist/types/ai-model/model-adapter/locate.d.ts.map +1 -1
  210. package/dist/types/ai-model/model-adapter/resolve.d.ts +4 -2
  211. package/dist/types/ai-model/model-adapter/resolve.d.ts.map +1 -1
  212. package/dist/types/ai-model/model-adapter/responses.d.ts +4 -0
  213. package/dist/types/ai-model/model-adapter/responses.d.ts.map +1 -0
  214. package/dist/types/ai-model/model-adapter/temperature-with-semantic-retry.d.ts +6 -0
  215. package/dist/types/ai-model/model-adapter/temperature-with-semantic-retry.d.ts.map +1 -0
  216. package/dist/types/ai-model/model-adapter/types.d.ts +42 -20
  217. package/dist/types/ai-model/model-adapter/types.d.ts.map +1 -1
  218. package/dist/types/ai-model/models/gpt.d.ts +15 -3
  219. package/dist/types/ai-model/models/gpt.d.ts.map +1 -1
  220. package/dist/types/ai-model/models/qwen.d.ts +2 -1
  221. package/dist/types/ai-model/models/qwen.d.ts.map +1 -1
  222. package/dist/types/ai-model/models/registry.d.ts +16 -3
  223. package/dist/types/ai-model/models/registry.d.ts.map +1 -1
  224. package/dist/types/ai-model/service-caller/call-ai.d.ts +2 -2
  225. package/dist/types/ai-model/service-caller/call-ai.d.ts.map +1 -1
  226. package/dist/types/ai-model/service-caller/codex/call-codex.d.ts +4 -2
  227. package/dist/types/ai-model/service-caller/codex/call-codex.d.ts.map +1 -1
  228. package/dist/types/ai-model/service-caller/codex/codex-app-server.d.ts +5 -4
  229. package/dist/types/ai-model/service-caller/codex/codex-app-server.d.ts.map +1 -1
  230. package/dist/types/ai-model/service-caller/index.d.ts +0 -1
  231. package/dist/types/ai-model/service-caller/index.d.ts.map +1 -1
  232. package/dist/types/ai-model/service-caller/model-call.d.ts +6 -6
  233. package/dist/types/ai-model/service-caller/model-call.d.ts.map +1 -1
  234. package/dist/types/ai-model/service-caller/openai/call-openai.d.ts +9 -1
  235. package/dist/types/ai-model/service-caller/openai/call-openai.d.ts.map +1 -1
  236. package/dist/types/ai-model/service-caller/openai/chat-completion/chat-completion.d.ts +3 -4
  237. package/dist/types/ai-model/service-caller/openai/chat-completion/chat-completion.d.ts.map +1 -1
  238. package/dist/types/ai-model/service-caller/openai/chat-completion/non-stream.d.ts +1 -1
  239. package/dist/types/ai-model/service-caller/openai/chat-completion/non-stream.d.ts.map +1 -1
  240. package/dist/types/ai-model/service-caller/openai/chat-completion/stream.d.ts +1 -1
  241. package/dist/types/ai-model/service-caller/openai/chat-completion/stream.d.ts.map +1 -1
  242. package/dist/types/ai-model/service-caller/openai/chat-completion/types.d.ts +5 -5
  243. package/dist/types/ai-model/service-caller/openai/chat-completion/types.d.ts.map +1 -1
  244. package/dist/types/ai-model/service-caller/openai/chat-completion/utils.d.ts +5 -0
  245. package/dist/types/ai-model/service-caller/openai/chat-completion/utils.d.ts.map +1 -1
  246. package/dist/types/ai-model/service-caller/openai/openai-client.d.ts +2 -2
  247. package/dist/types/ai-model/service-caller/openai/openai-client.d.ts.map +1 -1
  248. package/dist/types/ai-model/service-caller/openai/responses/non-stream.d.ts +4 -0
  249. package/dist/types/ai-model/service-caller/openai/responses/non-stream.d.ts.map +1 -0
  250. package/dist/types/ai-model/service-caller/openai/responses/responses.d.ts +8 -0
  251. package/dist/types/ai-model/service-caller/openai/responses/responses.d.ts.map +1 -0
  252. package/dist/types/ai-model/service-caller/openai/responses/stream.d.ts +4 -0
  253. package/dist/types/ai-model/service-caller/openai/responses/stream.d.ts.map +1 -0
  254. package/dist/types/ai-model/service-caller/openai/responses/types.d.ts +8 -0
  255. package/dist/types/ai-model/service-caller/openai/responses/types.d.ts.map +1 -0
  256. package/dist/types/ai-model/service-caller/openai/responses/utils.d.ts +8 -0
  257. package/dist/types/ai-model/service-caller/openai/responses/utils.d.ts.map +1 -0
  258. package/dist/types/ai-model/service-caller/semantic-retry.d.ts +2 -2
  259. package/dist/types/ai-model/service-caller/semantic-retry.d.ts.map +1 -1
  260. package/dist/types/ai-model/service-caller/types.d.ts +35 -5
  261. package/dist/types/ai-model/service-caller/types.d.ts.map +1 -1
  262. package/dist/types/ai-model/service-caller/utils.d.ts +5 -9
  263. package/dist/types/ai-model/service-caller/utils.d.ts.map +1 -1
  264. package/dist/types/ai-model/shared/model-locate-result/factory.d.ts.map +1 -1
  265. package/dist/types/ai-model/shared/model-locate-result/prompt-spec.d.ts +4 -1
  266. package/dist/types/ai-model/shared/model-locate-result/prompt-spec.d.ts.map +1 -1
  267. package/dist/types/ai-model/shared/model-locate-result/result-field.d.ts +5 -0
  268. package/dist/types/ai-model/shared/model-locate-result/result-field.d.ts.map +1 -0
  269. package/dist/types/ai-model/shared/model-locate-result/types.d.ts +6 -0
  270. package/dist/types/ai-model/shared/model-locate-result/types.d.ts.map +1 -1
  271. package/dist/types/ai-model/shared/multimodal-prompt.d.ts +3 -3
  272. package/dist/types/ai-model/shared/multimodal-prompt.d.ts.map +1 -1
  273. package/dist/types/ai-model/workflows/grounding/planning-action-locate.d.ts.map +1 -1
  274. package/dist/types/ai-model/workflows/grounding/section-locate.d.ts +2 -1
  275. package/dist/types/ai-model/workflows/grounding/section-locate.d.ts.map +1 -1
  276. package/dist/types/ai-model/workflows/grounding/types.d.ts +3 -2
  277. package/dist/types/ai-model/workflows/grounding/types.d.ts.map +1 -1
  278. package/dist/types/ai-model/workflows/grounding/utils.d.ts +3 -3
  279. package/dist/types/ai-model/workflows/grounding/utils.d.ts.map +1 -1
  280. package/dist/types/ai-model/workflows/insight/extraction.d.ts +1 -1
  281. package/dist/types/ai-model/workflows/insight/extraction.d.ts.map +1 -1
  282. package/dist/types/ai-model/workflows/insight/order-sensitive.d.ts.map +1 -1
  283. package/dist/types/ai-model/workflows/planning/conversation-history.d.ts +10 -8
  284. package/dist/types/ai-model/workflows/planning/conversation-history.d.ts.map +1 -1
  285. package/dist/types/ai-model/workflows/planning/custom-planning.d.ts +2 -2
  286. package/dist/types/ai-model/workflows/planning/custom-planning.d.ts.map +1 -1
  287. package/dist/types/ai-model/workflows/planning/locate-normalization.d.ts +1 -2
  288. package/dist/types/ai-model/workflows/planning/locate-normalization.d.ts.map +1 -1
  289. package/dist/types/ai-model/workflows/planning/standard-planning.d.ts.map +1 -1
  290. package/dist/types/ai-model/workflows/recorder-generation/common.d.ts +2 -1
  291. package/dist/types/ai-model/workflows/recorder-generation/common.d.ts.map +1 -1
  292. package/dist/types/ai-model/workflows/recorder-generation/markdown.d.ts +2 -2
  293. package/dist/types/ai-model/workflows/recorder-generation/markdown.d.ts.map +1 -1
  294. package/dist/types/ai-model/workflows/recorder-generation/metadata.d.ts.map +1 -1
  295. package/dist/types/ai-model/workflows/recorder-generation/playwright.d.ts.map +1 -1
  296. package/dist/types/ai-model/workflows/recorder-generation/yaml.d.ts.map +1 -1
  297. package/dist/types/service/index.d.ts.map +1 -1
  298. package/dist/types/types.d.ts +11 -2
  299. package/dist/types/types.d.ts.map +1 -1
  300. package/package.json +2 -2
@@ -16,14 +16,21 @@ class ConversationHistory {
16
16
  resetPendingFeedbackMessageIfExists() {
17
17
  if (this.pendingFeedbackMessage) this.pendingFeedbackMessage = '';
18
18
  }
19
- append(message) {
20
- this.messages.push(message);
19
+ appendMessage(message) {
20
+ this.messages.push({
21
+ type: 'input-message',
22
+ message
23
+ });
24
+ }
25
+ appendModelOutput(output) {
26
+ this.messages.push({
27
+ type: 'model-output',
28
+ output
29
+ });
21
30
  }
22
31
  seed(messages) {
23
32
  this.reset();
24
- messages.forEach((message)=>{
25
- this.append(message);
26
- });
33
+ this.messages.push(...messages);
27
34
  }
28
35
  reset() {
29
36
  this.messages.length = 0;
@@ -39,11 +46,12 @@ class ConversationHistory {
39
46
  const clonedMessages = structuredClone(this.messages);
40
47
  let imageCount = 0;
41
48
  for(let i = clonedMessages.length - 1; i >= 0; i--){
42
- const message = clonedMessages[i];
43
- const content = message.content;
49
+ const entry = clonedMessages[i];
50
+ if ('input-message' !== entry.type) continue;
51
+ const content = entry.message.content;
44
52
  if (Array.isArray(content)) for(let j = 0; j < content.length; j++){
45
53
  const item = content[j];
46
- if ('image_url' === item.type) {
54
+ if ('image' === item.type) {
47
55
  imageCount++;
48
56
  if (imageCount > maxImages) content[j] = {
49
57
  type: 'text',
@@ -166,7 +174,7 @@ class ConversationHistory {
166
174
  };
167
175
  const recentMessages = this.messages.slice(-keepCount);
168
176
  this.messages.length = 0;
169
- this.messages.push(omittedPlaceholder);
177
+ this.appendMessage(omittedPlaceholder);
170
178
  for (const msg of recentMessages)this.messages.push(msg);
171
179
  return true;
172
180
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/workflows/planning/conversation-history.mjs","sources":["../../../../../src/ai-model/workflows/planning/conversation-history.ts"],"sourcesContent":["import type { SubGoal } from '@/types';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport { buildSubGoalsText } from '../../prompt/planning/sub-goals-text';\n\nexport interface ConversationHistoryOptions {\n initialMessages?: ChatCompletionMessageParam[];\n}\n\nexport class ConversationHistory {\n private readonly messages: ChatCompletionMessageParam[] = [];\n private subGoals: SubGoal[] = [];\n private memories: string[] = [];\n private historicalLogs: string[] = [];\n\n public pendingFeedbackMessage: string;\n\n constructor(options?: ConversationHistoryOptions) {\n if (options?.initialMessages?.length) {\n this.seed(options.initialMessages);\n }\n this.pendingFeedbackMessage = '';\n }\n\n resetPendingFeedbackMessageIfExists() {\n if (this.pendingFeedbackMessage) {\n this.pendingFeedbackMessage = '';\n }\n }\n\n append(message: ChatCompletionMessageParam) {\n this.messages.push(message);\n }\n\n seed(messages: ChatCompletionMessageParam[]) {\n this.reset();\n messages.forEach((message) => {\n this.append(message);\n });\n }\n\n reset() {\n this.messages.length = 0;\n this.memories.length = 0;\n this.subGoals.length = 0;\n this.historicalLogs.length = 0;\n this.pendingFeedbackMessage = '';\n }\n\n /**\n * Snapshot the conversation history, and replace the images with text if the number of images exceeds the limit.\n * @param maxImages - The maximum number of images to include in the snapshot. Undefined means no limit.\n * @returns The snapshot of the conversation history.\n */\n snapshot(maxImages?: number): ChatCompletionMessageParam[] {\n if (maxImages === undefined) {\n return [...this.messages];\n }\n\n const clonedMessages = structuredClone(this.messages);\n let imageCount = 0;\n\n // Traverse from the end to the beginning\n for (let i = clonedMessages.length - 1; i >= 0; i--) {\n const message = clonedMessages[i];\n const content = message.content;\n\n // Only process if content is an array\n if (Array.isArray(content)) {\n for (let j = 0; j < content.length; j++) {\n const item = content[j];\n\n // Check if this is an image\n if (item.type === 'image_url') {\n imageCount++;\n\n // If we've exceeded the limit, replace with text\n if (imageCount > maxImages) {\n content[j] = {\n type: 'text',\n text: '(image ignored due to size optimization)',\n };\n }\n }\n }\n }\n }\n\n return clonedMessages;\n }\n\n get length(): number {\n return this.messages.length;\n }\n\n [Symbol.iterator](): IterableIterator<ChatCompletionMessageParam> {\n return this.messages[Symbol.iterator]();\n }\n\n toJSON(): ChatCompletionMessageParam[] {\n return this.snapshot();\n }\n\n // Planning sub-goal management methods\n\n /**\n * Set all sub-goals, replacing any existing ones.\n * Automatically marks the first pending goal as running.\n */\n setSubGoals(subGoals: SubGoal[]): void {\n this.subGoals = subGoals.map((goal) => ({ ...goal }));\n this.markFirstPendingAsRunning();\n }\n\n /**\n * Merge sub-goals from update-plan-content.\n * Preserves existing descriptions when incoming description is empty.\n *\n * This handles compact XML updates like:\n * <sub-goal index=\"1\" status=\"finished\" />\n */\n mergeSubGoals(subGoals: SubGoal[]): void {\n if (this.subGoals.length === 0) {\n this.setSubGoals(subGoals);\n return;\n }\n\n const existingByIndex = new Map(\n this.subGoals.map((goal) => [goal.index, goal] as const),\n );\n\n const mergedSubGoals = subGoals.map((goal) => {\n const existingGoal = existingByIndex.get(goal.index);\n const hasNonEmptyDescription = goal.description.trim().length > 0;\n\n if (!existingGoal && !hasNonEmptyDescription) {\n return null;\n }\n\n return {\n ...goal,\n description:\n hasNonEmptyDescription || !existingGoal\n ? goal.description\n : existingGoal.description,\n };\n });\n\n const validSubGoals = mergedSubGoals.filter((goal) => goal !== null);\n if (validSubGoals.length === 0) {\n return;\n }\n\n this.setSubGoals(validSubGoals);\n }\n\n /**\n * Update a single sub-goal by index.\n * Clears logs if status or description actually changes.\n * @returns true if the sub-goal was found and updated, false otherwise\n */\n updateSubGoal(\n index: number,\n updates: Partial<Omit<SubGoal, 'index'>>,\n ): boolean {\n const goal = this.subGoals.find((g) => g.index === index);\n if (!goal) {\n return false;\n }\n\n let changed = false;\n\n if (updates.status !== undefined && updates.status !== goal.status) {\n goal.status = updates.status;\n changed = true;\n }\n if (\n updates.description !== undefined &&\n updates.description !== goal.description\n ) {\n goal.description = updates.description;\n changed = true;\n }\n\n if (changed) {\n goal.logs = [];\n }\n\n return true;\n }\n\n /**\n * Mark the first pending sub-goal as running.\n * Clears logs since status changes.\n */\n markFirstPendingAsRunning(): void {\n const firstPending = this.subGoals.find((g) => g.status === 'pending');\n if (firstPending) {\n firstPending.status = 'running';\n firstPending.logs = [];\n }\n }\n\n /**\n * Mark a sub-goal as finished.\n * Automatically marks the next pending goal as running.\n * @returns true if the sub-goal was found and updated, false otherwise\n */\n markSubGoalFinished(index: number): boolean {\n const result = this.updateSubGoal(index, { status: 'finished' });\n if (result) {\n this.markFirstPendingAsRunning();\n }\n return result;\n }\n\n /**\n * Mark all sub-goals as finished.\n * Clears logs for any goal whose status actually changes.\n */\n markAllSubGoalsFinished(): void {\n for (const goal of this.subGoals) {\n if (goal.status !== 'finished') {\n goal.logs = [];\n }\n goal.status = 'finished';\n }\n }\n\n /**\n * Append a log entry to the currently running sub-goal.\n * The log describes an action performed while working on the sub-goal.\n */\n appendSubGoalLog(log: string): void {\n if (!log) {\n return;\n }\n const runningGoal = this.subGoals.find((g) => g.status === 'running');\n if (runningGoal) {\n if (!runningGoal.logs) {\n runningGoal.logs = [];\n }\n runningGoal.logs.push(log);\n }\n }\n\n /**\n * Convert sub-goals to text representation.\n * Includes actions performed (logs) for the current sub-goal.\n */\n subGoalsToText(): string {\n return buildSubGoalsText(this.subGoals);\n }\n\n // Historical log management methods (used in non-deepThink mode)\n\n /**\n * Append a log entry to the historical logs list.\n * Used in non-deepThink mode to track executed steps across planning rounds.\n */\n appendHistoricalLog(log: string): void {\n if (log) {\n this.historicalLogs.push(log);\n }\n }\n\n /**\n * Convert historical logs to text representation.\n * Provides context about previously executed steps to the model.\n */\n historicalLogsToText(): string {\n if (this.historicalLogs.length === 0) {\n return '';\n }\n\n const logLines = this.historicalLogs.map((log) => `- ${log}`).join('\\n');\n return `Here are the steps that have been executed:\\n${logLines}`;\n }\n\n // Memory management methods\n\n /**\n * Append a memory to the memories list\n */\n appendMemory(memory: string): void {\n if (memory) {\n this.memories.push(memory);\n }\n }\n\n /**\n * Get all memories\n */\n getMemories(): string[] {\n return [...this.memories];\n }\n\n /**\n * Convert memories to text representation\n */\n memoriesToText(): string {\n if (this.memories.length === 0) {\n return '';\n }\n\n return `Memories from previous steps:\\n---\\n${this.memories.join('\\n---\\n')}\\n`;\n }\n\n /**\n * Clear all memories\n */\n clearMemories(): void {\n this.memories.length = 0;\n }\n\n /**\n * Compress the conversation history if it exceeds the threshold.\n * Removes the oldest messages and replaces them with a single placeholder message.\n * @param threshold - The number of messages that triggers compression.\n * @param keepCount - The number of recent messages to keep after compression.\n * @returns true if compression was performed, false otherwise.\n */\n compressHistory(threshold: number, keepCount: number): boolean {\n if (this.messages.length <= threshold) {\n return false;\n }\n\n const omittedCount = this.messages.length - keepCount;\n const omittedPlaceholder: ChatCompletionMessageParam = {\n role: 'user',\n content: `(${omittedCount} previous conversation messages have been omitted)`,\n };\n\n // Keep only the last `keepCount` messages\n const recentMessages = this.messages.slice(-keepCount);\n\n // Reset and rebuild with placeholder + recent messages\n this.messages.length = 0;\n this.messages.push(omittedPlaceholder);\n for (const msg of recentMessages) {\n this.messages.push(msg);\n }\n\n return true;\n }\n}\n"],"names":["Symbol","ConversationHistory","message","messages","maxImages","undefined","clonedMessages","structuredClone","imageCount","i","content","Array","j","item","subGoals","goal","existingByIndex","Map","mergedSubGoals","existingGoal","hasNonEmptyDescription","validSubGoals","index","updates","g","changed","firstPending","result","log","runningGoal","buildSubGoalsText","logLines","memory","threshold","keepCount","omittedCount","omittedPlaceholder","recentMessages","msg","options"],"mappings":"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"}
1
+ {"version":3,"file":"ai-model/workflows/planning/conversation-history.mjs","sources":["../../../../../src/ai-model/workflows/planning/conversation-history.ts"],"sourcesContent":["import type { ConversationMessage } from '@/ai-model/service-caller/types';\nimport type { RawAssistantOutput, SubGoal } from '@/types';\nimport { buildSubGoalsText } from '../../prompt/planning/sub-goals-text';\nimport type { ConversationEntry } from '../../service-caller/types';\n\nexport interface ConversationHistoryOptions {\n initialMessages?: ConversationEntry[];\n}\n\nexport class ConversationHistory {\n private readonly messages: ConversationEntry[] = [];\n private subGoals: SubGoal[] = [];\n private memories: string[] = [];\n private historicalLogs: string[] = [];\n\n public pendingFeedbackMessage: string;\n\n constructor(options?: ConversationHistoryOptions) {\n if (options?.initialMessages?.length) {\n this.seed(options.initialMessages);\n }\n this.pendingFeedbackMessage = '';\n }\n\n resetPendingFeedbackMessageIfExists() {\n if (this.pendingFeedbackMessage) {\n this.pendingFeedbackMessage = '';\n }\n }\n\n appendMessage(message: ConversationMessage) {\n this.messages.push({ type: 'input-message', message });\n }\n\n appendModelOutput(output: RawAssistantOutput) {\n this.messages.push({ type: 'model-output', output });\n }\n\n seed(messages: ConversationEntry[]) {\n this.reset();\n this.messages.push(...messages);\n }\n\n reset() {\n this.messages.length = 0;\n this.memories.length = 0;\n this.subGoals.length = 0;\n this.historicalLogs.length = 0;\n this.pendingFeedbackMessage = '';\n }\n\n /**\n * Snapshot the conversation history, and replace the images with text if the number of images exceeds the limit.\n * @param maxImages - The maximum number of images to include in the snapshot. Undefined means no limit.\n * @returns The snapshot of the conversation history.\n */\n snapshot(maxImages?: number): ConversationEntry[] {\n if (maxImages === undefined) {\n return [...this.messages];\n }\n\n const clonedMessages = structuredClone(this.messages);\n let imageCount = 0;\n\n // Traverse from the end to the beginning\n for (let i = clonedMessages.length - 1; i >= 0; i--) {\n const entry = clonedMessages[i];\n if (entry.type !== 'input-message') {\n continue;\n }\n const content = entry.message.content;\n\n // Only process if content is an array\n if (Array.isArray(content)) {\n for (let j = 0; j < content.length; j++) {\n const item = content[j];\n\n // Check if this is an image\n if (item.type === 'image') {\n imageCount++;\n\n // If we've exceeded the limit, replace with text\n if (imageCount > maxImages) {\n content[j] = {\n type: 'text',\n text: '(image ignored due to size optimization)',\n };\n }\n }\n }\n }\n }\n\n return clonedMessages;\n }\n\n get length(): number {\n return this.messages.length;\n }\n\n [Symbol.iterator](): IterableIterator<ConversationEntry> {\n return this.messages[Symbol.iterator]();\n }\n\n toJSON(): ConversationEntry[] {\n return this.snapshot();\n }\n\n // Planning sub-goal management methods\n\n /**\n * Set all sub-goals, replacing any existing ones.\n * Automatically marks the first pending goal as running.\n */\n setSubGoals(subGoals: SubGoal[]): void {\n this.subGoals = subGoals.map((goal) => ({ ...goal }));\n this.markFirstPendingAsRunning();\n }\n\n /**\n * Merge sub-goals from update-plan-content.\n * Preserves existing descriptions when incoming description is empty.\n *\n * This handles compact XML updates like:\n * <sub-goal index=\"1\" status=\"finished\" />\n */\n mergeSubGoals(subGoals: SubGoal[]): void {\n if (this.subGoals.length === 0) {\n this.setSubGoals(subGoals);\n return;\n }\n\n const existingByIndex = new Map(\n this.subGoals.map((goal) => [goal.index, goal] as const),\n );\n\n const mergedSubGoals = subGoals.map((goal) => {\n const existingGoal = existingByIndex.get(goal.index);\n const hasNonEmptyDescription = goal.description.trim().length > 0;\n\n if (!existingGoal && !hasNonEmptyDescription) {\n return null;\n }\n\n return {\n ...goal,\n description:\n hasNonEmptyDescription || !existingGoal\n ? goal.description\n : existingGoal.description,\n };\n });\n\n const validSubGoals = mergedSubGoals.filter((goal) => goal !== null);\n if (validSubGoals.length === 0) {\n return;\n }\n\n this.setSubGoals(validSubGoals);\n }\n\n /**\n * Update a single sub-goal by index.\n * Clears logs if status or description actually changes.\n * @returns true if the sub-goal was found and updated, false otherwise\n */\n updateSubGoal(\n index: number,\n updates: Partial<Omit<SubGoal, 'index'>>,\n ): boolean {\n const goal = this.subGoals.find((g) => g.index === index);\n if (!goal) {\n return false;\n }\n\n let changed = false;\n\n if (updates.status !== undefined && updates.status !== goal.status) {\n goal.status = updates.status;\n changed = true;\n }\n if (\n updates.description !== undefined &&\n updates.description !== goal.description\n ) {\n goal.description = updates.description;\n changed = true;\n }\n\n if (changed) {\n goal.logs = [];\n }\n\n return true;\n }\n\n /**\n * Mark the first pending sub-goal as running.\n * Clears logs since status changes.\n */\n markFirstPendingAsRunning(): void {\n const firstPending = this.subGoals.find((g) => g.status === 'pending');\n if (firstPending) {\n firstPending.status = 'running';\n firstPending.logs = [];\n }\n }\n\n /**\n * Mark a sub-goal as finished.\n * Automatically marks the next pending goal as running.\n * @returns true if the sub-goal was found and updated, false otherwise\n */\n markSubGoalFinished(index: number): boolean {\n const result = this.updateSubGoal(index, { status: 'finished' });\n if (result) {\n this.markFirstPendingAsRunning();\n }\n return result;\n }\n\n /**\n * Mark all sub-goals as finished.\n * Clears logs for any goal whose status actually changes.\n */\n markAllSubGoalsFinished(): void {\n for (const goal of this.subGoals) {\n if (goal.status !== 'finished') {\n goal.logs = [];\n }\n goal.status = 'finished';\n }\n }\n\n /**\n * Append a log entry to the currently running sub-goal.\n * The log describes an action performed while working on the sub-goal.\n */\n appendSubGoalLog(log: string): void {\n if (!log) {\n return;\n }\n const runningGoal = this.subGoals.find((g) => g.status === 'running');\n if (runningGoal) {\n if (!runningGoal.logs) {\n runningGoal.logs = [];\n }\n runningGoal.logs.push(log);\n }\n }\n\n /**\n * Convert sub-goals to text representation.\n * Includes actions performed (logs) for the current sub-goal.\n */\n subGoalsToText(): string {\n return buildSubGoalsText(this.subGoals);\n }\n\n // Historical log management methods (used in non-deepThink mode)\n\n /**\n * Append a log entry to the historical logs list.\n * Used in non-deepThink mode to track executed steps across planning rounds.\n */\n appendHistoricalLog(log: string): void {\n if (log) {\n this.historicalLogs.push(log);\n }\n }\n\n /**\n * Convert historical logs to text representation.\n * Provides context about previously executed steps to the model.\n */\n historicalLogsToText(): string {\n if (this.historicalLogs.length === 0) {\n return '';\n }\n\n const logLines = this.historicalLogs.map((log) => `- ${log}`).join('\\n');\n return `Here are the steps that have been executed:\\n${logLines}`;\n }\n\n // Memory management methods\n\n /**\n * Append a memory to the memories list\n */\n appendMemory(memory: string): void {\n if (memory) {\n this.memories.push(memory);\n }\n }\n\n /**\n * Get all memories\n */\n getMemories(): string[] {\n return [...this.memories];\n }\n\n /**\n * Convert memories to text representation\n */\n memoriesToText(): string {\n if (this.memories.length === 0) {\n return '';\n }\n\n return `Memories from previous steps:\\n---\\n${this.memories.join('\\n---\\n')}\\n`;\n }\n\n /**\n * Clear all memories\n */\n clearMemories(): void {\n this.memories.length = 0;\n }\n\n /**\n * Compress the conversation history if it exceeds the threshold.\n * Removes the oldest messages and replaces them with a single placeholder message.\n * @param threshold - The number of messages that triggers compression.\n * @param keepCount - The number of recent messages to keep after compression.\n * @returns true if compression was performed, false otherwise.\n */\n compressHistory(threshold: number, keepCount: number): boolean {\n if (this.messages.length <= threshold) {\n return false;\n }\n\n const omittedCount = this.messages.length - keepCount;\n const omittedPlaceholder: ConversationMessage = {\n role: 'user',\n content: `(${omittedCount} previous conversation messages have been omitted)`,\n };\n\n // Keep only the last `keepCount` messages\n const recentMessages = this.messages.slice(-keepCount);\n\n // Reset and rebuild with placeholder + recent messages\n this.messages.length = 0;\n this.appendMessage(omittedPlaceholder);\n for (const msg of recentMessages) {\n this.messages.push(msg);\n }\n\n return true;\n }\n}\n"],"names":["Symbol","ConversationHistory","message","output","messages","maxImages","undefined","clonedMessages","structuredClone","imageCount","i","entry","content","Array","j","item","subGoals","goal","existingByIndex","Map","mergedSubGoals","existingGoal","hasNonEmptyDescription","validSubGoals","index","updates","g","changed","firstPending","result","log","runningGoal","buildSubGoalsText","logLines","memory","threshold","keepCount","omittedCount","omittedPlaceholder","recentMessages","msg","options"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { ScreenshotItem } from "../../../screenshot-item.mjs";
2
2
  import { prepareModelImage } from "../../model-adapter/image-preprocess.mjs";
3
3
  import { AIResponseParseError, callAIWithStringResponse } from "../../service-caller/index.mjs";
4
- import { preparedReferenceImagesToChatMessages } from "../../shared/multimodal-prompt.mjs";
4
+ import { preparedReferenceImagesToMessages } from "../../shared/multimodal-prompt.mjs";
5
5
  import { normalizePlanningActionLocateFields } from "./locate-normalization.mjs";
6
6
  function appendActionContext(systemPrompt, actionContext) {
7
7
  return systemPrompt + (actionContext ? `${actionContext}\n` : '');
@@ -12,9 +12,9 @@ function buildCustomPlanningMessages(input, config) {
12
12
  const systemPrompt = appendActionContext(config.buildSystemPrompt(), actionContext);
13
13
  const userInstructionText = input.userInstruction.text;
14
14
  const userInstruction = config.buildUserInstruction ? config.buildUserInstruction(userInstructionText) : userInstructionText;
15
- const referenceImageMessages = preparedReferenceImagesToChatMessages(input.userInstruction.referenceImages);
15
+ const referenceImageMessages = preparedReferenceImagesToMessages(input.userInstruction.referenceImages);
16
16
  if (conversationHistory.pendingFeedbackMessage) {
17
- conversationHistory.append({
17
+ conversationHistory.appendMessage({
18
18
  role: 'user',
19
19
  content: [
20
20
  {
@@ -25,14 +25,12 @@ function buildCustomPlanningMessages(input, config) {
25
25
  });
26
26
  conversationHistory.resetPendingFeedbackMessageIfExists();
27
27
  }
28
- conversationHistory.append({
28
+ conversationHistory.appendMessage({
29
29
  role: 'user',
30
30
  content: [
31
31
  {
32
- type: 'image_url',
33
- image_url: {
34
- url: context.screenshot.base64
35
- }
32
+ type: 'image',
33
+ url: context.screenshot.base64
36
34
  }
37
35
  ]
38
36
  });
@@ -84,7 +82,7 @@ async function runCustomPlanning(userInstruction, options, config) {
84
82
  coordinateSystem: config.coordinateSystem
85
83
  };
86
84
  const messages = buildCustomPlanningMessages(input, config.messages);
87
- const { content, usage, rawChoiceMessage } = await callAIWithStringResponse(messages, preparedOptions.modelRuntime, {
85
+ const { content, usage, rawAssistantOutput } = await callAIWithStringResponse(messages, preparedOptions.modelRuntime, {
88
86
  abortSignal: preparedOptions.abortSignal,
89
87
  requiresOriginalImageDetail: preparedOptions.includeLocateInPlanning
90
88
  });
@@ -101,16 +99,16 @@ async function runCustomPlanning(userInstruction, options, config) {
101
99
  locateResultContext: {
102
100
  preparedSize: preparedImage.preparedSize,
103
101
  contentSize: preparedImage.contentSize
104
- },
105
- acceptBbox2dAlias: preparedOptions.modelRuntime.adapter.acceptBbox2dAlias
102
+ }
106
103
  });
107
104
  shouldContinuePlanning = config.shouldContinuePlanning(parsed, actions);
108
105
  } catch (parseError) {
109
106
  const errorMessage = `Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`;
110
- throw new AIResponseParseError(errorMessage, JSON.stringify(content, void 0, 2), usage, rawChoiceMessage);
107
+ throw new AIResponseParseError(errorMessage, JSON.stringify(content, void 0, 2), usage, rawAssistantOutput);
111
108
  }
112
109
  const assistantContent = config.messages.buildAssistantContent?.(parsed, content, input);
113
- if (assistantContent) options.conversationHistory.append({
110
+ if (rawAssistantOutput?.type === 'responses' && options.modelRuntime.adapter.responses.replayRawAssistantOutput) options.conversationHistory.appendModelOutput(rawAssistantOutput);
111
+ else if (assistantContent) options.conversationHistory.appendMessage({
114
112
  role: 'assistant',
115
113
  content: assistantContent
116
114
  });
@@ -120,7 +118,7 @@ async function runCustomPlanning(userInstruction, options, config) {
120
118
  usage,
121
119
  shouldContinuePlanning,
122
120
  rawResponse: JSON.stringify(content, void 0, 2),
123
- rawChoiceMessage
121
+ rawAssistantOutput
124
122
  };
125
123
  }
126
124
  export { buildCustomPlanningMessages, runCustomPlanning };
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/workflows/planning/custom-planning.mjs","sources":["../../../../../src/ai-model/workflows/planning/custom-planning.ts"],"sourcesContent":["import type { PlanningAIResponse, PlanningAction } from '@/types';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport { ScreenshotItem } from '../../../screenshot-item';\nimport type {\n CustomPlanningInput,\n CustomPlanningMessageConfig,\n ResolvedCustomPlanningDefinition,\n} from '../../model-adapter/custom-planning-types';\nimport { prepareModelImage } from '../../model-adapter/image-preprocess';\nimport {\n AIResponseParseError,\n callAIWithStringResponse,\n} from '../../service-caller/index';\nimport {\n type PreparedUserPrompt,\n preparedReferenceImagesToChatMessages,\n} from '../../shared/multimodal-prompt';\nimport { normalizePlanningActionLocateFields } from './locate-normalization';\nimport type { PlanOptions } from './types';\n\nfunction appendActionContext(\n systemPrompt: string,\n actionContext?: string,\n): string {\n return systemPrompt + (actionContext ? `${actionContext}\\n` : '');\n}\n\nexport function buildCustomPlanningMessages<TParsed>(\n input: CustomPlanningInput,\n config: CustomPlanningMessageConfig<TParsed>,\n): ChatCompletionMessageParam[] {\n const { options } = input;\n const { conversationHistory, context, actionContext } = options;\n const systemPrompt = appendActionContext(\n config.buildSystemPrompt(),\n actionContext,\n );\n const userInstructionText = input.userInstruction.text;\n const userInstruction = config.buildUserInstruction\n ? config.buildUserInstruction(userInstructionText)\n : userInstructionText;\n const referenceImageMessages = preparedReferenceImagesToChatMessages(\n input.userInstruction.referenceImages,\n );\n\n if (conversationHistory.pendingFeedbackMessage) {\n conversationHistory.append({\n role: 'user',\n content: [\n {\n type: 'text',\n text: `${conversationHistory.pendingFeedbackMessage}. The previous action has been executed, here is the latest screenshot. Please continue according to the instruction.`,\n },\n ],\n });\n conversationHistory.resetPendingFeedbackMessageIfExists();\n }\n\n conversationHistory.append({\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: { url: context.screenshot.base64 },\n },\n ],\n });\n\n if (config.systemPromptPlacement === 'system-message') {\n return [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [{ type: 'text', text: userInstruction }],\n },\n ...referenceImageMessages,\n ...conversationHistory.snapshot(config.historyImageLimit),\n ];\n }\n\n return [\n {\n role: 'user',\n content: `${systemPrompt}${userInstruction}`,\n },\n ...referenceImageMessages,\n ...conversationHistory.snapshot(config.historyImageLimit),\n ];\n}\n\nexport async function runCustomPlanning<TParsed>(\n userInstruction: PreparedUserPrompt,\n options: PlanOptions,\n config: ResolvedCustomPlanningDefinition<TParsed>,\n): Promise<PlanningAIResponse> {\n const { context } = options;\n const preparedImage = await prepareModelImage({\n imageBase64: context.screenshot.base64,\n width: context.shotSize.width,\n height: context.shotSize.height,\n policy: options.modelRuntime.adapter.imagePreprocess,\n });\n const preparedOptions: PlanOptions = {\n ...options,\n context: {\n ...context,\n screenshot: ScreenshotItem.create(\n preparedImage.imageBase64,\n context.screenshot.capturedAt,\n ),\n shotSize: preparedImage.preparedSize,\n },\n };\n const input: CustomPlanningInput = {\n userInstruction,\n options: preparedOptions,\n coordinateSystem: config.coordinateSystem,\n };\n\n const messages = buildCustomPlanningMessages(input, config.messages);\n const { content, usage, rawChoiceMessage } = await callAIWithStringResponse(\n messages,\n preparedOptions.modelRuntime,\n {\n abortSignal: preparedOptions.abortSignal,\n requiresOriginalImageDetail: preparedOptions.includeLocateInPlanning,\n },\n );\n\n let parsed: TParsed;\n let actions: PlanningAction[];\n let shouldContinuePlanning: boolean;\n\n try {\n parsed = config.parseResponse(content, input);\n actions = config.transformActions(parsed, input);\n normalizePlanningActionLocateFields(actions, {\n actionSpace: preparedOptions.actionSpace,\n includeLocateInPlanning: preparedOptions.includeLocateInPlanning,\n locateResultCodec: config.coordinateNormalizer,\n locateResultContext: {\n preparedSize: preparedImage.preparedSize,\n contentSize: preparedImage.contentSize,\n },\n acceptBbox2dAlias: preparedOptions.modelRuntime.adapter.acceptBbox2dAlias,\n });\n shouldContinuePlanning = config.shouldContinuePlanning(parsed, actions);\n } catch (parseError) {\n const errorMessage = `Parse error: ${\n parseError instanceof Error ? parseError.message : String(parseError)\n }`;\n throw new AIResponseParseError(\n errorMessage,\n JSON.stringify(content, undefined, 2),\n usage,\n rawChoiceMessage,\n );\n }\n\n const assistantContent = config.messages.buildAssistantContent?.(\n parsed,\n content,\n input,\n );\n // UI-TARS and Auto-GLM define their own assistant history format.\n if (assistantContent) {\n options.conversationHistory.append({\n role: 'assistant',\n content: assistantContent,\n });\n }\n\n return {\n actions,\n log: config.buildResponseLog(parsed, content),\n usage,\n shouldContinuePlanning,\n rawResponse: JSON.stringify(content, undefined, 2),\n rawChoiceMessage,\n };\n}\n"],"names":["appendActionContext","systemPrompt","actionContext","buildCustomPlanningMessages","input","config","options","conversationHistory","context","userInstructionText","userInstruction","referenceImageMessages","preparedReferenceImagesToChatMessages","runCustomPlanning","preparedImage","prepareModelImage","preparedOptions","ScreenshotItem","messages","content","usage","rawChoiceMessage","callAIWithStringResponse","parsed","actions","shouldContinuePlanning","normalizePlanningActionLocateFields","parseError","errorMessage","Error","String","AIResponseParseError","JSON","undefined","assistantContent"],"mappings":"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"}
1
+ {"version":3,"file":"ai-model/workflows/planning/custom-planning.mjs","sources":["../../../../../src/ai-model/workflows/planning/custom-planning.ts"],"sourcesContent":["import type { PlanningAIResponse, PlanningAction } from '@/types';\nimport { ScreenshotItem } from '../../../screenshot-item';\nimport type {\n CustomPlanningInput,\n CustomPlanningMessageConfig,\n ResolvedCustomPlanningDefinition,\n} from '../../model-adapter/custom-planning-types';\nimport { prepareModelImage } from '../../model-adapter/image-preprocess';\nimport {\n AIResponseParseError,\n callAIWithStringResponse,\n} from '../../service-caller/index';\nimport type { ModelCallMessages } from '../../service-caller/types';\nimport {\n type PreparedUserPrompt,\n preparedReferenceImagesToMessages,\n} from '../../shared/multimodal-prompt';\nimport { normalizePlanningActionLocateFields } from './locate-normalization';\nimport type { PlanOptions } from './types';\n\nfunction appendActionContext(\n systemPrompt: string,\n actionContext?: string,\n): string {\n return systemPrompt + (actionContext ? `${actionContext}\\n` : '');\n}\n\nexport function buildCustomPlanningMessages<TParsed>(\n input: CustomPlanningInput,\n config: CustomPlanningMessageConfig<TParsed>,\n): ModelCallMessages {\n const { options } = input;\n const { conversationHistory, context, actionContext } = options;\n const systemPrompt = appendActionContext(\n config.buildSystemPrompt(),\n actionContext,\n );\n const userInstructionText = input.userInstruction.text;\n const userInstruction = config.buildUserInstruction\n ? config.buildUserInstruction(userInstructionText)\n : userInstructionText;\n const referenceImageMessages = preparedReferenceImagesToMessages(\n input.userInstruction.referenceImages,\n );\n\n if (conversationHistory.pendingFeedbackMessage) {\n conversationHistory.appendMessage({\n role: 'user',\n content: [\n {\n type: 'text',\n text: `${conversationHistory.pendingFeedbackMessage}. The previous action has been executed, here is the latest screenshot. Please continue according to the instruction.`,\n },\n ],\n });\n conversationHistory.resetPendingFeedbackMessageIfExists();\n }\n\n conversationHistory.appendMessage({\n role: 'user',\n content: [\n {\n type: 'image',\n url: context.screenshot.base64,\n },\n ],\n });\n\n if (config.systemPromptPlacement === 'system-message') {\n return [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [{ type: 'text', text: userInstruction }],\n },\n ...referenceImageMessages,\n ...conversationHistory.snapshot(config.historyImageLimit),\n ];\n }\n\n return [\n {\n role: 'user',\n content: `${systemPrompt}${userInstruction}`,\n },\n ...referenceImageMessages,\n ...conversationHistory.snapshot(config.historyImageLimit),\n ];\n}\n\nexport async function runCustomPlanning<TParsed>(\n userInstruction: PreparedUserPrompt,\n options: PlanOptions,\n config: ResolvedCustomPlanningDefinition<TParsed>,\n): Promise<PlanningAIResponse> {\n const { context } = options;\n const preparedImage = await prepareModelImage({\n imageBase64: context.screenshot.base64,\n width: context.shotSize.width,\n height: context.shotSize.height,\n policy: options.modelRuntime.adapter.imagePreprocess,\n });\n const preparedOptions: PlanOptions = {\n ...options,\n context: {\n ...context,\n screenshot: ScreenshotItem.create(\n preparedImage.imageBase64,\n context.screenshot.capturedAt,\n ),\n shotSize: preparedImage.preparedSize,\n },\n };\n const input: CustomPlanningInput = {\n userInstruction,\n options: preparedOptions,\n coordinateSystem: config.coordinateSystem,\n };\n\n const messages = buildCustomPlanningMessages(input, config.messages);\n const { content, usage, rawAssistantOutput } = await callAIWithStringResponse(\n messages,\n preparedOptions.modelRuntime,\n {\n abortSignal: preparedOptions.abortSignal,\n requiresOriginalImageDetail: preparedOptions.includeLocateInPlanning,\n },\n );\n\n let parsed: TParsed;\n let actions: PlanningAction[];\n let shouldContinuePlanning: boolean;\n\n try {\n parsed = config.parseResponse(content, input);\n actions = config.transformActions(parsed, input);\n normalizePlanningActionLocateFields(actions, {\n actionSpace: preparedOptions.actionSpace,\n includeLocateInPlanning: preparedOptions.includeLocateInPlanning,\n locateResultCodec: config.coordinateNormalizer,\n locateResultContext: {\n preparedSize: preparedImage.preparedSize,\n contentSize: preparedImage.contentSize,\n },\n });\n shouldContinuePlanning = config.shouldContinuePlanning(parsed, actions);\n } catch (parseError) {\n const errorMessage = `Parse error: ${\n parseError instanceof Error ? parseError.message : String(parseError)\n }`;\n throw new AIResponseParseError(\n errorMessage,\n JSON.stringify(content, undefined, 2),\n usage,\n rawAssistantOutput,\n );\n }\n\n const assistantContent = config.messages.buildAssistantContent?.(\n parsed,\n content,\n input,\n );\n // UI-TARS and Auto-GLM define their own assistant history format.\n if (\n rawAssistantOutput?.type === 'responses' &&\n options.modelRuntime.adapter.responses.replayRawAssistantOutput\n ) {\n options.conversationHistory.appendModelOutput(rawAssistantOutput);\n } else if (assistantContent) {\n options.conversationHistory.appendMessage({\n role: 'assistant',\n content: assistantContent,\n });\n }\n\n return {\n actions,\n log: config.buildResponseLog(parsed, content),\n usage,\n shouldContinuePlanning,\n rawResponse: JSON.stringify(content, undefined, 2),\n rawAssistantOutput,\n };\n}\n"],"names":["appendActionContext","systemPrompt","actionContext","buildCustomPlanningMessages","input","config","options","conversationHistory","context","userInstructionText","userInstruction","referenceImageMessages","preparedReferenceImagesToMessages","runCustomPlanning","preparedImage","prepareModelImage","preparedOptions","ScreenshotItem","messages","content","usage","rawAssistantOutput","callAIWithStringResponse","parsed","actions","shouldContinuePlanning","normalizePlanningActionLocateFields","parseError","errorMessage","Error","String","AIResponseParseError","JSON","undefined","assistantContent"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { findAllMidsceneLocatorField } from "../../../common.mjs";
2
2
  import { getDebug } from "@midscene/shared/logger";
3
3
  import { assert } from "@midscene/shared/utils";
4
+ import { locateResultKeys, readLocateResultField } from "../../shared/model-locate-result/result-field.mjs";
4
5
  const debug = getDebug('planning');
5
6
  function normalizePlanningActionLocateFields(actions, { actionSpace, ...options }) {
6
7
  actions.forEach((action)=>{
@@ -16,19 +17,14 @@ function normalizePlanningActionLocateFields(actions, { actionSpace, ...options
16
17
  });
17
18
  });
18
19
  }
19
- function normalizePlanningLocateParameter(locateParameter, { includeLocateInPlanning, locateResultCodec, locateResultContext, acceptBbox2dAlias = false }) {
20
+ function normalizePlanningLocateParameter(locateParameter, { includeLocateInPlanning, locateResultCodec, locateResultContext }) {
20
21
  if (!includeLocateInPlanning) return {
21
22
  prompt: locateParameter.prompt
22
23
  };
23
24
  assert(locateResultCodec, 'planning locate normalization requires a locate result codec');
24
- const resultKey = locateResultCodec.promptSpec.resultKey;
25
- const rawLocateValue = void 0 !== locateParameter[resultKey] ? locateParameter[resultKey] : acceptBbox2dAlias && 'bbox' === resultKey ? locateParameter.bbox_2d : void 0;
26
- const rawCoordinateKeys = new Set([
27
- resultKey,
28
- ...acceptBbox2dAlias && 'bbox' === resultKey ? [
29
- 'bbox_2d'
30
- ] : []
31
- ]);
25
+ const { promptSpec } = locateResultCodec;
26
+ const rawLocateValue = readLocateResultField(locateParameter, promptSpec);
27
+ const rawCoordinateKeys = new Set(locateResultKeys(promptSpec));
32
28
  const locateParamWithoutRawCoordinates = Object.fromEntries(Object.entries(locateParameter).filter(([key])=>!rawCoordinateKeys.has(key)));
33
29
  const result = locateResultCodec.toPixelResult(rawLocateValue, locateResultContext);
34
30
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/workflows/planning/locate-normalization.mjs","sources":["../../../../../src/ai-model/workflows/planning/locate-normalization.ts"],"sourcesContent":["import { findAllMidsceneLocatorField } from '@/common';\nimport type { DeviceAction } from '@/device';\nimport type { PlanningAction } from '@/types';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { ParsedPlanningLocateParameter } from '../../model-adapter/planning-protocol';\nimport type {\n LocateResultCodec,\n LocateResultContext,\n} from '../../shared/model-locate-result/types';\n\nconst debug = getDebug('planning');\n\nexport function normalizePlanningActionLocateFields(\n actions: PlanningAction[],\n {\n actionSpace,\n ...options\n }: PlanningLocateNormalizationOptions & {\n actionSpace: DeviceAction[];\n },\n): void {\n actions.forEach((action) => {\n const actionInActionSpace = actionSpace.find(\n (actionInSpace) => actionInSpace.name === action.type,\n );\n if (!actionInActionSpace) {\n debug('skip locate normalization for action outside actionSpace', action);\n return;\n }\n\n debug('actionInActionSpace matched', actionInActionSpace);\n const locateFields = findAllMidsceneLocatorField(\n actionInActionSpace.paramSchema,\n );\n\n debug('locateFields', locateFields);\n\n locateFields.forEach((field) => {\n const locateParameter = action.param?.[field];\n if (!locateParameter) {\n return;\n }\n\n action.param[field] = normalizePlanningLocateParameter(\n locateParameter,\n options,\n );\n });\n });\n}\n\nexport type PlanningLocateNormalizationOptions = {\n includeLocateInPlanning: boolean;\n locateResultCodec?: LocateResultCodec;\n locateResultContext: LocateResultContext;\n acceptBbox2dAlias?: boolean;\n};\n\nexport function normalizePlanningLocateParameter(\n locateParameter: ParsedPlanningLocateParameter,\n {\n includeLocateInPlanning,\n locateResultCodec,\n locateResultContext,\n acceptBbox2dAlias = false,\n }: PlanningLocateNormalizationOptions,\n): Record<string, unknown> {\n if (!includeLocateInPlanning) {\n // In prompt-only planning mode, ignore any accidental coordinates from the model.\n return { prompt: locateParameter.prompt };\n }\n\n assert(\n locateResultCodec,\n 'planning locate normalization requires a locate result codec',\n );\n\n const resultKey = locateResultCodec.promptSpec.resultKey;\n const rawLocateValue =\n locateParameter[resultKey] !== undefined\n ? locateParameter[resultKey]\n : acceptBbox2dAlias && resultKey === 'bbox'\n ? locateParameter.bbox_2d\n : undefined;\n\n // The raw result field is replaced by locatedPixelResult, so it should not\n // remain in the normalized locate parameter.\n const rawCoordinateKeys = new Set([\n resultKey,\n ...(acceptBbox2dAlias && resultKey === 'bbox' ? ['bbox_2d'] : []),\n ]);\n\n const locateParamWithoutRawCoordinates = Object.fromEntries(\n Object.entries(locateParameter).filter(\n ([key]) => !rawCoordinateKeys.has(key),\n ),\n );\n\n const result = locateResultCodec.toPixelResult(\n rawLocateValue,\n locateResultContext,\n );\n return {\n ...locateParamWithoutRawCoordinates,\n locatedPixelResult: result,\n };\n}\n"],"names":["debug","getDebug","normalizePlanningActionLocateFields","actions","actionSpace","options","action","actionInActionSpace","actionInSpace","locateFields","findAllMidsceneLocatorField","field","locateParameter","normalizePlanningLocateParameter","includeLocateInPlanning","locateResultCodec","locateResultContext","acceptBbox2dAlias","assert","resultKey","rawLocateValue","undefined","rawCoordinateKeys","Set","locateParamWithoutRawCoordinates","Object","key","result"],"mappings":";;;AAWA,MAAMA,QAAQC,SAAS;AAEhB,SAASC,oCACdC,OAAyB,EACzB,EACEC,WAAW,EACX,GAAGC,SAGJ;IAEDF,QAAQ,OAAO,CAAC,CAACG;QACf,MAAMC,sBAAsBH,YAAY,IAAI,CAC1C,CAACI,gBAAkBA,cAAc,IAAI,KAAKF,OAAO,IAAI;QAEvD,IAAI,CAACC,qBAAqB,YACxBP,MAAM,4DAA4DM;QAIpEN,MAAM,+BAA+BO;QACrC,MAAME,eAAeC,4BACnBH,oBAAoB,WAAW;QAGjCP,MAAM,gBAAgBS;QAEtBA,aAAa,OAAO,CAAC,CAACE;YACpB,MAAMC,kBAAkBN,OAAO,KAAK,EAAE,CAACK,MAAM;YAC7C,IAAI,CAACC,iBACH;YAGFN,OAAO,KAAK,CAACK,MAAM,GAAGE,iCACpBD,iBACAP;QAEJ;IACF;AACF;AASO,SAASQ,iCACdD,eAA8C,EAC9C,EACEE,uBAAuB,EACvBC,iBAAiB,EACjBC,mBAAmB,EACnBC,oBAAoB,KAAK,EACU;IAErC,IAAI,CAACH,yBAEH,OAAO;QAAE,QAAQF,gBAAgB,MAAM;IAAC;IAG1CM,OACEH,mBACA;IAGF,MAAMI,YAAYJ,kBAAkB,UAAU,CAAC,SAAS;IACxD,MAAMK,iBACJR,AAA+BS,WAA/BT,eAAe,CAACO,UAAU,GACtBP,eAAe,CAACO,UAAU,GAC1BF,qBAAqBE,AAAc,WAAdA,YACnBP,gBAAgB,OAAO,GACvBS;IAIR,MAAMC,oBAAoB,IAAIC,IAAI;QAChCJ;WACIF,qBAAqBE,AAAc,WAAdA,YAAuB;YAAC;SAAU,GAAG,EAAE;KACjE;IAED,MAAMK,mCAAmCC,OAAO,WAAW,CACzDA,OAAO,OAAO,CAACb,iBAAiB,MAAM,CACpC,CAAC,CAACc,IAAI,GAAK,CAACJ,kBAAkB,GAAG,CAACI;IAItC,MAAMC,SAASZ,kBAAkB,aAAa,CAC5CK,gBACAJ;IAEF,OAAO;QACL,GAAGQ,gCAAgC;QACnC,oBAAoBG;IACtB;AACF"}
1
+ {"version":3,"file":"ai-model/workflows/planning/locate-normalization.mjs","sources":["../../../../../src/ai-model/workflows/planning/locate-normalization.ts"],"sourcesContent":["import { findAllMidsceneLocatorField } from '@/common';\nimport type { DeviceAction } from '@/device';\nimport type { PlanningAction } from '@/types';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { ParsedPlanningLocateParameter } from '../../model-adapter/planning-protocol';\nimport {\n locateResultKeys,\n readLocateResultField,\n} from '../../shared/model-locate-result/result-field';\nimport type {\n LocateResultCodec,\n LocateResultContext,\n} from '../../shared/model-locate-result/types';\n\nconst debug = getDebug('planning');\n\nexport function normalizePlanningActionLocateFields(\n actions: PlanningAction[],\n {\n actionSpace,\n ...options\n }: PlanningLocateNormalizationOptions & {\n actionSpace: DeviceAction[];\n },\n): void {\n actions.forEach((action) => {\n const actionInActionSpace = actionSpace.find(\n (actionInSpace) => actionInSpace.name === action.type,\n );\n if (!actionInActionSpace) {\n debug('skip locate normalization for action outside actionSpace', action);\n return;\n }\n\n debug('actionInActionSpace matched', actionInActionSpace);\n const locateFields = findAllMidsceneLocatorField(\n actionInActionSpace.paramSchema,\n );\n\n debug('locateFields', locateFields);\n\n locateFields.forEach((field) => {\n const locateParameter = action.param?.[field];\n if (!locateParameter) {\n return;\n }\n\n action.param[field] = normalizePlanningLocateParameter(\n locateParameter,\n options,\n );\n });\n });\n}\n\nexport type PlanningLocateNormalizationOptions = {\n includeLocateInPlanning: boolean;\n locateResultCodec?: LocateResultCodec;\n locateResultContext: LocateResultContext;\n};\n\nexport function normalizePlanningLocateParameter(\n locateParameter: ParsedPlanningLocateParameter,\n {\n includeLocateInPlanning,\n locateResultCodec,\n locateResultContext,\n }: PlanningLocateNormalizationOptions,\n): Record<string, unknown> {\n if (!includeLocateInPlanning) {\n // In prompt-only planning mode, ignore any accidental coordinates from the model.\n return { prompt: locateParameter.prompt };\n }\n\n assert(\n locateResultCodec,\n 'planning locate normalization requires a locate result codec',\n );\n\n const { promptSpec } = locateResultCodec;\n const rawLocateValue = readLocateResultField(locateParameter, promptSpec);\n\n // Remove primary and alias fields after converting the raw coordinates.\n const rawCoordinateKeys = new Set(locateResultKeys(promptSpec));\n\n const locateParamWithoutRawCoordinates = Object.fromEntries(\n Object.entries(locateParameter).filter(\n ([key]) => !rawCoordinateKeys.has(key),\n ),\n );\n\n const result = locateResultCodec.toPixelResult(\n rawLocateValue,\n locateResultContext,\n );\n return {\n ...locateParamWithoutRawCoordinates,\n locatedPixelResult: result,\n };\n}\n"],"names":["debug","getDebug","normalizePlanningActionLocateFields","actions","actionSpace","options","action","actionInActionSpace","actionInSpace","locateFields","findAllMidsceneLocatorField","field","locateParameter","normalizePlanningLocateParameter","includeLocateInPlanning","locateResultCodec","locateResultContext","assert","promptSpec","rawLocateValue","readLocateResultField","rawCoordinateKeys","Set","locateResultKeys","locateParamWithoutRawCoordinates","Object","key","result"],"mappings":";;;;AAeA,MAAMA,QAAQC,SAAS;AAEhB,SAASC,oCACdC,OAAyB,EACzB,EACEC,WAAW,EACX,GAAGC,SAGJ;IAEDF,QAAQ,OAAO,CAAC,CAACG;QACf,MAAMC,sBAAsBH,YAAY,IAAI,CAC1C,CAACI,gBAAkBA,cAAc,IAAI,KAAKF,OAAO,IAAI;QAEvD,IAAI,CAACC,qBAAqB,YACxBP,MAAM,4DAA4DM;QAIpEN,MAAM,+BAA+BO;QACrC,MAAME,eAAeC,4BACnBH,oBAAoB,WAAW;QAGjCP,MAAM,gBAAgBS;QAEtBA,aAAa,OAAO,CAAC,CAACE;YACpB,MAAMC,kBAAkBN,OAAO,KAAK,EAAE,CAACK,MAAM;YAC7C,IAAI,CAACC,iBACH;YAGFN,OAAO,KAAK,CAACK,MAAM,GAAGE,iCACpBD,iBACAP;QAEJ;IACF;AACF;AAQO,SAASQ,iCACdD,eAA8C,EAC9C,EACEE,uBAAuB,EACvBC,iBAAiB,EACjBC,mBAAmB,EACgB;IAErC,IAAI,CAACF,yBAEH,OAAO;QAAE,QAAQF,gBAAgB,MAAM;IAAC;IAG1CK,OACEF,mBACA;IAGF,MAAM,EAAEG,UAAU,EAAE,GAAGH;IACvB,MAAMI,iBAAiBC,sBAAsBR,iBAAiBM;IAG9D,MAAMG,oBAAoB,IAAIC,IAAIC,iBAAiBL;IAEnD,MAAMM,mCAAmCC,OAAO,WAAW,CACzDA,OAAO,OAAO,CAACb,iBAAiB,MAAM,CACpC,CAAC,CAACc,IAAI,GAAK,CAACL,kBAAkB,GAAG,CAACK;IAItC,MAAMC,SAASZ,kBAAkB,aAAa,CAC5CI,gBACAH;IAEF,OAAO;QACL,GAAGQ,gCAAgC;QACnC,oBAAoBG;IACtB;AACF"}
@@ -6,7 +6,7 @@ import { buildStandardPlanningSystemPrompt } from "../../prompt/planning/index.m
6
6
  import { AIResponseParseError, callAI } from "../../service-caller/index.mjs";
7
7
  import { callAiAndParseWithRetry, withSemanticRetryFeedback } from "../../service-caller/semantic-retry.mjs";
8
8
  import { planningModelFamilyRequiredForLocateMessage } from "../../shared/model-locate-result/errors.mjs";
9
- import { preparedReferenceImagesToChatMessages } from "../../shared/multimodal-prompt.mjs";
9
+ import { preparedReferenceImagesToMessages } from "../../shared/multimodal-prompt.mjs";
10
10
  import { parsePlanningActions } from "./parse-planning-actions.mjs";
11
11
  import { parseStandardPlanningResponse } from "./standard-planning-parser.mjs";
12
12
  const debug = getDebug('planning');
@@ -45,8 +45,7 @@ async function callAndParsePlanningResponse(options) {
45
45
  actionSpace,
46
46
  includeLocateInPlanning,
47
47
  locateResultCodec,
48
- locateResultContext,
49
- acceptBbox2dAlias: modelRuntime.adapter.acceptBbox2dAlias
48
+ locateResultContext
50
49
  });
51
50
  return {
52
51
  response,
@@ -56,7 +55,7 @@ async function callAndParsePlanningResponse(options) {
56
55
  },
57
56
  toParseError: (parseError, response)=>{
58
57
  const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
59
- return new AIResponseParseError(`XML parse error: ${errorMessage}`, response.content, response.usage, response.rawChoiceMessage, response.reasoning_content);
58
+ return new AIResponseParseError(`XML parse error: ${errorMessage}`, response.content, response.usage, response.rawAssistantOutput, response.reasoning_content);
60
59
  },
61
60
  parseRetryTimes: modelRuntime.config.retryCount,
62
61
  parseRetryInterval: modelRuntime.config.retryInterval,
@@ -101,7 +100,7 @@ async function standardPlan(userInstruction, opts) {
101
100
  });
102
101
  const imagePayload = preparedImage.imageBase64;
103
102
  const actionContext = opts.actionContext ? `${opts.actionContext}\n` : '';
104
- const referenceImageMessages = preparedReferenceImagesToChatMessages(userInstruction.referenceImages);
103
+ const referenceImageMessages = preparedReferenceImagesToMessages(userInstruction.referenceImages);
105
104
  const instruction = [
106
105
  {
107
106
  role: 'user',
@@ -128,11 +127,8 @@ async function standardPlan(userInstruction, opts) {
128
127
  text: `${conversationHistory.pendingFeedbackMessage}. The previous action has been executed, here is the latest screenshot. Please continue according to the instruction.${memoriesSection}${executionProgressSection}`
129
128
  },
130
129
  {
131
- type: 'image_url',
132
- image_url: {
133
- url: imagePayload,
134
- detail: 'high'
135
- }
130
+ type: 'image',
131
+ url: imagePayload
136
132
  }
137
133
  ]
138
134
  };
@@ -145,15 +141,12 @@ async function standardPlan(userInstruction, opts) {
145
141
  text: `This is the current screenshot.${memoriesSection}${executionProgressSection}`
146
142
  },
147
143
  {
148
- type: 'image_url',
149
- image_url: {
150
- url: imagePayload,
151
- detail: 'high'
152
- }
144
+ type: 'image',
145
+ url: imagePayload
153
146
  }
154
147
  ]
155
148
  };
156
- conversationHistory.append(latestFeedbackMessage);
149
+ conversationHistory.appendMessage(latestFeedbackMessage);
157
150
  conversationHistory.compressHistory(50, 20);
158
151
  const historyLog = conversationHistory.snapshot(opts.imagesIncludeCount);
159
152
  const msgs = [
@@ -164,7 +157,7 @@ async function standardPlan(userInstruction, opts) {
164
157
  ...instruction,
165
158
  ...historyLog
166
159
  ];
167
- const { response: { content: rawResponse, usage, reasoning_content, rawChoiceMessage }, planFromAI, actions } = await callAndParsePlanningResponse({
160
+ const { response: { content: rawResponse, usage, reasoning_content, rawAssistantOutput }, planFromAI, actions } = await callAndParsePlanningResponse({
168
161
  messages: msgs,
169
162
  modelRuntime,
170
163
  abortSignal: opts.abortSignal,
@@ -189,7 +182,7 @@ async function standardPlan(userInstruction, opts) {
189
182
  ...planFromAI,
190
183
  actions,
191
184
  rawResponse,
192
- rawChoiceMessage,
185
+ rawAssistantOutput,
193
186
  usage,
194
187
  reasoning_content,
195
188
  yamlFlow,
@@ -202,16 +195,20 @@ async function standardPlan(userInstruction, opts) {
202
195
  if (planFromAI.log) conversationHistory.appendSubGoalLog(planFromAI.log);
203
196
  } else if (planFromAI.log) conversationHistory.appendHistoricalLog(planFromAI.log);
204
197
  if (planFromAI.memory) conversationHistory.appendMemory(planFromAI.memory);
205
- if (modelRuntime.adapter.chatCompletion.replayRawAssistantMessage && rawChoiceMessage) conversationHistory.append(rawChoiceMessage);
206
- else conversationHistory.append({
207
- role: 'assistant',
208
- content: [
209
- {
210
- type: 'text',
211
- text: rawResponse
212
- }
213
- ]
214
- });
198
+ const shouldReplayRawOutput = rawAssistantOutput?.type === 'responses' && modelRuntime.adapter.responses.replayRawAssistantOutput || rawAssistantOutput?.type === 'chat-completion' && modelRuntime.adapter.chatCompletion.replayRawAssistantMessage;
199
+ if (rawAssistantOutput && shouldReplayRawOutput) conversationHistory.appendModelOutput(rawAssistantOutput);
200
+ else {
201
+ if (!rawAssistantOutput) debug('Raw assistant output is unavailable; saving only response text in conversation history.');
202
+ conversationHistory.appendMessage({
203
+ role: 'assistant',
204
+ content: [
205
+ {
206
+ type: 'text',
207
+ text: rawResponse
208
+ }
209
+ ]
210
+ });
211
+ }
215
212
  return returnValue;
216
213
  }
217
214
  export { standardPlan };
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/workflows/planning/standard-planning.mjs","sources":["../../../../../src/ai-model/workflows/planning/standard-planning.ts"],"sourcesContent":["import type {\n PlanningAIResponse,\n PlanningAction,\n RawResponsePlanningAIResponse,\n} from '@/types';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport { buildYamlFlowFromPlans } from '../../../common';\nimport { prepareModelImage } from '../../model-adapter/image-preprocess';\nimport { buildStandardPlanningSystemPrompt } from '../../prompt/planning';\nimport { AIResponseParseError, callAI } from '../../service-caller/index';\nimport {\n callAiAndParseWithRetry,\n withSemanticRetryFeedback,\n} from '../../service-caller/semantic-retry';\nimport type {\n LocateResultCodec,\n LocateResultContext,\n} from '../../shared/model-locate-result';\nimport { planningModelFamilyRequiredForLocateMessage } from '../../shared/model-locate-result/errors';\nimport {\n type PreparedUserPrompt,\n preparedReferenceImagesToChatMessages,\n} from '../../shared/multimodal-prompt';\nimport { parsePlanningActions } from './parse-planning-actions';\nimport { parseStandardPlanningResponse } from './standard-planning-parser';\nimport type { PlanOptions } from './types';\n\nconst debug = getDebug('planning');\nconst warnLog = getDebug('planning', { console: true });\n\nconst noPreviousActionsText =\n 'No previous actions have been executed in this aiAct execution yet. If the instruction asks for actions, choose the first action to execute.';\ntype PlanningCallResponse = Awaited<ReturnType<typeof callAI>>;\n\ntype CallAndParsePlanningResponseOptions = {\n messages: ChatCompletionMessageParam[];\n modelRuntime: PlanOptions['modelRuntime'];\n abortSignal?: AbortSignal;\n includeLocateInPlanning: boolean;\n actionSpace: PlanOptions['actionSpace'];\n locateResultCodec?: LocateResultCodec;\n locateResultContext: LocateResultContext;\n includeThought: boolean;\n includeLog: boolean;\n};\n\nasync function callAndParsePlanningResponse(\n options: CallAndParsePlanningResponseOptions,\n): Promise<{\n response: PlanningCallResponse;\n planFromAI: RawResponsePlanningAIResponse;\n actions: PlanningAction[];\n}> {\n const {\n messages,\n modelRuntime,\n abortSignal,\n includeLocateInPlanning,\n actionSpace,\n locateResultCodec,\n locateResultContext,\n includeThought,\n includeLog,\n } = options;\n assert(\n modelRuntime.adapter.planning.kind === 'standard',\n 'callAndParsePlanningResponse requires a standard planning adapter',\n );\n const actionOutputProtocol =\n modelRuntime.adapter.planning.protocol.actionOutputProtocol;\n\n return callAiAndParseWithRetry({\n callAi: (retryAttempt, previousParseError) =>\n callAI(\n withSemanticRetryFeedback(messages, previousParseError),\n modelRuntime,\n {\n abortSignal,\n requiresOriginalImageDetail: includeLocateInPlanning,\n semanticRetryAttempt: retryAttempt,\n },\n ),\n parseResponse: (response) => {\n const planFromAI = parseStandardPlanningResponse(response.content, {\n includeThought,\n actionOutputProtocol,\n actionSpace,\n logSource: includeLog ? 'model' : 'action',\n });\n if (\n !planFromAI.action &&\n planFromAI.finalizeSuccess === undefined &&\n !planFromAI.error\n ) {\n throw new Error(\n 'Incomplete planning response: provide an action, <complete>, or <error>. A <planning> explanation alone is not sufficient.',\n );\n }\n if (planFromAI.action && planFromAI.finalizeSuccess !== undefined) {\n warnLog(\n 'Planning response included both an action and <complete>; ignoring <complete> output.',\n );\n planFromAI.finalizeMessage = undefined;\n planFromAI.finalizeSuccess = undefined;\n }\n\n const actions = planFromAI.action ? [planFromAI.action] : [];\n parsePlanningActions(actions, {\n parseRawLocateParameter: actionOutputProtocol.parseRawLocateParameter,\n actionSpace,\n includeLocateInPlanning,\n locateResultCodec,\n locateResultContext,\n acceptBbox2dAlias: modelRuntime.adapter.acceptBbox2dAlias,\n });\n return { response, planFromAI, actions };\n },\n toParseError: (parseError, response) => {\n const errorMessage =\n parseError instanceof Error ? parseError.message : String(parseError);\n return new AIResponseParseError(\n `XML parse error: ${errorMessage}`,\n response.content,\n response.usage,\n response.rawChoiceMessage,\n response.reasoning_content,\n );\n },\n parseRetryTimes: modelRuntime.config.retryCount,\n parseRetryInterval: modelRuntime.config.retryInterval,\n abortSignal,\n onParseRetry: (parseError) => {\n debug(\n 'retrying plan after response parsing failed: %s',\n parseError instanceof Error ? parseError.message : String(parseError),\n );\n },\n });\n}\n\nexport async function standardPlan(\n userInstruction: PreparedUserPrompt,\n opts: PlanOptions,\n): Promise<PlanningAIResponse> {\n const { context, conversationHistory } = opts;\n const modelRuntime = opts.modelRuntime;\n const { adapter } = modelRuntime;\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(\n adapter.planning.kind === 'standard',\n 'standardPlan requires a standard planning adapter',\n );\n const planningProtocol = adapter.planning.protocol;\n\n if (opts.includeLocateInPlanning && !modelRuntime.config.modelFamily) {\n throw new Error(\n planningModelFamilyRequiredForLocateMessage(modelRuntime.config.slot),\n );\n }\n\n const locateResultCodec = modelRuntime.config.modelFamily\n ? adapter.planning.locateResultCodec\n : undefined;\n\n // Only enable sub-goals when aiAct is in deep-thinking planning mode.\n const includeSubGoals = opts.effort === 'deepThink';\n const includeThought = opts.effort !== 'fast';\n const includeLog = opts.effort !== 'fast';\n\n if (opts.includeLocateInPlanning && !locateResultCodec) {\n throw new Error(\n planningModelFamilyRequiredForLocateMessage(modelRuntime.config.slot),\n );\n }\n\n const systemPrompt = await buildStandardPlanningSystemPrompt({\n actionSpace: opts.actionSpace,\n includeThought,\n includeLog,\n includeSubGoals,\n planningProtocol,\n ...(opts.includeLocateInPlanning && locateResultCodec\n ? {\n includeLocateInPlanning: true,\n locatePromptSpec: locateResultCodec.promptSpec,\n }\n : { includeLocateInPlanning: false }),\n });\n\n const preparedImage = await prepareModelImage({\n imageBase64: screenshotBase64,\n width: shotSize.width,\n height: shotSize.height,\n policy: adapter.imagePreprocess,\n });\n const imagePayload = preparedImage.imageBase64;\n\n const actionContext = opts.actionContext ? `${opts.actionContext}\\n` : '';\n\n const referenceImageMessages = preparedReferenceImagesToChatMessages(\n userInstruction.referenceImages,\n );\n const instruction: ChatCompletionMessageParam[] = [\n {\n role: 'user',\n content: [\n {\n type: 'text',\n text: `${actionContext}<user_instruction>${userInstruction.text}</user_instruction>`,\n },\n ],\n },\n ...referenceImageMessages,\n ];\n\n let latestFeedbackMessage: ChatCompletionMessageParam;\n\n // Build sub-goal status text to include in the message\n // In planning deep-think mode: show full sub-goals with logs\n // Otherwise: show historical execution logs\n const executionProgressText = includeSubGoals\n ? conversationHistory.subGoalsToText()\n : conversationHistory.historicalLogsToText();\n const executionProgressSection = executionProgressText\n ? `\\n\\n${executionProgressText}`\n : conversationHistory.pendingFeedbackMessage\n ? ''\n : `\\n\\n${noPreviousActionsText}`;\n\n // Build memories text to include in the message\n const memoriesText = conversationHistory.memoriesToText();\n const memoriesSection = memoriesText ? `\\n\\n${memoriesText}` : '';\n\n if (conversationHistory.pendingFeedbackMessage) {\n latestFeedbackMessage = {\n role: 'user',\n content: [\n {\n type: 'text',\n text: `${conversationHistory.pendingFeedbackMessage}. The previous action has been executed, here is the latest screenshot. Please continue according to the instruction.${memoriesSection}${executionProgressSection}`,\n },\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n detail: 'high',\n },\n },\n ],\n };\n\n conversationHistory.resetPendingFeedbackMessageIfExists();\n } else {\n latestFeedbackMessage = {\n role: 'user',\n content: [\n {\n type: 'text',\n text: `This is the current screenshot.${memoriesSection}${executionProgressSection}`,\n },\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n detail: 'high',\n },\n },\n ],\n };\n }\n conversationHistory.append(latestFeedbackMessage);\n\n // Compress history if it exceeds the threshold to avoid context overflow\n conversationHistory.compressHistory(50, 20);\n\n const historyLog = conversationHistory.snapshot(opts.imagesIncludeCount);\n\n const msgs: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n ...instruction,\n ...historyLog,\n ];\n\n const {\n response: {\n content: rawResponse,\n usage,\n reasoning_content,\n rawChoiceMessage,\n },\n planFromAI,\n actions,\n } = await callAndParsePlanningResponse({\n messages: msgs,\n modelRuntime,\n abortSignal: opts.abortSignal,\n includeLocateInPlanning: opts.includeLocateInPlanning,\n actionSpace: opts.actionSpace,\n locateResultCodec,\n locateResultContext: {\n preparedSize: preparedImage.preparedSize,\n contentSize: preparedImage.contentSize,\n },\n includeThought,\n includeLog,\n });\n\n // YAML is derived from validated actions outside the model-response retry scope.\n // dumpActionParam omits runtime-only locatedPixelResult fields.\n const yamlFlow = buildYamlFlowFromPlans(actions, opts.actionSpace);\n\n let shouldContinuePlanning = true;\n\n // Check if task is completed via <complete> tag\n if (planFromAI.finalizeSuccess !== undefined) {\n debug('task completed via <complete> tag, stop planning');\n shouldContinuePlanning = false;\n // Mark all sub-goals as finished when goal is completed in planning deep-think mode.\n if (includeSubGoals) {\n conversationHistory.markAllSubGoalsFinished();\n }\n }\n\n const returnValue: PlanningAIResponse = {\n ...planFromAI,\n actions,\n rawResponse,\n rawChoiceMessage,\n usage,\n reasoning_content,\n yamlFlow,\n shouldContinuePlanning,\n };\n\n assert(planFromAI, \"can't get plans from AI\");\n\n // TODO: The plan log is recorded before its action has executed, so a failed\n // action may still appear in the next round as an action already performed.\n // Move this write to the successful action execution path in TaskExecutor.action.\n // Update sub-goals in conversation history only in planning deep-think mode.\n if (includeSubGoals) {\n if (planFromAI.updateSubGoals?.length) {\n conversationHistory.mergeSubGoals(planFromAI.updateSubGoals);\n }\n if (planFromAI.markFinishedIndexes?.length) {\n for (const index of planFromAI.markFinishedIndexes) {\n conversationHistory.markSubGoalFinished(index);\n }\n }\n // Append the planning log to the currently running sub-goal\n if (planFromAI.log) {\n conversationHistory.appendSubGoalLog(planFromAI.log);\n }\n } else {\n // Without planning deep-think mode, accumulate logs as historical execution steps.\n if (planFromAI.log) {\n conversationHistory.appendHistoricalLog(planFromAI.log);\n }\n }\n\n // Append memory to conversation history if present\n if (planFromAI.memory) {\n conversationHistory.appendMemory(planFromAI.memory);\n }\n\n // Some model providers require opaque assistant fields to be replayed\n // verbatim in later turns. Keep this opt-in per model adapter so that an\n // unverified provider does not receive non-standard response fields.\n if (\n modelRuntime.adapter.chatCompletion.replayRawAssistantMessage &&\n rawChoiceMessage\n ) {\n conversationHistory.append(rawChoiceMessage as ChatCompletionMessageParam);\n } else {\n conversationHistory.append({\n role: 'assistant',\n content: [\n {\n type: 'text',\n text: rawResponse,\n },\n ],\n });\n }\n\n return returnValue;\n}\n"],"names":["debug","getDebug","warnLog","noPreviousActionsText","callAndParsePlanningResponse","options","messages","modelRuntime","abortSignal","includeLocateInPlanning","actionSpace","locateResultCodec","locateResultContext","includeThought","includeLog","assert","actionOutputProtocol","callAiAndParseWithRetry","retryAttempt","previousParseError","callAI","withSemanticRetryFeedback","response","planFromAI","parseStandardPlanningResponse","undefined","Error","actions","parsePlanningActions","parseError","errorMessage","String","AIResponseParseError","standardPlan","userInstruction","opts","context","conversationHistory","adapter","shotSize","screenshotBase64","planningProtocol","planningModelFamilyRequiredForLocateMessage","includeSubGoals","systemPrompt","buildStandardPlanningSystemPrompt","preparedImage","prepareModelImage","imagePayload","actionContext","referenceImageMessages","preparedReferenceImagesToChatMessages","instruction","latestFeedbackMessage","executionProgressText","executionProgressSection","memoriesText","memoriesSection","historyLog","msgs","rawResponse","usage","reasoning_content","rawChoiceMessage","yamlFlow","buildYamlFlowFromPlans","shouldContinuePlanning","returnValue","index"],"mappings":"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"}
1
+ {"version":3,"file":"ai-model/workflows/planning/standard-planning.mjs","sources":["../../../../../src/ai-model/workflows/planning/standard-planning.ts"],"sourcesContent":["import type { ConversationMessage } from '@/ai-model/service-caller/types';\nimport type {\n PlanningAIResponse,\n PlanningAction,\n RawResponsePlanningAIResponse,\n} from '@/types';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { buildYamlFlowFromPlans } from '../../../common';\nimport { prepareModelImage } from '../../model-adapter/image-preprocess';\nimport { buildStandardPlanningSystemPrompt } from '../../prompt/planning';\nimport { AIResponseParseError, callAI } from '../../service-caller/index';\nimport {\n callAiAndParseWithRetry,\n withSemanticRetryFeedback,\n} from '../../service-caller/semantic-retry';\nimport type { ModelCallMessages } from '../../service-caller/types';\nimport type {\n LocateResultCodec,\n LocateResultContext,\n} from '../../shared/model-locate-result';\nimport { planningModelFamilyRequiredForLocateMessage } from '../../shared/model-locate-result/errors';\nimport {\n type PreparedUserPrompt,\n preparedReferenceImagesToMessages,\n} from '../../shared/multimodal-prompt';\nimport { parsePlanningActions } from './parse-planning-actions';\nimport { parseStandardPlanningResponse } from './standard-planning-parser';\nimport type { PlanOptions } from './types';\n\nconst debug = getDebug('planning');\nconst warnLog = getDebug('planning', { console: true });\n\nconst noPreviousActionsText =\n 'No previous actions have been executed in this aiAct execution yet. If the instruction asks for actions, choose the first action to execute.';\ntype PlanningCallResponse = Awaited<ReturnType<typeof callAI>>;\n\ntype CallAndParsePlanningResponseOptions = {\n messages: ModelCallMessages;\n modelRuntime: PlanOptions['modelRuntime'];\n abortSignal?: AbortSignal;\n includeLocateInPlanning: boolean;\n actionSpace: PlanOptions['actionSpace'];\n locateResultCodec?: LocateResultCodec;\n locateResultContext: LocateResultContext;\n includeThought: boolean;\n includeLog: boolean;\n};\n\nasync function callAndParsePlanningResponse(\n options: CallAndParsePlanningResponseOptions,\n): Promise<{\n response: PlanningCallResponse;\n planFromAI: RawResponsePlanningAIResponse;\n actions: PlanningAction[];\n}> {\n const {\n messages,\n modelRuntime,\n abortSignal,\n includeLocateInPlanning,\n actionSpace,\n locateResultCodec,\n locateResultContext,\n includeThought,\n includeLog,\n } = options;\n assert(\n modelRuntime.adapter.planning.kind === 'standard',\n 'callAndParsePlanningResponse requires a standard planning adapter',\n );\n const actionOutputProtocol =\n modelRuntime.adapter.planning.protocol.actionOutputProtocol;\n\n return callAiAndParseWithRetry({\n callAi: (retryAttempt, previousParseError) =>\n callAI(\n withSemanticRetryFeedback(messages, previousParseError),\n modelRuntime,\n {\n abortSignal,\n requiresOriginalImageDetail: includeLocateInPlanning,\n semanticRetryAttempt: retryAttempt,\n },\n ),\n parseResponse: (response) => {\n const planFromAI = parseStandardPlanningResponse(response.content, {\n includeThought,\n actionOutputProtocol,\n actionSpace,\n logSource: includeLog ? 'model' : 'action',\n });\n if (\n !planFromAI.action &&\n planFromAI.finalizeSuccess === undefined &&\n !planFromAI.error\n ) {\n throw new Error(\n 'Incomplete planning response: provide an action, <complete>, or <error>. A <planning> explanation alone is not sufficient.',\n );\n }\n if (planFromAI.action && planFromAI.finalizeSuccess !== undefined) {\n warnLog(\n 'Planning response included both an action and <complete>; ignoring <complete> output.',\n );\n planFromAI.finalizeMessage = undefined;\n planFromAI.finalizeSuccess = undefined;\n }\n\n const actions = planFromAI.action ? [planFromAI.action] : [];\n parsePlanningActions(actions, {\n parseRawLocateParameter: actionOutputProtocol.parseRawLocateParameter,\n actionSpace,\n includeLocateInPlanning,\n locateResultCodec,\n locateResultContext,\n });\n return { response, planFromAI, actions };\n },\n toParseError: (parseError, response) => {\n const errorMessage =\n parseError instanceof Error ? parseError.message : String(parseError);\n return new AIResponseParseError(\n `XML parse error: ${errorMessage}`,\n response.content,\n response.usage,\n response.rawAssistantOutput,\n response.reasoning_content,\n );\n },\n parseRetryTimes: modelRuntime.config.retryCount,\n parseRetryInterval: modelRuntime.config.retryInterval,\n abortSignal,\n onParseRetry: (parseError) => {\n debug(\n 'retrying plan after response parsing failed: %s',\n parseError instanceof Error ? parseError.message : String(parseError),\n );\n },\n });\n}\n\nexport async function standardPlan(\n userInstruction: PreparedUserPrompt,\n opts: PlanOptions,\n): Promise<PlanningAIResponse> {\n const { context, conversationHistory } = opts;\n const modelRuntime = opts.modelRuntime;\n const { adapter } = modelRuntime;\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(\n adapter.planning.kind === 'standard',\n 'standardPlan requires a standard planning adapter',\n );\n const planningProtocol = adapter.planning.protocol;\n\n if (opts.includeLocateInPlanning && !modelRuntime.config.modelFamily) {\n throw new Error(\n planningModelFamilyRequiredForLocateMessage(modelRuntime.config.slot),\n );\n }\n\n const locateResultCodec = modelRuntime.config.modelFamily\n ? adapter.planning.locateResultCodec\n : undefined;\n\n // Only enable sub-goals when aiAct is in deep-thinking planning mode.\n const includeSubGoals = opts.effort === 'deepThink';\n const includeThought = opts.effort !== 'fast';\n const includeLog = opts.effort !== 'fast';\n\n if (opts.includeLocateInPlanning && !locateResultCodec) {\n throw new Error(\n planningModelFamilyRequiredForLocateMessage(modelRuntime.config.slot),\n );\n }\n\n const systemPrompt = await buildStandardPlanningSystemPrompt({\n actionSpace: opts.actionSpace,\n includeThought,\n includeLog,\n includeSubGoals,\n planningProtocol,\n ...(opts.includeLocateInPlanning && locateResultCodec\n ? {\n includeLocateInPlanning: true,\n locatePromptSpec: locateResultCodec.promptSpec,\n }\n : { includeLocateInPlanning: false }),\n });\n\n const preparedImage = await prepareModelImage({\n imageBase64: screenshotBase64,\n width: shotSize.width,\n height: shotSize.height,\n policy: adapter.imagePreprocess,\n });\n const imagePayload = preparedImage.imageBase64;\n\n const actionContext = opts.actionContext ? `${opts.actionContext}\\n` : '';\n\n const referenceImageMessages = preparedReferenceImagesToMessages(\n userInstruction.referenceImages,\n );\n const instruction: ConversationMessage[] = [\n {\n role: 'user',\n content: [\n {\n type: 'text',\n text: `${actionContext}<user_instruction>${userInstruction.text}</user_instruction>`,\n },\n ],\n },\n ...referenceImageMessages,\n ];\n\n let latestFeedbackMessage: ConversationMessage;\n\n // Build sub-goal status text to include in the message\n // In planning deep-think mode: show full sub-goals with logs\n // Otherwise: show historical execution logs\n const executionProgressText = includeSubGoals\n ? conversationHistory.subGoalsToText()\n : conversationHistory.historicalLogsToText();\n const executionProgressSection = executionProgressText\n ? `\\n\\n${executionProgressText}`\n : conversationHistory.pendingFeedbackMessage\n ? ''\n : `\\n\\n${noPreviousActionsText}`;\n\n // Build memories text to include in the message\n const memoriesText = conversationHistory.memoriesToText();\n const memoriesSection = memoriesText ? `\\n\\n${memoriesText}` : '';\n\n if (conversationHistory.pendingFeedbackMessage) {\n latestFeedbackMessage = {\n role: 'user',\n content: [\n {\n type: 'text',\n text: `${conversationHistory.pendingFeedbackMessage}. The previous action has been executed, here is the latest screenshot. Please continue according to the instruction.${memoriesSection}${executionProgressSection}`,\n },\n {\n type: 'image',\n url: imagePayload,\n },\n ],\n };\n\n conversationHistory.resetPendingFeedbackMessageIfExists();\n } else {\n latestFeedbackMessage = {\n role: 'user',\n content: [\n {\n type: 'text',\n text: `This is the current screenshot.${memoriesSection}${executionProgressSection}`,\n },\n {\n type: 'image',\n url: imagePayload,\n },\n ],\n };\n }\n conversationHistory.appendMessage(latestFeedbackMessage);\n\n // Compress history if it exceeds the threshold to avoid context overflow\n conversationHistory.compressHistory(50, 20);\n\n const historyLog = conversationHistory.snapshot(opts.imagesIncludeCount);\n\n const msgs: ModelCallMessages = [\n { role: 'system', content: systemPrompt },\n ...instruction,\n ...historyLog,\n ];\n\n const {\n response: {\n content: rawResponse,\n usage,\n reasoning_content,\n rawAssistantOutput,\n },\n planFromAI,\n actions,\n } = await callAndParsePlanningResponse({\n messages: msgs,\n modelRuntime,\n abortSignal: opts.abortSignal,\n includeLocateInPlanning: opts.includeLocateInPlanning,\n actionSpace: opts.actionSpace,\n locateResultCodec,\n locateResultContext: {\n preparedSize: preparedImage.preparedSize,\n contentSize: preparedImage.contentSize,\n },\n includeThought,\n includeLog,\n });\n\n // YAML is derived from validated actions outside the model-response retry scope.\n // dumpActionParam omits runtime-only locatedPixelResult fields.\n const yamlFlow = buildYamlFlowFromPlans(actions, opts.actionSpace);\n\n let shouldContinuePlanning = true;\n\n // Check if task is completed via <complete> tag\n if (planFromAI.finalizeSuccess !== undefined) {\n debug('task completed via <complete> tag, stop planning');\n shouldContinuePlanning = false;\n // Mark all sub-goals as finished when goal is completed in planning deep-think mode.\n if (includeSubGoals) {\n conversationHistory.markAllSubGoalsFinished();\n }\n }\n\n const returnValue: PlanningAIResponse = {\n ...planFromAI,\n actions,\n rawResponse,\n rawAssistantOutput,\n usage,\n reasoning_content,\n yamlFlow,\n shouldContinuePlanning,\n };\n\n assert(planFromAI, \"can't get plans from AI\");\n\n // TODO: The plan log is recorded before its action has executed, so a failed\n // action may still appear in the next round as an action already performed.\n // Move this write to the successful action execution path in TaskExecutor.action.\n // Update sub-goals in conversation history only in planning deep-think mode.\n if (includeSubGoals) {\n if (planFromAI.updateSubGoals?.length) {\n conversationHistory.mergeSubGoals(planFromAI.updateSubGoals);\n }\n if (planFromAI.markFinishedIndexes?.length) {\n for (const index of planFromAI.markFinishedIndexes) {\n conversationHistory.markSubGoalFinished(index);\n }\n }\n // Append the planning log to the currently running sub-goal\n if (planFromAI.log) {\n conversationHistory.appendSubGoalLog(planFromAI.log);\n }\n } else {\n // Without planning deep-think mode, accumulate logs as historical execution steps.\n if (planFromAI.log) {\n conversationHistory.appendHistoricalLog(planFromAI.log);\n }\n }\n\n // Append memory to conversation history if present\n if (planFromAI.memory) {\n conversationHistory.appendMemory(planFromAI.memory);\n }\n\n const shouldReplayRawOutput =\n (rawAssistantOutput?.type === 'responses' &&\n modelRuntime.adapter.responses.replayRawAssistantOutput) ||\n (rawAssistantOutput?.type === 'chat-completion' &&\n modelRuntime.adapter.chatCompletion.replayRawAssistantMessage);\n if (rawAssistantOutput && shouldReplayRawOutput) {\n conversationHistory.appendModelOutput(rawAssistantOutput);\n } else {\n if (!rawAssistantOutput) {\n debug(\n 'Raw assistant output is unavailable; saving only response text in conversation history.',\n );\n }\n conversationHistory.appendMessage({\n role: 'assistant',\n content: [\n {\n type: 'text',\n text: rawResponse,\n },\n ],\n });\n }\n\n return returnValue;\n}\n"],"names":["debug","getDebug","warnLog","noPreviousActionsText","callAndParsePlanningResponse","options","messages","modelRuntime","abortSignal","includeLocateInPlanning","actionSpace","locateResultCodec","locateResultContext","includeThought","includeLog","assert","actionOutputProtocol","callAiAndParseWithRetry","retryAttempt","previousParseError","callAI","withSemanticRetryFeedback","response","planFromAI","parseStandardPlanningResponse","undefined","Error","actions","parsePlanningActions","parseError","errorMessage","String","AIResponseParseError","standardPlan","userInstruction","opts","context","conversationHistory","adapter","shotSize","screenshotBase64","planningProtocol","planningModelFamilyRequiredForLocateMessage","includeSubGoals","systemPrompt","buildStandardPlanningSystemPrompt","preparedImage","prepareModelImage","imagePayload","actionContext","referenceImageMessages","preparedReferenceImagesToMessages","instruction","latestFeedbackMessage","executionProgressText","executionProgressSection","memoriesText","memoriesSection","historyLog","msgs","rawResponse","usage","reasoning_content","rawAssistantOutput","yamlFlow","buildYamlFlowFromPlans","shouldContinuePlanning","returnValue","index","shouldReplayRawOutput"],"mappings":"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"}
@@ -157,10 +157,8 @@ const createMessageContent = (promptText, screenshots = [], includeScreenshots =
157
157
  });
158
158
  screenshots.forEach((screenshot)=>{
159
159
  messageContent.push({
160
- type: 'image_url',
161
- image_url: {
162
- url: screenshot
163
- }
160
+ type: 'image',
161
+ url: screenshot
164
162
  });
165
163
  });
166
164
  }