@reconcrap/boss-recommend-mcp 2.0.47 → 2.0.49
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 +1586 -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/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 +1 -1
- package/src/domains/recommend/filters.js +610 -610
- package/src/domains/recommend/index.js +10 -10
- package/src/domains/recommend/jobs.js +378 -316
- package/src/domains/recommend/refresh.js +491 -472
- package/src/domains/recommend/roots.js +80 -80
- package/src/domains/recommend/run-service.js +50 -29
- 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
|
+
}
|
|
@@ -1256,11 +1256,13 @@ export async function runRecommendWorkflow({
|
|
|
1256
1256
|
: useLlmScreening
|
|
1257
1257
|
? llmResultToScreening(llmResult, screeningCandidate)
|
|
1258
1258
|
: screenCandidate(screeningCandidate, { criteria });
|
|
1259
|
-
let actionDiscovery = null;
|
|
1260
|
-
let postActionResult = null;
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1259
|
+
let actionDiscovery = null;
|
|
1260
|
+
let postActionResult = null;
|
|
1261
|
+
let closeFailureError = null;
|
|
1262
|
+
let closeRecoveryFailure = null;
|
|
1263
|
+
if (postActionEnabled && detailResult) {
|
|
1264
|
+
const postActionStarted = Date.now();
|
|
1265
|
+
await runControl.waitIfPaused();
|
|
1264
1266
|
runControl.throwIfCanceled();
|
|
1265
1267
|
runControl.setPhase("recommend:post-action");
|
|
1266
1268
|
await maybeHumanActionCooldown("before_post_action", timings);
|
|
@@ -1288,21 +1290,34 @@ export async function runRecommendWorkflow({
|
|
|
1288
1290
|
detailResult.close_result = await measureTiming(timings, "close_detail_ms", () => closeRecommendDetail(client));
|
|
1289
1291
|
await maybeHumanActionCooldown("after_detail_close", timings);
|
|
1290
1292
|
if (!detailResult.close_result?.closed) {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1293
|
+
closeFailureError = createRecommendCloseFailureError(detailResult.close_result);
|
|
1294
|
+
try {
|
|
1295
|
+
const recovery = await recoverAndReapplyRecommendContext("detail_close_failed", closeFailureError, {
|
|
1296
|
+
forceRecentNotView: true
|
|
1297
|
+
});
|
|
1298
|
+
detailResult.cv_acquisition = {
|
|
1299
|
+
...(detailResult.cv_acquisition || {}),
|
|
1300
|
+
close_recovery: {
|
|
1301
|
+
ok: Boolean(recovery.ok),
|
|
1302
|
+
method: recovery.method || "",
|
|
1303
|
+
forced_recent_not_view: Boolean(recovery.forced_recent_not_view),
|
|
1304
|
+
card_count: recovery.card_count || 0
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
} catch (error) {
|
|
1308
|
+
closeRecoveryFailure = error;
|
|
1309
|
+
detailResult.cv_acquisition = {
|
|
1310
|
+
...(detailResult.cv_acquisition || {}),
|
|
1311
|
+
close_recovery: {
|
|
1312
|
+
ok: false,
|
|
1313
|
+
reason: "context_recovery_failed",
|
|
1314
|
+
error: error?.message || String(error),
|
|
1315
|
+
forced_recent_not_view: true
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1306
1321
|
timings.total_ms = Date.now() - candidateStarted;
|
|
1307
1322
|
const compactResult = {
|
|
1308
1323
|
index,
|
|
@@ -1313,12 +1328,14 @@ export async function runRecommendWorkflow({
|
|
|
1313
1328
|
llm_screening: detailResult ? null : compactScreeningLlmResult(llmResult),
|
|
1314
1329
|
screening: compactScreening(screening),
|
|
1315
1330
|
action_discovery: compactActionDiscovery(actionDiscovery),
|
|
1316
|
-
post_action: postActionResult,
|
|
1317
|
-
error: recoverableDetailError
|
|
1318
|
-
? compactRecoverableDetailError(recoverableDetailError)
|
|
1319
|
-
:
|
|
1320
|
-
? compactError(
|
|
1321
|
-
|
|
1331
|
+
post_action: postActionResult,
|
|
1332
|
+
error: recoverableDetailError
|
|
1333
|
+
? compactRecoverableDetailError(recoverableDetailError)
|
|
1334
|
+
: closeRecoveryFailure
|
|
1335
|
+
? compactError(closeFailureError, "DETAIL_CLOSE_FAILED")
|
|
1336
|
+
: detailResult?.image_evidence?.ok === false
|
|
1337
|
+
? compactError({
|
|
1338
|
+
code: detailResult.image_evidence.error_code,
|
|
1322
1339
|
message: detailResult.image_evidence.error
|
|
1323
1340
|
}, "IMAGE_CAPTURE_FAILED")
|
|
1324
1341
|
: null,
|
|
@@ -1353,9 +1370,13 @@ export async function runRecommendWorkflow({
|
|
|
1353
1370
|
error: compactResult.error,
|
|
1354
1371
|
post_action: postActionResult
|
|
1355
1372
|
}
|
|
1356
|
-
});
|
|
1357
|
-
addTiming(compactResult.timings, "checkpoint_save_ms", Date.now() - checkpointStarted);
|
|
1358
|
-
|
|
1373
|
+
});
|
|
1374
|
+
addTiming(compactResult.timings, "checkpoint_save_ms", Date.now() - checkpointStarted);
|
|
1375
|
+
|
|
1376
|
+
if (closeRecoveryFailure) {
|
|
1377
|
+
throw closeRecoveryFailure;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1359
1380
|
if (postActionResult?.stop_run) {
|
|
1360
1381
|
listEndReason = postActionResult.reason || "post_action_stop";
|
|
1361
1382
|
break;
|