@predicatelabs/sdk 0.99.9

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 (302) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +252 -0
  3. package/dist/actions.d.ts +185 -0
  4. package/dist/actions.d.ts.map +1 -0
  5. package/dist/actions.js +1120 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/agent-runtime.d.ts +352 -0
  8. package/dist/agent-runtime.d.ts.map +1 -0
  9. package/dist/agent-runtime.js +1170 -0
  10. package/dist/agent-runtime.js.map +1 -0
  11. package/dist/agent.d.ts +164 -0
  12. package/dist/agent.d.ts.map +1 -0
  13. package/dist/agent.js +408 -0
  14. package/dist/agent.js.map +1 -0
  15. package/dist/asserts/expect.d.ts +159 -0
  16. package/dist/asserts/expect.d.ts.map +1 -0
  17. package/dist/asserts/expect.js +547 -0
  18. package/dist/asserts/expect.js.map +1 -0
  19. package/dist/asserts/index.d.ts +58 -0
  20. package/dist/asserts/index.d.ts.map +1 -0
  21. package/dist/asserts/index.js +70 -0
  22. package/dist/asserts/index.js.map +1 -0
  23. package/dist/asserts/query.d.ts +199 -0
  24. package/dist/asserts/query.d.ts.map +1 -0
  25. package/dist/asserts/query.js +288 -0
  26. package/dist/asserts/query.js.map +1 -0
  27. package/dist/backends/actions.d.ts +119 -0
  28. package/dist/backends/actions.d.ts.map +1 -0
  29. package/dist/backends/actions.js +291 -0
  30. package/dist/backends/actions.js.map +1 -0
  31. package/dist/backends/browser-use-adapter.d.ts +131 -0
  32. package/dist/backends/browser-use-adapter.d.ts.map +1 -0
  33. package/dist/backends/browser-use-adapter.js +219 -0
  34. package/dist/backends/browser-use-adapter.js.map +1 -0
  35. package/dist/backends/cdp-backend.d.ts +66 -0
  36. package/dist/backends/cdp-backend.d.ts.map +1 -0
  37. package/dist/backends/cdp-backend.js +273 -0
  38. package/dist/backends/cdp-backend.js.map +1 -0
  39. package/dist/backends/index.d.ts +80 -0
  40. package/dist/backends/index.d.ts.map +1 -0
  41. package/dist/backends/index.js +101 -0
  42. package/dist/backends/index.js.map +1 -0
  43. package/dist/backends/protocol.d.ts +156 -0
  44. package/dist/backends/protocol.d.ts.map +1 -0
  45. package/dist/backends/protocol.js +16 -0
  46. package/dist/backends/protocol.js.map +1 -0
  47. package/dist/backends/sentience-context.d.ts +143 -0
  48. package/dist/backends/sentience-context.d.ts.map +1 -0
  49. package/dist/backends/sentience-context.js +359 -0
  50. package/dist/backends/sentience-context.js.map +1 -0
  51. package/dist/backends/snapshot.d.ts +188 -0
  52. package/dist/backends/snapshot.d.ts.map +1 -0
  53. package/dist/backends/snapshot.js +360 -0
  54. package/dist/backends/snapshot.js.map +1 -0
  55. package/dist/browser.d.ts +154 -0
  56. package/dist/browser.d.ts.map +1 -0
  57. package/dist/browser.js +920 -0
  58. package/dist/browser.js.map +1 -0
  59. package/dist/canonicalization.d.ts +126 -0
  60. package/dist/canonicalization.d.ts.map +1 -0
  61. package/dist/canonicalization.js +161 -0
  62. package/dist/canonicalization.js.map +1 -0
  63. package/dist/captcha/strategies.d.ts +12 -0
  64. package/dist/captcha/strategies.d.ts.map +1 -0
  65. package/dist/captcha/strategies.js +43 -0
  66. package/dist/captcha/strategies.js.map +1 -0
  67. package/dist/captcha/types.d.ts +45 -0
  68. package/dist/captcha/types.d.ts.map +1 -0
  69. package/dist/captcha/types.js +12 -0
  70. package/dist/captcha/types.js.map +1 -0
  71. package/dist/cli.d.ts +5 -0
  72. package/dist/cli.d.ts.map +1 -0
  73. package/dist/cli.js +422 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/conversational-agent.d.ts +123 -0
  76. package/dist/conversational-agent.d.ts.map +1 -0
  77. package/dist/conversational-agent.js +341 -0
  78. package/dist/conversational-agent.js.map +1 -0
  79. package/dist/cursor-policy.d.ts +41 -0
  80. package/dist/cursor-policy.d.ts.map +1 -0
  81. package/dist/cursor-policy.js +81 -0
  82. package/dist/cursor-policy.js.map +1 -0
  83. package/dist/debugger.d.ts +28 -0
  84. package/dist/debugger.d.ts.map +1 -0
  85. package/dist/debugger.js +107 -0
  86. package/dist/debugger.js.map +1 -0
  87. package/dist/expect.d.ts +16 -0
  88. package/dist/expect.d.ts.map +1 -0
  89. package/dist/expect.js +67 -0
  90. package/dist/expect.js.map +1 -0
  91. package/dist/failure-artifacts.d.ts +95 -0
  92. package/dist/failure-artifacts.d.ts.map +1 -0
  93. package/dist/failure-artifacts.js +805 -0
  94. package/dist/failure-artifacts.js.map +1 -0
  95. package/dist/generator.d.ts +16 -0
  96. package/dist/generator.d.ts.map +1 -0
  97. package/dist/generator.js +205 -0
  98. package/dist/generator.js.map +1 -0
  99. package/dist/index.d.ts +37 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +160 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/inspector.d.ts +13 -0
  104. package/dist/inspector.d.ts.map +1 -0
  105. package/dist/inspector.js +153 -0
  106. package/dist/inspector.js.map +1 -0
  107. package/dist/llm-provider.d.ts +144 -0
  108. package/dist/llm-provider.d.ts.map +1 -0
  109. package/dist/llm-provider.js +460 -0
  110. package/dist/llm-provider.js.map +1 -0
  111. package/dist/ordinal.d.ts +90 -0
  112. package/dist/ordinal.d.ts.map +1 -0
  113. package/dist/ordinal.js +249 -0
  114. package/dist/ordinal.js.map +1 -0
  115. package/dist/overlay.d.ts +63 -0
  116. package/dist/overlay.d.ts.map +1 -0
  117. package/dist/overlay.js +102 -0
  118. package/dist/overlay.js.map +1 -0
  119. package/dist/protocols/browser-protocol.d.ts +79 -0
  120. package/dist/protocols/browser-protocol.d.ts.map +1 -0
  121. package/dist/protocols/browser-protocol.js +9 -0
  122. package/dist/protocols/browser-protocol.js.map +1 -0
  123. package/dist/query.d.ts +66 -0
  124. package/dist/query.d.ts.map +1 -0
  125. package/dist/query.js +482 -0
  126. package/dist/query.js.map +1 -0
  127. package/dist/read.d.ts +47 -0
  128. package/dist/read.d.ts.map +1 -0
  129. package/dist/read.js +128 -0
  130. package/dist/read.js.map +1 -0
  131. package/dist/recorder.d.ts +44 -0
  132. package/dist/recorder.d.ts.map +1 -0
  133. package/dist/recorder.js +262 -0
  134. package/dist/recorder.js.map +1 -0
  135. package/dist/runtime-agent.d.ts +72 -0
  136. package/dist/runtime-agent.d.ts.map +1 -0
  137. package/dist/runtime-agent.js +357 -0
  138. package/dist/runtime-agent.js.map +1 -0
  139. package/dist/screenshot.d.ts +17 -0
  140. package/dist/screenshot.d.ts.map +1 -0
  141. package/dist/screenshot.js +40 -0
  142. package/dist/screenshot.js.map +1 -0
  143. package/dist/snapshot-diff.d.ts +23 -0
  144. package/dist/snapshot-diff.d.ts.map +1 -0
  145. package/dist/snapshot-diff.js +119 -0
  146. package/dist/snapshot-diff.js.map +1 -0
  147. package/dist/snapshot.d.ts +47 -0
  148. package/dist/snapshot.d.ts.map +1 -0
  149. package/dist/snapshot.js +358 -0
  150. package/dist/snapshot.js.map +1 -0
  151. package/dist/textSearch.d.ts +64 -0
  152. package/dist/textSearch.d.ts.map +1 -0
  153. package/dist/textSearch.js +113 -0
  154. package/dist/textSearch.js.map +1 -0
  155. package/dist/tools/context.d.ts +18 -0
  156. package/dist/tools/context.d.ts.map +1 -0
  157. package/dist/tools/context.js +40 -0
  158. package/dist/tools/context.js.map +1 -0
  159. package/dist/tools/defaults.d.ts +5 -0
  160. package/dist/tools/defaults.d.ts.map +1 -0
  161. package/dist/tools/defaults.js +368 -0
  162. package/dist/tools/defaults.js.map +1 -0
  163. package/dist/tools/filesystem.d.ts +12 -0
  164. package/dist/tools/filesystem.d.ts.map +1 -0
  165. package/dist/tools/filesystem.js +137 -0
  166. package/dist/tools/filesystem.js.map +1 -0
  167. package/dist/tools/index.d.ts +5 -0
  168. package/dist/tools/index.d.ts.map +1 -0
  169. package/dist/tools/index.js +15 -0
  170. package/dist/tools/index.js.map +1 -0
  171. package/dist/tools/registry.d.ts +38 -0
  172. package/dist/tools/registry.d.ts.map +1 -0
  173. package/dist/tools/registry.js +100 -0
  174. package/dist/tools/registry.js.map +1 -0
  175. package/dist/tracing/cloud-sink.d.ts +189 -0
  176. package/dist/tracing/cloud-sink.d.ts.map +1 -0
  177. package/dist/tracing/cloud-sink.js +1067 -0
  178. package/dist/tracing/cloud-sink.js.map +1 -0
  179. package/dist/tracing/index-schema.d.ts +231 -0
  180. package/dist/tracing/index-schema.d.ts.map +1 -0
  181. package/dist/tracing/index-schema.js +235 -0
  182. package/dist/tracing/index-schema.js.map +1 -0
  183. package/dist/tracing/index.d.ts +12 -0
  184. package/dist/tracing/index.d.ts.map +1 -0
  185. package/dist/tracing/index.js +28 -0
  186. package/dist/tracing/index.js.map +1 -0
  187. package/dist/tracing/indexer.d.ts +20 -0
  188. package/dist/tracing/indexer.d.ts.map +1 -0
  189. package/dist/tracing/indexer.js +347 -0
  190. package/dist/tracing/indexer.js.map +1 -0
  191. package/dist/tracing/jsonl-sink.d.ts +51 -0
  192. package/dist/tracing/jsonl-sink.d.ts.map +1 -0
  193. package/dist/tracing/jsonl-sink.js +329 -0
  194. package/dist/tracing/jsonl-sink.js.map +1 -0
  195. package/dist/tracing/sink.d.ts +25 -0
  196. package/dist/tracing/sink.d.ts.map +1 -0
  197. package/dist/tracing/sink.js +15 -0
  198. package/dist/tracing/sink.js.map +1 -0
  199. package/dist/tracing/tracer-factory.d.ts +102 -0
  200. package/dist/tracing/tracer-factory.d.ts.map +1 -0
  201. package/dist/tracing/tracer-factory.js +375 -0
  202. package/dist/tracing/tracer-factory.js.map +1 -0
  203. package/dist/tracing/tracer.d.ts +140 -0
  204. package/dist/tracing/tracer.d.ts.map +1 -0
  205. package/dist/tracing/tracer.js +336 -0
  206. package/dist/tracing/tracer.js.map +1 -0
  207. package/dist/tracing/types.d.ts +203 -0
  208. package/dist/tracing/types.d.ts.map +1 -0
  209. package/dist/tracing/types.js +8 -0
  210. package/dist/tracing/types.js.map +1 -0
  211. package/dist/types.d.ts +422 -0
  212. package/dist/types.d.ts.map +1 -0
  213. package/dist/types.js +6 -0
  214. package/dist/types.js.map +1 -0
  215. package/dist/utils/action-executor.d.ts +25 -0
  216. package/dist/utils/action-executor.d.ts.map +1 -0
  217. package/dist/utils/action-executor.js +121 -0
  218. package/dist/utils/action-executor.js.map +1 -0
  219. package/dist/utils/browser-evaluator.d.ts +76 -0
  220. package/dist/utils/browser-evaluator.d.ts.map +1 -0
  221. package/dist/utils/browser-evaluator.js +130 -0
  222. package/dist/utils/browser-evaluator.js.map +1 -0
  223. package/dist/utils/browser.d.ts +30 -0
  224. package/dist/utils/browser.d.ts.map +1 -0
  225. package/dist/utils/browser.js +75 -0
  226. package/dist/utils/browser.js.map +1 -0
  227. package/dist/utils/element-filter.d.ts +76 -0
  228. package/dist/utils/element-filter.d.ts.map +1 -0
  229. package/dist/utils/element-filter.js +195 -0
  230. package/dist/utils/element-filter.js.map +1 -0
  231. package/dist/utils/grid-utils.d.ts +37 -0
  232. package/dist/utils/grid-utils.d.ts.map +1 -0
  233. package/dist/utils/grid-utils.js +283 -0
  234. package/dist/utils/grid-utils.js.map +1 -0
  235. package/dist/utils/llm-interaction-handler.d.ts +41 -0
  236. package/dist/utils/llm-interaction-handler.d.ts.map +1 -0
  237. package/dist/utils/llm-interaction-handler.js +171 -0
  238. package/dist/utils/llm-interaction-handler.js.map +1 -0
  239. package/dist/utils/llm-response-builder.d.ts +56 -0
  240. package/dist/utils/llm-response-builder.d.ts.map +1 -0
  241. package/dist/utils/llm-response-builder.js +130 -0
  242. package/dist/utils/llm-response-builder.js.map +1 -0
  243. package/dist/utils/selector-utils.d.ts +12 -0
  244. package/dist/utils/selector-utils.d.ts.map +1 -0
  245. package/dist/utils/selector-utils.js +32 -0
  246. package/dist/utils/selector-utils.js.map +1 -0
  247. package/dist/utils/snapshot-event-builder.d.ts +28 -0
  248. package/dist/utils/snapshot-event-builder.d.ts.map +1 -0
  249. package/dist/utils/snapshot-event-builder.js +88 -0
  250. package/dist/utils/snapshot-event-builder.js.map +1 -0
  251. package/dist/utils/snapshot-processor.d.ts +27 -0
  252. package/dist/utils/snapshot-processor.d.ts.map +1 -0
  253. package/dist/utils/snapshot-processor.js +47 -0
  254. package/dist/utils/snapshot-processor.js.map +1 -0
  255. package/dist/utils/trace-event-builder.d.ts +122 -0
  256. package/dist/utils/trace-event-builder.d.ts.map +1 -0
  257. package/dist/utils/trace-event-builder.js +365 -0
  258. package/dist/utils/trace-event-builder.js.map +1 -0
  259. package/dist/utils/trace-file-manager.d.ts +70 -0
  260. package/dist/utils/trace-file-manager.d.ts.map +1 -0
  261. package/dist/utils/trace-file-manager.js +194 -0
  262. package/dist/utils/trace-file-manager.js.map +1 -0
  263. package/dist/utils/zod.d.ts +5 -0
  264. package/dist/utils/zod.d.ts.map +1 -0
  265. package/dist/utils/zod.js +80 -0
  266. package/dist/utils/zod.js.map +1 -0
  267. package/dist/utils.d.ts +8 -0
  268. package/dist/utils.d.ts.map +1 -0
  269. package/dist/utils.js +13 -0
  270. package/dist/utils.js.map +1 -0
  271. package/dist/verification.d.ts +194 -0
  272. package/dist/verification.d.ts.map +1 -0
  273. package/dist/verification.js +530 -0
  274. package/dist/verification.js.map +1 -0
  275. package/dist/vision-executor.d.ts +18 -0
  276. package/dist/vision-executor.d.ts.map +1 -0
  277. package/dist/vision-executor.js +60 -0
  278. package/dist/vision-executor.js.map +1 -0
  279. package/dist/visual-agent.d.ts +120 -0
  280. package/dist/visual-agent.d.ts.map +1 -0
  281. package/dist/visual-agent.js +796 -0
  282. package/dist/visual-agent.js.map +1 -0
  283. package/dist/wait.d.ts +35 -0
  284. package/dist/wait.d.ts.map +1 -0
  285. package/dist/wait.js +76 -0
  286. package/dist/wait.js.map +1 -0
  287. package/package.json +94 -0
  288. package/spec/README.md +72 -0
  289. package/spec/SNAPSHOT_V1.md +208 -0
  290. package/spec/sdk-types.md +259 -0
  291. package/spec/snapshot.schema.json +148 -0
  292. package/src/extension/background.js +104 -0
  293. package/src/extension/content.js +162 -0
  294. package/src/extension/injected_api.js +1399 -0
  295. package/src/extension/manifest.json +36 -0
  296. package/src/extension/pkg/README.md +1340 -0
  297. package/src/extension/pkg/package.json +15 -0
  298. package/src/extension/pkg/sentience_core.d.ts +51 -0
  299. package/src/extension/pkg/sentience_core.js +371 -0
  300. package/src/extension/pkg/sentience_core_bg.wasm +0 -0
  301. package/src/extension/pkg/sentience_core_bg.wasm.d.ts +10 -0
  302. package/src/extension/release.json +116 -0
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ /**
3
+ * Utility functions for working with grid layout data in snapshots.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getGridBounds = getGridBounds;
7
+ /**
8
+ * Get grid coordinates (bounding boxes) for detected grids.
9
+ *
10
+ * Groups elements by grid_id and computes the overall bounding box,
11
+ * row/column counts, and item count for each grid.
12
+ *
13
+ * @param snapshot - The snapshot containing elements with layout data
14
+ * @param gridId - Optional grid ID to filter by. If undefined, returns all grids.
15
+ * @returns Array of GridInfo objects, one per detected grid, sorted by grid_id.
16
+ * Each GridInfo contains:
17
+ * - grid_id: The grid identifier
18
+ * - bbox: Bounding box (x, y, width, height) in document coordinates
19
+ * - row_count: Number of rows in the grid
20
+ * - col_count: Number of columns in the grid
21
+ * - item_count: Total number of items in the grid
22
+ * - confidence: Confidence score (currently 1.0)
23
+ * - label: Optional inferred label (e.g., "product_grid", "search_results", "navigation")
24
+ * Note: Label inference is best-effort and may not always be accurate
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const snapshot = await browser.snapshot();
29
+ * // Get all grids
30
+ * const allGrids = getGridBounds(snapshot);
31
+ * // Get specific grid
32
+ * const mainGrid = getGridBounds(snapshot, 0);
33
+ * if (mainGrid.length > 0) {
34
+ * console.log(`Grid 0: ${mainGrid[0].item_count} items at (${mainGrid[0].bbox.x}, ${mainGrid[0].bbox.y})`);
35
+ * }
36
+ * ```
37
+ */
38
+ function getGridBounds(snapshot, gridId) {
39
+ // Group elements by grid_id
40
+ const gridElements = new Map();
41
+ for (const elem of snapshot.elements) {
42
+ if (elem.layout?.grid_id != null) {
43
+ const gid = elem.layout.grid_id;
44
+ if (!gridElements.has(gid)) {
45
+ gridElements.set(gid, []);
46
+ }
47
+ gridElements.get(gid).push(elem);
48
+ }
49
+ }
50
+ // Filter by gridId if specified
51
+ if (gridId !== undefined) {
52
+ if (!gridElements.has(gridId)) {
53
+ return [];
54
+ }
55
+ const filtered = new Map([[gridId, gridElements.get(gridId)]]);
56
+ gridElements.clear();
57
+ filtered.forEach((v, k) => gridElements.set(k, v));
58
+ }
59
+ const gridInfos = [];
60
+ const gridDominantCounts = new Map();
61
+ // Sort by grid_id for consistent output
62
+ const sortedGridIds = Array.from(gridElements.keys()).sort((a, b) => a - b);
63
+ // First pass: compute all grid infos and count dominant group elements
64
+ for (const gid of sortedGridIds) {
65
+ const elementsInGrid = gridElements.get(gid);
66
+ if (elementsInGrid.length === 0) {
67
+ continue;
68
+ }
69
+ // Count dominant group elements in this grid
70
+ const dominantCount = elementsInGrid.filter(e => e.in_dominant_group === true).length;
71
+ gridDominantCounts.set(gid, {
72
+ dominant: dominantCount,
73
+ total: elementsInGrid.length,
74
+ });
75
+ // Compute bounding box
76
+ let minX = Infinity;
77
+ let minY = Infinity;
78
+ let maxX = -Infinity;
79
+ let maxY = -Infinity;
80
+ // Count rows and columns
81
+ const rowIndices = new Set();
82
+ const colIndices = new Set();
83
+ for (const elem of elementsInGrid) {
84
+ const bbox = elem.bbox;
85
+ minX = Math.min(minX, bbox.x);
86
+ minY = Math.min(minY, bbox.y);
87
+ maxX = Math.max(maxX, bbox.x + bbox.width);
88
+ maxY = Math.max(maxY, bbox.y + bbox.height);
89
+ if (elem.layout?.grid_pos) {
90
+ rowIndices.add(elem.layout.grid_pos.row_index);
91
+ colIndices.add(elem.layout.grid_pos.col_index);
92
+ }
93
+ }
94
+ // Infer grid label from element patterns (best-effort heuristic)
95
+ const label = inferGridLabel(elementsInGrid);
96
+ gridInfos.push({
97
+ grid_id: gid,
98
+ bbox: {
99
+ x: minX,
100
+ y: minY,
101
+ width: maxX - minX,
102
+ height: maxY - minY,
103
+ },
104
+ row_count: rowIndices.size,
105
+ col_count: colIndices.size,
106
+ item_count: elementsInGrid.length,
107
+ confidence: 1.0,
108
+ label: label,
109
+ is_dominant: false, // Will be set below
110
+ });
111
+ }
112
+ // Second pass: identify dominant grid
113
+ // The grid with the highest count (or highest percentage >= 50%) of dominant group elements
114
+ if (gridDominantCounts.size > 0) {
115
+ // Find grid with highest absolute count
116
+ let maxDominantCount = 0;
117
+ for (const { dominant } of gridDominantCounts.values()) {
118
+ maxDominantCount = Math.max(maxDominantCount, dominant);
119
+ }
120
+ if (maxDominantCount > 0) {
121
+ // Find grid(s) with highest count
122
+ const dominantGrids = [];
123
+ for (const [gid, counts] of gridDominantCounts.entries()) {
124
+ if (counts.dominant === maxDominantCount) {
125
+ dominantGrids.push(gid);
126
+ }
127
+ }
128
+ // If multiple grids tie, prefer the one with highest percentage
129
+ dominantGrids.sort((a, b) => {
130
+ const aCounts = gridDominantCounts.get(a);
131
+ const bCounts = gridDominantCounts.get(b);
132
+ const aPct = aCounts.total > 0 ? aCounts.dominant / aCounts.total : 0;
133
+ const bPct = bCounts.total > 0 ? bCounts.dominant / bCounts.total : 0;
134
+ return bPct - aPct;
135
+ });
136
+ // Mark the dominant grid
137
+ const dominantGid = dominantGrids[0];
138
+ const counts = gridDominantCounts.get(dominantGid);
139
+ // Only mark as dominant if it has >= 50% dominant group elements or >= 3 elements
140
+ if (counts.dominant >= 3 || (counts.total > 0 && counts.dominant / counts.total >= 0.5)) {
141
+ const gridInfo = gridInfos.find(g => g.grid_id === dominantGid);
142
+ if (gridInfo) {
143
+ gridInfo.is_dominant = true;
144
+ }
145
+ }
146
+ }
147
+ }
148
+ return gridInfos;
149
+ }
150
+ /**
151
+ * Infer grid label from element patterns using text fingerprinting (best-effort heuristic).
152
+ *
153
+ * Uses patterns similar to dominant_group.rs content filtering logic, inverted to detect
154
+ * semantic grid types. Analyzes first 5 items as a "bag of features".
155
+ *
156
+ * Returns null if label cannot be reliably determined.
157
+ * This is a simple heuristic and may not always be accurate.
158
+ */
159
+ function inferGridLabel(elements) {
160
+ if (elements.length === 0) {
161
+ return null;
162
+ }
163
+ // Sample first 5 items for fingerprinting (as suggested in feedback)
164
+ const sampleElements = elements.slice(0, 5);
165
+ const elementTexts = sampleElements.map(e => (e.text || '').trim()).filter(t => t.length > 0);
166
+ if (elementTexts.length === 0) {
167
+ return null;
168
+ }
169
+ // Collect text patterns
170
+ const allText = elementTexts.map(t => t.toLowerCase()).join(' ');
171
+ const hrefs = sampleElements.filter(e => e.href).map(e => (e.href || '').toLowerCase());
172
+ // =========================================================================
173
+ // 1. PRODUCT GRID: Currency symbols, action verbs, ratings
174
+ // =========================================================================
175
+ // Currency patterns: $, €, £, or price patterns like "19.99", "$50", "€30"
176
+ const currencyPattern = /[$€£¥]\s*\d+|\d+\.\d{2}/.test(allText);
177
+ const productActionVerbs = [
178
+ 'add to cart',
179
+ 'buy now',
180
+ 'shop now',
181
+ 'purchase',
182
+ 'out of stock',
183
+ 'in stock',
184
+ ];
185
+ const hasProductActions = productActionVerbs.some(verb => allText.includes(verb));
186
+ // Ratings pattern: "4.5 stars", "(120 reviews)", "4.5/5"
187
+ const ratingPattern = /\d+\.?\d*\s*(stars?|reviews?|\/5|\/10)/i.test(allText);
188
+ // Product URL patterns
189
+ const productUrlPatterns = ['/product/', '/item/', '/dp/', '/p/', '/products/'];
190
+ const hasProductUrls = hrefs.some(href => productUrlPatterns.some(pattern => href.includes(pattern)));
191
+ if ((currencyPattern || hasProductActions || ratingPattern) &&
192
+ (hasProductUrls ||
193
+ elementTexts.filter(t => /[$€£¥]\s*\d+|\d+\.\d{2}/.test(t.toLowerCase())).length >= 2)) {
194
+ return 'product_grid';
195
+ }
196
+ // =========================================================================
197
+ // 2. ARTICLE/NEWS FEED: Timestamps, bylines, reading time
198
+ // =========================================================================
199
+ // Timestamp patterns (reusing logic from dominant_group.rs)
200
+ // "2 hours ago", "3 days ago", "5 minutes ago", "1 second ago", "2 ago"
201
+ const timestampPatterns = [
202
+ /\d+\s+(hour|day|minute|second)s?\s+ago/i,
203
+ /\d+\s+ago/i, // Short form: "2 ago"
204
+ /\d{1,2}\s+(hour|day|minute|second)\s+ago/i, // Singular
205
+ ];
206
+ const hasTimestamps = timestampPatterns.some(pattern => pattern.test(allText));
207
+ // Date patterns: "Aug 21, 2024", "2024-01-13", "Jan 15"
208
+ const datePatterns = [
209
+ /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\s+\d{1,2},?\s+\d{4}/i,
210
+ /\d{4}-\d{2}-\d{2}/,
211
+ /\d{1,2}\/\d{1,2}\/\d{4}/,
212
+ ];
213
+ const hasDates = datePatterns.some(pattern => pattern.test(allText));
214
+ // Bylines: "By [Name]", "Author:", "Written by"
215
+ const bylinePatterns = ['by ', 'author:', 'written by', 'posted by'];
216
+ const hasBylines = bylinePatterns.some(pattern => allText.includes(pattern));
217
+ // Reading time: "5 min read", "10 min", "read more"
218
+ const readingTimePattern = /\d+\s*(min|minute)s?\s*(read)?/i.test(allText);
219
+ if (hasTimestamps || (hasDates && hasBylines) || readingTimePattern) {
220
+ return 'article_feed';
221
+ }
222
+ // =========================================================================
223
+ // 3. SEARCH RESULTS: Snippets, metadata, ellipses
224
+ // =========================================================================
225
+ const searchKeywords = ['result', 'search', 'found', 'showing', 'results 1-', 'sponsored'];
226
+ const hasSearchMetadata = searchKeywords.some(keyword => allText.includes(keyword));
227
+ // Snippet indicators: ellipses, "match found", truncated text
228
+ const hasEllipses = allText.includes('...') || elementTexts.some(t => t.length > 100 && t.includes('...'));
229
+ // Check if many elements are links (typical for search results)
230
+ const linkCount = sampleElements.filter(e => e.role === 'link' || e.href).length;
231
+ const isMostlyLinks = linkCount >= sampleElements.length * 0.7; // 70%+ are links
232
+ if ((hasSearchMetadata || hasEllipses) && isMostlyLinks) {
233
+ return 'search_results';
234
+ }
235
+ // =========================================================================
236
+ // 4. NAVIGATION: Short length, homogeneity, common nav terms
237
+ // =========================================================================
238
+ // Calculate average text length and variance
239
+ const textLengths = elementTexts.map(t => t.length);
240
+ if (textLengths.length > 0) {
241
+ const avgLength = textLengths.reduce((sum, len) => sum + len, 0) / textLengths.length;
242
+ // Low variance = homogeneous (typical of navigation)
243
+ const variance = textLengths.length > 1
244
+ ? textLengths.reduce((sum, len) => sum + Math.pow(len - avgLength, 2), 0) /
245
+ textLengths.length
246
+ : 0;
247
+ const navKeywords = [
248
+ 'home',
249
+ 'about',
250
+ 'contact',
251
+ 'menu',
252
+ 'login',
253
+ 'sign in',
254
+ 'profile',
255
+ 'settings',
256
+ ];
257
+ const hasNavKeywords = navKeywords.some(keyword => allText.includes(keyword));
258
+ // Navigation: short average length (< 15 chars) AND low variance OR nav keywords
259
+ if (avgLength < 15 && (variance < 20 || hasNavKeywords)) {
260
+ // Also check if all are links
261
+ if (sampleElements.every(e => e.role === 'link' || e.href)) {
262
+ return 'navigation';
263
+ }
264
+ }
265
+ }
266
+ // =========================================================================
267
+ // 5. BUTTON GRID: All buttons
268
+ // =========================================================================
269
+ if (sampleElements.every(e => e.role === 'button')) {
270
+ return 'button_grid';
271
+ }
272
+ // =========================================================================
273
+ // 6. LINK LIST: Mostly links but not navigation
274
+ // =========================================================================
275
+ const linkListCount = sampleElements.filter(e => e.role === 'link' || e.href).length;
276
+ if (linkListCount >= sampleElements.length * 0.8) {
277
+ // 80%+ are links
278
+ return 'link_list';
279
+ }
280
+ // Unknown/unclear
281
+ return null;
282
+ }
283
+ //# sourceMappingURL=grid-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid-utils.js","sourceRoot":"","sources":["../../src/utils/grid-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * LLMInteractionHandler - Handles LLM queries and response parsing
3
+ *
4
+ * Extracted from SentienceAgent to improve separation of concerns
5
+ */
6
+ import { LLMProvider, LLMResponse } from '../llm-provider';
7
+ import { Snapshot } from '../types';
8
+ /**
9
+ * LLMInteractionHandler handles all LLM-related operations
10
+ */
11
+ export declare class LLMInteractionHandler {
12
+ private llm;
13
+ private verbose;
14
+ constructor(llm: LLMProvider, verbose?: boolean);
15
+ /**
16
+ * Build context string from snapshot for LLM prompt
17
+ *
18
+ * Format: [ID] <role> "text" {cues} @ (x,y) size:WxH importance:score [status]
19
+ *
20
+ * @param snap - Snapshot containing elements
21
+ * @param goal - Goal/task description (unused but kept for API consistency)
22
+ * @returns Formatted context string
23
+ */
24
+ buildContext(snap: Snapshot, _goal: string): string;
25
+ /**
26
+ * Query LLM with standardized prompt template
27
+ *
28
+ * @param domContext - DOM context string (formatted elements)
29
+ * @param goal - Goal/task description
30
+ * @returns LLM response
31
+ */
32
+ queryLLM(domContext: string, goal: string): Promise<LLMResponse>;
33
+ /**
34
+ * Extract action string from LLM response
35
+ *
36
+ * @param response - LLM response
37
+ * @returns Action string (e.g., "CLICK(42)")
38
+ */
39
+ extractAction(response: LLMResponse): string;
40
+ }
41
+ //# sourceMappingURL=llm-interaction-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-interaction-handler.d.ts","sourceRoot":"","sources":["../../src/utils/llm-interaction-handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGpC;;GAEG;AACH,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,OAAO;gBADP,GAAG,EAAE,WAAW,EAChB,OAAO,GAAE,OAAc;IAGjC;;;;;;;;OAQG;IACH,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IA4DnD;;;;;;OAMG;IACG,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAgFtE;;;;;OAKG;IACH,aAAa,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM;CAG7C"}
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ /**
3
+ * LLMInteractionHandler - Handles LLM queries and response parsing
4
+ *
5
+ * Extracted from SentienceAgent to improve separation of concerns
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.LLMInteractionHandler = void 0;
9
+ const llm_response_builder_1 = require("./llm-response-builder");
10
+ /**
11
+ * LLMInteractionHandler handles all LLM-related operations
12
+ */
13
+ class LLMInteractionHandler {
14
+ constructor(llm, verbose = true) {
15
+ this.llm = llm;
16
+ this.verbose = verbose;
17
+ }
18
+ /**
19
+ * Build context string from snapshot for LLM prompt
20
+ *
21
+ * Format: [ID] <role> "text" {cues} @ (x,y) size:WxH importance:score [status]
22
+ *
23
+ * @param snap - Snapshot containing elements
24
+ * @param goal - Goal/task description (unused but kept for API consistency)
25
+ * @returns Formatted context string
26
+ */
27
+ buildContext(snap, _goal) {
28
+ const lines = [];
29
+ for (const el of snap.elements) {
30
+ // Skip REMOVED elements - they're not actionable and shouldn't be in LLM context
31
+ if (el.diff_status === 'REMOVED') {
32
+ continue;
33
+ }
34
+ // Extract visual cues
35
+ const cues = [];
36
+ if (el.visual_cues.is_primary)
37
+ cues.push('PRIMARY');
38
+ if (el.visual_cues.is_clickable)
39
+ cues.push('CLICKABLE');
40
+ if (el.visual_cues.background_color_name) {
41
+ cues.push(`color:${el.visual_cues.background_color_name}`);
42
+ }
43
+ // Format element line with improved readability
44
+ const cuesStr = cues.length > 0 ? ` {${cues.join(',')}}` : '';
45
+ // Better text handling - show truncation indicator
46
+ let textPreview = '';
47
+ if (el.text) {
48
+ if (el.text.length > 50) {
49
+ textPreview = `"${el.text.substring(0, 50)}..."`;
50
+ }
51
+ else {
52
+ textPreview = `"${el.text}"`;
53
+ }
54
+ }
55
+ // Build position and size info
56
+ const x = Math.floor(el.bbox.x);
57
+ const y = Math.floor(el.bbox.y);
58
+ const width = Math.floor(el.bbox.width);
59
+ const height = Math.floor(el.bbox.height);
60
+ const positionStr = `@ (${x},${y})`;
61
+ const sizeStr = `size:${width}x${height}`;
62
+ // Build status indicators (only include if relevant)
63
+ const statusParts = [];
64
+ if (!el.in_viewport) {
65
+ statusParts.push('not_in_viewport');
66
+ }
67
+ if (el.is_occluded) {
68
+ statusParts.push('occluded');
69
+ }
70
+ if (el.diff_status) {
71
+ statusParts.push(`diff:${el.diff_status}`);
72
+ }
73
+ const statusStr = statusParts.length > 0 ? ` [${statusParts.join(',')}]` : '';
74
+ // Format: [ID] <role> "text" {cues} @ (x,y) size:WxH importance:score [status]
75
+ lines.push(`[${el.id}] <${el.role}> ${textPreview}${cuesStr} ` +
76
+ `${positionStr} ${sizeStr} importance:${el.importance}${statusStr}`);
77
+ }
78
+ return lines.join('\n');
79
+ }
80
+ /**
81
+ * Query LLM with standardized prompt template
82
+ *
83
+ * @param domContext - DOM context string (formatted elements)
84
+ * @param goal - Goal/task description
85
+ * @returns LLM response
86
+ */
87
+ async queryLLM(domContext, goal) {
88
+ const systemPrompt = `You are an AI web automation agent.
89
+
90
+ GOAL: ${goal}
91
+
92
+ VISIBLE ELEMENTS (sorted by importance):
93
+ ${domContext}
94
+
95
+ VISUAL CUES EXPLAINED:
96
+ After the text, you may see visual cues in curly braces like {CLICKABLE} or {PRIMARY,CLICKABLE,color:white}:
97
+ - PRIMARY: Main call-to-action element on the page
98
+ - CLICKABLE: Element is clickable/interactive
99
+ - color:X: Background color name (e.g., color:white, color:blue)
100
+ Multiple cues are comma-separated inside the braces: {CLICKABLE,color:white}
101
+
102
+ ELEMENT FORMAT EXPLAINED:
103
+ Each element line follows this format:
104
+ [ID] <role> "text" {cues} @ (x,y) size:WxH importance:score [status]
105
+
106
+ Example: [346] <button> "Computer Accessories" {CLICKABLE,color:white} @ (664,100) size:150x40 importance:811
107
+
108
+ Breaking down each part:
109
+ - [ID]: The number in brackets is the element ID - use this EXACT number in CLICK/TYPE commands
110
+ Example: If you see [346], use CLICK(346) or TYPE(346, "text")
111
+ - <role>: Element type (button, link, textbox, etc.)
112
+ - "text": Visible text content (truncated with "..." if long)
113
+ - {cues}: Optional visual cues in curly braces (e.g., {CLICKABLE}, {PRIMARY,CLICKABLE}, {CLICKABLE,color:white})
114
+ If no cues, this part is omitted entirely
115
+ - @ (x,y): Element position in pixels from top-left corner
116
+ - size:WxH: Element dimensions (width x height in pixels)
117
+ - importance: Score indicating element relevance (higher = more important)
118
+ - [status]: Optional status flags in brackets (not_in_viewport, occluded, diff:ADDED/MODIFIED/etc)
119
+
120
+ CRITICAL RESPONSE FORMAT:
121
+ You MUST respond with ONLY ONE of these exact action formats:
122
+ - CLICK(id) - Click element by ID (use the number from [ID] brackets)
123
+ - TYPE(id, "text") - Type text into element (use the number from [ID] brackets)
124
+ - PRESS("key") - Press keyboard key (Enter, Escape, Tab, ArrowDown, etc)
125
+ - FINISH() - Task complete
126
+
127
+ DO NOT include any explanation, reasoning, or natural language.
128
+ DO NOT use markdown formatting or code blocks.
129
+ DO NOT say "The next step is..." or anything similar.
130
+
131
+ CORRECT Examples (matching element IDs from the list above):
132
+ If element is [346] <button> "Click me" → respond: CLICK(346)
133
+ If element is [15] <textbox> "Search" → respond: TYPE(15, "magic mouse")
134
+ PRESS("Enter")
135
+ FINISH()
136
+
137
+ INCORRECT Examples (DO NOT DO THIS):
138
+ "The next step is to click..."
139
+ "I will type..."
140
+ \`\`\`CLICK(42)\`\`\``;
141
+ const userPrompt = 'Return the single action command:';
142
+ try {
143
+ const response = await this.llm.generate(systemPrompt, userPrompt, {
144
+ temperature: 0.0,
145
+ });
146
+ // Validate response
147
+ if (!llm_response_builder_1.LLMResponseBuilder.validate(response)) {
148
+ throw new Error('Invalid LLM response format');
149
+ }
150
+ return response;
151
+ }
152
+ catch (error) {
153
+ if (this.verbose) {
154
+ console.error('LLM query failed:', error);
155
+ }
156
+ // Return error response
157
+ return llm_response_builder_1.LLMResponseBuilder.createErrorResponse(error instanceof Error ? error : new Error(String(error)), this.llm.modelName);
158
+ }
159
+ }
160
+ /**
161
+ * Extract action string from LLM response
162
+ *
163
+ * @param response - LLM response
164
+ * @returns Action string (e.g., "CLICK(42)")
165
+ */
166
+ extractAction(response) {
167
+ return response.content.trim();
168
+ }
169
+ }
170
+ exports.LLMInteractionHandler = LLMInteractionHandler;
171
+ //# sourceMappingURL=llm-interaction-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-interaction-handler.js","sourceRoot":"","sources":["../../src/utils/llm-interaction-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * LLMResponseBuilder - Helper for consistent LLM response building
3
+ *
4
+ * Provides standardized response building and error handling across LLM providers
5
+ */
6
+ import { LLMResponse } from '../llm-provider';
7
+ /**
8
+ * LLMResponseBuilder provides static methods for building and validating LLM responses
9
+ */
10
+ export declare class LLMResponseBuilder {
11
+ /**
12
+ * Build a standardized LLMResponse from provider-specific response data
13
+ *
14
+ * @param content - Response content text
15
+ * @param modelName - Model name/identifier
16
+ * @param usage - Token usage data (provider-specific format)
17
+ * @param providerType - Provider type for usage extraction
18
+ * @returns Standardized LLMResponse
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * // OpenAI format
23
+ * const response = LLMResponseBuilder.build(
24
+ * 'CLICK(1)',
25
+ * 'gpt-4o',
26
+ * { prompt_tokens: 100, completion_tokens: 20, total_tokens: 120 },
27
+ * 'openai'
28
+ * );
29
+ *
30
+ * // Anthropic format
31
+ * const response = LLMResponseBuilder.build(
32
+ * 'CLICK(1)',
33
+ * 'claude-3-5-sonnet',
34
+ * { input_tokens: 100, output_tokens: 20 },
35
+ * 'anthropic'
36
+ * );
37
+ * ```
38
+ */
39
+ static build(content: string, modelName: string, usage: any, providerType?: 'openai' | 'anthropic' | 'glm' | 'gemini' | 'generic'): LLMResponse;
40
+ /**
41
+ * Validate that an LLMResponse has required fields
42
+ *
43
+ * @param response - LLMResponse to validate
44
+ * @returns True if valid, false otherwise
45
+ */
46
+ static validate(response: LLMResponse): boolean;
47
+ /**
48
+ * Create an error response
49
+ *
50
+ * @param error - Error message or Error object
51
+ * @param modelName - Optional model name
52
+ * @returns LLMResponse with error content
53
+ */
54
+ static createErrorResponse(error: string | Error, modelName?: string): LLMResponse;
55
+ }
56
+ //# sourceMappingURL=llm-response-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-response-builder.d.ts","sourceRoot":"","sources":["../../src/utils/llm-response-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;GAEG;AACH,qBAAa,kBAAkB;IAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CAAC,KAAK,CACV,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,GAAG,EACV,YAAY,GAAE,QAAQ,GAAG,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAqB,GAC9E,WAAW;IAgDd;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO;IAoB/C;;;;;;OAMG;IACH,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW;CAUnF"}