@reconcrap/boss-recommend-mcp 1.1.9 → 1.1.11
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
|
@@ -36,6 +36,29 @@ function normalizeText(value) {
|
|
|
36
36
|
return String(value || "").replace(/\s+/g, " ").trim();
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
function sanitizeUrl(value) {
|
|
40
|
+
const raw = String(value || "").replace(/\s+/g, " ").trim();
|
|
41
|
+
const cleaned = raw
|
|
42
|
+
.replace(/^\uFEFF/, "")
|
|
43
|
+
.replace(/[\u200B-\u200F\u2028-\u202F\u2060-\u2064\uFEFF]/g, "")
|
|
44
|
+
.replace(/^["']|["']$/g, "");
|
|
45
|
+
return cleaned.replace(/\/+$/, "");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function validateUrlString(raw) {
|
|
49
|
+
const sanitized = sanitizeUrl(raw);
|
|
50
|
+
if (!sanitized) return { ok: false, error: "baseUrl 为空" };
|
|
51
|
+
try {
|
|
52
|
+
const url = new URL(sanitized);
|
|
53
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
54
|
+
return { ok: false, error: `协议无效: ${url.protocol} (期望 http 或 https)` };
|
|
55
|
+
}
|
|
56
|
+
return { ok: true, sanitized, full: sanitized };
|
|
57
|
+
} catch (e) {
|
|
58
|
+
return { ok: false, error: `URL 格式无效: ${e.message}`, raw };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
39
62
|
function parsePositiveInteger(raw) {
|
|
40
63
|
const value = Number.parseInt(String(raw || ""), 10);
|
|
41
64
|
return Number.isFinite(value) && value > 0 ? value : null;
|
|
@@ -1116,7 +1139,7 @@ const jsClickFavoriteFallback = `(() => {
|
|
|
1116
1139
|
return { ok: true };
|
|
1117
1140
|
})()`;
|
|
1118
1141
|
|
|
1119
|
-
const
|
|
1142
|
+
const jsGetGreetStateRecommend = `(() => {
|
|
1120
1143
|
const normalize = (value) => String(value || '').replace(/\s+/g, ' ').trim();
|
|
1121
1144
|
const isVisible = (doc, el) => {
|
|
1122
1145
|
if (!el) return false;
|
|
@@ -1161,7 +1184,7 @@ const jsGetGreetState = `(() => {
|
|
|
1161
1184
|
return { ok: false, error: 'GREET_BUTTON_NOT_FOUND' };
|
|
1162
1185
|
})()`;
|
|
1163
1186
|
|
|
1164
|
-
const
|
|
1187
|
+
const jsClickGreetFallbackRecommend = `(() => {
|
|
1165
1188
|
const topButton = Array.from(document.querySelectorAll('.resume-footer.item-operate button, .resume-footer-wrap button, button.btn-v2.btn-sure-v2'))
|
|
1166
1189
|
.find((item) => item && item.offsetParent !== null && /沟通|打招呼|聊一聊/.test(String(item.textContent || '').replace(/\\s+/g, ' ')));
|
|
1167
1190
|
if (topButton) {
|
|
@@ -1179,6 +1202,70 @@ const jsClickGreetFallback = `(() => {
|
|
|
1179
1202
|
return { ok: true };
|
|
1180
1203
|
})()`;
|
|
1181
1204
|
|
|
1205
|
+
const jsGetGreetStateFeatured = `(() => {
|
|
1206
|
+
const normalize = (value) => String(value || '').replace(/\s+/g, ' ').trim();
|
|
1207
|
+
const isVisible = (doc, el) => {
|
|
1208
|
+
if (!el) return false;
|
|
1209
|
+
const view = doc.defaultView || window;
|
|
1210
|
+
const style = view.getComputedStyle(el);
|
|
1211
|
+
if (style.display === 'none' || style.visibility === 'hidden' || Number(style.opacity || '1') < 0.02) {
|
|
1212
|
+
return false;
|
|
1213
|
+
}
|
|
1214
|
+
const rect = el.getBoundingClientRect();
|
|
1215
|
+
return rect.width > 2 && rect.height > 2;
|
|
1216
|
+
};
|
|
1217
|
+
const resolveGreet = (doc, offsetX, offsetY, scope) => {
|
|
1218
|
+
if (!doc) return null;
|
|
1219
|
+
const candidates = [
|
|
1220
|
+
...Array.from(doc.querySelectorAll('button.btn-v2.position-rights.btn-sure-v2')),
|
|
1221
|
+
...Array.from(doc.querySelectorAll('button.btn-v2.btn-sure-v2.position-rights')),
|
|
1222
|
+
...Array.from(doc.querySelectorAll('.resume-footer.item-operate button.btn-v2, .resume-footer-wrap button.btn-v2')),
|
|
1223
|
+
...Array.from(doc.querySelectorAll('.resume-footer.item-operate button, .resume-footer-wrap button'))
|
|
1224
|
+
];
|
|
1225
|
+
const button = candidates.find((item) => isVisible(doc, item) && /立即沟通|沟通|打招呼|聊一聊/.test(normalize(item.textContent))) || null;
|
|
1226
|
+
if (!button) return null;
|
|
1227
|
+
const rect = button.getBoundingClientRect();
|
|
1228
|
+
return {
|
|
1229
|
+
ok: true,
|
|
1230
|
+
disabled: Boolean(button.disabled),
|
|
1231
|
+
x: offsetX + rect.left + rect.width / 2,
|
|
1232
|
+
y: offsetY + rect.top + rect.height / 2,
|
|
1233
|
+
scope
|
|
1234
|
+
};
|
|
1235
|
+
};
|
|
1236
|
+
const topResult = resolveGreet(document, 0, 0, 'top');
|
|
1237
|
+
if (topResult) return topResult;
|
|
1238
|
+
|
|
1239
|
+
const frame = document.querySelector('iframe[name="recommendFrame"]')
|
|
1240
|
+
|| document.querySelector('iframe[src*="/web/frame/recommend/"]')
|
|
1241
|
+
|| document.querySelector('iframe');
|
|
1242
|
+
if (!frame || !frame.contentDocument) {
|
|
1243
|
+
return { ok: false, error: 'NO_RECOMMEND_IFRAME' };
|
|
1244
|
+
}
|
|
1245
|
+
const frameRect = frame.getBoundingClientRect();
|
|
1246
|
+
const frameResult = resolveGreet(frame.contentDocument, frameRect.left, frameRect.top, 'frame');
|
|
1247
|
+
if (frameResult) return frameResult;
|
|
1248
|
+
return { ok: false, error: 'GREET_BUTTON_NOT_FOUND' };
|
|
1249
|
+
})()`;
|
|
1250
|
+
|
|
1251
|
+
const jsClickGreetFallbackFeatured = `(() => {
|
|
1252
|
+
const topButton = Array.from(document.querySelectorAll('button.btn-v2.position-rights.btn-sure-v2, button.btn-v2.btn-sure-v2.position-rights, .resume-footer.item-operate button, .resume-footer-wrap button'))
|
|
1253
|
+
.find((item) => item && item.offsetParent !== null && /立即沟通|沟通|打招呼|聊一聊/.test(String(item.textContent || '').replace(/\\s+/g, ' ')));
|
|
1254
|
+
if (topButton) {
|
|
1255
|
+
topButton.click();
|
|
1256
|
+
return { ok: true, scope: 'top' };
|
|
1257
|
+
}
|
|
1258
|
+
const frame = document.querySelector('iframe[name="recommendFrame"]')
|
|
1259
|
+
|| document.querySelector('iframe[src*="/web/frame/recommend/"]')
|
|
1260
|
+
|| document.querySelector('iframe');
|
|
1261
|
+
if (!frame || !frame.contentDocument) return { ok: false, error: 'NO_RECOMMEND_IFRAME' };
|
|
1262
|
+
const doc = frame.contentDocument;
|
|
1263
|
+
const button = doc.querySelector('button.btn-v2.position-rights.btn-sure-v2, button.btn-v2.btn-sure-v2.position-rights');
|
|
1264
|
+
if (!button || button.offsetParent === null) return { ok: false, error: 'GREET_BUTTON_NOT_FOUND' };
|
|
1265
|
+
button.click();
|
|
1266
|
+
return { ok: true };
|
|
1267
|
+
})()`;
|
|
1268
|
+
|
|
1182
1269
|
const jsGetKnowButtonState = `(() => {
|
|
1183
1270
|
const normalize = (value) => String(value || '').replace(/\s+/g, '').trim();
|
|
1184
1271
|
const pickVisibleKnowButton = (doc) => {
|
|
@@ -1423,6 +1510,13 @@ const jsReloadRecommendFrame = `(() => {
|
|
|
1423
1510
|
class RecommendScreenCli {
|
|
1424
1511
|
constructor(args) {
|
|
1425
1512
|
this.args = args;
|
|
1513
|
+
const baseUrlCheck = validateUrlString(this.args.baseUrl);
|
|
1514
|
+
if (this.args.baseUrl && !baseUrlCheck.ok) {
|
|
1515
|
+
log(`[警告] baseUrl 校验失败: ${baseUrlCheck.error}, 原始值=${JSON.stringify(this.args.baseUrl)}`);
|
|
1516
|
+
}
|
|
1517
|
+
if (baseUrlCheck.sanitized) {
|
|
1518
|
+
this.args.baseUrl = baseUrlCheck.sanitized;
|
|
1519
|
+
}
|
|
1426
1520
|
this.client = null;
|
|
1427
1521
|
this.Runtime = null;
|
|
1428
1522
|
this.Input = null;
|
|
@@ -1924,7 +2018,7 @@ class RecommendScreenCli {
|
|
|
1924
2018
|
async pressEsc() {
|
|
1925
2019
|
await this.Input.dispatchKeyEvent({ type: "keyDown", windowsVirtualKeyCode: 27, key: "Escape", code: "Escape" });
|
|
1926
2020
|
await this.Input.dispatchKeyEvent({ type: "keyUp", windowsVirtualKeyCode: 27, key: "Escape", code: "Escape" });
|
|
1927
|
-
}
|
|
2021
|
+
}
|
|
1928
2022
|
async ensureDetailOpen() {
|
|
1929
2023
|
for (let index = 0; index < 20; index += 1) {
|
|
1930
2024
|
const state = await this.evaluate(jsWaitForDetail);
|
|
@@ -2244,7 +2338,9 @@ class RecommendScreenCli {
|
|
|
2244
2338
|
|
|
2245
2339
|
async callVisionModel(imagePath) {
|
|
2246
2340
|
const imageBase64 = fs.readFileSync(imagePath, "base64");
|
|
2247
|
-
const
|
|
2341
|
+
const rawBaseUrl = this.args.baseUrl;
|
|
2342
|
+
log(`[callVisionModel] baseUrl 原始值类型=${typeof rawBaseUrl}, 长度=${rawBaseUrl != null ? String(rawBaseUrl).length : "null/undefined"}, JSON编码=${JSON.stringify(rawBaseUrl)}`);
|
|
2343
|
+
const baseUrl = String(rawBaseUrl || "").replace(/\/$/, "");
|
|
2248
2344
|
const payload = {
|
|
2249
2345
|
model: this.args.model,
|
|
2250
2346
|
temperature: 0.1,
|
|
@@ -2300,7 +2396,9 @@ class RecommendScreenCli {
|
|
|
2300
2396
|
|
|
2301
2397
|
async callTextModel(resumeText) {
|
|
2302
2398
|
const safeResumeText = String(resumeText || "").slice(0, 28000);
|
|
2303
|
-
const
|
|
2399
|
+
const rawBaseUrl = this.args.baseUrl;
|
|
2400
|
+
log(`[callTextModel] baseUrl 原始值类型=${typeof rawBaseUrl}, 长度=${rawBaseUrl != null ? String(rawBaseUrl).length : "null/undefined"}, JSON编码=${JSON.stringify(rawBaseUrl)}`);
|
|
2401
|
+
const baseUrl = String(rawBaseUrl || "").replace(/\/$/, "");
|
|
2304
2402
|
const payload = {
|
|
2305
2403
|
model: this.args.model,
|
|
2306
2404
|
temperature: 0.1,
|
|
@@ -2433,7 +2531,11 @@ class RecommendScreenCli {
|
|
|
2433
2531
|
}
|
|
2434
2532
|
|
|
2435
2533
|
async greetCandidate() {
|
|
2436
|
-
const
|
|
2534
|
+
const greetStateScript = this.args.pageScope === "featured" ? jsGetGreetStateFeatured : jsGetGreetStateRecommend;
|
|
2535
|
+
const greetClickFallbackScript = this.args.pageScope === "featured"
|
|
2536
|
+
? jsClickGreetFallbackFeatured
|
|
2537
|
+
: jsClickGreetFallbackRecommend;
|
|
2538
|
+
const greet = await this.evaluate(greetStateScript);
|
|
2437
2539
|
if (!greet?.ok || greet.disabled) {
|
|
2438
2540
|
throw this.buildError("GREET_BUTTON_FAILED", greet?.error || "打招呼按钮不可用");
|
|
2439
2541
|
}
|
|
@@ -2441,7 +2543,7 @@ class RecommendScreenCli {
|
|
|
2441
2543
|
try {
|
|
2442
2544
|
await this.simulateHumanClick(greet.x, greet.y);
|
|
2443
2545
|
} catch {
|
|
2444
|
-
const fallback = await this.evaluate(
|
|
2546
|
+
const fallback = await this.evaluate(greetClickFallbackScript);
|
|
2445
2547
|
if (!fallback?.ok) {
|
|
2446
2548
|
throw this.buildError("GREET_BUTTON_FAILED", fallback?.error || "打招呼点击失败");
|
|
2447
2549
|
}
|
|
@@ -2962,4 +3064,4 @@ if (require.main === module) {
|
|
|
2962
3064
|
}
|
|
2963
3065
|
};
|
|
2964
3066
|
}
|
|
2965
|
-
|
|
3067
|
+
|