@reconcrap/boss-recommend-mcp 2.0.37 → 2.0.39
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 +0 -0
- package/config/screening-config.example.json +1 -1
- package/package.json +119 -119
- package/src/core/run/index.js +310 -310
- package/src/domains/recommend/detail.js +612 -569
- package/src/domains/recommend/refresh.js +78 -6
- package/src/domains/recommend/run-service.js +1421 -1414
- package/src/index.js +148 -9
- package/src/recommend-mcp.js +1719 -1715
- package/src/run-state.js +358 -356
|
@@ -92,6 +92,63 @@ function refreshFailureReason(method = "") {
|
|
|
92
92
|
return method === "page_navigate" ? "page_navigate_failed" : "page_reload_failed";
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
export function isRetryableRecommendFilterReapplyError(error) {
|
|
96
|
+
const message = String(error?.message || error || "");
|
|
97
|
+
return /Recommend filter panel did not open|Recommend filter trigger was not found|Recommend filter confirm button was not found|No matching recommend filter option/i.test(message);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function compactFilterReapplyError(error) {
|
|
101
|
+
return error?.message || String(error || "Recommend filter reapply failed");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function selectAndConfirmRefreshFilter(client, rootState, filterOptions, {
|
|
105
|
+
maxAttempts = 3,
|
|
106
|
+
retryDelayMs = 1500
|
|
107
|
+
} = {}) {
|
|
108
|
+
const attempts = [];
|
|
109
|
+
let currentRootState = rootState;
|
|
110
|
+
let lastError = null;
|
|
111
|
+
|
|
112
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
113
|
+
try {
|
|
114
|
+
const filter = await selectAndConfirmFirstSafeFilter(
|
|
115
|
+
client,
|
|
116
|
+
currentRootState.iframe.documentNodeId,
|
|
117
|
+
filterOptions
|
|
118
|
+
);
|
|
119
|
+
attempts.push({
|
|
120
|
+
ok: true,
|
|
121
|
+
method: "filter_reapply",
|
|
122
|
+
attempt
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
filter,
|
|
126
|
+
root_state: currentRootState,
|
|
127
|
+
attempts
|
|
128
|
+
};
|
|
129
|
+
} catch (error) {
|
|
130
|
+
lastError = error;
|
|
131
|
+
attempts.push({
|
|
132
|
+
ok: false,
|
|
133
|
+
method: "filter_reapply",
|
|
134
|
+
reason: "filter_reapply_failed",
|
|
135
|
+
error: compactFilterReapplyError(error),
|
|
136
|
+
attempt
|
|
137
|
+
});
|
|
138
|
+
if (attempt >= maxAttempts || !isRetryableRecommendFilterReapplyError(error)) {
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
if (retryDelayMs > 0) await sleep(retryDelayMs);
|
|
142
|
+
currentRootState = await getRecommendRoots(client);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const wrapped = new Error(compactFilterReapplyError(lastError));
|
|
147
|
+
wrapped.cause = lastError;
|
|
148
|
+
wrapped.filter_reapply_attempts = attempts;
|
|
149
|
+
throw wrapped;
|
|
150
|
+
}
|
|
151
|
+
|
|
95
152
|
async function applyRefreshMethod(client, method, {
|
|
96
153
|
jobLabel = "",
|
|
97
154
|
pageScope = "recommend",
|
|
@@ -107,6 +164,7 @@ async function applyRefreshMethod(client, method, {
|
|
|
107
164
|
let jobSelection = null;
|
|
108
165
|
let pageScopeResult = null;
|
|
109
166
|
let filterResult = null;
|
|
167
|
+
let filterReapplyAttempts = [];
|
|
110
168
|
try {
|
|
111
169
|
if (method === "page_navigate") {
|
|
112
170
|
await client.Page.navigate({ url: targetUrl || RECOMMEND_TARGET_URL });
|
|
@@ -145,11 +203,17 @@ async function applyRefreshMethod(client, method, {
|
|
|
145
203
|
throw new Error(`Recommend page scope was not selected after refresh reload: ${pageScopeResult.reason || pageScope}`);
|
|
146
204
|
}
|
|
147
205
|
currentRootState = await getRecommendRoots(client);
|
|
148
|
-
|
|
206
|
+
const filterSelection = await selectAndConfirmRefreshFilter(
|
|
149
207
|
client,
|
|
150
|
-
currentRootState
|
|
151
|
-
buildRecommendFilterSelectionOptions(filter, { forceRecentNotView })
|
|
208
|
+
currentRootState,
|
|
209
|
+
buildRecommendFilterSelectionOptions(filter, { forceRecentNotView }),
|
|
210
|
+
{
|
|
211
|
+
retryDelayMs: Math.max(1200, Math.min(5000, Math.floor((reloadSettleMs || 8000) / 2)))
|
|
212
|
+
}
|
|
152
213
|
);
|
|
214
|
+
filterResult = filterSelection.filter;
|
|
215
|
+
filterReapplyAttempts = filterSelection.attempts;
|
|
216
|
+
currentRootState = await getRecommendRoots(client);
|
|
153
217
|
const cardNodeIds = await waitForRecommendCardNodeIds(client, currentRootState.iframe.documentNodeId, {
|
|
154
218
|
timeoutMs: cardTimeoutMs,
|
|
155
219
|
intervalMs: 500
|
|
@@ -164,6 +228,7 @@ async function applyRefreshMethod(client, method, {
|
|
|
164
228
|
job_selection: jobSelection,
|
|
165
229
|
page_scope: pageScopeResult,
|
|
166
230
|
filter: filterResult,
|
|
231
|
+
filter_reapply_attempts: filterReapplyAttempts,
|
|
167
232
|
card_count: cardNodeIds.length,
|
|
168
233
|
root_state: currentRootState,
|
|
169
234
|
forced_recent_not_view: forceRecentNotView,
|
|
@@ -179,6 +244,7 @@ async function applyRefreshMethod(client, method, {
|
|
|
179
244
|
job_selection: jobSelection,
|
|
180
245
|
page_scope: pageScopeResult,
|
|
181
246
|
filter: filterResult,
|
|
247
|
+
filter_reapply_attempts: error?.filter_reapply_attempts || filterReapplyAttempts,
|
|
182
248
|
card_count: 0,
|
|
183
249
|
root_state: currentRootState,
|
|
184
250
|
forced_recent_not_view: forceRecentNotView,
|
|
@@ -229,11 +295,16 @@ export async function refreshRecommendListAtEnd(client, {
|
|
|
229
295
|
throw new Error(`Recommend page scope was not selected after end refresh: ${pageScopeResult.reason || pageScope}`);
|
|
230
296
|
}
|
|
231
297
|
currentRootState = await getRecommendRoots(client);
|
|
232
|
-
const
|
|
298
|
+
const filterSelection = await selectAndConfirmRefreshFilter(
|
|
233
299
|
client,
|
|
234
|
-
currentRootState
|
|
235
|
-
buildRecommendFilterSelectionOptions(filter, { forceRecentNotView })
|
|
300
|
+
currentRootState,
|
|
301
|
+
buildRecommendFilterSelectionOptions(filter, { forceRecentNotView }),
|
|
302
|
+
{
|
|
303
|
+
retryDelayMs: Math.max(1200, Math.min(5000, Math.floor((buttonSettleMs || 8000) / 2)))
|
|
304
|
+
}
|
|
236
305
|
);
|
|
306
|
+
const filterResult = filterSelection.filter;
|
|
307
|
+
currentRootState = await getRecommendRoots(client);
|
|
237
308
|
const cardNodeIds = await waitForRecommendCardNodeIds(client, currentRootState.iframe.documentNodeId, {
|
|
238
309
|
timeoutMs: cardTimeoutMs,
|
|
239
310
|
intervalMs: 500
|
|
@@ -244,6 +315,7 @@ export async function refreshRecommendListAtEnd(client, {
|
|
|
244
315
|
attempts,
|
|
245
316
|
page_scope: pageScopeResult,
|
|
246
317
|
filter: filterResult,
|
|
318
|
+
filter_reapply_attempts: filterSelection.attempts,
|
|
247
319
|
card_count: cardNodeIds.length,
|
|
248
320
|
root_state: currentRootState,
|
|
249
321
|
forced_recent_not_view: forceRecentNotView
|