@hsafa/ui-sdk 0.3.3 → 0.4.1
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/README.md +133 -2
- package/dist/index.cjs +23 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +572 -20
- package/dist/index.d.ts +572 -20
- package/dist/index.js +23 -23
- package/dist/index.js.map +1 -1
- package/docs/CUSTOM_UI_EXAMPLES.md +309 -0
- package/docs/DYNAMIC_PAGE_SCHEMAS.md +261 -0
- package/docs/HEADLESS_QUICK_REFERENCE.md +426 -0
- package/docs/HEADLESS_USAGE.md +682 -0
- package/docs/MIGRATION_TO_HEADLESS.md +408 -0
- package/docs/README.md +43 -71
- package/docs/handbook/00-Overview.md +69 -0
- package/docs/handbook/01-Quickstart.md +133 -0
- package/docs/handbook/02-Architecture.md +75 -0
- package/docs/handbook/03-Components-and-Hooks.md +81 -0
- package/docs/handbook/04-Streaming-and-Transport.md +73 -0
- package/docs/handbook/05-Tools-and-UI.md +73 -0
- package/docs/handbook/06-Storage-and-History.md +63 -0
- package/docs/handbook/07-Dynamic-Pages.md +49 -0
- package/docs/handbook/08-Server-Integration.md +84 -0
- package/docs/handbook/09-Agent-Studio-Client.md +40 -0
- package/docs/handbook/10-Examples-and-Recipes.md +154 -0
- package/docs/handbook/11-API-Reference-Map.md +48 -0
- package/docs/handbook/README.md +24 -0
- package/examples/custom-tools-example.tsx +401 -0
- package/examples/custom-ui-customizations-example.tsx +543 -0
- package/examples/dynamic-page-example.tsx +380 -0
- package/examples/headless-chat-example.tsx +537 -0
- package/examples/minimal-headless-example.tsx +142 -0
- package/package.json +3 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { ComponentType } from 'react';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -74,11 +74,12 @@ interface FloatingChatButtonProps {
|
|
|
74
74
|
}
|
|
75
75
|
declare function FloatingChatButton({ show, onClick, resolvedColors, floatingButtonPosition }: FloatingChatButtonProps): react_jsx_runtime.JSX.Element | null;
|
|
76
76
|
|
|
77
|
-
declare function useAutoScroll<T extends HTMLElement>(shouldScroll?: boolean): React.MutableRefObject<T | null>;
|
|
77
|
+
declare function useAutoScroll<T extends HTMLElement>(shouldScroll?: boolean): React$1.MutableRefObject<T | null>;
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* Type definitions for the Hsafa SDK - minimal exports used across the SDK
|
|
81
81
|
*/
|
|
82
|
+
|
|
82
83
|
type Attachment = {
|
|
83
84
|
id: string;
|
|
84
85
|
name?: string;
|
|
@@ -86,10 +87,60 @@ type Attachment = {
|
|
|
86
87
|
mimeType?: string;
|
|
87
88
|
size?: number;
|
|
88
89
|
};
|
|
90
|
+
type UserContentPart = {
|
|
91
|
+
type: 'text';
|
|
92
|
+
text: string;
|
|
93
|
+
} | {
|
|
94
|
+
type: 'image';
|
|
95
|
+
image: URL;
|
|
96
|
+
mediaType: string;
|
|
97
|
+
} | {
|
|
98
|
+
type: 'file';
|
|
99
|
+
data: string;
|
|
100
|
+
mediaType: string;
|
|
101
|
+
name?: string;
|
|
102
|
+
};
|
|
103
|
+
type AssistantContentPart = {
|
|
104
|
+
type: 'text';
|
|
105
|
+
text: string;
|
|
106
|
+
} | {
|
|
107
|
+
type: 'reasoning';
|
|
108
|
+
text: string;
|
|
109
|
+
} | {
|
|
110
|
+
type: 'tool-call';
|
|
111
|
+
toolCallId: string;
|
|
112
|
+
toolName?: string;
|
|
113
|
+
input?: any;
|
|
114
|
+
};
|
|
115
|
+
type ChatMessage = {
|
|
116
|
+
id: string;
|
|
117
|
+
role: 'user';
|
|
118
|
+
content: string | UserContentPart[];
|
|
119
|
+
createdAt?: number;
|
|
120
|
+
text?: string;
|
|
121
|
+
attachments?: Attachment[];
|
|
122
|
+
} | {
|
|
123
|
+
id: string;
|
|
124
|
+
role: 'assistant';
|
|
125
|
+
content?: string | AssistantContentPart[];
|
|
126
|
+
items: any[];
|
|
127
|
+
reasoning?: string;
|
|
128
|
+
reasoningOpen?: boolean;
|
|
129
|
+
mainAgentActions?: any[];
|
|
130
|
+
createdAt?: number;
|
|
131
|
+
};
|
|
89
132
|
type HsafaTool = ((input: any) => any | Promise<any>) | {
|
|
90
133
|
tool: (input: any) => any | Promise<any>;
|
|
91
134
|
executeEachToken?: boolean;
|
|
92
135
|
};
|
|
136
|
+
type CustomToolUIRenderProps = {
|
|
137
|
+
toolName: string;
|
|
138
|
+
toolCallId: string;
|
|
139
|
+
input: any;
|
|
140
|
+
output: any;
|
|
141
|
+
status?: string;
|
|
142
|
+
addToolResult: (result: any) => void;
|
|
143
|
+
};
|
|
93
144
|
interface HsafaChatProps {
|
|
94
145
|
agentId: string;
|
|
95
146
|
theme?: 'dark' | 'light';
|
|
@@ -121,20 +172,475 @@ interface HsafaChatProps {
|
|
|
121
172
|
defaultReasoningOpen?: boolean;
|
|
122
173
|
hideReasoningContent?: boolean;
|
|
123
174
|
HsafaTools?: Record<string, HsafaTool>;
|
|
175
|
+
dynamicPageTypes?: any[];
|
|
176
|
+
componentAboveInput?: React__default.ComponentType<any>;
|
|
177
|
+
editProcessContent?: EditProcessContent;
|
|
124
178
|
}
|
|
179
|
+
type EditProcessContent = {
|
|
180
|
+
title?: string;
|
|
181
|
+
content?: string | React__default.ComponentType<any>;
|
|
182
|
+
submit_button_label?: string;
|
|
183
|
+
cancel_button_label?: string;
|
|
184
|
+
icon?: React__default.ComponentType<any>;
|
|
185
|
+
message_icon?: React__default.ComponentType<any>;
|
|
186
|
+
};
|
|
125
187
|
|
|
126
|
-
declare function useFileUpload(baseUrl
|
|
188
|
+
declare function useFileUpload(baseUrl?: string): {
|
|
127
189
|
attachments: Attachment[];
|
|
128
190
|
uploading: boolean;
|
|
129
|
-
fileInputRef: React.MutableRefObject<HTMLInputElement | null>;
|
|
191
|
+
fileInputRef: React$1.MutableRefObject<HTMLInputElement | null>;
|
|
130
192
|
formatBytes: (bytes: number) => string;
|
|
131
193
|
handleRemoveAttachment: (id: string) => void;
|
|
132
194
|
handleFileSelection: (fileList: FileList | File[] | null, setError: (error: string | null) => void) => Promise<void>;
|
|
133
195
|
buildUserContent: (text: string, attachments: Attachment[]) => any[];
|
|
134
196
|
clearAttachments: () => void;
|
|
197
|
+
setAttachments: React$1.Dispatch<React$1.SetStateAction<Attachment[]>>;
|
|
135
198
|
MAX_UPLOAD_SIZE: number;
|
|
136
199
|
};
|
|
137
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Dynamic Page Types
|
|
203
|
+
* Defines all types for the Dynamic Page system
|
|
204
|
+
*/
|
|
205
|
+
interface DynamicPageGrid {
|
|
206
|
+
gridTemplateColumns: string;
|
|
207
|
+
gridTemplateRows: string;
|
|
208
|
+
gap?: string;
|
|
209
|
+
gridTemplateAreas?: string;
|
|
210
|
+
}
|
|
211
|
+
interface DynamicPageObjectMeta {
|
|
212
|
+
title?: string;
|
|
213
|
+
description?: string;
|
|
214
|
+
tags?: string[];
|
|
215
|
+
}
|
|
216
|
+
interface DynamicPageObject {
|
|
217
|
+
object_name: string;
|
|
218
|
+
area?: string;
|
|
219
|
+
data: any;
|
|
220
|
+
type?: string;
|
|
221
|
+
meta?: DynamicPageObjectMeta;
|
|
222
|
+
version: number;
|
|
223
|
+
updatedAt: string;
|
|
224
|
+
}
|
|
225
|
+
interface ComponentError {
|
|
226
|
+
object_name: string;
|
|
227
|
+
area: string;
|
|
228
|
+
error: string;
|
|
229
|
+
errorStack?: string | null;
|
|
230
|
+
timestamp: string;
|
|
231
|
+
type?: string;
|
|
232
|
+
}
|
|
233
|
+
interface DynamicPageState {
|
|
234
|
+
grid: DynamicPageGrid | null;
|
|
235
|
+
objects: Record<string, DynamicPageObject>;
|
|
236
|
+
componentErrors?: ComponentError[];
|
|
237
|
+
}
|
|
238
|
+
interface DynamicPageTypeConfig {
|
|
239
|
+
type: string;
|
|
240
|
+
component: React.ComponentType<any>;
|
|
241
|
+
description: string;
|
|
242
|
+
variants?: string[];
|
|
243
|
+
/** Optional Zod schema or JSON schema describing the expected data structure */
|
|
244
|
+
schema?: any;
|
|
245
|
+
/** Optional examples showing valid data for this type */
|
|
246
|
+
examples?: any[];
|
|
247
|
+
}
|
|
248
|
+
interface ToolResult {
|
|
249
|
+
success: boolean;
|
|
250
|
+
message?: string;
|
|
251
|
+
[key: string]: any;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Dynamic Page Operations
|
|
256
|
+
* All tool logic for managing dynamic pages
|
|
257
|
+
*/
|
|
258
|
+
|
|
259
|
+
declare class DynamicPageOperations {
|
|
260
|
+
private chatId;
|
|
261
|
+
private state;
|
|
262
|
+
private availableTypes;
|
|
263
|
+
private onStateChange;
|
|
264
|
+
constructor(chatId: string, state: DynamicPageState, availableTypes: DynamicPageTypeConfig[], onStateChange: (state: DynamicPageState) => void);
|
|
265
|
+
private updateState;
|
|
266
|
+
setGrid(params: {
|
|
267
|
+
gridTemplateColumns: string;
|
|
268
|
+
gridTemplateRows: string;
|
|
269
|
+
gap?: string;
|
|
270
|
+
gridTemplateAreas?: string;
|
|
271
|
+
}): ToolResult;
|
|
272
|
+
readGrid(): ToolResult;
|
|
273
|
+
readAvailableTypes(): ToolResult;
|
|
274
|
+
setObject(params: {
|
|
275
|
+
object_name: string;
|
|
276
|
+
area?: string;
|
|
277
|
+
data: any;
|
|
278
|
+
type?: string;
|
|
279
|
+
meta?: {
|
|
280
|
+
title?: string;
|
|
281
|
+
description?: string;
|
|
282
|
+
tags?: string[];
|
|
283
|
+
};
|
|
284
|
+
}): ToolResult;
|
|
285
|
+
editObject(params: {
|
|
286
|
+
object_name: string;
|
|
287
|
+
json_patch?: any[];
|
|
288
|
+
merge_patch?: any;
|
|
289
|
+
replace_entire_data?: boolean;
|
|
290
|
+
new_data?: any;
|
|
291
|
+
options?: any;
|
|
292
|
+
}): ToolResult;
|
|
293
|
+
deleteObject(params: {
|
|
294
|
+
object_name: string;
|
|
295
|
+
}): ToolResult;
|
|
296
|
+
readAllObjects(): ToolResult;
|
|
297
|
+
readObject(params: {
|
|
298
|
+
object_name: string;
|
|
299
|
+
}): ToolResult;
|
|
300
|
+
readAtPointer(params: {
|
|
301
|
+
object_name: string;
|
|
302
|
+
pointer?: string;
|
|
303
|
+
}): ToolResult;
|
|
304
|
+
renameObject(params: {
|
|
305
|
+
current_name: string;
|
|
306
|
+
new_name: string;
|
|
307
|
+
new_area?: string;
|
|
308
|
+
}): ToolResult;
|
|
309
|
+
moveObject(params: {
|
|
310
|
+
object_name: string;
|
|
311
|
+
target_area: string;
|
|
312
|
+
}): ToolResult;
|
|
313
|
+
validateGrid(): ToolResult;
|
|
314
|
+
readComponentErrors(params?: {
|
|
315
|
+
limit?: number;
|
|
316
|
+
}): ToolResult;
|
|
317
|
+
clearComponentErrors(): ToolResult;
|
|
318
|
+
private getRecentErrorsSummary;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* useDynamicPage Hook
|
|
323
|
+
* Manages dynamic page state and operations
|
|
324
|
+
*/
|
|
325
|
+
|
|
326
|
+
declare function useDynamicPage(chatIdParam: string, availableTypes: DynamicPageTypeConfig[]): {
|
|
327
|
+
state: DynamicPageState;
|
|
328
|
+
isDynamicPageOpen: boolean;
|
|
329
|
+
getOperations: () => DynamicPageOperations | null;
|
|
330
|
+
closeDynamicPage: () => void;
|
|
331
|
+
openDynamicPage: () => void;
|
|
332
|
+
handleError: (error: ComponentError) => void;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* useHsafaAgent - The main headless hook for Hsafa Agent
|
|
337
|
+
*
|
|
338
|
+
* This hook provides all the logic needed to integrate an AI agent into your custom UI.
|
|
339
|
+
* It handles chat state, tool execution, message streaming, and more.
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* ```tsx
|
|
343
|
+
* function MyCustomChat() {
|
|
344
|
+
* const agent = useHsafaAgent({
|
|
345
|
+
* agentId: 'my-agent',
|
|
346
|
+
* baseUrl: 'http://localhost:3000',
|
|
347
|
+
* tools: {
|
|
348
|
+
* customTool: async (input) => {
|
|
349
|
+
* return { result: 'Custom tool executed!' };
|
|
350
|
+
* }
|
|
351
|
+
* }
|
|
352
|
+
* });
|
|
353
|
+
*
|
|
354
|
+
* return (
|
|
355
|
+
* <div>
|
|
356
|
+
* {agent.messages.map(msg => (
|
|
357
|
+
* <div key={msg.id}>{msg.content}</div>
|
|
358
|
+
* ))}
|
|
359
|
+
* <input
|
|
360
|
+
* value={agent.input}
|
|
361
|
+
* onChange={(e) => agent.setInput(e.target.value)}
|
|
362
|
+
* onKeyPress={(e) => e.key === 'Enter' && agent.sendMessage()}
|
|
363
|
+
* />
|
|
364
|
+
* </div>
|
|
365
|
+
* );
|
|
366
|
+
* }
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
|
|
370
|
+
interface UseHsafaAgentConfig {
|
|
371
|
+
/** The agent ID to connect to */
|
|
372
|
+
agentId: string;
|
|
373
|
+
/** Base URL of your backend server */
|
|
374
|
+
baseUrl?: string;
|
|
375
|
+
/** Custom tools that the agent can use */
|
|
376
|
+
tools?: Record<string, any>;
|
|
377
|
+
/** Custom UI components for rendering tool results */
|
|
378
|
+
uiComponents?: Record<string, React.ComponentType<any>>;
|
|
379
|
+
/** Dynamic page type configurations */
|
|
380
|
+
dynamicPageTypes?: any[];
|
|
381
|
+
/** Callback when a message finishes */
|
|
382
|
+
onFinish?: (message: any) => void;
|
|
383
|
+
/** Callback when an error occurs */
|
|
384
|
+
onError?: (error: Error) => void;
|
|
385
|
+
/** Initial messages to load */
|
|
386
|
+
initialMessages?: any[];
|
|
387
|
+
/** Callback when messages change */
|
|
388
|
+
onMessagesChange?: (messages: any[]) => void;
|
|
389
|
+
}
|
|
390
|
+
interface HsafaAgentAPI {
|
|
391
|
+
/** Current input text */
|
|
392
|
+
input: string;
|
|
393
|
+
/** Set the input text */
|
|
394
|
+
setInput: (value: string) => void;
|
|
395
|
+
/** All chat messages */
|
|
396
|
+
messages: any[];
|
|
397
|
+
/** Whether the agent is currently processing */
|
|
398
|
+
isLoading: boolean;
|
|
399
|
+
/** Current chat status */
|
|
400
|
+
status: 'idle' | 'submitted' | 'streaming' | 'error' | 'ready';
|
|
401
|
+
/** Any error that occurred */
|
|
402
|
+
error: Error | undefined;
|
|
403
|
+
/** Send the current input as a message */
|
|
404
|
+
sendMessage: (options?: {
|
|
405
|
+
text?: string;
|
|
406
|
+
files?: any[];
|
|
407
|
+
}) => Promise<void>;
|
|
408
|
+
/** Stop the current generation */
|
|
409
|
+
stop: () => void;
|
|
410
|
+
/** Clear all messages and start a new chat */
|
|
411
|
+
newChat: () => void;
|
|
412
|
+
/** Set messages directly (for loading history) */
|
|
413
|
+
setMessages: (messages: any[]) => void;
|
|
414
|
+
/** Direct access to the underlying chat API */
|
|
415
|
+
chatApi: any;
|
|
416
|
+
/** Current chat ID */
|
|
417
|
+
chatId: string;
|
|
418
|
+
/** Set the chat ID (for switching chats) */
|
|
419
|
+
setChatId: (chatId: string) => void;
|
|
420
|
+
/** All available tools (built-in + custom + dynamic page) */
|
|
421
|
+
tools: Record<string, any>;
|
|
422
|
+
/** All available UI components */
|
|
423
|
+
uiComponents: Record<string, any>;
|
|
424
|
+
/** Dynamic page operations (if enabled) */
|
|
425
|
+
dynamicPage: ReturnType<typeof useDynamicPage> | null;
|
|
426
|
+
/** Ref to form host elements (for requestInput tool) */
|
|
427
|
+
formHostRef: React.MutableRefObject<Map<string, HTMLDivElement>>;
|
|
428
|
+
/** Ref to form state (for requestInput tool) */
|
|
429
|
+
formStateRef: React.MutableRefObject<Map<string, {
|
|
430
|
+
submitted?: boolean;
|
|
431
|
+
skipped?: boolean;
|
|
432
|
+
values?: Record<string, any>;
|
|
433
|
+
}>>;
|
|
434
|
+
/** Cleanup all active forms */
|
|
435
|
+
cleanupForms: () => void;
|
|
436
|
+
/** Callback when a UI component renders successfully */
|
|
437
|
+
onUISuccess: (toolCallId: string, toolName: string) => void;
|
|
438
|
+
/** Callback when a UI component encounters an error */
|
|
439
|
+
onUIError: (toolCallId: string, toolName: string, error: Error) => void;
|
|
440
|
+
}
|
|
441
|
+
declare function useHsafaAgent(config: UseHsafaAgentConfig): HsafaAgentAPI;
|
|
442
|
+
|
|
443
|
+
interface ChatMeta {
|
|
444
|
+
id: string;
|
|
445
|
+
title: string;
|
|
446
|
+
createdAt: number;
|
|
447
|
+
updatedAt: number;
|
|
448
|
+
}
|
|
449
|
+
interface ChatData {
|
|
450
|
+
id: string;
|
|
451
|
+
messages: ChatMessage[];
|
|
452
|
+
agentId?: string;
|
|
453
|
+
}
|
|
454
|
+
declare function createChatStorage(agentId: string): {
|
|
455
|
+
loadChatsIndex: () => ChatMeta[];
|
|
456
|
+
saveChatsIndex: (list: ChatMeta[]) => void;
|
|
457
|
+
loadChat: (id: string) => ChatData | null;
|
|
458
|
+
saveChat: (data: ChatData) => void;
|
|
459
|
+
upsertChatMeta: (meta: ChatMeta) => void;
|
|
460
|
+
deleteChatMeta: (id: string) => void;
|
|
461
|
+
deleteChatData: (id: string) => void;
|
|
462
|
+
deleteChat: (id: string) => void;
|
|
463
|
+
loadShowChatPreference: (defaultValue: boolean) => boolean;
|
|
464
|
+
saveShowChatPreference: (value: boolean) => void;
|
|
465
|
+
loadCurrentChatId: () => string | null;
|
|
466
|
+
saveCurrentChatId: (chatId: string) => void;
|
|
467
|
+
removeCurrentChatId: () => void;
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* useChatStorage - Hook for managing chat history persistence
|
|
472
|
+
*
|
|
473
|
+
* This hook provides utilities for saving and loading chat conversations
|
|
474
|
+
* to/from localStorage. It handles chat metadata, message persistence,
|
|
475
|
+
* and chat history management.
|
|
476
|
+
*
|
|
477
|
+
* @example
|
|
478
|
+
* ```tsx
|
|
479
|
+
* function MyChat() {
|
|
480
|
+
* const agent = useHsafaAgent({ agentId: 'my-agent' });
|
|
481
|
+
* const storage = useChatStorage({
|
|
482
|
+
* agentId: 'my-agent',
|
|
483
|
+
* chatId: agent.chatId,
|
|
484
|
+
* messages: agent.messages,
|
|
485
|
+
* isLoading: agent.isLoading,
|
|
486
|
+
* });
|
|
487
|
+
*
|
|
488
|
+
* return (
|
|
489
|
+
* <div>
|
|
490
|
+
* <button onClick={() => {
|
|
491
|
+
* const chat = storage.loadChat(chatId);
|
|
492
|
+
* if (chat) agent.setMessages(chat.messages);
|
|
493
|
+
* }}>
|
|
494
|
+
* Load Chat
|
|
495
|
+
* </button>
|
|
496
|
+
* <select onChange={(e) => storage.switchToChat(e.target.value, agent.setMessages)}>
|
|
497
|
+
* {storage.chatList.map(chat => (
|
|
498
|
+
* <option key={chat.id} value={chat.id}>{chat.title}</option>
|
|
499
|
+
* ))}
|
|
500
|
+
* </select>
|
|
501
|
+
* </div>
|
|
502
|
+
* );
|
|
503
|
+
* }
|
|
504
|
+
* ```
|
|
505
|
+
*/
|
|
506
|
+
|
|
507
|
+
interface UseChatStorageConfig {
|
|
508
|
+
/** The agent ID (used as storage namespace) */
|
|
509
|
+
agentId: string;
|
|
510
|
+
/** Current chat ID */
|
|
511
|
+
chatId: string;
|
|
512
|
+
/** Current messages to auto-save */
|
|
513
|
+
messages: any[];
|
|
514
|
+
/** Whether chat is currently loading (skip saving during load) */
|
|
515
|
+
isLoading?: boolean;
|
|
516
|
+
/** Whether to auto-save messages (default: true) */
|
|
517
|
+
autoSave?: boolean;
|
|
518
|
+
/** Whether to auto-restore last chat on mount (default: true) */
|
|
519
|
+
autoRestore?: boolean;
|
|
520
|
+
}
|
|
521
|
+
interface ChatMetadata {
|
|
522
|
+
id: string;
|
|
523
|
+
title: string;
|
|
524
|
+
createdAt: number;
|
|
525
|
+
updatedAt: number;
|
|
526
|
+
}
|
|
527
|
+
interface SavedChat {
|
|
528
|
+
id: string;
|
|
529
|
+
messages: any[];
|
|
530
|
+
agentId: string;
|
|
531
|
+
}
|
|
532
|
+
interface ChatStorageAPI {
|
|
533
|
+
/** List of all saved chats */
|
|
534
|
+
chatList: ChatMetadata[];
|
|
535
|
+
/** Current chat metadata */
|
|
536
|
+
currentChatMeta: ChatMetadata | null;
|
|
537
|
+
/** Refresh the chat list */
|
|
538
|
+
refreshChatList: () => void;
|
|
539
|
+
/** Load a specific chat */
|
|
540
|
+
loadChat: (chatId: string) => SavedChat | null;
|
|
541
|
+
/** Save the current chat */
|
|
542
|
+
saveCurrentChat: () => void;
|
|
543
|
+
/** Delete a chat */
|
|
544
|
+
deleteChat: (chatId: string) => void;
|
|
545
|
+
/** Switch to a different chat */
|
|
546
|
+
switchToChat: (chatId: string, setMessages: (messages: any[]) => void) => void;
|
|
547
|
+
/** Create a new chat */
|
|
548
|
+
createNewChat: (onNewChat: () => void) => void;
|
|
549
|
+
/** Search chats by title */
|
|
550
|
+
searchChats: (query: string) => ChatMetadata[];
|
|
551
|
+
/** The underlying storage utility */
|
|
552
|
+
storage: ReturnType<typeof createChatStorage>;
|
|
553
|
+
}
|
|
554
|
+
declare function useChatStorage(config: UseChatStorageConfig): ChatStorageAPI;
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* useMessageEditor - Hook for editing and regenerating messages
|
|
558
|
+
*
|
|
559
|
+
* This hook provides functionality to edit user messages and regenerate
|
|
560
|
+
* responses from a specific point in the conversation.
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* ```tsx
|
|
564
|
+
* function MyChat() {
|
|
565
|
+
* const agent = useHsafaAgent({ agentId: 'my-agent' });
|
|
566
|
+
* const editor = useMessageEditor({
|
|
567
|
+
* messages: agent.messages,
|
|
568
|
+
* isLoading: agent.isLoading,
|
|
569
|
+
* sendMessage: agent.sendMessage,
|
|
570
|
+
* setMessages: agent.setMessages,
|
|
571
|
+
* });
|
|
572
|
+
*
|
|
573
|
+
* return (
|
|
574
|
+
* <div>
|
|
575
|
+
* {agent.messages.map(msg => (
|
|
576
|
+
* <div key={msg.id}>
|
|
577
|
+
* {editor.isEditing(msg.id) ? (
|
|
578
|
+
* <div>
|
|
579
|
+
* <textarea
|
|
580
|
+
* value={editor.editingText}
|
|
581
|
+
* onChange={(e) => editor.setEditingText(e.target.value)}
|
|
582
|
+
* />
|
|
583
|
+
* <button onClick={() => editor.saveEdit(msg.id)}>Save</button>
|
|
584
|
+
* <button onClick={editor.cancelEdit}>Cancel</button>
|
|
585
|
+
* </div>
|
|
586
|
+
* ) : (
|
|
587
|
+
* <div>
|
|
588
|
+
* {msg.content}
|
|
589
|
+
* <button onClick={() => editor.startEdit(msg.id, msg.content)}>
|
|
590
|
+
* Edit
|
|
591
|
+
* </button>
|
|
592
|
+
* </div>
|
|
593
|
+
* )}
|
|
594
|
+
* </div>
|
|
595
|
+
* ))}
|
|
596
|
+
* </div>
|
|
597
|
+
* );
|
|
598
|
+
* }
|
|
599
|
+
* ```
|
|
600
|
+
*/
|
|
601
|
+
interface UseMessageEditorConfig {
|
|
602
|
+
/** Current messages array */
|
|
603
|
+
messages: any[];
|
|
604
|
+
/** Whether chat is currently loading */
|
|
605
|
+
isLoading: boolean;
|
|
606
|
+
/** Function to send a message */
|
|
607
|
+
sendMessage: (options: {
|
|
608
|
+
text: string;
|
|
609
|
+
files?: any[];
|
|
610
|
+
}) => Promise<void>;
|
|
611
|
+
/** Function to update messages array */
|
|
612
|
+
setMessages: (messages: any[]) => void;
|
|
613
|
+
/** Base URL for file uploads (if editing messages with attachments) */
|
|
614
|
+
baseUrl?: string;
|
|
615
|
+
}
|
|
616
|
+
interface MessageEditorAPI {
|
|
617
|
+
/** ID of the message currently being edited */
|
|
618
|
+
editingMessageId: string | null;
|
|
619
|
+
/** Current edit text */
|
|
620
|
+
editingText: string;
|
|
621
|
+
/** Set the edit text */
|
|
622
|
+
setEditingText: (text: string) => void;
|
|
623
|
+
/** Attachments for the edited message */
|
|
624
|
+
editAttachments: any[];
|
|
625
|
+
/** Set edit attachments */
|
|
626
|
+
setEditAttachments: (attachments: any[]) => void;
|
|
627
|
+
/** Whether files are currently uploading */
|
|
628
|
+
editUploading: boolean;
|
|
629
|
+
/** Start editing a message */
|
|
630
|
+
startEdit: (messageId: string, text: string, attachments?: any[]) => void;
|
|
631
|
+
/** Cancel editing */
|
|
632
|
+
cancelEdit: () => void;
|
|
633
|
+
/** Save the edit and regenerate from that point */
|
|
634
|
+
saveEdit: (messageId: string) => Promise<void>;
|
|
635
|
+
/** Check if a message is being edited */
|
|
636
|
+
isEditing: (messageId: string) => boolean;
|
|
637
|
+
/** Add attachments to the edit */
|
|
638
|
+
addEditAttachments: (files: FileList) => Promise<void>;
|
|
639
|
+
/** Remove an attachment from the edit */
|
|
640
|
+
removeEditAttachment: (id: string) => void;
|
|
641
|
+
}
|
|
642
|
+
declare function useMessageEditor(config: UseMessageEditorConfig): MessageEditorAPI;
|
|
643
|
+
|
|
138
644
|
/**
|
|
139
645
|
* Handler function for custom actions that can be triggered by the AI agent
|
|
140
646
|
*/
|
|
@@ -185,6 +691,16 @@ interface HsafaContextValue extends HsafaConfig {
|
|
|
185
691
|
isAnyChatOpen: boolean;
|
|
186
692
|
/** Set chat open state for a specific chat instance */
|
|
187
693
|
setChatOpenState: (chatId: string, isOpen: boolean) => void;
|
|
694
|
+
/** Currently active chat id (set by HsafaChat) */
|
|
695
|
+
currentChatId?: string;
|
|
696
|
+
/** Setter for current chat id */
|
|
697
|
+
setCurrentChatId: (chatId: string) => void;
|
|
698
|
+
/** Dynamic page types registered by active chat */
|
|
699
|
+
dynamicPageTypes: any[];
|
|
700
|
+
/** Register dynamic page types from a chat */
|
|
701
|
+
registerDynamicPageTypes: (chatId: string, types: any[]) => void;
|
|
702
|
+
/** Unregister dynamic page types when chat unmounts */
|
|
703
|
+
unregisterDynamicPageTypes: (chatId: string) => void;
|
|
188
704
|
}
|
|
189
705
|
/**
|
|
190
706
|
* Props for the HsafaProvider component
|
|
@@ -215,23 +731,13 @@ declare function HsafaProvider({ baseUrl, dir, theme, children }: HsafaProviderP
|
|
|
215
731
|
* ```tsx
|
|
216
732
|
* function MyComponent() {
|
|
217
733
|
* const { registerAction, baseUrl } = useHsafa();
|
|
218
|
-
*
|
|
219
|
-
* useEffect(() => {
|
|
220
|
-
* const unregister = registerAction('myAction', async (params) => {
|
|
221
|
-
* console.log('Action called with:', params);
|
|
222
|
-
* return { success: true };
|
|
223
|
-
* });
|
|
224
|
-
*
|
|
225
|
-
* return unregister;
|
|
226
|
-
* }, [registerAction]);
|
|
227
|
-
*
|
|
228
734
|
* return <div>My Component</div>;
|
|
229
735
|
* }
|
|
230
736
|
* ```
|
|
231
737
|
*/
|
|
232
738
|
declare function useHsafa(): HsafaContextValue;
|
|
233
739
|
|
|
234
|
-
declare function HsafaChat({ agentId, theme, primaryColor, primaryColorDark, primaryColorLight, backgroundColor, borderColor, textColor, accentColor, baseUrl, initialMessages, onMessagesChange, defaultOpen, floatingButtonPosition, HsafaTools, HsafaUI, }: HsafaChatProps & {
|
|
740
|
+
declare function HsafaChat({ agentId, theme, primaryColor, primaryColorDark, primaryColorLight, backgroundColor, borderColor, textColor, accentColor, baseUrl, initialMessages, onMessagesChange, defaultOpen, floatingButtonPosition, HsafaTools, HsafaUI, dynamicPageTypes, componentAboveInput, editProcessContent, }: HsafaChatProps & {
|
|
235
741
|
baseUrl?: string;
|
|
236
742
|
initialMessages?: any[];
|
|
237
743
|
onMessagesChange?: (messages: any[]) => void;
|
|
@@ -253,6 +759,7 @@ interface ContentContainerProps {
|
|
|
253
759
|
enableMargin?: boolean;
|
|
254
760
|
chatWidth?: number | string;
|
|
255
761
|
dir?: "ltr" | "rtl";
|
|
762
|
+
onDynamicPageError?: (error: ComponentError) => void;
|
|
256
763
|
}
|
|
257
764
|
/**
|
|
258
765
|
* ContentContainer component that wraps your content and applies animations
|
|
@@ -270,7 +777,7 @@ interface ContentContainerProps {
|
|
|
270
777
|
* <ContentContainer theme="dark" enableBorderAnimation>
|
|
271
778
|
* <YourApp />
|
|
272
779
|
* </ContentContainer>
|
|
273
|
-
* <HsafaChat agentId="agent-1" width={450} />
|
|
780
|
+
* <HsafaChat agentId="agent-1" width={450} dynamicPageTypes={types} />
|
|
274
781
|
* </HsafaProvider>
|
|
275
782
|
*
|
|
276
783
|
* // With custom chat width and RTL support
|
|
@@ -283,7 +790,7 @@ interface ContentContainerProps {
|
|
|
283
790
|
* >
|
|
284
791
|
* <YourApp />
|
|
285
792
|
* </ContentContainer>
|
|
286
|
-
* <HsafaChat agentId="agent-1" width={450} dir="rtl" />
|
|
793
|
+
* <HsafaChat agentId="agent-1" width={450} dir="rtl" dynamicPageTypes={types} />
|
|
287
794
|
* </HsafaProvider>
|
|
288
795
|
*
|
|
289
796
|
* // Disable margin (content stays full width)
|
|
@@ -291,11 +798,11 @@ interface ContentContainerProps {
|
|
|
291
798
|
* <ContentContainer enableMargin={false}>
|
|
292
799
|
* <YourApp />
|
|
293
800
|
* </ContentContainer>
|
|
294
|
-
* <HsafaChat agentId="agent-1" />
|
|
801
|
+
* <HsafaChat agentId="agent-1" dynamicPageTypes={types} />
|
|
295
802
|
* </HsafaProvider>
|
|
296
803
|
* ```
|
|
297
804
|
*/
|
|
298
|
-
declare function ContentContainer({ children, theme, primaryColor, backgroundColor, borderColor, textColor, mutedTextColor, enableBorderAnimation, borderRadius, enableContentBorder, className, enableMargin, chatWidth, dir, }: ContentContainerProps): react_jsx_runtime.JSX.Element;
|
|
805
|
+
declare function ContentContainer({ children, theme, primaryColor, backgroundColor, borderColor, textColor, mutedTextColor, enableBorderAnimation, borderRadius, enableContentBorder, className, enableMargin, chatWidth, dir, onDynamicPageError, }: ContentContainerProps): react_jsx_runtime.JSX.Element;
|
|
299
806
|
|
|
300
807
|
/**
|
|
301
808
|
* Component Registry for custom UI components
|
|
@@ -557,4 +1064,49 @@ type FillResult = {
|
|
|
557
1064
|
};
|
|
558
1065
|
declare function FillActiveInput(value: any, options?: FillInputOptions): Promise<FillResult>;
|
|
559
1066
|
|
|
560
|
-
|
|
1067
|
+
interface DynamicPageProps {
|
|
1068
|
+
state: DynamicPageState;
|
|
1069
|
+
typeConfigs: DynamicPageTypeConfig[];
|
|
1070
|
+
theme?: 'dark' | 'light';
|
|
1071
|
+
primaryColor?: string;
|
|
1072
|
+
backgroundColor?: string;
|
|
1073
|
+
borderColor?: string;
|
|
1074
|
+
textColor?: string;
|
|
1075
|
+
onError?: (error: ComponentError) => void;
|
|
1076
|
+
}
|
|
1077
|
+
declare function DynamicPage({ state, typeConfigs, theme, primaryColor, backgroundColor, borderColor, textColor, onError, }: DynamicPageProps): react_jsx_runtime.JSX.Element;
|
|
1078
|
+
|
|
1079
|
+
declare function createDynamicPageTools(getOperations: () => DynamicPageOperations | null, _addToolResult?: (payload: any) => void): {
|
|
1080
|
+
setGrid: (toolCall: any) => Promise<ToolResult>;
|
|
1081
|
+
readGrid: (toolCall: any) => Promise<ToolResult>;
|
|
1082
|
+
readAvailableTypes: () => Promise<ToolResult>;
|
|
1083
|
+
setObject: {
|
|
1084
|
+
executeEachToken: boolean;
|
|
1085
|
+
tool: (toolCall: any) => Promise<ToolResult>;
|
|
1086
|
+
};
|
|
1087
|
+
editObject: {
|
|
1088
|
+
executeEachToken: boolean;
|
|
1089
|
+
tool: (toolCall: any) => Promise<ToolResult>;
|
|
1090
|
+
};
|
|
1091
|
+
deleteObject: (toolCall: any) => Promise<ToolResult>;
|
|
1092
|
+
readAllObjects: () => Promise<ToolResult>;
|
|
1093
|
+
readObject: (toolCall: any) => Promise<ToolResult>;
|
|
1094
|
+
readAtPointer: (toolCall: any) => Promise<ToolResult>;
|
|
1095
|
+
renameObject: (toolCall: any) => Promise<ToolResult>;
|
|
1096
|
+
moveObject: (toolCall: any) => Promise<ToolResult>;
|
|
1097
|
+
validateGrid: () => Promise<ToolResult>;
|
|
1098
|
+
readComponentErrors: (toolCall: any) => Promise<ToolResult>;
|
|
1099
|
+
clearComponentErrors: () => Promise<ToolResult>;
|
|
1100
|
+
};
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Dynamic Page Storage
|
|
1104
|
+
* Manages localStorage persistence for dynamic page data linked to chat ID
|
|
1105
|
+
*/
|
|
1106
|
+
|
|
1107
|
+
declare function saveDynamicPageState(chatId: string, state: DynamicPageState): void;
|
|
1108
|
+
declare function loadDynamicPageState(chatId: string): DynamicPageState | null;
|
|
1109
|
+
declare function deleteDynamicPageState(chatId: string): void;
|
|
1110
|
+
declare function dynamicPageExists(chatId: string): boolean;
|
|
1111
|
+
|
|
1112
|
+
export { type Anchor, type Attachment, Button, type ButtonProps, type ChatMessage, type ChatMetadata, type ChatStorageAPI, type ComponentError, ContentContainer, type ContentContainerProps, CursorController, type CustomToolUIRenderProps, type DomComponent, DynamicPage, type DynamicPageGrid, type DynamicPageObject, type DynamicPageObjectMeta, DynamicPageOperations, type DynamicPageState, type DynamicPageTypeConfig, type EditProcessContent, FillActiveInput, type FillInputOptions, type FillResult, FloatingChatButton, type GetDomComponentsOptions, type GetDomComponentsResult, type GuideAction, type GuideCursorOptions, type GuideOptions, type GuideRunResult, type GuideStep, type GuideStepResult, type GuideTarget, type HsafaAgentAPI, HsafaChat, type HsafaChatProps, HsafaProvider, type HsafaTool, type MessageEditorAPI, type SavedChat, type ToolResult, type UIComponentProps, type UseChatStorageConfig, type UseHsafaAgentConfig, type UseMessageEditorConfig, registry as componentRegistry, guideCursor as controlCursor, createDynamicPageTools, deleteDynamicPageState, dynamicPageExists, getDomComponents, guideCursor, loadDynamicPageState, saveDynamicPageState, useAutoScroll, useChatStorage, useDynamicPage, useFileUpload, useHsafa, useHsafaAgent, useMessageEditor };
|