@nuanu-ai/agentbrowse 0.1.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 +104 -0
- package/dist/agentpay-gateway.d.ts +8 -0
- package/dist/agentpay-gateway.d.ts.map +1 -0
- package/dist/agentpay-gateway.js +58 -0
- package/dist/commands/act.d.ts +5 -0
- package/dist/commands/act.d.ts.map +1 -0
- package/dist/commands/act.js +30 -0
- package/dist/commands/captcha-solve.d.ts +6 -0
- package/dist/commands/captcha-solve.d.ts.map +1 -0
- package/dist/commands/captcha-solve.js +36 -0
- package/dist/commands/close.d.ts +5 -0
- package/dist/commands/close.d.ts.map +1 -0
- package/dist/commands/close.js +32 -0
- package/dist/commands/extract.d.ts +5 -0
- package/dist/commands/extract.d.ts.map +1 -0
- package/dist/commands/extract.js +59 -0
- package/dist/commands/launch.d.ts +10 -0
- package/dist/commands/launch.d.ts.map +1 -0
- package/dist/commands/launch.js +132 -0
- package/dist/commands/navigate.d.ts +5 -0
- package/dist/commands/navigate.d.ts.map +1 -0
- package/dist/commands/navigate.js +26 -0
- package/dist/commands/observe.d.ts +5 -0
- package/dist/commands/observe.d.ts.map +1 -0
- package/dist/commands/observe.js +36 -0
- package/dist/commands/screenshot.d.ts +5 -0
- package/dist/commands/screenshot.d.ts.map +1 -0
- package/dist/commands/screenshot.js +27 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +47 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +247 -0
- package/dist/output.d.ts +20 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +48 -0
- package/dist/session.d.ts +22 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +63 -0
- package/dist/solver/browser-launcher.d.ts +12 -0
- package/dist/solver/browser-launcher.d.ts.map +1 -0
- package/dist/solver/browser-launcher.js +265 -0
- package/dist/solver/captcha-detector.d.ts +22 -0
- package/dist/solver/captcha-detector.d.ts.map +1 -0
- package/dist/solver/captcha-detector.js +463 -0
- package/dist/solver/captcha-runtime.d.ts +18 -0
- package/dist/solver/captcha-runtime.d.ts.map +1 -0
- package/dist/solver/captcha-runtime.js +152 -0
- package/dist/solver/captcha-solver.d.ts +24 -0
- package/dist/solver/captcha-solver.d.ts.map +1 -0
- package/dist/solver/captcha-solver.js +88 -0
- package/dist/solver/config.d.ts +12 -0
- package/dist/solver/config.d.ts.map +1 -0
- package/dist/solver/config.js +67 -0
- package/dist/solver/fingerprint.d.ts +9 -0
- package/dist/solver/fingerprint.d.ts.map +1 -0
- package/dist/solver/fingerprint.js +96 -0
- package/dist/solver/profile-manager.d.ts +8 -0
- package/dist/solver/profile-manager.d.ts.map +1 -0
- package/dist/solver/profile-manager.js +74 -0
- package/dist/solver/types.d.ts +66 -0
- package/dist/solver/types.d.ts.map +1 -0
- package/dist/solver/types.js +1 -0
- package/dist/stagehand.d.ts +20 -0
- package/dist/stagehand.d.ts.map +1 -0
- package/dist/stagehand.js +46 -0
- package/package.json +66 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* browse status — Check browser state (alive, current URL, title).
|
|
3
|
+
*/
|
|
4
|
+
import { loadSession, isSessionAlive, getSessionPort, supportsCaptchaSolve } from '../session.js';
|
|
5
|
+
import { outputJSON } from '../output.js';
|
|
6
|
+
export async function status() {
|
|
7
|
+
const session = loadSession();
|
|
8
|
+
const port = getSessionPort(session);
|
|
9
|
+
if (!session || !isSessionAlive(session)) {
|
|
10
|
+
// Try CDP endpoint directly — Chrome may have been launched externally
|
|
11
|
+
try {
|
|
12
|
+
const res = await fetch(`http://localhost:${port}/json/version`);
|
|
13
|
+
if (res.ok) {
|
|
14
|
+
// Chrome is running but no session file — get page info via CDP
|
|
15
|
+
const listRes = await fetch(`http://localhost:${port}/json/list`);
|
|
16
|
+
const targets = (await listRes.json());
|
|
17
|
+
const page = targets.find((t) => t.type === 'page' && !t.url.startsWith('devtools://'));
|
|
18
|
+
outputJSON({
|
|
19
|
+
success: true,
|
|
20
|
+
alive: true,
|
|
21
|
+
url: page?.url ?? 'unknown',
|
|
22
|
+
title: page?.title ?? 'unknown',
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Chrome not running
|
|
28
|
+
}
|
|
29
|
+
outputJSON({ success: true, alive: false });
|
|
30
|
+
}
|
|
31
|
+
// Session exists and PID is alive — get page info via CDP
|
|
32
|
+
try {
|
|
33
|
+
const listRes = await fetch(`http://localhost:${port}/json/list`);
|
|
34
|
+
const targets = (await listRes.json());
|
|
35
|
+
const page = targets.find((t) => t.type === 'page' && !t.url.startsWith('devtools://'));
|
|
36
|
+
outputJSON({
|
|
37
|
+
success: true,
|
|
38
|
+
alive: true,
|
|
39
|
+
captchaSolveCapable: supportsCaptchaSolve(session),
|
|
40
|
+
url: page?.url ?? 'unknown',
|
|
41
|
+
title: page?.title ?? 'unknown',
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
outputJSON({ success: true, alive: false });
|
|
46
|
+
}
|
|
47
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { config as loadEnv } from 'dotenv';
|
|
3
|
+
loadEnv();
|
|
4
|
+
import { loadSession } from './session.js';
|
|
5
|
+
import { outputError, fatal, info } from './output.js';
|
|
6
|
+
const USAGE = `Usage: agentbrowse <command> [args] [options]
|
|
7
|
+
|
|
8
|
+
Commands:
|
|
9
|
+
launch [url] [options] Launch browser, optionally navigate to URL
|
|
10
|
+
solve-captcha [--timeout <s>] Wait for captcha and solve it on current page
|
|
11
|
+
navigate <url> Navigate current tab to URL
|
|
12
|
+
act "<instruction>" Perform an action (click, type, scroll...)
|
|
13
|
+
extract "<instruction>" Extract data from the page
|
|
14
|
+
observe ["<instruction>"] Discover available actions/elements
|
|
15
|
+
screenshot [--path <file>] Capture a screenshot
|
|
16
|
+
status Check browser state
|
|
17
|
+
close Close browser and clean up
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--compact Launch browser in compact window size (1280x900, default)
|
|
21
|
+
--full Launch browser in full-size window
|
|
22
|
+
--profile <name> Solver profile name for launch (default: "default")
|
|
23
|
+
--headless Launch browser in headless mode
|
|
24
|
+
--schema '<json>' Schema for extract (e.g. '{"price":"number"}')
|
|
25
|
+
--variables '<json>' Variables for act (sensitive, not sent to LLM)
|
|
26
|
+
--path <file> Output path for screenshot
|
|
27
|
+
--timeout <seconds> Timeout for solve-captcha command (default: 90)
|
|
28
|
+
--help Show this help message
|
|
29
|
+
|
|
30
|
+
Environment:
|
|
31
|
+
ANTHROPIC_API_KEY Required for browsing commands
|
|
32
|
+
AGENTBROWSE_MODEL Optional model override for browsing commands
|
|
33
|
+
AGENTPAY_API_KEY Required only for solve-captcha / gateway-backed solve
|
|
34
|
+
AGENTPAY_API_URL Optional API base URL override for solve-captcha`;
|
|
35
|
+
const KNOWN_COMMANDS = new Set([
|
|
36
|
+
'launch',
|
|
37
|
+
'navigate',
|
|
38
|
+
'solve-captcha',
|
|
39
|
+
'solve',
|
|
40
|
+
'captcha-solve',
|
|
41
|
+
'act',
|
|
42
|
+
'extract',
|
|
43
|
+
'observe',
|
|
44
|
+
'screenshot',
|
|
45
|
+
'status',
|
|
46
|
+
'close',
|
|
47
|
+
]);
|
|
48
|
+
function getCommand() {
|
|
49
|
+
const rawArgs = process.argv.slice(2);
|
|
50
|
+
if (rawArgs.length === 0 || rawArgs[0] === '--help') {
|
|
51
|
+
info(USAGE);
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
const command = rawArgs[0];
|
|
55
|
+
const args = rawArgs.slice(1);
|
|
56
|
+
return { command, args };
|
|
57
|
+
}
|
|
58
|
+
/** Parse --key value or --key 'value' from args array. */
|
|
59
|
+
function getFlag(args, flag) {
|
|
60
|
+
const idx = args.indexOf(flag);
|
|
61
|
+
if (idx === -1 || idx + 1 >= args.length)
|
|
62
|
+
return undefined;
|
|
63
|
+
return args[idx + 1];
|
|
64
|
+
}
|
|
65
|
+
function hasFlag(args, flag) {
|
|
66
|
+
return args.includes(flag);
|
|
67
|
+
}
|
|
68
|
+
/** Get the first positional argument (not starting with --). */
|
|
69
|
+
function getPositional(args, valueFlags = []) {
|
|
70
|
+
const valueFlagSet = new Set(valueFlags);
|
|
71
|
+
for (let i = 0; i < args.length; i++) {
|
|
72
|
+
const arg = args[i];
|
|
73
|
+
if (arg.startsWith('--')) {
|
|
74
|
+
if (valueFlagSet.has(arg)) {
|
|
75
|
+
i += 1;
|
|
76
|
+
}
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
return arg;
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
function parseLaunchArgs(args) {
|
|
84
|
+
let url;
|
|
85
|
+
let compact = true;
|
|
86
|
+
let profile;
|
|
87
|
+
let headless = false;
|
|
88
|
+
for (let i = 0; i < args.length; i++) {
|
|
89
|
+
const arg = args[i];
|
|
90
|
+
if (arg === '--headless') {
|
|
91
|
+
headless = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (arg === '--compact') {
|
|
95
|
+
compact = true;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (arg === '--full') {
|
|
99
|
+
compact = false;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (arg === '--profile') {
|
|
103
|
+
const value = args[i + 1];
|
|
104
|
+
if (!value || value.startsWith('--')) {
|
|
105
|
+
outputError('Usage: agentbrowse launch [url] [--profile <name>] [--headless]');
|
|
106
|
+
}
|
|
107
|
+
profile = value;
|
|
108
|
+
i += 1;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (arg.startsWith('--')) {
|
|
112
|
+
outputError(`Unknown launch option: ${arg}`);
|
|
113
|
+
}
|
|
114
|
+
if (url) {
|
|
115
|
+
outputError('Usage: agentbrowse launch [url] [--profile <name>] [--headless]');
|
|
116
|
+
}
|
|
117
|
+
url = arg;
|
|
118
|
+
}
|
|
119
|
+
return { url, compact, profile, headless };
|
|
120
|
+
}
|
|
121
|
+
function parseCaptchaTimeout(args) {
|
|
122
|
+
const timeoutRaw = getFlag(args, '--timeout');
|
|
123
|
+
const timeout = timeoutRaw ? Number(timeoutRaw) : undefined;
|
|
124
|
+
if (timeoutRaw && (!Number.isFinite(timeout) || timeout <= 0)) {
|
|
125
|
+
outputError('Invalid --timeout value. Expected a positive number of seconds.');
|
|
126
|
+
}
|
|
127
|
+
return timeout;
|
|
128
|
+
}
|
|
129
|
+
/** Require an active browser session, return CDP URL. */
|
|
130
|
+
function requireSession() {
|
|
131
|
+
const session = loadSession();
|
|
132
|
+
if (session)
|
|
133
|
+
return session.cdpUrl;
|
|
134
|
+
// Fallback: try CDP on port 9222 directly
|
|
135
|
+
// (Chrome may have been launched by agentpay-cli or externally)
|
|
136
|
+
// Caller will handle connection errors.
|
|
137
|
+
return 'ws://localhost:9222';
|
|
138
|
+
}
|
|
139
|
+
async function main() {
|
|
140
|
+
const parsed = getCommand();
|
|
141
|
+
if (!parsed)
|
|
142
|
+
process.exit(1);
|
|
143
|
+
const { command, args } = parsed;
|
|
144
|
+
if (!KNOWN_COMMANDS.has(command)) {
|
|
145
|
+
outputError(`Unknown command: ${command}\n\n${USAGE}`);
|
|
146
|
+
}
|
|
147
|
+
switch (command) {
|
|
148
|
+
case 'launch': {
|
|
149
|
+
const { launch } = await import('./commands/launch.js');
|
|
150
|
+
const launchArgs = parseLaunchArgs(args);
|
|
151
|
+
await launch(launchArgs.url, {
|
|
152
|
+
compact: launchArgs.compact,
|
|
153
|
+
profile: launchArgs.profile,
|
|
154
|
+
headless: launchArgs.headless,
|
|
155
|
+
});
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case 'navigate': {
|
|
159
|
+
const url = getPositional(args);
|
|
160
|
+
if (!url)
|
|
161
|
+
outputError('Usage: agentbrowse navigate <url>');
|
|
162
|
+
const { navigate } = await import('./commands/navigate.js');
|
|
163
|
+
await navigate(requireSession(), url);
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case 'solve-captcha': {
|
|
167
|
+
const timeout = parseCaptchaTimeout(args);
|
|
168
|
+
const { captchaSolve } = await import('./commands/captcha-solve.js');
|
|
169
|
+
await captchaSolve(loadSession(), timeout);
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
// Backward-compatible alias.
|
|
173
|
+
case 'solve': {
|
|
174
|
+
const target = getPositional(args, ['--timeout']);
|
|
175
|
+
if (target !== 'captcha') {
|
|
176
|
+
outputError('Usage: agentbrowse solve captcha [--timeout <seconds>]');
|
|
177
|
+
}
|
|
178
|
+
const timeout = parseCaptchaTimeout(args);
|
|
179
|
+
const { captchaSolve } = await import('./commands/captcha-solve.js');
|
|
180
|
+
await captchaSolve(loadSession(), timeout);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
// Backward-compatible alias.
|
|
184
|
+
case 'captcha-solve': {
|
|
185
|
+
const timeout = parseCaptchaTimeout(args);
|
|
186
|
+
const { captchaSolve } = await import('./commands/captcha-solve.js');
|
|
187
|
+
await captchaSolve(loadSession(), timeout);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
case 'act': {
|
|
191
|
+
const instruction = getPositional(args, ['--variables']);
|
|
192
|
+
if (!instruction)
|
|
193
|
+
outputError('Usage: agentbrowse act "<instruction>"');
|
|
194
|
+
let variables;
|
|
195
|
+
const varsJson = getFlag(args, '--variables');
|
|
196
|
+
if (varsJson) {
|
|
197
|
+
try {
|
|
198
|
+
variables = JSON.parse(varsJson);
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
outputError('Invalid --variables JSON');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const { act } = await import('./commands/act.js');
|
|
205
|
+
await act(requireSession(), instruction, variables);
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
case 'extract': {
|
|
209
|
+
const instruction = getPositional(args, ['--schema']);
|
|
210
|
+
if (!instruction)
|
|
211
|
+
outputError('Usage: agentbrowse extract "<instruction>"');
|
|
212
|
+
const schemaJson = getFlag(args, '--schema');
|
|
213
|
+
const { extract } = await import('./commands/extract.js');
|
|
214
|
+
await extract(requireSession(), instruction, schemaJson);
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
case 'observe': {
|
|
218
|
+
const instruction = getPositional(args);
|
|
219
|
+
const { observe } = await import('./commands/observe.js');
|
|
220
|
+
await observe(requireSession(), instruction);
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case 'screenshot': {
|
|
224
|
+
if (hasFlag(args, '--help')) {
|
|
225
|
+
info('Usage: agentbrowse screenshot [--path <file>]');
|
|
226
|
+
process.exit(0);
|
|
227
|
+
}
|
|
228
|
+
const filePath = getFlag(args, '--path');
|
|
229
|
+
const { screenshot } = await import('./commands/screenshot.js');
|
|
230
|
+
await screenshot(requireSession(), filePath);
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case 'status': {
|
|
234
|
+
const { status } = await import('./commands/status.js');
|
|
235
|
+
await status();
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
case 'close': {
|
|
239
|
+
const { close } = await import('./commands/close.js');
|
|
240
|
+
await close();
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
main().catch((err) => {
|
|
246
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
247
|
+
});
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured output helpers.
|
|
3
|
+
* Human-readable text to stdout/stderr.
|
|
4
|
+
*/
|
|
5
|
+
export interface BrowseResult {
|
|
6
|
+
success: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
/** Write result to stdout and exit. Errors go to stderr with exit 1. */
|
|
13
|
+
export declare function outputJSON(result: BrowseResult): never;
|
|
14
|
+
/** Write error to stderr and exit 1. */
|
|
15
|
+
export declare function outputError(error: string): never;
|
|
16
|
+
/** Write a progress/info message to stderr. */
|
|
17
|
+
export declare function info(message: string): void;
|
|
18
|
+
/** Fatal crash — unhandled error, exit 1. */
|
|
19
|
+
export declare function fatal(message: string): never;
|
|
20
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AASD,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAsBtD;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAEhD;AAED,+CAA+C;AAC/C,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,6CAA6C;AAC7C,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAG5C"}
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured output helpers.
|
|
3
|
+
* Human-readable text to stdout/stderr.
|
|
4
|
+
*/
|
|
5
|
+
/** Format a value for display. Objects/arrays → indented JSON, rest → string. */
|
|
6
|
+
function formatValue(value) {
|
|
7
|
+
if (value === null || value === undefined)
|
|
8
|
+
return '';
|
|
9
|
+
if (typeof value === 'object')
|
|
10
|
+
return JSON.stringify(value, null, 2);
|
|
11
|
+
return String(value);
|
|
12
|
+
}
|
|
13
|
+
/** Write result to stdout and exit. Errors go to stderr with exit 1. */
|
|
14
|
+
export function outputJSON(result) {
|
|
15
|
+
if (!result.success) {
|
|
16
|
+
process.stderr.write(`${result.error}\n`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const { success: _, ...rest } = result;
|
|
20
|
+
const entries = Object.entries(rest).filter(([, v]) => v !== undefined);
|
|
21
|
+
if (entries.length === 0) {
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
const maxKey = Math.max(...entries.map(([k]) => k.length));
|
|
25
|
+
for (const [key, value] of entries) {
|
|
26
|
+
const formatted = formatValue(value);
|
|
27
|
+
if (typeof value === 'object' && value !== null) {
|
|
28
|
+
process.stdout.write(`${key}:\n${formatted}\n`);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
process.stdout.write(`${key.padEnd(maxKey)} ${formatted}\n`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
/** Write error to stderr and exit 1. */
|
|
37
|
+
export function outputError(error) {
|
|
38
|
+
outputJSON({ success: false, error });
|
|
39
|
+
}
|
|
40
|
+
/** Write a progress/info message to stderr. */
|
|
41
|
+
export function info(message) {
|
|
42
|
+
process.stderr.write(`${message}\n`);
|
|
43
|
+
}
|
|
44
|
+
/** Fatal crash — unhandled error, exit 1. */
|
|
45
|
+
export function fatal(message) {
|
|
46
|
+
process.stderr.write(`[agentbrowse] Fatal: ${message}\n`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session persistence for agentbrowse.
|
|
3
|
+
* Stores CDP URL + Chrome PID in ~/.agentpay/browse-session.json
|
|
4
|
+
*/
|
|
5
|
+
export interface BrowseSession {
|
|
6
|
+
cdpUrl: string;
|
|
7
|
+
pid: number;
|
|
8
|
+
launchedAt: string;
|
|
9
|
+
port?: number;
|
|
10
|
+
profile?: string;
|
|
11
|
+
capabilities?: {
|
|
12
|
+
captchaSolve?: boolean;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare function saveSession(session: BrowseSession): void;
|
|
16
|
+
export declare function loadSession(): BrowseSession | null;
|
|
17
|
+
export declare function getSessionPort(session: BrowseSession | null): number;
|
|
18
|
+
export declare function deleteSession(): void;
|
|
19
|
+
export declare function supportsCaptchaSolve(session: BrowseSession | null): boolean;
|
|
20
|
+
/** Check if the Chrome process from the session is still alive. */
|
|
21
|
+
export declare function isSessionAlive(session: BrowseSession): boolean;
|
|
22
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,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;CACH;AAQD,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAGxD;AAED,wBAAgB,WAAW,IAAI,aAAa,GAAG,IAAI,CASlD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,CAapE;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAE3E;AAED,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAO9D"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session persistence for agentbrowse.
|
|
3
|
+
* Stores CDP URL + Chrome PID in ~/.agentpay/browse-session.json
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
const SESSION_DIR = join(homedir(), '.agentpay');
|
|
9
|
+
const SESSION_PATH = join(SESSION_DIR, 'browse-session.json');
|
|
10
|
+
function ensureDir() {
|
|
11
|
+
if (!existsSync(SESSION_DIR)) {
|
|
12
|
+
mkdirSync(SESSION_DIR, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function saveSession(session) {
|
|
16
|
+
ensureDir();
|
|
17
|
+
writeFileSync(SESSION_PATH, JSON.stringify(session, null, 2));
|
|
18
|
+
}
|
|
19
|
+
export function loadSession() {
|
|
20
|
+
if (!existsSync(SESSION_PATH))
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
const raw = JSON.parse(readFileSync(SESSION_PATH, 'utf-8'));
|
|
24
|
+
if (!raw.cdpUrl || !raw.pid)
|
|
25
|
+
return null;
|
|
26
|
+
return raw;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function getSessionPort(session) {
|
|
33
|
+
if (session?.port)
|
|
34
|
+
return session.port;
|
|
35
|
+
if (session?.cdpUrl) {
|
|
36
|
+
try {
|
|
37
|
+
const url = new URL(session.cdpUrl);
|
|
38
|
+
if (url.port)
|
|
39
|
+
return Number(url.port);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Ignore malformed cdpUrl and use default fallback.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return 9222;
|
|
46
|
+
}
|
|
47
|
+
export function deleteSession() {
|
|
48
|
+
if (existsSync(SESSION_PATH))
|
|
49
|
+
unlinkSync(SESSION_PATH);
|
|
50
|
+
}
|
|
51
|
+
export function supportsCaptchaSolve(session) {
|
|
52
|
+
return session?.capabilities?.captchaSolve === true;
|
|
53
|
+
}
|
|
54
|
+
/** Check if the Chrome process from the session is still alive. */
|
|
55
|
+
export function isSessionAlive(session) {
|
|
56
|
+
try {
|
|
57
|
+
process.kill(session.pid, 0);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Browser, Page } from 'puppeteer';
|
|
2
|
+
import type { LaunchOptions, ProfileInfo } from './types.js';
|
|
3
|
+
export type SolverSession = {
|
|
4
|
+
browser: Browser;
|
|
5
|
+
page: Page;
|
|
6
|
+
cdpUrl: string;
|
|
7
|
+
profile: ProfileInfo;
|
|
8
|
+
close: () => Promise<void>;
|
|
9
|
+
disconnect: () => Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
export declare function launchSolver(profile: ProfileInfo, opts?: LaunchOptions): Promise<SolverSession>;
|
|
12
|
+
//# sourceMappingURL=browser-launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-launcher.d.ts","sourceRoot":"","sources":["../../src/solver/browser-launcher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAsB,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAWjF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC,CAAC;AAcF,wBAAsB,YAAY,CAChC,OAAO,EAAE,WAAW,EACpB,IAAI,CAAC,EAAE,aAAa,GACnB,OAAO,CAAC,aAAa,CAAC,CA0ExB"}
|