@reconcrap/boss-recommend-mcp 1.1.12 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/boss-recommend-pipeline/SKILL.md +4 -3
- package/src/adapters.js +33 -19
- package/src/cli.js +1 -0
- package/src/index.js +327 -225
- package/src/parser.js +9 -4
- package/src/pipeline.js +7 -3
- package/src/test-adapters-runtime.js +107 -0
- package/src/test-index-async.js +33 -5
- package/src/test-parser.js +16 -0
- package/src/test-pipeline.js +78 -1
- package/vendor/boss-recommend-screen-cli/boss-recommend-screen-cli.cjs +95 -18
- package/vendor/boss-recommend-screen-cli/test-recoverable-resume-failures.cjs +16 -0
- package/vendor/boss-recommend-search-cli/src/cli.js +14 -6
- package/vendor/boss-recommend-search-cli/src/test-job-selection.js +2 -0
package/package.json
CHANGED
|
@@ -43,7 +43,7 @@ description: "Use when users ask to run Boss recommend-page filtering and screen
|
|
|
43
43
|
|
|
44
44
|
阶段 A(页面就绪前,禁止问岗位):
|
|
45
45
|
|
|
46
|
-
- 页面范围(`page_scope`)必须先确认:`recommend
|
|
46
|
+
- 页面范围(`page_scope`)必须先确认:`recommend`(推荐)/ `latest`(最新)/ `featured`(精选)
|
|
47
47
|
- 即使 instruction 里已出现“推荐/精选”关键词,也必须显式二次确认 `page_confirmed=true` 与 `page_value`
|
|
48
48
|
- 学校标签(`school_tag`,支持多选)
|
|
49
49
|
- 若输入混合了有效与无效选项(如 `985,211,qs100`),必须忽略无效项并保留有效项;不要直接回退到“不限”
|
|
@@ -97,7 +97,7 @@ description: "Use when users ask to run Boss recommend-page filtering and screen
|
|
|
97
97
|
- `instruction` (required)
|
|
98
98
|
- `confirmation`
|
|
99
99
|
- `page_confirmed`
|
|
100
|
-
- `page_value` (`recommend|featured`)
|
|
100
|
+
- `page_value` (`recommend|latest|featured`)
|
|
101
101
|
- `filters_confirmed`
|
|
102
102
|
- `school_tag_confirmed`
|
|
103
103
|
- `school_tag_value`(建议回传最终确认值,避免二轮调用丢失)
|
|
@@ -118,7 +118,7 @@ description: "Use when users ask to run Boss recommend-page filtering and screen
|
|
|
118
118
|
- `max_greet_count_confirmed`
|
|
119
119
|
- `max_greet_count_value` (integer)
|
|
120
120
|
- `overrides`
|
|
121
|
-
- `page_scope` (`recommend|featured`)
|
|
121
|
+
- `page_scope` (`recommend|latest|featured`)
|
|
122
122
|
- `school_tag`(可传单值或数组,如 `["985","211"]`)
|
|
123
123
|
- `degree`(可传单值或数组;如“本科及以上”应展开为 `["本科","硕士","博士"]`)
|
|
124
124
|
- `gender`
|
|
@@ -161,6 +161,7 @@ description: "Use when users ask to run Boss recommend-page filtering and screen
|
|
|
161
161
|
- recommend-search-cli 只负责应用推荐页筛选项。
|
|
162
162
|
- 若 `page_scope=featured`:必须严格按 `search -> 切换精选tab(data-status=3) -> screen` 顺序执行。
|
|
163
163
|
- 若 `page_scope=featured` 且校准文件缺失:必须先触发 `boss-recommend-mcp calibrate` 自动校准,成功后再继续。
|
|
164
|
+
- 若 `page_scope=latest`:执行路径与 `recommend` 一致(search + screen),但 screen 列表选择器应按最新 tab 结构读取(data-status=1)。
|
|
164
165
|
- recommend-screen-cli 负责滚动推荐列表、打开详情、提取完整简历图、调用多模态模型判断,并按单次确认的 `post_action` 执行收藏或打招呼。
|
|
165
166
|
- 精选页收藏仅允许“校准坐标 + 模拟点击”,成功判定仅看 network `add/del` 信号。
|
|
166
167
|
- 详情页处理完成后必须关闭详情页并确认已关闭。
|
package/src/adapters.js
CHANGED
|
@@ -20,6 +20,7 @@ const screenConfigTemplateDefaults = {
|
|
|
20
20
|
const DEFAULT_RECOMMEND_SCREEN_TIMEOUT_MS = 24 * 60 * 60 * 1000;
|
|
21
21
|
const PAGE_SCOPE_TO_TAB_STATUS = {
|
|
22
22
|
recommend: "0",
|
|
23
|
+
latest: "1",
|
|
23
24
|
featured: "3"
|
|
24
25
|
};
|
|
25
26
|
|
|
@@ -76,6 +77,7 @@ function normalizePageScope(value) {
|
|
|
76
77
|
const normalized = normalizeText(value).toLowerCase();
|
|
77
78
|
if (!normalized) return null;
|
|
78
79
|
if (["recommend", "推荐", "推荐页", "推荐页面"].includes(normalized)) return "recommend";
|
|
80
|
+
if (["latest", "最新", "最新页", "最新页面"].includes(normalized)) return "latest";
|
|
79
81
|
if (["featured", "精选", "精选页", "精选页面", "精选牛人"].includes(normalized)) return "featured";
|
|
80
82
|
return null;
|
|
81
83
|
}
|
|
@@ -1568,10 +1570,12 @@ function buildRecommendTabStateExpression() {
|
|
|
1568
1570
|
const activeTab = tabs.find((item) => item.active && item.status) || null;
|
|
1569
1571
|
const featuredCount = doc.querySelectorAll('li.geek-info-card').length;
|
|
1570
1572
|
const recommendCount = doc.querySelectorAll('ul.card-list > li.card-item').length;
|
|
1573
|
+
const latestCount = doc.querySelectorAll('.candidate-card-wrap .card-inner[data-geek], .candidate-card-wrap [data-geek]').length;
|
|
1571
1574
|
let inferredStatus = activeTab?.status || null;
|
|
1572
1575
|
if (!inferredStatus) {
|
|
1573
|
-
if (featuredCount > 0 && recommendCount === 0) inferredStatus = '3';
|
|
1574
|
-
else if (
|
|
1576
|
+
if (featuredCount > 0 && recommendCount === 0 && latestCount === 0) inferredStatus = '3';
|
|
1577
|
+
else if (latestCount > 0 && featuredCount === 0 && recommendCount === 0) inferredStatus = '1';
|
|
1578
|
+
else if (recommendCount > 0 && featuredCount === 0 && latestCount === 0) inferredStatus = '0';
|
|
1575
1579
|
}
|
|
1576
1580
|
return {
|
|
1577
1581
|
ok: true,
|
|
@@ -1579,7 +1583,8 @@ function buildRecommendTabStateExpression() {
|
|
|
1579
1583
|
tabs,
|
|
1580
1584
|
layout: {
|
|
1581
1585
|
featured_count: featuredCount,
|
|
1582
|
-
recommend_count: recommendCount
|
|
1586
|
+
recommend_count: recommendCount,
|
|
1587
|
+
latest_count: latestCount
|
|
1583
1588
|
}
|
|
1584
1589
|
};
|
|
1585
1590
|
})()`;
|
|
@@ -1958,25 +1963,34 @@ function buildRecommendRefreshStateExpression() {
|
|
|
1958
1963
|
const finishedWrap = Array.from(doc.querySelectorAll('.finished-wrap')).find((el) => isVisible(el)) || null;
|
|
1959
1964
|
const refreshButton = Array.from(doc.querySelectorAll('.finished-wrap .btn.btn-refresh, .finished-wrap .btn-refresh, .no-data-refresh .btn-refresh'))
|
|
1960
1965
|
.find((el) => isVisible(el)) || null;
|
|
1961
|
-
const cards = Array.from(doc.querySelectorAll('ul.card-list > li.card-item'));
|
|
1962
|
-
const candidateCards = cards.filter((card) => card.querySelector('.card-inner[data-geekid]'));
|
|
1963
|
-
const
|
|
1964
|
-
const
|
|
1965
|
-
|
|
1966
|
-
|
|
1966
|
+
const cards = Array.from(doc.querySelectorAll('ul.card-list > li.card-item'));
|
|
1967
|
+
const candidateCards = cards.filter((card) => card.querySelector('.card-inner[data-geekid]'));
|
|
1968
|
+
const latestCards = Array.from(doc.querySelectorAll('.candidate-card-wrap .card-inner[data-geek], .candidate-card-wrap [data-geek]'));
|
|
1969
|
+
const tabs = Array.from(doc.querySelectorAll('li.tab-item[data-status], li[data-status][class*="tab"]'));
|
|
1970
|
+
const activeTab = tabs.find((node) => /(?:^|\\s)(?:curr|current|active|selected)(?:\\s|$)/i.test(String(node.className || ''))) || null;
|
|
1971
|
+
const activeStatus = activeTab ? String(activeTab.getAttribute('data-status') || '') : '';
|
|
1972
|
+
const inferredStatus = activeStatus
|
|
1973
|
+
|| (latestCards.length > 0 && candidateCards.length === 0 ? '1' : candidateCards.length > 0 ? '0' : '');
|
|
1974
|
+
const effectiveCandidates = inferredStatus === '1' ? latestCards : candidateCards;
|
|
1975
|
+
const finishedText = finishedWrap ? String(finishedWrap.textContent || '').replace(/\\s+/g, ' ').trim() : '';
|
|
1976
|
+
const buttonText = refreshButton ? String(refreshButton.textContent || '').replace(/\\s+/g, ' ').trim() : '';
|
|
1977
|
+
return {
|
|
1978
|
+
ok: true,
|
|
1967
1979
|
frame_url: (() => {
|
|
1968
1980
|
try { return String(frame.contentWindow.location.href || ''); } catch { return ''; }
|
|
1969
1981
|
})(),
|
|
1970
|
-
finished_wrap_visible: Boolean(finishedWrap),
|
|
1971
|
-
finished_wrap_text: finishedText || null,
|
|
1972
|
-
refresh_button_visible: Boolean(refreshButton),
|
|
1973
|
-
refresh_button_text: buttonText || null,
|
|
1974
|
-
candidate_count:
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
}
|
|
1982
|
+
finished_wrap_visible: Boolean(finishedWrap),
|
|
1983
|
+
finished_wrap_text: finishedText || null,
|
|
1984
|
+
refresh_button_visible: Boolean(refreshButton),
|
|
1985
|
+
refresh_button_text: buttonText || null,
|
|
1986
|
+
candidate_count: effectiveCandidates.length,
|
|
1987
|
+
recommend_candidate_count: candidateCards.length,
|
|
1988
|
+
latest_candidate_count: latestCards.length,
|
|
1989
|
+
total_card_count: Math.max(cards.length, latestCards.length),
|
|
1990
|
+
list_ready: effectiveCandidates.length > 0
|
|
1991
|
+
};
|
|
1992
|
+
})()`;
|
|
1993
|
+
}
|
|
1980
1994
|
|
|
1981
1995
|
function buildRecommendRefreshClickExpression() {
|
|
1982
1996
|
return `(() => {
|
package/src/cli.js
CHANGED
|
@@ -187,6 +187,7 @@ function normalizePageScope(value) {
|
|
|
187
187
|
const normalized = String(value || "").trim().toLowerCase();
|
|
188
188
|
if (!normalized) return null;
|
|
189
189
|
if (["recommend", "推荐", "推荐页", "推荐页面"].includes(normalized)) return "recommend";
|
|
190
|
+
if (["latest", "最新", "最新页", "最新页面"].includes(normalized)) return "latest";
|
|
190
191
|
if (["featured", "精选", "精选页", "精选页面", "精选牛人"].includes(normalized)) return "featured";
|
|
191
192
|
return null;
|
|
192
193
|
}
|