-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathdetect-ai.js
More file actions
127 lines (109 loc) · 3.9 KB
/
Copy pathdetect-ai.js
File metadata and controls
127 lines (109 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { ResourceManager } from "./shared/shared-resource-manager.js";
import {
ensureProviderOptions,
handleApiKeyToggle,
handleProviderChange,
loadAIConfig,
persistAIConfig,
} from "./detect/ai-config.js";
import { getAiElements, setAIStatus } from "./detect/ai-shared.js";
import {
isChatContextStale,
resetAISession,
sendFollowupMessage,
startAIDiagnosis,
stopAIRequest,
updateAIControls,
} from "./detect/ai-session.js";
import { exportChatAsMarkdown, exportStructuredSnapshotAsMarkdown, renderChatPlaceholder } from "./detect/ai-ui.js";
import "./detect.js";
import "./toggle.js";
const sanitizeSnapshotForAI = (snapshot) => {
if (!snapshot) {
return snapshot;
}
const sanitized = JSON.parse(JSON.stringify(snapshot));
if (sanitized.http) {
sanitized.http.headers = {
redacted: true,
headerNames: Object.keys(snapshot.http?.headers || {}),
};
}
if (sanitized.webrtc) {
sanitized.webrtc.ips = Array.isArray(snapshot.webrtc?.ips) ? snapshot.webrtc.ips.map(() => "[redacted]") : [];
}
if (sanitized.browserFingerprint) {
sanitized.browserFingerprint.userAgent = "[redacted]";
}
// UA 字符串同等敏感:保留浏览器名/版本/OS,删除完整 UA
if (sanitized.compatibility?.browser) {
sanitized.compatibility.browser.userAgent = "[redacted]";
}
// UA-CH 高熵值与 User Agent 同等敏感:仅保留移动端布尔标志
if (sanitized.compatibility?.uaData) {
sanitized.compatibility.uaData = {
redacted: true,
mobile: !!snapshot.compatibility.uaData.mobile,
};
}
if (sanitized.hardwareFingerprint?.canvas) {
sanitized.hardwareFingerprint.canvas.hash = "[redacted]";
}
if (sanitized.hardwareFingerprint?.webgl) {
sanitized.hardwareFingerprint.webgl.hash = "[redacted]";
sanitized.hardwareFingerprint.webgl.vendor = "[redacted]";
sanitized.hardwareFingerprint.webgl.renderer = "[redacted]";
}
if (sanitized.hardwareFingerprint?.audio) {
sanitized.hardwareFingerprint.audio.hash = "[redacted]";
}
return sanitized;
};
const bindConfigPersistence = () => {
const elements = getAiElements();
[elements.baseUrlInput, elements.apiKeyInput, elements.modelInput].forEach((input) => {
ResourceManager.addEventListener(input, "change", async () => {
await persistAIConfig();
updateAIControls();
});
});
};
const initializeAIUi = async () => {
const elements = getAiElements();
ensureProviderOptions(elements.providerSelect);
renderChatPlaceholder();
await loadAIConfig();
updateAIControls();
ResourceManager.addEventListener(elements.providerSelect, "change", async () => {
await handleProviderChange();
updateAIControls();
});
ResourceManager.addEventListener(elements.apiKeyToggle, "click", handleApiKeyToggle);
ResourceManager.addEventListener(elements.startButton, "click", () => startAIDiagnosis(sanitizeSnapshotForAI));
ResourceManager.addEventListener(elements.stopButton, "click", stopAIRequest);
ResourceManager.addEventListener(elements.clearButton, "click", () => resetAISession());
ResourceManager.addEventListener(elements.exportStructuredButton, "click", () =>
exportStructuredSnapshotAsMarkdown(sanitizeSnapshotForAI),
);
ResourceManager.addEventListener(elements.sendButton, "click", () => sendFollowupMessage(sanitizeSnapshotForAI));
ResourceManager.addEventListener(elements.exportButton, "click", exportChatAsMarkdown);
ResourceManager.addEventListener(elements.userInput, "keydown", (event) => {
if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
event.preventDefault();
sendFollowupMessage(sanitizeSnapshotForAI);
}
});
bindConfigPersistence();
};
ResourceManager.addEventListener(window, "detect:snapshot-updated", () => {
if (isChatContextStale()) {
setAIStatus("ai_session_expired", "warning");
}
updateAIControls();
});
ResourceManager.addEventListener(window, "detect:run-finished", () => {
updateAIControls();
});
ResourceManager.addEventListener(window, "DOMContentLoaded", () => {
initializeAIUi();
});