@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
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
markInfiniteListCandidateProcessed,
|
|
19
19
|
resetInfiniteListForRefreshRound
|
|
20
20
|
} from "../../core/infinite-list/index.js";
|
|
21
|
+
import { createViewportRunGuard } from "../../core/self-heal/index.js";
|
|
21
22
|
import { screenCandidate } from "../../core/screening/index.js";
|
|
22
23
|
import {
|
|
23
24
|
closeRecruitDetail,
|
|
@@ -140,6 +141,18 @@ export async function runRecruitWorkflow({
|
|
|
140
141
|
domain: "recruit",
|
|
141
142
|
listName: "search-results"
|
|
142
143
|
});
|
|
144
|
+
const viewportGuard = createViewportRunGuard({
|
|
145
|
+
client,
|
|
146
|
+
domain: "recruit",
|
|
147
|
+
root: "frame",
|
|
148
|
+
frameOwnerRoot: "frameOwner",
|
|
149
|
+
runControl,
|
|
150
|
+
getRoots: getRecruitRoots
|
|
151
|
+
});
|
|
152
|
+
async function ensureRecruitViewport(rootState, phase) {
|
|
153
|
+
const result = await viewportGuard.ensure(rootState, { phase });
|
|
154
|
+
return result.rootState || rootState;
|
|
155
|
+
}
|
|
143
156
|
const results = [];
|
|
144
157
|
const refreshAttempts = [];
|
|
145
158
|
let refreshRounds = 0;
|
|
@@ -153,6 +166,7 @@ export async function runRecruitWorkflow({
|
|
|
153
166
|
runControl.throwIfCanceled();
|
|
154
167
|
runControl.setPhase("recruit:roots");
|
|
155
168
|
let rootState = await getRecruitRoots(client);
|
|
169
|
+
rootState = await ensureRecruitViewport(rootState, "roots");
|
|
156
170
|
runControl.checkpoint({
|
|
157
171
|
iframe_selector: rootState.iframe.selector,
|
|
158
172
|
iframe_document_node_id: rootState.iframe.documentNodeId,
|
|
@@ -186,11 +200,13 @@ export async function runRecruitWorkflow({
|
|
|
186
200
|
}
|
|
187
201
|
});
|
|
188
202
|
rootState = await getRecruitRoots(client);
|
|
203
|
+
rootState = await ensureRecruitViewport(rootState, "search");
|
|
189
204
|
}
|
|
190
205
|
|
|
191
206
|
await runControl.waitIfPaused();
|
|
192
207
|
runControl.throwIfCanceled();
|
|
193
208
|
runControl.setPhase("recruit:cards");
|
|
209
|
+
rootState = await ensureRecruitViewport(rootState, "cards");
|
|
194
210
|
cardNodeIds = await waitForRecruitCardNodeIds(client, rootState.iframe.documentNodeId, {
|
|
195
211
|
timeoutMs: cardTimeoutMs,
|
|
196
212
|
intervalMs: 300
|
|
@@ -209,13 +225,16 @@ export async function runRecruitWorkflow({
|
|
|
209
225
|
unique_seen: compactInfiniteListState(listState).seen_count,
|
|
210
226
|
scroll_count: 0,
|
|
211
227
|
refresh_rounds: 0,
|
|
212
|
-
refresh_attempts: 0
|
|
228
|
+
refresh_attempts: 0,
|
|
229
|
+
viewport_checks: viewportGuard.getStats().checks,
|
|
230
|
+
viewport_recoveries: viewportGuard.getStats().recoveries
|
|
213
231
|
});
|
|
214
232
|
|
|
215
233
|
while (results.length < limit) {
|
|
216
234
|
await runControl.waitIfPaused();
|
|
217
235
|
runControl.throwIfCanceled();
|
|
218
236
|
runControl.setPhase("recruit:candidate");
|
|
237
|
+
rootState = await ensureRecruitViewport(rootState, "candidate_loop");
|
|
219
238
|
|
|
220
239
|
const nextCandidateResult = await getNextInfiniteListCandidate({
|
|
221
240
|
client,
|
|
@@ -226,7 +245,9 @@ export async function runRecruitWorkflow({
|
|
|
226
245
|
settleMs: listSettleMs,
|
|
227
246
|
fallbackPoint: listFallbackPoint,
|
|
228
247
|
findNodeIds: async () => {
|
|
229
|
-
|
|
248
|
+
let currentRootState = await getRecruitRoots(client);
|
|
249
|
+
currentRootState = await ensureRecruitViewport(currentRootState, "candidate_find_nodes");
|
|
250
|
+
rootState = currentRootState;
|
|
230
251
|
const currentCardNodeIds = await waitForRecruitCardNodeIds(client, currentRootState.iframe.documentNodeId, {
|
|
231
252
|
timeoutMs: Math.min(cardTimeoutMs, 5000),
|
|
232
253
|
intervalMs: 300
|
|
@@ -283,10 +304,13 @@ export async function runRecruitWorkflow({
|
|
|
283
304
|
refresh_attempts: refreshAttempts.length,
|
|
284
305
|
refresh_method: refreshResult.method || null,
|
|
285
306
|
refresh_forced_recent_viewed: true,
|
|
286
|
-
list_end_reason: listEndReason
|
|
307
|
+
list_end_reason: listEndReason,
|
|
308
|
+
viewport_checks: viewportGuard.getStats().checks,
|
|
309
|
+
viewport_recoveries: viewportGuard.getStats().recoveries
|
|
287
310
|
});
|
|
288
311
|
if (refreshResult.ok) {
|
|
289
312
|
rootState = await getRecruitRoots(client);
|
|
313
|
+
rootState = await ensureRecruitViewport(rootState, "refresh_after");
|
|
290
314
|
cardNodeIds = await waitForRecruitCardNodeIds(client, rootState.iframe.documentNodeId, {
|
|
291
315
|
timeoutMs: cardTimeoutMs,
|
|
292
316
|
intervalMs: 300
|
|
@@ -318,6 +342,7 @@ export async function runRecruitWorkflow({
|
|
|
318
342
|
await runControl.waitIfPaused();
|
|
319
343
|
runControl.throwIfCanceled();
|
|
320
344
|
runControl.setPhase("recruit:detail");
|
|
345
|
+
rootState = await ensureRecruitViewport(rootState, "detail");
|
|
321
346
|
networkRecorder.clear();
|
|
322
347
|
const openedDetail = await openRecruitCardDetail(client, cardNodeId);
|
|
323
348
|
const waitPlan = getCvNetworkWaitPlan(cvAcquisitionState);
|
|
@@ -430,6 +455,8 @@ export async function runRecruitWorkflow({
|
|
|
430
455
|
refresh_rounds: refreshRounds,
|
|
431
456
|
refresh_attempts: refreshAttempts.length,
|
|
432
457
|
list_end_reason: listEndReason || null,
|
|
458
|
+
viewport_checks: viewportGuard.getStats().checks,
|
|
459
|
+
viewport_recoveries: viewportGuard.getStats().recoveries,
|
|
433
460
|
last_candidate_id: screeningCandidate.id || null,
|
|
434
461
|
last_candidate_key: candidateKey,
|
|
435
462
|
last_score: screening.score
|
|
@@ -459,6 +486,10 @@ export async function runRecruitWorkflow({
|
|
|
459
486
|
search_params: normalizedSearchParams,
|
|
460
487
|
card_count: cardNodeIds.length,
|
|
461
488
|
candidate_list: compactInfiniteListState(listState),
|
|
489
|
+
viewport_health: {
|
|
490
|
+
stats: viewportGuard.getStats(),
|
|
491
|
+
events: viewportGuard.getEvents()
|
|
492
|
+
},
|
|
462
493
|
list_end_reason: listEndReason || null,
|
|
463
494
|
refresh_rounds: refreshRounds,
|
|
464
495
|
refresh_attempts: refreshAttempts,
|
package/src/index.js
CHANGED
|
@@ -1911,7 +1911,8 @@ async function handleRunRecommendSelfHealTool({ workspaceRoot, args }) {
|
|
|
1911
1911
|
domain: "recommend",
|
|
1912
1912
|
roots: rootState?.roots || {},
|
|
1913
1913
|
selectorProbes: config.selectorProbes,
|
|
1914
|
-
accessibilityProbes: config.accessibilityProbes
|
|
1914
|
+
accessibilityProbes: config.accessibilityProbes,
|
|
1915
|
+
viewportProbes: config.viewportProbes
|
|
1915
1916
|
});
|
|
1916
1917
|
assertNoForbiddenCdpCalls(methodLog);
|
|
1917
1918
|
|
package/src/recommend-mcp.js
CHANGED
|
@@ -623,7 +623,8 @@ async function waitForHealthyRecommend(client, config, {
|
|
|
623
623
|
domain: "recommend",
|
|
624
624
|
roots: roots.roots,
|
|
625
625
|
selectorProbes: config.selectorProbes,
|
|
626
|
-
accessibilityProbes: config.accessibilityProbes
|
|
626
|
+
accessibilityProbes: config.accessibilityProbes,
|
|
627
|
+
viewportProbes: config.viewportProbes
|
|
627
628
|
});
|
|
628
629
|
if (lastCheck.status === HEALTH_STATUS.HEALTHY) return lastCheck;
|
|
629
630
|
await sleep(intervalMs);
|