explorbot 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/bin/explorbot-cli.ts +19 -7
  2. package/boat/api-tester/src/cli.ts +17 -0
  3. package/boat/doc-collector/src/cli.ts +14 -1
  4. package/boat/prima/README.md +96 -0
  5. package/boat/prima/package.json +14 -10
  6. package/boat/prima/src/cli.ts +29 -12
  7. package/boat/prima/src/envelope.ts +35 -13
  8. package/boat/prima/src/prima.ts +78 -45
  9. package/dist/bin/explorbot-cli.js +19 -7
  10. package/dist/boat/api-tester/src/cli.js +17 -0
  11. package/dist/boat/doc-collector/src/cli.js +14 -1
  12. package/dist/boat/prima/src/cli.js +26 -7
  13. package/dist/boat/prima/src/envelope.js +32 -8
  14. package/dist/boat/prima/src/prima.js +75 -43
  15. package/dist/models.json +4 -4
  16. package/dist/package.json +6 -2
  17. package/dist/src/action-result.d.ts +13 -0
  18. package/dist/src/action-result.js +46 -15
  19. package/dist/src/action.d.ts +5 -2
  20. package/dist/src/action.js +53 -18
  21. package/dist/src/ai/captain/web-mode.js +1 -2
  22. package/dist/src/ai/captain.d.ts +20 -0
  23. package/dist/src/ai/captain.js +10 -1
  24. package/dist/src/ai/driller.js +6 -2
  25. package/dist/src/ai/fisherman-tools.d.ts +40 -1
  26. package/dist/src/ai/fisherman-tools.js +39 -0
  27. package/dist/src/ai/fisherman.js +2 -1
  28. package/dist/src/ai/navigator.d.ts +28 -0
  29. package/dist/src/ai/navigator.js +223 -175
  30. package/dist/src/ai/pilot.d.ts +7 -4
  31. package/dist/src/ai/pilot.js +89 -30
  32. package/dist/src/ai/planner/subpages.js +2 -16
  33. package/dist/src/ai/planner.js +1 -1
  34. package/dist/src/ai/provider.d.ts +2 -2
  35. package/dist/src/ai/provider.js +28 -22
  36. package/dist/src/ai/researcher/cache.d.ts +10 -3
  37. package/dist/src/ai/researcher/cache.js +23 -10
  38. package/dist/src/ai/researcher/deep-analysis.js +1 -1
  39. package/dist/src/ai/researcher/fingerprint-worker.js +21 -4
  40. package/dist/src/ai/researcher.js +6 -4
  41. package/dist/src/ai/rules.js +1 -5
  42. package/dist/src/ai/session-analyst.js +2 -0
  43. package/dist/src/ai/tester.d.ts +6 -3
  44. package/dist/src/ai/tester.js +30 -35
  45. package/dist/src/ai/tools.d.ts +8 -5
  46. package/dist/src/ai/tools.js +83 -57
  47. package/dist/src/commands/config-command.d.ts +51 -0
  48. package/dist/src/commands/config-command.js +117 -0
  49. package/dist/src/commands/index.js +2 -0
  50. package/dist/src/commands/init-command.js +13 -20
  51. package/dist/src/config.d.ts +8 -1
  52. package/dist/src/config.js +43 -1
  53. package/dist/src/experience-tracker.d.ts +2 -0
  54. package/dist/src/experience-tracker.js +12 -0
  55. package/dist/src/explorbot.js +5 -2
  56. package/dist/src/playwright-recorder.js +6 -12
  57. package/dist/src/remote.d.ts +3 -2
  58. package/dist/src/remote.js +8 -2
  59. package/dist/src/state-manager.d.ts +1 -1
  60. package/dist/src/state-manager.js +3 -1
  61. package/dist/src/test-plan.d.ts +9 -0
  62. package/dist/src/test-plan.js +30 -0
  63. package/dist/src/utils/html-diff.d.ts +5 -0
  64. package/dist/src/utils/html-diff.js +65 -6
  65. package/dist/src/utils/logger.d.ts +1 -1
  66. package/dist/src/utils/logger.js +8 -0
  67. package/dist/src/utils/strings.d.ts +2 -0
  68. package/dist/src/utils/strings.js +32 -0
  69. package/dist/src/utils/url-matcher.d.ts +1 -0
  70. package/dist/src/utils/url-matcher.js +31 -2
  71. package/docs/basics/getting-started.md +33 -10
  72. package/docs/basics/providers.md +6 -4
  73. package/docs/contributing/npm-package.md +73 -4
  74. package/docs/index.json +2 -1
  75. package/docs/reference/commands.md +3 -0
  76. package/docs/reference/websocket.md +50 -0
  77. package/docs/superpowers/specs/2026-08-18-prima-false-verdicts.md +159 -0
  78. package/models.json +4 -4
  79. package/package.json +6 -2
  80. package/src/action-result.ts +61 -16
  81. package/src/action.ts +56 -18
  82. package/src/ai/captain/web-mode.ts +1 -2
  83. package/src/ai/captain.ts +9 -1
  84. package/src/ai/driller.ts +6 -2
  85. package/src/ai/fisherman-tools.ts +35 -0
  86. package/src/ai/fisherman.ts +2 -1
  87. package/src/ai/navigator.ts +238 -179
  88. package/src/ai/pilot.ts +104 -36
  89. package/src/ai/planner/subpages.ts +2 -13
  90. package/src/ai/planner.ts +1 -1
  91. package/src/ai/provider.ts +29 -21
  92. package/src/ai/researcher/cache.ts +29 -11
  93. package/src/ai/researcher/deep-analysis.ts +1 -1
  94. package/src/ai/researcher/fingerprint-worker.ts +23 -5
  95. package/src/ai/researcher.ts +6 -4
  96. package/src/ai/rules.ts +1 -5
  97. package/src/ai/session-analyst.ts +2 -0
  98. package/src/ai/tester.ts +33 -34
  99. package/src/ai/tools.ts +88 -61
  100. package/src/commands/config-command.ts +146 -0
  101. package/src/commands/index.ts +2 -0
  102. package/src/commands/init-command.ts +14 -20
  103. package/src/config.ts +47 -2
  104. package/src/experience-tracker.ts +13 -0
  105. package/src/explorbot.ts +4 -2
  106. package/src/playwright-recorder.ts +6 -11
  107. package/src/remote.ts +8 -2
  108. package/src/state-manager.ts +5 -2
  109. package/src/test-plan.ts +38 -0
  110. package/src/utils/html-diff.ts +72 -7
  111. package/src/utils/logger.ts +9 -1
  112. package/src/utils/strings.ts +36 -0
  113. package/src/utils/url-matcher.ts +27 -2
@@ -13,7 +13,7 @@ import { mdq } from "../utils/markdown-query.js";
13
13
  import { RulesLoader } from "../utils/rules-loader.js";
14
14
  import { annotatePageElements } from "../utils/web-annotate.js";
15
15
  import { ContextLengthError } from './provider.js';
16
- import { findSimilarResearch, getCachedResearch, saveResearch } from "./researcher/cache.js";
16
+ import { findSimilarResearch, getCachedResearch, reportResearch, saveResearch } from "./researcher/cache.js";
17
17
  import { WithCoordinates } from "./researcher/coordinates.js";
18
18
  import { WithDeepAnalysis } from "./researcher/deep-analysis.js";
19
19
  import { detectFocusedSection, hasFocusedSection, markSectionAsFocused, pickDefaultFocusedSection } from "./researcher/focus.js";
@@ -72,10 +72,12 @@ export class Researcher extends ResearcherBase {
72
72
  let retriesLeft = opts._retriesLeft ?? maxRetries;
73
73
  this.actionResult = ActionResult.fromState(state);
74
74
  const stateHash = state.hash || this.actionResult.getStateHash();
75
+ const researchState = { ...state, hash: stateHash };
75
76
  if (!force && stateHash) {
76
77
  const cached = getCachedResearch(stateHash);
77
78
  if (cached) {
78
79
  debugLog('Previous research result found');
80
+ reportResearch(stateHash, cached);
79
81
  return cached;
80
82
  }
81
83
  }
@@ -104,11 +106,11 @@ export class Researcher extends ResearcherBase {
104
106
  debugLog('Researching web page:', this.actionResult.url);
105
107
  const combinedHtml = await this.actionResult.combinedHtml();
106
108
  if (!deep && !force) {
107
- const similar = await findSimilarResearch(combinedHtml);
109
+ const similar = await findSimilarResearch(combinedHtml, state.url);
108
110
  if (similar) {
109
111
  tag('operation').log('Similar research found, reusing cached result');
110
112
  if (stateHash)
111
- saveResearch(stateHash, similar, combinedHtml);
113
+ saveResearch(researchState, similar, combinedHtml);
112
114
  tag('multiline').log(formatResearchSummary(similar));
113
115
  tag('success').log('Research complete (reused)');
114
116
  await this.hooksRunner.runAfterHook('researcher', state.url);
@@ -237,7 +239,7 @@ export class Researcher extends ResearcherBase {
237
239
  result.cleanup();
238
240
  let researchFile = null;
239
241
  if (stateHash) {
240
- researchFile = saveResearch(stateHash, result.text, combinedHtml);
242
+ researchFile = saveResearch(researchState, result.text, combinedHtml);
241
243
  }
242
244
  const summaryText = mdq(result.text).query('section2(/^summary/)').query('paragraph[0]').text().trim();
243
245
  const summaryLine = summaryText.split('\n')[0]?.trim().slice(0, 200);
@@ -2,10 +2,6 @@ import dedent from 'dedent';
2
2
  export const recommendedCodeceptCommands = ['I.click', 'I.type', 'I.fillField', 'I.see', 'I.seeElement'];
3
3
  const locatorPriorityRule = dedent `
4
4
  <locator_priority>
5
- When the page context shows the element a ref, such as [ref=e14], there is no locator to select: click it with clickRef
6
- and that ref. A ref names one exact element, so it never matches the wrong one and never has to be narrowed. Everything
7
- below is for elements the context gives no ref for.
8
-
9
5
  Use the following priority when selecting locators:
10
6
 
11
7
  1. ARIA locators (first choice) - target browser's accessibility tree, most reliable
@@ -76,7 +72,7 @@ const locatorStrategyRule = dedent `
76
72
 
77
73
  NEVER include \`eidx\` attribute in any locator (ARIA, CSS, XPath). It is an internal annotation.
78
74
 
79
- If <aria> section is not present or element is not found there, fall back to CSS/XPath locators from <html> section.
75
+ If the element is not found in the ARIA snapshot, fall back to CSS/XPath locators from page HTML.
80
76
 
81
77
  Stick to semantic attributes like role, aria-*, id, class, name, data-id, etc.
82
78
  Avoid IDs that follow framework auto-generation patterns (these change on every page load):
@@ -3,6 +3,7 @@ import path from 'node:path';
3
3
  import dedent from 'dedent';
4
4
  import { outputPath } from "../config.js";
5
5
  import { Stats } from "../stats.js";
6
+ import { tag } from "../utils/logger.js";
6
7
  export class SessionAnalyst {
7
8
  emoji = '🧐';
8
9
  provider;
@@ -103,6 +104,7 @@ export class SessionAnalyst {
103
104
  if (!existsSync(dir))
104
105
  mkdirSync(dir, { recursive: true });
105
106
  writeFileSync(filePath, markdown);
107
+ tag('data').log('report', { path: filePath, content: markdown });
106
108
  return filePath;
107
109
  }
108
110
  serializeTest(test, ref) {
@@ -11,6 +11,7 @@ import { Researcher } from './researcher.js';
11
11
  import { TaskAgent } from './task-agent.js';
12
12
  export declare class Tester extends TaskAgent implements Agent {
13
13
  readonly ACTION_TOOLS: string[];
14
+ readonly DELEGATED_ACTION_TOOLS: string[];
14
15
  readonly SPECIAL_CONTEXT_ACTION_TOOLS: string[];
15
16
  emoji: string;
16
17
  requestStore: RequestStore;
@@ -39,17 +40,16 @@ export declare class Tester extends TaskAgent implements Agent {
39
40
  getCurrentState(): ActionResult;
40
41
  get progressCheckInterval(): number;
41
42
  getConversation(): Conversation | null;
42
- test(task: Test): Promise<{
43
+ test(task: Test, opts?: TestOptions): Promise<{
43
44
  success: boolean;
44
45
  }>;
45
- runTestSession(task: Test, initialState: ActionResult, conversation: Conversation, handlers: TestSessionHandlers): Promise<{
46
+ runTestSession(task: Test, initialState: ActionResult, conversation: Conversation, handlers: TestSessionHandlers, opts: TestOptions): Promise<{
46
47
  success: boolean;
47
48
  }>;
48
49
  shouldAnalyzeProgress(iteration: number, currentState: ActionResult): boolean;
49
50
  shouldStopForStalledExecution(task: Test, previousState: ActionResult, toolExecutions: any[]): boolean;
50
51
  prepareInstructionsForNextStep(task: Test): Promise<string>;
51
52
  reinjectContextIfNeeded(iteration: number, currentState: ActionResult): Promise<string>;
52
- interactiveAriaWithRefs(state: ActionResult): Promise<string>;
53
53
  finishTest(task: Test): void;
54
54
  abortStartedTestOnErrorPage(task: Test, actionResult: ActionResult): Promise<{
55
55
  success: boolean;
@@ -93,4 +93,7 @@ export declare class Tester extends TaskAgent implements Agent {
93
93
  interface TestSessionHandlers {
94
94
  offFailedRequest?: () => void;
95
95
  }
96
+ export interface TestOptions {
97
+ startOnCurrentPage?: boolean;
98
+ }
96
99
  export {};
@@ -8,10 +8,11 @@ import { clearActivity, setActivity } from "../activity.js";
8
8
  import { Observability } from "../observability.js";
9
9
  import { Stats } from "../stats.js";
10
10
  import { TestResult } from "../test-plan.js";
11
- import { compactAriaSnapshot, detectFocusArea } from "../utils/aria.js";
11
+ import { detectFocusArea } from "../utils/aria.js";
12
12
  import { ErrorPageError, isErrorPage } from "../utils/error-page.js";
13
13
  import { createDebug, tag } from "../utils/logger.js";
14
14
  import { loop } from "../utils/loop.js";
15
+ import { compactErrorMessage } from "../utils/strings.js";
15
16
  import { actionRule, capabilityGroundingRule, dataProtectionRules, focusedElementRule, formRequirementsRule, locatorRule, multipleTabsRule, sectionContextRule } from "./rules.js";
16
17
  import { TaskAgent } from "./task-agent.js";
17
18
  import { createCodeceptJSTools, createIframeTools, withdrawVisionTools } from "./tools.js";
@@ -28,6 +29,7 @@ const SAMPLE_FILES = {
28
29
  };
29
30
  export class Tester extends TaskAgent {
30
31
  ACTION_TOOLS = ['click', 'hover', 'pressKey', 'form'];
32
+ DELEGATED_ACTION_TOOLS = ['interact'];
31
33
  SPECIAL_CONTEXT_ACTION_TOOLS = ['exitIframe'];
32
34
  emoji = '🧪';
33
35
  requestStore;
@@ -74,7 +76,7 @@ export class Tester extends TaskAgent {
74
76
  getConversation() {
75
77
  return this.currentConversation;
76
78
  }
77
- async test(task) {
79
+ async test(task, opts = {}) {
78
80
  Stats.tests++;
79
81
  const state = this.stateManager.getCurrentState();
80
82
  if (!state)
@@ -120,9 +122,9 @@ export class Tester extends TaskAgent {
120
122
  startUrl: task.startUrl,
121
123
  expected: task.expected,
122
124
  },
123
- }, async () => this.runTestSession(task, initialState, conversation, { offFailedRequest }));
125
+ }, async () => this.runTestSession(task, initialState, conversation, { offFailedRequest }, opts));
124
126
  }
125
- async runTestSession(task, initialState, conversation, handlers) {
127
+ async runTestSession(task, initialState, conversation, handlers, opts) {
126
128
  const { offFailedRequest } = handlers;
127
129
  if (this.pilot) {
128
130
  try {
@@ -151,16 +153,20 @@ export class Tester extends TaskAgent {
151
153
  await this.cleanupStartedTest(task);
152
154
  return { success: task.isSuccessful };
153
155
  }
154
- debugLog(`Navigating to ${task.startUrl}`);
155
- try {
156
- await this.explorer.visit(task.startUrl);
157
- }
158
- catch (error) {
159
- const result = await this.handleLoopError(task, error);
160
- if (result === 'stop') {
161
- offFailedRequest?.();
162
- await this.cleanupStartedTest(task);
163
- return { success: task.isSuccessful };
156
+ if (opts.startOnCurrentPage)
157
+ debugLog(`Starting on the page already open at ${task.startUrl}`);
158
+ if (!opts.startOnCurrentPage) {
159
+ debugLog(`Navigating to ${task.startUrl}`);
160
+ try {
161
+ await this.explorer.visit(task.startUrl);
162
+ }
163
+ catch (error) {
164
+ const result = await this.handleLoopError(task, error);
165
+ if (result === 'stop') {
166
+ offFailedRequest?.();
167
+ await this.cleanupStartedTest(task);
168
+ return { success: task.isSuccessful };
169
+ }
164
170
  }
165
171
  }
166
172
  const startState = this.stateManager.getCurrentState();
@@ -228,8 +234,6 @@ export class Tester extends TaskAgent {
228
234
  `);
229
235
  }
230
236
  conversation.cleanupTag('page_aria', '...cleaned aria snapshot...', 1);
231
- conversation.cleanupTag('page_html', '...cleaned HTML snapshot...', 1);
232
- conversation.cleanupTag('experience', '...cleaned experience...', 1);
233
237
  conversation.cleanupTag('applied_experience', '...cleaned past experience...', 1);
234
238
  conversation.cleanupTag('page_ui_map', '...cleaned UI map...', 1);
235
239
  conversation.cleanupTag('page_ui_map_overlay', '...cleaned UI overlay...', 1);
@@ -355,8 +359,6 @@ export class Tester extends TaskAgent {
355
359
  this.stalledIterations = 0;
356
360
  tag('info').log(`Pilot extending test (${extensions}/${this.MAX_EXTENSIONS})`);
357
361
  conversation.cleanupTag('page_aria', '...trimmed...', 1);
358
- conversation.cleanupTag('page_html', '...trimmed...', 0);
359
- conversation.cleanupTag('experience', '...trimmed...', 0);
360
362
  conversation.cleanupTag('page_ui_map', '...trimmed...', 0);
361
363
  conversation.cleanupTag('page_ui_map_overlay', '...trimmed...', 0);
362
364
  conversation.compactToolResults(1);
@@ -394,7 +396,7 @@ export class Tester extends TaskAgent {
394
396
  return false;
395
397
  const currentState = this.getCurrentState();
396
398
  const stateChanged = previousState.url !== currentState.url || previousState.hash !== currentState.hash;
397
- const actionTools = [...this.ACTION_TOOLS, ...this.SPECIAL_CONTEXT_ACTION_TOOLS];
399
+ const actionTools = [...this.ACTION_TOOLS, ...this.DELEGATED_ACTION_TOOLS, ...this.SPECIAL_CONTEXT_ACTION_TOOLS];
398
400
  const hasSuccessfulAction = toolExecutions.some((execution) => execution.wasSuccessful && actionTools.includes(execution.toolName));
399
401
  const hasSuccessfulAssertion = toolExecutions.some((execution) => execution.wasSuccessful && this.ASSERTION_TOOLS.includes(execution.toolName));
400
402
  if (stateChanged || hasSuccessfulAction || hasSuccessfulAssertion) {
@@ -418,6 +420,7 @@ export class Tester extends TaskAgent {
418
420
 
419
421
  <rules>
420
422
  Use tools ${this.ACTION_TOOLS.join(', ')} to interact with the page.
423
+ Fall back to interact() when those fail, when the step needs a sequence of actions, or when your context is not enough to locate the element.
421
424
  Use tool names exactly as listed in this prompt. Do not invent combined tool names, aliases, or names with channel markers such as "commentary".
422
425
  Match each tool input schema exactly. Do not invent parameter names or pass extra fields.
423
426
  Do not do unsuccesful clicks again.
@@ -528,13 +531,13 @@ export class Tester extends TaskAgent {
528
531
  </page>
529
532
 
530
533
  <page_aria>
531
- ${await this.interactiveAriaWithRefs(currentState)}
534
+ ${currentState.getInteractiveARIA()}
532
535
  </page_aria>
533
536
  ${uiMapSection}
534
537
 
535
538
  Use <page_ui_map> to understand the page structure and its main elements.
536
- However, <page_ui_map> is not always up to date, use <page_aria> and <page_html> to understand the ACTUAL state of the page
537
- Do not interact with elements that are not listed in <page_aria> and <page_html>
539
+ However, <page_ui_map> is not always up to date, use <page_aria> to understand the ACTUAL state of the page
540
+ Do not interact with elements that are not listed in <page_aria> or in HTML returned by tools
538
541
  Refer to information on page sections in <page_ui_map> and use container CSS locators to interact with elements inside sections
539
542
  `;
540
543
  return context;
@@ -563,16 +566,10 @@ export class Tester extends TaskAgent {
563
566
  </page>
564
567
 
565
568
  <page_aria>
566
- ${await this.interactiveAriaWithRefs(currentState)}
569
+ ${currentState.getInteractiveARIA()}
567
570
  </page_aria>
568
571
  `;
569
572
  }
570
- async interactiveAriaWithRefs(state) {
571
- const withRefs = await Promise.resolve(this.explorer?.withPage?.((page) => page.locator('body').ariaSnapshot({ mode: 'ai' }))).catch(() => null);
572
- if (!withRefs)
573
- return state.getInteractiveARIA();
574
- return compactAriaSnapshot(withRefs, false);
575
- }
576
573
  finishTest(task) {
577
574
  if (!task.result) {
578
575
  if (task.hasAchievedAll())
@@ -642,7 +639,7 @@ export class Tester extends TaskAgent {
642
639
 
643
640
  <rules>
644
641
  - Refer to UI Map from <page_ui_map> to understand the page structure and its main elements
645
- - Use only elements that exist in the provided ARIA tree or HTML, <page_aria> and <page_html>
642
+ - Use only elements that exist in <page_aria> or in HTML returned by tools
646
643
  - Use tool input schemas exactly as documented. Do not invent parameter names or add fields not listed by the tool schema.
647
644
  - Use click() for buttons, links, and clickable elements ONLY - do NOT include I.fillField() or I.type() commands in click() tool
648
645
  - click() commands array is for FALLBACK LOCATORS of the SAME element, NOT for clicking different elements in sequence. If you need to click two different elements, make two separate click() calls.
@@ -665,7 +662,8 @@ export class Tester extends TaskAgent {
665
662
  - Check for error messages to understand if there are issues
666
663
  - Verify if data was correctly saved and changes are reflected on the page
667
664
  - By default, you receive accessibility tree data which shows interactive elements and page structure
668
- - Understand current context by following <page_html>, <page_aria>, and <page_ui_map>
665
+ - Full page HTML is never injected automatically. When ARIA is not enough, delegate to the tools that read it: verify() to assert, interact() to act
666
+ - Understand current context by following <page_aria> and <page_ui_map>
669
667
  - Before submitting form, check all inputs were filled in correctly using see() tool
670
668
  - When you interact with form with inputs, ensure that you click corresponding button to save its data
671
669
  - Follow <locator_priority> rules when selecting locators for all tools
@@ -716,7 +714,6 @@ export class Tester extends TaskAgent {
716
714
  }
717
715
  buildScenarioBlock(task, actionResult) {
718
716
  const knowledge = this.getKnowledge(actionResult);
719
- const experience = this.getExperience(actionResult);
720
717
  return dedent `
721
718
  <task>
722
719
  SCENARIO GOAL: ${task.scenario}
@@ -745,8 +742,6 @@ export class Tester extends TaskAgent {
745
742
  ${this.buildAvailableFiles()}
746
743
 
747
744
  ${knowledge}
748
-
749
- ${experience}
750
745
  `;
751
746
  }
752
747
  getDeletableSessionNames(task) {
@@ -856,7 +851,7 @@ export class Tester extends TaskAgent {
856
851
  explanation,
857
852
  };
858
853
  if (resetAction.lastError) {
859
- result.error = resetAction.lastError.toString();
854
+ result.error = compactErrorMessage(resetAction.lastError);
860
855
  }
861
856
  return result;
862
857
  },
@@ -1,5 +1,5 @@
1
1
  import { ActionResult, type PageDiff } from '../action-result.js';
2
- import type { ExperienceTracker } from '../experience-tracker.js';
2
+ import { type ExperienceTracker } from '../experience-tracker.js';
3
3
  import { type Task } from '../test-plan.js';
4
4
  import type { ToolDeps } from './agent.js';
5
5
  import { Navigator } from './navigator.js';
@@ -16,10 +16,6 @@ export declare function createCodeceptJSTools({ explorer, stateManager, ai }: To
16
16
  commands: any;
17
17
  explanation: any;
18
18
  }, Record<string, any>, import("@ai-sdk/provider-utils").Context>>;
19
- clickRef: import("@ai-sdk/provider-utils").ExecutableTool<import("ai").Tool<{
20
- ref: any;
21
- element: any;
22
- }, Record<string, any>, import("@ai-sdk/provider-utils").Context>>;
23
19
  hover: import("@ai-sdk/provider-utils").ExecutableTool<import("ai").Tool<{
24
20
  commands: any;
25
21
  explanation: any;
@@ -34,6 +30,12 @@ export declare function createCodeceptJSTools({ explorer, stateManager, ai }: To
34
30
  explanation: any;
35
31
  }, Record<string, any>, import("@ai-sdk/provider-utils").Context>>;
36
32
  };
33
+ export declare function createRefTools({ explorer, stateManager }: ToolDeps, task: Task): {
34
+ clickRef: import("@ai-sdk/provider-utils").ExecutableTool<import("ai").Tool<{
35
+ ref: any;
36
+ element: any;
37
+ }, Record<string, any>, import("@ai-sdk/provider-utils").Context>>;
38
+ };
37
39
  export declare function createIframeTools({ explorer, stateManager }: ToolDeps): {
38
40
  exitIframe: import("@ai-sdk/provider-utils").ExecutableTool<import("ai").Tool<{
39
41
  reason?: string;
@@ -59,6 +61,7 @@ export declare function successToolResult(action: string, data?: Record<string,
59
61
  assertionSteps?: any[];
60
62
  }): Record<string, any>;
61
63
  export declare function isMajorPageChange(pageDiff: PageDiff): boolean;
64
+ export declare function hasFailedRequest(pageDiff: PageDiff): boolean;
62
65
  export declare function failedToolResult(action: string, message: string, data?: Record<string, any>, error?: Error | null): Promise<Record<string, any>>;
63
66
  export declare function withdrawVisionTools(tools: Record<string, any>): void;
64
67
  export declare function clickFailureSuggestion(attempts: Array<{