@reconcrap/boss-recommend-mcp 1.3.39 → 2.0.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.
Files changed (88) hide show
  1. package/README.md +86 -33
  2. package/package.json +62 -9
  3. package/skills/boss-chat/SKILL.md +5 -4
  4. package/skills/boss-recommend-pipeline/SKILL.md +21 -31
  5. package/skills/boss-recruit-pipeline/README.md +17 -0
  6. package/skills/boss-recruit-pipeline/SKILL.md +55 -0
  7. package/src/chat-mcp.js +1333 -0
  8. package/src/chat-runtime-config.js +559 -0
  9. package/src/cli.js +1254 -225
  10. package/src/core/browser/index.js +378 -0
  11. package/src/core/capture/index.js +298 -0
  12. package/src/core/cv-acquisition/index.js +219 -0
  13. package/src/core/greet-quota/index.js +54 -0
  14. package/src/core/infinite-list/index.js +459 -0
  15. package/src/core/reporting/legacy-csv.js +332 -0
  16. package/src/core/run/index.js +286 -0
  17. package/src/core/screening/index.js +1166 -0
  18. package/src/core/self-heal/index.js +848 -0
  19. package/src/domains/chat/cards.js +129 -0
  20. package/src/domains/chat/constants.js +183 -0
  21. package/src/domains/chat/detail.js +1369 -0
  22. package/src/domains/chat/index.js +7 -0
  23. package/src/domains/chat/jobs.js +334 -0
  24. package/src/domains/chat/page-guard.js +88 -0
  25. package/src/domains/chat/roots.js +56 -0
  26. package/src/domains/chat/run-service.js +1101 -0
  27. package/src/domains/recommend/actions.js +457 -0
  28. package/src/domains/recommend/cards.js +228 -0
  29. package/src/domains/recommend/constants.js +141 -0
  30. package/src/domains/recommend/detail.js +341 -0
  31. package/src/domains/recommend/filters.js +581 -0
  32. package/src/domains/recommend/index.js +10 -0
  33. package/src/domains/recommend/jobs.js +232 -0
  34. package/src/domains/recommend/refresh.js +204 -0
  35. package/src/domains/recommend/roots.js +78 -0
  36. package/src/domains/recommend/run-service.js +903 -0
  37. package/src/domains/recommend/scopes.js +245 -0
  38. package/src/domains/recruit/actions.js +277 -0
  39. package/src/domains/recruit/cards.js +66 -0
  40. package/src/domains/recruit/constants.js +130 -0
  41. package/src/domains/recruit/detail.js +414 -0
  42. package/src/domains/recruit/index.js +9 -0
  43. package/src/domains/recruit/instruction-parser.js +451 -0
  44. package/src/domains/recruit/refresh.js +40 -0
  45. package/src/domains/recruit/roots.js +67 -0
  46. package/src/domains/recruit/run-service.js +580 -0
  47. package/src/domains/recruit/search.js +1149 -0
  48. package/src/index.js +578 -419
  49. package/src/recommend-mcp.js +1257 -0
  50. package/src/recruit-mcp.js +1035 -0
  51. package/src/adapters.js +0 -3079
  52. package/src/boss-chat.js +0 -1037
  53. package/src/pipeline.js +0 -2249
  54. package/src/recommend-healing-config.js +0 -131
  55. package/src/recommend-healing-rules.json +0 -261
  56. package/src/self-heal.js +0 -2237
  57. package/src/test-adapters-runtime.js +0 -628
  58. package/src/test-boss-chat.js +0 -3196
  59. package/src/test-index-async.js +0 -498
  60. package/src/test-parser.js +0 -742
  61. package/src/test-pipeline.js +0 -2703
  62. package/src/test-run-state.js +0 -152
  63. package/src/test-self-heal.js +0 -224
  64. package/vendor/boss-chat-cli/README.md +0 -134
  65. package/vendor/boss-chat-cli/package.json +0 -53
  66. package/vendor/boss-chat-cli/src/app.js +0 -1501
  67. package/vendor/boss-chat-cli/src/browser/chat-page.js +0 -3562
  68. package/vendor/boss-chat-cli/src/cli.js +0 -1713
  69. package/vendor/boss-chat-cli/src/mcp/server.js +0 -149
  70. package/vendor/boss-chat-cli/src/mcp/tool-runtime.js +0 -193
  71. package/vendor/boss-chat-cli/src/runtime/async-run-state.js +0 -260
  72. package/vendor/boss-chat-cli/src/runtime/interaction.js +0 -102
  73. package/vendor/boss-chat-cli/src/runtime/run-control.js +0 -102
  74. package/vendor/boss-chat-cli/src/services/chrome-client.js +0 -107
  75. package/vendor/boss-chat-cli/src/services/llm.js +0 -1292
  76. package/vendor/boss-chat-cli/src/services/llm.test.js +0 -326
  77. package/vendor/boss-chat-cli/src/services/profile-store.js +0 -173
  78. package/vendor/boss-chat-cli/src/services/report-store.js +0 -317
  79. package/vendor/boss-chat-cli/src/services/resume-capture.js +0 -469
  80. package/vendor/boss-chat-cli/src/services/resume-network.js +0 -727
  81. package/vendor/boss-chat-cli/src/services/state-store.js +0 -90
  82. package/vendor/boss-chat-cli/src/utils/customer-key.js +0 -82
  83. package/vendor/boss-recommend-screen-cli/boss-recommend-screen-cli.cjs +0 -7072
  84. package/vendor/boss-recommend-screen-cli/scripts/capture-full-resume-canvas.cjs +0 -817
  85. package/vendor/boss-recommend-screen-cli/scripts/stitch_resume_chunks.py +0 -141
  86. package/vendor/boss-recommend-screen-cli/test-recoverable-resume-failures.cjs +0 -2423
  87. package/vendor/boss-recommend-search-cli/src/cli.js +0 -1698
  88. package/vendor/boss-recommend-search-cli/src/test-job-selection.js +0 -211
@@ -0,0 +1,129 @@
1
+ import { candidateKeyFromProfile } from "../../core/infinite-list/index.js";
2
+ import {
3
+ getAttributesMap,
4
+ getOuterHTML,
5
+ querySelectorAll,
6
+ sleep
7
+ } from "../../core/browser/index.js";
8
+ import {
9
+ htmlToText,
10
+ normalizeCandidateProfile,
11
+ normalizeText
12
+ } from "../../core/screening/index.js";
13
+ import { CHAT_CARD_SELECTORS } from "./constants.js";
14
+
15
+ function firstCandidateId(attributes = {}) {
16
+ return normalizeText(
17
+ attributes["data-id"]
18
+ || attributes["data-geekid"]
19
+ || attributes["data-geek"]
20
+ || attributes["data-uid"]
21
+ || attributes.key
22
+ || attributes.id
23
+ || ""
24
+ ) || null;
25
+ }
26
+
27
+ export async function findChatCandidateNodeIds(client, rootNodeId, {
28
+ selectors = CHAT_CARD_SELECTORS
29
+ } = {}) {
30
+ for (const selector of selectors) {
31
+ let nodeIds = [];
32
+ try {
33
+ nodeIds = await querySelectorAll(client, rootNodeId, selector);
34
+ } catch {
35
+ nodeIds = [];
36
+ }
37
+ if (nodeIds.length) {
38
+ return {
39
+ selector,
40
+ nodeIds
41
+ };
42
+ }
43
+ }
44
+ return {
45
+ selector: "",
46
+ nodeIds: []
47
+ };
48
+ }
49
+
50
+ export function chatCandidateKeyFromProfile(candidate = {}, options = {}) {
51
+ const id = normalizeText(candidate.id);
52
+ if (id) return `${candidate.domain || "chat"}:id:${id}`;
53
+ return candidateKeyFromProfile(candidate, options);
54
+ }
55
+
56
+ export async function findChatCandidateNodeIdById(client, rootNodeId, candidateId, {
57
+ selectors = CHAT_CARD_SELECTORS
58
+ } = {}) {
59
+ const expectedId = normalizeText(candidateId);
60
+ if (!expectedId) return 0;
61
+ const result = await findChatCandidateNodeIds(client, rootNodeId, { selectors });
62
+ for (const nodeId of result.nodeIds || []) {
63
+ try {
64
+ const attributes = await getAttributesMap(client, nodeId);
65
+ if (firstCandidateId(attributes) === expectedId) return nodeId;
66
+ } catch {
67
+ // Boss can remount chat cards while the list is active; keep scanning.
68
+ }
69
+ }
70
+ return 0;
71
+ }
72
+
73
+ export async function waitForChatCandidateNodeIds(client, rootNodeId, {
74
+ selectors = CHAT_CARD_SELECTORS,
75
+ timeoutMs = 12000,
76
+ intervalMs = 300
77
+ } = {}) {
78
+ const started = Date.now();
79
+ let result = {
80
+ selector: "",
81
+ nodeIds: []
82
+ };
83
+ while (Date.now() - started <= timeoutMs) {
84
+ result = await findChatCandidateNodeIds(client, rootNodeId, { selectors });
85
+ if (result.nodeIds.length) return result;
86
+ await sleep(intervalMs);
87
+ }
88
+ return result;
89
+ }
90
+
91
+ export async function readChatCardCandidate(client, cardNodeId, {
92
+ targetUrl = "",
93
+ source = "chat-domain-card",
94
+ metadata = {}
95
+ } = {}) {
96
+ const [attributes, outerHTML] = await Promise.all([
97
+ getAttributesMap(client, cardNodeId),
98
+ getOuterHTML(client, cardNodeId)
99
+ ]);
100
+ return normalizeCandidateProfile({
101
+ domain: "chat",
102
+ source,
103
+ id: firstCandidateId(attributes),
104
+ text: htmlToText(outerHTML),
105
+ attributes,
106
+ metadata: {
107
+ target_url: targetUrl,
108
+ card_node_id: cardNodeId,
109
+ html_length: outerHTML.length,
110
+ ...metadata
111
+ }
112
+ });
113
+ }
114
+
115
+ export async function readFirstChatCardCandidate(client, rootNodeId, options = {}) {
116
+ const cardResult = await findChatCandidateNodeIds(client, rootNodeId, options);
117
+ if (!cardResult.nodeIds.length) {
118
+ throw new Error("No chat candidate conversation cards found");
119
+ }
120
+
121
+ const candidate = await readChatCardCandidate(client, cardResult.nodeIds[0], options);
122
+ return {
123
+ card_count: cardResult.nodeIds.length,
124
+ selector: cardResult.selector,
125
+ first_card_node_id: cardResult.nodeIds[0],
126
+ card_node_ids: cardResult.nodeIds,
127
+ candidate
128
+ };
129
+ }
@@ -0,0 +1,183 @@
1
+ export const CHAT_TARGET_URL = "https://www.zhipin.com/web/chat/index";
2
+
3
+ export const CHAT_CARD_SELECTORS = Object.freeze([
4
+ ".geek-item[data-id]",
5
+ "div[role=\"listitem\"] .geek-item[data-id]",
6
+ ".geek-item",
7
+ ".geek-item-wrap",
8
+ "div[role=\"listitem\"]"
9
+ ]);
10
+
11
+ export const CHAT_JOB_LABEL_SELECTORS = Object.freeze([
12
+ ".chat-job .chat-select-job",
13
+ ".chat-job .dropmenu-label",
14
+ ".chat-top-job .ui-dropmenu-label",
15
+ ".job-select .ui-dropmenu-label"
16
+ ]);
17
+
18
+ export const CHAT_JOB_OPTION_SELECTORS = Object.freeze([
19
+ ".chat-job .ui-dropmenu-list li",
20
+ ".chat-top-job .ui-dropmenu-list li",
21
+ ".job-select .ui-dropmenu-list li",
22
+ ".chat-job li[value]"
23
+ ]);
24
+
25
+ export const CHAT_JOB_TRIGGER_SELECTORS = Object.freeze([
26
+ ".chat-job .chat-select-job",
27
+ ".chat-job .dropmenu-label",
28
+ ".chat-job",
29
+ ".chat-top-job .ui-dropmenu-label",
30
+ ".job-select .ui-dropmenu-label",
31
+ ".chat-job-select",
32
+ ".chat-job-selector",
33
+ ".job-selecter",
34
+ ".job-selector",
35
+ ".job-select-wrap",
36
+ ".job-select-box",
37
+ ".job-wrap",
38
+ ".chat-job-name",
39
+ ".top-chat-search"
40
+ ]);
41
+
42
+ export const CHAT_JOB_FALLBACK_SELECTORS = Object.freeze([
43
+ ".source-job[title]",
44
+ ".source-job"
45
+ ]);
46
+
47
+ export const CHAT_ACTIVE_CANDIDATE_SELECTORS = Object.freeze([
48
+ ".geek-item.selected[data-id]",
49
+ ".geek-item.selected",
50
+ ".geek-item.active[data-id]",
51
+ ".geek-item.active"
52
+ ]);
53
+
54
+ export const CHAT_PRIMARY_LABEL_SELECTORS = Object.freeze([
55
+ ".label-list .chat-label-item",
56
+ ".chat-label-item"
57
+ ]);
58
+
59
+ export const CHAT_MESSAGE_FILTER_SELECTORS = Object.freeze([
60
+ ".chat-message-filter-left span",
61
+ ".chat-message-filter-left [class*=\"item\"]",
62
+ ".chat-message-filter span",
63
+ ".chat-message-filter [class*=\"item\"]",
64
+ '[role="tab"]',
65
+ "button",
66
+ "span"
67
+ ]);
68
+
69
+ export const CHAT_ONLINE_RESUME_BUTTON_SELECTORS = Object.freeze([
70
+ "a.btn.resume-btn-online",
71
+ "a.resume-btn-online",
72
+ ".btn.resume-btn-online",
73
+ ".resume-btn-online"
74
+ ]);
75
+
76
+ export const CHAT_ATTACHMENT_RESUME_BUTTON_SELECTORS = Object.freeze([
77
+ ".resume-btn-file",
78
+ ".btn.resume-btn-file",
79
+ '[class*="resume-btn-file"]'
80
+ ]);
81
+
82
+ export const CHAT_ASK_RESUME_BUTTON_SELECTORS = Object.freeze([
83
+ "span.operate-btn",
84
+ ".operate-btn",
85
+ '[class*="operate"]',
86
+ '[class*="resume"]',
87
+ "button",
88
+ "a",
89
+ "span"
90
+ ]);
91
+
92
+ export const CHAT_EDITOR_SELECTORS = Object.freeze([
93
+ "#boss-chat-editor-input",
94
+ ".conversation-editor #boss-chat-editor-input",
95
+ ".conversation-editor .boss-chat-editor-input",
96
+ '[contenteditable="true"]',
97
+ "textarea"
98
+ ]);
99
+
100
+ export const CHAT_SEND_BUTTON_SELECTORS = Object.freeze([
101
+ ".conversation-editor .submit.active",
102
+ ".conversation-editor .submit-content .submit.active",
103
+ ".submit.active",
104
+ ".conversation-editor .submit-content .submit",
105
+ ".conversation-editor .submit",
106
+ ".submit-content .submit",
107
+ ".submit"
108
+ ]);
109
+
110
+ export const CHAT_CONFIRM_REQUEST_RESUME_SELECTORS = Object.freeze([
111
+ "span.boss-btn-primary.boss-btn",
112
+ ".boss-btn-primary.boss-btn",
113
+ ".boss-popup__wrapper .boss-btn-primary",
114
+ ".boss-dialog .boss-btn-primary",
115
+ ".boss-btn-primary",
116
+ "button",
117
+ "a",
118
+ "span"
119
+ ]);
120
+
121
+ export const CHAT_MESSAGE_LIST_SELECTORS = Object.freeze([
122
+ ".chat-message-list",
123
+ ".message-list",
124
+ ".chat-record",
125
+ ".conversation-message-list"
126
+ ]);
127
+
128
+ export const CHAT_RESUME_MODAL_SELECTORS = Object.freeze([
129
+ ".boss-popup__wrapper",
130
+ ".new-chat-resume-dialog-main-ui",
131
+ ".dialog-wrap.active",
132
+ ".boss-dialog",
133
+ ".geek-detail-modal",
134
+ ".modal",
135
+ ".resume-container",
136
+ ".resume-content-wrap",
137
+ ".resume-common-wrap",
138
+ ".resume-detail",
139
+ ".resume-recommend"
140
+ ]);
141
+
142
+ export const CHAT_RESUME_CONTENT_SELECTORS = Object.freeze([
143
+ ".resume-center-side .resume-detail-wrap",
144
+ ".resume-detail-wrap",
145
+ ".resume-content-wrap",
146
+ ".resume-common-wrap",
147
+ ".resume-detail",
148
+ ".resume-recommend",
149
+ ".new-resume-online-main-ui",
150
+ ".new-chat-resume-dialog-main-ui",
151
+ "canvas#resume"
152
+ ]);
153
+
154
+ export const CHAT_RESUME_IFRAME_SELECTORS = Object.freeze([
155
+ 'iframe[src*="/web/frame/c-resume/"]',
156
+ 'iframe[src*="resume"]',
157
+ 'iframe[name*="resume"]'
158
+ ]);
159
+
160
+ export const CHAT_RESUME_CLOSE_SELECTORS = Object.freeze([
161
+ ".boss-popup__close",
162
+ ".boss-dialog__close",
163
+ ".popup-close",
164
+ ".modal-close",
165
+ ".dialog-close",
166
+ ".close-btn",
167
+ ".icon-close",
168
+ '[aria-label*="关闭"]',
169
+ '[title*="关闭"]',
170
+ '[class*="close"]'
171
+ ]);
172
+
173
+ export const CHAT_PROFILE_NETWORK_PATTERNS = Object.freeze([
174
+ /\/wapi\/zpjob\/view\/geek\/info(?:\/v2)?\b/i,
175
+ /\/wapi\/zpjob\/chat\/geek\/info\b/i,
176
+ /\/wapi\/zpchat\/boss\/historyMsg\b/i,
177
+ /\/wapi\/zpchat\/session\/bossEnter\b/i,
178
+ /\/wapi\/zpitem\/web\/boss\/[^?#]*\/geek\/info\b/i,
179
+ /\/boss\/[^?#]*\/geek\/info\b/i,
180
+ /\/geek\/info\b/i,
181
+ /\/web\/frame\/c-resume\//i,
182
+ /resume/i
183
+ ]);