@nuanu-ai/agentbrowse 0.2.2 → 0.2.4

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 CHANGED
@@ -27,8 +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 Anthropic API key for browsing commands
31
- - an AgentPay API key for CLI startup
30
+ - an AgentPay API key for CLI startup and browsing commands
32
31
 
33
32
  ## Commands
34
33
 
@@ -77,25 +76,22 @@ agentbrowse close
77
76
 
78
77
  ## Configure
79
78
 
80
- Browsing commands use Anthropic via Stagehand:
79
+ `agentbrowse` uses the AgentPay backend for browser reasoning and gateway-backed
80
+ operations:
81
81
 
82
82
  ```bash
83
- export ANTHROPIC_API_KEY=...
83
+ export AGENTPAY_API_KEY=...
84
84
  ```
85
85
 
86
- Optional model override:
86
+ Optional API base URL override:
87
87
 
88
88
  ```bash
89
- export AGENTBROWSE_MODEL=anthropic/claude-haiku-4-5-20251001
89
+ export AGENTPAY_API_URL=https://durcottggsiesxxqzvbb.supabase.co/functions/v1/api
90
90
  ```
91
91
 
92
- `agentbrowse` also requires an AgentPay API key at startup so the CLI stays on
93
- the same gateway-backed contract as the rest of the toolchain.
94
-
95
92
  ## Runtime model
96
93
 
97
94
  - `agentbrowse` persists the active browser session under `~/.agentpay`
98
- - browsing commands require `ANTHROPIC_API_KEY`
99
95
  - all commands require `AGENTPAY_API_KEY`
100
96
  - `solve-captcha` requires both:
101
97
  - a session with captcha-solving capability
@@ -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
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAgLA,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"}
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
@@ -33,9 +33,7 @@ Options:
33
33
  --help Show this help message
34
34
 
35
35
  Environment:
36
- ANTHROPIC_API_KEY Required for browsing commands
37
- AGENTBROWSE_MODEL Optional model override for browsing commands
38
- AGENTPAY_API_KEY Required for CLI start
36
+ AGENTPAY_API_KEY Required for CLI start and browsing commands
39
37
  AGENTPAY_API_URL Optional API base URL override`;
40
38
  }
41
39
  const KNOWN_COMMANDS = new Set([
@@ -39,14 +39,14 @@ export class CaptchaSolver {
39
39
  throw new Error(`CAPTCHA solving timed out after ${Math.ceil(this.taskTimeoutMs / 1000)}s`);
40
40
  }
41
41
  async createTask(type, siteKey, pageUrl) {
42
- return this.request('POST', '/providers/captcha/tasks', {
42
+ return this.request('POST', '/tools/captcha/tasks', {
43
43
  type,
44
44
  site_key: siteKey,
45
45
  page_url: pageUrl,
46
46
  });
47
47
  }
48
48
  async getTaskStatus(taskId) {
49
- return this.request('GET', `/providers/captcha/tasks/${encodeURIComponent(taskId)}`);
49
+ return this.request('GET', `/tools/captcha/tasks/${encodeURIComponent(taskId)}`);
50
50
  }
51
51
  async request(method, path, body) {
52
52
  const url = `${this.apiUrl}${path}`;
@@ -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;AAUrD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,kDAAkD;AAClD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAczE;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"}
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
- model: resolveStagehandModel(),
17
+ llmClient: createAgentpayStagehandLlmClient(gateway),
20
18
  localBrowserLaunchOptions: {
21
19
  cdpUrl,
22
20
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuanu-ai/agentbrowse",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "description": "Standalone browser automation CLI for AI agents: launch, observe, act, extract, and solve captcha",
6
6
  "keywords": [