@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,195 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) Object.defineProperty(obj, key, {
3
+ value: value,
4
+ enumerable: true,
5
+ configurable: true,
6
+ writable: true
7
+ });
8
+ else obj[key] = value;
9
+ return obj;
10
+ }
11
+ var _computedKey;
12
+ _computedKey = Symbol.iterator;
13
+ let _computedKey1 = _computedKey;
14
+ class ConversationHistory {
15
+ resetPendingFeedbackMessageIfExists() {
16
+ if (this.pendingFeedbackMessage) this.pendingFeedbackMessage = '';
17
+ }
18
+ append(message) {
19
+ this.messages.push(message);
20
+ }
21
+ seed(messages) {
22
+ this.reset();
23
+ messages.forEach((message)=>{
24
+ this.append(message);
25
+ });
26
+ }
27
+ reset() {
28
+ this.messages.length = 0;
29
+ this.memories.length = 0;
30
+ this.subGoals.length = 0;
31
+ this.historicalLogs.length = 0;
32
+ this.pendingFeedbackMessage = '';
33
+ }
34
+ snapshot(maxImages) {
35
+ if (void 0 === maxImages) return [
36
+ ...this.messages
37
+ ];
38
+ const clonedMessages = structuredClone(this.messages);
39
+ let imageCount = 0;
40
+ for(let i = clonedMessages.length - 1; i >= 0; i--){
41
+ const message = clonedMessages[i];
42
+ const content = message.content;
43
+ if (Array.isArray(content)) for(let j = 0; j < content.length; j++){
44
+ const item = content[j];
45
+ if ('image_url' === item.type) {
46
+ imageCount++;
47
+ if (imageCount > maxImages) content[j] = {
48
+ type: 'text',
49
+ text: '(image ignored due to size optimization)'
50
+ };
51
+ }
52
+ }
53
+ }
54
+ return clonedMessages;
55
+ }
56
+ get length() {
57
+ return this.messages.length;
58
+ }
59
+ [_computedKey1]() {
60
+ return this.messages[Symbol.iterator]();
61
+ }
62
+ toJSON() {
63
+ return this.snapshot();
64
+ }
65
+ setSubGoals(subGoals) {
66
+ this.subGoals = subGoals.map((goal)=>({
67
+ ...goal
68
+ }));
69
+ this.markFirstPendingAsRunning();
70
+ }
71
+ mergeSubGoals(subGoals) {
72
+ if (0 === this.subGoals.length) return void this.setSubGoals(subGoals);
73
+ const existingByIndex = new Map(this.subGoals.map((goal)=>[
74
+ goal.index,
75
+ goal
76
+ ]));
77
+ const mergedSubGoals = subGoals.map((goal)=>{
78
+ const existingGoal = existingByIndex.get(goal.index);
79
+ const hasNonEmptyDescription = goal.description.trim().length > 0;
80
+ if (!existingGoal && !hasNonEmptyDescription) return null;
81
+ return {
82
+ ...goal,
83
+ description: hasNonEmptyDescription || !existingGoal ? goal.description : existingGoal.description
84
+ };
85
+ });
86
+ const validSubGoals = mergedSubGoals.filter((goal)=>null !== goal);
87
+ if (0 === validSubGoals.length) return;
88
+ this.setSubGoals(validSubGoals);
89
+ }
90
+ updateSubGoal(index, updates) {
91
+ const goal = this.subGoals.find((g)=>g.index === index);
92
+ if (!goal) return false;
93
+ let changed = false;
94
+ if (void 0 !== updates.status && updates.status !== goal.status) {
95
+ goal.status = updates.status;
96
+ changed = true;
97
+ }
98
+ if (void 0 !== updates.description && updates.description !== goal.description) {
99
+ goal.description = updates.description;
100
+ changed = true;
101
+ }
102
+ if (changed) goal.logs = [];
103
+ return true;
104
+ }
105
+ markFirstPendingAsRunning() {
106
+ const firstPending = this.subGoals.find((g)=>'pending' === g.status);
107
+ if (firstPending) {
108
+ firstPending.status = 'running';
109
+ firstPending.logs = [];
110
+ }
111
+ }
112
+ markSubGoalFinished(index) {
113
+ const result = this.updateSubGoal(index, {
114
+ status: 'finished'
115
+ });
116
+ if (result) this.markFirstPendingAsRunning();
117
+ return result;
118
+ }
119
+ markAllSubGoalsFinished() {
120
+ for (const goal of this.subGoals){
121
+ if ('finished' !== goal.status) goal.logs = [];
122
+ goal.status = 'finished';
123
+ }
124
+ }
125
+ appendSubGoalLog(log) {
126
+ if (!log) return;
127
+ const runningGoal = this.subGoals.find((g)=>'running' === g.status);
128
+ if (runningGoal) {
129
+ if (!runningGoal.logs) runningGoal.logs = [];
130
+ runningGoal.logs.push(log);
131
+ }
132
+ }
133
+ subGoalsToText() {
134
+ if (0 === this.subGoals.length) return '';
135
+ const lines = this.subGoals.map((goal)=>`${goal.index}. ${goal.description} (${goal.status})`);
136
+ const currentGoal = this.subGoals.find((goal)=>'running' === goal.status) || this.subGoals.find((goal)=>'pending' === goal.status);
137
+ let currentGoalText = '';
138
+ if (currentGoal) {
139
+ currentGoalText = `\nCurrent sub-goal is: ${currentGoal.description}`;
140
+ if (currentGoal.logs && currentGoal.logs.length > 0) {
141
+ const logLines = currentGoal.logs.map((log)=>`- ${log}`).join('\n');
142
+ currentGoalText += `\nActions performed for current sub-goal:\n${logLines}`;
143
+ }
144
+ }
145
+ return `Sub-goals:\n${lines.join('\n')}${currentGoalText}`;
146
+ }
147
+ appendHistoricalLog(log) {
148
+ if (log) this.historicalLogs.push(log);
149
+ }
150
+ historicalLogsToText() {
151
+ if (0 === this.historicalLogs.length) return '';
152
+ const logLines = this.historicalLogs.map((log)=>`- ${log}`).join('\n');
153
+ return `Here are the steps that have been executed:\n${logLines}`;
154
+ }
155
+ appendMemory(memory) {
156
+ if (memory) this.memories.push(memory);
157
+ }
158
+ getMemories() {
159
+ return [
160
+ ...this.memories
161
+ ];
162
+ }
163
+ memoriesToText() {
164
+ if (0 === this.memories.length) return '';
165
+ return `Memories from previous steps:\n---\n${this.memories.join('\n---\n')}\n`;
166
+ }
167
+ clearMemories() {
168
+ this.memories.length = 0;
169
+ }
170
+ compressHistory(threshold, keepCount) {
171
+ if (this.messages.length <= threshold) return false;
172
+ const omittedCount = this.messages.length - keepCount;
173
+ const omittedPlaceholder = {
174
+ role: 'user',
175
+ content: `(${omittedCount} previous conversation messages have been omitted)`
176
+ };
177
+ const recentMessages = this.messages.slice(-keepCount);
178
+ this.messages.length = 0;
179
+ this.messages.push(omittedPlaceholder);
180
+ for (const msg of recentMessages)this.messages.push(msg);
181
+ return true;
182
+ }
183
+ constructor(options){
184
+ _define_property(this, "messages", []);
185
+ _define_property(this, "subGoals", []);
186
+ _define_property(this, "memories", []);
187
+ _define_property(this, "historicalLogs", []);
188
+ _define_property(this, "pendingFeedbackMessage", void 0);
189
+ if (options?.initialMessages?.length) this.seed(options.initialMessages);
190
+ this.pendingFeedbackMessage = '';
191
+ }
192
+ }
193
+ export { ConversationHistory };
194
+
195
+ //# sourceMappingURL=conversation-history.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-model/conversation-history.mjs","sources":["../../../src/ai-model/conversation-history.ts"],"sourcesContent":["import type { SubGoal } from '@/types';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\n\nexport interface ConversationHistoryOptions {\n initialMessages?: ChatCompletionMessageParam[];\n}\n\nexport class ConversationHistory {\n private readonly messages: ChatCompletionMessageParam[] = [];\n private subGoals: SubGoal[] = [];\n private memories: string[] = [];\n private historicalLogs: string[] = [];\n\n public pendingFeedbackMessage: string;\n\n constructor(options?: ConversationHistoryOptions) {\n if (options?.initialMessages?.length) {\n this.seed(options.initialMessages);\n }\n this.pendingFeedbackMessage = '';\n }\n\n resetPendingFeedbackMessageIfExists() {\n if (this.pendingFeedbackMessage) {\n this.pendingFeedbackMessage = '';\n }\n }\n\n append(message: ChatCompletionMessageParam) {\n this.messages.push(message);\n }\n\n seed(messages: ChatCompletionMessageParam[]) {\n this.reset();\n messages.forEach((message) => {\n this.append(message);\n });\n }\n\n reset() {\n this.messages.length = 0;\n this.memories.length = 0;\n this.subGoals.length = 0;\n this.historicalLogs.length = 0;\n this.pendingFeedbackMessage = '';\n }\n\n /**\n * Snapshot the conversation history, and replace the images with text if the number of images exceeds the limit.\n * @param maxImages - The maximum number of images to include in the snapshot. Undefined means no limit.\n * @returns The snapshot of the conversation history.\n */\n snapshot(maxImages?: number): ChatCompletionMessageParam[] {\n if (maxImages === undefined) {\n return [...this.messages];\n }\n\n const clonedMessages = structuredClone(this.messages);\n let imageCount = 0;\n\n // Traverse from the end to the beginning\n for (let i = clonedMessages.length - 1; i >= 0; i--) {\n const message = clonedMessages[i];\n const content = message.content;\n\n // Only process if content is an array\n if (Array.isArray(content)) {\n for (let j = 0; j < content.length; j++) {\n const item = content[j];\n\n // Check if this is an image\n if (item.type === 'image_url') {\n imageCount++;\n\n // If we've exceeded the limit, replace with text\n if (imageCount > maxImages) {\n content[j] = {\n type: 'text',\n text: '(image ignored due to size optimization)',\n };\n }\n }\n }\n }\n }\n\n return clonedMessages;\n }\n\n get length(): number {\n return this.messages.length;\n }\n\n [Symbol.iterator](): IterableIterator<ChatCompletionMessageParam> {\n return this.messages[Symbol.iterator]();\n }\n\n toJSON(): ChatCompletionMessageParam[] {\n return this.snapshot();\n }\n\n // Sub-goal management methods\n\n /**\n * Set all sub-goals, replacing any existing ones.\n * Automatically marks the first pending goal as running.\n */\n setSubGoals(subGoals: SubGoal[]): void {\n this.subGoals = subGoals.map((goal) => ({ ...goal }));\n this.markFirstPendingAsRunning();\n }\n\n /**\n * Merge sub-goals from update-plan-content.\n * Preserves existing descriptions when incoming description is empty.\n *\n * This handles compact XML updates like:\n * <sub-goal index=\"1\" status=\"finished\" />\n */\n mergeSubGoals(subGoals: SubGoal[]): void {\n if (this.subGoals.length === 0) {\n this.setSubGoals(subGoals);\n return;\n }\n\n const existingByIndex = new Map(\n this.subGoals.map((goal) => [goal.index, goal] as const),\n );\n\n const mergedSubGoals = subGoals.map((goal) => {\n const existingGoal = existingByIndex.get(goal.index);\n const hasNonEmptyDescription = goal.description.trim().length > 0;\n\n if (!existingGoal && !hasNonEmptyDescription) {\n return null;\n }\n\n return {\n ...goal,\n description:\n hasNonEmptyDescription || !existingGoal\n ? goal.description\n : existingGoal.description,\n };\n });\n\n const validSubGoals = mergedSubGoals.filter((goal) => goal !== null);\n if (validSubGoals.length === 0) {\n return;\n }\n\n this.setSubGoals(validSubGoals);\n }\n\n /**\n * Update a single sub-goal by index.\n * Clears logs if status or description actually changes.\n * @returns true if the sub-goal was found and updated, false otherwise\n */\n updateSubGoal(\n index: number,\n updates: Partial<Omit<SubGoal, 'index'>>,\n ): boolean {\n const goal = this.subGoals.find((g) => g.index === index);\n if (!goal) {\n return false;\n }\n\n let changed = false;\n\n if (updates.status !== undefined && updates.status !== goal.status) {\n goal.status = updates.status;\n changed = true;\n }\n if (\n updates.description !== undefined &&\n updates.description !== goal.description\n ) {\n goal.description = updates.description;\n changed = true;\n }\n\n if (changed) {\n goal.logs = [];\n }\n\n return true;\n }\n\n /**\n * Mark the first pending sub-goal as running.\n * Clears logs since status changes.\n */\n markFirstPendingAsRunning(): void {\n const firstPending = this.subGoals.find((g) => g.status === 'pending');\n if (firstPending) {\n firstPending.status = 'running';\n firstPending.logs = [];\n }\n }\n\n /**\n * Mark a sub-goal as finished.\n * Automatically marks the next pending goal as running.\n * @returns true if the sub-goal was found and updated, false otherwise\n */\n markSubGoalFinished(index: number): boolean {\n const result = this.updateSubGoal(index, { status: 'finished' });\n if (result) {\n this.markFirstPendingAsRunning();\n }\n return result;\n }\n\n /**\n * Mark all sub-goals as finished.\n * Clears logs for any goal whose status actually changes.\n */\n markAllSubGoalsFinished(): void {\n for (const goal of this.subGoals) {\n if (goal.status !== 'finished') {\n goal.logs = [];\n }\n goal.status = 'finished';\n }\n }\n\n /**\n * Append a log entry to the currently running sub-goal.\n * The log describes an action performed while working on the sub-goal.\n */\n appendSubGoalLog(log: string): void {\n if (!log) {\n return;\n }\n const runningGoal = this.subGoals.find((g) => g.status === 'running');\n if (runningGoal) {\n if (!runningGoal.logs) {\n runningGoal.logs = [];\n }\n runningGoal.logs.push(log);\n }\n }\n\n /**\n * Convert sub-goals to text representation.\n * Includes actions performed (logs) for the current sub-goal.\n */\n subGoalsToText(): string {\n if (this.subGoals.length === 0) {\n return '';\n }\n\n const lines = this.subGoals.map((goal) => {\n return `${goal.index}. ${goal.description} (${goal.status})`;\n });\n\n // Running goal takes priority, otherwise show first pending\n const currentGoal =\n this.subGoals.find((goal) => goal.status === 'running') ||\n this.subGoals.find((goal) => goal.status === 'pending');\n\n let currentGoalText = '';\n if (currentGoal) {\n currentGoalText = `\\nCurrent sub-goal is: ${currentGoal.description}`;\n if (currentGoal.logs && currentGoal.logs.length > 0) {\n const logLines = currentGoal.logs.map((log) => `- ${log}`).join('\\n');\n currentGoalText += `\\nActions performed for current sub-goal:\\n${logLines}`;\n }\n }\n\n return `Sub-goals:\\n${lines.join('\\n')}${currentGoalText}`;\n }\n\n // Historical log management methods (used in non-deepThink mode)\n\n /**\n * Append a log entry to the historical logs list.\n * Used in non-deepThink mode to track executed steps across planning rounds.\n */\n appendHistoricalLog(log: string): void {\n if (log) {\n this.historicalLogs.push(log);\n }\n }\n\n /**\n * Convert historical logs to text representation.\n * Provides context about previously executed steps to the model.\n */\n historicalLogsToText(): string {\n if (this.historicalLogs.length === 0) {\n return '';\n }\n\n const logLines = this.historicalLogs.map((log) => `- ${log}`).join('\\n');\n return `Here are the steps that have been executed:\\n${logLines}`;\n }\n\n // Memory management methods\n\n /**\n * Append a memory to the memories list\n */\n appendMemory(memory: string): void {\n if (memory) {\n this.memories.push(memory);\n }\n }\n\n /**\n * Get all memories\n */\n getMemories(): string[] {\n return [...this.memories];\n }\n\n /**\n * Convert memories to text representation\n */\n memoriesToText(): string {\n if (this.memories.length === 0) {\n return '';\n }\n\n return `Memories from previous steps:\\n---\\n${this.memories.join('\\n---\\n')}\\n`;\n }\n\n /**\n * Clear all memories\n */\n clearMemories(): void {\n this.memories.length = 0;\n }\n\n /**\n * Compress the conversation history if it exceeds the threshold.\n * Removes the oldest messages and replaces them with a single placeholder message.\n * @param threshold - The number of messages that triggers compression.\n * @param keepCount - The number of recent messages to keep after compression.\n * @returns true if compression was performed, false otherwise.\n */\n compressHistory(threshold: number, keepCount: number): boolean {\n if (this.messages.length <= threshold) {\n return false;\n }\n\n const omittedCount = this.messages.length - keepCount;\n const omittedPlaceholder: ChatCompletionMessageParam = {\n role: 'user',\n content: `(${omittedCount} previous conversation messages have been omitted)`,\n };\n\n // Keep only the last `keepCount` messages\n const recentMessages = this.messages.slice(-keepCount);\n\n // Reset and rebuild with placeholder + recent messages\n this.messages.length = 0;\n this.messages.push(omittedPlaceholder);\n for (const msg of recentMessages) {\n this.messages.push(msg);\n }\n\n return true;\n }\n}\n"],"names":["Symbol","ConversationHistory","message","messages","maxImages","undefined","clonedMessages","structuredClone","imageCount","i","content","Array","j","item","subGoals","goal","existingByIndex","Map","mergedSubGoals","existingGoal","hasNonEmptyDescription","validSubGoals","index","updates","g","changed","firstPending","result","log","runningGoal","lines","currentGoal","currentGoalText","logLines","memory","threshold","keepCount","omittedCount","omittedPlaceholder","recentMessages","msg","options"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { AIResponseParseError, callAI, callAIWithObjectResponse, callAIWithStringResponse } from "./service-caller/index.mjs";
2
+ import { systemPromptToLocateElement } from "./prompt/llm-locator.mjs";
3
+ import { generatePlaywrightTest, generatePlaywrightTestStream } from "./prompt/playwright-generator.mjs";
4
+ import { generateYamlTest, generateYamlTestStream } from "./prompt/yaml-generator.mjs";
5
+ import { AiExtractElementInfo, AiJudgeOrderSensitive, AiLocateElement, AiLocateSection } from "./inspect.mjs";
6
+ import { plan } from "./llm-planning.mjs";
7
+ import { autoGLMPlanning } from "./auto-glm/planning.mjs";
8
+ import { PointSchema, RectSchema, SizeSchema, TMultimodalPromptSchema, TUserPromptSchema, adaptBboxToRect, dumpActionParam, findAllMidsceneLocatorField, getMidsceneLocationSchema, parseActionParam } from "../common.mjs";
9
+ import { uiTarsPlanning } from "./ui-tars-planning.mjs";
10
+ import { ConversationHistory } from "./conversation-history.mjs";
11
+ export { AIResponseParseError, AiExtractElementInfo, AiJudgeOrderSensitive, AiLocateElement, AiLocateSection, ConversationHistory, PointSchema, RectSchema, SizeSchema, TMultimodalPromptSchema, TUserPromptSchema, adaptBboxToRect, autoGLMPlanning, callAI, callAIWithObjectResponse, callAIWithStringResponse, dumpActionParam, findAllMidsceneLocatorField, generatePlaywrightTest, generatePlaywrightTestStream, generateYamlTest, generateYamlTestStream, getMidsceneLocationSchema, parseActionParam, plan, systemPromptToLocateElement, uiTarsPlanning };
@@ -0,0 +1,394 @@
1
+ import { generateElementByPoint, generateElementByRect } from "@midscene/shared/extractor/dom-util";
2
+ import { cropByRect, paddingToMatchBlockByBase64, preProcessImageUrl, scaleImage } from "@midscene/shared/img";
3
+ import { getDebug } from "@midscene/shared/logger";
4
+ import { assert } from "@midscene/shared/utils";
5
+ import { adaptBboxToRect, expandSearchArea, mergeRects } from "../common.mjs";
6
+ import { parseAutoGLMLocateResponse } from "./auto-glm/parser.mjs";
7
+ import { getAutoGLMLocatePrompt } from "./auto-glm/prompt.mjs";
8
+ import { isAutoGLM } from "./auto-glm/util.mjs";
9
+ import { extractDataQueryPrompt, parseXMLExtractionResponse, systemPromptToExtract } from "./prompt/extraction.mjs";
10
+ import { findElementPrompt, systemPromptToLocateElement } from "./prompt/llm-locator.mjs";
11
+ import { sectionLocatorInstruction, systemPromptToLocateSection } from "./prompt/llm-section-locator.mjs";
12
+ import { orderSensitiveJudgePrompt, systemPromptToJudgeOrderSensitive } from "./prompt/order-sensitive-judge.mjs";
13
+ import { AIResponseParseError, callAI, callAIWithObjectResponse, callAIWithStringResponse } from "./service-caller/index.mjs";
14
+ const debugInspect = getDebug('ai:inspect');
15
+ const debugSection = getDebug('ai:section');
16
+ async function buildSearchAreaConfig(options) {
17
+ const { context, baseRect, modelFamily } = options;
18
+ const scaleRatio = 2;
19
+ const sectionRect = expandSearchArea(baseRect, context.shotSize);
20
+ const croppedResult = await cropByRect(context.screenshot.base64, sectionRect, 'qwen2.5-vl' === modelFamily);
21
+ const scaledResult = await scaleImage(croppedResult.imageBase64, scaleRatio);
22
+ sectionRect.width = scaledResult.width;
23
+ sectionRect.height = scaledResult.height;
24
+ return {
25
+ rect: sectionRect,
26
+ imageBase64: scaledResult.imageBase64,
27
+ scale: scaleRatio
28
+ };
29
+ }
30
+ const extraTextFromUserPrompt = (prompt)=>{
31
+ if ('string' == typeof prompt) return prompt;
32
+ return prompt.prompt;
33
+ };
34
+ const promptsToChatParam = async (multimodalPrompt)=>{
35
+ const msgs = [];
36
+ if (multimodalPrompt?.images?.length) {
37
+ msgs.push({
38
+ role: 'user',
39
+ content: [
40
+ {
41
+ type: 'text',
42
+ text: 'Next, I will provide all the reference images.'
43
+ }
44
+ ]
45
+ });
46
+ for (const item of multimodalPrompt.images){
47
+ const base64 = await preProcessImageUrl(item.url, !!multimodalPrompt.convertHttpImage2Base64);
48
+ msgs.push({
49
+ role: 'user',
50
+ content: [
51
+ {
52
+ type: 'text',
53
+ text: `this is the reference image named '${item.name}':`
54
+ }
55
+ ]
56
+ });
57
+ msgs.push({
58
+ role: 'user',
59
+ content: [
60
+ {
61
+ type: 'image_url',
62
+ image_url: {
63
+ url: base64,
64
+ detail: 'high'
65
+ }
66
+ }
67
+ ]
68
+ });
69
+ }
70
+ }
71
+ return msgs;
72
+ };
73
+ async function AiLocateElement(options) {
74
+ const { context, targetElementDescription, modelConfig } = options;
75
+ const { modelFamily } = modelConfig;
76
+ const screenshotBase64 = context.screenshot.base64;
77
+ assert(targetElementDescription, "cannot find the target element description");
78
+ const targetElementDescriptionText = extraTextFromUserPrompt(targetElementDescription);
79
+ const userInstructionPrompt = findElementPrompt(targetElementDescriptionText);
80
+ const systemPrompt = isAutoGLM(modelFamily) ? getAutoGLMLocatePrompt(modelFamily) : systemPromptToLocateElement(modelFamily);
81
+ let imagePayload = screenshotBase64;
82
+ let imageWidth = context.shotSize.width;
83
+ let imageHeight = context.shotSize.height;
84
+ let originalImageWidth = imageWidth;
85
+ let originalImageHeight = imageHeight;
86
+ if (options.searchConfig) {
87
+ assert(options.searchConfig.rect, 'searchArea is provided but its rect cannot be found. Failed to locate element');
88
+ assert(options.searchConfig.imageBase64, 'searchArea is provided but its imageBase64 cannot be found. Failed to locate element');
89
+ imagePayload = options.searchConfig.imageBase64;
90
+ imageWidth = options.searchConfig.rect?.width;
91
+ imageHeight = options.searchConfig.rect?.height;
92
+ originalImageWidth = imageWidth;
93
+ originalImageHeight = imageHeight;
94
+ } else if ('qwen2.5-vl' === modelFamily) {
95
+ const paddedResult = await paddingToMatchBlockByBase64(imagePayload);
96
+ imageWidth = paddedResult.width;
97
+ imageHeight = paddedResult.height;
98
+ imagePayload = paddedResult.imageBase64;
99
+ }
100
+ const msgs = [
101
+ {
102
+ role: 'system',
103
+ content: systemPrompt
104
+ },
105
+ {
106
+ role: 'user',
107
+ content: [
108
+ {
109
+ type: 'image_url',
110
+ image_url: {
111
+ url: imagePayload,
112
+ detail: 'high'
113
+ }
114
+ },
115
+ {
116
+ type: 'text',
117
+ text: isAutoGLM(modelFamily) ? `Tap: ${userInstructionPrompt}` : userInstructionPrompt
118
+ }
119
+ ]
120
+ }
121
+ ];
122
+ if ('string' != typeof targetElementDescription) {
123
+ const addOns = await promptsToChatParam({
124
+ images: targetElementDescription.images,
125
+ convertHttpImage2Base64: targetElementDescription.convertHttpImage2Base64
126
+ });
127
+ msgs.push(...addOns);
128
+ }
129
+ if (isAutoGLM(modelFamily)) {
130
+ const { content: rawResponseContent, usage } = await callAIWithStringResponse(msgs, modelConfig, {
131
+ abortSignal: options.abortSignal
132
+ });
133
+ debugInspect('auto-glm rawResponse:', rawResponseContent);
134
+ const parsed = parseAutoGLMLocateResponse(rawResponseContent);
135
+ debugInspect('auto-glm thinking:', parsed.think);
136
+ debugInspect('auto-glm coordinates:', parsed.coordinates);
137
+ let resRect;
138
+ let matchedElements = [];
139
+ let errors = [];
140
+ if (parsed.error || !parsed.coordinates) {
141
+ errors = [
142
+ parsed.error || 'Failed to parse auto-glm response'
143
+ ];
144
+ debugInspect('auto-glm parse error:', errors[0]);
145
+ } else {
146
+ const { x, y } = parsed.coordinates;
147
+ debugInspect('auto-glm coordinates [0-999]:', {
148
+ x,
149
+ y
150
+ });
151
+ const pixelX = Math.round(x * imageWidth / 1000);
152
+ const pixelY = Math.round(y * imageHeight / 1000);
153
+ debugInspect('auto-glm pixel coordinates:', {
154
+ pixelX,
155
+ pixelY
156
+ });
157
+ let finalX = pixelX;
158
+ let finalY = pixelY;
159
+ if (options.searchConfig?.rect) {
160
+ finalX += options.searchConfig.rect.left;
161
+ finalY += options.searchConfig.rect.top;
162
+ }
163
+ const element = generateElementByPoint([
164
+ finalX,
165
+ finalY
166
+ ], targetElementDescriptionText);
167
+ resRect = element.rect;
168
+ debugInspect('auto-glm resRect:', resRect);
169
+ if (element) matchedElements = [
170
+ element
171
+ ];
172
+ }
173
+ return {
174
+ rect: resRect,
175
+ parseResult: {
176
+ elements: matchedElements,
177
+ errors
178
+ },
179
+ rawResponse: rawResponseContent,
180
+ usage,
181
+ reasoning_content: parsed.think
182
+ };
183
+ }
184
+ let res;
185
+ try {
186
+ res = await callAIWithObjectResponse(msgs, modelConfig, {
187
+ abortSignal: options.abortSignal
188
+ });
189
+ } catch (callError) {
190
+ const errorMessage = callError instanceof Error ? callError.message : String(callError);
191
+ const rawResponse = callError instanceof AIResponseParseError ? callError.rawResponse : errorMessage;
192
+ const usage = callError instanceof AIResponseParseError ? callError.usage : void 0;
193
+ return {
194
+ rect: void 0,
195
+ parseResult: {
196
+ elements: [],
197
+ errors: [
198
+ `AI call error: ${errorMessage}`
199
+ ]
200
+ },
201
+ rawResponse,
202
+ usage,
203
+ reasoning_content: void 0
204
+ };
205
+ }
206
+ const rawResponse = JSON.stringify(res.content);
207
+ let resRect;
208
+ let matchedElements = [];
209
+ let errors = 'errors' in res.content ? res.content.errors : [];
210
+ try {
211
+ if ('bbox' in res.content && Array.isArray(res.content.bbox) && res.content.bbox.length >= 1) {
212
+ resRect = adaptBboxToRect(res.content.bbox, imageWidth, imageHeight, options.searchConfig?.rect?.left, options.searchConfig?.rect?.top, originalImageWidth, originalImageHeight, modelFamily, options.searchConfig?.scale);
213
+ debugInspect('resRect', resRect);
214
+ const element = generateElementByRect(resRect, targetElementDescriptionText);
215
+ errors = [];
216
+ if (element) matchedElements = [
217
+ element
218
+ ];
219
+ }
220
+ } catch (e) {
221
+ const msg = e instanceof Error ? `Failed to parse bbox: ${e.message}` : 'unknown error in locate';
222
+ if (errors && errors?.length !== 0) errors.push(`(${msg})`);
223
+ else errors = [
224
+ msg
225
+ ];
226
+ }
227
+ return {
228
+ rect: resRect,
229
+ parseResult: {
230
+ elements: matchedElements,
231
+ errors: errors
232
+ },
233
+ rawResponse,
234
+ usage: res.usage,
235
+ reasoning_content: res.reasoning_content
236
+ };
237
+ }
238
+ async function AiLocateSection(options) {
239
+ const { context, sectionDescription, modelConfig } = options;
240
+ const { modelFamily } = modelConfig;
241
+ const screenshotBase64 = context.screenshot.base64;
242
+ const systemPrompt = systemPromptToLocateSection(modelFamily);
243
+ const sectionLocatorInstructionText = sectionLocatorInstruction(extraTextFromUserPrompt(sectionDescription));
244
+ const msgs = [
245
+ {
246
+ role: 'system',
247
+ content: systemPrompt
248
+ },
249
+ {
250
+ role: 'user',
251
+ content: [
252
+ {
253
+ type: 'image_url',
254
+ image_url: {
255
+ url: screenshotBase64,
256
+ detail: 'high'
257
+ }
258
+ },
259
+ {
260
+ type: 'text',
261
+ text: sectionLocatorInstructionText
262
+ }
263
+ ]
264
+ }
265
+ ];
266
+ if ('string' != typeof sectionDescription) {
267
+ const addOns = await promptsToChatParam({
268
+ images: sectionDescription.images,
269
+ convertHttpImage2Base64: sectionDescription.convertHttpImage2Base64
270
+ });
271
+ msgs.push(...addOns);
272
+ }
273
+ let result;
274
+ try {
275
+ result = await callAIWithObjectResponse(msgs, modelConfig, {
276
+ abortSignal: options.abortSignal
277
+ });
278
+ } catch (callError) {
279
+ const errorMessage = callError instanceof Error ? callError.message : String(callError);
280
+ const rawResponse = callError instanceof AIResponseParseError ? callError.rawResponse : errorMessage;
281
+ const usage = callError instanceof AIResponseParseError ? callError.usage : void 0;
282
+ return {
283
+ rect: void 0,
284
+ imageBase64: void 0,
285
+ error: `AI call error: ${errorMessage}`,
286
+ rawResponse,
287
+ usage
288
+ };
289
+ }
290
+ let searchAreaConfig;
291
+ const sectionBbox = result.content.bbox;
292
+ if (sectionBbox) {
293
+ const targetRect = adaptBboxToRect(sectionBbox, context.shotSize.width, context.shotSize.height, 0, 0, context.shotSize.width, context.shotSize.height, modelFamily);
294
+ debugSection('original targetRect %j', targetRect);
295
+ const referenceBboxList = result.content.references_bbox || [];
296
+ debugSection('referenceBboxList %j', referenceBboxList);
297
+ const referenceRects = referenceBboxList.filter((bbox)=>Array.isArray(bbox)).map((bbox)=>adaptBboxToRect(bbox, context.shotSize.width, context.shotSize.height, 0, 0, context.shotSize.width, context.shotSize.height, modelFamily));
298
+ debugSection('referenceRects %j', referenceRects);
299
+ const mergedRect = mergeRects([
300
+ targetRect,
301
+ ...referenceRects
302
+ ]);
303
+ debugSection('mergedRect %j', mergedRect);
304
+ const expandedRect = expandSearchArea(mergedRect, context.shotSize);
305
+ const originalWidth = expandedRect.width;
306
+ const originalHeight = expandedRect.height;
307
+ debugSection('expanded sectionRect %j', expandedRect);
308
+ searchAreaConfig = await buildSearchAreaConfig({
309
+ context,
310
+ baseRect: mergedRect,
311
+ modelFamily
312
+ });
313
+ debugSection('scaled sectionRect from %dx%d to %dx%d (scale=%d)', originalWidth, originalHeight, searchAreaConfig.rect.width, searchAreaConfig.rect.height, searchAreaConfig.scale);
314
+ }
315
+ return {
316
+ rect: searchAreaConfig?.rect,
317
+ imageBase64: searchAreaConfig?.imageBase64,
318
+ scale: searchAreaConfig?.scale,
319
+ error: result.content.error,
320
+ rawResponse: JSON.stringify(result.content),
321
+ usage: result.usage
322
+ };
323
+ }
324
+ async function AiExtractElementInfo(options) {
325
+ const { dataQuery, context, extractOption, multimodalPrompt, modelConfig } = options;
326
+ const systemPrompt = systemPromptToExtract();
327
+ const screenshotBase64 = context.screenshot.base64;
328
+ const extractDataPromptText = extractDataQueryPrompt(options.pageDescription || '', dataQuery);
329
+ const userContent = [];
330
+ if (extractOption?.screenshotIncluded !== false) userContent.push({
331
+ type: 'image_url',
332
+ image_url: {
333
+ url: screenshotBase64,
334
+ detail: 'high'
335
+ }
336
+ });
337
+ userContent.push({
338
+ type: 'text',
339
+ text: extractDataPromptText
340
+ });
341
+ const msgs = [
342
+ {
343
+ role: 'system',
344
+ content: systemPrompt
345
+ },
346
+ {
347
+ role: 'user',
348
+ content: userContent
349
+ }
350
+ ];
351
+ if (multimodalPrompt) {
352
+ const addOns = await promptsToChatParam({
353
+ images: multimodalPrompt.images,
354
+ convertHttpImage2Base64: multimodalPrompt.convertHttpImage2Base64
355
+ });
356
+ msgs.push(...addOns);
357
+ }
358
+ const { content: rawResponse, usage, reasoning_content } = await callAI(msgs, modelConfig);
359
+ let parseResult;
360
+ try {
361
+ parseResult = parseXMLExtractionResponse(rawResponse);
362
+ } catch (parseError) {
363
+ const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
364
+ throw new AIResponseParseError(`XML parse error: ${errorMessage}`, rawResponse, usage);
365
+ }
366
+ return {
367
+ parseResult,
368
+ rawResponse,
369
+ usage,
370
+ reasoning_content
371
+ };
372
+ }
373
+ async function AiJudgeOrderSensitive(description, callAIFn, modelConfig) {
374
+ const systemPrompt = systemPromptToJudgeOrderSensitive();
375
+ const userPrompt = orderSensitiveJudgePrompt(description);
376
+ const msgs = [
377
+ {
378
+ role: 'system',
379
+ content: systemPrompt
380
+ },
381
+ {
382
+ role: 'user',
383
+ content: userPrompt
384
+ }
385
+ ];
386
+ const result = await callAIFn(msgs, modelConfig);
387
+ return {
388
+ isOrderSensitive: result.content.isOrderSensitive ?? false,
389
+ usage: result.usage
390
+ };
391
+ }
392
+ export { AiExtractElementInfo, AiJudgeOrderSensitive, AiLocateElement, AiLocateSection, buildSearchAreaConfig };
393
+
394
+ //# sourceMappingURL=inspect.mjs.map