hunter-mate 0.1.25 → 0.1.27

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.
Files changed (90) hide show
  1. package/dist/assets/extension/background/{service-worker.20261017183328.js → service-worker.20261020181646.js} +60 -4
  2. package/dist/assets/extension/background/service-worker.js +60 -4
  3. package/dist/assets/extension/build-info.json +1 -1
  4. package/dist/assets/extension/content/index.js +284 -64
  5. package/dist/assets/extension/manifest.json +3 -3
  6. package/dist/assets/extension/sidepanel/index.html +1 -1
  7. package/dist/assets/extension/sidepanel/index.js +14 -14
  8. package/dist/assets/server/main.mjs +2318 -1987
  9. package/dist/index.js +52 -68
  10. package/dist/watchdog.js +62 -6
  11. package/dist/web/dist/404.html +1 -1
  12. package/dist/web/dist/_next/static/chunks/187-f067914dcd1330c2.js +32 -0
  13. package/dist/web/dist/_next/static/chunks/253-f4ac7af6647e4dba.js +1 -0
  14. package/dist/web/dist/_next/static/chunks/{589-f984bff035a1cb85.js → 589-5bb84ab8060e960b.js} +1 -1
  15. package/dist/web/dist/_next/static/chunks/659-b23050764c004f5f.js +1 -0
  16. package/dist/web/dist/_next/static/chunks/{686-9f419b70feea9470.js → 686-5f4ee3649cce07f1.js} +1 -1
  17. package/dist/web/dist/_next/static/chunks/728-cffab7e836020551.js +12 -0
  18. package/dist/web/dist/_next/static/chunks/{865-0ed23dd43c0832a2.js → 865-8e1d8c34192526ed.js} +1 -1
  19. package/dist/web/dist/_next/static/chunks/896-9dce6a3bc525edba.js +1 -0
  20. package/dist/web/dist/_next/static/chunks/{935-7be3e60dd8bc29d2.js → 935-12f1084f0e18c962.js} +1 -1
  21. package/dist/web/dist/_next/static/chunks/{a7067448-e416655baf443992.js → a7067448-3f2b194cfadb91fb.js} +1 -1
  22. package/dist/web/dist/_next/static/chunks/app/_not-found/{page-5b7249eb3c9a6cb9.js → page-46929212b0496a89.js} +1 -1
  23. package/dist/web/dist/_next/static/chunks/app/admin/data/{page-14698e9c4ddaa6d9.js → page-666f99fbfee46cc9.js} +1 -1
  24. package/dist/web/dist/_next/static/chunks/app/auth/verify/{page-05304d5803008d61.js → page-2da5807d6cdfdb4e.js} +1 -1
  25. package/dist/web/dist/_next/static/chunks/app/companies/{page-e8d02fe997579315.js → page-390d5e3073ec151d.js} +1 -1
  26. package/dist/web/dist/_next/static/chunks/app/company/admin/{page-c2584183bc4b34d1.js → page-02244f3f1a212c76.js} +1 -1
  27. package/dist/web/dist/_next/static/chunks/app/entity/{page-08755f96102f0565.js → page-d59a8103f8107d3b.js} +1 -1
  28. package/dist/web/dist/_next/static/chunks/app/jobs/page-fa83ce1b6c3b345d.js +1 -0
  29. package/dist/web/dist/_next/static/chunks/app/layout-15c4c2ba595b2a92.js +1 -0
  30. package/dist/web/dist/_next/static/chunks/app/logs/{page-be50a4e10b1a0024.js → page-badf48f4e7e32e17.js} +1 -1
  31. package/dist/web/dist/_next/static/chunks/app/matching/jobs/[id]/talents/{page-cf445b0cb8c2cb0a.js → page-73bca3864b8b9e44.js} +1 -1
  32. package/dist/web/dist/_next/static/chunks/app/matching/portraits/[id]/jobs/{page-c7ff0d79b6a75915.js → page-477c66bee61225fa.js} +1 -1
  33. package/dist/web/dist/_next/static/chunks/app/{page-bd282e1e5f0965f1.js → page-8ea324b366e3d374.js} +1 -1
  34. package/dist/web/dist/_next/static/chunks/app/parselog/{page-9814e75d6900a743.js → page-4f5c186442feb386.js} +1 -1
  35. package/dist/web/dist/_next/static/chunks/app/recordings/page-0fb8cafdd2f6762c.js +1 -0
  36. package/dist/web/dist/_next/static/chunks/app/resource-usage/{page-f6fa06bfe21bcd32.js → page-76be36ca978391a3.js} +1 -1
  37. package/dist/web/dist/_next/static/chunks/app/shared/[token]/{page-c9c5042a2d07c0bc.js → page-fe2b986867d317c0.js} +1 -1
  38. package/dist/web/dist/_next/static/chunks/app/snapshots/[id]/agent-prompt/{page-f54cf2f0058035ca.js → page-60ea46364a74b294.js} +1 -1
  39. package/dist/web/dist/_next/static/chunks/app/talents/{page-0edef6d07b3cf69d.js → page-5a2caa7a503ee041.js} +1 -1
  40. package/dist/web/dist/_next/static/chunks/app/team/insights/{page-8b3934df3e292368.js → page-5385dcd363f6e0cd.js} +1 -1
  41. package/dist/web/dist/_next/static/chunks/webpack-9cebd25e322e2cd7.js +1 -0
  42. package/dist/web/dist/_next/static/css/8f3c454cab3414d0.css +3 -0
  43. package/dist/web/dist/admin/data.html +1 -1
  44. package/dist/web/dist/admin/data.txt +5 -5
  45. package/dist/web/dist/auth/verify.html +1 -1
  46. package/dist/web/dist/auth/verify.txt +5 -5
  47. package/dist/web/dist/companies.html +1 -1
  48. package/dist/web/dist/companies.txt +5 -5
  49. package/dist/web/dist/company/admin.html +1 -1
  50. package/dist/web/dist/company/admin.txt +5 -5
  51. package/dist/web/dist/entity.html +1 -1
  52. package/dist/web/dist/entity.txt +5 -5
  53. package/dist/web/dist/index.html +1 -1
  54. package/dist/web/dist/index.txt +5 -5
  55. package/dist/web/dist/jobs.html +1 -1
  56. package/dist/web/dist/jobs.txt +5 -5
  57. package/dist/web/dist/logs.html +1 -1
  58. package/dist/web/dist/logs.txt +5 -5
  59. package/dist/web/dist/matching/jobs/placeholder/talents.html +1 -1
  60. package/dist/web/dist/matching/jobs/placeholder/talents.txt +5 -5
  61. package/dist/web/dist/matching/portraits/placeholder/jobs.html +1 -1
  62. package/dist/web/dist/matching/portraits/placeholder/jobs.txt +5 -5
  63. package/dist/web/dist/parselog.html +1 -1
  64. package/dist/web/dist/parselog.txt +5 -5
  65. package/dist/web/dist/recordings.html +1 -1
  66. package/dist/web/dist/recordings.txt +5 -5
  67. package/dist/web/dist/resource-usage.html +1 -1
  68. package/dist/web/dist/resource-usage.txt +5 -5
  69. package/dist/web/dist/shared/placeholder.html +1 -1
  70. package/dist/web/dist/shared/placeholder.txt +5 -5
  71. package/dist/web/dist/snapshots/placeholder/agent-prompt.html +1 -1
  72. package/dist/web/dist/snapshots/placeholder/agent-prompt.txt +5 -5
  73. package/dist/web/dist/talents.html +1 -1
  74. package/dist/web/dist/talents.txt +5 -5
  75. package/dist/web/dist/team/insights.html +1 -1
  76. package/dist/web/dist/team/insights.txt +5 -5
  77. package/package.json +3 -6
  78. package/dist/web/dist/_next/static/chunks/105-dcd8f6d5867c8995.js +0 -32
  79. package/dist/web/dist/_next/static/chunks/166.b263e636ff66212f.js +0 -1
  80. package/dist/web/dist/_next/static/chunks/253-a05d05b94bfbd7a4.js +0 -1
  81. package/dist/web/dist/_next/static/chunks/555-e2a871b9d2eccb03.js +0 -12
  82. package/dist/web/dist/_next/static/chunks/852-ad19b97821a4cf9e.js +0 -1
  83. package/dist/web/dist/_next/static/chunks/app/jobs/page-4827a9ef286b6483.js +0 -1
  84. package/dist/web/dist/_next/static/chunks/app/layout-af39afc7866e74db.js +0 -1
  85. package/dist/web/dist/_next/static/chunks/app/recordings/page-441016638b43c4f8.js +0 -1
  86. package/dist/web/dist/_next/static/chunks/webpack-54e74ccc9e9451ee.js +0 -1
  87. package/dist/web/dist/_next/static/css/10ba1fa1d6ce23a7.css +0 -3
  88. package/dist/web/dist/_next/static/css/f60d210841fab76b.css +0 -1
  89. /package/dist/web/dist/_next/static/{5MA8faUttk6FzlxGWnOlM → tYFZz41gyWi4-BhxuxlGU}/_buildManifest.js +0 -0
  90. /package/dist/web/dist/_next/static/{5MA8faUttk6FzlxGWnOlM → tYFZz41gyWi4-BhxuxlGU}/_ssgManifest.js +0 -0
@@ -228,6 +228,7 @@ var require_hbr = __commonJS({
228
228
  exports.createHbrEvent = createHbrEvent;
229
229
  exports.createNetworkEvent = createNetworkEvent;
230
230
  exports.createConsoleEvent = createConsoleEvent;
231
+ exports.createExceptionEvent = createExceptionEvent;
231
232
  exports.createResumeEvent = createResumeEvent;
232
233
  exports.createActionEvent = createActionEvent;
233
234
  function createHbrEvent(type, sessionId, payload, options) {
@@ -247,6 +248,9 @@ var require_hbr = __commonJS({
247
248
  function createConsoleEvent(sessionId, data, privacy = "private") {
248
249
  return createHbrEvent("console", sessionId, data, { privacy });
249
250
  }
251
+ function createExceptionEvent(sessionId, data, privacy = "private") {
252
+ return createHbrEvent("exception", sessionId, data, { privacy });
253
+ }
250
254
  function createResumeEvent(sessionId, data, privacy = "private") {
251
255
  return createHbrEvent("resume", sessionId, data, { privacy });
252
256
  }
@@ -2339,6 +2343,31 @@ async function findDetailTabToReuse(url) {
2339
2343
  return idle?.id;
2340
2344
  }
2341
2345
 
2346
+ // src/background/linkedin-search-filter.ts
2347
+ var LINKEDIN_DEFAULT_LOAD_TIMEOUT_MS = 9e4;
2348
+ var MIN_TIMEOUT_MS = 5e3;
2349
+ var MAX_TIMEOUT_MS = 3e5;
2350
+ function clampLoadTimeoutMs(raw) {
2351
+ const n = Number(raw);
2352
+ if (!Number.isFinite(n) || n <= 0) return LINKEDIN_DEFAULT_LOAD_TIMEOUT_MS;
2353
+ return Math.min(Math.max(n, MIN_TIMEOUT_MS), MAX_TIMEOUT_MS);
2354
+ }
2355
+ function buildCardMatcher(filters) {
2356
+ const needle = (v) => typeof v === "string" && v.trim() ? v.trim().toLowerCase() : null;
2357
+ const locNeedle = filters.geoUrn ? null : needle(filters.location);
2358
+ const coNeedle = needle(filters.company);
2359
+ return {
2360
+ locNeedle,
2361
+ coNeedle,
2362
+ match(ctx) {
2363
+ const h = (ctx || "").toLowerCase();
2364
+ if (locNeedle && !h.includes(locNeedle)) return false;
2365
+ if (coNeedle && !h.includes(coNeedle)) return false;
2366
+ return true;
2367
+ }
2368
+ };
2369
+ }
2370
+
2342
2371
  // src/background/control.ts
2343
2372
  var RUNTIME_BRIDGE_FILE = "content/control-runtime.js";
2344
2373
  async function invokeRuntimeBridge(command, args) {
@@ -2940,12 +2969,25 @@ var LINKEDIN_EXTRACT_SOURCE = String.raw`(async () => {
2940
2969
  });
2941
2970
  } else if (pageClass === 'list') {
2942
2971
  const seen = new Set();
2972
+ // 卡片上下文:LinkedIn list 页 a[href*=/in/] 埋在结果卡内,向上找最小"像卡片"的祖先
2973
+ // (innerText 40-500 字符),抓 headline/地区/公司行——location/company 过滤的判定依据
2974
+ // (2026-10-18 寻访实测:LinkedIn 对自由文本 location/company 查询参数基本不生效,
2975
+ // 必须在 client 端按卡片文本过滤,否则过滤器名存实亡)。
2976
+ const cardCtx = (a) => {
2977
+ let el = a;
2978
+ for (let up = 0; up < 5 && el.parentElement; up++) {
2979
+ el = el.parentElement;
2980
+ const t = (el.innerText || '').replace(/\s+/g, ' ').trim();
2981
+ if (t.length >= 40) return t.slice(0, 400);
2982
+ }
2983
+ return null;
2984
+ };
2943
2985
  for (const a of Array.from(document.querySelectorAll('a[href]'))) {
2944
2986
  const href = a.href || '';
2945
2987
  let m = href.match(/linkedin\.com\/in\/([^/?#]+)/);
2946
2988
  if (m && !seen.has('t:' + m[1])) {
2947
2989
  seen.add('t:' + m[1]);
2948
- links.talent.push({ url: 'https://www.linkedin.com/in/' + m[1] + '/', name: (a.textContent || '').trim().split('\n')[0] || m[1] });
2990
+ links.talent.push({ url: 'https://www.linkedin.com/in/' + m[1] + '/', name: (a.textContent || '').trim().split('\n')[0] || m[1], ctx: cardCtx(a) });
2949
2991
  }
2950
2992
  m = href.match(/linkedin\.com\/company\/([^/?#]+)/);
2951
2993
  if (m && !seen.has('c:' + m[1])) {
@@ -3025,7 +3067,7 @@ async function runLinkedInSearch(args, log, ctx) {
3025
3067
  const maxPages = Math.min(Math.max(Number(args.maxPages) || 3, 1), 10);
3026
3068
  const keepTab = args.keepTab === true;
3027
3069
  const activateTab = args.activateTab !== false;
3028
- const loadTimeoutMs = Math.min(Math.max(Number(args.loadTimeoutMs) || 25e3, 5e3), 3e5);
3070
+ const loadTimeoutMs = clampLoadTimeoutMs(args.loadTimeoutMs);
3029
3071
  const delayBase = typeof args.delayMs === "number" ? Number(args.delayMs) : 2500;
3030
3072
  let effectiveKeywords = keywords;
3031
3073
  if (!filters.geoUrn && typeof filters.location === "string" && filters.location.trim()) {
@@ -3039,6 +3081,9 @@ async function runLinkedInSearch(args, log, ctx) {
3039
3081
  if (typeof filters.geoUrn === "string" && filters.geoUrn) u.searchParams.set("geoUrn", filters.geoUrn);
3040
3082
  if (typeof filters.company === "string" && filters.company) u.searchParams.set("company", filters.company);
3041
3083
  if (typeof filters.school === "string" && filters.school) u.searchParams.set("school", filters.school);
3084
+ const matcher = buildCardMatcher(filters);
3085
+ const locNeedle = matcher.locNeedle;
3086
+ const coNeedle = matcher.coNeedle;
3042
3087
  const tab = await chrome.tabs.create({ url: u.toString(), active: false });
3043
3088
  log("info", "hm.linkedin.search tab created", { tabId: tab.id, url: u.toString(), maxPages, activateTab });
3044
3089
  if (activateTab && tab.id != null) {
@@ -3066,13 +3111,24 @@ async function runLinkedInSearch(args, log, ctx) {
3066
3111
  const extracted = await cdpEvaluate(tab.id, LINKEDIN_EXTRACT_SOURCE);
3067
3112
  lastUrl = extracted?.url || lastUrl;
3068
3113
  const pageLeads = extracted?.links?.talent || [];
3114
+ let pageFiltered = 0;
3069
3115
  for (const l of pageLeads) {
3116
+ if ((locNeedle || coNeedle) && !matcher.match(l.ctx)) {
3117
+ pageFiltered++;
3118
+ continue;
3119
+ }
3070
3120
  if (l.url && !leads.has(l.url)) {
3071
- leads.set(l.url, { url: l.url, name: l.name ?? null, page, source: "linkedin" });
3121
+ leads.set(l.url, {
3122
+ url: l.url,
3123
+ name: l.name ?? null,
3124
+ page,
3125
+ source: "linkedin",
3126
+ ...l.ctx ? { snippet: l.ctx.slice(0, 200) } : {}
3127
+ });
3072
3128
  }
3073
3129
  }
3074
3130
  pagesScanned = page;
3075
- log("info", "hm.linkedin.search page extracted", { page, pageLeads: pageLeads.length, total: leads.size });
3131
+ log("info", "hm.linkedin.search page extracted", { page, pageLeads: pageLeads.length, pageFiltered, total: leads.size });
3076
3132
  if (page >= maxPages) break;
3077
3133
  const clicked = await cdpEvaluate(tab.id, LINKEDIN_NEXT_CLICK_SOURCE).catch(() => false);
3078
3134
  const urlBefore = (await chrome.tabs.get(tab.id).catch(() => null))?.url || "";
@@ -228,6 +228,7 @@ var require_hbr = __commonJS({
228
228
  exports.createHbrEvent = createHbrEvent;
229
229
  exports.createNetworkEvent = createNetworkEvent;
230
230
  exports.createConsoleEvent = createConsoleEvent;
231
+ exports.createExceptionEvent = createExceptionEvent;
231
232
  exports.createResumeEvent = createResumeEvent;
232
233
  exports.createActionEvent = createActionEvent;
233
234
  function createHbrEvent(type, sessionId, payload, options) {
@@ -247,6 +248,9 @@ var require_hbr = __commonJS({
247
248
  function createConsoleEvent(sessionId, data, privacy = "private") {
248
249
  return createHbrEvent("console", sessionId, data, { privacy });
249
250
  }
251
+ function createExceptionEvent(sessionId, data, privacy = "private") {
252
+ return createHbrEvent("exception", sessionId, data, { privacy });
253
+ }
250
254
  function createResumeEvent(sessionId, data, privacy = "private") {
251
255
  return createHbrEvent("resume", sessionId, data, { privacy });
252
256
  }
@@ -2339,6 +2343,31 @@ async function findDetailTabToReuse(url) {
2339
2343
  return idle?.id;
2340
2344
  }
2341
2345
 
2346
+ // src/background/linkedin-search-filter.ts
2347
+ var LINKEDIN_DEFAULT_LOAD_TIMEOUT_MS = 9e4;
2348
+ var MIN_TIMEOUT_MS = 5e3;
2349
+ var MAX_TIMEOUT_MS = 3e5;
2350
+ function clampLoadTimeoutMs(raw) {
2351
+ const n = Number(raw);
2352
+ if (!Number.isFinite(n) || n <= 0) return LINKEDIN_DEFAULT_LOAD_TIMEOUT_MS;
2353
+ return Math.min(Math.max(n, MIN_TIMEOUT_MS), MAX_TIMEOUT_MS);
2354
+ }
2355
+ function buildCardMatcher(filters) {
2356
+ const needle = (v) => typeof v === "string" && v.trim() ? v.trim().toLowerCase() : null;
2357
+ const locNeedle = filters.geoUrn ? null : needle(filters.location);
2358
+ const coNeedle = needle(filters.company);
2359
+ return {
2360
+ locNeedle,
2361
+ coNeedle,
2362
+ match(ctx) {
2363
+ const h = (ctx || "").toLowerCase();
2364
+ if (locNeedle && !h.includes(locNeedle)) return false;
2365
+ if (coNeedle && !h.includes(coNeedle)) return false;
2366
+ return true;
2367
+ }
2368
+ };
2369
+ }
2370
+
2342
2371
  // src/background/control.ts
2343
2372
  var RUNTIME_BRIDGE_FILE = "content/control-runtime.js";
2344
2373
  async function invokeRuntimeBridge(command, args) {
@@ -2940,12 +2969,25 @@ var LINKEDIN_EXTRACT_SOURCE = String.raw`(async () => {
2940
2969
  });
2941
2970
  } else if (pageClass === 'list') {
2942
2971
  const seen = new Set();
2972
+ // 卡片上下文:LinkedIn list 页 a[href*=/in/] 埋在结果卡内,向上找最小"像卡片"的祖先
2973
+ // (innerText 40-500 字符),抓 headline/地区/公司行——location/company 过滤的判定依据
2974
+ // (2026-10-18 寻访实测:LinkedIn 对自由文本 location/company 查询参数基本不生效,
2975
+ // 必须在 client 端按卡片文本过滤,否则过滤器名存实亡)。
2976
+ const cardCtx = (a) => {
2977
+ let el = a;
2978
+ for (let up = 0; up < 5 && el.parentElement; up++) {
2979
+ el = el.parentElement;
2980
+ const t = (el.innerText || '').replace(/\s+/g, ' ').trim();
2981
+ if (t.length >= 40) return t.slice(0, 400);
2982
+ }
2983
+ return null;
2984
+ };
2943
2985
  for (const a of Array.from(document.querySelectorAll('a[href]'))) {
2944
2986
  const href = a.href || '';
2945
2987
  let m = href.match(/linkedin\.com\/in\/([^/?#]+)/);
2946
2988
  if (m && !seen.has('t:' + m[1])) {
2947
2989
  seen.add('t:' + m[1]);
2948
- links.talent.push({ url: 'https://www.linkedin.com/in/' + m[1] + '/', name: (a.textContent || '').trim().split('\n')[0] || m[1] });
2990
+ links.talent.push({ url: 'https://www.linkedin.com/in/' + m[1] + '/', name: (a.textContent || '').trim().split('\n')[0] || m[1], ctx: cardCtx(a) });
2949
2991
  }
2950
2992
  m = href.match(/linkedin\.com\/company\/([^/?#]+)/);
2951
2993
  if (m && !seen.has('c:' + m[1])) {
@@ -3025,7 +3067,7 @@ async function runLinkedInSearch(args, log, ctx) {
3025
3067
  const maxPages = Math.min(Math.max(Number(args.maxPages) || 3, 1), 10);
3026
3068
  const keepTab = args.keepTab === true;
3027
3069
  const activateTab = args.activateTab !== false;
3028
- const loadTimeoutMs = Math.min(Math.max(Number(args.loadTimeoutMs) || 25e3, 5e3), 3e5);
3070
+ const loadTimeoutMs = clampLoadTimeoutMs(args.loadTimeoutMs);
3029
3071
  const delayBase = typeof args.delayMs === "number" ? Number(args.delayMs) : 2500;
3030
3072
  let effectiveKeywords = keywords;
3031
3073
  if (!filters.geoUrn && typeof filters.location === "string" && filters.location.trim()) {
@@ -3039,6 +3081,9 @@ async function runLinkedInSearch(args, log, ctx) {
3039
3081
  if (typeof filters.geoUrn === "string" && filters.geoUrn) u.searchParams.set("geoUrn", filters.geoUrn);
3040
3082
  if (typeof filters.company === "string" && filters.company) u.searchParams.set("company", filters.company);
3041
3083
  if (typeof filters.school === "string" && filters.school) u.searchParams.set("school", filters.school);
3084
+ const matcher = buildCardMatcher(filters);
3085
+ const locNeedle = matcher.locNeedle;
3086
+ const coNeedle = matcher.coNeedle;
3042
3087
  const tab = await chrome.tabs.create({ url: u.toString(), active: false });
3043
3088
  log("info", "hm.linkedin.search tab created", { tabId: tab.id, url: u.toString(), maxPages, activateTab });
3044
3089
  if (activateTab && tab.id != null) {
@@ -3066,13 +3111,24 @@ async function runLinkedInSearch(args, log, ctx) {
3066
3111
  const extracted = await cdpEvaluate(tab.id, LINKEDIN_EXTRACT_SOURCE);
3067
3112
  lastUrl = extracted?.url || lastUrl;
3068
3113
  const pageLeads = extracted?.links?.talent || [];
3114
+ let pageFiltered = 0;
3069
3115
  for (const l of pageLeads) {
3116
+ if ((locNeedle || coNeedle) && !matcher.match(l.ctx)) {
3117
+ pageFiltered++;
3118
+ continue;
3119
+ }
3070
3120
  if (l.url && !leads.has(l.url)) {
3071
- leads.set(l.url, { url: l.url, name: l.name ?? null, page, source: "linkedin" });
3121
+ leads.set(l.url, {
3122
+ url: l.url,
3123
+ name: l.name ?? null,
3124
+ page,
3125
+ source: "linkedin",
3126
+ ...l.ctx ? { snippet: l.ctx.slice(0, 200) } : {}
3127
+ });
3072
3128
  }
3073
3129
  }
3074
3130
  pagesScanned = page;
3075
- log("info", "hm.linkedin.search page extracted", { page, pageLeads: pageLeads.length, total: leads.size });
3131
+ log("info", "hm.linkedin.search page extracted", { page, pageLeads: pageLeads.length, pageFiltered, total: leads.size });
3076
3132
  if (page >= maxPages) break;
3077
3133
  const clicked = await cdpEvaluate(tab.id, LINKEDIN_NEXT_CLICK_SOURCE).catch(() => false);
3078
3134
  const urlBefore = (await chrome.tabs.get(tab.id).catch(() => null))?.url || "";
@@ -1 +1 @@
1
- {"buildTime":"2026-10-17T18:33:28.755Z","version":"0.1.25"}
1
+ {"buildTime":"2026-10-20T18:16:46.896Z","version":"0.1.27"}