@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.
- package/LICENSE +24 -0
- package/README.md +252 -0
- package/dist/actions.d.ts +185 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +1120 -0
- package/dist/actions.js.map +1 -0
- package/dist/agent-runtime.d.ts +352 -0
- package/dist/agent-runtime.d.ts.map +1 -0
- package/dist/agent-runtime.js +1170 -0
- package/dist/agent-runtime.js.map +1 -0
- package/dist/agent.d.ts +164 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +408 -0
- package/dist/agent.js.map +1 -0
- package/dist/asserts/expect.d.ts +159 -0
- package/dist/asserts/expect.d.ts.map +1 -0
- package/dist/asserts/expect.js +547 -0
- package/dist/asserts/expect.js.map +1 -0
- package/dist/asserts/index.d.ts +58 -0
- package/dist/asserts/index.d.ts.map +1 -0
- package/dist/asserts/index.js +70 -0
- package/dist/asserts/index.js.map +1 -0
- package/dist/asserts/query.d.ts +199 -0
- package/dist/asserts/query.d.ts.map +1 -0
- package/dist/asserts/query.js +288 -0
- package/dist/asserts/query.js.map +1 -0
- package/dist/backends/actions.d.ts +119 -0
- package/dist/backends/actions.d.ts.map +1 -0
- package/dist/backends/actions.js +291 -0
- package/dist/backends/actions.js.map +1 -0
- package/dist/backends/browser-use-adapter.d.ts +131 -0
- package/dist/backends/browser-use-adapter.d.ts.map +1 -0
- package/dist/backends/browser-use-adapter.js +219 -0
- package/dist/backends/browser-use-adapter.js.map +1 -0
- package/dist/backends/cdp-backend.d.ts +66 -0
- package/dist/backends/cdp-backend.d.ts.map +1 -0
- package/dist/backends/cdp-backend.js +273 -0
- package/dist/backends/cdp-backend.js.map +1 -0
- package/dist/backends/index.d.ts +80 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +101 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/protocol.d.ts +156 -0
- package/dist/backends/protocol.d.ts.map +1 -0
- package/dist/backends/protocol.js +16 -0
- package/dist/backends/protocol.js.map +1 -0
- package/dist/backends/sentience-context.d.ts +143 -0
- package/dist/backends/sentience-context.d.ts.map +1 -0
- package/dist/backends/sentience-context.js +359 -0
- package/dist/backends/sentience-context.js.map +1 -0
- package/dist/backends/snapshot.d.ts +188 -0
- package/dist/backends/snapshot.d.ts.map +1 -0
- package/dist/backends/snapshot.js +360 -0
- package/dist/backends/snapshot.js.map +1 -0
- package/dist/browser.d.ts +154 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +920 -0
- package/dist/browser.js.map +1 -0
- package/dist/canonicalization.d.ts +126 -0
- package/dist/canonicalization.d.ts.map +1 -0
- package/dist/canonicalization.js +161 -0
- package/dist/canonicalization.js.map +1 -0
- package/dist/captcha/strategies.d.ts +12 -0
- package/dist/captcha/strategies.d.ts.map +1 -0
- package/dist/captcha/strategies.js +43 -0
- package/dist/captcha/strategies.js.map +1 -0
- package/dist/captcha/types.d.ts +45 -0
- package/dist/captcha/types.d.ts.map +1 -0
- package/dist/captcha/types.js +12 -0
- package/dist/captcha/types.js.map +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +422 -0
- package/dist/cli.js.map +1 -0
- package/dist/conversational-agent.d.ts +123 -0
- package/dist/conversational-agent.d.ts.map +1 -0
- package/dist/conversational-agent.js +341 -0
- package/dist/conversational-agent.js.map +1 -0
- package/dist/cursor-policy.d.ts +41 -0
- package/dist/cursor-policy.d.ts.map +1 -0
- package/dist/cursor-policy.js +81 -0
- package/dist/cursor-policy.js.map +1 -0
- package/dist/debugger.d.ts +28 -0
- package/dist/debugger.d.ts.map +1 -0
- package/dist/debugger.js +107 -0
- package/dist/debugger.js.map +1 -0
- package/dist/expect.d.ts +16 -0
- package/dist/expect.d.ts.map +1 -0
- package/dist/expect.js +67 -0
- package/dist/expect.js.map +1 -0
- package/dist/failure-artifacts.d.ts +95 -0
- package/dist/failure-artifacts.d.ts.map +1 -0
- package/dist/failure-artifacts.js +805 -0
- package/dist/failure-artifacts.js.map +1 -0
- package/dist/generator.d.ts +16 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +205 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +160 -0
- package/dist/index.js.map +1 -0
- package/dist/inspector.d.ts +13 -0
- package/dist/inspector.d.ts.map +1 -0
- package/dist/inspector.js +153 -0
- package/dist/inspector.js.map +1 -0
- package/dist/llm-provider.d.ts +144 -0
- package/dist/llm-provider.d.ts.map +1 -0
- package/dist/llm-provider.js +460 -0
- package/dist/llm-provider.js.map +1 -0
- package/dist/ordinal.d.ts +90 -0
- package/dist/ordinal.d.ts.map +1 -0
- package/dist/ordinal.js +249 -0
- package/dist/ordinal.js.map +1 -0
- package/dist/overlay.d.ts +63 -0
- package/dist/overlay.d.ts.map +1 -0
- package/dist/overlay.js +102 -0
- package/dist/overlay.js.map +1 -0
- package/dist/protocols/browser-protocol.d.ts +79 -0
- package/dist/protocols/browser-protocol.d.ts.map +1 -0
- package/dist/protocols/browser-protocol.js +9 -0
- package/dist/protocols/browser-protocol.js.map +1 -0
- package/dist/query.d.ts +66 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +482 -0
- package/dist/query.js.map +1 -0
- package/dist/read.d.ts +47 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +128 -0
- package/dist/read.js.map +1 -0
- package/dist/recorder.d.ts +44 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +262 -0
- package/dist/recorder.js.map +1 -0
- package/dist/runtime-agent.d.ts +72 -0
- package/dist/runtime-agent.d.ts.map +1 -0
- package/dist/runtime-agent.js +357 -0
- package/dist/runtime-agent.js.map +1 -0
- package/dist/screenshot.d.ts +17 -0
- package/dist/screenshot.d.ts.map +1 -0
- package/dist/screenshot.js +40 -0
- package/dist/screenshot.js.map +1 -0
- package/dist/snapshot-diff.d.ts +23 -0
- package/dist/snapshot-diff.d.ts.map +1 -0
- package/dist/snapshot-diff.js +119 -0
- package/dist/snapshot-diff.js.map +1 -0
- package/dist/snapshot.d.ts +47 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +358 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/textSearch.d.ts +64 -0
- package/dist/textSearch.d.ts.map +1 -0
- package/dist/textSearch.js +113 -0
- package/dist/textSearch.js.map +1 -0
- package/dist/tools/context.d.ts +18 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +40 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/defaults.d.ts +5 -0
- package/dist/tools/defaults.d.ts.map +1 -0
- package/dist/tools/defaults.js +368 -0
- package/dist/tools/defaults.js.map +1 -0
- package/dist/tools/filesystem.d.ts +12 -0
- package/dist/tools/filesystem.d.ts.map +1 -0
- package/dist/tools/filesystem.js +137 -0
- package/dist/tools/filesystem.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +15 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +38 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +100 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tracing/cloud-sink.d.ts +189 -0
- package/dist/tracing/cloud-sink.d.ts.map +1 -0
- package/dist/tracing/cloud-sink.js +1067 -0
- package/dist/tracing/cloud-sink.js.map +1 -0
- package/dist/tracing/index-schema.d.ts +231 -0
- package/dist/tracing/index-schema.d.ts.map +1 -0
- package/dist/tracing/index-schema.js +235 -0
- package/dist/tracing/index-schema.js.map +1 -0
- package/dist/tracing/index.d.ts +12 -0
- package/dist/tracing/index.d.ts.map +1 -0
- package/dist/tracing/index.js +28 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/tracing/indexer.d.ts +20 -0
- package/dist/tracing/indexer.d.ts.map +1 -0
- package/dist/tracing/indexer.js +347 -0
- package/dist/tracing/indexer.js.map +1 -0
- package/dist/tracing/jsonl-sink.d.ts +51 -0
- package/dist/tracing/jsonl-sink.d.ts.map +1 -0
- package/dist/tracing/jsonl-sink.js +329 -0
- package/dist/tracing/jsonl-sink.js.map +1 -0
- package/dist/tracing/sink.d.ts +25 -0
- package/dist/tracing/sink.d.ts.map +1 -0
- package/dist/tracing/sink.js +15 -0
- package/dist/tracing/sink.js.map +1 -0
- package/dist/tracing/tracer-factory.d.ts +102 -0
- package/dist/tracing/tracer-factory.d.ts.map +1 -0
- package/dist/tracing/tracer-factory.js +375 -0
- package/dist/tracing/tracer-factory.js.map +1 -0
- package/dist/tracing/tracer.d.ts +140 -0
- package/dist/tracing/tracer.d.ts.map +1 -0
- package/dist/tracing/tracer.js +336 -0
- package/dist/tracing/tracer.js.map +1 -0
- package/dist/tracing/types.d.ts +203 -0
- package/dist/tracing/types.d.ts.map +1 -0
- package/dist/tracing/types.js +8 -0
- package/dist/tracing/types.js.map +1 -0
- package/dist/types.d.ts +422 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/action-executor.d.ts +25 -0
- package/dist/utils/action-executor.d.ts.map +1 -0
- package/dist/utils/action-executor.js +121 -0
- package/dist/utils/action-executor.js.map +1 -0
- package/dist/utils/browser-evaluator.d.ts +76 -0
- package/dist/utils/browser-evaluator.d.ts.map +1 -0
- package/dist/utils/browser-evaluator.js +130 -0
- package/dist/utils/browser-evaluator.js.map +1 -0
- package/dist/utils/browser.d.ts +30 -0
- package/dist/utils/browser.d.ts.map +1 -0
- package/dist/utils/browser.js +75 -0
- package/dist/utils/browser.js.map +1 -0
- package/dist/utils/element-filter.d.ts +76 -0
- package/dist/utils/element-filter.d.ts.map +1 -0
- package/dist/utils/element-filter.js +195 -0
- package/dist/utils/element-filter.js.map +1 -0
- package/dist/utils/grid-utils.d.ts +37 -0
- package/dist/utils/grid-utils.d.ts.map +1 -0
- package/dist/utils/grid-utils.js +283 -0
- package/dist/utils/grid-utils.js.map +1 -0
- package/dist/utils/llm-interaction-handler.d.ts +41 -0
- package/dist/utils/llm-interaction-handler.d.ts.map +1 -0
- package/dist/utils/llm-interaction-handler.js +171 -0
- package/dist/utils/llm-interaction-handler.js.map +1 -0
- package/dist/utils/llm-response-builder.d.ts +56 -0
- package/dist/utils/llm-response-builder.d.ts.map +1 -0
- package/dist/utils/llm-response-builder.js +130 -0
- package/dist/utils/llm-response-builder.js.map +1 -0
- package/dist/utils/selector-utils.d.ts +12 -0
- package/dist/utils/selector-utils.d.ts.map +1 -0
- package/dist/utils/selector-utils.js +32 -0
- package/dist/utils/selector-utils.js.map +1 -0
- package/dist/utils/snapshot-event-builder.d.ts +28 -0
- package/dist/utils/snapshot-event-builder.d.ts.map +1 -0
- package/dist/utils/snapshot-event-builder.js +88 -0
- package/dist/utils/snapshot-event-builder.js.map +1 -0
- package/dist/utils/snapshot-processor.d.ts +27 -0
- package/dist/utils/snapshot-processor.d.ts.map +1 -0
- package/dist/utils/snapshot-processor.js +47 -0
- package/dist/utils/snapshot-processor.js.map +1 -0
- package/dist/utils/trace-event-builder.d.ts +122 -0
- package/dist/utils/trace-event-builder.d.ts.map +1 -0
- package/dist/utils/trace-event-builder.js +365 -0
- package/dist/utils/trace-event-builder.js.map +1 -0
- package/dist/utils/trace-file-manager.d.ts +70 -0
- package/dist/utils/trace-file-manager.d.ts.map +1 -0
- package/dist/utils/trace-file-manager.js +194 -0
- package/dist/utils/trace-file-manager.js.map +1 -0
- package/dist/utils/zod.d.ts +5 -0
- package/dist/utils/zod.d.ts.map +1 -0
- package/dist/utils/zod.js +80 -0
- package/dist/utils/zod.js.map +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +13 -0
- package/dist/utils.js.map +1 -0
- package/dist/verification.d.ts +194 -0
- package/dist/verification.d.ts.map +1 -0
- package/dist/verification.js +530 -0
- package/dist/verification.js.map +1 -0
- package/dist/vision-executor.d.ts +18 -0
- package/dist/vision-executor.d.ts.map +1 -0
- package/dist/vision-executor.js +60 -0
- package/dist/vision-executor.js.map +1 -0
- package/dist/visual-agent.d.ts +120 -0
- package/dist/visual-agent.d.ts.map +1 -0
- package/dist/visual-agent.js +796 -0
- package/dist/visual-agent.js.map +1 -0
- package/dist/wait.d.ts +35 -0
- package/dist/wait.d.ts.map +1 -0
- package/dist/wait.js +76 -0
- package/dist/wait.js.map +1 -0
- package/package.json +94 -0
- package/spec/README.md +72 -0
- package/spec/SNAPSHOT_V1.md +208 -0
- package/spec/sdk-types.md +259 -0
- package/spec/snapshot.schema.json +148 -0
- package/src/extension/background.js +104 -0
- package/src/extension/content.js +162 -0
- package/src/extension/injected_api.js +1399 -0
- package/src/extension/manifest.json +36 -0
- package/src/extension/pkg/README.md +1340 -0
- package/src/extension/pkg/package.json +15 -0
- package/src/extension/pkg/sentience_core.d.ts +51 -0
- package/src/extension/pkg/sentience_core.js +371 -0
- package/src/extension/pkg/sentience_core_bg.wasm +0 -0
- package/src/extension/pkg/sentience_core_bg.wasm.d.ts +10 -0
- 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"}
|