@usecrow/client 0.1.37 → 0.1.38

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 CHANGED
@@ -1 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("./PageController-Cu6KUkcn.cjs"),e=require("./browserUse-DYW8fqvT.cjs");e.setPageController(u.PageController);let o=null;function a(){o&&(console.log("[Crow] Stopping active browser-use automation"),o.stop(),o=null)}function c(t,l){return async n=>{const s=n.instruction||n.instruction;if(!s)return{status:"error",error:"Missing instruction parameter for browser_use tool"};const w=window.__crow_browser_callbacks,r=l||w,i=new e.CrowBrowserUse({productId:t.productId,apiUrl:t.apiUrl,onConfirmation:r==null?void 0:r.onConfirmation,onQuestion:r==null?void 0:r.onQuestion,onProgress:r==null?void 0:r.onProgress});o=i;try{return await i.execute(s)}finally{o=null}}}exports.PageController=u.PageController;exports.CrowBrowserUse=e.CrowBrowserUse;exports.createBrowserUseTool=c;exports.stopActiveBrowserUse=a;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./PageController-Cu6KUkcn.cjs"),i=require("./workflowExecutor-BUc7WzWF.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
+ ${s.join(`
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.d.ts CHANGED
@@ -69,6 +69,20 @@ declare function cleanUpHighlights(): void;
69
69
  */
70
70
  export declare function createBrowserUseTool(config: BrowserUseToolConfig, callbacks?: BrowserUseCallbacks): (args: BrowserUseToolArgs | Record<string, unknown>) => Promise<ToolResult>;
71
71
 
72
+ /**
73
+ * Create an execute_recorded_workflow tool handler for registration with CrowClient or widget.
74
+ *
75
+ * When the LLM calls this tool, the handler:
76
+ * 1. Fetches the workflow definition from the backend API (by name)
77
+ * 2. Creates a PageController and WorkflowExecutor
78
+ * 3. Executes the workflow steps deterministically (no LLM calls)
79
+ * 4. Returns the result
80
+ *
81
+ * @param config - Configuration with productId and apiUrl
82
+ * @returns Async function that executes recorded workflows
83
+ */
84
+ export declare function createExecuteRecordedWorkflowTool(config: BrowserUseToolConfig): (args: ExecuteRecordedWorkflowToolArgs | Record<string, unknown>) => Promise<ToolResult>;
85
+
72
86
  export declare class CrowBrowserUse {
73
87
  private config;
74
88
  private pageController;
@@ -143,6 +157,11 @@ declare interface ElementDomNode {
143
157
  [key: string]: unknown;
144
158
  }
145
159
 
160
+ export declare interface ExecuteRecordedWorkflowToolArgs {
161
+ workflow_name: string;
162
+ inputs?: Record<string, string | number | boolean>;
163
+ }
164
+
146
165
  /**
147
166
  * Derived from @page-agent/page-controller
148
167
  * Original: https://github.com/alibaba/page-agent
package/dist/browser.js CHANGED
@@ -1,36 +1,107 @@
1
- import { PageController as l } from "./PageController-D3uwrwlG.js";
2
- import { C as w, s as a } from "./browserUse-Cioetz2-.js";
3
- a(l);
4
- let r = null;
5
- function m() {
6
- r && (console.log("[Crow] Stopping active browser-use automation"), r.stop(), r = null);
1
+ import { PageController as p } from "./PageController-D3uwrwlG.js";
2
+ import { C as d, W as f, s as m } from "./workflowExecutor-DgghvBIA.js";
3
+ m(p);
4
+ let w = null;
5
+ function x() {
6
+ w && (console.log("[Crow] Stopping active browser-use automation"), w.stop(), w = null);
7
7
  }
8
- function U(n, i) {
9
- return async (t) => {
10
- const s = t.instruction || t.instruction;
11
- if (!s)
8
+ function g(c, a) {
9
+ return async (n) => {
10
+ const u = n.instruction || n.instruction;
11
+ if (!u)
12
12
  return {
13
13
  status: "error",
14
14
  error: "Missing instruction parameter for browser_use tool"
15
15
  };
16
- const u = window.__crow_browser_callbacks, o = i || u, e = new w({
17
- productId: n.productId,
18
- apiUrl: n.apiUrl,
16
+ const t = window.__crow_browser_callbacks, o = a || t, l = new d({
17
+ productId: c.productId,
18
+ apiUrl: c.apiUrl,
19
19
  onConfirmation: o == null ? void 0 : o.onConfirmation,
20
20
  onQuestion: o == null ? void 0 : o.onQuestion,
21
21
  onProgress: o == null ? void 0 : o.onProgress
22
22
  });
23
- r = e;
23
+ w = l;
24
24
  try {
25
- return await e.execute(s);
25
+ return await l.execute(u);
26
26
  } finally {
27
- r = null;
27
+ w = null;
28
+ }
29
+ };
30
+ }
31
+ function C(c) {
32
+ return async (a) => {
33
+ const n = a.workflow_name || a.workflow_name, u = a.inputs || a.inputs || {};
34
+ if (!n)
35
+ return {
36
+ status: "error",
37
+ error: "Missing workflow_name parameter for execute_recorded_workflow tool"
38
+ };
39
+ console.log(`[Crow] execute_recorded_workflow: Looking up "${n}"...`);
40
+ try {
41
+ const t = await fetch(
42
+ `${c.apiUrl}/api/products/${c.productId}/recorded-workflows`
43
+ );
44
+ if (!t.ok)
45
+ return {
46
+ status: "error",
47
+ error: `Failed to fetch recorded workflows: HTTP ${t.status}`
48
+ };
49
+ const o = await t.json(), l = o.find(
50
+ (s) => s.name.toLowerCase() === n.toLowerCase() && s.enabled
51
+ );
52
+ if (!l) {
53
+ const s = o.filter((r) => r.enabled).map((r) => r.name);
54
+ return {
55
+ status: "error",
56
+ error: `Workflow "${n}" not found. Available workflows: ${s.join(", ") || "none"}`
57
+ };
58
+ }
59
+ console.log(`[Crow] execute_recorded_workflow: Found "${l.name}" with ${l.steps.length} steps`);
60
+ const i = new p();
61
+ await i.updateTree();
62
+ const e = await new f(i, {
63
+ waitTimeout: 5e3,
64
+ pollInterval: 300,
65
+ stepDelay: 500,
66
+ stopOnFailure: !0,
67
+ onStepProgress: (s) => {
68
+ const r = s.success ? "OK" : "FAILED";
69
+ console.log(
70
+ `[Crow] Workflow step ${s.step_index + 1}: [${r}] ${s.description}`
71
+ );
72
+ }
73
+ }).execute(l, u);
74
+ if (e.success)
75
+ return {
76
+ status: "success",
77
+ data: {
78
+ workflow_name: e.workflow_name,
79
+ total_steps: e.total_steps,
80
+ completed_steps: e.completed_steps,
81
+ message: `Workflow "${e.workflow_name}" completed successfully (${e.completed_steps}/${e.total_steps} steps)`
82
+ }
83
+ };
84
+ {
85
+ const s = e.step_results.filter((r) => !r.success).map((r) => `Step ${r.step_index + 1} (${r.step_type}): ${r.message}`);
86
+ return {
87
+ status: "error",
88
+ error: `Workflow "${e.workflow_name}" failed. ${e.completed_steps}/${e.total_steps} steps completed. Failures:
89
+ ${s.join(`
90
+ `)}`
91
+ };
92
+ }
93
+ } catch (t) {
94
+ return console.error("[Crow] execute_recorded_workflow error:", t), {
95
+ status: "error",
96
+ error: `Workflow execution error: ${t instanceof Error ? t.message : String(t)}`
97
+ };
28
98
  }
29
99
  };
30
100
  }
31
101
  export {
32
- w as CrowBrowserUse,
33
- l as PageController,
34
- U as createBrowserUseTool,
35
- m as stopActiveBrowserUse
102
+ d as CrowBrowserUse,
103
+ p as PageController,
104
+ g as createBrowserUseTool,
105
+ C as createExecuteRecordedWorkflowTool,
106
+ x as stopActiveBrowserUse
36
107
  };
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("./browserUse-DYW8fqvT.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 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 o=r instanceof Error?r.message:String(r);return console.error(`[Crow] Tool ${e} failed:`,r),{status:"error",error:o}}}}const $="crow_conv_";class k{constructor(e,t){this.currentId=null,this.productId=e,this.apiUrl=t,this.currentId=this.loadFromStorage()}getStorageKey(){return`${$}${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 S(a){if(a==="[DONE]")return{type:"done"};try{const e=JSON.parse(a);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:",a),null}}function*C(a){const e=a.split(`
3
- `);for(const t of e)t.startsWith("data: ")&&(yield t.slice(6).trim())}async function*T(a,e){var o;const t=(o=a.body)==null?void 0:o.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:n,value:u}=await t.read();if(n)break;const d=s.decode(u);for(const l of C(d)){const h=S(l);if(h&&(h.type==="content"?(r+=h.text,yield{...h,accumulated:r}):yield h,h.type==="done"))return}}}finally{t.releaseLock()}}async function M(){try{return window.location.reload(),{status:"success",data:{refreshed:!0}}}catch(a){return{status:"error",error:a instanceof Error?a.message:"Failed to refresh page"}}}async function x(){var a;try{const e=document.title,t=window.location.href,s=window.location.pathname,r=(((a=document.body)==null?void 0:a.innerText)||"").slice(0,2e3).trim();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:M,whatsOnScreen:x},b=Object.keys(g),L="https://api.usecrow.org",U="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||L,model:e.model||U},this.identity=new _,this.tools=new v,this.conversations=new k(this.config.productId,this.config.apiUrl),this.tools.register(g),console.log("[Crow] Default tools registered:",b.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(o=>o.id===e?{...o,...t}:o),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 n,u,d,l,h,p,f,m,y,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="",o="";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 i of T(c,this.abortController.signal)){switch(i.type){case"content":r=i.accumulated,this.updateMessage(s,{content:r});break;case"thinking":o+=i.content,this.updateMessage(s,{thinking:o});break;case"thinking_complete":this.updateMessage(s,{thinkingComplete:!0});break;case"citations":this.updateMessage(s,{citations:i.citations});break;case"verification_status":this.identity.setVerified(i.isVerified);break;case"conversation_id":this.conversations.setCurrentId(i.conversationId);break;case"client_tool_call":await this.tools.execute(i.toolName,i.arguments),(u=(n=this.callbacks).onToolCall)==null||u.call(n,i);break;case"tool_call_start":case"tool_call_complete":(l=(d=this.callbacks).onToolCall)==null||l.call(d,i);break;case"workflow_started":case"workflow_todo_updated":case"workflow_ended":case"workflow_complete_prompt":(p=(h=this.callbacks).onWorkflow)==null||p.call(h,i);break;case"error":this.updateMessage(s,{content:i.message}),(m=(f=this.callbacks).onError)==null||m.call(f,new Error(i.message));break}yield i}}catch(c){if(c instanceof Error&&c.name==="AbortError"){r?this.updateMessage(s,{content:r}):(this._messages=this._messages.filter(i=>i.id!==s),this.notifyMessages());return}console.error("[Crow] Error:",c),this.updateMessage(s,{content:"Sorry, I encountered an error. Please try again."}),(w=(y=this.callbacks).onError)==null||w.call(y,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 E(a,e,t){const s=a.find(o=>o.name.toLowerCase()===e.toLowerCase());if(!s)return null;let r=s.path;if(t)for(const[o,n]of Object.entries(t))r=r.replace(`:${o}`,String(n));return r}function R(a,e){return async t=>{try{const s=t.page,r=t.params,o=t.url;let n=null;if(s){if(n=E(a,s,r),!n)return{status:"error",error:`Unknown page: "${s}". Available pages: ${a.map(d=>d.name).join(", ")}`}}else if(o)n=o;else return{status:"error",error:'Either "page" or "url" parameter is required'};const u=n.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g);return u?{status:"error",error:`Missing parameters: ${u.join(", ")}. Please provide values for these parameters.`}:e?(e(n),{status:"success",data:{navigated_to:n,page:s||void 0,method:"spa_router"}}):(window.location.href=n,{status:"success",data:{navigated_to:n,page:s||void 0,method:"full_navigation"}})}catch(s){return{status:"error",error:String(s)}}}}class A{constructor(e,t={}){this.controller=e,this.config={waitTimeout:t.waitTimeout??3e3,pollInterval:t.pollInterval??300,stepDelay:t.stepDelay??500,stopOnFailure:t.stopOnFailure??!1,onStepProgress:t.onStepProgress??(()=>{})}}async execute(e,t={}){const s=[];let r=0;console.log(`[WorkflowExecutor] Starting workflow: ${e.name} (${e.steps.length} steps)`);for(let n=0;n<e.steps.length;n++){const u=e.steps[n],d=this.resolveVariables(u,t);console.log(`[WorkflowExecutor] Step ${n+1}/${e.steps.length}: ${d.description}`);const l=await this.executeStep(d,n);if(s.push(l),this.config.onStepProgress(l),!l.success&&(r++,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:r,step_results:s,error:`Stopped at step ${n+1}: ${l.message}`};n<e.steps.length-1&&await this.delay(this.config.stepDelay)}const o=r===0;return console.log(`[WorkflowExecutor] Workflow "${e.name}" ${o?"completed successfully":`completed with ${r} failures`}`),{success:o,workflow_name:e.name,total_steps:e.steps.length,completed_steps:e.steps.length,failed_steps:r,step_results:s}}async executeStep(e,t){const s={step_index:t,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 o=await this.controller.navigateToUrl(e.url);return await this.delay(1e3),{...s,success:o.success,message:o.message}}await this.controller.updateTree();let r=this.controller.findElementByStrategies(e.selector_strategies);if(r===null&&e.selector_strategies.length>0&&(console.log(`[WorkflowExecutor] Element not found, waiting up to ${this.config.waitTimeout}ms...`),r=await this.controller.waitForElement(e.selector_strategies,this.config.waitTimeout,this.config.pollInterval)),r===null&&e.target_text&&(await this.controller.updateTree(),r=this.controller.findElementByText(e.target_text,!0),r===null&&(r=this.controller.findElementByText(e.target_text,!1))),r===null)return{...s,message:`Element not found for step: ${e.description} (target_text: "${e.target_text}")`};switch(s.element_index=r,e.type){case"click":{const o=await this.controller.clickElement(r);return{...s,success:o.success,message:o.message}}case"input":{if(e.value===void 0||e.value===null)return{...s,message:"Input step has no value"};const o=await this.controller.inputText(r,e.value);return{...s,success:o.success,message:o.message}}case"select":{if(!e.value)return{...s,message:"Select step has no value"};const o=await this.controller.selectOption(r,e.value);return{...s,success:o.success,message:o.message}}case"keypress":{if(!e.value)return{...s,message:"Keypress step has no key"};const o=await this.controller.pressKey(e.value,r);return{...s,success:o.success,message:o.message}}default:return{...s,message:`Unknown step type: ${e.type}`}}}catch(r){return{...s,message:`Error executing step: ${r instanceof Error?r.message:String(r)}`}}}resolveVariables(e,t){const s=r=>!r||!r.includes("{")?r:r.replace(/\{(\w+)\}/g,(o,n)=>n in t?String(t[n]):o);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(r=>({...r,value:s(r.value)||r.value}))}}delay(e){return new Promise(t=>setTimeout(t,e))}}exports.CrowBrowserUse=I.CrowBrowserUse;exports.ConversationManager=k;exports.CrowClient=O;exports.DEFAULT_TOOLS=g;exports.DEFAULT_TOOL_NAMES=b;exports.IdentityManager=_;exports.ToolManager=v;exports.WorkflowExecutor=A;exports.createNavigateToPageTool=R;exports.parseSSEChunk=C;exports.parseSSEData=S;exports.resolveRoute=E;exports.streamResponse=T;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("./workflowExecutor-BUc7WzWF.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"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 A(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=A;exports.parseSSEChunk=M;exports.parseSSEData=b;exports.resolveRoute=I;exports.streamResponse=S;