@roll-agent/browser-use-agent 0.7.1 → 0.7.3

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/SKILL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: browser-use-agent
3
- description: 浏览器操控 Agent。控制浏览器操作招聘平台——读取消息、打开聊天、发送回复、换微信、查看推荐列表、打招呼、查看简历。
3
+ description: 浏览器操控 Agent。控制浏览器操作招聘平台——读取消息、打开聊天、发送回复、换微信、滚动动态列表、查看推荐列表、打招呼、查看简历。
4
4
  metadata:
5
5
  roll-env-file: references/env.yaml
6
6
  ---
@@ -11,37 +11,108 @@ metadata:
11
11
 
12
12
  需要先启动 Agent 服务进程(HTTP 常驻),浏览器 session 跨调用持久。
13
13
 
14
+ 默认情况下,agent 会在可见浏览器页面内同时启用两类页内反馈:
15
+
16
+ - `BROWSER_VISUAL_CURSOR`:点击/输入前显示虚拟指针和点击波纹
17
+ - `BROWSER_VISUAL_ACTIVITY`:读取消息列表、识别账号、提取聊天详情等非点击型操作期间,显示状态胶囊、区域柔光和完成态反馈
18
+
19
+ 若不需要,可分别设为 `false` 关闭。
20
+
14
21
  完整 inputSchema 可通过 `roll agent tools browser-use-agent`(或 `--json`)查询。
15
22
 
16
23
  ## 通用 Tools
17
24
 
18
- - `browser_status()` — 查询浏览器运行状态和活跃 session;输出含 `replyAuthorityKeysLoaded`(启动期 Reply Authority 公钥是否预加载成功)和 `effectiveEnvSources`(声明过的 env key 的 `{present, fingerprint}`,SHA256 前 8 位,不泄漏 value)。后者被 `roll doctor` / `roll agent info` 消费,用于检测 env 声明与运行态的 drift
25
+ - `browser_status()` — 查询浏览器运行状态和活跃 session;输出含 `replyAuthorityKeysLoaded`(启动期 Reply Authority 公钥是否预加载成功)、`visualCursorEnabled`(页内虚拟指针是否启用)、`visualActivityEnabled`(页内读操作反馈是否启用)和 `effectiveEnvSources`(声明过的 env key 的 `{present, fingerprint}`,SHA256 前 8 位,不泄漏 value)。后者被 `roll doctor` / `roll agent info` 消费,用于检测 env 声明与运行态的 drift
19
26
  - `open_platform(platform)` — 通过原生 CDP 打开并聚焦招聘平台主页;登录前不会触发 Playwright attach
20
27
  - `list_pages(platform?)` — 通过原生 CDP 列出当前浏览器中可见的页面和 pageId(登录前 `pageId` 即原生 targetId)
21
28
  - `select_page(platform, pageId)` — 将指定页面绑定为平台当前活跃页;登录前优先走原生 CDP target 激活
22
- - `navigate_active_tab(url)` — 将当前激活 tab 导航到指定 URL
29
+ - `navigate_active_tab(url)` — 导航到指定 URL;若 URL 属于 `zhipin/yupao`,优先复用已打开的平台页,避免把无关 tab 导航成第二个平台页
23
30
 
24
31
  ## 调试 Tools
25
32
 
26
33
  - `attach_browser_session()` — 调试工具。显式执行一次 `connectOverCDP()`,用于隔离验证“仅 attach”是否会触发站点风控
34
+ - `zhipin_scroll_view(surface, direction?, steps?, distance?, settleMs?)` — 滚动 BOSS直聘页面内部动态列表容器,用于调试或显式翻页。`surface` 支持 `chat-list`、`chat-history`、`recommend-list`;不传 `direction` 时使用该 surface 的默认方向
27
35
 
28
36
  ## BOSS直聘 — 聊天 Tools
29
37
 
30
- - `zhipin_read_messages(limit?, onlyUnread?, sortBy?)` — 读取消息列表中的候选人,返回姓名、消息摘要,以及 `conversationId` / `candidateId`
31
- - `zhipin_open_chat(candidateName?, index?, preferUnread?)` — 打开指定候选人的聊天窗口(按姓名模糊匹配或列表索引)
32
- - `zhipin_get_candidate_info(candidateName?, index?, maxMessages?)` — 提取候选人资料、聊天记录,以及当前选中聊天的 `conversationId` / `candidateId`。输出里的 `candidateInfo.communicationPosition`、`candidateInfo.expectedLocation`、`candidateInfo.expectedPosition` 已按“沟通职位 + 最近关注”结构化解析;若 `communicationPosition` 含连字符类分隔符(`-` / `-` / `—` / `–`),则取第一段作为可选 `preferredBrand`,否则不输出该字段
38
+ - `zhipin_read_messages(limit?, onlyUnread?, sortBy?, autoScroll?, maxScrolls?)` — 读取消息列表中的候选人,默认返回全部消息;若只看未读,显式传 `onlyUnread=true`。默认 `autoScroll=true`,会向下滚动左侧消息列表内部容器并按 `conversationId` 合并去重;`maxScrolls` 默认 `4`,用于限制动态列表采集成本
39
+ - `zhipin_open_chat_page()` — 通过点击 Boss 左侧导航切换回「沟通」页;优先复用当前已登录的 Boss 页面,不让编排器去猜站内 URL
40
+ - `zhipin_open_chat(conversationId?, candidateName?, index?, preferUnread?)` — 打开指定候选人的聊天窗口;匹配优先级是 `conversationId` > `candidateName` > `index`
41
+ - `zhipin_get_candidate_info(conversationId?, candidateName?, index?, maxMessages?)` — 提取候选人资料、聊天记录,以及当前选中聊天的 `conversationId` / `candidateId`。输出里的 `candidateInfo.communicationPosition`、`candidateInfo.expectedLocation`、`candidateInfo.expectedPosition` 已按“沟通职位 + 最近关注”结构化解析;若 `communicationPosition` 含连字符类分隔符(`-` / `-` / `—` / `–`),则取第一段作为可选 `preferredBrand`,否则不输出该字段
33
42
  - `zhipin_send_reply(signedEnvelope, candidateName?, index?)` — 发送消息。只接受 Reply Authority Service 签发的 `signedEnvelope`;本地会先做 Ed25519 验签、过期检查、重放检查、目标绑定校验和 recruiter 绑定校验。启动期公钥预加载失败时直接前置拒绝,错误指向 `browser_status.replyAuthorityKeysLoaded`
34
- - `zhipin_exchange_wechat(candidateName?, index?)` — 换微信。指定 candidateName 会自动打开对应聊天后执行
43
+ - `zhipin_exchange_wechat(conversationId?, candidateName?, index?)` — 换微信。若已知 `conversationId`,优先传它;`candidateName/index` 只作兜底
35
44
  - `zhipin_get_username()` — 获取当前登录的招聘者用户名,返回 `username`(依赖当前 runtime 已跟踪页面;首次使用请先 `open_platform`,已打开但未跟踪页面可先 `list_pages + select_page`,确认登录后如需单独验证 attach,可先调用 `attach_browser_session`)。常用于 recruiter binding 解析和外部通知消息中的账号标识
36
45
 
46
+ ## BOSS直聘 — 聊天编排硬规则
47
+
48
+ 聊天工具链必须把 `conversationId` / `candidateId` 当作稳定主键,而不是把左侧列表的瞬时 `index` 当主键。
49
+
50
+ 原因:
51
+
52
+ - BOSS 左侧消息列表是虚拟列表,DOM 只保留当前窗口内的若干条记录
53
+ - 点击会话、发送消息、收到新消息后,列表会实时重排
54
+ - 同一个人上一轮是 `index=3`,下一轮可能已经变成 `index=0`
55
+ - 因此 `index` 只适合“当前这一轮、当前这个 DOM 快照内”的临时兜底,不适合跨 tool / 跨 agent 透传
56
+
57
+ 编排要求:
58
+
59
+ 1. 先调用 `zhipin_read_messages`
60
+ 2. 一旦返回了 `conversationId` / `candidateId`,后续所有 related tool 都复用这两个值
61
+ 3. 调 `zhipin_open_chat` / `zhipin_get_candidate_info` / `zhipin_exchange_wechat` 时,优先传 `conversationId`
62
+ 4. 调 `smart-reply-agent.generate_reply(..., target)` 时,`target.conversationId` / `target.candidateId` 必须直接来自 `browser-use-agent` 的真实输出
63
+ 5. 禁止把 `zhipin_read_messages` 返回数组里的 `index` 缓存到下一轮,再把它当作会话主键使用
64
+ 6. 只有在当前轮次拿不到 `conversationId` 时,才允许临时退回 `candidateName` 或 `index`
65
+
66
+ 动态列表要求:
67
+
68
+ - `zhipin_read_messages` 默认会自动滚动左侧消息列表;只有明确需要“只读当前可见 DOM”时才传 `autoScroll=false`
69
+ - 若要手动补采或诊断滚动状态,调用 `zhipin_scroll_view(surface="chat-list")`
70
+ - `onlyUnread=true` 时不要依赖 `limit` 提前停止采集;未读会话可能在当前首屏之后
71
+ - `zhipin_scroll_view(surface="chat-history", direction="up")` 可用于显式加载当前聊天更早的历史消息,但业务回复链路仍应优先用 `zhipin_get_candidate_info(conversationId)` 读取结构化详情
72
+
73
+ 错误做法:
74
+
75
+ - `zhipin_read_messages` 拿到 `index=2`,几轮之后再调用 `zhipin_open_chat(index=2)`
76
+ - 用 `candidateName` 重新模糊匹配一个会话,再把历史 `candidateId` 假定为同一个人
77
+ - `smart-reply-agent` 的 `target` 不用 `browser-use-agent` 返回的 `conversationId/candidateId`,而是由 orch 自己重建
78
+ - 手动滚动后继续用旧的 `index` 打开候选人;滚动和动态渲染后 `index` 仍只表示当前 DOM 快照
79
+
80
+ 推荐做法:
81
+
82
+ 1. `zhipin_read_messages` → 记录 `conversationId + candidateId + candidateName`
83
+ 2. `zhipin_open_chat(conversationId)`
84
+ 3. `zhipin_get_candidate_info(conversationId)`
85
+ 4. `smart-reply-agent.generate_reply(..., target={ platform, conversationId, candidateId, recruiterUsername|recruiterBinding })`
86
+ 5. `zhipin_send_reply(signedEnvelope)`
87
+
37
88
  ## BOSS直聘 — 推荐列表 Tools
38
89
 
39
- - `zhipin_get_candidate_list(maxResults?)` — 获取推荐列表页的候选人卡片信息(姓名、年龄、学历、期望薪资等)
90
+ - `zhipin_open_recommend_page()` — 通过点击 Boss 左侧导航切换到「推荐牛人」页;优先复用当前已登录的 Boss 页面,不让编排器去猜站内 URL
91
+ - `zhipin_filter_recommend_candidates(ageMin?, ageMax?, gender?, activity?)` — 在「推荐牛人」页打开筛选面板,只设置年龄、性别、活跃度[单选] 三个维度并提交。未传的维度会重置为 `不限`(年龄默认为 `16-不限`),不会点击岗位下拉,也不会清除学历、薪资、求职状态等其它筛选项
92
+ - `zhipin_get_candidate_list(maxResults?, autoScroll?, maxScrolls?)` — 获取推荐列表页的候选人卡片信息(姓名、年龄、学历、期望薪资等)。默认 `autoScroll=true`,会向下滚动推荐列表内部容器并按 `candidateId` / `data-geek` 合并去重;`maxScrolls` 默认 `4`。返回的 `scrollStats.stopReason` 可用于判断未达到 `maxResults` 的原因:`target-count`、`boundary`、`no-new-items`、`max-steps`
40
93
  - `zhipin_say_hello(indices)` — 对推荐列表中的候选人批量点击「打招呼」
41
94
  - `zhipin_open_resume(index)` — 点击候选人卡片打开简历详情弹窗
42
95
  - `zhipin_locate_resume_canvas()` — 定位简历弹窗中嵌套 iframe 内的 canvas 坐标(用于截图)
43
96
  - `zhipin_close_resume()` — 关闭简历详情弹窗
44
97
 
98
+ ## BOSS直聘 — 动态列表滚动规则
99
+
100
+ BOSS 页面通常不是整页滚动,而是内部容器滚动:
101
+
102
+ ```text
103
+ chat-list -> 左侧消息列表,默认向下滚动,去重主键 conversationId
104
+ chat-history -> 右侧聊天记录,默认向上滚动,用于加载更早历史
105
+ recommend-list -> 推荐牛人列表,默认向下滚动,去重主键 candidateId/data-geek
106
+ ```
107
+
108
+ 使用原则:
109
+
110
+ 1. 业务读取优先用自带 `autoScroll` 的工具:`zhipin_read_messages`、`zhipin_get_candidate_list`
111
+ 2. `zhipin_scroll_view` 只作为显式翻页、调试和补救工具,不作为业务读取的必经步骤
112
+ 3. 动态列表滚动后,`index` 会随当前 DOM 窗口变化;跨 tool 传递必须用 `conversationId` / `candidateId`
113
+ 4. `maxScrolls` 用于成本控制;需要更完整列表时再显式调大,不要无界滚动
114
+ 5. 推荐列表若 `total < maxResults`,先看 `scrollStats.stopReason`:`boundary` 表示触底后等待追加数据仍无新增,`no-new-items` 表示连续滚动没有新去重项,`max-steps` 表示到达滚动步数上限
115
+
45
116
  ## 鱼泡 Tools
46
117
 
47
118
  - `yupao_read_messages(limit?)` — 读取鱼泡未读消息列表
@@ -49,17 +120,25 @@ metadata:
49
120
 
50
121
  ## 典型工作流
51
122
 
52
- 1. `zhipin_read_messages` → 获取未读候选人列表
53
- 2. `zhipin_open_chat(candidateName)` → 打开某人的聊天
54
- 3. `zhipin_get_candidate_info` → 查看候选人资料、聊天记录,并拿到 `conversationId` / `candidateId`
55
- 4. `smart-reply-agent.generate_reply` 前,先尝试透传以下信号:
123
+ 1. `zhipin_read_messages` → 获取消息列表,并记录 `conversationId` / `candidateId`
124
+ 2. `zhipin_open_chat_page()` → 通过左侧导航切回 `沟通`(需要时)
125
+ 3. `zhipin_open_chat(conversationId)` → 按稳定会话 ID 打开聊天
126
+ 4. `zhipin_get_candidate_info(conversationId)` → 查看候选人资料、聊天记录
127
+ 5. 调 `smart-reply-agent.generate_reply` 前,先尝试透传以下信号:
56
128
  - 能读到就传:`candidateInfo.communicationPosition`、`candidateInfo.expectedLocation`、`candidateInfo.expectedPosition`
57
129
  - 读不到就如实不传
58
130
  - `preferredBrand`:仅当 `communicationPosition` 含连字符类分隔符(`-` / `-` / `—` / `–`)时,取第一段透传;没有分隔符就不传
59
131
  - 严禁把通用岗位名(如“餐饮兼职服务员”“门店服务员”)或 `zhipin_get_candidate_list.company`(候选人现/前雇主)伪装成 `preferredBrand`
60
- 5. `smart-reply-agent.generate_reply(..., target)` → 获取 `suggestedReply + signedEnvelope`
61
- 6. `zhipin_send_reply(signedEnvelope)` → 验签、校验 recruiterBinding 后发送回复
62
- 7. `zhipin_exchange_wechat` → 交换微信(可选)
132
+ 6. `smart-reply-agent.generate_reply(..., target)` → 获取 `suggestedReply + signedEnvelope`
133
+ 7. `zhipin_send_reply(signedEnvelope)` → 验签、校验 recruiterBinding 后发送回复
134
+ 8. `zhipin_exchange_wechat` → 交换微信(可选)
135
+
136
+ 推荐列表链路建议:
137
+
138
+ 1. `zhipin_open_recommend_page()` → 通过左侧导航切到 `推荐牛人`
139
+ 2. `zhipin_filter_recommend_candidates(ageMin?, ageMax?, gender?, activity?)` → 需要限定目标人群时先设置年龄、性别、活跃度;例如“男性,20-40 岁,刚刚活跃”对应 `gender="男", ageMin=20, ageMax=40, activity="刚刚活跃"`
140
+ 3. `zhipin_get_candidate_list(maxResults?, autoScroll=true, maxScrolls=4)` → 读取候选人卡片;默认会滚动动态列表并去重合并
141
+ 4. `zhipin_say_hello(indices)` → 批量打招呼
63
142
 
64
143
  ## 支持平台
65
144
 
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- export declare const BROWSER_USE_DECLARED_ENV_KEYS: readonly ["REPLY_AUTHORITY_KEYS_URL"];
2
+ export declare const BROWSER_USE_DECLARED_ENV_KEYS: readonly ["REPLY_AUTHORITY_KEYS_URL", "BROWSER_VISUAL_CURSOR", "BROWSER_VISUAL_ACTIVITY"];
3
3
  export declare const EffectiveEnvSourceSchema: z.ZodObject<{
4
4
  present: z.ZodBoolean;
5
5
  fingerprint: z.ZodOptional<z.ZodString>;