@reconcrap/boss-recommend-mcp 2.1.21 → 2.1.23
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 -2
- package/bin/boss-recommend-mcp.js +4 -4
- package/config/screening-config.example.json +33 -33
- package/package.json +2 -1
- package/scripts/install-macos.sh +280 -280
- package/scripts/postinstall.cjs +44 -44
- package/skills/boss-chat/README.md +42 -42
- package/skills/boss-chat/SKILL.md +106 -106
- package/skills/boss-recommend-pipeline/README.md +13 -13
- package/skills/boss-recommend-pipeline/SKILL.md +219 -214
- package/skills/boss-recruit-pipeline/README.md +19 -19
- package/skills/boss-recruit-pipeline/SKILL.md +89 -89
- package/src/chat-mcp.js +127 -127
- package/src/chat-runtime-config.js +775 -775
- package/src/cli.js +573 -573
- package/src/core/boss-cards/index.js +199 -199
- package/src/core/browser/index.js +2416 -2385
- package/src/core/capture/index.js +1201 -1201
- package/src/core/cv-acquisition/index.js +238 -238
- package/src/core/cv-capture-target/index.js +299 -299
- package/src/core/greet-quota/index.js +71 -71
- package/src/core/infinite-list/index.js +1315 -1306
- package/src/core/reporting/legacy-csv.js +334 -332
- package/src/core/run/index.js +44 -27
- package/src/core/run/timing.js +33 -33
- package/src/core/screening/index.js +2135 -2135
- package/src/core/self-heal/index.js +973 -973
- package/src/core/self-heal/viewport.js +564 -564
- package/src/detached-worker.js +99 -99
- package/src/domains/chat/cards.js +137 -137
- package/src/domains/chat/constants.js +9 -9
- package/src/domains/chat/detail.js +113 -113
- package/src/domains/chat/index.js +7 -7
- package/src/domains/chat/jobs.js +620 -620
- package/src/domains/chat/page-guard.js +122 -122
- package/src/domains/chat/roots.js +56 -56
- package/src/domains/chat/run-service.js +571 -571
- package/src/domains/common/account-rights-panel.js +314 -314
- package/src/domains/common/recovery-settle.js +159 -159
- package/src/domains/recommend/actions.js +472 -472
- package/src/domains/recommend/cards.js +243 -243
- package/src/domains/recommend/colleague-contact.js +333 -333
- package/src/domains/recommend/constants.js +228 -159
- package/src/domains/recommend/detail.js +655 -646
- package/src/domains/recommend/filters.js +748 -377
- package/src/domains/recommend/index.js +4 -3
- package/src/domains/recommend/jobs.js +542 -542
- package/src/domains/recommend/location.js +736 -0
- package/src/domains/recommend/refresh.js +575 -351
- package/src/domains/recommend/roots.js +80 -80
- package/src/domains/recommend/run-service.js +1616 -878
- package/src/domains/recommend/scopes.js +246 -246
- package/src/domains/recruit/actions.js +277 -277
- package/src/domains/recruit/cards.js +74 -74
- package/src/domains/recruit/constants.js +236 -236
- package/src/domains/recruit/detail.js +588 -588
- package/src/domains/recruit/index.js +9 -9
- package/src/domains/recruit/instruction-parser.js +866 -866
- package/src/domains/recruit/refresh.js +45 -45
- package/src/domains/recruit/roots.js +68 -68
- package/src/domains/recruit/run-service.js +1620 -1620
- package/src/domains/recruit/search.js +3229 -3229
- package/src/index.js +121 -4
- package/src/parser.js +376 -8
- package/src/recommend-mcp.js +1174 -914
- package/src/recommend-scheduler.js +535 -469
- package/src/recruit-mcp.js +2121 -2121
package/src/index.js
CHANGED
|
@@ -880,6 +880,14 @@ function createRunInputSchema() {
|
|
|
880
880
|
type: "string",
|
|
881
881
|
enum: ["不限", "近14天没有"]
|
|
882
882
|
},
|
|
883
|
+
current_city_only: {
|
|
884
|
+
type: "boolean",
|
|
885
|
+
description: "可选;true 表示仅推荐期望城市为当前已选城市的牛人,默认 false。不会切换城市。"
|
|
886
|
+
},
|
|
887
|
+
activity_level: {
|
|
888
|
+
type: "string",
|
|
889
|
+
description: "可选活跃度单选。标准选项:不限、刚刚活跃、今日活跃、3日内活跃、本周活跃、本月活跃。允许同义词、相对时间、英文和轻微错别字;系统会归一化为最靠近用户意图的标准选项,完全无法理解时默认 不限。"
|
|
890
|
+
},
|
|
883
891
|
skip_recent_colleague_contacted: {
|
|
884
892
|
type: "boolean",
|
|
885
893
|
description: "推荐页默认 true,用于跳过近14天同事沟通过的人选。搜索页请使用 recruit 工具的 filter_recent_colleague_contacted。"
|
|
@@ -987,6 +995,21 @@ function createRunInputSchema() {
|
|
|
987
995
|
type: "boolean",
|
|
988
996
|
description: "高级测试开关;默认 false。只有显式为 true 时才允许 deterministic/local scorer、跳过筛选器、card-only、dry-run 后置动作等调试路径"
|
|
989
997
|
},
|
|
998
|
+
debug_force_list_end_after_processed: {
|
|
999
|
+
type: "integer",
|
|
1000
|
+
minimum: 1,
|
|
1001
|
+
description: "仅限 debug_test_mode=true 的 live 诊断:在完成指定候选人数后的循环边界恰好一次模拟列表到底,并进入真实 Page.reload 刷新/筛选重放分支。与另外两个 debug_force_*_after_processed 参数互斥。"
|
|
1002
|
+
},
|
|
1003
|
+
debug_force_context_recovery_after_processed: {
|
|
1004
|
+
type: "integer",
|
|
1005
|
+
minimum: 1,
|
|
1006
|
+
description: "仅限 debug_test_mode=true 的 live 诊断:在完成指定候选人数后的循环边界恰好一次调用真实 recommend 上下文恢复与筛选重放。与另外两个 debug_force_*_after_processed 参数互斥。"
|
|
1007
|
+
},
|
|
1008
|
+
debug_force_cdp_reconnect_after_processed: {
|
|
1009
|
+
type: "integer",
|
|
1010
|
+
minimum: 1,
|
|
1011
|
+
description: "仅限 debug_test_mode=true 的 live 诊断:在完成指定候选人数后的循环边界恰好一次关闭当前原始 CDP 连接,随后依赖 guarded client 原生重连继续。不会执行页面脚本。与另外两个 debug_force_*_after_processed 参数互斥。"
|
|
1012
|
+
},
|
|
990
1013
|
screening_mode: {
|
|
991
1014
|
type: "string",
|
|
992
1015
|
enum: ["llm", "deterministic"],
|
|
@@ -1339,10 +1362,49 @@ function createListRecommendJobsInputSchema() {
|
|
|
1339
1362
|
|
|
1340
1363
|
function createScheduleRunInputSchema() {
|
|
1341
1364
|
const base = createRunInputSchema();
|
|
1365
|
+
const properties = { ...base.properties };
|
|
1366
|
+
for (const field of [
|
|
1367
|
+
"debug_test_mode",
|
|
1368
|
+
"debug_force_list_end_after_processed",
|
|
1369
|
+
"debug_force_context_recovery_after_processed",
|
|
1370
|
+
"debug_force_cdp_reconnect_after_processed"
|
|
1371
|
+
]) {
|
|
1372
|
+
delete properties[field];
|
|
1373
|
+
}
|
|
1374
|
+
properties.screening_mode = {
|
|
1375
|
+
...properties.screening_mode,
|
|
1376
|
+
enum: ["llm"],
|
|
1377
|
+
description: "定时 Recommend 仅允许生产 LLM 筛选;deterministic/local 调试模式不可定时。"
|
|
1378
|
+
};
|
|
1379
|
+
properties.use_llm = {
|
|
1380
|
+
...properties.use_llm,
|
|
1381
|
+
enum: [true],
|
|
1382
|
+
description: "定时 Recommend 仅允许 true;use_llm=false 属于调试模式。"
|
|
1383
|
+
};
|
|
1384
|
+
properties.detail_limit = {
|
|
1385
|
+
...properties.detail_limit,
|
|
1386
|
+
minimum: 1
|
|
1387
|
+
};
|
|
1388
|
+
properties.allow_card_only_screening = {
|
|
1389
|
+
...properties.allow_card_only_screening,
|
|
1390
|
+
enum: [false]
|
|
1391
|
+
};
|
|
1392
|
+
properties.dry_run_post_action = {
|
|
1393
|
+
...properties.dry_run_post_action,
|
|
1394
|
+
enum: [false]
|
|
1395
|
+
};
|
|
1396
|
+
properties.no_filter = {
|
|
1397
|
+
...properties.no_filter,
|
|
1398
|
+
enum: [false]
|
|
1399
|
+
};
|
|
1400
|
+
properties.filter_enabled = {
|
|
1401
|
+
...properties.filter_enabled,
|
|
1402
|
+
enum: [true]
|
|
1403
|
+
};
|
|
1342
1404
|
return {
|
|
1343
1405
|
...base,
|
|
1344
1406
|
properties: {
|
|
1345
|
-
...
|
|
1407
|
+
...properties,
|
|
1346
1408
|
schedule_id: {
|
|
1347
1409
|
type: "string",
|
|
1348
1410
|
description: "可选,自定义定时任务 id;默认自动生成"
|
|
@@ -1417,6 +1479,11 @@ function createCompactRunInputSchema() {
|
|
|
1417
1479
|
},
|
|
1418
1480
|
gender: { type: "string" },
|
|
1419
1481
|
recent_not_view: { type: "string" },
|
|
1482
|
+
current_city_only: { type: "boolean" },
|
|
1483
|
+
activity_level: {
|
|
1484
|
+
type: "string",
|
|
1485
|
+
description: "标准选项为 不限、刚刚活跃、今日活跃、3日内活跃、本周活跃、本月活跃;非精确输入会按最靠近的用户意图归一化,无法理解时默认 不限。"
|
|
1486
|
+
},
|
|
1420
1487
|
skip_recent_colleague_contacted: { type: "boolean" },
|
|
1421
1488
|
filter_recent_colleague_contacted: {
|
|
1422
1489
|
type: "boolean",
|
|
@@ -1450,6 +1517,10 @@ function createCompactRunInputSchema() {
|
|
|
1450
1517
|
slow_live: { type: "boolean" },
|
|
1451
1518
|
delay_ms: { type: "integer", minimum: 0 },
|
|
1452
1519
|
detail_limit: { type: "integer", minimum: 0 },
|
|
1520
|
+
debug_test_mode: { type: "boolean" },
|
|
1521
|
+
debug_force_list_end_after_processed: { type: "integer", minimum: 1 },
|
|
1522
|
+
debug_force_context_recovery_after_processed: { type: "integer", minimum: 1 },
|
|
1523
|
+
debug_force_cdp_reconnect_after_processed: { type: "integer", minimum: 1 },
|
|
1453
1524
|
execute_post_action: { type: "boolean" },
|
|
1454
1525
|
no_filter: { type: "boolean" },
|
|
1455
1526
|
dry_run: { type: "boolean" }
|
|
@@ -1461,10 +1532,31 @@ function createCompactRunInputSchema() {
|
|
|
1461
1532
|
|
|
1462
1533
|
function createCompactScheduleRunInputSchema() {
|
|
1463
1534
|
const base = createCompactRunInputSchema();
|
|
1535
|
+
const properties = { ...base.properties };
|
|
1536
|
+
for (const field of [
|
|
1537
|
+
"debug_test_mode",
|
|
1538
|
+
"debug_force_list_end_after_processed",
|
|
1539
|
+
"debug_force_context_recovery_after_processed",
|
|
1540
|
+
"debug_force_cdp_reconnect_after_processed"
|
|
1541
|
+
]) {
|
|
1542
|
+
delete properties[field];
|
|
1543
|
+
}
|
|
1544
|
+
properties.detail_limit = {
|
|
1545
|
+
...properties.detail_limit,
|
|
1546
|
+
minimum: 1
|
|
1547
|
+
};
|
|
1548
|
+
properties.no_filter = {
|
|
1549
|
+
...properties.no_filter,
|
|
1550
|
+
enum: [false]
|
|
1551
|
+
};
|
|
1552
|
+
properties.dry_run = {
|
|
1553
|
+
...properties.dry_run,
|
|
1554
|
+
enum: [false]
|
|
1555
|
+
};
|
|
1464
1556
|
return {
|
|
1465
1557
|
...base,
|
|
1466
1558
|
properties: {
|
|
1467
|
-
...
|
|
1559
|
+
...properties,
|
|
1468
1560
|
schedule_id: {
|
|
1469
1561
|
type: "string",
|
|
1470
1562
|
description: "可选,自定义定时任务 id;默认自动生成"
|
|
@@ -1821,7 +1913,32 @@ function validateRunArgs(args) {
|
|
|
1821
1913
|
return "arguments must be an object";
|
|
1822
1914
|
}
|
|
1823
1915
|
if (!args.instruction || typeof args.instruction !== "string") {
|
|
1824
|
-
return "instruction is required and must be a string";
|
|
1916
|
+
return "instruction is required and must be a string";
|
|
1917
|
+
}
|
|
1918
|
+
if (
|
|
1919
|
+
Object.prototype.hasOwnProperty.call(args, "debug_test_mode")
|
|
1920
|
+
&& typeof args.debug_test_mode !== "boolean"
|
|
1921
|
+
) {
|
|
1922
|
+
return "debug_test_mode must be a boolean";
|
|
1923
|
+
}
|
|
1924
|
+
const debugBoundaryFields = [
|
|
1925
|
+
"debug_force_list_end_after_processed",
|
|
1926
|
+
"debug_force_context_recovery_after_processed",
|
|
1927
|
+
"debug_force_cdp_reconnect_after_processed"
|
|
1928
|
+
];
|
|
1929
|
+
const configuredDebugBoundaries = [];
|
|
1930
|
+
for (const field of debugBoundaryFields) {
|
|
1931
|
+
if (!Object.prototype.hasOwnProperty.call(args, field)) continue;
|
|
1932
|
+
if (!Number.isInteger(args[field]) || args[field] <= 0) {
|
|
1933
|
+
return `${field} must be a positive integer`;
|
|
1934
|
+
}
|
|
1935
|
+
configuredDebugBoundaries.push(field);
|
|
1936
|
+
}
|
|
1937
|
+
if (configuredDebugBoundaries.length > 1) {
|
|
1938
|
+
return `${configuredDebugBoundaries.join(", ")} are mutually exclusive`;
|
|
1939
|
+
}
|
|
1940
|
+
if (configuredDebugBoundaries.length && args.debug_test_mode !== true) {
|
|
1941
|
+
return `${configuredDebugBoundaries[0]} requires debug_test_mode=true`;
|
|
1825
1942
|
}
|
|
1826
1943
|
return null;
|
|
1827
1944
|
}
|
|
@@ -3111,7 +3228,7 @@ async function handleRequest(message, workspaceRoot) {
|
|
|
3111
3228
|
);
|
|
3112
3229
|
}
|
|
3113
3230
|
|
|
3114
|
-
if ([TOOL_RUN_RECOMMEND, TOOL_START_RUN].includes(toolName)) {
|
|
3231
|
+
if ([TOOL_RUN_RECOMMEND, TOOL_START_RUN, TOOL_PREPARE_RUN].includes(toolName)) {
|
|
3115
3232
|
const inputError = validateRunArgs(args);
|
|
3116
3233
|
if (inputError) {
|
|
3117
3234
|
return createJsonRpcError(id, -32602, inputError);
|
package/src/parser.js
CHANGED
|
@@ -28,6 +28,50 @@ const DEGREE_ORDER = [
|
|
|
28
28
|
];
|
|
29
29
|
const GENDER_OPTIONS = ["不限", "男", "女"];
|
|
30
30
|
const RECENT_NOT_VIEW_OPTIONS = ["不限", "近14天没有"];
|
|
31
|
+
const ACTIVITY_LEVEL_OPTIONS = [
|
|
32
|
+
"不限",
|
|
33
|
+
"刚刚活跃",
|
|
34
|
+
"今日活跃",
|
|
35
|
+
"3日内活跃",
|
|
36
|
+
"本周活跃",
|
|
37
|
+
"本月活跃"
|
|
38
|
+
];
|
|
39
|
+
const ACTIVITY_LEVEL_ALIASES = Object.freeze({
|
|
40
|
+
"不限": [
|
|
41
|
+
"不限", "不限制", "无要求", "没有要求", "任意", "全部", "都可以", "均可", "随便", "无所谓",
|
|
42
|
+
"nolimit", "norestriction", "unrestricted", "any", "all", "anytime", "nopreference", "doesntmatter", "whatever"
|
|
43
|
+
],
|
|
44
|
+
"刚刚活跃": [
|
|
45
|
+
"刚刚活跃", "刚才活跃", "刚刚", "刚才", "刚上线", "刚刚上线", "当前在线", "现在在线", "正在在线", "在线", "最近活跃", "近期活跃",
|
|
46
|
+
"高活跃", "高活跃度", "活跃度高", "高度活跃", "非常活跃", "很活跃", "超级活跃", "极其活跃", "最活跃", "高频活跃",
|
|
47
|
+
"activenow", "online", "onlinenow", "justnow", "justactive", "justonline", "currentlyactive", "currentlyonline",
|
|
48
|
+
"recentlyactive", "activerecently", "highactivity", "highlyactive", "veryactive", "superactive", "extremelyactive", "mostactive"
|
|
49
|
+
],
|
|
50
|
+
"今日活跃": [
|
|
51
|
+
"今日活跃", "今天活跃", "今日", "今天", "当日", "当天", "当天活跃", "24小时内", "近24小时", "最近24小时", "过去24小时",
|
|
52
|
+
"today", "activetoday", "todayactive", "daily", "dailyactive", "每日活跃", "sameday", "withinthelastday", "inthelastday", "duringthecurrentday",
|
|
53
|
+
"within24hours", "last24hours", "past24hours"
|
|
54
|
+
],
|
|
55
|
+
"3日内活跃": [
|
|
56
|
+
"3日内活跃", "3天内活跃", "三日内活跃", "三天内活跃", "3日内", "3天内", "三日内", "三天内",
|
|
57
|
+
"近3日", "近3天", "最近3日", "最近3天", "过去3日", "过去3天", "昨日", "昨天", "前天", "最近几天",
|
|
58
|
+
"within3days", "last3days", "past3days", "recent3days", "yesterday", "daybeforeyesterday", "recentfewdays"
|
|
59
|
+
],
|
|
60
|
+
"本周活跃": [
|
|
61
|
+
"本周活跃", "本舟活跃", "这周活跃", "本周", "这周", "这个星期", "本星期", "本礼拜", "这礼拜", "一周内", "近一周", "最近一周", "近7天", "最近7天", "7日内", "7天内",
|
|
62
|
+
"中等活跃", "中度活跃", "一般活跃", "普通活跃", "适度活跃", "活跃度一般", "中等活跃度",
|
|
63
|
+
"thisweek", "currentweek", "thisweekend", "weekend", "withinweek", "withinaweek", "withinthelastweek", "inthelastweek", "inthepastweek",
|
|
64
|
+
"duringthecurrentweek", "overthelastweek", "overthepastweek", "lastweek", "pastweek", "weekly", "recent7days", "last7days", "past7days",
|
|
65
|
+
"mediumactivity", "moderatelyactive", "mediumactive", "fairlyactive", "averageactivity", "averagelyactive", "normallyactive"
|
|
66
|
+
],
|
|
67
|
+
"本月活跃": [
|
|
68
|
+
"本月活跃", "这个月活跃", "本月", "这个月", "当月", "一个月内", "近一个月", "最近一个月", "近30天", "最近30天", "30日内", "30天内",
|
|
69
|
+
"低活跃", "低活跃度", "活跃度低", "活跃度不高", "低度活跃", "不太活跃", "偶尔活跃", "较少活跃", "很少活跃", "低频活跃",
|
|
70
|
+
"thismonth", "currentmonth", "withinmonth", "withinamonth", "withinthelastmonth", "inthelastmonth", "inthepastmonth", "duringthecurrentmonth",
|
|
71
|
+
"overthelastmonth", "overthepastmonth", "lastmonth", "pastmonth", "monthly", "recent30days", "last30days", "past30days",
|
|
72
|
+
"lowactivity", "lowactive", "lessactive", "notveryactive", "occasionallyactive", "rarelyactive", "infrequentlyactive", "seldomactive"
|
|
73
|
+
]
|
|
74
|
+
});
|
|
31
75
|
const FILTER_CONFIRM_OPTIONS = [
|
|
32
76
|
{ label: "筛选项无误,继续", value: "confirm" },
|
|
33
77
|
{ label: "筛选项需要调整", value: "revise" }
|
|
@@ -97,10 +141,11 @@ const MAX_GREET_COUNT_PATTERNS = [
|
|
|
97
141
|
/最多(?:打招呼|沟通|联系)\s*(\d+)\s*(?:位|人|个)?/i,
|
|
98
142
|
/(?:打招呼|沟通|联系)(?:上限|最多|不超过|至多)(?:为|是|:|:)?\s*(\d+)/i
|
|
99
143
|
];
|
|
144
|
+
const RUN_META_FIELD_LABEL_PATTERN = "(?:页面选择|学校标签|院校标签|学历|学位|性别|是否过滤近14天看过|当前城市筛选|仅推荐本城市|仅推荐期望城市为本城市(?:的牛人)?|current[_\\s-]?city[_\\s-]?only|活跃度|活动度|activity[_\\s-]?level|筛选条件|目标筛选数|目标通过人数|通过筛选后动作|最大招呼数|最大打招呼数|岗位)";
|
|
100
145
|
const CRITERIA_EXPLICIT_MARKER_PATTERN = /筛选条件\s*[::]/i;
|
|
101
|
-
const CRITERIA_EXPLICIT_STOP_PATTERN =
|
|
146
|
+
const CRITERIA_EXPLICIT_STOP_PATTERN = new RegExp(`(?:^|[\\s;;])\\s*${RUN_META_FIELD_LABEL_PATTERN}\\s*[::]`, "i");
|
|
102
147
|
const CRITERIA_META_FIELD_PREFIX_PATTERNS = [
|
|
103
|
-
|
|
148
|
+
new RegExp(`^${RUN_META_FIELD_LABEL_PATTERN}\\s*(?:[::]|$)`, "i"),
|
|
104
149
|
/^(?:近?14天(?:内)?(?:没有|没看过|未查看)|(?:不过滤|保留|过滤|排除)[^。;;\n]{0,12}14天)\s*(?:[::]|$)?/i,
|
|
105
150
|
/^(?:目标(?:处理|筛选|通过)?(?:人数|数量)?|至少(?:处理|筛选|通过)|(?:处理|筛选|通过)\s*\d+\s*(?:位|人))(?:[::\s]|$)/i,
|
|
106
151
|
/^(?:最多(?:打招呼|沟通|联系)|(?:打招呼|沟通|联系)(?:上限|最多|不超过|至多))(?:[::\s]|$)/i,
|
|
@@ -302,13 +347,244 @@ function normalizeRecentNotView(value) {
|
|
|
302
347
|
return RECENT_NOT_VIEW_OPTIONS.includes(normalized) ? normalized : null;
|
|
303
348
|
}
|
|
304
349
|
|
|
350
|
+
function normalizeActivityIntentText(value) {
|
|
351
|
+
return normalizeText(value)
|
|
352
|
+
.normalize("NFKC")
|
|
353
|
+
.toLowerCase()
|
|
354
|
+
.replace(/[內内]/g, "内")
|
|
355
|
+
.replace(/[週周]/g, "周")
|
|
356
|
+
.replace(/[剛刚]/g, "刚")
|
|
357
|
+
.replace(/[當当]/g, "当")
|
|
358
|
+
.replace(/[無无]/g, "无")
|
|
359
|
+
.replace(/[躍跃]/g, "跃");
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function compactActivityIntentText(value) {
|
|
363
|
+
return normalizeActivityIntentText(value).replace(/[\s_\-—–::,,。;;、/|()[\]{}'"“”‘’]+/g, "");
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function stripActivityIntentWrappers(value) {
|
|
367
|
+
let current = compactActivityIntentText(value);
|
|
368
|
+
for (let index = 0; index < 4; index += 1) {
|
|
369
|
+
const previous = current;
|
|
370
|
+
current = current
|
|
371
|
+
.replace(/^(?:please|showme|iwant|want|setto|select|choose|filterby|activitylevel|activitystatus|activity|active|活跃度单选|活跃度|活动度|请选择|请选|选择|设置为|设为|设置|筛选为|筛选|仅推荐|只推荐|推荐|仅看|只看|只要|仅要|要求|希望|我要|想要|选项为|选项是|为|是|选)/, "")
|
|
372
|
+
.replace(/(?:candidates?|people|users?|talents?|option|active|的牛人|牛人|的候选人|候选人|的人选|人选|的人才|人才|的用户|用户|的人|选项|档位|程度|活跃度|活跃)$/u, "")
|
|
373
|
+
.replace(/^(?:为|是|to|is)/, "");
|
|
374
|
+
if (current === previous) break;
|
|
375
|
+
}
|
|
376
|
+
return current;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function parseChineseActivityNumber(value) {
|
|
380
|
+
const normalized = String(value || "");
|
|
381
|
+
if (/^\d+(?:\.\d+)?$/.test(normalized)) return Number(normalized);
|
|
382
|
+
if (normalized === "半") return 0.5;
|
|
383
|
+
const englishNumbers = {
|
|
384
|
+
half: 0.5,
|
|
385
|
+
one: 1,
|
|
386
|
+
two: 2,
|
|
387
|
+
couple: 2,
|
|
388
|
+
three: 3,
|
|
389
|
+
few: 3,
|
|
390
|
+
four: 4,
|
|
391
|
+
five: 5,
|
|
392
|
+
six: 6,
|
|
393
|
+
seven: 7,
|
|
394
|
+
eight: 8,
|
|
395
|
+
nine: 9,
|
|
396
|
+
ten: 10,
|
|
397
|
+
twenty: 20,
|
|
398
|
+
thirty: 30
|
|
399
|
+
};
|
|
400
|
+
if (Object.prototype.hasOwnProperty.call(englishNumbers, normalized.toLowerCase())) {
|
|
401
|
+
return englishNumbers[normalized.toLowerCase()];
|
|
402
|
+
}
|
|
403
|
+
const digits = { 零: 0, 一: 1, 二: 2, 两: 2, 三: 3, 四: 4, 五: 5, 六: 6, 七: 7, 八: 8, 九: 9 };
|
|
404
|
+
if (normalized === "十") return 10;
|
|
405
|
+
if (normalized.includes("十")) {
|
|
406
|
+
const [tens, ones] = normalized.split("十");
|
|
407
|
+
return (tens ? digits[tens] || 0 : 1) * 10 + (ones ? digits[ones] || 0 : 0);
|
|
408
|
+
}
|
|
409
|
+
return digits[normalized] ?? null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function activityLevelForRelativeDuration(value) {
|
|
413
|
+
const normalized = normalizeActivityIntentText(value);
|
|
414
|
+
const match = normalized.match(
|
|
415
|
+
/(?:近|最近|过去|过去的|within\s*|last\s*|past\s*)?(\d+(?:\.\d+)?|半|[一二两三四五六七八九十]+|half|one|two|couple|three|few|four|five|six|seven|eight|nine|ten|twenty|thirty)\s*(?:个)?\s*(小时|hours?|hrs?|hr|h|天|日|days?|day|d|周|星期|weeks?|week|w|月|months?|month)(?:内|以内|之内|ago)?/i
|
|
416
|
+
);
|
|
417
|
+
if (!match) return null;
|
|
418
|
+
const amount = parseChineseActivityNumber(match[1]);
|
|
419
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
420
|
+
const unit = match[2].toLowerCase();
|
|
421
|
+
if (/^(?:小时|hours?|hrs?|hr|h)$/.test(unit)) {
|
|
422
|
+
if (amount <= 2) return "刚刚活跃";
|
|
423
|
+
if (amount <= 24) return "今日活跃";
|
|
424
|
+
return activityLevelForRelativeDuration(`${Math.ceil(amount / 24)}天`);
|
|
425
|
+
}
|
|
426
|
+
if (/^(?:天|日|days?|day|d)$/.test(unit)) {
|
|
427
|
+
if (amount <= 1) return "今日活跃";
|
|
428
|
+
const nominalWindows = [
|
|
429
|
+
{ days: 3, activityLevel: "3日内活跃" },
|
|
430
|
+
{ days: 7, activityLevel: "本周活跃" },
|
|
431
|
+
{ days: 30, activityLevel: "本月活跃" }
|
|
432
|
+
];
|
|
433
|
+
return nominalWindows.reduce((closest, candidate) => {
|
|
434
|
+
const closestDistance = Math.abs(amount - closest.days);
|
|
435
|
+
const candidateDistance = Math.abs(amount - candidate.days);
|
|
436
|
+
if (candidateDistance < closestDistance) return candidate;
|
|
437
|
+
if (candidateDistance === closestDistance && candidate.days > closest.days) return candidate;
|
|
438
|
+
return closest;
|
|
439
|
+
}, nominalWindows[0]).activityLevel;
|
|
440
|
+
}
|
|
441
|
+
if (/^(?:周|星期|weeks?|week|w)$/.test(unit)) {
|
|
442
|
+
return activityLevelForRelativeDuration(`${amount * 7}天`);
|
|
443
|
+
}
|
|
444
|
+
return "本月活跃";
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function activityLevelsForSemanticPhrase(value) {
|
|
448
|
+
const normalized = normalizeActivityIntentText(value);
|
|
449
|
+
const compact = compactActivityIntentText(normalized);
|
|
450
|
+
const englishQualitativeText = normalized
|
|
451
|
+
.replace(/\bnot\s+(?:very|highly|high|super|extremely)\b/g, " low ");
|
|
452
|
+
const highQualitativeText = compact
|
|
453
|
+
.replace(/not(?:very|highly|high|super|extremely)active|nothighactivity/g, "")
|
|
454
|
+
.replace(/不太活跃|很少活跃|较少活跃|偶尔活跃|低频活跃|低度活跃|低活跃|活跃度不高|活跃度低/g, "");
|
|
455
|
+
const hasEnglishActivityContext = /\b(?:activity|active)\b/i.test(englishQualitativeText);
|
|
456
|
+
const hasChineseActivityContext = /活跃/.test(normalized);
|
|
457
|
+
const hasHighQualitativeIntent = (
|
|
458
|
+
/highactivity|highlyactive|veryactive|superactive|extremelyactive|mostactive|高活跃|活跃度高|高度活跃|非常活跃|很活跃|超级活跃|极其活跃|最活跃|高频活跃/.test(highQualitativeText)
|
|
459
|
+
|| (hasEnglishActivityContext && /\b(?:high|highly|very|super|extremely|most)\b/i.test(englishQualitativeText))
|
|
460
|
+
|| (hasChineseActivityContext && /高|非常|超级|极其|最活跃/.test(highQualitativeText))
|
|
461
|
+
);
|
|
462
|
+
const hasMediumQualitativeIntent = (
|
|
463
|
+
/mediumactivity|moderatelyactive|mediumactive|fairlyactive|averageactivity|averagelyactive|normallyactive|中等活跃|中度活跃|一般活跃|普通活跃|适度活跃|活跃度一般/.test(compact)
|
|
464
|
+
|| (hasEnglishActivityContext && /\b(?:medium|moderate|moderately|fair|fairly|average|normal|normally)\b/i.test(englishQualitativeText))
|
|
465
|
+
|| (hasChineseActivityContext && /中等|中度|一般|普通|适度/.test(normalized))
|
|
466
|
+
);
|
|
467
|
+
const hasLowQualitativeIntent = (
|
|
468
|
+
/lowactivity|lowactive|lessactive|notveryactive|nothighactivity|occasionallyactive|rarelyactive|infrequentlyactive|seldomactive|低活跃|活跃度低|活跃度不高|低度活跃|不太活跃|偶尔活跃|较少活跃|很少活跃|低频活跃/.test(compact)
|
|
469
|
+
|| (hasEnglishActivityContext && /\b(?:low|less|rare|rarely|occasional|occasionally|infrequent|infrequently|seldom)\b/i.test(englishQualitativeText))
|
|
470
|
+
|| (hasChineseActivityContext && /低|不太|偶尔|较少|很少|低频/.test(normalized))
|
|
471
|
+
);
|
|
472
|
+
const matches = [];
|
|
473
|
+
if (
|
|
474
|
+
/(?:no|without)(?:activity)?(?:limit|restriction|preference)|notrestricted|notactive|notonline|anyactivity|allactivity|dontcare|doesntmatter|不限|不限制|无要求|没有要求|任意|都可以|均可|无所谓/.test(compact)
|
|
475
|
+
) {
|
|
476
|
+
matches.push("不限");
|
|
477
|
+
}
|
|
478
|
+
if (/justnow|rightnow|currentlyactive|currentlyonline|onlinenow|刚刚|刚才|刚上线|当前在线|现在在线/.test(compact)) {
|
|
479
|
+
matches.push("刚刚活跃");
|
|
480
|
+
}
|
|
481
|
+
if (hasHighQualitativeIntent) {
|
|
482
|
+
matches.push("刚刚活跃");
|
|
483
|
+
}
|
|
484
|
+
if (/activetoday|todayactive|today|sameday|(?:within|during|in|over)?(?:the)?(?:last|past|current)(?:one)?day|今日|今天|当日|当天/.test(compact)) {
|
|
485
|
+
matches.push("今日活跃");
|
|
486
|
+
}
|
|
487
|
+
if (/yesterday|daybeforeyesterday|recentfewdays|昨日|昨天|前天|最近几天/.test(compact)) {
|
|
488
|
+
matches.push("3日内活跃");
|
|
489
|
+
}
|
|
490
|
+
if (/(?:this|current)week|(?:within|during|in|over)?(?:the)?(?:last|past)(?:one)?week|thisweekend|weekend|本周|这周|这个星期|本星期/.test(compact)) {
|
|
491
|
+
matches.push("本周活跃");
|
|
492
|
+
}
|
|
493
|
+
if (hasMediumQualitativeIntent) {
|
|
494
|
+
matches.push("本周活跃");
|
|
495
|
+
}
|
|
496
|
+
if (/(?:this|current)month|(?:within|during|in|over)?(?:the)?(?:last|past)(?:one)?month|本月|这个月|当月/.test(compact)) {
|
|
497
|
+
matches.push("本月活跃");
|
|
498
|
+
}
|
|
499
|
+
if (hasLowQualitativeIntent) {
|
|
500
|
+
matches.push("本月活跃");
|
|
501
|
+
}
|
|
502
|
+
return uniqueList(matches);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function activityEditDistance(left, right) {
|
|
506
|
+
const a = String(left || "");
|
|
507
|
+
const b = String(right || "");
|
|
508
|
+
const previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
509
|
+
for (let leftIndex = 1; leftIndex <= a.length; leftIndex += 1) {
|
|
510
|
+
const current = [leftIndex];
|
|
511
|
+
for (let rightIndex = 1; rightIndex <= b.length; rightIndex += 1) {
|
|
512
|
+
current[rightIndex] = Math.min(
|
|
513
|
+
current[rightIndex - 1] + 1,
|
|
514
|
+
previous[rightIndex] + 1,
|
|
515
|
+
previous[rightIndex - 1] + (a[leftIndex - 1] === b[rightIndex - 1] ? 0 : 1)
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
previous.splice(0, previous.length, ...current);
|
|
519
|
+
}
|
|
520
|
+
return previous[b.length];
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function resolveActivityLevelIntent(value) {
|
|
524
|
+
const normalized = normalizeActivityIntentText(value);
|
|
525
|
+
if (!normalized) return { value: "不限", recognized: false, method: "fallback" };
|
|
526
|
+
const compact = compactActivityIntentText(normalized);
|
|
527
|
+
const stripped = stripActivityIntentWrappers(compact);
|
|
528
|
+
const candidates = uniqueList([compact, stripped]);
|
|
529
|
+
|
|
530
|
+
for (const [activityLevel, aliases] of Object.entries(ACTIVITY_LEVEL_ALIASES)) {
|
|
531
|
+
const compactAliases = aliases.map((alias) => compactActivityIntentText(alias));
|
|
532
|
+
if (candidates.some((candidate) => compactAliases.includes(candidate))) {
|
|
533
|
+
return { value: activityLevel, recognized: true, method: "alias" };
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
const durationLevel = activityLevelForRelativeDuration(normalized)
|
|
538
|
+
|| activityLevelForRelativeDuration(stripped);
|
|
539
|
+
const semanticLevels = activityLevelsForSemanticPhrase(normalized);
|
|
540
|
+
const inferredLevels = uniqueList([...semanticLevels, durationLevel]);
|
|
541
|
+
if (inferredLevels.length === 1) {
|
|
542
|
+
return {
|
|
543
|
+
value: inferredLevels[0],
|
|
544
|
+
recognized: true,
|
|
545
|
+
method: durationLevel ? "duration" : "semantic"
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
if (inferredLevels.length > 1) {
|
|
549
|
+
return { value: "不限", recognized: false, method: "ambiguous" };
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const fuzzyMatches = [];
|
|
553
|
+
for (const [activityLevel, aliases] of Object.entries(ACTIVITY_LEVEL_ALIASES)) {
|
|
554
|
+
for (const alias of aliases) {
|
|
555
|
+
const compactAlias = compactActivityIntentText(alias);
|
|
556
|
+
if (compactAlias.length < 4) continue;
|
|
557
|
+
for (const candidate of candidates) {
|
|
558
|
+
if (candidate.length < 4 || Math.abs(candidate.length - compactAlias.length) > 1) continue;
|
|
559
|
+
const distance = activityEditDistance(candidate, compactAlias);
|
|
560
|
+
if (distance <= 1) fuzzyMatches.push({ activityLevel, distance });
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
if (fuzzyMatches.length) {
|
|
565
|
+
const minimumDistance = Math.min(...fuzzyMatches.map((item) => item.distance));
|
|
566
|
+
const closestLevels = uniqueList(
|
|
567
|
+
fuzzyMatches.filter((item) => item.distance === minimumDistance).map((item) => item.activityLevel)
|
|
568
|
+
);
|
|
569
|
+
if (closestLevels.length === 1) {
|
|
570
|
+
return { value: closestLevels[0], recognized: true, method: "fuzzy" };
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return { value: "不限", recognized: false, method: "fallback" };
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function normalizeActivityLevel(value) {
|
|
578
|
+
return resolveActivityLevelIntent(value).value;
|
|
579
|
+
}
|
|
580
|
+
|
|
305
581
|
function normalizeBooleanOverride(value) {
|
|
306
582
|
if (typeof value === "boolean") return value;
|
|
307
583
|
if (typeof value === "number") return value !== 0;
|
|
308
584
|
const normalized = normalizeText(value).toLowerCase();
|
|
309
585
|
if (!normalized) return null;
|
|
310
|
-
if (["true", "yes", "y", "1", "on", "enable", "enabled", "需要", "是", "开启"].includes(normalized)) return true;
|
|
311
|
-
if (["false", "no", "n", "0", "off", "disable", "disabled", "不需要", "否", "关闭"].includes(normalized)) return false;
|
|
586
|
+
if (["true", "yes", "y", "1", "on", "enable", "enabled", "需要", "是", "开启", "启用", "勾选", "选中"].includes(normalized)) return true;
|
|
587
|
+
if (["false", "no", "n", "0", "off", "disable", "disabled", "不需要", "否", "关闭", "不启用", "不勾选", "未选中"].includes(normalized)) return false;
|
|
312
588
|
return null;
|
|
313
589
|
}
|
|
314
590
|
|
|
@@ -383,6 +659,65 @@ function extractRecentNotView(text) {
|
|
|
383
659
|
return null;
|
|
384
660
|
}
|
|
385
661
|
|
|
662
|
+
function extractStructuredRunMetaValue(rawText, labelPattern) {
|
|
663
|
+
const normalized = String(rawText || "").replace(/\r\n/g, "\n");
|
|
664
|
+
const match = normalized.match(new RegExp(
|
|
665
|
+
`(?:^|[\\s;;])\\s*(?:${labelPattern})\\s*[::]\\s*([\\s\\S]*?)(?=(?:[\\s;;]\\s*${RUN_META_FIELD_LABEL_PATTERN}\\s*[::])|$)`,
|
|
666
|
+
"i"
|
|
667
|
+
));
|
|
668
|
+
return match ? normalizeText(String(match[1] || "").replace(/[。;;]+$/, "")) : null;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
function extractActivityLevel(rawText) {
|
|
672
|
+
const structured = extractStructuredRunMetaValue(rawText, "(?:活跃度|活动度|activity[_\\s-]?level)");
|
|
673
|
+
if (structured !== null) {
|
|
674
|
+
return {
|
|
675
|
+
explicit: true,
|
|
676
|
+
raw: structured || "(空值)",
|
|
677
|
+
value: normalizeActivityLevel(structured)
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
const normalized = normalizeText(rawText);
|
|
681
|
+
for (const value of ACTIVITY_LEVEL_OPTIONS.filter((item) => item !== "不限")) {
|
|
682
|
+
if (normalized.includes(value)) {
|
|
683
|
+
return { explicit: false, raw: value, value };
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
const activityClauses = String(rawText || "")
|
|
687
|
+
.split(/[,,。;;\n]+/)
|
|
688
|
+
.map((item) => normalizeText(item))
|
|
689
|
+
.filter((item) => /活[跃躍越]|在线|上[线線]|activity|active|online/i.test(item));
|
|
690
|
+
for (const clause of activityClauses) {
|
|
691
|
+
const resolved = resolveActivityLevelIntent(clause);
|
|
692
|
+
if (resolved.recognized) {
|
|
693
|
+
return { explicit: false, raw: clause, value: resolved.value };
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
return { explicit: false, raw: null, value: null };
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
function extractCurrentCityOnly(rawText) {
|
|
700
|
+
const structured = extractStructuredRunMetaValue(
|
|
701
|
+
rawText,
|
|
702
|
+
"(?:current[_\\s-]?city[_\\s-]?only|当前城市筛选|仅推荐本城市|仅推荐期望城市为本城市(?:的牛人)?)"
|
|
703
|
+
);
|
|
704
|
+
const structuredValue = normalizeBooleanOverride(structured);
|
|
705
|
+
if (structured !== null) return structuredValue;
|
|
706
|
+
|
|
707
|
+
const normalized = normalizeText(rawText);
|
|
708
|
+
if (
|
|
709
|
+
/(?:不限|不限制)期望城市|(?:关闭|取消|禁用|去掉|取消勾选)\s*(?:当前城市筛选|仅推荐本城市|仅推荐期望城市为本城市(?:的牛人)?|只推荐期望城市(?:是|为)?本城市)/i.test(normalized)
|
|
710
|
+
) {
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
if (
|
|
714
|
+
/\bcurrent[_\s-]?city[_\s-]?only\b|仅推荐期望城市为本城市(?:的牛人)?|只推荐期望城市(?:是|为)?本城市|仅推荐本城市/i.test(normalized)
|
|
715
|
+
) {
|
|
716
|
+
return true;
|
|
717
|
+
}
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
|
|
386
721
|
function extractTargetCount(text) {
|
|
387
722
|
for (const pattern of TARGET_COUNT_PATTERNS) {
|
|
388
723
|
const match = text.match(pattern);
|
|
@@ -411,7 +746,10 @@ function extractMaxGreetCount(text) {
|
|
|
411
746
|
|
|
412
747
|
function extractJobSelectionHint(text) {
|
|
413
748
|
const normalized = String(text || "").replace(/\r\n/g, "\n");
|
|
414
|
-
const match = normalized.match(
|
|
749
|
+
const match = normalized.match(new RegExp(
|
|
750
|
+
`(?:^|[\\s;;])\\s*(?:岗位|职位|job)\\s*[::]\\s*([\\s\\S]*?)(?=(?:[\\s;;]\\s*${RUN_META_FIELD_LABEL_PATTERN}\\s*[::])|$)`,
|
|
751
|
+
"i"
|
|
752
|
+
));
|
|
415
753
|
if (!match?.[1]) return null;
|
|
416
754
|
return normalizeText(String(match[1] || "").replace(/[。;;]+$/, "").trim());
|
|
417
755
|
}
|
|
@@ -437,6 +775,20 @@ function isMetaClause(clause) {
|
|
|
437
775
|
if (!withoutNumbering) return true;
|
|
438
776
|
if (CRITERIA_META_FIELD_PREFIX_PATTERNS.some((pattern) => pattern.test(withoutNumbering))) return true;
|
|
439
777
|
if (META_CLAUSE_PATTERNS.some((pattern) => pattern.test(withoutNumbering))) return true;
|
|
778
|
+
const activityCandidate = stripActivityIntentWrappers(withoutNumbering);
|
|
779
|
+
const activityIntent = resolveActivityLevelIntent(withoutNumbering);
|
|
780
|
+
const isKnownActivityAlias = Object.values(ACTIVITY_LEVEL_ALIASES)
|
|
781
|
+
.flat()
|
|
782
|
+
.map((item) => stripActivityIntentWrappers(item))
|
|
783
|
+
.includes(activityCandidate);
|
|
784
|
+
const isRelativeActivityDuration = /^(?:近|最近|过去|过去的|(?:(?:within|during|in|over)?(?:the)?(?:last|past)?))?(?:\d+(?:\.\d+)?|半|[一二两三四五六七八九十]+|half|one|two|couple|three|few|four|five|six|seven|eight|nine|ten|twenty|thirty)(?:个)?(?:小时|hours?|hrs?|hr|h|天|日|days?|day|d|周|星期|weeks?|week|w|月|months?|month)(?:内|以内|之内|ago)?$/i
|
|
785
|
+
.test(activityCandidate);
|
|
786
|
+
if (
|
|
787
|
+
activityIntent.recognized
|
|
788
|
+
&& (isKnownActivityAlias || isRelativeActivityDuration || activityIntent.method === "fuzzy")
|
|
789
|
+
) {
|
|
790
|
+
return true;
|
|
791
|
+
}
|
|
440
792
|
return false;
|
|
441
793
|
}
|
|
442
794
|
|
|
@@ -655,6 +1007,18 @@ export function parseRecommendInstruction({ instruction, confirmation, overrides
|
|
|
655
1007
|
const confirmationGender = normalizeGender(confirmation?.gender_value);
|
|
656
1008
|
const overrideRecentNotView = normalizeRecentNotView(overrides?.recent_not_view);
|
|
657
1009
|
const confirmationRecentNotView = normalizeRecentNotView(confirmation?.recent_not_view_value);
|
|
1010
|
+
const hasCurrentCityOnlyOverride = Object.prototype.hasOwnProperty.call(overrides || {}, "current_city_only");
|
|
1011
|
+
const currentCityOnly = hasCurrentCityOnlyOverride
|
|
1012
|
+
? normalizeBooleanOverride(overrides?.current_city_only) ?? false
|
|
1013
|
+
: extractCurrentCityOnly(rawInstruction) ?? false;
|
|
1014
|
+
const hasActivityLevelOverride = Object.prototype.hasOwnProperty.call(overrides || {}, "activity_level");
|
|
1015
|
+
const overrideActivityLevel = hasActivityLevelOverride
|
|
1016
|
+
? normalizeActivityLevel(overrides?.activity_level)
|
|
1017
|
+
: null;
|
|
1018
|
+
const instructionActivityLevel = extractActivityLevel(rawInstruction);
|
|
1019
|
+
const activityLevel = hasActivityLevelOverride
|
|
1020
|
+
? overrideActivityLevel
|
|
1021
|
+
: instructionActivityLevel.value || "不限";
|
|
658
1022
|
const overrideCriteria = overrides?.criteria;
|
|
659
1023
|
const criteriaResolution = buildCriteria({
|
|
660
1024
|
instruction: text,
|
|
@@ -694,7 +1058,9 @@ export function parseRecommendInstruction({ instruction, confirmation, overrides
|
|
|
694
1058
|
: ["不限"])
|
|
695
1059
|
),
|
|
696
1060
|
gender: overrideGender || confirmationGender || extractGender(text) || "不限",
|
|
697
|
-
recent_not_view: overrideRecentNotView || confirmationRecentNotView || extractRecentNotView(text) || "不限"
|
|
1061
|
+
recent_not_view: overrideRecentNotView || confirmationRecentNotView || extractRecentNotView(text) || "不限",
|
|
1062
|
+
current_city_only: currentCityOnly,
|
|
1063
|
+
activity_level: activityLevel
|
|
698
1064
|
};
|
|
699
1065
|
const screenParams = {
|
|
700
1066
|
criteria: criteriaResolution.raw || criteriaResolution.normalized || null,
|
|
@@ -919,10 +1285,12 @@ export function parseRecommendInstruction({ instruction, confirmation, overrides
|
|
|
919
1285
|
}
|
|
920
1286
|
|
|
921
1287
|
export {
|
|
1288
|
+
ACTIVITY_LEVEL_OPTIONS,
|
|
922
1289
|
DEGREE_OPTIONS,
|
|
923
1290
|
GENDER_OPTIONS,
|
|
924
1291
|
POST_ACTION_LABELS,
|
|
925
1292
|
POST_ACTION_OPTIONS,
|
|
926
1293
|
RECENT_NOT_VIEW_OPTIONS,
|
|
927
|
-
SCHOOL_TAG_OPTIONS
|
|
928
|
-
|
|
1294
|
+
SCHOOL_TAG_OPTIONS,
|
|
1295
|
+
normalizeActivityLevel
|
|
1296
|
+
};
|