@reconcrap/boss-recommend-mcp 2.1.21 → 2.1.22

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 (67) hide show
  1. package/README.md +5 -2
  2. package/bin/boss-recommend-mcp.js +4 -4
  3. package/config/screening-config.example.json +33 -33
  4. package/package.json +8 -8
  5. package/scripts/install-macos.sh +280 -280
  6. package/scripts/postinstall.cjs +44 -44
  7. package/skills/boss-chat/README.md +42 -42
  8. package/skills/boss-chat/SKILL.md +106 -106
  9. package/skills/boss-recommend-pipeline/README.md +13 -13
  10. package/skills/boss-recommend-pipeline/SKILL.md +219 -214
  11. package/skills/boss-recruit-pipeline/README.md +19 -19
  12. package/skills/boss-recruit-pipeline/SKILL.md +89 -89
  13. package/src/chat-mcp.js +127 -127
  14. package/src/chat-runtime-config.js +775 -775
  15. package/src/cli.js +573 -573
  16. package/src/core/boss-cards/index.js +199 -199
  17. package/src/core/browser/index.js +2419 -2415
  18. package/src/core/capture/index.js +1201 -1201
  19. package/src/core/cv-acquisition/index.js +238 -238
  20. package/src/core/cv-capture-target/index.js +299 -299
  21. package/src/core/greet-quota/index.js +71 -71
  22. package/src/core/infinite-list/index.js +1326 -1326
  23. package/src/core/reporting/legacy-csv.js +334 -332
  24. package/src/core/run/index.js +32 -32
  25. package/src/core/run/timing.js +33 -33
  26. package/src/core/screening/index.js +2135 -2135
  27. package/src/core/self-heal/index.js +973 -973
  28. package/src/core/self-heal/viewport.js +564 -564
  29. package/src/detached-worker.js +99 -99
  30. package/src/domains/chat/cards.js +137 -137
  31. package/src/domains/chat/constants.js +9 -9
  32. package/src/domains/chat/detail.js +113 -113
  33. package/src/domains/chat/index.js +7 -7
  34. package/src/domains/chat/jobs.js +620 -620
  35. package/src/domains/chat/page-guard.js +122 -122
  36. package/src/domains/chat/roots.js +56 -56
  37. package/src/domains/chat/run-service.js +571 -571
  38. package/src/domains/common/account-rights-panel.js +314 -314
  39. package/src/domains/common/recovery-settle.js +159 -159
  40. package/src/domains/recommend/actions.js +472 -472
  41. package/src/domains/recommend/cards.js +243 -243
  42. package/src/domains/recommend/colleague-contact.js +333 -333
  43. package/src/domains/recommend/constants.js +228 -159
  44. package/src/domains/recommend/detail.js +650 -650
  45. package/src/domains/recommend/filters.js +748 -377
  46. package/src/domains/recommend/index.js +4 -3
  47. package/src/domains/recommend/jobs.js +542 -542
  48. package/src/domains/recommend/location.js +736 -0
  49. package/src/domains/recommend/refresh.js +504 -361
  50. package/src/domains/recommend/roots.js +80 -80
  51. package/src/domains/recommend/run-service.js +987 -854
  52. package/src/domains/recommend/scopes.js +246 -246
  53. package/src/domains/recruit/actions.js +277 -277
  54. package/src/domains/recruit/cards.js +74 -74
  55. package/src/domains/recruit/constants.js +236 -236
  56. package/src/domains/recruit/detail.js +588 -588
  57. package/src/domains/recruit/index.js +9 -9
  58. package/src/domains/recruit/instruction-parser.js +866 -866
  59. package/src/domains/recruit/refresh.js +45 -45
  60. package/src/domains/recruit/roots.js +68 -68
  61. package/src/domains/recruit/run-service.js +1620 -1620
  62. package/src/domains/recruit/search.js +3229 -3229
  63. package/src/index.js +13 -0
  64. package/src/parser.js +376 -8
  65. package/src/recommend-mcp.js +929 -915
  66. package/src/recommend-scheduler.js +496 -496
  67. package/src/recruit-mcp.js +2121 -2121
@@ -12,17 +12,17 @@ import {
12
12
  querySelectorAll,
13
13
  sleep
14
14
  } from "../../core/browser/index.js";
15
- import {
16
- buildScreeningCandidateFromDetail,
17
- htmlToText
18
- } from "../../core/screening/index.js";
19
- import {
20
- closeBossAccountRightsBlockingPanel,
21
- findBossAccountRightsBlockingPanel
22
- } from "../common/account-rights-panel.js";
23
- import {
24
- CHAT_ACTIVE_CANDIDATE_SELECTORS,
25
- CHAT_ASK_RESUME_BUTTON_SELECTORS,
15
+ import {
16
+ buildScreeningCandidateFromDetail,
17
+ htmlToText
18
+ } from "../../core/screening/index.js";
19
+ import {
20
+ closeBossAccountRightsBlockingPanel,
21
+ findBossAccountRightsBlockingPanel
22
+ } from "../common/account-rights-panel.js";
23
+ import {
24
+ CHAT_ACTIVE_CANDIDATE_SELECTORS,
25
+ CHAT_ASK_RESUME_BUTTON_SELECTORS,
26
26
  CHAT_ATTACHMENT_RESUME_BUTTON_SELECTORS,
27
27
  CHAT_BLOCKING_PANEL_CLOSE_SELECTORS,
28
28
  CHAT_BLOCKING_PANEL_TEXT_QUERIES,
@@ -51,8 +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";
55
- export const CHAT_ONLINE_RESUME_MODAL_NOT_OPEN_CODE = "CHAT_ONLINE_RESUME_MODAL_NOT_OPEN";
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";
56
56
 
57
57
  const CHAT_CONVERSATION_CONTROL_SCOPE_SELECTORS = Object.freeze([
58
58
  ".conversation-main",
@@ -129,15 +129,15 @@ export function makeUnsafeChatOnlineResumeLinkError(target = {}, buttonHTML = ""
129
129
  return error;
130
130
  }
131
131
 
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
- }
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
+ }
141
141
 
142
142
  export function createChatProfileNetworkRecorder(client) {
143
143
  const events = [];
@@ -248,9 +248,9 @@ function chatCandidateIdFromAttributes(attributes = {}) {
248
248
  );
249
249
  }
250
250
 
251
- async function hydrateActiveChatCandidate(client, activeCandidate = null) {
252
- if (!activeCandidate?.node_id) return activeCandidate;
253
- let attributes = {};
251
+ async function hydrateActiveChatCandidate(client, activeCandidate = null) {
252
+ if (!activeCandidate?.node_id) return activeCandidate;
253
+ let attributes = {};
254
254
  let outerHTML = "";
255
255
  try {
256
256
  [attributes, outerHTML] = await Promise.all([
@@ -264,25 +264,25 @@ async function hydrateActiveChatCandidate(client, activeCandidate = null) {
264
264
  candidate_id: chatCandidateIdFromAttributes(attributes) || null,
265
265
  label: normalizeDetailText(htmlToText(outerHTML)),
266
266
  outer_html_length: outerHTML.length
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
+ };
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,
286
286
  expectedCandidateId = ""
287
287
  } = {}) {
288
288
  const started = Date.now();
@@ -758,29 +758,29 @@ export async function quickChatResumeModalOpenProbe(client, {
758
758
  };
759
759
  }
760
760
 
761
- export async function findChatBlockingPanel(client, {
762
- textQueries = CHAT_BLOCKING_PANEL_TEXT_QUERIES
763
- } = {}) {
764
- const panel = await findBossAccountRightsBlockingPanel(client, { textQueries });
765
- return panel.open
766
- ? { ...panel, reason: "blocking_panel_text_visible" }
767
- : panel;
768
- }
769
-
770
- export async function closeChatBlockingPanels(client, {
771
- attemptsLimit = 2,
772
- closeSelectors = CHAT_BLOCKING_PANEL_CLOSE_SELECTORS,
773
- textQueries = CHAT_BLOCKING_PANEL_TEXT_QUERIES
774
- } = {}) {
775
- return closeBossAccountRightsBlockingPanel(client, {
776
- attemptsLimit,
777
- closeSelectors,
778
- resolveRoots: getChatRoots,
779
- textQueries
780
- });
781
- }
782
-
783
- export async function readChatResumeHtml(client, resumeState) {
761
+ export async function findChatBlockingPanel(client, {
762
+ textQueries = CHAT_BLOCKING_PANEL_TEXT_QUERIES
763
+ } = {}) {
764
+ const panel = await findBossAccountRightsBlockingPanel(client, { textQueries });
765
+ return panel.open
766
+ ? { ...panel, reason: "blocking_panel_text_visible" }
767
+ : panel;
768
+ }
769
+
770
+ export async function closeChatBlockingPanels(client, {
771
+ attemptsLimit = 2,
772
+ closeSelectors = CHAT_BLOCKING_PANEL_CLOSE_SELECTORS,
773
+ textQueries = CHAT_BLOCKING_PANEL_TEXT_QUERIES
774
+ } = {}) {
775
+ return closeBossAccountRightsBlockingPanel(client, {
776
+ attemptsLimit,
777
+ closeSelectors,
778
+ resolveRoots: getChatRoots,
779
+ textQueries
780
+ });
781
+ }
782
+
783
+ export async function readChatResumeHtml(client, resumeState) {
784
784
  let popupHTML = "";
785
785
  let contentHTML = "";
786
786
  let resumeIframeHTML = "";
@@ -1001,12 +1001,12 @@ export async function openChatOnlineResume(client, {
1001
1001
  }
1002
1002
  }
1003
1003
 
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
- }
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
+ }
1010
1010
 
1011
1011
  export async function readChatConversationReadyState(client) {
1012
1012
  const rootState = await getChatRoots(client);
@@ -1194,21 +1194,21 @@ export async function sendChatMessage(client, expectedText = "", {
1194
1194
  };
1195
1195
  }
1196
1196
 
1197
- export async function clickChatAskResume(client, {
1198
- timeoutMs = 8000,
1199
- settleMs = 700,
1200
- skipWhenAttachmentResumeAvailable = true
1201
- } = {}) {
1197
+ export async function clickChatAskResume(client, {
1198
+ timeoutMs = 8000,
1199
+ settleMs = 700,
1200
+ skipWhenAttachmentResumeAvailable = true
1201
+ } = {}) {
1202
1202
  const started = Date.now();
1203
1203
  let lastState = null;
1204
1204
  let lastDisabledAskResume = null;
1205
1205
  while (Date.now() - started <= timeoutMs) {
1206
1206
  const state = await readChatConversationReadyState(client);
1207
1207
  lastState = state;
1208
- if (skipWhenAttachmentResumeAvailable && state.attachment_resume_enabled) {
1209
- return {
1210
- ok: true,
1211
- already_requested: true,
1208
+ if (skipWhenAttachmentResumeAvailable && state.attachment_resume_enabled) {
1209
+ return {
1210
+ ok: true,
1211
+ already_requested: true,
1212
1212
  attachment_resume_available: true,
1213
1213
  control: state.attachment_resume
1214
1214
  };
@@ -1390,32 +1390,32 @@ export async function waitForChatResumeRequestMessage(client, {
1390
1390
  };
1391
1391
  }
1392
1392
 
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) {
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) {
1419
1419
  return {
1420
1420
  requested: false,
1421
1421
  skipped: false,
@@ -1447,11 +1447,11 @@ export async function requestChatResumeForPassedCandidate(client, {
1447
1447
 
1448
1448
  const attempts = [];
1449
1449
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
1450
- const before = await getChatResumeRequestMessageState(client);
1451
- const askResult = await clickChatAskResume(client, {
1452
- timeoutMs: askResumeTimeoutMs,
1453
- skipWhenAttachmentResumeAvailable
1454
- });
1450
+ const before = await getChatResumeRequestMessageState(client);
1451
+ const askResult = await clickChatAskResume(client, {
1452
+ timeoutMs: askResumeTimeoutMs,
1453
+ skipWhenAttachmentResumeAvailable
1454
+ });
1455
1455
  let confirmResult = {
1456
1456
  confirmed: false,
1457
1457
  assumed_requested: Boolean(askResult.already_requested),
@@ -1,7 +1,7 @@
1
- export * from "./constants.js";
2
- export * from "./roots.js";
3
- export * from "./cards.js";
4
- export * from "./jobs.js";
5
- export * from "./page-guard.js";
6
- export * from "./detail.js";
7
- export * from "./run-service.js";
1
+ export * from "./constants.js";
2
+ export * from "./roots.js";
3
+ export * from "./cards.js";
4
+ export * from "./jobs.js";
5
+ export * from "./page-guard.js";
6
+ export * from "./detail.js";
7
+ export * from "./run-service.js";