@nuanu-ai/agentbrowse 0.2.1 → 0.2.3
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 +7 -10
- package/dist/agentpay-gateway.d.ts +1 -0
- package/dist/agentpay-gateway.d.ts.map +1 -1
- package/dist/agentpay-gateway.js +6 -1
- package/dist/agentpay-stagehand-llm.d.ts +19 -0
- package/dist/agentpay-stagehand-llm.d.ts.map +1 -0
- package/dist/agentpay-stagehand-llm.js +128 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -11
- package/dist/stagehand.d.ts.map +1 -1
- package/dist/stagehand.js +4 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ agentbrowse launch https://example.com
|
|
|
27
27
|
|
|
28
28
|
- Node.js 18+
|
|
29
29
|
- a Chrome-compatible browser runtime available on the machine
|
|
30
|
-
- an
|
|
30
|
+
- an AgentPay API key for CLI startup and browsing commands
|
|
31
31
|
|
|
32
32
|
## Commands
|
|
33
33
|
|
|
@@ -76,26 +76,23 @@ agentbrowse close
|
|
|
76
76
|
|
|
77
77
|
## Configure
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
`agentbrowse` uses the AgentPay backend for browser reasoning and gateway-backed
|
|
80
|
+
operations:
|
|
80
81
|
|
|
81
82
|
```bash
|
|
82
|
-
export
|
|
83
|
+
export AGENTPAY_API_KEY=...
|
|
83
84
|
```
|
|
84
85
|
|
|
85
|
-
Optional
|
|
86
|
+
Optional API base URL override:
|
|
86
87
|
|
|
87
88
|
```bash
|
|
88
|
-
export
|
|
89
|
+
export AGENTPAY_API_URL=https://durcottggsiesxxqzvbb.supabase.co/functions/v1/api
|
|
89
90
|
```
|
|
90
91
|
|
|
91
|
-
`solve-captcha` is separate and uses AgentPay gateway credentials only when
|
|
92
|
-
that command is invoked.
|
|
93
|
-
|
|
94
92
|
## Runtime model
|
|
95
93
|
|
|
96
94
|
- `agentbrowse` persists the active browser session under `~/.agentpay`
|
|
97
|
-
-
|
|
98
|
-
- normal browsing commands do not require `AGENTPAY_API_KEY`
|
|
95
|
+
- all commands require `AGENTPAY_API_KEY`
|
|
99
96
|
- `solve-captcha` requires both:
|
|
100
97
|
- a session with captcha-solving capability
|
|
101
98
|
- AgentPay gateway configuration
|
|
@@ -5,4 +5,5 @@ export interface AgentpayGatewayConfig {
|
|
|
5
5
|
export declare function tryResolveAgentpayGatewayConfig(): AgentpayGatewayConfig | null;
|
|
6
6
|
export declare function resolveAgentpayGatewayConfig(): AgentpayGatewayConfig;
|
|
7
7
|
export declare function applyAgentpayGatewayEnv(gateway: AgentpayGatewayConfig): void;
|
|
8
|
+
export declare function preflightAgentpayGateway(): Promise<AgentpayGatewayConfig>;
|
|
8
9
|
//# sourceMappingURL=agentpay-gateway.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentpay-gateway.d.ts","sourceRoot":"","sources":["../src/agentpay-gateway.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAiCD,wBAAgB,+BAA+B,IAAI,qBAAqB,GAAG,IAAI,CAoB9E;AAED,wBAAgB,4BAA4B,IAAI,qBAAqB,CAMpE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAG5E"}
|
|
1
|
+
{"version":3,"file":"agentpay-gateway.d.ts","sourceRoot":"","sources":["../src/agentpay-gateway.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAiCD,wBAAgB,+BAA+B,IAAI,qBAAqB,GAAG,IAAI,CAoB9E;AAED,wBAAgB,4BAA4B,IAAI,qBAAqB,CAMpE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAG5E;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAI/E"}
|
package/dist/agentpay-gateway.js
CHANGED
|
@@ -48,7 +48,7 @@ export function tryResolveAgentpayGatewayConfig() {
|
|
|
48
48
|
export function resolveAgentpayGatewayConfig() {
|
|
49
49
|
const gateway = tryResolveAgentpayGatewayConfig();
|
|
50
50
|
if (!gateway) {
|
|
51
|
-
throw new Error('
|
|
51
|
+
throw new Error('AgentPay API key is required.');
|
|
52
52
|
}
|
|
53
53
|
return gateway;
|
|
54
54
|
}
|
|
@@ -56,3 +56,8 @@ export function applyAgentpayGatewayEnv(gateway) {
|
|
|
56
56
|
process.env.AGENTPAY_API_KEY = gateway.apiKey;
|
|
57
57
|
process.env.AGENTPAY_API_URL = gateway.apiUrl;
|
|
58
58
|
}
|
|
59
|
+
export async function preflightAgentpayGateway() {
|
|
60
|
+
const gateway = resolveAgentpayGatewayConfig();
|
|
61
|
+
applyAgentpayGatewayEnv(gateway);
|
|
62
|
+
return gateway;
|
|
63
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { LLMClient, toJsonSchema, type CreateChatCompletionOptions, type LLMParsedResponse, type LLMResponse } from '@browserbasehq/stagehand';
|
|
2
|
+
import type { AgentpayGatewayConfig } from './agentpay-gateway.js';
|
|
3
|
+
export declare class AgentpayStagehandLlmClient extends LLMClient {
|
|
4
|
+
private readonly gateway;
|
|
5
|
+
type: "agentpay";
|
|
6
|
+
clientOptions: {};
|
|
7
|
+
constructor(gateway: AgentpayGatewayConfig);
|
|
8
|
+
createChatCompletion<T>(args: CreateChatCompletionOptions & {
|
|
9
|
+
options: {
|
|
10
|
+
response_model: {
|
|
11
|
+
name: string;
|
|
12
|
+
schema: Parameters<typeof toJsonSchema>[0];
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
}): Promise<LLMParsedResponse<T>>;
|
|
16
|
+
createChatCompletion<T = LLMResponse>(args: CreateChatCompletionOptions): Promise<T>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createAgentpayStagehandLlmClient(gateway: AgentpayGatewayConfig): AgentpayStagehandLlmClient;
|
|
19
|
+
//# sourceMappingURL=agentpay-stagehand-llm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentpay-stagehand-llm.d.ts","sourceRoot":"","sources":["../src/agentpay-stagehand-llm.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAEjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAiDnE,qBAAa,0BAA2B,SAAQ,SAAS;IAI3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,IAAI,EAAG,UAAU,CAAU;IAC3B,aAAa,KAAM;gBAEU,OAAO,EAAE,qBAAqB;IAKrD,oBAAoB,CAAC,CAAC,EAC1B,IAAI,EAAE,2BAA2B,GAAG;QAClC,OAAO,EAAE;YACP,cAAc,EAAE;gBACd,IAAI,EAAE,MAAM,CAAC;gBACb,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;aAC5C,CAAC;SACH,CAAC;KACH,GACA,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC1B,oBAAoB,CAAC,CAAC,GAAG,WAAW,EACxC,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC,CAAC,CAAC;CA4Fd;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,qBAAqB,GAC7B,0BAA0B,CAE5B"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { LLMClient, toJsonSchema, } from '@browserbasehq/stagehand';
|
|
2
|
+
function gatewayBaseUrl(gateway) {
|
|
3
|
+
return gateway.apiUrl.replace(/\/$/, '');
|
|
4
|
+
}
|
|
5
|
+
function isRetryableStatus(status) {
|
|
6
|
+
return status === 429 || status === 502 || status === 503 || status === 504 || status >= 500;
|
|
7
|
+
}
|
|
8
|
+
function resolvePurpose(options) {
|
|
9
|
+
const modelName = options.response_model?.name?.trim().toLowerCase();
|
|
10
|
+
switch (modelName) {
|
|
11
|
+
case 'observation':
|
|
12
|
+
return 'browse.observe';
|
|
13
|
+
case 'extraction':
|
|
14
|
+
return 'browse.extract';
|
|
15
|
+
case 'metadata':
|
|
16
|
+
return 'browse.extract.metadata';
|
|
17
|
+
case 'act':
|
|
18
|
+
return 'browse.act';
|
|
19
|
+
default:
|
|
20
|
+
return 'browse.stagehand';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function withRetry(fn, retries = 1) {
|
|
24
|
+
for (let attempt = 0;; attempt += 1) {
|
|
25
|
+
try {
|
|
26
|
+
return await fn();
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const retryable = err instanceof Error &&
|
|
30
|
+
(err.name === 'RetryableHttpError' || err.name === 'RetryableNetworkError');
|
|
31
|
+
if (!retryable || attempt >= retries) {
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
await new Promise((resolve) => setTimeout(resolve, 2_000 * (attempt + 1)));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class AgentpayStagehandLlmClient extends LLMClient {
|
|
39
|
+
gateway;
|
|
40
|
+
type = 'agentpay';
|
|
41
|
+
clientOptions = {};
|
|
42
|
+
constructor(gateway) {
|
|
43
|
+
super('agentpay/backend');
|
|
44
|
+
this.gateway = gateway;
|
|
45
|
+
this.modelName = 'agentpay/backend';
|
|
46
|
+
}
|
|
47
|
+
async createChatCompletion({ options, logger }) {
|
|
48
|
+
if (!options.response_model) {
|
|
49
|
+
logger({
|
|
50
|
+
category: 'llm',
|
|
51
|
+
message: 'agentpay backend llm client received unsupported non-structured completion',
|
|
52
|
+
level: 0,
|
|
53
|
+
});
|
|
54
|
+
throw new Error('AgentPay Stagehand LLM client currently requires response_model');
|
|
55
|
+
}
|
|
56
|
+
const url = `${gatewayBaseUrl(this.gateway)}/tools/llm/structured-chat`;
|
|
57
|
+
const body = {
|
|
58
|
+
purpose: resolvePurpose(options),
|
|
59
|
+
messages: options.messages,
|
|
60
|
+
response_model: {
|
|
61
|
+
name: options.response_model.name,
|
|
62
|
+
schema: toJsonSchema(options.response_model.schema),
|
|
63
|
+
},
|
|
64
|
+
image: options.image
|
|
65
|
+
? {
|
|
66
|
+
media_type: 'image/jpeg',
|
|
67
|
+
data_base64: options.image.buffer.toString('base64'),
|
|
68
|
+
description: options.image.description,
|
|
69
|
+
}
|
|
70
|
+
: undefined,
|
|
71
|
+
temperature: options.temperature,
|
|
72
|
+
max_output_tokens: options.maxOutputTokens,
|
|
73
|
+
};
|
|
74
|
+
const result = await withRetry(async () => {
|
|
75
|
+
let response;
|
|
76
|
+
try {
|
|
77
|
+
response = await fetch(url, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers: {
|
|
80
|
+
Authorization: `Bearer ${this.gateway.apiKey}`,
|
|
81
|
+
Accept: 'application/json',
|
|
82
|
+
'Content-Type': 'application/json',
|
|
83
|
+
},
|
|
84
|
+
body: JSON.stringify(body),
|
|
85
|
+
signal: AbortSignal.timeout(45_000),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
const error = new Error(`AgentPay LLM gateway network error: ${err instanceof Error ? err.message : String(err)}`);
|
|
90
|
+
error.name = 'RetryableNetworkError';
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
let json;
|
|
94
|
+
try {
|
|
95
|
+
json = (await response.json());
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
const parseError = new Error(`AgentPay LLM gateway returned non-JSON response (${response.status})`);
|
|
99
|
+
parseError.name = isRetryableStatus(response.status) ? 'RetryableHttpError' : 'HttpError';
|
|
100
|
+
throw parseError;
|
|
101
|
+
}
|
|
102
|
+
if (!response.ok) {
|
|
103
|
+
const message = typeof json.error === 'string' ? json.error : `HTTP ${response.status}`;
|
|
104
|
+
const error = new Error(`AgentPay LLM gateway error (${response.status}): ${message}`);
|
|
105
|
+
error.name = isRetryableStatus(response.status) ? 'RetryableHttpError' : 'HttpError';
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
return json;
|
|
109
|
+
});
|
|
110
|
+
logger({
|
|
111
|
+
category: 'llm',
|
|
112
|
+
message: 'agentpay backend structured completion finished',
|
|
113
|
+
level: 2,
|
|
114
|
+
auxiliary: {
|
|
115
|
+
provider: { value: result.provider, type: 'string' },
|
|
116
|
+
model: { value: result.model, type: 'string' },
|
|
117
|
+
purpose: { value: resolvePurpose(options), type: 'string' },
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
data: result.data,
|
|
122
|
+
usage: result.usage,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export function createAgentpayStagehandLlmClient(gateway) {
|
|
127
|
+
return new AgentpayStagehandLlmClient(gateway);
|
|
128
|
+
}
|
package/dist/index.d.ts
CHANGED
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":";AA8KA,iBAAe,IAAI,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsGhE;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
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { config as loadEnv } from 'dotenv';
|
|
3
|
+
import { realpathSync } from 'node:fs';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
3
5
|
loadEnv();
|
|
6
|
+
import { preflightAgentpayGateway } from './agentpay-gateway.js';
|
|
4
7
|
import { browseCommand, browseCommandName } from './command-name.js';
|
|
5
8
|
import { loadSession } from './session.js';
|
|
6
9
|
import { outputError, fatal, info } from './output.js';
|
|
@@ -30,10 +33,8 @@ Options:
|
|
|
30
33
|
--help Show this help message
|
|
31
34
|
|
|
32
35
|
Environment:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
AGENTPAY_API_KEY Required only for solve-captcha / gateway-backed solve
|
|
36
|
-
AGENTPAY_API_URL Optional API base URL override for solve-captcha`;
|
|
36
|
+
AGENTPAY_API_KEY Required for CLI start and browsing commands
|
|
37
|
+
AGENTPAY_API_URL Optional API base URL override`;
|
|
37
38
|
}
|
|
38
39
|
const KNOWN_COMMANDS = new Set([
|
|
39
40
|
'launch',
|
|
@@ -46,8 +47,8 @@ const KNOWN_COMMANDS = new Set([
|
|
|
46
47
|
'status',
|
|
47
48
|
'close',
|
|
48
49
|
]);
|
|
49
|
-
function getCommand() {
|
|
50
|
-
const rawArgs =
|
|
50
|
+
function getCommand(argv = process.argv) {
|
|
51
|
+
const rawArgs = argv.slice(2);
|
|
51
52
|
if (rawArgs.length === 0 || rawArgs[0] === '--help') {
|
|
52
53
|
info(usageText());
|
|
53
54
|
process.exit(0);
|
|
@@ -137,14 +138,20 @@ function requireSession() {
|
|
|
137
138
|
// Caller will handle connection errors.
|
|
138
139
|
return 'ws://localhost:9222';
|
|
139
140
|
}
|
|
140
|
-
async function main() {
|
|
141
|
-
const parsed = getCommand();
|
|
141
|
+
async function main(argv = process.argv) {
|
|
142
|
+
const parsed = getCommand(argv);
|
|
142
143
|
if (!parsed)
|
|
143
144
|
process.exit(1);
|
|
144
145
|
const { command, args } = parsed;
|
|
145
146
|
if (!KNOWN_COMMANDS.has(command)) {
|
|
146
147
|
outputError(`Unknown command: ${command}\n\n${usageText()}`);
|
|
147
148
|
}
|
|
149
|
+
try {
|
|
150
|
+
await preflightAgentpayGateway();
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
outputError(err instanceof Error ? err.message : String(err));
|
|
154
|
+
}
|
|
148
155
|
switch (command) {
|
|
149
156
|
case 'launch': {
|
|
150
157
|
const { launch } = await import('./commands/launch.js');
|
|
@@ -225,6 +232,21 @@ async function main() {
|
|
|
225
232
|
}
|
|
226
233
|
}
|
|
227
234
|
}
|
|
228
|
-
main
|
|
229
|
-
|
|
230
|
-
|
|
235
|
+
export { main };
|
|
236
|
+
export function isDirectExecution(metaUrl, argv = process.argv) {
|
|
237
|
+
const entry = argv[1];
|
|
238
|
+
if (!entry) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
return realpathSync(entry) === realpathSync(fileURLToPath(metaUrl));
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (isDirectExecution(import.meta.url)) {
|
|
249
|
+
main().catch((err) => {
|
|
250
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
251
|
+
});
|
|
252
|
+
}
|
package/dist/stagehand.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stagehand.d.ts","sourceRoot":"","sources":["../src/stagehand.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"stagehand.d.ts","sourceRoot":"","sources":["../src/stagehand.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAMrD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,kDAAkD;AAClD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAezE;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,IAAI,SAAmB,GAAG,MAAM,GAAG,IAAI,CAQpE;AAED,qDAAqD;AACrD,wBAAsB,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAI/F"}
|
package/dist/stagehand.js
CHANGED
|
@@ -6,17 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { execSync } from 'node:child_process';
|
|
8
8
|
import { Stagehand } from '@browserbasehq/stagehand';
|
|
9
|
+
import { createAgentpayStagehandLlmClient } from './agentpay-stagehand-llm.js';
|
|
10
|
+
import { resolveAgentpayGatewayConfig } from './agentpay-gateway.js';
|
|
9
11
|
const DEFAULT_CDP_PORT = 9222;
|
|
10
|
-
const DEFAULT_MODEL = 'anthropic/claude-haiku-4-5-20251001';
|
|
11
|
-
function resolveStagehandModel() {
|
|
12
|
-
const override = process.env.AGENTBROWSE_MODEL?.trim();
|
|
13
|
-
return override && override.length > 0 ? override : DEFAULT_MODEL;
|
|
14
|
-
}
|
|
15
12
|
/** Connect to an existing browser via CDP URL. */
|
|
16
13
|
export async function connectStagehand(cdpUrl) {
|
|
14
|
+
const gateway = resolveAgentpayGatewayConfig();
|
|
17
15
|
const stagehand = new Stagehand({
|
|
18
16
|
env: 'LOCAL',
|
|
19
|
-
|
|
17
|
+
llmClient: createAgentpayStagehandLlmClient(gateway),
|
|
20
18
|
localBrowserLaunchOptions: {
|
|
21
19
|
cdpUrl,
|
|
22
20
|
},
|