page-agent 0.0.3 → 0.0.5

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-zh.md ADDED
@@ -0,0 +1,128 @@
1
+ # PageAgent 🤖🪄
2
+
3
+ ![banner](https://img.alicdn.com/imgextra/i1/O1CN01RY0Wvh26ATVeDIX7v_!!6000000007621-0-tps-1672-512.jpg)
4
+
5
+ [![npm version](https://badge.fury.io/js/page-agent.svg)](https://badge.fury.io/js/page-agent) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) [![Downloads](https://img.shields.io/npm/dt/page-agent.svg)](https://www.npmjs.com/package/page-agent) [![Bundle Size](https://img.shields.io/bundlephobia/minzip/page-agent)](https://bundlephobia.com/package/page-agent) [![GitHub stars](https://img.shields.io/github/stars/alibaba/page-agent.svg)](https://github.com/alibaba/page-agent)
6
+
7
+ 纯 JS 实现的 GUI agent。使用自然语言操作你的 Web 应用。无须后端、客户端、浏览器插件。
8
+
9
+ 🌐 [English](./README.md) | **中文**
10
+
11
+ 👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/#/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a>
12
+
13
+ <video id="demo-video" src="https://github.com/user-attachments/assets/141bbb01-8022-4d1f-919d-9efc9a1dc1cf" width="640" crossorigin muted autoplay loop></video>
14
+
15
+ ---
16
+
17
+ ## ✨ Features
18
+
19
+ - **🎯 轻松集成**
20
+ - **🔐 端侧运行**
21
+ - **🧠 HTML 脱水**
22
+ - **💬 自然语言接口**
23
+ - **🎨 HITL 交互界面**
24
+
25
+ ## 🗺️ Roadmap
26
+
27
+ 👉 [**Roadmap**](./ROADMAP.md)
28
+
29
+ ## 🚀 快速开始
30
+
31
+ ### CDN 集成
32
+
33
+ ```html
34
+ <!-- 临时 CDN URL. 未来会变更 -->
35
+ <script
36
+ src="https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.4/page-agent.js"
37
+ crossorigin="true"
38
+ type="text/javascript"
39
+ ></script>
40
+ ```
41
+
42
+ ### NPM 安装
43
+
44
+ ```bash
45
+ npm install page-agent
46
+ ```
47
+
48
+ ```javascript
49
+ import { PageAgent } from 'page-agent'
50
+
51
+ // 测试接口
52
+ // @note: 限流,限制 prompt 内容,限制来源,随时变更,请替换成你自己的
53
+ // @note: 使用 DeepSeek-chat(3.2) 官方版本,使用协议和隐私策略见 DeepSeek 网站
54
+ const DEMO_MODEL = 'PAGE-AGENT-FREE-TESTING-RANDOM'
55
+ const DEMO_BASE_URL = 'https://hwcxiuzfylggtcktqgij.supabase.co/functions/v1/llm-testing-proxy'
56
+ const DEMO_API_KEY = 'PAGE-AGENT-FREE-TESTING-RANDOM'
57
+
58
+ const agent = new PageAgent({
59
+ modelName: DEMO_MODEL,
60
+ baseURL: DEMO_BASE_URL,
61
+ apiKey: DEMO_API_KEY,
62
+ language: 'zh-CN',
63
+ })
64
+
65
+ await agent.execute('点击登录按钮')
66
+ ```
67
+
68
+ ## 🏗️ 架构设计
69
+
70
+ PageAgent 采用清晰的模块化架构:
71
+
72
+ ```
73
+ src/
74
+ ├── PageAgent.ts # Agent 主流程
75
+ ├── dom/ # DOM 理解
76
+ ├── tools/ # 代理交互工具
77
+ ├── ui/ # UI 组件和面板
78
+ ├── llms/ # LLM 集成层
79
+ └── utils/ # 事件总线和工具
80
+ ```
81
+
82
+ ## 🤝 贡献
83
+
84
+ 欢迎社区贡献!以下是参与方式:
85
+
86
+ ### 开发环境
87
+
88
+ 1. Fork 项目仓库
89
+ 2. Clone or fork: `git clone https://github.com/alibaba/page-agent.git && cd page-agent`
90
+ 3. 安装依赖: `npm install`
91
+ 4. 启动开发: `npm start`
92
+
93
+ ### 贡献指南
94
+
95
+ 请在贡献前阅读我们的[行为准则](CODE_OF_CONDUCT.md)和[贡献指南](CONTRIBUTING.md)。
96
+
97
+ ## 👏 致谢
98
+
99
+ 本项目基于以下优秀项目构建:
100
+
101
+ - **[browser-use](https://github.com/browser-use/browser-use)**
102
+
103
+ PageAgent 专为**客户端网页增强**设计,不是服务端自动化工具。
104
+
105
+ ## 📄 许可证
106
+
107
+ MIT 许可证 - 详见 [LICENSE](LICENSE) 文件。
108
+
109
+ ```
110
+ DOM processing components and prompt are derived from browser-use:
111
+
112
+ Browser Use
113
+ Copyright (c) 2024 Gregor Zunic
114
+ Licensed under the MIT License
115
+
116
+ Original browser-use project: <https://github.com/browser-use/browser-use>
117
+
118
+ We gratefully acknowledge the browser-use project and its contributors for their
119
+ excellent work on web automation and DOM interaction patterns that helped make
120
+ this project possible.
121
+
122
+ Third-party dependencies and their licenses can be found in the package.json
123
+ file and in the node_modules directory after installation.
124
+ ```
125
+
126
+ ---
127
+
128
+ **⭐ 如果觉得 PageAgent 有用或有趣,请给项目点个星!**
package/README.md CHANGED
@@ -4,19 +4,19 @@
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/page-agent.svg)](https://badge.fury.io/js/page-agent) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) [![Downloads](https://img.shields.io/npm/dt/page-agent.svg)](https://www.npmjs.com/package/page-agent) [![Bundle Size](https://img.shields.io/bundlephobia/minzip/page-agent)](https://bundlephobia.com/package/page-agent) [![GitHub stars](https://img.shields.io/github/stars/alibaba/page-agent.svg)](https://github.com/alibaba/page-agent)
6
6
 
7
- **Transform your webpage into an AI-powered application with a single script tag.**
8
-
9
- An in-page UI agent in javascript. Control web interfaces with natural language.
7
+ The GUI Agent Living in Your Webpage. Control web interfaces with natural language.
10
8
 
11
9
  🌐 **English** | [中文](./README-zh.md)
12
10
 
13
- 👉 [🚀 **Demo**](https://alibaba.github.io/page-agent/) | [📖 **Documentation**](https://alibaba.github.io/page-agent/#/docs/introduction/overview)
11
+ 👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/#/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a>
12
+
13
+ <video id="demo-video" src="https://github.com/user-attachments/assets/de8d1964-8bde-494f-a52f-2975469557a5" width="640" crossorigin muted autoplay loop></video>
14
14
 
15
15
  ---
16
16
 
17
17
  ## ✨ Features
18
18
 
19
- - **🎯 Easy Integration**
19
+ - **🎯 Easy Integration** - Transform your webpage into an agent with a single script tag.
20
20
  - **🔐 Client-Side Processing**
21
21
  - **🧠 DOM Extraction**
22
22
  - **💬 Natural Language Interface**
@@ -33,7 +33,7 @@ An in-page UI agent in javascript. Control web interfaces with natural language.
33
33
  ```html
34
34
  <!-- temporary CDN URL. May change in the future -->
35
35
  <script
36
- src="https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.2/page-agent.js"
36
+ src="https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.4/page-agent.js"
37
37
  crossorigin="true"
38
38
  type="text/javascript"
39
39
  ></script>
@@ -48,6 +48,13 @@ declare interface AgentConfig {
48
48
  * @note when dispose caused by page unload, reason will be 'PAGE_UNLOADING'. this method CANNOT block unloading. async operations may be cut.
49
49
  */
50
50
  onDispose?: (this: PageAgent, reason?: string) => void;
51
+ /**
52
+ * @experimental
53
+ * Enable the experimental script execution tool that allows executing generated JavaScript code on the page.
54
+ * @note Can cause unpredictable side effects.
55
+ * @note May bypass some safe guards and data-masking mechanisms.
56
+ */
57
+ experimentalScriptExecutionTool?: boolean;
51
58
  /**
52
59
  * TODO: @unimplemented
53
60
  * hook when action causes a new page to be opened
@@ -167,11 +174,11 @@ declare class EventBus extends EventTarget {
167
174
  /**
168
175
  * Listen to built-in events
169
176
  */
170
- on<T extends keyof PageAgentEventMap>(event: T, handler: EventHandler<T & keyof PageAgentEventMap>): void;
177
+ on<T extends keyof PageAgentEventMap>(event: T, handler: EventHandler<T>): void;
171
178
  /**
172
179
  * Listen to built-in events (one-time)
173
180
  */
174
- once<T extends keyof PageAgentEventMap>(event: T, handler: EventHandler<T & keyof PageAgentEventMap>): void;
181
+ once<T extends keyof PageAgentEventMap>(event: T, handler: EventHandler<T>): void;
175
182
  /**
176
183
  * Emit built-in events
177
184
  */
@@ -3,7 +3,7 @@
3
3
  try {
4
4
  if (typeof document != "undefined") {
5
5
  var elementStyle = document.createElement("style");
6
- elementStyle.appendChild(document.createTextNode("._wrapper_d1n0a_1 {\n position: fixed;\n bottom: 100px;\n left: 50%;\n transform: translateX(-50%) translateY(20px);\n opacity: 0;\n z-index: 2147483642; /* 比 SimulatorMask 高一层 */\n box-sizing: border-box;\n\n overflow: visible;\n\n * {\n box-sizing: border-box;\n }\n\n --width: 360px;\n --height: 40px;\n --border-radius: 12px;\n\n --side-space: 12px; /* 控制栏两侧的间距 */\n --history-width: calc(var(--width) - var(--side-space) * 2);\n\n --color-1: rgb(57, 182, 255);\n --color-2: rgb(189, 69, 251);\n --color-3: rgb(255, 87, 51);\n --color-4: rgb(255, 214, 0);\n\n width: var(--width);\n height: var(--height);\n\n transition: all 0.3s ease-in-out;\n\n /* 响应式设计 */\n @media (max-width: 480px) {\n width: calc(100vw - 40px);\n left: 20px;\n transform: none;\n }\n\n ._background_d1n0a_40 {\n position: absolute;\n inset: -2px -8px;\n border-radius: calc(var(--border-radius) + 4px);\n filter: blur(16px);\n overflow: hidden;\n /* mix-blend-mode: lighten; */\n /* display: none; */\n\n &::before {\n content: '';\n z-index: -1;\n pointer-events: none;\n position: absolute;\n width: 100%;\n height: 100%;\n /* left: -100%; */\n left: 0;\n top: 0;\n\n background-image: linear-gradient(\n to bottom left,\n var(--color-1),\n var(--color-2),\n var(--color-1)\n );\n animation: _mask-running_d1n0a_1 2s linear infinite;\n }\n &::after {\n content: '';\n z-index: -1;\n pointer-events: none;\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n\n background-image: linear-gradient(\n to bottom left,\n var(--color-2),\n var(--color-1),\n var(--color-2)\n );\n animation: _mask-running_d1n0a_1 2s linear infinite;\n animation-delay: 1s;\n }\n }\n}\n\n@keyframes _mask-running_d1n0a_1 {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(100%);\n }\n}\n\n/* 控制栏 */\n._header_d1n0a_100 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n user-select: none;\n\n position: absolute;\n inset: 0;\n\n cursor: pointer;\n flex-shrink: 0; /* 防止 header 被压缩 */\n\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(10px);\n border-radius: var(--border-radius);\n background-clip: padding-box;\n\n box-shadow:\n 0 0 0px 2px rgba(255, 255, 255, 0.4),\n 0 0 5px 1px rgba(255, 255, 255, 0.3);\n\n ._statusSection_d1n0a_122 {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-height: 24px; /* 确保垂直居中 */\n\n ._indicator_d1n0a_129 {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.5);\n flex-shrink: 0;\n animation: none; /* 默认无动画 */\n\n /* 运行状态 - 有动画 */\n &._thinking_d1n0a_138 {\n background: rgb(57, 182, 255);\n animation: _pulse_d1n0a_1 0.8s ease-in-out infinite;\n }\n\n &._tool_executing_d1n0a_143 {\n background: rgb(189, 69, 251);\n animation: _pulse_d1n0a_1 0.6s ease-in-out infinite;\n }\n\n &._retry_d1n0a_148 {\n background: rgb(255, 214, 0);\n animation: _retryPulse_d1n0a_1 1s ease-in-out infinite;\n }\n\n /* 静止状态 - 无动画 */\n &._completed_d1n0a_154,\n &._input_d1n0a_155,\n &._output_d1n0a_156 {\n background: rgb(34, 197, 94);\n animation: none;\n }\n\n &._error_d1n0a_161 {\n background: rgb(239, 68, 68);\n animation: none;\n }\n }\n\n ._statusText_d1n0a_167 {\n color: white;\n font-size: 12px;\n line-height: 1;\n font-weight: 500;\n transition: all 0.3s ease-in-out;\n position: relative;\n overflow: hidden;\n display: flex;\n align-items: center;\n min-height: 24px; /* 确保垂直居中 */\n\n &._fadeOut_d1n0a_179 {\n animation: _statusTextFadeOut_d1n0a_1 0.3s ease forwards;\n }\n\n &._fadeIn_d1n0a_183 {\n animation: _statusTextFadeIn_d1n0a_1 0.3s ease forwards;\n }\n }\n }\n\n ._controls_d1n0a_189 {\n display: flex;\n align-items: center;\n gap: 4px;\n\n ._controlButton_d1n0a_194 {\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.1);\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n line-height: 1;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n }\n\n ._pauseButton_d1n0a_213 {\n font-weight: 600;\n &._paused_d1n0a_215 {\n background: rgba(34, 197, 94, 0.2); /* 绿色背景表示可以继续 */\n color: rgb(34, 197, 94);\n\n &:hover {\n background: rgba(34, 197, 94, 0.3);\n }\n }\n }\n\n ._stopButton_d1n0a_225 {\n background: rgba(239, 68, 68, 0.2);\n color: rgb(255, 41, 41);\n font-weight: 600;\n\n &:hover {\n background: rgba(239, 68, 68, 0.3);\n }\n }\n }\n}\n\n@keyframes _statusTextFadeIn_d1n0a_1 {\n 0% {\n opacity: 0;\n transform: translateY(5px);\n }\n 100% {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _statusTextFadeOut_d1n0a_1 {\n 0% {\n opacity: 1;\n transform: translateY(0);\n }\n 100% {\n opacity: 0;\n transform: translateY(-5px);\n }\n}\n\n._historySectionWrapper_d1n0a_259 {\n position: absolute;\n width: var(--history-width);\n bottom: var(--height);\n left: var(--side-space);\n z-index: -2;\n\n padding-top: 0px;\n visibility: collapse;\n overflow: hidden;\n\n transition: all 0.2s;\n\n background: rgba(2, 0, 20, 0.5);\n /* background: rgba(186, 186, 186, 0.2); */\n backdrop-filter: blur(10px);\n\n text-shadow: 0 0 1px rgba(0, 0, 0, 0.2);\n\n border-top-left-radius: calc(var(--border-radius) + 4px);\n border-top-right-radius: calc(var(--border-radius) + 4px);\n\n /* border: 2px solid rgba(255, 255, 255, 0.8); */\n border: 2px solid rgba(255, 255, 255, 0.4);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);\n\n /* @media (prefers-color-scheme: dark) {\n box-shadow:\n 0 8px 32px 0 rgba(0, 0, 0, 0.85),\n 0 2px 12px 0 rgba(57, 182, 255, 0.1);\n } */\n\n ._expanded_d1n0a_291 & {\n padding-top: 8px;\n visibility: visible;\n }\n\n ._historySection_d1n0a_259 {\n position: relative;\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: none;\n max-height: 0;\n padding-inline: 8px;\n\n transition: max-height 0.2s;\n\n ._expanded_d1n0a_291 & {\n max-height: 400px;\n }\n\n ._historyItem_d1n0a_310 {\n /* backdrop-filter: blur(10px); */\n padding: 8px 10px;\n margin-bottom: 6px;\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03));\n border-radius: 8px;\n border-left: 2px solid rgba(57, 182, 255, 0.5);\n font-size: 12px;\n color: white;\n /* color: black; */\n line-height: 1.3;\n position: relative;\n overflow: hidden;\n\n /* 微妙的内阴影 */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.1),\n 0 1px 3px rgba(0, 0, 0, 0.1);\n\n &::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);\n }\n\n &:hover {\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.06));\n /* transform: translateY(-1px); */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.15),\n 0 2px 4px rgba(0, 0, 0, 0.15);\n }\n\n &:last-child {\n margin-bottom: 10px;\n }\n\n &._completed_d1n0a_154,\n &._input_d1n0a_155,\n &._output_d1n0a_156 {\n border-left-color: rgb(34, 197, 94);\n background: linear-gradient(135deg, rgba(34, 197, 94, 0.1), rgba(34, 197, 94, 0.05));\n }\n\n &._error_d1n0a_161 {\n border-left-color: rgb(239, 68, 68);\n background: linear-gradient(135deg, rgba(239, 68, 68, 0.1), rgba(239, 68, 68, 0.05));\n }\n\n &._retry_d1n0a_148 {\n border-left-color: rgb(255, 214, 0);\n background: linear-gradient(135deg, rgba(255, 214, 0, 0.1), rgba(255, 214, 0, 0.05));\n }\n\n /* 突出显示 done 成功结果 */\n &._doneSuccess_d1n0a_369 {\n background: linear-gradient(\n 135deg,\n rgba(34, 197, 94, 0.25),\n rgba(34, 197, 94, 0.15),\n rgba(34, 197, 94, 0.08)\n );\n border: none;\n border-left: 4px solid rgb(34, 197, 94);\n box-shadow:\n 0 4px 12px rgba(34, 197, 94, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 20px rgba(34, 197, 94, 0.1);\n font-weight: 600;\n color: rgb(220, 252, 231);\n padding: 10px 12px;\n margin-bottom: 8px;\n border-radius: 8px;\n position: relative;\n overflow: hidden;\n\n &::before {\n background: linear-gradient(90deg, transparent, rgba(34, 197, 94, 0.4), transparent);\n }\n\n &::after {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);\n animation: _shimmer_d1n0a_1 2s ease-in-out infinite;\n }\n\n ._historyContent_d1n0a_405 {\n ._statusIcon_d1n0a_406 {\n font-size: 16px;\n animation: _celebrate_d1n0a_1 0.8s ease-in-out;\n filter: drop-shadow(0 2px 4px rgba(34, 197, 94, 0.5));\n }\n }\n }\n\n /* 突出显示 done 失败结果 */\n &._doneError_d1n0a_415 {\n background: linear-gradient(\n 135deg,\n rgba(239, 68, 68, 0.25),\n rgba(239, 68, 68, 0.15),\n rgba(239, 68, 68, 0.08)\n );\n border: none;\n border-left: 4px solid rgb(239, 68, 68);\n box-shadow:\n 0 4px 12px rgba(239, 68, 68, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 20px rgba(239, 68, 68, 0.1);\n font-weight: 600;\n color: rgb(254, 226, 226);\n padding: 10px 12px;\n margin-bottom: 8px;\n border-radius: 8px;\n position: relative;\n overflow: hidden;\n\n &::before {\n background: linear-gradient(90deg, transparent, rgba(239, 68, 68, 0.4), transparent);\n }\n\n ._historyContent_d1n0a_405 {\n ._statusIcon_d1n0a_406 {\n font-size: 16px;\n filter: drop-shadow(0 2px 4px rgba(239, 68, 68, 0.5));\n }\n }\n }\n\n ._historyContent_d1n0a_405 {\n display: flex;\n align-items: center;\n gap: 8px;\n\n word-break: break-all;\n white-space: pre-wrap;\n\n /* overflow-x: auto; */\n\n ._statusIcon_d1n0a_406 {\n font-size: 12px;\n flex-shrink: 0;\n line-height: 1;\n transition: all 0.3s ease;\n }\n }\n\n ._historyMeta_d1n0a_466 {\n font-size: 10px;\n color: rgba(255, 255, 255, 0.6);\n /* color: rgb(61, 61, 61); */\n margin-top: 8px;\n line-height: 1;\n }\n }\n }\n}\n\n/* 动画关键帧 - 更快的闪烁 */\n@keyframes _pulse_d1n0a_1 {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.4;\n transform: scale(1.3);\n }\n}\n\n/* 重试动画 - 旋转脉冲 */\n@keyframes _retryPulse_d1n0a_1 {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1) rotate(0deg);\n }\n 25% {\n opacity: 0.6;\n transform: scale(1.2) rotate(90deg);\n }\n 50% {\n opacity: 0.8;\n transform: scale(1.1) rotate(180deg);\n }\n 75% {\n opacity: 0.6;\n transform: scale(1.2) rotate(270deg);\n }\n}\n\n/* 庆祝动画 */\n@keyframes _celebrate_d1n0a_1 {\n 0%,\n 100% {\n transform: scale(1);\n }\n 25% {\n transform: scale(1.2) rotate(-5deg);\n }\n 75% {\n transform: scale(1.2) rotate(5deg);\n }\n}\n\n/* done 卡片的光泽效果 */\n@keyframes _shimmer_d1n0a_1 {\n 0% {\n left: -100%;\n }\n 100% {\n left: 100%;\n }\n}\n\n/* 输入区域样式 */\n._inputSectionWrapper_d1n0a_536 {\n position: absolute;\n width: var(--history-width);\n top: var(--height);\n left: var(--side-space);\n z-index: -1;\n\n visibility: visible;\n overflow: hidden;\n\n height: 48px;\n\n transition: all 0.2s;\n\n background: rgba(186, 186, 186, 0.2);\n backdrop-filter: blur(10px);\n\n border-bottom-left-radius: calc(var(--border-radius) + 4px);\n border-bottom-right-radius: calc(var(--border-radius) + 4px);\n\n border: 2px solid rgba(255, 255, 255, 0.3);\n box-shadow: 0 1px 16px rgba(0, 0, 0, 0.4);\n\n &._hidden_d1n0a_559 {\n visibility: collapse;\n height: 0;\n }\n\n ._inputSection_d1n0a_536 {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px 8px;\n\n ._taskInput_d1n0a_570 {\n flex: 1;\n background: rgba(255, 255, 255, 0.4);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 10px;\n padding-inline: 10px;\n color: rgb(20, 20, 20);\n font-size: 12px;\n height: 28px;\n line-height: 1;\n outline: none;\n transition: all 0.2s ease;\n\n /* text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); */\n\n /* border-color: rgba(57, 182, 255, 0.3); */\n\n &::placeholder {\n color: rgb(53, 53, 53);\n }\n\n &:focus {\n background: rgba(255, 255, 255, 0.8);\n border-color: rgba(57, 182, 255, 0.6);\n box-shadow: 0 0 0 2px rgba(57, 182, 255, 0.2);\n }\n }\n }\n}\n._wrapper_1oy2s_1 {\n position: fixed;\n inset: 0;\n z-index: 2147483641; /* 确保在所有元素之上,除了 panel */\n /* pointer-events: none; */\n cursor: not-allowed;\n overflow: hidden;\n\n display: none;\n}\n/* AI 光标样式 */\n._cursor_1vrf3_2 {\n position: absolute;\n width: var(--cursor-size, 75px);\n height: var(--cursor-size, 75px);\n pointer-events: none;\n z-index: 10000;\n transform: translate(-30%, -30%);\n\n animation: _cursor-enter_1vrf3_1 300ms ease-out forwards;\n}\n\n._cursorBorder_1vrf3_13 {\n position: absolute;\n inset: 0;\n background: linear-gradient(45deg, rgb(57, 182, 255), rgb(189, 69, 251));\n mask-image: url(https://img.alicdn.com/imgextra/i1/O1CN01YHLVYR1LvqWIyo5kH_!!6000000001362-2-tps-202-202.png);\n mask-size: 100% 100%;\n mask-repeat: no-repeat;\n animation: _cursor-breathe_1vrf3_1 2s ease-in-out infinite;\n}\n\n._cursorFilling_1vrf3_23 {\n position: absolute;\n inset: 0;\n background: url(https://img.alicdn.com/imgextra/i3/O1CN01JZOqOS1Tu1sIKbPLW_!!6000000002441-2-tps-202-202.png);\n background-size: 100% 100%;\n background-repeat: no-repeat;\n}\n\n._cursorRipple_1vrf3_31 {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n\n._cursor_1vrf3_2._clicking_1vrf3_37 ._cursorRipple_1vrf3_31::after {\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n left: -30%;\n top: -30%;\n border: 4px solid rgba(57, 182, 255, 1);\n border-radius: 50%;\n animation: _cursor-ripple_1vrf3_1 300ms ease-out forwards;\n}\n\n/* 光标动画关键帧 */\n@keyframes _cursor-breathe_1vrf3_1 {\n 0%,\n 100% {\n transform: scale(1);\n opacity: 0.9;\n }\n 50% {\n transform: scale(1.05);\n opacity: 1;\n }\n}\n\n@keyframes _cursor-rotate_1vrf3_1 {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n@keyframes _cursor-enter_1vrf3_1 {\n 0% {\n transform: translate(-30%, -30%) scale(0.5);\n opacity: 0;\n }\n 100% {\n transform: translate(-30%, -30%) scale(1);\n opacity: 1;\n }\n}\n\n@keyframes _cursor-ripple_1vrf3_1 {\n 0% {\n transform: scale(0);\n opacity: 1;\n }\n 100% {\n transform: scale(2);\n opacity: 0;\n }\n}"));
6
+ elementStyle.appendChild(document.createTextNode("._wrapper_1j0ct_1 {\n position: fixed;\n bottom: 100px;\n left: 50%;\n transform: translateX(-50%) translateY(20px);\n opacity: 0;\n z-index: 2147483642; /* 比 SimulatorMask 高一层 */\n box-sizing: border-box;\n\n overflow: visible;\n\n * {\n box-sizing: border-box;\n }\n\n --width: 360px;\n --height: 40px;\n --border-radius: 12px;\n\n --side-space: 12px; /* 控制栏两侧的间距 */\n --history-width: calc(var(--width) - var(--side-space) * 2);\n\n --color-1: rgb(57, 182, 255);\n --color-2: rgb(189, 69, 251);\n --color-3: rgb(255, 87, 51);\n --color-4: rgb(255, 214, 0);\n\n width: var(--width);\n height: var(--height);\n\n transition: all 0.3s ease-in-out;\n\n /* 响应式设计 */\n @media (max-width: 480px) {\n width: calc(100vw - 40px);\n --width: calc(100vw - 40px);\n }\n\n ._background_1j0ct_39 {\n position: absolute;\n inset: -2px -8px;\n border-radius: calc(var(--border-radius) + 4px);\n filter: blur(16px);\n overflow: hidden;\n /* mix-blend-mode: lighten; */\n /* display: none; */\n\n &::before {\n content: '';\n z-index: -1;\n pointer-events: none;\n position: absolute;\n width: 100%;\n height: 100%;\n /* left: -100%; */\n left: 0;\n top: 0;\n\n background-image: linear-gradient(\n to bottom left,\n var(--color-1),\n var(--color-2),\n var(--color-1)\n );\n animation: _mask-running_1j0ct_1 2s linear infinite;\n }\n &::after {\n content: '';\n z-index: -1;\n pointer-events: none;\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n\n background-image: linear-gradient(\n to bottom left,\n var(--color-2),\n var(--color-1),\n var(--color-2)\n );\n animation: _mask-running_1j0ct_1 2s linear infinite;\n animation-delay: 1s;\n }\n }\n}\n\n@keyframes _mask-running_1j0ct_1 {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(100%);\n }\n}\n\n/* 控制栏 */\n._header_1j0ct_99 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n user-select: none;\n\n position: absolute;\n inset: 0;\n\n cursor: pointer;\n flex-shrink: 0; /* 防止 header 被压缩 */\n\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(10px);\n border-radius: var(--border-radius);\n background-clip: padding-box;\n\n box-shadow:\n 0 0 0px 2px rgba(255, 255, 255, 0.4),\n 0 0 5px 1px rgba(255, 255, 255, 0.3);\n\n ._statusSection_1j0ct_121 {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-height: 24px; /* 确保垂直居中 */\n\n ._indicator_1j0ct_128 {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.5);\n flex-shrink: 0;\n animation: none; /* 默认无动画 */\n\n /* 运行状态 - 有动画 */\n &._thinking_1j0ct_137 {\n background: rgb(57, 182, 255);\n animation: _pulse_1j0ct_1 0.8s ease-in-out infinite;\n }\n\n &._tool_executing_1j0ct_142 {\n background: rgb(189, 69, 251);\n animation: _pulse_1j0ct_1 0.6s ease-in-out infinite;\n }\n\n &._retry_1j0ct_147 {\n background: rgb(255, 214, 0);\n animation: _retryPulse_1j0ct_1 1s ease-in-out infinite;\n }\n\n /* 静止状态 - 无动画 */\n &._completed_1j0ct_153,\n &._input_1j0ct_154,\n &._output_1j0ct_155 {\n background: rgb(34, 197, 94);\n animation: none;\n }\n\n &._error_1j0ct_160 {\n background: rgb(239, 68, 68);\n animation: none;\n }\n }\n\n ._statusText_1j0ct_166 {\n color: white;\n font-size: 12px;\n line-height: 1;\n font-weight: 500;\n transition: all 0.3s ease-in-out;\n position: relative;\n overflow: hidden;\n display: flex;\n align-items: center;\n min-height: 24px; /* 确保垂直居中 */\n\n &._fadeOut_1j0ct_178 {\n animation: _statusTextFadeOut_1j0ct_1 0.3s ease forwards;\n }\n\n &._fadeIn_1j0ct_182 {\n animation: _statusTextFadeIn_1j0ct_1 0.3s ease forwards;\n }\n }\n }\n\n ._controls_1j0ct_188 {\n display: flex;\n align-items: center;\n gap: 4px;\n\n ._controlButton_1j0ct_193 {\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.1);\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n line-height: 1;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n }\n\n ._pauseButton_1j0ct_212 {\n font-weight: 600;\n &._paused_1j0ct_214 {\n background: rgba(34, 197, 94, 0.2); /* 绿色背景表示可以继续 */\n color: rgb(34, 197, 94);\n\n &:hover {\n background: rgba(34, 197, 94, 0.3);\n }\n }\n }\n\n ._stopButton_1j0ct_224 {\n background: rgba(239, 68, 68, 0.2);\n color: rgb(255, 41, 41);\n font-weight: 600;\n\n &:hover {\n background: rgba(239, 68, 68, 0.3);\n }\n }\n }\n}\n\n@keyframes _statusTextFadeIn_1j0ct_1 {\n 0% {\n opacity: 0;\n transform: translateY(5px);\n }\n 100% {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _statusTextFadeOut_1j0ct_1 {\n 0% {\n opacity: 1;\n transform: translateY(0);\n }\n 100% {\n opacity: 0;\n transform: translateY(-5px);\n }\n}\n\n._historySectionWrapper_1j0ct_258 {\n position: absolute;\n width: var(--history-width);\n bottom: var(--height);\n left: var(--side-space);\n z-index: -2;\n\n padding-top: 0px;\n visibility: collapse;\n overflow: hidden;\n\n transition: all 0.2s;\n\n background: rgba(2, 0, 20, 0.5);\n /* background: rgba(186, 186, 186, 0.2); */\n backdrop-filter: blur(10px);\n\n text-shadow: 0 0 1px rgba(0, 0, 0, 0.2);\n\n border-top-left-radius: calc(var(--border-radius) + 4px);\n border-top-right-radius: calc(var(--border-radius) + 4px);\n\n /* border: 2px solid rgba(255, 255, 255, 0.8); */\n border: 2px solid rgba(255, 255, 255, 0.4);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);\n\n /* @media (prefers-color-scheme: dark) {\n box-shadow:\n 0 8px 32px 0 rgba(0, 0, 0, 0.85),\n 0 2px 12px 0 rgba(57, 182, 255, 0.1);\n } */\n\n ._expanded_1j0ct_290 & {\n padding-top: 8px;\n visibility: visible;\n }\n\n ._historySection_1j0ct_258 {\n position: relative;\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: none;\n max-height: 0;\n padding-inline: 8px;\n\n transition: max-height 0.2s;\n\n ._expanded_1j0ct_290 & {\n max-height: 400px;\n }\n\n ._historyItem_1j0ct_309 {\n /* backdrop-filter: blur(10px); */\n padding: 8px 10px;\n margin-bottom: 6px;\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03));\n border-radius: 8px;\n border-left: 2px solid rgba(57, 182, 255, 0.5);\n font-size: 12px;\n color: white;\n /* color: black; */\n line-height: 1.3;\n position: relative;\n overflow: hidden;\n\n /* 微妙的内阴影 */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.1),\n 0 1px 3px rgba(0, 0, 0, 0.1);\n\n &::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);\n }\n\n &:hover {\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.06));\n /* transform: translateY(-1px); */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.15),\n 0 2px 4px rgba(0, 0, 0, 0.15);\n }\n\n &:last-child {\n margin-bottom: 10px;\n }\n\n &._completed_1j0ct_153,\n &._input_1j0ct_154,\n &._output_1j0ct_155 {\n border-left-color: rgb(34, 197, 94);\n background: linear-gradient(135deg, rgba(34, 197, 94, 0.1), rgba(34, 197, 94, 0.05));\n }\n\n &._error_1j0ct_160 {\n border-left-color: rgb(239, 68, 68);\n background: linear-gradient(135deg, rgba(239, 68, 68, 0.1), rgba(239, 68, 68, 0.05));\n }\n\n &._retry_1j0ct_147 {\n border-left-color: rgb(255, 214, 0);\n background: linear-gradient(135deg, rgba(255, 214, 0, 0.1), rgba(255, 214, 0, 0.05));\n }\n\n /* 突出显示 done 成功结果 */\n &._doneSuccess_1j0ct_368 {\n background: linear-gradient(\n 135deg,\n rgba(34, 197, 94, 0.25),\n rgba(34, 197, 94, 0.15),\n rgba(34, 197, 94, 0.08)\n );\n border: none;\n border-left: 4px solid rgb(34, 197, 94);\n box-shadow:\n 0 4px 12px rgba(34, 197, 94, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 20px rgba(34, 197, 94, 0.1);\n font-weight: 600;\n color: rgb(220, 252, 231);\n padding: 10px 12px;\n margin-bottom: 8px;\n border-radius: 8px;\n position: relative;\n overflow: hidden;\n\n &::before {\n background: linear-gradient(90deg, transparent, rgba(34, 197, 94, 0.4), transparent);\n }\n\n &::after {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);\n animation: _shimmer_1j0ct_1 2s ease-in-out infinite;\n }\n\n ._historyContent_1j0ct_404 {\n ._statusIcon_1j0ct_405 {\n font-size: 16px;\n animation: _celebrate_1j0ct_1 0.8s ease-in-out;\n filter: drop-shadow(0 2px 4px rgba(34, 197, 94, 0.5));\n }\n }\n }\n\n /* 突出显示 done 失败结果 */\n &._doneError_1j0ct_414 {\n background: linear-gradient(\n 135deg,\n rgba(239, 68, 68, 0.25),\n rgba(239, 68, 68, 0.15),\n rgba(239, 68, 68, 0.08)\n );\n border: none;\n border-left: 4px solid rgb(239, 68, 68);\n box-shadow:\n 0 4px 12px rgba(239, 68, 68, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 20px rgba(239, 68, 68, 0.1);\n font-weight: 600;\n color: rgb(254, 226, 226);\n padding: 10px 12px;\n margin-bottom: 8px;\n border-radius: 8px;\n position: relative;\n overflow: hidden;\n\n &::before {\n background: linear-gradient(90deg, transparent, rgba(239, 68, 68, 0.4), transparent);\n }\n\n ._historyContent_1j0ct_404 {\n ._statusIcon_1j0ct_405 {\n font-size: 16px;\n filter: drop-shadow(0 2px 4px rgba(239, 68, 68, 0.5));\n }\n }\n }\n\n ._historyContent_1j0ct_404 {\n display: flex;\n align-items: center;\n gap: 8px;\n\n word-break: break-all;\n white-space: pre-wrap;\n\n /* overflow-x: auto; */\n\n ._statusIcon_1j0ct_405 {\n font-size: 12px;\n flex-shrink: 0;\n line-height: 1;\n transition: all 0.3s ease;\n }\n }\n\n ._historyMeta_1j0ct_465 {\n font-size: 10px;\n color: rgba(255, 255, 255, 0.6);\n /* color: rgb(61, 61, 61); */\n margin-top: 8px;\n line-height: 1;\n }\n }\n }\n}\n\n/* 动画关键帧 - 更快的闪烁 */\n@keyframes _pulse_1j0ct_1 {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.4;\n transform: scale(1.3);\n }\n}\n\n/* 重试动画 - 旋转脉冲 */\n@keyframes _retryPulse_1j0ct_1 {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1) rotate(0deg);\n }\n 25% {\n opacity: 0.6;\n transform: scale(1.2) rotate(90deg);\n }\n 50% {\n opacity: 0.8;\n transform: scale(1.1) rotate(180deg);\n }\n 75% {\n opacity: 0.6;\n transform: scale(1.2) rotate(270deg);\n }\n}\n\n/* 庆祝动画 */\n@keyframes _celebrate_1j0ct_1 {\n 0%,\n 100% {\n transform: scale(1);\n }\n 25% {\n transform: scale(1.2) rotate(-5deg);\n }\n 75% {\n transform: scale(1.2) rotate(5deg);\n }\n}\n\n/* done 卡片的光泽效果 */\n@keyframes _shimmer_1j0ct_1 {\n 0% {\n left: -100%;\n }\n 100% {\n left: 100%;\n }\n}\n\n/* 输入区域样式 */\n._inputSectionWrapper_1j0ct_535 {\n position: absolute;\n width: var(--history-width);\n top: var(--height);\n left: var(--side-space);\n z-index: -1;\n\n visibility: visible;\n overflow: hidden;\n\n height: 48px;\n\n transition: all 0.2s;\n\n background: rgba(186, 186, 186, 0.2);\n backdrop-filter: blur(10px);\n\n border-bottom-left-radius: calc(var(--border-radius) + 4px);\n border-bottom-right-radius: calc(var(--border-radius) + 4px);\n\n border: 2px solid rgba(255, 255, 255, 0.3);\n box-shadow: 0 1px 16px rgba(0, 0, 0, 0.4);\n\n &._hidden_1j0ct_558 {\n visibility: collapse;\n height: 0;\n }\n\n ._inputSection_1j0ct_535 {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px 8px;\n\n ._taskInput_1j0ct_569 {\n flex: 1;\n background: rgba(255, 255, 255, 0.4);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 10px;\n padding-inline: 10px;\n color: rgb(20, 20, 20);\n font-size: 12px;\n height: 28px;\n line-height: 1;\n outline: none;\n transition: all 0.2s ease;\n\n /* text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); */\n\n /* border-color: rgba(57, 182, 255, 0.3); */\n\n &::placeholder {\n color: rgb(53, 53, 53);\n }\n\n &:focus {\n background: rgba(255, 255, 255, 0.8);\n border-color: rgba(57, 182, 255, 0.6);\n box-shadow: 0 0 0 2px rgba(57, 182, 255, 0.2);\n }\n }\n }\n}\n._wrapper_1oy2s_1 {\n position: fixed;\n inset: 0;\n z-index: 2147483641; /* 确保在所有元素之上,除了 panel */\n /* pointer-events: none; */\n cursor: not-allowed;\n overflow: hidden;\n\n display: none;\n}\n/* AI 光标样式 */\n._cursor_1vrf3_2 {\n position: absolute;\n width: var(--cursor-size, 75px);\n height: var(--cursor-size, 75px);\n pointer-events: none;\n z-index: 10000;\n transform: translate(-30%, -30%);\n\n animation: _cursor-enter_1vrf3_1 300ms ease-out forwards;\n}\n\n._cursorBorder_1vrf3_13 {\n position: absolute;\n inset: 0;\n background: linear-gradient(45deg, rgb(57, 182, 255), rgb(189, 69, 251));\n mask-image: url(https://img.alicdn.com/imgextra/i1/O1CN01YHLVYR1LvqWIyo5kH_!!6000000001362-2-tps-202-202.png);\n mask-size: 100% 100%;\n mask-repeat: no-repeat;\n animation: _cursor-breathe_1vrf3_1 2s ease-in-out infinite;\n}\n\n._cursorFilling_1vrf3_23 {\n position: absolute;\n inset: 0;\n background: url(https://img.alicdn.com/imgextra/i3/O1CN01JZOqOS1Tu1sIKbPLW_!!6000000002441-2-tps-202-202.png);\n background-size: 100% 100%;\n background-repeat: no-repeat;\n}\n\n._cursorRipple_1vrf3_31 {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n\n._cursor_1vrf3_2._clicking_1vrf3_37 ._cursorRipple_1vrf3_31::after {\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n left: -30%;\n top: -30%;\n border: 4px solid rgba(57, 182, 255, 1);\n border-radius: 50%;\n animation: _cursor-ripple_1vrf3_1 300ms ease-out forwards;\n}\n\n/* 光标动画关键帧 */\n@keyframes _cursor-breathe_1vrf3_1 {\n 0%,\n 100% {\n transform: scale(1);\n opacity: 0.9;\n }\n 50% {\n transform: scale(1.05);\n opacity: 1;\n }\n}\n\n@keyframes _cursor-rotate_1vrf3_1 {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n@keyframes _cursor-enter_1vrf3_1 {\n 0% {\n transform: translate(-30%, -30%) scale(0.5);\n opacity: 0;\n }\n 100% {\n transform: translate(-30%, -30%) scale(1);\n opacity: 1;\n }\n}\n\n@keyframes _cursor-ripple_1vrf3_1 {\n 0% {\n transform: scale(0);\n opacity: 1;\n }\n 100% {\n transform: scale(2);\n opacity: 0;\n }\n}"));
7
7
  document.head.appendChild(elementStyle);
8
8
  }
9
9
  } catch (e) {
@@ -1189,7 +1189,7 @@ function flatTreeToString(flatTree, include_attributes) {
1189
1189
  }
1190
1190
  return false;
1191
1191
  }, "hasParentWithHighlightIndex");
1192
- const processNode = /* @__PURE__ */ __name((node, depth, result2) => {
1192
+ const processNode = /* @__PURE__ */ __name((node, depth, result22) => {
1193
1193
  let nextDepth = depth;
1194
1194
  const depthStr = " ".repeat(depth);
1195
1195
  if (node.type === "element") {
@@ -1264,23 +1264,23 @@ function flatTreeToString(flatTree, include_attributes) {
1264
1264
  line += " ";
1265
1265
  }
1266
1266
  line += " />";
1267
- result2.push(line);
1267
+ result22.push(line);
1268
1268
  }
1269
1269
  for (const child of node.children) {
1270
- processNode(child, nextDepth, result2);
1270
+ processNode(child, nextDepth, result22);
1271
1271
  }
1272
1272
  } else if (node.type === "text") {
1273
1273
  if (hasParentWithHighlightIndex(node)) {
1274
1274
  return;
1275
1275
  }
1276
1276
  if (node.parent && node.parent.type === "element" && node.parent.isVisible && node.parent.isTopElement) {
1277
- result2.push(`${depthStr}${node.text ?? ""}`);
1277
+ result22.push(`${depthStr}${node.text ?? ""}`);
1278
1278
  }
1279
1279
  }
1280
1280
  }, "processNode");
1281
- const result = [];
1282
- processNode(rootNode, 0, result);
1283
- return result.join("\n");
1281
+ const result2 = [];
1282
+ processNode(rootNode, 0, result2);
1283
+ return result2.join("\n");
1284
1284
  }
1285
1285
  __name(flatTreeToString, "flatTreeToString");
1286
1286
  const getAllTextTillNextClickableElement = /* @__PURE__ */ __name((node, maxDepth = -1) => {
@@ -1651,6 +1651,8 @@ function lenientParseMacroToolCall(responseData, inputSchema) {
1651
1651
  }
1652
1652
  switch (choice.finish_reason) {
1653
1653
  case "tool_calls":
1654
+ case "function_call":
1655
+ // gemini
1654
1656
  case "stop":
1655
1657
  break;
1656
1658
  case "length":
@@ -1902,8 +1904,8 @@ const _LLM = class _LLM {
1902
1904
  async invoke(messages, tools2, abortSignal) {
1903
1905
  return await withRetry(
1904
1906
  async () => {
1905
- const result = await this.client.invoke(messages, tools2, abortSignal);
1906
- return result;
1907
+ const result2 = await this.client.invoke(messages, tools2, abortSignal);
1908
+ return result2;
1907
1909
  },
1908
1910
  // retry settings
1909
1911
  {
@@ -2413,6 +2415,24 @@ tools.set(
2413
2415
  }, "execute")
2414
2416
  })
2415
2417
  );
2418
+ tools.set(
2419
+ "execute_javascript",
2420
+ tool({
2421
+ description: "Execute JavaScript code on the current page. Supports async/await syntax. Use with caution!",
2422
+ inputSchema: zod.object({
2423
+ script: zod.string()
2424
+ }),
2425
+ execute: /* @__PURE__ */ __name(async function(input) {
2426
+ try {
2427
+ const asyncFunction = eval(`(async () => { ${input.script} })`);
2428
+ const result = await asyncFunction();
2429
+ return `✅ Executed JavaScript. Result: ${result}` + await getSystemInfo();
2430
+ } catch (error2) {
2431
+ return `❌ Error executing JavaScript: ${error2}` + await getSystemInfo();
2432
+ }
2433
+ }, "execute")
2434
+ })
2435
+ );
2416
2436
  async function waitUntil(check, timeout = 60 * 601e3) {
2417
2437
  if (check()) return true;
2418
2438
  return new Promise((resolve, reject) => {
@@ -2527,48 +2547,48 @@ const _UIState = class _UIState {
2527
2547
  };
2528
2548
  __name(_UIState, "UIState");
2529
2549
  let UIState = _UIState;
2530
- const wrapper$1 = "_wrapper_d1n0a_1";
2531
- const background = "_background_d1n0a_40";
2532
- const header = "_header_d1n0a_100";
2533
- const pulse = "_pulse_d1n0a_1";
2534
- const retryPulse = "_retryPulse_d1n0a_1";
2535
- const statusTextFadeOut = "_statusTextFadeOut_d1n0a_1";
2536
- const statusTextFadeIn = "_statusTextFadeIn_d1n0a_1";
2537
- const statusSection = "_statusSection_d1n0a_122";
2538
- const indicator = "_indicator_d1n0a_129";
2539
- const thinking = "_thinking_d1n0a_138";
2540
- const tool_executing = "_tool_executing_d1n0a_143";
2541
- const retry = "_retry_d1n0a_148";
2542
- const completed = "_completed_d1n0a_154";
2543
- const input = "_input_d1n0a_155";
2544
- const output = "_output_d1n0a_156";
2545
- const error = "_error_d1n0a_161";
2546
- const statusText = "_statusText_d1n0a_167";
2547
- const fadeOut = "_fadeOut_d1n0a_179";
2548
- const fadeIn = "_fadeIn_d1n0a_183";
2549
- const controls = "_controls_d1n0a_189";
2550
- const controlButton = "_controlButton_d1n0a_194";
2551
- const pauseButton = "_pauseButton_d1n0a_213";
2552
- const paused = "_paused_d1n0a_215";
2553
- const stopButton = "_stopButton_d1n0a_225";
2554
- const historySectionWrapper = "_historySectionWrapper_d1n0a_259";
2555
- const shimmer = "_shimmer_d1n0a_1";
2556
- const celebrate = "_celebrate_d1n0a_1";
2557
- const expanded = "_expanded_d1n0a_291";
2558
- const historySection = "_historySection_d1n0a_259";
2559
- const historyItem = "_historyItem_d1n0a_310";
2560
- const doneSuccess = "_doneSuccess_d1n0a_369";
2561
- const historyContent = "_historyContent_d1n0a_405";
2562
- const statusIcon = "_statusIcon_d1n0a_406";
2563
- const doneError = "_doneError_d1n0a_415";
2564
- const historyMeta = "_historyMeta_d1n0a_466";
2565
- const inputSectionWrapper = "_inputSectionWrapper_d1n0a_536";
2566
- const hidden = "_hidden_d1n0a_559";
2567
- const inputSection = "_inputSection_d1n0a_536";
2568
- const taskInput = "_taskInput_d1n0a_570";
2550
+ const wrapper$1 = "_wrapper_1j0ct_1";
2551
+ const background = "_background_1j0ct_39";
2552
+ const header = "_header_1j0ct_99";
2553
+ const pulse = "_pulse_1j0ct_1";
2554
+ const retryPulse = "_retryPulse_1j0ct_1";
2555
+ const statusTextFadeOut = "_statusTextFadeOut_1j0ct_1";
2556
+ const statusTextFadeIn = "_statusTextFadeIn_1j0ct_1";
2557
+ const statusSection = "_statusSection_1j0ct_121";
2558
+ const indicator = "_indicator_1j0ct_128";
2559
+ const thinking = "_thinking_1j0ct_137";
2560
+ const tool_executing = "_tool_executing_1j0ct_142";
2561
+ const retry = "_retry_1j0ct_147";
2562
+ const completed = "_completed_1j0ct_153";
2563
+ const input = "_input_1j0ct_154";
2564
+ const output = "_output_1j0ct_155";
2565
+ const error = "_error_1j0ct_160";
2566
+ const statusText = "_statusText_1j0ct_166";
2567
+ const fadeOut = "_fadeOut_1j0ct_178";
2568
+ const fadeIn = "_fadeIn_1j0ct_182";
2569
+ const controls = "_controls_1j0ct_188";
2570
+ const controlButton = "_controlButton_1j0ct_193";
2571
+ const pauseButton = "_pauseButton_1j0ct_212";
2572
+ const paused = "_paused_1j0ct_214";
2573
+ const stopButton = "_stopButton_1j0ct_224";
2574
+ const historySectionWrapper = "_historySectionWrapper_1j0ct_258";
2575
+ const shimmer = "_shimmer_1j0ct_1";
2576
+ const celebrate = "_celebrate_1j0ct_1";
2577
+ const expanded = "_expanded_1j0ct_290";
2578
+ const historySection = "_historySection_1j0ct_258";
2579
+ const historyItem = "_historyItem_1j0ct_309";
2580
+ const doneSuccess = "_doneSuccess_1j0ct_368";
2581
+ const historyContent = "_historyContent_1j0ct_404";
2582
+ const statusIcon = "_statusIcon_1j0ct_405";
2583
+ const doneError = "_doneError_1j0ct_414";
2584
+ const historyMeta = "_historyMeta_1j0ct_465";
2585
+ const inputSectionWrapper = "_inputSectionWrapper_1j0ct_535";
2586
+ const hidden = "_hidden_1j0ct_558";
2587
+ const inputSection = "_inputSection_1j0ct_535";
2588
+ const taskInput = "_taskInput_1j0ct_569";
2569
2589
  const styles$1 = {
2570
2590
  wrapper: wrapper$1,
2571
- "mask-running": "_mask-running_d1n0a_1",
2591
+ "mask-running": "_mask-running_1j0ct_1",
2572
2592
  background,
2573
2593
  header,
2574
2594
  pulse,
@@ -3372,6 +3392,9 @@ const _PageAgent = class _PageAgent extends EventTarget {
3372
3392
  this.tools.set(name, tool2);
3373
3393
  }
3374
3394
  }
3395
+ if (!this.config.experimentalScriptExecutionTool) {
3396
+ this.tools.delete("execute_javascript");
3397
+ }
3375
3398
  patchReact();
3376
3399
  window.addEventListener("beforeunload", (e) => {
3377
3400
  if (!this.disposed) this.dispose("PAGE_UNLOADING");
@@ -3413,7 +3436,7 @@ const _PageAgent = class _PageAgent extends EventTarget {
3413
3436
  type: "thinking",
3414
3437
  displayText: this.i18n.t("ui.panel.thinking")
3415
3438
  });
3416
- const result = await __privateGet(this, _llm).invoke(
3439
+ const result2 = await __privateGet(this, _llm).invoke(
3417
3440
  [
3418
3441
  {
3419
3442
  role: "system",
@@ -3427,7 +3450,7 @@ const _PageAgent = class _PageAgent extends EventTarget {
3427
3450
  { AgentOutput: __privateMethod(this, _PageAgent_instances, packMacroTool_fn).call(this) },
3428
3451
  __privateGet(this, _abortController).signal
3429
3452
  );
3430
- const macroResult = result.toolResult;
3453
+ const macroResult = result2.toolResult;
3431
3454
  const input2 = macroResult.input;
3432
3455
  const output2 = macroResult.output;
3433
3456
  const brain = {
@@ -3444,7 +3467,7 @@ const _PageAgent = class _PageAgent extends EventTarget {
3444
3467
  this.history.push({
3445
3468
  brain,
3446
3469
  action,
3447
- usage: result.usage
3470
+ usage: result2.usage
3448
3471
  });
3449
3472
  console.log(chalk.green("Step finished:"), actionName);
3450
3473
  console.groupEnd();
@@ -3452,38 +3475,38 @@ const _PageAgent = class _PageAgent extends EventTarget {
3452
3475
  step++;
3453
3476
  if (step > MAX_STEPS) {
3454
3477
  __privateMethod(this, _PageAgent_instances, onDone_fn).call(this, "Step count exceeded maximum limit", false);
3455
- const result2 = {
3478
+ const result22 = {
3456
3479
  success: false,
3457
3480
  data: "Step count exceeded maximum limit",
3458
3481
  history: this.history
3459
3482
  };
3460
- await onAfterTask.call(this, result2);
3461
- return result2;
3483
+ await onAfterTask.call(this, result22);
3484
+ return result22;
3462
3485
  }
3463
3486
  if (actionName === "done") {
3464
3487
  const success = action.input?.success ?? false;
3465
3488
  const text = action.input?.text || "no text provided";
3466
3489
  console.log(chalk.green.bold("Task completed"), success, text);
3467
3490
  __privateMethod(this, _PageAgent_instances, onDone_fn).call(this, text, success);
3468
- const result2 = {
3491
+ const result22 = {
3469
3492
  success,
3470
3493
  data: text,
3471
3494
  history: this.history
3472
3495
  };
3473
- await onAfterTask.call(this, result2);
3474
- return result2;
3496
+ await onAfterTask.call(this, result22);
3497
+ return result22;
3475
3498
  }
3476
3499
  }
3477
3500
  } catch (error2) {
3478
3501
  console.error("Task failed", error2);
3479
3502
  __privateMethod(this, _PageAgent_instances, onDone_fn).call(this, String(error2), false);
3480
- const result = {
3503
+ const result2 = {
3481
3504
  success: false,
3482
3505
  data: String(error2),
3483
3506
  history: this.history
3484
3507
  };
3485
- await onAfterTask.call(this, result);
3486
- return result;
3508
+ await onAfterTask.call(this, result2);
3509
+ return result2;
3487
3510
  }
3488
3511
  }
3489
3512
  dispose(reason) {
@@ -3558,16 +3581,16 @@ packMacroTool_fn = /* @__PURE__ */ __name(function() {
3558
3581
  displayText: getToolExecutingText(toolName, toolInput, this.i18n)
3559
3582
  });
3560
3583
  const startTime = Date.now();
3561
- let result = await tool2.execute.bind(this)(toolInput);
3584
+ let result2 = await tool2.execute.bind(this)(toolInput);
3562
3585
  const duration = Date.now() - startTime;
3563
- console.log(chalk.green.bold(`Tool (${toolName}) executed for ${duration}ms`), result);
3586
+ console.log(chalk.green.bold(`Tool (${toolName}) executed for ${duration}ms`), result2);
3564
3587
  if (toolName === "wait") {
3565
3588
  __privateSet(this, _totalWaitTime, __privateGet(this, _totalWaitTime) + Math.round(toolInput.seconds + duration / 1e3));
3566
- result += `
3589
+ result2 += `
3567
3590
  <sys> You have waited ${__privateGet(this, _totalWaitTime)} seconds accumulatively.`;
3568
3591
  if (__privateGet(this, _totalWaitTime) >= 3)
3569
- result += "\nDo NOT wait any longer unless you have a good reason.\n";
3570
- result += "</sys>";
3592
+ result2 += "\nDo NOT wait any longer unless you have a good reason.\n";
3593
+ result2 += "</sys>";
3571
3594
  } else {
3572
3595
  __privateSet(this, _totalWaitTime, 0);
3573
3596
  }
@@ -3577,14 +3600,14 @@ packMacroTool_fn = /* @__PURE__ */ __name(function() {
3577
3600
  type: "tool_executing",
3578
3601
  toolName,
3579
3602
  toolArgs: toolInput,
3580
- toolResult: result,
3603
+ toolResult: result2,
3581
3604
  displayText: displayResult,
3582
3605
  duration
3583
3606
  });
3584
3607
  await new Promise((resolve) => setTimeout(resolve, 100));
3585
3608
  return {
3586
3609
  input: input2,
3587
- output: result
3610
+ output: result2
3588
3611
  };
3589
3612
  }, "execute")
3590
3613
  };