@reconcrap/boss-recommend-mcp 2.1.2 → 2.1.4
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 +30 -37
- package/package.json +7 -6
- package/skills/boss-recommend-pipeline/SKILL.md +53 -31
- package/src/cli.js +99 -0
- package/src/index.js +72 -3
- package/src/parser.js +38 -61
- package/src/recommend-mcp.js +158 -67
- package/src/recommend-scheduler.js +482 -0
package/README.md
CHANGED
|
@@ -83,6 +83,8 @@ MCP 工具:
|
|
|
83
83
|
|
|
84
84
|
- `list_recommend_jobs`(只读读取推荐页岗位下拉框,返回可直接用于 cron/一次性任务的 `job_names`)
|
|
85
85
|
- `prepare_recommend_pipeline_run`(只校验完整 payload 是否已可用于 cron/一次性任务;不启动筛选,返回 `READY + cron_ready=true` 后才应创建 cron)
|
|
86
|
+
- `schedule_recommend_pipeline_run`(创建 package-owned 定时任务;保存已 READY 的完整 payload,启动 detached scheduler,到点后直接调用 `start_recommend_pipeline_run`)
|
|
87
|
+
- `get_recommend_scheduled_run`(查询 package-owned 定时任务;到点后会显示内层 `run_id` 和 run 快照)
|
|
86
88
|
- `start_recommend_pipeline_run`(异步启动;同样先经过前置门禁,通过后返回 run_id)
|
|
87
89
|
- `get_recommend_pipeline_run`(轮询 run_id 状态)
|
|
88
90
|
- `cancel_recommend_pipeline_run`(取消运行中任务)
|
|
@@ -114,21 +116,24 @@ MCP 工具:
|
|
|
114
116
|
boss-recommend-mcp list-jobs --slow-live --port 9222
|
|
115
117
|
```
|
|
116
118
|
|
|
117
|
-
返回的 `job_names` 可直接作为后续 `start_recommend_pipeline_run` 的 `confirmation.job_value`
|
|
119
|
+
返回的 `job_names` 可直接作为后续 `start_recommend_pipeline_run` 的 `overrides.job`;旧版 `confirmation.job_value` 仍兼容。
|
|
118
120
|
|
|
119
|
-
Cron / 一次性定时任务设置建议先在设置阶段完成 Chrome
|
|
121
|
+
Cron / 一次性定时任务设置建议先在设置阶段完成 Chrome/登录/岗位发现与一次总确认;确认文件推荐只包含 `{ "final_confirmed": true }`:
|
|
120
122
|
|
|
121
123
|
```bash
|
|
122
124
|
boss-recommend-mcp prepare-run --instruction-file boss-recommend-instruction.txt --overrides-file boss-recommend-overrides.json --confirmation-file boss-recommend-confirmation.json --slow-live --port 9222
|
|
125
|
+
boss-recommend-mcp schedule-run --schedule-delay-minutes 10 --instruction-file boss-recommend-instruction.txt --overrides-file boss-recommend-overrides.json --confirmation-file boss-recommend-confirmation.json --slow-live --port 9222
|
|
126
|
+
boss-recommend-mcp schedule-status --schedule-id <schedule_id>
|
|
123
127
|
```
|
|
124
128
|
|
|
125
|
-
|
|
129
|
+
只有 `prepare-run` 输出 `status: "READY"` 且 `cron_ready: true` 后,才继续调用 `schedule-run`。只有 `schedule-run` 输出 `status: "SCHEDULED"` 且带有 `schedule_id` 后,才算定时任务真的创建成功。不要让外部 AI harness 自己拼 `/tmp/*.log` shell cron 或未来对话提醒;那类 cron 容易丢失 JSON/file 参数并在到点后重新卡确认门禁。
|
|
126
130
|
|
|
127
131
|
状态机:
|
|
128
132
|
|
|
129
133
|
- `NEED_INPUT`
|
|
130
134
|
- `NEED_CONFIRMATION`
|
|
131
135
|
- `READY`(仅准备工具)
|
|
136
|
+
- `SCHEDULED`(仅定时工具)
|
|
132
137
|
- `COMPLETED`
|
|
133
138
|
- `FAILED`
|
|
134
139
|
|
|
@@ -153,18 +158,16 @@ boss-recommend-mcp prepare-run --instruction-file boss-recommend-instruction.txt
|
|
|
153
158
|
- 学校标签支持多选语义:如“985、211”会同时勾选这两项
|
|
154
159
|
- 学校标签对“混合输入”按容错处理:如“985、211、qs100”会忽略无效项 `qs100`,保留并应用有效项;仅当全部无效或用户明确“不限”时才回落到“不限”
|
|
155
160
|
- 学历支持单选与多选语义:如“本科及以上”会展开为 `本科/硕士/博士`;如“大专、本科”只勾选这两项
|
|
156
|
-
-
|
|
157
|
-
- 页面就绪(已登录且在 recommend
|
|
158
|
-
- 在真正开始 search/screen
|
|
161
|
+
- 执行前会先补齐筛选值、岗位、后置动作和休息强度,然后只做一次总确认
|
|
162
|
+
- 页面就绪(已登录且在 recommend 页)后,会先提取岗位栏全部岗位,使用精确岗位名填入 run payload,再进入总确认
|
|
163
|
+
- 在真正开始 search/screen 或创建 cron 前,总确认需包含岗位、全部筛选参数、criteria、target_count、post_action、max_greet_count、restLevel 和定时信息(如适用)
|
|
159
164
|
- npm 全局安装后会自动执行 install:生成 skill、导出 MCP 模板,并自动尝试写入已检测到的外部 agent MCP 配置(含 Trae / trae-cn / Cursor / Claude / OpenClaw)
|
|
160
165
|
- 2.x installer 会迁移已存在的 legacy Boss MCP 配置:把 `boss-recommend` 指向统一 `@reconcrap/boss-recommend-mcp`,并从同一个 `mcp.json` 中移除旧 `boss-recruit-mcp` / standalone `boss-chat` / 本地 legacy Boss 路径;写入前会生成 `.boss-mcp-migration-*.bak` 备份
|
|
161
166
|
- 2.x installer 会刷新外部 agent skills:`boss-recommend-pipeline`、`boss-recruit-pipeline`、`boss-chat` 都来自当前包,旧 recruit/chat skill 会被覆盖为统一 MCP 路由
|
|
162
167
|
- npm / npx 安装后会自动初始化 `screening-config.json` 模板(优先写入 workspace 的 `config/`,不可写时回退到用户目录)
|
|
163
168
|
- npm 安装流程会预创建运行目录(跨平台):`~/.boss-recommend-mcp`、`~/.boss-recommend-mcp/runs`、`~/.boss-recommend-mcp/boss-chat` 及其 `logs/runs/profiles/reports/artifacts/state`
|
|
164
|
-
- `post_action`
|
|
165
|
-
- `
|
|
166
|
-
- 当 `post_action=greet` 时,必须在运行开始时确认 `max_greet_count`
|
|
167
|
-
- 若检测到 `max_greet_count` 可能由 agent 自动默认(例如与 `target_count` 相同且原始指令未明确),会强制再次向用户确认
|
|
169
|
+
- `post_action`、`target_count` 和 `max_greet_count`(当 `post_action=greet`)通过同一次总确认锁定
|
|
170
|
+
- 新流程中 `confirmation.final_confirmed=true` 是总确认;旧版逐字段 `*_confirmed` JSON 仍兼容但不是推荐写法
|
|
168
171
|
- 一旦确认 `post_action`,本次运行内所有通过人选都统一按该动作执行
|
|
169
172
|
- 若达到 `max_greet_count` 但流程仍需继续,后续通过人选会自动改为收藏
|
|
170
173
|
- 不会对每位候选人重复确认
|
|
@@ -269,6 +272,16 @@ npx -y @reconcrap/boss-recommend-mcp@latest run --detached --instruction-file bo
|
|
|
269
272
|
|
|
270
273
|
`--detached` 会让父进程输出 `ACCEPTED + run_id` 后退出,子进程继续持有 Chrome DevTools 会话并执行长任务。岗位发现可以使用只读 CLI:
|
|
271
274
|
|
|
275
|
+
如果是稍后启动/cron/定时任务,不要手写系统 cron;用 package-owned scheduler:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
npx -y @reconcrap/boss-recommend-mcp@latest prepare-run --instruction-file boss-recommend-instruction.txt --overrides-file boss-recommend-overrides.json --confirmation-file boss-recommend-confirmation.json --slow-live --port 9222
|
|
279
|
+
npx -y @reconcrap/boss-recommend-mcp@latest schedule-run --schedule-delay-minutes 10 --instruction-file boss-recommend-instruction.txt --overrides-file boss-recommend-overrides.json --confirmation-file boss-recommend-confirmation.json --slow-live --port 9222
|
|
280
|
+
npx -y @reconcrap/boss-recommend-mcp@latest schedule-status --schedule-id <schedule_id>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
`schedule-run` 会保存同一份已验证 payload 并启动 detached scheduler worker;到点后 worker 会直接调用包内 `start_recommend_pipeline_run`,不会重新让 AI harness 拼参数。
|
|
284
|
+
|
|
272
285
|
```bash
|
|
273
286
|
npx -y @reconcrap/boss-recommend-mcp@latest list-jobs --slow-live --port 9222
|
|
274
287
|
# 源码模式(GitHub clone 后)
|
|
@@ -463,6 +476,7 @@ Trae-CN / 长对话防循环建议:
|
|
|
463
476
|
|
|
464
477
|
- `start_recommend_pipeline_run` 为异步入口,但不会跳过同步确认流程。
|
|
465
478
|
- `prepare_recommend_pipeline_run` / `boss-recommend-mcp prepare-run` 用于 cron 设置阶段;它不启动筛选,只确认 payload 已经不需要到点后再问用户。
|
|
479
|
+
- `schedule_recommend_pipeline_run` / `boss-recommend-mcp schedule-run` 是推荐页定时启动的唯一推荐路径;它创建真实 package-owned detached scheduler,并返回 `schedule_id`。
|
|
466
480
|
- 定时心跳默认 120 秒一次;`updated_at` 仍会在阶段或进度变化时刷新。
|
|
467
481
|
- 每个 run 会持久化到 `~/.boss-recommend-mcp/runs/<run_id>.json`(可通过 `BOSS_RECOMMEND_HOME` 覆盖)。
|
|
468
482
|
- screen 阶段会持久化 checkpoint:`~/.boss-recommend-mcp/runs/<run_id>.checkpoint.json`。
|
|
@@ -476,27 +490,10 @@ Trae-CN / 长对话防循环建议:
|
|
|
476
490
|
{
|
|
477
491
|
"instruction": "推荐页筛选211女生,近14天没有,有 AI Agent 经验,符合标准的直接沟通",
|
|
478
492
|
"confirmation": {
|
|
479
|
-
"
|
|
480
|
-
"school_tag_confirmed": true,
|
|
481
|
-
"school_tag_value": ["985", "211"],
|
|
482
|
-
"degree_confirmed": true,
|
|
483
|
-
"degree_value": ["本科", "硕士", "博士"],
|
|
484
|
-
"gender_confirmed": true,
|
|
485
|
-
"gender_value": "女",
|
|
486
|
-
"recent_not_view_confirmed": true,
|
|
487
|
-
"recent_not_view_value": "近14天没有",
|
|
488
|
-
"criteria_confirmed": true,
|
|
489
|
-
"target_count_confirmed": true,
|
|
490
|
-
"target_count_value": 20,
|
|
491
|
-
"post_action_confirmed": true,
|
|
492
|
-
"post_action_value": "greet",
|
|
493
|
-
"final_confirmed": true,
|
|
494
|
-
"job_confirmed": true,
|
|
495
|
-
"job_value": "算法工程师(视频/图像模型方向) _ 杭州",
|
|
496
|
-
"max_greet_count_confirmed": true,
|
|
497
|
-
"max_greet_count_value": 10
|
|
493
|
+
"final_confirmed": true
|
|
498
494
|
},
|
|
499
495
|
"overrides": {
|
|
496
|
+
"page_scope": "recommend",
|
|
500
497
|
"school_tag": ["985", "211"],
|
|
501
498
|
"degree": ["本科", "硕士", "博士"],
|
|
502
499
|
"gender": "女",
|
|
@@ -507,18 +504,14 @@ Trae-CN / 长对话防循环建议:
|
|
|
507
504
|
"post_action": "greet",
|
|
508
505
|
"max_greet_count": 10
|
|
509
506
|
},
|
|
510
|
-
"
|
|
511
|
-
"
|
|
512
|
-
"criteria": "继续在聊天页处理有 AI Agent 或 MCP 项目经验的人选",
|
|
513
|
-
"start_from": "unread",
|
|
514
|
-
"target_count": 20,
|
|
515
|
-
"profile": "default",
|
|
516
|
-
"safe_pacing": true
|
|
517
|
-
}
|
|
507
|
+
"human_behavior": {
|
|
508
|
+
"restLevel": "medium"
|
|
518
509
|
}
|
|
519
510
|
}
|
|
520
511
|
```
|
|
521
512
|
|
|
513
|
+
`confirmation.final_confirmed=true` 表示用户已经看过并确认总览。旧版 `page_confirmed`、`school_tag_confirmed`、`job_confirmed` 等逐字段布尔值仍兼容,但新流程不需要主动生成它们。
|
|
514
|
+
|
|
522
515
|
## 测试
|
|
523
516
|
|
|
524
517
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reconcrap/boss-recommend-mcp",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "Unified MCP pipeline for recommend-page filtering and screening on Boss Zhipin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"boss",
|
|
@@ -79,11 +79,11 @@
|
|
|
79
79
|
"live:chat-image-screening": "node scripts/live-chat-image-screening-smoke.js"
|
|
80
80
|
},
|
|
81
81
|
"files": [
|
|
82
|
-
"bin",
|
|
83
|
-
"config/screening-config.example.json",
|
|
84
|
-
"skills",
|
|
85
|
-
"scripts/install-macos.sh",
|
|
86
|
-
"scripts/postinstall.cjs",
|
|
82
|
+
"bin",
|
|
83
|
+
"config/screening-config.example.json",
|
|
84
|
+
"skills",
|
|
85
|
+
"scripts/install-macos.sh",
|
|
86
|
+
"scripts/postinstall.cjs",
|
|
87
87
|
"src/core",
|
|
88
88
|
"src/domains",
|
|
89
89
|
"src/chat-mcp.js",
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"src/index.js",
|
|
94
94
|
"src/parser.js",
|
|
95
95
|
"src/recommend-mcp.js",
|
|
96
|
+
"src/recommend-scheduler.js",
|
|
96
97
|
"src/recruit-mcp.js",
|
|
97
98
|
"src/run-state.js",
|
|
98
99
|
"README.md"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "boss-recommend-pipeline"
|
|
3
|
-
description: "Use when users want Boss recommend-page filtering/screening via boss-recommend-mcp.
|
|
3
|
+
description: "Use when users want Boss recommend-page filtering/screening via boss-recommend-mcp. Gather required params, show one consolidated review, then run or schedule through the recommend MCP tools."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Boss Recommend Pipeline Skill
|
|
7
7
|
|
|
8
8
|
## Goal
|
|
9
9
|
|
|
10
|
-
当用户要在 Boss 推荐页筛人时,必须走 `start_recommend_pipeline_run
|
|
10
|
+
当用户要在 Boss 推荐页筛人时,必须走 `start_recommend_pipeline_run`;若是稍后/cron 启动,必须走 `schedule_recommend_pipeline_run`。先补齐缺失值并读取岗位列表,然后展示一次包含岗位、筛选项、criteria、目标人数、后置动作、最大招呼数、休息强度和定时信息的总确认;用户确认后设置 `final_confirmed=true` 即可启动或创建定时任务。2.0 CDP-only 路径不再支持 legacy recommend -> chat 自动衔接;若用户要聊天页筛选或求简历,必须在推荐页任务完成后显式改用 `boss-chat` 工具。
|
|
11
11
|
|
|
12
12
|
## Hard Rules (Must Follow)
|
|
13
13
|
|
|
@@ -19,10 +19,11 @@ description: "Use when users want Boss recommend-page filtering/screening via bo
|
|
|
19
19
|
|
|
20
20
|
- **确认不可代填(强制)**
|
|
21
21
|
- 禁止 agent 自行“设置合理参数”并代替用户确认。
|
|
22
|
-
-
|
|
22
|
+
- 禁止在用户未明确回复前,把 `final_confirmed=true`。
|
|
23
|
+
- 旧版 `*_confirmed` 字段仍兼容,但新流程不要逐项设置;把规范化后的值写入 `overrides`,总确认后只需要 `confirmation.final_confirmed=true`。
|
|
23
24
|
- 禁止在用户未明确回复前,自行填充 `page_scope/school_tag/degree/gender/recent_not_view/criteria/target_count/post_action/max_greet_count/job/rest_level`。
|
|
24
25
|
- 每次 run 必须明确询问用户本次休息强度 `rest_level`:`low`(旧策略)/ `medium`(约 5 小时或 700 人累计休息 30 分钟)/ `high`(约 5 小时或 700 人累计休息 1 小时);不得默认使用配置文件里的值替用户决定。
|
|
25
|
-
- 若工具返回 `pending_questions
|
|
26
|
+
- 若工具返回 `pending_questions`,只追问这些缺口;若只返回 `final_review`,不要再拆成逐字段确认。
|
|
26
27
|
|
|
27
28
|
- **岗位确认时机**
|
|
28
29
|
- 页面未就绪前,禁止询问 `job`。
|
|
@@ -30,7 +31,7 @@ description: "Use when users want Boss recommend-page filtering/screening via bo
|
|
|
30
31
|
|
|
31
32
|
- **参数确认**
|
|
32
33
|
- `criteria` 必须是用户开放式自然语言;禁止“严格/宽松执行”等预设替代。
|
|
33
|
-
- `post_action=greet`
|
|
34
|
+
- `post_action=greet` 时,`max_greet_count` 必须出现在总确认里;禁止未告知用户就自动默认为 `target_count`。
|
|
34
35
|
- 正式执行前必须 `final_confirmed=true`。
|
|
35
36
|
- 真实筛选禁止传 `detail_limit: 0`;recommend 默认必须打开候选人详情/CV。只有用户明确要求“卡片-only 调试”时,才允许同时传 `detail_limit: 0` 和 `allow_card_only_screening: true`。
|
|
36
37
|
|
|
@@ -40,29 +41,29 @@ description: "Use when users want Boss recommend-page filtering/screening via bo
|
|
|
40
41
|
- 最终执行前逐字回显将提交的 `instruction`;若与锁定值不一致,先修正再执行。
|
|
41
42
|
- 禁止在中途把用户意图拆成“recommend 已默认确认 + chat 单独执行”两条链路。
|
|
42
43
|
|
|
43
|
-
##
|
|
44
|
+
## Single Review Confirmation
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
必须确认:
|
|
46
|
+
先收集这些值:
|
|
48
47
|
|
|
49
48
|
- `page_scope`:`recommend|latest|featured`
|
|
50
|
-
- `school_tag
|
|
51
|
-
- `degree`(多选)
|
|
52
|
-
- `gender`
|
|
53
|
-
- `recent_not_view`
|
|
49
|
+
- `school_tag`、`degree`、`gender`、`recent_not_view`
|
|
54
50
|
- `criteria`(开放文本)
|
|
55
51
|
- `target_count`(可空)
|
|
56
52
|
- `post_action`:`favorite|greet|none`
|
|
57
53
|
- `max_greet_count`(仅当 `post_action=greet`)
|
|
58
54
|
- `rest_level`:`low|medium|high`
|
|
55
|
+
- `job`(来自 `list_recommend_jobs` / `job_options` 的精确岗位名)
|
|
56
|
+
- cron/定时任务的启动时间(如适用)
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
然后只做一次总确认。用户回复“确认 / 全部确认 / 无需调整”后,下一次工具调用写入:
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"confirmation": { "final_confirmed": true }
|
|
63
|
+
}
|
|
64
|
+
```
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
- `final_review`(岗位 + 全参数总确认)
|
|
66
|
+
已确认值放在 `overrides` 和 `human_behavior.restLevel`。不要因为工具返回 `final_review` 就再问页面、学历、学校、性别、14天、criteria、目标人数、动作、最大招呼数等逐项确认。
|
|
66
67
|
|
|
67
68
|
## Chat Handoff
|
|
68
69
|
|
|
@@ -94,12 +95,18 @@ description: "Use when users want Boss recommend-page filtering/screening via bo
|
|
|
94
95
|
- 限制:只读岗位列表,不启动筛选任务;若返回 `BOSS_LOGIN_REQUIRED`,必须让用户在自动打开的 Chrome 完成登录后重试,本次 cron 不得创建。
|
|
95
96
|
- Cron 准备工具:`prepare_recommend_pipeline_run`
|
|
96
97
|
- 用途:只校验参数是否已可用于 cron / 一次性任务,不启动筛选任务。
|
|
97
|
-
- 要求:只有返回 `status=READY` 且 `cron_ready=true`
|
|
98
|
+
- 要求:只有返回 `status=READY` 且 `cron_ready=true` 后,才允许继续创建定时任务。
|
|
98
99
|
- 若返回 `NEED_INPUT` / `NEED_CONFIRMATION` / `FAILED`:继续补齐 `pending_questions` 或修复登录/页面/config;不得先创建 cron。
|
|
100
|
+
- Cron 创建工具:`schedule_recommend_pipeline_run`
|
|
101
|
+
- 用途:保存已经 READY 的完整 payload,并启动 package-owned detached scheduler;到点后由包内 worker 直接调用 `start_recommend_pipeline_run`。
|
|
102
|
+
- 必填:同 `start_recommend_pipeline_run` 的完整 payload,另加 `schedule_delay_minutes` / `schedule_delay_seconds` / `schedule_run_at` 之一。
|
|
103
|
+
- 成功标准:必须返回 `status=SCHEDULED`、`schedule_created=true`、`schedule_id`、`run_at`。只有这个返回后,才可以告诉用户定时任务已创建。
|
|
104
|
+
- Cron 查询工具:`get_recommend_scheduled_run`
|
|
105
|
+
- 用途:用户问“任务是否启动/进度”时,先查 `schedule_id`。若到点后已启动,会返回内层 `run_id` 和 run 快照。
|
|
99
106
|
- 主工具:`start_recommend_pipeline_run`
|
|
100
107
|
- 必填:`instruction`
|
|
101
108
|
- 关键输入:
|
|
102
|
-
- `confirmation
|
|
109
|
+
- `confirmation`:新流程只需要 `{ "final_confirmed": true }`;旧版 `page_confirmed/page_value/.../job_confirmed/job_value` 仍兼容但不要主动制造逐项确认。
|
|
103
110
|
- `overrides`:`page_scope/school_tag/degree/gender/recent_not_view/criteria/job/target_count/post_action/max_greet_count`
|
|
104
111
|
- `human_behavior`:必须包含本次用户确认的 `restLevel`(例如 `{ "restLevel": "medium" }`)
|
|
105
112
|
- 不要传 `follow_up.chat`;该路径属于 legacy-only 行为
|
|
@@ -116,19 +123,33 @@ description: "Use when users want Boss recommend-page filtering/screening via bo
|
|
|
116
123
|
创建 cron 时必须在设置 cron 的当下完成全部交互:
|
|
117
124
|
|
|
118
125
|
1. 锁定用户原始 instruction,不改写、不摘要,criteria 放入 `overrides.criteria` 时必须逐字保留。
|
|
119
|
-
2.
|
|
126
|
+
2. 收集全部筛选项、`target_count`、`post_action`、`max_greet_count`(如需要)和本次 `rest_level`。
|
|
120
127
|
3. 调用 `list_recommend_jobs`;若 Chrome 未打开,工具会尝试自动打开本机 9222 Chrome 并进入推荐页。若返回 `BOSS_LOGIN_REQUIRED` 或页面不可用,停止 cron 创建,让用户登录/修复后重试。
|
|
121
|
-
4. 用 `job_names`
|
|
122
|
-
5. 调用 `prepare_recommend_pipeline_run` 传入将来要执行的完整 payload;只有 `READY + cron_ready=true`
|
|
123
|
-
6.
|
|
128
|
+
4. 用 `job_names` 中的精确岗位名填入 `overrides.job`,展示包含启动时间的最终总确认;用户确认后写入 `final_confirmed=true`。
|
|
129
|
+
5. 调用 `prepare_recommend_pipeline_run` 传入将来要执行的完整 payload;只有 `READY + cron_ready=true` 才能继续。
|
|
130
|
+
6. 立即调用 `schedule_recommend_pipeline_run`,传入同一份完整 payload 和 `schedule_delay_minutes` / `schedule_run_at`。禁止让 OpenClaw 自己写 `/tmp/*.log` shell cron、自然语言提醒、或未来对话回调来代替此工具。
|
|
131
|
+
7. 只有拿到 `SCHEDULED + schedule_id` 后才告诉用户定时任务已创建。回复必须包含 `schedule_id`,而不是只说“10 分钟后会启动”。
|
|
132
|
+
8. 到点后由 package-owned detached scheduler 启动;若 Chrome/登录异常,应作为 schedule/run 失败处理,不得再向用户追问参数。
|
|
124
133
|
|
|
125
|
-
Shell-only OpenClaw/QClaw cron
|
|
134
|
+
Shell-only OpenClaw/QClaw cron 设置同样先运行 prepare:
|
|
126
135
|
|
|
127
136
|
```powershell
|
|
128
137
|
npx -y @reconcrap/boss-recommend-mcp@latest prepare-run --instruction-file .\boss-recommend-instruction.txt --overrides-file .\boss-recommend-overrides.json --confirmation-file .\boss-recommend-confirmation.json --slow-live --port 9222
|
|
129
138
|
```
|
|
130
139
|
|
|
131
|
-
仅当上述命令输出 `READY` 且 `cron_ready=true`
|
|
140
|
+
仅当上述命令输出 `READY` 且 `cron_ready=true` 后,才允许继续创建定时任务。
|
|
141
|
+
|
|
142
|
+
然后必须用 package-owned scheduler 创建定时任务,不要手写系统 cron:
|
|
143
|
+
|
|
144
|
+
```powershell
|
|
145
|
+
npx -y @reconcrap/boss-recommend-mcp@latest schedule-run --schedule-delay-minutes 10 --instruction-file .\boss-recommend-instruction.txt --overrides-file .\boss-recommend-overrides.json --confirmation-file .\boss-recommend-confirmation.json --slow-live --port 9222
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
用户查询时:
|
|
149
|
+
|
|
150
|
+
```powershell
|
|
151
|
+
npx -y @reconcrap/boss-recommend-mcp@latest schedule-status --schedule-id <schedule_id>
|
|
152
|
+
```
|
|
132
153
|
|
|
133
154
|
## Async Run Policy
|
|
134
155
|
|
|
@@ -172,15 +193,16 @@ npx -y @reconcrap/boss-recommend-mcp@latest prepare-run --instruction-file .\bos
|
|
|
172
193
|
|
|
173
194
|
推荐做法:
|
|
174
195
|
|
|
175
|
-
1. 将锁定的用户原文写入 instruction 文件,将已确认参数写入 `overrides`
|
|
176
|
-
2. 先用 `prepare-run` 校验完整 payload 已 cron-ready;未返回 `READY + cron_ready=true`
|
|
177
|
-
3.
|
|
196
|
+
1. 将锁定的用户原文写入 instruction 文件,将已确认参数写入 `overrides` JSON;`confirmation` JSON 只需要 `{ "final_confirmed": true }`。
|
|
197
|
+
2. 先用 `prepare-run` 校验完整 payload 已 cron-ready;未返回 `READY + cron_ready=true` 不得创建定时任务或启动 run。
|
|
198
|
+
3. 若用户要“现在启动”,用 detached CLI 启动,让父命令返回启动证据,子进程继续持有 CDP 会话:
|
|
178
199
|
|
|
179
200
|
```powershell
|
|
180
201
|
npx -y @reconcrap/boss-recommend-mcp@latest run --detached --instruction-file .\boss-recommend-instruction.txt --overrides-file .\boss-recommend-overrides.json --confirmation-file .\boss-recommend-confirmation.json --slow-live --port 9222
|
|
181
202
|
```
|
|
182
203
|
|
|
183
|
-
4.
|
|
204
|
+
4. 若用户要“稍后/cron/定时启动”,用 `schedule-run`,不是 `run --detached`。若 `schedule-run` 未返回 `SCHEDULED + schedule_id`,不得告诉用户定时任务已创建。
|
|
205
|
+
5. 若即时 `run --detached` 返回 `ACCEPTED + run_id`,即任务已启动;记录 `run_id/stdout_path/stderr_path`。若返回 `NEED_INPUT` 或 `NEED_CONFIRMATION`,说明设置阶段漏掉了准备门禁,应回到 `prepare-run` 补齐,不能在到点后继续问用户确认。
|
|
184
206
|
|
|
185
207
|
兼容路径:
|
|
186
208
|
|
|
@@ -199,8 +221,8 @@ npx -y @reconcrap/boss-recommend-mcp@latest run --detached --instruction-file .\
|
|
|
199
221
|
## Response Style
|
|
200
222
|
|
|
201
223
|
- 用结构化中文。
|
|
202
|
-
-
|
|
203
|
-
- 仅在 `job_options`
|
|
224
|
+
- 未读取岗位列表前不要要求用户最终确认。
|
|
225
|
+
- 仅在 `job_options` 出现后选择精确岗位;最终确认卡片必须包含岗位和全部参数。
|
|
204
226
|
- 封闭式问题必须带完整标签选项;开放式问题(如 `criteria`)保持自由输入。
|
|
205
227
|
- 页面就绪失败提示必须包含 `debug_port`、recommend URL、以及登录 URL(若未登录):
|
|
206
228
|
- `https://www.zhipin.com/web/chat/recommend`
|
package/src/cli.js
CHANGED
|
@@ -28,6 +28,10 @@ import {
|
|
|
28
28
|
prepareRecommendPipelineRunTool,
|
|
29
29
|
startRecommendPipelineRunTool
|
|
30
30
|
} from "./recommend-mcp.js";
|
|
31
|
+
import {
|
|
32
|
+
getRecommendScheduledRunTool,
|
|
33
|
+
scheduleRecommendPipelineRunTool
|
|
34
|
+
} from "./recommend-scheduler.js";
|
|
31
35
|
import {
|
|
32
36
|
getBossScreenConfigResolution,
|
|
33
37
|
resolveBossChatRuntimeLayout as resolveCdpBossChatRuntimeLayout,
|
|
@@ -2694,6 +2698,8 @@ function printHelp() {
|
|
|
2694
2698
|
console.log(" boss-recommend-mcp Start the MCP server");
|
|
2695
2699
|
console.log(" boss-recommend-mcp start Start the MCP server");
|
|
2696
2700
|
console.log(" boss-recommend-mcp prepare-run Validate a cron-ready recommend run payload without starting screening");
|
|
2701
|
+
console.log(" boss-recommend-mcp schedule-run Create a package-owned delayed recommend run");
|
|
2702
|
+
console.log(" boss-recommend-mcp schedule-status Check a package-owned delayed recommend run");
|
|
2697
2703
|
console.log(" boss-recommend-mcp run Start a CDP-only recommend run through the shared run service");
|
|
2698
2704
|
console.log(" boss-recommend-mcp list-jobs CDP-only list of exact recommend job names for cron/one-shot inputs");
|
|
2699
2705
|
console.log(" boss-recommend-mcp chat <subcommand> Run CDP-only boss-chat health/prepare/status commands");
|
|
@@ -2711,6 +2717,8 @@ function printHelp() {
|
|
|
2711
2717
|
console.log("");
|
|
2712
2718
|
console.log("Run command:");
|
|
2713
2719
|
console.log(" boss-recommend-mcp prepare-run --instruction \"...\" --overrides-file overrides.json --confirmation-file confirmation.json");
|
|
2720
|
+
console.log(" boss-recommend-mcp schedule-run --schedule-delay-minutes 10 --instruction-file boss-recommend-instruction.txt --overrides-file overrides.json --confirmation-file confirmation.json");
|
|
2721
|
+
console.log(" boss-recommend-mcp schedule-status --schedule-id <id>");
|
|
2714
2722
|
console.log(" boss-recommend-mcp run --instruction \"推荐页上筛选211男生,近14天没有,有大模型平台经验\" --overrides-file overrides.json --confirmation-file confirmation.json");
|
|
2715
2723
|
console.log(" boss-recommend-mcp run --detached --instruction \"...\" --overrides-file overrides.json --confirmation-file confirmation.json");
|
|
2716
2724
|
console.log(" boss-recommend-mcp list-jobs --slow-live --port 9222");
|
|
@@ -2907,6 +2915,62 @@ async function preparePipelineOnce(options = {}) {
|
|
|
2907
2915
|
}
|
|
2908
2916
|
}
|
|
2909
2917
|
|
|
2918
|
+
function addScheduleOptions(args, options = {}) {
|
|
2919
|
+
const scheduleId = String(options["schedule-id"] || options.schedule_id || options.scheduleId || "").trim();
|
|
2920
|
+
if (scheduleId) args.schedule_id = scheduleId;
|
|
2921
|
+
const runAt = String(options["schedule-run-at"] || options.schedule_run_at || options.scheduleRunAt || options["run-at"] || options.run_at || "").trim();
|
|
2922
|
+
if (runAt) args.schedule_run_at = runAt;
|
|
2923
|
+
const delayMinutes = parseNonNegativeInteger(options["schedule-delay-minutes"] ?? options.schedule_delay_minutes ?? options.scheduleDelayMinutes);
|
|
2924
|
+
if (delayMinutes !== undefined) args.schedule_delay_minutes = delayMinutes;
|
|
2925
|
+
const delaySeconds = parseNonNegativeInteger(options["schedule-delay-seconds"] ?? options.schedule_delay_seconds ?? options.scheduleDelaySeconds);
|
|
2926
|
+
if (delaySeconds !== undefined) args.schedule_delay_seconds = delaySeconds;
|
|
2927
|
+
return args;
|
|
2928
|
+
}
|
|
2929
|
+
|
|
2930
|
+
async function schedulePipelineOnce(options = {}) {
|
|
2931
|
+
const workspaceRoot = getWorkspaceRoot(options);
|
|
2932
|
+
const { args, port } = buildRecommendRunCliInput(options);
|
|
2933
|
+
addScheduleOptions(args, options);
|
|
2934
|
+
const result = await scheduleRecommendPipelineRunTool({
|
|
2935
|
+
workspaceRoot,
|
|
2936
|
+
args
|
|
2937
|
+
});
|
|
2938
|
+
printJson({
|
|
2939
|
+
...result,
|
|
2940
|
+
cli: {
|
|
2941
|
+
...(result.cli || {}),
|
|
2942
|
+
command: "schedule-run",
|
|
2943
|
+
cdp_only: true,
|
|
2944
|
+
package_owned_scheduler: true,
|
|
2945
|
+
workspace_root: workspaceRoot,
|
|
2946
|
+
port
|
|
2947
|
+
}
|
|
2948
|
+
});
|
|
2949
|
+
if (result.status !== "SCHEDULED") {
|
|
2950
|
+
process.exitCode = 1;
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
function scheduleStatusCli(options = {}) {
|
|
2955
|
+
const scheduleId = String(options["schedule-id"] || options.schedule_id || options.scheduleId || "").trim();
|
|
2956
|
+
const result = getRecommendScheduledRunTool({
|
|
2957
|
+
args: {
|
|
2958
|
+
schedule_id: scheduleId
|
|
2959
|
+
}
|
|
2960
|
+
});
|
|
2961
|
+
printJson({
|
|
2962
|
+
...result,
|
|
2963
|
+
cli: {
|
|
2964
|
+
command: "schedule-status",
|
|
2965
|
+
cdp_only: true,
|
|
2966
|
+
package_owned_scheduler: true
|
|
2967
|
+
}
|
|
2968
|
+
});
|
|
2969
|
+
if (result.status !== "OK") {
|
|
2970
|
+
process.exitCode = 1;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2910
2974
|
async function runPipelineOnce(options = {}) {
|
|
2911
2975
|
const workspaceRoot = getWorkspaceRoot(options);
|
|
2912
2976
|
const { args, port } = buildRecommendRunCliInput(options);
|
|
@@ -3120,6 +3184,39 @@ export async function runCli(argv = process.argv) {
|
|
|
3120
3184
|
process.exitCode = 1;
|
|
3121
3185
|
}
|
|
3122
3186
|
break;
|
|
3187
|
+
case "schedule-run":
|
|
3188
|
+
case "schedule":
|
|
3189
|
+
try {
|
|
3190
|
+
await schedulePipelineOnce(options);
|
|
3191
|
+
} catch (error) {
|
|
3192
|
+
printJson({
|
|
3193
|
+
status: "FAILED",
|
|
3194
|
+
schedule_created: false,
|
|
3195
|
+
error: {
|
|
3196
|
+
code: "INVALID_CLI_INPUT",
|
|
3197
|
+
message: error.message || "Invalid CLI input",
|
|
3198
|
+
retryable: false
|
|
3199
|
+
}
|
|
3200
|
+
});
|
|
3201
|
+
process.exitCode = 1;
|
|
3202
|
+
}
|
|
3203
|
+
break;
|
|
3204
|
+
case "schedule-status":
|
|
3205
|
+
case "scheduled-run":
|
|
3206
|
+
try {
|
|
3207
|
+
scheduleStatusCli(options);
|
|
3208
|
+
} catch (error) {
|
|
3209
|
+
printJson({
|
|
3210
|
+
status: "FAILED",
|
|
3211
|
+
error: {
|
|
3212
|
+
code: "INVALID_CLI_INPUT",
|
|
3213
|
+
message: error.message || "Invalid CLI input",
|
|
3214
|
+
retryable: false
|
|
3215
|
+
}
|
|
3216
|
+
});
|
|
3217
|
+
process.exitCode = 1;
|
|
3218
|
+
}
|
|
3219
|
+
break;
|
|
3123
3220
|
case "list-jobs":
|
|
3124
3221
|
case "jobs":
|
|
3125
3222
|
case "recommend-jobs":
|
|
@@ -3282,6 +3379,8 @@ export const __testables = {
|
|
|
3282
3379
|
resolveBossChatRuntimeLayout: resolveCdpBossChatRuntimeLayout,
|
|
3283
3380
|
runBossChatCliCommand,
|
|
3284
3381
|
preparePipelineOnce,
|
|
3382
|
+
schedulePipelineOnce,
|
|
3383
|
+
scheduleStatusCli,
|
|
3285
3384
|
runPipelineOnce
|
|
3286
3385
|
};
|
|
3287
3386
|
|
package/src/index.js
CHANGED
|
@@ -39,6 +39,12 @@ import {
|
|
|
39
39
|
startRecruitPipelineRunTool,
|
|
40
40
|
validateRecruitPipelineArgs
|
|
41
41
|
} from "./recruit-mcp.js";
|
|
42
|
+
import {
|
|
43
|
+
__setRecommendSchedulerSpawnForTests,
|
|
44
|
+
getRecommendScheduledRunTool,
|
|
45
|
+
runScheduledRecommendWorker,
|
|
46
|
+
scheduleRecommendPipelineRunTool
|
|
47
|
+
} from "./recommend-scheduler.js";
|
|
42
48
|
import {
|
|
43
49
|
__resetRecommendMcpStateForTests,
|
|
44
50
|
__setRecommendMcpConnectorForTests,
|
|
@@ -90,6 +96,8 @@ const require = createRequire(import.meta.url);
|
|
|
90
96
|
const { version: SERVER_VERSION } = require("../package.json");
|
|
91
97
|
|
|
92
98
|
const TOOL_PREPARE_RUN = "prepare_recommend_pipeline_run";
|
|
99
|
+
const TOOL_SCHEDULE_RUN = "schedule_recommend_pipeline_run";
|
|
100
|
+
const TOOL_GET_SCHEDULED_RUN = "get_recommend_scheduled_run";
|
|
93
101
|
const TOOL_START_RUN = "start_recommend_pipeline_run";
|
|
94
102
|
const TOOL_GET_RUN = "get_recommend_pipeline_run";
|
|
95
103
|
const TOOL_CANCEL_RUN = "cancel_recommend_pipeline_run";
|
|
@@ -512,6 +520,7 @@ function createRunInputSchema() {
|
|
|
512
520
|
},
|
|
513
521
|
confirmation: {
|
|
514
522
|
type: "object",
|
|
523
|
+
description: "推荐页确认状态。新流程推荐只在用户看过总览后传 final_confirmed=true;逐字段 *_confirmed 为兼容旧调用保留。",
|
|
515
524
|
properties: {
|
|
516
525
|
page_confirmed: { type: "boolean" },
|
|
517
526
|
page_value: {
|
|
@@ -576,7 +585,10 @@ function createRunInputSchema() {
|
|
|
576
585
|
type: "string",
|
|
577
586
|
enum: ["favorite", "greet", "none"]
|
|
578
587
|
},
|
|
579
|
-
final_confirmed: {
|
|
588
|
+
final_confirmed: {
|
|
589
|
+
type: "boolean",
|
|
590
|
+
description: "用户已确认包含岗位、筛选项、criteria、目标、动作、最大招呼数和 restLevel 的总览。"
|
|
591
|
+
},
|
|
580
592
|
job_confirmed: { type: "boolean" },
|
|
581
593
|
job_value: { type: "string" },
|
|
582
594
|
max_greet_count_confirmed: { type: "boolean" },
|
|
@@ -706,8 +718,8 @@ function createRunInputSchema() {
|
|
|
706
718
|
type: "boolean",
|
|
707
719
|
description: "可选,VPN/慢页面 live 测试模式,放宽等待时间"
|
|
708
720
|
},
|
|
709
|
-
human_behavior: createHumanBehaviorInputSchema("
|
|
710
|
-
humanBehavior: createHumanBehaviorInputSchema("兼容字段;优先使用 human_behavior"),
|
|
721
|
+
human_behavior: createHumanBehaviorInputSchema("recommend 运行必须显式包含本次用户确认的 restLevel: low|medium|high;其他节奏配置可选"),
|
|
722
|
+
humanBehavior: createHumanBehaviorInputSchema("兼容字段;优先使用 human_behavior;recommend 运行同样必须显式包含 restLevel"),
|
|
711
723
|
human_behavior_enabled: {
|
|
712
724
|
type: "boolean",
|
|
713
725
|
description: "兼容字段;true 等同启用 paced 默认配置,false 等同 baseline"
|
|
@@ -1083,6 +1095,36 @@ function createListRecommendJobsInputSchema() {
|
|
|
1083
1095
|
};
|
|
1084
1096
|
}
|
|
1085
1097
|
|
|
1098
|
+
function createScheduleRunInputSchema() {
|
|
1099
|
+
const base = createRunInputSchema();
|
|
1100
|
+
return {
|
|
1101
|
+
...base,
|
|
1102
|
+
properties: {
|
|
1103
|
+
...base.properties,
|
|
1104
|
+
schedule_id: {
|
|
1105
|
+
type: "string",
|
|
1106
|
+
description: "可选,自定义定时任务 id;默认自动生成"
|
|
1107
|
+
},
|
|
1108
|
+
schedule_run_at: {
|
|
1109
|
+
type: "string",
|
|
1110
|
+
description: "ISO 时间字符串;到点后由 package-owned detached scheduler 启动已准备好的 payload"
|
|
1111
|
+
},
|
|
1112
|
+
schedule_delay_minutes: {
|
|
1113
|
+
type: "number",
|
|
1114
|
+
minimum: 0,
|
|
1115
|
+
description: "从现在开始延迟多少分钟后启动;适合 OpenClaw cron/定时任务设置"
|
|
1116
|
+
},
|
|
1117
|
+
schedule_delay_seconds: {
|
|
1118
|
+
type: "number",
|
|
1119
|
+
minimum: 0,
|
|
1120
|
+
description: "从现在开始延迟多少秒后启动;主要用于短延迟或测试"
|
|
1121
|
+
}
|
|
1122
|
+
},
|
|
1123
|
+
required: ["instruction"],
|
|
1124
|
+
additionalProperties: false
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1086
1128
|
function createToolsSchema() {
|
|
1087
1129
|
return [
|
|
1088
1130
|
{
|
|
@@ -1095,6 +1137,23 @@ function createToolsSchema() {
|
|
|
1095
1137
|
description: "只校验 Boss 推荐页流水线参数是否已可用于 cron/一次性任务;不会启动筛选任务。只有返回 READY/cron_ready=true 后才应创建定时任务。",
|
|
1096
1138
|
inputSchema: createRunInputSchema()
|
|
1097
1139
|
},
|
|
1140
|
+
{
|
|
1141
|
+
name: TOOL_SCHEDULE_RUN,
|
|
1142
|
+
description: "创建 package-owned Boss 推荐页定时任务:先校验 READY/cron_ready,再保存完整 payload,并由 detached scheduler 到点直接启动,不再依赖 AI harness 自己拼 shell cron。",
|
|
1143
|
+
inputSchema: createScheduleRunInputSchema()
|
|
1144
|
+
},
|
|
1145
|
+
{
|
|
1146
|
+
name: TOOL_GET_SCHEDULED_RUN,
|
|
1147
|
+
description: "查询 package-owned 推荐页定时任务状态;返回 schedule_id、worker 状态、到点后启动的 run_id 与运行快照。",
|
|
1148
|
+
inputSchema: {
|
|
1149
|
+
type: "object",
|
|
1150
|
+
properties: {
|
|
1151
|
+
schedule_id: { type: "string" }
|
|
1152
|
+
},
|
|
1153
|
+
required: ["schedule_id"],
|
|
1154
|
+
additionalProperties: false
|
|
1155
|
+
}
|
|
1156
|
+
},
|
|
1098
1157
|
{
|
|
1099
1158
|
name: TOOL_START_RUN,
|
|
1100
1159
|
description: "异步启动 Boss 推荐页流水线(含同步门禁预检);只有在前置确认与页面就绪通过后才返回 run_id。",
|
|
@@ -2626,6 +2685,10 @@ async function handleRequest(message, workspaceRoot) {
|
|
|
2626
2685
|
payload = await listRecommendJobsTool({ workspaceRoot, args });
|
|
2627
2686
|
} else if (toolName === TOOL_PREPARE_RUN) {
|
|
2628
2687
|
payload = prepareRecommendPipelineRunTool({ workspaceRoot, args });
|
|
2688
|
+
} else if (toolName === TOOL_SCHEDULE_RUN) {
|
|
2689
|
+
payload = await scheduleRecommendPipelineRunTool({ workspaceRoot, args });
|
|
2690
|
+
} else if (toolName === TOOL_GET_SCHEDULED_RUN) {
|
|
2691
|
+
payload = getRecommendScheduledRunTool({ args });
|
|
2629
2692
|
} else if (toolName === TOOL_START_RUN) {
|
|
2630
2693
|
payload = await handleStartRunTool({ workspaceRoot, args });
|
|
2631
2694
|
} else if (toolName === TOOL_GET_RUN) {
|
|
@@ -2825,6 +2888,12 @@ export const __testables = {
|
|
|
2825
2888
|
resetRecommendMcpStateForTests() {
|
|
2826
2889
|
__resetRecommendMcpStateForTests();
|
|
2827
2890
|
},
|
|
2891
|
+
setRecommendSchedulerSpawnForTests(nextImpl) {
|
|
2892
|
+
__setRecommendSchedulerSpawnForTests(nextImpl);
|
|
2893
|
+
},
|
|
2894
|
+
runScheduledRecommendWorkerForTests(options = {}) {
|
|
2895
|
+
return runScheduledRecommendWorker(options);
|
|
2896
|
+
},
|
|
2828
2897
|
setChatMcpConnectorForTests(nextImpl) {
|
|
2829
2898
|
forceChatInProcForTests = typeof nextImpl === "function";
|
|
2830
2899
|
__setChatMcpConnectorForTests(nextImpl);
|