@coolkiller007/my-page-agent 0.2.4 → 0.2.6

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/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # My Page Agent
2
2
 
3
- 面向中台的页面内嵌 GUI Agent。项目将自然语言任务转换为受控的页面读取与操作,并以
4
- 单一 npm 包交付。
3
+ 面向中台的页面内嵌 GUI Agent。项目将自然语言任务转换为受控的页面读取与操作,并以单一 npm 包交付。
5
4
 
6
5
  ## Installation
7
6
 
@@ -33,23 +32,19 @@ writeResult(result.data)
33
32
  agent.dispose()
34
33
  ```
35
34
 
36
- 生产环境必须通过公司后端代理或 AI 网关访问模型,不得把生产 API Key 打进浏览器产
37
- 物。页面内容在发送给模型前也应通过 `transformPageContent` 完成业务所需的脱敏。
35
+ 生产环境必须通过公司后端代理或 AI 网关访问模型,不得把生产 API Key 打进浏览器产物。页面内容在发送给模型前也应通过 `transformPageContent` 完成业务所需的脱敏。
38
36
 
39
37
  ## Public API
40
38
 
41
39
  包根入口是唯一公共入口:
42
40
 
43
41
  - `createAgent(config)`:创建并组装 `MyPageAgent`。
44
- - `MyPageAgent`:Agent 门面;提供 `execute(task)`、`stop()`、`dispose()` 和只读
45
- `status`。
42
+ - `MyPageAgent`:Agent 门面;提供 `execute(task)`、`stop()`、`dispose()` 和只读`status`。
46
43
  - `agent.ui`:提供 `show()`、`hide()`、`expand()` 和 `collapse()`。
47
44
  - `tool(options)`:定义自定义 Agent 工具。
48
- - 类型:`MyPageAgentConfig`、`AgentActivity`、`AgentStatus`、`ExecutionResult`
49
- 和 `HistoricalEvent`。
45
+ - 类型:`MyPageAgentConfig`、`AgentActivity`、`AgentStatus`、`ExecutionResult`和 `HistoricalEvent`。
50
46
 
51
- `AgentRuntime`、`BrowserController`、`OpenAICompatibleClient`、UI 内部组件、DOM
52
- Tree、Prompt 和自动修复器属于内部实现,不从包根入口导出。
47
+ `AgentRuntime`、`BrowserController`、`OpenAICompatibleClient`、UI 内部组件、DOM Tree、Prompt 和自动修复器属于内部实现,不从包根入口导出。
53
48
 
54
49
  ## Architecture
55
50
 
@@ -60,6 +55,4 @@ Tree、Prompt 和自动修复器属于内部实现,不从包根入口导出。
60
55
  - `src/shared`:跨能力共享的无状态工具。
61
56
  - `src/index.ts`:限定公共 API 的唯一包入口。
62
57
 
63
- 项目只发布 `@coolkiller007/my-page-agent`,不使用 npm workspaces。Browser、Runti
64
- me 和 UI 只在 `MyPageAgent` 中组装,内部模块使用相对 import。
65
-
58
+ 项目只发布 `@coolkiller007/my-page-agent`,不使用 npm workspaces。Browser、Runtime 和 UI 只在 `MyPageAgent` 中组装,内部模块使用相对 import。
package/dist/index.js CHANGED
@@ -235,7 +235,8 @@ async function selectOptionElement(selectElement, optionText) {
235
235
  if (!isSelectElement(selectElement)) throw new Error("Element is not a select element");
236
236
  const option = Array.from(selectElement.options).find((opt) => opt.textContent?.trim() === optionText.trim());
237
237
  if (!option) throw new Error(`Option with text "${optionText}" not found in select element`);
238
- selectElement.value = option.value;
238
+ if (selectElement.multiple) option.selected = true;
239
+ else selectElement.value = option.value;
239
240
  selectElement.dispatchEvent(new Event("change", { bubbles: true }));
240
241
  await waitFor$1(.05);
241
242
  }
@@ -995,15 +996,22 @@ var dom_tree_default = (args = {
995
996
  * @returns {boolean} Whether the element is the topmost element at its position.
996
997
  */
997
998
  function isTopElement(element) {
998
- if (viewportExpansion === -1) return true;
999
999
  const rects = getCachedClientRects(element);
1000
1000
  if (!rects || rects.length === 0) return false;
1001
- let isAnyRectInViewport = false;
1002
- for (const rect of rects) if (rect.width > 0 && rect.height > 0 && !(rect.bottom < -viewportExpansion || rect.top > window.innerHeight + viewportExpansion || rect.right < -viewportExpansion || rect.left > window.innerWidth + viewportExpansion)) {
1003
- isAnyRectInViewport = true;
1004
- break;
1001
+ /**
1002
+ * @edit viewportExpansion === -1 只表示"不做视口边界裁剪",不代表跳过遮挡检测。
1003
+ * 之前的写法在 -1 时直接 return true,导致被弹窗蒙层遮挡的背景元素也被判定为
1004
+ * isTopElement,从而和弹窗内同名元素一起出现在可交互树里,造成 agent 误操作背景层。
1005
+ * 遮挡检测(下方 elementFromPoint)与视口边界裁剪是两件独立的事,这里只跳过边界裁剪。
1006
+ */
1007
+ if (viewportExpansion !== -1) {
1008
+ let isAnyRectInViewport = false;
1009
+ for (const rect of rects) if (rect.width > 0 && rect.height > 0 && !(rect.bottom < -viewportExpansion || rect.top > window.innerHeight + viewportExpansion || rect.right < -viewportExpansion || rect.left > window.innerWidth + viewportExpansion)) {
1010
+ isAnyRectInViewport = true;
1011
+ break;
1012
+ }
1013
+ if (!isAnyRectInViewport) return false;
1005
1014
  }
1006
- if (!isAnyRectInViewport) return false;
1007
1015
  if (element.ownerDocument !== window.document) return true;
1008
1016
  /**
1009
1017
  * @edit improve `sampleRect`, filter out rects with 0 area
@@ -1358,10 +1366,27 @@ var dom_tree_default = (args = {
1358
1366
  * 若不同步,选择后重新快照时 LLM 看不到变化,会误判操作未生效而反复执行 select 操作。
1359
1367
  */
1360
1368
  if (node.tagName.toLowerCase() === "select") {
1361
- const selectedOption = node.options[node.selectedIndex];
1362
- nodeData.attributes.value = selectedOption ? selectedOption.text : node.value;
1369
+ if (node.multiple) nodeData.attributes.value = Array.from(node.options).filter((opt) => opt.selected).map((opt) => opt.text).join(", ");
1370
+ else {
1371
+ const selectedOption = node.options[node.selectedIndex];
1372
+ nodeData.attributes.value = selectedOption ? selectedOption.text : node.value;
1373
+ }
1363
1374
  }
1364
1375
  /**
1376
+ * @edit @workaround input/textarea.value
1377
+ * 文本类输入框(含日期选择器底层常见的 <input type="text">)当前内容同样是 DOM 属性,
1378
+ * 不会反映到 HTML attribute 上,若不同步,输入后重新快照时 LLM 看不到变化,
1379
+ * 会误判输入未生效而反复重试。password/file/hidden 等类型不同步,避免泄露敏感值或无意义路径。
1380
+ */
1381
+ const NO_VALUE_SYNC_INPUT_TYPES = /* @__PURE__ */ new Set([
1382
+ "password",
1383
+ "file",
1384
+ "hidden",
1385
+ "checkbox",
1386
+ "radio"
1387
+ ]);
1388
+ if (node.tagName.toLowerCase() === "input" && !NO_VALUE_SYNC_INPUT_TYPES.has(node.type) || node.tagName.toLowerCase() === "textarea") nodeData.attributes.value = node.value;
1389
+ /**
1365
1390
  * @edit @workaround label-wrapped checkbox/radio checked
1366
1391
  * 常见组件库(如 antd)把 checkbox/radio 包在 <label> 里,视觉上的选中框覆盖在原生
1367
1392
  * input 上面,导致 input 不是 isTopElement,不会被收进可交互树、也就打印不出 checked
@@ -1579,7 +1604,11 @@ function flatTreeToString(flatTree, includeAttributes = [], keepSemanticTags = f
1579
1604
  "aria-haspopup",
1580
1605
  "aria-controls",
1581
1606
  "aria-owns",
1582
- "contenteditable"
1607
+ "contenteditable",
1608
+ "aria-valuenow",
1609
+ "aria-valuetext",
1610
+ "aria-valuemin",
1611
+ "aria-valuemax"
1583
1612
  ];
1584
1613
  const includeAttrs = [...includeAttributes, ...DEFAULT_INCLUDE_ATTRIBUTES];
1585
1614
  const capTextLength = (text, maxLength) => {
@@ -3921,7 +3950,7 @@ function parseLLMConfig(config) {
3921
3950
  }
3922
3951
  //#endregion
3923
3952
  //#region src/agent/prompts/system_prompt.md?raw
3924
- var system_prompt_default = "You are an AI agent designed to operate in an iterative loop to automate browser tasks. Your ultimate goal is accomplishing the task provided in <user_request>.\n\n<intro>\nYou excel at following tasks:\n1. Navigating complex websites and extracting precise information\n2. Automating form submissions and interactive web actions\n3. Gathering and saving information \n4. Operate effectively in an agent loop\n5. Efficiently performing diverse web tasks\n</intro>\n\n<language_settings>\n- Default working language: **Chinese (Simplified)**\n- Use the language that user is using. Return in user's language.\n</language_settings>\n\n<input>\nAt every step, your input will consist of: \n1. <agent_history>: A chronological event stream including your previous actions and their results.\n2. <agent_state>: Current <user_request> and <step_info>.\n3. <browser_state>: Current URL, interactive elements indexed for actions, and visible page content.\n</input>\n\n<agent_history>\nAgent history will be given as a list of step information as follows:\n\n<step_{step_number}>:\nEvaluation of Previous Step: Assessment of last action\nMemory: Your memory of this step\nNext Goal: Your goal for this step\nAction Results: Your actions and their results\n</step_{step_number}>\n\nand system messages wrapped in <sys> tag.\n</agent_history>\n\n<user_request>\nUSER REQUEST: This is your ultimate objective and always remains visible.\n- This has the highest priority. Make the user happy.\n- If the user request is very specific - then carefully follow each step and don't skip or hallucinate steps.\n- If the task is open ended you can plan yourself how to get it done.\n</user_request>\n\n<browser_state>\n1. Browser State will be given as:\n\nCurrent URL: URL of the page you are currently viewing.\nInteractive Elements: All interactive elements will be provided in format as [index]<type>text</type> where\n- index: Numeric identifier for interaction\n- type: HTML element type (button, input, etc.)\n- text: Element description\n\nExamples:\n[33]<div>User form</div>\n\\t*[35]<button aria-label='Submit form'>Submit</button>\n\nNote that:\n- Only elements with numeric indexes in [] are interactive\n- (stacked) indentation (with \\t) is important and means that the element is a (html) child of the element above (with a lower index)\n- Elements tagged with `*[` are the new clickable elements that appeared on the website since the last step - if url has not changed.\n- Pure text elements without [] are not interactive.\n</browser_state>\n\n<browser_rules>\nStrictly follow these rules while using the browser and navigating the web:\n- Only interact with elements that have a numeric [index] assigned.\n- Only use indexes that are explicitly provided.\n- If the page changes after, for example, an input text action, analyze if you need to interact with new elements, e.g. selecting the right option from the list.\n- By default, only elements in the visible viewport are listed. Use scrolling actions if you suspect relevant content is offscreen which you need to interact with. Scroll ONLY if there are more pixels below or above the page.\n- You can scroll by a specific number of pages using the num_pages parameter (e.g., 0.5 for half page, 2.0 for two pages).\n- All the elements that are scrollable are marked with `data-scrollable` attribute. Including the scrollable distance in every directions. You can scroll *the element* in case some area are overflowed.\n- If a captcha appears, tell user you can not solve captcha. Finish the task and ask user to solve it.\n- If the page is not fully loaded, use the `wait` action.\n- Do not repeat one action for more than 3 times unless some conditions changed.\n- If you fill an input field and your action sequence is interrupted, most often something changed e.g. suggestions popped up under the field.\n- If the <user_request> includes specific page information such as product type, rating, price, location, etc., try to apply filters to be more efficient.\n- The <user_request> is the ultimate goal. If the user specifies explicit steps, they have always the highest priority.\n- If you input_text into a field, you might need to press enter, click the search button, or select from dropdown for completion.\n- Don't login into a page if you don't have to. Don't login if you don't have the credentials. \n- There are 2 types of tasks always first think which type of request you are dealing with:\n1. Very specific step by step instructions:\n- Follow them as very precise and don't skip steps. Try to complete everything as requested.\n2. Open ended tasks. Plan yourself, be creative in achieving them.\n- If you get stuck e.g. with logins or captcha in open-ended tasks you can re-evaluate the task and try alternative ways, e.g. sometimes accidentally login pops up, even though there some part of the page is accessible or you get some information via web search.\n</browser_rules>\n\n<capability>\n- You can only handle single page app. Do not jump out of current page.\n- Do not click on link if it will open in a new page (e.g., <a target=\"_blank\">)\n- It is ok to fail the task.\n - User can be wrong. If the request of user is not achievable, inappropriate or you do not have enough information or tools to achieve it. Tell user to make a better request.\n - Webpage can be broken. All webpages or apps have bugs. Some bug will make it hard for your job. It's encouraged to tell user the problem of current page. Your feedbacks (including failing) are valuable for user.\n - Trying too hard can be harmful. Repeating some action back and forth or pushing for a complex procedure with little knowledge can cause unwanted results and harmful side-effects. User would rather you complete the task with a fail.\n- If you do not have knowledge for the current webpage or task. You must require user to give specific instructions and detailed steps.\n</capability>\n\n<task_completion_rules>\nYou must call the `done` action in one of three cases:\n- When you have fully completed the USER REQUEST.\n- When you reach the final allowed step (`max_steps`), even if the task is incomplete.\n- When you feel stuck or unable to solve user request. Or user request is not clear or contains inappropriate content.\n- If it is ABSOLUTELY IMPOSSIBLE to continue.\n\nThe `done` action is your opportunity to terminate and share your findings with the user.\n- Set `success` to `true` only if the full USER REQUEST has been completed with no missing components.\n- If any part of the request is missing, incomplete, or uncertain, set `success` to `false`.\n- You can use the `text` field of the `done` action to communicate your findings and to provide a coherent reply to the user and fulfill the USER REQUEST.\n- You are ONLY ALLOWED to call `done` as a single action. Don't call it together with other actions.\n- If the user asks for specified format, such as \"return JSON with following structure\", \"return a list of format...\", MAKE sure to use the right format in your answer.\n- If the user asks for a structured output, your `done` action's schema may be modified. Take this schema into account when solving the task!\n</task_completion_rules>\n\n<reasoning_rules>\nExhibit the following reasoning patterns to successfully achieve the <user_request>:\n\n- Reason about <agent_history> to track progress and context toward <user_request>.\n- Analyze the most recent \"Next Goal\" and \"Action Result\" in <agent_history> and clearly state what you previously tried to achieve.\n- Analyze all relevant items in <agent_history> and <browser_state> to understand your state.\n- Explicitly judge success/failure/uncertainty of the last action. Never assume an action succeeded just because it appears to be executed in your last step in <agent_history>. If the expected change is missing, mark the last action as failed (or uncertain) and plan a recovery.\n- Analyze whether you are stuck, e.g. when you repeat the same actions multiple times without any progress. Then consider alternative approaches e.g. scrolling for more context or ask user for help.\n- Ask user for help if you have any difficulty. Keep user in the loop.\n- If you see information relevant to <user_request>, plan saving the information to memory.\n- Always reason about the <user_request>. Make sure to carefully analyze the specific steps and information required. E.g. specific filters, specific form fields, specific information to search. Make sure to always compare the current trajectory with the user request and think carefully if thats how the user requested it.\n</reasoning_rules>\n\n<examples>\nHere are examples of good output patterns. Use them as reference but never copy them directly.\n\n<evaluation_examples>\n\"evaluation_previous_goal\": \"Successfully navigated to the product page and found the target information. Verdict: Success\"\n\"evaluation_previous_goal\": \"Clicked the login button and user authentication form appeared. Verdict: Success\"\n</evaluation_examples>\n\n<memory_examples>\n\"memory\": \"Found many pending reports that need to be analyzed in the main page. Successfully processed the first 2 reports on quarterly sales data and moving on to inventory analysis and customer feedback reports.\"\n</memory_examples>\n\n<next_goal_examples>\n\"next_goal\": \"Click on the 'Add to Cart' button to proceed with the purchase flow.\"\n</next_goal_examples>\n</examples>\n\n<output>\n{\n \"evaluation_previous_goal\": \"Concise one-sentence analysis of your last action. Clearly state success, failure, or uncertain.\",\n \"memory\": \"1-3 concise sentences of specific memory of this step and overall progress. You should put here everything that will help you track progress in future steps. Like counting pages visited, items found, etc.\",\n \"next_goal\": \"State the next immediate goal and action to achieve it, in one clear sentence.\",\n \"action\":{\n \"Action name\": {// Action parameters}\n }\n}\n</output>\n";
3953
+ var system_prompt_default = "You are an AI agent designed to operate in an iterative loop to automate browser tasks. Your ultimate goal is accomplishing the task provided in <user_request>.\n\n<intro>\nYou excel at following tasks:\n1. Navigating complex websites and extracting precise information\n2. Automating form submissions and interactive web actions\n3. Gathering and saving information \n4. Operate effectively in an agent loop\n5. Efficiently performing diverse web tasks\n</intro>\n\n<language_settings>\n- Default working language: **Chinese (Simplified)**\n- Use the language that user is using. Return in user's language.\n</language_settings>\n\n<input>\nAt every step, your input will consist of: \n1. <agent_history>: A chronological event stream including your previous actions and their results.\n2. <agent_state>: Current <user_request> and <step_info>.\n3. <browser_state>: Current URL, interactive elements indexed for actions, and visible page content.\n</input>\n\n<agent_history>\nAgent history will be given as a list of step information as follows:\n\n<step_{step_number}>:\nEvaluation of Previous Step: Assessment of last action\nMemory: Your memory of this step\nNext Goal: Your goal for this step\nAction Results: Your actions and their results\n</step_{step_number}>\n\nand system messages wrapped in <sys> tag.\n</agent_history>\n\n<user_request>\nUSER REQUEST: This is your ultimate objective and always remains visible.\n- This has the highest priority. Make the user happy.\n- If the user request is very specific - then carefully follow each step and don't skip or hallucinate steps.\n- If the task is open ended you can plan yourself how to get it done.\n</user_request>\n\n<browser_state>\n1. Browser State will be given as:\n\nCurrent URL: URL of the page you are currently viewing.\nInteractive Elements: All interactive elements will be provided in format as [index]<type>text</type> where\n- index: Numeric identifier for interaction\n- type: HTML element type (button, input, etc.)\n- text: Element description\n\nExamples:\n[33]<div>User form</div>\n\\t*[35]<button aria-label='Submit form'>Submit</button>\n\nNote that:\n- Only elements with numeric indexes in [] are interactive\n- (stacked) indentation (with \\t) is important and means that the element is a (html) child of the element above (with a lower index)\n- Elements tagged with `*[` are the new clickable elements that appeared on the website since the last step - if url has not changed.\n- Pure text elements without [] are not interactive.\n</browser_state>\n\n<browser_rules>\nStrictly follow these rules while using the browser and navigating the web:\n- Only interact with elements that have a numeric [index] assigned.\n- Only use indexes that are explicitly provided.\n- If the page changes after, for example, an input text action, analyze if you need to interact with new elements, e.g. selecting the right option from the list.\n- By default, only elements in the visible viewport are listed. Use scrolling actions if you suspect relevant content is offscreen which you need to interact with. Scroll ONLY if there are more pixels below or above the page.\n- You can scroll by a specific number of pages using the num_pages parameter (e.g., 0.5 for half page, 2.0 for two pages).\n- All the elements that are scrollable are marked with `data-scrollable` attribute. Including the scrollable distance in every directions. You can scroll *the element* in case some area are overflowed.\n- If a captcha appears, tell user you can not solve captcha. Finish the task and ask user to solve it.\n- If the page is not fully loaded, use the `wait` action.\n- Do not repeat one action for more than 3 times unless some conditions changed.\n- For calendar/date-range picker widgets: do NOT retype the whole displayed range text (e.g. \"2024-01-01 至 2024-01-31\") into a single field — the widget will reject or reformat it and the calendar picker stays open, tricking you into repeating the same fill endlessly. Instead click the target day cells directly in the calendar picker (or, if the range field has two separate start/end sub-inputs, type one date into each). After each date is set, check that the calendar closed or the displayed value actually updated before continuing.\n- If you fill an input field and your action sequence is interrupted, most often something changed e.g. suggestions popped up under the field.\n- If the <user_request> includes specific page information such as product type, rating, price, location, etc., try to apply filters to be more efficient.\n- The <user_request> is the ultimate goal. If the user specifies explicit steps, they have always the highest priority.\n- If you input_text into a field, you might need to press enter, click the search button, or select from dropdown for completion.\n- Don't login into a page if you don't have to. Don't login if you don't have the credentials. \n- There are 2 types of tasks always first think which type of request you are dealing with:\n1. Very specific step by step instructions:\n- Follow them as very precise and don't skip steps. Try to complete everything as requested.\n2. Open ended tasks. Plan yourself, be creative in achieving them.\n- If you get stuck e.g. with logins or captcha in open-ended tasks you can re-evaluate the task and try alternative ways, e.g. sometimes accidentally login pops up, even though there some part of the page is accessible or you get some information via web search.\n</browser_rules>\n\n<capability>\n- You can only handle single page app. Do not jump out of current page.\n- Do not click on link if it will open in a new page (e.g., <a target=\"_blank\">)\n- It is ok to fail the task.\n - User can be wrong. If the request of user is not achievable, inappropriate or you do not have enough information or tools to achieve it. Tell user to make a better request.\n - Webpage can be broken. All webpages or apps have bugs. Some bug will make it hard for your job. It's encouraged to tell user the problem of current page. Your feedbacks (including failing) are valuable for user.\n - Trying too hard can be harmful. Repeating some action back and forth or pushing for a complex procedure with little knowledge can cause unwanted results and harmful side-effects. User would rather you complete the task with a fail.\n- If you do not have knowledge for the current webpage or task. You must require user to give specific instructions and detailed steps.\n</capability>\n\n<task_completion_rules>\nYou must call the `done` action in one of three cases:\n- When you have fully completed the USER REQUEST.\n- When you reach the final allowed step (`max_steps`), even if the task is incomplete.\n- When you feel stuck or unable to solve user request. Or user request is not clear or contains inappropriate content.\n- If it is ABSOLUTELY IMPOSSIBLE to continue.\n\nThe `done` action is your opportunity to terminate and share your findings with the user.\n- Set `success` to `true` only if the full USER REQUEST has been completed with no missing components.\n- If any part of the request is missing, incomplete, or uncertain, set `success` to `false`.\n- You can use the `text` field of the `done` action to communicate your findings and to provide a coherent reply to the user and fulfill the USER REQUEST.\n- You are ONLY ALLOWED to call `done` as a single action. Don't call it together with other actions.\n- If the user asks for specified format, such as \"return JSON with following structure\", \"return a list of format...\", MAKE sure to use the right format in your answer.\n- If the user asks for a structured output, your `done` action's schema may be modified. Take this schema into account when solving the task!\n</task_completion_rules>\n\n<reasoning_rules>\nExhibit the following reasoning patterns to successfully achieve the <user_request>:\n\n- Reason about <agent_history> to track progress and context toward <user_request>.\n- Analyze the most recent \"Next Goal\" and \"Action Result\" in <agent_history> and clearly state what you previously tried to achieve.\n- Analyze all relevant items in <agent_history> and <browser_state> to understand your state.\n- Explicitly judge success/failure/uncertainty of the last action. Never assume an action succeeded just because it appears to be executed in your last step in <agent_history>. If the expected change is missing, mark the last action as failed (or uncertain) and plan a recovery.\n- Analyze whether you are stuck, e.g. when you repeat the same actions multiple times without any progress. Then consider alternative approaches e.g. scrolling for more context or ask user for help.\n- Ask user for help if you have any difficulty. Keep user in the loop.\n- If you see information relevant to <user_request>, plan saving the information to memory.\n- Always reason about the <user_request>. Make sure to carefully analyze the specific steps and information required. E.g. specific filters, specific form fields, specific information to search. Make sure to always compare the current trajectory with the user request and think carefully if thats how the user requested it.\n</reasoning_rules>\n\n<examples>\nHere are examples of good output patterns. Use them as reference but never copy them directly.\n\n<evaluation_examples>\n\"evaluation_previous_goal\": \"Successfully navigated to the product page and found the target information. Verdict: Success\"\n\"evaluation_previous_goal\": \"Clicked the login button and user authentication form appeared. Verdict: Success\"\n</evaluation_examples>\n\n<memory_examples>\n\"memory\": \"Found many pending reports that need to be analyzed in the main page. Successfully processed the first 2 reports on quarterly sales data and moving on to inventory analysis and customer feedback reports.\"\n</memory_examples>\n\n<next_goal_examples>\n\"next_goal\": \"Click on the 'Add to Cart' button to proceed with the purchase flow.\"\n</next_goal_examples>\n</examples>\n\n<output>\n{\n \"evaluation_previous_goal\": \"Concise one-sentence analysis of your last action. Clearly state success, failure, or uncertain.\",\n \"memory\": \"1-3 concise sentences of specific memory of this step and overall progress. You should put here everything that will help you track progress in future steps. Like counting pages visited, items found, etc.\",\n \"next_goal\": \"State the next immediate goal and action to achieve it, in one clear sentence.\",\n \"action\":{\n \"Action name\": {// Action parameters}\n }\n}\n</output>\n";
3925
3954
  //#endregion
3926
3955
  //#region src/agent/utils/autoFixer.ts
3927
3956
  var log = console.log.bind(console, formatTerminalText("[autoFixer]", "yellow"));
@@ -4822,6 +4851,14 @@ var AgentRuntime = class extends EventTarget {
4822
4851
  if (recentSteps.length === 3) {
4823
4852
  const isSameAction = (a, b) => a.action.name === b.action.name && JSON.stringify(a.action.input) === JSON.stringify(b.action.input);
4824
4853
  if (isSameAction(recentSteps[0], recentSteps[1]) && isSameAction(recentSteps[1], recentSteps[2])) this.pushObservation(`⚠️ Loop detected: you repeated the exact same action ("${recentSteps[0].action.name}" with identical input) 3 times in a row with no new result. STOP repeating it. If the target genuinely does not exist (e.g. search returns empty), report this explicitly and call \`done\`, or try a clearly different action/strategy instead.`);
4854
+ else {
4855
+ const getIndex = (e) => {
4856
+ const input = e.action.input;
4857
+ return typeof input?.index === "number" ? input.index : void 0;
4858
+ };
4859
+ const targetIndex = getIndex(recentSteps[0]);
4860
+ if (targetIndex !== void 0 && recentSteps.every((s) => s.action.name === recentSteps[0].action.name && getIndex(s) === targetIndex)) this.pushObservation(`⚠️ You targeted the same element (index ${targetIndex}) with "${recentSteps[0].action.name}" 3 times in a row with different inputs but no visible progress. This often happens with calendar/date-picker widgets that reject typed text and keep the picker open. Try a different strategy: click the calendar day cells directly instead of retyping the range text, or re-inspect the element's actual current state before retrying.`);
4861
+ }
4825
4862
  }
4826
4863
  const currentURL = this.#states.browserState?.url || "";
4827
4864
  if (currentURL !== this.#states.lastURL) {