@reconcrap/boss-recommend-mcp 1.0.13 → 1.0.14

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reconcrap/boss-recommend-mcp",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "Unified MCP pipeline for recommend-page filtering and screening on Boss Zhipin",
5
5
  "keywords": [
6
6
  "boss",
@@ -1008,23 +1008,7 @@ const jsClickCloseFallback = `(() => {
1008
1008
  })()`;
1009
1009
 
1010
1010
  const jsReloadRecommendFrame = `(() => {
1011
- const frame = document.querySelector('iframe[name="recommendFrame"]')
1012
- || document.querySelector('iframe[src*="/web/frame/recommend/"]')
1013
- || document.querySelector('iframe');
1014
- if (!frame || !frame.contentWindow) {
1015
- return { ok: false, error: 'NO_RECOMMEND_IFRAME' };
1016
- }
1017
- try {
1018
- const current = String(frame.contentWindow.location.href || '');
1019
- if (current.includes('/web/frame/recommend/')) {
1020
- frame.contentWindow.location.reload();
1021
- } else {
1022
- frame.contentWindow.location.href = 'https://www.zhipin.com/web/frame/recommend/';
1023
- }
1024
- return { ok: true };
1025
- } catch (error) {
1026
- return { ok: false, error: String(error && error.message ? error.message : error) };
1027
- }
1011
+ return { ok: false, error: 'RELOAD_DISABLED_BY_POLICY' };
1028
1012
  })()`;
1029
1013
 
1030
1014
  class RecommendScreenCli {
@@ -1201,7 +1185,20 @@ class RecommendScreenCli {
1201
1185
  );
1202
1186
  }
1203
1187
 
1204
- async maximizeWindowIfPossible(reason = "unknown") {
1188
+ async getCurrentWindowState() {
1189
+ if (!this.Browser || !this.windowId || typeof this.Browser.getWindowBounds !== "function") {
1190
+ return null;
1191
+ }
1192
+ try {
1193
+ const info = await this.Browser.getWindowBounds({ windowId: this.windowId });
1194
+ const state = String(info?.bounds?.windowState || "").toLowerCase();
1195
+ return state || null;
1196
+ } catch {
1197
+ return null;
1198
+ }
1199
+ }
1200
+
1201
+ async setWindowStateIfPossible(windowState, reason = "unknown") {
1205
1202
  if (!this.Browser || !this.windowId || typeof this.Browser.setWindowBounds !== "function") {
1206
1203
  return false;
1207
1204
  }
@@ -1209,17 +1206,38 @@ class RecommendScreenCli {
1209
1206
  await this.Browser.setWindowBounds({
1210
1207
  windowId: this.windowId,
1211
1208
  bounds: {
1212
- windowState: "maximized"
1209
+ windowState
1213
1210
  }
1214
1211
  });
1215
- log(`[视口恢复] 已尝试最大化 Chrome 窗口,原因: ${reason}`);
1212
+ log(`[视口恢复] 已设置窗口状态为 ${windowState},原因: ${reason}`);
1216
1213
  return true;
1217
1214
  } catch (error) {
1218
- log(`[视口恢复] 最大化窗口失败: ${error.message || error}`);
1215
+ log(`[视口恢复] 设置窗口状态 ${windowState} 失败: ${error.message || error}`);
1219
1216
  return false;
1220
1217
  }
1221
1218
  }
1222
1219
 
1220
+ async toggleWindowStateForViewportRecovery(reason = "unknown") {
1221
+ const currentState = await this.getCurrentWindowState();
1222
+ const sequence = currentState === "normal"
1223
+ ? ["maximized", "normal"]
1224
+ : ["normal", "maximized"];
1225
+ let applied = false;
1226
+ for (const state of sequence) {
1227
+ const ok = await this.setWindowStateIfPossible(state, reason);
1228
+ if (ok) {
1229
+ applied = true;
1230
+ await sleep(humanDelay(520, 80));
1231
+ }
1232
+ }
1233
+ if (applied && this.Page && typeof this.Page.bringToFront === "function") {
1234
+ try {
1235
+ await this.Page.bringToFront();
1236
+ } catch {}
1237
+ }
1238
+ return applied;
1239
+ }
1240
+
1223
1241
  async ensureHealthyListViewport(reason = "unknown") {
1224
1242
  let state = await this.getListState();
1225
1243
  if (!this.isListViewportCollapsed(state)) {
@@ -1227,24 +1245,13 @@ class RecommendScreenCli {
1227
1245
  }
1228
1246
 
1229
1247
  log(`[视口恢复] 检测到推荐列表视口异常缩小,尝试自动恢复。原因: ${reason}`);
1230
- await this.maximizeWindowIfPossible(reason);
1231
- await sleep(humanDelay(800, 120));
1248
+ await this.toggleWindowStateForViewportRecovery(reason);
1249
+ await sleep(humanDelay(900, 130));
1232
1250
  state = await this.getListState();
1233
1251
  if (!this.isListViewportCollapsed(state)) {
1234
1252
  return { ok: true, recovered: true, state };
1235
1253
  }
1236
1254
 
1237
- const reloaded = await this.evaluate(jsReloadRecommendFrame);
1238
- if (reloaded?.ok) {
1239
- log("[视口恢复] 已触发 recommendFrame reload。");
1240
- await this.waitForListReady(45);
1241
- await sleep(humanDelay(900, 150));
1242
- state = await this.getListState();
1243
- if (!this.isListViewportCollapsed(state)) {
1244
- return { ok: true, recovered: true, state };
1245
- }
1246
- }
1247
-
1248
1255
  return {
1249
1256
  ok: false,
1250
1257
  recovered: false,
@@ -1597,35 +1604,21 @@ class RecommendScreenCli {
1597
1604
  }
1598
1605
  }
1599
1606
 
1600
- log(`[关闭详情] 常规关闭失败,进入强制恢复。最后状态: ${state?.reason || "unknown"}`);
1607
+ log(`[关闭详情] 常规关闭失败,进入额外 ESC 重试(禁用刷新/跳转)。最后状态: ${state?.reason || "unknown"}`);
1601
1608
  for (let retry = 0; retry < 2; retry += 1) {
1609
+ await sleep(2000);
1602
1610
  await this.pressEsc();
1603
- await sleep(900 + retry * 250);
1611
+ await sleep(humanDelay(260, 60));
1604
1612
  state = await this.getDetailClosedState();
1605
1613
  if (state?.closed) {
1606
- log(`[关闭详情] 强制ESC成功: ${state.reason || "closed"}`);
1614
+ log(`[关闭详情] 额外ESC成功: ${state.reason || "closed"}`);
1607
1615
  return true;
1608
1616
  }
1609
1617
  }
1610
1618
 
1611
- const reloaded = await this.evaluate(jsReloadRecommendFrame);
1612
- if (reloaded?.ok) {
1613
- log("[关闭详情] 已触发 recommendFrame reload,等待列表恢复。");
1614
- const listReady = await this.waitForListReady(45);
1615
- if (listReady) {
1616
- state = await this.getDetailClosedState();
1617
- if (state?.closed) {
1618
- log(`[关闭详情] reload 后恢复成功: ${state.reason || "closed"}`);
1619
- return true;
1620
- }
1621
- }
1622
- } else {
1623
- log(`[关闭详情] recommendFrame reload 失败: ${reloaded?.error || "unknown"}`);
1624
- }
1625
-
1626
1619
  state = await this.getDetailClosedState();
1627
- log(`[关闭详情] 失败,当前状态: ${state?.reason || "unknown"}`);
1628
- return false;
1620
+ log(`[关闭详情] 连续 ESC 后仍未确认关闭(${state?.reason || "unknown"}),按策略视为检测误差并继续下一位。`);
1621
+ return true;
1629
1622
  }
1630
1623
 
1631
1624
  async waitForListReady(maxRounds = 30) {