@usecrow/client 0.1.27 → 0.1.28

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,79 @@
1
+ (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(`._wrapper_7c7fs_1{position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483641;cursor:wait;overflow:hidden;display:none}._animatedBorder_7c7fs_14{position:absolute;top:0;right:0;bottom:0;left:0;--border-width: 3px;--glow-size: 8px;--animation-speed: 3s;opacity:0;transition:opacity .3s ease-out}._animatedBorderVisible_7c7fs_27{opacity:1}._animatedBorder_7c7fs_14:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border:var(--border-width) solid transparent;background:linear-gradient(90deg,#1e3a5f,#2563eb,#3b82f6,#60a5fa,#3b82f6,#2563eb,#1e3a5f) border-box;background-size:300% 100%;-webkit-mask:linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask:linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0);mask-composite:exclude;animation:_shimmerBorder_7c7fs_1 var(--animation-speed) linear infinite}._animatedBorder_7c7fs_14:after{content:"";position:absolute;inset:calc(-1 * var(--glow-size));border:calc(var(--border-width) + var(--glow-size)) solid transparent;background:linear-gradient(90deg,#1e3a5f,#2563eb,#3b82f6,#60a5fa,#3b82f6,#2563eb,#1e3a5f) border-box;background-size:300% 100%;-webkit-mask:linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask:linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0);mask-composite:exclude;animation:_shimmerBorder_7c7fs_1 var(--animation-speed) linear infinite;filter:blur(var(--glow-size));opacity:.6}@keyframes _shimmerBorder_7c7fs_1{0%{background-position:0% 50%}to{background-position:300% 50%}}._cursor_o2dvz_2{position:absolute;width:32px;height:32px;pointer-events:none;z-index:10000;background:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='48'%20height='48'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='%23000'%20d='M4.5.79v22.42l6.56-6.57h9.29L4.5.79z'%3e%3c/path%3e%3c/svg%3e");background-size:contain;background-repeat:no-repeat}._cursorRipple_o2dvz_14{position:absolute;width:48px;height:48px;pointer-events:none;top:8px;left:8px}._cursorRipple_o2dvz_14:after{content:"";opacity:0;position:absolute;top:0;right:0;bottom:0;left:0;border:3px solid rgba(59,130,246,.8);border-radius:50%}._cursor_o2dvz_2._clicking_o2dvz_32 ._cursorRipple_o2dvz_14:after{animation:_cursor-ripple_o2dvz_1 .3s ease-out forwards}@keyframes _cursor-ripple_o2dvz_1{0%{transform:scale(0);opacity:1}to{transform:scale(1.5);opacity:0}}`)),document.head.appendChild(e)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
2
+ var C = (i) => {
3
+ throw TypeError(i);
4
+ };
5
+ var g = (i, t, s) => t.has(i) || C("Cannot " + s);
6
+ var e = (i, t, s) => (g(i, t, "read from private field"), s ? s.call(i) : t.get(i)), d = (i, t, s) => t.has(i) ? C("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(i) : t.set(i, s), r = (i, t, s, l) => (g(i, t, "write to private field"), l ? l.call(i, s) : t.set(i, s), s), w = (i, t, s) => (g(i, t, "access private method"), s);
7
+ const y = "_wrapper_7c7fs_1", E = "_animatedBorder_7c7fs_14", L = "_animatedBorderVisible_7c7fs_27", v = {
8
+ wrapper: y,
9
+ animatedBorder: E,
10
+ animatedBorderVisible: L
11
+ }, P = "_cursor_o2dvz_2", b = "_cursorRipple_o2dvz_14", B = "_clicking_o2dvz_32", m = {
12
+ cursor: P,
13
+ cursorRipple: b,
14
+ clicking: B
15
+ };
16
+ var c, a, o, n, p, h, u, k, f;
17
+ class x {
18
+ constructor() {
19
+ d(this, u);
20
+ d(this, c);
21
+ d(this, a);
22
+ d(this, o);
23
+ d(this, n);
24
+ d(this, p);
25
+ d(this, h);
26
+ this.shown = !1, this.wrapper = document.createElement("div"), r(this, c, document.createElement("div")), r(this, a, document.createElement("div")), r(this, o, 0), r(this, n, 0), r(this, p, 0), r(this, h, 0), this.wrapper.id = "page-agent-runtime_simulator-mask", this.wrapper.className = v.wrapper, this.wrapper.setAttribute("data-browser-use-ignore", "true"), e(this, c).className = v.animatedBorder, this.wrapper.appendChild(e(this, c)), this.wrapper.addEventListener("click", (t) => {
27
+ t.stopPropagation(), t.preventDefault();
28
+ }), this.wrapper.addEventListener("mousedown", (t) => {
29
+ t.stopPropagation(), t.preventDefault();
30
+ }), this.wrapper.addEventListener("mouseup", (t) => {
31
+ t.stopPropagation(), t.preventDefault();
32
+ }), this.wrapper.addEventListener("mousemove", (t) => {
33
+ t.stopPropagation(), t.preventDefault();
34
+ }), this.wrapper.addEventListener("wheel", (t) => {
35
+ t.stopPropagation(), t.preventDefault();
36
+ }), this.wrapper.addEventListener("keydown", (t) => {
37
+ t.stopPropagation(), t.preventDefault();
38
+ }), this.wrapper.addEventListener("keyup", (t) => {
39
+ t.stopPropagation(), t.preventDefault();
40
+ }), w(this, u, k).call(this), document.body.appendChild(this.wrapper), w(this, u, f).call(this), window.addEventListener("PageAgent::MovePointerTo", (t) => {
41
+ const { x: s, y: l } = t.detail;
42
+ this.setCursorPosition(s, l);
43
+ }), window.addEventListener("PageAgent::ClickPointer", () => {
44
+ this.triggerClickAnimation();
45
+ });
46
+ }
47
+ setCursorPosition(t, s) {
48
+ r(this, p, t), r(this, h, s);
49
+ }
50
+ triggerClickAnimation() {
51
+ e(this, a).classList.remove(m.clicking), e(this, a).offsetHeight, e(this, a).classList.add(m.clicking);
52
+ }
53
+ show() {
54
+ this.shown || (this.shown = !0, this.wrapper.style.display = "block", requestAnimationFrame(() => {
55
+ e(this, c).classList.add(v.animatedBorderVisible);
56
+ }), r(this, o, window.innerWidth / 2), r(this, n, window.innerHeight / 2), r(this, p, e(this, o)), r(this, h, e(this, n)), e(this, a).style.left = `${e(this, o)}px`, e(this, a).style.top = `${e(this, n)}px`);
57
+ }
58
+ hide() {
59
+ this.shown && (this.shown = !1, e(this, c).classList.remove(v.animatedBorderVisible), e(this, a).classList.remove(m.clicking), setTimeout(() => {
60
+ this.wrapper.style.display = "none";
61
+ }, 300));
62
+ }
63
+ dispose() {
64
+ this.wrapper.remove();
65
+ }
66
+ }
67
+ c = new WeakMap(), a = new WeakMap(), o = new WeakMap(), n = new WeakMap(), p = new WeakMap(), h = new WeakMap(), u = new WeakSet(), k = function() {
68
+ e(this, a).className = m.cursor;
69
+ const t = document.createElement("div");
70
+ t.className = m.cursorRipple, e(this, a).appendChild(t), this.wrapper.appendChild(e(this, a));
71
+ }, f = function() {
72
+ const t = e(this, o) + (e(this, p) - e(this, o)) * 0.2, s = e(this, n) + (e(this, h) - e(this, n)) * 0.2, l = Math.abs(t - e(this, p));
73
+ l > 0 && (l < 2 ? r(this, o, e(this, p)) : r(this, o, t), e(this, a).style.left = `${e(this, o)}px`);
74
+ const _ = Math.abs(s - e(this, h));
75
+ _ > 0 && (_ < 2 ? r(this, n, e(this, h)) : r(this, n, s), e(this, a).style.top = `${e(this, n)}px`), requestAnimationFrame(() => w(this, u, f).call(this));
76
+ };
77
+ export {
78
+ x as SimulatorMask
79
+ };
@@ -0,0 +1,2 @@
1
+ (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(`._wrapper_7c7fs_1{position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483641;cursor:wait;overflow:hidden;display:none}._animatedBorder_7c7fs_14{position:absolute;top:0;right:0;bottom:0;left:0;--border-width: 3px;--glow-size: 8px;--animation-speed: 3s;opacity:0;transition:opacity .3s ease-out}._animatedBorderVisible_7c7fs_27{opacity:1}._animatedBorder_7c7fs_14:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border:var(--border-width) solid transparent;background:linear-gradient(90deg,#1e3a5f,#2563eb,#3b82f6,#60a5fa,#3b82f6,#2563eb,#1e3a5f) border-box;background-size:300% 100%;-webkit-mask:linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask:linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0);mask-composite:exclude;animation:_shimmerBorder_7c7fs_1 var(--animation-speed) linear infinite}._animatedBorder_7c7fs_14:after{content:"";position:absolute;inset:calc(-1 * var(--glow-size));border:calc(var(--border-width) + var(--glow-size)) solid transparent;background:linear-gradient(90deg,#1e3a5f,#2563eb,#3b82f6,#60a5fa,#3b82f6,#2563eb,#1e3a5f) border-box;background-size:300% 100%;-webkit-mask:linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask:linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0);mask-composite:exclude;animation:_shimmerBorder_7c7fs_1 var(--animation-speed) linear infinite;filter:blur(var(--glow-size));opacity:.6}@keyframes _shimmerBorder_7c7fs_1{0%{background-position:0% 50%}to{background-position:300% 50%}}._cursor_o2dvz_2{position:absolute;width:32px;height:32px;pointer-events:none;z-index:10000;background:url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='48'%20height='48'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='%23000'%20d='M4.5.79v22.42l6.56-6.57h9.29L4.5.79z'%3e%3c/path%3e%3c/svg%3e");background-size:contain;background-repeat:no-repeat}._cursorRipple_o2dvz_14{position:absolute;width:48px;height:48px;pointer-events:none;top:8px;left:8px}._cursorRipple_o2dvz_14:after{content:"";opacity:0;position:absolute;top:0;right:0;bottom:0;left:0;border:3px solid rgba(59,130,246,.8);border-radius:50%}._cursor_o2dvz_2._clicking_o2dvz_32 ._cursorRipple_o2dvz_14:after{animation:_cursor-ripple_o2dvz_1 .3s ease-out forwards}@keyframes _cursor-ripple_o2dvz_1{0%{transform:scale(0);opacity:1}to{transform:scale(1.5);opacity:0}}`)),document.head.appendChild(e)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
2
+ "use strict";var y=i=>{throw TypeError(i)};var g=(i,t,s)=>t.has(i)||y("Cannot "+s);var e=(i,t,s)=>(g(i,t,"read from private field"),s?s.call(i):t.get(i)),d=(i,t,s)=>t.has(i)?y("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(i):t.set(i,s),r=(i,t,s,l)=>(g(i,t,"write to private field"),l?l.call(i,s):t.set(i,s),s),w=(i,t,s)=>(g(i,t,"access private method"),s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C="_wrapper_7c7fs_1",b="_animatedBorder_7c7fs_14",E="_animatedBorderVisible_7c7fs_27",v={wrapper:C,animatedBorder:b,animatedBorderVisible:E},L="_cursor_o2dvz_2",P="_cursorRipple_o2dvz_14",B="_clicking_o2dvz_32",m={cursor:L,cursorRipple:P,clicking:B};var c,a,o,n,p,h,u,k,f;class D{constructor(){d(this,u);d(this,c);d(this,a);d(this,o);d(this,n);d(this,p);d(this,h);this.shown=!1,this.wrapper=document.createElement("div"),r(this,c,document.createElement("div")),r(this,a,document.createElement("div")),r(this,o,0),r(this,n,0),r(this,p,0),r(this,h,0),this.wrapper.id="page-agent-runtime_simulator-mask",this.wrapper.className=v.wrapper,this.wrapper.setAttribute("data-browser-use-ignore","true"),e(this,c).className=v.animatedBorder,this.wrapper.appendChild(e(this,c)),this.wrapper.addEventListener("click",t=>{t.stopPropagation(),t.preventDefault()}),this.wrapper.addEventListener("mousedown",t=>{t.stopPropagation(),t.preventDefault()}),this.wrapper.addEventListener("mouseup",t=>{t.stopPropagation(),t.preventDefault()}),this.wrapper.addEventListener("mousemove",t=>{t.stopPropagation(),t.preventDefault()}),this.wrapper.addEventListener("wheel",t=>{t.stopPropagation(),t.preventDefault()}),this.wrapper.addEventListener("keydown",t=>{t.stopPropagation(),t.preventDefault()}),this.wrapper.addEventListener("keyup",t=>{t.stopPropagation(),t.preventDefault()}),w(this,u,k).call(this),document.body.appendChild(this.wrapper),w(this,u,f).call(this),window.addEventListener("PageAgent::MovePointerTo",t=>{const{x:s,y:l}=t.detail;this.setCursorPosition(s,l)}),window.addEventListener("PageAgent::ClickPointer",()=>{this.triggerClickAnimation()})}setCursorPosition(t,s){r(this,p,t),r(this,h,s)}triggerClickAnimation(){e(this,a).classList.remove(m.clicking),e(this,a).offsetHeight,e(this,a).classList.add(m.clicking)}show(){this.shown||(this.shown=!0,this.wrapper.style.display="block",requestAnimationFrame(()=>{e(this,c).classList.add(v.animatedBorderVisible)}),r(this,o,window.innerWidth/2),r(this,n,window.innerHeight/2),r(this,p,e(this,o)),r(this,h,e(this,n)),e(this,a).style.left=`${e(this,o)}px`,e(this,a).style.top=`${e(this,n)}px`)}hide(){this.shown&&(this.shown=!1,e(this,c).classList.remove(v.animatedBorderVisible),e(this,a).classList.remove(m.clicking),setTimeout(()=>{this.wrapper.style.display="none"},300))}dispose(){this.wrapper.remove()}}c=new WeakMap,a=new WeakMap,o=new WeakMap,n=new WeakMap,p=new WeakMap,h=new WeakMap,u=new WeakSet,k=function(){e(this,a).className=m.cursor;const t=document.createElement("div");t.className=m.cursorRipple,e(this,a).appendChild(t),this.wrapper.appendChild(e(this,a))},f=function(){const t=e(this,o)+(e(this,p)-e(this,o))*.2,s=e(this,n)+(e(this,h)-e(this,n))*.2,l=Math.abs(t-e(this,p));l>0&&(l<2?r(this,o,e(this,p)):r(this,o,t),e(this,a).style.left=`${e(this,o)}px`);const _=Math.abs(s-e(this,h));_>0&&(_<2?r(this,n,e(this,h)):r(this,n,s),e(this,a).style.top=`${e(this,n)}px`),requestAnimationFrame(()=>w(this,u,f).call(this))};exports.SimulatorMask=D;
package/dist/browser.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("./PageController-GcMFZYwU.cjs"),r=require("./browserUse-BOc9kyBK.cjs");r.setPageController(s.PageController);function n(e){return async o=>{const t=o.instruction||o.instruction;return t?new r.CrowBrowserUse({productId:e.productId,apiUrl:e.apiUrl}).execute(t):{status:"error",error:"Missing instruction parameter for browser_use tool"}}}exports.PageController=s.PageController;exports.CrowBrowserUse=r.CrowBrowserUse;exports.createBrowserUseTool=n;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./PageController-72owMK9b.cjs"),o=require("./browserUse-CMYea2D_.cjs");o.setPageController(t.PageController);function w(e,i){return async n=>{const s=n.instruction||n.instruction;if(!s)return{status:"error",error:"Missing instruction parameter for browser_use tool"};const u=window.__crow_browser_callbacks,r=i||u;return new o.CrowBrowserUse({productId:e.productId,apiUrl:e.apiUrl,onConfirmation:r==null?void 0:r.onConfirmation,onQuestion:r==null?void 0:r.onQuestion,onProgress:r==null?void 0:r.onProgress}).execute(s)}}exports.PageController=t.PageController;exports.CrowBrowserUse=o.CrowBrowserUse;exports.createBrowserUseTool=w;
package/dist/browser.d.ts CHANGED
@@ -17,9 +17,18 @@ declare interface BrowserState {
17
17
  footer: string;
18
18
  }
19
19
 
20
+ export declare interface BrowserUseCallbacks {
21
+ onConfirmation?: (instruction: string) => Promise<boolean>;
22
+ onQuestion?: (question: string) => Promise<string>;
23
+ onProgress?: (step: number, maxSteps: number, action?: string) => void;
24
+ }
25
+
20
26
  declare interface BrowserUseConfig {
21
27
  productId: string;
22
28
  apiUrl: string;
29
+ onConfirmation?: (instruction: string) => Promise<boolean>;
30
+ onQuestion?: (question: string) => Promise<string>;
31
+ onProgress?: (step: number, maxSteps: number, action?: string) => void;
23
32
  }
24
33
 
25
34
  export declare interface BrowserUseToolArgs {
@@ -37,12 +46,20 @@ declare function cleanUpHighlights(): void;
37
46
  * Create a browser_use tool handler for registration with CrowClient or widget.
38
47
  *
39
48
  * @param config - Configuration with productId and apiUrl
49
+ * @param callbacks - Optional callbacks for user interaction (confirmation, questions, progress)
40
50
  * @returns Async function that executes browser automation tasks
41
51
  *
42
52
  * @example
43
53
  * ```typescript
44
- * // Widget usage
45
- * window.__crow_client_tools.browser_use = createBrowserUseTool({ productId, apiUrl });
54
+ * // Widget usage with callbacks
55
+ * window.__crow_client_tools.browser_use = createBrowserUseTool(
56
+ * { productId, apiUrl },
57
+ * {
58
+ * onConfirmation: (instruction) => showConfirmDialog(instruction),
59
+ * onQuestion: (question) => showQuestionDialog(question),
60
+ * onProgress: (step, maxSteps) => updateProgress(step, maxSteps),
61
+ * }
62
+ * );
46
63
  *
47
64
  * // SDK usage
48
65
  * client.registerTools({
@@ -50,7 +67,7 @@ declare function cleanUpHighlights(): void;
50
67
  * });
51
68
  * ```
52
69
  */
53
- export declare function createBrowserUseTool(config: BrowserUseToolConfig): (args: BrowserUseToolArgs | Record<string, unknown>) => Promise<ToolResult>;
70
+ export declare function createBrowserUseTool(config: BrowserUseToolConfig, callbacks?: BrowserUseCallbacks): (args: BrowserUseToolArgs | Record<string, unknown>) => Promise<ToolResult>;
54
71
 
55
72
  export declare class CrowBrowserUse {
56
73
  private config;
@@ -74,6 +91,10 @@ export declare class CrowBrowserUse {
74
91
  * Process a step on the server
75
92
  */
76
93
  private processStep;
94
+ /**
95
+ * Submit user's response to an ask_user question
96
+ */
97
+ private submitUserResponse;
77
98
  /**
78
99
  * Execute an action using PageController
79
100
  */
@@ -316,7 +337,7 @@ declare interface TextDomNode {
316
337
  }
317
338
 
318
339
  declare interface ToolResult {
319
- status: 'success' | 'error';
340
+ status: 'success' | 'error' | 'needs_input';
320
341
  data?: unknown;
321
342
  error?: string;
322
343
  }
package/dist/browser.js CHANGED
@@ -1,20 +1,26 @@
1
- import { PageController as t } from "./PageController-KoeqDxMP.js";
2
- import { C as s, s as n } from "./browserUse-BbPG4pH1.js";
3
- n(t);
4
- function a(r) {
5
- return async (o) => {
6
- const e = o.instruction || o.instruction;
7
- return e ? new s({
8
- productId: r.productId,
9
- apiUrl: r.apiUrl
10
- }).execute(e) : {
11
- status: "error",
12
- error: "Missing instruction parameter for browser_use tool"
13
- };
1
+ import { PageController as i } from "./PageController-BT9YJiz0.js";
2
+ import { C as u, s as w } from "./browserUse-CMq8wG4u.js";
3
+ w(i);
4
+ function m(o, t) {
5
+ return async (n) => {
6
+ const s = n.instruction || n.instruction;
7
+ if (!s)
8
+ return {
9
+ status: "error",
10
+ error: "Missing instruction parameter for browser_use tool"
11
+ };
12
+ const e = window.__crow_browser_callbacks, r = t || e;
13
+ return new u({
14
+ productId: o.productId,
15
+ apiUrl: o.apiUrl,
16
+ onConfirmation: r == null ? void 0 : r.onConfirmation,
17
+ onQuestion: r == null ? void 0 : r.onQuestion,
18
+ onProgress: r == null ? void 0 : r.onProgress
19
+ }).execute(s);
14
20
  };
15
21
  }
16
22
  export {
17
- s as CrowBrowserUse,
18
- t as PageController,
19
- a as createBrowserUseTool
23
+ u as CrowBrowserUse,
24
+ i as PageController,
25
+ m as createBrowserUseTool
20
26
  };
@@ -0,0 +1 @@
1
+ "use strict";let p=null,u=null;function w(l){p=l}async function d(){if(p)return p;if(!u)try{u=await Promise.resolve().then(()=>require("./PageController-72owMK9b.cjs"))}catch{throw new Error('PageController not available. Either import from "@usecrow/client/browser" or use the bundled version.')}return u.PageController}class h{constructor(t){this.pageController=null,this.sessionId=null,this.maxSteps=20,this.config=t}async initPageController(){if(this.pageController)return this.pageController;try{const t=await d();this.pageController=new t({enableMask:!0,viewportExpansion:500,highlightLabelOpacity:0,highlightOpacity:0}),await this.pageController.showMask();const e=this.pageController.mask;return e!=null&&e.wrapper&&(e.wrapper.style.pointerEvents="none"),console.log("[CrowBrowserUse] PageController initialized with non-blocking pointer"),this.pageController}catch(t){throw console.error("[CrowBrowserUse] Failed to initialize PageController:",t),new Error("Failed to initialize browser automation. Please import from @usecrow/client/browser.")}}async execute(t){if(console.log("[CrowBrowserUse] Starting task:",t),this.config.onConfirmation&&!await this.config.onConfirmation(t))return console.log("[CrowBrowserUse] User declined browser automation"),{status:"error",error:"User declined browser automation",data:{declined:!0}};try{const e=await this.initPageController(),o=await this.startSession(t);this.sessionId=o.session_id,this.maxSteps=o.max_steps,console.log("[CrowBrowserUse] Session started:",this.sessionId);let s=0,n;for(;s<this.maxSteps;){s++,this.config.onProgress&&this.config.onProgress(s,this.maxSteps);const a=await e.getBrowserState(),r=await this.processStep(a,n);if(r.needs_user_input&&r.question)if(console.log("[CrowBrowserUse] Agent asking user:",r.question),this.config.onQuestion){const c=await this.config.onQuestion(r.question);console.log("[CrowBrowserUse] User responded:",c);const i=await this.submitUserResponse(c,a);if(i.done)return console.log("[CrowBrowserUse] Task completed after user response:",i.message),await this.cleanup(),{status:i.success?"success":"error",data:{message:i.message,steps:s},error:i.success?void 0:i.message};i.action&&(n=await this.executeAction(e,i.action),console.log(`[CrowBrowserUse] Step ${s} (after user response):`,n));continue}else return console.log("[CrowBrowserUse] No question handler, returning needs_input"),await this.cleanup(),{status:"needs_input",error:r.question,data:{question:r.question,sessionId:this.sessionId}};if(r.done)return console.log("[CrowBrowserUse] Task completed:",r.message),await this.cleanup(),{status:r.success?"success":"error",data:{message:r.message,steps:s},error:r.success?void 0:r.message};if(r.error)return console.error("[CrowBrowserUse] Error:",r.error),await this.cleanup(),{status:"error",error:r.error};if(r.action&&(n=await this.executeAction(e,r.action),console.log(`[CrowBrowserUse] Step ${s}:`,n),this.config.onProgress)){const c=Object.keys(r.action)[0];this.config.onProgress(s,this.maxSteps,c)}r.reflection&&console.log("[CrowBrowserUse] Reflection:",r.reflection.next_goal)}return await this.cleanup(),{status:"error",error:`Task incomplete after ${this.maxSteps} steps`}}catch(e){return console.error("[CrowBrowserUse] Error:",e),await this.cleanup(),{status:"error",error:e instanceof Error?e.message:String(e)}}}async startSession(t){const e=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:t})});if(!e.ok){const o=await e.json().catch(()=>({detail:"Unknown error"}));throw new Error(o.detail||`Failed to start session: ${e.status}`)}return e.json()}async processStep(t,e){const o=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:t,action_result:e})});if(!o.ok){const s=await o.json().catch(()=>({detail:"Unknown error"}));throw new Error(s.detail||`Failed to process step: ${o.status}`)}return o.json()}async submitUserResponse(t,e){const o=await fetch(`${this.config.apiUrl}/api/browser-use/user-response`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:this.sessionId,product_id:this.config.productId,user_response:t,browser_state:e})});if(!o.ok){const s=await o.json().catch(()=>({detail:"Unknown error"}));throw new Error(s.detail||`Failed to submit user response: ${o.status}`)}return o.json()}async executeAction(t,e){const o=Object.keys(e)[0],s=e[o];try{switch(o){case"click_element_by_index":return(await t.clickElement(s.index)).message;case"input_text":return(await t.inputText(s.index,s.text)).message;case"select_dropdown_option":return(await t.selectOption(s.index,s.text)).message;case"scroll":return(await t.scroll({down:s.down,numPages:s.num_pages,pixels:s.pixels,index:s.index})).message;case"scroll_horizontally":return(await t.scrollHorizontally({right:s.right,pixels:s.pixels,index:s.index})).message;case"wait":{const n=s.seconds||1;return await new Promise(a=>setTimeout(a,n*1e3)),`Waited ${n} seconds`}case"done":return"Task completed";default:return`Unknown action: ${o}`}}catch(n){return`Action failed: ${n instanceof Error?n.message:String(n)}`}}async cleanup(){if(this.pageController){try{await this.pageController.hideMask(),await this.pageController.cleanUpHighlights(),this.pageController.dispose()}catch(t){console.warn("[CrowBrowserUse] Cleanup error:",t)}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(){await this.cleanup()}}exports.CrowBrowserUse=h;exports.setPageController=w;
@@ -1,21 +1,21 @@
1
- let c = null, l = null;
2
- function w(i) {
3
- c = i;
1
+ let p = null, u = null;
2
+ function d(l) {
3
+ p = l;
4
4
  }
5
- async function p() {
6
- if (c)
7
- return c;
8
- if (!l)
5
+ async function w() {
6
+ if (p)
7
+ return p;
8
+ if (!u)
9
9
  try {
10
- l = await import("./PageController-KoeqDxMP.js");
10
+ u = await import("./PageController-BT9YJiz0.js");
11
11
  } catch {
12
12
  throw new Error(
13
13
  'PageController not available. Either import from "@usecrow/client/browser" or use the bundled version.'
14
14
  );
15
15
  }
16
- return l.PageController;
16
+ return u.PageController;
17
17
  }
18
- class u {
18
+ class h {
19
19
  constructor(t) {
20
20
  this.pageController = null, this.sessionId = null, this.maxSteps = 20, this.config = t;
21
21
  }
@@ -26,7 +26,7 @@ class u {
26
26
  if (this.pageController)
27
27
  return this.pageController;
28
28
  try {
29
- const t = await p();
29
+ const t = await w();
30
30
  this.pageController = new t({
31
31
  enableMask: !0,
32
32
  viewportExpansion: 500,
@@ -47,29 +47,63 @@ class u {
47
47
  * Execute a browser automation task
48
48
  */
49
49
  async execute(t) {
50
- console.log("[CrowBrowserUse] Starting task:", t);
50
+ if (console.log("[CrowBrowserUse] Starting task:", t), this.config.onConfirmation && !await this.config.onConfirmation(t))
51
+ return console.log("[CrowBrowserUse] User declined browser automation"), {
52
+ status: "error",
53
+ error: "User declined browser automation",
54
+ data: { declined: !0 }
55
+ };
51
56
  try {
52
57
  const e = await this.initPageController(), o = await this.startSession(t);
53
58
  this.sessionId = o.session_id, this.maxSteps = o.max_steps, console.log("[CrowBrowserUse] Session started:", this.sessionId);
54
- let r = 0, s;
55
- for (; r < this.maxSteps; ) {
56
- r++;
57
- const a = await e.getBrowserState(), n = await this.processStep(a, s);
58
- if (n.done)
59
- return console.log("[CrowBrowserUse] Task completed:", n.message), await this.cleanup(), {
60
- status: n.success ? "success" : "error",
59
+ let s = 0, n;
60
+ for (; s < this.maxSteps; ) {
61
+ s++, this.config.onProgress && this.config.onProgress(s, this.maxSteps);
62
+ const a = await e.getBrowserState(), r = await this.processStep(a, n);
63
+ if (r.needs_user_input && r.question)
64
+ if (console.log("[CrowBrowserUse] Agent asking user:", r.question), this.config.onQuestion) {
65
+ const c = await this.config.onQuestion(r.question);
66
+ console.log("[CrowBrowserUse] User responded:", c);
67
+ const i = await this.submitUserResponse(c, a);
68
+ if (i.done)
69
+ return console.log("[CrowBrowserUse] Task completed after user response:", i.message), await this.cleanup(), {
70
+ status: i.success ? "success" : "error",
71
+ data: {
72
+ message: i.message,
73
+ steps: s
74
+ },
75
+ error: i.success ? void 0 : i.message
76
+ };
77
+ i.action && (n = await this.executeAction(e, i.action), console.log(`[CrowBrowserUse] Step ${s} (after user response):`, n));
78
+ continue;
79
+ } else
80
+ return console.log("[CrowBrowserUse] No question handler, returning needs_input"), await this.cleanup(), {
81
+ status: "needs_input",
82
+ error: r.question,
83
+ data: {
84
+ question: r.question,
85
+ sessionId: this.sessionId
86
+ }
87
+ };
88
+ if (r.done)
89
+ return console.log("[CrowBrowserUse] Task completed:", r.message), await this.cleanup(), {
90
+ status: r.success ? "success" : "error",
61
91
  data: {
62
- message: n.message,
63
- steps: r
92
+ message: r.message,
93
+ steps: s
64
94
  },
65
- error: n.success ? void 0 : n.message
95
+ error: r.success ? void 0 : r.message
66
96
  };
67
- if (n.error)
68
- return console.error("[CrowBrowserUse] Error:", n.error), await this.cleanup(), {
97
+ if (r.error)
98
+ return console.error("[CrowBrowserUse] Error:", r.error), await this.cleanup(), {
69
99
  status: "error",
70
- error: n.error
100
+ error: r.error
71
101
  };
72
- n.action && (s = await this.executeAction(e, n.action), console.log(`[CrowBrowserUse] Step ${r}:`, s)), n.reflection && console.log("[CrowBrowserUse] Reflection:", n.reflection.next_goal);
102
+ if (r.action && (n = await this.executeAction(e, r.action), console.log(`[CrowBrowserUse] Step ${s}:`, n), this.config.onProgress)) {
103
+ const c = Object.keys(r.action)[0];
104
+ this.config.onProgress(s, this.maxSteps, c);
105
+ }
106
+ r.reflection && console.log("[CrowBrowserUse] Reflection:", r.reflection.next_goal);
73
107
  }
74
108
  return await this.cleanup(), {
75
109
  status: "error",
@@ -115,8 +149,28 @@ class u {
115
149
  })
116
150
  });
117
151
  if (!o.ok) {
118
- const r = await o.json().catch(() => ({ detail: "Unknown error" }));
119
- throw new Error(r.detail || `Failed to process step: ${o.status}`);
152
+ const s = await o.json().catch(() => ({ detail: "Unknown error" }));
153
+ throw new Error(s.detail || `Failed to process step: ${o.status}`);
154
+ }
155
+ return o.json();
156
+ }
157
+ /**
158
+ * Submit user's response to an ask_user question
159
+ */
160
+ async submitUserResponse(t, e) {
161
+ const o = await fetch(`${this.config.apiUrl}/api/browser-use/user-response`, {
162
+ method: "POST",
163
+ headers: { "Content-Type": "application/json" },
164
+ body: JSON.stringify({
165
+ session_id: this.sessionId,
166
+ product_id: this.config.productId,
167
+ user_response: t,
168
+ browser_state: e
169
+ })
170
+ });
171
+ if (!o.ok) {
172
+ const s = await o.json().catch(() => ({ detail: "Unknown error" }));
173
+ throw new Error(s.detail || `Failed to submit user response: ${o.status}`);
120
174
  }
121
175
  return o.json();
122
176
  }
@@ -124,45 +178,45 @@ class u {
124
178
  * Execute an action using PageController
125
179
  */
126
180
  async executeAction(t, e) {
127
- const o = Object.keys(e)[0], r = e[o];
181
+ const o = Object.keys(e)[0], s = e[o];
128
182
  try {
129
183
  switch (o) {
130
184
  case "click_element_by_index":
131
- return (await t.clickElement(r.index)).message;
185
+ return (await t.clickElement(s.index)).message;
132
186
  case "input_text":
133
187
  return (await t.inputText(
134
- r.index,
135
- r.text
188
+ s.index,
189
+ s.text
136
190
  )).message;
137
191
  case "select_dropdown_option":
138
192
  return (await t.selectOption(
139
- r.index,
140
- r.text
193
+ s.index,
194
+ s.text
141
195
  )).message;
142
196
  case "scroll":
143
197
  return (await t.scroll({
144
- down: r.down,
145
- numPages: r.num_pages,
146
- pixels: r.pixels,
147
- index: r.index
198
+ down: s.down,
199
+ numPages: s.num_pages,
200
+ pixels: s.pixels,
201
+ index: s.index
148
202
  })).message;
149
203
  case "scroll_horizontally":
150
204
  return (await t.scrollHorizontally({
151
- right: r.right,
152
- pixels: r.pixels,
153
- index: r.index
205
+ right: s.right,
206
+ pixels: s.pixels,
207
+ index: s.index
154
208
  })).message;
155
209
  case "wait": {
156
- const s = r.seconds || 1;
157
- return await new Promise((a) => setTimeout(a, s * 1e3)), `Waited ${s} seconds`;
210
+ const n = s.seconds || 1;
211
+ return await new Promise((a) => setTimeout(a, n * 1e3)), `Waited ${n} seconds`;
158
212
  }
159
213
  case "done":
160
214
  return "Task completed";
161
215
  default:
162
216
  return `Unknown action: ${o}`;
163
217
  }
164
- } catch (s) {
165
- return `Action failed: ${s instanceof Error ? s.message : String(s)}`;
218
+ } catch (n) {
219
+ return `Action failed: ${n instanceof Error ? n.message : String(n)}`;
166
220
  }
167
221
  }
168
222
  /**
@@ -200,6 +254,6 @@ class u {
200
254
  }
201
255
  }
202
256
  export {
203
- u as C,
204
- w as s
257
+ h as C,
258
+ d as s
205
259
  };
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("./browserUse-BOc9kyBK.cjs");class _{constructor(){this.state={token:null,metadata:{},isVerified:!1},this.listeners=new Set}identify(e){const{token:t,...s}=e;this.state={token:t,metadata:s,isVerified:!1},this.notify(),console.log("[Crow] User identified")}setVerified(e){this.state={...this.state,isVerified:e},this.notify()}reset(){this.state={token:null,metadata:{},isVerified:!1},this.notify(),console.log("[Crow] User reset")}getToken(){return this.state.token}getState(){return{...this.state}}isIdentified(){return this.state.token!==null}isVerified(){return this.state.isVerified}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){const e=this.getState();for(const t of this.listeners)t(e)}}class k{constructor(){this.handlers={}}register(e){for(const[t,s]of Object.entries(e))typeof s=="function"?(this.handlers[t]=s,console.log(`[Crow] Registered client tool: ${t}`)):console.warn(`[Crow] Skipping ${t}: handler is not a function`)}unregister(e){delete this.handlers[e],console.log(`[Crow] Unregistered client tool: ${e}`)}has(e){return e in this.handlers}getRegisteredTools(){return Object.keys(this.handlers)}async execute(e,t){const s=this.handlers[e];if(!s)return console.warn(`[Crow] No handler registered for tool: ${e}`),{status:"error",error:`No handler registered for tool: ${e}`};try{console.log(`[Crow] Executing client tool: ${e}`,t);const r=await s(t);return console.log(`[Crow] Tool ${e} completed:`,r),r}catch(r){const i=r instanceof Error?r.message:String(r);return console.error(`[Crow] Tool ${e} failed:`,r),{status:"error",error:i}}}}const T="crow_conv_";class C{constructor(e,t){this.currentId=null,this.productId=e,this.apiUrl=t,this.currentId=this.loadFromStorage()}getStorageKey(){return`${T}${this.productId}`}loadFromStorage(){try{return localStorage.getItem(this.getStorageKey())}catch{return null}}saveToStorage(e){try{localStorage.setItem(this.getStorageKey(),e)}catch{}}clearStorage(){try{localStorage.removeItem(this.getStorageKey())}catch{}}getCurrentId(){return this.currentId}setCurrentId(e){this.currentId=e,e?this.saveToStorage(e):this.clearStorage()}hasRestoredConversation(){return this.currentId!==null}clear(){this.currentId=null,this.clearStorage()}async getConversations(e){try{const t=await fetch(`${this.apiUrl}/api/chat/conversations?product_id=${this.productId}&identity_token=${encodeURIComponent(e)}`);if(!t.ok)throw new Error(`HTTP error: ${t.status}`);return(await t.json()).conversations||[]}catch(t){return console.error("[Crow] Failed to load conversations:",t),[]}}async loadHistory(e,t){try{const s=await fetch(`${this.apiUrl}/api/chat/conversations/${e}/history?product_id=${this.productId}&identity_token=${encodeURIComponent(t)}`);if(!s.ok)throw new Error(`HTTP error: ${s.status}`);const r=await s.json();return this.parseHistoryMessages(r.messages||[])}catch(s){return console.error("[Crow] Failed to load conversation history:",s),[]}}async loadAnonymousHistory(e){try{const t=await fetch(`${this.apiUrl}/api/chat/conversations/${e}/history/anonymous?product_id=${this.productId}`);if(!t.ok)throw new Error(`HTTP error: ${t.status}`);const s=await t.json();return this.parseHistoryMessages(s.messages||[])}catch(t){return console.error("[Crow] Failed to load anonymous conversation history:",t),[]}}parseHistoryMessages(e){return e.filter(t=>t.role!=="tool"&&!t.content.startsWith("[Client Tool Result:")).map((t,s)=>({id:`history-${s}`,content:this.parseContent(t.content),role:t.role==="assistant"?"assistant":"user",timestamp:new Date}))}parseContent(e){try{const t=JSON.parse(e);if(Array.isArray(t)){const s=t.find(r=>r.type==="text");return(s==null?void 0:s.text)||e}}catch{}if(e.includes("'type': 'text'")){const t=e.match(/\{'text':\s*'((?:[^'\\]|\\.)*)'\s*,\s*'type':\s*'text'/);if(t)return t[1].replace(/\\n/g,`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("./browserUse-CMYea2D_.cjs");class _{constructor(){this.state={token:null,metadata:{},isVerified:!1},this.listeners=new Set}identify(e){const{token:t,...s}=e;this.state={token:t,metadata:s,isVerified:!1},this.notify(),console.log("[Crow] User identified")}setVerified(e){this.state={...this.state,isVerified:e},this.notify()}reset(){this.state={token:null,metadata:{},isVerified:!1},this.notify(),console.log("[Crow] User reset")}getToken(){return this.state.token}getState(){return{...this.state}}isIdentified(){return this.state.token!==null}isVerified(){return this.state.isVerified}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){const e=this.getState();for(const t of this.listeners)t(e)}}class k{constructor(){this.handlers={}}register(e){for(const[t,s]of Object.entries(e))typeof s=="function"?(this.handlers[t]=s,console.log(`[Crow] Registered client tool: ${t}`)):console.warn(`[Crow] Skipping ${t}: handler is not a function`)}unregister(e){delete this.handlers[e],console.log(`[Crow] Unregistered client tool: ${e}`)}has(e){return e in this.handlers}getRegisteredTools(){return Object.keys(this.handlers)}async execute(e,t){const s=this.handlers[e];if(!s)return console.warn(`[Crow] No handler registered for tool: ${e}`),{status:"error",error:`No handler registered for tool: ${e}`};try{console.log(`[Crow] Executing client tool: ${e}`,t);const r=await s(t);return console.log(`[Crow] Tool ${e} completed:`,r),r}catch(r){const i=r instanceof Error?r.message:String(r);return console.error(`[Crow] Tool ${e} failed:`,r),{status:"error",error:i}}}}const T="crow_conv_";class C{constructor(e,t){this.currentId=null,this.productId=e,this.apiUrl=t,this.currentId=this.loadFromStorage()}getStorageKey(){return`${T}${this.productId}`}loadFromStorage(){try{return localStorage.getItem(this.getStorageKey())}catch{return null}}saveToStorage(e){try{localStorage.setItem(this.getStorageKey(),e)}catch{}}clearStorage(){try{localStorage.removeItem(this.getStorageKey())}catch{}}getCurrentId(){return this.currentId}setCurrentId(e){this.currentId=e,e?this.saveToStorage(e):this.clearStorage()}hasRestoredConversation(){return this.currentId!==null}clear(){this.currentId=null,this.clearStorage()}async getConversations(e){try{const t=await fetch(`${this.apiUrl}/api/chat/conversations?product_id=${this.productId}&identity_token=${encodeURIComponent(e)}`);if(!t.ok)throw new Error(`HTTP error: ${t.status}`);return(await t.json()).conversations||[]}catch(t){return console.error("[Crow] Failed to load conversations:",t),[]}}async loadHistory(e,t){try{const s=await fetch(`${this.apiUrl}/api/chat/conversations/${e}/history?product_id=${this.productId}&identity_token=${encodeURIComponent(t)}`);if(!s.ok)throw new Error(`HTTP error: ${s.status}`);const r=await s.json();return this.parseHistoryMessages(r.messages||[])}catch(s){return console.error("[Crow] Failed to load conversation history:",s),[]}}async loadAnonymousHistory(e){try{const t=await fetch(`${this.apiUrl}/api/chat/conversations/${e}/history/anonymous?product_id=${this.productId}`);if(!t.ok)throw new Error(`HTTP error: ${t.status}`);const s=await t.json();return this.parseHistoryMessages(s.messages||[])}catch(t){return console.error("[Crow] Failed to load anonymous conversation history:",t),[]}}parseHistoryMessages(e){return e.filter(t=>t.role!=="tool"&&!t.content.startsWith("[Client Tool Result:")).map((t,s)=>({id:`history-${s}`,content:this.parseContent(t.content),role:t.role==="assistant"?"assistant":"user",timestamp:new Date}))}parseContent(e){try{const t=JSON.parse(e);if(Array.isArray(t)){const s=t.find(r=>r.type==="text");return(s==null?void 0:s.text)||e}}catch{}if(e.includes("'type': 'text'")){const t=e.match(/\{'text':\s*'((?:[^'\\]|\\.)*)'\s*,\s*'type':\s*'text'/);if(t)return t[1].replace(/\\n/g,`
2
2
  `).replace(/\\'/g,"'")}return e}}function M(n){if(n==="[DONE]")return{type:"done"};try{const e=JSON.parse(n);switch(e.type){case"verification_status":return{type:"verification_status",isVerified:e.is_verified===!0};case"conversation_id":return{type:"conversation_id",conversationId:e.conversation_id};case"thinking":return e.status==="complete"?{type:"thinking_complete"}:null;case"thinking_token":return{type:"thinking",content:e.content||""};case"content":return{type:"content",text:e.content||"",accumulated:""};case"citations":return{type:"citations",citations:e.citations};case"error":return{type:"error",message:e.message||"Unknown error"};case"tool_call_start":return{type:"tool_call_start",toolName:e.tool_name,arguments:e.arguments||{}};case"tool_call_complete":return{type:"tool_call_complete",toolName:e.tool_name,success:e.success};case"client_tool_call":return{type:"client_tool_call",toolName:e.tool_name,arguments:e.arguments||{}};case"workflow_started":return{type:"workflow_started",name:e.name,todos:e.todos};case"todo_updated":return{type:"workflow_todo_updated",todoId:e.id,status:e.status};case"workflow_ended":return{type:"workflow_ended"};case"workflow_complete_prompt":return{type:"workflow_complete_prompt"};default:return null}}catch{return console.error("[Crow] Failed to parse SSE data:",n),null}}function*b(n){const e=n.split(`
3
3
  `);for(const t of e)t.startsWith("data: ")&&(yield t.slice(6).trim())}async function*S(n,e){var i;const t=(i=n.body)==null?void 0:i.getReader();if(!t)throw new Error("Response body is not readable");const s=new TextDecoder;let r="";try{for(;;){if(e!=null&&e.aborted){t.cancel();return}const{done:l,value:d}=await t.read();if(l)break;const h=s.decode(d);for(const u of b(h)){const c=M(u);if(c&&(c.type==="content"?(r+=c.text,yield{...c,accumulated:r}):yield c,c.type==="done"))return}}}finally{t.releaseLock()}}const g={refreshPage:async()=>{try{return window.location.reload(),{status:"success",data:{message:"Page refresh initiated"}}}catch(n){return{status:"error",error:String(n)}}}},v=Object.keys(g),E="https://api.usecrow.org",L="claude-sonnet-4-20250514";class ${constructor(e){this.context={},this.abortController=null,this.callbacks={},this._messages=[],this.messageListeners=new Set,this._isLoading=!1,this.loadingListeners=new Set,this.config={productId:e.productId,apiUrl:e.apiUrl||E,model:e.model||L},this.identity=new _,this.tools=new k,this.conversations=new C(this.config.productId,this.config.apiUrl),this.tools.register(g),console.log("[Crow] Default tools registered:",v.join(", ")),this.identity.subscribe(t=>{var s,r;(r=(s=this.callbacks).onVerificationStatus)==null||r.call(s,t.isVerified)})}get productId(){return this.config.productId}get apiUrl(){return this.config.apiUrl}get model(){return this.config.model}set model(e){this.config.model=e}on(e){this.callbacks={...this.callbacks,...e}}identify(e){this.identity.identify(e)}resetUser(){this.identity.reset(),this.clearMessages()}isIdentified(){return this.identity.isIdentified()}isVerified(){return this.identity.isVerified()}registerTools(e){this.tools.register(e)}unregisterTool(e){this.tools.unregister(e)}getRegisteredTools(){return this.tools.getRegisteredTools()}setContext(e){this.context={...this.context,...e}}clearContext(){this.context={}}get messages(){return[...this._messages]}get isLoading(){return this._isLoading}onMessages(e){return this.messageListeners.add(e),()=>this.messageListeners.delete(e)}onLoading(e){return this.loadingListeners.add(e),()=>this.loadingListeners.delete(e)}clearMessages(){this._messages=[],this.conversations.clear(),this.notifyMessages()}loadMessages(e){this._messages=e,this.notifyMessages()}notifyMessages(){const e=this.messages;for(const t of this.messageListeners)t(e)}setLoading(e){this._isLoading=e;for(const t of this.loadingListeners)t(e)}addMessage(e){var t,s;this._messages=[...this._messages,e],this.notifyMessages(),(s=(t=this.callbacks).onMessage)==null||s.call(t,e)}updateMessage(e,t){var s,r;this._messages=this._messages.map(i=>i.id===e?{...i,...t}:i),this.notifyMessages(),(r=(s=this.callbacks).onMessageUpdate)==null||r.call(s,e,t)}generateMessageId(e){return`${e}-${Date.now()}-${Math.random().toString(36).slice(2,9)}`}get conversationId(){return this.conversations.getCurrentId()}set conversationId(e){this.conversations.setCurrentId(e)}async getConversations(){const e=this.identity.getToken();return e?this.conversations.getConversations(e):(console.warn("[Crow] Cannot get conversations: user not identified"),[])}async loadHistory(e){const t=this.identity.getToken();return t?this.conversations.loadHistory(e,t):this.conversations.loadAnonymousHistory(e)}async switchConversation(e){const t=await this.loadHistory(e);this.conversations.setCurrentId(e),this.loadMessages(t)}async*sendMessage(e){var l,d,h,u,c,f,p,y,m,w;if(!e.trim())return;const t=this.generateMessageId("user");this.addMessage({id:t,content:e,role:"user",timestamp:new Date});const s=this.generateMessageId("assistant");this.addMessage({id:s,content:"",role:"assistant",timestamp:new Date}),this.setLoading(!0),this.abortController=new AbortController;let r="",i="";try{const a=await fetch(`${this.config.apiUrl}/api/chat/message`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({product_id:this.config.productId,message:e,conversation_id:this.conversations.getCurrentId(),identity_token:this.identity.getToken(),model:this.config.model,context:Object.keys(this.context).length>0?this.context:void 0}),signal:this.abortController.signal});if(!a.ok)throw new Error(`HTTP error: ${a.status}`);for await(const o of S(a,this.abortController.signal)){switch(o.type){case"content":r=o.accumulated,this.updateMessage(s,{content:r});break;case"thinking":i+=o.content,this.updateMessage(s,{thinking:i});break;case"thinking_complete":this.updateMessage(s,{thinkingComplete:!0});break;case"citations":this.updateMessage(s,{citations:o.citations});break;case"verification_status":this.identity.setVerified(o.isVerified);break;case"conversation_id":this.conversations.setCurrentId(o.conversationId);break;case"client_tool_call":await this.tools.execute(o.toolName,o.arguments),(d=(l=this.callbacks).onToolCall)==null||d.call(l,o);break;case"tool_call_start":case"tool_call_complete":(u=(h=this.callbacks).onToolCall)==null||u.call(h,o);break;case"workflow_started":case"workflow_todo_updated":case"workflow_ended":case"workflow_complete_prompt":(f=(c=this.callbacks).onWorkflow)==null||f.call(c,o);break;case"error":this.updateMessage(s,{content:o.message}),(y=(p=this.callbacks).onError)==null||y.call(p,new Error(o.message));break}yield o}}catch(a){if(a instanceof Error&&a.name==="AbortError"){r?this.updateMessage(s,{content:r}):(this._messages=this._messages.filter(o=>o.id!==s),this.notifyMessages());return}console.error("[Crow] Error:",a),this.updateMessage(s,{content:"Sorry, I encountered an error. Please try again."}),(w=(m=this.callbacks).onError)==null||w.call(m,a instanceof Error?a:new Error(String(a)))}finally{this.setLoading(!1),this.abortController=null}}async send(e){let t=null;for await(const r of this.sendMessage(e))if(r.type==="done")break;const s=this.messages;return s.length>0&&(t=s[s.length-1],t.role==="assistant")?t:null}stop(){this.abortController&&(this.abortController.abort(),this.setLoading(!1))}destroy(){this.stop(),this.messageListeners.clear(),this.loadingListeners.clear()}}exports.CrowBrowserUse=I.CrowBrowserUse;exports.ConversationManager=C;exports.CrowClient=$;exports.DEFAULT_TOOLS=g;exports.DEFAULT_TOOL_NAMES=v;exports.IdentityManager=_;exports.ToolManager=k;exports.parseSSEChunk=b;exports.parseSSEData=M;exports.streamResponse=S;
package/dist/index.d.ts CHANGED
@@ -7,6 +7,9 @@ export declare interface ActiveWorkflow {
7
7
  declare interface BrowserUseConfig {
8
8
  productId: string;
9
9
  apiUrl: string;
10
+ onConfirmation?: (instruction: string) => Promise<boolean>;
11
+ onQuestion?: (question: string) => Promise<string>;
12
+ onProgress?: (step: number, maxSteps: number, action?: string) => void;
10
13
  }
11
14
 
12
15
  export declare interface Citation {
@@ -112,6 +115,10 @@ export declare class CrowBrowserUse {
112
115
  * Process a step on the server
113
116
  */
114
117
  private processStep;
118
+ /**
119
+ * Submit user's response to an ask_user question
120
+ */
121
+ private submitUserResponse;
115
122
  /**
116
123
  * Execute an action using PageController
117
124
  */
@@ -283,6 +290,19 @@ export declare interface CrowEventCallbacks {
283
290
  }) => void;
284
291
  onVerificationStatus?: (isVerified: boolean) => void;
285
292
  onError?: (error: Error) => void;
293
+ onBrowserUseConfirmation?: (event: {
294
+ instruction: string;
295
+ toolCallId: string;
296
+ }) => Promise<boolean>;
297
+ onBrowserUseQuestion?: (event: {
298
+ question: string;
299
+ sessionId: string;
300
+ }) => Promise<string>;
301
+ onBrowserUseProgress?: (event: {
302
+ step: number;
303
+ maxSteps: number;
304
+ action?: string;
305
+ }) => void;
286
306
  }
287
307
 
288
308
  export declare const DEFAULT_TOOL_NAMES: DefaultToolName[];
@@ -424,6 +444,19 @@ export declare type StreamEvent = {
424
444
  message: string;
425
445
  } | {
426
446
  type: 'done';
447
+ } | {
448
+ type: 'browser_use_confirmation';
449
+ instruction: string;
450
+ toolCallId: string;
451
+ } | {
452
+ type: 'browser_use_question';
453
+ question: string;
454
+ sessionId: string;
455
+ } | {
456
+ type: 'browser_use_progress';
457
+ step: number;
458
+ maxSteps: number;
459
+ action?: string;
427
460
  };
428
461
 
429
462
  /**
@@ -460,7 +493,7 @@ export declare class ToolManager {
460
493
  }
461
494
 
462
495
  export declare interface ToolResult {
463
- status: 'success' | 'error';
496
+ status: 'success' | 'error' | 'needs_input';
464
497
  data?: unknown;
465
498
  error?: string;
466
499
  }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as x } from "./browserUse-BbPG4pH1.js";
1
+ import { C as x } from "./browserUse-CMq8wG4u.js";
2
2
  class _ {
3
3
  constructor() {
4
4
  this.state = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usecrow/client",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "description": "Headless client for Crow AI agents - streaming, auth, tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",