@glittering0717/ai-browser 2.1.11 → 2.1.12

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": "@glittering0717/ai-browser",
3
- "version": "2.1.11",
3
+ "version": "2.1.12",
4
4
  "description": "AI-native browser — renders pixels for humans, structured semantic-tree API for agents. No screenshots, no OCR, no coordinate guessing.",
5
5
  "main": "src/main/index.js",
6
6
  "bin": {
@@ -2,4 +2,4 @@
2
2
  // Kept in JS (not imported from package.json) to avoid Node import-attribute
3
3
  // (JSON module) compatibility issues inside Electron. package.json "version"
4
4
  // is manually synced to this value; tests assert they match.
5
- export const VERSION = '2.1.11';
5
+ export const VERSION = '2.1.12';
@@ -54,20 +54,22 @@ export function wrapperHintExpr(aiId) {
54
54
  // 而这恰恰就是要找的那个链接。退一步用"8 字窗口命中":只要候选文字里有连续
55
55
  // 8 个字出现在容器文字里,就算相关 —— 中文 8 个字已经足够特异。
56
56
  function related(aggText, t) {
57
- if (aggText.indexOf(t) >= 0) return true;
58
- if (t.length < 8) return false;
57
+ if (aggText.indexOf(t) >= 0) return 2; // 整串命中:最可信
58
+ if (t.length < 8) return 0;
59
59
  for (var k = 0; k + 8 <= t.length; k++) {
60
- if (aggText.indexOf(t.slice(k, k + 8)) >= 0) return true;
60
+ if (aggText.indexOf(t.slice(k, k + 8)) >= 0) return 1;
61
61
  }
62
- return false;
62
+ return 0;
63
63
  }
64
+ var viewH = window.innerHeight || 800;
64
65
  for (var i = 0; i < limit; i++) {
65
66
  var c = cands[i];
66
67
  if (c === el) continue;
67
68
  if (c.contains(el)) continue; // 目标的祖先:点它等于又点一次外层
68
69
  var t = ownText(c);
69
70
  if (t.length < 6) continue;
70
- if (!related(agg, t)) continue;
71
+ var match = related(agg, t);
72
+ if (!match) continue;
71
73
  var r = c.getBoundingClientRect();
72
74
  if (r.width < 4 || r.height < 4) continue;
73
75
  var cs = getComputedStyle(c);
@@ -76,8 +78,23 @@ export function wrapperHintExpr(aiId) {
76
78
  var role = String((c.getAttribute && c.getAttribute('role')) || '');
77
79
  var clickable = (tag === 'A' || tag === 'BUTTON' || role === 'link' || role === 'button' || cs.cursor === 'pointer');
78
80
  var area = Math.max(1, Math.round(r.width) * Math.round(r.height));
79
- // 先看能不能点(拦不住点击的节点没有价值),再比谁更精确(面积小的更贴近那段文字)
80
- var score = (clickable ? 0 : 1e9) + area;
81
+ // 排序必须按"相关性"而不是"谁小":
82
+ // ① 整串命中优先于 8 字窗口命中 —— 知乎那边同一条私信里躺着第一期到第五十四期
83
+ // 五个链接,它们的 8 字窗口全都命中"创作打卡挑战赛",只按面积排会挑中
84
+ // 面积最小的那一期(实测挑成了第五十期,还滚在视口外 4500px);
85
+ // ② 视口内优先 —— 用户看到并想点的是屏幕上那个;
86
+ // ③ 能点的优先;
87
+ // ④ 最后才用面积(越贴近那段文字越精确)。
88
+ var inView = (r.y + r.height > 0 && r.y < viewH) ? 0 : 1;
89
+ // 更长的那段文字更具体:同一段预览里"创作打卡挑战赛"和"创作打卡挑战赛第五十四期"
90
+ // 都是整串命中,但后者才是用户想点的那一期。
91
+ var specificity = 200 - Math.min(199, t.length);
92
+ // 排序:整串命中 > 能点 > 更具体(文字更长)> 视口内 > 面积小。
93
+ // 为什么"更具体"排在"视口内"前面:同一段预览里的第一期…第五十四期五个链接,
94
+ // 整串命中的只有对的那一期,即使它在视口外也值得点(点击前会 scrollIntoView);
95
+ // 反过来点一个"看得见但期数错了"的链接,是把人带到错误页面。
96
+ var score = (2 - match) * 1e15 + (clickable ? 0 : 1e13)
97
+ + specificity * 1e9 + inView * 1e8 + Math.min(area, 99999);
81
98
  if (!best || score < best.score) {
82
99
  best = {
83
100
  score: score,
@@ -87,6 +104,7 @@ export function wrapperHintExpr(aiId) {
87
104
  text: t.slice(0, 60),
88
105
  box: { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) },
89
106
  clickable: clickable,
107
+ exact: match === 2,
90
108
  };
91
109
  }
92
110
  }