@reconcrap/boss-recommend-mcp 2.1.22 → 2.1.24
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/README.md +5 -0
- package/bin/boss-recommend-mcp.js +4 -4
- package/package.json +14 -8
- package/scripts/install-macos.sh +280 -280
- package/scripts/postinstall.cjs +44 -44
- package/skills/boss-chat/README.md +43 -42
- package/skills/boss-chat/SKILL.md +107 -106
- package/skills/boss-recommend-pipeline/README.md +13 -13
- package/skills/boss-recommend-pipeline/SKILL.md +47 -47
- package/skills/boss-recruit-pipeline/README.md +19 -19
- package/skills/boss-recruit-pipeline/SKILL.md +89 -89
- package/src/chat-mcp.js +301 -127
- package/src/core/boss-cards/index.js +199 -199
- package/src/core/browser/index.js +291 -114
- package/src/core/capture/index.js +2930 -1201
- package/src/core/cv-acquisition/index.js +512 -238
- package/src/core/cv-capture-target/index.js +513 -299
- package/src/core/greet-quota/index.js +71 -71
- package/src/core/infinite-list/index.js +11 -2
- package/src/core/reporting/legacy-csv.js +12 -12
- package/src/core/run/detached-launcher.js +305 -0
- package/src/core/run/index.js +112 -42
- package/src/core/run/timing.js +33 -33
- package/src/core/run/windows-detached-worker.ps1 +106 -0
- package/src/core/screening/index.js +2135 -2135
- package/src/core/self-heal/index.js +989 -973
- package/src/core/self-heal/viewport.js +1505 -564
- package/src/detached-worker.js +99 -99
- package/src/domains/chat/action-journal.js +443 -0
- package/src/domains/chat/cards.js +137 -137
- package/src/domains/chat/constants.js +9 -9
- package/src/domains/chat/detail.js +1684 -401
- package/src/domains/chat/index.js +8 -7
- package/src/domains/chat/jobs.js +620 -620
- package/src/domains/chat/page-guard.js +157 -122
- package/src/domains/chat/roots.js +56 -56
- package/src/domains/chat/run-service.js +1801 -760
- package/src/domains/common/account-rights-panel.js +314 -314
- package/src/domains/common/recovery-settle.js +159 -159
- package/src/domains/recommend/actions.js +515 -472
- package/src/domains/recommend/cards.js +243 -243
- package/src/domains/recommend/colleague-contact.js +333 -333
- package/src/domains/recommend/constants.js +92 -92
- package/src/domains/recommend/detail.js +12 -3
- package/src/domains/recommend/filters.js +611 -611
- package/src/domains/recommend/index.js +9 -9
- package/src/domains/recommend/jobs.js +542 -542
- package/src/domains/recommend/location.js +736 -736
- package/src/domains/recommend/refresh.js +410 -329
- package/src/domains/recommend/roots.js +80 -80
- package/src/domains/recommend/run-service.js +1783 -592
- 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 +236 -236
- package/src/domains/recruit/detail.js +588 -588
- package/src/domains/recruit/index.js +9 -9
- package/src/domains/recruit/instruction-parser.js +866 -866
- package/src/domains/recruit/refresh.js +45 -45
- package/src/domains/recruit/roots.js +68 -68
- package/src/domains/recruit/run-service.js +1817 -1620
- package/src/domains/recruit/search.js +3229 -3229
- package/src/index.js +124 -5
- package/src/parser.js +1296 -1296
- package/src/recommend-mcp.js +515 -80
- package/src/recommend-scheduler.js +66 -0
|
@@ -11,17 +11,17 @@ import {
|
|
|
11
11
|
clickRecommendEndRefreshButton,
|
|
12
12
|
waitForRecommendCardNodeIds
|
|
13
13
|
} from "./cards.js";
|
|
14
|
-
import {
|
|
15
|
-
RECOMMEND_RECENT_NOT_VIEW_LABEL,
|
|
16
|
-
RECOMMEND_TARGET_URL
|
|
17
|
-
} from "./constants.js";
|
|
18
|
-
import { selectAndConfirmFirstSafeFilter } from "./filters.js";
|
|
19
|
-
import { ensureRecommendCurrentCityOnly } from "./location.js";
|
|
20
|
-
import {
|
|
21
|
-
selectRecommendJob,
|
|
22
|
-
verifyRecommendJobSelection
|
|
23
|
-
} from "./jobs.js";
|
|
24
|
-
import { selectRecommendPageScope } from "./scopes.js";
|
|
14
|
+
import {
|
|
15
|
+
RECOMMEND_RECENT_NOT_VIEW_LABEL,
|
|
16
|
+
RECOMMEND_TARGET_URL
|
|
17
|
+
} from "./constants.js";
|
|
18
|
+
import { selectAndConfirmFirstSafeFilter } from "./filters.js";
|
|
19
|
+
import { ensureRecommendCurrentCityOnly } from "./location.js";
|
|
20
|
+
import {
|
|
21
|
+
selectRecommendJob,
|
|
22
|
+
verifyRecommendJobSelection
|
|
23
|
+
} from "./jobs.js";
|
|
24
|
+
import { selectRecommendPageScope } from "./scopes.js";
|
|
25
25
|
import {
|
|
26
26
|
getRecommendRoots,
|
|
27
27
|
waitForRecommendRoots
|
|
@@ -31,19 +31,19 @@ import { isStaleRecommendNodeError } from "./detail.js";
|
|
|
31
31
|
function normalizeLabels(labels = []) {
|
|
32
32
|
return labels.map((label) => String(label || "").trim()).filter(Boolean);
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
function normalizeFilterGroup(spec = {}) {
|
|
36
|
-
return {
|
|
37
|
-
group: String(spec.group || "").trim(),
|
|
38
|
-
labels: normalizeLabels(spec.labels || spec.filterLabels || []),
|
|
39
|
-
selectAllLabels: spec.selectAllLabels !== false,
|
|
40
|
-
allowUnlimited: spec.allowUnlimited === true,
|
|
41
|
-
verifySticky: spec.verifySticky === true
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function buildRecommendFilterGroups(filter = {}, {
|
|
46
|
-
forceRecentNotView = false
|
|
34
|
+
|
|
35
|
+
function normalizeFilterGroup(spec = {}) {
|
|
36
|
+
return {
|
|
37
|
+
group: String(spec.group || "").trim(),
|
|
38
|
+
labels: normalizeLabels(spec.labels || spec.filterLabels || []),
|
|
39
|
+
selectAllLabels: spec.selectAllLabels !== false,
|
|
40
|
+
allowUnlimited: spec.allowUnlimited === true,
|
|
41
|
+
verifySticky: spec.verifySticky === true
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function buildRecommendFilterGroups(filter = {}, {
|
|
46
|
+
forceRecentNotView = false
|
|
47
47
|
} = {}) {
|
|
48
48
|
const groups = [];
|
|
49
49
|
const sourceGroups = Array.isArray(filter.filterGroups)
|
|
@@ -68,19 +68,19 @@ export function buildRecommendFilterGroups(filter = {}, {
|
|
|
68
68
|
if (!recentGroup.labels.some((label) => label.replace(/\s+/g, "") === RECOMMEND_RECENT_NOT_VIEW_LABEL)) {
|
|
69
69
|
recentGroup.labels.push(RECOMMEND_RECENT_NOT_VIEW_LABEL);
|
|
70
70
|
}
|
|
71
|
-
recentGroup.selectAllLabels = true;
|
|
72
|
-
} else {
|
|
73
|
-
groups.unshift({
|
|
74
|
-
group: "recentNotView",
|
|
75
|
-
labels: [RECOMMEND_RECENT_NOT_VIEW_LABEL],
|
|
76
|
-
selectAllLabels: true,
|
|
77
|
-
allowUnlimited: false,
|
|
78
|
-
verifySticky: false
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return groups;
|
|
71
|
+
recentGroup.selectAllLabels = true;
|
|
72
|
+
} else {
|
|
73
|
+
groups.unshift({
|
|
74
|
+
group: "recentNotView",
|
|
75
|
+
labels: [RECOMMEND_RECENT_NOT_VIEW_LABEL],
|
|
76
|
+
selectAllLabels: true,
|
|
77
|
+
allowUnlimited: false,
|
|
78
|
+
verifySticky: false
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return groups;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
export function buildRecommendFilterSelectionOptions(filter = {}, {
|
|
@@ -90,57 +90,133 @@ export function buildRecommendFilterSelectionOptions(filter = {}, {
|
|
|
90
90
|
if (filterGroups.length > 1 || forceRecentNotView || Array.isArray(filter.filterGroups) || Array.isArray(filter.groups)) {
|
|
91
91
|
return { filterGroups };
|
|
92
92
|
}
|
|
93
|
-
const [singleGroup] = filterGroups;
|
|
94
|
-
if (singleGroup) {
|
|
95
|
-
return {
|
|
96
|
-
group: singleGroup.group,
|
|
97
|
-
labels: singleGroup.labels,
|
|
98
|
-
selectAllLabels: singleGroup.selectAllLabels,
|
|
99
|
-
allowUnlimited: singleGroup.allowUnlimited,
|
|
100
|
-
verifySticky: singleGroup.verifySticky
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
group: filter.group || "",
|
|
105
|
-
labels: normalizeLabels(filter.labels || filter.filterLabels || []),
|
|
106
|
-
selectAllLabels: filter.selectAllLabels !== false,
|
|
107
|
-
allowUnlimited: filter.allowUnlimited === true,
|
|
108
|
-
verifySticky: filter.verifySticky === true
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export async function applyRecommendFilterEnvelopeStages(filter = {}, {
|
|
113
|
-
applyCurrentCityOnly,
|
|
114
|
-
applyFilterPanel
|
|
115
|
-
} = {}) {
|
|
116
|
-
if (filter.enabled === false) {
|
|
117
|
-
return {
|
|
118
|
-
applied: false,
|
|
119
|
-
skipped: true,
|
|
120
|
-
current_city_only: null,
|
|
121
|
-
filter: null
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
if (typeof applyCurrentCityOnly !== "function" || typeof applyFilterPanel !== "function") {
|
|
125
|
-
throw new Error("Recommend native filter stages require location and filter-panel callbacks");
|
|
126
|
-
}
|
|
127
|
-
const currentCityOnlyResult = await applyCurrentCityOnly();
|
|
128
|
-
const filterResult = await applyFilterPanel();
|
|
129
|
-
return {
|
|
130
|
-
applied: true,
|
|
131
|
-
skipped: false,
|
|
132
|
-
current_city_only: currentCityOnlyResult,
|
|
133
|
-
filter: filterResult
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function refreshFailureReason(method = "") {
|
|
138
|
-
return method === "page_navigate" ? "page_navigate_failed" : "page_reload_failed";
|
|
93
|
+
const [singleGroup] = filterGroups;
|
|
94
|
+
if (singleGroup) {
|
|
95
|
+
return {
|
|
96
|
+
group: singleGroup.group,
|
|
97
|
+
labels: singleGroup.labels,
|
|
98
|
+
selectAllLabels: singleGroup.selectAllLabels,
|
|
99
|
+
allowUnlimited: singleGroup.allowUnlimited,
|
|
100
|
+
verifySticky: singleGroup.verifySticky
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
group: filter.group || "",
|
|
105
|
+
labels: normalizeLabels(filter.labels || filter.filterLabels || []),
|
|
106
|
+
selectAllLabels: filter.selectAllLabels !== false,
|
|
107
|
+
allowUnlimited: filter.allowUnlimited === true,
|
|
108
|
+
verifySticky: filter.verifySticky === true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function applyRecommendFilterEnvelopeStages(filter = {}, {
|
|
113
|
+
applyCurrentCityOnly,
|
|
114
|
+
applyFilterPanel
|
|
115
|
+
} = {}) {
|
|
116
|
+
if (filter.enabled === false) {
|
|
117
|
+
return {
|
|
118
|
+
applied: false,
|
|
119
|
+
skipped: true,
|
|
120
|
+
current_city_only: null,
|
|
121
|
+
filter: null
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if (typeof applyCurrentCityOnly !== "function" || typeof applyFilterPanel !== "function") {
|
|
125
|
+
throw new Error("Recommend native filter stages require location and filter-panel callbacks");
|
|
126
|
+
}
|
|
127
|
+
const currentCityOnlyResult = await applyCurrentCityOnly();
|
|
128
|
+
const filterResult = await applyFilterPanel();
|
|
129
|
+
return {
|
|
130
|
+
applied: true,
|
|
131
|
+
skipped: false,
|
|
132
|
+
current_city_only: currentCityOnlyResult,
|
|
133
|
+
filter: filterResult
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function refreshFailureReason(method = "") {
|
|
138
|
+
return method === "page_navigate" ? "page_navigate_failed" : "page_reload_failed";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function safeDiagnosticText(value, maxLength = 4000) {
|
|
142
|
+
const text = String(value ?? "");
|
|
143
|
+
return text.length > maxLength ? `${text.slice(0, maxLength)}…` : text;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function safeDiagnosticStack(stack) {
|
|
147
|
+
if (!stack) return null;
|
|
148
|
+
return safeDiagnosticText(stack, 8000)
|
|
149
|
+
.split(/\r?\n/)
|
|
150
|
+
.slice(0, 12)
|
|
151
|
+
.join("\n");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function buildErrorDiagnostic(error, {
|
|
155
|
+
depth = 0,
|
|
156
|
+
seen = new Set()
|
|
157
|
+
} = {}) {
|
|
158
|
+
if (!error) return null;
|
|
159
|
+
const isRecord = typeof error === "object" || typeof error === "function";
|
|
160
|
+
if (isRecord && seen.has(error)) {
|
|
161
|
+
return {
|
|
162
|
+
name: error?.name || "Error",
|
|
163
|
+
message: safeDiagnosticText(error?.message || String(error)),
|
|
164
|
+
circular: true
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (isRecord) seen.add(error);
|
|
168
|
+
const diagnostic = {
|
|
169
|
+
name: error?.name || "Error",
|
|
170
|
+
message: safeDiagnosticText(error?.message || String(error))
|
|
171
|
+
};
|
|
172
|
+
if (error?.code !== undefined && error?.code !== null && error.code !== "") {
|
|
173
|
+
diagnostic.code = typeof error.code === "number"
|
|
174
|
+
? error.code
|
|
175
|
+
: safeDiagnosticText(error.code, 300);
|
|
176
|
+
}
|
|
177
|
+
if (error?.phase) diagnostic.phase = safeDiagnosticText(error.phase, 300);
|
|
178
|
+
if (error?.cdp_method) diagnostic.cdp_method = safeDiagnosticText(error.cdp_method, 300);
|
|
179
|
+
if (error?.cdp_at) diagnostic.cdp_at = safeDiagnosticText(error.cdp_at, 100);
|
|
180
|
+
if (Number.isInteger(error?.cdp_node_id)) diagnostic.cdp_node_id = error.cdp_node_id;
|
|
181
|
+
if (Number.isInteger(error?.cdp_backend_node_id)) {
|
|
182
|
+
diagnostic.cdp_backend_node_id = error.cdp_backend_node_id;
|
|
183
|
+
}
|
|
184
|
+
if (Number.isInteger(error?.node_id)) diagnostic.node_id = error.node_id;
|
|
185
|
+
if (Number.isInteger(error?.backend_node_id)) diagnostic.backend_node_id = error.backend_node_id;
|
|
186
|
+
if (error?.cdp_search_id) diagnostic.cdp_search_id = safeDiagnosticText(error.cdp_search_id, 300);
|
|
187
|
+
if (Array.isArray(error?.cdp_param_keys)) {
|
|
188
|
+
diagnostic.cdp_param_keys = error.cdp_param_keys
|
|
189
|
+
.slice(0, 20)
|
|
190
|
+
.map((key) => safeDiagnosticText(key, 100));
|
|
191
|
+
}
|
|
192
|
+
const stack = safeDiagnosticStack(error?.stack);
|
|
193
|
+
if (stack) diagnostic.stack = stack;
|
|
194
|
+
if (depth < 2 && error?.cause && error.cause !== error) {
|
|
195
|
+
diagnostic.cause = buildErrorDiagnostic(error.cause, {
|
|
196
|
+
depth: depth + 1,
|
|
197
|
+
seen
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return diagnostic;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function compactRecommendRefreshErrorDiagnostic(error) {
|
|
204
|
+
return buildErrorDiagnostic(error);
|
|
139
205
|
}
|
|
140
206
|
|
|
141
207
|
export function isRetryableRecommendFilterReapplyError(error) {
|
|
142
|
-
const
|
|
143
|
-
|
|
208
|
+
const messages = [];
|
|
209
|
+
const seen = new Set();
|
|
210
|
+
let current = error;
|
|
211
|
+
for (let depth = 0; current && depth < 4; depth += 1) {
|
|
212
|
+
if ((typeof current === "object" || typeof current === "function") && seen.has(current)) break;
|
|
213
|
+
if (typeof current === "object" || typeof current === "function") seen.add(current);
|
|
214
|
+
if (isStaleRecommendNodeError(current)) return true;
|
|
215
|
+
messages.push(String(current?.message || current || ""));
|
|
216
|
+
current = current?.cause;
|
|
217
|
+
}
|
|
218
|
+
const message = messages.join("\n");
|
|
219
|
+
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|Invalid (?:backend )?node(?:\s*id)?|Node with given id does not exist|No node found for given backend id/i.test(message);
|
|
144
220
|
}
|
|
145
221
|
|
|
146
222
|
function compactFilterReapplyError(error) {
|
|
@@ -165,6 +241,7 @@ function compactJobSelectionAttempt({
|
|
|
165
241
|
method: "job_select",
|
|
166
242
|
reason: error ? "job_select_failed" : null,
|
|
167
243
|
error: error ? (error?.message || String(error)) : null,
|
|
244
|
+
error_diagnostic: error ? compactRecommendRefreshErrorDiagnostic(error) : null,
|
|
168
245
|
attempt,
|
|
169
246
|
iframe_document_node_id: iframeDocumentNodeId || 0,
|
|
170
247
|
selected: Boolean(selection?.selected),
|
|
@@ -326,6 +403,7 @@ async function selectAndConfirmRefreshFilter(client, rootState, filterOptions, {
|
|
|
326
403
|
method: "filter_reapply",
|
|
327
404
|
reason: "filter_reapply_failed",
|
|
328
405
|
error: compactFilterReapplyError(error),
|
|
406
|
+
error_diagnostic: compactRecommendRefreshErrorDiagnostic(error),
|
|
329
407
|
attempt
|
|
330
408
|
});
|
|
331
409
|
if (attempt >= maxAttempts || !isRetryableRecommendFilterReapplyError(error)) {
|
|
@@ -337,94 +415,95 @@ async function selectAndConfirmRefreshFilter(client, rootState, filterOptions, {
|
|
|
337
415
|
}
|
|
338
416
|
|
|
339
417
|
const wrapped = new Error(compactFilterReapplyError(lastError));
|
|
340
|
-
wrapped.cause = lastError;
|
|
341
|
-
wrapped.filter_reapply_attempts = attempts;
|
|
342
|
-
throw wrapped;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function compactCurrentCityOnlyReapplyError(error) {
|
|
346
|
-
return error?.message || String(error || "Recommend current-city-only reapply failed");
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function isRetryableRecommendCurrentCityOnlyReapplyError(error) {
|
|
350
|
-
if (isStaleRecommendNodeError(error)) return true;
|
|
351
|
-
const message = compactCurrentCityOnlyReapplyError(error);
|
|
352
|
-
return /current-city|current city|location|popover|trigger|checkbox|stale|did not (?:open|mount|close)/i.test(message)
|
|
353
|
-
&& !/unavailable/i.test(message);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
async function ensureRefreshCurrentCityOnly(client, rootState, {
|
|
357
|
-
enabled = false,
|
|
358
|
-
maxAttempts = 3,
|
|
359
|
-
retryDelayMs = 1500
|
|
360
|
-
} = {}) {
|
|
361
|
-
const attempts = [];
|
|
362
|
-
let currentRootState = rootState;
|
|
363
|
-
let lastError = null;
|
|
364
|
-
|
|
365
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
366
|
-
try {
|
|
367
|
-
const result = await ensureRecommendCurrentCityOnly(
|
|
368
|
-
client,
|
|
369
|
-
currentRootState.iframe.documentNodeId,
|
|
370
|
-
{ enabled }
|
|
371
|
-
);
|
|
372
|
-
attempts.push({
|
|
373
|
-
ok: true,
|
|
374
|
-
method: "current_city_only_reapply",
|
|
375
|
-
attempt,
|
|
376
|
-
result
|
|
377
|
-
});
|
|
378
|
-
return {
|
|
379
|
-
current_city_only: result,
|
|
380
|
-
root_state: currentRootState,
|
|
381
|
-
attempts
|
|
382
|
-
};
|
|
383
|
-
} catch (error) {
|
|
384
|
-
lastError = error;
|
|
385
|
-
attempts.push({
|
|
386
|
-
ok: false,
|
|
387
|
-
method: "current_city_only_reapply",
|
|
388
|
-
reason: "current_city_only_reapply_failed",
|
|
389
|
-
error: compactCurrentCityOnlyReapplyError(error),
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
wrapped
|
|
402
|
-
wrapped.
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
418
|
+
wrapped.cause = lastError;
|
|
419
|
+
wrapped.filter_reapply_attempts = attempts;
|
|
420
|
+
throw wrapped;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function compactCurrentCityOnlyReapplyError(error) {
|
|
424
|
+
return error?.message || String(error || "Recommend current-city-only reapply failed");
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function isRetryableRecommendCurrentCityOnlyReapplyError(error) {
|
|
428
|
+
if (isStaleRecommendNodeError(error)) return true;
|
|
429
|
+
const message = compactCurrentCityOnlyReapplyError(error);
|
|
430
|
+
return /current-city|current city|location|popover|trigger|checkbox|stale|did not (?:open|mount|close)/i.test(message)
|
|
431
|
+
&& !/unavailable/i.test(message);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
async function ensureRefreshCurrentCityOnly(client, rootState, {
|
|
435
|
+
enabled = false,
|
|
436
|
+
maxAttempts = 3,
|
|
437
|
+
retryDelayMs = 1500
|
|
438
|
+
} = {}) {
|
|
439
|
+
const attempts = [];
|
|
440
|
+
let currentRootState = rootState;
|
|
441
|
+
let lastError = null;
|
|
442
|
+
|
|
443
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
444
|
+
try {
|
|
445
|
+
const result = await ensureRecommendCurrentCityOnly(
|
|
446
|
+
client,
|
|
447
|
+
currentRootState.iframe.documentNodeId,
|
|
448
|
+
{ enabled }
|
|
449
|
+
);
|
|
450
|
+
attempts.push({
|
|
451
|
+
ok: true,
|
|
452
|
+
method: "current_city_only_reapply",
|
|
453
|
+
attempt,
|
|
454
|
+
result
|
|
455
|
+
});
|
|
456
|
+
return {
|
|
457
|
+
current_city_only: result,
|
|
458
|
+
root_state: currentRootState,
|
|
459
|
+
attempts
|
|
460
|
+
};
|
|
461
|
+
} catch (error) {
|
|
462
|
+
lastError = error;
|
|
463
|
+
attempts.push({
|
|
464
|
+
ok: false,
|
|
465
|
+
method: "current_city_only_reapply",
|
|
466
|
+
reason: "current_city_only_reapply_failed",
|
|
467
|
+
error: compactCurrentCityOnlyReapplyError(error),
|
|
468
|
+
error_diagnostic: compactRecommendRefreshErrorDiagnostic(error),
|
|
469
|
+
attempt
|
|
470
|
+
});
|
|
471
|
+
if (attempt >= maxAttempts || !isRetryableRecommendCurrentCityOnlyReapplyError(error)) {
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
474
|
+
if (retryDelayMs > 0) await sleep(retryDelayMs);
|
|
475
|
+
currentRootState = await getRecommendRoots(client);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const wrapped = new Error(compactCurrentCityOnlyReapplyError(lastError));
|
|
480
|
+
wrapped.cause = lastError;
|
|
481
|
+
wrapped.current_city_only_attempts = attempts;
|
|
482
|
+
throw wrapped;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
async function applyRefreshMethod(client, method, {
|
|
486
|
+
jobLabel = "",
|
|
487
|
+
pageScope = "recommend",
|
|
488
|
+
fallbackPageScope = "recommend",
|
|
489
|
+
filter = {},
|
|
411
490
|
targetUrl = RECOMMEND_TARGET_URL,
|
|
412
491
|
forceRecentNotView = true,
|
|
413
492
|
cardTimeoutMs = 30000,
|
|
414
493
|
reloadSettleMs = 8000
|
|
415
494
|
} = {}) {
|
|
416
|
-
const started = Date.now();
|
|
417
|
-
let currentRootState = null;
|
|
418
|
-
let jobSelection = null;
|
|
419
|
-
let jobSelectionAttempts = [];
|
|
420
|
-
let pageScopeResult = null;
|
|
421
|
-
let currentCityOnlyResult = null;
|
|
422
|
-
let currentCityOnlyAttempts = [];
|
|
423
|
-
let filterResult = null;
|
|
424
|
-
let filterReapplyAttempts = [];
|
|
425
|
-
let recoverySettle = null;
|
|
426
|
-
try {
|
|
427
|
-
if (method === "page_navigate") {
|
|
495
|
+
const started = Date.now();
|
|
496
|
+
let currentRootState = null;
|
|
497
|
+
let jobSelection = null;
|
|
498
|
+
let jobSelectionAttempts = [];
|
|
499
|
+
let pageScopeResult = null;
|
|
500
|
+
let currentCityOnlyResult = null;
|
|
501
|
+
let currentCityOnlyAttempts = [];
|
|
502
|
+
let filterResult = null;
|
|
503
|
+
let filterReapplyAttempts = [];
|
|
504
|
+
let recoverySettle = null;
|
|
505
|
+
try {
|
|
506
|
+
if (method === "page_navigate") {
|
|
428
507
|
await client.Page.navigate({ url: targetUrl || RECOMMEND_TARGET_URL });
|
|
429
508
|
} else {
|
|
430
509
|
await client.Page.reload({ ignoreCache: true });
|
|
@@ -467,83 +546,84 @@ async function applyRefreshMethod(client, method, {
|
|
|
467
546
|
settleMs: reloadSettleMs > 10000 ? 3000 : 1200,
|
|
468
547
|
timeoutMs: Math.max(10000, Math.min(cardTimeoutMs, 60000))
|
|
469
548
|
}
|
|
470
|
-
);
|
|
471
|
-
if (!pageScopeResult.selected) {
|
|
472
|
-
throw new Error(`Recommend page scope was not selected after refresh reload: ${pageScopeResult.reason || pageScope}`);
|
|
473
|
-
}
|
|
474
|
-
currentRootState = await getRecommendRoots(client);
|
|
475
|
-
const retryDelayMs = Math.max(1200, Math.min(5000, Math.floor((reloadSettleMs || 8000) / 2)));
|
|
476
|
-
const filterStages = await applyRecommendFilterEnvelopeStages(filter, {
|
|
477
|
-
applyCurrentCityOnly: async () => {
|
|
478
|
-
const selection = await ensureRefreshCurrentCityOnly(client, currentRootState, {
|
|
479
|
-
enabled: filter.currentCityOnly === true || filter.current_city_only === true,
|
|
480
|
-
retryDelayMs
|
|
481
|
-
});
|
|
482
|
-
currentCityOnlyAttempts = selection.attempts;
|
|
483
|
-
currentRootState = await getRecommendRoots(client);
|
|
484
|
-
return selection.current_city_only;
|
|
485
|
-
},
|
|
486
|
-
applyFilterPanel: async () => {
|
|
487
|
-
const selection = await selectAndConfirmRefreshFilter(
|
|
488
|
-
client,
|
|
489
|
-
currentRootState,
|
|
490
|
-
buildRecommendFilterSelectionOptions(filter, { forceRecentNotView }),
|
|
491
|
-
{ retryDelayMs }
|
|
492
|
-
);
|
|
493
|
-
filterReapplyAttempts = selection.attempts;
|
|
494
|
-
currentRootState = await getRecommendRoots(client);
|
|
495
|
-
return selection.filter;
|
|
496
|
-
}
|
|
497
|
-
});
|
|
498
|
-
currentCityOnlyResult = filterStages.current_city_only;
|
|
499
|
-
filterResult = filterStages.filter;
|
|
500
|
-
const cardNodeIds = await waitForRecommendCardNodeIds(client, currentRootState.iframe.documentNodeId, {
|
|
501
|
-
timeoutMs: cardTimeoutMs,
|
|
502
|
-
intervalMs: 500
|
|
503
|
-
});
|
|
504
|
-
if (!cardNodeIds.length) {
|
|
549
|
+
);
|
|
550
|
+
if (!pageScopeResult.selected) {
|
|
551
|
+
throw new Error(`Recommend page scope was not selected after refresh reload: ${pageScopeResult.reason || pageScope}`);
|
|
552
|
+
}
|
|
553
|
+
currentRootState = await getRecommendRoots(client);
|
|
554
|
+
const retryDelayMs = Math.max(1200, Math.min(5000, Math.floor((reloadSettleMs || 8000) / 2)));
|
|
555
|
+
const filterStages = await applyRecommendFilterEnvelopeStages(filter, {
|
|
556
|
+
applyCurrentCityOnly: async () => {
|
|
557
|
+
const selection = await ensureRefreshCurrentCityOnly(client, currentRootState, {
|
|
558
|
+
enabled: filter.currentCityOnly === true || filter.current_city_only === true,
|
|
559
|
+
retryDelayMs
|
|
560
|
+
});
|
|
561
|
+
currentCityOnlyAttempts = selection.attempts;
|
|
562
|
+
currentRootState = await getRecommendRoots(client);
|
|
563
|
+
return selection.current_city_only;
|
|
564
|
+
},
|
|
565
|
+
applyFilterPanel: async () => {
|
|
566
|
+
const selection = await selectAndConfirmRefreshFilter(
|
|
567
|
+
client,
|
|
568
|
+
currentRootState,
|
|
569
|
+
buildRecommendFilterSelectionOptions(filter, { forceRecentNotView }),
|
|
570
|
+
{ retryDelayMs }
|
|
571
|
+
);
|
|
572
|
+
filterReapplyAttempts = selection.attempts;
|
|
573
|
+
currentRootState = await getRecommendRoots(client);
|
|
574
|
+
return selection.filter;
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
currentCityOnlyResult = filterStages.current_city_only;
|
|
578
|
+
filterResult = filterStages.filter;
|
|
579
|
+
const cardNodeIds = await waitForRecommendCardNodeIds(client, currentRootState.iframe.documentNodeId, {
|
|
580
|
+
timeoutMs: cardTimeoutMs,
|
|
581
|
+
intervalMs: 500
|
|
582
|
+
});
|
|
583
|
+
if (!cardNodeIds.length) {
|
|
505
584
|
throw new Error("No recommend candidate cards were found after refresh reload");
|
|
506
585
|
}
|
|
507
586
|
return {
|
|
508
587
|
ok: true,
|
|
509
588
|
method,
|
|
510
|
-
target_url: method === "page_navigate" ? (targetUrl || RECOMMEND_TARGET_URL) : null,
|
|
511
|
-
job_selection: jobSelection,
|
|
512
|
-
job_selection_attempts: jobSelectionAttempts,
|
|
513
|
-
recovery_settle: recoverySettle,
|
|
514
|
-
page_scope: pageScopeResult,
|
|
515
|
-
current_city_only: currentCityOnlyResult,
|
|
516
|
-
current_city_only_attempts: currentCityOnlyAttempts,
|
|
517
|
-
filter: filterResult,
|
|
518
|
-
filter_reapply_attempts: filterReapplyAttempts,
|
|
519
|
-
card_count: cardNodeIds.length,
|
|
520
|
-
root_state: currentRootState,
|
|
521
|
-
forced_recent_not_view: Boolean(forceRecentNotView && filter.enabled !== false),
|
|
522
|
-
elapsed_ms: Date.now() - started
|
|
523
|
-
};
|
|
524
|
-
} catch (error) {
|
|
525
|
-
return {
|
|
526
|
-
ok: false,
|
|
589
|
+
target_url: method === "page_navigate" ? (targetUrl || RECOMMEND_TARGET_URL) : null,
|
|
590
|
+
job_selection: jobSelection,
|
|
591
|
+
job_selection_attempts: jobSelectionAttempts,
|
|
592
|
+
recovery_settle: recoverySettle,
|
|
593
|
+
page_scope: pageScopeResult,
|
|
594
|
+
current_city_only: currentCityOnlyResult,
|
|
595
|
+
current_city_only_attempts: currentCityOnlyAttempts,
|
|
596
|
+
filter: filterResult,
|
|
597
|
+
filter_reapply_attempts: filterReapplyAttempts,
|
|
598
|
+
card_count: cardNodeIds.length,
|
|
599
|
+
root_state: currentRootState,
|
|
600
|
+
forced_recent_not_view: Boolean(forceRecentNotView && filter.enabled !== false),
|
|
601
|
+
elapsed_ms: Date.now() - started
|
|
602
|
+
};
|
|
603
|
+
} catch (error) {
|
|
604
|
+
return {
|
|
605
|
+
ok: false,
|
|
527
606
|
method,
|
|
528
607
|
reason: refreshFailureReason(method),
|
|
529
608
|
error: error?.message || String(error),
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
|
|
609
|
+
error_diagnostic: compactRecommendRefreshErrorDiagnostic(error),
|
|
610
|
+
target_url: method === "page_navigate" ? (targetUrl || RECOMMEND_TARGET_URL) : null,
|
|
611
|
+
job_selection: jobSelection,
|
|
612
|
+
job_selection_attempts: error?.job_selection_attempts || jobSelectionAttempts,
|
|
613
|
+
recovery_settle: error?.recovery_settle || recoverySettle,
|
|
614
|
+
page_scope: pageScopeResult,
|
|
615
|
+
current_city_only: currentCityOnlyResult,
|
|
616
|
+
current_city_only_attempts: error?.current_city_only_attempts || currentCityOnlyAttempts,
|
|
617
|
+
filter: filterResult,
|
|
618
|
+
filter_reapply_attempts: error?.filter_reapply_attempts || filterReapplyAttempts,
|
|
619
|
+
card_count: 0,
|
|
620
|
+
root_state: currentRootState,
|
|
621
|
+
forced_recent_not_view: Boolean(forceRecentNotView && filter.enabled !== false),
|
|
622
|
+
elapsed_ms: Date.now() - started
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
547
627
|
export async function refreshRecommendListAtEnd(client, {
|
|
548
628
|
rootState = null,
|
|
549
629
|
jobLabel = "",
|
|
@@ -565,91 +645,92 @@ export async function refreshRecommendListAtEnd(client, {
|
|
|
565
645
|
currentRootState = currentRootState || await getRecommendRoots(client);
|
|
566
646
|
const buttonResult = await clickRecommendEndRefreshButton(
|
|
567
647
|
client,
|
|
568
|
-
currentRootState.iframe.documentNodeId,
|
|
569
|
-
{ settleMs: buttonSettleMs }
|
|
570
|
-
);
|
|
571
|
-
attempts.push(buttonResult);
|
|
572
|
-
if (buttonResult.ok) {
|
|
573
|
-
let pageScopeResult = null;
|
|
574
|
-
let currentCityOnlyResult = null;
|
|
575
|
-
let currentCityOnlyAttempts = [];
|
|
576
|
-
let filterResult = null;
|
|
577
|
-
let filterReapplyAttempts = [];
|
|
578
|
-
try {
|
|
579
|
-
currentRootState = await getRecommendRoots(client);
|
|
580
|
-
pageScopeResult = await selectRecommendPageScope(
|
|
581
|
-
client,
|
|
582
|
-
currentRootState.iframe.documentNodeId,
|
|
583
|
-
{
|
|
584
|
-
pageScope,
|
|
585
|
-
fallbackScope: fallbackPageScope,
|
|
648
|
+
currentRootState.iframe.documentNodeId,
|
|
649
|
+
{ settleMs: buttonSettleMs }
|
|
650
|
+
);
|
|
651
|
+
attempts.push(buttonResult);
|
|
652
|
+
if (buttonResult.ok) {
|
|
653
|
+
let pageScopeResult = null;
|
|
654
|
+
let currentCityOnlyResult = null;
|
|
655
|
+
let currentCityOnlyAttempts = [];
|
|
656
|
+
let filterResult = null;
|
|
657
|
+
let filterReapplyAttempts = [];
|
|
658
|
+
try {
|
|
659
|
+
currentRootState = await getRecommendRoots(client);
|
|
660
|
+
pageScopeResult = await selectRecommendPageScope(
|
|
661
|
+
client,
|
|
662
|
+
currentRootState.iframe.documentNodeId,
|
|
663
|
+
{
|
|
664
|
+
pageScope,
|
|
665
|
+
fallbackScope: fallbackPageScope,
|
|
586
666
|
settleMs: buttonSettleMs > 10000 ? 3000 : 1200,
|
|
587
667
|
timeoutMs: Math.max(10000, Math.min(cardTimeoutMs, 60000))
|
|
588
668
|
}
|
|
589
|
-
);
|
|
590
|
-
if (!pageScopeResult.selected) {
|
|
591
|
-
throw new Error(`Recommend page scope was not selected after end refresh: ${pageScopeResult.reason || pageScope}`);
|
|
592
|
-
}
|
|
593
|
-
currentRootState = await getRecommendRoots(client);
|
|
594
|
-
const retryDelayMs = Math.max(1200, Math.min(5000, Math.floor((buttonSettleMs || 8000) / 2)));
|
|
595
|
-
const filterStages = await applyRecommendFilterEnvelopeStages(filter, {
|
|
596
|
-
applyCurrentCityOnly: async () => {
|
|
597
|
-
const selection = await ensureRefreshCurrentCityOnly(client, currentRootState, {
|
|
598
|
-
enabled: filter.currentCityOnly === true || filter.current_city_only === true,
|
|
599
|
-
retryDelayMs
|
|
600
|
-
});
|
|
601
|
-
currentCityOnlyAttempts = selection.attempts;
|
|
602
|
-
currentRootState = await getRecommendRoots(client);
|
|
603
|
-
return selection.current_city_only;
|
|
604
|
-
},
|
|
605
|
-
applyFilterPanel: async () => {
|
|
606
|
-
const selection = await selectAndConfirmRefreshFilter(
|
|
607
|
-
client,
|
|
608
|
-
currentRootState,
|
|
609
|
-
buildRecommendFilterSelectionOptions(filter, { forceRecentNotView }),
|
|
610
|
-
{ retryDelayMs }
|
|
611
|
-
);
|
|
612
|
-
filterReapplyAttempts = selection.attempts;
|
|
613
|
-
currentRootState = await getRecommendRoots(client);
|
|
614
|
-
return selection.filter;
|
|
615
|
-
}
|
|
616
|
-
});
|
|
617
|
-
currentCityOnlyResult = filterStages.current_city_only;
|
|
618
|
-
filterResult = filterStages.filter;
|
|
619
|
-
const cardNodeIds = await waitForRecommendCardNodeIds(client, currentRootState.iframe.documentNodeId, {
|
|
620
|
-
timeoutMs: cardTimeoutMs,
|
|
621
|
-
intervalMs: 500
|
|
622
|
-
});
|
|
623
|
-
return {
|
|
624
|
-
ok: cardNodeIds.length > 0,
|
|
625
|
-
method: "end_refresh_button",
|
|
626
|
-
attempts,
|
|
627
|
-
page_scope: pageScopeResult,
|
|
628
|
-
current_city_only: currentCityOnlyResult,
|
|
629
|
-
current_city_only_attempts: currentCityOnlyAttempts,
|
|
630
|
-
filter: filterResult,
|
|
631
|
-
filter_reapply_attempts: filterReapplyAttempts,
|
|
632
|
-
card_count: cardNodeIds.length,
|
|
633
|
-
root_state: currentRootState,
|
|
634
|
-
forced_recent_not_view: Boolean(forceRecentNotView && filter.enabled !== false)
|
|
635
|
-
};
|
|
636
|
-
} catch (error) {
|
|
637
|
-
attempts.push({
|
|
638
|
-
ok: false,
|
|
639
|
-
method: "end_refresh_button_after_click",
|
|
640
|
-
reason: "end_refresh_reapply_failed",
|
|
641
|
-
error: error?.message || String(error),
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
669
|
+
);
|
|
670
|
+
if (!pageScopeResult.selected) {
|
|
671
|
+
throw new Error(`Recommend page scope was not selected after end refresh: ${pageScopeResult.reason || pageScope}`);
|
|
672
|
+
}
|
|
673
|
+
currentRootState = await getRecommendRoots(client);
|
|
674
|
+
const retryDelayMs = Math.max(1200, Math.min(5000, Math.floor((buttonSettleMs || 8000) / 2)));
|
|
675
|
+
const filterStages = await applyRecommendFilterEnvelopeStages(filter, {
|
|
676
|
+
applyCurrentCityOnly: async () => {
|
|
677
|
+
const selection = await ensureRefreshCurrentCityOnly(client, currentRootState, {
|
|
678
|
+
enabled: filter.currentCityOnly === true || filter.current_city_only === true,
|
|
679
|
+
retryDelayMs
|
|
680
|
+
});
|
|
681
|
+
currentCityOnlyAttempts = selection.attempts;
|
|
682
|
+
currentRootState = await getRecommendRoots(client);
|
|
683
|
+
return selection.current_city_only;
|
|
684
|
+
},
|
|
685
|
+
applyFilterPanel: async () => {
|
|
686
|
+
const selection = await selectAndConfirmRefreshFilter(
|
|
687
|
+
client,
|
|
688
|
+
currentRootState,
|
|
689
|
+
buildRecommendFilterSelectionOptions(filter, { forceRecentNotView }),
|
|
690
|
+
{ retryDelayMs }
|
|
691
|
+
);
|
|
692
|
+
filterReapplyAttempts = selection.attempts;
|
|
693
|
+
currentRootState = await getRecommendRoots(client);
|
|
694
|
+
return selection.filter;
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
currentCityOnlyResult = filterStages.current_city_only;
|
|
698
|
+
filterResult = filterStages.filter;
|
|
699
|
+
const cardNodeIds = await waitForRecommendCardNodeIds(client, currentRootState.iframe.documentNodeId, {
|
|
700
|
+
timeoutMs: cardTimeoutMs,
|
|
701
|
+
intervalMs: 500
|
|
702
|
+
});
|
|
703
|
+
return {
|
|
704
|
+
ok: cardNodeIds.length > 0,
|
|
705
|
+
method: "end_refresh_button",
|
|
706
|
+
attempts,
|
|
707
|
+
page_scope: pageScopeResult,
|
|
708
|
+
current_city_only: currentCityOnlyResult,
|
|
709
|
+
current_city_only_attempts: currentCityOnlyAttempts,
|
|
710
|
+
filter: filterResult,
|
|
711
|
+
filter_reapply_attempts: filterReapplyAttempts,
|
|
712
|
+
card_count: cardNodeIds.length,
|
|
713
|
+
root_state: currentRootState,
|
|
714
|
+
forced_recent_not_view: Boolean(forceRecentNotView && filter.enabled !== false)
|
|
715
|
+
};
|
|
716
|
+
} catch (error) {
|
|
717
|
+
attempts.push({
|
|
718
|
+
ok: false,
|
|
719
|
+
method: "end_refresh_button_after_click",
|
|
720
|
+
reason: "end_refresh_reapply_failed",
|
|
721
|
+
error: error?.message || String(error),
|
|
722
|
+
error_diagnostic: compactRecommendRefreshErrorDiagnostic(error),
|
|
723
|
+
page_scope: pageScopeResult,
|
|
724
|
+
current_city_only: currentCityOnlyResult,
|
|
725
|
+
current_city_only_attempts: error?.current_city_only_attempts || currentCityOnlyAttempts,
|
|
726
|
+
filter: filterResult,
|
|
727
|
+
filter_reapply_attempts: error?.filter_reapply_attempts || filterReapplyAttempts,
|
|
728
|
+
forced_recent_not_view: Boolean(forceRecentNotView && filter.enabled !== false)
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
653
734
|
const fallbackMethods = [];
|
|
654
735
|
if (forceNavigate && typeof client?.Page?.navigate === "function") {
|
|
655
736
|
fallbackMethods.push("page_navigate");
|
|
@@ -686,13 +767,13 @@ export async function refreshRecommendListAtEnd(client, {
|
|
|
686
767
|
return {
|
|
687
768
|
...(lastRefreshResult || {
|
|
688
769
|
ok: false,
|
|
689
|
-
method: fallbackMethods[fallbackMethods.length - 1] || "page_reload",
|
|
690
|
-
reason: "refresh_failed",
|
|
691
|
-
error: "Recommend refresh did not run",
|
|
692
|
-
card_count: 0,
|
|
693
|
-
root_state: currentRootState,
|
|
694
|
-
forced_recent_not_view: Boolean(forceRecentNotView && filter.enabled !== false)
|
|
695
|
-
}),
|
|
696
|
-
attempts
|
|
697
|
-
};
|
|
698
|
-
}
|
|
770
|
+
method: fallbackMethods[fallbackMethods.length - 1] || "page_reload",
|
|
771
|
+
reason: "refresh_failed",
|
|
772
|
+
error: "Recommend refresh did not run",
|
|
773
|
+
card_count: 0,
|
|
774
|
+
root_state: currentRootState,
|
|
775
|
+
forced_recent_not_view: Boolean(forceRecentNotView && filter.enabled !== false)
|
|
776
|
+
}),
|
|
777
|
+
attempts
|
|
778
|
+
};
|
|
779
|
+
}
|