@reconcrap/boss-recommend-mcp 2.1.14 → 2.1.15
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 +5 -5
- package/package.json +1 -1
- package/skills/boss-chat/README.md +2 -2
- package/skills/boss-chat/SKILL.md +7 -7
- package/skills/boss-recruit-pipeline/SKILL.md +23 -1
- package/src/chat-mcp.js +70 -73
- package/src/domains/chat/detail.js +79 -47
- package/src/domains/chat/run-service.js +400 -158
- package/src/domains/recruit/constants.js +65 -0
- package/src/domains/recruit/instruction-parser.js +362 -86
- package/src/domains/recruit/run-service.js +281 -10
- package/src/domains/recruit/search.js +2076 -298
- package/src/index.js +18 -12
- package/src/recommend-mcp.js +77 -8
- package/src/recruit-mcp.js +228 -3
package/src/index.js
CHANGED
|
@@ -1074,7 +1074,7 @@ function createBossChatStartInputSchema({ requireFullInput = false } = {}) {
|
|
|
1074
1074
|
},
|
|
1075
1075
|
criteria: {
|
|
1076
1076
|
type: "string",
|
|
1077
|
-
description: "boss-chat 的筛选 criteria"
|
|
1077
|
+
description: "boss-chat 的筛选 criteria;可留空,留空时进入 collect_cv 模式:不触发 LLM 筛选,只向没有在线/附件简历的人选求简历"
|
|
1078
1078
|
},
|
|
1079
1079
|
greeting_text: {
|
|
1080
1080
|
type: "string",
|
|
@@ -1133,8 +1133,8 @@ function createBossChatStartInputSchema({ requireFullInput = false } = {}) {
|
|
|
1133
1133
|
},
|
|
1134
1134
|
screening_mode: {
|
|
1135
1135
|
type: "string",
|
|
1136
|
-
enum: ["llm", "deterministic"],
|
|
1137
|
-
description: "筛选引擎;默认 llm
|
|
1136
|
+
enum: ["llm", "deterministic", "collect_cv"],
|
|
1137
|
+
description: "筛选引擎;默认 llm。有 criteria 时 deterministic 仅限 debug_test_mode=true;criteria 留空时自动 collect_cv"
|
|
1138
1138
|
},
|
|
1139
1139
|
debug_test_mode: {
|
|
1140
1140
|
type: "boolean",
|
|
@@ -1222,11 +1222,17 @@ function createBossChatStartInputSchema({ requireFullInput = false } = {}) {
|
|
|
1222
1222
|
start_from: "unread",
|
|
1223
1223
|
target_count: 20,
|
|
1224
1224
|
criteria: "请筛选 20 位符合条件的人选"
|
|
1225
|
+
},
|
|
1226
|
+
{
|
|
1227
|
+
job: "530272634",
|
|
1228
|
+
start_from: "all",
|
|
1229
|
+
target_count: "all",
|
|
1230
|
+
criteria: ""
|
|
1225
1231
|
}
|
|
1226
1232
|
]
|
|
1227
1233
|
};
|
|
1228
1234
|
if (requireFullInput) {
|
|
1229
|
-
schema.required = ["job", "start_from"
|
|
1235
|
+
schema.required = ["job", "start_from"];
|
|
1230
1236
|
schema.anyOf = [
|
|
1231
1237
|
{ required: ["target_count"] },
|
|
1232
1238
|
{ required: ["targetCount"] }
|
|
@@ -1546,7 +1552,7 @@ function createToolsSchema(toolset = getConfiguredMcpToolset()) {
|
|
|
1546
1552
|
},
|
|
1547
1553
|
{
|
|
1548
1554
|
name: TOOL_BOSS_CHAT_START_RUN,
|
|
1549
|
-
description: "异步启动一次 boss-chat/chat-only 任务。必须一次性提供 job、start_from、target_count
|
|
1555
|
+
description: "异步启动一次 boss-chat/chat-only 任务。必须一次性提供 job、start_from、target_count;criteria 可留空,留空时自动收集缺失简历而不触发 LLM 筛选。若用户选择扫到底/不限/全部候选人,必须字面传 target_count=\"all\"。严禁改用 start_recommend_pipeline_run。",
|
|
1550
1556
|
inputSchema: createBossChatStartInputSchema({ requireFullInput: true })
|
|
1551
1557
|
},
|
|
1552
1558
|
{
|
|
@@ -1603,17 +1609,17 @@ function createToolsSchema(toolset = getConfiguredMcpToolset()) {
|
|
|
1603
1609
|
},
|
|
1604
1610
|
{
|
|
1605
1611
|
name: TOOL_LIST_RECOMMEND_JOBS,
|
|
1606
|
-
description: "CDP-only 读取 Boss 推荐页岗位下拉框,返回所有可用岗位完整名称,方便 recommend/推荐页 cron/一次性任务提前填写 job 参数。不会启动筛选任务。chat-only、未读、全部聊天、求简历任务严禁调用本工具,必须用 list_boss_chat_jobs 或 prepare_boss_chat_run。",
|
|
1612
|
+
description: "CDP-only 读取 Boss 推荐页岗位下拉框,返回所有可用岗位完整名称,方便 recommend/推荐页 cron/一次性任务提前填写 job 参数。不会启动筛选任务。chat-only、未读、全部聊天、求简历任务严禁调用本工具,必须用 list_boss_chat_jobs 或 prepare_boss_chat_run。搜索页/search/recruit、/web/chat/search 任务也严禁调用本工具,必须用 boss-recruit/run_recruit_pipeline 或 boss-recruit/start_recruit_pipeline_run。",
|
|
1607
1613
|
inputSchema: createListRecommendJobsInputSchema()
|
|
1608
1614
|
},
|
|
1609
1615
|
{
|
|
1610
1616
|
name: TOOL_RUN_RECOMMEND,
|
|
1611
|
-
description: "立即通过原生 MCP 启动 Boss
|
|
1617
|
+
description: "立即通过原生 MCP 启动 Boss 推荐页筛选。仅用于 boss-recommend/推荐页,不用于搜索页。搜索页/search/recruit、/web/chat/search 任务必须调用 boss-recruit/run_recruit_pipeline 或 boss-recruit/start_recruit_pipeline_run。它是 start_recommend_pipeline_run 的短别名;用户已经确认并要现在启动时,优先调用本工具,不需要先调用 prepare_recommend_pipeline_run。必须作为 MCP tool call 调用,禁止通过 terminal/shell/run_command/PowerShell/CLI/manual JSON-RPC 代替,也不要用 schedule_recommend_pipeline_run 冒充立即启动。",
|
|
1612
1618
|
inputSchema: runInputSchema
|
|
1613
1619
|
},
|
|
1614
1620
|
{
|
|
1615
1621
|
name: TOOL_START_RUN,
|
|
1616
|
-
description: "立即通过原生 MCP 异步启动 Boss
|
|
1622
|
+
description: "立即通过原生 MCP 异步启动 Boss 推荐页流水线(含同步门禁预检)。仅用于 boss-recommend/推荐页,不用于搜索页。搜索页/search/recruit、/web/chat/search 任务必须调用 boss-recruit/start_recruit_pipeline_run 或 boss-recruit/run_recruit_pipeline。用户已经确认并要现在启动时,优先调用本工具或 run_recommend,不需要先调用 prepare_recommend_pipeline_run。必须作为 MCP tool call 调用,禁止通过 terminal/shell/run_command/PowerShell/CLI/manual JSON-RPC 代替,也不要用 schedule_recommend_pipeline_run 冒充立即启动。",
|
|
1617
1623
|
inputSchema: runInputSchema
|
|
1618
1624
|
},
|
|
1619
1625
|
{
|
|
@@ -1736,12 +1742,12 @@ function createToolsSchema(toolset = getConfiguredMcpToolset()) {
|
|
|
1736
1742
|
},
|
|
1737
1743
|
{
|
|
1738
1744
|
name: TOOL_RUN_RECRUIT_PIPELINE,
|
|
1739
|
-
description: "
|
|
1745
|
+
description: "Boss 搜索页/search/recruit 专用入口;Trae-CN split-server 下应调用 boss-recruit/run_recruit_pipeline。默认 async,sync 模式会等待终态。必须提供搜索页岗位 job(关键词输入框旁边的岗位选择)和 keyword/search intent;不要改用 boss-recommend/run_recommend 或 boss-recommend/start_recommend_pipeline_run。所有浏览器动作走共享 CDP-only recruit service。",
|
|
1740
1746
|
inputSchema: createRecruitPipelineInputSchema()
|
|
1741
1747
|
},
|
|
1742
1748
|
{
|
|
1743
1749
|
name: TOOL_START_RECRUIT_PIPELINE_RUN,
|
|
1744
|
-
description: "异步启动 Boss recruit
|
|
1750
|
+
description: "异步启动 Boss 搜索页/search/recruit 流水线;Trae-CN split-server 下应调用 boss-recruit/start_recruit_pipeline_run。必须提供搜索页岗位 job(关键词输入框旁边的岗位选择)和 keyword/search intent;先完成参数/criteria/default 确认门禁,再连接 Chrome search 页执行。不要改用 boss-recommend/start_recommend_pipeline_run。",
|
|
1745
1751
|
inputSchema: createRecruitPipelineInputSchema()
|
|
1746
1752
|
},
|
|
1747
1753
|
{
|
|
@@ -1811,8 +1817,8 @@ function validateBossChatStartArgs(args) {
|
|
|
1811
1817
|
}
|
|
1812
1818
|
}
|
|
1813
1819
|
if (Object.prototype.hasOwnProperty.call(args, "criteria")) {
|
|
1814
|
-
if (typeof args.criteria !== "string"
|
|
1815
|
-
return "criteria must be a
|
|
1820
|
+
if (typeof args.criteria !== "string") {
|
|
1821
|
+
return "criteria must be a string when provided";
|
|
1816
1822
|
}
|
|
1817
1823
|
}
|
|
1818
1824
|
if (
|
package/src/recommend-mcp.js
CHANGED
|
@@ -102,7 +102,71 @@ function findRouteSignals(text, patterns = []) {
|
|
|
102
102
|
return signals;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
function detectExplicitNonRecommendScope(args = {}) {
|
|
106
|
+
const fields = [
|
|
107
|
+
["page_scope", args.page_scope],
|
|
108
|
+
["confirmation.page_value", args.confirmation?.page_value],
|
|
109
|
+
["overrides.page_scope", args.overrides?.page_scope],
|
|
110
|
+
["target_url_includes", args.target_url_includes],
|
|
111
|
+
["overrides.target_url_includes", args.overrides?.target_url_includes]
|
|
112
|
+
];
|
|
113
|
+
for (const [field, value] of fields) {
|
|
114
|
+
const normalized = normalizeText(value).toLowerCase();
|
|
115
|
+
if (!normalized) continue;
|
|
116
|
+
if (/\/web\/chat\/index|chat\/index/.test(normalized) || ["chat", "chat-page", "boss-chat"].includes(normalized)) {
|
|
117
|
+
return {
|
|
118
|
+
domain: "chat",
|
|
119
|
+
signals: [`${field}:chat`],
|
|
120
|
+
text: normalized
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (/\/web\/chat\/search|chat\/search/.test(normalized) || ["search", "search-page", "recruit", "recruit-page", "boss-recruit"].includes(normalized)) {
|
|
124
|
+
return {
|
|
125
|
+
domain: "search",
|
|
126
|
+
signals: [`${field}:search`],
|
|
127
|
+
text: normalized
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function detectRecruitShapedRecommendArgs(args = {}) {
|
|
135
|
+
const checks = [
|
|
136
|
+
["keyword", args.keyword],
|
|
137
|
+
["search_keyword", args.search_keyword],
|
|
138
|
+
["city", args.city],
|
|
139
|
+
["confirmation.keyword_value", args.confirmation?.keyword_value],
|
|
140
|
+
["confirmation.keyword_confirmed", args.confirmation?.keyword_confirmed],
|
|
141
|
+
["confirmation.search_params_confirmed", args.confirmation?.search_params_confirmed],
|
|
142
|
+
["overrides.keyword", args.overrides?.keyword],
|
|
143
|
+
["overrides.search_keyword", args.overrides?.search_keyword],
|
|
144
|
+
["overrides.city", args.overrides?.city],
|
|
145
|
+
["overrides.filter_recent_viewed", args.overrides?.filter_recent_viewed],
|
|
146
|
+
["overrides.schools", args.overrides?.schools],
|
|
147
|
+
["overrides.school_tags", args.overrides?.school_tags]
|
|
148
|
+
];
|
|
149
|
+
const signals = [];
|
|
150
|
+
for (const [field, value] of checks) {
|
|
151
|
+
if (value === undefined || value === null) continue;
|
|
152
|
+
if (Array.isArray(value) && value.length === 0) continue;
|
|
153
|
+
if (typeof value === "string" && !normalizeText(value)) continue;
|
|
154
|
+
signals.push(field);
|
|
155
|
+
}
|
|
156
|
+
if (!signals.length) return null;
|
|
157
|
+
return {
|
|
158
|
+
domain: "search",
|
|
159
|
+
signals: signals.map((field) => `${field}:recruit_arg`),
|
|
160
|
+
text: signals.join(" ")
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
105
164
|
function detectNonRecommendRoute(args = {}) {
|
|
165
|
+
const explicitRoute = detectExplicitNonRecommendScope(args);
|
|
166
|
+
if (explicitRoute) return explicitRoute;
|
|
167
|
+
const recruitArgRoute = detectRecruitShapedRecommendArgs(args);
|
|
168
|
+
if (recruitArgRoute) return recruitArgRoute;
|
|
169
|
+
|
|
106
170
|
const text = collectRecommendRouteText(args);
|
|
107
171
|
if (!text) return null;
|
|
108
172
|
const chatSignals = findRouteSignals(text, [
|
|
@@ -126,6 +190,7 @@ function detectNonRecommendRoute(args = {}) {
|
|
|
126
190
|
const searchSignals = findRouteSignals(text, [
|
|
127
191
|
{ label: "search-only", pattern: /\bsearch[-\s]?only\b/i },
|
|
128
192
|
{ label: "search page", pattern: /\bsearch\s+page\b/i },
|
|
193
|
+
{ label: "search keyword", pattern: /搜索关键词|关键词|keyword/i },
|
|
129
194
|
{ label: "recruit pipeline", pattern: /\brecruit\s+pipeline\b/i },
|
|
130
195
|
{ label: "chat/search", pattern: /(?:\/web\/chat\/search|chat\/search)/i },
|
|
131
196
|
{ label: "搜索页", pattern: /搜索页/ },
|
|
@@ -148,16 +213,18 @@ function buildWrongRecommendRouteResponse(route) {
|
|
|
148
213
|
route_guard: true,
|
|
149
214
|
error: {
|
|
150
215
|
code: "WRONG_BOSS_TOOL_FOR_CHAT",
|
|
151
|
-
message: "This request is explicitly chat-only/chat-page work.
|
|
216
|
+
message: "This request is explicitly chat-only/chat-page work. In Trae-CN split toolsets, call boss-chat/boss_chat_health_check, then boss-chat/list_boss_chat_jobs or boss-chat/prepare_boss_chat_run, then boss-chat/start_boss_chat_run. Do not call boss-recommend tools.",
|
|
152
217
|
retryable: false
|
|
153
218
|
},
|
|
154
219
|
detected_domain: "chat",
|
|
155
220
|
detected_signals: route.signals || [],
|
|
221
|
+
wrong_server: "boss-recommend",
|
|
222
|
+
recommended_server: "boss-chat",
|
|
156
223
|
recommended_tool_sequence: [
|
|
157
|
-
"boss_chat_health_check",
|
|
158
|
-
"list_boss_chat_jobs",
|
|
159
|
-
"prepare_boss_chat_run",
|
|
160
|
-
"start_boss_chat_run"
|
|
224
|
+
"boss-chat/boss_chat_health_check",
|
|
225
|
+
"boss-chat/list_boss_chat_jobs",
|
|
226
|
+
"boss-chat/prepare_boss_chat_run",
|
|
227
|
+
"boss-chat/start_boss_chat_run"
|
|
161
228
|
]
|
|
162
229
|
};
|
|
163
230
|
}
|
|
@@ -167,14 +234,16 @@ function buildWrongRecommendRouteResponse(route) {
|
|
|
167
234
|
route_guard: true,
|
|
168
235
|
error: {
|
|
169
236
|
code: "WRONG_BOSS_TOOL_FOR_SEARCH",
|
|
170
|
-
message: "This request is explicitly search/recruit-page work.
|
|
237
|
+
message: "This request is explicitly search/recruit-page work. In Trae-CN split toolsets, call boss-recruit/run_recruit_pipeline or boss-recruit/start_recruit_pipeline_run. Do not call boss-recommend/run_recommend or boss-recommend/start_recommend_pipeline_run.",
|
|
171
238
|
retryable: false
|
|
172
239
|
},
|
|
173
240
|
detected_domain: "search",
|
|
174
241
|
detected_signals: route.signals || [],
|
|
242
|
+
wrong_server: "boss-recommend",
|
|
243
|
+
recommended_server: "boss-recruit",
|
|
175
244
|
recommended_tool_sequence: [
|
|
176
|
-
"run_recruit_pipeline",
|
|
177
|
-
"start_recruit_pipeline_run"
|
|
245
|
+
"boss-recruit/run_recruit_pipeline",
|
|
246
|
+
"boss-recruit/start_recruit_pipeline_run"
|
|
178
247
|
]
|
|
179
248
|
};
|
|
180
249
|
}
|
package/src/recruit-mcp.js
CHANGED
|
@@ -697,11 +697,25 @@ export function createRecruitPipelineInputSchema() {
|
|
|
697
697
|
},
|
|
698
698
|
confirmation: {
|
|
699
699
|
type: "object",
|
|
700
|
+
description: "搜索页确认状态。新流程建议在用户看过总览后传 final_confirmed=true;逐字段 *_confirmed 为兼容旧调用保留。",
|
|
700
701
|
properties: {
|
|
702
|
+
final_confirmed: {
|
|
703
|
+
type: "boolean",
|
|
704
|
+
description: "用户已确认包含岗位、关键词、城市、学历/院校、是否过滤已看、criteria、目标人数、动作和 restLevel 的总览。"
|
|
705
|
+
},
|
|
706
|
+
job_confirmed: { type: "boolean" },
|
|
707
|
+
job_value: { type: "string" },
|
|
701
708
|
keyword_confirmed: { type: "boolean" },
|
|
702
709
|
keyword_value: { type: "string" },
|
|
703
710
|
search_params_confirmed: { type: "boolean" },
|
|
704
711
|
criteria_confirmed: { type: "boolean" },
|
|
712
|
+
criteria_value: { type: "string" },
|
|
713
|
+
post_action_confirmed: { type: "boolean" },
|
|
714
|
+
post_action_value: {
|
|
715
|
+
type: "string",
|
|
716
|
+
enum: ["greet", "none"]
|
|
717
|
+
},
|
|
718
|
+
max_greet_count_value: { type: "integer", minimum: 1 },
|
|
705
719
|
use_default_for_missing: { type: "boolean" }
|
|
706
720
|
},
|
|
707
721
|
additionalProperties: false
|
|
@@ -709,18 +723,188 @@ export function createRecruitPipelineInputSchema() {
|
|
|
709
723
|
overrides: {
|
|
710
724
|
type: "object",
|
|
711
725
|
properties: {
|
|
726
|
+
job: { type: "string" },
|
|
727
|
+
job_title: { type: "string" },
|
|
728
|
+
selected_job: { type: "string" },
|
|
712
729
|
city: { type: "string" },
|
|
713
|
-
degree: {
|
|
730
|
+
degree: {
|
|
731
|
+
anyOf: [
|
|
732
|
+
{ type: "string" },
|
|
733
|
+
{ type: "array", items: { type: "string" }, minItems: 1 }
|
|
734
|
+
]
|
|
735
|
+
},
|
|
736
|
+
degrees: {
|
|
737
|
+
anyOf: [
|
|
738
|
+
{ type: "string" },
|
|
739
|
+
{ type: "array", items: { type: "string" }, minItems: 1 }
|
|
740
|
+
]
|
|
741
|
+
},
|
|
714
742
|
filter_recent_viewed: { type: "boolean" },
|
|
743
|
+
recent_not_view: {
|
|
744
|
+
anyOf: [
|
|
745
|
+
{ type: "boolean" },
|
|
746
|
+
{ type: "string" }
|
|
747
|
+
]
|
|
748
|
+
},
|
|
715
749
|
schools: {
|
|
716
750
|
anyOf: [
|
|
717
751
|
{ type: "array", items: { type: "string" } },
|
|
718
752
|
{ type: "string" }
|
|
719
753
|
]
|
|
720
754
|
},
|
|
755
|
+
school_tag: {
|
|
756
|
+
anyOf: [
|
|
757
|
+
{ type: "array", items: { type: "string" } },
|
|
758
|
+
{ type: "string" }
|
|
759
|
+
]
|
|
760
|
+
},
|
|
761
|
+
school_tags: {
|
|
762
|
+
anyOf: [
|
|
763
|
+
{ type: "array", items: { type: "string" } },
|
|
764
|
+
{ type: "string" }
|
|
765
|
+
]
|
|
766
|
+
},
|
|
767
|
+
experience: {
|
|
768
|
+
anyOf: [
|
|
769
|
+
{ type: "string" },
|
|
770
|
+
{
|
|
771
|
+
type: "object",
|
|
772
|
+
properties: {
|
|
773
|
+
mode: { type: "string" },
|
|
774
|
+
label: { type: "string" },
|
|
775
|
+
option: { type: "string" },
|
|
776
|
+
start: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
777
|
+
end: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
778
|
+
min: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
779
|
+
max: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
780
|
+
from: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
781
|
+
to: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
782
|
+
start_value: { type: "integer" },
|
|
783
|
+
end_value: { type: "integer" }
|
|
784
|
+
},
|
|
785
|
+
additionalProperties: false
|
|
786
|
+
}
|
|
787
|
+
]
|
|
788
|
+
},
|
|
789
|
+
experiences: {
|
|
790
|
+
anyOf: [
|
|
791
|
+
{ type: "array", items: { type: "string" } },
|
|
792
|
+
{ type: "string" }
|
|
793
|
+
]
|
|
794
|
+
},
|
|
795
|
+
experience_range: {
|
|
796
|
+
anyOf: [
|
|
797
|
+
{ type: "string" },
|
|
798
|
+
{
|
|
799
|
+
type: "object",
|
|
800
|
+
properties: {
|
|
801
|
+
mode: { type: "string" },
|
|
802
|
+
label: { type: "string" },
|
|
803
|
+
option: { type: "string" },
|
|
804
|
+
start: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
805
|
+
end: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
806
|
+
min: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
807
|
+
max: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
808
|
+
from: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
809
|
+
to: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
810
|
+
start_value: { type: "integer" },
|
|
811
|
+
end_value: { type: "integer" }
|
|
812
|
+
},
|
|
813
|
+
additionalProperties: false
|
|
814
|
+
}
|
|
815
|
+
]
|
|
816
|
+
},
|
|
817
|
+
experience_start: {
|
|
818
|
+
anyOf: [
|
|
819
|
+
{ type: "string" },
|
|
820
|
+
{ type: "integer" }
|
|
821
|
+
]
|
|
822
|
+
},
|
|
823
|
+
experience_end: {
|
|
824
|
+
anyOf: [
|
|
825
|
+
{ type: "string" },
|
|
826
|
+
{ type: "integer" }
|
|
827
|
+
]
|
|
828
|
+
},
|
|
829
|
+
gender: { type: "string" },
|
|
830
|
+
age: {
|
|
831
|
+
anyOf: [
|
|
832
|
+
{ type: "string" },
|
|
833
|
+
{
|
|
834
|
+
type: "object",
|
|
835
|
+
properties: {
|
|
836
|
+
mode: { type: "string" },
|
|
837
|
+
label: { type: "string" },
|
|
838
|
+
option: { type: "string" },
|
|
839
|
+
min: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
840
|
+
max: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
841
|
+
start: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
842
|
+
end: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
843
|
+
from: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
844
|
+
to: { anyOf: [{ type: "string" }, { type: "integer" }] }
|
|
845
|
+
},
|
|
846
|
+
additionalProperties: false
|
|
847
|
+
}
|
|
848
|
+
]
|
|
849
|
+
},
|
|
850
|
+
ages: {
|
|
851
|
+
anyOf: [
|
|
852
|
+
{ type: "array", items: { type: "string" } },
|
|
853
|
+
{ type: "string" }
|
|
854
|
+
]
|
|
855
|
+
},
|
|
856
|
+
age_range: {
|
|
857
|
+
anyOf: [
|
|
858
|
+
{ type: "string" },
|
|
859
|
+
{
|
|
860
|
+
type: "object",
|
|
861
|
+
properties: {
|
|
862
|
+
mode: { type: "string" },
|
|
863
|
+
label: { type: "string" },
|
|
864
|
+
option: { type: "string" },
|
|
865
|
+
min: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
866
|
+
max: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
867
|
+
start: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
868
|
+
end: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
869
|
+
from: { anyOf: [{ type: "string" }, { type: "integer" }] },
|
|
870
|
+
to: { anyOf: [{ type: "string" }, { type: "integer" }] }
|
|
871
|
+
},
|
|
872
|
+
additionalProperties: false
|
|
873
|
+
}
|
|
874
|
+
]
|
|
875
|
+
},
|
|
876
|
+
age_min: {
|
|
877
|
+
anyOf: [
|
|
878
|
+
{ type: "string" },
|
|
879
|
+
{ type: "integer" }
|
|
880
|
+
]
|
|
881
|
+
},
|
|
882
|
+
age_max: {
|
|
883
|
+
anyOf: [
|
|
884
|
+
{ type: "string" },
|
|
885
|
+
{ type: "integer" }
|
|
886
|
+
]
|
|
887
|
+
},
|
|
888
|
+
min_age: {
|
|
889
|
+
anyOf: [
|
|
890
|
+
{ type: "string" },
|
|
891
|
+
{ type: "integer" }
|
|
892
|
+
]
|
|
893
|
+
},
|
|
894
|
+
max_age: {
|
|
895
|
+
anyOf: [
|
|
896
|
+
{ type: "string" },
|
|
897
|
+
{ type: "integer" }
|
|
898
|
+
]
|
|
899
|
+
},
|
|
721
900
|
keyword: { type: "string" },
|
|
722
901
|
target_count: { type: "integer", minimum: 1 },
|
|
723
|
-
criteria: { type: "string" }
|
|
902
|
+
criteria: { type: "string" },
|
|
903
|
+
post_action: {
|
|
904
|
+
type: "string",
|
|
905
|
+
enum: ["greet", "none"]
|
|
906
|
+
},
|
|
907
|
+
max_greet_count: { type: "integer", minimum: 1 }
|
|
724
908
|
},
|
|
725
909
|
additionalProperties: false
|
|
726
910
|
},
|
|
@@ -805,6 +989,29 @@ export function createRecruitPipelineInputSchema() {
|
|
|
805
989
|
type: "integer",
|
|
806
990
|
minimum: 0,
|
|
807
991
|
description: "候选人之间的延迟;live pause/resume 测试可增大它"
|
|
992
|
+
},
|
|
993
|
+
execute_post_action: {
|
|
994
|
+
type: "boolean",
|
|
995
|
+
description: "可选,是否实际执行通过后的 search 后置动作 greet;默认 true"
|
|
996
|
+
},
|
|
997
|
+
dry_run_post_action: {
|
|
998
|
+
type: "boolean",
|
|
999
|
+
description: "可选,只验证 search 打招呼动作发现/配额/可点击路径,不实际点击"
|
|
1000
|
+
},
|
|
1001
|
+
action_timeout_ms: {
|
|
1002
|
+
type: "integer",
|
|
1003
|
+
minimum: 1000,
|
|
1004
|
+
description: "可选,等待详情页 greet 控件出现的超时时间"
|
|
1005
|
+
},
|
|
1006
|
+
action_interval_ms: {
|
|
1007
|
+
type: "integer",
|
|
1008
|
+
minimum: 100,
|
|
1009
|
+
description: "可选,轮询详情页 greet 控件的间隔"
|
|
1010
|
+
},
|
|
1011
|
+
action_after_click_delay_ms: {
|
|
1012
|
+
type: "integer",
|
|
1013
|
+
minimum: 0,
|
|
1014
|
+
description: "可选,点击 greet 后等待页面状态稳定的时间"
|
|
808
1015
|
}
|
|
809
1016
|
},
|
|
810
1017
|
required: ["instruction"],
|
|
@@ -1183,6 +1390,9 @@ function getRunOptions(args, parsed, session, configResolution = null) {
|
|
|
1183
1390
|
const targetCount = parsePositiveInteger(args.max_candidates, parsed.screenParams.target_count || 10);
|
|
1184
1391
|
const screeningMode = normalizeScreeningModeArg(args);
|
|
1185
1392
|
const humanBehavior = resolveHumanBehaviorForRun(args, configResolution?.config || {});
|
|
1393
|
+
const executePostAction = args.dry_run_post_action === true
|
|
1394
|
+
? false
|
|
1395
|
+
: args.execute_post_action !== false;
|
|
1186
1396
|
return {
|
|
1187
1397
|
client: session.client,
|
|
1188
1398
|
targetUrl: RECRUIT_TARGET_URL,
|
|
@@ -1215,6 +1425,14 @@ function getRunOptions(args, parsed, session, configResolution = null) {
|
|
|
1215
1425
|
imageOutputDir: resolveBossConfiguredOutputDir("", getRecruitRunsDir()),
|
|
1216
1426
|
humanRestEnabled: humanBehavior.restEnabled,
|
|
1217
1427
|
humanBehavior,
|
|
1428
|
+
postAction: parsed.screenParams?.post_action || "none",
|
|
1429
|
+
maxGreetCount: Number.isInteger(parsed.screenParams?.max_greet_count)
|
|
1430
|
+
? parsed.screenParams.max_greet_count
|
|
1431
|
+
: null,
|
|
1432
|
+
executePostAction,
|
|
1433
|
+
actionTimeoutMs: parsePositiveInteger(args.action_timeout_ms, slowLive ? 12000 : 8000),
|
|
1434
|
+
actionIntervalMs: parsePositiveInteger(args.action_interval_ms, 400),
|
|
1435
|
+
actionAfterClickDelayMs: parseNonNegativeInteger(args.action_after_click_delay_ms, 900),
|
|
1218
1436
|
name: "mcp-recruit-pipeline-run"
|
|
1219
1437
|
};
|
|
1220
1438
|
}
|
|
@@ -1364,7 +1582,14 @@ async function startRecruitPipelineRunInternal(args = {}, { workspaceRoot = "",
|
|
|
1364
1582
|
run: persistedStarted,
|
|
1365
1583
|
poll_after_sec: DEFAULT_RECRUIT_POLL_AFTER_SEC,
|
|
1366
1584
|
review: parsed.review,
|
|
1367
|
-
message:
|
|
1585
|
+
message: parsed.screenParams?.post_action === "greet"
|
|
1586
|
+
? `Recruit pipeline run started through shared CDP-only recruit service with post_action=greet${args.dry_run_post_action === true ? " in dry-run mode" : ""}.`
|
|
1587
|
+
: "Recruit pipeline run started through shared CDP-only recruit service.",
|
|
1588
|
+
post_action: {
|
|
1589
|
+
requested: parsed.screenParams?.post_action || "none",
|
|
1590
|
+
execute_post_action: args.dry_run_post_action === true ? false : args.execute_post_action !== false,
|
|
1591
|
+
max_greet_count: Number.isInteger(parsed.screenParams?.max_greet_count) ? parsed.screenParams.max_greet_count : null
|
|
1592
|
+
}
|
|
1368
1593
|
};
|
|
1369
1594
|
}
|
|
1370
1595
|
|