@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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as D } from "./browserUse-Cioetz2-.js";
1
+ import { C as R, W as D } from "./workflowExecutor-ijFlX3nx.js";
2
2
  class _ {
3
3
  constructor() {
4
4
  this.state = {
@@ -71,7 +71,7 @@ class _ {
71
71
  t(e);
72
72
  }
73
73
  }
74
- class v {
74
+ class k {
75
75
  constructor() {
76
76
  this.handlers = {};
77
77
  }
@@ -115,15 +115,15 @@ class v {
115
115
  const r = await s(t);
116
116
  return console.log(`[Crow] Tool ${e} completed:`, r), r;
117
117
  } catch (r) {
118
- const o = r instanceof Error ? r.message : String(r);
118
+ const n = r instanceof Error ? r.message : String(r);
119
119
  return console.error(`[Crow] Tool ${e} failed:`, r), {
120
120
  status: "error",
121
- error: o
121
+ error: n
122
122
  };
123
123
  }
124
124
  }
125
125
  }
126
- const k = "crow_conv_";
126
+ const v = "crow_conv_";
127
127
  class C {
128
128
  constructor(e, t) {
129
129
  this.currentId = null, this.productId = e, this.apiUrl = t, this.currentId = this.loadFromStorage();
@@ -132,7 +132,7 @@ class C {
132
132
  * Get localStorage key for this product
133
133
  */
134
134
  getStorageKey() {
135
- return `${k}${this.productId}`;
135
+ return `${v}${this.productId}`;
136
136
  }
137
137
  /**
138
138
  * Load conversation ID from localStorage
@@ -269,11 +269,11 @@ class C {
269
269
  return e;
270
270
  }
271
271
  }
272
- function S(a) {
273
- if (a === "[DONE]")
272
+ function b(o) {
273
+ if (o === "[DONE]")
274
274
  return { type: "done" };
275
275
  try {
276
- const e = JSON.parse(a);
276
+ const e = JSON.parse(o);
277
277
  switch (e.type) {
278
278
  case "verification_status":
279
279
  return {
@@ -350,18 +350,18 @@ function S(a) {
350
350
  return null;
351
351
  }
352
352
  } catch {
353
- return console.error("[Crow] Failed to parse SSE data:", a), null;
353
+ return console.error("[Crow] Failed to parse SSE data:", o), null;
354
354
  }
355
355
  }
356
- function* b(a) {
357
- const e = a.split(`
356
+ function* I(o) {
357
+ const e = o.split(`
358
358
  `);
359
359
  for (const t of e)
360
360
  t.startsWith("data: ") && (yield t.slice(6).trim());
361
361
  }
362
- async function* T(a, e) {
363
- var o;
364
- const t = (o = a.body) == null ? void 0 : o.getReader();
362
+ async function* M(o, e) {
363
+ var n;
364
+ const t = (n = o.body) == null ? void 0 : n.getReader();
365
365
  if (!t)
366
366
  throw new Error("Response body is not readable");
367
367
  const s = new TextDecoder();
@@ -372,12 +372,12 @@ async function* T(a, e) {
372
372
  t.cancel();
373
373
  return;
374
374
  }
375
- const { done: n, value: u } = await t.read();
376
- if (n) break;
377
- const d = s.decode(u);
378
- for (const l of b(d)) {
379
- const h = S(l);
380
- if (h && (h.type === "content" ? (r += h.text, yield { ...h, accumulated: r }) : yield h, h.type === "done"))
375
+ const { done: i, value: d } = await t.read();
376
+ if (i) break;
377
+ const h = s.decode(d);
378
+ for (const u of I(h)) {
379
+ const l = b(u);
380
+ if (l && (l.type === "content" ? (r += l.text, yield { ...l, accumulated: r }) : yield l, l.type === "done"))
381
381
  return;
382
382
  }
383
383
  }
@@ -385,20 +385,20 @@ async function* T(a, e) {
385
385
  t.releaseLock();
386
386
  }
387
387
  }
388
- async function $() {
388
+ async function S() {
389
389
  try {
390
390
  return window.location.reload(), { status: "success", data: { refreshed: !0 } };
391
- } catch (a) {
391
+ } catch (o) {
392
392
  return {
393
393
  status: "error",
394
- error: a instanceof Error ? a.message : "Failed to refresh page"
394
+ error: o instanceof Error ? o.message : "Failed to refresh page"
395
395
  };
396
396
  }
397
397
  }
398
- async function x() {
399
- var a;
398
+ async function T() {
399
+ var o;
400
400
  try {
401
- const e = document.title, t = window.location.href, s = window.location.pathname, r = (((a = document.body) == null ? void 0 : a.innerText) || "").slice(0, 2e3).trim();
401
+ const e = document.title, t = window.location.href, s = window.location.pathname, r = (((o = document.body) == null ? void 0 : o.innerText) || "").slice(0, 2e3).trim();
402
402
  return {
403
403
  status: "success",
404
404
  data: {
@@ -416,19 +416,19 @@ async function x() {
416
416
  }
417
417
  }
418
418
  const w = {
419
- refreshPage: $,
420
- whatsOnScreen: x
421
- }, I = Object.keys(w), E = "https://api.usecrow.org", M = "claude-sonnet-4-20250514";
419
+ refreshPage: S,
420
+ whatsOnScreen: T
421
+ }, $ = Object.keys(w), E = "https://api.usecrow.org", L = "claude-sonnet-4-20250514";
422
422
  class U {
423
423
  constructor(e) {
424
424
  this.context = {}, this.abortController = null, this.callbacks = {}, this._messages = [], this.messageListeners = /* @__PURE__ */ new Set(), this._isLoading = !1, this.loadingListeners = /* @__PURE__ */ new Set(), this.config = {
425
425
  productId: e.productId,
426
426
  apiUrl: e.apiUrl || E,
427
- model: e.model || M
428
- }, this.identity = new _(), this.tools = new v(), this.conversations = new C(
427
+ model: e.model || L
428
+ }, this.identity = new _(), this.tools = new k(), this.conversations = new C(
429
429
  this.config.productId,
430
430
  this.config.apiUrl
431
- ), this.tools.register(w), console.log("[Crow] Default tools registered:", I.join(", ")), this.identity.subscribe((t) => {
431
+ ), this.tools.register(w), console.log("[Crow] Default tools registered:", $.join(", ")), this.identity.subscribe((t) => {
432
432
  var s, r;
433
433
  (r = (s = this.callbacks).onVerificationStatus) == null || r.call(s, t.isVerified);
434
434
  });
@@ -585,7 +585,7 @@ class U {
585
585
  updateMessage(e, t) {
586
586
  var s, r;
587
587
  this._messages = this._messages.map(
588
- (o) => o.id === e ? { ...o, ...t } : o
588
+ (n) => n.id === e ? { ...n, ...t } : n
589
589
  ), this.notifyMessages(), (r = (s = this.callbacks).onMessageUpdate) == null || r.call(s, e, t);
590
590
  }
591
591
  generateMessageId(e) {
@@ -635,7 +635,7 @@ class U {
635
635
  * Returns an async generator of stream events
636
636
  */
637
637
  async *sendMessage(e) {
638
- var n, u, d, l, h, g, p, f, m, y;
638
+ var i, d, h, u, l, g, f, p, y, m;
639
639
  if (!e.trim())
640
640
  return;
641
641
  const t = this.generateMessageId("user");
@@ -652,7 +652,7 @@ class U {
652
652
  role: "assistant",
653
653
  timestamp: /* @__PURE__ */ new Date()
654
654
  }), this.setLoading(!0), this.abortController = new AbortController();
655
- let r = "", o = "";
655
+ let r = "", n = "";
656
656
  try {
657
657
  const c = await fetch(`${this.config.apiUrl}/api/chat/message`, {
658
658
  method: "POST",
@@ -669,53 +669,53 @@ class U {
669
669
  });
670
670
  if (!c.ok)
671
671
  throw new Error(`HTTP error: ${c.status}`);
672
- for await (const i of T(c, this.abortController.signal)) {
673
- switch (i.type) {
672
+ for await (const a of M(c, this.abortController.signal)) {
673
+ switch (a.type) {
674
674
  case "content":
675
- r = i.accumulated, this.updateMessage(s, { content: r });
675
+ r = a.accumulated, this.updateMessage(s, { content: r });
676
676
  break;
677
677
  case "thinking":
678
- o += i.content, this.updateMessage(s, { thinking: o });
678
+ n += a.content, this.updateMessage(s, { thinking: n });
679
679
  break;
680
680
  case "thinking_complete":
681
681
  this.updateMessage(s, { thinkingComplete: !0 });
682
682
  break;
683
683
  case "citations":
684
- this.updateMessage(s, { citations: i.citations });
684
+ this.updateMessage(s, { citations: a.citations });
685
685
  break;
686
686
  case "verification_status":
687
- this.identity.setVerified(i.isVerified);
687
+ this.identity.setVerified(a.isVerified);
688
688
  break;
689
689
  case "conversation_id":
690
- this.conversations.setCurrentId(i.conversationId);
690
+ this.conversations.setCurrentId(a.conversationId);
691
691
  break;
692
692
  case "client_tool_call":
693
- await this.tools.execute(i.toolName, i.arguments), (u = (n = this.callbacks).onToolCall) == null || u.call(n, i);
693
+ await this.tools.execute(a.toolName, a.arguments), (d = (i = this.callbacks).onToolCall) == null || d.call(i, a);
694
694
  break;
695
695
  case "tool_call_start":
696
696
  case "tool_call_complete":
697
- (l = (d = this.callbacks).onToolCall) == null || l.call(d, i);
697
+ (u = (h = this.callbacks).onToolCall) == null || u.call(h, a);
698
698
  break;
699
699
  case "workflow_started":
700
700
  case "workflow_todo_updated":
701
701
  case "workflow_ended":
702
702
  case "workflow_complete_prompt":
703
- (g = (h = this.callbacks).onWorkflow) == null || g.call(h, i);
703
+ (g = (l = this.callbacks).onWorkflow) == null || g.call(l, a);
704
704
  break;
705
705
  case "error":
706
- this.updateMessage(s, { content: i.message }), (f = (p = this.callbacks).onError) == null || f.call(p, new Error(i.message));
706
+ this.updateMessage(s, { content: a.message }), (p = (f = this.callbacks).onError) == null || p.call(f, new Error(a.message));
707
707
  break;
708
708
  }
709
- yield i;
709
+ yield a;
710
710
  }
711
711
  } catch (c) {
712
712
  if (c instanceof Error && c.name === "AbortError") {
713
- r ? this.updateMessage(s, { content: r }) : (this._messages = this._messages.filter((i) => i.id !== s), this.notifyMessages());
713
+ r ? this.updateMessage(s, { content: r }) : (this._messages = this._messages.filter((a) => a.id !== s), this.notifyMessages());
714
714
  return;
715
715
  }
716
716
  console.error("[Crow] Error:", c), this.updateMessage(s, {
717
717
  content: "Sorry, I encountered an error. Please try again."
718
- }), (y = (m = this.callbacks).onError) == null || y.call(m, c instanceof Error ? c : new Error(String(c)));
718
+ }), (m = (y = this.callbacks).onError) == null || m.call(y, c instanceof Error ? c : new Error(String(c)));
719
719
  } finally {
720
720
  this.setLoading(!1), this.abortController = null;
721
721
  }
@@ -747,50 +747,50 @@ class U {
747
747
  this.stop(), this.messageListeners.clear(), this.loadingListeners.clear();
748
748
  }
749
749
  }
750
- function L(a, e, t) {
751
- const s = a.find(
752
- (o) => o.name.toLowerCase() === e.toLowerCase()
750
+ function x(o, e, t) {
751
+ const s = o.find(
752
+ (n) => n.name.toLowerCase() === e.toLowerCase()
753
753
  );
754
754
  if (!s) return null;
755
755
  let r = s.path;
756
756
  if (t)
757
- for (const [o, n] of Object.entries(t))
758
- r = r.replace(`:${o}`, String(n));
757
+ for (const [n, i] of Object.entries(t))
758
+ r = r.replace(`:${n}`, String(i));
759
759
  return r;
760
760
  }
761
- function O(a, e) {
761
+ function O(o, e) {
762
762
  return async (t) => {
763
763
  try {
764
- const s = t.page, r = t.params, o = t.url;
765
- let n = null;
764
+ const s = t.page, r = t.params, n = t.url;
765
+ let i = null;
766
766
  if (s) {
767
- if (n = L(a, s, r), !n)
767
+ if (i = x(o, s, r), !i)
768
768
  return {
769
769
  status: "error",
770
- error: `Unknown page: "${s}". Available pages: ${a.map((d) => d.name).join(", ")}`
770
+ error: `Unknown page: "${s}". Available pages: ${o.map((h) => h.name).join(", ")}`
771
771
  };
772
- } else if (o)
773
- n = o;
772
+ } else if (n)
773
+ i = n;
774
774
  else
775
775
  return {
776
776
  status: "error",
777
777
  error: 'Either "page" or "url" parameter is required'
778
778
  };
779
- const u = n.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g);
780
- return u ? {
779
+ const d = i.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g);
780
+ return d ? {
781
781
  status: "error",
782
- error: `Missing parameters: ${u.join(", ")}. Please provide values for these parameters.`
783
- } : e ? (e(n), {
782
+ error: `Missing parameters: ${d.join(", ")}. Please provide values for these parameters.`
783
+ } : e ? (e(i), {
784
784
  status: "success",
785
785
  data: {
786
- navigated_to: n,
786
+ navigated_to: i,
787
787
  page: s || void 0,
788
788
  method: "spa_router"
789
789
  }
790
- }) : (window.location.href = n, {
790
+ }) : (window.location.href = i, {
791
791
  status: "success",
792
792
  data: {
793
- navigated_to: n,
793
+ navigated_to: i,
794
794
  page: s || void 0,
795
795
  method: "full_navigation"
796
796
  }
@@ -803,147 +803,18 @@ function O(a, e) {
803
803
  }
804
804
  };
805
805
  }
806
- class R {
807
- constructor(e, t = {}) {
808
- this.controller = e, this.config = {
809
- waitTimeout: t.waitTimeout ?? 3e3,
810
- pollInterval: t.pollInterval ?? 300,
811
- stepDelay: t.stepDelay ?? 500,
812
- stopOnFailure: t.stopOnFailure ?? !1,
813
- onStepProgress: t.onStepProgress ?? (() => {
814
- })
815
- };
816
- }
817
- /**
818
- * Execute a recorded workflow with variable substitution.
819
- */
820
- async execute(e, t = {}) {
821
- const s = [];
822
- let r = 0;
823
- console.log(`[WorkflowExecutor] Starting workflow: ${e.name} (${e.steps.length} steps)`);
824
- for (let n = 0; n < e.steps.length; n++) {
825
- const u = e.steps[n], d = this.resolveVariables(u, t);
826
- console.log(`[WorkflowExecutor] Step ${n + 1}/${e.steps.length}: ${d.description}`);
827
- const l = await this.executeStep(d, n);
828
- if (s.push(l), this.config.onStepProgress(l), !l.success && (r++, console.warn(`[WorkflowExecutor] Step ${n + 1} failed: ${l.message}`), this.config.stopOnFailure))
829
- return {
830
- success: !1,
831
- workflow_name: e.name,
832
- total_steps: e.steps.length,
833
- completed_steps: n + 1,
834
- failed_steps: r,
835
- step_results: s,
836
- error: `Stopped at step ${n + 1}: ${l.message}`
837
- };
838
- n < e.steps.length - 1 && await this.delay(this.config.stepDelay);
839
- }
840
- const o = r === 0;
841
- return console.log(
842
- `[WorkflowExecutor] Workflow "${e.name}" ${o ? "completed successfully" : `completed with ${r} failures`}`
843
- ), {
844
- success: o,
845
- workflow_name: e.name,
846
- total_steps: e.steps.length,
847
- completed_steps: e.steps.length,
848
- failed_steps: r,
849
- step_results: s
850
- };
851
- }
852
- /**
853
- * Execute a single step.
854
- */
855
- async executeStep(e, t) {
856
- const s = {
857
- step_index: t,
858
- step_type: e.type,
859
- description: e.description,
860
- success: !1,
861
- message: ""
862
- };
863
- try {
864
- if (e.type === "navigation") {
865
- if (!e.url)
866
- return { ...s, message: "Navigation step has no URL" };
867
- const o = await this.controller.navigateToUrl(e.url);
868
- return await this.delay(1e3), { ...s, success: o.success, message: o.message };
869
- }
870
- await this.controller.updateTree();
871
- let r = this.controller.findElementByStrategies(e.selector_strategies);
872
- if (r === null && e.selector_strategies.length > 0 && (console.log(`[WorkflowExecutor] Element not found, waiting up to ${this.config.waitTimeout}ms...`), r = await this.controller.waitForElement(
873
- e.selector_strategies,
874
- this.config.waitTimeout,
875
- this.config.pollInterval
876
- )), r === null && e.target_text && (await this.controller.updateTree(), r = this.controller.findElementByText(e.target_text, !0), r === null && (r = this.controller.findElementByText(e.target_text, !1))), r === null)
877
- return {
878
- ...s,
879
- message: `Element not found for step: ${e.description} (target_text: "${e.target_text}")`
880
- };
881
- switch (s.element_index = r, e.type) {
882
- case "click": {
883
- const o = await this.controller.clickElement(r);
884
- return { ...s, success: o.success, message: o.message };
885
- }
886
- case "input": {
887
- if (e.value === void 0 || e.value === null)
888
- return { ...s, message: "Input step has no value" };
889
- const o = await this.controller.inputText(r, e.value);
890
- return { ...s, success: o.success, message: o.message };
891
- }
892
- case "select": {
893
- if (!e.value)
894
- return { ...s, message: "Select step has no value" };
895
- const o = await this.controller.selectOption(r, e.value);
896
- return { ...s, success: o.success, message: o.message };
897
- }
898
- case "keypress": {
899
- if (!e.value)
900
- return { ...s, message: "Keypress step has no key" };
901
- const o = await this.controller.pressKey(e.value, r);
902
- return { ...s, success: o.success, message: o.message };
903
- }
904
- default:
905
- return { ...s, message: `Unknown step type: ${e.type}` };
906
- }
907
- } catch (r) {
908
- return {
909
- ...s,
910
- message: `Error executing step: ${r instanceof Error ? r.message : String(r)}`
911
- };
912
- }
913
- }
914
- /**
915
- * Replace {variable_name} placeholders in step fields with actual values.
916
- */
917
- resolveVariables(e, t) {
918
- const s = (r) => !r || !r.includes("{") ? r : r.replace(/\{(\w+)\}/g, (o, n) => n in t ? String(t[n]) : o);
919
- return {
920
- ...e,
921
- description: s(e.description) || e.description,
922
- target_text: s(e.target_text) || e.target_text,
923
- value: s(e.value),
924
- url: s(e.url),
925
- selector_strategies: e.selector_strategies.map((r) => ({
926
- ...r,
927
- value: s(r.value) || r.value
928
- }))
929
- };
930
- }
931
- delay(e) {
932
- return new Promise((t) => setTimeout(t, e));
933
- }
934
- }
935
806
  export {
936
807
  C as ConversationManager,
937
- D as CrowBrowserUse,
808
+ R as CrowBrowserUse,
938
809
  U as CrowClient,
939
810
  w as DEFAULT_TOOLS,
940
- I as DEFAULT_TOOL_NAMES,
811
+ $ as DEFAULT_TOOL_NAMES,
941
812
  _ as IdentityManager,
942
- v as ToolManager,
943
- R as WorkflowExecutor,
813
+ k as ToolManager,
814
+ D as WorkflowExecutor,
944
815
  O as createNavigateToPageTool,
945
- b as parseSSEChunk,
946
- S as parseSSEData,
947
- L as resolveRoute,
948
- T as streamResponse
816
+ I as parseSSEChunk,
817
+ b as parseSSEData,
818
+ x as resolveRoute,
819
+ M as streamResponse
949
820
  };
@@ -0,0 +1 @@
1
+ "use strict";let m=null,f=null;function P(g){m=g}async function E(){if(m)return m;if(!f)try{f=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 f.PageController}class ${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 E();this.pageController=new e({enableMask:!0,viewportExpansion:500,highlightLabelOpacity:0,highlightOpacity:0}),await this.pageController.showMask();const o=this.pageController.mask;return o!=null&&o.wrapper&&(o.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 o,s,t,r,n,h,p,l,x,y,C,_,S,U;if(console.log("[CrowBrowserUse] Starting task:",e),this.config.onConfirmation&&!await this.config.onConfirmation(e))return console.log("[CrowBrowserUse] User declined browser automation"),(s=(o=this.config).onProgress)==null||s.call(o,-1,this.maxSteps),{status:"error",error:"User declined browser automation",data:{declined:!0}};try{const a=await this.initPageController(),b=await this.startSession(e);this.sessionId=b.session_id,this.maxSteps=b.max_steps,console.log("[CrowBrowserUse] Session started:",this.sessionId);let u=0,c;for(;u<this.maxSteps;){if(this.aborted)return console.log("[CrowBrowserUse] Task cancelled by user"),await this.cleanup(),(r=(t=this.config).onProgress)==null||r.call(t,-1,this.maxSteps),{status:"error",error:"Task cancelled by user"};u++;const v=await a.getBrowserState(),d=a.mask;d!=null&&d.wrapper&&(d.wrapper.style.pointerEvents="none");const i=await this.processStep(v,c);if(i.needs_user_input&&i.question){if(console.log("[CrowBrowserUse] Asking user:",i.question),!this.config.onQuestion){c="User input not available - no callback provided",console.warn("[CrowBrowserUse] No onQuestion callback provided");continue}try{const w=await this.config.onQuestion(i.question);c=`User answered: ${w}`,console.log("[CrowBrowserUse] User answered:",w)}catch(w){if(c="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(),(h=(n=this.config).onProgress)==null||h.call(n,-1,this.maxSteps),{status:"error",error:"Task cancelled by user"}}continue}if(i.done)return console.log("[CrowBrowserUse] Task completed:",i.message),await this.cleanup(),(l=(p=this.config).onProgress)==null||l.call(p,u,this.maxSteps),{status:i.success?"success":"error",data:{message:i.message,steps:u},error:i.success?void 0:i.message};if(i.error)return console.error("[CrowBrowserUse] Error:",i.error),await this.cleanup(),(y=(x=this.config).onProgress)==null||y.call(x,-1,this.maxSteps),{status:"error",error:i.error};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)}return await this.cleanup(),(_=(C=this.config).onProgress)==null||_.call(C,-1,this.maxSteps),{status:"error",error:`Task incomplete after ${this.maxSteps} steps`}}catch(a){return console.error("[CrowBrowserUse] Error:",a),await this.cleanup(),(U=(S=this.config).onProgress)==null||U.call(S,-1,this.maxSteps),{status:"error",error:a instanceof Error?a.message:String(a)}}}async startSession(e){const o=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(!o.ok){const s=await o.json().catch(()=>({detail:"Unknown error"}));throw new Error(s.detail||`Failed to start session: ${o.status}`)}return o.json()}async processStep(e,o){const s=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:o})});if(!s.ok){const t=await s.json().catch(()=>({detail:"Unknown error"}));throw new Error(t.detail||`Failed to process step: ${s.status}`)}return s.json()}async executeAction(e,o){const s=Object.keys(o)[0],t=o[s];try{switch(s){case"click_element_by_index":return(await e.clickElement(t.index)).message;case"input_text":return(await e.inputText(t.index,t.text)).message;case"select_dropdown_option":return(await e.selectOption(t.index,t.text)).message;case"scroll":return(await e.scroll({down:t.down,numPages:t.num_pages,pixels:t.pixels,index:t.index})).message;case"scroll_horizontally":return(await e.scrollHorizontally({right:t.right,pixels:t.pixels,index:t.index})).message;case"wait":{const r=t.seconds||1;return await new Promise(n=>setTimeout(n,r*1e3)),`Waited ${r} seconds`}case"done":return"Task completed";default:return`Unknown action: ${s}`}}catch(r){return`Action failed: ${r instanceof Error?r.message:String(r)}`}}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()}}class k{constructor(e,o={}){this.controller=e,this.config={waitTimeout:o.waitTimeout??3e3,pollInterval:o.pollInterval??300,stepDelay:o.stepDelay??500,stopOnFailure:o.stopOnFailure??!1,onStepProgress:o.onStepProgress??(()=>{})}}async execute(e,o={}){const s=[];let t=0;console.log(`[WorkflowExecutor] Starting workflow: ${e.name} (${e.steps.length} steps)`);for(let n=0;n<e.steps.length;n++){const h=e.steps[n],p=this.resolveVariables(h,o);console.log(`[WorkflowExecutor] Step ${n+1}/${e.steps.length}: ${p.description}`);const l=await this.executeStep(p,n);if(s.push(l),this.config.onStepProgress(l),!l.success&&(t++,console.warn(`[WorkflowExecutor] Step ${n+1} failed: ${l.message}`),this.config.stopOnFailure))return{success:!1,workflow_name:e.name,total_steps:e.steps.length,completed_steps:n+1,failed_steps:t,step_results:s,error:`Stopped at step ${n+1}: ${l.message}`};n<e.steps.length-1&&await this.delay(this.config.stepDelay)}const r=t===0;return console.log(`[WorkflowExecutor] Workflow "${e.name}" ${r?"completed successfully":`completed with ${t} failures`}`),{success:r,workflow_name:e.name,total_steps:e.steps.length,completed_steps:e.steps.length,failed_steps:t,step_results:s}}async executeStep(e,o){const s={step_index:o,step_type:e.type,description:e.description,success:!1,message:""};try{if(e.type==="navigation"){if(!e.url)return{...s,message:"Navigation step has no URL"};const r=await this.controller.navigateToUrl(e.url);return await this.delay(1e3),{...s,success:r.success,message:r.message}}await this.controller.updateTree();let t=this.controller.findElementByStrategies(e.selector_strategies);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(e.selector_strategies,this.config.waitTimeout,this.config.pollInterval)),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)return{...s,message:`Element not found for step: ${e.description} (target_text: "${e.target_text}")`};switch(s.element_index=t,e.type){case"click":{const r=await this.controller.clickElement(t);return{...s,success:r.success,message:r.message}}case"input":{if(e.value===void 0||e.value===null)return{...s,message:"Input step has no value"};const r=await this.controller.inputText(t,e.value);return{...s,success:r.success,message:r.message}}case"select":{if(!e.value)return{...s,message:"Select step has no value"};const r=await this.controller.selectOption(t,e.value);return{...s,success:r.success,message:r.message}}case"keypress":{if(!e.value)return{...s,message:"Keypress step has no key"};const r=await this.controller.pressKey(e.value,t);return{...s,success:r.success,message:r.message}}default:return{...s,message:`Unknown step type: ${e.type}`}}}catch(t){return{...s,message:`Error executing step: ${t instanceof Error?t.message:String(t)}`}}}resolveVariables(e,o){const s=t=>!t||!t.includes("{")?t:t.replace(/\{(\w+)\}/g,(r,n)=>n in o?String(o[n]):r);return{...e,description:s(e.description)||e.description,target_text:s(e.target_text)||e.target_text,value:s(e.value),url:s(e.url),selector_strategies:e.selector_strategies.map(t=>({...t,value:s(t.value)||t.value}))}}delay(e){return new Promise(o=>setTimeout(o,e))}}exports.CrowBrowserUse=$;exports.WorkflowExecutor=k;exports.setPageController=P;