@glittering0717/ai-browser 2.1.10 → 2.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glittering0717/ai-browser",
3
- "version": "2.1.10",
3
+ "version": "2.1.11",
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": {
@@ -309,6 +309,40 @@ function extractTree() {
309
309
  function hasIconInside(el) {
310
310
  try { return !!(el.querySelector && el.querySelector("svg,img,i[class],[class*=icon]")); } catch (e) { return false; }
311
311
  }
312
+
313
+ // ---- label 是否"由子树文字拼出来"(agg 标记的判据)-------------------------
314
+ //
315
+ // 为什么需要(2026-10-25 知乎私信活动链接):列表行 `<div class="ChatUserListItem" onclick>`
316
+ // 在树里是 `generic`,label 却是整段预览文字的拼接:
317
+ // "创作者小助手 10-21 ☄️最新一期「创作打卡挑战赛」活动来喽!「创作打卡挑战赛第五十四期 」将于…"
318
+ // 于是"按文字找链接"必定先命中这个容器(点它只选中会话),而真链接的 label 只有
319
+ // 那 11 个字。用户看到的现象是"树里有、点不动",且完全无从判断为什么。
320
+ //
321
+ // 判据是 DOM 事实,不猜:**自身没有直接文字**(own text 为空)却有子元素、
322
+ // 而 label 又够长 —— 这段 label 只可能是从下面拼上来的,打 agg:1 让读树的人
323
+ // 一眼看出"文字不归它"。可交互角色(a/button/input…)即使包着 span,文字语义
324
+ // 也归它自己,不标;aria-label/title 是作者写的名字,也不是拼接,同样不标。
325
+ var CONTAINER_ROLES = {
326
+ generic: 1, group: 1, list: 1, listitem: 1, table: 1, row: 1, cell: 1, gridcell: 1,
327
+ article: 1, region: 1, main: 1, navigation: 1, section: 1, paragraph: 1, none: 1
328
+ };
329
+ function ownTextOf(el) {
330
+ var s = "";
331
+ try {
332
+ for (var i = 0; i < el.childNodes.length; i++) {
333
+ var c = el.childNodes[i];
334
+ if (c.nodeType === 3) s += c.textContent;
335
+ }
336
+ } catch (e) {}
337
+ return String(s).replace(/\s+/g, " ").trim();
338
+ }
339
+ function isAggregatedLabel(el, role, label, labelMeta) {
340
+ if (!label || label.length < 8) return false;
341
+ if (!CONTAINER_ROLES[role]) return false;
342
+ if (labelMeta && labelMeta.kind && labelMeta.kind !== "text") return false;
343
+ if (!el.children || !el.children.length) return false;
344
+ return ownTextOf(el).length < 3;
345
+ }
312
346
  function isNamed(el) {
313
347
  return !!elementName(el).trim() || hasIconInside(el);
314
348
  }
@@ -821,6 +855,14 @@ function extractTree() {
821
855
  // 把 aria-label / alt / title / placeholder 排除掉(它们不在 innerText 里)。
822
856
  // 正常节点不写,省 token。
823
857
  if (labelMeta.kind && labelMeta.kind !== "text") node.label_kind = labelMeta.kind;
858
+ // label 是**子树文字的拼接**时打 agg:1 —— 读树的人必须能分辨"这段文字是我的"
859
+ // 和"这段文字在我下面",否则按文字找链接会命中列表行容器,点了什么都不会发生。
860
+ // 2026-10-25 知乎私信:`<div class="ChatUserListItem" onclick>` 的 label 成了
861
+ // "创作者小助手 10-21 ☄️最新一期「创作打卡挑战赛」活动来喽!…",agent 点它
862
+ // 只选中会话,真链接(<a>创作打卡挑战赛第五十四期</a>)在会话面板里。
863
+ // 判据用 DOM 事实而不是猜:自身没有直接文字(own text 为空)却有子元素、
864
+ // label 还够长 —— 那这段 label 只可能是从下面拼上来的。
865
+ if (isAggregatedLabel(el, role, label, labelMeta)) node.agg = 1;
824
866
  // Attach current value for input/textarea/contenteditable.
825
867
  // 截断走共享契约(src/shared/value_contract.cjs):按 Unicode code point
826
868
  // 计数,截断时带 value_truncated / value_full_length / value_fetch_ref,
@@ -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.10';
5
+ export const VERSION = '2.1.11';