@usecrow/client 0.1.37 → 0.1.39

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,365 @@
1
+ let m = null, f = null;
2
+ function P(g) {
3
+ m = g;
4
+ }
5
+ async function E() {
6
+ if (m)
7
+ return m;
8
+ if (!f)
9
+ try {
10
+ f = await import("./PageController-D3uwrwlG.js");
11
+ } catch {
12
+ throw new Error(
13
+ 'PageController not available. Either import from "@usecrow/client/browser" or use the bundled version.'
14
+ );
15
+ }
16
+ return f.PageController;
17
+ }
18
+ class $ {
19
+ constructor(e) {
20
+ this.pageController = null, this.sessionId = null, this.maxSteps = 20, this.aborted = !1, this.config = e;
21
+ }
22
+ /**
23
+ * Initialize PageController with non-blocking pointer
24
+ */
25
+ async initPageController() {
26
+ if (this.pageController)
27
+ return this.pageController;
28
+ try {
29
+ const e = await E();
30
+ this.pageController = new e({
31
+ enableMask: !0,
32
+ viewportExpansion: 500,
33
+ highlightLabelOpacity: 0,
34
+ // Hide numbered labels from users
35
+ highlightOpacity: 0
36
+ // Hide highlight boxes from users
37
+ }), await this.pageController.showMask();
38
+ const o = this.pageController.mask;
39
+ return o != null && o.wrapper && (o.wrapper.style.pointerEvents = "none"), console.log("[CrowBrowserUse] PageController initialized with non-blocking pointer"), this.pageController;
40
+ } catch (e) {
41
+ throw console.error("[CrowBrowserUse] Failed to initialize PageController:", e), new Error(
42
+ "Failed to initialize browser automation. Please import from @usecrow/client/browser."
43
+ );
44
+ }
45
+ }
46
+ /**
47
+ * Execute a browser automation task
48
+ */
49
+ async execute(e) {
50
+ var o, s, t, r, n, h, p, l, x, y, C, _, S, U;
51
+ if (console.log("[CrowBrowserUse] Starting task:", e), this.config.onConfirmation && !await this.config.onConfirmation(e))
52
+ return console.log("[CrowBrowserUse] User declined browser automation"), (s = (o = this.config).onProgress) == null || s.call(o, -1, this.maxSteps), {
53
+ status: "error",
54
+ error: "User declined browser automation",
55
+ data: { declined: !0 }
56
+ };
57
+ try {
58
+ const a = await this.initPageController(), b = await this.startSession(e);
59
+ this.sessionId = b.session_id, this.maxSteps = b.max_steps, console.log("[CrowBrowserUse] Session started:", this.sessionId);
60
+ let u = 0, c;
61
+ for (; u < this.maxSteps; ) {
62
+ if (this.aborted)
63
+ return console.log("[CrowBrowserUse] Task cancelled by user"), await this.cleanup(), (r = (t = this.config).onProgress) == null || r.call(t, -1, this.maxSteps), {
64
+ status: "error",
65
+ error: "Task cancelled by user"
66
+ };
67
+ u++;
68
+ const v = await a.getBrowserState(), d = a.mask;
69
+ d != null && d.wrapper && (d.wrapper.style.pointerEvents = "none");
70
+ const i = await this.processStep(v, c);
71
+ if (i.needs_user_input && i.question) {
72
+ if (console.log("[CrowBrowserUse] Asking user:", i.question), !this.config.onQuestion) {
73
+ c = "User input not available - no callback provided", console.warn("[CrowBrowserUse] No onQuestion callback provided");
74
+ continue;
75
+ }
76
+ try {
77
+ const w = await this.config.onQuestion(i.question);
78
+ c = `User answered: ${w}`, console.log("[CrowBrowserUse] User answered:", w);
79
+ } catch (w) {
80
+ if (c = "User cancelled or failed to respond", console.log("[CrowBrowserUse] User cancelled or error:", w), this.aborted)
81
+ return console.log("[CrowBrowserUse] Aborted after user cancelled"), await this.cleanup(), (h = (n = this.config).onProgress) == null || h.call(n, -1, this.maxSteps), {
82
+ status: "error",
83
+ error: "Task cancelled by user"
84
+ };
85
+ }
86
+ continue;
87
+ }
88
+ if (i.done)
89
+ return console.log("[CrowBrowserUse] Task completed:", i.message), await this.cleanup(), (l = (p = this.config).onProgress) == null || l.call(p, u, this.maxSteps), {
90
+ status: i.success ? "success" : "error",
91
+ data: {
92
+ message: i.message,
93
+ steps: u
94
+ },
95
+ error: i.success ? void 0 : i.message
96
+ };
97
+ if (i.error)
98
+ return console.error("[CrowBrowserUse] Error:", i.error), await this.cleanup(), (y = (x = this.config).onProgress) == null || y.call(x, -1, this.maxSteps), {
99
+ status: "error",
100
+ error: i.error
101
+ };
102
+ i.action && (c = await this.executeAction(a, i.action), c.startsWith("Action failed:") ? console.error(`[CrowBrowserUse] Step ${u} FAILED:`, c) : console.log(`[CrowBrowserUse] Step ${u}:`, c)), i.reflection && console.log("[CrowBrowserUse] Reflection:", i.reflection.next_goal);
103
+ }
104
+ return await this.cleanup(), (_ = (C = this.config).onProgress) == null || _.call(C, -1, this.maxSteps), {
105
+ status: "error",
106
+ error: `Task incomplete after ${this.maxSteps} steps`
107
+ };
108
+ } catch (a) {
109
+ return console.error("[CrowBrowserUse] Error:", a), await this.cleanup(), (U = (S = this.config).onProgress) == null || U.call(S, -1, this.maxSteps), {
110
+ status: "error",
111
+ error: a instanceof Error ? a.message : String(a)
112
+ };
113
+ }
114
+ }
115
+ /**
116
+ * Start a browser-use session on the server
117
+ */
118
+ async startSession(e) {
119
+ const o = await fetch(`${this.config.apiUrl}/api/browser-use/start`, {
120
+ method: "POST",
121
+ headers: { "Content-Type": "application/json" },
122
+ body: JSON.stringify({
123
+ product_id: this.config.productId,
124
+ task: e
125
+ })
126
+ });
127
+ if (!o.ok) {
128
+ const s = await o.json().catch(() => ({ detail: "Unknown error" }));
129
+ throw new Error(s.detail || `Failed to start session: ${o.status}`);
130
+ }
131
+ return o.json();
132
+ }
133
+ /**
134
+ * Process a step on the server
135
+ */
136
+ async processStep(e, o) {
137
+ const s = await fetch(`${this.config.apiUrl}/api/browser-use/step`, {
138
+ method: "POST",
139
+ headers: { "Content-Type": "application/json" },
140
+ body: JSON.stringify({
141
+ session_id: this.sessionId,
142
+ product_id: this.config.productId,
143
+ browser_state: e,
144
+ action_result: o
145
+ })
146
+ });
147
+ if (!s.ok) {
148
+ const t = await s.json().catch(() => ({ detail: "Unknown error" }));
149
+ throw new Error(t.detail || `Failed to process step: ${s.status}`);
150
+ }
151
+ return s.json();
152
+ }
153
+ /**
154
+ * Execute an action using PageController
155
+ */
156
+ async executeAction(e, o) {
157
+ const s = Object.keys(o)[0], t = o[s];
158
+ try {
159
+ switch (s) {
160
+ case "click_element_by_index":
161
+ return (await e.clickElement(t.index)).message;
162
+ case "input_text":
163
+ return (await e.inputText(
164
+ t.index,
165
+ t.text
166
+ )).message;
167
+ case "select_dropdown_option":
168
+ return (await e.selectOption(
169
+ t.index,
170
+ t.text
171
+ )).message;
172
+ case "scroll":
173
+ return (await e.scroll({
174
+ down: t.down,
175
+ numPages: t.num_pages,
176
+ pixels: t.pixels,
177
+ index: t.index
178
+ })).message;
179
+ case "scroll_horizontally":
180
+ return (await e.scrollHorizontally({
181
+ right: t.right,
182
+ pixels: t.pixels,
183
+ index: t.index
184
+ })).message;
185
+ case "wait": {
186
+ const r = t.seconds || 1;
187
+ return await new Promise((n) => setTimeout(n, r * 1e3)), `Waited ${r} seconds`;
188
+ }
189
+ case "done":
190
+ return "Task completed";
191
+ default:
192
+ return `Unknown action: ${s}`;
193
+ }
194
+ } catch (r) {
195
+ return `Action failed: ${r instanceof Error ? r.message : String(r)}`;
196
+ }
197
+ }
198
+ /**
199
+ * Cleanup resources
200
+ */
201
+ async cleanup() {
202
+ if (this.pageController) {
203
+ try {
204
+ await this.pageController.hideMask(), await this.pageController.cleanUpHighlights(), this.pageController.dispose();
205
+ } catch (e) {
206
+ console.warn("[CrowBrowserUse] Cleanup error:", e);
207
+ }
208
+ this.pageController = null;
209
+ }
210
+ if (this.sessionId) {
211
+ try {
212
+ await fetch(`${this.config.apiUrl}/api/browser-use/end`, {
213
+ method: "POST",
214
+ headers: { "Content-Type": "application/json" },
215
+ body: JSON.stringify({
216
+ session_id: this.sessionId,
217
+ product_id: this.config.productId
218
+ })
219
+ });
220
+ } catch {
221
+ }
222
+ this.sessionId = null;
223
+ }
224
+ }
225
+ /**
226
+ * Stop the current task
227
+ */
228
+ async stop() {
229
+ this.aborted = !0, await this.cleanup();
230
+ }
231
+ }
232
+ class T {
233
+ constructor(e, o = {}) {
234
+ this.controller = e, this.config = {
235
+ waitTimeout: o.waitTimeout ?? 3e3,
236
+ pollInterval: o.pollInterval ?? 300,
237
+ stepDelay: o.stepDelay ?? 500,
238
+ stopOnFailure: o.stopOnFailure ?? !1,
239
+ onStepProgress: o.onStepProgress ?? (() => {
240
+ })
241
+ };
242
+ }
243
+ /**
244
+ * Execute a recorded workflow with variable substitution.
245
+ */
246
+ async execute(e, o = {}) {
247
+ const s = [];
248
+ let t = 0;
249
+ console.log(`[WorkflowExecutor] Starting workflow: ${e.name} (${e.steps.length} steps)`);
250
+ for (let n = 0; n < e.steps.length; n++) {
251
+ const h = e.steps[n], p = this.resolveVariables(h, o);
252
+ console.log(`[WorkflowExecutor] Step ${n + 1}/${e.steps.length}: ${p.description}`);
253
+ const l = await this.executeStep(p, n);
254
+ if (s.push(l), this.config.onStepProgress(l), !l.success && (t++, console.warn(`[WorkflowExecutor] Step ${n + 1} failed: ${l.message}`), this.config.stopOnFailure))
255
+ return {
256
+ success: !1,
257
+ workflow_name: e.name,
258
+ total_steps: e.steps.length,
259
+ completed_steps: n + 1,
260
+ failed_steps: t,
261
+ step_results: s,
262
+ error: `Stopped at step ${n + 1}: ${l.message}`
263
+ };
264
+ n < e.steps.length - 1 && await this.delay(this.config.stepDelay);
265
+ }
266
+ const r = t === 0;
267
+ return console.log(
268
+ `[WorkflowExecutor] Workflow "${e.name}" ${r ? "completed successfully" : `completed with ${t} failures`}`
269
+ ), {
270
+ success: r,
271
+ workflow_name: e.name,
272
+ total_steps: e.steps.length,
273
+ completed_steps: e.steps.length,
274
+ failed_steps: t,
275
+ step_results: s
276
+ };
277
+ }
278
+ /**
279
+ * Execute a single step.
280
+ */
281
+ async executeStep(e, o) {
282
+ const s = {
283
+ step_index: o,
284
+ step_type: e.type,
285
+ description: e.description,
286
+ success: !1,
287
+ message: ""
288
+ };
289
+ try {
290
+ if (e.type === "navigation") {
291
+ if (!e.url)
292
+ return { ...s, message: "Navigation step has no URL" };
293
+ const r = await this.controller.navigateToUrl(e.url);
294
+ return await this.delay(1e3), { ...s, success: r.success, message: r.message };
295
+ }
296
+ await this.controller.updateTree();
297
+ let t = this.controller.findElementByStrategies(e.selector_strategies);
298
+ if (t === null && e.selector_strategies.length > 0 && (console.log(`[WorkflowExecutor] Element not found, waiting up to ${this.config.waitTimeout}ms...`), t = await this.controller.waitForElement(
299
+ e.selector_strategies,
300
+ this.config.waitTimeout,
301
+ this.config.pollInterval
302
+ )), t === null && e.target_text && (await this.controller.updateTree(), t = this.controller.findElementByText(e.target_text, !0), t === null && (t = this.controller.findElementByText(e.target_text, !1))), t === null)
303
+ return {
304
+ ...s,
305
+ message: `Element not found for step: ${e.description} (target_text: "${e.target_text}")`
306
+ };
307
+ switch (s.element_index = t, e.type) {
308
+ case "click": {
309
+ const r = await this.controller.clickElement(t);
310
+ return { ...s, success: r.success, message: r.message };
311
+ }
312
+ case "input": {
313
+ if (e.value === void 0 || e.value === null)
314
+ return { ...s, message: "Input step has no value" };
315
+ const r = await this.controller.inputText(t, e.value);
316
+ return { ...s, success: r.success, message: r.message };
317
+ }
318
+ case "select": {
319
+ if (!e.value)
320
+ return { ...s, message: "Select step has no value" };
321
+ const r = await this.controller.selectOption(t, e.value);
322
+ return { ...s, success: r.success, message: r.message };
323
+ }
324
+ case "keypress": {
325
+ if (!e.value)
326
+ return { ...s, message: "Keypress step has no key" };
327
+ const r = await this.controller.pressKey(e.value, t);
328
+ return { ...s, success: r.success, message: r.message };
329
+ }
330
+ default:
331
+ return { ...s, message: `Unknown step type: ${e.type}` };
332
+ }
333
+ } catch (t) {
334
+ return {
335
+ ...s,
336
+ message: `Error executing step: ${t instanceof Error ? t.message : String(t)}`
337
+ };
338
+ }
339
+ }
340
+ /**
341
+ * Replace {variable_name} placeholders in step fields with actual values.
342
+ */
343
+ resolveVariables(e, o) {
344
+ const s = (t) => !t || !t.includes("{") ? t : t.replace(/\{(\w+)\}/g, (r, n) => n in o ? String(o[n]) : r);
345
+ return {
346
+ ...e,
347
+ description: s(e.description) || e.description,
348
+ target_text: s(e.target_text) || e.target_text,
349
+ value: s(e.value),
350
+ url: s(e.url),
351
+ selector_strategies: e.selector_strategies.map((t) => ({
352
+ ...t,
353
+ value: s(t.value) || t.value
354
+ }))
355
+ };
356
+ }
357
+ delay(e) {
358
+ return new Promise((o) => setTimeout(o, e));
359
+ }
360
+ }
361
+ export {
362
+ $ as C,
363
+ T as W,
364
+ P as s
365
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usecrow/client",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
4
4
  "description": "Headless client for Crow AI agents - streaming, auth, tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1,235 +0,0 @@
1
- let d = null, h = null;
2
- function B(w) {
3
- d = w;
4
- }
5
- async function _() {
6
- if (d)
7
- return d;
8
- if (!h)
9
- try {
10
- h = await import("./PageController-D3uwrwlG.js");
11
- } catch {
12
- throw new Error(
13
- 'PageController not available. Either import from "@usecrow/client/browser" or use the bundled version.'
14
- );
15
- }
16
- return h.PageController;
17
- }
18
- class T {
19
- constructor(e) {
20
- this.pageController = null, this.sessionId = null, this.maxSteps = 20, this.aborted = !1, this.config = e;
21
- }
22
- /**
23
- * Initialize PageController with non-blocking pointer
24
- */
25
- async initPageController() {
26
- if (this.pageController)
27
- return this.pageController;
28
- try {
29
- const e = await _();
30
- this.pageController = new e({
31
- enableMask: !0,
32
- viewportExpansion: 500,
33
- highlightLabelOpacity: 0,
34
- // Hide numbered labels from users
35
- highlightOpacity: 0
36
- // Hide highlight boxes from users
37
- }), await this.pageController.showMask();
38
- const s = this.pageController.mask;
39
- return s != null && s.wrapper && (s.wrapper.style.pointerEvents = "none"), console.log("[CrowBrowserUse] PageController initialized with non-blocking pointer"), this.pageController;
40
- } catch (e) {
41
- throw console.error("[CrowBrowserUse] Failed to initialize PageController:", e), new Error(
42
- "Failed to initialize browser automation. Please import from @usecrow/client/browser."
43
- );
44
- }
45
- }
46
- /**
47
- * Execute a browser automation task
48
- */
49
- async execute(e) {
50
- var s, n, r, o, c, g, f, m, C, y, x, U, b, S;
51
- if (console.log("[CrowBrowserUse] Starting task:", e), this.config.onConfirmation && !await this.config.onConfirmation(e))
52
- return console.log("[CrowBrowserUse] User declined browser automation"), (n = (s = this.config).onProgress) == null || n.call(s, -1, this.maxSteps), {
53
- status: "error",
54
- error: "User declined browser automation",
55
- data: { declined: !0 }
56
- };
57
- try {
58
- const i = await this.initPageController(), P = await this.startSession(e);
59
- this.sessionId = P.session_id, this.maxSteps = P.max_steps, console.log("[CrowBrowserUse] Session started:", this.sessionId);
60
- let l = 0, a;
61
- for (; l < this.maxSteps; ) {
62
- if (this.aborted)
63
- return console.log("[CrowBrowserUse] Task cancelled by user"), await this.cleanup(), (o = (r = this.config).onProgress) == null || o.call(r, -1, this.maxSteps), {
64
- status: "error",
65
- error: "Task cancelled by user"
66
- };
67
- l++;
68
- const k = await i.getBrowserState(), u = i.mask;
69
- u != null && u.wrapper && (u.wrapper.style.pointerEvents = "none");
70
- const t = await this.processStep(k, a);
71
- if (t.needs_user_input && t.question) {
72
- if (console.log("[CrowBrowserUse] Asking user:", t.question), !this.config.onQuestion) {
73
- a = "User input not available - no callback provided", console.warn("[CrowBrowserUse] No onQuestion callback provided");
74
- continue;
75
- }
76
- try {
77
- const p = await this.config.onQuestion(t.question);
78
- a = `User answered: ${p}`, console.log("[CrowBrowserUse] User answered:", p);
79
- } catch (p) {
80
- if (a = "User cancelled or failed to respond", console.log("[CrowBrowserUse] User cancelled or error:", p), this.aborted)
81
- return console.log("[CrowBrowserUse] Aborted after user cancelled"), await this.cleanup(), (g = (c = this.config).onProgress) == null || g.call(c, -1, this.maxSteps), {
82
- status: "error",
83
- error: "Task cancelled by user"
84
- };
85
- }
86
- continue;
87
- }
88
- if (t.done)
89
- return console.log("[CrowBrowserUse] Task completed:", t.message), await this.cleanup(), (m = (f = this.config).onProgress) == null || m.call(f, l, this.maxSteps), {
90
- status: t.success ? "success" : "error",
91
- data: {
92
- message: t.message,
93
- steps: l
94
- },
95
- error: t.success ? void 0 : t.message
96
- };
97
- if (t.error)
98
- return console.error("[CrowBrowserUse] Error:", t.error), await this.cleanup(), (y = (C = this.config).onProgress) == null || y.call(C, -1, this.maxSteps), {
99
- status: "error",
100
- error: t.error
101
- };
102
- t.action && (a = await this.executeAction(i, t.action), console.log(`[CrowBrowserUse] Step ${l}:`, a)), t.reflection && console.log("[CrowBrowserUse] Reflection:", t.reflection.next_goal);
103
- }
104
- return await this.cleanup(), (U = (x = this.config).onProgress) == null || U.call(x, -1, this.maxSteps), {
105
- status: "error",
106
- error: `Task incomplete after ${this.maxSteps} steps`
107
- };
108
- } catch (i) {
109
- return console.error("[CrowBrowserUse] Error:", i), await this.cleanup(), (S = (b = this.config).onProgress) == null || S.call(b, -1, this.maxSteps), {
110
- status: "error",
111
- error: i instanceof Error ? i.message : String(i)
112
- };
113
- }
114
- }
115
- /**
116
- * Start a browser-use session on the server
117
- */
118
- async startSession(e) {
119
- const s = await fetch(`${this.config.apiUrl}/api/browser-use/start`, {
120
- method: "POST",
121
- headers: { "Content-Type": "application/json" },
122
- body: JSON.stringify({
123
- product_id: this.config.productId,
124
- task: e
125
- })
126
- });
127
- if (!s.ok) {
128
- const n = await s.json().catch(() => ({ detail: "Unknown error" }));
129
- throw new Error(n.detail || `Failed to start session: ${s.status}`);
130
- }
131
- return s.json();
132
- }
133
- /**
134
- * Process a step on the server
135
- */
136
- async processStep(e, s) {
137
- const n = await fetch(`${this.config.apiUrl}/api/browser-use/step`, {
138
- method: "POST",
139
- headers: { "Content-Type": "application/json" },
140
- body: JSON.stringify({
141
- session_id: this.sessionId,
142
- product_id: this.config.productId,
143
- browser_state: e,
144
- action_result: s
145
- })
146
- });
147
- if (!n.ok) {
148
- const r = await n.json().catch(() => ({ detail: "Unknown error" }));
149
- throw new Error(r.detail || `Failed to process step: ${n.status}`);
150
- }
151
- return n.json();
152
- }
153
- /**
154
- * Execute an action using PageController
155
- */
156
- async executeAction(e, s) {
157
- const n = Object.keys(s)[0], r = s[n];
158
- try {
159
- switch (n) {
160
- case "click_element_by_index":
161
- return (await e.clickElement(r.index)).message;
162
- case "input_text":
163
- return (await e.inputText(
164
- r.index,
165
- r.text
166
- )).message;
167
- case "select_dropdown_option":
168
- return (await e.selectOption(
169
- r.index,
170
- r.text
171
- )).message;
172
- case "scroll":
173
- return (await e.scroll({
174
- down: r.down,
175
- numPages: r.num_pages,
176
- pixels: r.pixels,
177
- index: r.index
178
- })).message;
179
- case "scroll_horizontally":
180
- return (await e.scrollHorizontally({
181
- right: r.right,
182
- pixels: r.pixels,
183
- index: r.index
184
- })).message;
185
- case "wait": {
186
- const o = r.seconds || 1;
187
- return await new Promise((c) => setTimeout(c, o * 1e3)), `Waited ${o} seconds`;
188
- }
189
- case "done":
190
- return "Task completed";
191
- default:
192
- return `Unknown action: ${n}`;
193
- }
194
- } catch (o) {
195
- return `Action failed: ${o instanceof Error ? o.message : String(o)}`;
196
- }
197
- }
198
- /**
199
- * Cleanup resources
200
- */
201
- async cleanup() {
202
- if (this.pageController) {
203
- try {
204
- await this.pageController.hideMask(), await this.pageController.cleanUpHighlights(), this.pageController.dispose();
205
- } catch (e) {
206
- console.warn("[CrowBrowserUse] Cleanup error:", e);
207
- }
208
- this.pageController = null;
209
- }
210
- if (this.sessionId) {
211
- try {
212
- await fetch(`${this.config.apiUrl}/api/browser-use/end`, {
213
- method: "POST",
214
- headers: { "Content-Type": "application/json" },
215
- body: JSON.stringify({
216
- session_id: this.sessionId,
217
- product_id: this.config.productId
218
- })
219
- });
220
- } catch {
221
- }
222
- this.sessionId = null;
223
- }
224
- }
225
- /**
226
- * Stop the current task
227
- */
228
- async stop() {
229
- this.aborted = !0, await this.cleanup();
230
- }
231
- }
232
- export {
233
- T as C,
234
- B as s
235
- };
@@ -1 +0,0 @@
1
- "use strict";let d=null,h=null;function B(p){d=p}async function _(){if(d)return d;if(!h)try{h=await Promise.resolve().then(()=>require("./PageController-Cu6KUkcn.cjs"))}catch{throw new Error('PageController not available. Either import from "@usecrow/client/browser" or use the bundled version.')}return h.PageController}class T{constructor(e){this.pageController=null,this.sessionId=null,this.maxSteps=20,this.aborted=!1,this.config=e}async initPageController(){if(this.pageController)return this.pageController;try{const e=await _();this.pageController=new e({enableMask:!0,viewportExpansion:500,highlightLabelOpacity:0,highlightOpacity:0}),await this.pageController.showMask();const s=this.pageController.mask;return s!=null&&s.wrapper&&(s.wrapper.style.pointerEvents="none"),console.log("[CrowBrowserUse] PageController initialized with non-blocking pointer"),this.pageController}catch(e){throw console.error("[CrowBrowserUse] Failed to initialize PageController:",e),new Error("Failed to initialize browser automation. Please import from @usecrow/client/browser.")}}async execute(e){var s,n,r,o,c,g,f,C,m,y,x,U,b,S;if(console.log("[CrowBrowserUse] Starting task:",e),this.config.onConfirmation&&!await this.config.onConfirmation(e))return console.log("[CrowBrowserUse] User declined browser automation"),(n=(s=this.config).onProgress)==null||n.call(s,-1,this.maxSteps),{status:"error",error:"User declined browser automation",data:{declined:!0}};try{const i=await this.initPageController(),P=await this.startSession(e);this.sessionId=P.session_id,this.maxSteps=P.max_steps,console.log("[CrowBrowserUse] Session started:",this.sessionId);let l=0,a;for(;l<this.maxSteps;){if(this.aborted)return console.log("[CrowBrowserUse] Task cancelled by user"),await this.cleanup(),(o=(r=this.config).onProgress)==null||o.call(r,-1,this.maxSteps),{status:"error",error:"Task cancelled by user"};l++;const k=await i.getBrowserState(),u=i.mask;u!=null&&u.wrapper&&(u.wrapper.style.pointerEvents="none");const t=await this.processStep(k,a);if(t.needs_user_input&&t.question){if(console.log("[CrowBrowserUse] Asking user:",t.question),!this.config.onQuestion){a="User input not available - no callback provided",console.warn("[CrowBrowserUse] No onQuestion callback provided");continue}try{const w=await this.config.onQuestion(t.question);a=`User answered: ${w}`,console.log("[CrowBrowserUse] User answered:",w)}catch(w){if(a="User cancelled or failed to respond",console.log("[CrowBrowserUse] User cancelled or error:",w),this.aborted)return console.log("[CrowBrowserUse] Aborted after user cancelled"),await this.cleanup(),(g=(c=this.config).onProgress)==null||g.call(c,-1,this.maxSteps),{status:"error",error:"Task cancelled by user"}}continue}if(t.done)return console.log("[CrowBrowserUse] Task completed:",t.message),await this.cleanup(),(C=(f=this.config).onProgress)==null||C.call(f,l,this.maxSteps),{status:t.success?"success":"error",data:{message:t.message,steps:l},error:t.success?void 0:t.message};if(t.error)return console.error("[CrowBrowserUse] Error:",t.error),await this.cleanup(),(y=(m=this.config).onProgress)==null||y.call(m,-1,this.maxSteps),{status:"error",error:t.error};t.action&&(a=await this.executeAction(i,t.action),console.log(`[CrowBrowserUse] Step ${l}:`,a)),t.reflection&&console.log("[CrowBrowserUse] Reflection:",t.reflection.next_goal)}return await this.cleanup(),(U=(x=this.config).onProgress)==null||U.call(x,-1,this.maxSteps),{status:"error",error:`Task incomplete after ${this.maxSteps} steps`}}catch(i){return console.error("[CrowBrowserUse] Error:",i),await this.cleanup(),(S=(b=this.config).onProgress)==null||S.call(b,-1,this.maxSteps),{status:"error",error:i instanceof Error?i.message:String(i)}}}async startSession(e){const s=await fetch(`${this.config.apiUrl}/api/browser-use/start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({product_id:this.config.productId,task:e})});if(!s.ok){const n=await s.json().catch(()=>({detail:"Unknown error"}));throw new Error(n.detail||`Failed to start session: ${s.status}`)}return s.json()}async processStep(e,s){const n=await fetch(`${this.config.apiUrl}/api/browser-use/step`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:this.sessionId,product_id:this.config.productId,browser_state:e,action_result:s})});if(!n.ok){const r=await n.json().catch(()=>({detail:"Unknown error"}));throw new Error(r.detail||`Failed to process step: ${n.status}`)}return n.json()}async executeAction(e,s){const n=Object.keys(s)[0],r=s[n];try{switch(n){case"click_element_by_index":return(await e.clickElement(r.index)).message;case"input_text":return(await e.inputText(r.index,r.text)).message;case"select_dropdown_option":return(await e.selectOption(r.index,r.text)).message;case"scroll":return(await e.scroll({down:r.down,numPages:r.num_pages,pixels:r.pixels,index:r.index})).message;case"scroll_horizontally":return(await e.scrollHorizontally({right:r.right,pixels:r.pixels,index:r.index})).message;case"wait":{const o=r.seconds||1;return await new Promise(c=>setTimeout(c,o*1e3)),`Waited ${o} seconds`}case"done":return"Task completed";default:return`Unknown action: ${n}`}}catch(o){return`Action failed: ${o instanceof Error?o.message:String(o)}`}}async cleanup(){if(this.pageController){try{await this.pageController.hideMask(),await this.pageController.cleanUpHighlights(),this.pageController.dispose()}catch(e){console.warn("[CrowBrowserUse] Cleanup error:",e)}this.pageController=null}if(this.sessionId){try{await fetch(`${this.config.apiUrl}/api/browser-use/end`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:this.sessionId,product_id:this.config.productId})})}catch{}this.sessionId=null}}async stop(){this.aborted=!0,await this.cleanup()}}exports.CrowBrowserUse=T;exports.setPageController=B;