hunter-mate 0.1.3 → 0.1.5
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/LICENSE +21 -0
- package/dist/assets/extension/background/service-worker.js +113 -24
- package/dist/assets/extension/content/index.js +239 -134
- package/dist/assets/extension/manifest.json +2 -4
- package/dist/assets/extension/sidepanel/index.js +76 -2
- package/dist/assets/server/app.module.js +4 -2
- package/dist/assets/server/app.module.js.map +1 -1
- package/dist/assets/server/build-info.json +1 -1
- package/dist/assets/server/db/sqlite.module.js +4 -0
- package/dist/assets/server/db/sqlite.module.js.map +1 -1
- package/dist/assets/server/devops/devops-sink-init.d.ts +14 -1
- package/dist/assets/server/devops/devops-sink-init.js +8 -3
- package/dist/assets/server/devops/devops-sink-init.js.map +1 -1
- package/dist/assets/server/doctor/doctor.controller.d.ts +13 -0
- package/dist/assets/server/doctor/doctor.controller.js +62 -0
- package/dist/assets/server/doctor/doctor.controller.js.map +1 -0
- package/dist/assets/server/doctor/doctor.module.d.ts +2 -0
- package/dist/assets/server/doctor/doctor.module.js +27 -0
- package/dist/assets/server/doctor/doctor.module.js.map +1 -0
- package/dist/assets/server/doctor/doctor.service.d.ts +15 -0
- package/dist/assets/server/doctor/doctor.service.js +209 -0
- package/dist/assets/server/doctor/doctor.service.js.map +1 -0
- package/dist/assets/server/doctor/doctor.types.d.ts +46 -0
- package/dist/assets/server/doctor/doctor.types.js +3 -0
- package/dist/assets/server/doctor/doctor.types.js.map +1 -0
- package/dist/assets/server/extraction/adapter.service.d.ts +18 -4
- package/dist/assets/server/extraction/adapter.service.js +129 -15
- package/dist/assets/server/extraction/adapter.service.js.map +1 -1
- package/dist/assets/server/extraction/anomaly-report.service.d.ts +12 -0
- package/dist/assets/server/extraction/anomaly-report.service.js +81 -0
- package/dist/assets/server/extraction/anomaly-report.service.js.map +1 -0
- package/dist/assets/server/extraction/entities/adapter-rule.entity.d.ts +13 -0
- package/dist/assets/server/extraction/entities/adapter-rule.entity.js +71 -0
- package/dist/assets/server/extraction/entities/adapter-rule.entity.js.map +1 -0
- package/dist/assets/server/extraction/entities/parse-log.entity.d.ts +4 -1
- package/dist/assets/server/extraction/entities/parse-log.entity.js +15 -0
- package/dist/assets/server/extraction/entities/parse-log.entity.js.map +1 -1
- package/dist/assets/server/extraction/extraction-entity.controller.d.ts +40 -2
- package/dist/assets/server/extraction/extraction-entity.controller.js +196 -13
- package/dist/assets/server/extraction/extraction-entity.controller.js.map +1 -1
- package/dist/assets/server/extraction/extraction-rule.service.js +16 -8
- package/dist/assets/server/extraction/extraction-rule.service.js.map +1 -1
- package/dist/assets/server/extraction/extraction.module.js +12 -2
- package/dist/assets/server/extraction/extraction.module.js.map +1 -1
- package/dist/assets/server/extraction/extraction.service.d.ts +17 -1
- package/dist/assets/server/extraction/extraction.service.js +125 -42
- package/dist/assets/server/extraction/extraction.service.js.map +1 -1
- package/dist/assets/server/extraction/linkedin-extractor.d.ts +1 -0
- package/dist/assets/server/extraction/linkedin-extractor.js +244 -0
- package/dist/assets/server/extraction/linkedin-extractor.js.map +1 -0
- package/dist/assets/server/extraction/rrweb-snapshot.utils.d.ts +15 -0
- package/dist/assets/server/extraction/rrweb-snapshot.utils.js +48 -0
- package/dist/assets/server/extraction/rrweb-snapshot.utils.js.map +1 -0
- package/dist/assets/server/extraction/rrweb-snapshot.utils.spec.d.ts +1 -0
- package/dist/assets/server/extraction/rrweb-snapshot.utils.spec.js +60 -0
- package/dist/assets/server/extraction/rrweb-snapshot.utils.spec.js.map +1 -0
- package/dist/assets/server/extraction/script-rule.d.ts +1 -0
- package/dist/assets/server/extraction/script-rule.js +4 -0
- package/dist/assets/server/extraction/script-rule.js.map +1 -1
- package/dist/assets/server/extraction/snapshot-analysis.service.d.ts +23 -0
- package/dist/assets/server/extraction/snapshot-analysis.service.js +147 -0
- package/dist/assets/server/extraction/snapshot-analysis.service.js.map +1 -0
- package/dist/assets/server/recording/entities/recording-snapshot.entity.d.ts +16 -0
- package/dist/assets/server/recording/entities/recording-snapshot.entity.js +91 -0
- package/dist/assets/server/recording/entities/recording-snapshot.entity.js.map +1 -0
- package/dist/assets/server/recording/recording-event-bus.service.d.ts +4 -0
- package/dist/assets/server/recording/recording-event-bus.service.js +25 -0
- package/dist/assets/server/recording/recording-event-bus.service.js.map +1 -0
- package/dist/assets/server/recording/recording-snapshot.service.d.ts +13 -0
- package/dist/assets/server/recording/recording-snapshot.service.js +81 -0
- package/dist/assets/server/recording/recording-snapshot.service.js.map +1 -0
- package/dist/assets/server/recording/recording-snapshot.service.spec.d.ts +1 -0
- package/dist/assets/server/recording/recording-snapshot.service.spec.js +65 -0
- package/dist/assets/server/recording/recording-snapshot.service.spec.js.map +1 -0
- package/dist/assets/server/recording/recording.controller.d.ts +3 -1
- package/dist/assets/server/recording/recording.controller.js +7 -3
- package/dist/assets/server/recording/recording.controller.js.map +1 -1
- package/dist/assets/server/recording/recording.module.js +11 -4
- package/dist/assets/server/recording/recording.module.js.map +1 -1
- package/dist/assets/server/recording/recording.service.d.ts +5 -21
- package/dist/assets/server/recording/recording.service.js +22 -9
- package/dist/assets/server/recording/recording.service.js.map +1 -1
- package/dist/assets/server/site/entities/site-registry.entity.d.ts +2 -0
- package/dist/assets/server/site/entities/site-registry.entity.js +10 -0
- package/dist/assets/server/site/entities/site-registry.entity.js.map +1 -1
- package/dist/assets/server/site/site.controller.d.ts +2 -0
- package/dist/assets/server/site/site.controller.js +1 -1
- package/dist/assets/server/site/site.controller.js.map +1 -1
- package/dist/assets/server/site/site.service.d.ts +2 -1
- package/dist/assets/server/site/site.service.js +10 -3
- package/dist/assets/server/site/site.service.js.map +1 -1
- package/dist/auto-doctor.d.ts +8 -0
- package/dist/auto-doctor.js +34 -0
- package/dist/commands/doctor.d.ts +43 -0
- package/dist/commands/doctor.js +179 -7
- package/dist/commands/extension.js +2 -2
- package/dist/commands/extras.d.ts +1 -1
- package/dist/commands/extras.js +4 -3
- package/dist/commands/install.js +11 -8
- package/dist/index.js +7 -0
- package/dist/native-check.js +8 -1
- package/dist/updater.d.ts +9 -5
- package/dist/updater.js +75 -9
- package/package.json +3 -3
|
@@ -10497,10 +10497,10 @@
|
|
|
10497
10497
|
mutationBuffers.push(mutationBuffer);
|
|
10498
10498
|
mutationBuffer.init(options);
|
|
10499
10499
|
const [ObserverCtor, iframeCleanup] = mutationObserverCtor();
|
|
10500
|
-
const
|
|
10500
|
+
const observer2 = new ObserverCtor(
|
|
10501
10501
|
callbackWrapper(mutationBuffer.processMutations.bind(mutationBuffer))
|
|
10502
10502
|
);
|
|
10503
|
-
|
|
10503
|
+
observer2.observe(rootEl, {
|
|
10504
10504
|
attributes: true,
|
|
10505
10505
|
attributeOldValue: true,
|
|
10506
10506
|
characterData: true,
|
|
@@ -10508,7 +10508,7 @@
|
|
|
10508
10508
|
childList: true,
|
|
10509
10509
|
subtree: true
|
|
10510
10510
|
});
|
|
10511
|
-
return [
|
|
10511
|
+
return [observer2, iframeCleanup];
|
|
10512
10512
|
}
|
|
10513
10513
|
function initMoveObserver({
|
|
10514
10514
|
mousemoveCb,
|
|
@@ -11811,7 +11811,7 @@
|
|
|
11811
11811
|
if (!isNativeShadowDom(shadowRoot2)) return;
|
|
11812
11812
|
if (this.shadowDoms.has(shadowRoot2)) return;
|
|
11813
11813
|
this.shadowDoms.add(shadowRoot2);
|
|
11814
|
-
const [
|
|
11814
|
+
const [observer2] = initMutationObserver(
|
|
11815
11815
|
{
|
|
11816
11816
|
...this.bypassOptions,
|
|
11817
11817
|
doc,
|
|
@@ -11821,7 +11821,7 @@
|
|
|
11821
11821
|
},
|
|
11822
11822
|
shadowRoot2
|
|
11823
11823
|
);
|
|
11824
|
-
this.restoreHandlers.push(() =>
|
|
11824
|
+
this.restoreHandlers.push(() => observer2.disconnect());
|
|
11825
11825
|
this.restoreHandlers.push(
|
|
11826
11826
|
initScrollObserver({
|
|
11827
11827
|
...this.bypassOptions,
|
|
@@ -12945,13 +12945,13 @@
|
|
|
12945
12945
|
console.warn(error);
|
|
12946
12946
|
}
|
|
12947
12947
|
});
|
|
12948
|
-
const
|
|
12948
|
+
const init2 = () => {
|
|
12949
12949
|
takeFullSnapshot$1();
|
|
12950
12950
|
handlers.push(observe(document));
|
|
12951
12951
|
recording = true;
|
|
12952
12952
|
};
|
|
12953
12953
|
if (["interactive", "complete"].includes(document.readyState)) {
|
|
12954
|
-
|
|
12954
|
+
init2();
|
|
12955
12955
|
} else {
|
|
12956
12956
|
handlers.push(
|
|
12957
12957
|
on("DOMContentLoaded", () => {
|
|
@@ -12959,7 +12959,7 @@
|
|
|
12959
12959
|
type: EventType.DomContentLoaded,
|
|
12960
12960
|
data: {}
|
|
12961
12961
|
});
|
|
12962
|
-
if (recordAfter === "DOMContentLoaded")
|
|
12962
|
+
if (recordAfter === "DOMContentLoaded") init2();
|
|
12963
12963
|
})
|
|
12964
12964
|
);
|
|
12965
12965
|
handlers.push(
|
|
@@ -12970,7 +12970,7 @@
|
|
|
12970
12970
|
type: EventType.Load,
|
|
12971
12971
|
data: {}
|
|
12972
12972
|
});
|
|
12973
|
-
if (recordAfter === "load")
|
|
12973
|
+
if (recordAfter === "load") init2();
|
|
12974
12974
|
},
|
|
12975
12975
|
window
|
|
12976
12976
|
)
|
|
@@ -13046,20 +13046,20 @@
|
|
|
13046
13046
|
}
|
|
13047
13047
|
function patchNetwork() {
|
|
13048
13048
|
const originalFetch = window.fetch;
|
|
13049
|
-
window.fetch = async function patchedFetch(input2,
|
|
13050
|
-
const response = await originalFetch.apply(this, [input2,
|
|
13049
|
+
window.fetch = async function patchedFetch(input2, init2) {
|
|
13050
|
+
const response = await originalFetch.apply(this, [input2, init2]);
|
|
13051
13051
|
try {
|
|
13052
13052
|
const url = typeof input2 === "string" ? input2 : input2.url;
|
|
13053
13053
|
const requestHeaders = {};
|
|
13054
|
-
if (
|
|
13055
|
-
new Headers(
|
|
13054
|
+
if (init2?.headers) {
|
|
13055
|
+
new Headers(init2.headers).forEach((value, key) => {
|
|
13056
13056
|
requestHeaders[key] = value;
|
|
13057
13057
|
});
|
|
13058
13058
|
}
|
|
13059
13059
|
const event = (0, import_shared.createNetworkEvent)(
|
|
13060
13060
|
sessionId,
|
|
13061
13061
|
{
|
|
13062
|
-
method:
|
|
13062
|
+
method: init2?.method || "GET",
|
|
13063
13063
|
url: (0, import_shared.redactUrlQuery)(url),
|
|
13064
13064
|
requestHeaders: (0, import_shared.redactHeaders)(requestHeaders),
|
|
13065
13065
|
responseHeaders: (0, import_shared.redactHeaders)(Object.fromEntries(response.headers.entries())),
|
|
@@ -13098,20 +13098,34 @@
|
|
|
13098
13098
|
|
|
13099
13099
|
// src/content/recorder.ts
|
|
13100
13100
|
var stopFn = null;
|
|
13101
|
+
var currentSessionId = null;
|
|
13102
|
+
var currentSourceUrl = "";
|
|
13103
|
+
var CHECKOUT_EVERY_NMS = 3e4;
|
|
13104
|
+
var CHECKOUT_EVERY_NTH = 200;
|
|
13101
13105
|
function startRecording(sessionId4) {
|
|
13102
13106
|
if (stopFn) return;
|
|
13103
13107
|
setSessionId(sessionId4);
|
|
13104
13108
|
setSessionId2(sessionId4);
|
|
13105
13109
|
patchNetwork();
|
|
13106
13110
|
patchConsole();
|
|
13107
|
-
|
|
13111
|
+
currentSessionId = sessionId4;
|
|
13112
|
+
currentSourceUrl = window.location.href;
|
|
13108
13113
|
const stop = record({
|
|
13109
|
-
emit(event) {
|
|
13110
|
-
|
|
13114
|
+
emit(event, isCheckout) {
|
|
13115
|
+
if (isCheckout != null && event && typeof event === "object") {
|
|
13116
|
+
event.isCheckout = isCheckout === true;
|
|
13117
|
+
}
|
|
13118
|
+
const hbrEvent = (0, import_shared3.createHbrEvent)("rrweb", sessionId4, event, {
|
|
13119
|
+
privacy: "private",
|
|
13120
|
+
sourceUrl: currentSourceUrl
|
|
13121
|
+
});
|
|
13111
13122
|
sendToBackground({ type: "recording-event", payload: hbrEvent });
|
|
13112
13123
|
},
|
|
13113
13124
|
recordCanvas: false,
|
|
13114
|
-
collectFonts: false
|
|
13125
|
+
collectFonts: false,
|
|
13126
|
+
checkoutEveryNms: CHECKOUT_EVERY_NMS,
|
|
13127
|
+
checkoutEveryNth: CHECKOUT_EVERY_NTH,
|
|
13128
|
+
maskAllInputs: true
|
|
13115
13129
|
});
|
|
13116
13130
|
if (!stop) return;
|
|
13117
13131
|
stopFn = stop;
|
|
@@ -13121,9 +13135,22 @@
|
|
|
13121
13135
|
if (stopFn) {
|
|
13122
13136
|
stopFn();
|
|
13123
13137
|
stopFn = null;
|
|
13138
|
+
currentSessionId = null;
|
|
13139
|
+
currentSourceUrl = "";
|
|
13124
13140
|
console.log("[HunterMate] recording stopped");
|
|
13125
13141
|
}
|
|
13126
13142
|
}
|
|
13143
|
+
function setRecordingSourceUrl(url) {
|
|
13144
|
+
currentSourceUrl = url;
|
|
13145
|
+
}
|
|
13146
|
+
function takeCheckpoint(isCheckout = true) {
|
|
13147
|
+
if (!stopFn) return;
|
|
13148
|
+
try {
|
|
13149
|
+
record.takeFullSnapshot(isCheckout);
|
|
13150
|
+
} catch (err) {
|
|
13151
|
+
console.warn("[HunterMate] takeFullSnapshot failed", err);
|
|
13152
|
+
}
|
|
13153
|
+
}
|
|
13127
13154
|
|
|
13128
13155
|
// src/shared/etld.ts
|
|
13129
13156
|
var MULTI_PART_SUFFIXES = /* @__PURE__ */ new Set([
|
|
@@ -13228,101 +13255,6 @@
|
|
|
13228
13255
|
return out;
|
|
13229
13256
|
}
|
|
13230
13257
|
|
|
13231
|
-
// src/content/floating-overlay.ts
|
|
13232
|
-
var OVERLAY_ID = "hunter-mate-overlay";
|
|
13233
|
-
function removeOverlay() {
|
|
13234
|
-
const existing = document.getElementById(OVERLAY_ID);
|
|
13235
|
-
if (existing) existing.remove();
|
|
13236
|
-
}
|
|
13237
|
-
async function showOverlay(pageInfo, parseResult) {
|
|
13238
|
-
removeOverlay();
|
|
13239
|
-
if (pageInfo.category === "unknown" || !parseResult) return;
|
|
13240
|
-
const container2 = document.createElement("div");
|
|
13241
|
-
container2.id = OVERLAY_ID;
|
|
13242
|
-
container2.style.cssText = `
|
|
13243
|
-
position: fixed;
|
|
13244
|
-
top: 80px;
|
|
13245
|
-
right: 20px;
|
|
13246
|
-
width: 260px;
|
|
13247
|
-
max-height: 360px;
|
|
13248
|
-
overflow: auto;
|
|
13249
|
-
background: #fff;
|
|
13250
|
-
border: 1px solid #dadce0;
|
|
13251
|
-
border-radius: 8px;
|
|
13252
|
-
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
13253
|
-
z-index: 2147483647;
|
|
13254
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
13255
|
-
font-size: 13px;
|
|
13256
|
-
padding: 12px;
|
|
13257
|
-
color: #202124;
|
|
13258
|
-
`;
|
|
13259
|
-
const title = document.createElement("div");
|
|
13260
|
-
title.style.cssText = "font-weight:bold;margin-bottom:8px;display:flex;align-items:center;gap:6px;";
|
|
13261
|
-
const status = parseResult.parsedResumeId ? "parsed" : "parse-failed";
|
|
13262
|
-
if (status === "parse-failed") {
|
|
13263
|
-
title.innerHTML = "<span>\u274C</span><span>\u89E3\u6790\u5931\u8D25</span>";
|
|
13264
|
-
container2.appendChild(title);
|
|
13265
|
-
document.body.appendChild(container2);
|
|
13266
|
-
return;
|
|
13267
|
-
}
|
|
13268
|
-
const isMerged = parseResult.matchType === "merged";
|
|
13269
|
-
const resumeCount = parseResult.portraitResumeCount || 1;
|
|
13270
|
-
if (isMerged && resumeCount > 1) {
|
|
13271
|
-
title.innerHTML = `<span>\u2705</span><span>\u5DF2\u6536\u5F55 (\u5171 ${resumeCount} \u4EFD\u6765\u6E90)</span>`;
|
|
13272
|
-
} else if (isMerged) {
|
|
13273
|
-
title.innerHTML = "<span>\u{1F50D}</span><span>\u7591\u4F3C\u5DF2\u6536\u5F55 / \u540C\u4EBA</span>";
|
|
13274
|
-
} else {
|
|
13275
|
-
title.innerHTML = "<span>\u{1F195}</span><span>\u65B0\u4EBA\u624D\uFF0C\u5DF2\u5165\u5E93</span>";
|
|
13276
|
-
}
|
|
13277
|
-
container2.appendChild(title);
|
|
13278
|
-
const meta = document.createElement("div");
|
|
13279
|
-
meta.style.cssText = "color:#5f6368;margin-bottom:8px;";
|
|
13280
|
-
meta.textContent = `\u7F6E\u4FE1\u5EA6 ${Math.round((parseResult.overallConfidence || 0) * 100)}% \xB7 \u753B\u50CF ${parseResult.portraitId?.slice(0, 8) || "N/A"}`;
|
|
13281
|
-
container2.appendChild(meta);
|
|
13282
|
-
if (pageInfo.category === "talent" && parseResult.portraitId) {
|
|
13283
|
-
await renderRecommendedJobs(container2, parseResult.portraitId);
|
|
13284
|
-
}
|
|
13285
|
-
document.body.appendChild(container2);
|
|
13286
|
-
setTimeout(() => {
|
|
13287
|
-
container2.style.opacity = "0.95";
|
|
13288
|
-
container2.style.transition = "opacity 0.3s";
|
|
13289
|
-
}, 5e3);
|
|
13290
|
-
}
|
|
13291
|
-
async function renderRecommendedJobs(container2, portraitId) {
|
|
13292
|
-
const header = document.createElement("div");
|
|
13293
|
-
header.style.cssText = "font-weight:bold;margin:8px 0 4px;border-top:1px solid #eee;padding-top:8px;";
|
|
13294
|
-
header.textContent = "\u63A8\u8350\u804C\u4F4D";
|
|
13295
|
-
container2.appendChild(header);
|
|
13296
|
-
try {
|
|
13297
|
-
const res = await fetch(`${SERVER_HTTP_URL}/matching/portraits/${portraitId}/jobs`);
|
|
13298
|
-
if (!res.ok) throw new Error(`status ${res.status}`);
|
|
13299
|
-
const matches = (await res.json()).slice(0, 3);
|
|
13300
|
-
if (!matches.length) {
|
|
13301
|
-
const empty = document.createElement("div");
|
|
13302
|
-
empty.style.cssText = "color:#888;";
|
|
13303
|
-
empty.textContent = "\u6682\u65E0\u5339\u914D\u804C\u4F4D";
|
|
13304
|
-
container2.appendChild(empty);
|
|
13305
|
-
return;
|
|
13306
|
-
}
|
|
13307
|
-
for (const m of matches) {
|
|
13308
|
-
const row = document.createElement("div");
|
|
13309
|
-
row.style.cssText = "padding:6px 0;border-bottom:1px solid #f1f3f4;cursor:pointer;";
|
|
13310
|
-
const score = m.scores?.overall ?? 0;
|
|
13311
|
-
row.innerHTML = `<div style="font-weight:500;">\u804C\u4F4D #${m.jobCaseId}</div>
|
|
13312
|
-
<div style="color:#5f6368;font-size:12px;">\u5339\u914D\u5EA6 ${score}%</div>`;
|
|
13313
|
-
row.addEventListener("click", () => {
|
|
13314
|
-
window.open(`http://localhost:3000/jobs/${m.jobCaseId}`, "_blank");
|
|
13315
|
-
});
|
|
13316
|
-
container2.appendChild(row);
|
|
13317
|
-
}
|
|
13318
|
-
} catch {
|
|
13319
|
-
const err = document.createElement("div");
|
|
13320
|
-
err.style.cssText = "color:#888;";
|
|
13321
|
-
err.textContent = "\u63A8\u8350\u804C\u4F4D\u52A0\u8F7D\u5931\u8D25";
|
|
13322
|
-
container2.appendChild(err);
|
|
13323
|
-
}
|
|
13324
|
-
}
|
|
13325
|
-
|
|
13326
13258
|
// ../../node_modules/.pnpm/@chromepilot+logger-kit@0.1.3_@nestjs+common@10.4.22_class-transformer@0.5.1_class-validator@_v44hq6ikmqzoani6tawke4nway/node_modules/@chromepilot/logger-kit/dist/client/logger.js
|
|
13327
13259
|
function stringifyArg(arg) {
|
|
13328
13260
|
if (typeof arg === "string")
|
|
@@ -13488,18 +13420,105 @@
|
|
|
13488
13420
|
});
|
|
13489
13421
|
}
|
|
13490
13422
|
|
|
13423
|
+
// src/content/dom-watch.ts
|
|
13424
|
+
var BIG_DOM_THRESHOLD = 50;
|
|
13425
|
+
var SNAPSHOT_COOLDOWN_MS = 1e3;
|
|
13426
|
+
var lastSnapshotAt = 0;
|
|
13427
|
+
var observer = null;
|
|
13428
|
+
var onBigChangeCallback = null;
|
|
13429
|
+
var originalPushState = null;
|
|
13430
|
+
var originalReplaceState = null;
|
|
13431
|
+
function canTakeCheckpoint() {
|
|
13432
|
+
return Date.now() - lastSnapshotAt > SNAPSHOT_COOLDOWN_MS;
|
|
13433
|
+
}
|
|
13434
|
+
function markCheckpointTaken() {
|
|
13435
|
+
lastSnapshotAt = Date.now();
|
|
13436
|
+
}
|
|
13437
|
+
function patchHistory(onChange) {
|
|
13438
|
+
if (originalPushState) return;
|
|
13439
|
+
originalPushState = history.pushState;
|
|
13440
|
+
originalReplaceState = history.replaceState;
|
|
13441
|
+
history.pushState = function(...args) {
|
|
13442
|
+
originalPushState.apply(this, args);
|
|
13443
|
+
onChange();
|
|
13444
|
+
};
|
|
13445
|
+
history.replaceState = function(...args) {
|
|
13446
|
+
originalReplaceState.apply(this, args);
|
|
13447
|
+
onChange();
|
|
13448
|
+
};
|
|
13449
|
+
window.addEventListener("popstate", onChange);
|
|
13450
|
+
}
|
|
13451
|
+
function restoreHistory() {
|
|
13452
|
+
if (originalPushState) {
|
|
13453
|
+
history.pushState = originalPushState;
|
|
13454
|
+
originalPushState = null;
|
|
13455
|
+
}
|
|
13456
|
+
if (originalReplaceState) {
|
|
13457
|
+
history.replaceState = originalReplaceState;
|
|
13458
|
+
originalReplaceState = null;
|
|
13459
|
+
}
|
|
13460
|
+
}
|
|
13461
|
+
function initDomWatch(onBigChange) {
|
|
13462
|
+
onBigChangeCallback = onBigChange;
|
|
13463
|
+
patchHistory(() => {
|
|
13464
|
+
});
|
|
13465
|
+
if (typeof MutationObserver !== "undefined" && document.body) {
|
|
13466
|
+
let buffer = [];
|
|
13467
|
+
let flushTimer = null;
|
|
13468
|
+
const flush = () => {
|
|
13469
|
+
flushTimer = null;
|
|
13470
|
+
const mutations = buffer;
|
|
13471
|
+
buffer = [];
|
|
13472
|
+
let changedNodes = 0;
|
|
13473
|
+
for (const m of mutations) {
|
|
13474
|
+
changedNodes += m.addedNodes.length + m.removedNodes.length;
|
|
13475
|
+
}
|
|
13476
|
+
if (changedNodes > BIG_DOM_THRESHOLD && canTakeCheckpoint()) {
|
|
13477
|
+
onBigChangeCallback?.();
|
|
13478
|
+
}
|
|
13479
|
+
};
|
|
13480
|
+
observer = new MutationObserver((mutations) => {
|
|
13481
|
+
buffer.push(...mutations);
|
|
13482
|
+
if (!flushTimer) {
|
|
13483
|
+
flushTimer = setTimeout(flush, 200);
|
|
13484
|
+
}
|
|
13485
|
+
});
|
|
13486
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
13487
|
+
}
|
|
13488
|
+
}
|
|
13489
|
+
function destroyDomWatch() {
|
|
13490
|
+
observer?.disconnect();
|
|
13491
|
+
observer = null;
|
|
13492
|
+
restoreHistory();
|
|
13493
|
+
onBigChangeCallback = null;
|
|
13494
|
+
}
|
|
13495
|
+
|
|
13491
13496
|
// src/content/index.ts
|
|
13492
13497
|
function generateSessionId() {
|
|
13493
13498
|
return `rec-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
13494
13499
|
}
|
|
13495
13500
|
var sessionId3 = null;
|
|
13496
13501
|
var autoParseStarted = false;
|
|
13502
|
+
var currentSitePolicy = null;
|
|
13503
|
+
var currentSourceUrl2 = window.location.href;
|
|
13497
13504
|
var contentLogger = createMessageLogger({
|
|
13498
13505
|
context: "content",
|
|
13499
13506
|
sessionId: () => sessionId3 || `tab-${location.hostname}`
|
|
13500
13507
|
});
|
|
13501
13508
|
contentLogger.patchConsole();
|
|
13502
13509
|
var ACTIONABLE_CLASSES = /* @__PURE__ */ new Set(["talent", "job", "company"]);
|
|
13510
|
+
async function querySitePolicy() {
|
|
13511
|
+
try {
|
|
13512
|
+
const policy = await chrome.runtime.sendMessage({
|
|
13513
|
+
type: "query-site-policy",
|
|
13514
|
+
payload: { url: window.location.href }
|
|
13515
|
+
});
|
|
13516
|
+
currentSitePolicy = policy || { record: false, parse: false };
|
|
13517
|
+
} catch {
|
|
13518
|
+
currentSitePolicy = { record: false, parse: false };
|
|
13519
|
+
}
|
|
13520
|
+
return currentSitePolicy || { record: false, parse: false };
|
|
13521
|
+
}
|
|
13503
13522
|
function beginRecording() {
|
|
13504
13523
|
if (sessionId3) return sessionId3;
|
|
13505
13524
|
const cls = classifyPage();
|
|
@@ -13512,11 +13531,19 @@
|
|
|
13512
13531
|
return null;
|
|
13513
13532
|
}
|
|
13514
13533
|
sessionId3 = generateSessionId();
|
|
13534
|
+
currentSourceUrl2 = window.location.href;
|
|
13515
13535
|
startRecording(sessionId3);
|
|
13516
13536
|
sendToBackground({
|
|
13517
13537
|
type: "recording-started",
|
|
13518
13538
|
payload: { sessionId: sessionId3, classification: cls }
|
|
13519
13539
|
});
|
|
13540
|
+
initDomWatch(() => {
|
|
13541
|
+
if (sessionId3 && canTakeCheckpoint2()) {
|
|
13542
|
+
takeCheckpoint(false);
|
|
13543
|
+
markCheckpointTaken();
|
|
13544
|
+
contentLogger.info("content:checkpoint:dom-big-change", { sessionId: sessionId3, url: window.location.href });
|
|
13545
|
+
}
|
|
13546
|
+
});
|
|
13520
13547
|
beginAutoParse(cls);
|
|
13521
13548
|
return sessionId3;
|
|
13522
13549
|
}
|
|
@@ -13524,11 +13551,16 @@
|
|
|
13524
13551
|
if (!sessionId3) return;
|
|
13525
13552
|
const ended = sessionId3;
|
|
13526
13553
|
stopRecording();
|
|
13554
|
+
destroyDomWatch();
|
|
13527
13555
|
sendToBackground({ type: "recording-stopped", payload: { sessionId: ended } });
|
|
13528
13556
|
sessionId3 = null;
|
|
13529
13557
|
autoParseStarted = false;
|
|
13558
|
+
currentSourceUrl2 = "";
|
|
13530
13559
|
return ended;
|
|
13531
13560
|
}
|
|
13561
|
+
function canTakeCheckpoint2() {
|
|
13562
|
+
return true;
|
|
13563
|
+
}
|
|
13532
13564
|
async function beginAutoParse(cls) {
|
|
13533
13565
|
if (autoParseStarted) return;
|
|
13534
13566
|
if (!ACTIONABLE_CLASSES.has(cls.pageClass)) {
|
|
@@ -13538,14 +13570,22 @@
|
|
|
13538
13570
|
autoParseStarted = true;
|
|
13539
13571
|
updatePageStatus(cls, "parsing");
|
|
13540
13572
|
await waitForStable(2500, 500);
|
|
13541
|
-
const
|
|
13542
|
-
if (!
|
|
13573
|
+
const currentSessionId2 = sessionId3;
|
|
13574
|
+
if (!currentSessionId2) {
|
|
13543
13575
|
updatePageStatus(cls, "parse-failed");
|
|
13544
13576
|
return;
|
|
13545
13577
|
}
|
|
13546
|
-
|
|
13578
|
+
if (cls.pageClass === "talent" || cls.pageClass === "job" || cls.pageClass === "company") {
|
|
13579
|
+
await whenVisible();
|
|
13580
|
+
await scrollToLoadFullPage(5e3);
|
|
13581
|
+
await scrollSections(["Experience", "Education", "Skills", "Projects"]);
|
|
13582
|
+
takeCheckpoint(false);
|
|
13583
|
+
markCheckpointTaken();
|
|
13584
|
+
await waitForStable(1200, 300);
|
|
13585
|
+
}
|
|
13586
|
+
contentLogger.info("content:auto-parse:start", { sessionId: currentSessionId2, pageClass: cls.pageClass });
|
|
13547
13587
|
try {
|
|
13548
|
-
const parseRes = await fetch(`${SERVER_HTTP_URL}/parse/${
|
|
13588
|
+
const parseRes = await fetch(`${SERVER_HTTP_URL}/parse/${currentSessionId2}`, {
|
|
13549
13589
|
method: "POST"
|
|
13550
13590
|
});
|
|
13551
13591
|
if (!parseRes.ok) {
|
|
@@ -13555,26 +13595,15 @@
|
|
|
13555
13595
|
const result2 = await parseRes.json();
|
|
13556
13596
|
const ok = result2.status === "ok" && result2.entity;
|
|
13557
13597
|
contentLogger.info("content:auto-parse:done", {
|
|
13558
|
-
sessionId:
|
|
13598
|
+
sessionId: currentSessionId2,
|
|
13559
13599
|
status: result2.status,
|
|
13560
13600
|
ok,
|
|
13561
13601
|
entityId: result2.entity?.id
|
|
13562
13602
|
});
|
|
13563
13603
|
updatePageStatus(cls, ok ? "parsed" : "parse-failed", result2);
|
|
13564
|
-
if (ok) {
|
|
13565
|
-
showOverlay(
|
|
13566
|
-
{ category: cls.pageClass, system: cls.domain, url: window.location.href },
|
|
13567
|
-
{
|
|
13568
|
-
snapshotId: currentSessionId,
|
|
13569
|
-
parsedResumeId: String(result2.entity.id),
|
|
13570
|
-
overallConfidence: result2.extracted ? 0.8 : 0.2,
|
|
13571
|
-
matchType: result2.entity.isNew === false ? "merged" : "new"
|
|
13572
|
-
}
|
|
13573
|
-
);
|
|
13574
|
-
}
|
|
13575
13604
|
} catch (err) {
|
|
13576
13605
|
contentLogger.error("content:auto-parse:failed", {
|
|
13577
|
-
sessionId:
|
|
13606
|
+
sessionId: currentSessionId2,
|
|
13578
13607
|
error: err.message || String(err)
|
|
13579
13608
|
});
|
|
13580
13609
|
updatePageStatus(cls, "parse-failed");
|
|
@@ -13599,14 +13628,90 @@
|
|
|
13599
13628
|
function waitForStable(baseMs, jitterMs) {
|
|
13600
13629
|
return new Promise((resolve) => setTimeout(resolve, baseMs + Math.random() * jitterMs));
|
|
13601
13630
|
}
|
|
13602
|
-
|
|
13631
|
+
function whenVisible() {
|
|
13632
|
+
if (!document.hidden) return Promise.resolve();
|
|
13633
|
+
return new Promise((resolve) => {
|
|
13634
|
+
const handler = () => {
|
|
13635
|
+
if (document.visibilityState === "visible") {
|
|
13636
|
+
document.removeEventListener("visibilitychange", handler);
|
|
13637
|
+
resolve();
|
|
13638
|
+
}
|
|
13639
|
+
};
|
|
13640
|
+
document.addEventListener("visibilitychange", handler);
|
|
13641
|
+
});
|
|
13642
|
+
}
|
|
13643
|
+
function scrollToLoadFullPage(durationMs = 5e3) {
|
|
13644
|
+
return new Promise((resolve) => {
|
|
13645
|
+
const start = performance.now();
|
|
13646
|
+
const startY = window.scrollY;
|
|
13647
|
+
const docHeight = () => document.body.scrollHeight || document.documentElement.scrollHeight;
|
|
13648
|
+
let lastHeight = docHeight();
|
|
13649
|
+
let lastChange = start;
|
|
13650
|
+
const maxMs = Math.max(durationMs * 3, 15e3);
|
|
13651
|
+
const stableThresholdMs = 1500;
|
|
13652
|
+
const interval = setInterval(() => {
|
|
13653
|
+
const now = performance.now();
|
|
13654
|
+
const elapsed = now - start;
|
|
13655
|
+
const target = Math.max(0, docHeight() - window.innerHeight);
|
|
13656
|
+
let nextY;
|
|
13657
|
+
if (elapsed < durationMs) {
|
|
13658
|
+
nextY = Math.min(target, target * elapsed / durationMs);
|
|
13659
|
+
} else {
|
|
13660
|
+
nextY = target;
|
|
13661
|
+
}
|
|
13662
|
+
window.scrollTo({ top: nextY, behavior: "auto" });
|
|
13663
|
+
const h = docHeight();
|
|
13664
|
+
if (h > lastHeight) {
|
|
13665
|
+
lastHeight = h;
|
|
13666
|
+
lastChange = now;
|
|
13667
|
+
}
|
|
13668
|
+
const stable = now - lastChange >= stableThresholdMs;
|
|
13669
|
+
if (stable && elapsed > durationMs || elapsed > maxMs) {
|
|
13670
|
+
clearInterval(interval);
|
|
13671
|
+
window.scrollTo({ top: startY, behavior: "auto" });
|
|
13672
|
+
resolve();
|
|
13673
|
+
}
|
|
13674
|
+
}, 150);
|
|
13675
|
+
});
|
|
13676
|
+
}
|
|
13677
|
+
async function scrollSections(keywords) {
|
|
13678
|
+
const headings = Array.from(document.querySelectorAll("h2")).filter(
|
|
13679
|
+
(h) => keywords.some((kw) => h.textContent?.includes(kw))
|
|
13680
|
+
);
|
|
13681
|
+
for (const h of headings) {
|
|
13682
|
+
h.scrollIntoView({ block: "center", behavior: "auto" });
|
|
13683
|
+
await waitForStable(600, 100);
|
|
13684
|
+
}
|
|
13685
|
+
}
|
|
13686
|
+
async function init() {
|
|
13687
|
+
const policy = await querySitePolicy();
|
|
13688
|
+
if (!policy.record) {
|
|
13689
|
+
contentLogger.info("content:site-not-target", { url: window.location.href });
|
|
13690
|
+
return;
|
|
13691
|
+
}
|
|
13692
|
+
beginRecording();
|
|
13693
|
+
}
|
|
13694
|
+
init();
|
|
13603
13695
|
var lastUrl = window.location.href;
|
|
13604
13696
|
setInterval(() => {
|
|
13605
13697
|
if (window.location.href !== lastUrl) {
|
|
13606
13698
|
lastUrl = window.location.href;
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13699
|
+
currentSourceUrl2 = lastUrl;
|
|
13700
|
+
setRecordingSourceUrl(lastUrl);
|
|
13701
|
+
if (sessionId3) {
|
|
13702
|
+
takeCheckpoint(true);
|
|
13703
|
+
markCheckpointTaken();
|
|
13704
|
+
contentLogger.info("content:checkpoint:route-change", { sessionId: sessionId3, url: lastUrl });
|
|
13705
|
+
autoParseStarted = false;
|
|
13706
|
+
const cls = classifyPage();
|
|
13707
|
+
sendToBackground({
|
|
13708
|
+
type: "recording-started",
|
|
13709
|
+
payload: { sessionId: sessionId3, classification: cls }
|
|
13710
|
+
});
|
|
13711
|
+
beginAutoParse(cls);
|
|
13712
|
+
} else {
|
|
13713
|
+
init();
|
|
13714
|
+
}
|
|
13610
13715
|
}
|
|
13611
13716
|
}, 1e3);
|
|
13612
13717
|
window.addEventListener("beforeunload", () => {
|
|
@@ -29,9 +29,7 @@
|
|
|
29
29
|
"content_scripts": [
|
|
30
30
|
{
|
|
31
31
|
"matches": [
|
|
32
|
-
"https
|
|
33
|
-
"https://*.zhipin.com/*",
|
|
34
|
-
"https://*.liepin.com/*"
|
|
32
|
+
"https://*/*"
|
|
35
33
|
],
|
|
36
34
|
"js": [
|
|
37
35
|
"content/index.js"
|
|
@@ -45,5 +43,5 @@
|
|
|
45
43
|
"action": {
|
|
46
44
|
"default_title": "__MSG_extActionTitle__"
|
|
47
45
|
},
|
|
48
|
-
"buildTime": "2026-
|
|
46
|
+
"buildTime": "2026-09-01T00:24:44.899Z"
|
|
49
47
|
}
|