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,114 @@
1
+ /**
2
+ * DeepSpider - 浏览器环境提取工具
3
+ */
4
+
5
+ import { z } from 'zod';
6
+ import { tool } from '@langchain/core/tools';
7
+ import { EnvExtractor } from '../../env/EnvExtractor.js';
8
+
9
+ const extractor = new EnvExtractor();
10
+
11
+ /**
12
+ * 生成环境提取脚本
13
+ */
14
+ export const generateExtractScript = tool(
15
+ async ({ objPath, includeProto }) => {
16
+ const script = extractor.generateExtractScript(objPath, { includeProto });
17
+ return JSON.stringify({
18
+ success: true,
19
+ objPath,
20
+ script,
21
+ usage: '在浏览器控制台或通过 browser_evaluate 执行此脚本',
22
+ }, null, 2);
23
+ },
24
+ {
25
+ name: 'generate_extract_script',
26
+ description: '生成从浏览器提取指定对象环境的脚本代码',
27
+ schema: z.object({
28
+ objPath: z.string().describe('要提取的对象路径,如 navigator, screen.__proto__'),
29
+ includeProto: z.boolean().default(true).describe('是否包含原型链属性'),
30
+ }),
31
+ }
32
+ );
33
+
34
+ /**
35
+ * 生成批量提取脚本
36
+ */
37
+ export const generateBatchExtractScript = tool(
38
+ async ({ objPaths }) => {
39
+ const script = extractor.generateBatchExtractScript(objPaths);
40
+ return JSON.stringify({
41
+ success: true,
42
+ targets: objPaths,
43
+ script,
44
+ }, null, 2);
45
+ },
46
+ {
47
+ name: 'generate_batch_extract_script',
48
+ description: '生成批量提取多个对象环境的脚本',
49
+ schema: z.object({
50
+ objPaths: z.array(z.string()).describe('要提取的对象路径列表'),
51
+ }),
52
+ }
53
+ );
54
+
55
+ /**
56
+ * 将提取结果转换为补丁代码
57
+ */
58
+ export const convertToPatchCode = tool(
59
+ async ({ extractResult, objPath }) => {
60
+ const patchCode = extractor.generatePatchCode(extractResult, objPath);
61
+ const patchType = extractor.classifyPatch(objPath);
62
+
63
+ return JSON.stringify({
64
+ success: true,
65
+ objPath,
66
+ patchType,
67
+ patchCode,
68
+ suggestion: patchType === 'universal'
69
+ ? '建议持久化到通用环境库'
70
+ : '建议按需使用',
71
+ }, null, 2);
72
+ },
73
+ {
74
+ name: 'convert_to_patch_code',
75
+ description: '将浏览器提取的环境数据转换为可注入的补丁代码',
76
+ schema: z.object({
77
+ extractResult: z.string().describe('浏览器执行提取脚本返回的 JSON'),
78
+ objPath: z.string().describe('对象路径'),
79
+ }),
80
+ }
81
+ );
82
+
83
+ /**
84
+ * 分类补丁类型
85
+ */
86
+ export const classifyPatch = tool(
87
+ async ({ objPath }) => {
88
+ const patchType = extractor.classifyPatch(objPath);
89
+ return JSON.stringify({
90
+ objPath,
91
+ type: patchType,
92
+ description: {
93
+ 'universal': '通用环境,建议持久化',
94
+ 'browser-chrome': 'Chrome 特有,按浏览器存储',
95
+ 'browser-firefox': 'Firefox 特有,按浏览器存储',
96
+ 'site-specific': '网站特定,按域名存储',
97
+ }[patchType] || '未知类型',
98
+ }, null, 2);
99
+ },
100
+ {
101
+ name: 'classify_patch',
102
+ description: '判断补丁的类型(通用/浏览器特定/网站特定)',
103
+ schema: z.object({
104
+ objPath: z.string().describe('对象路径'),
105
+ }),
106
+ }
107
+ );
108
+
109
+ export const extractTools = [
110
+ generateExtractScript,
111
+ generateBatchExtractScript,
112
+ convertToPatchCode,
113
+ classifyPatch,
114
+ ];
@@ -0,0 +1,54 @@
1
+ /**
2
+ * DeepSpider - 代码提取辅助工具
3
+ * 提供信息辅助 AI 进行代码提取
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import { tool } from '@langchain/core/tools';
8
+ import { ASTAnalyzer } from '../../analyzer/ASTAnalyzer.js';
9
+
10
+ const astAnalyzer = new ASTAnalyzer();
11
+
12
+ /**
13
+ * 获取函数列表
14
+ */
15
+ export const listFunctions = tool(
16
+ async ({ code }) => {
17
+ const functions = astAnalyzer.extractFunctions(code);
18
+ return JSON.stringify({
19
+ count: functions.length,
20
+ functions: functions.slice(0, 50),
21
+ }, null, 2);
22
+ },
23
+ {
24
+ name: 'list_functions',
25
+ description: '列出代码中的所有函数,辅助定位目标函数',
26
+ schema: z.object({
27
+ code: z.string().describe('源代码'),
28
+ }),
29
+ }
30
+ );
31
+
32
+ /**
33
+ * 获取函数代码片段
34
+ */
35
+ export const getFunctionCode = tool(
36
+ async ({ code, funcName }) => {
37
+ const slice = astAnalyzer.extractSlice(code, funcName);
38
+ return JSON.stringify({
39
+ funcName,
40
+ found: !!slice,
41
+ code: slice || '未找到该函数',
42
+ }, null, 2);
43
+ },
44
+ {
45
+ name: 'get_function_code',
46
+ description: '获取指定函数的代码片段',
47
+ schema: z.object({
48
+ code: z.string().describe('源代码'),
49
+ funcName: z.string().describe('函数名'),
50
+ }),
51
+ }
52
+ );
53
+
54
+ export const extractorTools = [listFunctions, getFunctionCode];
@@ -0,0 +1,224 @@
1
+ /**
2
+ * DeepSpider - 文件操作工具
3
+ * 统一存储到 ~/.deepspider/output/
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import { tool } from '@langchain/core/tools';
8
+ import { writeFileSync, readFileSync, existsSync, readdirSync, statSync } from 'fs';
9
+ import { dirname, join, isAbsolute, relative } from 'path';
10
+ import { PATHS, ensureDir, DEEPSPIDER_HOME } from '../../config/paths.js';
11
+
12
+ const OUTPUT_DIR = PATHS.OUTPUT_DIR;
13
+
14
+ function ensureFileDir(filePath) {
15
+ const dir = dirname(filePath);
16
+ ensureDir(dir);
17
+ }
18
+
19
+ function getSafePath(filePath) {
20
+ if (isAbsolute(filePath)) {
21
+ // 如果是 ~/.deepspider/ 目录下的路径,直接使用
22
+ if (filePath.startsWith(DEEPSPIDER_HOME)) {
23
+ return filePath;
24
+ }
25
+ // 其他绝对路径:放到 OUTPUT_DIR 下
26
+ return join(OUTPUT_DIR, filePath.replace(/^\/+/, ''));
27
+ }
28
+ return join(OUTPUT_DIR, filePath);
29
+ }
30
+
31
+ export const artifactSave = tool(
32
+ async ({ file_path, content }) => {
33
+ try {
34
+ const safePath = getSafePath(file_path);
35
+ ensureFileDir(safePath);
36
+ writeFileSync(safePath, content, 'utf-8');
37
+ console.log('[artifact_save] 已保存:', safePath);
38
+ return JSON.stringify({ success: true, path: safePath, size: content.length });
39
+ } catch (e) {
40
+ return JSON.stringify({ success: false, error: e.message });
41
+ }
42
+ },
43
+ {
44
+ name: 'artifact_save',
45
+ description: '保存逆向分析产出文件(代码、数据、报告等)到 ~/.deepspider/output/ 目录',
46
+ schema: z.object({
47
+ file_path: z.string().describe('文件路径(相对于 output 目录)'),
48
+ content: z.string().describe('文件内容'),
49
+ }),
50
+ }
51
+ );
52
+
53
+ export const artifactLoad = tool(
54
+ async ({ file_path }) => {
55
+ try {
56
+ const safePath = getSafePath(file_path);
57
+ if (!existsSync(safePath)) {
58
+ return JSON.stringify({ success: false, error: '文件不存在' });
59
+ }
60
+ const content = readFileSync(safePath, 'utf-8');
61
+ return JSON.stringify({ success: true, content, size: content.length });
62
+ } catch (e) {
63
+ return JSON.stringify({ success: false, error: e.message });
64
+ }
65
+ },
66
+ {
67
+ name: 'artifact_load',
68
+ description: '读取逆向分析产出文件(从 ~/.deepspider/output/ 目录)',
69
+ schema: z.object({
70
+ file_path: z.string().describe('文件路径(相对于 output 目录)'),
71
+ }),
72
+ }
73
+ );
74
+
75
+ export const artifactEdit = tool(
76
+ async ({ file_path, old_string, new_string, replace_all = false }) => {
77
+ try {
78
+ const safePath = getSafePath(file_path);
79
+ if (!existsSync(safePath)) {
80
+ return JSON.stringify({ success: false, error: '文件不存在' });
81
+ }
82
+ let content = readFileSync(safePath, 'utf-8');
83
+ const occurrences = content.split(old_string).length - 1;
84
+
85
+ if (occurrences === 0) {
86
+ return JSON.stringify({ success: false, error: '未找到要替换的字符串' });
87
+ }
88
+ if (occurrences > 1 && !replace_all) {
89
+ return JSON.stringify({
90
+ success: false,
91
+ error: `找到 ${occurrences} 处匹配,请使用 replace_all=true 或提供更精确的字符串`
92
+ });
93
+ }
94
+
95
+ content = replace_all
96
+ ? content.split(old_string).join(new_string)
97
+ : content.replace(old_string, new_string);
98
+
99
+ writeFileSync(safePath, content, 'utf-8');
100
+ return JSON.stringify({ success: true, path: safePath, replacements: replace_all ? occurrences : 1 });
101
+ } catch (e) {
102
+ return JSON.stringify({ success: false, error: e.message });
103
+ }
104
+ },
105
+ {
106
+ name: 'artifact_edit',
107
+ description: '编辑逆向分析产出文件,替换指定字符串',
108
+ schema: z.object({
109
+ file_path: z.string().describe('文件路径'),
110
+ old_string: z.string().describe('要替换的原字符串'),
111
+ new_string: z.string().describe('替换后的新字符串'),
112
+ replace_all: z.boolean().optional().default(false).describe('是否替换所有匹配'),
113
+ }),
114
+ }
115
+ );
116
+
117
+ /**
118
+ * 递归遍历目录,匹配文件
119
+ */
120
+ function walkDir(dir, pattern, results = []) {
121
+ if (!existsSync(dir)) return results;
122
+
123
+ const entries = readdirSync(dir, { withFileTypes: true });
124
+ for (const entry of entries) {
125
+ const fullPath = join(dir, entry.name);
126
+ if (entry.isDirectory()) {
127
+ walkDir(fullPath, pattern, results);
128
+ } else if (entry.isFile()) {
129
+ // 简单的 glob 匹配:支持 * 和 **
130
+ const relativePath = relative(OUTPUT_DIR, fullPath);
131
+ if (matchGlob(relativePath, pattern)) {
132
+ results.push(relativePath);
133
+ }
134
+ }
135
+ }
136
+ return results;
137
+ }
138
+
139
+ /**
140
+ * 简单的 glob 匹配
141
+ */
142
+ function matchGlob(path, pattern) {
143
+ // 转换 glob 为正则
144
+ const regex = pattern
145
+ .replace(/\*\*/g, '{{GLOBSTAR}}')
146
+ .replace(/\*/g, '[^/]*')
147
+ .replace(/\?/g, '.')
148
+ .replace(/{{GLOBSTAR}}/g, '.*');
149
+ return new RegExp(`^${regex}$`).test(path);
150
+ }
151
+
152
+ export const artifactGlob = tool(
153
+ async ({ pattern }) => {
154
+ try {
155
+ const files = walkDir(OUTPUT_DIR, pattern);
156
+ return JSON.stringify({ success: true, files, count: files.length });
157
+ } catch (e) {
158
+ return JSON.stringify({ success: false, error: e.message });
159
+ }
160
+ },
161
+ {
162
+ name: 'artifact_glob',
163
+ description: '在产出目录中查找匹配模式的文件(支持 * 和 ** 通配符)',
164
+ schema: z.object({
165
+ pattern: z.string().describe('文件匹配模式,如 "*.py" 或 "**/*.js"'),
166
+ }),
167
+ }
168
+ );
169
+
170
+ /**
171
+ * 在文件中搜索内容
172
+ */
173
+ function searchInFile(filePath, pattern, isRegex) {
174
+ try {
175
+ const content = readFileSync(filePath, 'utf-8');
176
+ const lines = content.split('\n');
177
+ const matches = [];
178
+ const regex = isRegex ? new RegExp(pattern, 'g') : null;
179
+
180
+ for (let i = 0; i < lines.length; i++) {
181
+ const line = lines[i];
182
+ const found = isRegex ? regex.test(line) : line.includes(pattern);
183
+ if (found) {
184
+ matches.push({ line: i + 1, content: line.trim() });
185
+ }
186
+ if (isRegex) regex.lastIndex = 0; // 重置正则
187
+ }
188
+ return matches;
189
+ } catch (e) {
190
+ return [];
191
+ }
192
+ }
193
+
194
+ export const artifactGrep = tool(
195
+ async ({ pattern, file_pattern = '**/*', is_regex = false }) => {
196
+ try {
197
+ const files = walkDir(OUTPUT_DIR, file_pattern);
198
+ const results = [];
199
+
200
+ for (const file of files) {
201
+ const fullPath = join(OUTPUT_DIR, file);
202
+ const matches = searchInFile(fullPath, pattern, is_regex);
203
+ if (matches.length > 0) {
204
+ results.push({ file, matches });
205
+ }
206
+ }
207
+
208
+ return JSON.stringify({ success: true, results, total_files: files.length, matched_files: results.length });
209
+ } catch (e) {
210
+ return JSON.stringify({ success: false, error: e.message });
211
+ }
212
+ },
213
+ {
214
+ name: 'artifact_grep',
215
+ description: '在产出文件中搜索内容',
216
+ schema: z.object({
217
+ pattern: z.string().describe('搜索模式(字符串或正则表达式)'),
218
+ file_pattern: z.string().optional().default('**/*').describe('文件匹配模式'),
219
+ is_regex: z.boolean().optional().default(false).describe('是否使用正则表达式'),
220
+ }),
221
+ }
222
+ );
223
+
224
+ export const fileTools = [artifactSave, artifactLoad, artifactEdit, artifactGlob, artifactGrep];
@@ -0,0 +1,84 @@
1
+ /**
2
+ * DeepSpider - Hook 工具
3
+ * 提供网络请求和 Cookie 监控能力
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import { tool } from '@langchain/core/tools';
8
+ import { NetworkHook } from '../../env/NetworkHook.js';
9
+ import { CookieHook } from '../../env/CookieHook.js';
10
+
11
+ const networkHook = new NetworkHook();
12
+ const cookieHook = new CookieHook();
13
+
14
+ /**
15
+ * 生成 XHR Hook 代码
16
+ */
17
+ export const generateXHRHook = tool(
18
+ async ({ captureBody, captureResponse }) => {
19
+ const code = networkHook.generateXHRHookCode({ captureBody, captureResponse });
20
+ return JSON.stringify({
21
+ success: true,
22
+ code,
23
+ usage: "注入后通过 __deepspider__.getLogs('xhr') 获取日志",
24
+ }, null, 2);
25
+ },
26
+ {
27
+ name: 'generate_xhr_hook',
28
+ description: '生成 XMLHttpRequest Hook 代码,拦截所有 XHR 请求',
29
+ schema: z.object({
30
+ captureBody: z.boolean().default(true).describe('是否捕获请求体'),
31
+ captureResponse: z.boolean().default(true).describe('是否捕获响应'),
32
+ }),
33
+ }
34
+ );
35
+
36
+ /**
37
+ * 生成 Fetch Hook 代码
38
+ */
39
+ export const generateFetchHook = tool(
40
+ async ({ captureBody, captureResponse }) => {
41
+ const code = networkHook.generateFetchHookCode({ captureBody, captureResponse });
42
+ return JSON.stringify({
43
+ success: true,
44
+ code,
45
+ usage: "注入后通过 __deepspider__.getLogs('fetch') 获取日志",
46
+ }, null, 2);
47
+ },
48
+ {
49
+ name: 'generate_fetch_hook',
50
+ description: '生成 Fetch Hook 代码,拦截所有 fetch 请求',
51
+ schema: z.object({
52
+ captureBody: z.boolean().default(true).describe('是否捕获请求体'),
53
+ captureResponse: z.boolean().default(true).describe('是否捕获响应'),
54
+ }),
55
+ }
56
+ );
57
+
58
+ /**
59
+ * 生成 Cookie Hook 代码
60
+ */
61
+ export const generateCookieHook = tool(
62
+ async ({ trackRead, trackWrite }) => {
63
+ const code = cookieHook.generateCookieHookCode({ trackRead, trackWrite });
64
+ return JSON.stringify({
65
+ success: true,
66
+ code,
67
+ usage: "注入后通过 __deepspider__.getLogs('cookie') 获取日志",
68
+ }, null, 2);
69
+ },
70
+ {
71
+ name: 'generate_cookie_hook',
72
+ description: '生成 Cookie Hook 代码,监控 document.cookie 读写',
73
+ schema: z.object({
74
+ trackRead: z.boolean().default(true).describe('是否监控读取'),
75
+ trackWrite: z.boolean().default(true).describe('是否监控写入'),
76
+ }),
77
+ }
78
+ );
79
+
80
+ export const hookTools = [
81
+ generateXHRHook,
82
+ generateFetchHook,
83
+ generateCookieHook,
84
+ ];
@@ -0,0 +1,178 @@
1
+ /**
2
+ * DeepSpider - Hook 管理工具
3
+ * 供 Agent 在运行时动态控制 Hook
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import { tool } from '@langchain/core/tools';
8
+ import { getBrowser } from '../../browser/index.js';
9
+
10
+ /**
11
+ * 通过 CDP 执行 JS
12
+ */
13
+ async function evaluateViaCDP(browser, expression) {
14
+ const cdp = await browser.getCDPSession();
15
+ if (!cdp) return null;
16
+ const result = await cdp.send('Runtime.evaluate', {
17
+ expression,
18
+ returnByValue: true,
19
+ });
20
+ return result.result?.value;
21
+ }
22
+
23
+ /**
24
+ * 列出所有可用的 Hook
25
+ */
26
+ export const listHooks = tool(
27
+ async () => {
28
+ try {
29
+ const browser = await getBrowser();
30
+ if (!browser.getPage()) {
31
+ return JSON.stringify({ success: false, error: '浏览器未就绪' });
32
+ }
33
+ const result = await evaluateViaCDP(
34
+ browser,
35
+ `JSON.stringify(window.__deepspider__?.listHooks?.() || [])`
36
+ );
37
+ return JSON.stringify({
38
+ success: true,
39
+ hooks: JSON.parse(result || '[]')
40
+ });
41
+ } catch (e) {
42
+ return JSON.stringify({ success: false, error: e.message });
43
+ }
44
+ },
45
+ {
46
+ name: 'list_hooks',
47
+ description: '列出所有可用的 Hook 及其状态',
48
+ schema: z.object({}),
49
+ }
50
+ );
51
+
52
+ /**
53
+ * 启用指定的 Hook
54
+ */
55
+ export const enableHook = tool(
56
+ async ({ name }) => {
57
+ try {
58
+ const browser = await getBrowser();
59
+ if (!browser.getPage()) {
60
+ return JSON.stringify({ success: false, error: '浏览器未就绪' });
61
+ }
62
+ const result = await evaluateViaCDP(
63
+ browser,
64
+ `window.__deepspider__?.enableHook?.('${name}')`
65
+ );
66
+ return JSON.stringify({ success: result === true, name });
67
+ } catch (e) {
68
+ return JSON.stringify({ success: false, error: e.message });
69
+ }
70
+ },
71
+ {
72
+ name: 'enable_hook',
73
+ description: '启用指定的 Hook',
74
+ schema: z.object({
75
+ name: z.string().describe('Hook 名称'),
76
+ }),
77
+ }
78
+ );
79
+
80
+ /**
81
+ * 禁用指定的 Hook
82
+ */
83
+ export const disableHook = tool(
84
+ async ({ name }) => {
85
+ try {
86
+ const browser = await getBrowser();
87
+ if (!browser.getPage()) {
88
+ return JSON.stringify({ success: false, error: '浏览器未就绪' });
89
+ }
90
+ const result = await evaluateViaCDP(
91
+ browser,
92
+ `window.__deepspider__?.disableHook?.('${name}')`
93
+ );
94
+ return JSON.stringify({ success: result === true, name });
95
+ } catch (e) {
96
+ return JSON.stringify({ success: false, error: e.message });
97
+ }
98
+ },
99
+ {
100
+ name: 'disable_hook',
101
+ description: '禁用指定的 Hook',
102
+ schema: z.object({
103
+ name: z.string().describe('要禁用的 Hook 名称'),
104
+ }),
105
+ }
106
+ );
107
+
108
+ /**
109
+ * 注入自定义 Hook 代码
110
+ */
111
+ export const injectHook = tool(
112
+ async ({ code }) => {
113
+ try {
114
+ const browser = await getBrowser();
115
+ if (!browser.getPage()) {
116
+ return JSON.stringify({ success: false, error: '浏览器未就绪' });
117
+ }
118
+ const escapedCode = code
119
+ .replace(/\\/g, '\\\\')
120
+ .replace(/'/g, "\\'")
121
+ .replace(/\n/g, '\\n');
122
+
123
+ const result = await evaluateViaCDP(
124
+ browser,
125
+ `JSON.stringify(window.__deepspider__?.injectHook?.('${escapedCode}'))`
126
+ );
127
+ return result || JSON.stringify({ success: false, error: '注入失败' });
128
+ } catch (e) {
129
+ return JSON.stringify({ success: false, error: e.message });
130
+ }
131
+ },
132
+ {
133
+ name: 'inject_hook',
134
+ description: '注入自定义 Hook 代码到浏览器',
135
+ schema: z.object({
136
+ code: z.string().describe('要注入的 JS 代码'),
137
+ }),
138
+ }
139
+ );
140
+
141
+ /**
142
+ * 设置 Hook 配置
143
+ */
144
+ export const setHookConfig = tool(
145
+ async ({ key, value }) => {
146
+ try {
147
+ const browser = await getBrowser();
148
+ if (!browser.getPage()) {
149
+ return JSON.stringify({ success: false, error: '浏览器未就绪' });
150
+ }
151
+ const val = typeof value === 'string' ? `'${value}'` : value;
152
+ const result = await evaluateViaCDP(
153
+ browser,
154
+ `window.__deepspider__?.setConfig?.('${key}', ${val})`
155
+ );
156
+ return JSON.stringify({ success: result === true, key, value });
157
+ } catch (e) {
158
+ return JSON.stringify({ success: false, error: e.message });
159
+ }
160
+ },
161
+ {
162
+ name: 'set_hook_config',
163
+ description: '设置 Hook 配置(silent, captureStack, logToConsole 等)',
164
+ schema: z.object({
165
+ key: z.string().describe('配置项名称'),
166
+ value: z.union([z.boolean(), z.number(), z.string()]).describe('配置值'),
167
+ }),
168
+ }
169
+ );
170
+
171
+ // 导出所有工具
172
+ export const hookManagerTools = [
173
+ listHooks,
174
+ enableHook,
175
+ disableHook,
176
+ injectHook,
177
+ setHookConfig,
178
+ ];