@reconcrap/boss-recommend-mcp 2.1.14 → 2.1.16
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 +34 -5
- package/package.json +8 -7
- 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 +127 -88
- package/src/core/greet-quota/index.js +17 -0
- package/src/core/reporting/legacy-csv.js +5 -1
- package/src/domains/chat/detail.js +79 -47
- package/src/domains/chat/run-service.js +400 -158
- package/src/domains/recommend/colleague-contact.js +333 -0
- package/src/domains/recommend/index.js +1 -0
- package/src/domains/recommend/run-service.js +166 -77
- package/src/domains/recruit/constants.js +69 -0
- package/src/domains/recruit/instruction-parser.js +403 -86
- package/src/domains/recruit/run-service.js +320 -11
- package/src/domains/recruit/search.js +2118 -306
- package/src/index.js +38 -23
- package/src/parser.js +45 -2
- package/src/recommend-mcp.js +92 -18
- package/src/recruit-mcp.js +236 -3
|
@@ -51,7 +51,8 @@ import {
|
|
|
51
51
|
makeForbiddenChatResumeNavigationError
|
|
52
52
|
} from "./page-guard.js";
|
|
53
53
|
|
|
54
|
-
export const CHAT_UNSAFE_ONLINE_RESUME_LINK_CODE = "CHAT_UNSAFE_ONLINE_RESUME_LINK";
|
|
54
|
+
export const CHAT_UNSAFE_ONLINE_RESUME_LINK_CODE = "CHAT_UNSAFE_ONLINE_RESUME_LINK";
|
|
55
|
+
export const CHAT_ONLINE_RESUME_MODAL_NOT_OPEN_CODE = "CHAT_ONLINE_RESUME_MODAL_NOT_OPEN";
|
|
55
56
|
|
|
56
57
|
const CHAT_CONVERSATION_CONTROL_SCOPE_SELECTORS = Object.freeze([
|
|
57
58
|
".conversation-main",
|
|
@@ -128,10 +129,15 @@ export function makeUnsafeChatOnlineResumeLinkError(target = {}, buttonHTML = ""
|
|
|
128
129
|
return error;
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
export function isUnsafeChatOnlineResumeLinkError(error) {
|
|
132
|
-
return error?.code === CHAT_UNSAFE_ONLINE_RESUME_LINK_CODE
|
|
133
|
-
|| /CHAT_UNSAFE_ONLINE_RESUME_LINK/i.test(String(error?.message || error || ""));
|
|
134
|
-
}
|
|
132
|
+
export function isUnsafeChatOnlineResumeLinkError(error) {
|
|
133
|
+
return error?.code === CHAT_UNSAFE_ONLINE_RESUME_LINK_CODE
|
|
134
|
+
|| /CHAT_UNSAFE_ONLINE_RESUME_LINK/i.test(String(error?.message || error || ""));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function isChatOnlineResumeModalOpenFailureError(error) {
|
|
138
|
+
return error?.code === CHAT_ONLINE_RESUME_MODAL_NOT_OPEN_CODE
|
|
139
|
+
|| /Chat online resume modal did not open/i.test(String(error?.message || error || ""));
|
|
140
|
+
}
|
|
135
141
|
|
|
136
142
|
export function createChatProfileNetworkRecorder(client) {
|
|
137
143
|
const events = [];
|
|
@@ -242,9 +248,9 @@ function chatCandidateIdFromAttributes(attributes = {}) {
|
|
|
242
248
|
);
|
|
243
249
|
}
|
|
244
250
|
|
|
245
|
-
async function hydrateActiveChatCandidate(client, activeCandidate = null) {
|
|
246
|
-
if (!activeCandidate?.node_id) return activeCandidate;
|
|
247
|
-
let attributes = {};
|
|
251
|
+
async function hydrateActiveChatCandidate(client, activeCandidate = null) {
|
|
252
|
+
if (!activeCandidate?.node_id) return activeCandidate;
|
|
253
|
+
let attributes = {};
|
|
248
254
|
let outerHTML = "";
|
|
249
255
|
try {
|
|
250
256
|
[attributes, outerHTML] = await Promise.all([
|
|
@@ -258,12 +264,25 @@ async function hydrateActiveChatCandidate(client, activeCandidate = null) {
|
|
|
258
264
|
candidate_id: chatCandidateIdFromAttributes(attributes) || null,
|
|
259
265
|
label: normalizeDetailText(htmlToText(outerHTML)),
|
|
260
266
|
outer_html_length: outerHTML.length
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
export async function
|
|
265
|
-
|
|
266
|
-
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export async function readChatActiveCandidateState(client) {
|
|
271
|
+
const rootState = await getChatRoots(client);
|
|
272
|
+
const activeCandidate = await queryFirstAcrossChatRoots(
|
|
273
|
+
client,
|
|
274
|
+
rootState.roots,
|
|
275
|
+
CHAT_ACTIVE_CANDIDATE_SELECTORS
|
|
276
|
+
);
|
|
277
|
+
return {
|
|
278
|
+
roots: rootState.roots,
|
|
279
|
+
active_candidate: await hydrateActiveChatCandidate(client, activeCandidate)
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export async function waitForChatOnlineResumeButton(client, {
|
|
284
|
+
timeoutMs = 12000,
|
|
285
|
+
intervalMs = 250,
|
|
267
286
|
expectedCandidateId = ""
|
|
268
287
|
} = {}) {
|
|
269
288
|
const started = Date.now();
|
|
@@ -982,10 +1001,12 @@ export async function openChatOnlineResume(client, {
|
|
|
982
1001
|
}
|
|
983
1002
|
}
|
|
984
1003
|
|
|
985
|
-
const error = new Error("Chat online resume modal did not open");
|
|
986
|
-
error.
|
|
987
|
-
|
|
988
|
-
|
|
1004
|
+
const error = new Error("Chat online resume modal did not open");
|
|
1005
|
+
error.code = CHAT_ONLINE_RESUME_MODAL_NOT_OPEN_CODE;
|
|
1006
|
+
error.retryable = true;
|
|
1007
|
+
error.attempts = attempts;
|
|
1008
|
+
throw error;
|
|
1009
|
+
}
|
|
989
1010
|
|
|
990
1011
|
export async function readChatConversationReadyState(client) {
|
|
991
1012
|
const rootState = await getChatRoots(client);
|
|
@@ -1173,20 +1194,21 @@ export async function sendChatMessage(client, expectedText = "", {
|
|
|
1173
1194
|
};
|
|
1174
1195
|
}
|
|
1175
1196
|
|
|
1176
|
-
export async function clickChatAskResume(client, {
|
|
1177
|
-
timeoutMs = 8000,
|
|
1178
|
-
settleMs = 700
|
|
1179
|
-
|
|
1197
|
+
export async function clickChatAskResume(client, {
|
|
1198
|
+
timeoutMs = 8000,
|
|
1199
|
+
settleMs = 700,
|
|
1200
|
+
skipWhenAttachmentResumeAvailable = true
|
|
1201
|
+
} = {}) {
|
|
1180
1202
|
const started = Date.now();
|
|
1181
1203
|
let lastState = null;
|
|
1182
1204
|
let lastDisabledAskResume = null;
|
|
1183
1205
|
while (Date.now() - started <= timeoutMs) {
|
|
1184
1206
|
const state = await readChatConversationReadyState(client);
|
|
1185
1207
|
lastState = state;
|
|
1186
|
-
if (state.attachment_resume_enabled) {
|
|
1187
|
-
return {
|
|
1188
|
-
ok: true,
|
|
1189
|
-
already_requested: true,
|
|
1208
|
+
if (skipWhenAttachmentResumeAvailable && state.attachment_resume_enabled) {
|
|
1209
|
+
return {
|
|
1210
|
+
ok: true,
|
|
1211
|
+
already_requested: true,
|
|
1190
1212
|
attachment_resume_available: true,
|
|
1191
1213
|
control: state.attachment_resume
|
|
1192
1214
|
};
|
|
@@ -1368,23 +1390,32 @@ export async function waitForChatResumeRequestMessage(client, {
|
|
|
1368
1390
|
};
|
|
1369
1391
|
}
|
|
1370
1392
|
|
|
1371
|
-
export async function requestChatResumeForPassedCandidate(client, {
|
|
1372
|
-
greetingText = "Hi同学,能麻烦发下简历吗?",
|
|
1373
|
-
maxAttempts = 3,
|
|
1374
|
-
askResumeTimeoutMs = 8000,
|
|
1375
|
-
dryRun = false
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
const
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1393
|
+
export async function requestChatResumeForPassedCandidate(client, {
|
|
1394
|
+
greetingText = "Hi同学,能麻烦发下简历吗?",
|
|
1395
|
+
maxAttempts = 3,
|
|
1396
|
+
askResumeTimeoutMs = 8000,
|
|
1397
|
+
dryRun = false,
|
|
1398
|
+
skipWhenAttachmentResumeAvailable = true
|
|
1399
|
+
} = {}) {
|
|
1400
|
+
const effectiveGreetingText = normalizeDetailText(greetingText) || "Hi同学,能麻烦发下简历吗?";
|
|
1401
|
+
const initialState = await readChatConversationReadyState(client);
|
|
1402
|
+
if (skipWhenAttachmentResumeAvailable && initialState.attachment_resume_enabled) {
|
|
1403
|
+
return {
|
|
1404
|
+
requested: false,
|
|
1405
|
+
skipped: true,
|
|
1406
|
+
reason: "attachment_resume_already_available",
|
|
1407
|
+
initial_state: initialState
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
if (initialState.already_requested_resume) {
|
|
1411
|
+
return {
|
|
1412
|
+
requested: false,
|
|
1413
|
+
skipped: true,
|
|
1414
|
+
reason: "resume_request_already_pending",
|
|
1415
|
+
initial_state: initialState
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
if (dryRun) {
|
|
1388
1419
|
return {
|
|
1389
1420
|
requested: false,
|
|
1390
1421
|
skipped: false,
|
|
@@ -1416,10 +1447,11 @@ export async function requestChatResumeForPassedCandidate(client, {
|
|
|
1416
1447
|
|
|
1417
1448
|
const attempts = [];
|
|
1418
1449
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
1419
|
-
const before = await getChatResumeRequestMessageState(client);
|
|
1420
|
-
const askResult = await clickChatAskResume(client, {
|
|
1421
|
-
timeoutMs: askResumeTimeoutMs
|
|
1422
|
-
|
|
1450
|
+
const before = await getChatResumeRequestMessageState(client);
|
|
1451
|
+
const askResult = await clickChatAskResume(client, {
|
|
1452
|
+
timeoutMs: askResumeTimeoutMs,
|
|
1453
|
+
skipWhenAttachmentResumeAvailable
|
|
1454
|
+
});
|
|
1423
1455
|
let confirmResult = {
|
|
1424
1456
|
confirmed: false,
|
|
1425
1457
|
assumed_requested: Boolean(askResult.already_requested),
|