@aluvia/sdk 1.1.0 → 1.4.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.
- package/README.md +410 -285
- package/dist/cjs/api/account.js +10 -74
- package/dist/cjs/api/apiUtils.js +80 -0
- package/dist/cjs/api/geos.js +2 -63
- package/dist/cjs/api/request.js +8 -2
- package/dist/cjs/bin/account.js +31 -0
- package/dist/cjs/bin/api-helpers.js +58 -0
- package/dist/cjs/bin/cli-adapter.js +16 -0
- package/dist/cjs/bin/cli.js +245 -0
- package/dist/cjs/bin/close.js +120 -0
- package/dist/cjs/bin/geos.js +10 -0
- package/dist/cjs/bin/mcp-helpers.js +57 -0
- package/dist/cjs/bin/mcp-server.js +220 -0
- package/dist/cjs/bin/mcp-tools.js +90 -0
- package/dist/cjs/bin/open.js +293 -0
- package/dist/cjs/bin/session.js +259 -0
- package/dist/cjs/client/AluviaClient.js +365 -189
- package/dist/cjs/client/BlockDetection.js +486 -0
- package/dist/cjs/client/ConfigManager.js +26 -23
- package/dist/cjs/client/PageLoadDetection.js +175 -0
- package/dist/cjs/client/ProxyServer.js +4 -2
- package/dist/cjs/client/logger.js +4 -0
- package/dist/cjs/client/rules.js +38 -49
- package/dist/cjs/connect.js +117 -0
- package/dist/cjs/errors.js +12 -1
- package/dist/cjs/index.js +5 -1
- package/dist/cjs/session/lock.js +186 -0
- package/dist/esm/api/account.js +2 -66
- package/dist/esm/api/apiUtils.js +71 -0
- package/dist/esm/api/geos.js +2 -63
- package/dist/esm/api/request.js +8 -2
- package/dist/esm/bin/account.js +28 -0
- package/dist/esm/bin/api-helpers.js +53 -0
- package/dist/esm/bin/cli-adapter.js +8 -0
- package/dist/esm/bin/cli.js +242 -0
- package/dist/esm/bin/close.js +117 -0
- package/dist/esm/bin/geos.js +7 -0
- package/dist/esm/bin/mcp-helpers.js +51 -0
- package/dist/esm/bin/mcp-server.js +185 -0
- package/dist/esm/bin/mcp-tools.js +78 -0
- package/dist/esm/bin/open.js +256 -0
- package/dist/esm/bin/session.js +252 -0
- package/dist/esm/client/AluviaClient.js +371 -195
- package/dist/esm/client/BlockDetection.js +482 -0
- package/dist/esm/client/ConfigManager.js +21 -18
- package/dist/esm/client/PageLoadDetection.js +171 -0
- package/dist/esm/client/ProxyServer.js +5 -3
- package/dist/esm/client/logger.js +4 -0
- package/dist/esm/client/rules.js +36 -49
- package/dist/esm/connect.js +81 -0
- package/dist/esm/errors.js +10 -0
- package/dist/esm/index.js +5 -3
- package/dist/esm/session/lock.js +142 -0
- package/dist/types/api/AluviaApi.d.ts +2 -7
- package/dist/types/api/account.d.ts +1 -16
- package/dist/types/api/apiUtils.d.ts +28 -0
- package/dist/types/api/geos.d.ts +1 -1
- package/dist/types/bin/account.d.ts +1 -0
- package/dist/types/bin/api-helpers.d.ts +20 -0
- package/dist/types/bin/cli-adapter.d.ts +8 -0
- package/dist/types/bin/cli.d.ts +2 -0
- package/dist/types/bin/close.d.ts +1 -0
- package/dist/types/bin/geos.d.ts +1 -0
- package/dist/types/bin/mcp-helpers.d.ts +28 -0
- package/dist/types/bin/mcp-server.d.ts +2 -0
- package/dist/types/bin/mcp-tools.d.ts +46 -0
- package/dist/types/bin/open.d.ts +21 -0
- package/dist/types/bin/session.d.ts +11 -0
- package/dist/types/client/AluviaClient.d.ts +51 -4
- package/dist/types/client/BlockDetection.d.ts +96 -0
- package/dist/types/client/ConfigManager.d.ts +6 -1
- package/dist/types/client/PageLoadDetection.d.ts +93 -0
- package/dist/types/client/logger.d.ts +2 -0
- package/dist/types/client/rules.d.ts +18 -0
- package/dist/types/client/types.d.ts +48 -47
- package/dist/types/connect.d.ts +18 -0
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/index.d.ts +7 -5
- package/dist/types/session/lock.d.ts +43 -0
- package/package.json +21 -12
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-exports for @aluvia/mcp. MCP package imports from @aluvia/sdk/cli.
|
|
3
|
+
*/
|
|
4
|
+
export { handleSession } from "./session.js";
|
|
5
|
+
export { handleAccount } from "./account.js";
|
|
6
|
+
export { handleGeos } from "./geos.js";
|
|
7
|
+
export { handleOpen } from "./open.js";
|
|
8
|
+
export { captureOutput } from "./mcp-helpers.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function handleClose(sessionName?: string, closeAll?: boolean): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function handleGeos(): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP output capture helpers.
|
|
3
|
+
*
|
|
4
|
+
* The CLI handlers call `output()` which normally does `console.log` + `process.exit()`.
|
|
5
|
+
* In MCP mode, we switch `output()` to throw an MCPOutputCapture instead,
|
|
6
|
+
* allowing us to catch and return the data without exiting the process.
|
|
7
|
+
*
|
|
8
|
+
* Uses AsyncLocalStorage so concurrent MCP tool calls don't interfere.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Thrown by output() when in capture mode.
|
|
12
|
+
* Contains the JSON data and exit code that would have been written to stdout.
|
|
13
|
+
*/
|
|
14
|
+
export declare class MCPOutputCapture {
|
|
15
|
+
readonly data: Record<string, unknown>;
|
|
16
|
+
readonly exitCode: number;
|
|
17
|
+
constructor(data: Record<string, unknown>, exitCode: number);
|
|
18
|
+
}
|
|
19
|
+
export declare function isCapturing(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Run a CLI handler function in capture mode.
|
|
22
|
+
* Returns the data that output() would have written to stdout.
|
|
23
|
+
* Safe for concurrent use — each call gets its own async context.
|
|
24
|
+
*/
|
|
25
|
+
export declare function captureOutput(fn: () => Promise<void> | void): Promise<{
|
|
26
|
+
data: Record<string, unknown>;
|
|
27
|
+
isError: boolean;
|
|
28
|
+
}>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool implementations.
|
|
3
|
+
*
|
|
4
|
+
* Each tool wraps the corresponding CLI handler via captureOutput(),
|
|
5
|
+
* converting the handler's JSON output into MCP tool results.
|
|
6
|
+
*/
|
|
7
|
+
type ToolResult = {
|
|
8
|
+
data: Record<string, unknown>;
|
|
9
|
+
isError: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function sessionStart(args: {
|
|
12
|
+
url: string;
|
|
13
|
+
connectionId?: number;
|
|
14
|
+
headful?: boolean;
|
|
15
|
+
browserSession?: string;
|
|
16
|
+
autoUnblock?: boolean;
|
|
17
|
+
disableBlockDetection?: boolean;
|
|
18
|
+
}): Promise<ToolResult>;
|
|
19
|
+
export declare function sessionClose(args: {
|
|
20
|
+
browserSession?: string;
|
|
21
|
+
all?: boolean;
|
|
22
|
+
}): Promise<ToolResult>;
|
|
23
|
+
export declare function sessionList(): Promise<ToolResult>;
|
|
24
|
+
export declare function sessionGet(args: {
|
|
25
|
+
browserSession?: string;
|
|
26
|
+
}): Promise<ToolResult>;
|
|
27
|
+
export declare function sessionRotateIp(args: {
|
|
28
|
+
browserSession?: string;
|
|
29
|
+
}): Promise<ToolResult>;
|
|
30
|
+
export declare function sessionSetGeo(args: {
|
|
31
|
+
geo?: string;
|
|
32
|
+
clear?: boolean;
|
|
33
|
+
browserSession?: string;
|
|
34
|
+
}): Promise<ToolResult>;
|
|
35
|
+
export declare function sessionSetRules(args: {
|
|
36
|
+
rules?: string;
|
|
37
|
+
remove?: string;
|
|
38
|
+
browserSession?: string;
|
|
39
|
+
}): Promise<ToolResult>;
|
|
40
|
+
export declare function accountGet(): Promise<ToolResult>;
|
|
41
|
+
export declare function accountUsage(args: {
|
|
42
|
+
start?: string;
|
|
43
|
+
end?: string;
|
|
44
|
+
}): Promise<ToolResult>;
|
|
45
|
+
export declare function geosList(): Promise<ToolResult>;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type OpenOptions = {
|
|
2
|
+
url: string;
|
|
3
|
+
connectionId?: number;
|
|
4
|
+
headless?: boolean;
|
|
5
|
+
sessionName?: string;
|
|
6
|
+
autoUnblock?: boolean;
|
|
7
|
+
disableBlockDetection?: boolean;
|
|
8
|
+
run?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Called from cli.ts when running `session start <url>`.
|
|
12
|
+
* Spawns the actual browser in a detached child and polls until ready.
|
|
13
|
+
* Returns a Promise that resolves via process.exit() (never returns normally).
|
|
14
|
+
*/
|
|
15
|
+
export declare function handleOpen({ url, connectionId, headless, sessionName, autoUnblock, disableBlockDetection, run }: OpenOptions): Promise<never>;
|
|
16
|
+
/**
|
|
17
|
+
* Daemon entry point — runs in the detached child process.
|
|
18
|
+
* Starts the proxy + browser, writes lock, and stays alive.
|
|
19
|
+
* Logs go to the daemon log file (stdout is redirected), not to the user.
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleOpenDaemon({ url, connectionId, headless, sessionName, autoUnblock, disableBlockDetection, run }: OpenOptions): Promise<void>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type ParsedSessionArgs = {
|
|
2
|
+
url?: string;
|
|
3
|
+
connectionId?: number;
|
|
4
|
+
headed: boolean;
|
|
5
|
+
sessionName?: string;
|
|
6
|
+
autoUnblock: boolean;
|
|
7
|
+
disableBlockDetection: boolean;
|
|
8
|
+
run?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function parseSessionArgs(args: string[]): ParsedSessionArgs;
|
|
11
|
+
export declare function handleSession(args: string[]): Promise<void>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AluviaClientConnection, AluviaClientOptions } from
|
|
2
|
-
import { AluviaApi } from
|
|
1
|
+
import type { AluviaClientConnection, AluviaClientOptions } from "./types.js";
|
|
2
|
+
import { AluviaApi } from "../api/AluviaApi.js";
|
|
3
3
|
/**
|
|
4
4
|
* AluviaClient is the main entry point for the Aluvia Client.
|
|
5
5
|
*
|
|
@@ -14,13 +14,38 @@ export declare class AluviaClient {
|
|
|
14
14
|
private startPromise;
|
|
15
15
|
private readonly logger;
|
|
16
16
|
readonly api: AluviaApi;
|
|
17
|
+
private blockDetection;
|
|
18
|
+
private pageStates;
|
|
19
|
+
/** Promise-based mutex to serialize handleDetectionResult's critical section. */
|
|
20
|
+
private _detectionMutex;
|
|
21
|
+
/** Read-only access to the connection ID from ConfigManager. */
|
|
22
|
+
get connectionId(): number | undefined;
|
|
17
23
|
constructor(options: AluviaClientOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Attaches per-page listeners for two-pass detection and SPA navigation.
|
|
26
|
+
*/
|
|
27
|
+
private attachPageListeners;
|
|
28
|
+
/**
|
|
29
|
+
* Attaches page listeners to all existing and future pages in a context.
|
|
30
|
+
*/
|
|
31
|
+
private attachBlockDetectionListener;
|
|
32
|
+
/**
|
|
33
|
+
* Handle a detection result: fire callback, check persistent block, reload if needed.
|
|
34
|
+
*
|
|
35
|
+
* The auto-unblock critical section (persistent-block checks, rule updates, page reload)
|
|
36
|
+
* is serialized via a promise-based mutex to prevent concurrent calls from reading stale
|
|
37
|
+
* state and producing duplicate rule additions or missed persistent-block escalation.
|
|
38
|
+
*/
|
|
39
|
+
private handleDetectionResult;
|
|
40
|
+
/**
|
|
41
|
+
* Auto-unblock critical section. Must only be called under _detectionMutex.
|
|
42
|
+
*/
|
|
43
|
+
private _handleAutoUnblock;
|
|
18
44
|
/**
|
|
19
45
|
* Start the Aluvia Client connection:
|
|
20
46
|
* - Fetch initial account connection config from Aluvia.
|
|
21
47
|
* - Start polling for config updates.
|
|
22
|
-
* -
|
|
23
|
-
* - If localProxy is disabled: do NOT start a local proxy; adapters use gateway proxy settings.
|
|
48
|
+
* - Start a local HTTP proxy on 127.0.0.1:<localPort or free port>.
|
|
24
49
|
*
|
|
25
50
|
* Returns the active connection with host/port/url and a stop() method.
|
|
26
51
|
*/
|
|
@@ -47,4 +72,26 @@ export declare class AluviaClient {
|
|
|
47
72
|
* Pass null to clear geo targeting.
|
|
48
73
|
*/
|
|
49
74
|
updateTargetGeo(targetGeo: string | null): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Get a list of hostnames that have been detected as blocked.
|
|
77
|
+
*
|
|
78
|
+
* This list is maintained in-memory and cleared when the client is stopped.
|
|
79
|
+
* Only available when block detection is enabled.
|
|
80
|
+
*/
|
|
81
|
+
getBlockedHostnames(): string[];
|
|
82
|
+
/**
|
|
83
|
+
* Clear the list of blocked hostnames and retried URLs.
|
|
84
|
+
*
|
|
85
|
+
* Only available when block detection is enabled.
|
|
86
|
+
*/
|
|
87
|
+
clearBlockedHostnames(): void;
|
|
88
|
+
/**
|
|
89
|
+
* Import Playwright, auto-installing if necessary.
|
|
90
|
+
* Returns the chromium browser type for launching.
|
|
91
|
+
*/
|
|
92
|
+
private _initPlaywright;
|
|
93
|
+
/**
|
|
94
|
+
* Find a free TCP port by briefly binding to port 0.
|
|
95
|
+
*/
|
|
96
|
+
private static findFreePort;
|
|
50
97
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Logger } from "./logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Detection block status based on scoring
|
|
4
|
+
*/
|
|
5
|
+
export type DetectionBlockStatus = "blocked" | "suspected" | "clear";
|
|
6
|
+
/**
|
|
7
|
+
* A single detection signal with weight
|
|
8
|
+
*/
|
|
9
|
+
export type DetectionSignal = {
|
|
10
|
+
name: string;
|
|
11
|
+
weight: number;
|
|
12
|
+
details: string;
|
|
13
|
+
source: "fast" | "full";
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A single hop in a redirect chain
|
|
17
|
+
*/
|
|
18
|
+
export type RedirectHop = {
|
|
19
|
+
url: string;
|
|
20
|
+
statusCode: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Result of block detection analysis
|
|
24
|
+
*/
|
|
25
|
+
export type BlockDetectionResult = {
|
|
26
|
+
url: string;
|
|
27
|
+
hostname: string;
|
|
28
|
+
blockStatus: DetectionBlockStatus;
|
|
29
|
+
score: number;
|
|
30
|
+
signals: DetectionSignal[];
|
|
31
|
+
pass: "fast" | "full";
|
|
32
|
+
persistentBlock: boolean;
|
|
33
|
+
redirectChain: RedirectHop[];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Configuration for block detection
|
|
37
|
+
*/
|
|
38
|
+
export type BlockDetectionConfig = {
|
|
39
|
+
enabled?: boolean;
|
|
40
|
+
challengeSelectors?: string[];
|
|
41
|
+
extraKeywords?: string[];
|
|
42
|
+
extraStatusCodes?: number[];
|
|
43
|
+
networkIdleTimeoutMs?: number;
|
|
44
|
+
autoUnblock?: boolean;
|
|
45
|
+
autoUnblockOnSuspected?: boolean;
|
|
46
|
+
onDetection?: (result: BlockDetectionResult, page: any) => void | Promise<void>;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* BlockDetection handles detection of website blocks, CAPTCHAs, and WAF challenges
|
|
50
|
+
* using a weighted scoring system across multiple signal types.
|
|
51
|
+
*/
|
|
52
|
+
export declare class BlockDetection {
|
|
53
|
+
private config;
|
|
54
|
+
private logger;
|
|
55
|
+
retriedUrls: Set<string>;
|
|
56
|
+
persistentHostnames: Set<string>;
|
|
57
|
+
private statusCodeSet;
|
|
58
|
+
private allTitleKeywords;
|
|
59
|
+
constructor(config: BlockDetectionConfig, logger: Logger);
|
|
60
|
+
getNetworkIdleTimeoutMs(): number;
|
|
61
|
+
isEnabled(): boolean;
|
|
62
|
+
getOnDetection(): ((result: BlockDetectionResult, page: any) => void | Promise<void>) | undefined;
|
|
63
|
+
isAutoUnblock(): boolean;
|
|
64
|
+
isAutoUnblockOnSuspected(): boolean;
|
|
65
|
+
private computeScore;
|
|
66
|
+
private detectHttpStatus;
|
|
67
|
+
private detectResponseHeaders;
|
|
68
|
+
private detectTitleKeywords;
|
|
69
|
+
private detectChallengeSelectors;
|
|
70
|
+
private detectVisibleText;
|
|
71
|
+
private detectTextToHtmlRatio;
|
|
72
|
+
private detectRedirectChain;
|
|
73
|
+
private detectMetaRefresh;
|
|
74
|
+
/**
|
|
75
|
+
* Fast pass - runs at domcontentloaded. Only HTTP status + response headers.
|
|
76
|
+
* If score >= 0.9, caller should trigger remediation immediately.
|
|
77
|
+
*/
|
|
78
|
+
analyzeFast(page: any, response: any): Promise<BlockDetectionResult>;
|
|
79
|
+
/**
|
|
80
|
+
* Run all content-based detectors in parallel.
|
|
81
|
+
* Shared by analyzeFull and analyzeSpa.
|
|
82
|
+
*/
|
|
83
|
+
private runContentDetectors;
|
|
84
|
+
/**
|
|
85
|
+
* Full pass - runs after networkidle. Runs all detectors and merges with fast pass.
|
|
86
|
+
*/
|
|
87
|
+
analyzeFull(page: any, response: any, fastResult?: BlockDetectionResult): Promise<BlockDetectionResult>;
|
|
88
|
+
/**
|
|
89
|
+
* SPA navigation analysis - content-based detectors only, no HTTP signals.
|
|
90
|
+
*/
|
|
91
|
+
analyzeSpa(page: any): Promise<BlockDetectionResult>;
|
|
92
|
+
private reEvaluateIfSuspected;
|
|
93
|
+
private makeResult;
|
|
94
|
+
private logResult;
|
|
95
|
+
private extractHostname;
|
|
96
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { GatewayProtocol, LogLevel } from './types.js';
|
|
2
|
+
import type { NormalizedRules } from './rules.js';
|
|
2
3
|
/**
|
|
3
4
|
* Raw proxy configuration derived from the account-connection response and client options.
|
|
4
5
|
*/
|
|
@@ -15,6 +16,8 @@ export type RawProxyConfig = {
|
|
|
15
16
|
export type ConnectionNetworkConfig = {
|
|
16
17
|
rawProxy: RawProxyConfig;
|
|
17
18
|
rules: string[];
|
|
19
|
+
/** Pre-normalized rules for efficient per-request matching. */
|
|
20
|
+
normalizedRules: NormalizedRules;
|
|
18
21
|
sessionId: string | null;
|
|
19
22
|
targetGeo: string | null;
|
|
20
23
|
/**
|
|
@@ -63,6 +66,8 @@ export declare class ConfigManager {
|
|
|
63
66
|
private readonly strict;
|
|
64
67
|
private accountConnectionId;
|
|
65
68
|
private pollInFlight;
|
|
69
|
+
/** Public read-only access to the account connection ID. */
|
|
70
|
+
get connectionId(): number | undefined;
|
|
66
71
|
constructor(options: ConfigManagerOptions);
|
|
67
72
|
/**
|
|
68
73
|
* Fetch initial configuration from the account connections API.
|
|
@@ -86,7 +91,7 @@ export declare class ConfigManager {
|
|
|
86
91
|
* Returns null if init() hasn't been called or failed.
|
|
87
92
|
*/
|
|
88
93
|
getConfig(): ConnectionNetworkConfig | null;
|
|
89
|
-
setConfig(body:
|
|
94
|
+
setConfig(body: Record<string, unknown>): Promise<ConnectionNetworkConfig | null>;
|
|
90
95
|
/**
|
|
91
96
|
* Perform a single poll iteration.
|
|
92
97
|
* Called by the polling timer.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Logger } from "./logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for page load detection
|
|
4
|
+
*/
|
|
5
|
+
export type PageLoadDetectionConfig = {
|
|
6
|
+
/**
|
|
7
|
+
* Enable automatic detection of blocking/captchas
|
|
8
|
+
* Default: true
|
|
9
|
+
*/
|
|
10
|
+
enabled?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Keywords to search for in page content that indicate blocking
|
|
13
|
+
* Default: ['captcha', 'blocked', 'access denied', 'forbidden', 'cloudflare', 'please verify', 'recaptcha']
|
|
14
|
+
*/
|
|
15
|
+
blockingKeywords?: string[];
|
|
16
|
+
/**
|
|
17
|
+
* HTTP status codes that indicate blocking
|
|
18
|
+
* Default: [403, 429, 503]
|
|
19
|
+
*/
|
|
20
|
+
blockingStatusCodes?: number[];
|
|
21
|
+
/**
|
|
22
|
+
* Minimum content length for a successful page load
|
|
23
|
+
* Pages with less content may have failed to load
|
|
24
|
+
* Default: 100
|
|
25
|
+
*/
|
|
26
|
+
minContentLength?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Automatically add hostname to rules when blocking is detected
|
|
29
|
+
* Default: false (user must opt-in)
|
|
30
|
+
*/
|
|
31
|
+
autoAddRules?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Callback when blocking is detected
|
|
34
|
+
* Receives the hostname, detection reason, and the page object
|
|
35
|
+
*/
|
|
36
|
+
onBlockingDetected?: (hostname: string, reason: BlockingReason, page: any) => void | Promise<void>;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Reason why blocking was detected
|
|
40
|
+
*/
|
|
41
|
+
export type BlockingReason = {
|
|
42
|
+
type: "status_code" | "keyword" | "content_length" | "error";
|
|
43
|
+
details: string;
|
|
44
|
+
statusCode?: number;
|
|
45
|
+
keyword?: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Result of page load detection
|
|
49
|
+
*/
|
|
50
|
+
export type PageLoadDetectionResult = {
|
|
51
|
+
url: string;
|
|
52
|
+
hostname: string;
|
|
53
|
+
success: boolean;
|
|
54
|
+
blocked: boolean;
|
|
55
|
+
reason?: BlockingReason;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* PageLoadDetection handles enhanced detection of page load failures and blocking
|
|
59
|
+
*/
|
|
60
|
+
export declare class PageLoadDetection {
|
|
61
|
+
private config;
|
|
62
|
+
private logger;
|
|
63
|
+
private blockedHostnames;
|
|
64
|
+
constructor(config: PageLoadDetectionConfig, logger: Logger);
|
|
65
|
+
/**
|
|
66
|
+
* Update detection configuration
|
|
67
|
+
*/
|
|
68
|
+
updateConfig(config: Partial<PageLoadDetectionConfig>): void;
|
|
69
|
+
/**
|
|
70
|
+
* Check if a hostname is already marked as blocked
|
|
71
|
+
*/
|
|
72
|
+
isHostnameBlocked(hostname: string): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Get all blocked hostnames
|
|
75
|
+
*/
|
|
76
|
+
getBlockedHostnames(): string[];
|
|
77
|
+
/**
|
|
78
|
+
* Clear blocked hostnames cache
|
|
79
|
+
*/
|
|
80
|
+
clearBlockedHostnames(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Analyze a page load and detect if it was blocked
|
|
83
|
+
*/
|
|
84
|
+
analyzePage(page: any, response: any): Promise<PageLoadDetectionResult>;
|
|
85
|
+
/**
|
|
86
|
+
* Handle detected blocking
|
|
87
|
+
*/
|
|
88
|
+
private handleBlocking;
|
|
89
|
+
/**
|
|
90
|
+
* Extract hostname from URL
|
|
91
|
+
*/
|
|
92
|
+
private extractHostname;
|
|
93
|
+
}
|
|
@@ -31,4 +31,22 @@ export declare function matchPattern(hostname: string, pattern: string): boolean
|
|
|
31
31
|
* @param rules - Array of rule patterns
|
|
32
32
|
* @returns true if the hostname should be proxied
|
|
33
33
|
*/
|
|
34
|
+
/**
|
|
35
|
+
* Pre-normalized rules for efficient per-request matching.
|
|
36
|
+
*/
|
|
37
|
+
export type NormalizedRules = {
|
|
38
|
+
positiveRules: string[];
|
|
39
|
+
negativeRules: string[];
|
|
40
|
+
hasCatchAll: boolean;
|
|
41
|
+
empty: boolean;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Pre-process raw rule strings into a NormalizedRules structure.
|
|
45
|
+
* Call once when config is loaded, then use shouldProxyNormalized() per request.
|
|
46
|
+
*/
|
|
47
|
+
export declare function normalizeRules(rules: string[]): NormalizedRules;
|
|
48
|
+
/**
|
|
49
|
+
* Fast proxy decision using pre-normalized rules.
|
|
50
|
+
*/
|
|
51
|
+
export declare function shouldProxyNormalized(hostname: string, rules: NormalizedRules): boolean;
|
|
34
52
|
export declare function shouldProxy(hostname: string, rules: string[]): boolean;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import type { BlockDetectionConfig } from "./BlockDetection.js";
|
|
1
2
|
/**
|
|
2
3
|
* Protocol used to connect to the Aluvia gateway.
|
|
3
4
|
*/
|
|
4
|
-
export type GatewayProtocol =
|
|
5
|
+
export type GatewayProtocol = "http" | "https";
|
|
5
6
|
/**
|
|
6
7
|
* Log level for the client.
|
|
7
8
|
*/
|
|
8
|
-
export type LogLevel =
|
|
9
|
+
export type LogLevel = "silent" | "info" | "debug";
|
|
9
10
|
export type PlaywrightProxySettings = {
|
|
10
11
|
server: string;
|
|
11
12
|
username?: string;
|
|
@@ -72,14 +73,6 @@ export type AluviaClientOptions = {
|
|
|
72
73
|
* POST /account/connections
|
|
73
74
|
*/
|
|
74
75
|
connectionId?: number;
|
|
75
|
-
/**
|
|
76
|
-
* Optional: enable local proxy mode (client proxy mode).
|
|
77
|
-
*
|
|
78
|
-
* If true (default): start the local proxy (127.0.0.1:<port>) and route traffic dynamically.
|
|
79
|
-
* If false: do NOT start a local proxy; adapters return gateway proxy settings
|
|
80
|
-
* from the account connection API response for direct use by Playwright/Axios/etc.
|
|
81
|
-
*/
|
|
82
|
-
localProxy?: boolean;
|
|
83
76
|
/**
|
|
84
77
|
* Optional: strict startup behavior.
|
|
85
78
|
*
|
|
@@ -87,8 +80,8 @@ export type AluviaClientOptions = {
|
|
|
87
80
|
* an account connection config (proxy credentials + rules). This prevents
|
|
88
81
|
* "silent direct routing" where the local proxy starts but bypasses Aluvia.
|
|
89
82
|
*
|
|
90
|
-
* If false:
|
|
91
|
-
*
|
|
83
|
+
* If false: the SDK may still start a local proxy and route traffic directly
|
|
84
|
+
* when config is unavailable.
|
|
92
85
|
*/
|
|
93
86
|
strict?: boolean;
|
|
94
87
|
/**
|
|
@@ -103,42 +96,40 @@ export type AluviaClientOptions = {
|
|
|
103
96
|
* Note: Playwright must be installed as a dependency for this option to work.
|
|
104
97
|
*/
|
|
105
98
|
startPlaywright?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Optional: configuration for website block detection.
|
|
101
|
+
*
|
|
102
|
+
* When enabled (default), the SDK monitors pages using a weighted scoring
|
|
103
|
+
* system across multiple signal types (HTTP status, WAF headers, DOM
|
|
104
|
+
* selectors, visible text, redirect chains) with two-pass analysis.
|
|
105
|
+
*/
|
|
106
|
+
blockDetection?: BlockDetectionConfig;
|
|
107
|
+
/**
|
|
108
|
+
* Optional: run the Playwright browser in headless or headed mode.
|
|
109
|
+
*
|
|
110
|
+
* If true (default): the browser runs without a visible window.
|
|
111
|
+
* If false: the browser opens a visible window.
|
|
112
|
+
*
|
|
113
|
+
* Only applies when `startPlaywright` is true.
|
|
114
|
+
*/
|
|
115
|
+
headless?: boolean;
|
|
106
116
|
};
|
|
107
117
|
/**
|
|
108
118
|
* Represents an active Aluvia Client connection.
|
|
109
119
|
*/
|
|
110
120
|
export type AluviaClientConnection = {
|
|
111
121
|
/**
|
|
112
|
-
* Proxy host
|
|
113
|
-
*
|
|
114
|
-
* - In client proxy mode (localProxy: true): this is the local proxy host ('127.0.0.1').
|
|
115
|
-
* - In gateway mode: this is the Aluvia gateway host (typically 'gateway.aluvia.io').
|
|
122
|
+
* Proxy host: `'127.0.0.1'` (the local proxy).
|
|
116
123
|
*/
|
|
117
124
|
host: string;
|
|
118
125
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* - In client proxy mode (localProxy: true): this is the local proxy port.
|
|
122
|
-
* - In gateway mode: this is the Aluvia gateway port (typically 8080 or 8443).
|
|
126
|
+
* The local proxy port.
|
|
123
127
|
*/
|
|
124
128
|
port: number;
|
|
125
129
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* - In client proxy mode (localProxy: true): 'http://127.0.0.1:<port>'
|
|
129
|
-
* - In gateway mode: '<protocol>://gateway.aluvia.io:<port>'
|
|
130
|
-
*
|
|
131
|
-
* (The local proxy itself is always HTTP; it may tunnel to an HTTP or HTTPS
|
|
132
|
-
* gateway upstream based on gatewayProtocol/gatewayPort.)
|
|
130
|
+
* Proxy URL: `'http://127.0.0.1:<port>'`.
|
|
133
131
|
*/
|
|
134
132
|
url: string;
|
|
135
|
-
/**
|
|
136
|
-
* Returns a credential-embedded proxy URL intended for clients that require auth in the URL.
|
|
137
|
-
*
|
|
138
|
-
* Note: This value contains secrets (proxy username/password). Avoid logging it or putting it
|
|
139
|
-
* in places that may be exposed (e.g., process args).
|
|
140
|
-
*/
|
|
141
|
-
getUrl(): string;
|
|
142
133
|
/**
|
|
143
134
|
* Playwright adapter for chromium/firefox/webkit launch options.
|
|
144
135
|
*/
|
|
@@ -157,8 +148,8 @@ export type AluviaClientConnection = {
|
|
|
157
148
|
* Useful for: Axios, got, node-fetch (legacy).
|
|
158
149
|
*/
|
|
159
150
|
asNodeAgents(): {
|
|
160
|
-
http: import(
|
|
161
|
-
https: import(
|
|
151
|
+
http: import("node:http").Agent;
|
|
152
|
+
https: import("node:http").Agent;
|
|
162
153
|
};
|
|
163
154
|
/**
|
|
164
155
|
* Axios adapter config.
|
|
@@ -168,8 +159,8 @@ export type AluviaClientConnection = {
|
|
|
168
159
|
*/
|
|
169
160
|
asAxiosConfig(): {
|
|
170
161
|
proxy: false;
|
|
171
|
-
httpAgent: import(
|
|
172
|
-
httpsAgent: import(
|
|
162
|
+
httpAgent: import("node:http").Agent;
|
|
163
|
+
httpsAgent: import("node:http").Agent;
|
|
173
164
|
};
|
|
174
165
|
/**
|
|
175
166
|
* got adapter options.
|
|
@@ -178,14 +169,14 @@ export type AluviaClientConnection = {
|
|
|
178
169
|
*/
|
|
179
170
|
asGotOptions(): {
|
|
180
171
|
agent: {
|
|
181
|
-
http: import(
|
|
182
|
-
https: import(
|
|
172
|
+
http: import("node:http").Agent;
|
|
173
|
+
https: import("node:http").Agent;
|
|
183
174
|
};
|
|
184
175
|
};
|
|
185
176
|
/**
|
|
186
177
|
* undici proxy dispatcher (for undici fetch / undici clients).
|
|
187
178
|
*/
|
|
188
|
-
asUndiciDispatcher(): import(
|
|
179
|
+
asUndiciDispatcher(): import("undici").Dispatcher;
|
|
189
180
|
/**
|
|
190
181
|
* Returns a `fetch` function powered by undici that uses the proxy dispatcher per request.
|
|
191
182
|
*
|
|
@@ -202,15 +193,25 @@ export type AluviaClientConnection = {
|
|
|
202
193
|
* The browser is already configured to use the Aluvia proxy, so you can use it directly.
|
|
203
194
|
*/
|
|
204
195
|
browser?: any;
|
|
196
|
+
browserContext?: any;
|
|
205
197
|
/**
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
198
|
+
* Chrome DevTools Protocol HTTP endpoint URL (for example: http://127.0.0.1:<port>).
|
|
199
|
+
*
|
|
200
|
+
* Only available if `startPlaywright: true` was passed to AluviaClientOptions.
|
|
201
|
+
* Intended for use by external tools that connect to the browser via CDP.
|
|
202
|
+
* Tools that require a WebSocket debugger URL should derive it from this HTTP
|
|
203
|
+
* endpoint (for example, by fetching `${cdpUrl}/json/version` and using the
|
|
204
|
+
* `webSocketDebuggerUrl` field from the response).
|
|
210
205
|
*/
|
|
211
|
-
|
|
206
|
+
cdpUrl?: string;
|
|
212
207
|
/**
|
|
213
|
-
*
|
|
208
|
+
* Close this proxy instance:
|
|
209
|
+
* - Close the local proxy server.
|
|
210
|
+
* - Close the browser (if started).
|
|
211
|
+
* - Stop config polling.
|
|
214
212
|
*/
|
|
215
213
|
close(): Promise<void>;
|
|
214
|
+
/** @deprecated Use `close()` instead. */
|
|
215
|
+
stop(): Promise<void>;
|
|
216
216
|
};
|
|
217
|
+
export type { BlockDetectionConfig, BlockDetectionResult, DetectionBlockStatus, DetectionSignal, RedirectHop, } from "./BlockDetection.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ConnectResult = {
|
|
2
|
+
browser: any;
|
|
3
|
+
context: any;
|
|
4
|
+
page: any;
|
|
5
|
+
sessionName: string;
|
|
6
|
+
cdpUrl: string;
|
|
7
|
+
connectionId: number | undefined;
|
|
8
|
+
disconnect: () => Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Connect to a running Aluvia browser session via CDP.
|
|
12
|
+
*
|
|
13
|
+
* - No args: auto-discovers a single running session.
|
|
14
|
+
* - With session name: connects to that specific session.
|
|
15
|
+
*
|
|
16
|
+
* Requires `playwright` as a peer dependency.
|
|
17
|
+
*/
|
|
18
|
+
export declare function connect(sessionName?: string): Promise<ConnectResult>;
|
package/dist/types/errors.d.ts
CHANGED
|
@@ -23,3 +23,9 @@ export declare class ApiError extends Error {
|
|
|
23
23
|
export declare class ProxyStartError extends Error {
|
|
24
24
|
constructor(message?: string);
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Thrown by connect() when it cannot establish a CDP connection to a running session.
|
|
28
|
+
*/
|
|
29
|
+
export declare class ConnectError extends Error {
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|