@midscene/core 1.12.10-beta-20260920031616.0 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/dist/es/agent/agent.mjs +103 -6
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/index.mjs +4 -3
  4. package/dist/es/agent/tasks.mjs +2 -2
  5. package/dist/es/agent/tasks.mjs.map +1 -1
  6. package/dist/es/agent/test-runner-nodes.mjs +291 -40
  7. package/dist/es/agent/test-runner-nodes.mjs.map +1 -1
  8. package/dist/es/agent/utils.mjs +1 -1
  9. package/dist/es/device/index.mjs +15 -2
  10. package/dist/es/device/index.mjs.map +1 -1
  11. package/dist/es/dump/html-utils.mjs +37 -4
  12. package/dist/es/dump/html-utils.mjs.map +1 -1
  13. package/dist/es/dump/screenshot-store.mjs +8 -1
  14. package/dist/es/dump/screenshot-store.mjs.map +1 -1
  15. package/dist/es/report-cli.mjs +9 -4
  16. package/dist/es/report-cli.mjs.map +1 -1
  17. package/dist/es/report-generator.mjs +117 -4
  18. package/dist/es/report-generator.mjs.map +1 -1
  19. package/dist/es/report-html-template.mjs +1 -1
  20. package/dist/es/report.mjs +190 -41
  21. package/dist/es/report.mjs.map +1 -1
  22. package/dist/es/test-run-report.mjs.map +1 -1
  23. package/dist/es/test-runner/engine/case-runner.mjs +52 -0
  24. package/dist/es/test-runner/engine/case-runner.mjs.map +1 -0
  25. package/dist/es/test-runner/engine/document-runtime.mjs +273 -0
  26. package/dist/es/test-runner/engine/document-runtime.mjs.map +1 -0
  27. package/dist/es/test-runner/engine/execute-step.mjs +177 -0
  28. package/dist/es/test-runner/engine/execute-step.mjs.map +1 -0
  29. package/dist/es/test-runner/engine/execution-failure.mjs +39 -0
  30. package/dist/es/test-runner/engine/execution-failure.mjs.map +1 -0
  31. package/dist/es/test-runner/engine/index.mjs +12 -0
  32. package/dist/es/test-runner/engine/project-runtime.mjs +142 -0
  33. package/dist/es/test-runner/engine/project-runtime.mjs.map +1 -0
  34. package/dist/es/test-runner/engine/registry.mjs +61 -0
  35. package/dist/es/test-runner/engine/registry.mjs.map +1 -0
  36. package/dist/es/test-runner/engine/resource-operations.mjs +211 -0
  37. package/dist/es/test-runner/engine/resource-operations.mjs.map +1 -0
  38. package/dist/es/test-runner/engine/run-collected-case.mjs +193 -0
  39. package/dist/es/test-runner/engine/run-collected-case.mjs.map +1 -0
  40. package/dist/es/test-runner/engine/run-workflow-document.mjs +155 -0
  41. package/dist/es/test-runner/engine/run-workflow-document.mjs.map +1 -0
  42. package/dist/es/test-runner/engine/scheduler.mjs +27 -0
  43. package/dist/es/test-runner/engine/scheduler.mjs.map +1 -0
  44. package/dist/es/test-runner/engine/scope-teardown.mjs +16 -0
  45. package/dist/es/test-runner/engine/scope-teardown.mjs.map +1 -0
  46. package/dist/es/test-runner/engine/types.mjs +0 -0
  47. package/dist/es/test-runner/errors.mjs +201 -0
  48. package/dist/es/test-runner/errors.mjs.map +1 -0
  49. package/dist/es/test-runner/execution-record.mjs +83 -0
  50. package/dist/es/test-runner/execution-record.mjs.map +1 -0
  51. package/dist/es/test-runner/index.mjs +12 -0
  52. package/dist/es/test-runner/node/define-node.mjs +44 -0
  53. package/dist/es/test-runner/node/define-node.mjs.map +1 -0
  54. package/dist/es/test-runner/node/index.mjs +2 -0
  55. package/dist/es/test-runner/node/types.mjs +0 -0
  56. package/dist/es/test-runner/parser/document-format.mjs +21 -0
  57. package/dist/es/test-runner/parser/document-format.mjs.map +1 -0
  58. package/dist/es/test-runner/parser/normalize.mjs +87 -0
  59. package/dist/es/test-runner/parser/normalize.mjs.map +1 -0
  60. package/dist/es/test-runner/parser/types.mjs +0 -0
  61. package/dist/es/test-runner/project.mjs +0 -0
  62. package/dist/es/test-runner/reporting/agent-report.mjs +23 -0
  63. package/dist/es/test-runner/reporting/agent-report.mjs.map +1 -0
  64. package/dist/es/test-runner/reporting/execution-record.mjs +73 -0
  65. package/dist/es/test-runner/reporting/execution-record.mjs.map +1 -0
  66. package/dist/es/test-runner/reporting/merge-report.mjs +231 -0
  67. package/dist/es/test-runner/reporting/merge-report.mjs.map +1 -0
  68. package/dist/es/test-runner/reporting/sanitize.mjs +162 -0
  69. package/dist/es/test-runner/reporting/sanitize.mjs.map +1 -0
  70. package/dist/es/test-runner/reporting/test-run-report.mjs +327 -0
  71. package/dist/es/test-runner/reporting/test-run-report.mjs.map +1 -0
  72. package/dist/es/test-runner/reporting/types.mjs +0 -0
  73. package/dist/es/utils.mjs +1 -1
  74. package/dist/es/yaml/execution-context.node.mjs +6 -0
  75. package/dist/es/yaml/execution-context.node.mjs.map +1 -0
  76. package/dist/es/yaml/execution-context.stub.mjs +8 -0
  77. package/dist/es/yaml/execution-context.stub.mjs.map +1 -0
  78. package/dist/es/yaml/execution-session.mjs +90 -0
  79. package/dist/es/yaml/execution-session.mjs.map +1 -0
  80. package/dist/es/yaml/index.mjs +2 -1
  81. package/dist/es/yaml/legacy-yaml-execution-record.mjs +47 -0
  82. package/dist/es/yaml/legacy-yaml-execution-record.mjs.map +1 -0
  83. package/dist/es/yaml/legacy-yaml-report.mjs +52 -0
  84. package/dist/es/yaml/legacy-yaml-report.mjs.map +1 -0
  85. package/dist/es/yaml/legacy-yaml-runtime.mjs +119 -0
  86. package/dist/es/yaml/legacy-yaml-runtime.mjs.map +1 -0
  87. package/dist/es/yaml/player-state.mjs +15 -0
  88. package/dist/es/yaml/player-state.mjs.map +1 -0
  89. package/dist/es/yaml/player.mjs +214 -348
  90. package/dist/es/yaml/player.mjs.map +1 -1
  91. package/dist/es/yaml/report-policy.mjs +7 -0
  92. package/dist/es/yaml/report-policy.mjs.map +1 -0
  93. package/dist/es/yaml/test-runner-compat.mjs +301 -0
  94. package/dist/es/yaml/test-runner-compat.mjs.map +1 -0
  95. package/dist/es/yaml/test-runner-nodes.mjs +147 -0
  96. package/dist/es/yaml/test-runner-nodes.mjs.map +1 -0
  97. package/dist/es/yaml/utils.mjs +12 -1
  98. package/dist/es/yaml/utils.mjs.map +1 -1
  99. package/dist/es/yaml-runtime.mjs +7 -0
  100. package/dist/es/yaml.mjs.map +1 -1
  101. package/dist/lib/agent/agent.js +103 -6
  102. package/dist/lib/agent/agent.js.map +1 -1
  103. package/dist/lib/agent/index.js +37 -3
  104. package/dist/lib/agent/tasks.js +2 -2
  105. package/dist/lib/agent/tasks.js.map +1 -1
  106. package/dist/lib/agent/test-runner-nodes.js +329 -45
  107. package/dist/lib/agent/test-runner-nodes.js.map +1 -1
  108. package/dist/lib/agent/utils.js +1 -1
  109. package/dist/lib/device/index.js +15 -2
  110. package/dist/lib/device/index.js.map +1 -1
  111. package/dist/lib/dump/html-utils.js +43 -4
  112. package/dist/lib/dump/html-utils.js.map +1 -1
  113. package/dist/lib/dump/screenshot-store.js +8 -1
  114. package/dist/lib/dump/screenshot-store.js.map +1 -1
  115. package/dist/lib/report-cli.js +8 -3
  116. package/dist/lib/report-cli.js.map +1 -1
  117. package/dist/lib/report-generator.js +114 -1
  118. package/dist/lib/report-generator.js.map +1 -1
  119. package/dist/lib/report-html-template.js +1 -1
  120. package/dist/lib/report.js +187 -38
  121. package/dist/lib/report.js.map +1 -1
  122. package/dist/lib/test-run-report.js.map +1 -1
  123. package/dist/lib/test-runner/engine/case-runner.js +89 -0
  124. package/dist/lib/test-runner/engine/case-runner.js.map +1 -0
  125. package/dist/lib/test-runner/engine/document-runtime.js +307 -0
  126. package/dist/lib/test-runner/engine/document-runtime.js.map +1 -0
  127. package/dist/lib/test-runner/engine/execute-step.js +211 -0
  128. package/dist/lib/test-runner/engine/execute-step.js.map +1 -0
  129. package/dist/lib/test-runner/engine/execution-failure.js +79 -0
  130. package/dist/lib/test-runner/engine/execution-failure.js.map +1 -0
  131. package/dist/lib/test-runner/engine/index.js +137 -0
  132. package/dist/lib/test-runner/engine/index.js.map +1 -0
  133. package/dist/lib/test-runner/engine/project-runtime.js +176 -0
  134. package/dist/lib/test-runner/engine/project-runtime.js.map +1 -0
  135. package/dist/lib/test-runner/engine/registry.js +95 -0
  136. package/dist/lib/test-runner/engine/registry.js.map +1 -0
  137. package/dist/lib/test-runner/engine/resource-operations.js +272 -0
  138. package/dist/lib/test-runner/engine/resource-operations.js.map +1 -0
  139. package/dist/lib/test-runner/engine/run-collected-case.js +227 -0
  140. package/dist/lib/test-runner/engine/run-collected-case.js.map +1 -0
  141. package/dist/lib/test-runner/engine/run-workflow-document.js +189 -0
  142. package/dist/lib/test-runner/engine/run-workflow-document.js.map +1 -0
  143. package/dist/lib/test-runner/engine/scheduler.js +64 -0
  144. package/dist/lib/test-runner/engine/scheduler.js.map +1 -0
  145. package/dist/lib/test-runner/engine/scope-teardown.js +50 -0
  146. package/dist/lib/test-runner/engine/scope-teardown.js.map +1 -0
  147. package/dist/lib/test-runner/engine/types.js +20 -0
  148. package/dist/lib/test-runner/engine/types.js.map +1 -0
  149. package/dist/lib/test-runner/errors.js +283 -0
  150. package/dist/lib/test-runner/errors.js.map +1 -0
  151. package/dist/lib/test-runner/execution-record.js +123 -0
  152. package/dist/lib/test-runner/execution-record.js.map +1 -0
  153. package/dist/lib/test-runner/index.js +137 -0
  154. package/dist/lib/test-runner/index.js.map +1 -0
  155. package/dist/lib/test-runner/node/define-node.js +78 -0
  156. package/dist/lib/test-runner/node/define-node.js.map +1 -0
  157. package/dist/lib/test-runner/node/index.js +67 -0
  158. package/dist/lib/test-runner/node/index.js.map +1 -0
  159. package/dist/lib/test-runner/node/types.js +20 -0
  160. package/dist/lib/test-runner/node/types.js.map +1 -0
  161. package/dist/lib/test-runner/parser/document-format.js +58 -0
  162. package/dist/lib/test-runner/parser/document-format.js.map +1 -0
  163. package/dist/lib/test-runner/parser/normalize.js +124 -0
  164. package/dist/lib/test-runner/parser/normalize.js.map +1 -0
  165. package/dist/lib/test-runner/parser/types.js +20 -0
  166. package/dist/lib/test-runner/parser/types.js.map +1 -0
  167. package/dist/lib/test-runner/project.js +20 -0
  168. package/dist/lib/test-runner/project.js.map +1 -0
  169. package/dist/lib/test-runner/reporting/agent-report.js +57 -0
  170. package/dist/lib/test-runner/reporting/agent-report.js.map +1 -0
  171. package/dist/lib/test-runner/reporting/execution-record.js +107 -0
  172. package/dist/lib/test-runner/reporting/execution-record.js.map +1 -0
  173. package/dist/lib/test-runner/reporting/merge-report.js +265 -0
  174. package/dist/lib/test-runner/reporting/merge-report.js.map +1 -0
  175. package/dist/lib/test-runner/reporting/sanitize.js +202 -0
  176. package/dist/lib/test-runner/reporting/sanitize.js.map +1 -0
  177. package/dist/lib/test-runner/reporting/test-run-report.js +364 -0
  178. package/dist/lib/test-runner/reporting/test-run-report.js.map +1 -0
  179. package/dist/lib/test-runner/reporting/types.js +20 -0
  180. package/dist/lib/test-runner/reporting/types.js.map +1 -0
  181. package/dist/lib/utils.js +1 -1
  182. package/dist/lib/yaml/execution-context.node.js +43 -0
  183. package/dist/lib/yaml/execution-context.node.js.map +1 -0
  184. package/dist/lib/yaml/execution-context.stub.js +45 -0
  185. package/dist/lib/yaml/execution-context.stub.js.map +1 -0
  186. package/dist/lib/yaml/execution-session.js +136 -0
  187. package/dist/lib/yaml/execution-session.js.map +1 -0
  188. package/dist/lib/yaml/index.js +49 -7
  189. package/dist/lib/yaml/legacy-yaml-execution-record.js +81 -0
  190. package/dist/lib/yaml/legacy-yaml-execution-record.js.map +1 -0
  191. package/dist/lib/yaml/legacy-yaml-report.js +86 -0
  192. package/dist/lib/yaml/legacy-yaml-report.js.map +1 -0
  193. package/dist/lib/yaml/legacy-yaml-runtime.js +156 -0
  194. package/dist/lib/yaml/legacy-yaml-runtime.js.map +1 -0
  195. package/dist/lib/yaml/player-state.js +52 -0
  196. package/dist/lib/yaml/player-state.js.map +1 -0
  197. package/dist/lib/yaml/player.js +213 -347
  198. package/dist/lib/yaml/player.js.map +1 -1
  199. package/dist/lib/yaml/report-policy.js +41 -0
  200. package/dist/lib/yaml/report-policy.js.map +1 -0
  201. package/dist/lib/yaml/test-runner-compat.js +344 -0
  202. package/dist/lib/yaml/test-runner-compat.js.map +1 -0
  203. package/dist/lib/yaml/test-runner-nodes.js +184 -0
  204. package/dist/lib/yaml/test-runner-nodes.js.map +1 -0
  205. package/dist/lib/yaml/utils.js +18 -1
  206. package/dist/lib/yaml/utils.js.map +1 -1
  207. package/dist/lib/yaml-runtime.js +67 -0
  208. package/dist/lib/yaml-runtime.js.map +1 -0
  209. package/dist/lib/yaml.js.map +1 -1
  210. package/dist/types/agent/agent.d.ts +14 -1
  211. package/dist/types/agent/agent.d.ts.map +1 -1
  212. package/dist/types/agent/index.d.ts +4 -3
  213. package/dist/types/agent/index.d.ts.map +1 -1
  214. package/dist/types/agent/tasks.d.ts +1 -1
  215. package/dist/types/agent/tasks.d.ts.map +1 -1
  216. package/dist/types/agent/test-runner-nodes.d.ts +226 -0
  217. package/dist/types/agent/test-runner-nodes.d.ts.map +1 -1
  218. package/dist/types/device/index.d.ts +1 -1
  219. package/dist/types/device/index.d.ts.map +1 -1
  220. package/dist/types/dump/html-utils.d.ts +4 -0
  221. package/dist/types/dump/html-utils.d.ts.map +1 -1
  222. package/dist/types/dump/screenshot-store.d.ts +2 -1
  223. package/dist/types/dump/screenshot-store.d.ts.map +1 -1
  224. package/dist/types/report-cli.d.ts.map +1 -1
  225. package/dist/types/report-generator.d.ts +10 -0
  226. package/dist/types/report-generator.d.ts.map +1 -1
  227. package/dist/types/report.d.ts +3 -1
  228. package/dist/types/report.d.ts.map +1 -1
  229. package/dist/types/test-run-report.d.ts +18 -2
  230. package/dist/types/test-run-report.d.ts.map +1 -1
  231. package/dist/types/test-runner/engine/case-runner.d.ts +13 -0
  232. package/dist/types/test-runner/engine/case-runner.d.ts.map +1 -0
  233. package/dist/types/test-runner/engine/document-runtime.d.ts +4 -0
  234. package/dist/types/test-runner/engine/document-runtime.d.ts.map +1 -0
  235. package/dist/types/test-runner/engine/execute-step.d.ts +17 -0
  236. package/dist/types/test-runner/engine/execute-step.d.ts.map +1 -0
  237. package/dist/types/test-runner/engine/execution-failure.d.ts +13 -0
  238. package/dist/types/test-runner/engine/execution-failure.d.ts.map +1 -0
  239. package/dist/types/test-runner/engine/index.d.ts +13 -0
  240. package/dist/types/test-runner/engine/index.d.ts.map +1 -0
  241. package/dist/types/test-runner/engine/project-runtime.d.ts +3 -0
  242. package/dist/types/test-runner/engine/project-runtime.d.ts.map +1 -0
  243. package/dist/types/test-runner/engine/registry.d.ts +12 -0
  244. package/dist/types/test-runner/engine/registry.d.ts.map +1 -0
  245. package/dist/types/test-runner/engine/resource-operations.d.ts +32 -0
  246. package/dist/types/test-runner/engine/resource-operations.d.ts.map +1 -0
  247. package/dist/types/test-runner/engine/run-collected-case.d.ts +4 -0
  248. package/dist/types/test-runner/engine/run-collected-case.d.ts.map +1 -0
  249. package/dist/types/test-runner/engine/run-workflow-document.d.ts +4 -0
  250. package/dist/types/test-runner/engine/run-workflow-document.d.ts.map +1 -0
  251. package/dist/types/test-runner/engine/scheduler.d.ts +12 -0
  252. package/dist/types/test-runner/engine/scheduler.d.ts.map +1 -0
  253. package/dist/types/test-runner/engine/scope-teardown.d.ts +3 -0
  254. package/dist/types/test-runner/engine/scope-teardown.d.ts.map +1 -0
  255. package/dist/types/test-runner/engine/types.d.ts +226 -0
  256. package/dist/types/test-runner/engine/types.d.ts.map +1 -0
  257. package/dist/types/test-runner/errors.d.ts +79 -0
  258. package/dist/types/test-runner/errors.d.ts.map +1 -0
  259. package/dist/types/test-runner/execution-record.d.ts +43 -0
  260. package/dist/types/test-runner/execution-record.d.ts.map +1 -0
  261. package/dist/types/test-runner/index.d.ts +20 -0
  262. package/dist/types/test-runner/index.d.ts.map +1 -0
  263. package/dist/types/test-runner/node/define-node.d.ts +4 -0
  264. package/dist/types/test-runner/node/define-node.d.ts.map +1 -0
  265. package/dist/types/test-runner/node/index.d.ts +3 -0
  266. package/dist/types/test-runner/node/index.d.ts.map +1 -0
  267. package/dist/types/test-runner/node/types.d.ts +66 -0
  268. package/dist/types/test-runner/node/types.d.ts.map +1 -0
  269. package/dist/types/test-runner/parser/document-format.d.ts +8 -0
  270. package/dist/types/test-runner/parser/document-format.d.ts.map +1 -0
  271. package/dist/types/test-runner/parser/normalize.d.ts +9 -0
  272. package/dist/types/test-runner/parser/normalize.d.ts.map +1 -0
  273. package/dist/types/test-runner/parser/types.d.ts +69 -0
  274. package/dist/types/test-runner/parser/types.d.ts.map +1 -0
  275. package/dist/types/test-runner/project.d.ts +75 -0
  276. package/dist/types/test-runner/project.d.ts.map +1 -0
  277. package/dist/types/test-runner/reporting/agent-report.d.ts +9 -0
  278. package/dist/types/test-runner/reporting/agent-report.d.ts.map +1 -0
  279. package/dist/types/test-runner/reporting/execution-record.d.ts +9 -0
  280. package/dist/types/test-runner/reporting/execution-record.d.ts.map +1 -0
  281. package/dist/types/test-runner/reporting/merge-report.d.ts +15 -0
  282. package/dist/types/test-runner/reporting/merge-report.d.ts.map +1 -0
  283. package/dist/types/test-runner/reporting/sanitize.d.ts +6 -0
  284. package/dist/types/test-runner/reporting/sanitize.d.ts.map +1 -0
  285. package/dist/types/test-runner/reporting/test-run-report.d.ts +5 -0
  286. package/dist/types/test-runner/reporting/test-run-report.d.ts.map +1 -0
  287. package/dist/types/test-runner/reporting/types.d.ts +34 -0
  288. package/dist/types/test-runner/reporting/types.d.ts.map +1 -0
  289. package/dist/types/yaml/execution-context.node.d.ts +4 -0
  290. package/dist/types/yaml/execution-context.node.d.ts.map +1 -0
  291. package/dist/types/yaml/execution-context.stub.d.ts +6 -0
  292. package/dist/types/yaml/execution-context.stub.d.ts.map +1 -0
  293. package/dist/types/yaml/execution-session.d.ts +17 -0
  294. package/dist/types/yaml/execution-session.d.ts.map +1 -0
  295. package/dist/types/yaml/index.d.ts +1 -1
  296. package/dist/types/yaml/index.d.ts.map +1 -1
  297. package/dist/types/yaml/legacy-yaml-execution-record.d.ts +24 -0
  298. package/dist/types/yaml/legacy-yaml-execution-record.d.ts.map +1 -0
  299. package/dist/types/yaml/legacy-yaml-report.d.ts +19 -0
  300. package/dist/types/yaml/legacy-yaml-report.d.ts.map +1 -0
  301. package/dist/types/yaml/legacy-yaml-runtime.d.ts +23 -0
  302. package/dist/types/yaml/legacy-yaml-runtime.d.ts.map +1 -0
  303. package/dist/types/yaml/player-state.d.ts +11 -0
  304. package/dist/types/yaml/player-state.d.ts.map +1 -0
  305. package/dist/types/yaml/player.d.ts +11 -3
  306. package/dist/types/yaml/player.d.ts.map +1 -1
  307. package/dist/types/yaml/report-policy.d.ts +4 -0
  308. package/dist/types/yaml/report-policy.d.ts.map +1 -0
  309. package/dist/types/yaml/test-runner-compat.d.ts +17 -0
  310. package/dist/types/yaml/test-runner-compat.d.ts.map +1 -0
  311. package/dist/types/yaml/test-runner-nodes.d.ts +6 -0
  312. package/dist/types/yaml/test-runner-nodes.d.ts.map +1 -0
  313. package/dist/types/yaml/utils.d.ts +9 -0
  314. package/dist/types/yaml/utils.d.ts.map +1 -1
  315. package/dist/types/yaml-runtime.d.ts +13 -0
  316. package/dist/types/yaml-runtime.d.ts.map +1 -0
  317. package/dist/types/yaml.d.ts +25 -7
  318. package/dist/types/yaml.d.ts.map +1 -1
  319. package/package.json +28 -2
@@ -1,12 +1,18 @@
1
- import { existsSync, mkdirSync, writeFileSync } from "node:fs";
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { basename, dirname, join, resolve } from "node:path";
3
- import { assert, ifInBrowser, ifInWorker } from "@midscene/shared/utils";
4
- import { z } from "zod";
5
- import { deriveCaseStatus } from "../dump/task-status.mjs";
6
3
  import { getMidsceneRunSubDir } from "@midscene/shared/common";
7
4
  import { getDebug } from "@midscene/shared/logger";
5
+ import { assert, ifInBrowser, ifInWorker, uuid } from "@midscene/shared/utils";
6
+ import { WorkflowExecutionFailure, WorkflowPublicationError } from "../test-runner/engine/execution-failure.mjs";
7
+ import { cleanupResources } from "../test-runner/engine/resource-operations.mjs";
8
8
  import { runFreeFnCleanup } from "./cleanup.mjs";
9
- import { buildDetailedLocateParam, buildDetailedLocateParamAndRestParams } from "./utils.mjs";
9
+ import { YamlExecutionOwnershipError, currentYamlSignal, enterYamlExecution, runInYamlExecutionContext } from "./execution-session.mjs";
10
+ import { createLegacyYamlExecutionRecord } from "./legacy-yaml-execution-record.mjs";
11
+ import { publishLegacyYamlReport } from "./legacy-yaml-report.mjs";
12
+ import { createLegacyYamlRuntime, legacyYamlOutcomeError } from "./legacy-yaml-runtime.mjs";
13
+ import { getLegacyYamlPlayerState, initializeLegacyYamlPlayerState } from "./player-state.mjs";
14
+ import { collectLegacyYamlDocument } from "./test-runner-compat.mjs";
15
+ import { resolveWebTarget, resolveYamlOutputConfig } from "./utils.mjs";
10
16
  function _define_property(obj, key, value) {
11
17
  if (key in obj) Object.defineProperty(obj, key, {
12
18
  value: value,
@@ -18,57 +24,12 @@ function _define_property(obj, key, value) {
18
24
  return obj;
19
25
  }
20
26
  const debug = getDebug('yaml-player');
21
- const aiTaskHandlerMap = {
22
- aiQuery: 'aiQuery',
23
- aiNumber: 'aiNumber',
24
- aiString: 'aiString',
25
- aiBoolean: 'aiBoolean',
26
- aiAsk: 'aiAsk',
27
- aiLocate: 'aiLocate'
28
- };
29
- const isStringParamSchema = (schema)=>{
30
- if (!schema) return false;
31
- const schemaDef = schema?._def;
32
- if (!schemaDef?.typeName) return false;
33
- switch(schemaDef.typeName){
34
- case z.ZodFirstPartyTypeKind.ZodString:
35
- case z.ZodFirstPartyTypeKind.ZodEnum:
36
- case z.ZodFirstPartyTypeKind.ZodNativeEnum:
37
- return true;
38
- case z.ZodFirstPartyTypeKind.ZodLiteral:
39
- return 'string' == typeof schemaDef.value;
40
- case z.ZodFirstPartyTypeKind.ZodOptional:
41
- case z.ZodFirstPartyTypeKind.ZodNullable:
42
- case z.ZodFirstPartyTypeKind.ZodDefault:
43
- return isStringParamSchema(schemaDef.innerType);
44
- case z.ZodFirstPartyTypeKind.ZodEffects:
45
- return isStringParamSchema(schemaDef.schema);
46
- case z.ZodFirstPartyTypeKind.ZodPipeline:
47
- return isStringParamSchema(schemaDef.out);
48
- case z.ZodFirstPartyTypeKind.ZodUnion:
49
- {
50
- const options = schemaDef.options;
51
- return Array.isArray(options) ? options.every((option)=>isStringParamSchema(option)) : false;
52
- }
53
- default:
54
- return false;
55
- }
56
- };
57
- const buildShortcutActionParam = (actionName, interfaceAlias, value)=>{
58
- if ('Launch' === actionName || 'launch' === interfaceAlias) return {
59
- uri: value
60
- };
61
- if ('Terminate' === actionName || 'terminate' === interfaceAlias) return {
62
- uri: value
63
- };
64
- if ('RunAdbShell' === actionName || 'runAdbShell' === interfaceAlias || 'RunHdcShell' === actionName || 'runHdcShell' === interfaceAlias) return {
65
- command: value
66
- };
67
- };
68
27
  class ScriptPlayer {
69
28
  setResult(key, value) {
70
29
  const keyToUse = key || this.unnamedResultIndex++;
71
- if (this.result[keyToUse]) console.warn(`result key ${keyToUse} already exists, will overwrite`);
30
+ if (this.result[keyToUse]) getDebug('yaml-player', {
31
+ console: true
32
+ })(`result key ${keyToUse} already exists, will overwrite`);
72
33
  this.result[keyToUse] = value;
73
34
  return this.flushResult();
74
35
  }
@@ -80,7 +41,7 @@ class ScriptPlayer {
80
41
  const taskIndexToNotify = 'number' == typeof taskIndex ? taskIndex : this.currentTaskIndex;
81
42
  if ('number' != typeof taskIndexToNotify) return;
82
43
  const taskStatus = this.taskStatusList[taskIndexToNotify];
83
- if (this.onTaskStatusChange) this.onTaskStatusChange(taskStatus);
44
+ this.onTaskStatusChange?.(taskStatus);
84
45
  }
85
46
  async setTaskStatus(index, statusValue, error) {
86
47
  this.taskStatusList[index].status = statusValue;
@@ -90,266 +51,78 @@ class ScriptPlayer {
90
51
  setTaskIndex(taskIndex) {
91
52
  this.currentTaskIndex = taskIndex;
92
53
  }
93
- flushResult() {
54
+ async flushResult() {
94
55
  if (this.output) {
95
56
  const output = resolve(process.cwd(), this.output);
96
- const outputDir = dirname(output);
97
- if (!existsSync(outputDir)) mkdirSync(outputDir, {
98
- recursive: true
57
+ await this.publish(output, async ()=>{
58
+ const outputDir = dirname(output);
59
+ await mkdir(outputDir, {
60
+ recursive: true
61
+ });
62
+ await writeFile(output, JSON.stringify(this.result || {}, void 0, 2));
99
63
  });
100
- writeFileSync(output, JSON.stringify(this.result || {}, void 0, 2));
101
64
  }
102
65
  }
103
- flushUnstableLogContent() {
66
+ async flushUnstableLogContent() {
104
67
  if (this.unstableLogContent) {
105
68
  const content = this.interfaceAgent?._unstableLogContent();
106
69
  const filePath = resolve(process.cwd(), this.unstableLogContent);
107
- const outputDir = dirname(filePath);
108
- if (!existsSync(outputDir)) mkdirSync(outputDir, {
109
- recursive: true
70
+ await this.publish(filePath, async ()=>{
71
+ const outputDir = dirname(filePath);
72
+ await mkdir(outputDir, {
73
+ recursive: true
74
+ });
75
+ await writeFile(filePath, JSON.stringify(content, null, 2));
110
76
  });
111
- writeFileSync(filePath, JSON.stringify(content, null, 2));
112
77
  }
113
78
  }
79
+ async publish(path, write) {
80
+ try {
81
+ await write();
82
+ } catch (cause) {
83
+ const error = new WorkflowPublicationError('write-result', path, cause);
84
+ this.publicationErrors.push(error);
85
+ throw error;
86
+ }
87
+ }
88
+ createRuntime(agent) {
89
+ return createLegacyYamlRuntime({
90
+ agent,
91
+ actionSpace: this.actionSpace,
92
+ sourcePath: this.scriptPath,
93
+ setResult: (key, value)=>this.setResult(key, value)
94
+ });
95
+ }
114
96
  async playTask(taskStatus, agent) {
115
97
  const { flow } = taskStatus;
116
98
  assert(flow, 'missing flow in task');
117
- for(const flowItemIndex in flow){
118
- const currentStep = Number.parseInt(flowItemIndex, 10);
119
- taskStatus.currentStep = currentStep;
120
- const flowItem = flow[flowItemIndex];
121
- const flowItemRecord = flowItem;
122
- const executionCountBeforeStep = agent.dump?.executions?.length ?? 0;
123
- this.failedReportExecutionInCurrentStep = false;
124
- try {
125
- await this.playFlowItem(agent, flowItem, flowItemRecord, flowItemIndex);
126
- } catch (error) {
127
- this.failedReportExecutionInCurrentStep = this.hasFailedReportExecutionSince(agent, executionCountBeforeStep);
128
- throw error;
99
+ const statusIndex = this.taskStatusList.indexOf(taskStatus);
100
+ const declaredIndex = taskStatus.index;
101
+ const taskIndex = statusIndex >= 0 ? statusIndex : 'number' == typeof declaredIndex && Number.isInteger(declaredIndex) ? declaredIndex : 0;
102
+ const state = getLegacyYamlPlayerState(this);
103
+ state.executionResult = await this.createRuntime(agent).runTask(taskStatus, taskIndex, {
104
+ onStepStart: (info)=>{
105
+ if ('case' === info.scope && 'steps' === info.case.phase) taskStatus.currentStep = info.case.stepIndex;
129
106
  }
130
- }
107
+ });
108
+ const outcome = state.executionResult.cases[0];
109
+ if (!outcome || 'not-run' === outcome.status) throw new Error(`Task "${taskStatus.name}" did not run.`);
110
+ if ('failed' === outcome.status) throw legacyYamlOutcomeError(outcome);
131
111
  this.reportFile = agent.reportFile;
132
112
  await this.flushUnstableLogContent();
133
113
  }
134
- hasFailedReportExecutionSince(agent, executionCountBefore) {
135
- const executions = (agent.dump?.executions ?? []).slice(executionCountBefore);
136
- return 'failed' === deriveCaseStatus(executions);
137
- }
138
- async playFlowItem(agent, flowItem, flowItemRecord, flowItemIndex) {
139
- if ('Finalize' in flowItemRecord) return;
140
- debug(`playing step ${flowItemIndex}, flowItem=${JSON.stringify(flowItem)}`);
141
- const simpleAIKey = Object.keys(aiTaskHandlerMap).find((key)=>Object.prototype.hasOwnProperty.call(flowItemRecord, key));
142
- if ('aiAct' in flowItem || 'aiAction' in flowItem || 'ai' in flowItem) {
143
- const actionTask = flowItem;
144
- const { aiAct, aiAction, ai, instruction, ...actionOptions } = actionTask;
145
- const actionPrompt = aiAct ?? aiAction ?? ai;
146
- let promptForAI;
147
- if ('string' == typeof instruction && instruction) promptForAI = instruction;
148
- else if (instruction && 'object' == typeof instruction && 'string' == typeof instruction.prompt && instruction.prompt) promptForAI = instruction;
149
- else if (actionPrompt && 'object' == typeof actionPrompt && 'string' == typeof actionPrompt.prompt && actionPrompt.prompt) promptForAI = actionPrompt;
150
- else if ('string' == typeof actionPrompt && actionPrompt) promptForAI = actionPrompt;
151
- assert(promptForAI, 'missing prompt for ai (aiAct)');
152
- await agent.aiAct(promptForAI, actionOptions);
153
- } else if ('runGherkinScenario' in flowItem) {
154
- const gherkinScenarioTask = flowItem;
155
- const { runGherkinScenario } = gherkinScenarioTask;
156
- assert(runGherkinScenario, 'missing scenario for runGherkinScenario');
157
- await agent.runGherkinScenario(runGherkinScenario, {
158
- cacheable: false
159
- });
160
- } else if ('aiAssert' in flowItem) {
161
- const assertTask = flowItem;
162
- const { aiAssert: prompt, errorMessage: msg, name, ...restOpts } = assertTask;
163
- assert(prompt, 'missing prompt for aiAssert');
164
- assert(!Object.prototype.hasOwnProperty.call(assertTask, 'observe'), '`observe` is not supported in YAML aiAssert. Use agent.startObserving() from code instead.');
165
- const result = await agent.aiAssert(prompt, msg, {
166
- ...restOpts,
167
- keepRawResponse: true
168
- });
169
- const pass = result?.pass;
170
- const thought = result?.thought;
171
- const message = result?.message;
172
- this.setResult(name, {
173
- pass,
174
- thought,
175
- message
176
- });
177
- if (!pass) throw new Error(message);
178
- } else if (simpleAIKey) {
179
- const { [simpleAIKey]: prompt, name, ...options } = flowItem;
180
- assert(prompt, `missing prompt for ${simpleAIKey}`);
181
- assert(!Object.prototype.hasOwnProperty.call(flowItem, 'observe'), '`observe` is not supported in YAML flow items. Use agent.startObserving() from code instead.');
182
- const agentMethod = agent[aiTaskHandlerMap[simpleAIKey]];
183
- assert('function' == typeof agentMethod, `missing agent method for ${simpleAIKey}`);
184
- const aiResult = await agentMethod.call(agent, prompt, options);
185
- this.setResult(name, aiResult);
186
- } else if ('aiWaitFor' in flowItem) {
187
- const waitForTask = flowItem;
188
- const { aiWaitFor, timeout, ...restWaitForOpts } = waitForTask;
189
- const prompt = aiWaitFor;
190
- assert(prompt, 'missing prompt for aiWaitFor');
191
- const waitForOptions = {
192
- ...restWaitForOpts,
193
- ...void 0 !== timeout ? {
194
- timeout,
195
- timeoutMs: timeout
196
- } : {}
197
- };
198
- await agent.aiWaitFor(prompt, waitForOptions);
199
- } else if ('sleep' in flowItem) {
200
- const sleepTask = flowItem;
201
- const ms = sleepTask.sleep;
202
- let msNumber = ms;
203
- if ('string' == typeof ms) msNumber = Number.parseInt(ms, 10);
204
- assert(Number.isFinite(msNumber) && msNumber > 0, `ms for sleep must be greater than 0, but got ${ms}`);
205
- await agent.sleep(msNumber);
206
- } else if ("javascript" in flowItem) {
207
- const evaluateJavaScriptTask = flowItem;
208
- const result = await agent.evaluateJavaScript(evaluateJavaScriptTask.javascript);
209
- this.setResult(evaluateJavaScriptTask.name, result);
210
- } else if ('logScreenshot' in flowItem || 'recordToReport' in flowItem) {
211
- const recordTask = flowItem;
212
- const title = recordTask.recordToReport ?? recordTask.logScreenshot ?? 'untitled';
213
- const content = recordTask.content || '';
214
- await agent.recordToReport(title, {
215
- content
216
- });
217
- } else if ('aiInput' in flowItem) {
218
- const { aiInput, value: rawValue, ...inputTask } = flowItem;
219
- let locatePrompt;
220
- let value;
221
- if (inputTask.locate) {
222
- value = aiInput || rawValue;
223
- locatePrompt = inputTask.locate;
224
- } else {
225
- locatePrompt = aiInput || '';
226
- value = rawValue;
227
- }
228
- await agent.callActionInActionSpace('Input', {
229
- ...inputTask,
230
- ...void 0 !== value ? {
231
- value: String(value)
232
- } : {},
233
- ...locatePrompt ? {
234
- locate: buildDetailedLocateParam(locatePrompt, inputTask)
235
- } : {}
236
- });
237
- } else if ('aiKeyboardPress' in flowItem) {
238
- const { aiKeyboardPress, ...keyboardPressTask } = flowItem;
239
- let locatePrompt;
240
- let keyName;
241
- if (keyboardPressTask.locate) {
242
- keyName = aiKeyboardPress;
243
- locatePrompt = keyboardPressTask.locate;
244
- } else if (keyboardPressTask.keyName) {
245
- keyName = keyboardPressTask.keyName;
246
- locatePrompt = aiKeyboardPress;
247
- } else keyName = aiKeyboardPress;
248
- await agent.callActionInActionSpace('KeyboardPress', {
249
- ...keyboardPressTask,
250
- ...keyName ? {
251
- keyName
252
- } : {},
253
- ...locatePrompt ? {
254
- locate: buildDetailedLocateParam(locatePrompt, keyboardPressTask)
255
- } : {}
256
- });
257
- } else if ('aiScroll' in flowItem) {
258
- const { aiScroll, ...scrollTask } = flowItem;
259
- const { locate, ...scrollOptions } = scrollTask;
260
- const locatePrompt = locate ?? aiScroll ?? void 0;
261
- await agent.aiScroll(locatePrompt, scrollOptions);
262
- } else if ('aiTap' in flowItem) {
263
- const { aiTap, prompt, locate, ...tapOptions } = flowItem;
264
- let locatePrompt;
265
- let opts = tapOptions;
266
- const locateObj = locate ?? ('object' == typeof aiTap && null !== aiTap ? aiTap.locate : void 0);
267
- if ('string' == typeof aiTap && aiTap) locatePrompt = aiTap;
268
- else if ('object' == typeof locateObj && locateObj?.prompt) {
269
- const { prompt: lp, ...locateOpts } = locateObj;
270
- locatePrompt = lp;
271
- opts = {
272
- ...locateOpts,
273
- ...tapOptions
274
- };
275
- } else locatePrompt = aiTap?.prompt || prompt || locateObj;
276
- assert(locatePrompt, 'missing prompt for aiTap');
277
- await agent.aiTap(locatePrompt, opts);
278
- } else {
279
- const actionSpace = this.actionSpace;
280
- let locatePromptShortcut;
281
- let actionParamForMatchedAction;
282
- const matchedAction = actionSpace.find((action)=>{
283
- const actionInterfaceAlias = action.interfaceAlias;
284
- if (actionInterfaceAlias && Object.prototype.hasOwnProperty.call(flowItem, actionInterfaceAlias)) {
285
- actionParamForMatchedAction = flowItem[actionInterfaceAlias];
286
- if ('string' == typeof actionParamForMatchedAction) locatePromptShortcut = actionParamForMatchedAction;
287
- return true;
288
- }
289
- const keyOfActionInActionSpace = action.name;
290
- if (Object.prototype.hasOwnProperty.call(flowItem, keyOfActionInActionSpace)) {
291
- actionParamForMatchedAction = flowItem[keyOfActionInActionSpace];
292
- if ('string' == typeof actionParamForMatchedAction) locatePromptShortcut = actionParamForMatchedAction;
293
- return true;
294
- }
295
- return false;
296
- });
297
- assert(matchedAction, `unknown flowItem in yaml: ${JSON.stringify(flowItem)}`);
298
- const schemaIsStringParam = isStringParamSchema(matchedAction.paramSchema);
299
- let stringParamToCall;
300
- const resultName = flowItem.name;
301
- const timeout = flowItem.timeout;
302
- const hasRunAdbShellAlias = Object.prototype.hasOwnProperty.call(flowItem, 'runAdbShell');
303
- if (hasRunAdbShellAlias && 'string' == typeof actionParamForMatchedAction && 'number' == typeof timeout && 'function' == typeof agent.runAdbShell) {
304
- const result = await agent.runAdbShell(actionParamForMatchedAction, {
305
- timeout
306
- });
307
- if (void 0 !== result) this.setResult(resultName, result);
308
- return;
309
- }
310
- const specialActionParamToCall = 'string' == typeof actionParamForMatchedAction ? buildShortcutActionParam(matchedAction.name, matchedAction.interfaceAlias, actionParamForMatchedAction) : void 0;
311
- if (specialActionParamToCall) {
312
- debug(`matchedAction: ${matchedAction.name}`, `flowParams: ${JSON.stringify(specialActionParamToCall)}`);
313
- const result = await agent.callActionInActionSpace(matchedAction.name, specialActionParamToCall);
314
- if (void 0 !== result) this.setResult(resultName, result);
315
- } else if ('string' == typeof actionParamForMatchedAction && schemaIsStringParam) {
316
- if (matchedAction.paramSchema) {
317
- const parseResult = matchedAction.paramSchema.safeParse(actionParamForMatchedAction);
318
- if (parseResult.success && 'string' == typeof parseResult.data) stringParamToCall = parseResult.data;
319
- else if (!parseResult.success) {
320
- debug(`parse failed for action ${matchedAction.name} with string param`, parseResult.error);
321
- stringParamToCall = actionParamForMatchedAction;
322
- }
323
- } else stringParamToCall = actionParamForMatchedAction;
324
- if (void 0 !== stringParamToCall) {
325
- debug(`matchedAction: ${matchedAction.name}`, `flowParams: ${JSON.stringify(stringParamToCall)}`);
326
- const result = await agent.callActionInActionSpace(matchedAction.name, stringParamToCall);
327
- const resultName = flowItem.name;
328
- if (void 0 !== result) this.setResult(resultName, result);
329
- }
330
- } else {
331
- const sourceForParams = locatePromptShortcut && 'string' == typeof actionParamForMatchedAction ? {
332
- ...flowItem,
333
- prompt: locatePromptShortcut
334
- } : 'object' == typeof actionParamForMatchedAction && null !== actionParamForMatchedAction ? actionParamForMatchedAction : flowItem;
335
- const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePromptShortcut || '', sourceForParams, [
336
- matchedAction.name,
337
- matchedAction.interfaceAlias || '_never_mind_'
338
- ]);
339
- const flowParams = {
340
- ...restParams,
341
- locate: locateParam
342
- };
343
- debug(`matchedAction: ${matchedAction.name}`, `flowParams: ${JSON.stringify(flowParams, null, 2)}`);
344
- const result = await agent.callActionInActionSpace(matchedAction.name, flowParams);
345
- const resultName = flowItem.name;
346
- if (void 0 !== result) this.setResult(resultName, result);
347
- }
348
- }
349
- }
350
114
  async run() {
351
- const { target, web, android, ios, harmony, computer, tasks } = this.script;
352
- const webEnv = web || target;
115
+ return runInYamlExecutionContext(()=>this.runInContext());
116
+ }
117
+ async runInContext() {
118
+ const startedAt = new Date();
119
+ const runId = uuid();
120
+ const state = getLegacyYamlPlayerState(this);
121
+ state.executionResult = void 0;
122
+ state.executionRecord = void 0;
123
+ this.publicationErrors = [];
124
+ const { android, ios, harmony, computer } = this.script;
125
+ const webEnv = resolveWebTarget(this.script)?.target;
353
126
  const androidEnv = android;
354
127
  const iosEnv = ios;
355
128
  const harmonyEnv = harmony;
@@ -358,65 +131,155 @@ class ScriptPlayer {
358
131
  this.setPlayerStatus('running');
359
132
  let agent = null;
360
133
  let freeFn = [];
134
+ let setupError;
135
+ let executionError;
136
+ let cleanupError;
137
+ let signal;
138
+ let session;
361
139
  try {
362
140
  const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(platform);
363
- this.actionSpace = await newAgent.getActionSpace();
364
141
  agent = newAgent;
142
+ agent._prepareForTestRunner?.();
143
+ freeFn = [
144
+ ...newFreeFn || []
145
+ ];
146
+ session = enterYamlExecution(agent);
147
+ signal = currentYamlSignal(agent);
148
+ signal?.throwIfAborted();
149
+ this.actionSpace = await agent.getActionSpace();
365
150
  const originalOnTaskStartTip = agent.onTaskStartTip;
366
151
  agent.onTaskStartTip = (tip)=>{
367
152
  if ('running' === this.status) this.agentStatusTip = tip;
368
153
  originalOnTaskStartTip?.(tip);
369
154
  };
370
- freeFn = [
371
- ...newFreeFn || [],
372
- {
373
- name: 'restore-agent-onTaskStartTip',
374
- fn: ()=>{
375
- if (agent) agent.onTaskStartTip = originalOnTaskStartTip;
376
- }
155
+ freeFn.push({
156
+ name: 'restore-agent-onTaskStartTip',
157
+ fn: ()=>{
158
+ if (agent) agent.onTaskStartTip = originalOnTaskStartTip;
377
159
  }
378
- ];
379
- } catch (e) {
380
- this.setPlayerStatus('error', e);
381
- return;
160
+ });
161
+ } catch (error) {
162
+ if (error instanceof YamlExecutionOwnershipError) throw error;
163
+ setupError = error;
164
+ this.setPlayerStatus('error', error);
382
165
  }
383
166
  this.interfaceAgent = agent;
384
- let taskIndex = 0;
385
- this.setPlayerStatus('running');
386
- let errorFlag = false;
387
- while(taskIndex < tasks.length){
388
- const taskStatus = this.taskStatusList[taskIndex];
389
- this.setTaskStatus(taskIndex, 'running');
390
- this.setTaskIndex(taskIndex);
391
- this.failedReportExecutionInCurrentStep = false;
392
- try {
393
- await this.playTask(taskStatus, this.interfaceAgent);
394
- this.setTaskStatus(taskIndex, 'done');
395
- } catch (e) {
396
- this.setTaskStatus(taskIndex, 'error', e);
397
- const recordErrorToReport = agent.recordErrorToReport;
398
- if (!this.failedReportExecutionInCurrentStep && 'function' == typeof recordErrorToReport) try {
399
- await recordErrorToReport.call(agent, `YAML task failed - ${taskStatus.name}`, {
400
- error: e,
401
- content: `Step ${taskStatus.currentStep ?? 0} failed while running YAML task "${taskStatus.name}".`
402
- });
403
- } catch (reportError) {
404
- debug('failed to record yaml error to report', reportError);
405
- }
406
- if (taskStatus.continueOnError) ;
407
- else {
408
- this.reportFile = agent.reportFile;
409
- errorFlag = true;
410
- break;
411
- }
167
+ const document = collectLegacyYamlDocument(this.script, this.scriptPath ?? '<inline-yaml>', this.actionSpace);
168
+ const runtime = agent && !setupError ? this.createRuntime(agent) : void 0;
169
+ try {
170
+ if (runtime && agent) {
171
+ state.executionResult = await runtime.runScript(this.script, {
172
+ document,
173
+ signal,
174
+ createDocumentRunId: ()=>runId,
175
+ onCaseStart: (collectedCase)=>{
176
+ const taskIndex = collectedCase.caseIndex;
177
+ this.setTaskIndex(taskIndex);
178
+ return this.setTaskStatus(taskIndex, 'running');
179
+ },
180
+ onStepStart: (info)=>{
181
+ if ('case' !== info.scope || 'steps' !== info.case.phase) return;
182
+ const taskStatus = this.taskStatusList[info.case.caseIndex];
183
+ if (taskStatus) taskStatus.currentStep = info.case.stepIndex;
184
+ },
185
+ onCaseOutcome: async (outcome)=>{
186
+ if ('not-run' === outcome.status) return;
187
+ const taskIndex = outcome.caseIndex;
188
+ const taskStatus = this.taskStatusList[taskIndex];
189
+ assert(taskStatus, `missing YAML task at index ${taskIndex}`);
190
+ this.reportFile = agent?.reportFile;
191
+ if ('success' === outcome.status) {
192
+ await this.setTaskStatus(taskIndex, 'done');
193
+ await this.flushUnstableLogContent();
194
+ return;
195
+ }
196
+ const error = legacyYamlOutcomeError(outcome);
197
+ await this.setTaskStatus(taskIndex, 'error', error);
198
+ }
199
+ });
200
+ const stoppedOnFailure = state.executionResult.cases.some((outcome)=>'failed' === outcome.status && !this.taskStatusList[outcome.caseIndex]?.continueOnError);
201
+ this.setPlayerStatus(stoppedOnFailure || signal?.aborted ? 'error' : 'done');
412
202
  }
413
- this.reportFile = agent?.reportFile;
414
- taskIndex++;
203
+ } catch (error) {
204
+ executionError = error;
205
+ if (error instanceof WorkflowExecutionFailure) state.executionResult = error.result;
206
+ this.setPlayerStatus('error', error);
415
207
  }
416
- if (errorFlag) this.setPlayerStatus('error');
417
- else this.setPlayerStatus('done');
208
+ this.reportFile = agent?.reportFile;
418
209
  this.agentStatusTip = '';
419
- await runFreeFnCleanup(freeFn);
210
+ try {
211
+ if (session?.isRoot && agent) await cleanupResources([
212
+ agent
213
+ ], ()=>runFreeFnCleanup(freeFn), {
214
+ owner: this,
215
+ signal,
216
+ onDeferredError: (error)=>getDebug('yaml-player', {
217
+ console: true
218
+ })(`Deferred YAML cleanup failed: ${String(error)}`)
219
+ });
220
+ else await runFreeFnCleanup(freeFn);
221
+ } catch (error) {
222
+ cleanupError = error;
223
+ this.setPlayerStatus('error', setupError ?? executionError ?? error);
224
+ }
225
+ const endedAt = new Date();
226
+ const cleanupErrors = cleanupError instanceof AggregateError ? cleanupError.errors : void 0 === cleanupError ? [] : [
227
+ cleanupError
228
+ ];
229
+ state.executionRecord = createLegacyYamlExecutionRecord({
230
+ runId,
231
+ attemptIndex: 0,
232
+ script: this.script,
233
+ document,
234
+ startedAt,
235
+ endedAt,
236
+ execution: state.executionResult,
237
+ setupError,
238
+ executionError,
239
+ cleanupErrors,
240
+ aborted: signal?.aborted ?? false,
241
+ publicationErrors: this.publicationErrors,
242
+ outputs: this.result,
243
+ reportFile: agent?.reportFile,
244
+ children: session?.children
245
+ });
246
+ let reportError;
247
+ if (!session || session.isRoot) try {
248
+ const published = await publishLegacyYamlReport({
249
+ agent,
250
+ record: state.executionRecord,
251
+ runId,
252
+ script: this.script,
253
+ scriptPath: this.scriptPath,
254
+ fallbackReportFileName: state.fallbackReportFileName
255
+ });
256
+ this.reportFile = published.reportFile;
257
+ state.executionRecord = published.record;
258
+ } catch (error) {
259
+ reportError = error;
260
+ this.setPlayerStatus('error', setupError ?? executionError ?? cleanupError ?? error);
261
+ state.executionRecord = Object.freeze({
262
+ ...state.executionRecord,
263
+ status: 'failed',
264
+ reportError: error
265
+ });
266
+ }
267
+ session?.finish(state.executionRecord);
268
+ if (reportError) {
269
+ const errors = [
270
+ setupError,
271
+ executionError,
272
+ ...cleanupErrors,
273
+ reportError
274
+ ].filter((error)=>void 0 !== error);
275
+ throw 1 === errors.length ? reportError : new AggregateError(errors, 'YAML execution/report finalization failed');
276
+ }
277
+ if (executionError && cleanupError) throw new AggregateError([
278
+ executionError,
279
+ ...cleanupErrors
280
+ ], 'YAML execution and cleanup failed');
281
+ if (executionError) throw executionError;
282
+ if (cleanupError) throw cleanupError;
420
283
  }
421
284
  constructor(script, setupAgent, onTaskStatusChange, scriptPath){
422
285
  _define_property(this, "script", void 0);
@@ -428,6 +291,7 @@ class ScriptPlayer {
428
291
  _define_property(this, "reportFile", void 0);
429
292
  _define_property(this, "result", void 0);
430
293
  _define_property(this, "unnamedResultIndex", void 0);
294
+ _define_property(this, "publicationErrors", void 0);
431
295
  _define_property(this, "output", void 0);
432
296
  _define_property(this, "unstableLogContent", void 0);
433
297
  _define_property(this, "errorInSetup", void 0);
@@ -436,33 +300,35 @@ class ScriptPlayer {
436
300
  _define_property(this, "target", void 0);
437
301
  _define_property(this, "actionSpace", void 0);
438
302
  _define_property(this, "scriptPath", void 0);
439
- _define_property(this, "failedReportExecutionInCurrentStep", void 0);
440
303
  this.script = script;
441
304
  this.setupAgent = setupAgent;
442
305
  this.onTaskStatusChange = onTaskStatusChange;
443
306
  this.taskStatusList = [];
444
307
  this.status = 'init';
445
308
  this.unnamedResultIndex = 0;
309
+ this.publicationErrors = [];
446
310
  this.interfaceAgent = null;
447
311
  this.actionSpace = [];
448
- this.failedReportExecutionInCurrentStep = false;
449
312
  this.scriptPath = scriptPath;
313
+ collectLegacyYamlDocument(script, scriptPath);
314
+ initializeLegacyYamlPlayerState(this);
450
315
  this.result = {};
451
- this.target = script.target || script.web || script.android || script.ios || script.computer || script.config;
316
+ this.target = resolveWebTarget(script)?.target || script.android || script.ios || script.harmony || script.computer || script.config;
317
+ const outputConfig = resolveYamlOutputConfig(script);
452
318
  if (ifInBrowser || ifInWorker) {
453
319
  this.output = void 0;
454
320
  debug('output is undefined in browser or worker');
455
- } else if (this.target?.output) {
456
- this.output = resolve(process.cwd(), this.target.output);
321
+ } else if (outputConfig.output) {
322
+ this.output = resolve(process.cwd(), outputConfig.output);
457
323
  debug('setting output by config.output', this.output);
458
324
  } else {
459
325
  const scriptName = this.scriptPath ? basename(this.scriptPath, '.yaml').replace(/\.(ya?ml)$/i, '') : "script";
460
- this.output = join(getMidsceneRunSubDir('output'), `${scriptName}-${Date.now()}.json`);
326
+ this.output = join(getMidsceneRunSubDir('output'), `${scriptName}-${uuid()}.json`);
461
327
  debug("setting output by script path", this.output);
462
328
  }
463
329
  if (ifInBrowser || ifInWorker) this.unstableLogContent = void 0;
464
- else if ('string' == typeof this.target?.unstableLogContent) this.unstableLogContent = resolve(process.cwd(), this.target.unstableLogContent);
465
- else if (this.target?.unstableLogContent === true) this.unstableLogContent = join(getMidsceneRunSubDir('output'), 'unstableLogContent.json');
330
+ else if ('string' == typeof outputConfig.unstableLogContent) this.unstableLogContent = resolve(process.cwd(), outputConfig.unstableLogContent);
331
+ else if (true === outputConfig.unstableLogContent) this.unstableLogContent = join(getMidsceneRunSubDir('output'), 'unstableLogContent.json');
466
332
  this.taskStatusList = (script.tasks || []).map((task, taskIndex)=>({
467
333
  ...task,
468
334
  index: taskIndex,