@usecrow/client 0.1.43 → 0.1.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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 { }