@aiscene/core 9.0.6 → 9.0.8

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 (686) hide show
  1. package/dist/es/agent/agent.mjs +24 -11
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/cache-config.mjs +19 -0
  4. package/dist/es/agent/cache-config.mjs.map +1 -0
  5. package/dist/es/agent/file-chooser.mjs +82 -0
  6. package/dist/es/agent/file-chooser.mjs.map +1 -0
  7. package/dist/es/agent/insight.mjs +101 -0
  8. package/dist/es/agent/insight.mjs.map +1 -0
  9. package/dist/es/agent/metrics.mjs +81 -0
  10. package/dist/es/agent/metrics.mjs.map +1 -0
  11. package/dist/es/agent/progress/ai-act-progress.mjs +199 -0
  12. package/dist/es/agent/progress/ai-act-progress.mjs.map +1 -0
  13. package/dist/es/agent/progress/index.mjs +2 -0
  14. package/dist/es/agent/progress/progress-bus.mjs +52 -0
  15. package/dist/es/agent/progress/progress-bus.mjs.map +1 -0
  16. package/dist/es/agent/prompt-context.mjs +25 -0
  17. package/dist/es/agent/prompt-context.mjs.map +1 -0
  18. package/dist/es/agent/record-to-report.mjs +14 -0
  19. package/dist/es/agent/record-to-report.mjs.map +1 -0
  20. package/dist/es/agent/run-gherkin-scenario.mjs +114 -0
  21. package/dist/es/agent/run-gherkin-scenario.mjs.map +1 -0
  22. package/dist/es/agent/run-markdown.mjs +62 -0
  23. package/dist/es/agent/run-markdown.mjs.map +1 -0
  24. package/dist/es/agent/screenshot-preparation.mjs +37 -0
  25. package/dist/es/agent/screenshot-preparation.mjs.map +1 -0
  26. package/dist/es/agent/ui-observer.mjs +385 -0
  27. package/dist/es/agent/ui-observer.mjs.map +1 -0
  28. package/dist/es/agent/utils.mjs +42 -4
  29. package/dist/es/agent/utils.mjs.map +1 -1
  30. package/dist/es/ai-model/connectivity/fixture.mjs +8 -0
  31. package/dist/es/ai-model/connectivity/fixture.mjs.map +1 -0
  32. package/dist/es/ai-model/connectivity/index.mjs +2 -0
  33. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs +160 -0
  34. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs.map +1 -0
  35. package/dist/es/ai-model/conversation-history.mjs.map +1 -1
  36. package/dist/es/ai-model/index.mjs +2 -1
  37. package/dist/es/ai-model/inspect.mjs +1 -1
  38. package/dist/es/ai-model/inspect.mjs.map +1 -1
  39. package/dist/es/ai-model/model-adapter/chat-completion.mjs +69 -0
  40. package/dist/es/ai-model/model-adapter/chat-completion.mjs.map +1 -0
  41. package/dist/es/ai-model/model-adapter/custom-planning-action.mjs +6 -0
  42. package/dist/es/ai-model/model-adapter/custom-planning-action.mjs.map +1 -0
  43. package/dist/es/ai-model/model-adapter/custom-planning-types.mjs +0 -0
  44. package/dist/es/ai-model/model-adapter/default-insight-protocol.mjs +28 -0
  45. package/dist/es/ai-model/model-adapter/default-insight-protocol.mjs.map +1 -0
  46. package/dist/es/ai-model/model-adapter/default-locate-protocol.mjs +145 -0
  47. package/dist/es/ai-model/model-adapter/default-locate-protocol.mjs.map +1 -0
  48. package/dist/es/ai-model/model-adapter/default-planning-protocol.mjs +124 -0
  49. package/dist/es/ai-model/model-adapter/default-planning-protocol.mjs.map +1 -0
  50. package/dist/es/ai-model/model-adapter/image-preprocess.mjs +27 -0
  51. package/dist/es/ai-model/model-adapter/image-preprocess.mjs.map +1 -0
  52. package/dist/es/ai-model/model-adapter/index.mjs +2 -0
  53. package/dist/es/ai-model/model-adapter/insight-protocol.mjs +0 -0
  54. package/dist/es/ai-model/model-adapter/insight.mjs +13 -0
  55. package/dist/es/ai-model/model-adapter/insight.mjs.map +1 -0
  56. package/dist/es/ai-model/model-adapter/locate-protocol.mjs +0 -0
  57. package/dist/es/ai-model/model-adapter/locate.mjs +53 -0
  58. package/dist/es/ai-model/model-adapter/locate.mjs.map +1 -0
  59. package/dist/es/ai-model/model-adapter/planning-protocol.mjs +0 -0
  60. package/dist/es/ai-model/model-adapter/planning.mjs +49 -0
  61. package/dist/es/ai-model/model-adapter/planning.mjs.map +1 -0
  62. package/dist/es/ai-model/model-adapter/resolve.mjs +54 -0
  63. package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -0
  64. package/dist/es/ai-model/model-adapter/types.mjs +0 -0
  65. package/dist/es/ai-model/models/auto-glm/actions.mjs +205 -0
  66. package/dist/es/ai-model/models/auto-glm/actions.mjs.map +1 -0
  67. package/dist/es/ai-model/models/auto-glm/adapter.mjs +45 -0
  68. package/dist/es/ai-model/models/auto-glm/adapter.mjs.map +1 -0
  69. package/dist/es/ai-model/models/auto-glm/locate.mjs +11 -0
  70. package/dist/es/ai-model/models/auto-glm/locate.mjs.map +1 -0
  71. package/dist/es/ai-model/models/auto-glm/parser.mjs +217 -0
  72. package/dist/es/ai-model/models/auto-glm/parser.mjs.map +1 -0
  73. package/dist/es/ai-model/models/auto-glm/planning.mjs +33 -0
  74. package/dist/es/ai-model/models/auto-glm/planning.mjs.map +1 -0
  75. package/dist/es/ai-model/models/auto-glm/prompt.mjs +214 -0
  76. package/dist/es/ai-model/models/auto-glm/prompt.mjs.map +1 -0
  77. package/dist/es/ai-model/models/deepseek/adapter.mjs +79 -0
  78. package/dist/es/ai-model/models/deepseek/adapter.mjs.map +1 -0
  79. package/dist/es/ai-model/models/deepseek/locate-protocol.mjs +89 -0
  80. package/dist/es/ai-model/models/deepseek/locate-protocol.mjs.map +1 -0
  81. package/dist/es/ai-model/models/default.mjs +13 -0
  82. package/dist/es/ai-model/models/default.mjs.map +1 -0
  83. package/dist/es/ai-model/models/doubao.mjs +95 -0
  84. package/dist/es/ai-model/models/doubao.mjs.map +1 -0
  85. package/dist/es/ai-model/models/gemini.mjs +100 -0
  86. package/dist/es/ai-model/models/gemini.mjs.map +1 -0
  87. package/dist/es/ai-model/models/glm.mjs +46 -0
  88. package/dist/es/ai-model/models/glm.mjs.map +1 -0
  89. package/dist/es/ai-model/models/gpt.mjs +43 -0
  90. package/dist/es/ai-model/models/gpt.mjs.map +1 -0
  91. package/dist/es/ai-model/models/index.mjs +2 -0
  92. package/dist/es/ai-model/models/kimi.mjs +102 -0
  93. package/dist/es/ai-model/models/kimi.mjs.map +1 -0
  94. package/dist/es/ai-model/models/mimo.mjs +36 -0
  95. package/dist/es/ai-model/models/mimo.mjs.map +1 -0
  96. package/dist/es/ai-model/models/qwen.mjs +139 -0
  97. package/dist/es/ai-model/models/qwen.mjs.map +1 -0
  98. package/dist/es/ai-model/models/registry.mjs +51 -0
  99. package/dist/es/ai-model/models/registry.mjs.map +1 -0
  100. package/dist/es/ai-model/models/ui-tars/actions.mjs +147 -0
  101. package/dist/es/ai-model/models/ui-tars/actions.mjs.map +1 -0
  102. package/dist/es/ai-model/models/ui-tars/adapter.mjs +102 -0
  103. package/dist/es/ai-model/models/ui-tars/adapter.mjs.map +1 -0
  104. package/dist/es/ai-model/models/ui-tars/parser.mjs +40 -0
  105. package/dist/es/ai-model/models/ui-tars/parser.mjs.map +1 -0
  106. package/dist/es/ai-model/models/ui-tars/planning.mjs +25 -0
  107. package/dist/es/ai-model/models/ui-tars/planning.mjs.map +1 -0
  108. package/dist/es/ai-model/models/ui-tars/prompt.mjs +36 -0
  109. package/dist/es/ai-model/models/ui-tars/prompt.mjs.map +1 -0
  110. package/dist/es/ai-model/models/utils/intent.mjs +6 -0
  111. package/dist/es/ai-model/models/utils/intent.mjs.map +1 -0
  112. package/dist/es/ai-model/prompt/insight/index.mjs +3 -0
  113. package/dist/es/ai-model/prompt/insight/system-prompt.mjs +104 -0
  114. package/dist/es/ai-model/prompt/insight/system-prompt.mjs.map +1 -0
  115. package/dist/es/ai-model/prompt/insight/user-prompt.mjs +23 -0
  116. package/dist/es/ai-model/prompt/insight/user-prompt.mjs.map +1 -0
  117. package/dist/es/ai-model/prompt/locate/element-system-prompt.mjs +12 -0
  118. package/dist/es/ai-model/prompt/locate/element-system-prompt.mjs.map +1 -0
  119. package/dist/es/ai-model/prompt/locate/grounding-rules.mjs +13 -0
  120. package/dist/es/ai-model/prompt/locate/grounding-rules.mjs.map +1 -0
  121. package/dist/es/ai-model/prompt/locate/index.mjs +4 -0
  122. package/dist/es/ai-model/prompt/locate/search-area-system-prompt.mjs +9 -0
  123. package/dist/es/ai-model/prompt/locate/search-area-system-prompt.mjs.map +1 -0
  124. package/dist/es/ai-model/prompt/planning/action-output-example.mjs +52 -0
  125. package/dist/es/ai-model/prompt/planning/action-output-example.mjs.map +1 -0
  126. package/dist/es/ai-model/prompt/planning/action-space-description.mjs +28 -0
  127. package/dist/es/ai-model/prompt/planning/action-space-description.mjs.map +1 -0
  128. package/dist/es/ai-model/prompt/planning/index.mjs +6 -0
  129. package/dist/es/ai-model/prompt/planning/multi-turn-example.mjs +221 -0
  130. package/dist/es/ai-model/prompt/planning/multi-turn-example.mjs.map +1 -0
  131. package/dist/es/ai-model/prompt/planning/planning-response-example.mjs +25 -0
  132. package/dist/es/ai-model/prompt/planning/planning-response-example.mjs.map +1 -0
  133. package/dist/es/ai-model/prompt/planning/sub-goals-text.mjs +17 -0
  134. package/dist/es/ai-model/prompt/planning/sub-goals-text.mjs.map +1 -0
  135. package/dist/es/ai-model/prompt/planning/system-prompt.mjs +293 -0
  136. package/dist/es/ai-model/prompt/planning/system-prompt.mjs.map +1 -0
  137. package/dist/es/ai-model/service-caller/codex-app-server.mjs +1 -0
  138. package/dist/es/ai-model/service-caller/codex-app-server.mjs.map +1 -1
  139. package/dist/es/ai-model/service-caller/index.mjs +35 -16
  140. package/dist/es/ai-model/service-caller/index.mjs.map +1 -1
  141. package/dist/es/ai-model/service-caller/model-call-recorder.mjs +74 -0
  142. package/dist/es/ai-model/service-caller/model-call-recorder.mjs.map +1 -0
  143. package/dist/es/ai-model/service-caller/openai-error.mjs +147 -0
  144. package/dist/es/ai-model/service-caller/openai-error.mjs.map +1 -0
  145. package/dist/es/ai-model/service-caller/proxy-deps.node.mjs +9 -0
  146. package/dist/es/ai-model/service-caller/proxy-deps.node.mjs.map +1 -0
  147. package/dist/es/ai-model/service-caller/proxy-deps.stub.mjs +12 -0
  148. package/dist/es/ai-model/service-caller/proxy-deps.stub.mjs.map +1 -0
  149. package/dist/es/ai-model/service-caller/semantic-retry.mjs +33 -0
  150. package/dist/es/ai-model/service-caller/semantic-retry.mjs.map +1 -0
  151. package/dist/es/ai-model/service-caller/types.mjs +0 -0
  152. package/dist/es/ai-model/shared/action-schema.mjs +15 -0
  153. package/dist/es/ai-model/shared/action-schema.mjs.map +1 -0
  154. package/dist/es/ai-model/shared/json.mjs +63 -0
  155. package/dist/es/ai-model/shared/json.mjs.map +1 -0
  156. package/dist/es/ai-model/shared/model-locate-result/bbox.mjs +60 -0
  157. package/dist/es/ai-model/shared/model-locate-result/bbox.mjs.map +1 -0
  158. package/dist/es/ai-model/shared/model-locate-result/coordinate-distance.mjs +10 -0
  159. package/dist/es/ai-model/shared/model-locate-result/coordinate-distance.mjs.map +1 -0
  160. package/dist/es/ai-model/shared/model-locate-result/errors.mjs +9 -0
  161. package/dist/es/ai-model/shared/model-locate-result/errors.mjs.map +1 -0
  162. package/dist/es/ai-model/shared/model-locate-result/factory.mjs +39 -0
  163. package/dist/es/ai-model/shared/model-locate-result/factory.mjs.map +1 -0
  164. package/dist/es/ai-model/shared/model-locate-result/index.mjs +6 -0
  165. package/dist/es/ai-model/shared/model-locate-result/parse.mjs +45 -0
  166. package/dist/es/ai-model/shared/model-locate-result/parse.mjs.map +1 -0
  167. package/dist/es/ai-model/shared/model-locate-result/pixel-bbox-mapper.mjs +67 -0
  168. package/dist/es/ai-model/shared/model-locate-result/pixel-bbox-mapper.mjs.map +1 -0
  169. package/dist/es/ai-model/shared/model-locate-result/prompt-spec.mjs +110 -0
  170. package/dist/es/ai-model/shared/model-locate-result/prompt-spec.mjs.map +1 -0
  171. package/dist/es/ai-model/shared/model-locate-result/types.mjs +9 -0
  172. package/dist/es/ai-model/shared/model-locate-result/types.mjs.map +1 -0
  173. package/dist/es/ai-model/shared/multimodal-prompt.mjs +55 -0
  174. package/dist/es/ai-model/shared/multimodal-prompt.mjs.map +1 -0
  175. package/dist/es/ai-model/shared/xml.mjs +42 -0
  176. package/dist/es/ai-model/shared/xml.mjs.map +1 -0
  177. package/dist/es/ai-model/workflows/grounding/index.mjs +4 -0
  178. package/dist/es/ai-model/workflows/grounding/locate-result-rect.mjs +23 -0
  179. package/dist/es/ai-model/workflows/grounding/locate-result-rect.mjs.map +1 -0
  180. package/dist/es/ai-model/workflows/grounding/locate.mjs +168 -0
  181. package/dist/es/ai-model/workflows/grounding/locate.mjs.map +1 -0
  182. package/dist/es/ai-model/workflows/grounding/planning-action-locate.mjs +97 -0
  183. package/dist/es/ai-model/workflows/grounding/planning-action-locate.mjs.map +1 -0
  184. package/dist/es/ai-model/workflows/grounding/search-area-mapping.mjs +18 -0
  185. package/dist/es/ai-model/workflows/grounding/search-area-mapping.mjs.map +1 -0
  186. package/dist/es/ai-model/workflows/grounding/search-area.mjs +55 -0
  187. package/dist/es/ai-model/workflows/grounding/search-area.mjs.map +1 -0
  188. package/dist/es/ai-model/workflows/grounding/section-locate.mjs +146 -0
  189. package/dist/es/ai-model/workflows/grounding/section-locate.mjs.map +1 -0
  190. package/dist/es/ai-model/workflows/grounding/types.mjs +0 -0
  191. package/dist/es/ai-model/workflows/grounding/utils.mjs +50 -0
  192. package/dist/es/ai-model/workflows/grounding/utils.mjs.map +1 -0
  193. package/dist/es/ai-model/workflows/insight/extraction.mjs +101 -0
  194. package/dist/es/ai-model/workflows/insight/extraction.mjs.map +1 -0
  195. package/dist/es/ai-model/workflows/insight/index.mjs +3 -0
  196. package/dist/es/ai-model/workflows/insight/insight-response-parser.mjs +26 -0
  197. package/dist/es/ai-model/workflows/insight/insight-response-parser.mjs.map +1 -0
  198. package/dist/es/ai-model/workflows/insight/order-sensitive.mjs +29 -0
  199. package/dist/es/ai-model/workflows/insight/order-sensitive.mjs.map +1 -0
  200. package/dist/es/ai-model/workflows/planning/conversation-history.mjs +185 -0
  201. package/dist/es/ai-model/workflows/planning/conversation-history.mjs.map +1 -0
  202. package/dist/es/ai-model/workflows/planning/custom-planning.mjs +129 -0
  203. package/dist/es/ai-model/workflows/planning/custom-planning.mjs.map +1 -0
  204. package/dist/es/ai-model/workflows/planning/index.mjs +4 -0
  205. package/dist/es/ai-model/workflows/planning/locate-normalization.mjs +41 -0
  206. package/dist/es/ai-model/workflows/planning/locate-normalization.mjs.map +1 -0
  207. package/dist/es/ai-model/workflows/planning/planning-action-log.mjs +22 -0
  208. package/dist/es/ai-model/workflows/planning/planning-action-log.mjs.map +1 -0
  209. package/dist/es/ai-model/workflows/planning/standard-planning-parser.mjs +99 -0
  210. package/dist/es/ai-model/workflows/planning/standard-planning-parser.mjs.map +1 -0
  211. package/dist/es/ai-model/workflows/planning/standard-planning.mjs +219 -0
  212. package/dist/es/ai-model/workflows/planning/standard-planning.mjs.map +1 -0
  213. package/dist/es/ai-model/workflows/planning/types.mjs +0 -0
  214. package/dist/es/ai-model/workflows/recorder-generation/common.mjs +171 -0
  215. package/dist/es/ai-model/workflows/recorder-generation/common.mjs.map +1 -0
  216. package/dist/es/ai-model/workflows/recorder-generation/index.mjs +5 -0
  217. package/dist/es/ai-model/workflows/recorder-generation/markdown.mjs +253 -0
  218. package/dist/es/ai-model/workflows/recorder-generation/markdown.mjs.map +1 -0
  219. package/dist/es/ai-model/workflows/recorder-generation/metadata.mjs +83 -0
  220. package/dist/es/ai-model/workflows/recorder-generation/metadata.mjs.map +1 -0
  221. package/dist/es/ai-model/workflows/recorder-generation/playwright.mjs +123 -0
  222. package/dist/es/ai-model/workflows/recorder-generation/playwright.mjs.map +1 -0
  223. package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs +162 -0
  224. package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs.map +1 -0
  225. package/dist/es/common.mjs +12 -1
  226. package/dist/es/common.mjs.map +1 -1
  227. package/dist/es/constants.mjs +4 -0
  228. package/dist/es/constants.mjs.map +1 -0
  229. package/dist/es/device/index.mjs.map +1 -1
  230. package/dist/es/device/input-strategy.mjs +34 -0
  231. package/dist/es/device/input-strategy.mjs.map +1 -0
  232. package/dist/es/dump/html-utils.mjs +16 -1
  233. package/dist/es/dump/html-utils.mjs.map +1 -1
  234. package/dist/es/dump/image-reference.mjs +63 -0
  235. package/dist/es/dump/image-reference.mjs.map +1 -0
  236. package/dist/es/dump/report-action-dump.mjs +244 -0
  237. package/dist/es/dump/report-action-dump.mjs.map +1 -0
  238. package/dist/es/dump/report-dump-compactor.mjs +200 -0
  239. package/dist/es/dump/report-dump-compactor.mjs.map +1 -0
  240. package/dist/es/dump/screenshot-store.mjs +124 -37
  241. package/dist/es/dump/screenshot-store.mjs.map +1 -1
  242. package/dist/es/dump/task-service-dump.mjs +17 -0
  243. package/dist/es/dump/task-service-dump.mjs.map +1 -0
  244. package/dist/es/dump/task-status.mjs +18 -0
  245. package/dist/es/dump/task-status.mjs.map +1 -0
  246. package/dist/es/element-describer.mjs +198 -0
  247. package/dist/es/element-describer.mjs.map +1 -0
  248. package/dist/es/errors.mjs +20 -0
  249. package/dist/es/errors.mjs.map +1 -0
  250. package/dist/es/report-html-template.mjs +4 -0
  251. package/dist/es/report-html-template.mjs.map +1 -0
  252. package/dist/es/report-stats.mjs +113 -0
  253. package/dist/es/report-stats.mjs.map +1 -0
  254. package/dist/es/screenshot-item.mjs +7 -2
  255. package/dist/es/screenshot-item.mjs.map +1 -1
  256. package/dist/es/service/index.mjs +10 -5
  257. package/dist/es/service/index.mjs.map +1 -1
  258. package/dist/es/task-runner.mjs.map +1 -1
  259. package/dist/es/types.mjs.map +1 -1
  260. package/dist/es/utils.mjs +1 -1
  261. package/dist/es/yaml/cleanup.mjs +13 -0
  262. package/dist/es/yaml/cleanup.mjs.map +1 -0
  263. package/dist/lib/agent/agent.js +24 -11
  264. package/dist/lib/agent/agent.js.map +1 -1
  265. package/dist/lib/agent/cache-config.js +53 -0
  266. package/dist/lib/agent/cache-config.js.map +1 -0
  267. package/dist/lib/agent/file-chooser.js +125 -0
  268. package/dist/lib/agent/file-chooser.js.map +1 -0
  269. package/dist/lib/agent/insight.js +135 -0
  270. package/dist/lib/agent/insight.js.map +1 -0
  271. package/dist/lib/agent/metrics.js +115 -0
  272. package/dist/lib/agent/metrics.js.map +1 -0
  273. package/dist/lib/agent/progress/ai-act-progress.js +239 -0
  274. package/dist/lib/agent/progress/ai-act-progress.js.map +1 -0
  275. package/dist/lib/agent/progress/index.js +67 -0
  276. package/dist/lib/agent/progress/index.js.map +1 -0
  277. package/dist/lib/agent/progress/progress-bus.js +86 -0
  278. package/dist/lib/agent/progress/progress-bus.js.map +1 -0
  279. package/dist/lib/agent/prompt-context.js +62 -0
  280. package/dist/lib/agent/prompt-context.js.map +1 -0
  281. package/dist/lib/agent/record-to-report.js +48 -0
  282. package/dist/lib/agent/record-to-report.js.map +1 -0
  283. package/dist/lib/agent/run-gherkin-scenario.js +151 -0
  284. package/dist/lib/agent/run-gherkin-scenario.js.map +1 -0
  285. package/dist/lib/agent/run-markdown.js +96 -0
  286. package/dist/lib/agent/run-markdown.js.map +1 -0
  287. package/dist/lib/agent/screenshot-preparation.js +74 -0
  288. package/dist/lib/agent/screenshot-preparation.js.map +1 -0
  289. package/dist/lib/agent/ui-observer.js +425 -0
  290. package/dist/lib/agent/ui-observer.js.map +1 -0
  291. package/dist/lib/agent/utils.js +46 -2
  292. package/dist/lib/agent/utils.js.map +1 -1
  293. package/dist/lib/ai-model/connectivity/fixture.js +45 -0
  294. package/dist/lib/ai-model/connectivity/fixture.js.map +1 -0
  295. package/dist/lib/ai-model/connectivity/index.js +38 -0
  296. package/dist/lib/ai-model/connectivity/index.js.map +1 -0
  297. package/dist/lib/ai-model/connectivity/run-connectivity-test.js +204 -0
  298. package/dist/lib/ai-model/connectivity/run-connectivity-test.js.map +1 -0
  299. package/dist/lib/ai-model/conversation-history.js.map +1 -1
  300. package/dist/lib/ai-model/index.js +15 -11
  301. package/dist/lib/ai-model/inspect.js +1 -1
  302. package/dist/lib/ai-model/inspect.js.map +1 -1
  303. package/dist/lib/ai-model/model-adapter/chat-completion.js +103 -0
  304. package/dist/lib/ai-model/model-adapter/chat-completion.js.map +1 -0
  305. package/dist/lib/ai-model/model-adapter/custom-planning-action.js +40 -0
  306. package/dist/lib/ai-model/model-adapter/custom-planning-action.js.map +1 -0
  307. package/dist/lib/ai-model/model-adapter/custom-planning-types.js +20 -0
  308. package/dist/lib/ai-model/model-adapter/custom-planning-types.js.map +1 -0
  309. package/dist/lib/ai-model/model-adapter/default-insight-protocol.js +62 -0
  310. package/dist/lib/ai-model/model-adapter/default-insight-protocol.js.map +1 -0
  311. package/dist/lib/ai-model/model-adapter/default-locate-protocol.js +182 -0
  312. package/dist/lib/ai-model/model-adapter/default-locate-protocol.js.map +1 -0
  313. package/dist/lib/ai-model/model-adapter/default-planning-protocol.js +170 -0
  314. package/dist/lib/ai-model/model-adapter/default-planning-protocol.js.map +1 -0
  315. package/dist/lib/ai-model/model-adapter/image-preprocess.js +61 -0
  316. package/dist/lib/ai-model/model-adapter/image-preprocess.js.map +1 -0
  317. package/dist/lib/ai-model/model-adapter/index.js +38 -0
  318. package/dist/lib/ai-model/model-adapter/index.js.map +1 -0
  319. package/dist/lib/ai-model/model-adapter/insight-protocol.js +20 -0
  320. package/dist/lib/ai-model/model-adapter/insight-protocol.js.map +1 -0
  321. package/dist/lib/ai-model/model-adapter/insight.js +50 -0
  322. package/dist/lib/ai-model/model-adapter/insight.js.map +1 -0
  323. package/dist/lib/ai-model/model-adapter/locate-protocol.js +20 -0
  324. package/dist/lib/ai-model/model-adapter/locate-protocol.js.map +1 -0
  325. package/dist/lib/ai-model/model-adapter/locate.js +87 -0
  326. package/dist/lib/ai-model/model-adapter/locate.js.map +1 -0
  327. package/dist/lib/ai-model/model-adapter/planning-protocol.js +20 -0
  328. package/dist/lib/ai-model/model-adapter/planning-protocol.js.map +1 -0
  329. package/dist/lib/ai-model/model-adapter/planning.js +86 -0
  330. package/dist/lib/ai-model/model-adapter/planning.js.map +1 -0
  331. package/dist/lib/ai-model/model-adapter/resolve.js +88 -0
  332. package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -0
  333. package/dist/lib/ai-model/model-adapter/types.js +20 -0
  334. package/dist/lib/ai-model/model-adapter/types.js.map +1 -0
  335. package/dist/lib/ai-model/models/auto-glm/actions.js +239 -0
  336. package/dist/lib/ai-model/models/auto-glm/actions.js.map +1 -0
  337. package/dist/lib/ai-model/models/auto-glm/adapter.js +79 -0
  338. package/dist/lib/ai-model/models/auto-glm/adapter.js.map +1 -0
  339. package/dist/lib/ai-model/models/auto-glm/locate.js +45 -0
  340. package/dist/lib/ai-model/models/auto-glm/locate.js.map +1 -0
  341. package/dist/lib/ai-model/models/auto-glm/parser.js +260 -0
  342. package/dist/lib/ai-model/models/auto-glm/parser.js.map +1 -0
  343. package/dist/lib/ai-model/models/auto-glm/planning.js +67 -0
  344. package/dist/lib/ai-model/models/auto-glm/planning.js.map +1 -0
  345. package/dist/lib/ai-model/models/auto-glm/prompt.js +257 -0
  346. package/dist/lib/ai-model/models/auto-glm/prompt.js.map +1 -0
  347. package/dist/lib/ai-model/models/deepseek/adapter.js +113 -0
  348. package/dist/lib/ai-model/models/deepseek/adapter.js.map +1 -0
  349. package/dist/lib/ai-model/models/deepseek/locate-protocol.js +132 -0
  350. package/dist/lib/ai-model/models/deepseek/locate-protocol.js.map +1 -0
  351. package/dist/lib/ai-model/models/default.js +47 -0
  352. package/dist/lib/ai-model/models/default.js.map +1 -0
  353. package/dist/lib/ai-model/models/doubao.js +132 -0
  354. package/dist/lib/ai-model/models/doubao.js.map +1 -0
  355. package/dist/lib/ai-model/models/gemini.js +137 -0
  356. package/dist/lib/ai-model/models/gemini.js.map +1 -0
  357. package/dist/lib/ai-model/models/glm.js +80 -0
  358. package/dist/lib/ai-model/models/glm.js.map +1 -0
  359. package/dist/lib/ai-model/models/gpt.js +77 -0
  360. package/dist/lib/ai-model/models/gpt.js.map +1 -0
  361. package/dist/lib/ai-model/models/index.js +41 -0
  362. package/dist/lib/ai-model/models/index.js.map +1 -0
  363. package/dist/lib/ai-model/models/kimi.js +136 -0
  364. package/dist/lib/ai-model/models/kimi.js.map +1 -0
  365. package/dist/lib/ai-model/models/mimo.js +70 -0
  366. package/dist/lib/ai-model/models/mimo.js.map +1 -0
  367. package/dist/lib/ai-model/models/qwen.js +173 -0
  368. package/dist/lib/ai-model/models/qwen.js.map +1 -0
  369. package/dist/lib/ai-model/models/registry.js +91 -0
  370. package/dist/lib/ai-model/models/registry.js.map +1 -0
  371. package/dist/lib/ai-model/models/ui-tars/actions.js +181 -0
  372. package/dist/lib/ai-model/models/ui-tars/actions.js.map +1 -0
  373. package/dist/lib/ai-model/models/ui-tars/adapter.js +136 -0
  374. package/dist/lib/ai-model/models/ui-tars/adapter.js.map +1 -0
  375. package/dist/lib/ai-model/models/ui-tars/parser.js +74 -0
  376. package/dist/lib/ai-model/models/ui-tars/parser.js.map +1 -0
  377. package/dist/lib/ai-model/models/ui-tars/planning.js +59 -0
  378. package/dist/lib/ai-model/models/ui-tars/planning.js.map +1 -0
  379. package/dist/lib/ai-model/models/ui-tars/prompt.js +73 -0
  380. package/dist/lib/ai-model/models/ui-tars/prompt.js.map +1 -0
  381. package/dist/lib/ai-model/models/utils/intent.js +40 -0
  382. package/dist/lib/ai-model/models/utils/intent.js.map +1 -0
  383. package/dist/lib/ai-model/prompt/insight/index.js +45 -0
  384. package/dist/lib/ai-model/prompt/insight/index.js.map +1 -0
  385. package/dist/lib/ai-model/prompt/insight/system-prompt.js +138 -0
  386. package/dist/lib/ai-model/prompt/insight/system-prompt.js.map +1 -0
  387. package/dist/lib/ai-model/prompt/insight/user-prompt.js +60 -0
  388. package/dist/lib/ai-model/prompt/insight/user-prompt.js.map +1 -0
  389. package/dist/lib/ai-model/prompt/locate/element-system-prompt.js +46 -0
  390. package/dist/lib/ai-model/prompt/locate/element-system-prompt.js.map +1 -0
  391. package/dist/lib/ai-model/prompt/locate/grounding-rules.js +47 -0
  392. package/dist/lib/ai-model/prompt/locate/grounding-rules.js.map +1 -0
  393. package/dist/lib/ai-model/prompt/locate/index.js +46 -0
  394. package/dist/lib/ai-model/prompt/locate/index.js.map +1 -0
  395. package/dist/lib/ai-model/prompt/locate/search-area-system-prompt.js +43 -0
  396. package/dist/lib/ai-model/prompt/locate/search-area-system-prompt.js.map +1 -0
  397. package/dist/lib/ai-model/prompt/planning/action-output-example.js +92 -0
  398. package/dist/lib/ai-model/prompt/planning/action-output-example.js.map +1 -0
  399. package/dist/lib/ai-model/prompt/planning/action-space-description.js +75 -0
  400. package/dist/lib/ai-model/prompt/planning/action-space-description.js.map +1 -0
  401. package/dist/lib/ai-model/prompt/planning/index.js +63 -0
  402. package/dist/lib/ai-model/prompt/planning/index.js.map +1 -0
  403. package/dist/lib/ai-model/prompt/planning/multi-turn-example.js +255 -0
  404. package/dist/lib/ai-model/prompt/planning/multi-turn-example.js.map +1 -0
  405. package/dist/lib/ai-model/prompt/planning/planning-response-example.js +59 -0
  406. package/dist/lib/ai-model/prompt/planning/planning-response-example.js.map +1 -0
  407. package/dist/lib/ai-model/prompt/planning/sub-goals-text.js +51 -0
  408. package/dist/lib/ai-model/prompt/planning/sub-goals-text.js.map +1 -0
  409. package/dist/lib/ai-model/prompt/planning/system-prompt.js +327 -0
  410. package/dist/lib/ai-model/prompt/planning/system-prompt.js.map +1 -0
  411. package/dist/lib/ai-model/service-caller/codex-app-server.js +1 -0
  412. package/dist/lib/ai-model/service-caller/codex-app-server.js.map +1 -1
  413. package/dist/lib/ai-model/service-caller/index.js +35 -16
  414. package/dist/lib/ai-model/service-caller/index.js.map +1 -1
  415. package/dist/lib/ai-model/service-caller/model-call-recorder.js +124 -0
  416. package/dist/lib/ai-model/service-caller/model-call-recorder.js.map +1 -0
  417. package/dist/lib/ai-model/service-caller/openai-error.js +184 -0
  418. package/dist/lib/ai-model/service-caller/openai-error.js.map +1 -0
  419. package/dist/lib/ai-model/service-caller/proxy-deps.node.js +46 -0
  420. package/dist/lib/ai-model/service-caller/proxy-deps.node.js.map +1 -0
  421. package/dist/lib/ai-model/service-caller/proxy-deps.stub.js +49 -0
  422. package/dist/lib/ai-model/service-caller/proxy-deps.stub.js.map +1 -0
  423. package/dist/lib/ai-model/service-caller/semantic-retry.js +70 -0
  424. package/dist/lib/ai-model/service-caller/semantic-retry.js.map +1 -0
  425. package/dist/lib/ai-model/service-caller/types.js +20 -0
  426. package/dist/lib/ai-model/service-caller/types.js.map +1 -0
  427. package/dist/lib/ai-model/shared/action-schema.js +49 -0
  428. package/dist/lib/ai-model/shared/action-schema.js.map +1 -0
  429. package/dist/lib/ai-model/shared/json.js +103 -0
  430. package/dist/lib/ai-model/shared/json.js.map +1 -0
  431. package/dist/lib/ai-model/shared/model-locate-result/bbox.js +106 -0
  432. package/dist/lib/ai-model/shared/model-locate-result/bbox.js.map +1 -0
  433. package/dist/lib/ai-model/shared/model-locate-result/coordinate-distance.js +44 -0
  434. package/dist/lib/ai-model/shared/model-locate-result/coordinate-distance.js.map +1 -0
  435. package/dist/lib/ai-model/shared/model-locate-result/errors.js +46 -0
  436. package/dist/lib/ai-model/shared/model-locate-result/errors.js.map +1 -0
  437. package/dist/lib/ai-model/shared/model-locate-result/factory.js +76 -0
  438. package/dist/lib/ai-model/shared/model-locate-result/factory.js.map +1 -0
  439. package/dist/lib/ai-model/shared/model-locate-result/index.js +66 -0
  440. package/dist/lib/ai-model/shared/model-locate-result/index.js.map +1 -0
  441. package/dist/lib/ai-model/shared/model-locate-result/parse.js +88 -0
  442. package/dist/lib/ai-model/shared/model-locate-result/parse.js.map +1 -0
  443. package/dist/lib/ai-model/shared/model-locate-result/pixel-bbox-mapper.js +101 -0
  444. package/dist/lib/ai-model/shared/model-locate-result/pixel-bbox-mapper.js.map +1 -0
  445. package/dist/lib/ai-model/shared/model-locate-result/prompt-spec.js +156 -0
  446. package/dist/lib/ai-model/shared/model-locate-result/prompt-spec.js.map +1 -0
  447. package/dist/lib/ai-model/shared/model-locate-result/types.js +46 -0
  448. package/dist/lib/ai-model/shared/model-locate-result/types.js.map +1 -0
  449. package/dist/lib/ai-model/shared/multimodal-prompt.js +95 -0
  450. package/dist/lib/ai-model/shared/multimodal-prompt.js.map +1 -0
  451. package/dist/lib/ai-model/shared/xml.js +79 -0
  452. package/dist/lib/ai-model/shared/xml.js.map +1 -0
  453. package/dist/lib/ai-model/workflows/grounding/index.js +46 -0
  454. package/dist/lib/ai-model/workflows/grounding/index.js.map +1 -0
  455. package/dist/lib/ai-model/workflows/grounding/locate-result-rect.js +60 -0
  456. package/dist/lib/ai-model/workflows/grounding/locate-result-rect.js.map +1 -0
  457. package/dist/lib/ai-model/workflows/grounding/locate.js +208 -0
  458. package/dist/lib/ai-model/workflows/grounding/locate.js.map +1 -0
  459. package/dist/lib/ai-model/workflows/grounding/planning-action-locate.js +131 -0
  460. package/dist/lib/ai-model/workflows/grounding/planning-action-locate.js.map +1 -0
  461. package/dist/lib/ai-model/workflows/grounding/search-area-mapping.js +52 -0
  462. package/dist/lib/ai-model/workflows/grounding/search-area-mapping.js.map +1 -0
  463. package/dist/lib/ai-model/workflows/grounding/search-area.js +92 -0
  464. package/dist/lib/ai-model/workflows/grounding/search-area.js.map +1 -0
  465. package/dist/lib/ai-model/workflows/grounding/section-locate.js +180 -0
  466. package/dist/lib/ai-model/workflows/grounding/section-locate.js.map +1 -0
  467. package/dist/lib/ai-model/workflows/grounding/types.js +20 -0
  468. package/dist/lib/ai-model/workflows/grounding/types.js.map +1 -0
  469. package/dist/lib/ai-model/workflows/grounding/utils.js +87 -0
  470. package/dist/lib/ai-model/workflows/grounding/utils.js.map +1 -0
  471. package/dist/lib/ai-model/workflows/insight/extraction.js +135 -0
  472. package/dist/lib/ai-model/workflows/insight/extraction.js.map +1 -0
  473. package/dist/lib/ai-model/workflows/insight/index.js +42 -0
  474. package/dist/lib/ai-model/workflows/insight/index.js.map +1 -0
  475. package/dist/lib/ai-model/workflows/insight/insight-response-parser.js +60 -0
  476. package/dist/lib/ai-model/workflows/insight/insight-response-parser.js.map +1 -0
  477. package/dist/lib/ai-model/workflows/insight/order-sensitive.js +63 -0
  478. package/dist/lib/ai-model/workflows/insight/order-sensitive.js.map +1 -0
  479. package/dist/lib/ai-model/workflows/planning/conversation-history.js +219 -0
  480. package/dist/lib/ai-model/workflows/planning/conversation-history.js.map +1 -0
  481. package/dist/lib/ai-model/workflows/planning/custom-planning.js +166 -0
  482. package/dist/lib/ai-model/workflows/planning/custom-planning.js.map +1 -0
  483. package/dist/lib/ai-model/workflows/planning/index.js +49 -0
  484. package/dist/lib/ai-model/workflows/planning/index.js.map +1 -0
  485. package/dist/lib/ai-model/workflows/planning/locate-normalization.js +75 -0
  486. package/dist/lib/ai-model/workflows/planning/locate-normalization.js.map +1 -0
  487. package/dist/lib/ai-model/workflows/planning/planning-action-log.js +56 -0
  488. package/dist/lib/ai-model/workflows/planning/planning-action-log.js.map +1 -0
  489. package/dist/lib/ai-model/workflows/planning/standard-planning-parser.js +142 -0
  490. package/dist/lib/ai-model/workflows/planning/standard-planning-parser.js.map +1 -0
  491. package/dist/lib/ai-model/workflows/planning/standard-planning.js +253 -0
  492. package/dist/lib/ai-model/workflows/planning/standard-planning.js.map +1 -0
  493. package/dist/lib/ai-model/workflows/planning/types.js +20 -0
  494. package/dist/lib/ai-model/workflows/planning/types.js.map +1 -0
  495. package/dist/lib/ai-model/workflows/recorder-generation/common.js +232 -0
  496. package/dist/lib/ai-model/workflows/recorder-generation/common.js.map +1 -0
  497. package/dist/lib/ai-model/workflows/recorder-generation/index.js +68 -0
  498. package/dist/lib/ai-model/workflows/recorder-generation/index.js.map +1 -0
  499. package/dist/lib/ai-model/workflows/recorder-generation/markdown.js +293 -0
  500. package/dist/lib/ai-model/workflows/recorder-generation/markdown.js.map +1 -0
  501. package/dist/lib/ai-model/workflows/recorder-generation/metadata.js +117 -0
  502. package/dist/lib/ai-model/workflows/recorder-generation/metadata.js.map +1 -0
  503. package/dist/lib/ai-model/workflows/recorder-generation/playwright.js +184 -0
  504. package/dist/lib/ai-model/workflows/recorder-generation/playwright.js.map +1 -0
  505. package/dist/lib/ai-model/workflows/recorder-generation/yaml.js +232 -0
  506. package/dist/lib/ai-model/workflows/recorder-generation/yaml.js.map +1 -0
  507. package/dist/lib/common.js +18 -1
  508. package/dist/lib/common.js.map +1 -1
  509. package/dist/lib/constants.js +38 -0
  510. package/dist/lib/constants.js.map +1 -0
  511. package/dist/lib/device/index.js.map +1 -1
  512. package/dist/lib/device/input-strategy.js +80 -0
  513. package/dist/lib/device/input-strategy.js.map +1 -0
  514. package/dist/lib/dump/html-utils.js +18 -0
  515. package/dist/lib/dump/html-utils.js.map +1 -1
  516. package/dist/lib/dump/image-reference.js +115 -0
  517. package/dist/lib/dump/image-reference.js.map +1 -0
  518. package/dist/lib/dump/report-action-dump.js +284 -0
  519. package/dist/lib/dump/report-action-dump.js.map +1 -0
  520. package/dist/lib/dump/report-dump-compactor.js +234 -0
  521. package/dist/lib/dump/report-dump-compactor.js.map +1 -0
  522. package/dist/lib/dump/screenshot-store.js +146 -38
  523. package/dist/lib/dump/screenshot-store.js.map +1 -1
  524. package/dist/lib/dump/task-service-dump.js +54 -0
  525. package/dist/lib/dump/task-service-dump.js.map +1 -0
  526. package/dist/lib/dump/task-status.js +55 -0
  527. package/dist/lib/dump/task-status.js.map +1 -0
  528. package/dist/lib/element-describer.js +238 -0
  529. package/dist/lib/element-describer.js.map +1 -0
  530. package/dist/lib/errors.js +54 -0
  531. package/dist/lib/errors.js.map +1 -0
  532. package/dist/lib/report-html-template.js +38 -0
  533. package/dist/lib/report-html-template.js.map +1 -0
  534. package/dist/lib/report-stats.js +147 -0
  535. package/dist/lib/report-stats.js.map +1 -0
  536. package/dist/lib/screenshot-item.js +7 -2
  537. package/dist/lib/screenshot-item.js.map +1 -1
  538. package/dist/lib/service/index.js +10 -5
  539. package/dist/lib/service/index.js.map +1 -1
  540. package/dist/lib/task-runner.js.map +1 -1
  541. package/dist/lib/types.js +2 -2
  542. package/dist/lib/types.js.map +1 -1
  543. package/dist/lib/utils.js +1 -1
  544. package/dist/lib/yaml/cleanup.js +47 -0
  545. package/dist/lib/yaml/cleanup.js.map +1 -0
  546. package/dist/types/agent/agent.d.ts +5 -9
  547. package/dist/types/agent/cache-config.d.ts +2 -0
  548. package/dist/types/agent/file-chooser.d.ts +19 -0
  549. package/dist/types/agent/insight.d.ts +21 -0
  550. package/dist/types/agent/metrics.d.ts +48 -0
  551. package/dist/types/agent/progress/ai-act-progress.d.ts +21 -0
  552. package/dist/types/agent/progress/index.d.ts +2 -0
  553. package/dist/types/agent/progress/progress-bus.d.ts +33 -0
  554. package/dist/types/agent/prompt-context.d.ts +3 -0
  555. package/dist/types/agent/record-to-report.d.ts +2 -0
  556. package/dist/types/agent/run-gherkin-scenario.d.ts +26 -0
  557. package/dist/types/agent/run-markdown.d.ts +6 -0
  558. package/dist/types/agent/screenshot-preparation.d.ts +20 -0
  559. package/dist/types/agent/ui-observer.d.ts +103 -0
  560. package/dist/types/agent/utils.d.ts +12 -1
  561. package/dist/types/ai-model/connectivity/fixture.d.ts +5 -0
  562. package/dist/types/ai-model/connectivity/index.d.ts +1 -0
  563. package/dist/types/ai-model/connectivity/run-connectivity-test.d.ts +11 -0
  564. package/dist/types/ai-model/index.d.ts +2 -0
  565. package/dist/types/ai-model/model-adapter/chat-completion.d.ts +2 -0
  566. package/dist/types/ai-model/model-adapter/custom-planning-action.d.ts +25 -0
  567. package/dist/types/ai-model/model-adapter/custom-planning-types.d.ts +31 -0
  568. package/dist/types/ai-model/model-adapter/default-insight-protocol.d.ts +2 -0
  569. package/dist/types/ai-model/model-adapter/default-locate-protocol.d.ts +7 -0
  570. package/dist/types/ai-model/model-adapter/default-planning-protocol.d.ts +25 -0
  571. package/dist/types/ai-model/model-adapter/image-preprocess.d.ts +30 -0
  572. package/dist/types/ai-model/model-adapter/index.d.ts +2 -0
  573. package/dist/types/ai-model/model-adapter/insight-protocol.d.ts +24 -0
  574. package/dist/types/ai-model/model-adapter/insight.d.ts +3 -0
  575. package/dist/types/ai-model/model-adapter/locate-protocol.d.ts +23 -0
  576. package/dist/types/ai-model/model-adapter/locate.d.ts +4 -0
  577. package/dist/types/ai-model/model-adapter/planning-protocol.d.ts +53 -0
  578. package/dist/types/ai-model/model-adapter/planning.d.ts +6 -0
  579. package/dist/types/ai-model/model-adapter/resolve.d.ts +12 -0
  580. package/dist/types/ai-model/model-adapter/types.d.ts +218 -0
  581. package/dist/types/ai-model/models/auto-glm/actions.d.ts +81 -0
  582. package/dist/types/ai-model/models/auto-glm/adapter.d.ts +5 -0
  583. package/dist/types/ai-model/models/auto-glm/locate.d.ts +2 -0
  584. package/dist/types/ai-model/models/auto-glm/parser.d.ts +14 -0
  585. package/dist/types/ai-model/models/auto-glm/planning.d.ts +5 -0
  586. package/dist/types/ai-model/models/auto-glm/prompt.d.ts +4 -0
  587. package/dist/types/ai-model/models/deepseek/adapter.d.ts +39 -0
  588. package/dist/types/ai-model/models/deepseek/locate-protocol.d.ts +5 -0
  589. package/dist/types/ai-model/models/default.d.ts +2 -0
  590. package/dist/types/ai-model/models/doubao.d.ts +7 -0
  591. package/dist/types/ai-model/models/gemini.d.ts +37 -0
  592. package/dist/types/ai-model/models/glm.d.ts +21 -0
  593. package/dist/types/ai-model/models/gpt.d.ts +20 -0
  594. package/dist/types/ai-model/models/index.d.ts +2 -0
  595. package/dist/types/ai-model/models/kimi.d.ts +45 -0
  596. package/dist/types/ai-model/models/mimo.d.ts +10 -0
  597. package/dist/types/ai-model/models/qwen.d.ts +33 -0
  598. package/dist/types/ai-model/models/registry.d.ts +187 -0
  599. package/dist/types/ai-model/models/ui-tars/actions.d.ts +3 -0
  600. package/dist/types/ai-model/models/ui-tars/adapter.d.ts +6 -0
  601. package/dist/types/ai-model/models/ui-tars/parser.d.ts +72 -0
  602. package/dist/types/ai-model/models/ui-tars/planning.d.ts +4 -0
  603. package/dist/types/ai-model/models/ui-tars/prompt.d.ts +2 -0
  604. package/dist/types/ai-model/models/utils/intent.d.ts +2 -0
  605. package/dist/types/ai-model/prompt/insight/index.d.ts +2 -0
  606. package/dist/types/ai-model/prompt/insight/system-prompt.d.ts +6 -0
  607. package/dist/types/ai-model/prompt/insight/user-prompt.d.ts +3 -0
  608. package/dist/types/ai-model/prompt/locate/element-system-prompt.d.ts +4 -0
  609. package/dist/types/ai-model/prompt/locate/grounding-rules.d.ts +1 -0
  610. package/dist/types/ai-model/prompt/locate/index.d.ts +3 -0
  611. package/dist/types/ai-model/prompt/locate/search-area-system-prompt.d.ts +4 -0
  612. package/dist/types/ai-model/prompt/planning/action-output-example.d.ts +17 -0
  613. package/dist/types/ai-model/prompt/planning/action-space-description.d.ts +11 -0
  614. package/dist/types/ai-model/prompt/planning/index.d.ts +6 -0
  615. package/dist/types/ai-model/prompt/planning/multi-turn-example.d.ts +10 -0
  616. package/dist/types/ai-model/prompt/planning/planning-response-example.d.ts +28 -0
  617. package/dist/types/ai-model/prompt/planning/sub-goals-text.d.ts +2 -0
  618. package/dist/types/ai-model/prompt/planning/system-prompt.d.ts +18 -0
  619. package/dist/types/ai-model/service-caller/index.d.ts +21 -6
  620. package/dist/types/ai-model/service-caller/model-call-recorder.d.ts +12 -0
  621. package/dist/types/ai-model/service-caller/openai-error.d.ts +26 -0
  622. package/dist/types/ai-model/service-caller/proxy-deps.node.d.ts +2 -0
  623. package/dist/types/ai-model/service-caller/proxy-deps.stub.d.ts +2 -0
  624. package/dist/types/ai-model/service-caller/semantic-retry.d.ts +30 -0
  625. package/dist/types/ai-model/service-caller/types.d.ts +2 -0
  626. package/dist/types/ai-model/shared/action-schema.d.ts +4 -0
  627. package/dist/types/ai-model/shared/json.d.ts +26 -0
  628. package/dist/types/ai-model/shared/model-locate-result/bbox.d.ts +6 -0
  629. package/dist/types/ai-model/shared/model-locate-result/coordinate-distance.d.ts +4 -0
  630. package/dist/types/ai-model/shared/model-locate-result/errors.d.ts +2 -0
  631. package/dist/types/ai-model/shared/model-locate-result/factory.d.ts +3 -0
  632. package/dist/types/ai-model/shared/model-locate-result/index.d.ts +7 -0
  633. package/dist/types/ai-model/shared/model-locate-result/parse.d.ts +8 -0
  634. package/dist/types/ai-model/shared/model-locate-result/pixel-bbox-mapper.d.ts +7 -0
  635. package/dist/types/ai-model/shared/model-locate-result/prompt-spec.d.ts +6 -0
  636. package/dist/types/ai-model/shared/model-locate-result/types.d.ts +150 -0
  637. package/dist/types/ai-model/shared/multimodal-prompt.d.ts +13 -0
  638. package/dist/types/ai-model/shared/xml.d.ts +15 -0
  639. package/dist/types/ai-model/workflows/grounding/index.d.ts +3 -0
  640. package/dist/types/ai-model/workflows/grounding/locate-result-rect.d.ts +5 -0
  641. package/dist/types/ai-model/workflows/grounding/locate.d.ts +7 -0
  642. package/dist/types/ai-model/workflows/grounding/planning-action-locate.d.ts +4 -0
  643. package/dist/types/ai-model/workflows/grounding/search-area-mapping.d.ts +4 -0
  644. package/dist/types/ai-model/workflows/grounding/search-area.d.ts +18 -0
  645. package/dist/types/ai-model/workflows/grounding/section-locate.d.ts +16 -0
  646. package/dist/types/ai-model/workflows/grounding/types.d.ts +56 -0
  647. package/dist/types/ai-model/workflows/grounding/utils.d.ts +25 -0
  648. package/dist/types/ai-model/workflows/insight/extraction.d.ts +18 -0
  649. package/dist/types/ai-model/workflows/insight/index.d.ts +2 -0
  650. package/dist/types/ai-model/workflows/insight/insight-response-parser.d.ts +4 -0
  651. package/dist/types/ai-model/workflows/insight/order-sensitive.d.ts +6 -0
  652. package/dist/types/ai-model/workflows/planning/conversation-history.d.ts +105 -0
  653. package/dist/types/ai-model/workflows/planning/custom-planning.d.ts +7 -0
  654. package/dist/types/ai-model/workflows/planning/index.d.ts +3 -0
  655. package/dist/types/ai-model/workflows/planning/locate-normalization.d.ts +12 -0
  656. package/dist/types/ai-model/workflows/planning/planning-action-log.d.ts +2 -0
  657. package/dist/types/ai-model/workflows/planning/standard-planning-parser.d.ts +31 -0
  658. package/dist/types/ai-model/workflows/planning/standard-planning.d.ts +4 -0
  659. package/dist/types/ai-model/workflows/planning/types.d.ts +16 -0
  660. package/dist/types/ai-model/workflows/recorder-generation/common.d.ts +89 -0
  661. package/dist/types/ai-model/workflows/recorder-generation/index.d.ts +7 -0
  662. package/dist/types/ai-model/workflows/recorder-generation/markdown.d.ts +7 -0
  663. package/dist/types/ai-model/workflows/recorder-generation/metadata.d.ts +13 -0
  664. package/dist/types/ai-model/workflows/recorder-generation/playwright.d.ts +26 -0
  665. package/dist/types/ai-model/workflows/recorder-generation/yaml.d.ts +17 -0
  666. package/dist/types/common.d.ts +2 -0
  667. package/dist/types/constants.d.ts +1 -0
  668. package/dist/types/device/index.d.ts +15 -4
  669. package/dist/types/device/input-strategy.d.ts +44 -0
  670. package/dist/types/dump/html-utils.d.ts +1 -0
  671. package/dist/types/dump/image-reference.d.ts +36 -0
  672. package/dist/types/dump/report-action-dump.d.ts +127 -0
  673. package/dist/types/dump/report-dump-compactor.d.ts +7 -0
  674. package/dist/types/dump/screenshot-store.d.ts +32 -15
  675. package/dist/types/dump/task-service-dump.d.ts +3 -0
  676. package/dist/types/dump/task-status.d.ts +41 -0
  677. package/dist/types/element-describer.d.ts +43 -0
  678. package/dist/types/errors.d.ts +5 -0
  679. package/dist/types/report-html-template.d.ts +1 -0
  680. package/dist/types/report-stats.d.ts +39 -0
  681. package/dist/types/screenshot-item.d.ts +1 -0
  682. package/dist/types/service/index.d.ts +6 -2
  683. package/dist/types/task-runner.d.ts +6 -0
  684. package/dist/types/types.d.ts +98 -5
  685. package/dist/types/yaml/cleanup.d.ts +2 -0
  686. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-html-template.mjs","sources":["../../src/report-html-template.ts"],"sourcesContent":["// Keep the Report template in its own source module. Core's bundle:false\n// builds must emit standalone CJS and ESM module files so the Report build can\n// replace them independently without rewriting the rest of Core's output.\nexport const REPORT_HTML_TEMPLATE = 'REPLACE_ME_WITH_REPORT_HTML';\n"],"names":["REPORT_HTML_TEMPLATE"],"mappings":"AAGO,MAAMA,uBAAuB"}
@@ -0,0 +1,113 @@
1
+ const usageKeys = [
2
+ 'intent',
3
+ 'slot',
4
+ 'model_name',
5
+ 'response_model_name',
6
+ "model_description",
7
+ 'prompt_tokens',
8
+ 'cached_input',
9
+ 'completion_tokens',
10
+ 'total_tokens',
11
+ 'time_cost',
12
+ 'request_id'
13
+ ];
14
+ function finiteNumber(value) {
15
+ return 'number' == typeof value && Number.isFinite(value) ? value : void 0;
16
+ }
17
+ function usageValue(usage, key) {
18
+ return Math.max(0, finiteNumber(usage[key]) ?? 0);
19
+ }
20
+ function hasUsage(usage) {
21
+ return Boolean(usage && usageKeys.some((key)=>void 0 !== usage[key] && null !== usage[key]));
22
+ }
23
+ function usageTotalTokens(usage) {
24
+ const explicitTotal = finiteNumber(usage.total_tokens);
25
+ if (void 0 !== explicitTotal && explicitTotal > 0) return explicitTotal;
26
+ return usageValue(usage, 'prompt_tokens') + usageValue(usage, 'completion_tokens');
27
+ }
28
+ function usageModelName(usage) {
29
+ return usage.model_name || usage.response_model_name || usage.model_description || usage.intent || 'Unknown';
30
+ }
31
+ function collectReportSummary(report, options = {}) {
32
+ if (!report || !Array.isArray(report.executions)) throw new Error('collectReportSummary: report.executions must be an array');
33
+ let earliestTimestamp;
34
+ let latestTimestamp;
35
+ let modelCallCount = 0;
36
+ let modelCallTimeMs = 0;
37
+ const models = new Map();
38
+ const addTimestamp = (value)=>{
39
+ const timestamp = finiteNumber(value);
40
+ if (void 0 === timestamp) return;
41
+ earliestTimestamp = void 0 === earliestTimestamp ? timestamp : Math.min(earliestTimestamp, timestamp);
42
+ latestTimestamp = void 0 === latestTimestamp ? timestamp : Math.max(latestTimestamp, timestamp);
43
+ };
44
+ const addUsage = (usage)=>{
45
+ if (!hasUsage(usage)) return;
46
+ const modelName = usageModelName(usage);
47
+ const current = models.get(modelName) ?? {
48
+ modelName,
49
+ callCount: 0,
50
+ promptTokens: 0,
51
+ cachedInputTokens: 0,
52
+ completionTokens: 0,
53
+ totalTokens: 0,
54
+ modelCallTimeMs: 0
55
+ };
56
+ const callTimeMs = usageValue(usage, 'time_cost');
57
+ models.set(modelName, {
58
+ modelName,
59
+ callCount: current.callCount + 1,
60
+ promptTokens: current.promptTokens + usageValue(usage, 'prompt_tokens'),
61
+ cachedInputTokens: current.cachedInputTokens + usageValue(usage, 'cached_input'),
62
+ completionTokens: current.completionTokens + usageValue(usage, 'completion_tokens'),
63
+ totalTokens: current.totalTokens + usageTotalTokens(usage),
64
+ modelCallTimeMs: current.modelCallTimeMs + callTimeMs
65
+ });
66
+ modelCallCount += 1;
67
+ modelCallTimeMs += callTimeMs;
68
+ };
69
+ for (const execution of report.executions)for (const task of execution.tasks){
70
+ addTimestamp(task.timing?.start);
71
+ addTimestamp(task.timing?.end);
72
+ addUsage(task.usage);
73
+ addUsage(task.searchAreaUsage);
74
+ }
75
+ const modelSummaries = Array.from(models.values());
76
+ const tokens = modelSummaries.reduce((total, model)=>({
77
+ promptTokens: total.promptTokens + model.promptTokens,
78
+ cachedInputTokens: total.cachedInputTokens + model.cachedInputTokens,
79
+ completionTokens: total.completionTokens + model.completionTokens,
80
+ totalTokens: total.totalTokens + model.totalTokens
81
+ }), {
82
+ promptTokens: 0,
83
+ cachedInputTokens: 0,
84
+ completionTokens: 0,
85
+ totalTokens: 0
86
+ });
87
+ const fallback = finiteNumber(options.wallTimeFallbackMs);
88
+ const hasFallback = void 0 !== fallback && fallback >= 0;
89
+ let wallTimeMs;
90
+ let wallTimeSource;
91
+ if (void 0 !== earliestTimestamp && void 0 !== latestTimestamp) {
92
+ wallTimeMs = Math.max(0, latestTimestamp - earliestTimestamp);
93
+ wallTimeSource = 'task-timestamps';
94
+ } else if (hasFallback) {
95
+ wallTimeMs = fallback;
96
+ wallTimeSource = 'fallback';
97
+ } else wallTimeSource = 'unavailable';
98
+ return {
99
+ timing: {
100
+ wallTimeMs,
101
+ wallTimeStart: 'task-timestamps' === wallTimeSource ? earliestTimestamp : void 0,
102
+ wallTimeEnd: 'task-timestamps' === wallTimeSource ? latestTimestamp : void 0,
103
+ wallTimeSource,
104
+ modelCallTimeMs,
105
+ modelCallCount
106
+ },
107
+ tokens,
108
+ models: modelSummaries
109
+ };
110
+ }
111
+ export { collectReportSummary };
112
+
113
+ //# sourceMappingURL=report-stats.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-stats.mjs","sources":["../../src/report-stats.ts"],"sourcesContent":["import type { AIUsageInfo, IReportActionDump } from './types';\n\nexport interface ReportModelUsageSummary {\n modelName: string;\n callCount: number;\n promptTokens: number;\n cachedInputTokens: number;\n completionTokens: number;\n totalTokens: number;\n modelCallTimeMs: number;\n}\n\nexport interface ReportTokenSummary {\n promptTokens: number;\n cachedInputTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\nexport interface ReportTimingSummary {\n /**\n * Elapsed time between the earliest and latest recorded task timestamps.\n * Falls back to `wallTimeFallbackMs` only when no task timestamps exist.\n */\n wallTimeMs?: number;\n wallTimeStart?: number;\n wallTimeEnd?: number;\n wallTimeSource: 'task-timestamps' | 'fallback' | 'unavailable';\n /** Sum of every recorded model request duration. */\n modelCallTimeMs: number;\n modelCallCount: number;\n}\n\nexport interface ReportSummary {\n timing: ReportTimingSummary;\n tokens: ReportTokenSummary;\n models: ReportModelUsageSummary[];\n}\n\nexport interface CollectReportSummaryOptions {\n /** Generic fallback for reports without task timestamps, such as test time. */\n wallTimeFallbackMs?: number;\n}\n\nconst usageKeys = [\n 'intent',\n 'slot',\n 'model_name',\n 'response_model_name',\n 'model_description',\n 'prompt_tokens',\n 'cached_input',\n 'completion_tokens',\n 'total_tokens',\n 'time_cost',\n 'request_id',\n] as const;\n\nfunction finiteNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction usageValue(usage: AIUsageInfo, key: string): number {\n return Math.max(0, finiteNumber(usage[key]) ?? 0);\n}\n\nfunction hasUsage(usage: AIUsageInfo | undefined): usage is AIUsageInfo {\n return Boolean(\n usage &&\n usageKeys.some((key) => usage[key] !== undefined && usage[key] !== null),\n );\n}\n\nfunction usageTotalTokens(usage: AIUsageInfo): number {\n const explicitTotal = finiteNumber(usage.total_tokens);\n if (explicitTotal !== undefined && explicitTotal > 0) {\n return explicitTotal;\n }\n return (\n usageValue(usage, 'prompt_tokens') + usageValue(usage, 'completion_tokens')\n );\n}\n\nfunction usageModelName(usage: AIUsageInfo): string {\n return (\n usage.model_name ||\n usage.response_model_name ||\n usage.model_description ||\n usage.intent ||\n 'Unknown'\n );\n}\n\nexport function collectReportSummary(\n report: Pick<IReportActionDump, 'executions'>,\n options: CollectReportSummaryOptions = {},\n): ReportSummary {\n if (!report || !Array.isArray(report.executions)) {\n throw new Error('collectReportSummary: report.executions must be an array');\n }\n\n let earliestTimestamp: number | undefined;\n let latestTimestamp: number | undefined;\n let modelCallCount = 0;\n let modelCallTimeMs = 0;\n const models = new Map<string, ReportModelUsageSummary>();\n\n const addTimestamp = (value: unknown) => {\n const timestamp = finiteNumber(value);\n if (timestamp === undefined) return;\n earliestTimestamp =\n earliestTimestamp === undefined\n ? timestamp\n : Math.min(earliestTimestamp, timestamp);\n latestTimestamp =\n latestTimestamp === undefined\n ? timestamp\n : Math.max(latestTimestamp, timestamp);\n };\n\n const addUsage = (usage: AIUsageInfo | undefined) => {\n if (!hasUsage(usage)) return;\n\n const modelName = usageModelName(usage);\n const current = models.get(modelName) ?? {\n modelName,\n callCount: 0,\n promptTokens: 0,\n cachedInputTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n modelCallTimeMs: 0,\n };\n const callTimeMs = usageValue(usage, 'time_cost');\n\n models.set(modelName, {\n modelName,\n callCount: current.callCount + 1,\n promptTokens: current.promptTokens + usageValue(usage, 'prompt_tokens'),\n cachedInputTokens:\n current.cachedInputTokens + usageValue(usage, 'cached_input'),\n completionTokens:\n current.completionTokens + usageValue(usage, 'completion_tokens'),\n totalTokens: current.totalTokens + usageTotalTokens(usage),\n modelCallTimeMs: current.modelCallTimeMs + callTimeMs,\n });\n modelCallCount += 1;\n modelCallTimeMs += callTimeMs;\n };\n\n for (const execution of report.executions) {\n for (const task of execution.tasks) {\n addTimestamp(task.timing?.start);\n addTimestamp(task.timing?.end);\n addUsage(task.usage);\n addUsage(task.searchAreaUsage);\n }\n }\n\n const modelSummaries = Array.from(models.values());\n const tokens = modelSummaries.reduce<ReportTokenSummary>(\n (total, model) => ({\n promptTokens: total.promptTokens + model.promptTokens,\n cachedInputTokens: total.cachedInputTokens + model.cachedInputTokens,\n completionTokens: total.completionTokens + model.completionTokens,\n totalTokens: total.totalTokens + model.totalTokens,\n }),\n {\n promptTokens: 0,\n cachedInputTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n },\n );\n\n const fallback = finiteNumber(options.wallTimeFallbackMs);\n const hasFallback = fallback !== undefined && fallback >= 0;\n let wallTimeMs: number | undefined;\n let wallTimeSource: ReportTimingSummary['wallTimeSource'];\n\n if (earliestTimestamp !== undefined && latestTimestamp !== undefined) {\n wallTimeMs = Math.max(0, latestTimestamp - earliestTimestamp);\n wallTimeSource = 'task-timestamps';\n } else if (hasFallback) {\n wallTimeMs = fallback;\n wallTimeSource = 'fallback';\n } else {\n wallTimeSource = 'unavailable';\n }\n\n return {\n timing: {\n wallTimeMs,\n wallTimeStart:\n wallTimeSource === 'task-timestamps' ? earliestTimestamp : undefined,\n wallTimeEnd:\n wallTimeSource === 'task-timestamps' ? latestTimestamp : undefined,\n wallTimeSource,\n modelCallTimeMs,\n modelCallCount,\n },\n tokens,\n models: modelSummaries,\n };\n}\n"],"names":["usageKeys","finiteNumber","value","Number","undefined","usageValue","usage","key","Math","hasUsage","Boolean","usageTotalTokens","explicitTotal","usageModelName","collectReportSummary","report","options","Array","Error","earliestTimestamp","latestTimestamp","modelCallCount","modelCallTimeMs","models","Map","addTimestamp","timestamp","addUsage","modelName","current","callTimeMs","execution","task","modelSummaries","tokens","total","model","fallback","hasFallback","wallTimeMs","wallTimeSource"],"mappings":"AA4CA,MAAMA,YAAY;IAChB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,SAASC,aAAaC,KAAc;IAClC,OAAO,AAAiB,YAAjB,OAAOA,SAAsBC,OAAO,QAAQ,CAACD,SAChDA,QACAE;AACN;AAEA,SAASC,WAAWC,KAAkB,EAAEC,GAAW;IACjD,OAAOC,KAAK,GAAG,CAAC,GAAGP,aAAaK,KAAK,CAACC,IAAI,KAAK;AACjD;AAEA,SAASE,SAASH,KAA8B;IAC9C,OAAOI,QACLJ,SACEN,UAAU,IAAI,CAAC,CAACO,MAAQD,AAAeF,WAAfE,KAAK,CAACC,IAAI,IAAkBD,AAAe,SAAfA,KAAK,CAACC,IAAI;AAEpE;AAEA,SAASI,iBAAiBL,KAAkB;IAC1C,MAAMM,gBAAgBX,aAAaK,MAAM,YAAY;IACrD,IAAIM,AAAkBR,WAAlBQ,iBAA+BA,gBAAgB,GACjD,OAAOA;IAET,OACEP,WAAWC,OAAO,mBAAmBD,WAAWC,OAAO;AAE3D;AAEA,SAASO,eAAeP,KAAkB;IACxC,OACEA,MAAM,UAAU,IAChBA,MAAM,mBAAmB,IACzBA,MAAM,iBAAiB,IACvBA,MAAM,MAAM,IACZ;AAEJ;AAEO,SAASQ,qBACdC,MAA6C,EAC7CC,UAAuC,CAAC,CAAC;IAEzC,IAAI,CAACD,UAAU,CAACE,MAAM,OAAO,CAACF,OAAO,UAAU,GAC7C,MAAM,IAAIG,MAAM;IAGlB,IAAIC;IACJ,IAAIC;IACJ,IAAIC,iBAAiB;IACrB,IAAIC,kBAAkB;IACtB,MAAMC,SAAS,IAAIC;IAEnB,MAAMC,eAAe,CAACvB;QACpB,MAAMwB,YAAYzB,aAAaC;QAC/B,IAAIwB,AAActB,WAAdsB,WAAyB;QAC7BP,oBACEA,AAAsBf,WAAtBe,oBACIO,YACAlB,KAAK,GAAG,CAACW,mBAAmBO;QAClCN,kBACEA,AAAoBhB,WAApBgB,kBACIM,YACAlB,KAAK,GAAG,CAACY,iBAAiBM;IAClC;IAEA,MAAMC,WAAW,CAACrB;QAChB,IAAI,CAACG,SAASH,QAAQ;QAEtB,MAAMsB,YAAYf,eAAeP;QACjC,MAAMuB,UAAUN,OAAO,GAAG,CAACK,cAAc;YACvCA;YACA,WAAW;YACX,cAAc;YACd,mBAAmB;YACnB,kBAAkB;YAClB,aAAa;YACb,iBAAiB;QACnB;QACA,MAAME,aAAazB,WAAWC,OAAO;QAErCiB,OAAO,GAAG,CAACK,WAAW;YACpBA;YACA,WAAWC,QAAQ,SAAS,GAAG;YAC/B,cAAcA,QAAQ,YAAY,GAAGxB,WAAWC,OAAO;YACvD,mBACEuB,QAAQ,iBAAiB,GAAGxB,WAAWC,OAAO;YAChD,kBACEuB,QAAQ,gBAAgB,GAAGxB,WAAWC,OAAO;YAC/C,aAAauB,QAAQ,WAAW,GAAGlB,iBAAiBL;YACpD,iBAAiBuB,QAAQ,eAAe,GAAGC;QAC7C;QACAT,kBAAkB;QAClBC,mBAAmBQ;IACrB;IAEA,KAAK,MAAMC,aAAahB,OAAO,UAAU,CACvC,KAAK,MAAMiB,QAAQD,UAAU,KAAK,CAAE;QAClCN,aAAaO,KAAK,MAAM,EAAE;QAC1BP,aAAaO,KAAK,MAAM,EAAE;QAC1BL,SAASK,KAAK,KAAK;QACnBL,SAASK,KAAK,eAAe;IAC/B;IAGF,MAAMC,iBAAiBhB,MAAM,IAAI,CAACM,OAAO,MAAM;IAC/C,MAAMW,SAASD,eAAe,MAAM,CAClC,CAACE,OAAOC,QAAW;YACjB,cAAcD,MAAM,YAAY,GAAGC,MAAM,YAAY;YACrD,mBAAmBD,MAAM,iBAAiB,GAAGC,MAAM,iBAAiB;YACpE,kBAAkBD,MAAM,gBAAgB,GAAGC,MAAM,gBAAgB;YACjE,aAAaD,MAAM,WAAW,GAAGC,MAAM,WAAW;QACpD,IACA;QACE,cAAc;QACd,mBAAmB;QACnB,kBAAkB;QAClB,aAAa;IACf;IAGF,MAAMC,WAAWpC,aAAae,QAAQ,kBAAkB;IACxD,MAAMsB,cAAcD,AAAajC,WAAbiC,YAA0BA,YAAY;IAC1D,IAAIE;IACJ,IAAIC;IAEJ,IAAIrB,AAAsBf,WAAtBe,qBAAmCC,AAAoBhB,WAApBgB,iBAA+B;QACpEmB,aAAa/B,KAAK,GAAG,CAAC,GAAGY,kBAAkBD;QAC3CqB,iBAAiB;IACnB,OAAO,IAAIF,aAAa;QACtBC,aAAaF;QACbG,iBAAiB;IACnB,OACEA,iBAAiB;IAGnB,OAAO;QACL,QAAQ;YACND;YACA,eACEC,AAAmB,sBAAnBA,iBAAuCrB,oBAAoBf;YAC7D,aACEoC,AAAmB,sBAAnBA,iBAAuCpB,kBAAkBhB;YAC3DoC;YACAlB;YACAD;QACF;QACAa;QACA,QAAQD;IACV;AACF"}
@@ -21,6 +21,11 @@ class ScreenshotItem {
21
21
  static create(base64, capturedAt) {
22
22
  return new ScreenshotItem(uuid(), base64, capturedAt);
23
23
  }
24
+ static fromFile(filePath, mimeType, capturedAt) {
25
+ const item = new ScreenshotItem(uuid(), null, capturedAt, 'image/jpeg' === mimeType ? 'jpeg' : 'png');
26
+ item._persistedPath = filePath;
27
+ return item;
28
+ }
24
29
  get id() {
25
30
  return this._id;
26
31
  }
@@ -103,7 +108,7 @@ class ScreenshotItem {
103
108
  get rawBase64() {
104
109
  return this.base64.replace(/^data:image\/(png|jpeg|jpg);base64,/, '');
105
110
  }
106
- constructor(id, base64, capturedAt){
111
+ constructor(id, base64, capturedAt, format){
107
112
  _define_property(this, "_id", void 0);
108
113
  _define_property(this, "_base64", void 0);
109
114
  _define_property(this, "_format", void 0);
@@ -113,7 +118,7 @@ class ScreenshotItem {
113
118
  _define_property(this, "_persistedHtmlPath", null);
114
119
  this._id = id;
115
120
  this._base64 = base64;
116
- this._format = detectFormat(base64);
121
+ this._format = format ?? detectFormat(base64 || '');
117
122
  this._capturedAt = capturedAt;
118
123
  }
119
124
  }
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot-item.mjs","sources":["../../src/screenshot-item.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { uuid } from '@aiscene/shared/utils';\nimport { extractImageByIdSync } from './dump/html-utils';\nimport {\n type ScreenshotRef,\n normalizeScreenshotRef,\n} from './dump/screenshot-store';\n\n/**\n * Serialization format for ScreenshotItem\n * - { $screenshot: \"id\" } - inline mode, references imageMap in HTML\n * - { base64: \"path\" } - directory mode, references external file path\n */\nexport type ScreenshotSerializeFormat = ScreenshotRef;\n\n/**\n * Detect image format from base64 data URI prefix.\n */\nfunction detectFormat(base64: string): 'png' | 'jpeg' {\n if (base64.startsWith('data:image/jpeg')) return 'jpeg';\n if (base64.startsWith('data:image/jpg')) return 'jpeg';\n return 'png';\n}\n\n/**\n * ScreenshotItem encapsulates screenshot data.\n *\n * Supports lazy loading after memory release:\n * - inline mode: reads from HTML file using streaming (extractImageByIdSync)\n * - directory mode: reads from file on disk\n *\n * After persistence, memory is released but the screenshot can be recovered\n * on-demand from disk, making it safe to release memory at any time.\n */\nexport class ScreenshotItem {\n private _id: string;\n private _base64: string | null;\n private _format: 'png' | 'jpeg';\n private _capturedAt: number;\n private _serializedRef: ScreenshotRef | null = null;\n private _persistedPath: string | null = null;\n private _persistedHtmlPath: string | null = null;\n\n private constructor(id: string, base64: string, capturedAt: number) {\n this._id = id;\n this._base64 = base64;\n this._format = detectFormat(base64);\n this._capturedAt = capturedAt;\n }\n\n /** Create a new ScreenshotItem from base64 data */\n static create(base64: string, capturedAt: number): ScreenshotItem {\n return new ScreenshotItem(uuid(), base64, capturedAt);\n }\n\n get id(): string {\n return this._id;\n }\n\n /** Get the image format (png or jpeg) */\n get format(): 'png' | 'jpeg' {\n return this._format;\n }\n\n /** Get the file extension for this screenshot */\n get extension(): string {\n return this._format === 'jpeg' ? 'jpeg' : 'png';\n }\n\n /** Get screenshot capture timestamp in milliseconds */\n get capturedAt(): number {\n return this._capturedAt;\n }\n\n get base64(): string {\n // If data is in memory, return it directly\n if (this._base64 !== null) {\n return this._base64;\n }\n\n const loadFromFile = (): string => {\n if (this._persistedPath === null) {\n throw new Error(`Screenshot ${this._id}: file recovery path missing`);\n }\n const buffer = readFileSync(this._persistedPath);\n return `data:image/${this._format};base64,${buffer.toString('base64')}`;\n };\n\n const loadFromInline = (): string => {\n if (this._persistedHtmlPath === null) {\n throw new Error(`Screenshot ${this._id}: HTML recovery path missing`);\n }\n const data = extractImageByIdSync(this._persistedHtmlPath, this._id);\n if (data) {\n return data;\n }\n throw new Error(\n `Screenshot ${this._id}: cannot recover from HTML (id not found in ${this._persistedHtmlPath})`,\n );\n };\n\n // Recover from the primary serialized mode first.\n if (this._serializedRef?.storage === 'file') {\n return loadFromFile();\n }\n\n if (this._serializedRef?.storage === 'inline') {\n return loadFromInline();\n }\n\n // Fall back to whichever recovery path is available.\n if (this._persistedPath !== null) {\n return loadFromFile();\n }\n\n if (this._persistedHtmlPath !== null) {\n return loadFromInline();\n }\n\n throw new Error(\n `Screenshot ${this._id}: base64 data released without recovery path`,\n );\n }\n\n /** Check if base64 data is still available in memory (not yet released) */\n hasBase64(): boolean {\n return this._base64 !== null;\n }\n\n /**\n * Mark as persisted to HTML (inline mode).\n * Releases base64 memory, but keeps HTML path for lazy loading recovery.\n * @param htmlPath - absolute path to the HTML file containing the image\n */\n markPersistedInline(htmlPath: string): ScreenshotRef {\n const ref = this.createRef('inline');\n this._serializedRef = ref;\n this._persistedHtmlPath = htmlPath;\n this._base64 = null;\n return ref;\n }\n\n /**\n * Register a file-backed recovery path without changing the serialized mode.\n * Used when inline persistence also needs a shared file copy next to dumps.\n */\n registerPersistedFileCopy(\n relativePath: string,\n absolutePath: string,\n ): ScreenshotRef {\n const ref = this.createRef('file', relativePath);\n this._persistedPath = absolutePath;\n this._base64 = null;\n return ref;\n }\n\n /**\n * Mark as persisted to file (directory mode).\n * Releases base64 memory, but keeps file path for lazy loading recovery.\n * @param relativePath - relative path for serialization (e.g., \"./screenshots/id.jpeg\")\n * @param absolutePath - absolute path for lazy loading recovery\n */\n markPersistedToPath(\n relativePath: string,\n absolutePath: string,\n ): ScreenshotRef {\n const ref = this.registerPersistedFileCopy(relativePath, absolutePath);\n this._serializedRef = ref;\n return ref;\n }\n\n /** Serialize for JSON - format depends on persistence state */\n toSerializable(): ScreenshotSerializeFormat {\n return (\n this._serializedRef ?? {\n type: 'midscene_screenshot_ref',\n id: this._id,\n capturedAt: this._capturedAt,\n mimeType: this._format === 'jpeg' ? 'image/jpeg' : 'image/png',\n storage: 'inline',\n }\n );\n }\n\n /** Check if a value is a serialized ScreenshotItem reference (inline or directory mode) */\n static isSerialized(value: unknown): value is ScreenshotSerializeFormat {\n return normalizeScreenshotRef(value) !== null;\n }\n\n private createRef(\n storage: 'inline' | 'file',\n relativePath?: string,\n ): ScreenshotRef {\n const baseRef: Omit<ScreenshotRef, 'path'> = {\n type: 'midscene_screenshot_ref',\n id: this._id,\n capturedAt: this._capturedAt,\n mimeType: this._format === 'jpeg' ? 'image/jpeg' : 'image/png',\n storage,\n };\n if (storage === 'file') {\n return {\n ...baseRef,\n storage,\n path: relativePath!,\n };\n }\n return baseRef;\n }\n\n /**\n * Get base64 data without the data URI prefix.\n * Useful for writing raw binary data to files.\n */\n get rawBase64(): string {\n return this.base64.replace(/^data:image\\/(png|jpeg|jpg);base64,/, '');\n }\n}\n"],"names":["detectFormat","base64","ScreenshotItem","capturedAt","uuid","loadFromFile","Error","buffer","readFileSync","loadFromInline","data","extractImageByIdSync","htmlPath","ref","relativePath","absolutePath","value","normalizeScreenshotRef","storage","baseRef","id"],"mappings":"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"}
1
+ {"version":3,"file":"screenshot-item.mjs","sources":["../../src/screenshot-item.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { uuid } from '@aiscene/shared/utils';\nimport { extractImageByIdSync } from './dump/html-utils';\nimport {\n type ScreenshotRef,\n normalizeScreenshotRef,\n} from './dump/screenshot-store';\n\n/**\n * Serialization format for ScreenshotItem\n * - { $screenshot: \"id\" } - inline mode, references imageMap in HTML\n * - { base64: \"path\" } - directory mode, references external file path\n */\nexport type ScreenshotSerializeFormat = ScreenshotRef;\n\n/**\n * Detect image format from base64 data URI prefix.\n */\nfunction detectFormat(base64: string): 'png' | 'jpeg' {\n if (base64.startsWith('data:image/jpeg')) return 'jpeg';\n if (base64.startsWith('data:image/jpg')) return 'jpeg';\n return 'png';\n}\n\n/**\n * ScreenshotItem encapsulates screenshot data.\n *\n * Supports lazy loading after memory release:\n * - inline mode: reads from HTML file using streaming (extractImageByIdSync)\n * - directory mode: reads from file on disk\n *\n * After persistence, memory is released but the screenshot can be recovered\n * on-demand from disk, making it safe to release memory at any time.\n */\nexport class ScreenshotItem {\n private _id: string;\n private _base64: string | null;\n private _format: 'png' | 'jpeg';\n private _capturedAt: number;\n private _serializedRef: ScreenshotRef | null = null;\n private _persistedPath: string | null = null;\n private _persistedHtmlPath: string | null = null;\n\n private constructor(\n id: string,\n base64: string | null,\n capturedAt: number,\n format?: 'png' | 'jpeg',\n ) {\n this._id = id;\n this._base64 = base64;\n this._format = format ?? detectFormat(base64 || '');\n this._capturedAt = capturedAt;\n }\n\n /** Create a new ScreenshotItem from base64 data */\n static create(base64: string, capturedAt: number): ScreenshotItem {\n return new ScreenshotItem(uuid(), base64, capturedAt);\n }\n\n static fromFile(\n filePath: string,\n mimeType: 'image/png' | 'image/jpeg',\n capturedAt: number,\n ): ScreenshotItem {\n const item = new ScreenshotItem(\n uuid(),\n null,\n capturedAt,\n mimeType === 'image/jpeg' ? 'jpeg' : 'png',\n );\n item._persistedPath = filePath;\n return item;\n }\n\n get id(): string {\n return this._id;\n }\n\n /** Get the image format (png or jpeg) */\n get format(): 'png' | 'jpeg' {\n return this._format;\n }\n\n /** Get the file extension for this screenshot */\n get extension(): string {\n return this._format === 'jpeg' ? 'jpeg' : 'png';\n }\n\n /** Get screenshot capture timestamp in milliseconds */\n get capturedAt(): number {\n return this._capturedAt;\n }\n\n get base64(): string {\n // If data is in memory, return it directly\n if (this._base64 !== null) {\n return this._base64;\n }\n\n const loadFromFile = (): string => {\n if (this._persistedPath === null) {\n throw new Error(`Screenshot ${this._id}: file recovery path missing`);\n }\n const buffer = readFileSync(this._persistedPath);\n return `data:image/${this._format};base64,${buffer.toString('base64')}`;\n };\n\n const loadFromInline = (): string => {\n if (this._persistedHtmlPath === null) {\n throw new Error(`Screenshot ${this._id}: HTML recovery path missing`);\n }\n const data = extractImageByIdSync(this._persistedHtmlPath, this._id);\n if (data) {\n return data;\n }\n throw new Error(\n `Screenshot ${this._id}: cannot recover from HTML (id not found in ${this._persistedHtmlPath})`,\n );\n };\n\n // Recover from the primary serialized mode first.\n if (this._serializedRef?.storage === 'file') {\n return loadFromFile();\n }\n\n if (this._serializedRef?.storage === 'inline') {\n return loadFromInline();\n }\n\n // Fall back to whichever recovery path is available.\n if (this._persistedPath !== null) {\n return loadFromFile();\n }\n\n if (this._persistedHtmlPath !== null) {\n return loadFromInline();\n }\n\n throw new Error(\n `Screenshot ${this._id}: base64 data released without recovery path`,\n );\n }\n\n /** Check if base64 data is still available in memory (not yet released) */\n hasBase64(): boolean {\n return this._base64 !== null;\n }\n\n /**\n * Mark as persisted to HTML (inline mode).\n * Releases base64 memory, but keeps HTML path for lazy loading recovery.\n * @param htmlPath - absolute path to the HTML file containing the image\n */\n markPersistedInline(htmlPath: string): ScreenshotRef {\n const ref = this.createRef('inline');\n this._serializedRef = ref;\n this._persistedHtmlPath = htmlPath;\n this._base64 = null;\n return ref;\n }\n\n /**\n * Register a file-backed recovery path without changing the serialized mode.\n * Used when inline persistence also needs a shared file copy next to dumps.\n */\n registerPersistedFileCopy(\n relativePath: string,\n absolutePath: string,\n ): ScreenshotRef {\n const ref = this.createRef('file', relativePath);\n this._persistedPath = absolutePath;\n this._base64 = null;\n return ref;\n }\n\n /**\n * Mark as persisted to file (directory mode).\n * Releases base64 memory, but keeps file path for lazy loading recovery.\n * @param relativePath - relative path for serialization (e.g., \"./screenshots/id.jpeg\")\n * @param absolutePath - absolute path for lazy loading recovery\n */\n markPersistedToPath(\n relativePath: string,\n absolutePath: string,\n ): ScreenshotRef {\n const ref = this.registerPersistedFileCopy(relativePath, absolutePath);\n this._serializedRef = ref;\n return ref;\n }\n\n /** Serialize for JSON - format depends on persistence state */\n toSerializable(): ScreenshotSerializeFormat {\n return (\n this._serializedRef ?? {\n type: 'midscene_screenshot_ref',\n id: this._id,\n capturedAt: this._capturedAt,\n mimeType: this._format === 'jpeg' ? 'image/jpeg' : 'image/png',\n storage: 'inline',\n }\n );\n }\n\n /** Check if a value is a serialized ScreenshotItem reference (inline or directory mode) */\n static isSerialized(value: unknown): value is ScreenshotSerializeFormat {\n return normalizeScreenshotRef(value) !== null;\n }\n\n private createRef(\n storage: 'inline' | 'file',\n relativePath?: string,\n ): ScreenshotRef {\n const baseRef: Omit<ScreenshotRef, 'path'> = {\n type: 'midscene_screenshot_ref',\n id: this._id,\n capturedAt: this._capturedAt,\n mimeType: this._format === 'jpeg' ? 'image/jpeg' : 'image/png',\n storage,\n };\n if (storage === 'file') {\n return {\n ...baseRef,\n storage,\n path: relativePath!,\n };\n }\n return baseRef;\n }\n\n /**\n * Get base64 data without the data URI prefix.\n * Useful for writing raw binary data to files.\n */\n get rawBase64(): string {\n return this.base64.replace(/^data:image\\/(png|jpeg|jpg);base64,/, '');\n }\n}\n"],"names":["detectFormat","base64","ScreenshotItem","capturedAt","uuid","filePath","mimeType","item","loadFromFile","Error","buffer","readFileSync","loadFromInline","data","extractImageByIdSync","htmlPath","ref","relativePath","absolutePath","value","normalizeScreenshotRef","storage","baseRef","id","format"],"mappings":"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"}
@@ -20,13 +20,17 @@ function _define_property(obj, key, value) {
20
20
  return obj;
21
21
  }
22
22
  const debug = getDebug('ai:service');
23
+ function resolveModelConfig(input) {
24
+ return 'config' in input ? input.config : input;
25
+ }
23
26
  class Service {
24
27
  async getAIMemory() {
25
28
  const memories = await this.memoryRetrieverFn?.() || [];
26
29
  const normalizedMemories = normalizeAIMemory(memories);
27
30
  return normalizedMemories.length ? normalizedMemories : void 0;
28
31
  }
29
- async locate(query, opt, modelConfig, abortSignal) {
32
+ async locate(query, opt, modelRuntimeOrConfig, abortSignal) {
33
+ const modelConfig = resolveModelConfig(modelRuntimeOrConfig);
30
34
  const queryPrompt = 'string' == typeof query ? query : query.prompt;
31
35
  assert(queryPrompt, 'query is required for locate');
32
36
  assert('object' == typeof query, 'query should be an object for locate');
@@ -215,9 +219,10 @@ class Service {
215
219
  dump
216
220
  };
217
221
  }
218
- async describe(target, modelConfig, opt) {
222
+ async describe(target, modelRuntimeOrConfig, opt) {
223
+ const modelConfig = resolveModelConfig(modelRuntimeOrConfig);
219
224
  assert(target, 'target is required for service.describe');
220
- const context = await this.contextRetrieverFn();
225
+ const context = opt?.context || await this.contextRetrieverFn();
221
226
  const { shotSize } = context;
222
227
  const screenshotBase64 = context.screenshot.base64;
223
228
  assert(screenshotBase64, 'screenshot is required for service.describe');
@@ -240,7 +245,7 @@ class Service {
240
245
  ],
241
246
  borderThickness: 3
242
247
  });
243
- if (opt?.deepLocate) {
248
+ if (opt?.deepLocate || opt?.deepDescribe) {
244
249
  const searchArea = expandSearchArea(targetRect, shotSize);
245
250
  debug('describe: cropping to searchArea', searchArea);
246
251
  const croppedResult = await cropByRect(imagePayload, searchArea, 'qwen2.5-vl' === modelFamily);
@@ -272,7 +277,7 @@ class Service {
272
277
  ]
273
278
  }
274
279
  ];
275
- const res = await callAIWithObjectResponse(msgs, modelConfig);
280
+ const res = await callAIWithObjectResponse(msgs, modelRuntimeOrConfig);
276
281
  const { content } = res;
277
282
  assert(!content.error, `describe failed: ${content.error}`);
278
283
  assert(content.description, 'failed to describe the element');
@@ -1 +1 @@
1
- {"version":3,"file":"service/index.mjs","sources":["../../../src/service/index.ts"],"sourcesContent":["import { isAutoGLM, isUITars } from '@/ai-model/auto-glm/util';\nimport {\n AIResponseParseError,\n AiExtractElementInfo,\n AiLocateElement,\n callAIWithObjectResponse,\n} from '@/ai-model/index';\nimport { AiLocateSection, buildSearchAreaConfig } from '@/ai-model/inspect';\nimport { elementDescriberInstruction } from '@/ai-model/prompt/describe';\nimport { formatAIMemories, normalizeAIMemory } from '@/ai-model/prompt/util';\nimport { type AIArgs, expandSearchArea } from '@/common';\nimport type {\n AIDescribeElementResponse,\n AIUsageInfo,\n DetailedLocateParam,\n LocateResultElement,\n LocateResultWithDump,\n PartialServiceDumpFromSDK,\n PlanningLocateParam,\n Rect,\n ServiceExtractOption,\n ServiceExtractParam,\n ServiceExtractResult,\n ServiceTaskInfo,\n UIContext,\n} from '@/types';\nimport { ServiceError } from '@/types';\nimport type { IModelConfig } from '@aiscene/shared/env';\nimport { compositeElementInfoImg, cropByRect } from '@aiscene/shared/img';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { assert } from '@aiscene/shared/utils';\nimport type { TMultimodalPrompt } from '../common';\nimport { createServiceDump } from './utils';\n\nexport interface LocateOpts {\n context?: UIContext;\n planLocatedElement?: LocateResultElement;\n}\n\nexport type AnyValue<T> = {\n [K in keyof T]: unknown extends T[K] ? any : T[K];\n};\n\ninterface ServiceOptions {\n taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n memoryRetrieverFn?: () => readonly string[] | Promise<readonly string[]>;\n}\n\nconst debug = getDebug('ai:service');\nexport default class Service {\n contextRetrieverFn: () => Promise<UIContext> | UIContext;\n\n taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n private memoryRetrieverFn?: () =>\n | readonly string[]\n | Promise<readonly string[]>;\n\n constructor(\n context: UIContext | (() => Promise<UIContext> | UIContext),\n opt?: ServiceOptions,\n ) {\n assert(context, 'context is required for Service');\n if (typeof context === 'function') {\n this.contextRetrieverFn = context;\n } else {\n this.contextRetrieverFn = () => Promise.resolve(context);\n }\n\n if (typeof opt?.taskInfo !== 'undefined') {\n this.taskInfo = opt.taskInfo;\n }\n this.memoryRetrieverFn = opt?.memoryRetrieverFn;\n }\n\n private async getAIMemory(): Promise<string[] | undefined> {\n const memories = (await this.memoryRetrieverFn?.()) || [];\n const normalizedMemories = normalizeAIMemory(memories);\n return normalizedMemories.length ? normalizedMemories : undefined;\n }\n\n async locate(\n query: PlanningLocateParam,\n opt: LocateOpts,\n modelConfig: IModelConfig,\n abortSignal?: AbortSignal,\n ): Promise<LocateResultWithDump> {\n const queryPrompt = typeof query === 'string' ? query : query.prompt;\n assert(queryPrompt, 'query is required for locate');\n\n assert(typeof query === 'object', 'query should be an object for locate');\n\n const hasPlanLocatedElement = !!opt?.planLocatedElement?.rect;\n\n let searchAreaPrompt;\n if (query.deepLocate && !hasPlanLocatedElement) {\n searchAreaPrompt = query.prompt;\n }\n\n const { modelFamily } = modelConfig;\n\n if (searchAreaPrompt && !modelFamily) {\n console.warn(\n 'The \"deepLocate\" feature is not supported with multimodal LLM. Please config VL model for Midscene. https://midscenejs.com/model-config',\n );\n searchAreaPrompt = undefined;\n }\n\n if (searchAreaPrompt && isAutoGLM(modelFamily)) {\n console.warn('The \"deepLocate\" feature is not supported with AutoGLM.');\n searchAreaPrompt = undefined;\n }\n\n const context = opt?.context || (await this.contextRetrieverFn());\n const memories = await this.getAIMemory();\n\n let searchArea: Rect | undefined = undefined;\n let searchAreaRawResponse: string | undefined = undefined;\n let searchAreaUsage: AIUsageInfo | undefined = undefined;\n let searchAreaResponse:\n | Awaited<ReturnType<typeof AiLocateSection>>\n | undefined = undefined;\n if (query.deepLocate && hasPlanLocatedElement) {\n const searchAreaConfig = await buildSearchAreaConfig({\n context,\n baseRect: opt.planLocatedElement!.rect,\n modelFamily,\n });\n searchArea = searchAreaConfig.rect;\n\n searchAreaRawResponse = JSON.stringify({\n source: 'plan-located-element',\n rect: opt.planLocatedElement!.rect,\n });\n searchAreaResponse = {\n rect: searchArea,\n imageBase64: searchAreaConfig.imageBase64,\n scale: searchAreaConfig.scale,\n rawResponse: searchAreaRawResponse,\n };\n } else if (searchAreaPrompt) {\n searchAreaResponse = await AiLocateSection({\n context,\n sectionDescription: searchAreaPrompt,\n modelConfig,\n memories,\n abortSignal,\n });\n assert(\n searchAreaResponse.rect,\n `cannot find search area for \"${searchAreaPrompt}\"${\n searchAreaResponse.error ? `: ${searchAreaResponse.error}` : ''\n }`,\n );\n searchAreaRawResponse = searchAreaResponse.rawResponse;\n searchAreaUsage = searchAreaResponse.usage;\n searchArea = searchAreaResponse.rect;\n }\n\n const startTime = Date.now();\n const { parseResult, rect, rawResponse, usage, reasoning_content } =\n await AiLocateElement({\n context,\n targetElementDescription: queryPrompt,\n searchConfig: searchAreaResponse,\n modelConfig,\n memories,\n abortSignal,\n });\n\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse: JSON.stringify(rawResponse),\n formatResponse: JSON.stringify(parseResult),\n usage,\n searchArea,\n searchAreaRawResponse,\n searchAreaUsage,\n reasoning_content,\n };\n\n let errorLog: string | undefined;\n if (parseResult.errors?.length) {\n errorLog = `failed to locate element: \\n${parseResult.errors.join('\\n')}`;\n }\n\n const dumpData: PartialServiceDumpFromSDK = {\n type: 'locate',\n userQuery: {\n element: queryPrompt,\n },\n matchedElement: [],\n matchedRect: rect,\n data: null,\n taskInfo,\n deepLocate: !!searchArea,\n error: errorLog,\n };\n\n const elements = parseResult.elements || [];\n\n const dump = createServiceDump({\n ...dumpData,\n matchedElement: elements,\n });\n\n if (errorLog) {\n throw new ServiceError(errorLog, dump);\n }\n\n if (elements.length > 1) {\n throw new ServiceError(\n `locate: multiple elements found, length = ${elements.length}`,\n dump,\n );\n }\n\n if (elements.length === 1) {\n return {\n element: {\n center: elements[0]!.center,\n rect: elements[0]!.rect,\n description: elements[0]!.description,\n },\n rect,\n dump,\n };\n }\n\n return {\n element: null,\n rect,\n dump,\n };\n }\n\n async extract<T>(\n dataDemand: ServiceExtractParam,\n modelConfig: IModelConfig,\n opt?: ServiceExtractOption,\n pageDescription?: string,\n multimodalPrompt?: TMultimodalPrompt,\n context?: UIContext,\n ): Promise<ServiceExtractResult<T>> {\n assert(context, 'context is required for extract');\n assert(\n typeof dataDemand === 'object' || typeof dataDemand === 'string',\n `dataDemand should be object or string, but get ${typeof dataDemand}`,\n );\n\n const startTime = Date.now();\n\n let parseResult: Awaited<\n ReturnType<typeof AiExtractElementInfo<T>>\n >['parseResult'];\n let rawResponse: string;\n let usage: Awaited<ReturnType<typeof AiExtractElementInfo<T>>>['usage'];\n let reasoning_content: string | undefined;\n\n try {\n const result = await AiExtractElementInfo<T>({\n context,\n dataQuery: dataDemand,\n multimodalPrompt,\n extractOption: opt,\n modelConfig,\n pageDescription,\n memories: await this.getAIMemory(),\n });\n parseResult = result.parseResult;\n rawResponse = result.rawResponse;\n usage = result.usage;\n reasoning_content = result.reasoning_content;\n } catch (error) {\n if (error instanceof AIResponseParseError) {\n // Create dump with usage and rawResponse from the error\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse: error.rawResponse,\n usage: error.usage,\n };\n const dump = createServiceDump({\n type: 'extract',\n userQuery: { dataDemand },\n matchedElement: [],\n data: null,\n taskInfo,\n error: error.message,\n });\n throw new ServiceError(error.message, dump);\n }\n throw error;\n }\n\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse,\n formatResponse: JSON.stringify(parseResult),\n usage,\n reasoning_content,\n };\n\n let errorLog: string | undefined;\n if (parseResult.errors?.length) {\n errorLog = `AI response error: \\n${parseResult.errors.join('\\n')}`;\n }\n\n const dumpData: PartialServiceDumpFromSDK = {\n type: 'extract',\n userQuery: {\n dataDemand,\n },\n matchedElement: [],\n data: null,\n taskInfo,\n error: errorLog,\n };\n\n const { data, thought } = parseResult || {};\n\n const dump = createServiceDump({\n ...dumpData,\n data,\n });\n\n if (errorLog && !data) {\n throw new ServiceError(errorLog, dump);\n }\n\n return {\n data,\n thought,\n usage,\n reasoning_content,\n dump,\n };\n }\n\n async describe(\n target: Rect | [number, number],\n modelConfig: IModelConfig,\n opt?: {\n deepLocate?: boolean;\n },\n ): Promise<Pick<AIDescribeElementResponse, 'description'>> {\n assert(target, 'target is required for service.describe');\n const context = await this.contextRetrieverFn();\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(screenshotBase64, 'screenshot is required for service.describe');\n // The result of the \"describe\" function will be used for positioning, so essentially it is a form of grounding.\n const { modelFamily } = modelConfig;\n const systemPrompt = elementDescriberInstruction();\n\n // Convert [x,y] center point to Rect if needed\n const defaultRectSize = 30;\n const targetRect: Rect = Array.isArray(target)\n ? {\n left: Math.floor(target[0] - defaultRectSize / 2),\n top: Math.floor(target[1] - defaultRectSize / 2),\n width: defaultRectSize,\n height: defaultRectSize,\n }\n : target;\n\n let imagePayload = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n size: shotSize,\n elementsPositionInfo: [\n {\n rect: targetRect,\n },\n ],\n borderThickness: 3,\n });\n\n if (opt?.deepLocate) {\n const searchArea = expandSearchArea(targetRect, shotSize);\n // Always crop in describe mode. Unlike locate's deepLocate (where\n // cropping too small loses context for finding elements), describe's\n // deepLocate intentionally zooms in so the model produces a more\n // precise description from a focused view. expandSearchArea already\n // guarantees a minimum 400x400 area with surrounding context.\n debug('describe: cropping to searchArea', searchArea);\n const croppedResult = await cropByRect(\n imagePayload,\n searchArea,\n modelFamily === 'qwen2.5-vl',\n );\n imagePayload = croppedResult.imageBase64;\n }\n\n const memories = await this.getAIMemory();\n const memoryText = formatAIMemories(memories);\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n ...(memoryText\n ? [\n {\n type: 'text' as const,\n text: memoryText,\n },\n ]\n : []),\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n detail: 'high',\n },\n },\n ],\n },\n ];\n\n const res = await callAIWithObjectResponse<AIDescribeElementResponse>(\n msgs,\n modelConfig,\n );\n\n const { content } = res;\n assert(!content.error, `describe failed: ${content.error}`);\n assert(content.description, 'failed to describe the element');\n return content;\n }\n}\n"],"names":["debug","getDebug","Service","memories","normalizedMemories","normalizeAIMemory","undefined","query","opt","modelConfig","abortSignal","queryPrompt","assert","hasPlanLocatedElement","searchAreaPrompt","modelFamily","console","isAutoGLM","context","searchArea","searchAreaRawResponse","searchAreaUsage","searchAreaResponse","searchAreaConfig","buildSearchAreaConfig","JSON","AiLocateSection","startTime","Date","parseResult","rect","rawResponse","usage","reasoning_content","AiLocateElement","timeCost","taskInfo","errorLog","dumpData","elements","dump","createServiceDump","ServiceError","dataDemand","pageDescription","multimodalPrompt","result","AiExtractElementInfo","error","AIResponseParseError","data","thought","target","shotSize","screenshotBase64","systemPrompt","elementDescriberInstruction","defaultRectSize","targetRect","Array","Math","imagePayload","compositeElementInfoImg","expandSearchArea","croppedResult","cropByRect","memoryText","formatAIMemories","msgs","res","callAIWithObjectResponse","content","Promise"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAgDA,MAAMA,QAAQC,SAAS;AACR,MAAMC;IAyBnB,MAAc,cAA6C;QACzD,MAAMC,WAAY,MAAM,IAAI,CAAC,iBAAiB,QAAS,EAAE;QACzD,MAAMC,qBAAqBC,kBAAkBF;QAC7C,OAAOC,mBAAmB,MAAM,GAAGA,qBAAqBE;IAC1D;IAEA,MAAM,OACJC,KAA0B,EAC1BC,GAAe,EACfC,WAAyB,EACzBC,WAAyB,EACM;QAC/B,MAAMC,cAAc,AAAiB,YAAjB,OAAOJ,QAAqBA,QAAQA,MAAM,MAAM;QACpEK,OAAOD,aAAa;QAEpBC,OAAO,AAAiB,YAAjB,OAAOL,OAAoB;QAElC,MAAMM,wBAAwB,CAAC,CAACL,KAAK,oBAAoB;QAEzD,IAAIM;QACJ,IAAIP,MAAM,UAAU,IAAI,CAACM,uBACvBC,mBAAmBP,MAAM,MAAM;QAGjC,MAAM,EAAEQ,WAAW,EAAE,GAAGN;QAExB,IAAIK,oBAAoB,CAACC,aAAa;YACpCC,QAAQ,IAAI,CACV;YAEFF,mBAAmBR;QACrB;QAEA,IAAIQ,oBAAoBG,UAAUF,cAAc;YAC9CC,QAAQ,IAAI,CAAC;YACbF,mBAAmBR;QACrB;QAEA,MAAMY,UAAUV,KAAK,WAAY,MAAM,IAAI,CAAC,kBAAkB;QAC9D,MAAML,WAAW,MAAM,IAAI,CAAC,WAAW;QAEvC,IAAIgB;QACJ,IAAIC;QACJ,IAAIC;QACJ,IAAIC;QAGJ,IAAIf,MAAM,UAAU,IAAIM,uBAAuB;YAC7C,MAAMU,mBAAmB,MAAMC,sBAAsB;gBACnDN;gBACA,UAAUV,IAAI,kBAAkB,CAAE,IAAI;gBACtCO;YACF;YACAI,aAAaI,iBAAiB,IAAI;YAElCH,wBAAwBK,KAAK,SAAS,CAAC;gBACrC,QAAQ;gBACR,MAAMjB,IAAI,kBAAkB,CAAE,IAAI;YACpC;YACAc,qBAAqB;gBACnB,MAAMH;gBACN,aAAaI,iBAAiB,WAAW;gBACzC,OAAOA,iBAAiB,KAAK;gBAC7B,aAAaH;YACf;QACF,OAAO,IAAIN,kBAAkB;YAC3BQ,qBAAqB,MAAMI,gBAAgB;gBACzCR;gBACA,oBAAoBJ;gBACpBL;gBACAN;gBACAO;YACF;YACAE,OACEU,mBAAmB,IAAI,EACvB,CAAC,6BAA6B,EAAER,iBAAiB,CAAC,EAChDQ,mBAAmB,KAAK,GAAG,CAAC,EAAE,EAAEA,mBAAmB,KAAK,EAAE,GAAG,IAC7D;YAEJF,wBAAwBE,mBAAmB,WAAW;YACtDD,kBAAkBC,mBAAmB,KAAK;YAC1CH,aAAaG,mBAAmB,IAAI;QACtC;QAEA,MAAMK,YAAYC,KAAK,GAAG;QAC1B,MAAM,EAAEC,WAAW,EAAEC,IAAI,EAAEC,WAAW,EAAEC,KAAK,EAAEC,iBAAiB,EAAE,GAChE,MAAMC,gBAAgB;YACpBhB;YACA,0BAA0BP;YAC1B,cAAcW;YACdb;YACAN;YACAO;QACF;QAEF,MAAMyB,WAAWP,KAAK,GAAG,KAAKD;QAC9B,MAAMS,WAA4B;YAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YACtC,YAAYD;YACZ,aAAaV,KAAK,SAAS,CAACM;YAC5B,gBAAgBN,KAAK,SAAS,CAACI;YAC/BG;YACAb;YACAC;YACAC;YACAY;QACF;QAEA,IAAII;QACJ,IAAIR,YAAY,MAAM,EAAE,QACtBQ,WAAW,CAAC,4BAA4B,EAAER,YAAY,MAAM,CAAC,IAAI,CAAC,OAAO;QAG3E,MAAMS,WAAsC;YAC1C,MAAM;YACN,WAAW;gBACT,SAAS3B;YACX;YACA,gBAAgB,EAAE;YAClB,aAAamB;YACb,MAAM;YACNM;YACA,YAAY,CAAC,CAACjB;YACd,OAAOkB;QACT;QAEA,MAAME,WAAWV,YAAY,QAAQ,IAAI,EAAE;QAE3C,MAAMW,OAAOC,kBAAkB;YAC7B,GAAGH,QAAQ;YACX,gBAAgBC;QAClB;QAEA,IAAIF,UACF,MAAM,IAAIK,aAAaL,UAAUG;QAGnC,IAAID,SAAS,MAAM,GAAG,GACpB,MAAM,IAAIG,aACR,CAAC,0CAA0C,EAAEH,SAAS,MAAM,EAAE,EAC9DC;QAIJ,IAAID,AAAoB,MAApBA,SAAS,MAAM,EACjB,OAAO;YACL,SAAS;gBACP,QAAQA,QAAQ,CAAC,EAAE,CAAE,MAAM;gBAC3B,MAAMA,QAAQ,CAAC,EAAE,CAAE,IAAI;gBACvB,aAAaA,QAAQ,CAAC,EAAE,CAAE,WAAW;YACvC;YACAT;YACAU;QACF;QAGF,OAAO;YACL,SAAS;YACTV;YACAU;QACF;IACF;IAEA,MAAM,QACJG,UAA+B,EAC/BlC,WAAyB,EACzBD,GAA0B,EAC1BoC,eAAwB,EACxBC,gBAAoC,EACpC3B,OAAmB,EACe;QAClCN,OAAOM,SAAS;QAChBN,OACE,AAAsB,YAAtB,OAAO+B,cAA2B,AAAsB,YAAtB,OAAOA,YACzC,CAAC,+CAA+C,EAAE,OAAOA,YAAY;QAGvE,MAAMhB,YAAYC,KAAK,GAAG;QAE1B,IAAIC;QAGJ,IAAIE;QACJ,IAAIC;QACJ,IAAIC;QAEJ,IAAI;YACF,MAAMa,SAAS,MAAMC,qBAAwB;gBAC3C7B;gBACA,WAAWyB;gBACXE;gBACA,eAAerC;gBACfC;gBACAmC;gBACA,UAAU,MAAM,IAAI,CAAC,WAAW;YAClC;YACAf,cAAciB,OAAO,WAAW;YAChCf,cAAce,OAAO,WAAW;YAChCd,QAAQc,OAAO,KAAK;YACpBb,oBAAoBa,OAAO,iBAAiB;QAC9C,EAAE,OAAOE,OAAO;YACd,IAAIA,iBAAiBC,sBAAsB;gBAEzC,MAAMd,WAAWP,KAAK,GAAG,KAAKD;gBAC9B,MAAMS,WAA4B;oBAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;oBACtC,YAAYD;oBACZ,aAAaa,MAAM,WAAW;oBAC9B,OAAOA,MAAM,KAAK;gBACpB;gBACA,MAAMR,OAAOC,kBAAkB;oBAC7B,MAAM;oBACN,WAAW;wBAAEE;oBAAW;oBACxB,gBAAgB,EAAE;oBAClB,MAAM;oBACNP;oBACA,OAAOY,MAAM,OAAO;gBACtB;gBACA,MAAM,IAAIN,aAAaM,MAAM,OAAO,EAAER;YACxC;YACA,MAAMQ;QACR;QAEA,MAAMb,WAAWP,KAAK,GAAG,KAAKD;QAC9B,MAAMS,WAA4B;YAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YACtC,YAAYD;YACZJ;YACA,gBAAgBN,KAAK,SAAS,CAACI;YAC/BG;YACAC;QACF;QAEA,IAAII;QACJ,IAAIR,YAAY,MAAM,EAAE,QACtBQ,WAAW,CAAC,qBAAqB,EAAER,YAAY,MAAM,CAAC,IAAI,CAAC,OAAO;QAGpE,MAAMS,WAAsC;YAC1C,MAAM;YACN,WAAW;gBACTK;YACF;YACA,gBAAgB,EAAE;YAClB,MAAM;YACNP;YACA,OAAOC;QACT;QAEA,MAAM,EAAEa,IAAI,EAAEC,OAAO,EAAE,GAAGtB,eAAe,CAAC;QAE1C,MAAMW,OAAOC,kBAAkB;YAC7B,GAAGH,QAAQ;YACXY;QACF;QAEA,IAAIb,YAAY,CAACa,MACf,MAAM,IAAIR,aAAaL,UAAUG;QAGnC,OAAO;YACLU;YACAC;YACAnB;YACAC;YACAO;QACF;IACF;IAEA,MAAM,SACJY,MAA+B,EAC/B3C,WAAyB,EACzBD,GAEC,EACwD;QACzDI,OAAOwC,QAAQ;QACf,MAAMlC,UAAU,MAAM,IAAI,CAAC,kBAAkB;QAC7C,MAAM,EAAEmC,QAAQ,EAAE,GAAGnC;QACrB,MAAMoC,mBAAmBpC,QAAQ,UAAU,CAAC,MAAM;QAClDN,OAAO0C,kBAAkB;QAEzB,MAAM,EAAEvC,WAAW,EAAE,GAAGN;QACxB,MAAM8C,eAAeC;QAGrB,MAAMC,kBAAkB;QACxB,MAAMC,aAAmBC,MAAM,OAAO,CAACP,UACnC;YACE,MAAMQ,KAAK,KAAK,CAACR,MAAM,CAAC,EAAE,GAAGK,kBAAkB;YAC/C,KAAKG,KAAK,KAAK,CAACR,MAAM,CAAC,EAAE,GAAGK,kBAAkB;YAC9C,OAAOA;YACP,QAAQA;QACV,IACAL;QAEJ,IAAIS,eAAe,MAAMC,wBAAwB;YAC/C,gBAAgBR;YAChB,MAAMD;YACN,sBAAsB;gBACpB;oBACE,MAAMK;gBACR;aACD;YACD,iBAAiB;QACnB;QAEA,IAAIlD,KAAK,YAAY;YACnB,MAAMW,aAAa4C,iBAAiBL,YAAYL;YAMhDrD,MAAM,oCAAoCmB;YAC1C,MAAM6C,gBAAgB,MAAMC,WAC1BJ,cACA1C,YACAJ,AAAgB,iBAAhBA;YAEF8C,eAAeG,cAAc,WAAW;QAC1C;QAEA,MAAM7D,WAAW,MAAM,IAAI,CAAC,WAAW;QACvC,MAAM+D,aAAaC,iBAAiBhE;QACpC,MAAMiE,OAAe;YACnB;gBAAE,MAAM;gBAAU,SAASb;YAAa;YACxC;gBACE,MAAM;gBACN,SAAS;uBACHW,aACA;wBACE;4BACE,MAAM;4BACN,MAAMA;wBACR;qBACD,GACD,EAAE;oBACN;wBACE,MAAM;wBACN,WAAW;4BACT,KAAKL;4BACL,QAAQ;wBACV;oBACF;iBACD;YACH;SACD;QAED,MAAMQ,MAAM,MAAMC,yBAChBF,MACA3D;QAGF,MAAM,EAAE8D,OAAO,EAAE,GAAGF;QACpBzD,OAAO,CAAC2D,QAAQ,KAAK,EAAE,CAAC,iBAAiB,EAAEA,QAAQ,KAAK,EAAE;QAC1D3D,OAAO2D,QAAQ,WAAW,EAAE;QAC5B,OAAOA;IACT;IAvXA,YACErD,OAA2D,EAC3DV,GAAoB,CACpB;QAVF;QAEA;QACA,uBAAQ,qBAAR;QAQEI,OAAOM,SAAS;QAChB,IAAI,AAAmB,cAAnB,OAAOA,SACT,IAAI,CAAC,kBAAkB,GAAGA;aAE1B,IAAI,CAAC,kBAAkB,GAAG,IAAMsD,QAAQ,OAAO,CAACtD;QAGlD,IAAI,AAAyB,WAAlBV,KAAK,UACd,IAAI,CAAC,QAAQ,GAAGA,IAAI,QAAQ;QAE9B,IAAI,CAAC,iBAAiB,GAAGA,KAAK;IAChC;AAyWF"}
1
+ {"version":3,"file":"service/index.mjs","sources":["../../../src/service/index.ts"],"sourcesContent":["import { isAutoGLM, isUITars } from '@/ai-model/auto-glm/util';\nimport {\n AIResponseParseError,\n AiExtractElementInfo,\n AiLocateElement,\n callAIWithObjectResponse,\n type ModelRuntime,\n} from '@/ai-model/index';\nimport { AiLocateSection, buildSearchAreaConfig } from '@/ai-model/inspect';\nimport { elementDescriberInstruction } from '@/ai-model/prompt/describe';\nimport { formatAIMemories, normalizeAIMemory } from '@/ai-model/prompt/util';\nimport { type AIArgs, expandSearchArea } from '@/common';\nimport type {\n AIDescribeElementResponse,\n AIUsageInfo,\n DetailedLocateParam,\n LocateResultElement,\n LocateResultWithDump,\n PartialServiceDumpFromSDK,\n PlanningLocateParam,\n Rect,\n ServiceExtractOption,\n ServiceExtractParam,\n ServiceExtractResult,\n ServiceTaskInfo,\n UIContext,\n} from '@/types';\nimport { ServiceError } from '@/types';\nimport type { IModelConfig } from '@aiscene/shared/env';\nimport { compositeElementInfoImg, cropByRect } from '@aiscene/shared/img';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { assert } from '@aiscene/shared/utils';\nimport type { TMultimodalPrompt } from '../common';\nimport { createServiceDump } from './utils';\n\nexport interface LocateOpts {\n context?: UIContext;\n planLocatedElement?: LocateResultElement;\n}\n\nexport type AnyValue<T> = {\n [K in keyof T]: unknown extends T[K] ? any : T[K];\n};\n\ninterface ServiceOptions {\n taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n memoryRetrieverFn?: () => readonly string[] | Promise<readonly string[]>;\n}\n\nconst debug = getDebug('ai:service');\ntype ModelRuntimeInput = IModelConfig | ModelRuntime;\n\nfunction resolveModelConfig(input: ModelRuntimeInput): IModelConfig {\n return 'config' in input ? input.config : input;\n}\n\nexport default class Service {\n contextRetrieverFn: () => Promise<UIContext> | UIContext;\n\n taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n private memoryRetrieverFn?: () =>\n | readonly string[]\n | Promise<readonly string[]>;\n\n constructor(\n context: UIContext | (() => Promise<UIContext> | UIContext),\n opt?: ServiceOptions,\n ) {\n assert(context, 'context is required for Service');\n if (typeof context === 'function') {\n this.contextRetrieverFn = context;\n } else {\n this.contextRetrieverFn = () => Promise.resolve(context);\n }\n\n if (typeof opt?.taskInfo !== 'undefined') {\n this.taskInfo = opt.taskInfo;\n }\n this.memoryRetrieverFn = opt?.memoryRetrieverFn;\n }\n\n private async getAIMemory(): Promise<string[] | undefined> {\n const memories = (await this.memoryRetrieverFn?.()) || [];\n const normalizedMemories = normalizeAIMemory(memories);\n return normalizedMemories.length ? normalizedMemories : undefined;\n }\n\n async locate(\n query: PlanningLocateParam,\n opt: LocateOpts,\n modelRuntimeOrConfig: ModelRuntimeInput,\n abortSignal?: AbortSignal,\n ): Promise<LocateResultWithDump> {\n const modelConfig = resolveModelConfig(modelRuntimeOrConfig);\n const queryPrompt = typeof query === 'string' ? query : query.prompt;\n assert(queryPrompt, 'query is required for locate');\n\n assert(typeof query === 'object', 'query should be an object for locate');\n\n const hasPlanLocatedElement = !!opt?.planLocatedElement?.rect;\n\n let searchAreaPrompt;\n if (query.deepLocate && !hasPlanLocatedElement) {\n searchAreaPrompt = query.prompt;\n }\n\n const { modelFamily } = modelConfig;\n\n if (searchAreaPrompt && !modelFamily) {\n console.warn(\n 'The \"deepLocate\" feature is not supported with multimodal LLM. Please config VL model for Midscene. https://midscenejs.com/model-config',\n );\n searchAreaPrompt = undefined;\n }\n\n if (searchAreaPrompt && isAutoGLM(modelFamily)) {\n console.warn('The \"deepLocate\" feature is not supported with AutoGLM.');\n searchAreaPrompt = undefined;\n }\n\n const context = opt?.context || (await this.contextRetrieverFn());\n const memories = await this.getAIMemory();\n\n let searchArea: Rect | undefined = undefined;\n let searchAreaRawResponse: string | undefined = undefined;\n let searchAreaUsage: AIUsageInfo | undefined = undefined;\n let searchAreaResponse:\n | Awaited<ReturnType<typeof AiLocateSection>>\n | undefined = undefined;\n if (query.deepLocate && hasPlanLocatedElement) {\n const searchAreaConfig = await buildSearchAreaConfig({\n context,\n baseRect: opt.planLocatedElement!.rect,\n modelFamily,\n });\n searchArea = searchAreaConfig.rect;\n\n searchAreaRawResponse = JSON.stringify({\n source: 'plan-located-element',\n rect: opt.planLocatedElement!.rect,\n });\n searchAreaResponse = {\n rect: searchArea,\n imageBase64: searchAreaConfig.imageBase64,\n scale: searchAreaConfig.scale,\n rawResponse: searchAreaRawResponse,\n };\n } else if (searchAreaPrompt) {\n searchAreaResponse = await AiLocateSection({\n context,\n sectionDescription: searchAreaPrompt,\n modelConfig,\n memories,\n abortSignal,\n });\n assert(\n searchAreaResponse.rect,\n `cannot find search area for \"${searchAreaPrompt}\"${\n searchAreaResponse.error ? `: ${searchAreaResponse.error}` : ''\n }`,\n );\n searchAreaRawResponse = searchAreaResponse.rawResponse;\n searchAreaUsage = searchAreaResponse.usage;\n searchArea = searchAreaResponse.rect;\n }\n\n const startTime = Date.now();\n const { parseResult, rect, rawResponse, usage, reasoning_content } =\n await AiLocateElement({\n context,\n targetElementDescription: queryPrompt,\n searchConfig: searchAreaResponse,\n modelConfig,\n memories,\n abortSignal,\n });\n\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse: JSON.stringify(rawResponse),\n formatResponse: JSON.stringify(parseResult),\n usage,\n searchArea,\n searchAreaRawResponse,\n searchAreaUsage,\n reasoning_content,\n };\n\n let errorLog: string | undefined;\n if (parseResult.errors?.length) {\n errorLog = `failed to locate element: \\n${parseResult.errors.join('\\n')}`;\n }\n\n const dumpData: PartialServiceDumpFromSDK = {\n type: 'locate',\n userQuery: {\n element: queryPrompt,\n },\n matchedElement: [],\n matchedRect: rect,\n data: null,\n taskInfo,\n deepLocate: !!searchArea,\n error: errorLog,\n };\n\n const elements = parseResult.elements || [];\n\n const dump = createServiceDump({\n ...dumpData,\n matchedElement: elements,\n });\n\n if (errorLog) {\n throw new ServiceError(errorLog, dump);\n }\n\n if (elements.length > 1) {\n throw new ServiceError(\n `locate: multiple elements found, length = ${elements.length}`,\n dump,\n );\n }\n\n if (elements.length === 1) {\n return {\n element: {\n center: elements[0]!.center,\n rect: elements[0]!.rect,\n description: elements[0]!.description,\n },\n rect,\n dump,\n };\n }\n\n return {\n element: null,\n rect,\n dump,\n };\n }\n\n async extract<T>(\n dataDemand: ServiceExtractParam,\n modelConfig: IModelConfig,\n opt?: ServiceExtractOption,\n pageDescription?: string,\n multimodalPrompt?: TMultimodalPrompt,\n context?: UIContext,\n ): Promise<ServiceExtractResult<T>> {\n assert(context, 'context is required for extract');\n assert(\n typeof dataDemand === 'object' || typeof dataDemand === 'string',\n `dataDemand should be object or string, but get ${typeof dataDemand}`,\n );\n\n const startTime = Date.now();\n\n let parseResult: Awaited<\n ReturnType<typeof AiExtractElementInfo<T>>\n >['parseResult'];\n let rawResponse: string;\n let usage: Awaited<ReturnType<typeof AiExtractElementInfo<T>>>['usage'];\n let reasoning_content: string | undefined;\n\n try {\n const result = await AiExtractElementInfo<T>({\n context,\n dataQuery: dataDemand,\n multimodalPrompt,\n extractOption: opt,\n modelConfig,\n pageDescription,\n memories: await this.getAIMemory(),\n });\n parseResult = result.parseResult;\n rawResponse = result.rawResponse;\n usage = result.usage;\n reasoning_content = result.reasoning_content;\n } catch (error) {\n if (error instanceof AIResponseParseError) {\n // Create dump with usage and rawResponse from the error\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse: error.rawResponse,\n usage: error.usage,\n };\n const dump = createServiceDump({\n type: 'extract',\n userQuery: { dataDemand },\n matchedElement: [],\n data: null,\n taskInfo,\n error: error.message,\n });\n throw new ServiceError(error.message, dump);\n }\n throw error;\n }\n\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse,\n formatResponse: JSON.stringify(parseResult),\n usage,\n reasoning_content,\n };\n\n let errorLog: string | undefined;\n if (parseResult.errors?.length) {\n errorLog = `AI response error: \\n${parseResult.errors.join('\\n')}`;\n }\n\n const dumpData: PartialServiceDumpFromSDK = {\n type: 'extract',\n userQuery: {\n dataDemand,\n },\n matchedElement: [],\n data: null,\n taskInfo,\n error: errorLog,\n };\n\n const { data, thought } = parseResult || {};\n\n const dump = createServiceDump({\n ...dumpData,\n data,\n });\n\n if (errorLog && !data) {\n throw new ServiceError(errorLog, dump);\n }\n\n return {\n data,\n thought,\n usage,\n reasoning_content,\n dump,\n };\n }\n\n async describe(\n target: Rect | [number, number],\n modelRuntimeOrConfig: ModelRuntimeInput,\n opt?: {\n deepLocate?: boolean;\n deepDescribe?: boolean;\n context?: UIContext;\n },\n ): Promise<Pick<AIDescribeElementResponse, 'description'>> {\n const modelConfig = resolveModelConfig(modelRuntimeOrConfig);\n assert(target, 'target is required for service.describe');\n const context = opt?.context || (await this.contextRetrieverFn());\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(screenshotBase64, 'screenshot is required for service.describe');\n // The result of the \"describe\" function will be used for positioning, so essentially it is a form of grounding.\n const { modelFamily } = modelConfig;\n const systemPrompt = elementDescriberInstruction();\n\n // Convert [x,y] center point to Rect if needed\n const defaultRectSize = 30;\n const targetRect: Rect = Array.isArray(target)\n ? {\n left: Math.floor(target[0] - defaultRectSize / 2),\n top: Math.floor(target[1] - defaultRectSize / 2),\n width: defaultRectSize,\n height: defaultRectSize,\n }\n : target;\n\n let imagePayload = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n size: shotSize,\n elementsPositionInfo: [\n {\n rect: targetRect,\n },\n ],\n borderThickness: 3,\n });\n\n if (opt?.deepLocate || opt?.deepDescribe) {\n const searchArea = expandSearchArea(targetRect, shotSize);\n // Always crop in describe mode. Unlike locate's deepLocate (where\n // cropping too small loses context for finding elements), describe's\n // deepLocate intentionally zooms in so the model produces a more\n // precise description from a focused view. expandSearchArea already\n // guarantees a minimum 400x400 area with surrounding context.\n debug('describe: cropping to searchArea', searchArea);\n const croppedResult = await cropByRect(\n imagePayload,\n searchArea,\n modelFamily === 'qwen2.5-vl',\n );\n imagePayload = croppedResult.imageBase64;\n }\n\n const memories = await this.getAIMemory();\n const memoryText = formatAIMemories(memories);\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n ...(memoryText\n ? [\n {\n type: 'text' as const,\n text: memoryText,\n },\n ]\n : []),\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n detail: 'high',\n },\n },\n ],\n },\n ];\n\n const res = await callAIWithObjectResponse<AIDescribeElementResponse>(\n msgs,\n modelRuntimeOrConfig,\n );\n\n const { content } = res;\n assert(!content.error, `describe failed: ${content.error}`);\n assert(content.description, 'failed to describe the element');\n return content;\n }\n}\n"],"names":["debug","getDebug","resolveModelConfig","input","Service","memories","normalizedMemories","normalizeAIMemory","undefined","query","opt","modelRuntimeOrConfig","abortSignal","modelConfig","queryPrompt","assert","hasPlanLocatedElement","searchAreaPrompt","modelFamily","console","isAutoGLM","context","searchArea","searchAreaRawResponse","searchAreaUsage","searchAreaResponse","searchAreaConfig","buildSearchAreaConfig","JSON","AiLocateSection","startTime","Date","parseResult","rect","rawResponse","usage","reasoning_content","AiLocateElement","timeCost","taskInfo","errorLog","dumpData","elements","dump","createServiceDump","ServiceError","dataDemand","pageDescription","multimodalPrompt","result","AiExtractElementInfo","error","AIResponseParseError","data","thought","target","shotSize","screenshotBase64","systemPrompt","elementDescriberInstruction","defaultRectSize","targetRect","Array","Math","imagePayload","compositeElementInfoImg","expandSearchArea","croppedResult","cropByRect","memoryText","formatAIMemories","msgs","res","callAIWithObjectResponse","content","Promise"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"task-runner.mjs","sources":["../../src/task-runner.ts"],"sourcesContent":["import type { ScreenshotItem } from '@/screenshot-item';\nimport { setTimingFieldOnce } from '@/task-timing';\nimport {\n ExecutionDump,\n type ExecutionRecorderItem,\n type ExecutionTask,\n type ExecutionTaskActionApply,\n type ExecutionTaskApply,\n type ExecutionTaskPlanningLocateOutput,\n type ExecutionTaskProgressOptions,\n type ExecutionTaskReturn,\n type ExecutorContext,\n type PlanningActionParamError,\n type UIContext,\n} from '@/types';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { assert, uuid } from '@aiscene/shared/utils';\n\nconst debug = getDebug('task-runner');\nconst UI_CONTEXT_CACHE_TTL_MS = 300;\n\ntype TaskRunnerInitOptions = ExecutionTaskProgressOptions & {\n tasks?: ExecutionTaskApply[];\n onTaskUpdate?: (\n runner: TaskRunner,\n error?: TaskExecutionError,\n ) => Promise<void> | void;\n};\n\ntype TaskRunnerOperationOptions = {\n allowWhenError?: boolean;\n};\n\nexport class TaskRunner {\n readonly id: string;\n name: string;\n\n tasks: ExecutionTask[];\n\n // status of runner\n status: 'init' | 'pending' | 'running' | 'completed' | 'error';\n\n onTaskStart?: ExecutionTaskProgressOptions['onTaskStart'];\n\n private readonly uiContextBuilder: () => Promise<UIContext>;\n\n private readonly onTaskUpdate?:\n | ((runner: TaskRunner, error?: TaskExecutionError) => Promise<void> | void)\n | undefined;\n\n private readonly executionLogTime: number;\n\n constructor(\n name: string,\n uiContextBuilder: () => Promise<UIContext>,\n options?: TaskRunnerInitOptions,\n ) {\n this.id = uuid();\n this.status =\n options?.tasks && options.tasks.length > 0 ? 'pending' : 'init';\n this.name = name;\n this.tasks = (options?.tasks || []).map((item) =>\n this.markTaskAsPending(item),\n );\n this.onTaskStart = options?.onTaskStart;\n this.uiContextBuilder = uiContextBuilder;\n this.onTaskUpdate = options?.onTaskUpdate;\n this.executionLogTime = Date.now();\n }\n\n private async emitOnTaskUpdate(error?: TaskExecutionError): Promise<void> {\n if (!this.onTaskUpdate) {\n return;\n }\n await this.onTaskUpdate(this, error);\n }\n\n private lastUiContext?: {\n context: UIContext;\n capturedAt: number;\n };\n\n private async getUiContext(options?: { forceRefresh?: boolean }): Promise<\n UIContext | undefined\n > {\n const now = Date.now();\n const shouldReuse =\n !options?.forceRefresh &&\n this.lastUiContext &&\n now - this.lastUiContext.capturedAt <= UI_CONTEXT_CACHE_TTL_MS;\n\n if (shouldReuse && this.lastUiContext?.context) {\n debug(\n `reuse cached uiContext captured ${now - this.lastUiContext.capturedAt}ms ago`,\n );\n return this.lastUiContext?.context;\n }\n\n try {\n const uiContext = await this.uiContextBuilder();\n if (uiContext) {\n this.lastUiContext = {\n context: uiContext,\n capturedAt: Date.now(),\n };\n } else {\n this.lastUiContext = undefined;\n }\n return uiContext;\n } catch (error) {\n this.lastUiContext = undefined;\n throw error;\n }\n }\n\n private async captureScreenshot(): Promise<ScreenshotItem | undefined> {\n try {\n const uiContext = await this.getUiContext({ forceRefresh: true });\n return uiContext?.screenshot;\n } catch (error) {\n console.error('error while capturing screenshot', error);\n }\n return undefined;\n }\n\n private attachRecorderItem(\n task: ExecutionTask,\n screenshot: ScreenshotItem | undefined,\n phase: 'after-calling',\n ): void {\n if (!phase || !screenshot) {\n return;\n }\n\n const recorderItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: Date.now(),\n screenshot,\n timing: phase,\n };\n\n if (!task.recorder) {\n task.recorder = [recorderItem];\n return;\n }\n task.recorder.push(recorderItem);\n }\n\n private markTaskAsPending(task: ExecutionTaskApply): ExecutionTask {\n return {\n taskId: uuid(),\n status: 'pending',\n ...task,\n };\n }\n\n private normalizeStatusFromError(\n options?: TaskRunnerOperationOptions,\n errorMessage?: string,\n ): void {\n if (this.status !== 'error') {\n return;\n }\n assert(\n options?.allowWhenError,\n errorMessage ||\n `task runner is in error state, cannot proceed\\nerror=${this.latestErrorTask()?.error}\\n${this.latestErrorTask()?.errorStack}`,\n );\n // reset runner state so new tasks can run\n this.status = this.tasks.length > 0 ? 'pending' : 'init';\n }\n\n async append(\n task: ExecutionTaskApply[] | ExecutionTaskApply,\n options?: TaskRunnerOperationOptions,\n ): Promise<void> {\n this.normalizeStatusFromError(\n options,\n `task runner is in error state, cannot append task\\nerror=${this.latestErrorTask()?.error}\\n${this.latestErrorTask()?.errorStack}`,\n );\n if (Array.isArray(task)) {\n this.tasks.push(...task.map((item) => this.markTaskAsPending(item)));\n } else {\n this.tasks.push(this.markTaskAsPending(task));\n }\n if (this.status !== 'running') {\n this.status = 'pending';\n }\n await this.emitOnTaskUpdate();\n }\n\n async appendAndFlush(\n task: ExecutionTaskApply[] | ExecutionTaskApply,\n options?: TaskRunnerOperationOptions,\n ): Promise<{ output: any; thought?: string } | undefined> {\n await this.append(task, options);\n return this.flush(options);\n }\n\n async flush(\n options?: TaskRunnerOperationOptions,\n ): Promise<{ output: any; thought?: string } | undefined> {\n if (this.status === 'init' && this.tasks.length > 0) {\n console.warn(\n 'illegal state for task runner, status is init but tasks are not empty',\n );\n }\n\n this.normalizeStatusFromError(options, 'task runner is in error state');\n assert(this.status !== 'running', 'task runner is already running');\n assert(this.status !== 'completed', 'task runner is already completed');\n\n const nextPendingIndex = this.tasks.findIndex(\n (task) => task.status === 'pending',\n );\n if (nextPendingIndex < 0) {\n // all tasks are completed\n return;\n }\n\n this.status = 'running';\n await this.emitOnTaskUpdate();\n let taskIndex = nextPendingIndex;\n let successfullyCompleted = true;\n\n let previousFindOutput: ExecutionTaskPlanningLocateOutput | undefined;\n\n while (taskIndex < this.tasks.length) {\n const task = this.tasks[taskIndex];\n assert(\n task.status === 'pending',\n `task status should be pending, but got: ${task.status}`,\n );\n task.timing = {\n start: Date.now(),\n };\n try {\n task.status = 'running';\n await this.emitOnTaskUpdate();\n try {\n if (this.onTaskStart) {\n await this.onTaskStart(task);\n }\n } catch (e) {\n console.error('error in onTaskStart', e);\n }\n assert(\n ['Insight', 'Action Space', 'Planning'].indexOf(task.type) >= 0,\n `unsupported task type: ${task.type}`,\n );\n\n const { executor, param } = task;\n assert(executor, `executor is required for task type: ${task.type}`);\n\n let returnValue;\n // For Insight tasks (Query/Assert/WaitFor), always get fresh context\n // to ensure we have the latest UI state after any preceding actions\n const forceRefresh = task.type === 'Insight';\n setTimingFieldOnce(task.timing, 'getUiContextStart');\n const uiContext = await this.getUiContext({ forceRefresh });\n setTimingFieldOnce(task.timing, 'getUiContextEnd');\n\n task.uiContext = uiContext;\n const executorContext: ExecutorContext = {\n task,\n element: previousFindOutput?.element,\n uiContext,\n };\n\n if (task.type === 'Insight') {\n assert(\n task.subType === 'Query' ||\n task.subType === 'Assert' ||\n task.subType === 'WaitFor' ||\n task.subType === 'Boolean' ||\n task.subType === 'Number' ||\n task.subType === 'String',\n `unsupported service subType: ${task.subType}`,\n );\n returnValue = await task.executor(param, executorContext);\n } else if (task.type === 'Planning') {\n returnValue = await task.executor(param, executorContext);\n if (task.subType === 'Locate') {\n previousFindOutput = (\n returnValue as ExecutionTaskReturn<ExecutionTaskPlanningLocateOutput>\n )?.output;\n }\n } else if (task.type === 'Action Space') {\n returnValue = await task.executor(param, executorContext);\n } else {\n console.warn(\n `unsupported task type: ${task.type}, will try to execute it directly`,\n );\n returnValue = await task.executor(param, executorContext);\n }\n\n const isLastTask = taskIndex === this.tasks.length - 1;\n\n if (isLastTask) {\n setTimingFieldOnce(task.timing, 'captureAfterCallingSnapshotStart');\n const screenshot = await this.captureScreenshot();\n this.attachRecorderItem(task, screenshot, 'after-calling');\n setTimingFieldOnce(task.timing, 'captureAfterCallingSnapshotEnd');\n }\n\n Object.assign(task, returnValue);\n task.status = 'finished';\n task.timing.end = Date.now();\n task.timing.cost = task.timing.end - task.timing.start;\n await this.emitOnTaskUpdate();\n taskIndex++;\n } catch (e: any) {\n successfullyCompleted = false;\n task.error = e;\n task.errorMessage =\n e?.message || (typeof e === 'string' ? e : 'error-without-message');\n task.errorStack = e.stack;\n\n task.status = 'failed';\n task.timing.end = Date.now();\n task.timing.cost = task.timing.end - task.timing.start;\n await this.emitOnTaskUpdate();\n break;\n }\n }\n\n // set all remaining tasks as cancelled\n for (let i = taskIndex + 1; i < this.tasks.length; i++) {\n this.tasks[i].status = 'cancelled';\n }\n if (taskIndex + 1 < this.tasks.length) {\n await this.emitOnTaskUpdate();\n }\n\n let finalizeError: TaskExecutionError | undefined;\n if (!successfullyCompleted) {\n this.status = 'error';\n const errorTask = this.latestErrorTask();\n const messageBase =\n errorTask?.errorMessage ||\n (errorTask?.error ? String(errorTask.error) : 'Task execution failed');\n const stack = errorTask?.errorStack;\n const message = stack ? `${messageBase}\\n${stack}` : messageBase;\n finalizeError = new TaskExecutionError(message, this, errorTask, {\n cause: errorTask?.error,\n });\n await this.emitOnTaskUpdate(finalizeError);\n } else {\n this.status = 'completed';\n await this.emitOnTaskUpdate();\n }\n\n if (finalizeError) {\n throw finalizeError;\n }\n\n if (this.tasks.length) {\n // return the last output\n const outputIndex = Math.min(taskIndex, this.tasks.length - 1);\n const { thought, output } = this.tasks[outputIndex];\n return {\n thought,\n output,\n };\n }\n }\n\n isInErrorState(): boolean {\n return this.status === 'error';\n }\n\n latestErrorTask(): ExecutionTask | null {\n if (this.status !== 'error') {\n return null;\n }\n // Find the LAST failed task (not the first one)\n // This is important when using allowWhenError to continue after errors\n for (let i = this.tasks.length - 1; i >= 0; i--) {\n if (this.tasks[i].status === 'failed') {\n return this.tasks[i];\n }\n }\n return null;\n }\n\n dump(): ExecutionDump {\n return new ExecutionDump({\n id: this.id,\n logTime: this.executionLogTime,\n name: this.name,\n tasks: this.tasks,\n });\n }\n\n async appendErrorPlan(errorMsg: string): Promise<{\n output: undefined;\n runner: TaskRunner;\n }> {\n const errorTask: ExecutionTaskActionApply<PlanningActionParamError> = {\n type: 'Action Space',\n subType: 'Error',\n param: {\n thought: errorMsg,\n },\n thought: errorMsg,\n executor: async () => {\n throw new Error(errorMsg || 'error without thought');\n },\n };\n await this.appendAndFlush(errorTask);\n\n return {\n output: undefined,\n runner: this,\n };\n }\n}\n\nexport class TaskExecutionError extends Error {\n runner: TaskRunner;\n\n errorTask: ExecutionTask | null;\n\n constructor(\n message: string,\n runner: TaskRunner,\n errorTask: ExecutionTask | null,\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.runner = runner;\n this.errorTask = errorTask;\n }\n}\n"],"names":["debug","getDebug","UI_CONTEXT_CACHE_TTL_MS","TaskRunner","error","options","now","Date","shouldReuse","uiContext","undefined","console","task","screenshot","phase","recorderItem","uuid","errorMessage","assert","Array","item","nextPendingIndex","taskIndex","successfullyCompleted","previousFindOutput","e","executor","param","returnValue","forceRefresh","setTimingFieldOnce","executorContext","isLastTask","Object","i","finalizeError","errorTask","messageBase","String","stack","message","TaskExecutionError","outputIndex","Math","thought","output","ExecutionDump","errorMsg","Error","name","uiContextBuilder","runner"],"mappings":"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"}
1
+ {"version":3,"file":"task-runner.mjs","sources":["../../src/task-runner.ts"],"sourcesContent":["import type { ScreenshotItem } from '@/screenshot-item';\nimport { setTimingFieldOnce } from '@/task-timing';\nimport {\n ExecutionDump,\n type ExecutionRecorderItem,\n type ExecutionTask,\n type ExecutionTaskActionApply,\n type ExecutionTaskApply,\n type ExecutionTaskPlanningLocateOutput,\n type ExecutionTaskProgressOptions,\n type ExecutionTaskReturn,\n type ExecutorContext,\n type PlanningActionParamError,\n type UIContext,\n} from '@/types';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { assert, uuid } from '@aiscene/shared/utils';\n\nconst debug = getDebug('task-runner');\nconst UI_CONTEXT_CACHE_TTL_MS = 300;\n\nexport type TaskRunnerEventKind =\n | 'append'\n | 'start'\n | 'finish'\n | 'error'\n | 'cancel';\n\nexport interface TaskRunnerEvent {\n kind: TaskRunnerEventKind;\n task: ExecutionTask;\n runner: TaskRunner;\n}\n\ntype TaskRunnerInitOptions = ExecutionTaskProgressOptions & {\n tasks?: ExecutionTaskApply[];\n onTaskUpdate?: (\n runner: TaskRunner,\n error?: TaskExecutionError,\n ) => Promise<void> | void;\n};\n\ntype TaskRunnerOperationOptions = {\n allowWhenError?: boolean;\n};\n\nexport class TaskRunner {\n readonly id: string;\n name: string;\n\n tasks: ExecutionTask[];\n\n // status of runner\n status: 'init' | 'pending' | 'running' | 'completed' | 'error';\n\n onTaskStart?: ExecutionTaskProgressOptions['onTaskStart'];\n\n private readonly uiContextBuilder: () => Promise<UIContext>;\n\n private readonly onTaskUpdate?:\n | ((runner: TaskRunner, error?: TaskExecutionError) => Promise<void> | void)\n | undefined;\n\n private readonly executionLogTime: number;\n\n constructor(\n name: string,\n uiContextBuilder: () => Promise<UIContext>,\n options?: TaskRunnerInitOptions,\n ) {\n this.id = uuid();\n this.status =\n options?.tasks && options.tasks.length > 0 ? 'pending' : 'init';\n this.name = name;\n this.tasks = (options?.tasks || []).map((item) =>\n this.markTaskAsPending(item),\n );\n this.onTaskStart = options?.onTaskStart;\n this.uiContextBuilder = uiContextBuilder;\n this.onTaskUpdate = options?.onTaskUpdate;\n this.executionLogTime = Date.now();\n }\n\n private async emitOnTaskUpdate(error?: TaskExecutionError): Promise<void> {\n if (!this.onTaskUpdate) {\n return;\n }\n await this.onTaskUpdate(this, error);\n }\n\n private lastUiContext?: {\n context: UIContext;\n capturedAt: number;\n };\n\n private async getUiContext(options?: { forceRefresh?: boolean }): Promise<\n UIContext | undefined\n > {\n const now = Date.now();\n const shouldReuse =\n !options?.forceRefresh &&\n this.lastUiContext &&\n now - this.lastUiContext.capturedAt <= UI_CONTEXT_CACHE_TTL_MS;\n\n if (shouldReuse && this.lastUiContext?.context) {\n debug(\n `reuse cached uiContext captured ${now - this.lastUiContext.capturedAt}ms ago`,\n );\n return this.lastUiContext?.context;\n }\n\n try {\n const uiContext = await this.uiContextBuilder();\n if (uiContext) {\n this.lastUiContext = {\n context: uiContext,\n capturedAt: Date.now(),\n };\n } else {\n this.lastUiContext = undefined;\n }\n return uiContext;\n } catch (error) {\n this.lastUiContext = undefined;\n throw error;\n }\n }\n\n private async captureScreenshot(): Promise<ScreenshotItem | undefined> {\n try {\n const uiContext = await this.getUiContext({ forceRefresh: true });\n return uiContext?.screenshot;\n } catch (error) {\n console.error('error while capturing screenshot', error);\n }\n return undefined;\n }\n\n private attachRecorderItem(\n task: ExecutionTask,\n screenshot: ScreenshotItem | undefined,\n phase: 'after-calling',\n ): void {\n if (!phase || !screenshot) {\n return;\n }\n\n const recorderItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: Date.now(),\n screenshot,\n timing: phase,\n };\n\n if (!task.recorder) {\n task.recorder = [recorderItem];\n return;\n }\n task.recorder.push(recorderItem);\n }\n\n private markTaskAsPending(task: ExecutionTaskApply): ExecutionTask {\n return {\n taskId: uuid(),\n status: 'pending',\n ...task,\n };\n }\n\n private normalizeStatusFromError(\n options?: TaskRunnerOperationOptions,\n errorMessage?: string,\n ): void {\n if (this.status !== 'error') {\n return;\n }\n assert(\n options?.allowWhenError,\n errorMessage ||\n `task runner is in error state, cannot proceed\\nerror=${this.latestErrorTask()?.error}\\n${this.latestErrorTask()?.errorStack}`,\n );\n // reset runner state so new tasks can run\n this.status = this.tasks.length > 0 ? 'pending' : 'init';\n }\n\n async append(\n task: ExecutionTaskApply[] | ExecutionTaskApply,\n options?: TaskRunnerOperationOptions,\n ): Promise<void> {\n this.normalizeStatusFromError(\n options,\n `task runner is in error state, cannot append task\\nerror=${this.latestErrorTask()?.error}\\n${this.latestErrorTask()?.errorStack}`,\n );\n if (Array.isArray(task)) {\n this.tasks.push(...task.map((item) => this.markTaskAsPending(item)));\n } else {\n this.tasks.push(this.markTaskAsPending(task));\n }\n if (this.status !== 'running') {\n this.status = 'pending';\n }\n await this.emitOnTaskUpdate();\n }\n\n async appendAndFlush(\n task: ExecutionTaskApply[] | ExecutionTaskApply,\n options?: TaskRunnerOperationOptions,\n ): Promise<{ output: any; thought?: string } | undefined> {\n await this.append(task, options);\n return this.flush(options);\n }\n\n async flush(\n options?: TaskRunnerOperationOptions,\n ): Promise<{ output: any; thought?: string } | undefined> {\n if (this.status === 'init' && this.tasks.length > 0) {\n console.warn(\n 'illegal state for task runner, status is init but tasks are not empty',\n );\n }\n\n this.normalizeStatusFromError(options, 'task runner is in error state');\n assert(this.status !== 'running', 'task runner is already running');\n assert(this.status !== 'completed', 'task runner is already completed');\n\n const nextPendingIndex = this.tasks.findIndex(\n (task) => task.status === 'pending',\n );\n if (nextPendingIndex < 0) {\n // all tasks are completed\n return;\n }\n\n this.status = 'running';\n await this.emitOnTaskUpdate();\n let taskIndex = nextPendingIndex;\n let successfullyCompleted = true;\n\n let previousFindOutput: ExecutionTaskPlanningLocateOutput | undefined;\n\n while (taskIndex < this.tasks.length) {\n const task = this.tasks[taskIndex];\n assert(\n task.status === 'pending',\n `task status should be pending, but got: ${task.status}`,\n );\n task.timing = {\n start: Date.now(),\n };\n try {\n task.status = 'running';\n await this.emitOnTaskUpdate();\n try {\n if (this.onTaskStart) {\n await this.onTaskStart(task);\n }\n } catch (e) {\n console.error('error in onTaskStart', e);\n }\n assert(\n ['Insight', 'Action Space', 'Planning'].indexOf(task.type) >= 0,\n `unsupported task type: ${task.type}`,\n );\n\n const { executor, param } = task;\n assert(executor, `executor is required for task type: ${task.type}`);\n\n let returnValue;\n // For Insight tasks (Query/Assert/WaitFor), always get fresh context\n // to ensure we have the latest UI state after any preceding actions\n const forceRefresh = task.type === 'Insight';\n setTimingFieldOnce(task.timing, 'getUiContextStart');\n const uiContext = await this.getUiContext({ forceRefresh });\n setTimingFieldOnce(task.timing, 'getUiContextEnd');\n\n task.uiContext = uiContext;\n const executorContext: ExecutorContext = {\n task,\n element: previousFindOutput?.element,\n uiContext,\n };\n\n if (task.type === 'Insight') {\n assert(\n task.subType === 'Query' ||\n task.subType === 'Assert' ||\n task.subType === 'WaitFor' ||\n task.subType === 'Boolean' ||\n task.subType === 'Number' ||\n task.subType === 'String',\n `unsupported service subType: ${task.subType}`,\n );\n returnValue = await task.executor(param, executorContext);\n } else if (task.type === 'Planning') {\n returnValue = await task.executor(param, executorContext);\n if (task.subType === 'Locate') {\n previousFindOutput = (\n returnValue as ExecutionTaskReturn<ExecutionTaskPlanningLocateOutput>\n )?.output;\n }\n } else if (task.type === 'Action Space') {\n returnValue = await task.executor(param, executorContext);\n } else {\n console.warn(\n `unsupported task type: ${task.type}, will try to execute it directly`,\n );\n returnValue = await task.executor(param, executorContext);\n }\n\n const isLastTask = taskIndex === this.tasks.length - 1;\n\n if (isLastTask) {\n setTimingFieldOnce(task.timing, 'captureAfterCallingSnapshotStart');\n const screenshot = await this.captureScreenshot();\n this.attachRecorderItem(task, screenshot, 'after-calling');\n setTimingFieldOnce(task.timing, 'captureAfterCallingSnapshotEnd');\n }\n\n Object.assign(task, returnValue);\n task.status = 'finished';\n task.timing.end = Date.now();\n task.timing.cost = task.timing.end - task.timing.start;\n await this.emitOnTaskUpdate();\n taskIndex++;\n } catch (e: any) {\n successfullyCompleted = false;\n task.error = e;\n task.errorMessage =\n e?.message || (typeof e === 'string' ? e : 'error-without-message');\n task.errorStack = e.stack;\n\n task.status = 'failed';\n task.timing.end = Date.now();\n task.timing.cost = task.timing.end - task.timing.start;\n await this.emitOnTaskUpdate();\n break;\n }\n }\n\n // set all remaining tasks as cancelled\n for (let i = taskIndex + 1; i < this.tasks.length; i++) {\n this.tasks[i].status = 'cancelled';\n }\n if (taskIndex + 1 < this.tasks.length) {\n await this.emitOnTaskUpdate();\n }\n\n let finalizeError: TaskExecutionError | undefined;\n if (!successfullyCompleted) {\n this.status = 'error';\n const errorTask = this.latestErrorTask();\n const messageBase =\n errorTask?.errorMessage ||\n (errorTask?.error ? String(errorTask.error) : 'Task execution failed');\n const stack = errorTask?.errorStack;\n const message = stack ? `${messageBase}\\n${stack}` : messageBase;\n finalizeError = new TaskExecutionError(message, this, errorTask, {\n cause: errorTask?.error,\n });\n await this.emitOnTaskUpdate(finalizeError);\n } else {\n this.status = 'completed';\n await this.emitOnTaskUpdate();\n }\n\n if (finalizeError) {\n throw finalizeError;\n }\n\n if (this.tasks.length) {\n // return the last output\n const outputIndex = Math.min(taskIndex, this.tasks.length - 1);\n const { thought, output } = this.tasks[outputIndex];\n return {\n thought,\n output,\n };\n }\n }\n\n isInErrorState(): boolean {\n return this.status === 'error';\n }\n\n latestErrorTask(): ExecutionTask | null {\n if (this.status !== 'error') {\n return null;\n }\n // Find the LAST failed task (not the first one)\n // This is important when using allowWhenError to continue after errors\n for (let i = this.tasks.length - 1; i >= 0; i--) {\n if (this.tasks[i].status === 'failed') {\n return this.tasks[i];\n }\n }\n return null;\n }\n\n dump(): ExecutionDump {\n return new ExecutionDump({\n id: this.id,\n logTime: this.executionLogTime,\n name: this.name,\n tasks: this.tasks,\n });\n }\n\n async appendErrorPlan(errorMsg: string): Promise<{\n output: undefined;\n runner: TaskRunner;\n }> {\n const errorTask: ExecutionTaskActionApply<PlanningActionParamError> = {\n type: 'Action Space',\n subType: 'Error',\n param: {\n thought: errorMsg,\n },\n thought: errorMsg,\n executor: async () => {\n throw new Error(errorMsg || 'error without thought');\n },\n };\n await this.appendAndFlush(errorTask);\n\n return {\n output: undefined,\n runner: this,\n };\n }\n}\n\nexport class TaskExecutionError extends Error {\n runner: TaskRunner;\n\n errorTask: ExecutionTask | null;\n\n constructor(\n message: string,\n runner: TaskRunner,\n errorTask: ExecutionTask | null,\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.runner = runner;\n this.errorTask = errorTask;\n }\n}\n"],"names":["debug","getDebug","UI_CONTEXT_CACHE_TTL_MS","TaskRunner","error","options","now","Date","shouldReuse","uiContext","undefined","console","task","screenshot","phase","recorderItem","uuid","errorMessage","assert","Array","item","nextPendingIndex","taskIndex","successfullyCompleted","previousFindOutput","e","executor","param","returnValue","forceRefresh","setTimingFieldOnce","executorContext","isLastTask","Object","i","finalizeError","errorTask","messageBase","String","stack","message","TaskExecutionError","outputIndex","Math","thought","output","ExecutionDump","errorMsg","Error","name","uiContextBuilder","runner"],"mappings":"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"}