@reconcrap/boss-recommend-mcp 2.0.22 → 2.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reconcrap/boss-recommend-mcp",
3
- "version": "2.0.22",
3
+ "version": "2.0.23",
4
4
  "description": "Unified MCP pipeline for recommend-page filtering and screening on Boss Zhipin",
5
5
  "keywords": [
6
6
  "boss",
@@ -336,6 +336,39 @@ function isRequestedResumeText(text = "") {
336
336
  );
337
337
  }
338
338
 
339
+ function isResumeRequestSentMessageText(text = "") {
340
+ const normalized = normalizeDetailText(text);
341
+ return Boolean(
342
+ normalized.includes("简历请求已发送")
343
+ || normalized.includes("已发送简历")
344
+ || normalized.includes("已求简历")
345
+ || normalized.includes("已索要简历")
346
+ || normalized.includes("已发送")
347
+ );
348
+ }
349
+
350
+ function countTextOccurrences(text = "", needle = "") {
351
+ if (!needle) return 0;
352
+ let count = 0;
353
+ let index = 0;
354
+ while (index < text.length) {
355
+ const found = text.indexOf(needle, index);
356
+ if (found < 0) break;
357
+ count += 1;
358
+ index = found + needle.length;
359
+ }
360
+ return count;
361
+ }
362
+
363
+ function countResumeRequestSentMessageMarkers(lines = []) {
364
+ const markers = ["简历请求已发送", "已发送简历", "已求简历", "已索要简历", "已发送"];
365
+ return lines.reduce((total, line) => (
366
+ total + markers.reduce((lineTotal, marker) => (
367
+ lineTotal + countTextOccurrences(line, marker)
368
+ ), 0)
369
+ ), 0);
370
+ }
371
+
339
372
  function isRequestedResumeControlTarget(target = {}) {
340
373
  const label = normalizeDetailText(target.label);
341
374
  const className = String(target.attributes?.class || "");
@@ -1034,13 +1067,6 @@ export async function clickChatAskResume(client, {
1034
1067
  control: state.attachment_resume
1035
1068
  };
1036
1069
  }
1037
- if (state.already_requested_resume) {
1038
- return {
1039
- ok: true,
1040
- already_requested: true,
1041
- control: state.requested_resume
1042
- };
1043
- }
1044
1070
  if (state.ask_resume?.node_id && !state.ask_resume.disabled) {
1045
1071
  try {
1046
1072
  if (state.ask_resume.center) {
@@ -1063,6 +1089,13 @@ export async function clickChatAskResume(client, {
1063
1089
  };
1064
1090
  }
1065
1091
  }
1092
+ if (state.already_requested_resume) {
1093
+ return {
1094
+ ok: true,
1095
+ already_requested: true,
1096
+ control: state.requested_resume
1097
+ };
1098
+ }
1066
1099
  await sleep(250);
1067
1100
  }
1068
1101
  return {
@@ -1151,11 +1184,12 @@ export async function getChatResumeRequestMessageState(client) {
1151
1184
  text = htmlToText(await getOuterHTML(client, nodeId));
1152
1185
  } catch {}
1153
1186
  const lines = text.split(/\r?\n/).map(normalizeDetailText).filter(Boolean);
1154
- const matching = lines.filter((line) => line.includes("简历请求已发送"));
1187
+ const matching = lines.filter((line) => isResumeRequestSentMessageText(line));
1188
+ const count = countResumeRequestSentMessageMarkers(lines);
1155
1189
  return {
1156
1190
  ok: Boolean(text),
1157
1191
  selector: messageRoot?.selector || "top",
1158
- count: matching.length,
1192
+ count,
1159
1193
  last_text: matching[matching.length - 1] || lines[lines.length - 1] || "",
1160
1194
  recent: lines.slice(-12)
1161
1195
  };
@@ -1170,9 +1204,7 @@ export async function waitForChatResumeRequestMessage(client, {
1170
1204
  let state = null;
1171
1205
  while (Date.now() - started <= timeoutMs) {
1172
1206
  state = await getChatResumeRequestMessageState(client);
1173
- const observed = state.count > baselineCount
1174
- || state.last_text.includes("简历请求已发送")
1175
- || state.recent.some((item) => item.includes("简历请求已发送"));
1207
+ const observed = state.count > baselineCount;
1176
1208
  if (observed) {
1177
1209
  return {
1178
1210
  observed: true,
@@ -1204,14 +1236,6 @@ export async function requestChatResumeForPassedCandidate(client, {
1204
1236
  initial_state: initialState
1205
1237
  };
1206
1238
  }
1207
- if (initialState.already_requested_resume) {
1208
- return {
1209
- requested: true,
1210
- skipped: true,
1211
- reason: "resume_already_requested",
1212
- initial_state: initialState
1213
- };
1214
- }
1215
1239
  if (dryRun) {
1216
1240
  return {
1217
1241
  requested: false,