@aiscene/core 1.7.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 (279) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -0
  3. package/dist/es/agent/agent.mjs +749 -0
  4. package/dist/es/agent/agent.mjs.map +1 -0
  5. package/dist/es/agent/common.mjs +0 -0
  6. package/dist/es/agent/execution-session.mjs +41 -0
  7. package/dist/es/agent/execution-session.mjs.map +1 -0
  8. package/dist/es/agent/index.mjs +6 -0
  9. package/dist/es/agent/task-builder.mjs +332 -0
  10. package/dist/es/agent/task-builder.mjs.map +1 -0
  11. package/dist/es/agent/task-cache.mjs +214 -0
  12. package/dist/es/agent/task-cache.mjs.map +1 -0
  13. package/dist/es/agent/tasks.mjs +426 -0
  14. package/dist/es/agent/tasks.mjs.map +1 -0
  15. package/dist/es/agent/ui-utils.mjs +91 -0
  16. package/dist/es/agent/ui-utils.mjs.map +1 -0
  17. package/dist/es/agent/utils.mjs +198 -0
  18. package/dist/es/agent/utils.mjs.map +1 -0
  19. package/dist/es/ai-model/auto-glm/actions.mjs +237 -0
  20. package/dist/es/ai-model/auto-glm/actions.mjs.map +1 -0
  21. package/dist/es/ai-model/auto-glm/index.mjs +6 -0
  22. package/dist/es/ai-model/auto-glm/parser.mjs +239 -0
  23. package/dist/es/ai-model/auto-glm/parser.mjs.map +1 -0
  24. package/dist/es/ai-model/auto-glm/planning.mjs +71 -0
  25. package/dist/es/ai-model/auto-glm/planning.mjs.map +1 -0
  26. package/dist/es/ai-model/auto-glm/prompt.mjs +222 -0
  27. package/dist/es/ai-model/auto-glm/prompt.mjs.map +1 -0
  28. package/dist/es/ai-model/auto-glm/util.mjs +9 -0
  29. package/dist/es/ai-model/auto-glm/util.mjs.map +1 -0
  30. package/dist/es/ai-model/conversation-history.mjs +195 -0
  31. package/dist/es/ai-model/conversation-history.mjs.map +1 -0
  32. package/dist/es/ai-model/index.mjs +11 -0
  33. package/dist/es/ai-model/inspect.mjs +394 -0
  34. package/dist/es/ai-model/inspect.mjs.map +1 -0
  35. package/dist/es/ai-model/llm-planning.mjs +233 -0
  36. package/dist/es/ai-model/llm-planning.mjs.map +1 -0
  37. package/dist/es/ai-model/prompt/common.mjs +7 -0
  38. package/dist/es/ai-model/prompt/common.mjs.map +1 -0
  39. package/dist/es/ai-model/prompt/describe.mjs +66 -0
  40. package/dist/es/ai-model/prompt/describe.mjs.map +1 -0
  41. package/dist/es/ai-model/prompt/extraction.mjs +129 -0
  42. package/dist/es/ai-model/prompt/extraction.mjs.map +1 -0
  43. package/dist/es/ai-model/prompt/llm-locator.mjs +51 -0
  44. package/dist/es/ai-model/prompt/llm-locator.mjs.map +1 -0
  45. package/dist/es/ai-model/prompt/llm-planning.mjs +568 -0
  46. package/dist/es/ai-model/prompt/llm-planning.mjs.map +1 -0
  47. package/dist/es/ai-model/prompt/llm-section-locator.mjs +44 -0
  48. package/dist/es/ai-model/prompt/llm-section-locator.mjs.map +1 -0
  49. package/dist/es/ai-model/prompt/order-sensitive-judge.mjs +35 -0
  50. package/dist/es/ai-model/prompt/order-sensitive-judge.mjs.map +1 -0
  51. package/dist/es/ai-model/prompt/playwright-generator.mjs +117 -0
  52. package/dist/es/ai-model/prompt/playwright-generator.mjs.map +1 -0
  53. package/dist/es/ai-model/prompt/ui-tars-planning.mjs +36 -0
  54. package/dist/es/ai-model/prompt/ui-tars-planning.mjs.map +1 -0
  55. package/dist/es/ai-model/prompt/util.mjs +59 -0
  56. package/dist/es/ai-model/prompt/util.mjs.map +1 -0
  57. package/dist/es/ai-model/prompt/yaml-generator.mjs +219 -0
  58. package/dist/es/ai-model/prompt/yaml-generator.mjs.map +1 -0
  59. package/dist/es/ai-model/service-caller/codex-app-server.mjs +575 -0
  60. package/dist/es/ai-model/service-caller/codex-app-server.mjs.map +1 -0
  61. package/dist/es/ai-model/service-caller/image-detail.mjs +6 -0
  62. package/dist/es/ai-model/service-caller/image-detail.mjs.map +1 -0
  63. package/dist/es/ai-model/service-caller/index.mjs +473 -0
  64. package/dist/es/ai-model/service-caller/index.mjs.map +1 -0
  65. package/dist/es/ai-model/ui-tars-planning.mjs +249 -0
  66. package/dist/es/ai-model/ui-tars-planning.mjs.map +1 -0
  67. package/dist/es/common.mjs +371 -0
  68. package/dist/es/common.mjs.map +1 -0
  69. package/dist/es/device/device-options.mjs +0 -0
  70. package/dist/es/device/index.mjs +341 -0
  71. package/dist/es/device/index.mjs.map +1 -0
  72. package/dist/es/dump/html-utils.mjs +284 -0
  73. package/dist/es/dump/html-utils.mjs.map +1 -0
  74. package/dist/es/dump/image-restoration.mjs +43 -0
  75. package/dist/es/dump/image-restoration.mjs.map +1 -0
  76. package/dist/es/dump/index.mjs +3 -0
  77. package/dist/es/index.mjs +15 -0
  78. package/dist/es/index.mjs.map +1 -0
  79. package/dist/es/report-generator.mjs +162 -0
  80. package/dist/es/report-generator.mjs.map +1 -0
  81. package/dist/es/report.mjs +137 -0
  82. package/dist/es/report.mjs.map +1 -0
  83. package/dist/es/screenshot-item.mjs +105 -0
  84. package/dist/es/screenshot-item.mjs.map +1 -0
  85. package/dist/es/service/index.mjs +274 -0
  86. package/dist/es/service/index.mjs.map +1 -0
  87. package/dist/es/service/utils.mjs +15 -0
  88. package/dist/es/service/utils.mjs.map +1 -0
  89. package/dist/es/skill/index.mjs +38 -0
  90. package/dist/es/skill/index.mjs.map +1 -0
  91. package/dist/es/task-runner.mjs +263 -0
  92. package/dist/es/task-runner.mjs.map +1 -0
  93. package/dist/es/task-timing.mjs +12 -0
  94. package/dist/es/task-timing.mjs.map +1 -0
  95. package/dist/es/tree.mjs +13 -0
  96. package/dist/es/tree.mjs.map +1 -0
  97. package/dist/es/types.mjs +199 -0
  98. package/dist/es/types.mjs.map +1 -0
  99. package/dist/es/utils.mjs +229 -0
  100. package/dist/es/utils.mjs.map +1 -0
  101. package/dist/es/yaml/builder.mjs +13 -0
  102. package/dist/es/yaml/builder.mjs.map +1 -0
  103. package/dist/es/yaml/index.mjs +4 -0
  104. package/dist/es/yaml/player.mjs +434 -0
  105. package/dist/es/yaml/player.mjs.map +1 -0
  106. package/dist/es/yaml/utils.mjs +102 -0
  107. package/dist/es/yaml/utils.mjs.map +1 -0
  108. package/dist/es/yaml.mjs +0 -0
  109. package/dist/lib/agent/agent.js +797 -0
  110. package/dist/lib/agent/agent.js.map +1 -0
  111. package/dist/lib/agent/common.js +5 -0
  112. package/dist/lib/agent/execution-session.js +75 -0
  113. package/dist/lib/agent/execution-session.js.map +1 -0
  114. package/dist/lib/agent/index.js +81 -0
  115. package/dist/lib/agent/index.js.map +1 -0
  116. package/dist/lib/agent/task-builder.js +369 -0
  117. package/dist/lib/agent/task-builder.js.map +1 -0
  118. package/dist/lib/agent/task-cache.js +266 -0
  119. package/dist/lib/agent/task-cache.js.map +1 -0
  120. package/dist/lib/agent/tasks.js +469 -0
  121. package/dist/lib/agent/tasks.js.map +1 -0
  122. package/dist/lib/agent/ui-utils.js +143 -0
  123. package/dist/lib/agent/ui-utils.js.map +1 -0
  124. package/dist/lib/agent/utils.js +275 -0
  125. package/dist/lib/agent/utils.js.map +1 -0
  126. package/dist/lib/ai-model/auto-glm/actions.js +271 -0
  127. package/dist/lib/ai-model/auto-glm/actions.js.map +1 -0
  128. package/dist/lib/ai-model/auto-glm/index.js +66 -0
  129. package/dist/lib/ai-model/auto-glm/index.js.map +1 -0
  130. package/dist/lib/ai-model/auto-glm/parser.js +282 -0
  131. package/dist/lib/ai-model/auto-glm/parser.js.map +1 -0
  132. package/dist/lib/ai-model/auto-glm/planning.js +105 -0
  133. package/dist/lib/ai-model/auto-glm/planning.js.map +1 -0
  134. package/dist/lib/ai-model/auto-glm/prompt.js +259 -0
  135. package/dist/lib/ai-model/auto-glm/prompt.js.map +1 -0
  136. package/dist/lib/ai-model/auto-glm/util.js +46 -0
  137. package/dist/lib/ai-model/auto-glm/util.js.map +1 -0
  138. package/dist/lib/ai-model/conversation-history.js +229 -0
  139. package/dist/lib/ai-model/conversation-history.js.map +1 -0
  140. package/dist/lib/ai-model/index.js +125 -0
  141. package/dist/lib/ai-model/index.js.map +1 -0
  142. package/dist/lib/ai-model/inspect.js +440 -0
  143. package/dist/lib/ai-model/inspect.js.map +1 -0
  144. package/dist/lib/ai-model/llm-planning.js +270 -0
  145. package/dist/lib/ai-model/llm-planning.js.map +1 -0
  146. package/dist/lib/ai-model/prompt/common.js +41 -0
  147. package/dist/lib/ai-model/prompt/common.js.map +1 -0
  148. package/dist/lib/ai-model/prompt/describe.js +100 -0
  149. package/dist/lib/ai-model/prompt/describe.js.map +1 -0
  150. package/dist/lib/ai-model/prompt/extraction.js +169 -0
  151. package/dist/lib/ai-model/prompt/extraction.js.map +1 -0
  152. package/dist/lib/ai-model/prompt/llm-locator.js +88 -0
  153. package/dist/lib/ai-model/prompt/llm-locator.js.map +1 -0
  154. package/dist/lib/ai-model/prompt/llm-planning.js +605 -0
  155. package/dist/lib/ai-model/prompt/llm-planning.js.map +1 -0
  156. package/dist/lib/ai-model/prompt/llm-section-locator.js +81 -0
  157. package/dist/lib/ai-model/prompt/llm-section-locator.js.map +1 -0
  158. package/dist/lib/ai-model/prompt/order-sensitive-judge.js +72 -0
  159. package/dist/lib/ai-model/prompt/order-sensitive-judge.js.map +1 -0
  160. package/dist/lib/ai-model/prompt/playwright-generator.js +178 -0
  161. package/dist/lib/ai-model/prompt/playwright-generator.js.map +1 -0
  162. package/dist/lib/ai-model/prompt/ui-tars-planning.js +73 -0
  163. package/dist/lib/ai-model/prompt/ui-tars-planning.js.map +1 -0
  164. package/dist/lib/ai-model/prompt/util.js +105 -0
  165. package/dist/lib/ai-model/prompt/util.js.map +1 -0
  166. package/dist/lib/ai-model/prompt/yaml-generator.js +280 -0
  167. package/dist/lib/ai-model/prompt/yaml-generator.js.map +1 -0
  168. package/dist/lib/ai-model/service-caller/codex-app-server.js +624 -0
  169. package/dist/lib/ai-model/service-caller/codex-app-server.js.map +1 -0
  170. package/dist/lib/ai-model/service-caller/image-detail.js +40 -0
  171. package/dist/lib/ai-model/service-caller/image-detail.js.map +1 -0
  172. package/dist/lib/ai-model/service-caller/index.js +538 -0
  173. package/dist/lib/ai-model/service-caller/index.js.map +1 -0
  174. package/dist/lib/ai-model/ui-tars-planning.js +283 -0
  175. package/dist/lib/ai-model/ui-tars-planning.js.map +1 -0
  176. package/dist/lib/common.js +480 -0
  177. package/dist/lib/common.js.map +1 -0
  178. package/dist/lib/device/device-options.js +20 -0
  179. package/dist/lib/device/device-options.js.map +1 -0
  180. package/dist/lib/device/index.js +468 -0
  181. package/dist/lib/device/index.js.map +1 -0
  182. package/dist/lib/dump/html-utils.js +357 -0
  183. package/dist/lib/dump/html-utils.js.map +1 -0
  184. package/dist/lib/dump/image-restoration.js +77 -0
  185. package/dist/lib/dump/image-restoration.js.map +1 -0
  186. package/dist/lib/dump/index.js +60 -0
  187. package/dist/lib/dump/index.js.map +1 -0
  188. package/dist/lib/index.js +146 -0
  189. package/dist/lib/index.js.map +1 -0
  190. package/dist/lib/report-generator.js +200 -0
  191. package/dist/lib/report-generator.js.map +1 -0
  192. package/dist/lib/report.js +171 -0
  193. package/dist/lib/report.js.map +1 -0
  194. package/dist/lib/screenshot-item.js +139 -0
  195. package/dist/lib/screenshot-item.js.map +1 -0
  196. package/dist/lib/service/index.js +308 -0
  197. package/dist/lib/service/index.js.map +1 -0
  198. package/dist/lib/service/utils.js +49 -0
  199. package/dist/lib/service/utils.js.map +1 -0
  200. package/dist/lib/skill/index.js +72 -0
  201. package/dist/lib/skill/index.js.map +1 -0
  202. package/dist/lib/task-runner.js +300 -0
  203. package/dist/lib/task-runner.js.map +1 -0
  204. package/dist/lib/task-timing.js +46 -0
  205. package/dist/lib/task-timing.js.map +1 -0
  206. package/dist/lib/tree.js +53 -0
  207. package/dist/lib/tree.js.map +1 -0
  208. package/dist/lib/types.js +288 -0
  209. package/dist/lib/types.js.map +1 -0
  210. package/dist/lib/utils.js +308 -0
  211. package/dist/lib/utils.js.map +1 -0
  212. package/dist/lib/yaml/builder.js +57 -0
  213. package/dist/lib/yaml/builder.js.map +1 -0
  214. package/dist/lib/yaml/index.js +81 -0
  215. package/dist/lib/yaml/index.js.map +1 -0
  216. package/dist/lib/yaml/player.js +468 -0
  217. package/dist/lib/yaml/player.js.map +1 -0
  218. package/dist/lib/yaml/utils.js +155 -0
  219. package/dist/lib/yaml/utils.js.map +1 -0
  220. package/dist/lib/yaml.js +20 -0
  221. package/dist/lib/yaml.js.map +1 -0
  222. package/dist/types/agent/agent.d.ts +205 -0
  223. package/dist/types/agent/common.d.ts +0 -0
  224. package/dist/types/agent/execution-session.d.ts +36 -0
  225. package/dist/types/agent/index.d.ts +10 -0
  226. package/dist/types/agent/task-builder.d.ts +34 -0
  227. package/dist/types/agent/task-cache.d.ts +49 -0
  228. package/dist/types/agent/tasks.d.ts +69 -0
  229. package/dist/types/agent/ui-utils.d.ts +14 -0
  230. package/dist/types/agent/utils.d.ts +31 -0
  231. package/dist/types/ai-model/auto-glm/actions.d.ts +78 -0
  232. package/dist/types/ai-model/auto-glm/index.d.ts +6 -0
  233. package/dist/types/ai-model/auto-glm/parser.d.ts +18 -0
  234. package/dist/types/ai-model/auto-glm/planning.d.ts +12 -0
  235. package/dist/types/ai-model/auto-glm/prompt.d.ts +27 -0
  236. package/dist/types/ai-model/auto-glm/util.d.ts +13 -0
  237. package/dist/types/ai-model/conversation-history.d.ts +105 -0
  238. package/dist/types/ai-model/index.d.ts +14 -0
  239. package/dist/types/ai-model/inspect.d.ts +67 -0
  240. package/dist/types/ai-model/llm-planning.d.ts +19 -0
  241. package/dist/types/ai-model/prompt/common.d.ts +2 -0
  242. package/dist/types/ai-model/prompt/describe.d.ts +1 -0
  243. package/dist/types/ai-model/prompt/extraction.d.ts +7 -0
  244. package/dist/types/ai-model/prompt/llm-locator.d.ts +3 -0
  245. package/dist/types/ai-model/prompt/llm-planning.d.ts +10 -0
  246. package/dist/types/ai-model/prompt/llm-section-locator.d.ts +3 -0
  247. package/dist/types/ai-model/prompt/order-sensitive-judge.d.ts +2 -0
  248. package/dist/types/ai-model/prompt/playwright-generator.d.ts +26 -0
  249. package/dist/types/ai-model/prompt/ui-tars-planning.d.ts +2 -0
  250. package/dist/types/ai-model/prompt/util.d.ts +33 -0
  251. package/dist/types/ai-model/prompt/yaml-generator.d.ts +100 -0
  252. package/dist/types/ai-model/service-caller/codex-app-server.d.ts +42 -0
  253. package/dist/types/ai-model/service-caller/image-detail.d.ts +2 -0
  254. package/dist/types/ai-model/service-caller/index.d.ts +49 -0
  255. package/dist/types/ai-model/ui-tars-planning.d.ts +72 -0
  256. package/dist/types/common.d.ts +288 -0
  257. package/dist/types/device/device-options.d.ts +142 -0
  258. package/dist/types/device/index.d.ts +2528 -0
  259. package/dist/types/dump/html-utils.d.ts +63 -0
  260. package/dist/types/dump/image-restoration.d.ts +6 -0
  261. package/dist/types/dump/index.d.ts +5 -0
  262. package/dist/types/index.d.ts +17 -0
  263. package/dist/types/report-generator.d.ts +66 -0
  264. package/dist/types/report.d.ts +22 -0
  265. package/dist/types/screenshot-item.d.ts +66 -0
  266. package/dist/types/service/index.d.ts +24 -0
  267. package/dist/types/service/utils.d.ts +2 -0
  268. package/dist/types/skill/index.d.ts +25 -0
  269. package/dist/types/task-runner.d.ts +50 -0
  270. package/dist/types/task-timing.d.ts +8 -0
  271. package/dist/types/tree.d.ts +4 -0
  272. package/dist/types/types.d.ts +669 -0
  273. package/dist/types/utils.d.ts +40 -0
  274. package/dist/types/yaml/builder.d.ts +2 -0
  275. package/dist/types/yaml/index.d.ts +4 -0
  276. package/dist/types/yaml/player.d.ts +34 -0
  277. package/dist/types/yaml/utils.d.ts +9 -0
  278. package/dist/types/yaml.d.ts +217 -0
  279. package/package.json +130 -0
@@ -0,0 +1,38 @@
1
+ import { CLIError, runToolsCLI } from "@midscene/shared/cli";
2
+ import { BaseMidsceneTools } from "@midscene/shared/mcp";
3
+ import { Agent } from "../agent/agent.mjs";
4
+ function _define_property(obj, key, value) {
5
+ if (key in obj) Object.defineProperty(obj, key, {
6
+ value: value,
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true
10
+ });
11
+ else obj[key] = value;
12
+ return obj;
13
+ }
14
+ class SkillMidsceneTools extends BaseMidsceneTools {
15
+ createTemporaryDevice() {
16
+ return new this.DeviceClass();
17
+ }
18
+ async ensureAgent() {
19
+ if (!this.agent) {
20
+ const device = new this.DeviceClass();
21
+ this.agent = new Agent(device);
22
+ }
23
+ return this.agent;
24
+ }
25
+ constructor(DeviceClass){
26
+ super(), _define_property(this, "DeviceClass", void 0), this.DeviceClass = DeviceClass;
27
+ }
28
+ }
29
+ function runSkillCLI(options) {
30
+ const tools = new SkillMidsceneTools(options.DeviceClass);
31
+ return runToolsCLI(tools, options.scriptName).catch((e)=>{
32
+ if (!(e instanceof CLIError)) console.error(e);
33
+ process.exit(e instanceof CLIError ? e.exitCode : 1);
34
+ });
35
+ }
36
+ export { runSkillCLI };
37
+
38
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill/index.mjs","sources":["../../../src/skill/index.ts"],"sourcesContent":["import { CLIError, runToolsCLI } from '@midscene/shared/cli';\nimport { BaseMidsceneTools } from '@midscene/shared/mcp';\nimport type { BaseAgent, BaseDevice } from '@midscene/shared/mcp';\nimport { Agent } from '../agent/agent';\nimport type { AbstractInterface } from '../device';\n\ntype DeviceClass = new (...args: any[]) => AbstractInterface;\n\n/**\n * Skill tools manager that lazily creates Agent from a Device class.\n * Used by runSkillCLI for CLI / Agent Skills scenarios where no agent exists at startup.\n */\nclass SkillMidsceneTools extends BaseMidsceneTools<BaseAgent> {\n constructor(private DeviceClass: DeviceClass) {\n super();\n }\n\n protected createTemporaryDevice(): BaseDevice {\n return new this.DeviceClass() as unknown as BaseDevice;\n }\n\n protected async ensureAgent(): Promise<BaseAgent> {\n if (!this.agent) {\n const device = new this.DeviceClass();\n this.agent = new Agent(device) as unknown as BaseAgent;\n }\n return this.agent;\n }\n}\n\nexport interface SkillCLIOptions {\n scriptName: string;\n DeviceClass: DeviceClass;\n}\n\n/**\n * Launch a Skill CLI for a custom interface Device class.\n * This enables AI coding assistants (Claude Code, Cline, etc.) to control\n * your custom interface through CLI commands.\n *\n * @example\n * ```typescript\n * #!/usr/bin/env node\n * import { runSkillCLI } from '@midscene/core/skill';\n * import { SampleDevice } from './sample-device';\n *\n * runSkillCLI({\n * DeviceClass: SampleDevice,\n * scriptName: 'my-device',\n * });\n * ```\n */\nexport function runSkillCLI(options: SkillCLIOptions): Promise<void> {\n const tools = new SkillMidsceneTools(options.DeviceClass);\n return runToolsCLI(tools, options.scriptName).catch((e) => {\n if (!(e instanceof CLIError)) console.error(e);\n process.exit(e instanceof CLIError ? e.exitCode : 1);\n });\n}\n"],"names":["SkillMidsceneTools","BaseMidsceneTools","device","Agent","DeviceClass","runSkillCLI","options","tools","runToolsCLI","e","CLIError","console","process"],"mappings":";;;;;;;;;;;;;AAYA,MAAMA,2BAA2BC;IAKrB,wBAAoC;QAC5C,OAAO,IAAI,IAAI,CAAC,WAAW;IAC7B;IAEA,MAAgB,cAAkC;QAChD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;YACf,MAAMC,SAAS,IAAI,IAAI,CAAC,WAAW;YACnC,IAAI,CAAC,KAAK,GAAG,IAAIC,MAAMD;QACzB;QACA,OAAO,IAAI,CAAC,KAAK;IACnB;IAdA,YAAoBE,WAAwB,CAAE;QAC5C,KAAK,wDADaA,WAAW,GAAXA;IAEpB;AAaF;AAwBO,SAASC,YAAYC,OAAwB;IAClD,MAAMC,QAAQ,IAAIP,mBAAmBM,QAAQ,WAAW;IACxD,OAAOE,YAAYD,OAAOD,QAAQ,UAAU,EAAE,KAAK,CAAC,CAACG;QACnD,IAAI,CAAEA,CAAAA,aAAaC,QAAO,GAAIC,QAAQ,KAAK,CAACF;QAC5CG,QAAQ,IAAI,CAACH,aAAaC,WAAWD,EAAE,QAAQ,GAAG;IACpD;AACF"}
@@ -0,0 +1,263 @@
1
+ import { setTimingFieldOnce } from "./task-timing.mjs";
2
+ import { ExecutionDump } from "./types.mjs";
3
+ import { getDebug } from "@midscene/shared/logger";
4
+ import { assert, uuid } from "@midscene/shared/utils";
5
+ function _define_property(obj, key, value) {
6
+ if (key in obj) Object.defineProperty(obj, key, {
7
+ value: value,
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true
11
+ });
12
+ else obj[key] = value;
13
+ return obj;
14
+ }
15
+ const debug = getDebug('task-runner');
16
+ const UI_CONTEXT_CACHE_TTL_MS = 300;
17
+ class TaskRunner {
18
+ async emitOnTaskUpdate(error) {
19
+ if (!this.onTaskUpdate) return;
20
+ await this.onTaskUpdate(this, error);
21
+ }
22
+ async getUiContext(options) {
23
+ const now = Date.now();
24
+ const shouldReuse = !options?.forceRefresh && this.lastUiContext && now - this.lastUiContext.capturedAt <= UI_CONTEXT_CACHE_TTL_MS;
25
+ if (shouldReuse && this.lastUiContext?.context) {
26
+ debug(`reuse cached uiContext captured ${now - this.lastUiContext.capturedAt}ms ago`);
27
+ return this.lastUiContext?.context;
28
+ }
29
+ try {
30
+ const uiContext = await this.uiContextBuilder();
31
+ if (uiContext) this.lastUiContext = {
32
+ context: uiContext,
33
+ capturedAt: Date.now()
34
+ };
35
+ else this.lastUiContext = void 0;
36
+ return uiContext;
37
+ } catch (error) {
38
+ this.lastUiContext = void 0;
39
+ throw error;
40
+ }
41
+ }
42
+ async captureScreenshot() {
43
+ try {
44
+ const uiContext = await this.getUiContext({
45
+ forceRefresh: true
46
+ });
47
+ return uiContext?.screenshot;
48
+ } catch (error) {
49
+ console.error('error while capturing screenshot', error);
50
+ }
51
+ }
52
+ attachRecorderItem(task, screenshot, phase) {
53
+ if (!phase || !screenshot) return;
54
+ const recorderItem = {
55
+ type: 'screenshot',
56
+ ts: Date.now(),
57
+ screenshot,
58
+ timing: phase
59
+ };
60
+ if (!task.recorder) {
61
+ task.recorder = [
62
+ recorderItem
63
+ ];
64
+ return;
65
+ }
66
+ task.recorder.push(recorderItem);
67
+ }
68
+ markTaskAsPending(task) {
69
+ return {
70
+ taskId: uuid(),
71
+ status: 'pending',
72
+ ...task
73
+ };
74
+ }
75
+ normalizeStatusFromError(options, errorMessage) {
76
+ if ('error' !== this.status) return;
77
+ assert(options?.allowWhenError, errorMessage || `task runner is in error state, cannot proceed\nerror=${this.latestErrorTask()?.error}\n${this.latestErrorTask()?.errorStack}`);
78
+ this.status = this.tasks.length > 0 ? 'pending' : 'init';
79
+ }
80
+ async append(task, options) {
81
+ this.normalizeStatusFromError(options, `task runner is in error state, cannot append task\nerror=${this.latestErrorTask()?.error}\n${this.latestErrorTask()?.errorStack}`);
82
+ if (Array.isArray(task)) this.tasks.push(...task.map((item)=>this.markTaskAsPending(item)));
83
+ else this.tasks.push(this.markTaskAsPending(task));
84
+ if ('running' !== this.status) this.status = 'pending';
85
+ await this.emitOnTaskUpdate();
86
+ }
87
+ async appendAndFlush(task, options) {
88
+ await this.append(task, options);
89
+ return this.flush(options);
90
+ }
91
+ async flush(options) {
92
+ if ('init' === this.status && this.tasks.length > 0) console.warn('illegal state for task runner, status is init but tasks are not empty');
93
+ this.normalizeStatusFromError(options, 'task runner is in error state');
94
+ assert('running' !== this.status, 'task runner is already running');
95
+ assert('completed' !== this.status, 'task runner is already completed');
96
+ const nextPendingIndex = this.tasks.findIndex((task)=>'pending' === task.status);
97
+ if (nextPendingIndex < 0) return;
98
+ this.status = 'running';
99
+ await this.emitOnTaskUpdate();
100
+ let taskIndex = nextPendingIndex;
101
+ let successfullyCompleted = true;
102
+ let previousFindOutput;
103
+ while(taskIndex < this.tasks.length){
104
+ const task = this.tasks[taskIndex];
105
+ assert('pending' === task.status, `task status should be pending, but got: ${task.status}`);
106
+ task.timing = {
107
+ start: Date.now()
108
+ };
109
+ try {
110
+ task.status = 'running';
111
+ await this.emitOnTaskUpdate();
112
+ try {
113
+ if (this.onTaskStart) await this.onTaskStart(task);
114
+ } catch (e) {
115
+ console.error('error in onTaskStart', e);
116
+ }
117
+ assert([
118
+ 'Insight',
119
+ 'Action Space',
120
+ 'Planning'
121
+ ].indexOf(task.type) >= 0, `unsupported task type: ${task.type}`);
122
+ const { executor, param } = task;
123
+ assert(executor, `executor is required for task type: ${task.type}`);
124
+ let returnValue;
125
+ const forceRefresh = 'Insight' === task.type;
126
+ setTimingFieldOnce(task.timing, 'getUiContextStart');
127
+ const uiContext = await this.getUiContext({
128
+ forceRefresh
129
+ });
130
+ setTimingFieldOnce(task.timing, 'getUiContextEnd');
131
+ task.uiContext = uiContext;
132
+ const executorContext = {
133
+ task,
134
+ element: previousFindOutput?.element,
135
+ uiContext
136
+ };
137
+ if ('Insight' === task.type) {
138
+ assert('Query' === task.subType || 'Assert' === task.subType || 'WaitFor' === task.subType || 'Boolean' === task.subType || 'Number' === task.subType || 'String' === task.subType, `unsupported service subType: ${task.subType}`);
139
+ returnValue = await task.executor(param, executorContext);
140
+ } else if ('Planning' === task.type) {
141
+ returnValue = await task.executor(param, executorContext);
142
+ if ('Locate' === task.subType) previousFindOutput = returnValue?.output;
143
+ } else if ('Action Space' === task.type) returnValue = await task.executor(param, executorContext);
144
+ else {
145
+ console.warn(`unsupported task type: ${task.type}, will try to execute it directly`);
146
+ returnValue = await task.executor(param, executorContext);
147
+ }
148
+ const isLastTask = taskIndex === this.tasks.length - 1;
149
+ if (isLastTask) {
150
+ setTimingFieldOnce(task.timing, 'captureAfterCallingSnapshotStart');
151
+ const screenshot = await this.captureScreenshot();
152
+ this.attachRecorderItem(task, screenshot, 'after-calling');
153
+ setTimingFieldOnce(task.timing, 'captureAfterCallingSnapshotEnd');
154
+ }
155
+ Object.assign(task, returnValue);
156
+ task.status = 'finished';
157
+ task.timing.end = Date.now();
158
+ task.timing.cost = task.timing.end - task.timing.start;
159
+ await this.emitOnTaskUpdate();
160
+ taskIndex++;
161
+ } catch (e) {
162
+ successfullyCompleted = false;
163
+ task.error = e;
164
+ task.errorMessage = e?.message || ('string' == typeof e ? e : 'error-without-message');
165
+ task.errorStack = e.stack;
166
+ task.status = 'failed';
167
+ task.timing.end = Date.now();
168
+ task.timing.cost = task.timing.end - task.timing.start;
169
+ await this.emitOnTaskUpdate();
170
+ break;
171
+ }
172
+ }
173
+ for(let i = taskIndex + 1; i < this.tasks.length; i++)this.tasks[i].status = 'cancelled';
174
+ if (taskIndex + 1 < this.tasks.length) await this.emitOnTaskUpdate();
175
+ let finalizeError;
176
+ if (successfullyCompleted) {
177
+ this.status = 'completed';
178
+ await this.emitOnTaskUpdate();
179
+ } else {
180
+ this.status = 'error';
181
+ const errorTask = this.latestErrorTask();
182
+ const messageBase = errorTask?.errorMessage || (errorTask?.error ? String(errorTask.error) : 'Task execution failed');
183
+ const stack = errorTask?.errorStack;
184
+ const message = stack ? `${messageBase}\n${stack}` : messageBase;
185
+ finalizeError = new TaskExecutionError(message, this, errorTask, {
186
+ cause: errorTask?.error
187
+ });
188
+ await this.emitOnTaskUpdate(finalizeError);
189
+ }
190
+ if (finalizeError) throw finalizeError;
191
+ if (this.tasks.length) {
192
+ const outputIndex = Math.min(taskIndex, this.tasks.length - 1);
193
+ const { thought, output } = this.tasks[outputIndex];
194
+ return {
195
+ thought,
196
+ output
197
+ };
198
+ }
199
+ }
200
+ isInErrorState() {
201
+ return 'error' === this.status;
202
+ }
203
+ latestErrorTask() {
204
+ if ('error' !== this.status) return null;
205
+ for(let i = this.tasks.length - 1; i >= 0; i--)if ('failed' === this.tasks[i].status) return this.tasks[i];
206
+ return null;
207
+ }
208
+ dump() {
209
+ return new ExecutionDump({
210
+ id: this.id,
211
+ logTime: this.executionLogTime,
212
+ name: this.name,
213
+ tasks: this.tasks
214
+ });
215
+ }
216
+ async appendErrorPlan(errorMsg) {
217
+ const errorTask = {
218
+ type: 'Action Space',
219
+ subType: 'Error',
220
+ param: {
221
+ thought: errorMsg
222
+ },
223
+ thought: errorMsg,
224
+ executor: async ()=>{
225
+ throw new Error(errorMsg || 'error without thought');
226
+ }
227
+ };
228
+ await this.appendAndFlush(errorTask);
229
+ return {
230
+ output: void 0,
231
+ runner: this
232
+ };
233
+ }
234
+ constructor(name, uiContextBuilder, options){
235
+ _define_property(this, "id", void 0);
236
+ _define_property(this, "name", void 0);
237
+ _define_property(this, "tasks", void 0);
238
+ _define_property(this, "status", void 0);
239
+ _define_property(this, "onTaskStart", void 0);
240
+ _define_property(this, "uiContextBuilder", void 0);
241
+ _define_property(this, "onTaskUpdate", void 0);
242
+ _define_property(this, "executionLogTime", void 0);
243
+ _define_property(this, "lastUiContext", void 0);
244
+ this.id = uuid();
245
+ this.status = options?.tasks && options.tasks.length > 0 ? 'pending' : 'init';
246
+ this.name = name;
247
+ this.tasks = (options?.tasks || []).map((item)=>this.markTaskAsPending(item));
248
+ this.onTaskStart = options?.onTaskStart;
249
+ this.uiContextBuilder = uiContextBuilder;
250
+ this.onTaskUpdate = options?.onTaskUpdate;
251
+ this.executionLogTime = Date.now();
252
+ }
253
+ }
254
+ class TaskExecutionError extends Error {
255
+ constructor(message, runner, errorTask, options){
256
+ super(message, options), _define_property(this, "runner", void 0), _define_property(this, "errorTask", void 0);
257
+ this.runner = runner;
258
+ this.errorTask = errorTask;
259
+ }
260
+ }
261
+ export { TaskExecutionError, TaskRunner };
262
+
263
+ //# sourceMappingURL=task-runner.mjs.map
@@ -0,0 +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 '@midscene/shared/logger';\nimport { assert, uuid } from '@midscene/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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"}
@@ -0,0 +1,12 @@
1
+ import { getDebug } from "@midscene/shared/logger";
2
+ const debugTiming = getDebug('task-timing');
3
+ function setTimingFieldOnce(timing, field) {
4
+ if (!timing) return void debugTiming(`[warning] timing object missing, skip set. field=${field}`);
5
+ const value = Date.now();
6
+ const existingValue = timing[field];
7
+ if (void 0 !== existingValue) return void debugTiming(`[warning] duplicate timing field set ignored. field=${field}, existing=${existingValue}, incoming=${value}`);
8
+ timing[field] = value;
9
+ }
10
+ export { setTimingFieldOnce };
11
+
12
+ //# sourceMappingURL=task-timing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-timing.mjs","sources":["../../src/task-timing.ts"],"sourcesContent":["import type { ExecutionTask } from '@/types';\nimport { getDebug } from '@midscene/shared/logger';\n\nconst debugTiming = getDebug('task-timing');\n\ntype ExecutionTaskTiming = NonNullable<ExecutionTask['timing']>;\n\ntype NumericTimingField = {\n [K in keyof ExecutionTaskTiming]-?: ExecutionTaskTiming[K] extends\n | number\n | undefined\n ? K\n : never;\n}[keyof ExecutionTaskTiming];\n\nexport type TimingSettableField = Exclude<\n NumericTimingField,\n 'start' | 'end' | 'cost'\n>;\n\nexport function setTimingFieldOnce(\n timing: ExecutionTaskTiming | undefined,\n field: TimingSettableField,\n): void {\n if (!timing) {\n debugTiming(`[warning] timing object missing, skip set. field=${field}`);\n return;\n }\n\n const value = Date.now();\n const existingValue = timing[field];\n if (existingValue !== undefined) {\n debugTiming(\n `[warning] duplicate timing field set ignored. field=${field}, existing=${existingValue}, incoming=${value}`,\n );\n return;\n }\n\n timing[field] = value;\n}\n"],"names":["debugTiming","getDebug","setTimingFieldOnce","timing","field","value","Date","existingValue","undefined"],"mappings":";AAGA,MAAMA,cAAcC,SAAS;AAiBtB,SAASC,mBACdC,MAAuC,EACvCC,KAA0B;IAE1B,IAAI,CAACD,QAAQ,YACXH,YAAY,CAAC,iDAAiD,EAAEI,OAAO;IAIzE,MAAMC,QAAQC,KAAK,GAAG;IACtB,MAAMC,gBAAgBJ,MAAM,CAACC,MAAM;IACnC,IAAIG,AAAkBC,WAAlBD,eAA6B,YAC/BP,YACE,CAAC,oDAAoD,EAAEI,MAAM,WAAW,EAAEG,cAAc,WAAW,EAAEF,OAAO;IAKhHF,MAAM,CAACC,MAAM,GAAGC;AAClB"}
@@ -0,0 +1,13 @@
1
+ import { descriptionOfTree, treeToList, trimAttributes, truncateText } from "@midscene/shared/extractor";
2
+ const ELEMENT_COUNT_WARNING_THRESHOLD = 5000;
3
+ const TREE_SIZE_WARNING_MESSAGE = 'The number of elements is too large, it may cause the prompt to be too long, please use domIncluded: "visible-only" to reduce the number of elements';
4
+ function tree_descriptionOfTree(tree, truncateTextLength, filterNonTextContent = false, visibleOnly = true) {
5
+ if (!visibleOnly) {
6
+ const flatElements = treeToList(tree);
7
+ if (flatElements.length >= ELEMENT_COUNT_WARNING_THRESHOLD) console.warn(TREE_SIZE_WARNING_MESSAGE);
8
+ }
9
+ return descriptionOfTree(tree, truncateTextLength, filterNonTextContent, visibleOnly);
10
+ }
11
+ export { tree_descriptionOfTree as descriptionOfTree, trimAttributes, truncateText };
12
+
13
+ //# sourceMappingURL=tree.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.mjs","sources":["../../src/tree.ts"],"sourcesContent":["import type { BaseElement, ElementTreeNode } from '@midscene/shared/types';\n\nimport {\n descriptionOfTree as sharedDescriptionOfTree,\n treeToList,\n trimAttributes,\n truncateText,\n} from '@midscene/shared/extractor';\n\nconst ELEMENT_COUNT_WARNING_THRESHOLD = 5000;\nconst TREE_SIZE_WARNING_MESSAGE =\n 'The number of elements is too large, it may cause the prompt to be too long, please use domIncluded: \"visible-only\" to reduce the number of elements';\n\nexport { trimAttributes, truncateText };\n\nexport function descriptionOfTree<\n ElementType extends BaseElement = BaseElement,\n>(\n tree: ElementTreeNode<ElementType>,\n truncateTextLength?: number,\n filterNonTextContent = false,\n visibleOnly = true,\n) {\n if (!visibleOnly) {\n const flatElements = treeToList(tree);\n if (flatElements.length >= ELEMENT_COUNT_WARNING_THRESHOLD) {\n console.warn(TREE_SIZE_WARNING_MESSAGE);\n }\n }\n\n return sharedDescriptionOfTree(\n tree,\n truncateTextLength,\n filterNonTextContent,\n visibleOnly,\n );\n}\n"],"names":["ELEMENT_COUNT_WARNING_THRESHOLD","TREE_SIZE_WARNING_MESSAGE","descriptionOfTree","tree","truncateTextLength","filterNonTextContent","visibleOnly","flatElements","treeToList","console","sharedDescriptionOfTree"],"mappings":";AASA,MAAMA,kCAAkC;AACxC,MAAMC,4BACJ;AAIK,SAASC,uBAGdC,IAAkC,EAClCC,kBAA2B,EAC3BC,uBAAuB,KAAK,EAC5BC,cAAc,IAAI;IAElB,IAAI,CAACA,aAAa;QAChB,MAAMC,eAAeC,WAAWL;QAChC,IAAII,aAAa,MAAM,IAAIP,iCACzBS,QAAQ,IAAI,CAACR;IAEjB;IAEA,OAAOS,kBACLP,MACAC,oBACAC,sBACAC;AAEJ"}
@@ -0,0 +1,199 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { restoreImageReferences } from "./dump/image-restoration.mjs";
4
+ import { ScreenshotItem } from "./screenshot-item.mjs";
5
+ export * from "./yaml.mjs";
6
+ function _define_property(obj, key, value) {
7
+ if (key in obj) Object.defineProperty(obj, key, {
8
+ value: value,
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true
12
+ });
13
+ else obj[key] = value;
14
+ return obj;
15
+ }
16
+ class UIContext {
17
+ }
18
+ class ServiceError extends Error {
19
+ constructor(message, dump){
20
+ super(message), _define_property(this, "dump", void 0);
21
+ this.name = 'ServiceError';
22
+ this.dump = dump;
23
+ }
24
+ }
25
+ function replacerForDumpSerialization(_key, value) {
26
+ if (value && value.constructor?.name === 'Page') return '[Page object]';
27
+ if (value && value.constructor?.name === 'Browser') return '[Browser object]';
28
+ if (value && 'function' == typeof value.toSerializable) return value.toSerializable();
29
+ return value;
30
+ }
31
+ function reviverForDumpDeserialization(key, value) {
32
+ if ('screenshot' !== key || 'object' != typeof value || null === value) return value;
33
+ if (ScreenshotItem.isSerialized(value)) return value;
34
+ 'base64' in value && value.base64;
35
+ return value;
36
+ }
37
+ class ExecutionDump {
38
+ serialize(indents) {
39
+ return JSON.stringify(this.toJSON(), replacerForDumpSerialization, indents);
40
+ }
41
+ toJSON() {
42
+ return {
43
+ id: this.id,
44
+ logTime: this.logTime,
45
+ name: this.name,
46
+ description: this.description,
47
+ tasks: this.tasks.map((task)=>({
48
+ ...task,
49
+ recorder: task.recorder || []
50
+ })),
51
+ aiActContext: this.aiActContext
52
+ };
53
+ }
54
+ static fromSerializedString(serialized) {
55
+ const parsed = JSON.parse(serialized, reviverForDumpDeserialization);
56
+ return new ExecutionDump(parsed);
57
+ }
58
+ static fromJSON(data) {
59
+ return new ExecutionDump(data);
60
+ }
61
+ collectScreenshots() {
62
+ const screenshots = [];
63
+ for (const task of this.tasks){
64
+ if (task.uiContext?.screenshot instanceof ScreenshotItem) screenshots.push(task.uiContext.screenshot);
65
+ if (task.recorder) {
66
+ for (const record of task.recorder)if (record.screenshot instanceof ScreenshotItem) screenshots.push(record.screenshot);
67
+ }
68
+ }
69
+ return screenshots;
70
+ }
71
+ constructor(data){
72
+ _define_property(this, "id", void 0);
73
+ _define_property(this, "logTime", void 0);
74
+ _define_property(this, "name", void 0);
75
+ _define_property(this, "description", void 0);
76
+ _define_property(this, "tasks", void 0);
77
+ _define_property(this, "aiActContext", void 0);
78
+ this.id = data.id;
79
+ this.logTime = data.logTime;
80
+ this.name = data.name;
81
+ this.description = data.description;
82
+ this.tasks = data.tasks;
83
+ this.aiActContext = data.aiActContext;
84
+ }
85
+ }
86
+ class GroupedActionDump {
87
+ serialize(indents) {
88
+ return JSON.stringify(this.toJSON(), replacerForDumpSerialization, indents);
89
+ }
90
+ serializeWithInlineScreenshots(indents) {
91
+ const processValue = (obj)=>{
92
+ if (obj instanceof ScreenshotItem) return {
93
+ base64: obj.base64,
94
+ capturedAt: obj.capturedAt
95
+ };
96
+ if (Array.isArray(obj)) return obj.map(processValue);
97
+ if (obj && 'object' == typeof obj) {
98
+ const entries = Object.entries(obj).map(([key, value])=>[
99
+ key,
100
+ processValue(value)
101
+ ]);
102
+ return Object.fromEntries(entries);
103
+ }
104
+ return obj;
105
+ };
106
+ const data = processValue(this.toJSON());
107
+ return JSON.stringify(data, null, indents);
108
+ }
109
+ toJSON() {
110
+ return {
111
+ sdkVersion: this.sdkVersion,
112
+ groupName: this.groupName,
113
+ groupDescription: this.groupDescription,
114
+ modelBriefs: this.modelBriefs,
115
+ executions: this.executions.map((exec)=>exec.toJSON()),
116
+ deviceType: this.deviceType
117
+ };
118
+ }
119
+ static fromSerializedString(serialized) {
120
+ const parsed = JSON.parse(serialized, reviverForDumpDeserialization);
121
+ return new GroupedActionDump(parsed);
122
+ }
123
+ static fromJSON(data) {
124
+ return new GroupedActionDump(data);
125
+ }
126
+ collectAllScreenshots() {
127
+ const screenshots = [];
128
+ for (const execution of this.executions)screenshots.push(...execution.collectScreenshots());
129
+ return screenshots;
130
+ }
131
+ serializeToFiles(basePath) {
132
+ const screenshotsDir = `${basePath}.screenshots`;
133
+ if (!existsSync(screenshotsDir)) mkdirSync(screenshotsDir, {
134
+ recursive: true
135
+ });
136
+ const screenshotMap = {};
137
+ const screenshots = this.collectAllScreenshots();
138
+ for (const screenshot of screenshots)if (screenshot.hasBase64()) {
139
+ const imagePath = join(screenshotsDir, `${screenshot.id}.${screenshot.extension}`);
140
+ const rawBase64 = screenshot.rawBase64;
141
+ writeFileSync(imagePath, Buffer.from(rawBase64, 'base64'));
142
+ screenshotMap[screenshot.id] = imagePath;
143
+ }
144
+ writeFileSync(`${basePath}.screenshots.json`, JSON.stringify(screenshotMap), 'utf-8');
145
+ writeFileSync(basePath, this.serialize(), 'utf-8');
146
+ }
147
+ static fromFilesAsInlineJson(basePath) {
148
+ const dumpString = readFileSync(basePath, 'utf-8');
149
+ const screenshotsMapPath = `${basePath}.screenshots.json`;
150
+ if (!existsSync(screenshotsMapPath)) return dumpString;
151
+ const screenshotMap = JSON.parse(readFileSync(screenshotsMapPath, 'utf-8'));
152
+ const imageMap = {};
153
+ for (const [id, filePath] of Object.entries(screenshotMap))if (existsSync(filePath)) {
154
+ const data = readFileSync(filePath);
155
+ const mime = filePath.endsWith('.jpeg') || filePath.endsWith('.jpg') ? 'jpeg' : 'png';
156
+ imageMap[id] = `data:image/${mime};base64,${data.toString('base64')}`;
157
+ }
158
+ const dumpData = JSON.parse(dumpString);
159
+ const processedData = restoreImageReferences(dumpData, (id)=>imageMap[id] ?? '');
160
+ return JSON.stringify(processedData);
161
+ }
162
+ static cleanupFiles(basePath) {
163
+ const filesToClean = [
164
+ basePath,
165
+ `${basePath}.screenshots.json`,
166
+ `${basePath}.screenshots`
167
+ ];
168
+ for (const filePath of filesToClean)try {
169
+ rmSync(filePath, {
170
+ force: true,
171
+ recursive: true
172
+ });
173
+ } catch {}
174
+ }
175
+ static getFilePaths(basePath) {
176
+ return [
177
+ basePath,
178
+ `${basePath}.screenshots.json`,
179
+ `${basePath}.screenshots`
180
+ ];
181
+ }
182
+ constructor(data){
183
+ _define_property(this, "sdkVersion", void 0);
184
+ _define_property(this, "groupName", void 0);
185
+ _define_property(this, "groupDescription", void 0);
186
+ _define_property(this, "modelBriefs", void 0);
187
+ _define_property(this, "executions", void 0);
188
+ _define_property(this, "deviceType", void 0);
189
+ this.sdkVersion = data.sdkVersion;
190
+ this.groupName = data.groupName;
191
+ this.groupDescription = data.groupDescription;
192
+ this.modelBriefs = data.modelBriefs;
193
+ this.executions = data.executions.map((exec)=>exec instanceof ExecutionDump ? exec : ExecutionDump.fromJSON(exec));
194
+ this.deviceType = data.deviceType;
195
+ }
196
+ }
197
+ export { ExecutionDump, GroupedActionDump, ServiceError, UIContext };
198
+
199
+ //# sourceMappingURL=types.mjs.map