@reconcrap/boss-recommend-mcp 1.0.1 → 1.0.2
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
CHANGED
|
@@ -76,9 +76,15 @@ function normalizeDegree(value) {
|
|
|
76
76
|
return DEGREE_OPTIONS.includes(normalized) ? normalized : null;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
function sortDegreeSelection(values) {
|
|
80
|
-
return Array.from(new Set(values.filter(Boolean))).sort((left, right) => DEGREE_ORDER.indexOf(left) - DEGREE_ORDER.indexOf(right));
|
|
81
|
-
}
|
|
79
|
+
function sortDegreeSelection(values) {
|
|
80
|
+
return Array.from(new Set(values.filter(Boolean))).sort((left, right) => DEGREE_ORDER.indexOf(left) - DEGREE_ORDER.indexOf(right));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function selectionEquals(left, right) {
|
|
84
|
+
if (!Array.isArray(left) || !Array.isArray(right)) return false;
|
|
85
|
+
if (left.length !== right.length) return false;
|
|
86
|
+
return left.every((value, index) => value === right[index]);
|
|
87
|
+
}
|
|
82
88
|
|
|
83
89
|
function expandDegreeAtOrAbove(value) {
|
|
84
90
|
const normalized = normalizeDegree(value);
|
|
@@ -1115,35 +1121,53 @@ class RecommendSearchCli {
|
|
|
1115
1121
|
})()`);
|
|
1116
1122
|
}
|
|
1117
1123
|
|
|
1118
|
-
async selectSchoolFilter(labels) {
|
|
1119
|
-
const ensure = await this.ensureGroupReady("school");
|
|
1120
|
-
if (!ensure?.ok) {
|
|
1121
|
-
throw new Error(ensure?.error || "GROUP_NOT_FOUND");
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
const targetLabels = Array.isArray(labels) && labels.length > 0 ? labels : ["不限"];
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1124
|
+
async selectSchoolFilter(labels) {
|
|
1125
|
+
const ensure = await this.ensureGroupReady("school");
|
|
1126
|
+
if (!ensure?.ok) {
|
|
1127
|
+
throw new Error(ensure?.error || "GROUP_NOT_FOUND");
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
const targetLabels = Array.isArray(labels) && labels.length > 0 ? labels : ["不限"];
|
|
1131
|
+
const desired = sortSchoolSelection(targetLabels);
|
|
1132
|
+
const expectDefaultOnly = desired.includes("不限");
|
|
1133
|
+
let lastState = null;
|
|
1134
|
+
|
|
1135
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
1136
|
+
const state = await this.getSchoolFilterState();
|
|
1137
|
+
if (!state?.ok) {
|
|
1138
|
+
throw new Error(state?.error || "SCHOOL_FILTER_STATE_FAILED");
|
|
1139
|
+
}
|
|
1140
|
+
lastState = state;
|
|
1141
|
+
const current = sortSchoolSelection(state.activeLabels || []);
|
|
1142
|
+
const matched = expectDefaultOnly
|
|
1143
|
+
? Boolean(state.defaultActive)
|
|
1144
|
+
: (!state.defaultActive && selectionEquals(current, desired));
|
|
1145
|
+
if (matched) {
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
if (expectDefaultOnly) {
|
|
1150
|
+
await this.selectOption("school", "不限");
|
|
1151
|
+
await sleep(humanDelay(180, 50));
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
if (state.defaultActive) {
|
|
1156
|
+
const clearDefault = await this.clickOptionBySelector("school", "不限");
|
|
1157
|
+
if (!clearDefault?.ok) {
|
|
1158
|
+
throw new Error(clearDefault?.error || "SCHOOL_DEFAULT_CLEAR_FAILED");
|
|
1159
|
+
}
|
|
1160
|
+
await sleep(humanDelay(180, 50));
|
|
1161
|
+
}
|
|
1162
|
+
for (const label of desired) {
|
|
1163
|
+
await this.selectOption("school", label);
|
|
1164
|
+
await sleep(humanDelay(120, 40));
|
|
1165
|
+
}
|
|
1166
|
+
await sleep(humanDelay(180, 50));
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
throw new Error(`SCHOOL_FILTER_VERIFY_FAILED:${JSON.stringify(lastState || {})}`);
|
|
1170
|
+
}
|
|
1147
1171
|
|
|
1148
1172
|
async getDegreeFilterState() {
|
|
1149
1173
|
return this.evaluate(`(() => {
|
|
@@ -1183,35 +1207,53 @@ class RecommendSearchCli {
|
|
|
1183
1207
|
})()`);
|
|
1184
1208
|
}
|
|
1185
1209
|
|
|
1186
|
-
async selectDegreeFilter(labels) {
|
|
1187
|
-
const ensure = await this.ensureGroupReady("degree");
|
|
1188
|
-
if (!ensure?.ok) {
|
|
1189
|
-
throw new Error(ensure?.error || "GROUP_NOT_FOUND");
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
const targetLabels = Array.isArray(labels) && labels.length > 0 ? labels : ["不限"];
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1210
|
+
async selectDegreeFilter(labels) {
|
|
1211
|
+
const ensure = await this.ensureGroupReady("degree");
|
|
1212
|
+
if (!ensure?.ok) {
|
|
1213
|
+
throw new Error(ensure?.error || "GROUP_NOT_FOUND");
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
const targetLabels = Array.isArray(labels) && labels.length > 0 ? labels : ["不限"];
|
|
1217
|
+
const desired = sortDegreeSelection(targetLabels);
|
|
1218
|
+
const expectDefaultOnly = desired.includes("不限");
|
|
1219
|
+
let lastState = null;
|
|
1220
|
+
|
|
1221
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
1222
|
+
const state = await this.getDegreeFilterState();
|
|
1223
|
+
if (!state?.ok) {
|
|
1224
|
+
throw new Error(state?.error || "DEGREE_FILTER_STATE_FAILED");
|
|
1225
|
+
}
|
|
1226
|
+
lastState = state;
|
|
1227
|
+
const current = sortDegreeSelection(state.activeLabels || []);
|
|
1228
|
+
const matched = expectDefaultOnly
|
|
1229
|
+
? Boolean(state.defaultActive)
|
|
1230
|
+
: (!state.defaultActive && selectionEquals(current, desired));
|
|
1231
|
+
if (matched) {
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
if (expectDefaultOnly) {
|
|
1236
|
+
await this.selectOption("degree", "不限");
|
|
1237
|
+
await sleep(humanDelay(180, 50));
|
|
1238
|
+
continue;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
if (state.defaultActive) {
|
|
1242
|
+
const clearDefault = await this.clickOptionBySelector("degree", "不限");
|
|
1243
|
+
if (!clearDefault?.ok) {
|
|
1244
|
+
throw new Error(clearDefault?.error || "DEGREE_DEFAULT_CLEAR_FAILED");
|
|
1245
|
+
}
|
|
1246
|
+
await sleep(humanDelay(180, 50));
|
|
1247
|
+
}
|
|
1248
|
+
for (const label of desired) {
|
|
1249
|
+
await this.selectOption("degree", label);
|
|
1250
|
+
await sleep(humanDelay(120, 40));
|
|
1251
|
+
}
|
|
1252
|
+
await sleep(humanDelay(180, 50));
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
throw new Error(`DEGREE_FILTER_VERIFY_FAILED:${JSON.stringify(lastState || {})}`);
|
|
1256
|
+
}
|
|
1215
1257
|
|
|
1216
1258
|
async countCandidates() {
|
|
1217
1259
|
return this.evaluate(`(() => {
|
|
@@ -1306,20 +1348,26 @@ class RecommendSearchCli {
|
|
|
1306
1348
|
await this.openFilterPanel();
|
|
1307
1349
|
await this.selectSchoolFilter(this.args.schoolTag);
|
|
1308
1350
|
await this.selectOption("gender", this.args.gender);
|
|
1309
|
-
await this.selectOption("recentNotView", this.args.recentNotView);
|
|
1310
|
-
await this.selectDegreeFilter(this.args.degree);
|
|
1311
|
-
await this.
|
|
1312
|
-
const
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1351
|
+
await this.selectOption("recentNotView", this.args.recentNotView);
|
|
1352
|
+
await this.selectDegreeFilter(this.args.degree);
|
|
1353
|
+
const verifiedSchoolState = await this.getSchoolFilterState();
|
|
1354
|
+
const verifiedDegreeState = await this.getDegreeFilterState();
|
|
1355
|
+
await this.closeFilterPanel();
|
|
1356
|
+
const candidateInfo = await this.waitForCandidateCountStable();
|
|
1357
|
+
|
|
1358
|
+
console.log(JSON.stringify({
|
|
1359
|
+
status: "COMPLETED",
|
|
1360
|
+
result: {
|
|
1317
1361
|
applied_filters: {
|
|
1318
1362
|
school_tag: this.args.schoolTag,
|
|
1319
1363
|
degree: this.args.degree,
|
|
1320
1364
|
gender: this.args.gender,
|
|
1321
1365
|
recent_not_view: this.args.recentNotView
|
|
1322
1366
|
},
|
|
1367
|
+
verified_filters: {
|
|
1368
|
+
school: verifiedSchoolState,
|
|
1369
|
+
degree: verifiedDegreeState
|
|
1370
|
+
},
|
|
1323
1371
|
selected_job: selectedJob,
|
|
1324
1372
|
candidate_count: candidateInfo?.candidateCount ?? null,
|
|
1325
1373
|
page_state: {
|