@aluvia/sdk 1.4.1 → 2.0.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/CHANGELOG.md +188 -0
- package/README.md +162 -477
- package/dist/cjs/api/apiUtils.js +4 -1
- package/dist/cjs/client/AluviaClient.js +30 -32
- package/dist/cjs/client/BlockDetection.js +69 -87
- package/dist/cjs/client/rules.js +12 -2
- package/dist/cjs/connect.js +2 -2
- package/dist/cjs/index.js +12 -1
- package/dist/cjs/session/lock.js +40 -4
- package/dist/esm/api/apiUtils.js +4 -1
- package/dist/esm/client/AluviaClient.js +38 -40
- package/dist/esm/client/BlockDetection.js +69 -87
- package/dist/esm/client/rules.js +12 -2
- package/dist/esm/connect.js +2 -2
- package/dist/esm/index.js +6 -4
- package/dist/esm/session/lock.js +40 -4
- package/dist/types/client/AluviaClient.d.ts +2 -2
- package/dist/types/client/BlockDetection.d.ts +4 -4
- package/dist/types/client/types.d.ts +11 -11
- package/dist/types/index.d.ts +9 -7
- package/package.json +15 -23
- package/dist/cjs/bin/account.js +0 -31
- package/dist/cjs/bin/api-helpers.js +0 -58
- package/dist/cjs/bin/cli-adapter.js +0 -16
- package/dist/cjs/bin/cli.js +0 -245
- package/dist/cjs/bin/close.js +0 -120
- package/dist/cjs/bin/geos.js +0 -10
- package/dist/cjs/bin/mcp-helpers.js +0 -57
- package/dist/cjs/bin/open.js +0 -317
- package/dist/cjs/bin/session.js +0 -259
- package/dist/esm/bin/account.js +0 -28
- package/dist/esm/bin/api-helpers.js +0 -53
- package/dist/esm/bin/cli-adapter.js +0 -8
- package/dist/esm/bin/cli.js +0 -242
- package/dist/esm/bin/close.js +0 -117
- package/dist/esm/bin/geos.js +0 -7
- package/dist/esm/bin/mcp-helpers.js +0 -51
- package/dist/esm/bin/open.js +0 -280
- package/dist/esm/bin/session.js +0 -252
- package/dist/types/bin/account.d.ts +0 -1
- package/dist/types/bin/api-helpers.d.ts +0 -20
- package/dist/types/bin/cli-adapter.d.ts +0 -8
- package/dist/types/bin/cli.d.ts +0 -2
- package/dist/types/bin/close.d.ts +0 -1
- package/dist/types/bin/geos.d.ts +0 -1
- package/dist/types/bin/mcp-helpers.d.ts +0 -28
- package/dist/types/bin/open.d.ts +0 -21
- package/dist/types/bin/session.d.ts +0 -11
package/dist/esm/bin/session.js
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import crypto from 'node:crypto';
|
|
2
|
-
import { handleOpen } from './open.js';
|
|
3
|
-
import { handleClose } from './close.js';
|
|
4
|
-
import { listSessions } from '../session/lock.js';
|
|
5
|
-
import { requireApi, resolveSession, requireConnectionId } from './api-helpers.js';
|
|
6
|
-
import { output } from './cli.js';
|
|
7
|
-
export function parseSessionArgs(args) {
|
|
8
|
-
let url;
|
|
9
|
-
let connectionId;
|
|
10
|
-
let headed = false;
|
|
11
|
-
let sessionName;
|
|
12
|
-
let autoUnblock = false;
|
|
13
|
-
let disableBlockDetection = false;
|
|
14
|
-
let run;
|
|
15
|
-
for (let i = 0; i < args.length; i++) {
|
|
16
|
-
if (args[i] === '--connection-id' && args[i + 1]) {
|
|
17
|
-
const parsed = Number(args[i + 1]);
|
|
18
|
-
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
19
|
-
output({ error: `Invalid --connection-id: '${args[i + 1]}' must be a positive integer.` }, 1);
|
|
20
|
-
}
|
|
21
|
-
connectionId = parsed;
|
|
22
|
-
i++;
|
|
23
|
-
}
|
|
24
|
-
else if (args[i] === '--browser-session' && args[i + 1]) {
|
|
25
|
-
sessionName = args[i + 1];
|
|
26
|
-
i++;
|
|
27
|
-
}
|
|
28
|
-
else if (args[i] === '--run' && args[i + 1]) {
|
|
29
|
-
run = args[i + 1];
|
|
30
|
-
i++;
|
|
31
|
-
}
|
|
32
|
-
else if (args[i] === '--headful') {
|
|
33
|
-
headed = true;
|
|
34
|
-
}
|
|
35
|
-
else if (args[i] === '--auto-unblock') {
|
|
36
|
-
autoUnblock = true;
|
|
37
|
-
}
|
|
38
|
-
else if (args[i] === '--disable-block-detection') {
|
|
39
|
-
disableBlockDetection = true;
|
|
40
|
-
}
|
|
41
|
-
else if (!url && !args[i].startsWith('--')) {
|
|
42
|
-
url = args[i];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return { url, connectionId, headed, sessionName, autoUnblock, disableBlockDetection, run };
|
|
46
|
-
}
|
|
47
|
-
export async function handleSession(args) {
|
|
48
|
-
const subcommand = args[0];
|
|
49
|
-
if (!subcommand) {
|
|
50
|
-
return output({ error: 'Missing session subcommand. Run "aluvia help" for usage.' }, 1);
|
|
51
|
-
}
|
|
52
|
-
switch (subcommand) {
|
|
53
|
-
case 'start':
|
|
54
|
-
return handleSessionStart(args.slice(1));
|
|
55
|
-
case 'close':
|
|
56
|
-
return handleSessionClose(args.slice(1));
|
|
57
|
-
case 'list':
|
|
58
|
-
return handleSessionList();
|
|
59
|
-
case 'get':
|
|
60
|
-
return handleSessionGet(args.slice(1));
|
|
61
|
-
case 'rotate-ip':
|
|
62
|
-
return handleSessionRotateIp(args.slice(1));
|
|
63
|
-
case 'set-geo':
|
|
64
|
-
return handleSessionSetGeo(args.slice(1));
|
|
65
|
-
case 'set-rules':
|
|
66
|
-
return handleSessionSetRules(args.slice(1));
|
|
67
|
-
default:
|
|
68
|
-
return output({ error: `Unknown session subcommand: '${subcommand}'. Run "aluvia help" for usage.` }, 1);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
async function handleSessionStart(args) {
|
|
72
|
-
const parsed = parseSessionArgs(args);
|
|
73
|
-
if (!parsed.url) {
|
|
74
|
-
return output({ error: 'URL is required. Usage: aluvia session start <url> [options]' }, 1);
|
|
75
|
-
}
|
|
76
|
-
const opts = {
|
|
77
|
-
url: parsed.url,
|
|
78
|
-
connectionId: parsed.connectionId,
|
|
79
|
-
headless: !parsed.headed,
|
|
80
|
-
sessionName: parsed.sessionName,
|
|
81
|
-
autoUnblock: parsed.autoUnblock,
|
|
82
|
-
disableBlockDetection: parsed.disableBlockDetection,
|
|
83
|
-
run: parsed.run,
|
|
84
|
-
};
|
|
85
|
-
// Delegates to the existing open handler (spawns daemon, waits for ready)
|
|
86
|
-
await handleOpen(opts);
|
|
87
|
-
}
|
|
88
|
-
async function handleSessionClose(args) {
|
|
89
|
-
let sessionName;
|
|
90
|
-
let all = false;
|
|
91
|
-
for (let i = 0; i < args.length; i++) {
|
|
92
|
-
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
93
|
-
sessionName = args[i + 1];
|
|
94
|
-
i++;
|
|
95
|
-
}
|
|
96
|
-
else if (args[i] === '--all') {
|
|
97
|
-
all = true;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
await handleClose(sessionName, all);
|
|
101
|
-
}
|
|
102
|
-
function handleSessionList() {
|
|
103
|
-
const sessions = listSessions();
|
|
104
|
-
return output({
|
|
105
|
-
sessions: sessions.map((s) => ({
|
|
106
|
-
browserSession: s.session,
|
|
107
|
-
pid: s.pid,
|
|
108
|
-
startUrl: s.url ?? null,
|
|
109
|
-
cdpUrl: s.cdpUrl ?? null,
|
|
110
|
-
connectionId: s.connectionId ?? null,
|
|
111
|
-
blockDetection: s.blockDetection ?? false,
|
|
112
|
-
autoUnblock: s.autoUnblock ?? false,
|
|
113
|
-
})),
|
|
114
|
-
count: sessions.length,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
async function handleSessionGet(args) {
|
|
118
|
-
let sessionName;
|
|
119
|
-
for (let i = 0; i < args.length; i++) {
|
|
120
|
-
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
121
|
-
sessionName = args[i + 1];
|
|
122
|
-
i++;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const { session, lock } = resolveSession(sessionName);
|
|
126
|
-
const connId = lock.connectionId;
|
|
127
|
-
const base = {
|
|
128
|
-
browserSession: session,
|
|
129
|
-
pid: lock.pid,
|
|
130
|
-
startUrl: lock.url ?? null,
|
|
131
|
-
cdpUrl: lock.cdpUrl ?? null,
|
|
132
|
-
connectionId: connId ?? null,
|
|
133
|
-
blockDetection: lock.blockDetection ?? false,
|
|
134
|
-
autoUnblock: lock.autoUnblock ?? false,
|
|
135
|
-
lastDetection: lock.lastDetection ?? null,
|
|
136
|
-
};
|
|
137
|
-
// If we have a connection ID, enrich with full connection object from API
|
|
138
|
-
if (connId != null) {
|
|
139
|
-
try {
|
|
140
|
-
const api = requireApi();
|
|
141
|
-
const conn = await api.account.connections.get(connId);
|
|
142
|
-
if (conn) {
|
|
143
|
-
base.connection = conn;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
// API enrichment is best-effort; base lock data is still returned
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return output(base);
|
|
151
|
-
}
|
|
152
|
-
async function handleSessionRotateIp(args) {
|
|
153
|
-
let sessionName;
|
|
154
|
-
for (let i = 0; i < args.length; i++) {
|
|
155
|
-
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
156
|
-
sessionName = args[i + 1];
|
|
157
|
-
i++;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
const { session, lock } = resolveSession(sessionName);
|
|
161
|
-
const connId = requireConnectionId(lock, session);
|
|
162
|
-
const api = requireApi();
|
|
163
|
-
const newSessionId = crypto.randomUUID().replace(/-/g, '');
|
|
164
|
-
await api.account.connections.patch(connId, { session_id: newSessionId });
|
|
165
|
-
return output({
|
|
166
|
-
browserSession: session,
|
|
167
|
-
connectionId: connId,
|
|
168
|
-
sessionId: newSessionId,
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
async function handleSessionSetGeo(args) {
|
|
172
|
-
let sessionName;
|
|
173
|
-
let geo;
|
|
174
|
-
let clear = false;
|
|
175
|
-
for (let i = 0; i < args.length; i++) {
|
|
176
|
-
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
177
|
-
sessionName = args[i + 1];
|
|
178
|
-
i++;
|
|
179
|
-
}
|
|
180
|
-
else if (args[i] === '--clear') {
|
|
181
|
-
clear = true;
|
|
182
|
-
}
|
|
183
|
-
else if (!geo && !args[i].startsWith('--')) {
|
|
184
|
-
geo = args[i];
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
if (!geo && !clear) {
|
|
188
|
-
return output({ error: 'Geo code is required. Usage: aluvia session set-geo <geo> [--browser-session <name>]' }, 1);
|
|
189
|
-
}
|
|
190
|
-
if (geo && !geo.trim()) {
|
|
191
|
-
return output({ error: 'Geo code cannot be empty. Provide a valid geo code or use --clear.' }, 1);
|
|
192
|
-
}
|
|
193
|
-
const { session, lock } = resolveSession(sessionName);
|
|
194
|
-
const connId = requireConnectionId(lock, session);
|
|
195
|
-
const api = requireApi();
|
|
196
|
-
const targetGeo = clear ? null : geo.trim();
|
|
197
|
-
await api.account.connections.patch(connId, { target_geo: targetGeo });
|
|
198
|
-
return output({
|
|
199
|
-
browserSession: session,
|
|
200
|
-
connectionId: connId,
|
|
201
|
-
targetGeo,
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
async function handleSessionSetRules(args) {
|
|
205
|
-
let sessionName;
|
|
206
|
-
let removeRules;
|
|
207
|
-
let appendRules;
|
|
208
|
-
for (let i = 0; i < args.length; i++) {
|
|
209
|
-
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
210
|
-
sessionName = args[i + 1];
|
|
211
|
-
i++;
|
|
212
|
-
}
|
|
213
|
-
else if (args[i] === '--remove' && args[i + 1]) {
|
|
214
|
-
removeRules = args[i + 1];
|
|
215
|
-
i++;
|
|
216
|
-
}
|
|
217
|
-
else if (!appendRules && !args[i].startsWith('--')) {
|
|
218
|
-
appendRules = args[i];
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (!appendRules && !removeRules) {
|
|
222
|
-
return output({ error: 'Rules are required. Usage: aluvia session set-rules <rules> [--browser-session <name>]' }, 1);
|
|
223
|
-
}
|
|
224
|
-
if (appendRules && removeRules) {
|
|
225
|
-
return output({ error: 'Cannot both append and remove rules. Use either <rules> or --remove <rules>, not both.' }, 1);
|
|
226
|
-
}
|
|
227
|
-
const { session, lock } = resolveSession(sessionName);
|
|
228
|
-
const connId = requireConnectionId(lock, session);
|
|
229
|
-
const api = requireApi();
|
|
230
|
-
// Fetch current rules
|
|
231
|
-
const conn = await api.account.connections.get(connId);
|
|
232
|
-
const currentRules = conn?.rules ?? [];
|
|
233
|
-
let newRules;
|
|
234
|
-
if (removeRules) {
|
|
235
|
-
// Remove mode: filter out specified rules
|
|
236
|
-
const toRemove = new Set(removeRules.split(',').map((r) => r.trim()).filter(Boolean));
|
|
237
|
-
newRules = currentRules.filter((r) => !toRemove.has(r));
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
// Append mode: add new rules to existing (deduplicate)
|
|
241
|
-
const toAdd = appendRules.split(',').map((r) => r.trim()).filter(Boolean);
|
|
242
|
-
const existing = new Set(currentRules);
|
|
243
|
-
newRules = [...currentRules, ...toAdd.filter((r) => !existing.has(r))];
|
|
244
|
-
}
|
|
245
|
-
await api.account.connections.patch(connId, { rules: newRules });
|
|
246
|
-
return output({
|
|
247
|
-
browserSession: session,
|
|
248
|
-
connectionId: connId,
|
|
249
|
-
rules: newRules,
|
|
250
|
-
count: newRules.length,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function handleAccount(args: string[]): Promise<void>;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { AluviaApi } from '../api/AluviaApi.js';
|
|
2
|
-
import type { LockData } from '../session/lock.js';
|
|
3
|
-
/**
|
|
4
|
-
* Create an AluviaApi instance from ALUVIA_API_KEY env var.
|
|
5
|
-
* Calls output() and exits if the key is missing.
|
|
6
|
-
*/
|
|
7
|
-
export declare function requireApi(): AluviaApi;
|
|
8
|
-
/**
|
|
9
|
-
* Resolve a session by name or auto-select when only one is running.
|
|
10
|
-
* Calls output() and exits on error (no sessions, ambiguous sessions, stale lock).
|
|
11
|
-
*/
|
|
12
|
-
export declare function resolveSession(sessionName?: string): {
|
|
13
|
-
session: string;
|
|
14
|
-
lock: LockData;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Require a connection ID from lock data.
|
|
18
|
-
* Calls output() and exits if connectionId is missing.
|
|
19
|
-
*/
|
|
20
|
-
export declare function requireConnectionId(lock: LockData, session: string): number;
|
|
@@ -1,8 +0,0 @@
|
|
|
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";
|
package/dist/types/bin/cli.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function handleClose(sessionName?: string, closeAll?: boolean): Promise<void>;
|
package/dist/types/bin/geos.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function handleGeos(): Promise<void>;
|
|
@@ -1,28 +0,0 @@
|
|
|
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
|
-
}>;
|
package/dist/types/bin/open.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
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>;
|
|
@@ -1,11 +0,0 @@
|
|
|
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>;
|