@reconcrap/boss-recommend-mcp 2.0.46 → 2.0.47
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/bin/boss-recommend-mcp.js +4 -4
- package/config/screening-config.example.json +27 -27
- package/package.json +1 -1
- package/scripts/postinstall.cjs +44 -44
- package/skills/boss-chat/README.md +39 -39
- package/skills/boss-chat/SKILL.md +93 -93
- package/skills/boss-recommend-pipeline/README.md +12 -12
- package/skills/boss-recommend-pipeline/SKILL.md +180 -180
- package/skills/boss-recruit-pipeline/README.md +17 -17
- package/skills/boss-recruit-pipeline/SKILL.md +58 -58
- package/src/chat-mcp.js +1780 -1780
- package/src/chat-runtime-config.js +749 -749
- package/src/cli.js +3054 -3054
- package/src/core/boss-cards/index.js +199 -199
- package/src/core/browser/index.js +1453 -1453
- package/src/core/capture/index.js +1201 -1201
- package/src/core/cv-acquisition/index.js +238 -238
- package/src/core/cv-capture-target/index.js +299 -299
- package/src/core/greet-quota/index.js +54 -54
- package/src/core/infinite-list/index.js +1326 -1326
- package/src/core/reporting/legacy-csv.js +341 -341
- package/src/core/run/timing.js +33 -33
- package/src/core/screening/index.js +50 -3
- package/src/core/self-heal/index.js +973 -973
- package/src/core/self-heal/viewport.js +564 -564
- package/src/domains/chat/cards.js +137 -137
- package/src/domains/chat/constants.js +221 -221
- package/src/domains/chat/detail.js +1668 -1668
- package/src/domains/chat/index.js +7 -7
- package/src/domains/chat/jobs.js +592 -592
- package/src/domains/chat/page-guard.js +98 -98
- package/src/domains/chat/roots.js +56 -56
- package/src/domains/chat/run-service.js +1977 -1977
- package/src/domains/recommend/actions.js +457 -457
- package/src/domains/recommend/cards.js +243 -243
- package/src/domains/recommend/constants.js +165 -165
- package/src/domains/recommend/detail.js +25 -18
- package/src/domains/recommend/filters.js +610 -610
- package/src/domains/recommend/index.js +10 -10
- package/src/domains/recommend/jobs.js +316 -316
- package/src/domains/recommend/refresh.js +472 -472
- package/src/domains/recommend/roots.js +80 -80
- package/src/domains/recommend/run-service.js +27 -20
- package/src/domains/recommend/scopes.js +246 -246
- package/src/domains/recruit/actions.js +277 -277
- package/src/domains/recruit/cards.js +74 -74
- package/src/domains/recruit/constants.js +167 -167
- package/src/domains/recruit/detail.js +461 -461
- package/src/domains/recruit/index.js +9 -9
- package/src/domains/recruit/instruction-parser.js +451 -451
- package/src/domains/recruit/refresh.js +44 -44
- package/src/domains/recruit/roots.js +68 -68
- package/src/domains/recruit/run-service.js +1207 -1207
- package/src/domains/recruit/search.js +1202 -1202
- package/src/recommend-mcp.js +22 -22
- package/src/recruit-mcp.js +1338 -1338
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
import {
|
|
2
|
-
findIframeDocument,
|
|
3
|
-
getDocumentRoot,
|
|
4
|
-
querySelector,
|
|
5
|
-
sleep
|
|
6
|
-
} from "../../core/browser/index.js";
|
|
7
|
-
import { RECOMMEND_IFRAME_SELECTORS } from "./constants.js";
|
|
8
|
-
|
|
9
|
-
export async function getRecommendRoots(client, {
|
|
10
|
-
iframeSelectors = RECOMMEND_IFRAME_SELECTORS,
|
|
11
|
-
requireFrame = true
|
|
12
|
-
} = {}) {
|
|
13
|
-
const topRoot = await getDocumentRoot(client);
|
|
14
|
-
const iframe = await findIframeDocument(client, topRoot.nodeId, iframeSelectors);
|
|
15
|
-
if (!iframe && requireFrame) {
|
|
16
|
-
throw new Error("recommendFrame iframe was not found");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
topRoot,
|
|
21
|
-
iframe,
|
|
22
|
-
roots: [
|
|
23
|
-
{ name: "top", nodeId: topRoot.nodeId },
|
|
24
|
-
iframe ? { name: "recommend-frame", nodeId: iframe.documentNodeId } : null
|
|
25
|
-
].filter(Boolean),
|
|
26
|
-
rootNodes: {
|
|
27
|
-
top: topRoot.nodeId,
|
|
28
|
-
frame: iframe?.documentNodeId || 0,
|
|
29
|
-
frameOwner: iframe?.nodeId || 0
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export async function waitForRecommendRoots(client, {
|
|
35
|
-
timeoutMs = 10000,
|
|
36
|
-
intervalMs = 250,
|
|
37
|
-
iframeSelectors = RECOMMEND_IFRAME_SELECTORS
|
|
38
|
-
} = {}) {
|
|
39
|
-
const started = Date.now();
|
|
40
|
-
let lastState = null;
|
|
41
|
-
while (Date.now() - started <= timeoutMs) {
|
|
42
|
-
try {
|
|
43
|
-
lastState = await getRecommendRoots(client, {
|
|
44
|
-
iframeSelectors,
|
|
45
|
-
requireFrame: false
|
|
46
|
-
});
|
|
47
|
-
} catch (error) {
|
|
48
|
-
lastState = {
|
|
49
|
-
error: error?.message || String(error),
|
|
50
|
-
roots: [],
|
|
51
|
-
rootNodes: {
|
|
52
|
-
top: 0,
|
|
53
|
-
frame: 0,
|
|
54
|
-
frameOwner: 0
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
if (lastState.iframe?.documentNodeId) return lastState;
|
|
59
|
-
await sleep(intervalMs);
|
|
60
|
-
}
|
|
61
|
-
return lastState;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export async function queryFirstAcrossRoots(client, roots, selectors) {
|
|
65
|
-
for (const root of roots) {
|
|
66
|
-
if (!root?.nodeId) continue;
|
|
67
|
-
for (const selector of selectors) {
|
|
68
|
-
const nodeId = await querySelector(client, root.nodeId, selector);
|
|
69
|
-
if (nodeId) {
|
|
70
|
-
return {
|
|
71
|
-
root: root.name,
|
|
72
|
-
root_node_id: root.nodeId,
|
|
73
|
-
selector,
|
|
74
|
-
node_id: nodeId
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
findIframeDocument,
|
|
3
|
+
getDocumentRoot,
|
|
4
|
+
querySelector,
|
|
5
|
+
sleep
|
|
6
|
+
} from "../../core/browser/index.js";
|
|
7
|
+
import { RECOMMEND_IFRAME_SELECTORS } from "./constants.js";
|
|
8
|
+
|
|
9
|
+
export async function getRecommendRoots(client, {
|
|
10
|
+
iframeSelectors = RECOMMEND_IFRAME_SELECTORS,
|
|
11
|
+
requireFrame = true
|
|
12
|
+
} = {}) {
|
|
13
|
+
const topRoot = await getDocumentRoot(client);
|
|
14
|
+
const iframe = await findIframeDocument(client, topRoot.nodeId, iframeSelectors);
|
|
15
|
+
if (!iframe && requireFrame) {
|
|
16
|
+
throw new Error("recommendFrame iframe was not found");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
topRoot,
|
|
21
|
+
iframe,
|
|
22
|
+
roots: [
|
|
23
|
+
{ name: "top", nodeId: topRoot.nodeId },
|
|
24
|
+
iframe ? { name: "recommend-frame", nodeId: iframe.documentNodeId } : null
|
|
25
|
+
].filter(Boolean),
|
|
26
|
+
rootNodes: {
|
|
27
|
+
top: topRoot.nodeId,
|
|
28
|
+
frame: iframe?.documentNodeId || 0,
|
|
29
|
+
frameOwner: iframe?.nodeId || 0
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function waitForRecommendRoots(client, {
|
|
35
|
+
timeoutMs = 10000,
|
|
36
|
+
intervalMs = 250,
|
|
37
|
+
iframeSelectors = RECOMMEND_IFRAME_SELECTORS
|
|
38
|
+
} = {}) {
|
|
39
|
+
const started = Date.now();
|
|
40
|
+
let lastState = null;
|
|
41
|
+
while (Date.now() - started <= timeoutMs) {
|
|
42
|
+
try {
|
|
43
|
+
lastState = await getRecommendRoots(client, {
|
|
44
|
+
iframeSelectors,
|
|
45
|
+
requireFrame: false
|
|
46
|
+
});
|
|
47
|
+
} catch (error) {
|
|
48
|
+
lastState = {
|
|
49
|
+
error: error?.message || String(error),
|
|
50
|
+
roots: [],
|
|
51
|
+
rootNodes: {
|
|
52
|
+
top: 0,
|
|
53
|
+
frame: 0,
|
|
54
|
+
frameOwner: 0
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (lastState.iframe?.documentNodeId) return lastState;
|
|
59
|
+
await sleep(intervalMs);
|
|
60
|
+
}
|
|
61
|
+
return lastState;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function queryFirstAcrossRoots(client, roots, selectors) {
|
|
65
|
+
for (const root of roots) {
|
|
66
|
+
if (!root?.nodeId) continue;
|
|
67
|
+
for (const selector of selectors) {
|
|
68
|
+
const nodeId = await querySelector(client, root.nodeId, selector);
|
|
69
|
+
if (nodeId) {
|
|
70
|
+
return {
|
|
71
|
+
root: root.name,
|
|
72
|
+
root_node_id: root.nodeId,
|
|
73
|
+
selector,
|
|
74
|
+
node_id: nodeId
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
@@ -46,13 +46,14 @@ import {
|
|
|
46
46
|
screenCandidate
|
|
47
47
|
} from "../../core/screening/index.js";
|
|
48
48
|
import {
|
|
49
|
-
closeRecommendDetail,
|
|
50
|
-
createRecommendDetailNetworkRecorder,
|
|
51
|
-
extractRecommendDetailCandidate,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
closeRecommendDetail,
|
|
50
|
+
createRecommendDetailNetworkRecorder,
|
|
51
|
+
extractRecommendDetailCandidate,
|
|
52
|
+
isRecommendDetailOpenMissError,
|
|
53
|
+
isStaleRecommendNodeError,
|
|
54
|
+
openRecommendCardDetailWithFreshRetry,
|
|
55
|
+
waitForRecommendDetailNetworkEvents
|
|
56
|
+
} from "./detail.js";
|
|
56
57
|
import {
|
|
57
58
|
readRecommendCardCandidate,
|
|
58
59
|
waitForRecommendCardNodeIds
|
|
@@ -416,12 +417,13 @@ export function countRecommendResultStatuses(results = [], {
|
|
|
416
417
|
detail_open_failed: results.filter((item) => (
|
|
417
418
|
item.error?.code === "DETAIL_STALE_NODE"
|
|
418
419
|
|| item.error?.code === "DETAIL_OPEN_FAILED"
|
|
419
|
-
)).length,
|
|
420
|
-
transient_recovered: results.filter((item) => (
|
|
421
|
-
item.error?.code === "DETAIL_STALE_NODE"
|
|
422
|
-
|| item.error?.code === "
|
|
423
|
-
|| item.error?.code === "
|
|
424
|
-
|| item.error?.code === "
|
|
420
|
+
)).length,
|
|
421
|
+
transient_recovered: results.filter((item) => (
|
|
422
|
+
item.error?.code === "DETAIL_STALE_NODE"
|
|
423
|
+
|| item.error?.code === "DETAIL_OPEN_FAILED"
|
|
424
|
+
|| item.error?.code === "IMAGE_CAPTURE_STALE_NODE"
|
|
425
|
+
|| item.error?.code === "IMAGE_CAPTURE_TIMEOUT"
|
|
426
|
+
|| item.error?.code === "IMAGE_CAPTURE_TOTAL_TIMEOUT"
|
|
425
427
|
)).length
|
|
426
428
|
};
|
|
427
429
|
}
|
|
@@ -461,6 +463,9 @@ function compactError(error, fallbackCode = "RECOMMEND_RUN_ERROR") {
|
|
|
461
463
|
if (error.passed_count != null) {
|
|
462
464
|
result.passed_count = error.passed_count;
|
|
463
465
|
}
|
|
466
|
+
if (Array.isArray(error.recommend_detail_open_attempts)) {
|
|
467
|
+
result.recommend_detail_open_attempts = error.recommend_detail_open_attempts;
|
|
468
|
+
}
|
|
464
469
|
return result;
|
|
465
470
|
}
|
|
466
471
|
|
|
@@ -548,9 +553,9 @@ function createImageCaptureFailureScreening(candidate, error) {
|
|
|
548
553
|
};
|
|
549
554
|
}
|
|
550
555
|
|
|
551
|
-
export function isRecoverableRecommendDetailError(error) {
|
|
552
|
-
return isStaleRecommendNodeError(error);
|
|
553
|
-
}
|
|
556
|
+
export function isRecoverableRecommendDetailError(error) {
|
|
557
|
+
return isStaleRecommendNodeError(error) || isRecommendDetailOpenMissError(error);
|
|
558
|
+
}
|
|
554
559
|
|
|
555
560
|
function compactRecoverableDetailError(error) {
|
|
556
561
|
return compactError(error, isStaleRecommendNodeError(error) ? "DETAIL_STALE_NODE" : "DETAIL_OPEN_FAILED");
|
|
@@ -560,10 +565,12 @@ function createRecoverableDetailFailureScreening(candidate, error) {
|
|
|
560
565
|
return {
|
|
561
566
|
status: "fail",
|
|
562
567
|
passed: false,
|
|
563
|
-
score: 0,
|
|
564
|
-
reasons: isStaleRecommendNodeError(error)
|
|
565
|
-
? ["detail_open_failed", "stale_node"]
|
|
566
|
-
:
|
|
568
|
+
score: 0,
|
|
569
|
+
reasons: isStaleRecommendNodeError(error)
|
|
570
|
+
? ["detail_open_failed", "stale_node"]
|
|
571
|
+
: isRecommendDetailOpenMissError(error)
|
|
572
|
+
? ["detail_open_failed", "detail_open_miss"]
|
|
573
|
+
: ["detail_open_failed"],
|
|
567
574
|
error: compactRecoverableDetailError(error),
|
|
568
575
|
candidate
|
|
569
576
|
};
|