agentpage 0.0.10 → 0.0.12
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 +256 -232
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
# AutoPilot
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 浏览器内嵌 AI Agent SDK:让 AI 通过 tool-calling 操作网页。
|
|
4
4
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
基于原生 `fetch` 的纯浏览器 AI 客户端,支持 **OpenAI** / **GitHub Copilot** / **Anthropic**。唯一运行时依赖:`@sinclair/typebox`。
|
|
7
|
+
AutoPilot 的目标不是生成文本,而是在浏览器中完成真实任务:点击、填写、导航、等待、执行脚本,并在每一轮根据最新页面状态持续推进。
|
|
10
8
|
|
|
11
9
|
---
|
|
12
10
|
|
|
13
|
-
##
|
|
11
|
+
## 项目定位
|
|
14
12
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
- **多轮记忆** — 可开关的对话历史,Agent 能记住上下文
|
|
21
|
-
- **Chrome Extension 支持** — 内置 Service Worker ↔ Content Script 消息桥
|
|
22
|
-
- **~2000 行** — 轻量、可审计、无黑箱
|
|
13
|
+
- 运行环境:浏览器(可扩展到 Chrome Extension)
|
|
14
|
+
- 核心机制:快照驱动 + 工具调用 + 增量消费
|
|
15
|
+
- 架构分层:
|
|
16
|
+
- `core`:环境无关引擎(Agent Loop、AI Client、Tool Registry)
|
|
17
|
+
- `web`:浏览器能力实现(DOM/导航/快照/等待/执行)
|
|
23
18
|
|
|
24
19
|
---
|
|
25
20
|
|
|
@@ -31,299 +26,328 @@
|
|
|
31
26
|
pnpm install
|
|
32
27
|
```
|
|
33
28
|
|
|
34
|
-
###
|
|
29
|
+
### 基本使用
|
|
35
30
|
|
|
36
|
-
```
|
|
37
|
-
import { WebAgent } from "
|
|
31
|
+
```ts
|
|
32
|
+
import { WebAgent } from "agentpage";
|
|
38
33
|
|
|
39
34
|
const agent = new WebAgent({
|
|
40
35
|
token: "your-api-key",
|
|
41
|
-
provider: "
|
|
42
|
-
model: "
|
|
43
|
-
memory: true,
|
|
44
|
-
autoSnapshot: true,
|
|
36
|
+
provider: "deepseek", // openai | copilot | anthropic | deepseek
|
|
37
|
+
model: "deepseek-chat",
|
|
38
|
+
memory: true,
|
|
39
|
+
autoSnapshot: true,
|
|
40
|
+
stream: true,
|
|
45
41
|
});
|
|
46
42
|
|
|
47
|
-
agent.registerTools();
|
|
43
|
+
agent.registerTools();
|
|
48
44
|
|
|
49
45
|
agent.callbacks = {
|
|
50
|
-
|
|
51
|
-
onToolCall: (name, input) => console.log("
|
|
52
|
-
onToolResult: (name, result) => console.log("
|
|
53
|
-
|
|
46
|
+
onRound: (round) => console.log("round", round + 1),
|
|
47
|
+
onToolCall: (name, input) => console.log("tool", name, input),
|
|
48
|
+
onToolResult: (name, result) => console.log("result", name, result.content),
|
|
49
|
+
onText: (text) => console.log("assistant", text),
|
|
54
50
|
};
|
|
55
51
|
|
|
56
|
-
const result = await agent.chat("
|
|
52
|
+
const result = await agent.chat("打开任务弹窗,填写标题和优先级,然后提交");
|
|
57
53
|
console.log(result.reply);
|
|
58
54
|
```
|
|
59
55
|
|
|
60
|
-
###
|
|
56
|
+
### 启动 Demo
|
|
61
57
|
|
|
62
58
|
```bash
|
|
63
|
-
pnpm demo
|
|
59
|
+
pnpm demo
|
|
64
60
|
```
|
|
65
61
|
|
|
66
|
-
Demo 页面提供开箱即用的聊天 UI(暗色主题),包含:
|
|
67
|
-
- Token 输入(localStorage 持久化)
|
|
68
|
-
- 模型选择(gpt-4o / gpt-4o-mini / o3-mini)
|
|
69
|
-
- Dry-run 开关 & 多轮记忆开关
|
|
70
|
-
- 6 个快捷测试按钮(页面信息、DOM 快照、点击、链接、滚动、DOM 计数)
|
|
71
|
-
- 实时展示工具调用和结果
|
|
72
|
-
|
|
73
62
|
---
|
|
74
63
|
|
|
75
|
-
##
|
|
64
|
+
## 当前目录结构(权威)
|
|
76
65
|
|
|
77
|
-
```
|
|
66
|
+
```text
|
|
78
67
|
src/
|
|
79
|
-
├── core/
|
|
80
|
-
│ ├──
|
|
81
|
-
│ ├──
|
|
82
|
-
│ ├──
|
|
83
|
-
│ ├──
|
|
84
|
-
│
|
|
85
|
-
│
|
|
86
|
-
├──
|
|
87
|
-
│ ├──
|
|
88
|
-
│
|
|
89
|
-
│
|
|
90
|
-
│
|
|
91
|
-
│
|
|
92
|
-
│
|
|
93
|
-
│
|
|
94
|
-
│ ├──
|
|
95
|
-
│
|
|
96
|
-
│
|
|
97
|
-
|
|
98
|
-
├──
|
|
99
|
-
├──
|
|
68
|
+
├── core/
|
|
69
|
+
│ ├── index.ts
|
|
70
|
+
│ ├── types.ts
|
|
71
|
+
│ ├── tool-params.ts
|
|
72
|
+
│ ├── tool-registry.ts
|
|
73
|
+
│ ├── system-prompt.ts
|
|
74
|
+
│ ├── agent-loop/
|
|
75
|
+
│ │ ├── index.ts
|
|
76
|
+
│ │ ├── types.ts
|
|
77
|
+
│ │ ├── constants.ts
|
|
78
|
+
│ │ ├── helpers.ts
|
|
79
|
+
│ │ ├── snapshot.ts
|
|
80
|
+
│ │ ├── messages.ts
|
|
81
|
+
│ │ └── recovery.ts
|
|
82
|
+
│ └── ai-client/
|
|
83
|
+
│ ├── index.ts
|
|
84
|
+
│ ├── constants.ts
|
|
85
|
+
│ ├── custom.ts
|
|
86
|
+
│ ├── openai.ts
|
|
87
|
+
│ ├── anthropic.ts
|
|
88
|
+
│ ├── deepseek.ts
|
|
89
|
+
│ └── sse.ts
|
|
90
|
+
└── web/
|
|
91
|
+
├── index.ts
|
|
92
|
+
├── dom-tool.ts # 兼容转发层(re-export)
|
|
93
|
+
├── navigate-tool.ts # 兼容转发层(re-export)
|
|
94
|
+
├── page-info-tool.ts # 兼容转发层(re-export)
|
|
95
|
+
├── wait-tool.ts # 兼容转发层(re-export)
|
|
96
|
+
├── evaluate-tool.ts # 兼容转发层(re-export)
|
|
97
|
+
├── ref-store.ts
|
|
98
|
+
├── messaging.ts
|
|
99
|
+
└── tools/
|
|
100
|
+
├── dom-tool.ts
|
|
101
|
+
├── navigate-tool.ts
|
|
102
|
+
├── page-info-tool.ts
|
|
103
|
+
├── wait-tool.ts
|
|
104
|
+
└── evaluate-tool.ts
|
|
100
105
|
```
|
|
101
106
|
|
|
102
|
-
|
|
107
|
+
---
|
|
103
108
|
|
|
104
|
-
|
|
109
|
+
## 核心原理
|
|
105
110
|
|
|
106
|
-
|
|
107
|
-
|----|------|------|------|
|
|
108
|
-
| **core** | `src/core/` | 无(纯 TypeScript + fetch) | 任意(浏览器 / Worker) |
|
|
109
|
-
| **web** | `src/web/` | core + DOM API | 浏览器 |
|
|
111
|
+
### 1) 快照驱动决策
|
|
110
112
|
|
|
111
|
-
|
|
112
|
-
- ToolRegistry 是实例化的(非全局 Map),每个 Agent 拥有独立的工具集
|
|
113
|
-
- 全链路「容错不中断」— 单个工具失败不会中止 Agent 循环
|
|
113
|
+
AI 每一轮不是“凭记忆猜页面”,而是基于最新快照选择可执行动作。
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
快照包含:
|
|
116
|
+
- 元素标签与关键信息
|
|
117
|
+
- hash selector(如 `#a1b2c`)
|
|
118
|
+
- 结构化层级关系
|
|
119
|
+
|
|
120
|
+
### 2) 任务增量消费
|
|
116
121
|
|
|
117
|
-
|
|
122
|
+
用户任务会被分解成子任务,按轮次逐步“吃掉”:
|
|
118
123
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
| `anthropic` | `https://api.anthropic.com` | `x-api-key: <API Key>` |
|
|
124
|
+
- 轮次 N:做当前快照可满足的动作
|
|
125
|
+
- 工具执行后刷新快照
|
|
126
|
+
- 轮次 N+1:继续做剩余子任务
|
|
127
|
+
- 全部完成后返回总结文本
|
|
124
128
|
|
|
125
|
-
|
|
129
|
+
新增(渐进式协议):
|
|
130
|
+
- 每轮都会显式携带 `Current remaining instruction`(当前剩余文本)
|
|
131
|
+
- 每轮都会携带 `Previous round planned task array`(上一轮执行计划)
|
|
132
|
+
- 模型可在文本中返回:
|
|
133
|
+
- `REMAINING: <剩余内容>`:表示还有任务要继续
|
|
134
|
+
- `REMAINING: DONE`:表示剩余任务已空
|
|
126
135
|
|
|
127
|
-
###
|
|
136
|
+
### 3) 批量但不跨变更链式执行
|
|
128
137
|
|
|
129
|
-
|
|
138
|
+
允许同轮批量执行多个“当前可见目标”的动作;
|
|
139
|
+
不允许把“会导致新 DOM 出现”的后续动作强行塞进同轮。
|
|
130
140
|
|
|
131
|
-
|
|
132
|
-
|
|
141
|
+
例子:
|
|
142
|
+
- 可同轮:同时填写两个已可见输入框
|
|
143
|
+
- 不可同轮:点击“打开弹窗”后立即填写弹窗字段(应等下一轮新快照)
|
|
133
144
|
|
|
134
|
-
|
|
135
|
-
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 完整架构流程图(含链路)
|
|
148
|
+
|
|
149
|
+
### A. 端到端主流程
|
|
150
|
+
|
|
151
|
+
```mermaid
|
|
152
|
+
flowchart TD
|
|
153
|
+
U[用户输入任务] --> W[WebAgent.chat]
|
|
154
|
+
W --> P[构建 system prompt + 准备工具定义]
|
|
155
|
+
P --> L[executeAgentLoop]
|
|
156
|
+
L --> S[读取/刷新 latest snapshot]
|
|
157
|
+
S --> M[buildCompactMessages]
|
|
158
|
+
M --> C[AIClient.chat]
|
|
159
|
+
C --> D{是否返回 toolCalls}
|
|
160
|
+
D -->|是| X[ToolRegistry.dispatch 执行工具]
|
|
161
|
+
X --> T[写入 trace 与结果]
|
|
162
|
+
T --> S
|
|
163
|
+
D -->|否| F[输出最终总结并结束]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### B. 分层模块关系
|
|
167
|
+
|
|
168
|
+
```mermaid
|
|
169
|
+
flowchart LR
|
|
170
|
+
subgraph Web[web 层]
|
|
171
|
+
WI[web/index.ts\nWebAgent]
|
|
172
|
+
WT[web tools]
|
|
173
|
+
RS[ref-store.ts]
|
|
174
|
+
MG[messaging.ts]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
subgraph Core[core 层]
|
|
178
|
+
AL[agent-loop/*]
|
|
179
|
+
TR[tool-registry.ts]
|
|
180
|
+
SP[system-prompt.ts]
|
|
181
|
+
AI[ai-client/*]
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
WI --> AL
|
|
185
|
+
WI --> TR
|
|
186
|
+
WI --> SP
|
|
187
|
+
WI --> WT
|
|
188
|
+
WT --> RS
|
|
189
|
+
WI --> MG
|
|
190
|
+
|
|
191
|
+
AL --> AI
|
|
192
|
+
AL --> TR
|
|
136
193
|
```
|
|
137
194
|
|
|
138
|
-
|
|
195
|
+
### C. Agent Loop 轮次时序
|
|
196
|
+
|
|
197
|
+
```mermaid
|
|
198
|
+
sequenceDiagram
|
|
199
|
+
participant User as User
|
|
200
|
+
participant Agent as WebAgent
|
|
201
|
+
participant Loop as AgentLoop
|
|
202
|
+
participant AI as AIClient
|
|
203
|
+
participant Tool as ToolRegistry
|
|
204
|
+
|
|
205
|
+
User->>Agent: chat(task)
|
|
206
|
+
Agent->>Loop: executeAgentLoop(...)
|
|
207
|
+
loop round 0..max
|
|
208
|
+
Loop->>Loop: read snapshot/context
|
|
209
|
+
Loop->>AI: compact messages + tools
|
|
210
|
+
AI-->>Loop: text/toolCalls
|
|
211
|
+
alt has toolCalls
|
|
212
|
+
Loop->>Tool: dispatch tool calls
|
|
213
|
+
Tool-->>Loop: results
|
|
214
|
+
Loop->>Loop: recovery + refresh snapshot
|
|
215
|
+
else final text
|
|
216
|
+
Loop-->>Agent: final reply
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
```
|
|
139
220
|
|
|
140
|
-
|
|
141
|
-
import { buildChatRequest, parseChatResponse } from "autopilot/core/ai-client";
|
|
221
|
+
---
|
|
142
222
|
|
|
143
|
-
|
|
144
|
-
const req = buildChatRequest(config, { systemPrompt, messages, tools });
|
|
223
|
+
## Agent Loop 细节
|
|
145
224
|
|
|
146
|
-
|
|
147
|
-
req.headers["X-Custom"] = "value";
|
|
225
|
+
主流程位于 `src/core/agent-loop/index.ts`:
|
|
148
226
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
227
|
+
1. 确保当前快照可用
|
|
228
|
+
2. 构建紧凑消息(原始目标 + done steps + 最新快照)
|
|
229
|
+
3. 调用 AI
|
|
230
|
+
4. 执行工具调用并记录 trace
|
|
231
|
+
5. 运行保护机制
|
|
232
|
+
6. 刷新快照并进入下一轮
|
|
233
|
+
|
|
234
|
+
### 渐进式执行状态(新增)
|
|
235
|
+
|
|
236
|
+
`src/core/agent-loop/index.ts` 内部维护 3 个关键状态:
|
|
237
|
+
- `remainingInstruction`:当前轮次待消费文本(初始值为用户原始输入)
|
|
238
|
+
- `previousRoundTasks`:上一轮执行任务数组
|
|
239
|
+
- `lastPlannedBatchKey`:用于识别是否连续两轮给出完全相同的任务批次
|
|
240
|
+
|
|
241
|
+
停机规则:
|
|
242
|
+
- 若模型返回无工具调用 → 直接结束
|
|
243
|
+
- 若连续两轮规划出相同任务批次,且上一轮无错误 → 自动终止,防止自转
|
|
244
|
+
- 若模型文本包含 `REMAINING: DONE`,通常下一轮会自然进入“无工具调用总结”并结束
|
|
245
|
+
|
|
246
|
+
### 紧凑消息结构
|
|
247
|
+
|
|
248
|
+
由 `messages.ts` 构建,核心语义:
|
|
249
|
+
- Master goal:用户原始任务(永远保留)
|
|
250
|
+
- Done steps:已完成动作(避免重复)
|
|
251
|
+
- Execution context + latest snapshot:当前可执行范围
|
|
252
|
+
|
|
253
|
+
### 快照生命周期
|
|
254
|
+
|
|
255
|
+
由 `snapshot.ts` 管理:
|
|
256
|
+
- 读取快照
|
|
257
|
+
- 包裹快照边界
|
|
258
|
+
- 去重历史快照
|
|
259
|
+
- 剥离旧 prompt 快照
|
|
155
260
|
|
|
156
261
|
---
|
|
157
262
|
|
|
158
|
-
##
|
|
263
|
+
## 保护机制
|
|
159
264
|
|
|
160
|
-
|
|
161
|
-
|------|------|------|
|
|
162
|
-
| **dom** | `click`, `fill`, `type`, `get_text`, `get_attr`, `set_attr`, `add_class`, `remove_class` | DOM 操作(支持 ref 路径和 CSS 选择器) |
|
|
163
|
-
| **navigate** | `goto`, `back`, `forward`, `reload`, `scroll` | 页面导航 |
|
|
164
|
-
| **page_info** | `get_url`, `get_title`, `get_selection`, `get_viewport`, `snapshot`, `query_all` | 页面信息与 DOM 快照 |
|
|
165
|
-
| **wait** | `wait_for_selector`, `wait_for_hidden`, `wait_for_text` | 等待元素变化(MutationObserver) |
|
|
166
|
-
| **evaluate** | *expression* | 执行任意 JavaScript(`new Function`) |
|
|
265
|
+
由 `recovery.ts` 提供:
|
|
167
266
|
|
|
168
|
-
|
|
267
|
+
- 冗余 `page_info` 拦截:减少无意义工具调用
|
|
268
|
+
- 元素找不到恢复:自动等待并刷新快照
|
|
269
|
+
- 导航 URL 变化检测:更新上下文,防止旧定位污染
|
|
270
|
+
- 空转检测:避免循环无进展
|
|
271
|
+
- 重复批次防自转:连续返回同一批任务时自动停止
|
|
169
272
|
|
|
170
|
-
|
|
273
|
+
这些机制直接决定“调用次数、成功率、稳定性”。
|
|
171
274
|
|
|
172
|
-
|
|
275
|
+
---
|
|
173
276
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
[a] "首页" href="/" ref="/body/header/nav/a[1]"
|
|
178
|
-
[a] "关于" href="/about" ref="/body/header/nav/a[2]"
|
|
179
|
-
[main] ref="/body/main"
|
|
180
|
-
[h1] "欢迎" ref="/body/main/h1"
|
|
181
|
-
[input] type="text" placeholder="搜索..." ref="/body/main/input"
|
|
182
|
-
[button] "搜索" id="search-btn" onclick ref="/body/main/button"
|
|
183
|
-
```
|
|
277
|
+
## AI Client 设计
|
|
278
|
+
|
|
279
|
+
`src/core/ai-client/` 提供统一接口,内部按 provider 适配:
|
|
184
280
|
|
|
185
|
-
|
|
281
|
+
- `openai.ts`:OpenAI / Copilot 协议
|
|
282
|
+
- `anthropic.ts`:Anthropic 协议
|
|
283
|
+
- `deepseek.ts`:DeepSeek 协议
|
|
284
|
+
- `sse.ts`:流式事件解析
|
|
186
285
|
|
|
187
|
-
|
|
286
|
+
统一输出为 `AIChatResponse`,上层 loop 无需关心 provider 差异。
|
|
188
287
|
|
|
189
|
-
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Web 工具体系
|
|
291
|
+
|
|
292
|
+
内置 5 个工具(`src/web/*.ts`):
|
|
293
|
+
|
|
294
|
+
1. `dom`:点击、填写、输入等交互
|
|
295
|
+
2. `navigate`:跳转、前进后退、滚动
|
|
296
|
+
3. `page_info`:URL/标题/快照/查询
|
|
297
|
+
4. `wait`:等待元素或文本条件
|
|
298
|
+
5. `evaluate`:执行页面上下文 JS
|
|
299
|
+
|
|
300
|
+
通过 `ToolRegistry` 统一暴露给模型,执行结果标准化返回。
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## 扩展与自定义
|
|
305
|
+
|
|
306
|
+
### 注册自定义工具
|
|
307
|
+
|
|
308
|
+
```ts
|
|
190
309
|
import { Type } from "@sinclair/typebox";
|
|
191
310
|
|
|
192
311
|
agent.registerTool({
|
|
193
312
|
name: "my_tool",
|
|
194
|
-
description: "
|
|
313
|
+
description: "业务工具说明",
|
|
195
314
|
schema: Type.Object({
|
|
196
|
-
|
|
315
|
+
value: Type.String(),
|
|
197
316
|
}),
|
|
198
317
|
async execute(params) {
|
|
199
|
-
return { content:
|
|
318
|
+
return { content: `ok: ${params.value}` };
|
|
200
319
|
},
|
|
201
320
|
});
|
|
202
321
|
```
|
|
203
322
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
## API
|
|
207
|
-
|
|
208
|
-
### `WebAgent`
|
|
323
|
+
### Chrome Extension 模式
|
|
209
324
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
**配置选项:**
|
|
215
|
-
|
|
216
|
-
| 选项 | 类型 | 默认值 | 说明 |
|
|
217
|
-
|------|------|--------|------|
|
|
218
|
-
| `token` | `string` | 必填 | API Key(GitHub PAT / OpenAI key / Anthropic key) |
|
|
219
|
-
| `provider` | `string` | `"copilot"` | AI 提供商:`"copilot"` \| `"openai"` \| `"anthropic"` |
|
|
220
|
-
| `model` | `string` | `"gpt-4o"` | 模型名称 |
|
|
221
|
-
| `baseURL` | `string` | — | 自定义 API 基础 URL |
|
|
222
|
-
| `dryRun` | `boolean` | `false` | 干运行(只打印工具调用不执行) |
|
|
223
|
-
| `systemPrompt` | `string` | — | 自定义系统提示词(不传则使用默认) |
|
|
224
|
-
| `maxRounds` | `number` | `10` | 最大工具调用轮次 |
|
|
225
|
-
| `memory` | `boolean` | `false` | 多轮对话记忆开关 |
|
|
226
|
-
| `autoSnapshot` | `boolean` | `true` | 每次 chat 前自动生成 DOM 快照 |
|
|
227
|
-
|
|
228
|
-
**方法:**
|
|
229
|
-
|
|
230
|
-
| 方法 | 说明 |
|
|
231
|
-
|------|------|
|
|
232
|
-
| `registerTools()` | 注册 5 个内置 Web 工具 |
|
|
233
|
-
| `registerTool(tool)` | 注册自定义工具 |
|
|
234
|
-
| `getTools()` | 获取所有已注册工具定义 |
|
|
235
|
-
| `chat(message)` | 发送消息,返回 `AgentLoopResult` |
|
|
236
|
-
| `setToken(token)` | 更新 API Key |
|
|
237
|
-
| `setProvider(provider)` | 更新 AI 提供商 |
|
|
238
|
-
| `setModel(model)` | 更新模型 |
|
|
239
|
-
| `setDryRun(enabled)` | 切换干运行模式 |
|
|
240
|
-
| `setSystemPrompt(prompt)` | 设置自定义系统提示词 |
|
|
241
|
-
| `setMemory(enabled)` | 开关多轮记忆(关闭时自动清空历史) |
|
|
242
|
-
| `getMemory()` | 获取当前记忆开关状态 |
|
|
243
|
-
| `setAutoSnapshot(enabled)` | 开关自动快照 |
|
|
244
|
-
| `getAutoSnapshot()` | 获取当前自动快照开关 |
|
|
245
|
-
| `clearHistory()` | 清空对话历史(不影响记忆开关) |
|
|
246
|
-
|
|
247
|
-
**回调(`callbacks`):**
|
|
248
|
-
|
|
249
|
-
| 回调 | 触发时机 |
|
|
250
|
-
|------|---------|
|
|
251
|
-
| `onRound(round)` | 每轮循环开始(round 从 0 开始) |
|
|
252
|
-
| `onText(text)` | AI 返回文本回复 |
|
|
253
|
-
| `onToolCall(name, input)` | AI 请求调用工具(执行前) |
|
|
254
|
-
| `onToolResult(name, result)` | 工具执行完成 |
|
|
255
|
-
| `onSnapshot(snapshot)` | 自动快照生成完成 |
|
|
256
|
-
|
|
257
|
-
### `AgentLoopResult`
|
|
258
|
-
|
|
259
|
-
`chat()` 返回值:
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
{
|
|
263
|
-
reply: string; // AI 的最终文本回复
|
|
264
|
-
toolCalls: Array<{ // 所有工具调用记录
|
|
265
|
-
name: string;
|
|
266
|
-
input: unknown;
|
|
267
|
-
result: ToolCallResult;
|
|
268
|
-
}>;
|
|
269
|
-
messages: AIMessage[]; // 完整对话消息(用于多轮记忆累积)
|
|
270
|
-
}
|
|
271
|
-
```
|
|
325
|
+
`web/messaging.ts` 提供消息桥:
|
|
326
|
+
- Service Worker 发起工具调用
|
|
327
|
+
- Content Script 执行 DOM 工具
|
|
328
|
+
- 回传结果给后台 Agent
|
|
272
329
|
|
|
273
330
|
---
|
|
274
331
|
|
|
275
|
-
##
|
|
276
|
-
|
|
277
|
-
AutoPilot 内置 Service Worker ↔ Content Script 消息桥,解决 Chrome Extension 的作用域隔离:
|
|
278
|
-
|
|
279
|
-
```
|
|
280
|
-
Service Worker (后台) Content Script (页面)
|
|
281
|
-
┌──────────────────┐ ┌──────────────────────┐
|
|
282
|
-
│ AI Agent 核心 │ AUTOPILOT_TOOL_CALL │ DOM 操作执行 │
|
|
283
|
-
│ createProxy │ ────────────────► │ registerToolHandler │
|
|
284
|
-
│ Executor() │ │ │
|
|
285
|
-
│ │ AUTOPILOT_TOOL_RESULT│ │
|
|
286
|
-
│ │ ◄──────────────── │ │
|
|
287
|
-
└──────────────────┘ └──────────────────────┘
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
```typescript
|
|
291
|
-
// Service Worker 端
|
|
292
|
-
import { createProxyExecutor } from "agentpage";
|
|
293
|
-
const execute = createProxyExecutor();
|
|
332
|
+
## 设计约束(必须遵守)
|
|
294
333
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
334
|
+
- `web` 只依赖 `core`,`core` 不依赖 DOM API
|
|
335
|
+
- ToolRegistry 必须实例化,禁止全局单例污染
|
|
336
|
+
- 工具失败应返回可消费结果,不应直接中断主循环
|
|
337
|
+
- 消息策略与系统提示必须一致(否则会增加无效 completion)
|
|
299
338
|
|
|
300
339
|
---
|
|
301
340
|
|
|
302
|
-
##
|
|
341
|
+
## 开发命令
|
|
303
342
|
|
|
304
343
|
```bash
|
|
305
|
-
pnpm install
|
|
306
|
-
pnpm
|
|
307
|
-
pnpm
|
|
308
|
-
pnpm
|
|
309
|
-
pnpm
|
|
310
|
-
pnpm format:check # 检查格式(oxfmt --check,不修改)
|
|
311
|
-
pnpm demo # 启动 Demo(Vite,端口 3000)
|
|
312
|
-
pnpm test # 运行测试(vitest run,单次执行)
|
|
313
|
-
pnpm test:watch # 运行测试(vitest watch 模式)
|
|
344
|
+
pnpm install
|
|
345
|
+
pnpm check
|
|
346
|
+
pnpm test
|
|
347
|
+
pnpm demo
|
|
348
|
+
pnpm build
|
|
314
349
|
```
|
|
315
350
|
|
|
316
|
-
### 工具链
|
|
317
|
-
|
|
318
|
-
| 工具 | 用途 |
|
|
319
|
-
|------|------|
|
|
320
|
-
| **tsdown** | 构建打包(产出 `dist/`) |
|
|
321
|
-
| **oxlint** | 代码检查(替代 ESLint) |
|
|
322
|
-
| **oxfmt** | 代码格式化(替代 Prettier) |
|
|
323
|
-
| **vitest** | 测试框架(覆盖率阈值 60%) |
|
|
324
|
-
| **vite** | Demo 开发服务器 |
|
|
325
|
-
| **TypeScript 5.9+** | 严格模式,`module: NodeNext` |
|
|
326
|
-
|
|
327
351
|
---
|
|
328
352
|
|
|
329
353
|
## License
|