@usecrow/client 0.1.43 → 0.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -3
- package/dist/index.d.ts +57 -9
- package/dist/index.js +50 -790
- package/dist/index.native.cjs +3 -0
- package/dist/index.native.d.ts +517 -0
- package/dist/index.native.js +788 -0
- package/package.json +3 -1
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class C{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 a=r instanceof Error?r.message:String(r);return console.error(`[Crow] Tool ${e} failed:`,r),{status:"error",error:a}}}}const L="crow_conv_";class S{constructor(e,t,s){this.currentId=null,this.productId=e,this.apiUrl=t,this.storage=s,this.currentId=this.loadFromStorage()}getStorageKey(){return`${L}${this.productId}`}loadFromStorage(){try{return this.storage.getItem(this.getStorageKey())}catch{return null}}saveToStorage(e){try{this.storage.setItem(this.getStorageKey(),e)}catch{}}clearStorage(){try{this.storage.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 I(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*b(o){const e=o.split(`
|
|
3
|
+
`);for(const t of e)t.startsWith("data: ")&&(yield t.slice(6).trim())}async function*M(o,e){var a;const t=(a=o.body)==null?void 0:a.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=I(u);if(c&&(c.type==="content"?(r+=c.text,yield{...c,accumulated:r}):yield c,c.type==="done"))return}}}finally{t.releaseLock()}}const $=typeof window<"u"&&typeof document<"u";async function U(){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 f=$?{whatsOnScreen:U}:{},g=Object.keys(f);function T(){try{const o="__crow_test__";return localStorage.setItem(o,"1"),localStorage.removeItem(o),{getItem:e=>localStorage.getItem(e),setItem:(e,t)=>localStorage.setItem(e,t),removeItem:e=>localStorage.removeItem(e)}}catch{return p()}}function p(){const o=new Map;return{getItem:e=>o.get(e)??null,setItem:(e,t)=>o.set(e,t),removeItem:e=>o.delete(e)}}const x="https://api.usecrow.org",O="claude-sonnet-4-20250514",E=typeof window<"u"&&typeof document<"u";function A(o){return o.storage?o.storage:E?T():p()}function R(o){return o.streamReader?o.streamReader:M}class N{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||x,model:e.model||O,subdomain:e.subdomain};const t=A(e);this.readStream=R(e),this.identity=new C,this.tools=new v,this.conversations=new S(this.config.productId,this.config.apiUrl,t),(e.enableBrowserTools??(E&&g.length>0))&&(this.tools.register(f),console.log("[Crow] Default tools registered:",g.join(", "))),this.identity.subscribe(r=>{var a,l;(l=(a=this.callbacks).onVerificationStatus)==null||l.call(a,r.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(a=>a.id===e?{...a,...t}:a),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,m,y,w,_,k;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="",a="";try{const i=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,subdomain:this.config.subdomain,context:Object.keys(this.context).length>0?this.context:void 0}),signal:this.abortController.signal});if(!i.ok)throw new Error(`HTTP error: ${i.status}`);for await(const n of this.readStream(i,this.abortController.signal)){switch(n.type){case"content":r=n.accumulated,this.updateMessage(s,{content:r});break;case"thinking":a+=n.content,this.updateMessage(s,{thinking:a});break;case"thinking_complete":this.updateMessage(s,{thinkingComplete:!0});break;case"citations":this.updateMessage(s,{citations:n.citations});break;case"verification_status":this.identity.setVerified(n.isVerified);break;case"conversation_id":this.conversations.setCurrentId(n.conversationId);break;case"client_tool_call":await this.tools.execute(n.toolName,n.arguments),(d=(l=this.callbacks).onToolCall)==null||d.call(l,n);break;case"tool_call_start":case"tool_call_complete":(u=(h=this.callbacks).onToolCall)==null||u.call(h,n);break;case"workflow_started":case"workflow_todo_updated":case"workflow_ended":case"workflow_complete_prompt":(m=(c=this.callbacks).onWorkflow)==null||m.call(c,n);break;case"error":this.updateMessage(s,{content:n.message}),(w=(y=this.callbacks).onError)==null||w.call(y,new Error(n.message));break}yield n}}catch(i){if(i instanceof Error&&i.name==="AbortError"){r?this.updateMessage(s,{content:r}):(this._messages=this._messages.filter(n=>n.id!==s),this.notifyMessages());return}console.error("[Crow] Error:",i),this.updateMessage(s,{content:"Sorry, I encountered an error. Please try again."}),(k=(_=this.callbacks).onError)==null||k.call(_,i instanceof Error?i:new Error(String(i)))}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.ConversationManager=S;exports.CrowClient=N;exports.DEFAULT_TOOLS=f;exports.DEFAULT_TOOL_NAMES=g;exports.IdentityManager=C;exports.ToolManager=v;exports.createLocalStorageAdapter=T;exports.createMemoryStorageAdapter=p;exports.parseSSEChunk=b;exports.parseSSEData=I;exports.streamResponse=M;
|
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
export declare interface ActiveWorkflow {
|
|
2
|
+
name: string;
|
|
3
|
+
todos: WorkflowTodo[];
|
|
4
|
+
isComplete?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export declare interface Citation {
|
|
8
|
+
document_id: string;
|
|
9
|
+
filename: string;
|
|
10
|
+
similarity?: number;
|
|
11
|
+
image_url?: string;
|
|
12
|
+
page?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export declare interface ContextData {
|
|
16
|
+
/** Current page URL or path */
|
|
17
|
+
page?: string;
|
|
18
|
+
/** Custom context data */
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export declare interface Conversation {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string | null;
|
|
25
|
+
created_at: string;
|
|
26
|
+
updated_at: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare class ConversationManager {
|
|
30
|
+
private productId;
|
|
31
|
+
private apiUrl;
|
|
32
|
+
private storage;
|
|
33
|
+
private currentId;
|
|
34
|
+
constructor(productId: string, apiUrl: string, storage: StorageAdapter);
|
|
35
|
+
/**
|
|
36
|
+
* Get storage key for this product
|
|
37
|
+
*/
|
|
38
|
+
private getStorageKey;
|
|
39
|
+
/**
|
|
40
|
+
* Load conversation ID from storage
|
|
41
|
+
*/
|
|
42
|
+
private loadFromStorage;
|
|
43
|
+
/**
|
|
44
|
+
* Save conversation ID to storage
|
|
45
|
+
*/
|
|
46
|
+
private saveToStorage;
|
|
47
|
+
/**
|
|
48
|
+
* Clear conversation ID from storage
|
|
49
|
+
*/
|
|
50
|
+
private clearStorage;
|
|
51
|
+
/**
|
|
52
|
+
* Get current conversation ID
|
|
53
|
+
*/
|
|
54
|
+
getCurrentId(): string | null;
|
|
55
|
+
/**
|
|
56
|
+
* Set current conversation ID
|
|
57
|
+
*/
|
|
58
|
+
setCurrentId(id: string | null): void;
|
|
59
|
+
/**
|
|
60
|
+
* Check if there's a restored conversation
|
|
61
|
+
*/
|
|
62
|
+
hasRestoredConversation(): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Clear current conversation (start new)
|
|
65
|
+
*/
|
|
66
|
+
clear(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Fetch list of conversations for verified user
|
|
69
|
+
*/
|
|
70
|
+
getConversations(identityToken: string): Promise<Conversation[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Load conversation history for verified user
|
|
73
|
+
*/
|
|
74
|
+
loadHistory(conversationId: string, identityToken: string): Promise<Message[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Load conversation history for anonymous user
|
|
77
|
+
*/
|
|
78
|
+
loadAnonymousHistory(conversationId: string): Promise<Message[]>;
|
|
79
|
+
/**
|
|
80
|
+
* Parse history messages from API format
|
|
81
|
+
*/
|
|
82
|
+
private parseHistoryMessages;
|
|
83
|
+
/**
|
|
84
|
+
* Parse structured content (with thinking/text blocks) and extract just text
|
|
85
|
+
*/
|
|
86
|
+
private parseContent;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* localStorage-backed adapter (default for browsers).
|
|
91
|
+
* Falls back to in-memory when localStorage is unavailable.
|
|
92
|
+
*/
|
|
93
|
+
export declare function createLocalStorageAdapter(): StorageAdapter;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* In-memory adapter. Useful for React Native, SSR, or tests.
|
|
97
|
+
* Data does not persist across sessions.
|
|
98
|
+
*/
|
|
99
|
+
export declare function createMemoryStorageAdapter(): StorageAdapter;
|
|
100
|
+
|
|
101
|
+
export declare class CrowClient {
|
|
102
|
+
private config;
|
|
103
|
+
private identity;
|
|
104
|
+
private tools;
|
|
105
|
+
private conversations;
|
|
106
|
+
private readStream;
|
|
107
|
+
private context;
|
|
108
|
+
private abortController;
|
|
109
|
+
private callbacks;
|
|
110
|
+
private _messages;
|
|
111
|
+
private messageListeners;
|
|
112
|
+
private _isLoading;
|
|
113
|
+
private loadingListeners;
|
|
114
|
+
constructor(config: CrowClientConfig);
|
|
115
|
+
/**
|
|
116
|
+
* Get current product ID
|
|
117
|
+
*/
|
|
118
|
+
get productId(): string;
|
|
119
|
+
/**
|
|
120
|
+
* Get current API URL
|
|
121
|
+
*/
|
|
122
|
+
get apiUrl(): string;
|
|
123
|
+
/**
|
|
124
|
+
* Get/set current model
|
|
125
|
+
*/
|
|
126
|
+
get model(): string;
|
|
127
|
+
set model(value: string);
|
|
128
|
+
/**
|
|
129
|
+
* Register event callbacks
|
|
130
|
+
*/
|
|
131
|
+
on(callbacks: CrowEventCallbacks): void;
|
|
132
|
+
/**
|
|
133
|
+
* Identify the current user with a JWT token
|
|
134
|
+
*/
|
|
135
|
+
identify(options: IdentifyOptions): void;
|
|
136
|
+
/**
|
|
137
|
+
* Reset user identity (call on logout)
|
|
138
|
+
*/
|
|
139
|
+
resetUser(): void;
|
|
140
|
+
/**
|
|
141
|
+
* Check if user is identified
|
|
142
|
+
*/
|
|
143
|
+
isIdentified(): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Check if user is verified by server
|
|
146
|
+
*/
|
|
147
|
+
isVerified(): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Register client-side tool handlers
|
|
150
|
+
*/
|
|
151
|
+
registerTools(tools: ToolHandlers): void;
|
|
152
|
+
/**
|
|
153
|
+
* Unregister a tool handler
|
|
154
|
+
*/
|
|
155
|
+
unregisterTool(name: string): void;
|
|
156
|
+
/**
|
|
157
|
+
* Get list of registered tool names
|
|
158
|
+
*/
|
|
159
|
+
getRegisteredTools(): string[];
|
|
160
|
+
/**
|
|
161
|
+
* Set context data to be sent with messages
|
|
162
|
+
*/
|
|
163
|
+
setContext(data: ContextData): void;
|
|
164
|
+
/**
|
|
165
|
+
* Clear context data
|
|
166
|
+
*/
|
|
167
|
+
clearContext(): void;
|
|
168
|
+
/**
|
|
169
|
+
* Get current messages
|
|
170
|
+
*/
|
|
171
|
+
get messages(): Message[];
|
|
172
|
+
/**
|
|
173
|
+
* Check if currently loading/streaming
|
|
174
|
+
*/
|
|
175
|
+
get isLoading(): boolean;
|
|
176
|
+
/**
|
|
177
|
+
* Subscribe to message changes
|
|
178
|
+
*/
|
|
179
|
+
onMessages(callback: (messages: Message[]) => void): () => void;
|
|
180
|
+
/**
|
|
181
|
+
* Subscribe to loading state changes
|
|
182
|
+
*/
|
|
183
|
+
onLoading(callback: (isLoading: boolean) => void): () => void;
|
|
184
|
+
/**
|
|
185
|
+
* Clear all messages and start new conversation
|
|
186
|
+
*/
|
|
187
|
+
clearMessages(): void;
|
|
188
|
+
/**
|
|
189
|
+
* Load messages from history
|
|
190
|
+
*/
|
|
191
|
+
loadMessages(messages: Message[]): void;
|
|
192
|
+
private notifyMessages;
|
|
193
|
+
private setLoading;
|
|
194
|
+
private addMessage;
|
|
195
|
+
private updateMessage;
|
|
196
|
+
private generateMessageId;
|
|
197
|
+
/**
|
|
198
|
+
* Get current conversation ID
|
|
199
|
+
*/
|
|
200
|
+
get conversationId(): string | null;
|
|
201
|
+
/**
|
|
202
|
+
* Set current conversation ID
|
|
203
|
+
*/
|
|
204
|
+
set conversationId(id: string | null);
|
|
205
|
+
/**
|
|
206
|
+
* Get list of conversations for verified user
|
|
207
|
+
*/
|
|
208
|
+
getConversations(): Promise<Conversation[]>;
|
|
209
|
+
/**
|
|
210
|
+
* Load conversation history
|
|
211
|
+
*/
|
|
212
|
+
loadHistory(conversationId: string): Promise<Message[]>;
|
|
213
|
+
/**
|
|
214
|
+
* Switch to a different conversation
|
|
215
|
+
*/
|
|
216
|
+
switchConversation(conversationId: string): Promise<void>;
|
|
217
|
+
/**
|
|
218
|
+
* Send a message and receive streaming response
|
|
219
|
+
* Returns an async generator of stream events
|
|
220
|
+
*/
|
|
221
|
+
sendMessage(content: string): AsyncGenerator<StreamEvent>;
|
|
222
|
+
/**
|
|
223
|
+
* Send a message and wait for complete response (non-streaming)
|
|
224
|
+
*/
|
|
225
|
+
send(content: string): Promise<Message | null>;
|
|
226
|
+
/**
|
|
227
|
+
* Stop current generation
|
|
228
|
+
*/
|
|
229
|
+
stop(): void;
|
|
230
|
+
/**
|
|
231
|
+
* Destroy the client and clean up resources
|
|
232
|
+
*/
|
|
233
|
+
destroy(): void;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export declare interface CrowClientConfig {
|
|
237
|
+
/** Your Crow product ID from the dashboard */
|
|
238
|
+
productId: string;
|
|
239
|
+
/** API URL (defaults to https://api.usecrow.org) */
|
|
240
|
+
apiUrl?: string;
|
|
241
|
+
/** Default model to use */
|
|
242
|
+
model?: string;
|
|
243
|
+
/**
|
|
244
|
+
* Storage adapter for persisting conversation state.
|
|
245
|
+
* Defaults to localStorage (browser) or in-memory if unavailable.
|
|
246
|
+
*/
|
|
247
|
+
storage?: StorageAdapter;
|
|
248
|
+
/**
|
|
249
|
+
* Custom stream reader for SSE responses.
|
|
250
|
+
* Override this for React Native or other non-browser runtimes
|
|
251
|
+
* where Response.body.getReader() is not available.
|
|
252
|
+
*/
|
|
253
|
+
streamReader?: StreamReader;
|
|
254
|
+
/**
|
|
255
|
+
* Whether to register browser-only default tools (whatsOnScreen).
|
|
256
|
+
* Defaults to true in browser environments, false otherwise.
|
|
257
|
+
*/
|
|
258
|
+
enableBrowserTools?: boolean;
|
|
259
|
+
/** Subdomain for multi-endpoint products (routes to specific backend config) */
|
|
260
|
+
subdomain?: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export declare interface CrowEventCallbacks {
|
|
264
|
+
onMessage?: (message: Message) => void;
|
|
265
|
+
onMessageUpdate?: (messageId: string, updates: Partial<Message>) => void;
|
|
266
|
+
onToolCall?: (event: StreamEvent & {
|
|
267
|
+
type: 'tool_call_start' | 'tool_call_complete' | 'client_tool_call';
|
|
268
|
+
}) => void;
|
|
269
|
+
onWorkflow?: (event: StreamEvent & {
|
|
270
|
+
type: 'workflow_started' | 'workflow_todo_updated' | 'workflow_ended' | 'workflow_complete_prompt';
|
|
271
|
+
}) => void;
|
|
272
|
+
onVerificationStatus?: (isVerified: boolean) => void;
|
|
273
|
+
onError?: (error: Error) => void;
|
|
274
|
+
onBrowserUseConfirmation?: (event: {
|
|
275
|
+
instruction: string;
|
|
276
|
+
toolCallId: string;
|
|
277
|
+
}) => Promise<boolean>;
|
|
278
|
+
onBrowserUseQuestion?: (event: {
|
|
279
|
+
question: string;
|
|
280
|
+
sessionId: string;
|
|
281
|
+
}) => Promise<string>;
|
|
282
|
+
onBrowserUseProgress?: (event: {
|
|
283
|
+
step: number;
|
|
284
|
+
maxSteps: number;
|
|
285
|
+
action?: string;
|
|
286
|
+
}) => void;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export declare const DEFAULT_TOOL_NAMES: DefaultToolName[];
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Browser default tools. Empty object in non-browser runtimes.
|
|
293
|
+
*/
|
|
294
|
+
export declare const DEFAULT_TOOLS: ToolHandlers;
|
|
295
|
+
|
|
296
|
+
export declare type DefaultToolName = 'whatsOnScreen';
|
|
297
|
+
|
|
298
|
+
export declare interface IdentifyOptions {
|
|
299
|
+
/** JWT token from your backend for user verification */
|
|
300
|
+
token: string;
|
|
301
|
+
/** Optional user display name */
|
|
302
|
+
name?: string;
|
|
303
|
+
/** Optional user email */
|
|
304
|
+
email?: string;
|
|
305
|
+
/** Any additional metadata */
|
|
306
|
+
[key: string]: unknown;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export declare class IdentityManager {
|
|
310
|
+
private state;
|
|
311
|
+
private listeners;
|
|
312
|
+
/**
|
|
313
|
+
* Identify the current user with a JWT token
|
|
314
|
+
*/
|
|
315
|
+
identify(options: IdentifyOptions): void;
|
|
316
|
+
/**
|
|
317
|
+
* Update verification status (called when server confirms)
|
|
318
|
+
*/
|
|
319
|
+
setVerified(isVerified: boolean): void;
|
|
320
|
+
/**
|
|
321
|
+
* Reset user identity (call on logout)
|
|
322
|
+
*/
|
|
323
|
+
reset(): void;
|
|
324
|
+
/**
|
|
325
|
+
* Get current identity token
|
|
326
|
+
*/
|
|
327
|
+
getToken(): string | null;
|
|
328
|
+
/**
|
|
329
|
+
* Get current identity state
|
|
330
|
+
*/
|
|
331
|
+
getState(): IdentityState;
|
|
332
|
+
/**
|
|
333
|
+
* Check if user is identified
|
|
334
|
+
*/
|
|
335
|
+
isIdentified(): boolean;
|
|
336
|
+
/**
|
|
337
|
+
* Check if user is verified
|
|
338
|
+
*/
|
|
339
|
+
isVerified(): boolean;
|
|
340
|
+
/**
|
|
341
|
+
* Subscribe to identity changes
|
|
342
|
+
*/
|
|
343
|
+
subscribe(callback: (state: IdentityState) => void): () => void;
|
|
344
|
+
private notify;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export declare interface IdentityState {
|
|
348
|
+
token: string | null;
|
|
349
|
+
metadata: Record<string, unknown>;
|
|
350
|
+
isVerified: boolean;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export declare interface Message {
|
|
354
|
+
id: string;
|
|
355
|
+
content: string;
|
|
356
|
+
role: 'user' | 'assistant';
|
|
357
|
+
timestamp: Date;
|
|
358
|
+
/** Citations from knowledge base */
|
|
359
|
+
citations?: Citation[];
|
|
360
|
+
/** Claude's reasoning/thinking trace */
|
|
361
|
+
thinking?: string;
|
|
362
|
+
/** Whether thinking is complete */
|
|
363
|
+
thinkingComplete?: boolean;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Parse SSE chunk into lines and extract data
|
|
368
|
+
*/
|
|
369
|
+
export declare function parseSSEChunk(chunk: string): Generator<string>;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Parse a single SSE data line into a StreamEvent
|
|
373
|
+
*/
|
|
374
|
+
export declare function parseSSEData(data: string): StreamEvent | null;
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Synchronous key-value storage interface.
|
|
378
|
+
* Matches the subset of Web Storage API used by ConversationManager.
|
|
379
|
+
*/
|
|
380
|
+
export declare interface StorageAdapter {
|
|
381
|
+
getItem(key: string): string | null;
|
|
382
|
+
setItem(key: string, value: string): void;
|
|
383
|
+
removeItem(key: string): void;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export declare type StreamEvent = {
|
|
387
|
+
type: 'content';
|
|
388
|
+
text: string;
|
|
389
|
+
accumulated: string;
|
|
390
|
+
} | {
|
|
391
|
+
type: 'thinking';
|
|
392
|
+
content: string;
|
|
393
|
+
} | {
|
|
394
|
+
type: 'thinking_complete';
|
|
395
|
+
} | {
|
|
396
|
+
type: 'citations';
|
|
397
|
+
citations: Citation[];
|
|
398
|
+
} | {
|
|
399
|
+
type: 'tool_call_start';
|
|
400
|
+
toolName: string;
|
|
401
|
+
displayName?: string;
|
|
402
|
+
arguments: Record<string, unknown>;
|
|
403
|
+
} | {
|
|
404
|
+
type: 'tool_call_complete';
|
|
405
|
+
toolName: string;
|
|
406
|
+
displayName?: string;
|
|
407
|
+
success: boolean;
|
|
408
|
+
} | {
|
|
409
|
+
type: 'client_tool_call';
|
|
410
|
+
toolName: string;
|
|
411
|
+
displayName?: string;
|
|
412
|
+
arguments: Record<string, unknown>;
|
|
413
|
+
} | {
|
|
414
|
+
type: 'tool_consent_required';
|
|
415
|
+
toolName: string;
|
|
416
|
+
displayName?: string;
|
|
417
|
+
arguments: Record<string, unknown>;
|
|
418
|
+
} | {
|
|
419
|
+
type: 'workflow_started';
|
|
420
|
+
name: string;
|
|
421
|
+
todos: WorkflowTodo[];
|
|
422
|
+
} | {
|
|
423
|
+
type: 'workflow_todo_updated';
|
|
424
|
+
todoId: string;
|
|
425
|
+
status: 'pending' | 'completed';
|
|
426
|
+
} | {
|
|
427
|
+
type: 'workflow_ended';
|
|
428
|
+
} | {
|
|
429
|
+
type: 'workflow_complete_prompt';
|
|
430
|
+
} | {
|
|
431
|
+
type: 'verification_status';
|
|
432
|
+
isVerified: boolean;
|
|
433
|
+
} | {
|
|
434
|
+
type: 'conversation_id';
|
|
435
|
+
conversationId: string;
|
|
436
|
+
} | {
|
|
437
|
+
type: 'error';
|
|
438
|
+
message: string;
|
|
439
|
+
} | {
|
|
440
|
+
type: 'done';
|
|
441
|
+
} | {
|
|
442
|
+
type: 'suggested_actions';
|
|
443
|
+
actions: SuggestedAction[];
|
|
444
|
+
} | {
|
|
445
|
+
type: 'browser_use_confirmation';
|
|
446
|
+
instruction: string;
|
|
447
|
+
toolCallId: string;
|
|
448
|
+
} | {
|
|
449
|
+
type: 'browser_use_question';
|
|
450
|
+
question: string;
|
|
451
|
+
sessionId: string;
|
|
452
|
+
} | {
|
|
453
|
+
type: 'browser_use_progress';
|
|
454
|
+
step: number;
|
|
455
|
+
maxSteps: number;
|
|
456
|
+
action?: string;
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* A function that reads SSE events from an HTTP Response.
|
|
461
|
+
*
|
|
462
|
+
* Browser default: uses Response.body.getReader() + TextDecoder.
|
|
463
|
+
* React Native: uses XMLHttpRequest onprogress or text-based parsing.
|
|
464
|
+
*/
|
|
465
|
+
export declare type StreamReader = (response: Response, signal?: AbortSignal) => AsyncGenerator<StreamEvent>;
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Create an async generator that streams events from a Response
|
|
469
|
+
*/
|
|
470
|
+
export declare function streamResponse(response: Response, signal?: AbortSignal): AsyncGenerator<StreamEvent>;
|
|
471
|
+
|
|
472
|
+
export declare interface SuggestedAction {
|
|
473
|
+
label: string;
|
|
474
|
+
message: string;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export declare type ToolHandler = (args: Record<string, unknown>) => Promise<ToolResult> | ToolResult;
|
|
478
|
+
|
|
479
|
+
export declare type ToolHandlers = Record<string, ToolHandler>;
|
|
480
|
+
|
|
481
|
+
export declare class ToolManager {
|
|
482
|
+
private handlers;
|
|
483
|
+
/**
|
|
484
|
+
* Register client-side tool handlers
|
|
485
|
+
*/
|
|
486
|
+
register(tools: ToolHandlers): void;
|
|
487
|
+
/**
|
|
488
|
+
* Unregister a tool handler
|
|
489
|
+
*/
|
|
490
|
+
unregister(name: string): void;
|
|
491
|
+
/**
|
|
492
|
+
* Check if a tool is registered
|
|
493
|
+
*/
|
|
494
|
+
has(name: string): boolean;
|
|
495
|
+
/**
|
|
496
|
+
* Get all registered tool names
|
|
497
|
+
*/
|
|
498
|
+
getRegisteredTools(): string[];
|
|
499
|
+
/**
|
|
500
|
+
* Execute a client-side tool
|
|
501
|
+
*/
|
|
502
|
+
execute(name: string, args: Record<string, unknown>): Promise<ToolResult>;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export declare interface ToolResult {
|
|
506
|
+
status: 'success' | 'error' | 'needs_input';
|
|
507
|
+
data?: unknown;
|
|
508
|
+
error?: string;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
export declare interface WorkflowTodo {
|
|
512
|
+
id: string;
|
|
513
|
+
text: string;
|
|
514
|
+
status: 'pending' | 'completed';
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
export { }
|