deepspider 0.1.0

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 (261) hide show
  1. package/.claude/agents/check.md +122 -0
  2. package/.claude/agents/debug.md +106 -0
  3. package/.claude/agents/dispatch.md +214 -0
  4. package/.claude/agents/implement.md +96 -0
  5. package/.claude/agents/plan.md +396 -0
  6. package/.claude/agents/research.md +120 -0
  7. package/.claude/commands/evolve/merge.md +80 -0
  8. package/.claude/commands/trellis/before-backend-dev.md +13 -0
  9. package/.claude/commands/trellis/before-frontend-dev.md +13 -0
  10. package/.claude/commands/trellis/break-loop.md +107 -0
  11. package/.claude/commands/trellis/check-backend.md +13 -0
  12. package/.claude/commands/trellis/check-cross-layer.md +153 -0
  13. package/.claude/commands/trellis/check-frontend.md +13 -0
  14. package/.claude/commands/trellis/create-command.md +154 -0
  15. package/.claude/commands/trellis/finish-work.md +129 -0
  16. package/.claude/commands/trellis/integrate-skill.md +219 -0
  17. package/.claude/commands/trellis/onboard.md +358 -0
  18. package/.claude/commands/trellis/parallel.md +193 -0
  19. package/.claude/commands/trellis/record-session.md +62 -0
  20. package/.claude/commands/trellis/start.md +280 -0
  21. package/.claude/commands/trellis/update-spec.md +213 -0
  22. package/.claude/hooks/inject-subagent-context.py +758 -0
  23. package/.claude/hooks/ralph-loop.py +374 -0
  24. package/.claude/hooks/session-start.py +126 -0
  25. package/.claude/settings.json +41 -0
  26. package/.claude/skills/deepagents-guide/SKILL.md +428 -0
  27. package/.cursor/commands/trellis-before-backend-dev.md +13 -0
  28. package/.cursor/commands/trellis-before-frontend-dev.md +13 -0
  29. package/.cursor/commands/trellis-break-loop.md +107 -0
  30. package/.cursor/commands/trellis-check-backend.md +13 -0
  31. package/.cursor/commands/trellis-check-cross-layer.md +153 -0
  32. package/.cursor/commands/trellis-check-frontend.md +13 -0
  33. package/.cursor/commands/trellis-create-command.md +154 -0
  34. package/.cursor/commands/trellis-finish-work.md +129 -0
  35. package/.cursor/commands/trellis-integrate-skill.md +219 -0
  36. package/.cursor/commands/trellis-onboard.md +358 -0
  37. package/.cursor/commands/trellis-record-session.md +62 -0
  38. package/.cursor/commands/trellis-start.md +156 -0
  39. package/.cursor/commands/trellis-update-spec.md +213 -0
  40. package/.env.example +11 -0
  41. package/.husky/pre-commit +1 -0
  42. package/.mcp.json +8 -0
  43. package/.trellis/.template-hashes.json +65 -0
  44. package/.trellis/.version +1 -0
  45. package/.trellis/scripts/add-session.sh +384 -0
  46. package/.trellis/scripts/common/developer.sh +129 -0
  47. package/.trellis/scripts/common/git-context.sh +263 -0
  48. package/.trellis/scripts/common/paths.sh +208 -0
  49. package/.trellis/scripts/common/phase.sh +150 -0
  50. package/.trellis/scripts/common/registry.sh +247 -0
  51. package/.trellis/scripts/common/task-queue.sh +142 -0
  52. package/.trellis/scripts/common/task-utils.sh +151 -0
  53. package/.trellis/scripts/common/worktree.sh +128 -0
  54. package/.trellis/scripts/create-bootstrap.sh +299 -0
  55. package/.trellis/scripts/get-context.sh +7 -0
  56. package/.trellis/scripts/get-developer.sh +15 -0
  57. package/.trellis/scripts/init-developer.sh +34 -0
  58. package/.trellis/scripts/multi-agent/cleanup.sh +396 -0
  59. package/.trellis/scripts/multi-agent/create-pr.sh +241 -0
  60. package/.trellis/scripts/multi-agent/plan.sh +207 -0
  61. package/.trellis/scripts/multi-agent/start.sh +310 -0
  62. package/.trellis/scripts/multi-agent/status.sh +828 -0
  63. package/.trellis/scripts/task.sh +1118 -0
  64. package/.trellis/spec/backend/deepagents-guide.md +337 -0
  65. package/.trellis/spec/backend/directory-structure.md +126 -0
  66. package/.trellis/spec/backend/examples/skills/deepagents-guide/README.md +11 -0
  67. package/.trellis/spec/backend/examples/skills/deepagents-guide/agent.js.template +20 -0
  68. package/.trellis/spec/backend/examples/skills/deepagents-guide/skills-config.js.template +13 -0
  69. package/.trellis/spec/backend/examples/skills/deepagents-guide/subagent.js.template +19 -0
  70. package/.trellis/spec/backend/hook-guidelines.md +178 -0
  71. package/.trellis/spec/backend/index.md +36 -0
  72. package/.trellis/spec/backend/quality-guidelines.md +201 -0
  73. package/.trellis/spec/backend/state-management.md +76 -0
  74. package/.trellis/spec/backend/tool-guidelines.md +144 -0
  75. package/.trellis/spec/backend/type-safety.md +71 -0
  76. package/.trellis/spec/guides/code-reuse-thinking-guide.md +92 -0
  77. package/.trellis/spec/guides/cross-layer-thinking-guide.md +94 -0
  78. package/.trellis/spec/guides/index.md +79 -0
  79. package/.trellis/tasks/archive/02-02-evolving-skills/prd.md +61 -0
  80. package/.trellis/tasks/archive/02-02-evolving-skills/task.json +29 -0
  81. package/.trellis/tasks/archive/2026-02/00-bootstrap-guidelines/prd.md +86 -0
  82. package/.trellis/tasks/archive/2026-02/00-bootstrap-guidelines/task.json +27 -0
  83. package/.trellis/tasks/archive/2026-02/02-02-skills-system/check.jsonl +3 -0
  84. package/.trellis/tasks/archive/2026-02/02-02-skills-system/debug.jsonl +2 -0
  85. package/.trellis/tasks/archive/2026-02/02-02-skills-system/implement.jsonl +5 -0
  86. package/.trellis/tasks/archive/2026-02/02-02-skills-system/prd.md +33 -0
  87. package/.trellis/tasks/archive/2026-02/02-02-skills-system/task.json +41 -0
  88. package/.trellis/workflow.md +407 -0
  89. package/.trellis/workspace/index.md +123 -0
  90. package/.trellis/workspace/pony/index.md +40 -0
  91. package/.trellis/workspace/pony/journal-1.md +7 -0
  92. package/.trellis/worktree.yaml +47 -0
  93. package/AGENTS.md +18 -0
  94. package/CLAUDE.md +292 -0
  95. package/README.md +134 -0
  96. package/agents/deepspider.md +142 -0
  97. package/docs/DEBUG.md +42 -0
  98. package/docs/GUIDE.md +334 -0
  99. package/docs/PROMPT.md +60 -0
  100. package/docs/USAGE.md +226 -0
  101. package/eslint.config.js +51 -0
  102. package/package.json +78 -0
  103. package/requirements-crypto.txt +14 -0
  104. package/src/agent/index.js +97 -0
  105. package/src/agent/logger.js +164 -0
  106. package/src/agent/middleware/filterTools.js +64 -0
  107. package/src/agent/middleware/report.js +79 -0
  108. package/src/agent/prompts/system.js +315 -0
  109. package/src/agent/run.js +575 -0
  110. package/src/agent/skills/anti-detect/SKILL.md +28 -0
  111. package/src/agent/skills/anti-detect/evolved.md +12 -0
  112. package/src/agent/skills/captcha/SKILL.md +37 -0
  113. package/src/agent/skills/captcha/evolved.md +12 -0
  114. package/src/agent/skills/config.js +30 -0
  115. package/src/agent/skills/crawler/SKILL.md +9 -0
  116. package/src/agent/skills/crawler/evolved.md +16 -0
  117. package/src/agent/skills/dynamic-analysis/SKILL.md +91 -0
  118. package/src/agent/skills/dynamic-analysis/evolved.md +12 -0
  119. package/src/agent/skills/env/SKILL.md +72 -0
  120. package/src/agent/skills/env/evolved.md +12 -0
  121. package/src/agent/skills/evolve.js +79 -0
  122. package/src/agent/skills/general/SKILL.md +12 -0
  123. package/src/agent/skills/general/evolved.md +12 -0
  124. package/src/agent/skills/js2python/SKILL.md +30 -0
  125. package/src/agent/skills/js2python/evolved.md +13 -0
  126. package/src/agent/skills/report/SKILL.md +21 -0
  127. package/src/agent/skills/report/evolved.md +12 -0
  128. package/src/agent/skills/sandbox/SKILL.md +22 -0
  129. package/src/agent/skills/sandbox/evolved.md +16 -0
  130. package/src/agent/skills/static-analysis/SKILL.md +93 -0
  131. package/src/agent/skills/static-analysis/evolved.md +12 -0
  132. package/src/agent/skills/xpath/SKILL.md +119 -0
  133. package/src/agent/subagents/anti-detect.js +45 -0
  134. package/src/agent/subagents/captcha.js +51 -0
  135. package/src/agent/subagents/crawler.js +138 -0
  136. package/src/agent/subagents/dynamic.js +64 -0
  137. package/src/agent/subagents/env-agent.js +82 -0
  138. package/src/agent/subagents/index.js +37 -0
  139. package/src/agent/subagents/js2python.js +72 -0
  140. package/src/agent/subagents/sandbox.js +55 -0
  141. package/src/agent/subagents/static.js +66 -0
  142. package/src/agent/tools/analysis.js +135 -0
  143. package/src/agent/tools/analyzer.js +85 -0
  144. package/src/agent/tools/anti-detect.js +89 -0
  145. package/src/agent/tools/antidebug.js +64 -0
  146. package/src/agent/tools/async.js +43 -0
  147. package/src/agent/tools/browser.js +324 -0
  148. package/src/agent/tools/captcha.js +223 -0
  149. package/src/agent/tools/capture.js +179 -0
  150. package/src/agent/tools/correlate.js +303 -0
  151. package/src/agent/tools/crawler.js +116 -0
  152. package/src/agent/tools/cryptohook.js +80 -0
  153. package/src/agent/tools/debug.js +246 -0
  154. package/src/agent/tools/deobfuscator.js +90 -0
  155. package/src/agent/tools/env.js +83 -0
  156. package/src/agent/tools/envdump.js +92 -0
  157. package/src/agent/tools/evolve.js +164 -0
  158. package/src/agent/tools/extract.js +114 -0
  159. package/src/agent/tools/extractor.js +54 -0
  160. package/src/agent/tools/file.js +224 -0
  161. package/src/agent/tools/hook.js +84 -0
  162. package/src/agent/tools/hookManager.js +178 -0
  163. package/src/agent/tools/index.js +137 -0
  164. package/src/agent/tools/nodejs.js +101 -0
  165. package/src/agent/tools/patch.js +46 -0
  166. package/src/agent/tools/preprocess.js +71 -0
  167. package/src/agent/tools/profile.js +122 -0
  168. package/src/agent/tools/python.js +627 -0
  169. package/src/agent/tools/report.js +124 -0
  170. package/src/agent/tools/runtime.js +132 -0
  171. package/src/agent/tools/sandbox.js +79 -0
  172. package/src/agent/tools/store.js +73 -0
  173. package/src/agent/tools/trace.js +74 -0
  174. package/src/agent/tools/tracing.js +201 -0
  175. package/src/agent/tools/utils.js +51 -0
  176. package/src/agent/tools/verify.js +184 -0
  177. package/src/agent/tools/webcrack.js +109 -0
  178. package/src/analyzer/ASTAnalyzer.js +387 -0
  179. package/src/analyzer/CallStackAnalyzer.js +379 -0
  180. package/src/analyzer/Deobfuscator.js +289 -0
  181. package/src/analyzer/EncryptionAnalyzer.js +99 -0
  182. package/src/analyzer/index.js +22 -0
  183. package/src/browser/EnvBridge.js +186 -0
  184. package/src/browser/cdp.js +168 -0
  185. package/src/browser/client.js +197 -0
  186. package/src/browser/collector.js +444 -0
  187. package/src/browser/collectors/RequestCryptoLinker.js +109 -0
  188. package/src/browser/collectors/ResponseSearcher.js +107 -0
  189. package/src/browser/collectors/ScriptCollector.js +158 -0
  190. package/src/browser/collectors/index.js +26 -0
  191. package/src/browser/defaultHooks.js +932 -0
  192. package/src/browser/hooks/crypto.js +55 -0
  193. package/src/browser/hooks/index.js +64 -0
  194. package/src/browser/hooks/native.js +9 -0
  195. package/src/browser/hooks/network.js +33 -0
  196. package/src/browser/index.js +42 -0
  197. package/src/browser/interceptors/NetworkInterceptor.js +116 -0
  198. package/src/browser/interceptors/ScriptInterceptor.js +76 -0
  199. package/src/browser/interceptors/index.js +6 -0
  200. package/src/browser/ui/analysisPanel.js +1782 -0
  201. package/src/browser/ui/confirmDialog.js +158 -0
  202. package/src/browser/ui/panel.html +152 -0
  203. package/src/browser/ui/selector.js +170 -0
  204. package/src/config/index.js +5 -0
  205. package/src/config/paths.js +71 -0
  206. package/src/config/patterns/crypto.js +36 -0
  207. package/src/config/profiles/chrome.json +71 -0
  208. package/src/config/profiles/firefox.json +44 -0
  209. package/src/config/profiles/safari.json +38 -0
  210. package/src/core/EnvMonitor.js +200 -0
  211. package/src/core/PatchGenerator.js +278 -0
  212. package/src/core/Sandbox.js +181 -0
  213. package/src/env/AntiAntiDebug.js +111 -0
  214. package/src/env/AsyncHook.js +68 -0
  215. package/src/env/BrowserAPIList.js +265 -0
  216. package/src/env/CookieHook.js +48 -0
  217. package/src/env/CryptoHook.js +205 -0
  218. package/src/env/EnvCodeGenerator.js +157 -0
  219. package/src/env/EnvDumper.js +356 -0
  220. package/src/env/EnvExtractor.js +220 -0
  221. package/src/env/HookBase.js +618 -0
  222. package/src/env/NetworkHook.js +159 -0
  223. package/src/env/modules/bom/history.js +29 -0
  224. package/src/env/modules/bom/location.js +26 -0
  225. package/src/env/modules/bom/navigator.js +70 -0
  226. package/src/env/modules/bom/screen.js +26 -0
  227. package/src/env/modules/bom/storage.js +23 -0
  228. package/src/env/modules/dom/document.js +110 -0
  229. package/src/env/modules/dom/event.js +51 -0
  230. package/src/env/modules/index.js +34 -0
  231. package/src/env/modules/webapi/fetch.js +46 -0
  232. package/src/env/modules/webapi/url.js +47 -0
  233. package/src/env/modules/webapi/xhr.js +48 -0
  234. package/src/index.js +27 -0
  235. package/src/mcp/server.js +89 -0
  236. package/src/store/DataStore.js +708 -0
  237. package/src/store/Store.js +158 -0
  238. package/src/store/Validator.js +24 -0
  239. package/test/analyze.test.js +90 -0
  240. package/test/envdump.test.js +74 -0
  241. package/test/flow.test.js +90 -0
  242. package/test/hooks.test.js +138 -0
  243. package/test/plugin.test.js +35 -0
  244. package/test/refactor-full.test.js +30 -0
  245. package/test/refactor.test.js +21 -0
  246. package/test/samples/obfuscated.js +61 -0
  247. package/test/samples/original.js +66 -0
  248. package/test/samples/v10_eval_chain.js +52 -0
  249. package/test/samples/v11_bytecode_vm.js +81 -0
  250. package/test/samples/v12_polymorphic.js +69 -0
  251. package/test/samples/v1_ob_basic.js +98 -0
  252. package/test/samples/v2_ob_advanced.js +99 -0
  253. package/test/samples/v3_jjencode.js +77 -0
  254. package/test/samples/v4_aaencode.js +73 -0
  255. package/test/samples/v5_control_flow.js +86 -0
  256. package/test/samples/v6_string_encryption.js +71 -0
  257. package/test/samples/v7_jsvmp.js +83 -0
  258. package/test/samples/v8_anti_debug.js +79 -0
  259. package/test/samples/v9_proxy_trap.js +49 -0
  260. package/test/samples.test.js +96 -0
  261. package/test/webcrack.test.js +55 -0
@@ -0,0 +1,99 @@
1
+ /**
2
+ * DeepSpider - 加密分析器
3
+ * 算法识别、参数追踪、密钥提取
4
+ */
5
+
6
+ import { ASTAnalyzer } from './ASTAnalyzer.js';
7
+ import { cryptoPatterns } from '../config/patterns/crypto.js';
8
+
9
+ export class EncryptionAnalyzer {
10
+ constructor() {
11
+ this.astAnalyzer = new ASTAnalyzer();
12
+ this.cryptoPatterns = [
13
+ { name: 'MD5', pattern: /md5|MD5/, type: 'hash' },
14
+ { name: 'SHA1', pattern: /sha1|SHA1/, type: 'hash' },
15
+ { name: 'SHA256', pattern: /sha256|SHA256/, type: 'hash' },
16
+ { name: 'AES', pattern: /\baes\b|AES|CryptoJS\.AES/, type: 'symmetric' },
17
+ { name: 'DES', pattern: /\bdes\b|DES|CryptoJS\.DES/, type: 'symmetric' },
18
+ { name: 'Base64', pattern: /btoa|atob|base64/i, type: 'encoding' },
19
+ { name: 'RSA', pattern: /\brsa\b|RSA|JSEncrypt/, type: 'asymmetric' },
20
+ { name: 'HMAC', pattern: /hmac|HMAC/, type: 'mac' }
21
+ ];
22
+ }
23
+
24
+ analyze(code) {
25
+ const functions = this.astAnalyzer.extractFunctions(code);
26
+ const calls = this.astAnalyzer.extractCalls(code);
27
+ const detected = [];
28
+
29
+ // 检测加密模式
30
+ for (const p of this.cryptoPatterns) {
31
+ if (p.pattern.test(code)) {
32
+ detected.push({ name: p.name, type: p.type });
33
+ }
34
+ }
35
+
36
+ // 查找可疑的加密函数
37
+ const suspiciousFuncs = functions.filter(f =>
38
+ /encrypt|decrypt|sign|hash|encode|decode|cipher/i.test(f.name)
39
+ );
40
+
41
+ // 查找密钥相关变量
42
+ const keys = this._findKeys(code);
43
+
44
+ return {
45
+ detectedAlgorithms: detected,
46
+ suspiciousFunctions: suspiciousFuncs,
47
+ possibleKeys: keys,
48
+ totalFunctions: functions.length,
49
+ totalCalls: calls.length
50
+ };
51
+ }
52
+
53
+ traceParam(code, paramName) {
54
+ const ast = this.astAnalyzer.parse(code);
55
+ const traces = [];
56
+
57
+ // 简化实现:查找参数使用位置
58
+ const regex = new RegExp(`\\b${paramName}\\b`, 'g');
59
+ let match;
60
+ while ((match = regex.exec(code)) !== null) {
61
+ traces.push({ position: match.index });
62
+ }
63
+
64
+ return { param: paramName, traces };
65
+ }
66
+
67
+ _findKeys(code) {
68
+ const keys = [];
69
+ const keyPattern = /(?:key|secret|password|iv|salt)\s*[=:]\s*['"]([^'"]+)['"]/gi;
70
+ let match;
71
+ while ((match = keyPattern.exec(code)) !== null) {
72
+ keys.push({
73
+ value: match[1],
74
+ position: match.index
75
+ });
76
+ }
77
+ return keys;
78
+ }
79
+
80
+ // 使用模式库进行深度检测
81
+ detectWithPatterns(code) {
82
+ const detected = [];
83
+ for (const [key, pattern] of Object.entries(cryptoPatterns)) {
84
+ for (const sig of pattern.signatures) {
85
+ if (sig.test(code)) {
86
+ detected.push({
87
+ algorithm: pattern.name,
88
+ type: pattern.type,
89
+ confidence: 0.9
90
+ });
91
+ break;
92
+ }
93
+ }
94
+ }
95
+ return detected;
96
+ }
97
+ }
98
+
99
+ export default EncryptionAnalyzer;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * DeepSpider - 分析器注册表
3
+ */
4
+
5
+ import { ASTAnalyzer } from './ASTAnalyzer.js';
6
+ import { CallStackAnalyzer } from './CallStackAnalyzer.js';
7
+ import { EncryptionAnalyzer } from './EncryptionAnalyzer.js';
8
+ import { Deobfuscator } from './Deobfuscator.js';
9
+
10
+ export const analyzers = {
11
+ ast: ASTAnalyzer,
12
+ callstack: CallStackAnalyzer,
13
+ encryption: EncryptionAnalyzer,
14
+ deobfuscator: Deobfuscator
15
+ };
16
+
17
+ export function getAnalyzer(name) {
18
+ const Analyzer = analyzers[name];
19
+ return Analyzer ? new Analyzer() : null;
20
+ }
21
+
22
+ export default analyzers;
@@ -0,0 +1,186 @@
1
+ /**
2
+ * DeepSpider - 环境补全桥接器
3
+ * 连接 EnvDumper(发现缺失)与 EnvCollector(采集真实数据)
4
+ */
5
+
6
+ import { EnvCollector } from './collector.js';
7
+ import { PatchGenerator } from '../core/PatchGenerator.js';
8
+
9
+ export class EnvBridge {
10
+ constructor(page) {
11
+ this.collector = new EnvCollector(page);
12
+ this.patchGenerator = new PatchGenerator();
13
+ this.collectedData = new Map();
14
+ }
15
+
16
+ /**
17
+ * 根据缺失列表自动采集并生成补丁
18
+ * @param {string[]} missingPaths - EnvDumper 发现的缺失属性路径
19
+ */
20
+ async autoFix(missingPaths) {
21
+ const results = {
22
+ collected: [],
23
+ patched: [],
24
+ failed: []
25
+ };
26
+
27
+ for (const path of missingPaths) {
28
+ try {
29
+ // 1. 从真实浏览器采集
30
+ const collected = await this.collector.collect(path, { depth: 2 });
31
+
32
+ if (!collected.success) {
33
+ results.failed.push({ path, reason: 'collect_failed', error: collected.error });
34
+ continue;
35
+ }
36
+
37
+ results.collected.push(path);
38
+ this.collectedData.set(path, collected);
39
+
40
+ // 2. 生成补丁代码
41
+ const patch = this._generatePatch(path, collected);
42
+ if (patch) {
43
+ results.patched.push({ path, code: patch });
44
+ }
45
+
46
+ } catch (e) {
47
+ results.failed.push({ path, reason: 'error', error: e.message });
48
+ }
49
+ }
50
+
51
+ return results;
52
+ }
53
+
54
+ /**
55
+ * 根据采集数据生成补丁代码
56
+ */
57
+ _generatePatch(path, collected) {
58
+ const { data, descriptor } = collected;
59
+
60
+ if (!data) return null;
61
+
62
+ const parts = path.split('.');
63
+ const propName = parts.pop();
64
+ const parentPath = parts.join('.') || 'window';
65
+
66
+ // 根据数据类型生成不同的补丁
67
+ switch (data.type) {
68
+ case 'string':
69
+ return `${parentPath}.${propName} = "${data.value}";`;
70
+
71
+ case 'number':
72
+ return `${parentPath}.${propName} = ${data.value};`;
73
+
74
+ case 'boolean':
75
+ return `${parentPath}.${propName} = ${data.value};`;
76
+
77
+ case 'array':
78
+ return `${parentPath}.${propName} = ${JSON.stringify(
79
+ data.value.map(v => v.value)
80
+ )};`;
81
+
82
+ case 'object':
83
+ if (descriptor?.hasGetter) {
84
+ // 有 getter 的属性用 defineProperty
85
+ return this._generateDefineProperty(parentPath, propName, data);
86
+ }
87
+ return this._generateObjectPatch(parentPath, propName, data);
88
+
89
+ case 'function':
90
+ return `${parentPath}.${propName} = function ${data.name || ''}() {};`;
91
+
92
+ default:
93
+ return `${parentPath}.${propName} = undefined;`;
94
+ }
95
+ }
96
+
97
+ _generateDefineProperty(parentPath, propName, data) {
98
+ const value = this._serializeValue(data);
99
+ return `Object.defineProperty(${parentPath}, "${propName}", {
100
+ get: function() { return ${value}; },
101
+ configurable: true
102
+ });`;
103
+ }
104
+
105
+ _generateObjectPatch(parentPath, propName, data) {
106
+ if (!data.properties) {
107
+ return `${parentPath}.${propName} = {};`;
108
+ }
109
+
110
+ const props = [];
111
+ for (const [key, val] of Object.entries(data.properties)) {
112
+ if (val.type === 'function') {
113
+ props.push(`${key}: function() {}`);
114
+ } else if (val.type === 'object') {
115
+ props.push(`${key}: {}`);
116
+ } else {
117
+ props.push(`${key}: ${this._serializeValue(val)}`);
118
+ }
119
+ }
120
+
121
+ return `${parentPath}.${propName} = { ${props.join(', ')} };`;
122
+ }
123
+
124
+ _serializeValue(data) {
125
+ switch (data.type) {
126
+ case 'string': return `"${data.value}"`;
127
+ case 'number': return data.value;
128
+ case 'boolean': return data.value;
129
+ case 'null': return 'null';
130
+ case 'undefined': return 'undefined';
131
+ case 'array': return JSON.stringify(data.value?.map(v => v.value) || []);
132
+ default: return '{}';
133
+ }
134
+ }
135
+
136
+ /**
137
+ * 生成合并后的完整补丁代码
138
+ */
139
+ generateMergedPatch(patches) {
140
+ const grouped = new Map();
141
+
142
+ for (const { path, code } of patches) {
143
+ const root = path.split('.')[0];
144
+ if (!grouped.has(root)) {
145
+ grouped.set(root, []);
146
+ }
147
+ grouped.get(root).push(code);
148
+ }
149
+
150
+ const lines = ['// DeepSpider Auto-Generated Patch'];
151
+ for (const [root, codes] of grouped) {
152
+ lines.push(`\n// === ${root} ===`);
153
+ lines.push(...codes);
154
+ }
155
+
156
+ return lines.join('\n');
157
+ }
158
+
159
+ /**
160
+ * 完整的补环境流程
161
+ */
162
+ async runFullPipeline(missingPaths) {
163
+ console.log(`[DeepSpider:bridge] 开始补环境,共 ${missingPaths.length} 个缺失属性`);
164
+
165
+ // 1. 采集并生成补丁
166
+ const result = await this.autoFix(missingPaths);
167
+
168
+ // 2. 合并补丁
169
+ const mergedCode = this.generateMergedPatch(result.patched);
170
+
171
+ // 3. 返回结果
172
+ return {
173
+ success: result.failed.length === 0,
174
+ stats: {
175
+ total: missingPaths.length,
176
+ collected: result.collected.length,
177
+ patched: result.patched.length,
178
+ failed: result.failed.length
179
+ },
180
+ patchCode: mergedCode,
181
+ failed: result.failed
182
+ };
183
+ }
184
+ }
185
+
186
+ export default EnvBridge;
@@ -0,0 +1,168 @@
1
+ /**
2
+ * DeepSpider - CDP 会话管理
3
+ * 封装 Chrome DevTools Protocol 操作
4
+ */
5
+
6
+ export class CDPSession {
7
+ constructor(client) {
8
+ this.client = client;
9
+ this.breakpoints = new Map();
10
+ this.scriptSources = new Map();
11
+ this.pausedHandler = null;
12
+ }
13
+
14
+ /**
15
+ * 从 BrowserClient 创建 CDP 会话
16
+ */
17
+ static async fromBrowser(browserClient) {
18
+ const client = await browserClient.getCDPSession();
19
+ const session = new CDPSession(client);
20
+ await session.enable();
21
+ return session;
22
+ }
23
+
24
+ /**
25
+ * 启用必要的 CDP 域
26
+ */
27
+ async enable() {
28
+ await Promise.all([
29
+ this.client.send('Debugger.enable'),
30
+ this.client.send('Runtime.enable'),
31
+ this.client.send('Page.enable'),
32
+ this.client.send('Network.enable'),
33
+ ]);
34
+
35
+ // 设置异步调用栈深度
36
+ await this.client.send('Debugger.setAsyncCallStackDepth', { maxDepth: 32 });
37
+
38
+ // 监听脚本解析事件
39
+ this.client.on('Debugger.scriptParsed', (event) => {
40
+ if (event.url) {
41
+ this.scriptSources.set(event.scriptId, event.url);
42
+ }
43
+ });
44
+ }
45
+
46
+ /**
47
+ * 设置断点
48
+ */
49
+ async setBreakpoint(url, lineNumber, columnNumber = 0) {
50
+ const result = await this.client.send('Debugger.setBreakpointByUrl', {
51
+ url,
52
+ lineNumber,
53
+ columnNumber,
54
+ });
55
+ if (result.breakpointId) {
56
+ this.breakpoints.set(result.breakpointId, { url, lineNumber, columnNumber });
57
+ }
58
+ return result;
59
+ }
60
+
61
+ /**
62
+ * 移除断点
63
+ */
64
+ async removeBreakpoint(breakpointId) {
65
+ await this.client.send('Debugger.removeBreakpoint', { breakpointId });
66
+ this.breakpoints.delete(breakpointId);
67
+ }
68
+
69
+ /**
70
+ * 设置 XHR 断点
71
+ */
72
+ async setXHRBreakpoint(urlPattern = '') {
73
+ await this.client.send('DOMDebugger.setXHRBreakpoint', { url: urlPattern });
74
+ }
75
+
76
+ /**
77
+ * 恢复执行
78
+ */
79
+ async resume() {
80
+ await this.client.send('Debugger.resume');
81
+ }
82
+
83
+ /**
84
+ * 单步执行
85
+ */
86
+ async stepOver() {
87
+ await this.client.send('Debugger.stepOver');
88
+ }
89
+
90
+ async stepInto() {
91
+ await this.client.send('Debugger.stepInto');
92
+ }
93
+
94
+ async stepOut() {
95
+ await this.client.send('Debugger.stepOut');
96
+ }
97
+
98
+ /**
99
+ * 获取脚本源码
100
+ */
101
+ async getScriptSource(scriptId) {
102
+ const result = await this.client.send('Debugger.getScriptSource', { scriptId });
103
+ return result.scriptSource;
104
+ }
105
+
106
+ /**
107
+ * 获取作用域变量
108
+ */
109
+ async getScopeVariables(callFrameId) {
110
+ const result = await this.client.send('Debugger.evaluateOnCallFrame', {
111
+ callFrameId,
112
+ expression: 'JSON.stringify(Object.keys(this))',
113
+ returnByValue: true,
114
+ });
115
+ return result;
116
+ }
117
+
118
+ /**
119
+ * 在调用帧上执行表达式
120
+ */
121
+ async evaluate(callFrameId, expression) {
122
+ const result = await this.client.send('Debugger.evaluateOnCallFrame', {
123
+ callFrameId,
124
+ expression,
125
+ returnByValue: true,
126
+ });
127
+ return result.result?.value;
128
+ }
129
+
130
+ /**
131
+ * 监听断点暂停事件
132
+ */
133
+ onPaused(handler) {
134
+ this.pausedHandler = handler;
135
+ this.client.on('Debugger.paused', handler);
136
+ }
137
+
138
+ /**
139
+ * 移除暂停监听
140
+ */
141
+ offPaused() {
142
+ if (this.pausedHandler) {
143
+ this.client.off('Debugger.paused', this.pausedHandler);
144
+ this.pausedHandler = null;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * 发送 CDP 命令(代理到 client)
150
+ */
151
+ send(method, params = {}) {
152
+ return this.client.send(method, params);
153
+ }
154
+
155
+ /**
156
+ * 监听 CDP 事件(代理到 client)
157
+ */
158
+ on(event, handler) {
159
+ return this.client.on(event, handler);
160
+ }
161
+
162
+ /**
163
+ * 移除 CDP 事件监听(代理到 client)
164
+ */
165
+ off(event, handler) {
166
+ return this.client.off(event, handler);
167
+ }
168
+ }
@@ -0,0 +1,197 @@
1
+ /**
2
+ * DeepSpider - Patchright 浏览器客户端
3
+ * 使用反检测版 Playwright
4
+ */
5
+
6
+ import { chromium } from 'patchright';
7
+ import { getDefaultHookScript } from './defaultHooks.js';
8
+ import { NetworkInterceptor } from './interceptors/NetworkInterceptor.js';
9
+ import { ScriptInterceptor } from './interceptors/ScriptInterceptor.js';
10
+ import { getDataStore } from '../store/DataStore.js';
11
+
12
+ export class BrowserClient {
13
+ constructor() {
14
+ this.browser = null;
15
+ this.context = null;
16
+ this.page = null;
17
+ this.pages = [];
18
+ this.cdpSession = null;
19
+ this.networkInterceptor = null;
20
+ this.scriptInterceptor = null;
21
+ this.hookScript = null;
22
+ this.onMessage = null;
23
+ }
24
+
25
+ /**
26
+ * 启动浏览器
27
+ */
28
+ async launch(options = {}) {
29
+ // 启动新会话
30
+ const dataStore = getDataStore();
31
+ dataStore.startSession();
32
+
33
+ const {
34
+ headless = false,
35
+ executablePath = null,
36
+ args = [],
37
+ } = options;
38
+
39
+ const launchOptions = {
40
+ headless,
41
+ args: [
42
+ '--disable-blink-features=AutomationControlled',
43
+ '--disable-web-security',
44
+ '--ignore-certificate-errors',
45
+ ...args,
46
+ ],
47
+ };
48
+
49
+ if (executablePath) {
50
+ launchOptions.executablePath = executablePath;
51
+ }
52
+
53
+ this.browser = await chromium.launch(launchOptions);
54
+ this.context = await this.browser.newContext({
55
+ ignoreHTTPSErrors: true,
56
+ });
57
+
58
+ // 保存 hook 脚本
59
+ this.hookScript = getDefaultHookScript();
60
+
61
+ // 使用 addInitScript 在 context 级别注入
62
+ await this.context.addInitScript(this.hookScript);
63
+
64
+ this.page = await this.context.newPage();
65
+
66
+ // 监听新页面创建(弹窗、新标签页)
67
+ this.context.on('page', async (newPage) => {
68
+ console.log('[BrowserClient] 检测到新页面');
69
+ this.pages.push(newPage);
70
+ this.page = newPage; // 切换到新页面
71
+ await this.setupPage(newPage);
72
+
73
+ // 监听页面关闭
74
+ newPage.on('close', () => {
75
+ this.pages = this.pages.filter(p => p !== newPage);
76
+ if (this.page === newPage && this.pages.length > 0) {
77
+ this.page = this.pages[this.pages.length - 1];
78
+ }
79
+ });
80
+ });
81
+
82
+ // 设置当前页面
83
+ this.pages.push(this.page);
84
+ await this.setupPage(this.page);
85
+
86
+ return this;
87
+ }
88
+
89
+ /**
90
+ * 设置页面(CDP 拦截器 + 消息绑定)
91
+ */
92
+ async setupPage(page) {
93
+ try {
94
+ const cdp = await page.context().newCDPSession(page);
95
+
96
+ // 1. 启用 Runtime 域
97
+ await cdp.send('Runtime.enable');
98
+
99
+ // 2. 添加 CDP binding(前端调用此函数,后端接收)
100
+ await cdp.send('Runtime.addBinding', { name: '__deepspider_send__' });
101
+
102
+ // 3. 监听 binding 调用
103
+ cdp.on('Runtime.bindingCalled', (event) => {
104
+ if (event.name === '__deepspider_send__') {
105
+ try {
106
+ const data = JSON.parse(event.payload);
107
+ console.log('[BrowserClient] 收到消息:', data.type);
108
+ if (this.onMessage) {
109
+ this.onMessage(data, page);
110
+ }
111
+ } catch (e) {
112
+ console.error('[BrowserClient] 解析消息失败:', e.message);
113
+ }
114
+ }
115
+ });
116
+
117
+ // 4. 启动拦截器
118
+ const networkInterceptor = new NetworkInterceptor(cdp, page);
119
+ const scriptInterceptor = new ScriptInterceptor(cdp, page);
120
+ await networkInterceptor.start();
121
+ await scriptInterceptor.start();
122
+
123
+ // 保存引用
124
+ if (page === this.page) {
125
+ this.cdpSession = cdp;
126
+ this.networkInterceptor = networkInterceptor;
127
+ this.scriptInterceptor = scriptInterceptor;
128
+ }
129
+
130
+ // 监听页面导航
131
+ page.on('framenavigated', (frame) => {
132
+ if (frame === page.mainFrame()) {
133
+ console.log('[BrowserClient] 页面导航到:', frame.url());
134
+ }
135
+ });
136
+
137
+ console.log('[BrowserClient] 页面已设置:', page.url() || '(空白页)');
138
+ } catch (e) {
139
+ console.error('[BrowserClient] 设置页面失败:', e.message);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * 获取 CDP 会话(始终使用当前页面的 session)
145
+ */
146
+ async getCDPSession() {
147
+ // 每次都为当前页面创建新的 CDP session,确保上下文正确
148
+ if (this.page) {
149
+ try {
150
+ this.cdpSession = await this.page.context().newCDPSession(this.page);
151
+ } catch (e) {
152
+ console.error('[BrowserClient] 创建 CDP session 失败:', e.message);
153
+ return null;
154
+ }
155
+ }
156
+ return this.cdpSession;
157
+ }
158
+
159
+ /**
160
+ * 导航到 URL
161
+ */
162
+ async navigate(url, options = {}) {
163
+ const { waitUntil = 'domcontentloaded' } = options;
164
+ await this.page.goto(url, { waitUntil });
165
+ return this.page.url();
166
+ }
167
+
168
+ /**
169
+ * 获取当前页面
170
+ */
171
+ getPage() {
172
+ return this.page;
173
+ }
174
+
175
+ /**
176
+ * 获取浏览器上下文
177
+ */
178
+ getContext() {
179
+ return this.context;
180
+ }
181
+
182
+ /**
183
+ * 关闭浏览器
184
+ */
185
+ async close() {
186
+ if (this.cdpSession) {
187
+ await this.cdpSession.detach().catch(() => {});
188
+ this.cdpSession = null;
189
+ }
190
+ if (this.browser) {
191
+ await this.browser.close();
192
+ this.browser = null;
193
+ this.context = null;
194
+ this.page = null;
195
+ }
196
+ }
197
+ }