@tangle-network/browser-agent-driver 0.32.0 → 0.33.1
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/dist/artifacts/filesystem-sink.d.ts +1 -1
- package/dist/artifacts/filesystem-sink.js +1 -1
- package/dist/brain/index.d.ts +7 -12
- package/dist/brain/index.d.ts.map +1 -1
- package/dist/brain/index.js +47 -70
- package/dist/brain/index.js.map +1 -1
- package/dist/browser-launch.js +1 -3
- package/dist/browser-launch.js.map +1 -1
- package/dist/captcha.d.ts.map +1 -1
- package/dist/captcha.js +1 -3
- package/dist/captcha.js.map +1 -1
- package/dist/cli-attach.d.ts +2 -2
- package/dist/cli-attach.js +2 -2
- package/dist/cli-design-audit.js +6 -6
- package/dist/cli-design-audit.js.map +1 -1
- package/dist/cli.js +26 -28
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/design/audit/build-result.d.ts +3 -0
- package/dist/design/audit/build-result.d.ts.map +1 -1
- package/dist/design/audit/build-result.js +10 -2
- package/dist/design/audit/build-result.js.map +1 -1
- package/dist/design/audit/evaluate.d.ts +5 -2
- package/dist/design/audit/evaluate.d.ts.map +1 -1
- package/dist/design/audit/evaluate.js +9 -3
- package/dist/design/audit/evaluate.js.map +1 -1
- package/dist/design/audit/patches/generate.d.ts +12 -0
- package/dist/design/audit/patches/generate.d.ts.map +1 -1
- package/dist/design/audit/patches/generate.js +16 -9
- package/dist/design/audit/patches/generate.js.map +1 -1
- package/dist/design/audit/pipeline.d.ts +3 -3
- package/dist/design/audit/pipeline.d.ts.map +1 -1
- package/dist/design/audit/pipeline.js +4 -3
- package/dist/design/audit/pipeline.js.map +1 -1
- package/dist/drivers/cursor-overlay.d.ts +1 -1
- package/dist/drivers/cursor-overlay.d.ts.map +1 -1
- package/dist/drivers/cursor-overlay.js +2 -2
- package/dist/drivers/extract-with-index.d.ts +4 -7
- package/dist/drivers/extract-with-index.d.ts.map +1 -1
- package/dist/drivers/extract-with-index.js +4 -7
- package/dist/drivers/extract-with-index.js.map +1 -1
- package/dist/drivers/overlay-label.d.ts +3 -4
- package/dist/drivers/overlay-label.d.ts.map +1 -1
- package/dist/drivers/overlay-label.js.map +1 -1
- package/dist/drivers/playwright.d.ts +2 -2
- package/dist/drivers/playwright.d.ts.map +1 -1
- package/dist/drivers/playwright.js +10 -24
- package/dist/drivers/playwright.js.map +1 -1
- package/dist/drivers/som-overlay.d.ts +2 -3
- package/dist/drivers/som-overlay.d.ts.map +1 -1
- package/dist/drivers/som-overlay.js +2 -3
- package/dist/drivers/som-overlay.js.map +1 -1
- package/dist/drivers/types.d.ts +3 -9
- package/dist/drivers/types.d.ts.map +1 -1
- package/dist/multi-actor.d.ts.map +1 -1
- package/dist/multi-actor.js +2 -3
- package/dist/multi-actor.js.map +1 -1
- package/dist/provider-defaults.d.ts +1 -0
- package/dist/provider-defaults.d.ts.map +1 -1
- package/dist/provider-defaults.js +24 -0
- package/dist/provider-defaults.js.map +1 -1
- package/dist/run-state.d.ts +3 -32
- package/dist/run-state.d.ts.map +1 -1
- package/dist/run-state.js +5 -39
- package/dist/run-state.js.map +1 -1
- package/dist/runner/completion-language.d.ts +2 -0
- package/dist/runner/completion-language.d.ts.map +1 -0
- package/dist/runner/completion-language.js +5 -0
- package/dist/runner/completion-language.js.map +1 -0
- package/dist/runner/direct-start.d.ts +19 -0
- package/dist/runner/direct-start.d.ts.map +1 -0
- package/dist/runner/direct-start.js +295 -0
- package/dist/runner/direct-start.js.map +1 -0
- package/dist/runner/events.d.ts +3 -6
- package/dist/runner/events.d.ts.map +1 -1
- package/dist/runner/events.js.map +1 -1
- package/dist/runner/fan-out.d.ts +6 -9
- package/dist/runner/fan-out.d.ts.map +1 -1
- package/dist/runner/fan-out.js +7 -15
- package/dist/runner/fan-out.js.map +1 -1
- package/dist/runner/goal-decomposer.d.ts +0 -1
- package/dist/runner/goal-decomposer.d.ts.map +1 -1
- package/dist/runner/goal-decomposer.js +0 -1
- package/dist/runner/goal-decomposer.js.map +1 -1
- package/dist/runner/google-flights-preflight.d.ts +35 -0
- package/dist/runner/google-flights-preflight.d.ts.map +1 -0
- package/dist/runner/google-flights-preflight.js +411 -0
- package/dist/runner/google-flights-preflight.js.map +1 -0
- package/dist/runner/interrupt-controller.d.ts +1 -1
- package/dist/runner/interrupt-controller.js +1 -1
- package/dist/runner/overlay-narration.d.ts +1 -1
- package/dist/runner/overlay-narration.js +1 -1
- package/dist/runner/parallel-runner.d.ts +3 -6
- package/dist/runner/parallel-runner.d.ts.map +1 -1
- package/dist/runner/parallel-runner.js +2 -3
- package/dist/runner/parallel-runner.js.map +1 -1
- package/dist/runner/pattern-extractor.d.ts +2 -2
- package/dist/runner/pattern-extractor.js +2 -2
- package/dist/runner/runner.d.ts +15 -39
- package/dist/runner/runner.d.ts.map +1 -1
- package/dist/runner/runner.js +208 -255
- package/dist/runner/runner.js.map +1 -1
- package/dist/runner/stream-webhook.d.ts +1 -1
- package/dist/runner/stream-webhook.js +1 -1
- package/dist/skills/domain-loader.d.ts +1 -2
- package/dist/skills/domain-loader.d.ts.map +1 -1
- package/dist/skills/domain-loader.js +1 -2
- package/dist/skills/domain-loader.js.map +1 -1
- package/dist/supervisor/critic.js +1 -4
- package/dist/supervisor/critic.js.map +1 -1
- package/dist/telemetry/schema.d.ts +2 -2
- package/dist/telemetry/schema.js +2 -2
- package/dist/test-runner.d.ts +4 -5
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +2 -3
- package/dist/test-runner.js.map +1 -1
- package/dist/types.d.ts +21 -21
- package/dist/types.d.ts.map +1 -1
- package/package.json +57 -54
package/dist/brain/index.d.ts
CHANGED
|
@@ -91,9 +91,8 @@ export declare class Brain {
|
|
|
91
91
|
* non-streaming — that every OpenAI-compatible proxy is guaranteed to serve.
|
|
92
92
|
*
|
|
93
93
|
* The single source of truth for "we're talking to a proxy, be conservative
|
|
94
|
-
* about API features"
|
|
95
|
-
*
|
|
96
|
-
* this predicate.
|
|
94
|
+
* about API features"; both `createForceNonStreamingFetch()` and the
|
|
95
|
+
* `forceReasoning` gate route through this predicate.
|
|
97
96
|
*/
|
|
98
97
|
private isProxiedOpenAI;
|
|
99
98
|
/** Get a LLM model instance, optionally with provider/model override (e.g. for CAPTCHA fallback) */
|
|
@@ -215,21 +214,17 @@ export declare class Brain {
|
|
|
215
214
|
forceVision?: boolean;
|
|
216
215
|
}): Promise<BrainDecision>;
|
|
217
216
|
/**
|
|
218
|
-
*
|
|
217
|
+
* Vision-first decision path. The screenshot is the primary
|
|
219
218
|
* observation; DOM snapshot is minimal context (URL, title only in pure
|
|
220
219
|
* vision mode, or compact DOM in hybrid mode). The LLM outputs
|
|
221
220
|
* coordinate-based actions (clickAt, typeAt) in 1024×768 virtual space.
|
|
222
221
|
*/
|
|
223
222
|
private decideVision;
|
|
224
223
|
/**
|
|
225
|
-
*
|
|
224
|
+
* Generate a structured plan for the entire task with one LLM call.
|
|
226
225
|
*
|
|
227
226
|
* The runner executes the plan deterministically (no LLM between steps),
|
|
228
227
|
* falling back to per-action `decide()` only when verification fails.
|
|
229
|
-
* This is the architectural shift that breaks the "1 LLM call per
|
|
230
|
-
* action" assumption — a 9-action task becomes 1 plan call + 9
|
|
231
|
-
* deterministic executes instead of 9 LLM calls.
|
|
232
|
-
*
|
|
233
228
|
* Returns null when:
|
|
234
229
|
* - the LLM response is unparseable JSON (fall through to per-action)
|
|
235
230
|
* - the plan has zero steps
|
|
@@ -280,6 +275,7 @@ export declare class Brain {
|
|
|
280
275
|
raw: string;
|
|
281
276
|
tokensUsed?: number;
|
|
282
277
|
designSystemScore?: Record<string, unknown>;
|
|
278
|
+
parseError?: string;
|
|
283
279
|
}>;
|
|
284
280
|
/**
|
|
285
281
|
* Extract reusable knowledge from a completed trajectory.
|
|
@@ -315,9 +311,8 @@ export declare class Brain {
|
|
|
315
311
|
* like MDN, Python docs, W3C spec where the value the agent needs lives in
|
|
316
312
|
* a `<dl>/<code>/<pre>` block, not in an interactive element)
|
|
317
313
|
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
* unchanged because by then the LLM has already seen the full snapshot once.
|
|
314
|
+
* New-page callers use a larger default budget; same-page callers can pass a
|
|
315
|
+
* tighter budget after the model has already seen the full snapshot once.
|
|
321
316
|
*/
|
|
322
317
|
export declare function budgetSnapshot(snapshot: string, maxChars?: number): string;
|
|
323
318
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/brain/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAsB,MAAM,IAAI,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAY,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/brain/index.ts"],"names":[],"mappings":"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"}
|
package/dist/brain/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { generateText, streamText } from 'ai';
|
|
8
8
|
import { AriaSnapshotHelper } from '../drivers/snapshot.js';
|
|
9
|
-
import { resolveProviderApiKey, resolveProviderModelName, isClaudeCodeRoutedModel, ZAI_OPENAI_BASE_URL, ZAI_ANTHROPIC_BASE_URL, } from '../provider-defaults.js';
|
|
9
|
+
import { resolveProviderApiKey, resolveProviderModelName, isClaudeCodeRoutedModel, shouldSendTemperature, ZAI_OPENAI_BASE_URL, ZAI_ANTHROPIC_BASE_URL, } from '../provider-defaults.js';
|
|
10
10
|
import { buildFirstPartyBoundaryNote } from '../domain-policy.js';
|
|
11
11
|
import { generateWithSandboxBackend } from '../providers/sandbox-backend.js';
|
|
12
12
|
/** Core system prompt: preamble, actions, format, and rules 1-14 (always sent) */
|
|
@@ -79,13 +79,13 @@ const DATA_EXTRACTION_RULES = `
|
|
|
79
79
|
21. EFFICIENT COMPLETION: When you have enough data to answer the goal, complete immediately. Do not navigate to additional pages for "confirmation" if the data was already extracted or is visible in the current a11y tree. Include all extracted data in the completion result
|
|
80
80
|
22. EXTRACT BEFORE NAVIGATING: On search results, directory listings, or any page showing multiple items, ALWAYS extract ALL needed data BEFORE clicking into individual items. Use extractWithIndex with a wide query for unknown structure, or runScript with document.querySelectorAll('.result-card') if the structure is well-known. Many sites use anti-bot protection on detail pages but leave listing pages accessible. If you can answer the goal from list-level data, do so without navigating deeper.
|
|
81
81
|
23. FILTER vs SEARCH: When a goal asks to filter results (e.g., "under $50", "4+ stars"), look for filter controls (sliders, dropdowns, checkboxes in a sidebar or toolbar) rather than typing filter values into the search box. Search boxes are for keyword queries, not numeric filters. After applying a filter: (1) wait 2-3 seconds for results to update, (2) verify the filter took effect by checking the updated results, (3) extract the filtered data. Do NOT keep searching for more filter controls after one is applied — extract and complete
|
|
82
|
-
25. EXTRACTWITHINDEX RECOVERY: If a previous runScript returned null/empty/{x:null} on an extraction task, the selector was wrong. DO NOT retry the same runScript or guess a similar selector — the LLM cannot guess CSS class names that aren't visible in the snapshot. Switch to extractWithIndex with a WIDE query: \`'p, span, dd, code, strong, em'\` plus a \`contains\` filter naming the expected text fragment (e.g. contains: "downloads" for npm download counts, contains: "callbackFn" for MDN method signatures). The response shows you the actual text per element so you can pick by content match.
|
|
82
|
+
25. EXTRACTWITHINDEX RECOVERY: If a previous runScript returned null/empty/{x:null} on an extraction task, the selector was wrong. DO NOT retry the same runScript or guess a similar selector — the LLM cannot guess CSS class names that aren't visible in the snapshot. Switch to extractWithIndex with a WIDE query: \`'p, span, dd, code, strong, em'\` plus a \`contains\` filter naming the expected text fragment (e.g. contains: "downloads" for npm download counts, contains: "callbackFn" for MDN method signatures). The response shows you the actual text per element so you can pick by content match. Pick-by-content beats pick-by-selector on pages where the planner couldn't see the data at plan time.`;
|
|
83
83
|
/** Heavy page rules (19-20, 24): injected when snapshot is large or turn count is high */
|
|
84
84
|
const HEAVY_PAGE_RULES = `
|
|
85
85
|
19. FORM FIELD TARGETING: Before typing, verify you are targeting the correct input field using its @ref from the ELEMENTS list. If multiple inputs are visible (e.g., search box + price filter), ensure you select the right one by checking its label or placeholder text in the a11y tree. Never assume focus — always specify the exact @ref
|
|
86
86
|
20. SECTION NAVIGATION: When you need to find a specific section (e.g., rugby, sports, travel) and the nav links aren't in the truncated a11y tree, use runScript to discover navigation: JSON.stringify(Array.from(document.querySelectorAll('nav a, header a, [role="navigation"] a, .nav a')).slice(0, 30).map(a => ({text: a.textContent.trim(), href: a.href}))). Then navigate directly to the matching section URL
|
|
87
87
|
24. HEAVY PAGE RECOVERY: If a page takes very long to load or seems stuck, do NOT wait — use runScript to check document.readyState and extract whatever content is already in the DOM. Partial data is better than a timeout. If the page is completely blank, try navigating to a simpler version (mobile site, search page) instead of waiting`;
|
|
88
|
-
/**
|
|
88
|
+
/** URL-first navigation rules for complex forms and search pages.
|
|
89
89
|
* Teaches the agent to construct search/results URLs from goal text
|
|
90
90
|
* instead of fighting form UIs. Works on any site with URL parameters. */
|
|
91
91
|
const URL_FIRST_RULES = `
|
|
@@ -139,7 +139,7 @@ EXAMPLE 3 — Batch fill a multi-field form (one turn instead of ten):
|
|
|
139
139
|
{"plan":["Fill all visible Personal Info fields","Click Next","Fill Contact step","Submit"],"currentStep":0,"action":{"action":"fill","fields":{"@firstname":"Jordan","@lastname":"Rivera","@dob":"1990-04-15"},"selects":{"@gender":"other"}},"reasoning":"Step 1 of the form has 3 text fields and 1 select all visible at once. Filling them in a single batch action saves 7 turns vs typing each individually.","expectedEffect":"All four Step 1 fields populated with the supplied values"}`;
|
|
140
140
|
/** Full static prompt (all rules) — used as default when config.systemPrompt is not set */
|
|
141
141
|
const SYSTEM_PROMPT = CORE_RULES + SEARCH_RULES + DATA_EXTRACTION_RULES + HEAVY_PAGE_RULES + REASONING_SUFFIX;
|
|
142
|
-
//
|
|
142
|
+
// Vision-first system prompt for pure coordinate actions.
|
|
143
143
|
const VISION_FIRST_PROMPT = `You are a browser automation agent. You operate by looking at screenshots and clicking on elements using pixel coordinates.
|
|
144
144
|
|
|
145
145
|
The screenshot shows the current page state at 1024×768 resolution. You identify elements visually and specify where to click using (x, y) coordinates in this coordinate space.
|
|
@@ -239,7 +239,7 @@ REASONING FRAMEWORK:
|
|
|
239
239
|
2. Where is the element I need to interact with? Estimate its (x, y) coordinates.
|
|
240
240
|
3. What is the smallest action that makes progress toward the goal?
|
|
241
241
|
4. If my last action failed, WHY did it fail? Try a different location or strategy.`;
|
|
242
|
-
//
|
|
242
|
+
// Unified vision+DOM prompt. The model sees BOTH the screenshot AND
|
|
243
243
|
// the ARIA snapshot with @refs. It can use EITHER coordinate actions (clickAt/
|
|
244
244
|
// typeAt for visual targets) OR ref actions (click/type/fill for DOM elements).
|
|
245
245
|
// This lets it pick the best tool per interaction: vision for visual layout,
|
|
@@ -427,7 +427,7 @@ export class Brain {
|
|
|
427
427
|
scoutModelName;
|
|
428
428
|
scoutProvider;
|
|
429
429
|
scoutUseVision;
|
|
430
|
-
//
|
|
430
|
+
// Per-role model overrides.
|
|
431
431
|
plannerModel;
|
|
432
432
|
plannerProvider;
|
|
433
433
|
verifierModel;
|
|
@@ -466,7 +466,7 @@ export class Brain {
|
|
|
466
466
|
this.scoutModelName = config.scout?.model;
|
|
467
467
|
this.scoutProvider = config.scout?.provider;
|
|
468
468
|
this.scoutUseVision = config.scout?.useVision === true;
|
|
469
|
-
//
|
|
469
|
+
// Per-role model overrides.
|
|
470
470
|
this.plannerModel = config.models?.planner?.model;
|
|
471
471
|
this.plannerProvider = config.models?.planner?.provider;
|
|
472
472
|
this.verifierModel = config.models?.verifier?.model;
|
|
@@ -486,8 +486,10 @@ export class Brain {
|
|
|
486
486
|
});
|
|
487
487
|
}
|
|
488
488
|
shouldSendTemperature(modelName = this.modelName) {
|
|
489
|
-
//
|
|
490
|
-
|
|
489
|
+
// Reasoning models reject an explicit temperature — see the shared
|
|
490
|
+
// capability check (GPT-5, o-series, Opus 4.8+, Kimi K2.6+, DeepSeek
|
|
491
|
+
// reasoner).
|
|
492
|
+
return shouldSendTemperature(modelName);
|
|
491
493
|
}
|
|
492
494
|
generationOptions(maxOutputTokens, selection) {
|
|
493
495
|
const providerName = selection?.provider || this.provider;
|
|
@@ -530,9 +532,8 @@ export class Brain {
|
|
|
530
532
|
* non-streaming — that every OpenAI-compatible proxy is guaranteed to serve.
|
|
531
533
|
*
|
|
532
534
|
* The single source of truth for "we're talking to a proxy, be conservative
|
|
533
|
-
* about API features"
|
|
534
|
-
*
|
|
535
|
-
* this predicate.
|
|
535
|
+
* about API features"; both `createForceNonStreamingFetch()` and the
|
|
536
|
+
* `forceReasoning` gate route through this predicate.
|
|
536
537
|
*/
|
|
537
538
|
isProxiedOpenAI(providerName) {
|
|
538
539
|
return providerName === 'openai' && Boolean(this.baseUrl);
|
|
@@ -832,9 +833,8 @@ export class Brain {
|
|
|
832
833
|
shouldUseNavigationModel(state, extraContext, turnInfo) {
|
|
833
834
|
if (!this.adaptiveModelRouting || !this.navModelName)
|
|
834
835
|
return false;
|
|
835
|
-
//
|
|
836
|
-
//
|
|
837
|
-
// pages, and error recovery where reasoning matters.
|
|
836
|
+
// Use the navigation model for DOM-only same-page turns. Keep the primary
|
|
837
|
+
// model for first turns, new pages, and error recovery.
|
|
838
838
|
const isFirstTurn = !turnInfo || turnInfo.current <= 1;
|
|
839
839
|
const samePageAsPrevious = this.lastDecisionUrl === state.url;
|
|
840
840
|
const hasError = extraContext?.includes('REJECTED') || extraContext?.includes('ERROR');
|
|
@@ -1063,8 +1063,7 @@ export class Brain {
|
|
|
1063
1063
|
// Zone 1 (intact): last 2 turns — full content
|
|
1064
1064
|
// Zone 2 (standard): turns 3-5 back — ELEMENTS stripped from user msgs
|
|
1065
1065
|
// Zone 3 (deep compact): turns 6+ back — both user and assistant ultra-compacted
|
|
1066
|
-
//
|
|
1067
|
-
// Google Flights to lose essential history on 30-turn runs.
|
|
1066
|
+
// Keep enough older history for long multi-step travel workflows.
|
|
1068
1067
|
const deepCompactBefore = Math.max(0, this.history.length - 10);
|
|
1069
1068
|
return this.history.map((msg, idx) => {
|
|
1070
1069
|
// Zone 1: keep recent turns intact
|
|
@@ -1182,7 +1181,7 @@ export class Brain {
|
|
|
1182
1181
|
});
|
|
1183
1182
|
}
|
|
1184
1183
|
async decide(goal, state, extraContext, turnInfo, options) {
|
|
1185
|
-
//
|
|
1184
|
+
// Vision-first and hybrid modes delegate to the vision path.
|
|
1186
1185
|
if (this.observationMode === 'vision' || this.observationMode === 'hybrid') {
|
|
1187
1186
|
return this.decideVision(goal, state, extraContext, turnInfo);
|
|
1188
1187
|
}
|
|
@@ -1201,10 +1200,8 @@ export class Brain {
|
|
|
1201
1200
|
&& diffChanges > 0
|
|
1202
1201
|
&& diffTotal > 0
|
|
1203
1202
|
&& diffChanges / diffTotal < 0.3;
|
|
1204
|
-
// Tighter snapshot budget on same-page turns
|
|
1205
|
-
//
|
|
1206
|
-
// docs/W3C spec) get the full <dl>/<code>/<pre> content the LLM needs to write
|
|
1207
|
-
// a working runScript on the first try.
|
|
1203
|
+
// Tighter snapshot budget on same-page turns; new pages keep enough
|
|
1204
|
+
// content for extraction from docs/spec pages.
|
|
1208
1205
|
const snapshotBudget = samePageAsPrevious ? 8_000 : 24_000;
|
|
1209
1206
|
let visibleSnapshot;
|
|
1210
1207
|
let elementsHeader;
|
|
@@ -1362,17 +1359,15 @@ ${visibleSnapshot}`;
|
|
|
1362
1359
|
};
|
|
1363
1360
|
}
|
|
1364
1361
|
/**
|
|
1365
|
-
*
|
|
1362
|
+
* Vision-first decision path. The screenshot is the primary
|
|
1366
1363
|
* observation; DOM snapshot is minimal context (URL, title only in pure
|
|
1367
1364
|
* vision mode, or compact DOM in hybrid mode). The LLM outputs
|
|
1368
1365
|
* coordinate-based actions (clickAt, typeAt) in 1024×768 virtual space.
|
|
1369
1366
|
*/
|
|
1370
1367
|
async decideVision(goal, state, extraContext, turnInfo) {
|
|
1371
1368
|
this.lastDecisionUrl = state.url;
|
|
1372
|
-
//
|
|
1373
|
-
//
|
|
1374
|
-
// expanded, content loaded), the DIFF is the signal. Send only what
|
|
1375
|
-
// changed instead of the full snapshot. Saves 3-5k tokens per turn.
|
|
1369
|
+
// Adaptive observation: on same-page hybrid turns, send only changed
|
|
1370
|
+
// elements when the diff is small.
|
|
1376
1371
|
const isHybrid = this.observationMode === 'hybrid';
|
|
1377
1372
|
const samePageAsPrevious = this.lastDecisionUrl === state.url;
|
|
1378
1373
|
const isFirstTurn = !turnInfo || turnInfo.current <= 1;
|
|
@@ -1437,10 +1432,8 @@ Title: ${state.title}`;
|
|
|
1437
1432
|
{ type: 'text', text: textContent },
|
|
1438
1433
|
{ type: 'image', image: state.screenshot, mediaType: 'image/jpeg' },
|
|
1439
1434
|
];
|
|
1440
|
-
//
|
|
1441
|
-
//
|
|
1442
|
-
// dead weight that pushes cumulative token count past the cost cap.
|
|
1443
|
-
// This alone fixes 3/5 Gen 13 failures (cost_cap at 101-106k).
|
|
1435
|
+
// Strip old screenshots from history; the current screenshot is the only
|
|
1436
|
+
// image the model needs for this turn.
|
|
1444
1437
|
const compacted = this.compactHistory().map((msg) => {
|
|
1445
1438
|
if (msg.role !== 'user' || !Array.isArray(msg.content))
|
|
1446
1439
|
return msg;
|
|
@@ -1454,13 +1447,12 @@ Title: ${state.title}`;
|
|
|
1454
1447
|
...compacted,
|
|
1455
1448
|
{ role: 'user', content: userContent },
|
|
1456
1449
|
];
|
|
1457
|
-
//
|
|
1458
|
-
//
|
|
1459
|
-
// differently, hitting cost cap in 3 turns. Vision turns stay on main model.
|
|
1450
|
+
// Vision turns stay on the main model because smaller model routes can
|
|
1451
|
+
// count image tokens differently and exhaust the token budget.
|
|
1460
1452
|
const modelOpts = { provider: this.provider, model: this.modelName };
|
|
1461
1453
|
const nearingEnd = turnInfo && turnInfo.current >= turnInfo.max - 3;
|
|
1462
1454
|
const maxTokens = nearingEnd ? 1200 : 600;
|
|
1463
|
-
//
|
|
1455
|
+
// Hybrid mode uses the unified prompt with both action vocabularies.
|
|
1464
1456
|
const systemPrompt = isHybrid ? UNIFIED_VISION_DOM_PROMPT : VISION_FIRST_PROMPT;
|
|
1465
1457
|
const result = await this.generate(systemPrompt, messages, modelOpts, maxTokens);
|
|
1466
1458
|
const raw = result.text;
|
|
@@ -1489,14 +1481,10 @@ Title: ${state.title}`;
|
|
|
1489
1481
|
};
|
|
1490
1482
|
}
|
|
1491
1483
|
/**
|
|
1492
|
-
*
|
|
1484
|
+
* Generate a structured plan for the entire task with one LLM call.
|
|
1493
1485
|
*
|
|
1494
1486
|
* The runner executes the plan deterministically (no LLM between steps),
|
|
1495
1487
|
* falling back to per-action `decide()` only when verification fails.
|
|
1496
|
-
* This is the architectural shift that breaks the "1 LLM call per
|
|
1497
|
-
* action" assumption — a 9-action task becomes 1 plan call + 9
|
|
1498
|
-
* deterministic executes instead of 9 LLM calls.
|
|
1499
|
-
*
|
|
1500
1488
|
* Returns null when:
|
|
1501
1489
|
* - the LLM response is unparseable JSON (fall through to per-action)
|
|
1502
1490
|
* - the plan has zero steps
|
|
@@ -1509,11 +1497,8 @@ Title: ${state.title}`;
|
|
|
1509
1497
|
const startedAt = Date.now();
|
|
1510
1498
|
const maxSteps = options?.maxSteps ?? 12;
|
|
1511
1499
|
const extraContext = options?.extraContext;
|
|
1512
|
-
//
|
|
1513
|
-
//
|
|
1514
|
-
// writes the runScript that runs on the first observation. Without enough
|
|
1515
|
-
// snapshot context (especially `<dl>/<dt>/<code>/<pre>` content lines that
|
|
1516
|
-
// Gen 10C now preserves), the planner emits selectors that don't exist.
|
|
1500
|
+
// Planner snapshots keep enough context for extraction tasks, especially
|
|
1501
|
+
// docs/spec pages with data in `<dl>`, `<code>`, and `<pre>` blocks.
|
|
1517
1502
|
const snapshot = budgetSnapshot(state.snapshot, 24_000);
|
|
1518
1503
|
const planSystemPrompt = `You are a planning engine for a browser automation agent.
|
|
1519
1504
|
|
|
@@ -1584,10 +1569,8 @@ ELEMENTS:
|
|
|
1584
1569
|
${snapshot}
|
|
1585
1570
|
${extraContext ? `\n${extraContext}\n` : ''}
|
|
1586
1571
|
What is the complete plan?`;
|
|
1587
|
-
//
|
|
1588
|
-
//
|
|
1589
|
-
// the planner can see the visual layout. This helps on sites like
|
|
1590
|
-
// Google Flights where the DOM doesn't convey form structure well.
|
|
1572
|
+
// In vision-capable modes, include the screenshot so the planner can use
|
|
1573
|
+
// visual layout when the DOM does not capture form structure.
|
|
1591
1574
|
const isVisionPlanner = (this.observationMode === 'hybrid' || this.observationMode === 'vision') && !!state.screenshot;
|
|
1592
1575
|
const userContent = isVisionPlanner
|
|
1593
1576
|
? [
|
|
@@ -1595,7 +1578,7 @@ What is the complete plan?`;
|
|
|
1595
1578
|
{ type: 'image', image: state.screenshot, mediaType: 'image/jpeg' },
|
|
1596
1579
|
]
|
|
1597
1580
|
: userText;
|
|
1598
|
-
//
|
|
1581
|
+
// Planner can use its own model override.
|
|
1599
1582
|
const planModelOpts = this.plannerModel
|
|
1600
1583
|
? { provider: (this.plannerProvider || this.provider), model: this.plannerModel }
|
|
1601
1584
|
: { provider: this.provider, model: this.modelName };
|
|
@@ -1855,7 +1838,7 @@ ${budgetSnapshot(state.snapshot)}${siteBoundaryNote ? `\n\n${siteBoundaryNote}`
|
|
|
1855
1838
|
|
|
1856
1839
|
Was the goal actually achieved? Analyze the current page state carefully.`;
|
|
1857
1840
|
const userContent = this.buildUserContent(textContent, state.screenshot, true);
|
|
1858
|
-
//
|
|
1841
|
+
// Verifier can use its own model, then the navigation model, then main.
|
|
1859
1842
|
const verifyProvider = this.verifierProvider
|
|
1860
1843
|
? this.verifierProvider
|
|
1861
1844
|
: (this.adaptiveModelRouting && this.navModelName ? (this.navProvider || this.provider) : undefined);
|
|
@@ -1954,7 +1937,7 @@ Audit this page for design quality, UX issues, and visual bugs.`;
|
|
|
1954
1937
|
suggestion: String(f.suggestion ?? ''),
|
|
1955
1938
|
...(f.cssSelector ? { cssSelector: String(f.cssSelector) } : {}),
|
|
1956
1939
|
...(f.cssFix ? { cssFix: String(f.cssFix) } : {}),
|
|
1957
|
-
//
|
|
1940
|
+
// Optional ROI fields.
|
|
1958
1941
|
...(clampScore(f.impact) !== undefined ? { impact: clampScore(f.impact) } : {}),
|
|
1959
1942
|
...(clampScore(f.effort) !== undefined ? { effort: clampScore(f.effort) } : {}),
|
|
1960
1943
|
...(VALID_BLAST.has(f.blast)
|
|
@@ -1978,12 +1961,13 @@ Audit this page for design quality, UX issues, and visual bugs.`;
|
|
|
1978
1961
|
designSystemScore,
|
|
1979
1962
|
};
|
|
1980
1963
|
}
|
|
1981
|
-
catch {
|
|
1964
|
+
catch (err) {
|
|
1982
1965
|
return {
|
|
1983
1966
|
score: 5,
|
|
1984
1967
|
findings: [],
|
|
1985
1968
|
raw,
|
|
1986
1969
|
tokensUsed,
|
|
1970
|
+
parseError: err instanceof Error ? err.message : String(err),
|
|
1987
1971
|
};
|
|
1988
1972
|
}
|
|
1989
1973
|
}
|
|
@@ -2063,11 +2047,9 @@ Only include facts that are genuinely useful. Quality over quantity. Max 10 fact
|
|
|
2063
2047
|
'fill', 'clickSequence',
|
|
2064
2048
|
'clickAt', 'typeAt',
|
|
2065
2049
|
'clickLabel', 'typeLabel',
|
|
2066
|
-
//
|
|
2067
|
-
// execute time; here we just accept the shape.
|
|
2050
|
+
// Macro dispatch. The driver validates the macro name at execute time.
|
|
2068
2051
|
'macro',
|
|
2069
|
-
//
|
|
2070
|
-
// only checks shape (subGoals[] or baseUrl+goalTemplate+items).
|
|
2052
|
+
// Parallel fan-out. Runner handles dispatch; validator checks shape.
|
|
2071
2053
|
'fanOut',
|
|
2072
2054
|
]);
|
|
2073
2055
|
// Parse strategy: exact → first-{/last-} extraction.
|
|
@@ -2251,9 +2233,8 @@ function deduplicateSnapshot(snapshot) {
|
|
|
2251
2233
|
* like MDN, Python docs, W3C spec where the value the agent needs lives in
|
|
2252
2234
|
* a `<dl>/<code>/<pre>` block, not in an interactive element)
|
|
2253
2235
|
*
|
|
2254
|
-
*
|
|
2255
|
-
*
|
|
2256
|
-
* unchanged because by then the LLM has already seen the full snapshot once.
|
|
2236
|
+
* New-page callers use a larger default budget; same-page callers can pass a
|
|
2237
|
+
* tighter budget after the model has already seen the full snapshot once.
|
|
2257
2238
|
*/
|
|
2258
2239
|
export function budgetSnapshot(snapshot, maxChars = 24_000) {
|
|
2259
2240
|
// Skip dedup on small snapshots — not enough repetition to justify the O(n) scan
|
|
@@ -2437,19 +2418,18 @@ function validateAction(actionType, data) {
|
|
|
2437
2418
|
...(typeof data.intervalMs === 'number' ? { intervalMs: data.intervalMs } : {}),
|
|
2438
2419
|
};
|
|
2439
2420
|
}
|
|
2440
|
-
//
|
|
2421
|
+
// Vision-first coordinate actions.
|
|
2441
2422
|
case 'clickAt':
|
|
2442
2423
|
return { action: 'clickAt', x: num(data.x, 0), y: num(data.y, 0) };
|
|
2443
2424
|
case 'typeAt':
|
|
2444
2425
|
return { action: 'typeAt', x: num(data.x, 0), y: num(data.y, 0), text: optStr('text') };
|
|
2445
|
-
//
|
|
2426
|
+
// Set-of-Marks label-based actions.
|
|
2446
2427
|
case 'clickLabel':
|
|
2447
2428
|
return { action: 'clickLabel', label: num(data.label, 0) };
|
|
2448
2429
|
case 'typeLabel':
|
|
2449
2430
|
return { action: 'typeLabel', label: num(data.label, 0), text: optStr('text') };
|
|
2450
|
-
//
|
|
2451
|
-
//
|
|
2452
|
-
// legitimately be omitted for macros that declare no params.
|
|
2431
|
+
// Macro invocation. The driver validates the name and required args at
|
|
2432
|
+
// execute time; macros without params may omit args.
|
|
2453
2433
|
case 'macro': {
|
|
2454
2434
|
const args = {};
|
|
2455
2435
|
if (data.args && typeof data.args === 'object' && !Array.isArray(data.args)) {
|
|
@@ -2511,11 +2491,8 @@ function isStringRecord(value) {
|
|
|
2511
2491
|
return true;
|
|
2512
2492
|
}
|
|
2513
2493
|
/**
|
|
2514
|
-
*
|
|
2515
|
-
*
|
|
2516
|
-
* default to SSE streaming when the client omits the field (observed on
|
|
2517
|
-
* router.tangle.tools). The AI SDK's generateText path does not handle
|
|
2518
|
-
* SSE, and we can't rely on the gateway respecting the absence of `stream`.
|
|
2494
|
+
* Build a fetch replacement that forces `"stream": false` on chat completions
|
|
2495
|
+
* bodies for OpenAI-compatible gateways that default to SSE streaming.
|
|
2519
2496
|
*/
|
|
2520
2497
|
function createForceNonStreamingFetch() {
|
|
2521
2498
|
return async (input, init) => {
|