@jshookmcp/jshook 0.2.5 → 0.2.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/README.md +5 -5
- package/README.zh.md +5 -5
- package/dist/packages/extension-sdk/src/workflow.d.ts +17 -2
- package/dist/packages/extension-sdk/src/workflow.js +36 -0
- package/dist/src/modules/browser/BrowserPool.d.ts +49 -0
- package/dist/src/modules/browser/BrowserPool.js +288 -0
- package/dist/src/modules/deobfuscator/AdvancedDeobfuscator.d.ts +5 -0
- package/dist/src/modules/deobfuscator/AdvancedDeobfuscator.js +43 -2
- package/dist/src/modules/deobfuscator/Deobfuscator.js +5 -0
- package/dist/src/modules/external/ExternalToolRunner.js +1 -1
- package/dist/src/server/MCPServer.context.d.ts +1 -0
- package/dist/src/server/domains/browser/handlers/stealth-injection.d.ts +1 -0
- package/dist/src/server/domains/browser/handlers/stealth-injection.js +3 -0
- package/dist/src/server/domains/shared-state-board/definitions.d.ts +2 -0
- package/dist/src/server/domains/shared-state-board/definitions.js +78 -0
- package/dist/src/server/domains/shared-state-board/handlers.impl.d.ts +58 -0
- package/dist/src/server/domains/shared-state-board/handlers.impl.js +419 -0
- package/dist/src/server/domains/shared-state-board/index.d.ts +2 -0
- package/dist/src/server/domains/shared-state-board/index.js +2 -0
- package/dist/src/server/domains/shared-state-board/manifest.d.ts +57 -0
- package/dist/src/server/domains/shared-state-board/manifest.js +74 -0
- package/dist/src/server/http/SseStream.d.ts +21 -0
- package/dist/src/server/http/SseStream.js +129 -0
- package/dist/src/server/teams/TeamManager.d.ts +43 -0
- package/dist/src/server/teams/TeamManager.js +238 -0
- package/dist/src/server/teams/index.d.ts +1 -0
- package/dist/src/server/teams/index.js +1 -0
- package/dist/src/server/workflows/WorkflowContract.d.ts +20 -4
- package/dist/src/server/workflows/WorkflowContract.js +40 -0
- package/dist/src/server/workflows/WorkflowEngine.js +190 -13
- package/dist/src/types/deobfuscator.d.ts +1 -0
- package/dist/src/utils/cache/CachedDecorator.d.ts +8 -0
- package/dist/src/utils/cache/CachedDecorator.js +55 -0
- package/dist/src/utils/cache/PersistentCache.d.ts +33 -0
- package/dist/src/utils/cache/PersistentCache.js +246 -0
- package/dist/src/utils/cache/index.d.ts +2 -0
- package/dist/src/utils/cache/index.js +2 -0
- package/package.json +11 -12
- package/scripts/postinstall.cjs +54 -27
- package/workflows/anti-bot-diagnoser/.jshook-install.json +14 -0
- package/workflows/anti-bot-diagnoser/LICENSE +21 -0
- package/workflows/anti-bot-diagnoser/README.md +105 -0
- package/workflows/anti-bot-diagnoser/docs/agent-recipes.md +44 -0
- package/workflows/anti-bot-diagnoser/meta.yaml +6 -0
- package/workflows/anti-bot-diagnoser/package.json +22 -0
- package/workflows/anti-bot-diagnoser/tsconfig.json +15 -0
- package/workflows/anti-bot-diagnoser/workflow.ts +224 -0
- package/workflows/api-openapi-probe/.jshook-install.json +14 -0
- package/workflows/api-openapi-probe/meta.yaml +6 -0
- package/workflows/api-openapi-probe/package.json +22 -0
- package/workflows/api-openapi-probe/pnpm-lock.yaml +819 -0
- package/workflows/api-openapi-probe/tsconfig.json +15 -0
- package/workflows/api-openapi-probe/workflow.ts +40 -0
- package/workflows/api-probe-batch/.jshook-install.json +14 -0
- package/workflows/api-probe-batch/LICENSE +21 -0
- package/workflows/api-probe-batch/README.md +45 -0
- package/workflows/api-probe-batch/meta.yaml +4 -0
- package/workflows/api-probe-batch/package.json +23 -0
- package/workflows/api-probe-batch/tsconfig.json +16 -0
- package/workflows/api-probe-batch/workflow.ts +111 -0
- package/workflows/auth-bootstrap/.jshook-install.json +14 -0
- package/workflows/auth-bootstrap/LICENSE +21 -0
- package/workflows/auth-bootstrap/README.md +74 -0
- package/workflows/auth-bootstrap/meta.yaml +4 -0
- package/workflows/auth-bootstrap/package.json +23 -0
- package/workflows/auth-bootstrap/tsconfig.json +16 -0
- package/workflows/auth-bootstrap/workflow.ts +141 -0
- package/workflows/auth-extract/.jshook-install.json +14 -0
- package/workflows/auth-extract/meta.yaml +6 -0
- package/workflows/auth-extract/package.json +22 -0
- package/workflows/auth-extract/pnpm-lock.yaml +819 -0
- package/workflows/auth-extract/tsconfig.json +15 -0
- package/workflows/auth-extract/workflow.ts +36 -0
- package/workflows/auth-surface-mapper/.jshook-install.json +14 -0
- package/workflows/auth-surface-mapper/meta.yaml +6 -0
- package/workflows/auth-surface-mapper/package.json +22 -0
- package/workflows/auth-surface-mapper/pnpm-lock.yaml +819 -0
- package/workflows/auth-surface-mapper/tsconfig.json +15 -0
- package/workflows/auth-surface-mapper/workflow.ts +104 -0
- package/workflows/batch-register/.jshook-install.json +14 -0
- package/workflows/batch-register/LICENSE +21 -0
- package/workflows/batch-register/README.md +39 -0
- package/workflows/batch-register/meta.yaml +4 -0
- package/workflows/batch-register/package.json +23 -0
- package/workflows/batch-register/tsconfig.json +16 -0
- package/workflows/batch-register/workflow.ts +67 -0
- package/workflows/bundle-recovery/.jshook-install.json +14 -0
- package/workflows/bundle-recovery/LICENSE +21 -0
- package/workflows/bundle-recovery/README.md +105 -0
- package/workflows/bundle-recovery/docs/agent-recipes.md +44 -0
- package/workflows/bundle-recovery/meta.yaml +6 -0
- package/workflows/bundle-recovery/package.json +22 -0
- package/workflows/bundle-recovery/tsconfig.json +15 -0
- package/workflows/bundle-recovery/workflow.ts +179 -0
- package/workflows/challenge-detector/.jshook-install.json +14 -0
- package/workflows/challenge-detector/meta.yaml +14 -0
- package/workflows/challenge-detector/package.json +22 -0
- package/workflows/challenge-detector/pnpm-lock.yaml +819 -0
- package/workflows/challenge-detector/tsconfig.json +15 -0
- package/workflows/challenge-detector/workflow.ts +298 -0
- package/workflows/deobfuscation-pipeline/.jshook-install.json +14 -0
- package/workflows/deobfuscation-pipeline/meta.yaml +6 -0
- package/workflows/deobfuscation-pipeline/package.json +22 -0
- package/workflows/deobfuscation-pipeline/pnpm-lock.yaml +819 -0
- package/workflows/deobfuscation-pipeline/tsconfig.json +15 -0
- package/workflows/deobfuscation-pipeline/workflow.ts +119 -0
- package/workflows/electron-bridge-mapper/.jshook-install.json +14 -0
- package/workflows/electron-bridge-mapper/meta.yaml +6 -0
- package/workflows/electron-bridge-mapper/package.json +22 -0
- package/workflows/electron-bridge-mapper/pnpm-lock.yaml +819 -0
- package/workflows/electron-bridge-mapper/tsconfig.json +15 -0
- package/workflows/electron-bridge-mapper/workflow.ts +125 -0
- package/workflows/evidence-pack/.jshook-install.json +14 -0
- package/workflows/evidence-pack/LICENSE +21 -0
- package/workflows/evidence-pack/README.md +105 -0
- package/workflows/evidence-pack/docs/agent-recipes.md +44 -0
- package/workflows/evidence-pack/meta.yaml +6 -0
- package/workflows/evidence-pack/package.json +22 -0
- package/workflows/evidence-pack/tsconfig.json +15 -0
- package/workflows/evidence-pack/workflow.ts +154 -0
- package/workflows/js-bundle-search/.jshook-install.json +14 -0
- package/workflows/js-bundle-search/LICENSE +21 -0
- package/workflows/js-bundle-search/README.md +46 -0
- package/workflows/js-bundle-search/meta.yaml +4 -0
- package/workflows/js-bundle-search/package.json +23 -0
- package/workflows/js-bundle-search/tsconfig.json +16 -0
- package/workflows/js-bundle-search/workflow.ts +118 -0
- package/workflows/protocol-registry/.jshook-install.json +14 -0
- package/workflows/protocol-registry/meta.yaml +6 -0
- package/workflows/protocol-registry/package.json +22 -0
- package/workflows/protocol-registry/pnpm-lock.yaml +819 -0
- package/workflows/protocol-registry/tsconfig.json +15 -0
- package/workflows/protocol-registry/workflow.ts +107 -0
- package/workflows/qwen-mail-open-latest/meta.yaml +7 -0
- package/workflows/qwen-mail-open-latest/package.json +22 -0
- package/workflows/qwen-mail-open-latest/pnpm-lock.yaml +819 -0
- package/workflows/qwen-mail-open-latest/tsconfig.json +15 -0
- package/workflows/qwen-mail-open-latest/workflow.ts +77 -0
- package/workflows/register-account-flow/.jshook-install.json +14 -0
- package/workflows/register-account-flow/LICENSE +21 -0
- package/workflows/register-account-flow/README.md +64 -0
- package/workflows/register-account-flow/meta.yaml +4 -0
- package/workflows/register-account-flow/package.json +23 -0
- package/workflows/register-account-flow/tsconfig.json +16 -0
- package/workflows/register-account-flow/workflow.ts +127 -0
- package/workflows/replay-lab/.jshook-install.json +14 -0
- package/workflows/replay-lab/meta.yaml +6 -0
- package/workflows/replay-lab/package.json +22 -0
- package/workflows/replay-lab/pnpm-lock.yaml +819 -0
- package/workflows/replay-lab/tsconfig.json +15 -0
- package/workflows/replay-lab/workflow.ts +106 -0
- package/workflows/script-evidence-scan/.jshook-install.json +14 -0
- package/workflows/script-evidence-scan/LICENSE +21 -0
- package/workflows/script-evidence-scan/README.md +61 -0
- package/workflows/script-evidence-scan/meta.yaml +4 -0
- package/workflows/script-evidence-scan/package.json +23 -0
- package/workflows/script-evidence-scan/tsconfig.json +16 -0
- package/workflows/script-evidence-scan/workflow.ts +89 -0
- package/workflows/signature-hunter/.jshook-install.json +14 -0
- package/workflows/signature-hunter/LICENSE +21 -0
- package/workflows/signature-hunter/README.md +105 -0
- package/workflows/signature-hunter/docs/agent-recipes.md +44 -0
- package/workflows/signature-hunter/meta.yaml +6 -0
- package/workflows/signature-hunter/package.json +22 -0
- package/workflows/signature-hunter/tsconfig.json +15 -0
- package/workflows/signature-hunter/workflow.ts +170 -0
- package/workflows/signing-lineage/.jshook-install.json +14 -0
- package/workflows/signing-lineage/meta.yaml +6 -0
- package/workflows/signing-lineage/package.json +22 -0
- package/workflows/signing-lineage/pnpm-lock.yaml +819 -0
- package/workflows/signing-lineage/tsconfig.json +15 -0
- package/workflows/signing-lineage/workflow.ts +120 -0
- package/workflows/temp-mail-extract-link/.jshook-install.json +14 -0
- package/workflows/temp-mail-extract-link/LICENSE +21 -0
- package/workflows/temp-mail-extract-link/README.md +71 -0
- package/workflows/temp-mail-extract-link/meta.yaml +4 -0
- package/workflows/temp-mail-extract-link/package.json +23 -0
- package/workflows/temp-mail-extract-link/tsconfig.json +16 -0
- package/workflows/temp-mail-extract-link/workflow.ts +221 -0
- package/workflows/temp-mail-open-latest/.jshook-install.json +14 -0
- package/workflows/temp-mail-open-latest/LICENSE +21 -0
- package/workflows/temp-mail-open-latest/README.md +61 -0
- package/workflows/temp-mail-open-latest/meta.yaml +4 -0
- package/workflows/temp-mail-open-latest/package.json +23 -0
- package/workflows/temp-mail-open-latest/tsconfig.json +16 -0
- package/workflows/temp-mail-open-latest/workflow.ts +136 -0
- package/workflows/template/.jshook-install.json +14 -0
- package/workflows/template/LICENSE +21 -0
- package/workflows/template/README.md +45 -0
- package/workflows/template/docs/SKILL.md +111 -0
- package/workflows/template/meta.yaml +6 -0
- package/workflows/template/package.json +22 -0
- package/workflows/template/pnpm-lock.yaml +819 -0
- package/workflows/template/tsconfig.json +15 -0
- package/workflows/template/workflow.ts +73 -0
- package/workflows/web-api-capture-session/.jshook-install.json +14 -0
- package/workflows/web-api-capture-session/LICENSE +21 -0
- package/workflows/web-api-capture-session/README.md +64 -0
- package/workflows/web-api-capture-session/meta.yaml +4 -0
- package/workflows/web-api-capture-session/package.json +23 -0
- package/workflows/web-api-capture-session/tsconfig.json +16 -0
- package/workflows/web-api-capture-session/workflow.ts +124 -0
- package/workflows/ws-protocol-lifter/.jshook-install.json +14 -0
- package/workflows/ws-protocol-lifter/LICENSE +21 -0
- package/workflows/ws-protocol-lifter/README.md +105 -0
- package/workflows/ws-protocol-lifter/docs/agent-recipes.md +44 -0
- package/workflows/ws-protocol-lifter/meta.yaml +6 -0
- package/workflows/ws-protocol-lifter/package.json +22 -0
- package/workflows/ws-protocol-lifter/tsconfig.json +15 -0
- package/workflows/ws-protocol-lifter/workflow.ts +163 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @jshookmcp/jshook
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
|
-
[](https://nodejs.org/)
|
|
5
5
|
[](https://www.typescriptlang.org/)
|
|
6
6
|
[](https://modelcontextprotocol.io/)
|
|
7
7
|
[](https://pnpm.io/)
|
|
@@ -50,10 +50,10 @@ Provides a comprehensive suite of tools for AI-assisted JavaScript analysis, bro
|
|
|
50
50
|
The built-in surface below is generated from the runtime registry and checked in CI.
|
|
51
51
|
|
|
52
52
|
<!-- metadata-sync:start -->
|
|
53
|
-
- Package version: `0.2.
|
|
54
|
-
- Built-in domains: `
|
|
55
|
-
- Built-in tools: `
|
|
56
|
-
- Domains: `antidebug`, `browser`, `coordination`, `core`, `debugger`, `encoding`, `evidence`, `graphql`, `hooks`, `instrumentation`, `macro`, `maintenance`, `memory`, `network`, `platform`, `process`, `sandbox`, `sourcemap`, `streaming`, `trace`, `transform`, `wasm`, `workflow`
|
|
53
|
+
- Package version: `0.2.6`
|
|
54
|
+
- Built-in domains: `24`
|
|
55
|
+
- Built-in tools: `337`
|
|
56
|
+
- Domains: `antidebug`, `browser`, `coordination`, `core`, `debugger`, `encoding`, `evidence`, `graphql`, `hooks`, `instrumentation`, `macro`, `maintenance`, `memory`, `network`, `platform`, `process`, `sandbox`, `shared-state-board`, `sourcemap`, `streaming`, `trace`, `transform`, `wasm`, `workflow`
|
|
57
57
|
- Note: this snapshot is generated from the runtime registry; do not edit the counts by hand.
|
|
58
58
|
<!-- metadata-sync:end -->
|
|
59
59
|
|
package/README.zh.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @jshookmcp/jshook
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
|
-
[](https://nodejs.org/)
|
|
5
5
|
[](https://www.typescriptlang.org/)
|
|
6
6
|
[](https://modelcontextprotocol.io/)
|
|
7
7
|
[](https://pnpm.io/)
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
下面的内置能力快照由运行时 registry 动态生成,并在 CI 中校验。
|
|
51
51
|
|
|
52
52
|
<!-- metadata-sync:start -->
|
|
53
|
-
- 包版本:`0.2.
|
|
54
|
-
- 内置工具域:`
|
|
55
|
-
- 内置工具数:`
|
|
56
|
-
- 域列表:`antidebug`, `browser`, `coordination`, `core`, `debugger`, `encoding`, `evidence`, `graphql`, `hooks`, `instrumentation`, `macro`, `maintenance`, `memory`, `network`, `platform`, `process`, `sandbox`, `sourcemap`, `streaming`, `trace`, `transform`, `wasm`, `workflow`
|
|
53
|
+
- 包版本:`0.2.6`
|
|
54
|
+
- 内置工具域:`24`
|
|
55
|
+
- 内置工具数:`337`
|
|
56
|
+
- 域列表:`antidebug`, `browser`, `coordination`, `core`, `debugger`, `encoding`, `evidence`, `graphql`, `hooks`, `instrumentation`, `macro`, `maintenance`, `memory`, `network`, `platform`, `process`, `sandbox`, `shared-state-board`, `sourcemap`, `streaming`, `trace`, `transform`, `wasm`, `workflow`
|
|
57
57
|
- 说明:以上数据由运行时 registry 动态生成,不要手改计数。
|
|
58
58
|
<!-- metadata-sync:end -->
|
|
59
59
|
|
|
@@ -3,7 +3,7 @@ export interface RetryPolicy {
|
|
|
3
3
|
backoffMs: number;
|
|
4
4
|
multiplier?: number;
|
|
5
5
|
}
|
|
6
|
-
export type WorkflowNodeType = 'tool' | 'sequence' | 'parallel' | 'branch';
|
|
6
|
+
export type WorkflowNodeType = 'tool' | 'sequence' | 'parallel' | 'branch' | 'fallback';
|
|
7
7
|
export interface ToolNode {
|
|
8
8
|
readonly kind: 'tool';
|
|
9
9
|
readonly id: string;
|
|
@@ -32,7 +32,13 @@ export interface BranchNode {
|
|
|
32
32
|
readonly whenTrue: WorkflowNode;
|
|
33
33
|
readonly whenFalse?: WorkflowNode;
|
|
34
34
|
}
|
|
35
|
-
export
|
|
35
|
+
export interface FallbackNode {
|
|
36
|
+
readonly kind: 'fallback';
|
|
37
|
+
readonly id: string;
|
|
38
|
+
readonly primary: WorkflowNode;
|
|
39
|
+
readonly fallback: WorkflowNode;
|
|
40
|
+
}
|
|
41
|
+
export type WorkflowNode = ToolNode | SequenceNode | ParallelNode | BranchNode | FallbackNode;
|
|
36
42
|
export interface ToolNodeOptions {
|
|
37
43
|
input?: Record<string, unknown>;
|
|
38
44
|
retry?: RetryPolicy;
|
|
@@ -102,6 +108,7 @@ declare abstract class CompositeNodeBuilder<T extends WorkflowNode> extends Work
|
|
|
102
108
|
sequence(id: string, config?: (b: SequenceNodeBuilder) => void): this;
|
|
103
109
|
parallel(id: string, config?: (b: ParallelNodeBuilder) => void): this;
|
|
104
110
|
branch(id: string, predicateId: string, config?: (b: BranchNodeBuilder) => void): this;
|
|
111
|
+
fallback(id: string, config?: (b: FallbackNodeBuilder) => void): this;
|
|
105
112
|
}
|
|
106
113
|
export declare class SequenceNodeBuilder extends CompositeNodeBuilder<SequenceNode> {
|
|
107
114
|
build(): SequenceNode;
|
|
@@ -124,6 +131,13 @@ export declare class BranchNodeBuilder extends WorkflowNodeBuilder<BranchNode> {
|
|
|
124
131
|
whenFalse(nodeBuilder: AnyWorkflowNodeBuilder): this;
|
|
125
132
|
build(): BranchNode;
|
|
126
133
|
}
|
|
134
|
+
export declare class FallbackNodeBuilder extends WorkflowNodeBuilder<FallbackNode> {
|
|
135
|
+
private _primary?;
|
|
136
|
+
private _fallback?;
|
|
137
|
+
primary(nodeBuilder: AnyWorkflowNodeBuilder): this;
|
|
138
|
+
fallback(nodeBuilder: AnyWorkflowNodeBuilder): this;
|
|
139
|
+
build(): FallbackNode;
|
|
140
|
+
}
|
|
127
141
|
export declare class WorkflowBuilder {
|
|
128
142
|
private _id;
|
|
129
143
|
private _displayName;
|
|
@@ -153,4 +167,5 @@ export declare function toolNode(id: string, toolName: string): ToolNodeBuilder;
|
|
|
153
167
|
export declare function sequenceNode(id: string): SequenceNodeBuilder;
|
|
154
168
|
export declare function parallelNode(id: string): ParallelNodeBuilder;
|
|
155
169
|
export declare function branchNode(id: string, predicateId: string): BranchNodeBuilder;
|
|
170
|
+
export declare function fallbackNode(id: string): FallbackNodeBuilder;
|
|
156
171
|
export {};
|
|
@@ -81,6 +81,13 @@ class CompositeNodeBuilder extends WorkflowNodeBuilder {
|
|
|
81
81
|
this._steps.push(builder);
|
|
82
82
|
return this;
|
|
83
83
|
}
|
|
84
|
+
fallback(id, config) {
|
|
85
|
+
const builder = new FallbackNodeBuilder(id);
|
|
86
|
+
if (config)
|
|
87
|
+
config(builder);
|
|
88
|
+
this._steps.push(builder);
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
84
91
|
}
|
|
85
92
|
export class SequenceNodeBuilder extends CompositeNodeBuilder {
|
|
86
93
|
build() {
|
|
@@ -147,6 +154,32 @@ export class BranchNodeBuilder extends WorkflowNodeBuilder {
|
|
|
147
154
|
};
|
|
148
155
|
}
|
|
149
156
|
}
|
|
157
|
+
export class FallbackNodeBuilder extends WorkflowNodeBuilder {
|
|
158
|
+
_primary;
|
|
159
|
+
_fallback;
|
|
160
|
+
primary(nodeBuilder) {
|
|
161
|
+
this._primary = nodeBuilder;
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
fallback(nodeBuilder) {
|
|
165
|
+
this._fallback = nodeBuilder;
|
|
166
|
+
return this;
|
|
167
|
+
}
|
|
168
|
+
build() {
|
|
169
|
+
if (!this._primary) {
|
|
170
|
+
throw new Error(`FallbackNode '${this.id}' requires a primary step`);
|
|
171
|
+
}
|
|
172
|
+
if (!this._fallback) {
|
|
173
|
+
throw new Error(`FallbackNode '${this.id}' requires a fallback step`);
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
kind: 'fallback',
|
|
177
|
+
id: this.id,
|
|
178
|
+
primary: this._primary.build(),
|
|
179
|
+
fallback: this._fallback.build(),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
150
183
|
export class WorkflowBuilder {
|
|
151
184
|
_id;
|
|
152
185
|
_displayName;
|
|
@@ -234,3 +267,6 @@ export function parallelNode(id) {
|
|
|
234
267
|
export function branchNode(id, predicateId) {
|
|
235
268
|
return new BranchNodeBuilder(id, predicateId);
|
|
236
269
|
}
|
|
270
|
+
export function fallbackNode(id) {
|
|
271
|
+
return new FallbackNodeBuilder(id);
|
|
272
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Page as PuppeteerPage } from 'rebrowser-puppeteer-core';
|
|
2
|
+
import { UnifiedBrowserManager, type UnifiedBrowserConfig } from './UnifiedBrowserManager.js';
|
|
3
|
+
export interface BrowserProfile {
|
|
4
|
+
name: string;
|
|
5
|
+
config?: UnifiedBrowserConfig;
|
|
6
|
+
idleTimeout?: number;
|
|
7
|
+
maxTabs?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface BrowserPoolStats {
|
|
10
|
+
totalEntries: number;
|
|
11
|
+
inUseCount: number;
|
|
12
|
+
idleCount: number;
|
|
13
|
+
totalPages: number;
|
|
14
|
+
entries: Array<{
|
|
15
|
+
profile: string;
|
|
16
|
+
inUse: boolean;
|
|
17
|
+
pageCount: number;
|
|
18
|
+
lastAccess: Date;
|
|
19
|
+
disposed: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
export declare class BrowserPool {
|
|
23
|
+
private entries;
|
|
24
|
+
private defaultIdleTimeout;
|
|
25
|
+
private defaultMaxTabs;
|
|
26
|
+
private isDisposed;
|
|
27
|
+
private cleanupInterval?;
|
|
28
|
+
constructor(options?: {
|
|
29
|
+
defaultIdleTimeout?: number;
|
|
30
|
+
defaultMaxTabs?: number;
|
|
31
|
+
cleanupInterval?: number;
|
|
32
|
+
});
|
|
33
|
+
acquire(profile: BrowserProfile): Promise<UnifiedBrowserManager>;
|
|
34
|
+
release(instance: UnifiedBrowserManager): Promise<void>;
|
|
35
|
+
createTab(instance: UnifiedBrowserManager): Promise<PuppeteerPage>;
|
|
36
|
+
closeTab(instance: UnifiedBrowserManager, page: PuppeteerPage): Promise<void>;
|
|
37
|
+
getTabs(instance: UnifiedBrowserManager): PuppeteerPage[];
|
|
38
|
+
switchTab(instance: UnifiedBrowserManager, index: number): PuppeteerPage;
|
|
39
|
+
getStats(): BrowserPoolStats;
|
|
40
|
+
dispose(): Promise<void>;
|
|
41
|
+
disposeProfile(profileName: string): Promise<boolean>;
|
|
42
|
+
private findEntryByInstance;
|
|
43
|
+
private startIdleTimer;
|
|
44
|
+
private clearIdleTimer;
|
|
45
|
+
private disposeEntry;
|
|
46
|
+
private cleanupIdle;
|
|
47
|
+
private getMaxTabsForEntry;
|
|
48
|
+
private getMaxIdleTimeoutForEntry;
|
|
49
|
+
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
import { UnifiedBrowserManager } from './UnifiedBrowserManager.js';
|
|
3
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 5 * 60 * 1000;
|
|
4
|
+
const DEFAULT_MAX_TABS = 10;
|
|
5
|
+
export class BrowserPool {
|
|
6
|
+
entries = new Map();
|
|
7
|
+
defaultIdleTimeout;
|
|
8
|
+
defaultMaxTabs;
|
|
9
|
+
isDisposed = false;
|
|
10
|
+
cleanupInterval;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.defaultIdleTimeout = options?.defaultIdleTimeout ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
13
|
+
this.defaultMaxTabs = options?.defaultMaxTabs ?? DEFAULT_MAX_TABS;
|
|
14
|
+
const interval = options?.cleanupInterval ?? 60 * 1000;
|
|
15
|
+
this.cleanupInterval = setInterval(() => this.cleanupIdle(), interval);
|
|
16
|
+
}
|
|
17
|
+
async acquire(profile) {
|
|
18
|
+
if (this.isDisposed) {
|
|
19
|
+
throw new Error('BrowserPool has been disposed');
|
|
20
|
+
}
|
|
21
|
+
const existing = this.entries.get(profile.name);
|
|
22
|
+
if (existing && !existing.disposed) {
|
|
23
|
+
logger.debug(`[BrowserPool] Reusing browser for profile "${profile.name}"`);
|
|
24
|
+
existing.inUse = true;
|
|
25
|
+
existing.lastAccess = Date.now();
|
|
26
|
+
this.clearIdleTimer(existing);
|
|
27
|
+
return existing.manager;
|
|
28
|
+
}
|
|
29
|
+
if (existing) {
|
|
30
|
+
this.entries.delete(profile.name);
|
|
31
|
+
}
|
|
32
|
+
logger.info(`[BrowserPool] Creating new browser for profile "${profile.name}"`);
|
|
33
|
+
const config = {
|
|
34
|
+
driver: profile.config?.driver ?? 'chrome',
|
|
35
|
+
headless: profile.config?.headless,
|
|
36
|
+
args: profile.config?.args,
|
|
37
|
+
executablePath: profile.config?.executablePath,
|
|
38
|
+
debugPort: profile.config?.debugPort,
|
|
39
|
+
proxy: profile.config?.proxy,
|
|
40
|
+
os: profile.config?.os,
|
|
41
|
+
geoip: profile.config?.geoip,
|
|
42
|
+
};
|
|
43
|
+
const manager = new UnifiedBrowserManager(config);
|
|
44
|
+
await manager.launch();
|
|
45
|
+
const browser = manager.getBrowser();
|
|
46
|
+
const entry = {
|
|
47
|
+
profile: profile.name,
|
|
48
|
+
manager,
|
|
49
|
+
browser,
|
|
50
|
+
pages: [],
|
|
51
|
+
lastAccess: Date.now(),
|
|
52
|
+
inUse: true,
|
|
53
|
+
disposed: false,
|
|
54
|
+
profileConfig: profile,
|
|
55
|
+
};
|
|
56
|
+
this.entries.set(profile.name, entry);
|
|
57
|
+
logger.debug(`[BrowserPool] Browser acquired for profile "${profile.name}"`);
|
|
58
|
+
return manager;
|
|
59
|
+
}
|
|
60
|
+
async release(instance) {
|
|
61
|
+
if (this.isDisposed) {
|
|
62
|
+
logger.warn('[BrowserPool] Cannot release: pool is disposed');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const entry = this.findEntryByInstance(instance);
|
|
66
|
+
if (!entry) {
|
|
67
|
+
logger.warn('[BrowserPool] Instance not found in pool, skipping release');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!entry.inUse) {
|
|
71
|
+
logger.warn(`[BrowserPool] Profile "${entry.profile}" was not in use`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
entry.inUse = false;
|
|
75
|
+
entry.lastAccess = Date.now();
|
|
76
|
+
this.startIdleTimer(entry);
|
|
77
|
+
logger.debug(`[BrowserPool] Released browser for profile "${entry.profile}"`);
|
|
78
|
+
}
|
|
79
|
+
async createTab(instance) {
|
|
80
|
+
const entry = this.findEntryByInstance(instance);
|
|
81
|
+
if (!entry) {
|
|
82
|
+
throw new Error('Browser instance not found in pool');
|
|
83
|
+
}
|
|
84
|
+
if (entry.disposed) {
|
|
85
|
+
throw new Error(`Browser for profile "${entry.profile}" has been disposed`);
|
|
86
|
+
}
|
|
87
|
+
if (entry.browser === null) {
|
|
88
|
+
throw new Error(`Browser for profile "${entry.profile}" has no browser instance`);
|
|
89
|
+
}
|
|
90
|
+
const maxTabs = this.getMaxTabsForEntry(entry);
|
|
91
|
+
if (entry.pages.length >= maxTabs) {
|
|
92
|
+
throw new Error(`Maximum tabs (${maxTabs}) reached for profile "${entry.profile}". Close some tabs first.`);
|
|
93
|
+
}
|
|
94
|
+
const page = await entry.browser.newPage();
|
|
95
|
+
entry.pages.push(page);
|
|
96
|
+
entry.lastAccess = Date.now();
|
|
97
|
+
logger.debug(`[BrowserPool] Created new tab in profile "${entry.profile}" (total: ${entry.pages.length})`);
|
|
98
|
+
page.on('close', () => {
|
|
99
|
+
const index = entry.pages.indexOf(page);
|
|
100
|
+
if (index !== -1) {
|
|
101
|
+
entry.pages.splice(index, 1);
|
|
102
|
+
logger.debug(`[BrowserPool] Tab closed in profile "${entry.profile}" (remaining: ${entry.pages.length})`);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return page;
|
|
106
|
+
}
|
|
107
|
+
async closeTab(instance, page) {
|
|
108
|
+
const entry = this.findEntryByInstance(instance);
|
|
109
|
+
if (!entry) {
|
|
110
|
+
throw new Error('Browser instance not found in pool');
|
|
111
|
+
}
|
|
112
|
+
if (entry.browser === null) {
|
|
113
|
+
throw new Error(`Browser for profile "${entry.profile}" has no browser instance`);
|
|
114
|
+
}
|
|
115
|
+
const index = entry.pages.indexOf(page);
|
|
116
|
+
if (index === -1) {
|
|
117
|
+
throw new Error('Page not found in this browser instance');
|
|
118
|
+
}
|
|
119
|
+
await page.close();
|
|
120
|
+
entry.lastAccess = Date.now();
|
|
121
|
+
logger.debug(`[BrowserPool] Closed tab in profile "${entry.profile}"`);
|
|
122
|
+
}
|
|
123
|
+
getTabs(instance) {
|
|
124
|
+
const entry = this.findEntryByInstance(instance);
|
|
125
|
+
if (!entry) {
|
|
126
|
+
throw new Error('Browser instance not found in pool');
|
|
127
|
+
}
|
|
128
|
+
return [...entry.pages];
|
|
129
|
+
}
|
|
130
|
+
switchTab(instance, index) {
|
|
131
|
+
const tabs = this.getTabs(instance);
|
|
132
|
+
if (index < 0 || index >= tabs.length) {
|
|
133
|
+
throw new Error(`Invalid tab index ${index}. Available tabs: 0-${tabs.length - 1} (total: ${tabs.length})`);
|
|
134
|
+
}
|
|
135
|
+
return tabs[index];
|
|
136
|
+
}
|
|
137
|
+
getStats() {
|
|
138
|
+
const entries = [];
|
|
139
|
+
let inUseCount = 0;
|
|
140
|
+
let idleCount = 0;
|
|
141
|
+
let totalPages = 0;
|
|
142
|
+
for (const [, entry] of this.entries) {
|
|
143
|
+
if (entry.inUse) {
|
|
144
|
+
inUseCount++;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
idleCount++;
|
|
148
|
+
}
|
|
149
|
+
totalPages += entry.pages.length;
|
|
150
|
+
entries.push({
|
|
151
|
+
profile: entry.profile,
|
|
152
|
+
inUse: entry.inUse,
|
|
153
|
+
pageCount: entry.pages.length,
|
|
154
|
+
lastAccess: new Date(entry.lastAccess),
|
|
155
|
+
disposed: entry.disposed,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
totalEntries: this.entries.size,
|
|
160
|
+
inUseCount,
|
|
161
|
+
idleCount,
|
|
162
|
+
totalPages,
|
|
163
|
+
entries,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
async dispose() {
|
|
167
|
+
logger.info('[BrowserPool] Disposing pool...');
|
|
168
|
+
this.isDisposed = true;
|
|
169
|
+
if (this.cleanupInterval) {
|
|
170
|
+
clearInterval(this.cleanupInterval);
|
|
171
|
+
this.cleanupInterval = undefined;
|
|
172
|
+
}
|
|
173
|
+
const closePromises = [];
|
|
174
|
+
for (const [, entry] of this.entries) {
|
|
175
|
+
closePromises.push(this.disposeEntry(entry));
|
|
176
|
+
}
|
|
177
|
+
await Promise.all(closePromises);
|
|
178
|
+
this.entries.clear();
|
|
179
|
+
logger.info('[BrowserPool] Pool disposed successfully');
|
|
180
|
+
}
|
|
181
|
+
async disposeProfile(profileName) {
|
|
182
|
+
const entry = this.entries.get(profileName);
|
|
183
|
+
if (!entry) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
await this.disposeEntry(entry);
|
|
187
|
+
this.entries.delete(profileName);
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
findEntryByInstance(instance) {
|
|
191
|
+
for (const [, entry] of this.entries) {
|
|
192
|
+
if (entry.manager === instance) {
|
|
193
|
+
return entry;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
startIdleTimer(entry) {
|
|
199
|
+
this.clearIdleTimer(entry);
|
|
200
|
+
const timeout = this.getMaxIdleTimeoutForEntry(entry);
|
|
201
|
+
entry.idleTimer = setTimeout(() => {
|
|
202
|
+
if (!entry.inUse && !entry.disposed) {
|
|
203
|
+
logger.info(`[BrowserPool] Auto-disposing idle browser for profile "${entry.profile}" (idle > ${timeout}ms)`);
|
|
204
|
+
this.disposeEntry(entry).catch((error) => {
|
|
205
|
+
logger.error(`[BrowserPool] Failed to dispose idle entry: ${String(error)}`);
|
|
206
|
+
});
|
|
207
|
+
this.entries.delete(entry.profile);
|
|
208
|
+
}
|
|
209
|
+
}, timeout);
|
|
210
|
+
}
|
|
211
|
+
clearIdleTimer(entry) {
|
|
212
|
+
if (entry.idleTimer) {
|
|
213
|
+
clearTimeout(entry.idleTimer);
|
|
214
|
+
entry.idleTimer = undefined;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async disposeEntry(entry) {
|
|
218
|
+
if (entry.disposed) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
entry.disposed = true;
|
|
222
|
+
this.clearIdleTimer(entry);
|
|
223
|
+
try {
|
|
224
|
+
const closePages = entry.pages.map(async (page) => {
|
|
225
|
+
try {
|
|
226
|
+
if (!page.isClosed()) {
|
|
227
|
+
await page.close();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
logger.warn(`[BrowserPool] Failed to close page: ${String(error)}`);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
await Promise.all(closePages);
|
|
235
|
+
entry.pages = [];
|
|
236
|
+
await entry.manager.close();
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
logger.error(`[BrowserPool] Failed to dispose entry "${entry.profile}": ${error instanceof Error ? error.message : String(error)}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
cleanupIdle() {
|
|
243
|
+
if (this.isDisposed) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const now = Date.now();
|
|
247
|
+
const toDispose = [];
|
|
248
|
+
for (const [profile, entry] of this.entries) {
|
|
249
|
+
if (!entry.inUse && !entry.disposed) {
|
|
250
|
+
const timeout = this.getMaxIdleTimeoutForEntry(entry);
|
|
251
|
+
if (now - entry.lastAccess > timeout) {
|
|
252
|
+
toDispose.push(profile);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
for (const profile of toDispose) {
|
|
257
|
+
const entry = this.entries.get(profile);
|
|
258
|
+
if (entry) {
|
|
259
|
+
logger.debug(`[BrowserPool] Cleanup: disposing idle profile "${profile}" (last accessed ${new Date(entry.lastAccess).toISOString()})`);
|
|
260
|
+
this.disposeEntry(entry).catch((error) => {
|
|
261
|
+
logger.error(`[BrowserPool] Cleanup failed for "${profile}": ${String(error)}`);
|
|
262
|
+
});
|
|
263
|
+
this.entries.delete(profile);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (toDispose.length > 0) {
|
|
267
|
+
logger.info(`[BrowserPool] Cleanup: disposed ${toDispose.length} idle profiles`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
getMaxTabsForEntry(entry) {
|
|
271
|
+
const managerWithTabLimit = entry.manager;
|
|
272
|
+
const managerLimit = typeof managerWithTabLimit.getMaxTabs === 'function'
|
|
273
|
+
? managerWithTabLimit.getMaxTabs()
|
|
274
|
+
: undefined;
|
|
275
|
+
return typeof managerLimit === 'number'
|
|
276
|
+
? managerLimit
|
|
277
|
+
: (entry.profileConfig.maxTabs ?? this.defaultMaxTabs);
|
|
278
|
+
}
|
|
279
|
+
getMaxIdleTimeoutForEntry(entry) {
|
|
280
|
+
const managerWithIdleTimeout = entry.manager;
|
|
281
|
+
const managerTimeout = typeof managerWithIdleTimeout.getIdleTimeout === 'function'
|
|
282
|
+
? managerWithIdleTimeout.getIdleTimeout()
|
|
283
|
+
: undefined;
|
|
284
|
+
return typeof managerTimeout === 'number'
|
|
285
|
+
? managerTimeout
|
|
286
|
+
: (entry.profileConfig.idleTimeout ?? this.defaultIdleTimeout);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
@@ -20,6 +20,7 @@ export interface AdvancedDeobfuscateResult {
|
|
|
20
20
|
detectedTechniques: string[];
|
|
21
21
|
confidence: number;
|
|
22
22
|
warnings: string[];
|
|
23
|
+
cached?: boolean;
|
|
23
24
|
astOptimized?: boolean;
|
|
24
25
|
bundle?: DeobfuscateBundleSummary;
|
|
25
26
|
savedTo?: string;
|
|
@@ -33,6 +34,10 @@ export interface AdvancedDeobfuscateResult {
|
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
export declare class AdvancedDeobfuscator {
|
|
37
|
+
private resultCache;
|
|
38
|
+
private maxCacheSize;
|
|
39
|
+
private generateCacheKey;
|
|
36
40
|
deobfuscate(options: AdvancedDeobfuscateOptions): Promise<AdvancedDeobfuscateResult>;
|
|
41
|
+
private storeCacheEntry;
|
|
37
42
|
private calculateConfidence;
|
|
38
43
|
}
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import { logger } from '../../utils/logger.js';
|
|
2
2
|
import { runWebcrack } from '../deobfuscator/webcrack.js';
|
|
3
3
|
import { detectObfuscationType as detectObfuscationTypeUtil } from '../deobfuscator/Deobfuscator.utils.js';
|
|
4
|
+
import crypto from 'crypto';
|
|
4
5
|
export class AdvancedDeobfuscator {
|
|
6
|
+
resultCache = new Map();
|
|
7
|
+
maxCacheSize = 100;
|
|
8
|
+
generateCacheKey(options) {
|
|
9
|
+
const key = JSON.stringify({
|
|
10
|
+
aggressiveVM: options.aggressiveVM,
|
|
11
|
+
code: options.code.substring(0, 2000),
|
|
12
|
+
detectOnly: options.detectOnly,
|
|
13
|
+
forceOutput: options.forceOutput,
|
|
14
|
+
includeModuleCode: options.includeModuleCode,
|
|
15
|
+
jsx: options.jsx,
|
|
16
|
+
mangle: options.mangle,
|
|
17
|
+
mappings: options.mappings,
|
|
18
|
+
maxBundleModules: options.maxBundleModules,
|
|
19
|
+
outputDir: options.outputDir,
|
|
20
|
+
timeout: options.timeout,
|
|
21
|
+
unpack: options.unpack,
|
|
22
|
+
unminify: options.unminify,
|
|
23
|
+
useASTOptimization: options.useASTOptimization,
|
|
24
|
+
});
|
|
25
|
+
return crypto.createHash('md5').update(key).digest('hex');
|
|
26
|
+
}
|
|
5
27
|
async deobfuscate(options) {
|
|
28
|
+
const cacheKey = this.generateCacheKey(options);
|
|
29
|
+
const cached = this.resultCache.get(cacheKey);
|
|
30
|
+
if (cached) {
|
|
31
|
+
logger.debug('Advanced deobfuscation result from cache');
|
|
32
|
+
return { ...cached, cached: true };
|
|
33
|
+
}
|
|
6
34
|
logger.info('Starting advanced webcrack deobfuscation...');
|
|
7
35
|
const detectedTechniques = detectObfuscationTypeUtil(options.code);
|
|
8
36
|
const warnings = [];
|
|
@@ -16,7 +44,7 @@ export class AdvancedDeobfuscator {
|
|
|
16
44
|
warnings.push('timeout is currently ignored; webcrack controls its own execution flow.');
|
|
17
45
|
}
|
|
18
46
|
if (options.detectOnly) {
|
|
19
|
-
|
|
47
|
+
const result = {
|
|
20
48
|
code: options.code,
|
|
21
49
|
detectedTechniques,
|
|
22
50
|
confidence: Math.min(0.6 + detectedTechniques.length * 0.05, 0.9),
|
|
@@ -28,6 +56,8 @@ export class AdvancedDeobfuscator {
|
|
|
28
56
|
engine: 'webcrack',
|
|
29
57
|
webcrackApplied: false,
|
|
30
58
|
};
|
|
59
|
+
this.storeCacheEntry(cacheKey, result);
|
|
60
|
+
return { ...result, cached: false };
|
|
31
61
|
}
|
|
32
62
|
const webcrackResult = await runWebcrack(options.code, {
|
|
33
63
|
unpack: options.unpack,
|
|
@@ -58,7 +88,7 @@ export class AdvancedDeobfuscator {
|
|
|
58
88
|
detectedTechniques.push('mangle');
|
|
59
89
|
}
|
|
60
90
|
detectedTechniques.push('webcrack');
|
|
61
|
-
|
|
91
|
+
const result = {
|
|
62
92
|
code: webcrackResult.code,
|
|
63
93
|
detectedTechniques: Array.from(new Set(detectedTechniques)),
|
|
64
94
|
confidence: this.calculateConfidence(webcrackResult, detectedTechniques),
|
|
@@ -70,6 +100,17 @@ export class AdvancedDeobfuscator {
|
|
|
70
100
|
engine: 'webcrack',
|
|
71
101
|
webcrackApplied: true,
|
|
72
102
|
};
|
|
103
|
+
this.storeCacheEntry(cacheKey, result);
|
|
104
|
+
return { ...result, cached: false };
|
|
105
|
+
}
|
|
106
|
+
storeCacheEntry(cacheKey, result) {
|
|
107
|
+
if (this.resultCache.size >= this.maxCacheSize) {
|
|
108
|
+
const firstKey = this.resultCache.keys().next().value;
|
|
109
|
+
if (firstKey) {
|
|
110
|
+
this.resultCache.delete(firstKey);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
this.resultCache.set(cacheKey, result);
|
|
73
114
|
}
|
|
74
115
|
calculateConfidence(webcrackResult, detectedTechniques) {
|
|
75
116
|
let confidence = 0.72 + detectedTechniques.length * 0.03;
|
|
@@ -10,15 +10,18 @@ export class Deobfuscator {
|
|
|
10
10
|
}
|
|
11
11
|
generateCacheKey(options) {
|
|
12
12
|
const key = JSON.stringify({
|
|
13
|
+
aggressive: options.aggressive,
|
|
13
14
|
code: options.code.substring(0, 2000),
|
|
14
15
|
forceOutput: options.forceOutput,
|
|
15
16
|
includeModuleCode: options.includeModuleCode,
|
|
17
|
+
inlineFunctions: options.inlineFunctions,
|
|
16
18
|
jsx: options.jsx,
|
|
17
19
|
llm: false,
|
|
18
20
|
mangle: options.mangle ?? options.renameVariables,
|
|
19
21
|
mappings: options.mappings,
|
|
20
22
|
maxBundleModules: options.maxBundleModules,
|
|
21
23
|
outputDir: options.outputDir,
|
|
24
|
+
preserveLogic: options.preserveLogic,
|
|
22
25
|
unpack: options.unpack,
|
|
23
26
|
unminify: options.unminify,
|
|
24
27
|
});
|
|
@@ -29,6 +32,7 @@ export class Deobfuscator {
|
|
|
29
32
|
const cached = this.resultCache.get(cacheKey);
|
|
30
33
|
if (cached) {
|
|
31
34
|
logger.debug('Deobfuscation result from cache');
|
|
35
|
+
cached.cached = true;
|
|
32
36
|
return cached;
|
|
33
37
|
}
|
|
34
38
|
logger.info('Starting webcrack deobfuscation...');
|
|
@@ -110,6 +114,7 @@ export class Deobfuscator {
|
|
|
110
114
|
this.resultCache.delete(firstKey);
|
|
111
115
|
}
|
|
112
116
|
}
|
|
117
|
+
result.cached = false;
|
|
113
118
|
this.resultCache.set(cacheKey, result);
|
|
114
119
|
return result;
|
|
115
120
|
}
|
|
@@ -158,7 +158,7 @@ export class ExternalToolRunner {
|
|
|
158
158
|
const resolved = resolve(requestedCwd);
|
|
159
159
|
const projectRoot = getProjectRoot();
|
|
160
160
|
const rel = relative(projectRoot, resolved);
|
|
161
|
-
if (rel && !rel.startsWith('..') && !isAbsolute(rel)
|
|
161
|
+
if (rel && !rel.startsWith('..') && !isAbsolute(rel)) {
|
|
162
162
|
return resolved;
|
|
163
163
|
}
|
|
164
164
|
const tmpDirs = [process.env.TEMP, process.env.TMP, '/tmp', '/var/tmp'].filter(Boolean);
|
|
@@ -91,6 +91,7 @@ export interface DomainInstances {
|
|
|
91
91
|
traceHandlers?: import('./domains/trace/index.js').TraceToolHandlers;
|
|
92
92
|
evidenceHandlers?: import('./domains/evidence/index.js').EvidenceHandlers;
|
|
93
93
|
instrumentationHandlers?: import('./domains/instrumentation/index.js').InstrumentationHandlers | undefined;
|
|
94
|
+
sharedStateBoardHandlers?: import('./domains/shared-state-board/index.js').SharedStateBoardHandlers;
|
|
94
95
|
}
|
|
95
96
|
export interface ServerMethods {
|
|
96
97
|
registerCaches(): Promise<void>;
|
|
@@ -5,6 +5,7 @@ interface StealthInjectionHandlersDeps {
|
|
|
5
5
|
pageController: PageController;
|
|
6
6
|
getActiveDriver: () => 'chrome' | 'camoufox';
|
|
7
7
|
}
|
|
8
|
+
export declare function _resetFingerprintCacheForTesting(): void;
|
|
8
9
|
export declare class StealthInjectionHandlers {
|
|
9
10
|
private deps;
|
|
10
11
|
constructor(deps: StealthInjectionHandlersDeps);
|