@nuanu-ai/agentbrowse 0.2.22 → 0.2.23
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 +10 -0
- package/dist/commands/close.d.ts +12 -1
- package/dist/commands/close.d.ts.map +1 -1
- package/dist/commands/close.js +19 -21
- package/dist/commands/launch.d.ts +22 -1
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +122 -59
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -9
- package/dist/owned-process.d.ts +4 -0
- package/dist/owned-process.d.ts.map +1 -0
- package/dist/owned-process.js +57 -0
- package/dist/session.d.ts +13 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +52 -7
- package/dist/solver/types.d.ts +2 -0
- package/dist/solver/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,6 +47,16 @@ agentbrowse launch https://example.com
|
|
|
47
47
|
agentbrowse launch https://example.com --headless
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
By default, `launch` runs in headful mode. Use `--headless` only when you
|
|
51
|
+
intentionally want a hidden browser:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
agentbrowse launch https://example.com --headless
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If you want to state the default mode explicitly in scripts, use
|
|
58
|
+
`--headful`.
|
|
59
|
+
|
|
50
60
|
Navigate current session:
|
|
51
61
|
|
|
52
62
|
```bash
|
package/dist/commands/close.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* browse close — Close the browser and clean up session.
|
|
3
3
|
*/
|
|
4
|
-
export
|
|
4
|
+
export type CloseSuccessResult = {
|
|
5
|
+
success: true;
|
|
6
|
+
};
|
|
7
|
+
export type CloseFailureResult = {
|
|
8
|
+
success: false;
|
|
9
|
+
error: 'browser_close_failed';
|
|
10
|
+
outcomeType: 'blocked';
|
|
11
|
+
message: 'Browser close failed.';
|
|
12
|
+
reason: string;
|
|
13
|
+
};
|
|
14
|
+
export type CloseResult = CloseSuccessResult | CloseFailureResult;
|
|
15
|
+
export declare function close(): Promise<CloseResult>;
|
|
5
16
|
//# sourceMappingURL=close.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"close.d.ts","sourceRoot":"","sources":["../../src/commands/close.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"close.d.ts","sourceRoot":"","sources":["../../src/commands/close.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,IAAI,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,sBAAsB,CAAC;IAC9B,WAAW,EAAE,SAAS,CAAC;IACvB,OAAO,EAAE,uBAAuB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAMlE,wBAAsB,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC,CAwBlD"}
|
package/dist/commands/close.js
CHANGED
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* browse close — Close the browser and clean up session.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { loadSession, deleteSession } from '../session.js';
|
|
5
|
+
import { info } from '../output.js';
|
|
6
|
+
import { terminateOwnedPid } from '../owned-process.js';
|
|
7
|
+
function isOwnedSessionRecord(session) {
|
|
8
|
+
return session?.identity?.ownership === 'agentbrowse';
|
|
9
|
+
}
|
|
7
10
|
export async function close() {
|
|
8
11
|
const session = loadSession();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
info(`Killed Chrome on port ${port}`);
|
|
12
|
+
if (isOwnedSessionRecord(session)) {
|
|
13
|
+
const termination = await terminateOwnedPid(session.pid);
|
|
14
|
+
if (termination === 'still_alive') {
|
|
15
|
+
info(`Owned browser pid ${session.pid} did not exit; keeping session record`);
|
|
16
|
+
return {
|
|
17
|
+
success: false,
|
|
18
|
+
error: 'browser_close_failed',
|
|
19
|
+
outcomeType: 'blocked',
|
|
20
|
+
message: 'Browser close failed.',
|
|
21
|
+
reason: `Owned browser pid ${session.pid} did not exit after SIGTERM/SIGKILL.`,
|
|
22
|
+
};
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
catch {
|
|
26
|
-
/* no process on port */
|
|
24
|
+
info(`Killed owned browser pid ${session.pid}`);
|
|
27
25
|
}
|
|
28
26
|
if (session) {
|
|
29
27
|
deleteSession();
|
|
30
28
|
}
|
|
31
|
-
|
|
29
|
+
return { success: true };
|
|
32
30
|
}
|
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* browse launch [url] — Start browser session, optionally navigate.
|
|
3
3
|
*/
|
|
4
|
+
import type { SecretCatalogSummary } from '../secrets/catalog-sync.js';
|
|
4
5
|
export type LaunchCliOptions = {
|
|
5
6
|
compact?: boolean;
|
|
6
7
|
profile?: string;
|
|
7
8
|
headless?: boolean;
|
|
9
|
+
proxy?: string;
|
|
10
|
+
noProxy?: boolean;
|
|
8
11
|
};
|
|
9
|
-
export
|
|
12
|
+
export type LaunchSuccessResult = {
|
|
13
|
+
success: true;
|
|
14
|
+
runtime: 'managed';
|
|
15
|
+
captchaSolveCapable: true;
|
|
16
|
+
profile: string;
|
|
17
|
+
cdpUrl: string;
|
|
18
|
+
url: string;
|
|
19
|
+
title: string;
|
|
20
|
+
secretCatalog?: SecretCatalogSummary;
|
|
21
|
+
};
|
|
22
|
+
export type LaunchFailureResult = {
|
|
23
|
+
success: false;
|
|
24
|
+
error: 'browser_launch_failed';
|
|
25
|
+
outcomeType: 'blocked';
|
|
26
|
+
message: 'Browser launch failed.';
|
|
27
|
+
reason: string;
|
|
28
|
+
};
|
|
29
|
+
export type LaunchResult = LaunchSuccessResult | LaunchFailureResult;
|
|
30
|
+
export declare function launch(url?: string, opts?: LaunchCliOptions): Promise<LaunchResult>;
|
|
10
31
|
//# sourceMappingURL=launch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/commands/launch.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/commands/launch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAWvE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,SAAS,CAAC;IACnB,mBAAmB,EAAE,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,uBAAuB,CAAC;IAC/B,WAAW,EAAE,SAAS,CAAC;IACvB,OAAO,EAAE,wBAAwB,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,mBAAmB,GAAG,mBAAmB,CAAC;AAErE,wBAAsB,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAazF"}
|
package/dist/commands/launch.js
CHANGED
|
@@ -1,92 +1,112 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* browse launch [url] — Start browser session, optionally navigate.
|
|
3
3
|
*/
|
|
4
|
-
import { execSync } from 'node:child_process';
|
|
5
4
|
import { readConfig } from '../solver/config.js';
|
|
6
5
|
import { ensureProfile } from '../solver/profile-manager.js';
|
|
7
6
|
import { launchSolver } from '../solver/browser-launcher.js';
|
|
8
|
-
import { saveSession } from '../session.js';
|
|
7
|
+
import { buildOwnedSession, isOwnedSession, loadSession, saveSession } from '../session.js';
|
|
9
8
|
import { findChromePid } from '../stagehand.js';
|
|
10
|
-
import { outputContractFailure, outputJSON } from '../output.js';
|
|
11
9
|
import { applyAgentpayGatewayEnv, tryResolveAgentpayGatewayConfig } from '../agentpay-gateway.js';
|
|
12
10
|
import { connectPlaywright, disconnectPlaywright, syncLaunchPage } from '../playwright-runtime.js';
|
|
13
11
|
import { summarizeSecretCatalog, syncSecretCatalogForUrl } from '../secrets/catalog-sync.js';
|
|
14
|
-
|
|
12
|
+
import { terminateOwnedPid } from '../owned-process.js';
|
|
13
|
+
import { info } from '../output.js';
|
|
15
14
|
const DEFAULT_PROFILE = 'default';
|
|
16
15
|
const COMPACT_WINDOW = {
|
|
17
16
|
width: 1280,
|
|
18
17
|
height: 900,
|
|
19
18
|
};
|
|
20
19
|
export async function launch(url, opts) {
|
|
21
|
-
await
|
|
20
|
+
const cleanupFailure = await cleanupOwnedSession();
|
|
21
|
+
if (cleanupFailure) {
|
|
22
|
+
return cleanupFailure;
|
|
23
|
+
}
|
|
22
24
|
const compact = opts?.compact ?? true;
|
|
23
25
|
const profileName = opts?.profile ?? DEFAULT_PROFILE;
|
|
24
26
|
const headless = opts?.headless ?? false;
|
|
25
|
-
|
|
27
|
+
const proxyOverride = opts?.proxy;
|
|
28
|
+
const noProxy = opts?.noProxy ?? false;
|
|
29
|
+
return launchManaged(url, profileName, headless, compact, proxyOverride, noProxy);
|
|
26
30
|
}
|
|
27
|
-
async function
|
|
28
|
-
const
|
|
29
|
-
if (
|
|
30
|
-
return;
|
|
31
|
-
for (const pid of pids) {
|
|
32
|
-
try {
|
|
33
|
-
process.kill(pid, 'SIGTERM');
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
// Skip stale PID.
|
|
37
|
-
}
|
|
31
|
+
async function cleanupOwnedSession() {
|
|
32
|
+
const existingSession = loadSession();
|
|
33
|
+
if (!isOwnedSession(existingSession)) {
|
|
34
|
+
return null;
|
|
38
35
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
await sleep(100);
|
|
36
|
+
const termination = await terminateOwnedPid(existingSession.pid);
|
|
37
|
+
if (termination === 'still_alive') {
|
|
38
|
+
return buildLaunchFailure(new Error(`Existing owned browser pid ${existingSession.pid} did not exit after SIGTERM/SIGKILL.`));
|
|
43
39
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
function buildLaunchFailure(err) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: 'browser_launch_failed',
|
|
46
|
+
outcomeType: 'blocked',
|
|
47
|
+
message: 'Browser launch failed.',
|
|
48
|
+
reason: formatUnknownError(err),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function getPortFromCdpUrl(cdpUrl) {
|
|
52
|
+
try {
|
|
53
|
+
const url = new URL(cdpUrl);
|
|
54
|
+
if (!url.port) {
|
|
55
|
+
return undefined;
|
|
50
56
|
}
|
|
57
|
+
const port = Number(url.port);
|
|
58
|
+
return Number.isFinite(port) && port > 0 ? port : undefined;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return undefined;
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
|
-
async function launchManaged(url, profileName, headless, compact) {
|
|
64
|
+
async function launchManaged(url, profileName, headless, compact, proxyOverride, noProxy = false) {
|
|
54
65
|
let session;
|
|
55
66
|
let browser = null;
|
|
56
67
|
let secretCatalogSummary;
|
|
57
68
|
try {
|
|
58
|
-
const
|
|
69
|
+
const baseProfile = ensureProfile(profileName);
|
|
59
70
|
const config = readConfig();
|
|
71
|
+
const runtimeProxy = resolveLaunchProxy({
|
|
72
|
+
profileProxy: baseProfile.fingerprint.proxy,
|
|
73
|
+
configProxy: config.defaults?.proxy,
|
|
74
|
+
cliProxy: proxyOverride,
|
|
75
|
+
noProxy,
|
|
76
|
+
});
|
|
77
|
+
const profile = withLaunchProxy(baseProfile, runtimeProxy);
|
|
60
78
|
const gateway = tryResolveAgentpayGatewayConfig();
|
|
61
79
|
if (gateway) {
|
|
62
80
|
applyAgentpayGatewayEnv(gateway);
|
|
63
81
|
}
|
|
82
|
+
if (runtimeProxy) {
|
|
83
|
+
info(`[launch] starting browser with proxy ${runtimeProxy.server}`);
|
|
84
|
+
}
|
|
64
85
|
session = await launchSolver(profile, {
|
|
65
86
|
headless: headless || config.defaults?.headless,
|
|
66
87
|
url,
|
|
67
|
-
cdpPort:
|
|
88
|
+
cdpPort: undefined,
|
|
68
89
|
windowSize: compact ? COMPACT_WINDOW : undefined,
|
|
69
90
|
});
|
|
70
91
|
}
|
|
71
92
|
catch (err) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
93
|
+
return buildLaunchFailure(err);
|
|
94
|
+
}
|
|
95
|
+
const cdpPort = getPortFromCdpUrl(session.cdpUrl);
|
|
96
|
+
const chromePid = findChromePid(cdpPort);
|
|
97
|
+
if (!chromePid) {
|
|
98
|
+
await session.close().catch(() => undefined);
|
|
99
|
+
return buildLaunchFailure(new Error('Launched browser PID could not be resolved.'));
|
|
78
100
|
}
|
|
79
|
-
const
|
|
80
|
-
const persistedSession = {
|
|
101
|
+
const persistedSession = buildOwnedSession({
|
|
81
102
|
cdpUrl: session.cdpUrl,
|
|
82
103
|
pid: chromePid,
|
|
83
|
-
port: CDP_PORT,
|
|
84
104
|
profile: profileName,
|
|
85
105
|
launchedAt: new Date().toISOString(),
|
|
86
106
|
capabilities: {
|
|
87
107
|
captchaSolve: true,
|
|
88
108
|
},
|
|
89
|
-
};
|
|
109
|
+
});
|
|
90
110
|
saveSession(persistedSession);
|
|
91
111
|
let currentUrl = session.page.url();
|
|
92
112
|
let title = await session.page.title().catch(() => '');
|
|
@@ -111,10 +131,12 @@ async function launchManaged(url, profileName, headless, compact) {
|
|
|
111
131
|
}
|
|
112
132
|
if (url) {
|
|
113
133
|
const snapshot = await syncSecretCatalogForUrl(persistedSession, currentUrl || url);
|
|
114
|
-
|
|
134
|
+
if (snapshot) {
|
|
135
|
+
secretCatalogSummary = summarizeSecretCatalog(snapshot);
|
|
136
|
+
}
|
|
115
137
|
}
|
|
116
138
|
saveSession(persistedSession);
|
|
117
|
-
|
|
139
|
+
return {
|
|
118
140
|
success: true,
|
|
119
141
|
runtime: 'managed',
|
|
120
142
|
captchaSolveCapable: true,
|
|
@@ -123,21 +145,7 @@ async function launchManaged(url, profileName, headless, compact) {
|
|
|
123
145
|
url: currentUrl,
|
|
124
146
|
title,
|
|
125
147
|
secretCatalog: secretCatalogSummary,
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
function getPidsOnPort(port) {
|
|
129
|
-
try {
|
|
130
|
-
const out = execSync(`lsof -ti :${port}`, { encoding: 'utf-8' }).trim();
|
|
131
|
-
if (!out)
|
|
132
|
-
return [];
|
|
133
|
-
return out
|
|
134
|
-
.split('\n')
|
|
135
|
-
.map((value) => Number(value))
|
|
136
|
-
.filter((value) => Number.isFinite(value) && value > 0);
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
return [];
|
|
140
|
-
}
|
|
148
|
+
};
|
|
141
149
|
}
|
|
142
150
|
function formatUnknownError(err) {
|
|
143
151
|
if (err instanceof Error)
|
|
@@ -154,6 +162,61 @@ function formatUnknownError(err) {
|
|
|
154
162
|
}
|
|
155
163
|
return String(err);
|
|
156
164
|
}
|
|
157
|
-
function
|
|
158
|
-
|
|
165
|
+
function resolveLaunchProxy(options) {
|
|
166
|
+
if (options.noProxy) {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
if (options.cliProxy) {
|
|
170
|
+
return normalizeProxySetting(options.cliProxy);
|
|
171
|
+
}
|
|
172
|
+
if (options.configProxy) {
|
|
173
|
+
return normalizeProxySetting(options.configProxy);
|
|
174
|
+
}
|
|
175
|
+
if (options.profileProxy) {
|
|
176
|
+
return normalizeProxySetting(options.profileProxy);
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
function withLaunchProxy(profile, proxy) {
|
|
181
|
+
return {
|
|
182
|
+
...profile,
|
|
183
|
+
fingerprint: {
|
|
184
|
+
...profile.fingerprint,
|
|
185
|
+
proxy,
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function normalizeProxySetting(value) {
|
|
190
|
+
if (typeof value === 'string') {
|
|
191
|
+
return parseProxyString(value);
|
|
192
|
+
}
|
|
193
|
+
const normalized = parseProxyString(value.server);
|
|
194
|
+
const username = value.username?.trim() || normalized.username;
|
|
195
|
+
const password = value.password ?? normalized.password;
|
|
196
|
+
return {
|
|
197
|
+
server: normalized.server,
|
|
198
|
+
...(username ? { username } : {}),
|
|
199
|
+
...(password ? { password } : {}),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function parseProxyString(value) {
|
|
203
|
+
const trimmed = value.trim();
|
|
204
|
+
if (!trimmed) {
|
|
205
|
+
throw new Error('Proxy value must not be empty.');
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
const parsed = new URL(trimmed);
|
|
209
|
+
const server = `${parsed.protocol}//${parsed.host}`;
|
|
210
|
+
if (!parsed.hostname) {
|
|
211
|
+
throw new Error('missing hostname');
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
server,
|
|
215
|
+
...(parsed.username ? { username: decodeURIComponent(parsed.username) } : {}),
|
|
216
|
+
...(parsed.password ? { password: decodeURIComponent(parsed.password) } : {}),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return { server: trimmed };
|
|
221
|
+
}
|
|
159
222
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA0QA,iBAAe,IAAI,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgKhE;AAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAEhB,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAWzF"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ loadEnv();
|
|
|
6
6
|
import { preflightAgentpayGateway } from './agentpay-gateway.js';
|
|
7
7
|
import { browseCommand, browseCommandName } from './command-name.js';
|
|
8
8
|
import { loadSession } from './session.js';
|
|
9
|
-
import { outputError, fatal, info } from './output.js';
|
|
9
|
+
import { outputError, outputJSON, fatal, info } from './output.js';
|
|
10
10
|
function usageText() {
|
|
11
11
|
return `Usage: ${browseCommandName()} <command> [args] [options]
|
|
12
12
|
|
|
@@ -32,8 +32,10 @@ Options:
|
|
|
32
32
|
--compact Launch browser in compact window size (1280x900, default)
|
|
33
33
|
--full Launch browser in full-size window
|
|
34
34
|
--profile <name> Solver profile name for launch (default: "default")
|
|
35
|
+
--proxy <url> Launch browser through proxy for this run only
|
|
36
|
+
--proxyless Ignore configured/profile proxy for this run only
|
|
37
|
+
--headful Explicit alias for headful browser mode (default)
|
|
35
38
|
--headless Launch browser in headless mode
|
|
36
|
-
--no-headless Explicit alias for visible browser mode
|
|
37
39
|
--path <file> Output path for screenshot
|
|
38
40
|
--timeout <seconds> Timeout for solve-captcha command (default: 90)
|
|
39
41
|
--help Show this help message
|
|
@@ -113,13 +115,15 @@ function parseLaunchArgs(args) {
|
|
|
113
115
|
let compact = true;
|
|
114
116
|
let profile;
|
|
115
117
|
let headless = false;
|
|
118
|
+
let proxy;
|
|
119
|
+
let noProxy = false;
|
|
116
120
|
for (let i = 0; i < args.length; i++) {
|
|
117
121
|
const arg = args[i];
|
|
118
122
|
if (arg === '--headless') {
|
|
119
123
|
headless = true;
|
|
120
124
|
continue;
|
|
121
125
|
}
|
|
122
|
-
if (arg === '--
|
|
126
|
+
if (arg === '--headful') {
|
|
123
127
|
headless = false;
|
|
124
128
|
continue;
|
|
125
129
|
}
|
|
@@ -134,21 +138,36 @@ function parseLaunchArgs(args) {
|
|
|
134
138
|
if (arg === '--profile') {
|
|
135
139
|
const value = args[i + 1];
|
|
136
140
|
if (!value || value.startsWith('--')) {
|
|
137
|
-
outputError(`Usage: ${browseCommand('launch', '[url]', '[--profile <name>]', '[--headless]')}`);
|
|
141
|
+
outputError(`Usage: ${browseCommand('launch', '[url]', '[--profile <name>]', '[--proxy <url>|--proxyless]', '[--headful|--headless]')}`);
|
|
138
142
|
}
|
|
139
143
|
profile = value;
|
|
140
144
|
i += 1;
|
|
141
145
|
continue;
|
|
142
146
|
}
|
|
147
|
+
if (arg === '--proxy') {
|
|
148
|
+
const value = args[i + 1];
|
|
149
|
+
if (!value || value.startsWith('--')) {
|
|
150
|
+
outputError(`Usage: ${browseCommand('launch', '[url]', '[--profile <name>]', '[--proxy <url>|--proxyless]', '[--headful|--headless]')}`);
|
|
151
|
+
}
|
|
152
|
+
proxy = value;
|
|
153
|
+
noProxy = false;
|
|
154
|
+
i += 1;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (arg === '--proxyless') {
|
|
158
|
+
proxy = undefined;
|
|
159
|
+
noProxy = true;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
143
162
|
if (arg.startsWith('--')) {
|
|
144
163
|
outputError(`Unknown launch option: ${arg}`);
|
|
145
164
|
}
|
|
146
165
|
if (url) {
|
|
147
|
-
outputError(`Usage: ${browseCommand('launch', '[url]', '[--profile <name>]', '[--headless]')}`);
|
|
166
|
+
outputError(`Usage: ${browseCommand('launch', '[url]', '[--profile <name>]', '[--proxy <url>|--proxyless]', '[--headful|--headless]')}`);
|
|
148
167
|
}
|
|
149
168
|
url = arg;
|
|
150
169
|
}
|
|
151
|
-
return { url, compact, profile, headless };
|
|
170
|
+
return { url, compact, profile, headless, proxy, noProxy };
|
|
152
171
|
}
|
|
153
172
|
function parseCaptchaTimeout(args) {
|
|
154
173
|
const timeoutRaw = getFlag(args, '--timeout');
|
|
@@ -220,11 +239,13 @@ async function main(argv = process.argv) {
|
|
|
220
239
|
case 'launch': {
|
|
221
240
|
const { launch } = await import('./commands/launch.js');
|
|
222
241
|
const launchArgs = parseLaunchArgs(args);
|
|
223
|
-
await launch(launchArgs.url, {
|
|
242
|
+
outputJSON(await launch(launchArgs.url, {
|
|
224
243
|
compact: launchArgs.compact,
|
|
225
244
|
profile: launchArgs.profile,
|
|
226
245
|
headless: launchArgs.headless,
|
|
227
|
-
|
|
246
|
+
proxy: launchArgs.proxy,
|
|
247
|
+
noProxy: launchArgs.noProxy,
|
|
248
|
+
}));
|
|
228
249
|
break;
|
|
229
250
|
}
|
|
230
251
|
case 'navigate': {
|
|
@@ -322,7 +343,7 @@ async function main(argv = process.argv) {
|
|
|
322
343
|
}
|
|
323
344
|
case 'close': {
|
|
324
345
|
const { close } = await import('./commands/close.js');
|
|
325
|
-
await close();
|
|
346
|
+
outputJSON(await close());
|
|
326
347
|
break;
|
|
327
348
|
}
|
|
328
349
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type OwnedPidTerminationResult = 'not_found' | 'terminated' | 'sigkilled' | 'still_alive';
|
|
2
|
+
export declare function isPidAlive(pid: number): boolean;
|
|
3
|
+
export declare function terminateOwnedPid(pid: number): Promise<OwnedPidTerminationResult>;
|
|
4
|
+
//# sourceMappingURL=owned-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owned-process.d.ts","sourceRoot":"","sources":["../src/owned-process.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,yBAAyB,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,aAAa,CAAC;AAEjG,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAW/C;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAsBvF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const TERM_WAIT_ATTEMPTS = 10;
|
|
2
|
+
const TERM_WAIT_MS = 100;
|
|
3
|
+
const KILL_WAIT_ATTEMPTS = 5;
|
|
4
|
+
const KILL_WAIT_MS = 20;
|
|
5
|
+
export function isPidAlive(pid) {
|
|
6
|
+
try {
|
|
7
|
+
process.kill(pid, 0);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
const code = getErrorCode(error);
|
|
12
|
+
if (code === 'EPERM') {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function terminateOwnedPid(pid) {
|
|
19
|
+
try {
|
|
20
|
+
process.kill(pid, 'SIGTERM');
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
return isPidAlive(pid) ? 'still_alive' : 'not_found';
|
|
24
|
+
}
|
|
25
|
+
if (await waitForPidExit(pid, TERM_WAIT_ATTEMPTS, TERM_WAIT_MS)) {
|
|
26
|
+
return 'terminated';
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
process.kill(pid, 'SIGKILL');
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return isPidAlive(pid) ? 'still_alive' : 'sigkilled';
|
|
33
|
+
}
|
|
34
|
+
if (await waitForPidExit(pid, KILL_WAIT_ATTEMPTS, KILL_WAIT_MS)) {
|
|
35
|
+
return 'sigkilled';
|
|
36
|
+
}
|
|
37
|
+
return 'still_alive';
|
|
38
|
+
}
|
|
39
|
+
async function waitForPidExit(pid, attempts, intervalMs) {
|
|
40
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
41
|
+
if (!isPidAlive(pid)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
await sleep(intervalMs);
|
|
45
|
+
}
|
|
46
|
+
return !isPidAlive(pid);
|
|
47
|
+
}
|
|
48
|
+
function getErrorCode(error) {
|
|
49
|
+
if (!error || typeof error !== 'object') {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
const code = Reflect.get(error, 'code');
|
|
53
|
+
return typeof code === 'string' ? code : undefined;
|
|
54
|
+
}
|
|
55
|
+
function sleep(ms) {
|
|
56
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
57
|
+
}
|
package/dist/session.d.ts
CHANGED
|
@@ -19,12 +19,21 @@ export interface BrowseSession {
|
|
|
19
19
|
launchedAt: string;
|
|
20
20
|
port?: number;
|
|
21
21
|
profile?: string;
|
|
22
|
+
identity?: BrowseSessionIdentity;
|
|
22
23
|
capabilities?: {
|
|
23
24
|
captchaSolve?: boolean;
|
|
24
25
|
};
|
|
25
26
|
runtime?: BrowseRuntimeState;
|
|
26
27
|
transientSecretCache?: Record<string, CachedTransientSecretEntry>;
|
|
27
28
|
}
|
|
29
|
+
export interface BrowseSessionIdentity {
|
|
30
|
+
browserInstanceRef: string;
|
|
31
|
+
endpoint: string;
|
|
32
|
+
pid: number;
|
|
33
|
+
profile?: string;
|
|
34
|
+
launchedAt: string;
|
|
35
|
+
ownership: 'agentbrowse';
|
|
36
|
+
}
|
|
28
37
|
export declare function cleanupTransientSecretCache(session: BrowseSession, options?: {
|
|
29
38
|
now?: string;
|
|
30
39
|
}): boolean;
|
|
@@ -34,11 +43,15 @@ export declare function getCachedTransientSecret(session: BrowseSession, intentI
|
|
|
34
43
|
}): CachedTransientSecretEntry | null;
|
|
35
44
|
export declare function deleteCachedTransientSecret(session: BrowseSession, intentId: string): boolean;
|
|
36
45
|
export declare function serializeSession(session: BrowseSession): string;
|
|
46
|
+
export declare function buildOwnedSession(session: Omit<BrowseSession, 'port' | 'identity'>): BrowseSession;
|
|
37
47
|
export declare function saveSession(session: BrowseSession): void;
|
|
38
48
|
export declare function loadSession(): BrowseSession | null;
|
|
39
49
|
export declare function getSessionPort(session: BrowseSession | null): number;
|
|
40
50
|
export declare function deleteSession(): void;
|
|
41
51
|
export declare function supportsCaptchaSolve(session: BrowseSession | null): boolean;
|
|
52
|
+
export declare function isOwnedSession(session: BrowseSession | null | undefined): session is BrowseSession & {
|
|
53
|
+
identity: BrowseSessionIdentity;
|
|
54
|
+
};
|
|
42
55
|
/** Check if the Chrome process from the session is still alive. */
|
|
43
56
|
export declare function isSessionAlive(session: BrowseSession): boolean;
|
|
44
57
|
//# sourceMappingURL=session.d.ts.map
|
package/dist/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAK/D,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE;QACb,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,CAAC;IACF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;CACnE;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAK/D,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,YAAY,CAAC,EAAE;QACb,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,CAAC;IACF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,qBAAqB;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,aAAa,CAAC;CAC1B;AAkDD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,OAAO,CAqBT;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,0BAA0B,GAChC,0BAA0B,CAQ5B;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,0BAA0B,GAAG,IAAI,CAMnC;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAW7F;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAW/D;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU,CAAC,GAChD,aAAa,CAaf;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAGxD;AAED,wBAAgB,WAAW,IAAI,aAAa,GAAG,IAAI,CAclD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,CAWpE;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAE3E;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GACxC,OAAO,IAAI,aAAa,GAAG;IAAE,QAAQ,EAAE,qBAAqB,CAAA;CAAE,CAahE;AAED,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAO9D"}
|
package/dist/session.js
CHANGED
|
@@ -20,6 +20,30 @@ function ensureDir() {
|
|
|
20
20
|
mkdirSync(SESSION_DIR, { recursive: true });
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
function parseSessionPort(cdpUrl) {
|
|
24
|
+
try {
|
|
25
|
+
const url = new URL(cdpUrl);
|
|
26
|
+
if (!url.port) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const port = Number(url.port);
|
|
30
|
+
return Number.isFinite(port) && port > 0 ? port : undefined;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function parseBrowserInstanceRef(cdpUrl) {
|
|
37
|
+
try {
|
|
38
|
+
const url = new URL(cdpUrl);
|
|
39
|
+
const pathSegments = url.pathname.split('/').filter(Boolean);
|
|
40
|
+
return pathSegments.at(-1) ?? cdpUrl;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
const pathSegments = cdpUrl.split('/').filter(Boolean);
|
|
44
|
+
return pathSegments.at(-1) ?? cdpUrl;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
23
47
|
function isExpired(expiresAt, now) {
|
|
24
48
|
if (!expiresAt) {
|
|
25
49
|
return false;
|
|
@@ -79,6 +103,20 @@ export function serializeSession(session) {
|
|
|
79
103
|
return value;
|
|
80
104
|
}, 2);
|
|
81
105
|
}
|
|
106
|
+
export function buildOwnedSession(session) {
|
|
107
|
+
return {
|
|
108
|
+
...session,
|
|
109
|
+
port: parseSessionPort(session.cdpUrl),
|
|
110
|
+
identity: {
|
|
111
|
+
browserInstanceRef: parseBrowserInstanceRef(session.cdpUrl),
|
|
112
|
+
endpoint: session.cdpUrl,
|
|
113
|
+
pid: session.pid,
|
|
114
|
+
profile: session.profile,
|
|
115
|
+
launchedAt: session.launchedAt,
|
|
116
|
+
ownership: 'agentbrowse',
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
82
120
|
export function saveSession(session) {
|
|
83
121
|
ensureDir();
|
|
84
122
|
writeFileSync(SESSION_PATH, serializeSession(session));
|
|
@@ -105,13 +143,9 @@ export function getSessionPort(session) {
|
|
|
105
143
|
if (session?.port)
|
|
106
144
|
return session.port;
|
|
107
145
|
if (session?.cdpUrl) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return Number(url.port);
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
// Ignore malformed cdpUrl and use default fallback.
|
|
146
|
+
const parsedPort = parseSessionPort(session.cdpUrl);
|
|
147
|
+
if (parsedPort) {
|
|
148
|
+
return parsedPort;
|
|
115
149
|
}
|
|
116
150
|
}
|
|
117
151
|
return 9222;
|
|
@@ -123,6 +157,17 @@ export function deleteSession() {
|
|
|
123
157
|
export function supportsCaptchaSolve(session) {
|
|
124
158
|
return session?.capabilities?.captchaSolve === true;
|
|
125
159
|
}
|
|
160
|
+
export function isOwnedSession(session) {
|
|
161
|
+
if (!session?.identity) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
return (session.identity.ownership === 'agentbrowse' &&
|
|
165
|
+
session.identity.endpoint === session.cdpUrl &&
|
|
166
|
+
session.identity.pid === session.pid &&
|
|
167
|
+
session.identity.launchedAt === session.launchedAt &&
|
|
168
|
+
session.identity.browserInstanceRef.length > 0 &&
|
|
169
|
+
session.identity.profile === session.profile);
|
|
170
|
+
}
|
|
126
171
|
/** Check if the Chrome process from the session is still alive. */
|
|
127
172
|
export function isSessionAlive(session) {
|
|
128
173
|
try {
|
package/dist/solver/types.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export type ProxyConfig = {
|
|
|
24
24
|
username?: string;
|
|
25
25
|
password?: string;
|
|
26
26
|
};
|
|
27
|
+
export type ProxySetting = string | ProxyConfig;
|
|
27
28
|
export type ProfileInfo = {
|
|
28
29
|
name: string;
|
|
29
30
|
fingerprint: BrowserFingerprint;
|
|
@@ -37,6 +38,7 @@ export type SolverConfig = {
|
|
|
37
38
|
};
|
|
38
39
|
defaults?: {
|
|
39
40
|
headless?: boolean;
|
|
41
|
+
proxy?: ProxySetting;
|
|
40
42
|
};
|
|
41
43
|
};
|
|
42
44
|
export type CaptchaType = 'recaptcha-v2' | 'hcaptcha' | 'turnstile';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/solver/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,kBAAkB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/solver/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,CAAC;AAEhD,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,kBAAkB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,KAAK,CAAC,EAAE,YAAY,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AAEpE,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,sBAAsB,CAAC;AACrE,MAAM,MAAM,sBAAsB,GAAG,aAAa,GAAG,UAAU,GAAG,cAAc,CAAC;AAEjF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE;QACX,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuanu-ai/agentbrowse",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Browser automation CLI for AI agents: control a CDP browser, observe UI surfaces, act on refs, extract data, capture screenshots, complete protected fills, and solve captchas",
|
|
6
6
|
"keywords": [
|