@jshookmcp/jshook 0.1.5 → 0.1.6
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 +661 -661
- package/README.md +72 -40
- package/README.zh.md +77 -40
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +13 -1
- package/dist/modules/analyzer/IntelligentAnalyzer.js +19 -11
- package/dist/modules/browser/BrowserModeManager.d.ts +5 -0
- package/dist/modules/browser/BrowserModeManager.js +96 -10
- package/dist/modules/browser/CamoufoxBrowserManager.d.ts +4 -0
- package/dist/modules/browser/CamoufoxBrowserManager.js +64 -3
- package/dist/modules/browser/TabRegistry.js +3 -2
- package/dist/modules/browser/UnifiedBrowserManager.d.ts +5 -0
- package/dist/modules/browser/UnifiedBrowserManager.js +62 -9
- package/dist/modules/captcha/AICaptchaDetector.js +185 -185
- package/dist/modules/debugger/DebuggerSessionManager.d.ts +4 -0
- package/dist/modules/debugger/DebuggerSessionManager.js +29 -19
- package/dist/modules/debugger/ScriptManager.impl.class.d.ts +4 -0
- package/dist/modules/debugger/ScriptManager.impl.class.js +46 -21
- package/dist/modules/emulator/EnvironmentEmulator.js +2 -2
- package/dist/modules/monitor/NetworkMonitor.impl.d.ts +1 -0
- package/dist/modules/monitor/NetworkMonitor.impl.js +22 -15
- package/dist/modules/monitor/PerformanceMonitor.js +64 -32
- package/dist/modules/process/LinuxProcessManager.d.ts +3 -1
- package/dist/modules/process/LinuxProcessManager.js +7 -3
- package/dist/modules/process/MacProcessManager.d.ts +3 -1
- package/dist/modules/process/MacProcessManager.js +32 -28
- package/dist/modules/process/ProcessManager.impl.d.ts +5 -1
- package/dist/modules/process/ProcessManager.impl.js +54 -13
- package/dist/modules/process/index.d.ts +3 -1
- package/dist/modules/process/index.js +2 -2
- package/dist/modules/process/memory/AuditTrail.d.ts +25 -0
- package/dist/modules/process/memory/AuditTrail.js +44 -0
- package/dist/modules/process/memory/availability.js +49 -49
- package/dist/modules/process/memory/injector.js +185 -185
- package/dist/modules/process/memory/linux/mapsParser.d.ts +16 -0
- package/dist/modules/process/memory/linux/mapsParser.js +28 -0
- package/dist/modules/process/memory/reader.js +50 -50
- package/dist/modules/process/memory/regions.enumerate.js +45 -1
- package/dist/modules/process/memory/regions.protection.js +48 -2
- package/dist/modules/process/memory/scanner.d.ts +4 -1
- package/dist/modules/process/memory/scanner.js +383 -182
- package/dist/modules/process/memory/writer.js +54 -54
- package/dist/native/NativeMemoryManager.impl.d.ts +4 -0
- package/dist/native/NativeMemoryManager.impl.js +72 -24
- package/dist/native/NativeMemoryManager.utils.d.ts +1 -0
- package/dist/native/NativeMemoryManager.utils.js +44 -1
- package/dist/native/scripts/linux/enum-windows.sh +12 -12
- package/dist/native/scripts/macos/enum-windows.applescript +22 -22
- package/dist/native/scripts/windows/enum-windows-by-class.ps1 +51 -51
- package/dist/native/scripts/windows/enum-windows.ps1 +44 -44
- package/dist/native/scripts/windows/inject-dll.ps1 +21 -21
- package/dist/server/MCPServer.search.d.ts +3 -0
- package/dist/server/MCPServer.search.js +21 -2
- package/dist/server/ToolCallContextGuard.d.ts +2 -0
- package/dist/server/ToolCallContextGuard.js +29 -14
- package/dist/server/ToolSearch.js +11 -5
- package/dist/server/domains/browser/definitions.tools.page-core.js +53 -53
- package/dist/server/domains/browser/definitions.tools.runtime.js +40 -40
- package/dist/server/domains/browser/definitions.tools.security.js +76 -76
- package/dist/server/domains/browser/handlers/tab-workflow.js +6 -4
- package/dist/server/domains/maintenance/handlers.extensions.js +46 -26
- package/dist/server/domains/process/definitions.js +20 -7
- package/dist/server/domains/process/handlers.impl.core.runtime.base.d.ts +35 -0
- package/dist/server/domains/process/handlers.impl.core.runtime.base.js +107 -1
- package/dist/server/domains/process/handlers.impl.core.runtime.inject.js +111 -2
- package/dist/server/domains/process/handlers.impl.core.runtime.memory.d.ts +9 -0
- package/dist/server/domains/process/handlers.impl.core.runtime.memory.js +282 -31
- package/dist/server/domains/process/manifest.js +1 -0
- package/dist/server/domains/transform/handlers.impl.transform-base.js +102 -102
- package/dist/server/domains/workflow/handlers.impl.workflow-api.js +14 -4
- package/dist/server/domains/workflow/handlers.impl.workflow-base.js +51 -51
- package/dist/server/registry/discovery.js +17 -12
- package/dist/server/registry/index.js +10 -2
- package/dist/utils/TokenBudgetManager.d.ts +1 -0
- package/dist/utils/TokenBudgetManager.js +22 -0
- package/package.json +5 -1
- package/src/native/scripts/linux/enum-windows.sh +12 -12
- package/src/native/scripts/macos/enum-windows.applescript +22 -22
- package/src/native/scripts/windows/enum-windows-by-class.ps1 +51 -51
- package/src/native/scripts/windows/enum-windows.ps1 +44 -44
- package/src/native/scripts/windows/inject-dll.ps1 +21 -21
|
@@ -135,194 +135,194 @@ export class AICaptchaDetector {
|
|
|
135
135
|
bodyTextPreview: `${pageInfo.bodyText.substring(0, 200)}...`,
|
|
136
136
|
};
|
|
137
137
|
return `#
|
|
138
|
-
|
|
139
|
-
##
|
|
140
|
-
,(CAPTCHA),。
|
|
141
|
-
|
|
142
|
-
##
|
|
138
|
+
|
|
139
|
+
##
|
|
140
|
+
,(CAPTCHA),。
|
|
141
|
+
|
|
142
|
+
##
|
|
143
143
|
\`\`\`json
|
|
144
144
|
${JSON.stringify(promptPayload, null, 2)}
|
|
145
145
|
\`\`\`
|
|
146
|
-
|
|
147
|
-
##
|
|
148
|
-
|
|
149
|
-
### 1. (Interactive CAPTCHA)
|
|
150
|
-
**1.1 (Slider CAPTCHA)**
|
|
151
|
-
- ****: 、
|
|
152
|
-
- ****: (Geetest)、、、
|
|
153
|
-
- ****: 、、""
|
|
154
|
-
- **DOM**: \`.geetest_slider\`, \`.nc_1_wrapper\`, \`.tcaptcha-transform\`
|
|
155
|
-
|
|
156
|
-
**1.2 (Image CAPTCHA)**
|
|
157
|
-
- ****: ("")
|
|
158
|
-
- ****: reCAPTCHA v2、hCaptcha
|
|
159
|
-
- ****: 3x34x4、
|
|
160
|
-
- **DOM**: \`iframe[src*="recaptcha"]\`, \`.h-captcha\`
|
|
161
|
-
|
|
162
|
-
**1.3 (Text CAPTCHA)**
|
|
163
|
-
- ****: /
|
|
164
|
-
- ****: 、
|
|
165
|
-
- ****: ""
|
|
166
|
-
|
|
167
|
-
### 2. (Automatic CAPTCHA)
|
|
168
|
-
**2.1 reCAPTCHA v3**
|
|
169
|
-
- ****: ,reCAPTCHA
|
|
170
|
-
- ****: "Protected by reCAPTCHA"
|
|
171
|
-
|
|
172
|
-
**2.2 Cloudflare Turnstile**
|
|
173
|
-
- ****: "" / "Checking your browser"
|
|
174
|
-
- ****: Cloudflare logo、、Ray ID
|
|
175
|
-
|
|
176
|
-
### 3. (False Positives - )
|
|
177
|
-
**3.1 **
|
|
178
|
-
- 、、
|
|
179
|
-
- ""()
|
|
180
|
-
- ""()
|
|
181
|
-
|
|
182
|
-
**3.2 **
|
|
183
|
-
- 、
|
|
184
|
-
- 、
|
|
185
|
-
-
|
|
186
|
-
|
|
187
|
-
**3.3 UI**
|
|
188
|
-
- Range slider、Progress bar
|
|
189
|
-
- Carousel、Swiper
|
|
190
|
-
- 、
|
|
191
|
-
|
|
192
|
-
##
|
|
193
|
-
|
|
194
|
-
### Step 1:
|
|
195
|
-
1. :
|
|
196
|
-
- +
|
|
197
|
-
- +
|
|
198
|
-
- ""
|
|
199
|
-
- ""
|
|
200
|
-
- Cloudflare/reCAPTCHA logo
|
|
201
|
-
|
|
202
|
-
### Step 2:
|
|
203
|
-
1. URL:
|
|
204
|
-
- \`/captcha\`, \`/challenge\`, \`/verify\`
|
|
205
|
-
- \`cdn-cgi/challenge\` (Cloudflare)
|
|
206
|
-
- \`recaptcha.net\`, \`hcaptcha.com\`
|
|
207
|
-
|
|
208
|
-
2. :
|
|
209
|
-
- ""、""、""
|
|
210
|
-
- "Verify", "Challenge", "Security Check"
|
|
211
|
-
|
|
212
|
-
3. :
|
|
213
|
-
- suspiciousElements →
|
|
214
|
-
- →
|
|
215
|
-
|
|
216
|
-
### Step 3:
|
|
217
|
-
1. :
|
|
218
|
-
- ""、""
|
|
219
|
-
- ,
|
|
220
|
-
- → \`detected: false\`
|
|
221
|
-
|
|
222
|
-
2. /UI:
|
|
223
|
-
- 、、
|
|
224
|
-
- → \`detected: false\`
|
|
225
|
-
|
|
226
|
-
### Step 4:
|
|
227
|
-
- **90-100%**: + DOM
|
|
228
|
-
- **70-89%**: ,DOM
|
|
229
|
-
- **50-69%**: ,
|
|
230
|
-
- **0-49%**:
|
|
231
|
-
|
|
232
|
-
##
|
|
233
|
-
|
|
234
|
-
**JSON Schema**:
|
|
235
|
-
|
|
236
|
-
\`\`\`json
|
|
237
|
-
{
|
|
238
|
-
"detected": boolean,
|
|
239
|
-
"type": "slider" | "image" | "recaptcha" | "hcaptcha" | "cloudflare" | "text_input" | "none",
|
|
240
|
-
"confidence": number,
|
|
241
|
-
"reasoning": string,
|
|
242
|
-
"location": {
|
|
243
|
-
"x": number,
|
|
244
|
-
"y": number,
|
|
245
|
-
"width": number,
|
|
246
|
-
"height": number
|
|
247
|
-
} | null,
|
|
248
|
-
"vendor": "geetest" | "tencent" | "aliyun" | "recaptcha" | "hcaptcha" | "cloudflare" | "unknown",
|
|
249
|
-
"suggestions": string[]
|
|
250
|
-
}
|
|
251
|
-
\`\`\`
|
|
252
|
-
|
|
253
|
-
###
|
|
254
|
-
- **detected**: ()
|
|
255
|
-
- **type**: ()
|
|
256
|
-
- **confidence**: (0-100)
|
|
257
|
-
- **reasoning**: (200,)
|
|
258
|
-
- **location**: (,null)
|
|
259
|
-
- **vendor**: ("unknown")
|
|
260
|
-
- **suggestions**: (,2-3)
|
|
261
|
-
|
|
262
|
-
###
|
|
263
|
-
|
|
264
|
-
**1: **
|
|
265
|
-
\`\`\`json
|
|
266
|
-
{
|
|
267
|
-
"detected": true,
|
|
268
|
-
"type": "slider",
|
|
269
|
-
"confidence": 95,
|
|
270
|
-
"reasoning": ":1) ;2) '';3) DOM.geetest_slider。。",
|
|
271
|
-
"location": {
|
|
272
|
-
"x": 450,
|
|
273
|
-
"y": 300,
|
|
274
|
-
"width": 320,
|
|
275
|
-
"height": 180
|
|
276
|
-
},
|
|
277
|
-
"vendor": "geetest",
|
|
278
|
-
"suggestions": [
|
|
279
|
-
"",
|
|
280
|
-
"captcha_wait",
|
|
281
|
-
","
|
|
282
|
-
]
|
|
283
|
-
}
|
|
284
|
-
\`\`\`
|
|
285
|
-
|
|
286
|
-
**2: - **
|
|
287
|
-
\`\`\`json
|
|
288
|
-
{
|
|
289
|
-
"detected": false,
|
|
290
|
-
"type": "none",
|
|
291
|
-
"confidence": 95,
|
|
292
|
-
"reasoning": "'''',,。,。",
|
|
293
|
-
"location": null,
|
|
294
|
-
"vendor": "unknown",
|
|
295
|
-
"suggestions": [
|
|
296
|
-
",",
|
|
297
|
-
""
|
|
298
|
-
]
|
|
299
|
-
}
|
|
300
|
-
\`\`\`
|
|
301
|
-
|
|
302
|
-
**3: **
|
|
303
|
-
\`\`\`json
|
|
304
|
-
{
|
|
305
|
-
"detected": false,
|
|
306
|
-
"type": "none",
|
|
307
|
-
"confidence": 98,
|
|
308
|
-
"reasoning": ",、。,suspiciousElements,URL。",
|
|
309
|
-
"location": null,
|
|
310
|
-
"vendor": "unknown",
|
|
311
|
-
"suggestions": [
|
|
312
|
-
",",
|
|
313
|
-
""
|
|
314
|
-
]
|
|
315
|
-
}
|
|
316
|
-
\`\`\`
|
|
317
|
-
|
|
318
|
-
##
|
|
319
|
-
|
|
320
|
-
1. ****: \`detected: false\`,
|
|
321
|
-
2. ****: > DOM >
|
|
322
|
-
3. ****: URL、、DOM、
|
|
323
|
-
4. ****: reasoning
|
|
324
|
-
5. ****: suggestions
|
|
325
|
-
|
|
146
|
+
|
|
147
|
+
##
|
|
148
|
+
|
|
149
|
+
### 1. (Interactive CAPTCHA)
|
|
150
|
+
**1.1 (Slider CAPTCHA)**
|
|
151
|
+
- ****: 、
|
|
152
|
+
- ****: (Geetest)、、、
|
|
153
|
+
- ****: 、、""
|
|
154
|
+
- **DOM**: \`.geetest_slider\`, \`.nc_1_wrapper\`, \`.tcaptcha-transform\`
|
|
155
|
+
|
|
156
|
+
**1.2 (Image CAPTCHA)**
|
|
157
|
+
- ****: ("")
|
|
158
|
+
- ****: reCAPTCHA v2、hCaptcha
|
|
159
|
+
- ****: 3x34x4、
|
|
160
|
+
- **DOM**: \`iframe[src*="recaptcha"]\`, \`.h-captcha\`
|
|
161
|
+
|
|
162
|
+
**1.3 (Text CAPTCHA)**
|
|
163
|
+
- ****: /
|
|
164
|
+
- ****: 、
|
|
165
|
+
- ****: ""
|
|
166
|
+
|
|
167
|
+
### 2. (Automatic CAPTCHA)
|
|
168
|
+
**2.1 reCAPTCHA v3**
|
|
169
|
+
- ****: ,reCAPTCHA
|
|
170
|
+
- ****: "Protected by reCAPTCHA"
|
|
171
|
+
|
|
172
|
+
**2.2 Cloudflare Turnstile**
|
|
173
|
+
- ****: "" / "Checking your browser"
|
|
174
|
+
- ****: Cloudflare logo、、Ray ID
|
|
175
|
+
|
|
176
|
+
### 3. (False Positives - )
|
|
177
|
+
**3.1 **
|
|
178
|
+
- 、、
|
|
179
|
+
- ""()
|
|
180
|
+
- ""()
|
|
181
|
+
|
|
182
|
+
**3.2 **
|
|
183
|
+
- 、
|
|
184
|
+
- 、
|
|
185
|
+
-
|
|
186
|
+
|
|
187
|
+
**3.3 UI**
|
|
188
|
+
- Range slider、Progress bar
|
|
189
|
+
- Carousel、Swiper
|
|
190
|
+
- 、
|
|
191
|
+
|
|
192
|
+
##
|
|
193
|
+
|
|
194
|
+
### Step 1:
|
|
195
|
+
1. :
|
|
196
|
+
- +
|
|
197
|
+
- +
|
|
198
|
+
- ""
|
|
199
|
+
- ""
|
|
200
|
+
- Cloudflare/reCAPTCHA logo
|
|
201
|
+
|
|
202
|
+
### Step 2:
|
|
203
|
+
1. URL:
|
|
204
|
+
- \`/captcha\`, \`/challenge\`, \`/verify\`
|
|
205
|
+
- \`cdn-cgi/challenge\` (Cloudflare)
|
|
206
|
+
- \`recaptcha.net\`, \`hcaptcha.com\`
|
|
207
|
+
|
|
208
|
+
2. :
|
|
209
|
+
- ""、""、""
|
|
210
|
+
- "Verify", "Challenge", "Security Check"
|
|
211
|
+
|
|
212
|
+
3. :
|
|
213
|
+
- suspiciousElements →
|
|
214
|
+
- →
|
|
215
|
+
|
|
216
|
+
### Step 3:
|
|
217
|
+
1. :
|
|
218
|
+
- ""、""
|
|
219
|
+
- ,
|
|
220
|
+
- → \`detected: false\`
|
|
221
|
+
|
|
222
|
+
2. /UI:
|
|
223
|
+
- 、、
|
|
224
|
+
- → \`detected: false\`
|
|
225
|
+
|
|
226
|
+
### Step 4:
|
|
227
|
+
- **90-100%**: + DOM
|
|
228
|
+
- **70-89%**: ,DOM
|
|
229
|
+
- **50-69%**: ,
|
|
230
|
+
- **0-49%**:
|
|
231
|
+
|
|
232
|
+
##
|
|
233
|
+
|
|
234
|
+
**JSON Schema**:
|
|
235
|
+
|
|
236
|
+
\`\`\`json
|
|
237
|
+
{
|
|
238
|
+
"detected": boolean,
|
|
239
|
+
"type": "slider" | "image" | "recaptcha" | "hcaptcha" | "cloudflare" | "text_input" | "none",
|
|
240
|
+
"confidence": number,
|
|
241
|
+
"reasoning": string,
|
|
242
|
+
"location": {
|
|
243
|
+
"x": number,
|
|
244
|
+
"y": number,
|
|
245
|
+
"width": number,
|
|
246
|
+
"height": number
|
|
247
|
+
} | null,
|
|
248
|
+
"vendor": "geetest" | "tencent" | "aliyun" | "recaptcha" | "hcaptcha" | "cloudflare" | "unknown",
|
|
249
|
+
"suggestions": string[]
|
|
250
|
+
}
|
|
251
|
+
\`\`\`
|
|
252
|
+
|
|
253
|
+
###
|
|
254
|
+
- **detected**: ()
|
|
255
|
+
- **type**: ()
|
|
256
|
+
- **confidence**: (0-100)
|
|
257
|
+
- **reasoning**: (200,)
|
|
258
|
+
- **location**: (,null)
|
|
259
|
+
- **vendor**: ("unknown")
|
|
260
|
+
- **suggestions**: (,2-3)
|
|
261
|
+
|
|
262
|
+
###
|
|
263
|
+
|
|
264
|
+
**1: **
|
|
265
|
+
\`\`\`json
|
|
266
|
+
{
|
|
267
|
+
"detected": true,
|
|
268
|
+
"type": "slider",
|
|
269
|
+
"confidence": 95,
|
|
270
|
+
"reasoning": ":1) ;2) '';3) DOM.geetest_slider。。",
|
|
271
|
+
"location": {
|
|
272
|
+
"x": 450,
|
|
273
|
+
"y": 300,
|
|
274
|
+
"width": 320,
|
|
275
|
+
"height": 180
|
|
276
|
+
},
|
|
277
|
+
"vendor": "geetest",
|
|
278
|
+
"suggestions": [
|
|
279
|
+
"",
|
|
280
|
+
"captcha_wait",
|
|
281
|
+
","
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
\`\`\`
|
|
285
|
+
|
|
286
|
+
**2: - **
|
|
287
|
+
\`\`\`json
|
|
288
|
+
{
|
|
289
|
+
"detected": false,
|
|
290
|
+
"type": "none",
|
|
291
|
+
"confidence": 95,
|
|
292
|
+
"reasoning": "'''',,。,。",
|
|
293
|
+
"location": null,
|
|
294
|
+
"vendor": "unknown",
|
|
295
|
+
"suggestions": [
|
|
296
|
+
",",
|
|
297
|
+
""
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
\`\`\`
|
|
301
|
+
|
|
302
|
+
**3: **
|
|
303
|
+
\`\`\`json
|
|
304
|
+
{
|
|
305
|
+
"detected": false,
|
|
306
|
+
"type": "none",
|
|
307
|
+
"confidence": 98,
|
|
308
|
+
"reasoning": ",、。,suspiciousElements,URL。",
|
|
309
|
+
"location": null,
|
|
310
|
+
"vendor": "unknown",
|
|
311
|
+
"suggestions": [
|
|
312
|
+
",",
|
|
313
|
+
""
|
|
314
|
+
]
|
|
315
|
+
}
|
|
316
|
+
\`\`\`
|
|
317
|
+
|
|
318
|
+
##
|
|
319
|
+
|
|
320
|
+
1. ****: \`detected: false\`,
|
|
321
|
+
2. ****: > DOM >
|
|
322
|
+
3. ****: URL、、DOM、
|
|
323
|
+
4. ****: reasoning
|
|
324
|
+
5. ****: suggestions
|
|
325
|
+
|
|
326
326
|
,JSON。`;
|
|
327
327
|
}
|
|
328
328
|
parseAIResponse(response, screenshotPath) {
|
|
@@ -7,7 +7,11 @@ type SavedDebuggerSessionSummary = {
|
|
|
7
7
|
};
|
|
8
8
|
export declare class DebuggerSessionManager {
|
|
9
9
|
private debuggerManager;
|
|
10
|
+
private readonly SESSION_IMPORT_BATCH_SIZE;
|
|
11
|
+
private readonly SESSION_FILE_READ_BATCH_SIZE;
|
|
10
12
|
constructor(debuggerManager: DebuggerManager);
|
|
13
|
+
private processInBatches;
|
|
14
|
+
private readSessionFile;
|
|
11
15
|
private validateFilePath;
|
|
12
16
|
exportSession(metadata?: DebuggerSession['metadata']): DebuggerSession;
|
|
13
17
|
saveSession(filePath?: string, metadata?: DebuggerSession['metadata']): Promise<string>;
|
|
@@ -4,9 +4,20 @@ import * as path from 'path';
|
|
|
4
4
|
import { logger } from '../../utils/logger.js';
|
|
5
5
|
export class DebuggerSessionManager {
|
|
6
6
|
debuggerManager;
|
|
7
|
+
SESSION_IMPORT_BATCH_SIZE = 8;
|
|
8
|
+
SESSION_FILE_READ_BATCH_SIZE = 8;
|
|
7
9
|
constructor(debuggerManager) {
|
|
8
10
|
this.debuggerManager = debuggerManager;
|
|
9
11
|
}
|
|
12
|
+
async processInBatches(items, batchSize, worker) {
|
|
13
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
14
|
+
const batch = items.slice(i, i + batchSize);
|
|
15
|
+
await Promise.all(batch.map((item) => worker(item)));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async readSessionFile(filePath) {
|
|
19
|
+
return fs.readFile(filePath, 'utf-8');
|
|
20
|
+
}
|
|
10
21
|
async validateFilePath(filePath) {
|
|
11
22
|
const resolved = path.resolve(filePath);
|
|
12
23
|
const cwd = await fs.realpath(process.cwd());
|
|
@@ -70,7 +81,7 @@ export class DebuggerSessionManager {
|
|
|
70
81
|
}
|
|
71
82
|
async loadSessionFromFile(filePath) {
|
|
72
83
|
const resolvedPath = await this.validateFilePath(filePath);
|
|
73
|
-
const content = await
|
|
84
|
+
const content = await this.readSessionFile(resolvedPath);
|
|
74
85
|
const session = JSON.parse(content);
|
|
75
86
|
await this.importSession(session);
|
|
76
87
|
logger.info(`Session loaded from ${resolvedPath}`, {
|
|
@@ -93,7 +104,7 @@ export class DebuggerSessionManager {
|
|
|
93
104
|
await this.debuggerManager.clearAllBreakpoints();
|
|
94
105
|
let successCount = 0;
|
|
95
106
|
let failCount = 0;
|
|
96
|
-
|
|
107
|
+
await this.processInBatches(session.breakpoints, this.SESSION_IMPORT_BATCH_SIZE, async (bp) => {
|
|
97
108
|
try {
|
|
98
109
|
if (bp.location.url) {
|
|
99
110
|
await this.debuggerManager.setBreakpointByUrl({
|
|
@@ -122,7 +133,7 @@ export class DebuggerSessionManager {
|
|
|
122
133
|
logger.error('Failed to restore breakpoint:', error, bp);
|
|
123
134
|
failCount++;
|
|
124
135
|
}
|
|
125
|
-
}
|
|
136
|
+
});
|
|
126
137
|
if (session.pauseOnExceptions) {
|
|
127
138
|
await this.debuggerManager.setPauseOnExceptions(session.pauseOnExceptions);
|
|
128
139
|
}
|
|
@@ -143,23 +154,22 @@ export class DebuggerSessionManager {
|
|
|
143
154
|
}
|
|
144
155
|
const files = await fs.readdir(sessionsDir);
|
|
145
156
|
const sessions = [];
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
logger.warn(`Failed to read session file ${file}:`, error);
|
|
160
|
-
}
|
|
157
|
+
const sessionFiles = files.filter((file) => file.endsWith('.json'));
|
|
158
|
+
await this.processInBatches(sessionFiles, this.SESSION_FILE_READ_BATCH_SIZE, async (file) => {
|
|
159
|
+
const filePath = path.join(sessionsDir, file);
|
|
160
|
+
try {
|
|
161
|
+
const content = await this.readSessionFile(filePath);
|
|
162
|
+
const session = JSON.parse(content);
|
|
163
|
+
sessions.push({
|
|
164
|
+
path: filePath,
|
|
165
|
+
timestamp: session.timestamp,
|
|
166
|
+
metadata: session.metadata,
|
|
167
|
+
});
|
|
161
168
|
}
|
|
162
|
-
|
|
169
|
+
catch (error) {
|
|
170
|
+
logger.warn(`Failed to read session file ${file}:`, error);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
163
173
|
sessions.sort((a, b) => b.timestamp - a.timestamp);
|
|
164
174
|
return sessions;
|
|
165
175
|
}
|
|
@@ -12,6 +12,9 @@ export interface ScriptInfo {
|
|
|
12
12
|
}
|
|
13
13
|
export declare class ScriptManager {
|
|
14
14
|
private collector;
|
|
15
|
+
private static readonly SOURCE_LOAD_BATCH_SIZE;
|
|
16
|
+
private static readonly SEARCH_LINE_YIELD_INTERVAL;
|
|
17
|
+
private static readonly SEARCH_SCRIPT_YIELD_INTERVAL;
|
|
15
18
|
private cdpSession;
|
|
16
19
|
private scripts;
|
|
17
20
|
private scriptsByUrl;
|
|
@@ -23,6 +26,7 @@ export declare class ScriptManager {
|
|
|
23
26
|
constructor(collector: CodeCollector);
|
|
24
27
|
init(): Promise<void>;
|
|
25
28
|
private doInit;
|
|
29
|
+
private loadScriptSourceInternal;
|
|
26
30
|
enable(): Promise<void>;
|
|
27
31
|
getAllScripts(includeSource?: boolean, maxScripts?: number): Promise<ScriptInfo[]>;
|
|
28
32
|
getScriptSource(scriptId?: string, url?: string): Promise<ScriptInfo | null>;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { setImmediate as waitForImmediate } from 'node:timers/promises';
|
|
1
2
|
import { logger } from '../../utils/logger.js';
|
|
2
3
|
import { extractFunctionTreeCore, } from '../debugger/ScriptManager.impl.extract-function-tree.js';
|
|
3
4
|
export class ScriptManager {
|
|
4
5
|
collector;
|
|
6
|
+
static SOURCE_LOAD_BATCH_SIZE = 8;
|
|
7
|
+
static SEARCH_LINE_YIELD_INTERVAL = 250;
|
|
8
|
+
static SEARCH_SCRIPT_YIELD_INTERVAL = 10;
|
|
5
9
|
cdpSession = null;
|
|
6
10
|
scripts = new Map();
|
|
7
11
|
scriptsByUrl = new Map();
|
|
@@ -54,6 +58,25 @@ export class ScriptManager {
|
|
|
54
58
|
this.initialized = true;
|
|
55
59
|
logger.info('ScriptManager initialized');
|
|
56
60
|
}
|
|
61
|
+
async loadScriptSourceInternal(script) {
|
|
62
|
+
if (script.source) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const { scriptSource } = await this.cdpSession.send('Debugger.getScriptSource', {
|
|
67
|
+
scriptId: script.scriptId,
|
|
68
|
+
});
|
|
69
|
+
script.source = scriptSource;
|
|
70
|
+
script.sourceLength = scriptSource.length;
|
|
71
|
+
this.buildKeywordIndex(script.scriptId, script.url, scriptSource);
|
|
72
|
+
this.chunkScript(script.scriptId, scriptSource);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
logger.warn(`Failed to get source for script ${script.scriptId}:`, error);
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
57
80
|
async enable() {
|
|
58
81
|
return this.init();
|
|
59
82
|
}
|
|
@@ -70,23 +93,27 @@ export class ScriptManager {
|
|
|
70
93
|
logger.warn(`Loading source code for ${limitedScripts.length} scripts. This may use significant memory.`);
|
|
71
94
|
let loadedCount = 0;
|
|
72
95
|
let failedCount = 0;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
script.source = scriptSource;
|
|
96
|
+
const missingScripts = limitedScripts.filter((script) => !script.source);
|
|
97
|
+
for (let batchStart = 0; batchStart < missingScripts.length; batchStart += ScriptManager.SOURCE_LOAD_BATCH_SIZE) {
|
|
98
|
+
const batch = missingScripts.slice(batchStart, batchStart + ScriptManager.SOURCE_LOAD_BATCH_SIZE);
|
|
99
|
+
const settled = await Promise.allSettled(batch.map(async (script) => {
|
|
100
|
+
const loaded = await this.loadScriptSourceInternal(script);
|
|
101
|
+
if (loaded) {
|
|
80
102
|
loadedCount++;
|
|
81
103
|
if (loadedCount % 10 === 0) {
|
|
82
104
|
logger.debug(`Loaded ${loadedCount}/${limitedScripts.length} scripts...`);
|
|
83
105
|
}
|
|
84
106
|
}
|
|
85
|
-
|
|
86
|
-
|
|
107
|
+
else {
|
|
108
|
+
failedCount++;
|
|
109
|
+
}
|
|
110
|
+
}));
|
|
111
|
+
for (const result of settled) {
|
|
112
|
+
if (result.status === 'rejected') {
|
|
87
113
|
failedCount++;
|
|
88
114
|
}
|
|
89
115
|
}
|
|
116
|
+
await waitForImmediate();
|
|
90
117
|
}
|
|
91
118
|
logger.info(`getAllScripts: ${limitedScripts.length} scripts (loaded: ${loadedCount}, failed: ${failedCount})`);
|
|
92
119
|
}
|
|
@@ -121,17 +148,9 @@ export class ScriptManager {
|
|
|
121
148
|
return null;
|
|
122
149
|
}
|
|
123
150
|
if (!targetScript.source) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
});
|
|
128
|
-
targetScript.source = scriptSource;
|
|
129
|
-
targetScript.sourceLength = scriptSource.length;
|
|
130
|
-
this.buildKeywordIndex(targetScript.scriptId, targetScript.url, scriptSource);
|
|
131
|
-
this.chunkScript(targetScript.scriptId, scriptSource);
|
|
132
|
-
}
|
|
133
|
-
catch (error) {
|
|
134
|
-
logger.error(`Failed to get script source for ${targetScript.scriptId}:`, error);
|
|
151
|
+
const loaded = await this.loadScriptSourceInternal(targetScript);
|
|
152
|
+
if (!loaded) {
|
|
153
|
+
logger.error(`Failed to get script source for ${targetScript.scriptId}`);
|
|
135
154
|
return null;
|
|
136
155
|
}
|
|
137
156
|
}
|
|
@@ -166,7 +185,7 @@ export class ScriptManager {
|
|
|
166
185
|
: new RegExp(keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), caseSensitive ? 'g' : 'gi');
|
|
167
186
|
const matches = [];
|
|
168
187
|
const scripts = await this.getAllScripts(true, 500);
|
|
169
|
-
for (const script of scripts) {
|
|
188
|
+
for (const [scriptIndex, script] of scripts.entries()) {
|
|
170
189
|
if (!script.source)
|
|
171
190
|
continue;
|
|
172
191
|
if (matches.length >= maxMatches)
|
|
@@ -193,6 +212,12 @@ export class ScriptManager {
|
|
|
193
212
|
context,
|
|
194
213
|
});
|
|
195
214
|
}
|
|
215
|
+
if ((i + 1) % ScriptManager.SEARCH_LINE_YIELD_INTERVAL === 0) {
|
|
216
|
+
await waitForImmediate();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if ((scriptIndex + 1) % ScriptManager.SEARCH_SCRIPT_YIELD_INTERVAL === 0) {
|
|
220
|
+
await waitForImmediate();
|
|
196
221
|
}
|
|
197
222
|
}
|
|
198
223
|
logger.info(`searchInScripts: "${keyword}" - found ${matches.length} matches`);
|
|
@@ -12,8 +12,8 @@ export class EnvironmentEmulator {
|
|
|
12
12
|
llm;
|
|
13
13
|
constructor(llm) {
|
|
14
14
|
this.llm = llm;
|
|
15
|
-
if (llm) {
|
|
16
|
-
logger.
|
|
15
|
+
if (!llm) {
|
|
16
|
+
logger.debug('LLM service unavailable, skipping AI environment analysis');
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
async analyze(options) {
|
|
@@ -8,6 +8,7 @@ export declare class NetworkMonitor {
|
|
|
8
8
|
private responses;
|
|
9
9
|
private readonly MAX_NETWORK_RECORDS;
|
|
10
10
|
private readonly MAX_INJECTED_RECORDS;
|
|
11
|
+
private readonly JS_RESPONSE_CONCURRENCY;
|
|
11
12
|
private responseBodyCache;
|
|
12
13
|
private readonly MAX_BODY_CACHE_ENTRIES;
|
|
13
14
|
private networkListeners;
|