@reconcrap/boss-recommend-mcp 1.1.2 → 1.1.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/package.json +1 -1
- package/src/index.js +2 -2
- package/src/parser.js +19 -28
- package/src/pipeline.js +8 -6
- package/src/test-parser.js +55 -0
- package/vendor/boss-recommend-screen-cli/boss-recommend-screen-cli.cjs +11 -4
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -203,7 +203,7 @@ function createRunInputSchema() {
|
|
|
203
203
|
post_action_confirmed: { type: "boolean" },
|
|
204
204
|
post_action_value: {
|
|
205
205
|
type: "string",
|
|
206
|
-
enum: ["favorite", "greet"]
|
|
206
|
+
enum: ["favorite", "greet", "none"]
|
|
207
207
|
},
|
|
208
208
|
final_confirmed: { type: "boolean" },
|
|
209
209
|
job_confirmed: { type: "boolean" },
|
|
@@ -267,7 +267,7 @@ function createRunInputSchema() {
|
|
|
267
267
|
max_greet_count: { type: "integer", minimum: 1 },
|
|
268
268
|
post_action: {
|
|
269
269
|
type: "string",
|
|
270
|
-
enum: ["favorite", "greet"]
|
|
270
|
+
enum: ["favorite", "greet", "none"]
|
|
271
271
|
}
|
|
272
272
|
},
|
|
273
273
|
additionalProperties: false
|
package/src/parser.js
CHANGED
|
@@ -28,10 +28,11 @@ const DEGREE_ORDER = [
|
|
|
28
28
|
];
|
|
29
29
|
const GENDER_OPTIONS = ["不限", "男", "女"];
|
|
30
30
|
const RECENT_NOT_VIEW_OPTIONS = ["不限", "近14天没有"];
|
|
31
|
-
const POST_ACTION_OPTIONS = ["favorite", "greet"];
|
|
31
|
+
const POST_ACTION_OPTIONS = ["favorite", "greet", "none"];
|
|
32
32
|
const POST_ACTION_LABELS = {
|
|
33
33
|
favorite: "收藏",
|
|
34
|
-
greet: "直接沟通"
|
|
34
|
+
greet: "直接沟通",
|
|
35
|
+
none: "什么也不做"
|
|
35
36
|
};
|
|
36
37
|
const LEADING_NOISE_PATTERNS = [
|
|
37
38
|
/^使用boss-recommend-pipeline skills/i,
|
|
@@ -90,7 +91,7 @@ const FILTER_CLAUSE_PATTERNS = [
|
|
|
90
91
|
/近?14天(?:内)?没有|近?14天(?:内)?没看过|近?14天(?:内)?未查看|过滤[^。;;\n]{0,12}14天|排除[^。;;\n]{0,12}14天/i,
|
|
91
92
|
/目标(?:处理|筛选)?(?:人数|数量)?|至少(?:处理|筛选)|(?:处理|筛选)\s*\d+\s*(?:位|人)/i,
|
|
92
93
|
/最多(?:打招呼|沟通|联系)|(?:打招呼|沟通|联系)(?:上限|最多|不超过|至多)/i,
|
|
93
|
-
|
|
94
|
+
/收藏|打招呼|直接沟通|什么也不做|不做任何操作|不操作|仅筛选|只筛选/i
|
|
94
95
|
];
|
|
95
96
|
const META_CLAUSE_PATTERNS = [
|
|
96
97
|
/推荐页|推荐页面|boss推荐/i,
|
|
@@ -259,6 +260,9 @@ function normalizePostAction(value) {
|
|
|
259
260
|
if (!normalized) return null;
|
|
260
261
|
if (["favorite", "fav", "收藏"].includes(normalized)) return "favorite";
|
|
261
262
|
if (["greet", "chat", "打招呼", "直接沟通", "沟通"].includes(normalized)) return "greet";
|
|
263
|
+
if (["none", "noop", "no-op", "什么也不做", "不做任何操作", "不操作", "仅筛选", "只筛选"].includes(normalized)) {
|
|
264
|
+
return "none";
|
|
265
|
+
}
|
|
262
266
|
return null;
|
|
263
267
|
}
|
|
264
268
|
|
|
@@ -377,6 +381,8 @@ function resolvePostAction({ instruction, confirmation, overrides }) {
|
|
|
377
381
|
? "favorite"
|
|
378
382
|
: /打招呼|直接沟通|沟通/.test(instruction)
|
|
379
383
|
? "greet"
|
|
384
|
+
: /什么也不做|不做任何操作|不操作|仅筛选|只筛选/.test(instruction)
|
|
385
|
+
? "none"
|
|
380
386
|
: null;
|
|
381
387
|
const proposed = overrideValue || confirmationValue || instructionValue || null;
|
|
382
388
|
|
|
@@ -534,41 +540,25 @@ export function parseRecommendInstruction({ instruction, confirmation, overrides
|
|
|
534
540
|
invalidOverrideSchoolTags: schoolTagAudit.invalid,
|
|
535
541
|
maxGreetCountResolution
|
|
536
542
|
});
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
);
|
|
542
|
-
const hasDegreeSignal = Boolean(
|
|
543
|
-
(Array.isArray(overrideDegrees) && overrideDegrees.length > 0)
|
|
544
|
-
|| (Array.isArray(confirmationDegrees) && confirmationDegrees.length > 0)
|
|
545
|
-
|| (Array.isArray(detectedDegrees) && detectedDegrees.length > 0)
|
|
546
|
-
);
|
|
547
|
-
const hasGenderSignal = Boolean(
|
|
548
|
-
overrideGender
|
|
549
|
-
|| confirmationGender
|
|
550
|
-
|| extractGender(text)
|
|
551
|
-
);
|
|
552
|
-
const hasRecentNotViewSignal = Boolean(
|
|
553
|
-
overrideRecentNotView
|
|
554
|
-
|| confirmationRecentNotView
|
|
555
|
-
|| extractRecentNotView(text)
|
|
556
|
-
);
|
|
543
|
+
const hasConfirmedSchoolTagValue = Array.isArray(confirmationSchoolTag) && confirmationSchoolTag.length > 0;
|
|
544
|
+
const hasConfirmedDegreeValue = Array.isArray(confirmationDegrees) && confirmationDegrees.length > 0;
|
|
545
|
+
const hasConfirmedGenderValue = Boolean(confirmationGender);
|
|
546
|
+
const hasConfirmedRecentNotViewValue = Boolean(confirmationRecentNotView);
|
|
557
547
|
const needs_school_tag_confirmation = (
|
|
558
548
|
confirmation?.school_tag_confirmed !== true
|
|
559
|
-
|| !
|
|
549
|
+
|| !hasConfirmedSchoolTagValue
|
|
560
550
|
);
|
|
561
551
|
const needs_degree_confirmation = (
|
|
562
552
|
confirmation?.degree_confirmed !== true
|
|
563
|
-
|| !
|
|
553
|
+
|| !hasConfirmedDegreeValue
|
|
564
554
|
);
|
|
565
555
|
const needs_gender_confirmation = (
|
|
566
556
|
confirmation?.gender_confirmed !== true
|
|
567
|
-
|| !
|
|
557
|
+
|| !hasConfirmedGenderValue
|
|
568
558
|
);
|
|
569
559
|
const needs_recent_not_view_confirmation = (
|
|
570
560
|
confirmation?.recent_not_view_confirmed !== true
|
|
571
|
-
|| !
|
|
561
|
+
|| !hasConfirmedRecentNotViewValue
|
|
572
562
|
);
|
|
573
563
|
const needs_filters_confirmation = (
|
|
574
564
|
confirmation?.filters_confirmed !== true
|
|
@@ -659,7 +649,8 @@ export function parseRecommendInstruction({ instruction, confirmation, overrides
|
|
|
659
649
|
value: postActionResolution.proposed_post_action,
|
|
660
650
|
options: [
|
|
661
651
|
{ label: POST_ACTION_LABELS.favorite, value: "favorite" },
|
|
662
|
-
{ label: POST_ACTION_LABELS.greet, value: "greet" }
|
|
652
|
+
{ label: POST_ACTION_LABELS.greet, value: "greet" },
|
|
653
|
+
{ label: POST_ACTION_LABELS.none, value: "none" }
|
|
663
654
|
]
|
|
664
655
|
});
|
|
665
656
|
}
|
package/src/pipeline.js
CHANGED
|
@@ -959,7 +959,7 @@ export async function runRecommendPipeline(
|
|
|
959
959
|
});
|
|
960
960
|
|
|
961
961
|
return {
|
|
962
|
-
status: "COMPLETED",
|
|
962
|
+
status: "COMPLETED",
|
|
963
963
|
search_params: parsed.searchParams,
|
|
964
964
|
screen_params: parsed.screenParams,
|
|
965
965
|
result: {
|
|
@@ -976,8 +976,10 @@ export async function runRecommendPipeline(
|
|
|
976
976
|
post_action: parsed.screenParams.post_action,
|
|
977
977
|
max_greet_count: parsed.screenParams.max_greet_count,
|
|
978
978
|
greet_count: screenSummary.greet_count ?? 0,
|
|
979
|
-
greet_limit_fallback_count: screenSummary.greet_limit_fallback_count ?? 0
|
|
980
|
-
},
|
|
981
|
-
message:
|
|
982
|
-
|
|
983
|
-
|
|
979
|
+
greet_limit_fallback_count: screenSummary.greet_limit_fallback_count ?? 0
|
|
980
|
+
},
|
|
981
|
+
message: parsed.screenParams.post_action === "none"
|
|
982
|
+
? "Recommend 流水线已完成。本次 post_action=none:符合条件的人选仅记录到 CSV,不执行收藏或打招呼。"
|
|
983
|
+
: "Recommend 流水线已完成。post_action 在运行开始时已一次性确认;若选择打招呼并设置上限,超出上限后会自动改为收藏。"
|
|
984
|
+
};
|
|
985
|
+
}
|
package/src/test-parser.js
CHANGED
|
@@ -29,9 +29,13 @@ function testConfirmedPostActionAndOverrides() {
|
|
|
29
29
|
confirmation: {
|
|
30
30
|
filters_confirmed: true,
|
|
31
31
|
school_tag_confirmed: true,
|
|
32
|
+
school_tag_value: ["211"],
|
|
32
33
|
degree_confirmed: true,
|
|
34
|
+
degree_value: ["本科"],
|
|
33
35
|
gender_confirmed: true,
|
|
36
|
+
gender_value: "女",
|
|
34
37
|
recent_not_view_confirmed: true,
|
|
38
|
+
recent_not_view_value: "近14天没有",
|
|
35
39
|
criteria_confirmed: true,
|
|
36
40
|
target_count_confirmed: true,
|
|
37
41
|
target_count_value: 12,
|
|
@@ -67,6 +71,30 @@ function testConfirmedPostActionAndOverrides() {
|
|
|
67
71
|
assert.equal(result.needs_max_greet_count_confirmation, false);
|
|
68
72
|
}
|
|
69
73
|
|
|
74
|
+
function testMissingRecentNotViewValueShouldRequireReconfirmation() {
|
|
75
|
+
const result = parseRecommendInstruction({
|
|
76
|
+
instruction: "推荐页筛选985男生,近14天没有,有销售经验,符合标准收藏",
|
|
77
|
+
confirmation: {
|
|
78
|
+
filters_confirmed: true,
|
|
79
|
+
school_tag_confirmed: true,
|
|
80
|
+
school_tag_value: ["985"],
|
|
81
|
+
degree_confirmed: true,
|
|
82
|
+
degree_value: ["本科"],
|
|
83
|
+
gender_confirmed: true,
|
|
84
|
+
gender_value: "男",
|
|
85
|
+
recent_not_view_confirmed: true,
|
|
86
|
+
criteria_confirmed: true,
|
|
87
|
+
target_count_confirmed: true,
|
|
88
|
+
post_action_confirmed: true,
|
|
89
|
+
post_action_value: "favorite"
|
|
90
|
+
},
|
|
91
|
+
overrides: null
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
assert.equal(result.needs_recent_not_view_confirmation, true);
|
|
95
|
+
assert.equal(result.pending_questions.some((q) => q.field === "recent_not_view"), true);
|
|
96
|
+
}
|
|
97
|
+
|
|
70
98
|
function testFilterConfirmedWithoutExplicitValuesShouldRequireReconfirmation() {
|
|
71
99
|
const result = parseRecommendInstruction({
|
|
72
100
|
instruction: "通过boss推荐skill帮我找人",
|
|
@@ -401,6 +429,31 @@ function testTargetCountCanBeSkippedAfterConfirmation() {
|
|
|
401
429
|
assert.equal(result.screenParams.target_count, null);
|
|
402
430
|
}
|
|
403
431
|
|
|
432
|
+
function testPostActionNoneCanBeConfirmed() {
|
|
433
|
+
const result = parseRecommendInstruction({
|
|
434
|
+
instruction: "推荐页筛选211女生,近14天没有,有AI经验,符合标准什么也不做",
|
|
435
|
+
confirmation: {
|
|
436
|
+
filters_confirmed: true,
|
|
437
|
+
school_tag_confirmed: true,
|
|
438
|
+
school_tag_value: ["211"],
|
|
439
|
+
degree_confirmed: true,
|
|
440
|
+
degree_value: ["本科"],
|
|
441
|
+
gender_confirmed: true,
|
|
442
|
+
gender_value: "女",
|
|
443
|
+
recent_not_view_confirmed: true,
|
|
444
|
+
recent_not_view_value: "近14天没有",
|
|
445
|
+
criteria_confirmed: true,
|
|
446
|
+
target_count_confirmed: true,
|
|
447
|
+
post_action_confirmed: true,
|
|
448
|
+
post_action_value: "none"
|
|
449
|
+
},
|
|
450
|
+
overrides: null
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
assert.equal(result.screenParams.post_action, "none");
|
|
454
|
+
assert.equal(result.needs_post_action_confirmation, false);
|
|
455
|
+
}
|
|
456
|
+
|
|
404
457
|
function testJobSelectionHintCanComeFromOverrides() {
|
|
405
458
|
const result = parseRecommendInstruction({
|
|
406
459
|
instruction: "推荐页筛选211女生,有算法经验,符合标准收藏",
|
|
@@ -426,6 +479,7 @@ function testMcpMentionShouldStayInCriteria() {
|
|
|
426
479
|
function main() {
|
|
427
480
|
testNeedConfirmationIncludesPostAction();
|
|
428
481
|
testConfirmedPostActionAndOverrides();
|
|
482
|
+
testMissingRecentNotViewValueShouldRequireReconfirmation();
|
|
429
483
|
testFilterConfirmedWithoutExplicitValuesShouldRequireReconfirmation();
|
|
430
484
|
testFilterConfirmedWithExplicitConfirmationValuesShouldNotFallbackToUnlimited();
|
|
431
485
|
testMultipleSchoolTagsMarkedSuspicious();
|
|
@@ -445,6 +499,7 @@ function main() {
|
|
|
445
499
|
testGreetAutoFilledMaxGreetCountShouldRequireReconfirmation();
|
|
446
500
|
testTargetCountNeedsConfirmationEvenWhenOptional();
|
|
447
501
|
testTargetCountCanBeSkippedAfterConfirmation();
|
|
502
|
+
testPostActionNoneCanBeConfirmed();
|
|
448
503
|
testJobSelectionHintCanComeFromOverrides();
|
|
449
504
|
console.log("parser tests passed");
|
|
450
505
|
}
|
|
@@ -31,6 +31,9 @@ function normalizePostAction(value) {
|
|
|
31
31
|
if (!normalized) return null;
|
|
32
32
|
if (["favorite", "fav", "收藏"].includes(normalized)) return "favorite";
|
|
33
33
|
if (["greet", "chat", "打招呼", "直接沟通", "沟通"].includes(normalized)) return "greet";
|
|
34
|
+
if (["none", "noop", "no-op", "什么也不做", "不做任何操作", "不操作", "仅筛选", "只筛选"].includes(normalized)) {
|
|
35
|
+
return "none";
|
|
36
|
+
}
|
|
34
37
|
return null;
|
|
35
38
|
}
|
|
36
39
|
|
|
@@ -210,10 +213,11 @@ async function promptMissingInputs(args) {
|
|
|
210
213
|
if (!(args.postActionConfirmed === true && args.postAction)) {
|
|
211
214
|
args.postAction = await askWithValidation(
|
|
212
215
|
ask,
|
|
213
|
-
"本次通过人选统一执行什么动作?请输入 1(收藏)
|
|
216
|
+
"本次通过人选统一执行什么动作?请输入 1(收藏) / 2(直接沟通) / 3(什么也不做): ",
|
|
214
217
|
(value) => {
|
|
215
218
|
if (value === "1") return "favorite";
|
|
216
219
|
if (value === "2") return "greet";
|
|
220
|
+
if (value === "3") return "none";
|
|
217
221
|
return null;
|
|
218
222
|
}
|
|
219
223
|
);
|
|
@@ -289,9 +293,10 @@ async function promptPostAction() {
|
|
|
289
293
|
});
|
|
290
294
|
const ask = (question) => new Promise((resolve) => rl.question(question, resolve));
|
|
291
295
|
try {
|
|
292
|
-
const answer = normalizeText(await ask("本次通过人选统一执行什么动作?请输入 1(收藏)
|
|
296
|
+
const answer = normalizeText(await ask("本次通过人选统一执行什么动作?请输入 1(收藏) / 2(直接沟通) / 3(什么也不做): "));
|
|
293
297
|
if (answer === "1") return "favorite";
|
|
294
298
|
if (answer === "2") return "greet";
|
|
299
|
+
if (answer === "3") return "none";
|
|
295
300
|
throw new Error("INVALID_POST_ACTION_CONFIRMATION");
|
|
296
301
|
} finally {
|
|
297
302
|
rl.close();
|
|
@@ -1955,7 +1960,9 @@ class RecommendScreenCli {
|
|
|
1955
1960
|
}
|
|
1956
1961
|
const actionResult = effectiveAction === "favorite"
|
|
1957
1962
|
? await this.favoriteCandidate()
|
|
1958
|
-
:
|
|
1963
|
+
: effectiveAction === "greet"
|
|
1964
|
+
? await this.greetCandidate()
|
|
1965
|
+
: { actionTaken: "none" };
|
|
1959
1966
|
if (actionResult.actionTaken === "greet") {
|
|
1960
1967
|
this.greetCount += 1;
|
|
1961
1968
|
}
|
|
@@ -2050,7 +2057,7 @@ async function main() {
|
|
|
2050
2057
|
console.log(JSON.stringify({
|
|
2051
2058
|
status: "COMPLETED",
|
|
2052
2059
|
result: {
|
|
2053
|
-
usage: "node boss-recommend-screen-cli.cjs --criteria \"有 MCP 开发经验\" --post-action greet --max-greet-count 10 --post-action-confirmed true --baseurl <url> --apikey <key> --model <model> --port 9222 --output <csv-path> --checkpoint-path <checkpoint.json> --pause-control-path <pause-control.json> [--resume]"
|
|
2060
|
+
usage: "node boss-recommend-screen-cli.cjs --criteria \"有 MCP 开发经验\" --post-action <favorite|greet|none> --max-greet-count 10 --post-action-confirmed true --baseurl <url> --apikey <key> --model <model> --port 9222 --output <csv-path> --checkpoint-path <checkpoint.json> --pause-control-path <pause-control.json> [--resume]"
|
|
2054
2061
|
}
|
|
2055
2062
|
}));
|
|
2056
2063
|
return;
|