@reconcrap/boss-recommend-mcp 2.0.4 → 2.0.6
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 +1 -1
- package/src/chat-mcp.js +2 -1
- package/src/core/browser/index.js +1 -0
- package/src/core/self-heal/index.js +128 -3
- package/src/core/self-heal/viewport.js +564 -0
- package/src/domains/chat/run-service.js +52 -8
- package/src/domains/recommend/detail.js +189 -6
- package/src/domains/recommend/roots.js +4 -2
- package/src/domains/recommend/run-service.js +51 -7
- package/src/domains/recruit/roots.js +2 -1
- package/src/domains/recruit/run-service.js +34 -3
- package/src/index.js +2 -1
- package/src/recommend-mcp.js +2 -1
package/package.json
CHANGED
package/src/chat-mcp.js
CHANGED
|
@@ -494,7 +494,8 @@ async function waitForHealthyChat(client, config, {
|
|
|
494
494
|
domain: "chat",
|
|
495
495
|
roots: roots.roots,
|
|
496
496
|
selectorProbes: config.selectorProbes,
|
|
497
|
-
accessibilityProbes: config.accessibilityProbes
|
|
497
|
+
accessibilityProbes: config.accessibilityProbes,
|
|
498
|
+
viewportProbes: config.viewportProbes
|
|
498
499
|
});
|
|
499
500
|
if (lastCheck.status === HEALTH_STATUS.HEALTHY) return lastCheck;
|
|
500
501
|
await sleep(intervalMs);
|
|
@@ -5,6 +5,26 @@ import {
|
|
|
5
5
|
querySelectorAll,
|
|
6
6
|
sleep
|
|
7
7
|
} from "../browser/index.js";
|
|
8
|
+
import {
|
|
9
|
+
compactViewportHealthResult,
|
|
10
|
+
ensureHealthyViewport
|
|
11
|
+
} from "./viewport.js";
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
buildViewportHealthDiagnostics,
|
|
15
|
+
compactViewportHealthResult,
|
|
16
|
+
compactViewportState,
|
|
17
|
+
createViewportRunGuard,
|
|
18
|
+
ensureHealthyViewport,
|
|
19
|
+
getCurrentWindowInfo,
|
|
20
|
+
isListViewportCollapsed,
|
|
21
|
+
readViewportState,
|
|
22
|
+
setWindowStateIfPossible,
|
|
23
|
+
toggleWindowStateForViewportRecovery,
|
|
24
|
+
VIEWPORT_COLLAPSE_MIN_EXPECTED_WIDTH,
|
|
25
|
+
VIEWPORT_COLLAPSE_NEAR_FULLSCREEN_RATIO,
|
|
26
|
+
VIEWPORT_COLLAPSE_RATIO_THRESHOLD
|
|
27
|
+
} from "./viewport.js";
|
|
8
28
|
|
|
9
29
|
export const PROBE_STATUS = Object.freeze({
|
|
10
30
|
PASS: "pass",
|
|
@@ -245,6 +265,26 @@ export function createNetworkProbe({
|
|
|
245
265
|
};
|
|
246
266
|
}
|
|
247
267
|
|
|
268
|
+
export function createViewportCollapseProbe({
|
|
269
|
+
id = "viewport_collapse",
|
|
270
|
+
root = "frame",
|
|
271
|
+
frameOwnerRoot = "frameOwner",
|
|
272
|
+
required = true,
|
|
273
|
+
repair = true,
|
|
274
|
+
description = ""
|
|
275
|
+
} = {}) {
|
|
276
|
+
if (!id) throw new Error("Viewport collapse probe requires an id");
|
|
277
|
+
return {
|
|
278
|
+
type: "viewport",
|
|
279
|
+
id,
|
|
280
|
+
root,
|
|
281
|
+
frameOwnerRoot,
|
|
282
|
+
required: Boolean(required),
|
|
283
|
+
repair: Boolean(repair),
|
|
284
|
+
description
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
248
288
|
export async function runSelectorProbe(client, roots, probe) {
|
|
249
289
|
const nodeId = rootNodeId(roots, probe.root);
|
|
250
290
|
if (!nodeId) {
|
|
@@ -338,6 +378,52 @@ export function runNetworkProbe(networkEvents = [], probe) {
|
|
|
338
378
|
};
|
|
339
379
|
}
|
|
340
380
|
|
|
381
|
+
export async function runViewportCollapseProbe(client, roots, probe) {
|
|
382
|
+
const nodeId = rootNodeId(roots, probe.root);
|
|
383
|
+
if (!nodeId) {
|
|
384
|
+
return {
|
|
385
|
+
...probe,
|
|
386
|
+
ok: !probe.required,
|
|
387
|
+
status: probe.required ? PROBE_STATUS.BLOCKED : PROBE_STATUS.OPTIONAL_ABSENT,
|
|
388
|
+
count: 0,
|
|
389
|
+
collapsed: false,
|
|
390
|
+
recovered: false,
|
|
391
|
+
error: `Root not found: ${probe.root}`
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
const health = await ensureHealthyViewport(client, {
|
|
397
|
+
roots,
|
|
398
|
+
root: probe.root,
|
|
399
|
+
frameOwnerRoot: probe.frameOwnerRoot,
|
|
400
|
+
reason: probe.id,
|
|
401
|
+
repair: probe.repair
|
|
402
|
+
});
|
|
403
|
+
const ok = Boolean(health.ok);
|
|
404
|
+
return {
|
|
405
|
+
...probe,
|
|
406
|
+
ok: probe.required ? ok : true,
|
|
407
|
+
status: ok ? PROBE_STATUS.PASS : probe.required ? PROBE_STATUS.FAIL : PROBE_STATUS.OPTIONAL_ABSENT,
|
|
408
|
+
count: ok ? 1 : 0,
|
|
409
|
+
collapsed: Boolean(health.collapsed),
|
|
410
|
+
recovered: Boolean(health.recovered),
|
|
411
|
+
viewport_health: compactViewportHealthResult(health),
|
|
412
|
+
error: health.error || null
|
|
413
|
+
};
|
|
414
|
+
} catch (error) {
|
|
415
|
+
return {
|
|
416
|
+
...probe,
|
|
417
|
+
ok: !probe.required,
|
|
418
|
+
status: probe.required ? PROBE_STATUS.ERROR : PROBE_STATUS.OPTIONAL_ABSENT,
|
|
419
|
+
count: 0,
|
|
420
|
+
collapsed: false,
|
|
421
|
+
recovered: false,
|
|
422
|
+
error: error?.message || String(error)
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
341
427
|
export function summarizeProbeResults(probes = []) {
|
|
342
428
|
const required = probes.filter((probe) => probe.required);
|
|
343
429
|
const blocked = required.filter((probe) => probe.status === PROBE_STATUS.BLOCKED);
|
|
@@ -370,6 +456,7 @@ export function buildDriftReport(probes = []) {
|
|
|
370
456
|
expected_min_count: probe.minCount,
|
|
371
457
|
observed_count: probe.count || 0,
|
|
372
458
|
selectors: probe.selectors || [],
|
|
459
|
+
viewport_health: probe.viewport_health || undefined,
|
|
373
460
|
error: probe.error || null
|
|
374
461
|
}));
|
|
375
462
|
}
|
|
@@ -380,6 +467,7 @@ export async function runSelfHealCheck({
|
|
|
380
467
|
roots = {},
|
|
381
468
|
selectorProbes = [],
|
|
382
469
|
accessibilityProbes = [],
|
|
470
|
+
viewportProbes = [],
|
|
383
471
|
networkProbes = [],
|
|
384
472
|
networkEvents = []
|
|
385
473
|
} = {}) {
|
|
@@ -393,8 +481,13 @@ export async function runSelfHealCheck({
|
|
|
393
481
|
accessibilityResults.push(await runAccessibilityProbe(client, probe));
|
|
394
482
|
}
|
|
395
483
|
|
|
484
|
+
const viewportResults = [];
|
|
485
|
+
for (const probe of viewportProbes) {
|
|
486
|
+
viewportResults.push(await runViewportCollapseProbe(client, roots, probe));
|
|
487
|
+
}
|
|
488
|
+
|
|
396
489
|
const networkResults = networkProbes.map((probe) => runNetworkProbe(networkEvents, probe));
|
|
397
|
-
const probes = [...selectorResults, ...accessibilityResults, ...networkResults];
|
|
490
|
+
const probes = [...selectorResults, ...accessibilityResults, ...viewportResults, ...networkResults];
|
|
398
491
|
const summary = summarizeProbeResults(probes);
|
|
399
492
|
|
|
400
493
|
return {
|
|
@@ -507,6 +600,16 @@ export function buildRecommendSelfHealConfig(rules = {}) {
|
|
|
507
600
|
description: "Candidate detail popup may mount inside the recommend frame"
|
|
508
601
|
})
|
|
509
602
|
],
|
|
603
|
+
viewportProbes: [
|
|
604
|
+
createViewportCollapseProbe({
|
|
605
|
+
id: "recommend_viewport_collapse",
|
|
606
|
+
root: "frame",
|
|
607
|
+
frameOwnerRoot: "frameOwner",
|
|
608
|
+
required: true,
|
|
609
|
+
repair: true,
|
|
610
|
+
description: "Recommend frame/list viewport has not collapsed relative to the Chrome window"
|
|
611
|
+
})
|
|
612
|
+
],
|
|
510
613
|
accessibilityProbes: [
|
|
511
614
|
createAccessibilityProbe({
|
|
512
615
|
id: "accessibility_tree",
|
|
@@ -610,6 +713,16 @@ export function buildRecruitSelfHealConfig(rules = {}) {
|
|
|
610
713
|
description: "Candidate detail popup may mount inside the search frame"
|
|
611
714
|
})
|
|
612
715
|
],
|
|
716
|
+
viewportProbes: [
|
|
717
|
+
createViewportCollapseProbe({
|
|
718
|
+
id: "recruit_viewport_collapse",
|
|
719
|
+
root: "frame",
|
|
720
|
+
frameOwnerRoot: "frameOwner",
|
|
721
|
+
required: true,
|
|
722
|
+
repair: true,
|
|
723
|
+
description: "Search frame/list viewport has not collapsed relative to the Chrome window"
|
|
724
|
+
})
|
|
725
|
+
],
|
|
613
726
|
accessibilityProbes: [
|
|
614
727
|
createAccessibilityProbe({
|
|
615
728
|
id: "accessibility_tree",
|
|
@@ -711,6 +824,16 @@ export function buildChatSelfHealConfig(rules = {}) {
|
|
|
711
824
|
description: "Resume iframe appears after the online resume is opened"
|
|
712
825
|
})
|
|
713
826
|
],
|
|
827
|
+
viewportProbes: [
|
|
828
|
+
createViewportCollapseProbe({
|
|
829
|
+
id: "chat_viewport_collapse",
|
|
830
|
+
root: "top",
|
|
831
|
+
frameOwnerRoot: "top",
|
|
832
|
+
required: true,
|
|
833
|
+
repair: true,
|
|
834
|
+
description: "Chat list viewport has not collapsed relative to the Chrome window"
|
|
835
|
+
})
|
|
836
|
+
],
|
|
714
837
|
accessibilityProbes: [
|
|
715
838
|
createAccessibilityProbe({
|
|
716
839
|
id: "accessibility_tree",
|
|
@@ -756,7 +879,8 @@ export async function resolveRecommendSelfHealRoots(client, config = buildRecomm
|
|
|
756
879
|
return {
|
|
757
880
|
roots: {
|
|
758
881
|
top: topRoot.nodeId,
|
|
759
|
-
frame: iframe.documentNodeId
|
|
882
|
+
frame: iframe.documentNodeId,
|
|
883
|
+
frameOwner: iframe.nodeId
|
|
760
884
|
},
|
|
761
885
|
topRoot,
|
|
762
886
|
iframe
|
|
@@ -779,7 +903,8 @@ export async function resolveRecruitSelfHealRoots(client, config = buildRecruitS
|
|
|
779
903
|
return {
|
|
780
904
|
roots: {
|
|
781
905
|
top: topRoot.nodeId,
|
|
782
|
-
frame: iframe.documentNodeId
|
|
906
|
+
frame: iframe.documentNodeId,
|
|
907
|
+
frameOwner: iframe.nodeId
|
|
783
908
|
},
|
|
784
909
|
topRoot,
|
|
785
910
|
iframe
|