@roll-agent/browser-use-agent 0.9.0 → 0.9.1

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.
@@ -105,11 +105,13 @@ export type NativeRecommendJobSelectorState = {
105
105
  readonly options: readonly NativeRecommendJobOption[];
106
106
  };
107
107
  export type NativeRecommendJobSelectRequest = {
108
+ readonly jobRef?: string;
108
109
  readonly jobValue?: string;
109
110
  readonly jobName?: string;
110
111
  readonly index?: number;
111
112
  readonly searchKeyword?: string;
112
113
  readonly useSearch?: boolean;
114
+ readonly forceClick?: boolean;
113
115
  };
114
116
  export type NativeRecommendJobSelectResult = {
115
117
  readonly success: boolean;
@@ -121,6 +123,15 @@ export type NativeRecommendJobSelectResult = {
121
123
  readonly matchedCount: number;
122
124
  readonly error?: string;
123
125
  };
126
+ export type NativeRecommendJobListResult = {
127
+ readonly success: boolean;
128
+ readonly status: "listed" | "recommend_not_ready" | "selector_not_found";
129
+ readonly current?: NativeRecommendJobOption;
130
+ readonly options: readonly NativeRecommendJobOption[];
131
+ readonly availableCount: number;
132
+ readonly canSwitch: boolean;
133
+ readonly error?: string;
134
+ };
124
135
  export type NativeWechatExchangeResult = {
125
136
  readonly success: boolean;
126
137
  readonly exchanged: boolean;
@@ -182,7 +193,9 @@ export declare class ZhipinNativePagePort {
182
193
  private selectRecommendJobMatch;
183
194
  private getCurrentRecommendJobOption;
184
195
  private currentRecommendJobMatchesRequest;
196
+ private hasRecommendJobAlternative;
185
197
  private clickRecommendJobOption;
198
+ listRecommendJobs(options?: NativeClickOptions): Promise<NativeRecommendJobListResult>;
186
199
  selectRecommendJob(request: NativeRecommendJobSelectRequest, options?: NativeClickOptions): Promise<NativeRecommendJobSelectResult>;
187
200
  clickSidebarSection(section: "chat" | "recommend", options?: NativeClickOptions): Promise<boolean>;
188
201
  scrollSurface(surface: ZhipinListSurface, options?: {
@@ -0,0 +1,48 @@
1
+ export declare const ZHIPIN_CANDIDATE_REF_PREFIX: "@c";
2
+ export declare const ZHIPIN_RECOMMEND_JOB_REF_PREFIX: "@j";
3
+ export declare const ZHIPIN_CANDIDATE_REF_PATTERN: RegExp;
4
+ export declare const ZHIPIN_RECOMMEND_JOB_REF_PATTERN: RegExp;
5
+ export interface ZhipinCandidateRefSource {
6
+ readonly index: number;
7
+ readonly candidateId: string;
8
+ readonly name?: string;
9
+ }
10
+ export interface ZhipinCandidateRefTarget extends ZhipinCandidateRefSource {
11
+ readonly candidateRef: string;
12
+ }
13
+ export interface ZhipinRecommendJobRefSource {
14
+ readonly index: number;
15
+ readonly value: string;
16
+ readonly label: string;
17
+ readonly isCurrent: boolean;
18
+ }
19
+ export interface ZhipinRecommendJobRefTarget extends ZhipinRecommendJobRefSource {
20
+ readonly jobRef: string;
21
+ }
22
+ export declare function buildZhipinCandidateRef(index: number): string;
23
+ export declare function buildZhipinRecommendJobRef(index: number): string;
24
+ export declare function parseZhipinCandidateRef(ref: string): number | undefined;
25
+ export declare function parseZhipinRecommendJobRef(ref: string): number | undefined;
26
+ export declare function resolveZhipinCandidateIndex(input: {
27
+ readonly index?: number | undefined;
28
+ readonly candidateRef?: string | undefined;
29
+ }): number;
30
+ export declare function resolveZhipinCandidateIndices(input: {
31
+ readonly indices?: readonly number[] | undefined;
32
+ readonly candidateRefs?: readonly string[] | undefined;
33
+ }): number[];
34
+ export declare function rememberZhipinCandidateRefs(candidates: readonly ZhipinCandidateRefSource[]): ZhipinCandidateRefTarget[];
35
+ export declare function rememberZhipinRecommendJobRefs(jobs: readonly ZhipinRecommendJobRefSource[]): ZhipinRecommendJobRefTarget[];
36
+ export declare function clearZhipinCandidateRefsForTests(): void;
37
+ export declare function clearZhipinRecommendJobRefsForTests(): void;
38
+ export declare function resolveZhipinCandidateRefTarget(candidateRef: string): ZhipinCandidateRefTarget;
39
+ export declare function resolveZhipinRecommendJobRefTarget(jobRef: string): ZhipinRecommendJobRefTarget;
40
+ export declare function resolveZhipinCandidateTargets(input: {
41
+ readonly indices?: readonly number[] | undefined;
42
+ readonly candidateRefs?: readonly string[] | undefined;
43
+ }): ZhipinCandidateRefTarget[];
44
+ export declare function isZhipinCandidateTargetCurrent(target: ZhipinCandidateRefTarget, current: {
45
+ readonly found?: boolean;
46
+ readonly candidateId: string;
47
+ readonly name?: string;
48
+ }): boolean;
@@ -1,13 +1,14 @@
1
- import { findTrackedPlatformPage } from "../pages/platform-page.ts";
2
- import { getContextManager } from "../runtime-holder.ts";
1
+ import { setTimeout as delay } from "node:timers/promises";
2
+ import { getContextManager, getRuntime } from "../runtime-holder.ts";
3
3
  import { detectPlatformFromUrl, matchesPlatformHost } from "../platforms.ts";
4
- import { toAttachedPageInfo } from "../page-info.ts";
4
+ import { toNativePageInfo } from "../page-info.ts";
5
5
  type NavigateActiveTabDeps = {
6
6
  readonly getContextManager: typeof getContextManager;
7
+ readonly getRuntime: typeof getRuntime;
7
8
  readonly detectPlatformFromUrl: typeof detectPlatformFromUrl;
8
9
  readonly matchesPlatformHost: typeof matchesPlatformHost;
9
- readonly findTrackedPlatformPage: typeof findTrackedPlatformPage;
10
- readonly toAttachedPageInfo: typeof toAttachedPageInfo;
10
+ readonly toNativePageInfo: typeof toNativePageInfo;
11
+ readonly delay: typeof delay;
11
12
  };
12
13
  export declare function setNavigateActiveTabDepsForTests(override: Partial<NavigateActiveTabDeps> | undefined): void;
13
14
  export declare const navigateActiveTab: import("@roll-agent/sdk").ToolDefinition<{
@@ -28,6 +28,7 @@ export declare const zhipinGetCandidateList: import("@roll-agent/sdk").ToolDefin
28
28
  expectedSalary: string;
29
29
  tags: string[];
30
30
  buttonText: string;
31
+ candidateRef: string;
31
32
  }[];
32
33
  total: number;
33
34
  error?: string | undefined;
@@ -0,0 +1,31 @@
1
+ import { NativeVisualActivitySession } from "../native-visual-activity-session.ts";
2
+ import { openZhipinNativePagePort } from "../pages/zhipin/native-page.ts";
3
+ import type { ZhipinNativePagePort } from "../pages/zhipin/native-page.ts";
4
+ type NativeVisualActivitySessionLike = Pick<NativeVisualActivitySession, "begin" | "highlightSelector" | "previewMouseMotion" | "succeed" | "fail">;
5
+ type ZhipinListRecommendJobsDeps = {
6
+ readonly openNativePagePort: typeof openZhipinNativePagePort;
7
+ readonly createNativeVisualActivitySession: (page: ZhipinNativePagePort) => NativeVisualActivitySessionLike;
8
+ };
9
+ export declare function setZhipinListRecommendJobsDepsForTests(override: Partial<ZhipinListRecommendJobsDeps> | undefined): void;
10
+ export declare const zhipinListRecommendJobs: import("@roll-agent/sdk").ToolDefinition<{}, {
11
+ status: "recommend_not_ready" | "selector_not_found" | "listed";
12
+ success: boolean;
13
+ availableCount: number;
14
+ canSwitch: boolean;
15
+ jobs: {
16
+ value: string;
17
+ index: number;
18
+ label: string;
19
+ isCurrent: boolean;
20
+ jobRef?: string | undefined;
21
+ }[];
22
+ error?: string | undefined;
23
+ current?: {
24
+ value: string;
25
+ index: number;
26
+ label: string;
27
+ isCurrent: boolean;
28
+ jobRef?: string | undefined;
29
+ } | undefined;
30
+ }>;
31
+ export {};
@@ -1,8 +1,10 @@
1
1
  export declare const zhipinOpenResume: import("@roll-agent/sdk").ToolDefinition<{
2
- index: number;
2
+ index?: number | undefined;
3
+ candidateRef?: string | undefined;
3
4
  }, {
4
5
  success: boolean;
5
6
  candidateId: string;
6
7
  candidateName: string;
7
8
  error?: string | undefined;
9
+ candidateRef?: string | undefined;
8
10
  }>;
@@ -9,7 +9,8 @@ type ZhipinSayHelloDeps = {
9
9
  };
10
10
  export declare function setZhipinSayHelloDepsForTests(override: Partial<ZhipinSayHelloDeps> | undefined): void;
11
11
  export declare const zhipinSayHello: import("@roll-agent/sdk").ToolDefinition<{
12
- indices: number[];
12
+ indices?: number[] | undefined;
13
+ candidateRefs?: string[] | undefined;
13
14
  }, {
14
15
  success: boolean;
15
16
  results: {
@@ -17,6 +18,7 @@ export declare const zhipinSayHello: import("@roll-agent/sdk").ToolDefinition<{
17
18
  success: boolean;
18
19
  candidateId: string;
19
20
  candidateName: string;
21
+ candidateRef: string;
20
22
  error?: string | undefined;
21
23
  }[];
22
24
  summary: {
@@ -9,10 +9,12 @@ type ZhipinSelectRecommendJobDeps = {
9
9
  export declare function setZhipinSelectRecommendJobDepsForTests(override: Partial<ZhipinSelectRecommendJobDeps> | undefined): void;
10
10
  export declare const zhipinSelectRecommendJob: import("@roll-agent/sdk").ToolDefinition<{
11
11
  index?: number | undefined;
12
+ jobRef?: string | undefined;
12
13
  jobValue?: string | undefined;
13
14
  jobName?: string | undefined;
14
15
  searchKeyword?: string | undefined;
15
16
  useSearch?: boolean | undefined;
17
+ forceClick?: boolean | undefined;
16
18
  }, {
17
19
  options: {
18
20
  value: string;
@@ -24,10 +26,12 @@ export declare const zhipinSelectRecommendJob: import("@roll-agent/sdk").ToolDef
24
26
  success: boolean;
25
27
  requested: {
26
28
  index?: number | undefined;
29
+ jobRef?: string | undefined;
27
30
  jobValue?: string | undefined;
28
31
  jobName?: string | undefined;
29
32
  searchKeyword?: string | undefined;
30
33
  useSearch?: boolean | undefined;
34
+ forceClick?: boolean | undefined;
31
35
  };
32
36
  matchedCount: number;
33
37
  error?: string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roll-agent/browser-use-agent",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "zod": "^3.25.76",
48
- "@roll-agent/browser": "0.3.0",
48
+ "@roll-agent/browser": "0.3.1",
49
49
  "@roll-agent/sdk": "0.1.6"
50
50
  },
51
51
  "devDependencies": {
@@ -4,6 +4,17 @@
4
4
 
5
5
  `conversationId` / `candidateId` 是跨 tool 的稳定主键,`index` 只表示当前 DOM 快照。
6
6
 
7
+ ## BOSS 页面入口
8
+
9
+ `navigate_active_tab(url)` 是通用 native CDP 导航工具,但不能直接跳转 BOSS `/web/chat/*` 后台路径。
10
+
11
+ 页面切换规则:
12
+
13
+ 1. 进入聊天页:调用 `zhipin_open_chat_page()`,由工具点击站内「沟通」导航。
14
+ 2. 进入推荐牛人页:调用 `zhipin_open_recommend_page()`,由工具点击站内「推荐牛人」导航。
15
+ 3. 如果页面没有可用 BOSS 后台 target,不要用 `navigate_active_tab("https://www.zhipin.com/web/chat/recommend")` 补救;让用户先恢复登录后的 BOSS 页面或调用 `open_platform("zhipin")` 进入平台主页。
16
+ 4. `navigate_active_tab` 不触发 Playwright attach,也不调用 `Runtime.enable`,但它不替代 BOSS 业务语义导航工具。
17
+
7
18
  错误做法:
8
19
 
9
20
  - 把 `zhipin_read_messages` 返回数组里的 `index` 当作后续点击主键。
@@ -25,19 +36,50 @@
25
36
 
26
37
  优先级:
27
38
 
28
- 1. 已知岗位 `value` 时,调用 `zhipin_select_recommend_job({ jobValue })`。
29
- 2. 只知道标题时,调用 `zhipin_select_recommend_job({ jobName })`;工具会先匹配当前下拉项,未命中再使用下拉搜索框。
30
- 3. `index` 只表示当前下拉快照顺序,筛选、搜索或岗位列表刷新后必须重新读取/选择,不要跨步骤长期保存。
39
+ 1. 先调用 `zhipin_list_recommend_jobs()` 读取当前岗位下拉,只读不切换。
40
+ 2. 如果 `canSwitch:false`,当前账号/页面没有可切换岗位,跳过岗位切换。
41
+ 3. 已知 `jobRef` 时,调用 `zhipin_select_recommend_job({ jobRef })`。
42
+ 4. 已知岗位 `value` 时,调用 `zhipin_select_recommend_job({ jobValue })`。
43
+ 5. 只知道标题时,调用 `zhipin_select_recommend_job({ jobName })`;工具会先匹配当前下拉项,未命中再使用下拉搜索框。
44
+ 6. `index` 只表示当前下拉快照顺序,筛选、搜索或岗位列表刷新后必须重新读取/选择,不要跨步骤长期保存。
45
+
46
+ `jobRef` 规则:
47
+
48
+ - `jobRef` 格式如 `@j1`,只来自 `zhipin_list_recommend_jobs()` 输出。
49
+ - `jobRef` 只对最近一次岗位下拉快照有效;筛选、搜索、刷新或页面重开后必须重新读取。
50
+ - orchestrator 不要自行构造 `jobRef`。
51
+ - `jobRef` 不是安全边界,只是降低编排认知负担;真实 DOM 点击仍由工具解析到 `value` / `index` 后执行。
52
+ - 默认不要传 `forceClick:true`;只有需要重新点击已选中的岗位项时才使用。
31
53
 
32
54
  推荐链路:
33
55
 
34
56
  ```text
35
57
  zhipin_open_recommend_page()
36
- -> zhipin_select_recommend_job({ jobValue | jobName })
37
- -> zhipin_filter_recommend_candidates(...)
58
+ -> zhipin_list_recommend_jobs()
59
+ -> zhipin_select_recommend_job({ jobRef | jobValue | jobName }) # 可选;canSwitch=false 时跳过
60
+ -> zhipin_filter_recommend_candidates(...) # 可选;requires_vip 时跳过
38
61
  -> zhipin_get_candidate_list(...)
39
62
  ```
40
63
 
64
+ ## 推荐候选人筛选
65
+
66
+ `zhipin_filter_recommend_candidates(ageMin?, ageMax?, gender?, activity?)` 只处理年龄、性别、活跃度三个维度。
67
+
68
+ 返回状态处理:
69
+
70
+ | `status` | 含义 | 编排动作 |
71
+ | --- | --- | --- |
72
+ | `applied` | 筛选已提交 | 继续 `zhipin_get_candidate_list` |
73
+ | `recommend_not_ready` | 推荐页未就绪 | 先调用 `zhipin_open_recommend_page()` |
74
+ | `requires_vip` | 当前账号没有权限使用该筛选,页面触发 VIP 弹窗 | 不要反复尝试绕过;跳过筛选或调整业务策略 |
75
+ | `error` | 操作失败 | 读取 `error` 后决定是否重试 |
76
+
77
+ 实操规则:
78
+
79
+ 1. `requires_vip` 是硬边界,不是暂态加载失败。
80
+ 2. 如果筛选不可用,直接读取当前推荐列表,再由 orchestrator 按 `age`、`buttonText`、岗位信号等字段做结果过滤。
81
+ 3. 列表字段过滤不能替代平台筛选的完整语义;它只用于降低明显不合适目标的后续操作风险。
82
+
41
83
  ## 动态列表
42
84
 
43
85
  BOSS 页面通常不是整页滚动,而是内部容器滚动:
@@ -115,8 +157,25 @@ recommend-list -> 推荐牛人列表,默认向下滚动,去重主键 candid
115
157
  ## 推荐候选人链路
116
158
 
117
159
  1. `zhipin_open_recommend_page()`。
118
- 2. `zhipin_filter_recommend_candidates(ageMin?, ageMax?, gender?, activity?)`。
160
+ 2. `zhipin_filter_recommend_candidates(ageMin?, ageMax?, gender?, activity?)`(可选;`requires_vip` 时跳过)。
119
161
  3. `zhipin_get_candidate_list(maxResults?, autoScroll=true, maxScrolls=4)`。
120
- 4. `zhipin_say_hello(indices)`。
162
+ 4. orchestrator 过滤 `buttonText` / 年龄 / 业务资格。
163
+ 5. `zhipin_say_hello(candidateRefs)`。
164
+
165
+ `zhipin_get_candidate_list` 会给每个候选人返回 `candidateRef`,例如 `@c1`。
166
+
167
+ 优先级:
168
+
169
+ 1. 上层 orchestrator 优先把 `candidateRef` 传给 `zhipin_say_hello({ candidateRefs })` 或 `zhipin_open_resume({ candidateRef })`。
170
+ 2. `indices` / `index` 只作为当前 DOM 快照兜底。
171
+ 3. 筛选、滚动加载、搜索、刷新或页面重开后必须重新调用 `zhipin_get_candidate_list`,不要复用旧 `candidateRef`。
172
+ 4. 不要由 orchestrator 自己构造 `@c1`;只使用 tool 输出中的 `candidateRef`。
173
+ 5. 聊天消息列表没有 `candidateRef`;聊天回复链路继续使用 `conversationId` / `candidateId`。
174
+ 6. 调 `zhipin_say_hello` 前先过滤 `buttonText:"打招呼"`;`buttonText` 为空通常表示已打过招呼,不应重复点击。
175
+ 7. 如果业务有年龄、资格或岗位匹配约束,先按 `age` / `expectedPosition` / `tags` 等字段过滤,不要把所有 `candidateRefs` 盲目提交。
176
+
177
+ 失效保护:
121
178
 
122
- `zhipin_say_hello(indices)` `indices` 也是当前 DOM 快照索引;筛选、滚动或列表刷新后必须重新读取列表。
179
+ - 如果 `candidateRef` 对应的 `candidateId` / `name` 与当前 DOM 不一致,工具会返回 `success:false` 并提示“候选人引用已过期”。
180
+ - 收到过期提示后,重新执行推荐候选人链路的第 3 步,再提交新的 `candidateRefs`。
181
+ - 同一快照内可以一次提交多个 `candidateRefs` 连续打招呼;如果 BOSS 在点击后重排列表,工具会拒绝过期 ref,orchestrator 应刷新列表后只重试剩余目标。