@usecrow/client 0.1.38 → 0.1.40
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/browser.cjs +1 -1
- package/dist/browser.js +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.d.ts +5 -0
- package/dist/index.js +10 -3
- package/dist/workflowExecutor-D1pVvfZw.cjs +1 -0
- package/dist/{workflowExecutor-DgghvBIA.js → workflowExecutor-ijFlX3nx.js} +14 -14
- package/package.json +1 -1
- package/dist/workflowExecutor-BUc7WzWF.cjs +0 -1
package/dist/browser.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./PageController-Cu6KUkcn.cjs"),i=require("./workflowExecutor-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./PageController-Cu6KUkcn.cjs"),i=require("./workflowExecutor-D1pVvfZw.cjs");i.setPageController(p.PageController);let w=null;function f(){w&&(console.log("[Crow] Stopping active browser-use automation"),w.stop(),w=null)}function _(c,a){return async n=>{const u=n.instruction||n.instruction;if(!u)return{status:"error",error:"Missing instruction parameter for browser_use tool"};const t=window.__crow_browser_callbacks,o=a||t,l=new i.CrowBrowserUse({productId:c.productId,apiUrl:c.apiUrl,onConfirmation:o==null?void 0:o.onConfirmation,onQuestion:o==null?void 0:o.onQuestion,onProgress:o==null?void 0:o.onProgress});w=l;try{return await l.execute(u)}finally{w=null}}}function m(c){return async a=>{const n=a.workflow_name||a.workflow_name,u=a.inputs||a.inputs||{};if(!n)return{status:"error",error:"Missing workflow_name parameter for execute_recorded_workflow tool"};console.log(`[Crow] execute_recorded_workflow: Looking up "${n}"...`);try{const t=await fetch(`${c.apiUrl}/api/products/${c.productId}/recorded-workflows`);if(!t.ok)return{status:"error",error:`Failed to fetch recorded workflows: HTTP ${t.status}`};const o=await t.json(),l=o.find(s=>s.name.toLowerCase()===n.toLowerCase()&&s.enabled);if(!l){const s=o.filter(r=>r.enabled).map(r=>r.name);return{status:"error",error:`Workflow "${n}" not found. Available workflows: ${s.join(", ")||"none"}`}}console.log(`[Crow] execute_recorded_workflow: Found "${l.name}" with ${l.steps.length} steps`);const d=new p.PageController;await d.updateTree();const e=await new i.WorkflowExecutor(d,{waitTimeout:5e3,pollInterval:300,stepDelay:500,stopOnFailure:!0,onStepProgress:s=>{const r=s.success?"OK":"FAILED";console.log(`[Crow] Workflow step ${s.step_index+1}: [${r}] ${s.description}`)}}).execute(l,u);if(e.success)return{status:"success",data:{workflow_name:e.workflow_name,total_steps:e.total_steps,completed_steps:e.completed_steps,message:`Workflow "${e.workflow_name}" completed successfully (${e.completed_steps}/${e.total_steps} steps)`}};{const s=e.step_results.filter(r=>!r.success).map(r=>`Step ${r.step_index+1} (${r.step_type}): ${r.message}`);return{status:"error",error:`Workflow "${e.workflow_name}" failed. ${e.completed_steps}/${e.total_steps} steps completed. Failures:
|
|
2
2
|
${s.join(`
|
|
3
3
|
`)}`}}}catch(t){return console.error("[Crow] execute_recorded_workflow error:",t),{status:"error",error:`Workflow execution error: ${t instanceof Error?t.message:String(t)}`}}}}exports.PageController=p.PageController;exports.CrowBrowserUse=i.CrowBrowserUse;exports.createBrowserUseTool=_;exports.createExecuteRecordedWorkflowTool=m;exports.stopActiveBrowserUse=f;
|
package/dist/browser.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("./workflowExecutor-
|
|
2
|
-
`).replace(/\\'/g,"'")}return e}}function b(o){if(o==="[DONE]")return{type:"done"};try{const e=JSON.parse(o);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,displayName:e.display_name||void 0,arguments:e.arguments||{}};case"tool_call_complete":return{type:"tool_call_complete",toolName:e.tool_name,displayName:e.display_name||void 0,success:e.success};case"client_tool_call":return{type:"client_tool_call",toolName:e.tool_name,displayName:e.display_name||void 0,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:",o),null}}function*M(o){const e=o.split(`
|
|
3
|
-
`);for(const t of e)t.startsWith("data: ")&&(yield t.slice(6).trim())}async function*S(o,e){var n;const t=(n=o.body)==null?void 0:n.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:i,value:d}=await t.read();if(i)break;const u=s.decode(d);for(const h of M(u)){const l=b(h);if(l&&(l.type==="content"?(r+=l.text,yield{...l,accumulated:r}):yield l,l.type==="done"))return}}}finally{t.releaseLock()}}async function L(){try{return window.location.reload(),{status:"success",data:{refreshed:!0}}}catch(o){return{status:"error",error:o instanceof Error?o.message:"Failed to refresh page"}}}async function $(){var o;try{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();return{status:"success",data:{title:e,url:t,pathname:s,visibleText:r}}}catch(e){return{status:"error",error:e instanceof Error?e.message:"Failed to read screen"}}}const g={refreshPage:L,whatsOnScreen:$},T=Object.keys(g),U="https://api.usecrow.org",x="claude-sonnet-4-20250514";class O{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||U,model:e.model||x},this.identity=new k,this.tools=new v,this.conversations=new C(this.config.productId,this.config.apiUrl),this.tools.register(g),console.log("[Crow] Default tools registered:",T.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(n=>n.id===e?{...n,...t}:n),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 i,d,u,h,l,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="",n="";try{const c=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(!c.ok)throw new Error(`HTTP error: ${c.status}`);for await(const a of S(c,this.abortController.signal)){switch(a.type){case"content":r=a.accumulated,this.updateMessage(s,{content:r});break;case"thinking":n+=a.content,this.updateMessage(s,{thinking:n});break;case"thinking_complete":this.updateMessage(s,{thinkingComplete:!0});break;case"citations":this.updateMessage(s,{citations:a.citations});break;case"verification_status":this.identity.setVerified(a.isVerified);break;case"conversation_id":this.conversations.setCurrentId(a.conversationId);break;case"client_tool_call":await this.tools.execute(a.toolName,a.arguments),(d=(i=this.callbacks).onToolCall)==null||d.call(i,a);break;case"tool_call_start":case"tool_call_complete":(h=(u=this.callbacks).onToolCall)==null||h.call(u,a);break;case"workflow_started":case"workflow_todo_updated":case"workflow_ended":case"workflow_complete_prompt":(f=(l=this.callbacks).onWorkflow)==null||f.call(l,a);break;case"error":this.updateMessage(s,{content:a.message}),(y=(p=this.callbacks).onError)==null||y.call(p,new Error(a.message));break}yield a}}catch(c){if(c instanceof Error&&c.name==="AbortError"){r?this.updateMessage(s,{content:r}):(this._messages=this._messages.filter(a=>a.id!==s),this.notifyMessages());return}console.error("[Crow] Error:",c),this.updateMessage(s,{content:"Sorry, I encountered an error. Please try again."}),(w=(m=this.callbacks).onError)==null||w.call(m,c instanceof Error?c:new Error(String(c)))}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()}}function I(o,e,t){const s=o.find(n=>n.name.toLowerCase()===e.toLowerCase());if(!s)return null;let r=s.path;if(t)for(const[n,i]of Object.entries(t))r=r.replace(`:${n}`,String(i));return r}function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("./workflowExecutor-D1pVvfZw.cjs");class k{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 v{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 n=r instanceof Error?r.message:String(r);return console.error(`[Crow] Tool ${e} failed:`,r),{status:"error",error:n}}}}const E="crow_conv_";class C{constructor(e,t){this.currentId=null,this.productId=e,this.apiUrl=t,this.currentId=this.loadFromStorage()}getStorageKey(){return`${E}${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
|
+
`).replace(/\\'/g,"'")}return e}}function b(o){if(o==="[DONE]")return{type:"done"};try{const e=JSON.parse(o);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,displayName:e.display_name||void 0,arguments:e.arguments||{}};case"tool_call_complete":return{type:"tool_call_complete",toolName:e.tool_name,displayName:e.display_name||void 0,success:e.success};case"client_tool_call":return{type:"client_tool_call",toolName:e.tool_name,displayName:e.display_name||void 0,arguments:e.arguments||{}};case"tool_consent_required":return{type:"tool_consent_required",toolName:e.tool_name,displayName:e.display_name||void 0,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:",o),null}}function*M(o){const e=o.split(`
|
|
3
|
+
`);for(const t of e)t.startsWith("data: ")&&(yield t.slice(6).trim())}async function*S(o,e){var n;const t=(n=o.body)==null?void 0:n.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:i,value:d}=await t.read();if(i)break;const u=s.decode(d);for(const h of M(u)){const l=b(h);if(l&&(l.type==="content"?(r+=l.text,yield{...l,accumulated:r}):yield l,l.type==="done"))return}}}finally{t.releaseLock()}}async function L(){try{return window.location.reload(),{status:"success",data:{refreshed:!0}}}catch(o){return{status:"error",error:o instanceof Error?o.message:"Failed to refresh page"}}}async function $(){var o;try{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();return{status:"success",data:{title:e,url:t,pathname:s,visibleText:r}}}catch(e){return{status:"error",error:e instanceof Error?e.message:"Failed to read screen"}}}const g={refreshPage:L,whatsOnScreen:$},T=Object.keys(g),U="https://api.usecrow.org",x="claude-sonnet-4-20250514";class O{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||U,model:e.model||x},this.identity=new k,this.tools=new v,this.conversations=new C(this.config.productId,this.config.apiUrl),this.tools.register(g),console.log("[Crow] Default tools registered:",T.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(n=>n.id===e?{...n,...t}:n),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 i,d,u,h,l,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="",n="";try{const c=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(!c.ok)throw new Error(`HTTP error: ${c.status}`);for await(const a of S(c,this.abortController.signal)){switch(a.type){case"content":r=a.accumulated,this.updateMessage(s,{content:r});break;case"thinking":n+=a.content,this.updateMessage(s,{thinking:n});break;case"thinking_complete":this.updateMessage(s,{thinkingComplete:!0});break;case"citations":this.updateMessage(s,{citations:a.citations});break;case"verification_status":this.identity.setVerified(a.isVerified);break;case"conversation_id":this.conversations.setCurrentId(a.conversationId);break;case"client_tool_call":await this.tools.execute(a.toolName,a.arguments),(d=(i=this.callbacks).onToolCall)==null||d.call(i,a);break;case"tool_call_start":case"tool_call_complete":(h=(u=this.callbacks).onToolCall)==null||h.call(u,a);break;case"workflow_started":case"workflow_todo_updated":case"workflow_ended":case"workflow_complete_prompt":(f=(l=this.callbacks).onWorkflow)==null||f.call(l,a);break;case"error":this.updateMessage(s,{content:a.message}),(y=(p=this.callbacks).onError)==null||y.call(p,new Error(a.message));break}yield a}}catch(c){if(c instanceof Error&&c.name==="AbortError"){r?this.updateMessage(s,{content:r}):(this._messages=this._messages.filter(a=>a.id!==s),this.notifyMessages());return}console.error("[Crow] Error:",c),this.updateMessage(s,{content:"Sorry, I encountered an error. Please try again."}),(w=(m=this.callbacks).onError)==null||w.call(m,c instanceof Error?c:new Error(String(c)))}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()}}function I(o,e,t){const s=o.find(n=>n.name.toLowerCase()===e.toLowerCase());if(!s)return null;let r=s.path;if(t)for(const[n,i]of Object.entries(t))r=r.replace(`:${n}`,String(i));return r}function N(o,e){return async t=>{try{const s=t.page,r=t.params,n=t.url;let i=null;if(s){if(i=I(o,s,r),!i)return{status:"error",error:`Unknown page: "${s}". Available pages: ${o.map(u=>u.name).join(", ")}`}}else if(n)i=n;else return{status:"error",error:'Either "page" or "url" parameter is required'};const d=i.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g);return d?{status:"error",error:`Missing parameters: ${d.join(", ")}. Please provide values for these parameters.`}:e?(e(i),{status:"success",data:{navigated_to:i,page:s||void 0,method:"spa_router"}}):(window.location.href=i,{status:"success",data:{navigated_to:i,page:s||void 0,method:"full_navigation"}})}catch(s){return{status:"error",error:String(s)}}}}exports.CrowBrowserUse=_.CrowBrowserUse;exports.WorkflowExecutor=_.WorkflowExecutor;exports.ConversationManager=C;exports.CrowClient=O;exports.DEFAULT_TOOLS=g;exports.DEFAULT_TOOL_NAMES=T;exports.IdentityManager=k;exports.ToolManager=v;exports.createNavigateToPageTool=N;exports.parseSSEChunk=M;exports.parseSSEData=b;exports.resolveRoute=I;exports.streamResponse=S;
|
package/dist/index.d.ts
CHANGED
|
@@ -786,6 +786,11 @@ export declare type StreamEvent = {
|
|
|
786
786
|
toolName: string;
|
|
787
787
|
displayName?: string;
|
|
788
788
|
arguments: Record<string, unknown>;
|
|
789
|
+
} | {
|
|
790
|
+
type: 'tool_consent_required';
|
|
791
|
+
toolName: string;
|
|
792
|
+
displayName?: string;
|
|
793
|
+
arguments: Record<string, unknown>;
|
|
789
794
|
} | {
|
|
790
795
|
type: 'workflow_started';
|
|
791
796
|
name: string;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as R, W as D } from "./workflowExecutor-
|
|
1
|
+
import { C as R, W as D } from "./workflowExecutor-ijFlX3nx.js";
|
|
2
2
|
class _ {
|
|
3
3
|
constructor() {
|
|
4
4
|
this.state = {
|
|
@@ -330,6 +330,13 @@ function b(o) {
|
|
|
330
330
|
displayName: e.display_name || void 0,
|
|
331
331
|
arguments: e.arguments || {}
|
|
332
332
|
};
|
|
333
|
+
case "tool_consent_required":
|
|
334
|
+
return {
|
|
335
|
+
type: "tool_consent_required",
|
|
336
|
+
toolName: e.tool_name,
|
|
337
|
+
displayName: e.display_name || void 0,
|
|
338
|
+
arguments: e.arguments || {}
|
|
339
|
+
};
|
|
333
340
|
case "workflow_started":
|
|
334
341
|
return {
|
|
335
342
|
type: "workflow_started",
|
|
@@ -758,7 +765,7 @@ function x(o, e, t) {
|
|
|
758
765
|
r = r.replace(`:${n}`, String(i));
|
|
759
766
|
return r;
|
|
760
767
|
}
|
|
761
|
-
function
|
|
768
|
+
function N(o, e) {
|
|
762
769
|
return async (t) => {
|
|
763
770
|
try {
|
|
764
771
|
const s = t.page, r = t.params, n = t.url;
|
|
@@ -812,7 +819,7 @@ export {
|
|
|
812
819
|
_ as IdentityManager,
|
|
813
820
|
k as ToolManager,
|
|
814
821
|
D as WorkflowExecutor,
|
|
815
|
-
|
|
822
|
+
N as createNavigateToPageTool,
|
|
816
823
|
I as parseSSEChunk,
|
|
817
824
|
b as parseSSEData,
|
|
818
825
|
x as resolveRoute,
|
|
@@ -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;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
let m = null, f = null;
|
|
2
|
-
function
|
|
2
|
+
function P(g) {
|
|
3
3
|
m = g;
|
|
4
4
|
}
|
|
5
|
-
async function
|
|
5
|
+
async function E() {
|
|
6
6
|
if (m)
|
|
7
7
|
return m;
|
|
8
8
|
if (!f)
|
|
@@ -26,7 +26,7 @@ class $ {
|
|
|
26
26
|
if (this.pageController)
|
|
27
27
|
return this.pageController;
|
|
28
28
|
try {
|
|
29
|
-
const e = await
|
|
29
|
+
const e = await E();
|
|
30
30
|
this.pageController = new e({
|
|
31
31
|
enableMask: !0,
|
|
32
32
|
viewportExpansion: 500,
|
|
@@ -47,7 +47,7 @@ class $ {
|
|
|
47
47
|
* Execute a browser automation task
|
|
48
48
|
*/
|
|
49
49
|
async execute(e) {
|
|
50
|
-
var o, s, t, r, n, h,
|
|
50
|
+
var o, s, t, r, n, h, p, l, x, y, C, _, S, U;
|
|
51
51
|
if (console.log("[CrowBrowserUse] Starting task:", e), this.config.onConfirmation && !await this.config.onConfirmation(e))
|
|
52
52
|
return console.log("[CrowBrowserUse] User declined browser automation"), (s = (o = this.config).onProgress) == null || s.call(o, -1, this.maxSteps), {
|
|
53
53
|
status: "error",
|
|
@@ -57,14 +57,14 @@ class $ {
|
|
|
57
57
|
try {
|
|
58
58
|
const a = await this.initPageController(), b = await this.startSession(e);
|
|
59
59
|
this.sessionId = b.session_id, this.maxSteps = b.max_steps, console.log("[CrowBrowserUse] Session started:", this.sessionId);
|
|
60
|
-
let
|
|
61
|
-
for (;
|
|
60
|
+
let u = 0, c;
|
|
61
|
+
for (; u < this.maxSteps; ) {
|
|
62
62
|
if (this.aborted)
|
|
63
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
64
|
status: "error",
|
|
65
65
|
error: "Task cancelled by user"
|
|
66
66
|
};
|
|
67
|
-
|
|
67
|
+
u++;
|
|
68
68
|
const v = await a.getBrowserState(), d = a.mask;
|
|
69
69
|
d != null && d.wrapper && (d.wrapper.style.pointerEvents = "none");
|
|
70
70
|
const i = await this.processStep(v, c);
|
|
@@ -86,11 +86,11 @@ class $ {
|
|
|
86
86
|
continue;
|
|
87
87
|
}
|
|
88
88
|
if (i.done)
|
|
89
|
-
return console.log("[CrowBrowserUse] Task completed:", i.message), await this.cleanup(), (l = (
|
|
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
90
|
status: i.success ? "success" : "error",
|
|
91
91
|
data: {
|
|
92
92
|
message: i.message,
|
|
93
|
-
steps:
|
|
93
|
+
steps: u
|
|
94
94
|
},
|
|
95
95
|
error: i.success ? void 0 : i.message
|
|
96
96
|
};
|
|
@@ -99,7 +99,7 @@ class $ {
|
|
|
99
99
|
status: "error",
|
|
100
100
|
error: i.error
|
|
101
101
|
};
|
|
102
|
-
i.action && (c = await this.executeAction(a, i.action), console.log(`[CrowBrowserUse] Step ${
|
|
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
103
|
}
|
|
104
104
|
return await this.cleanup(), (_ = (C = this.config).onProgress) == null || _.call(C, -1, this.maxSteps), {
|
|
105
105
|
status: "error",
|
|
@@ -248,9 +248,9 @@ class T {
|
|
|
248
248
|
let t = 0;
|
|
249
249
|
console.log(`[WorkflowExecutor] Starting workflow: ${e.name} (${e.steps.length} steps)`);
|
|
250
250
|
for (let n = 0; n < e.steps.length; n++) {
|
|
251
|
-
const h = e.steps[n],
|
|
252
|
-
console.log(`[WorkflowExecutor] Step ${n + 1}/${e.steps.length}: ${
|
|
253
|
-
const l = await this.executeStep(
|
|
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
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
255
|
return {
|
|
256
256
|
success: !1,
|
|
@@ -361,5 +361,5 @@ class T {
|
|
|
361
361
|
export {
|
|
362
362
|
$ as C,
|
|
363
363
|
T as W,
|
|
364
|
-
|
|
364
|
+
P as s
|
|
365
365
|
};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
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,u,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 p=0,c;for(;p<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"};p++;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=(u=this.config).onProgress)==null||l.call(u,p,this.maxSteps),{status:i.success?"success":"error",data:{message:i.message,steps:p},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),console.log(`[CrowBrowserUse] Step ${p}:`,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],u=this.resolveVariables(h,o);console.log(`[WorkflowExecutor] Step ${n+1}/${e.steps.length}: ${u.description}`);const l=await this.executeStep(u,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;
|