pageqa 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  用自然语言驱动的页面测试 agent。基于 **pi-agent-core**(状态化 LLM agent)编排测试步骤,**browserskill(`bsk`)** 驱动真实浏览器执行,自然语言解析由可配置的 LLM 端点完成。最终产出可读文本报告与机器可读 JSON 报告,返回可接入 CI 的退出码。
4
4
 
5
- - 运行时:**Node.js + TypeScript**,npm 分发,CLI 入口。
5
+ <https://github.com/user-attachments/assets/d5315f93-7e02-4445-a7cf-506b3bfcaa2d>
6
+
7
+ - 运行时:**Node.js + TypeScript**,以 npm 包分发、CLI 入口;仓库开发使用 **pnpm**(锁文件为 `pnpm-lock.yaml`)。
6
8
  - 浏览器驱动:**browserskill(`bsk`)**,连接一个已运行的真实浏览器(Chrome/Edge),支持公开页与登录态页面。
7
9
  - 自然语言驱动:**pi-agent-core** 状态化 agent,把自然语言意图解析为浏览器操作步骤并自动编排;LLM 后端通过可配置的 OpenAI 兼容端点接入(base URL / API Key / 模型均可配置)。
8
10
 
@@ -12,16 +14,29 @@
12
14
 
13
15
  `bsk` 是连接真实浏览器(Chrome/Edge)的驱动,本项目通过它执行页面操作。
14
16
 
15
- - 项目主页与安装方式:**https://github.com/Tencent/BrowserSkill**
16
- - 按仓库 README 安装 `bsk` CLI 并启动 daemon,然后连接一个已登录的浏览器(支持公开页与登录态页面)。
17
+ - 项目主页与安装方式:**<https://github.com/Tencent/BrowserSkill>**
18
+ - 按仓库 README **安装 `bsk` CLI**(只需装一次)。
19
+
20
+ > **无需手动启动 daemon**:运行 `pageqa` 时会自动检查并在 daemon 未运行时后台启动它(`bsk daemon start`),每个进程只启动一次。你也可以用 `bsk status` 查看状态。
21
+
22
+ **浏览器连接仍需你来做**(这是物理操作,pageqa 无法自动完成):在浏览器中安装 bsk 扩展并完成连接。若启动时检测不到任何已连接浏览器,pageqa 会明确报错并提示你先连接,而不是卡死。
17
23
 
18
24
  验证安装与连接:
25
+
19
26
  ```bash
20
- bsk status # 确认 daemon 已启动且已连接浏览器
21
- bsk session start # 创建 session(CLI 也会自动创建)
27
+ bsk status # 查看 daemon 与已连接浏览器
28
+ bsk session start # 可选:手动创建 session(不传 --session 时 pageqa 会自动创建)
22
29
  ```
23
30
 
24
- > 提示:本工具的 `--session <id>` 即来自 `bsk session start` 返回的 `session_id`;不传时 CLI 会自动新建一个(前提 daemon 已连浏览器)。
31
+ > 提示:本工具的 `--session <id>` 即来自 `bsk session start` 返回的 `session_id`;不传时 CLI 会自动新建一个(前提已有浏览器连接)。
32
+
33
+ > **重点提示:要执行「文件上传」用例,必须先给 bsk 浏览器扩展开启「允许访问文件网址(Allow access to file URLs)」,否则上传一定失败。**
34
+ >
35
+ > 开启方式(Edge / Chrome):打开 `edge://extensions`(或 `chrome://extensions`)→ 找到 BrowserSkill 扩展 → 点「详细信息」→ 打开「允许访问文件网址」开关 → 回到扩展卡片点一次「重新加载」(必要时重启浏览器)。
36
+ >
37
+ > 未开启时的典型报错:`the upload trigger did not activate a file input`,以及 `the browser could not attach the staged file to the input ... {"code":-32000,"message":"Not allowed"}`。
38
+ >
39
+ > 这是浏览器级设置,**pageqa 与 bsk 都无法自动开启**(Agent Window 也无法打开 `edge://` 页面),必须人工开一次;开启后本机所有上传用例都可用。
25
40
 
26
41
  ### 2. LLM 后端(可配置 OpenAI 兼容端点)
27
42
 
@@ -31,6 +46,7 @@ bsk session start # 创建 session(CLI 也会自动创建)
31
46
  - 默认 Key:`codebuddy-proxy-key`
32
47
 
33
48
  可用环境变量覆盖(优先级高于配置文件):
49
+
34
50
  - `PAGEQA_LLM_BASE_URL`
35
51
  - `PAGEQA_LLM_API_KEY`
36
52
  - `PAGEQA_LLM_MODEL`
@@ -54,17 +70,73 @@ bsk session start # 创建 session(CLI 也会自动创建)
54
70
  - **优先级(高 → 低)**:环境变量 `PAGEQA_LLM_*` > 用户配置文件 `config.json` > 内置默认值。
55
71
  - 例如要改用其他兼容 OpenAI 的端点,把 `baseUrl`/`apiKey`/`model` 改掉即可,无需改代码。
56
72
 
73
+ ### 4. Jev 语义断言(可选增强)
74
+
75
+ > **什么是 Jev?** Jev 是 TypeSafe AI 推出的 [System One 模型](https://docs.typesafe.ai),专为结构化决策设计。它不做文本生成,而是直接返回校准后的概率值(如匹配度 0.93)。适合替代原有的字符串包含匹配,做更精准的语义级断言。
76
+
77
+ **启用方式**:在 `~/.pageqa/config.json` 中添加 `jev` 字段,或设置环境变量:
78
+
79
+ ```json
80
+ {
81
+ "baseUrl": "http://127.0.0.1:3000/v1",
82
+ "apiKey": "codebuddy-proxy-key",
83
+ "model": "hunyuan-2.0-instruct",
84
+ "jev": {
85
+ "enabled": true,
86
+ "apiKey": "your-typesafe-api-key",
87
+ "model": "jev-latest",
88
+ "threshold": 0.5
89
+ }
90
+ }
91
+ ```
92
+
93
+ | Jev 配置项 | 说明 | 默认值 |
94
+ | --- | --- | --- |
95
+ | `enabled` | 是否启用 Jev 语义断言 | `false` |
96
+ | `apiKey` | TypeSafe API 密钥 | (无) |
97
+ | `model` | Jev 模型 ID | `jev-latest` |
98
+ | `threshold` | 语义匹配概率阈值(0~1) | `0.5` |
99
+
100
+ **环境变量覆盖**(优先级高于配置文件):
101
+
102
+ - `PAGEQA_JEV_ENABLED=true`
103
+ - `PAGEQA_JEV_API_KEY=<your-key>`
104
+ - `PAGEQA_JEV_MODEL=jev-latest`
105
+ - `PAGEQA_JEV_THRESHOLD=0.6`
106
+
107
+ **获取 API Key**:
108
+
109
+ 1. 访问 [console.typesafe.ai/settings/keys](https://console.typesafe.ai/settings/keys)(需等待早期访问权限)
110
+ 2. 或通过 Vercel AI Gateway 获取
111
+
112
+ **工作原理**:启用后,`assert_text` 工具会将页面快照文本发送给 Jev,由 Jev 判断页面内容是否语义匹配断言期望。相比原有的字符串 `includes` 匹配,Jev 能处理同义词、近义表达、大小写变体等情况,大幅降低误判。
113
+
114
+ **降级机制**:若 Jev API 调用失败(网络/超时/鉴权错误),会自动回退到原有的字符串包含匹配,确保测试不因 Jev 服务中断而失败。
115
+
116
+ **架构示意**:
117
+
118
+ ```text
119
+ 自然语言意图
120
+ └─> pi-agent-core Agent(LLM → 可配置 OpenAI 兼容端点)
121
+ └─> bsk 工具:navigate / snapshot / click / fill / hover / scroll / wait
122
+ └─> 真实浏览器(bsk 连接)
123
+ └─> assert_text ──→ Jev Noul API(可选,语义匹配)
124
+ └─> 结论与证据 → 报告(文本/JSON)+ 退出码
125
+ ```
126
+
57
127
  ## 安装
58
128
 
59
- 本地开发:
129
+ 本地开发(仓库使用 pnpm,请先安装:`npm install -g pnpm`):
130
+
60
131
  ```bash
61
- npm install
62
- npm run build
132
+ pnpm install --frozen-lockfile
133
+ pnpm run build
63
134
  ```
64
135
 
65
136
  全局安装(发布后):
137
+
66
138
  ```bash
67
- npm install -g pageqa
139
+ npm install -g pageqa # 或 pnpm add -g pageqa
68
140
  pageqa --init-config # 在用户目录创建配置文件 ~/.pageqa/config.json
69
141
  ```
70
142
 
@@ -91,6 +163,27 @@ pageqa --suite "打开 https://example.com 并断言标题包含 Example"
91
163
 
92
164
  脚本(`.md`/`.txt`)中用 `## 场景名` 分隔多个独立测试场景,CLI 会逐个运行、分别给出结论,并汇总整体 PASS/FAIL 与总退出码(任一场景失败则整体失败)。
93
165
 
166
+ ### 脚本占位符(运行时变量)
167
+
168
+ 脚本里可以写 `${timestamp}` 之类的占位符,CLI 在读取脚本时按本机当前时间展开。同一次运行内所有占位符共用同一时刻,所以「名称 + 时间戳」这类用例既不会重名,也不必每次手工改时间戳:
169
+
170
+ ```md
171
+ ## P1 创建产品
172
+
173
+ 打开 https://example.com/product
174
+ 点击「新增」,填写产品名称 `自动化测试产品${timestamp}`
175
+ 断言页面包含 `自动化测试产品${timestamp}`
176
+ ```
177
+
178
+ | 占位符 | 展开结果 |
179
+ | --- | --- |
180
+ | `${timestamp}` | `yyyyMMddHHmm`,如 `202609191146` |
181
+ | `${date}` / `${time}` | `yyyyMMdd` / `HHmmss` |
182
+ | `${datetime}` | `yyyyMMddHHmmss` |
183
+ | `${timestamp:<格式>}` | 自定义格式,支持 `yyyy` `yy` `MM` `dd` `HH` `mm` `ss` `SSS`,如 `${timestamp:yyyy-MM-dd HH:mm}` |
184
+
185
+ 未识别的占位符(如 `${PATH}`)原样保留,不会被替换。完整示例:`examples/plm-product-bom.md`。
186
+
94
187
  ### CLI 选项
95
188
 
96
189
  | 选项 | 说明 |
@@ -104,27 +197,58 @@ pageqa --suite "打开 https://example.com 并断言标题包含 Example"
104
197
 
105
198
  退出码:`0` 全部断言通过;`1` 任一断言失败/错误/无法执行。可直接接入 CI。
106
199
 
200
+ ### 文件上传
201
+
202
+ 脚本里直接写「点击某个上传按钮上传本地文件 `<绝对路径>`」,agent 会调用 `upload` 工具完成(可运行 `examples/element-plus-upload.md` 体验):
203
+
204
+ ```md
205
+ ## U1 点击 Click to upload 上传图片
206
+
207
+ 打开 https://element-plus.org/zh-CN/component/upload
208
+ 点击示例中的「Click to upload」按钮并上传本地文件 D:\Downloads\example.png
209
+ 等待 2 秒,让上传列表完成渲染
210
+ 断言页面中已出现上传的文件名 example.png
211
+ ```
212
+
213
+ ```bash
214
+ pageqa examples/element-plus-upload.md
215
+ ```
216
+
217
+ 要点(踩过的坑):
218
+
219
+ - **先开扩展权限**:见「前置 → 1. 安装并配置 browserskill」中的重点提示。未开启时上传必然失败,报 `Not allowed`。
220
+ - `target` 传**触发文件选择器的元素**(按钮的 `@eN` 或 CSS 选择器);不要传隐藏的 `input[type=file]`——它没有可见几何,bsk 会拒绝点击并报 `target element has no visible geometry`。省略 `target` 时由 bsk 自动在页面中查找文件输入框。
221
+ - **不要先 `click` 上传按钮再调用上传**:原生系统文件选择框无法被自动化操作,单独 click 会把流程挂住。`upload` 会自己点击触发元素并接管文件选择器。
222
+ - 路径必须是**本机绝对路径且文件真实存在**:`upload` 会先校验,不存在直接报错,不会默默跳过。
223
+ - 像 `el-upload` 这类「点击按钮 → 页面 JS 触发隐藏 input」的组件,首次尝试可能返回 `did not activate a file input`(时序问题,不是权限问题);此时重试一次即可成功。
224
+ - 上传动作成功不等于用例通过:**真伪仍由页面断言决定**。若站点把文件提交到外部接口而接口不可用(例如 element-plus 文档示例提交到 `run.mocky.io`,本机证书校验失败),组件会在上传失败后移除该文件,此时「断言文件出现在列表中」会如实报 FAIL——这是被测页面的真实行为,不是工具问题。
225
+
107
226
  ## 工作原理
108
227
 
109
228
  ```
110
229
  自然语言意图
111
230
  └─> pi-agent-core Agent(LLM: pi-ai 自定义 provider -> 可配置 OpenAI 兼容端点)
112
- └─> bsk 工具:navigate / snapshot / click / fill / hover / scroll / wait / assert_text
231
+ └─> bsk 工具:navigate / snapshot / click / fill / upload / hover / scroll / wait / assert_text
113
232
  └─> 真实浏览器(bsk 连接)
114
233
  └─> 结论与证据 -> 报告(文本/JSON)+ 退出码
115
234
  ```
116
235
 
117
236
  可用工具(`src/bsk/tools.ts`):
237
+
118
238
  - `navigate(url)` 打开网页
119
239
  - `snapshot()` 读取页面 aria 树与可见文本(标题、段落、链接、按钮等)
120
240
  - `click(target)` / `fill(target, value)` / `hover(target)` 元素交互(target 用 `@eN` 引用或 CSS 选择器)
241
+ - `upload(target, file)` 上传本地文件(target 为触发文件选择器的元素,省略则由 bsk 自动查找文件输入框)
121
242
  - `scroll(target)` / `wait(ms)` 滚动与等待
122
243
  - `assert_text(expectation)` 断言页面是否包含指定文本,返回「成立/不成立」与证据
123
244
 
245
+ **长流程保护(自动续跑)**:一轮对话结束后,如果 agent 自报的进度没跑满(`步骤完成:k/n` 且 `k < n`),或者用例里写了断言但报告只解析到一部分,pageqa 会自动补一次「继续执行剩余步骤」的提示并继续跑,最多 5 轮;续跑后进度与断言数都没有推进就停止。这样可以避免模型做完一两步就自行收尾、却让报告看起来正常的情况。
246
+
124
247
  ## 验证
125
248
 
126
249
  ```bash
127
- npm test
250
+ pnpm test # 端到端冒烟:需 bsk daemon 已连接浏览器 + LLM 端点可用
251
+ pnpm run test:unit # 仅单元测试:不依赖浏览器与 LLM
128
252
  ```
129
253
 
130
254
  冒烟测试覆盖:A1 打开+标题断言、A2 元素交互与断言、A3 失败可读原因与退出码、A4 文本/JSON 报告。需 bsk daemon 连接浏览器且 LLM 端点可用。
@@ -137,7 +261,18 @@ pageqa examples/smoke.md --json
137
261
 
138
262
  ## CI 集成
139
263
 
140
- `.github/workflows/ci.yml` 演示如何在 GitHub Actions 中接入:安装 bsk 并连接浏览器 构建 运行 `examples/smoke.md`上传 JSON 报告。失败场景会使退出码非零,从而标记 CI 失败。LLM 端点地址/Key 通过仓库 Secrets(`PAGEQA_LLM_BASE_URL` 等)注入。
264
+ **`.github/workflows/ci.yml`**:在 `master`/`main` push PR 上运行,流程为 pnpm 冻结锁文件安装(`pnpm install --frozen-lockfile`)→ `pnpm run build` → `pnpm run test:unit`。
265
+
266
+ 端到端冒烟(`examples/smoke.md`)需要 bsk daemon、已连接的真实浏览器与可用的 LLM 端点,GitHub 托管 runner 上不具备这些条件,因此不在仓库 CI 中运行。若要在自己的 CI 里跑端到端,用环境变量注入 LLM 端点(`PAGEQA_LLM_BASE_URL` / `PAGEQA_LLM_API_KEY` / `PAGEQA_LLM_MODEL`,建议放仓库 Secrets):
267
+
268
+ ```bash
269
+ pnpm run build
270
+ node dist/index.js --json examples/smoke.md
271
+ ```
272
+
273
+ 任一断言失败会返回非零退出码,可直接作为 CI 门禁。
274
+
275
+ **`.github/workflows/release.yml`**:推送 `v*` tag 时触发,`check` job 先冻结锁文件安装并构建,随后通过 npm **OIDC 可信发布**(依赖 `id-token: write`,无需 `NPM_TOKEN`)发布到 npm 并自动创建 GitHub Release。发布产物附带 SLSA provenance 证明,因此 `package.json` 中的 `repository` 字段必须与仓库地址一致,不可删除。
141
276
 
142
277
  ## 目录
143
278
 
@@ -146,7 +281,11 @@ src/
146
281
  index.ts CLI 入口
147
282
  agent.ts 编排器(pi-agent-core Agent + bsk 工具 + 报告)
148
283
  llm.ts LLM 后端(pi-ai 自定义 provider -> 可配置 OpenAI 兼容端点)
149
- bsk/tools.ts browserskill 工具层
284
+ bsk/tools.ts browserskill 工具层(含 upload 文件上传)
150
285
  report.ts 报告解析与渲染
286
+ examples/
287
+ smoke.md 示例套件(A1–A3)
288
+ github-star.md GitHub Star 用例
289
+ element-plus-upload.md 文件上传用例(点击 Click to upload 上传本地图片)
151
290
  tests/smoke.test.mjs 端到端验证
152
291
  ```
package/dist/agent.d.ts CHANGED
@@ -2,6 +2,7 @@ import { type TestReport } from "./report.js";
2
2
  export interface AgentOptions {
3
3
  session?: string;
4
4
  systemPrompt?: string;
5
+ debug?: boolean;
5
6
  }
6
7
  export interface AgentRunResult {
7
8
  report: TestReport;
@@ -15,6 +16,8 @@ interface Scenario {
15
16
  }
16
17
  /**
17
18
  * 用 pi-agent-core 编排一次自然语言页面测试:注入 bsk 工具,驱动浏览器执行,整理报告。
19
+ * 若配置中启用了 Jev(PAGEQA_JEV_ENABLED=true 且配置了 API Key),
20
+ * 断言环节会使用 Jev 语义判断替代字符串包含匹配。
18
21
  */
19
22
  export declare function runAgent(input: string, opts?: AgentOptions): Promise<AgentRunResult>;
20
23
  /** 把一个脚本拆分为多个场景(按 `## ` 二级标题分隔)。无标题则整体作为一个场景。 */
package/dist/agent.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import { Agent } from "@earendil-works/pi-agent-core";
2
2
  import { createLlmBackend } from "./llm.js";
3
- import { createBskTools, ensureSession } from "./bsk/tools.js";
4
- import { buildReport } from "./report.js";
3
+ import { createBskTools, ensureSession, ensureBskReady } from "./bsk/tools.js";
4
+ import { JevClient } from "./jev.js";
5
+ import { loadConfig } from "./config.js";
6
+ import { buildReport, countAssertions, parseAssertions, parseProgress, } from "./report.js";
5
7
  const DEFAULT_SYSTEM_PROMPT = [
6
8
  "你是「页面测试 agent」。你根据用户的自然语言测试意图,驱动浏览器完成端到端测试。",
7
9
  "",
@@ -9,26 +11,131 @@ const DEFAULT_SYSTEM_PROMPT = [
9
11
  "- navigate(url): 打开网页",
10
12
  "- snapshot(): 读取页面 aria 树与可见文本(标题、段落、链接、按钮等),并定位元素",
11
13
  "- click(target) / fill(target, value) / hover(target): 元素交互,target 用 @eN 引用或 CSS 选择器",
14
+ "- upload(target, file): 上传本地文件到文件输入框/上传区域,target 传触发上传的元素(或省略由工具自动查找)",
12
15
  "- scroll(target) / wait(ms): 滚动与等待",
13
16
  "- assert_text(expectation): 断言页面是否包含某文本,返回「成立/不成立」与证据",
14
17
  "",
15
- "工作流程:",
16
- "1. 若需要打开页面,先 navigate",
17
- "2. snapshot 读取当前内容并定位要操作的元素。",
18
+ "工作流程(必须严格遵守):",
19
+ "1. 第一步永远是 navigate(url) 打开目标页面,等待其加载完成。",
20
+ "2. navigate 之后立即调用 snapshot() 确认页面已真实打开、读取当前内容并定位元素。",
18
21
  "3. 按用户意图逐步交互;每次交互后如需要可再次 snapshot 确认状态。",
19
- "4. assert_text 校验关键结果,或在 snapshot 基础上自行判断文本/标题是否匹配。",
22
+ "4. 只有在 navigate + snapshot 已成功、页面确为期望页面之后,才能调用 assert_text 校验关键结果。",
20
23
  "5. 最后用简洁中文给出结论:每个断言「成立/不成立」,并附证据(实际看到的标题或文本片段)。",
21
- "6. 不要编造未观察到的内容;若元素不存在或断言失败,明确说明。",
24
+ "",
25
+ "完整性要求(长流程尤其重要):",
26
+ "- 必须按顺序执行完提示中列出的**每一个步骤**(包括以 `### ` 标注的每个子步骤),不得只完成前几步就总结收尾。",
27
+ "- 每完成一个步骤,简要记一句「第 k 步完成:<结果>」,再继续下一步;不要提前输出最终结论。",
28
+ "- 结尾必须单独输出一行进度声明,格式固定:`步骤完成:<已完成步骤数>/<总步骤数>`。",
29
+ " 例如共 7 个步骤且全部完成时输出 `步骤完成:7/7`;只完成 4 步则输出 `步骤完成:4/7`。",
30
+ "- 若某步骤确实无法完成(元素找不到、操作被拒绝等),明确说明该步骤失败及原因,然后继续或终止,但仍要如实输出进度声明。",
31
+ "- 只要还有未执行的步骤,就继续调用工具执行下一步,不要中途停下等待用户输入;只有全部步骤都执行(或已明确失败)后才输出进度声明并收尾。",
32
+ "- 工具调用失败(如 click 找不到元素、超时)不等于该步骤失败:必须先重新 snapshot 定位元素后重试;同一操作连续两次失败才可判定该步骤失败。",
33
+ "",
34
+ "硬性约束(违反即视为测试失败):",
35
+ "- 严禁在 navigate 之前调用 assert_text:页面尚未打开时断言必然不成立,且会误报通过。",
36
+ "- 严禁在尚未 snapshot 确认页面内容的情况下就断言;若 snapshot 返回内容为空或明显不是目标页面,应报告「不成立」并说明原因,而不是编造结论。",
37
+ "- 严禁在步骤未执行完的情况下给出「测试通过」结论;宁可报告某步骤失败,也不要静默省略步骤。",
38
+ "- 不要编造未观察到的内容;若元素不存在、导航失败或页面未打开,明确说明。",
39
+ "- 涉及文件上传时必须用 upload 工具:原生系统文件选择框无法被自动化点击,直接 click 上传按钮会卡住流程。",
22
40
  "",
23
41
  "只输出测试结论与证据,不要输出多余解释。",
24
42
  ].join("\n");
43
+ // 上下文压力控制:长流程会累积大量页面快照(一次快照几千至上万字符),
44
+ // 默认模型上下文窗口只有 32k token,若不裁剪会把早期的步骤说明挤出上下文,
45
+ // 导致模型「忘记」后续步骤而提前收尾。
46
+ const CONTEXT_CHAR_LIMIT = 40_000;
47
+ const KEEP_RECENT_MESSAGES = 12;
48
+ const MAX_OLD_TOOL_CHARS = 1_500;
49
+ const TRIMMED_MARK = "(较早的快照已省略";
50
+ // 长流程最常见的失败模式:模型做完一两步就自行收尾(不再调用工具、直接给结论),
51
+ // 后面的步骤根本没执行。这里按 agent 自报的进度/已解析断言数补「继续执行」提示,
52
+ // 直到跑满、确实没有进展或达到次数上限为止。
53
+ const MAX_CONTINUATIONS = 5;
54
+ /** 构造续跑提示:只要求接着做,不重复已完成步骤,并再次强调进度声明格式。 */
55
+ function continuePrompt(progress) {
56
+ const tail = "不要重复已完成的步骤;每完成一步记「第 k 步完成:<结果>」,全部步骤执行完后必须单独输出一行「步骤完成:<已完成数>/<总数>」。";
57
+ if (progress) {
58
+ return (`进度检查:你自报的进度是 ${progress.done}/${progress.total},仍有步骤未执行。` +
59
+ `请从第 ${progress.done + 1} 步开始继续执行剩余步骤,` +
60
+ tail);
61
+ }
62
+ return ("进度检查:你没有输出进度声明「步骤完成:<已完成数>/<总数>」,且用例中的断言/步骤尚未全部执行。" +
63
+ "请继续执行剩余步骤," +
64
+ tail +
65
+ "若确实有步骤无法完成,也要如实输出实际进度。");
66
+ }
67
+ /** 粗略估算消息文本总字符数。 */
68
+ function estimateChars(messages) {
69
+ let n = 0;
70
+ for (const m of messages) {
71
+ const content = m.content;
72
+ if (typeof content === "string") {
73
+ n += content.length;
74
+ }
75
+ else if (Array.isArray(content)) {
76
+ for (const part of content) {
77
+ if (typeof part?.text === "string")
78
+ n += part.text.length;
79
+ }
80
+ }
81
+ }
82
+ return n;
83
+ }
84
+ /** 截断较早的工具结果(保留最近若干条完整),避免快照把上下文撑爆。 */
85
+ function trimOldToolResults(messages, keepRecent, maxChars) {
86
+ const cut = messages.length - keepRecent;
87
+ if (cut <= 0)
88
+ return messages;
89
+ return messages.map((m, i) => {
90
+ if (i >= cut)
91
+ return m;
92
+ const msg = m;
93
+ if (msg.role !== "toolResult" || !Array.isArray(msg.content))
94
+ return m;
95
+ let changed = false;
96
+ const content = msg.content.map((part) => {
97
+ if (part?.type !== "text" ||
98
+ typeof part.text !== "string" ||
99
+ part.text.length <= maxChars ||
100
+ part.text.includes(TRIMMED_MARK)) {
101
+ return part;
102
+ }
103
+ changed = true;
104
+ return {
105
+ ...part,
106
+ text: part.text.slice(0, maxChars) +
107
+ `\n${TRIMMED_MARK}${part.text.length - maxChars} 字符,如需查看请重新 snapshot)`,
108
+ };
109
+ });
110
+ return changed ? { ...m, content } : m;
111
+ });
112
+ }
25
113
  /**
26
114
  * 用 pi-agent-core 编排一次自然语言页面测试:注入 bsk 工具,驱动浏览器执行,整理报告。
115
+ * 若配置中启用了 Jev(PAGEQA_JEV_ENABLED=true 且配置了 API Key),
116
+ * 断言环节会使用 Jev 语义判断替代字符串包含匹配。
27
117
  */
28
118
  export async function runAgent(input, opts = {}) {
119
+ const debug = opts.debug ?? false;
120
+ const log = debug
121
+ ? (m) => process.stderr.write("[debug] " + m + "\n")
122
+ : () => { };
123
+ const t0 = Date.now();
124
+ log("[runAgent] 开始,输入长度=" + input.length);
29
125
  const { models, model } = createLlmBackend();
126
+ log("[runAgent] LLM 后端已创建,model=" + model.id);
127
+ log("[runAgent] 创建/复用 bsk session...");
128
+ await ensureBskReady(debug);
30
129
  const session = ensureSession(opts.session);
31
- const tools = createBskTools({ session });
130
+ log("[runAgent] bsk session=" + session);
131
+ const jevCfg = loadConfig().jev;
132
+ const jevClient = new JevClient(jevCfg, debug);
133
+ log("[runAgent] Jev enabled=" + jevClient.enabled);
134
+ const tools = createBskTools({ session, jevClient, debug });
135
+ log("[runAgent] 工具数=" +
136
+ tools.length +
137
+ " " +
138
+ tools.map((t) => t.name).join(", "));
32
139
  const events = [];
33
140
  const agent = new Agent({
34
141
  initialState: {
@@ -37,20 +144,96 @@ export async function runAgent(input, opts = {}) {
37
144
  tools,
38
145
  },
39
146
  streamFn: models.streamSimple.bind(models),
147
+ // 上下文超限前,先把较早的页面快照裁剪掉,保住最近的上下文与用例步骤。
148
+ transformContext: async (messages) => {
149
+ const before = estimateChars(messages);
150
+ if (before <= CONTEXT_CHAR_LIMIT)
151
+ return messages;
152
+ const trimmed = trimOldToolResults(messages, KEEP_RECENT_MESSAGES, MAX_OLD_TOOL_CHARS);
153
+ log("[runAgent] 上下文裁剪:" +
154
+ before +
155
+ " -> " +
156
+ estimateChars(trimmed) +
157
+ " 字符(消息 " +
158
+ messages.length +
159
+ " 条)");
160
+ return trimmed;
161
+ },
40
162
  });
41
163
  agent.subscribe((e) => {
42
- if (e.type === "tool_execution_start")
164
+ if (e.type === "tool_execution_start") {
43
165
  events.push("[tool] " + e.toolName);
44
- else if (e.type === "tool_execution_end")
45
- events.push("[tool-ok] " + e.toolName);
46
- else if (e.type === "message_update" && e.assistantMessageEvent?.type === "text_delta") {
166
+ log("[agent] 工具调用开始: " + e.toolName);
167
+ }
168
+ else if (e.type === "tool_execution_end") {
169
+ // 工具失败必须显式记录,否则报告里看不出「某步其实报错了」
170
+ events.push((e.isError ? "[tool-error] " : "[tool-ok] ") + e.toolName);
171
+ log("[agent] 工具调用" + (e.isError ? "失败" : "完成") + ": " + e.toolName);
172
+ }
173
+ else if (e.type === "message_update" &&
174
+ e.assistantMessageEvent?.type === "text_delta") {
47
175
  events.push(e.assistantMessageEvent.delta);
48
176
  }
49
177
  });
178
+ log("[runAgent] 发送 prompt...");
50
179
  await agent.prompt(input);
180
+ log("[runAgent] prompt 完成,等待 idle...");
51
181
  await agent.waitForIdle();
182
+ // 续跑:只在「有明确证据表明还没执行完」时才追问,避免正常用例被多余打扰。
183
+ // 证据 = agent 自报进度未满,或用例中断言数还没跑够。
184
+ const expectedAssertions = countAssertions(input);
185
+ let lastSignature = null;
186
+ for (let round = 0; round < MAX_CONTINUATIONS; round++) {
187
+ if (agent.state.errorMessage)
188
+ break;
189
+ const transcriptSoFar = events.join("");
190
+ const progress = parseProgress(transcriptSoFar);
191
+ const parsed = parseAssertions(transcriptSoFar).length;
192
+ const incomplete = progress
193
+ ? progress.done < progress.total
194
+ : expectedAssertions > 0 && parsed < expectedAssertions;
195
+ if (!incomplete)
196
+ break;
197
+ const signature = (progress ? `${progress.done}/${progress.total}` : "-") + "|" + parsed;
198
+ if (round > 0 && signature === lastSignature) {
199
+ log("[runAgent] 续跑后进度未推进(" + signature + "),停止续跑");
200
+ break;
201
+ }
202
+ lastSignature = signature;
203
+ const note = "[continue] 第 " +
204
+ (round + 1) +
205
+ " 次续跑(进度 " +
206
+ (progress ? `${progress.done}/${progress.total}` : "未声明") +
207
+ ",断言 " +
208
+ parsed +
209
+ "/" +
210
+ expectedAssertions +
211
+ ")\n";
212
+ events.push(note);
213
+ log("[runAgent] " + note.trim());
214
+ await agent.prompt(continuePrompt(progress));
215
+ await agent.waitForIdle();
216
+ }
217
+ log("[runAgent] idle 完成,耗时=" + (Date.now() - t0) + "ms");
218
+ // 循环可能因模型报错/上下文超限而提前结束;此时绝不能当成「正常跑完」。
219
+ const agentError = agent.state.errorMessage;
220
+ log("[runAgent] 消息数=" +
221
+ agent.state.messages.length +
222
+ ",错误=" +
223
+ (agentError ?? "无"));
224
+ if (agentError)
225
+ events.push("\n[agent-error] " + agentError + "\n");
52
226
  const transcript = events.join("");
53
227
  const report = buildReport(input, transcript);
228
+ if (agentError) {
229
+ report.status = "fail";
230
+ report.assertions.push({
231
+ expectation: "agent 正常执行完毕(未因错误中断)",
232
+ verdict: "fail",
233
+ evidence: agentError,
234
+ });
235
+ }
236
+ log("[runAgent] 断言数=" + report.assertions.length + ",状态=" + report.status);
54
237
  return {
55
238
  report,
56
239
  text: renderText(report),
@@ -86,7 +269,9 @@ export function splitScenarios(script) {
86
269
  // 一级标题(#)与##之前的开场说明文字:不计入任何场景
87
270
  }
88
271
  flush();
89
- return collected.length ? collected : [{ name: "场景 1", body: script.trim() }];
272
+ return collected.length
273
+ ? collected
274
+ : [{ name: "场景 1", body: script.trim() }];
90
275
  }
91
276
  /** 批量运行多个场景并汇总报告。任一失败则整体失败。 */
92
277
  export async function runSuite(script, opts = {}) {
@@ -96,17 +281,25 @@ export async function runSuite(script, opts = {}) {
96
281
  const r = await runAgent(sc.body, { ...opts, systemPrompt: undefined });
97
282
  results.push(r);
98
283
  }
99
- const overall = results.every((r) => r.report.status === "pass") ? "pass" : "fail";
284
+ const overall = results.every((r) => r.report.status === "pass")
285
+ ? "pass"
286
+ : "fail";
100
287
  const summary = {
101
288
  status: overall,
102
289
  assertions: results.flatMap((r, i) => r.report.assertions.map((a) => ({
103
290
  ...a,
104
291
  expectation: "[" + (scenarios[i]?.name ?? String(i + 1)) + "] " + a.expectation,
105
292
  }))),
106
- summary: "共 " + results.length + " 个场景,通过 " +
107
- results.filter((r) => r.report.status === "pass").length + " 个",
293
+ summary: "共 " +
294
+ results.length +
295
+ " 个场景,通过 " +
296
+ results.filter((r) => r.report.status === "pass").length +
297
+ " 个",
108
298
  transcript: results
109
- .map((r, i) => "## " + (scenarios[i]?.name ?? String(i + 1)) + "\n" + r.transcript.trim())
299
+ .map((r, i) => "## " +
300
+ (scenarios[i]?.name ?? String(i + 1)) +
301
+ "\n" +
302
+ r.transcript.trim())
110
303
  .join("\n\n"),
111
304
  };
112
305
  return {
@@ -143,8 +336,13 @@ function renderSuiteText(summary, results, scenarios) {
143
336
  lines.push("场景数: " + results.length);
144
337
  results.forEach((r, i) => {
145
338
  lines.push("");
146
- lines.push("--- 场景 " + (i + 1) + ":" + (scenarios[i]?.name ?? "") +
147
- " [" + (r.report.status === "pass" ? "PASS" : "FAIL") + "] ---");
339
+ lines.push("--- 场景 " +
340
+ (i + 1) +
341
+ ":" +
342
+ (scenarios[i]?.name ?? "") +
343
+ " [" +
344
+ (r.report.status === "pass" ? "PASS" : "FAIL") +
345
+ "] ---");
148
346
  for (const a of r.report.assertions)
149
347
  lines.push(assertionLine(a));
150
348
  if (r.report.summary)
package/dist/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,14 @@
1
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
2
+ import { JevClient } from "../jev.js";
3
+ /**
4
+ * 自动确保 bsk 就绪:启动 daemon(若未运行)+ 校验浏览器连接(若未连则报错)。
5
+ * 整个进程只真正执行一次(readyPromise 缓存)。
6
+ */
7
+ export declare function ensureBskReady(debug?: boolean): Promise<void>;
2
8
  export interface BskToolOptions {
3
9
  session: string;
10
+ jevClient?: JevClient;
11
+ debug?: boolean;
4
12
  }
5
13
  /** 构造一组浏览器操作工具,供 page-test agent 调用。 */
6
14
  export declare function createBskTools(opts: BskToolOptions): AgentTool[];