@usecrow/client 0.1.19 → 0.1.21

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.
@@ -0,0 +1,284 @@
1
+ 'use strict';
2
+
3
+ var pageController = require('@page-agent/page-controller');
4
+
5
+ // src/browser.ts
6
+
7
+ // src/browserUse.ts
8
+ var injectedPageController = null;
9
+ var PageControllerModule = null;
10
+ function setPageController(PC) {
11
+ injectedPageController = PC;
12
+ }
13
+ async function getPageController() {
14
+ if (injectedPageController) {
15
+ return injectedPageController;
16
+ }
17
+ if (!PageControllerModule) {
18
+ try {
19
+ PageControllerModule = await import('@page-agent/page-controller');
20
+ } catch (error) {
21
+ throw new Error(
22
+ 'PageController not available. Either import from "@usecrow/client/browser" or install @page-agent/page-controller as a dependency.'
23
+ );
24
+ }
25
+ }
26
+ return PageControllerModule.PageController;
27
+ }
28
+ var CrowBrowserUse = class {
29
+ constructor(config) {
30
+ this.pageController = null;
31
+ this.sessionId = null;
32
+ this.maxSteps = 20;
33
+ this.config = config;
34
+ }
35
+ /**
36
+ * Initialize PageController with non-blocking pointer
37
+ */
38
+ async initPageController() {
39
+ if (this.pageController) {
40
+ return this.pageController;
41
+ }
42
+ try {
43
+ const PageController2 = await getPageController();
44
+ this.pageController = new PageController2({
45
+ enableMask: true,
46
+ viewportExpansion: 500,
47
+ highlightLabelOpacity: 0,
48
+ // Hide numbered labels from users
49
+ highlightOpacity: 0
50
+ // Hide highlight boxes from users
51
+ });
52
+ await this.pageController.showMask();
53
+ const mask = this.pageController.mask;
54
+ if (mask?.wrapper) {
55
+ mask.wrapper.style.pointerEvents = "none";
56
+ }
57
+ console.log("[CrowBrowserUse] PageController initialized with non-blocking pointer");
58
+ return this.pageController;
59
+ } catch (error) {
60
+ console.error("[CrowBrowserUse] Failed to import @page-agent/page-controller:", error);
61
+ throw new Error(
62
+ "Failed to initialize browser automation. Make sure @page-agent/page-controller is installed."
63
+ );
64
+ }
65
+ }
66
+ /**
67
+ * Execute a browser automation task
68
+ */
69
+ async execute(task) {
70
+ console.log("[CrowBrowserUse] Starting task:", task);
71
+ try {
72
+ const controller = await this.initPageController();
73
+ const startResponse = await this.startSession(task);
74
+ this.sessionId = startResponse.session_id;
75
+ this.maxSteps = startResponse.max_steps;
76
+ console.log("[CrowBrowserUse] Session started:", this.sessionId);
77
+ let stepCount = 0;
78
+ let lastActionResult;
79
+ while (stepCount < this.maxSteps) {
80
+ stepCount++;
81
+ const browserState = await controller.getBrowserState();
82
+ const stepResponse = await this.processStep(browserState, lastActionResult);
83
+ if (stepResponse.done) {
84
+ console.log("[CrowBrowserUse] Task completed:", stepResponse.message);
85
+ await this.cleanup();
86
+ return {
87
+ status: stepResponse.success ? "success" : "error",
88
+ data: {
89
+ message: stepResponse.message,
90
+ steps: stepCount
91
+ },
92
+ error: stepResponse.success ? void 0 : stepResponse.message
93
+ };
94
+ }
95
+ if (stepResponse.error) {
96
+ console.error("[CrowBrowserUse] Error:", stepResponse.error);
97
+ await this.cleanup();
98
+ return {
99
+ status: "error",
100
+ error: stepResponse.error
101
+ };
102
+ }
103
+ if (stepResponse.action) {
104
+ lastActionResult = await this.executeAction(controller, stepResponse.action);
105
+ console.log(`[CrowBrowserUse] Step ${stepCount}:`, lastActionResult);
106
+ }
107
+ if (stepResponse.reflection) {
108
+ console.log("[CrowBrowserUse] Reflection:", stepResponse.reflection.next_goal);
109
+ }
110
+ }
111
+ await this.cleanup();
112
+ return {
113
+ status: "error",
114
+ error: `Task incomplete after ${this.maxSteps} steps`
115
+ };
116
+ } catch (error) {
117
+ console.error("[CrowBrowserUse] Error:", error);
118
+ await this.cleanup();
119
+ return {
120
+ status: "error",
121
+ error: error instanceof Error ? error.message : String(error)
122
+ };
123
+ }
124
+ }
125
+ /**
126
+ * Start a browser-use session on the server
127
+ */
128
+ async startSession(task) {
129
+ const response = await fetch(`${this.config.apiUrl}/api/browser-use/start`, {
130
+ method: "POST",
131
+ headers: { "Content-Type": "application/json" },
132
+ body: JSON.stringify({
133
+ product_id: this.config.productId,
134
+ task
135
+ })
136
+ });
137
+ if (!response.ok) {
138
+ const error = await response.json().catch(() => ({ detail: "Unknown error" }));
139
+ throw new Error(error.detail || `Failed to start session: ${response.status}`);
140
+ }
141
+ return response.json();
142
+ }
143
+ /**
144
+ * Process a step on the server
145
+ */
146
+ async processStep(browserState, actionResult) {
147
+ const response = await fetch(`${this.config.apiUrl}/api/browser-use/step`, {
148
+ method: "POST",
149
+ headers: { "Content-Type": "application/json" },
150
+ body: JSON.stringify({
151
+ session_id: this.sessionId,
152
+ product_id: this.config.productId,
153
+ browser_state: browserState,
154
+ action_result: actionResult
155
+ })
156
+ });
157
+ if (!response.ok) {
158
+ const error = await response.json().catch(() => ({ detail: "Unknown error" }));
159
+ throw new Error(error.detail || `Failed to process step: ${response.status}`);
160
+ }
161
+ return response.json();
162
+ }
163
+ /**
164
+ * Execute an action using PageController
165
+ */
166
+ async executeAction(controller, action) {
167
+ const actionName = Object.keys(action)[0];
168
+ const actionParams = action[actionName];
169
+ try {
170
+ switch (actionName) {
171
+ case "click_element_by_index": {
172
+ const result = await controller.clickElement(actionParams.index);
173
+ return result.message;
174
+ }
175
+ case "input_text": {
176
+ const result = await controller.inputText(
177
+ actionParams.index,
178
+ actionParams.text
179
+ );
180
+ return result.message;
181
+ }
182
+ case "select_dropdown_option": {
183
+ const result = await controller.selectOption(
184
+ actionParams.index,
185
+ actionParams.text
186
+ );
187
+ return result.message;
188
+ }
189
+ case "scroll": {
190
+ const result = await controller.scroll({
191
+ down: actionParams.down,
192
+ numPages: actionParams.num_pages,
193
+ pixels: actionParams.pixels,
194
+ index: actionParams.index
195
+ });
196
+ return result.message;
197
+ }
198
+ case "scroll_horizontally": {
199
+ const result = await controller.scrollHorizontally({
200
+ right: actionParams.right,
201
+ pixels: actionParams.pixels,
202
+ index: actionParams.index
203
+ });
204
+ return result.message;
205
+ }
206
+ case "wait": {
207
+ const seconds = actionParams.seconds || 1;
208
+ await new Promise((resolve) => setTimeout(resolve, seconds * 1e3));
209
+ return `Waited ${seconds} seconds`;
210
+ }
211
+ case "done": {
212
+ return "Task completed";
213
+ }
214
+ default:
215
+ return `Unknown action: ${actionName}`;
216
+ }
217
+ } catch (error) {
218
+ return `Action failed: ${error instanceof Error ? error.message : String(error)}`;
219
+ }
220
+ }
221
+ /**
222
+ * Cleanup resources
223
+ */
224
+ async cleanup() {
225
+ if (this.pageController) {
226
+ try {
227
+ await this.pageController.hideMask();
228
+ await this.pageController.cleanUpHighlights();
229
+ this.pageController.dispose();
230
+ } catch (error) {
231
+ console.warn("[CrowBrowserUse] Cleanup error:", error);
232
+ }
233
+ this.pageController = null;
234
+ }
235
+ if (this.sessionId) {
236
+ try {
237
+ await fetch(`${this.config.apiUrl}/api/browser-use/end`, {
238
+ method: "POST",
239
+ headers: { "Content-Type": "application/json" },
240
+ body: JSON.stringify({
241
+ session_id: this.sessionId,
242
+ product_id: this.config.productId
243
+ })
244
+ });
245
+ } catch (error) {
246
+ }
247
+ this.sessionId = null;
248
+ }
249
+ }
250
+ /**
251
+ * Stop the current task
252
+ */
253
+ async stop() {
254
+ await this.cleanup();
255
+ }
256
+ };
257
+
258
+ // src/browser.ts
259
+ setPageController(pageController.PageController);
260
+ function createBrowserUseTool(config) {
261
+ return async (args) => {
262
+ const instruction = args.instruction || args.instruction;
263
+ if (!instruction) {
264
+ return {
265
+ status: "error",
266
+ error: "Missing instruction parameter for browser_use tool"
267
+ };
268
+ }
269
+ const browserUse = new CrowBrowserUse({
270
+ productId: config.productId,
271
+ apiUrl: config.apiUrl
272
+ });
273
+ return browserUse.execute(instruction);
274
+ };
275
+ }
276
+
277
+ Object.defineProperty(exports, "PageController", {
278
+ enumerable: true,
279
+ get: function () { return pageController.PageController; }
280
+ });
281
+ exports.CrowBrowserUse = CrowBrowserUse;
282
+ exports.createBrowserUseTool = createBrowserUseTool;
283
+ //# sourceMappingURL=browser.cjs.map
284
+ //# sourceMappingURL=browser.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/browserUse.ts","../src/browser.ts"],"names":["PageController"],"mappings":"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","file":"browser.cjs","sourcesContent":["/**\n * CrowBrowserUse - Client-side browser automation orchestrator\n *\n * Handles DOM operations via PageController while server makes LLM decisions.\n * API keys stay secure on the server.\n *\n * Usage:\n * - For widget/bundled contexts: import from '@usecrow/client/browser' which\n * statically imports PageController and injects it automatically.\n * - For standalone SDK: install @page-agent/page-controller and use dynamic import fallback.\n */\n\nimport type { ToolResult } from './types';\n\n// PageController types - using 'any' to avoid coupling to the optional peer dependency\ntype PageControllerInstance = any;\ntype PageControllerClass = any;\n\n// Injected PageController class (set by browser.ts for bundled contexts)\nlet injectedPageController: PageControllerClass | null = null;\n\n// Cached dynamic import module\nlet PageControllerModule: { PageController: PageControllerClass } | null = null;\n\n/**\n * Inject PageController class for bundled contexts.\n * Called by @usecrow/client/browser which does the static import.\n */\nexport function setPageController(PC: PageControllerClass): void {\n injectedPageController = PC;\n}\n\n/**\n * Get PageController class - uses injected version if available,\n * otherwise falls back to dynamic import.\n */\nasync function getPageController(): Promise<PageControllerClass> {\n // Use injected PageController if available (from browser.ts)\n if (injectedPageController) {\n return injectedPageController;\n }\n\n // Fallback to dynamic import for standalone SDK usage\n if (!PageControllerModule) {\n try {\n PageControllerModule = await import('@page-agent/page-controller') as any;\n } catch (error) {\n throw new Error(\n 'PageController not available. Either import from \"@usecrow/client/browser\" ' +\n 'or install @page-agent/page-controller as a dependency.'\n );\n }\n }\n return PageControllerModule!.PageController;\n}\n\ninterface BrowserUseConfig {\n productId: string;\n apiUrl: string;\n}\n\ninterface BrowserUseStartResponse {\n session_id: string;\n max_steps: number;\n}\n\ninterface BrowserUseStepResponse {\n done: boolean;\n success?: boolean;\n message?: string;\n action?: Record<string, unknown>;\n step?: number;\n reflection?: {\n evaluation?: string;\n memory?: string;\n next_goal?: string;\n };\n error?: string;\n}\n\nexport class CrowBrowserUse {\n private config: BrowserUseConfig;\n private pageController: PageControllerInstance | null = null;\n private sessionId: string | null = null;\n private maxSteps: number = 20;\n\n constructor(config: BrowserUseConfig) {\n this.config = config;\n }\n\n /**\n * Initialize PageController with non-blocking pointer\n */\n private async initPageController(): Promise<PageControllerInstance> {\n if (this.pageController) {\n return this.pageController;\n }\n\n try {\n const PageController = await getPageController();\n\n this.pageController = new PageController({\n enableMask: true,\n viewportExpansion: 500,\n highlightLabelOpacity: 0, // Hide numbered labels from users\n highlightOpacity: 0, // Hide highlight boxes from users\n });\n\n // Show mask and make it non-blocking\n await this.pageController.showMask();\n\n // Make pointer visible but non-blocking (access internal mask property)\n const mask = (this.pageController as any).mask;\n if (mask?.wrapper) {\n mask.wrapper.style.pointerEvents = 'none';\n }\n\n console.log('[CrowBrowserUse] PageController initialized with non-blocking pointer');\n return this.pageController;\n } catch (error) {\n console.error('[CrowBrowserUse] Failed to import @page-agent/page-controller:', error);\n throw new Error(\n 'Failed to initialize browser automation. Make sure @page-agent/page-controller is installed.'\n );\n }\n }\n\n /**\n * Execute a browser automation task\n */\n async execute(task: string): Promise<ToolResult> {\n console.log('[CrowBrowserUse] Starting task:', task);\n\n try {\n // Initialize PageController\n const controller = await this.initPageController();\n\n // Start session on server\n const startResponse = await this.startSession(task);\n this.sessionId = startResponse.session_id;\n this.maxSteps = startResponse.max_steps;\n\n console.log('[CrowBrowserUse] Session started:', this.sessionId);\n\n // Run the automation loop\n let stepCount = 0;\n let lastActionResult: string | undefined;\n\n while (stepCount < this.maxSteps) {\n stepCount++;\n\n // Get browser state\n const browserState = await controller.getBrowserState();\n\n // Send to server for LLM decision\n const stepResponse = await this.processStep(browserState, lastActionResult);\n\n // Check if done\n if (stepResponse.done) {\n console.log('[CrowBrowserUse] Task completed:', stepResponse.message);\n await this.cleanup();\n\n return {\n status: stepResponse.success ? 'success' : 'error',\n data: {\n message: stepResponse.message,\n steps: stepCount,\n },\n error: stepResponse.success ? undefined : stepResponse.message,\n };\n }\n\n // Check for error\n if (stepResponse.error) {\n console.error('[CrowBrowserUse] Error:', stepResponse.error);\n await this.cleanup();\n\n return {\n status: 'error',\n error: stepResponse.error,\n };\n }\n\n // Execute the action\n if (stepResponse.action) {\n lastActionResult = await this.executeAction(controller, stepResponse.action);\n console.log(`[CrowBrowserUse] Step ${stepCount}:`, lastActionResult);\n }\n\n // Log reflection if available\n if (stepResponse.reflection) {\n console.log('[CrowBrowserUse] Reflection:', stepResponse.reflection.next_goal);\n }\n }\n\n // Reached max steps\n await this.cleanup();\n return {\n status: 'error',\n error: `Task incomplete after ${this.maxSteps} steps`,\n };\n } catch (error) {\n console.error('[CrowBrowserUse] Error:', error);\n await this.cleanup();\n\n return {\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Start a browser-use session on the server\n */\n private async startSession(task: string): Promise<BrowserUseStartResponse> {\n const response = await fetch(`${this.config.apiUrl}/api/browser-use/start`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n product_id: this.config.productId,\n task,\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ detail: 'Unknown error' }));\n throw new Error(error.detail || `Failed to start session: ${response.status}`);\n }\n\n return response.json();\n }\n\n /**\n * Process a step on the server\n */\n private async processStep(\n browserState: {\n url: string;\n title: string;\n content: string;\n header: string;\n footer: string;\n },\n actionResult?: string\n ): Promise<BrowserUseStepResponse> {\n const response = await fetch(`${this.config.apiUrl}/api/browser-use/step`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n session_id: this.sessionId,\n product_id: this.config.productId,\n browser_state: browserState,\n action_result: actionResult,\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ detail: 'Unknown error' }));\n throw new Error(error.detail || `Failed to process step: ${response.status}`);\n }\n\n return response.json();\n }\n\n /**\n * Execute an action using PageController\n */\n private async executeAction(\n controller: PageControllerInstance,\n action: Record<string, unknown>\n ): Promise<string> {\n const actionName = Object.keys(action)[0];\n const actionParams = action[actionName] as Record<string, unknown>;\n\n try {\n switch (actionName) {\n case 'click_element_by_index': {\n const result = await controller.clickElement(actionParams.index as number);\n return result.message;\n }\n\n case 'input_text': {\n const result = await controller.inputText(\n actionParams.index as number,\n actionParams.text as string\n );\n return result.message;\n }\n\n case 'select_dropdown_option': {\n const result = await controller.selectOption(\n actionParams.index as number,\n actionParams.text as string\n );\n return result.message;\n }\n\n case 'scroll': {\n const result = await controller.scroll({\n down: actionParams.down as boolean,\n numPages: actionParams.num_pages as number,\n pixels: actionParams.pixels as number | undefined,\n index: actionParams.index as number | undefined,\n });\n return result.message;\n }\n\n case 'scroll_horizontally': {\n const result = await controller.scrollHorizontally({\n right: actionParams.right as boolean,\n pixels: actionParams.pixels as number,\n index: actionParams.index as number | undefined,\n });\n return result.message;\n }\n\n case 'wait': {\n const seconds = (actionParams.seconds as number) || 1;\n await new Promise((resolve) => setTimeout(resolve, seconds * 1000));\n return `Waited ${seconds} seconds`;\n }\n\n case 'done': {\n // Done is handled at the step level, not here\n return 'Task completed';\n }\n\n default:\n return `Unknown action: ${actionName}`;\n }\n } catch (error) {\n return `Action failed: ${error instanceof Error ? error.message : String(error)}`;\n }\n }\n\n /**\n * Cleanup resources\n */\n private async cleanup(): Promise<void> {\n if (this.pageController) {\n try {\n await this.pageController.hideMask();\n await this.pageController.cleanUpHighlights();\n this.pageController.dispose();\n } catch (error) {\n console.warn('[CrowBrowserUse] Cleanup error:', error);\n }\n this.pageController = null;\n }\n\n // End session on server if still active\n if (this.sessionId) {\n try {\n await fetch(`${this.config.apiUrl}/api/browser-use/end`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n session_id: this.sessionId,\n product_id: this.config.productId,\n }),\n });\n } catch (error) {\n // Ignore - session may have already ended\n }\n this.sessionId = null;\n }\n }\n\n /**\n * Stop the current task\n */\n async stop(): Promise<void> {\n await this.cleanup();\n }\n}\n","/**\n * @usecrow/client/browser - Browser automation module with PageController\n *\n * This module statically imports @page-agent/page-controller, making it\n * suitable for bundled contexts (widget, webpack, vite) where the import\n * can be resolved at build time.\n *\n * Usage:\n * ```typescript\n * import { createBrowserUseTool, CrowBrowserUse } from '@usecrow/client/browser';\n *\n * // Option 1: Create a tool handler for registration\n * const browserUseTool = createBrowserUseTool({ productId, apiUrl });\n * client.registerTools({ browser_use: browserUseTool });\n *\n * // Option 2: Use CrowBrowserUse directly\n * const browserUse = new CrowBrowserUse({ productId, apiUrl });\n * await browserUse.execute('Click the login button');\n * ```\n */\n\n// Static import of PageController - resolved at build time by bundler\nimport { PageController } from '@page-agent/page-controller';\nimport { CrowBrowserUse, setPageController } from './browserUse';\nimport type { ToolResult } from './types';\n\n// Inject PageController immediately when this module is imported\nsetPageController(PageController);\n\n// Re-export CrowBrowserUse for direct usage\nexport { CrowBrowserUse };\n\n// Re-export PageController for advanced usage\nexport { PageController };\n\nexport interface BrowserUseToolConfig {\n productId: string;\n apiUrl: string;\n}\n\nexport interface BrowserUseToolArgs {\n instruction: string;\n}\n\n/**\n * Create a browser_use tool handler for registration with CrowClient or widget.\n *\n * @param config - Configuration with productId and apiUrl\n * @returns Async function that executes browser automation tasks\n *\n * @example\n * ```typescript\n * // Widget usage\n * window.__crow_client_tools.browser_use = createBrowserUseTool({ productId, apiUrl });\n *\n * // SDK usage\n * client.registerTools({\n * browser_use: createBrowserUseTool({ productId, apiUrl })\n * });\n * ```\n */\nexport function createBrowserUseTool(config: BrowserUseToolConfig) {\n return async (args: BrowserUseToolArgs | Record<string, unknown>): Promise<ToolResult> => {\n const instruction = (args as BrowserUseToolArgs).instruction || (args as Record<string, unknown>).instruction as string;\n\n if (!instruction) {\n return {\n status: 'error',\n error: 'Missing instruction parameter for browser_use tool',\n };\n }\n\n const browserUse = new CrowBrowserUse({\n productId: config.productId,\n apiUrl: config.apiUrl,\n });\n\n return browserUse.execute(instruction);\n };\n}\n"]}
@@ -0,0 +1,52 @@
1
+ export { PageController } from '@page-agent/page-controller';
2
+ import { e as ToolResult } from './browserUse-CZNpayEF.cjs';
3
+ export { g as CrowBrowserUse } from './browserUse-CZNpayEF.cjs';
4
+
5
+ /**
6
+ * @usecrow/client/browser - Browser automation module with PageController
7
+ *
8
+ * This module statically imports @page-agent/page-controller, making it
9
+ * suitable for bundled contexts (widget, webpack, vite) where the import
10
+ * can be resolved at build time.
11
+ *
12
+ * Usage:
13
+ * ```typescript
14
+ * import { createBrowserUseTool, CrowBrowserUse } from '@usecrow/client/browser';
15
+ *
16
+ * // Option 1: Create a tool handler for registration
17
+ * const browserUseTool = createBrowserUseTool({ productId, apiUrl });
18
+ * client.registerTools({ browser_use: browserUseTool });
19
+ *
20
+ * // Option 2: Use CrowBrowserUse directly
21
+ * const browserUse = new CrowBrowserUse({ productId, apiUrl });
22
+ * await browserUse.execute('Click the login button');
23
+ * ```
24
+ */
25
+
26
+ interface BrowserUseToolConfig {
27
+ productId: string;
28
+ apiUrl: string;
29
+ }
30
+ interface BrowserUseToolArgs {
31
+ instruction: string;
32
+ }
33
+ /**
34
+ * Create a browser_use tool handler for registration with CrowClient or widget.
35
+ *
36
+ * @param config - Configuration with productId and apiUrl
37
+ * @returns Async function that executes browser automation tasks
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Widget usage
42
+ * window.__crow_client_tools.browser_use = createBrowserUseTool({ productId, apiUrl });
43
+ *
44
+ * // SDK usage
45
+ * client.registerTools({
46
+ * browser_use: createBrowserUseTool({ productId, apiUrl })
47
+ * });
48
+ * ```
49
+ */
50
+ declare function createBrowserUseTool(config: BrowserUseToolConfig): (args: BrowserUseToolArgs | Record<string, unknown>) => Promise<ToolResult>;
51
+
52
+ export { type BrowserUseToolArgs, type BrowserUseToolConfig, createBrowserUseTool };
@@ -0,0 +1,52 @@
1
+ export { PageController } from '@page-agent/page-controller';
2
+ import { e as ToolResult } from './browserUse-CZNpayEF.js';
3
+ export { g as CrowBrowserUse } from './browserUse-CZNpayEF.js';
4
+
5
+ /**
6
+ * @usecrow/client/browser - Browser automation module with PageController
7
+ *
8
+ * This module statically imports @page-agent/page-controller, making it
9
+ * suitable for bundled contexts (widget, webpack, vite) where the import
10
+ * can be resolved at build time.
11
+ *
12
+ * Usage:
13
+ * ```typescript
14
+ * import { createBrowserUseTool, CrowBrowserUse } from '@usecrow/client/browser';
15
+ *
16
+ * // Option 1: Create a tool handler for registration
17
+ * const browserUseTool = createBrowserUseTool({ productId, apiUrl });
18
+ * client.registerTools({ browser_use: browserUseTool });
19
+ *
20
+ * // Option 2: Use CrowBrowserUse directly
21
+ * const browserUse = new CrowBrowserUse({ productId, apiUrl });
22
+ * await browserUse.execute('Click the login button');
23
+ * ```
24
+ */
25
+
26
+ interface BrowserUseToolConfig {
27
+ productId: string;
28
+ apiUrl: string;
29
+ }
30
+ interface BrowserUseToolArgs {
31
+ instruction: string;
32
+ }
33
+ /**
34
+ * Create a browser_use tool handler for registration with CrowClient or widget.
35
+ *
36
+ * @param config - Configuration with productId and apiUrl
37
+ * @returns Async function that executes browser automation tasks
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Widget usage
42
+ * window.__crow_client_tools.browser_use = createBrowserUseTool({ productId, apiUrl });
43
+ *
44
+ * // SDK usage
45
+ * client.registerTools({
46
+ * browser_use: createBrowserUseTool({ productId, apiUrl })
47
+ * });
48
+ * ```
49
+ */
50
+ declare function createBrowserUseTool(config: BrowserUseToolConfig): (args: BrowserUseToolArgs | Record<string, unknown>) => Promise<ToolResult>;
51
+
52
+ export { type BrowserUseToolArgs, type BrowserUseToolConfig, createBrowserUseTool };