@hsafa/ui-sdk 0.1.2 → 0.1.4

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.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import * as React from 'react';
2
- import React__default, { ComponentType } from 'react';
1
+ import * as react from 'react';
2
+ import react__default, { ComponentType } from 'react';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
5
  /**
6
6
  * Props for the Button component
7
7
  */
8
- interface ButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
8
+ interface ButtonProps extends react__default.ButtonHTMLAttributes<HTMLButtonElement> {
9
9
  /** Visual style variant of the button */
10
10
  variant?: "primary" | "secondary" | "outline" | "ghost";
11
11
  /** Size of the button */
@@ -13,7 +13,7 @@ interface ButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElem
13
13
  /** Whether the button is in a loading state */
14
14
  loading?: boolean;
15
15
  /** Content to be displayed inside the button */
16
- children: React__default.ReactNode;
16
+ children: react__default.ReactNode;
17
17
  }
18
18
  /**
19
19
  * A versatile button component with multiple variants, sizes, and states.
@@ -33,7 +33,268 @@ interface ButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElem
33
33
  * <Button onClick={() => console.log('Clicked!')}>Click me</Button>
34
34
  * ```
35
35
  */
36
- declare const Button: React__default.FC<ButtonProps>;
36
+ declare const Button: react__default.FC<ButtonProps>;
37
+
38
+ /**
39
+ * Vercel AI SDK compatible message types
40
+ * Based on https://sdk.vercel.ai/docs/ai-sdk-core/messages
41
+ */
42
+ type TextPart = {
43
+ type: 'text';
44
+ text: string;
45
+ };
46
+ type ImagePart = {
47
+ type: 'image';
48
+ image: string | URL;
49
+ mediaType?: string;
50
+ };
51
+ type FilePart = {
52
+ type: 'file';
53
+ data: string | URL;
54
+ mediaType: string;
55
+ name?: string;
56
+ };
57
+ type UserContentPart = TextPart | ImagePart | FilePart;
58
+ type AssistantTextPart = {
59
+ type: 'text';
60
+ text: string;
61
+ };
62
+ type ReasoningPart = {
63
+ type: 'reasoning';
64
+ text: string;
65
+ };
66
+ type AssistantFilePart = {
67
+ type: 'file';
68
+ data: string | URL;
69
+ mediaType: string;
70
+ filename?: string;
71
+ };
72
+ type ToolCallPart = {
73
+ type: 'tool-call';
74
+ toolCallId: string;
75
+ toolName: string;
76
+ input: any;
77
+ };
78
+ type AssistantContentPart = AssistantTextPart | ReasoningPart | AssistantFilePart | ToolCallPart;
79
+ interface Attachment {
80
+ id: string;
81
+ name: string;
82
+ url: string;
83
+ mimeType: string;
84
+ size: number;
85
+ }
86
+
87
+ /**
88
+ * Type definitions for the HsafaChat component
89
+ */
90
+
91
+ type MainAgentAction$1 = {
92
+ type: 'reasoning';
93
+ reasoning: string;
94
+ status: 'streaming' | 'finished';
95
+ startDate?: number;
96
+ endDate?: number;
97
+ durationMs?: number;
98
+ } | {
99
+ type: 'tool-call';
100
+ toolCallId?: string;
101
+ toolName?: string;
102
+ input?: any;
103
+ inputText?: string;
104
+ output?: any;
105
+ status: 'input_streaming' | 'running' | 'finished' | 'error';
106
+ error?: string;
107
+ startDate?: number;
108
+ endDate?: number;
109
+ durationMs?: number;
110
+ } | {
111
+ type: 'step';
112
+ stepNumber?: number;
113
+ finishReason?: string;
114
+ usage?: any;
115
+ startDate?: number;
116
+ endDate?: number;
117
+ durationMs?: number;
118
+ } | {
119
+ type: 'text';
120
+ text: string;
121
+ status: 'streaming' | 'finished';
122
+ startDate?: number;
123
+ endDate?: number;
124
+ durationMs?: number;
125
+ } | {
126
+ type: 'source';
127
+ source: any;
128
+ durationMs?: number;
129
+ } | {
130
+ type: 'file';
131
+ file: any;
132
+ durationMs?: number;
133
+ } | {
134
+ type: 'response';
135
+ items: any[];
136
+ [key: string]: any;
137
+ startDate?: number;
138
+ endDate?: number;
139
+ durationMs?: number;
140
+ };
141
+ type ChatMessage = {
142
+ id: string;
143
+ role: 'user';
144
+ content: string | UserContentPart[];
145
+ createdAt?: number;
146
+ text?: string;
147
+ attachments?: Attachment[];
148
+ } | {
149
+ id: string;
150
+ role: 'assistant';
151
+ content?: string | AssistantContentPart[];
152
+ items: any[];
153
+ reasoning?: string;
154
+ reasoningOpen?: boolean;
155
+ reasoningTokens?: number;
156
+ createdAt?: number;
157
+ requestParams?: any;
158
+ mcpToolCalls?: Array<{
159
+ toolName: string;
160
+ args: any;
161
+ timestamp: number;
162
+ status?: 'pending' | 'running' | 'completed' | 'failed';
163
+ }>;
164
+ mcpToolResults?: Record<string, any>;
165
+ mainAgentActions?: MainAgentAction$1[];
166
+ firstAgentMessage?: string;
167
+ firstAgentContinue?: boolean;
168
+ autoGenerated?: boolean;
169
+ hidden?: boolean;
170
+ turnIndex?: number;
171
+ controlDecision?: 'continue' | 'done';
172
+ followUpPrompt?: string;
173
+ };
174
+ interface HsafaChatProps {
175
+ agentId: string;
176
+ children?: React.ReactNode;
177
+ theme?: 'dark' | 'light';
178
+ primaryColor?: string;
179
+ backgroundColor?: string;
180
+ borderColor?: string;
181
+ textColor?: string;
182
+ accentColor?: string;
183
+ width?: number | string;
184
+ maxWidth?: number | string;
185
+ height?: string;
186
+ expandable?: boolean;
187
+ alwaysOpen?: boolean;
188
+ defaultOpen?: boolean;
189
+ floatingButtonPosition?: {
190
+ bottom?: number | string;
191
+ right?: number | string;
192
+ top?: number | string;
193
+ left?: number | string;
194
+ };
195
+ enableBorderAnimation?: boolean;
196
+ enableContentPadding?: boolean;
197
+ borderRadius?: number | string;
198
+ enableContentBorder?: boolean;
199
+ placeholder?: string;
200
+ title?: string;
201
+ className?: string;
202
+ chatContainerClassName?: string;
203
+ dir?: 'rtl' | 'ltr';
204
+ language?: 'en' | 'ar';
205
+ defaultReasoningOpen?: boolean;
206
+ hideReasoningContent?: boolean;
207
+ }
208
+
209
+ declare const themeColors: {
210
+ dark: {
211
+ primaryColor: string;
212
+ backgroundColor: string;
213
+ borderColor: string;
214
+ textColor: string;
215
+ accentColor: string;
216
+ mutedTextColor: string;
217
+ inputBackground: string;
218
+ cardBackground: string;
219
+ hoverBackground: string;
220
+ };
221
+ light: {
222
+ primaryColor: string;
223
+ backgroundColor: string;
224
+ borderColor: string;
225
+ textColor: string;
226
+ accentColor: string;
227
+ mutedTextColor: string;
228
+ inputBackground: string;
229
+ cardBackground: string;
230
+ hoverBackground: string;
231
+ };
232
+ };
233
+ type ThemeColors = typeof themeColors.dark;
234
+
235
+ type TranslationKeys = {
236
+ 'header.maximize': string;
237
+ 'header.minimize': string;
238
+ 'header.new': string;
239
+ 'header.history': string;
240
+ 'header.close': string;
241
+ 'input.placeholder': string;
242
+ 'input.attachFiles': string;
243
+ 'input.insertLink': string;
244
+ 'input.send': string;
245
+ 'input.stop': string;
246
+ 'input.uploadingFiles': string;
247
+ 'input.previewImage': string;
248
+ 'input.removeFile': string;
249
+ 'editor.cancel': string;
250
+ 'editor.saveAndRegenerate': string;
251
+ 'editor.clickToEdit': string;
252
+ 'messages.empty': string;
253
+ 'messages.error': string;
254
+ 'history.search': string;
255
+ 'history.noChatsFound': string;
256
+ 'history.untitledChat': string;
257
+ 'history.deleteChat': string;
258
+ 'general.agent': string;
259
+ };
260
+
261
+ interface MessageListProps {
262
+ messages: ChatMessage[];
263
+ streaming: boolean;
264
+ editingMessageId: string | null;
265
+ editingMessageText: string;
266
+ editingAttachments?: Attachment[];
267
+ error: string | null;
268
+ actionStatuses: Map<string, 'executing' | 'executed'>;
269
+ components: Map<string, react__default.ComponentType<any>>;
270
+ theme: 'light' | 'dark';
271
+ resolvedColors: ThemeColors;
272
+ onEditingTextChange: (text: string) => void;
273
+ onRemoveAttachment?: (id: string) => void;
274
+ onAddAttachments?: (files: FileList) => void;
275
+ uploading?: boolean;
276
+ onStartEdit: (messageId: string, text: string) => void;
277
+ onCancelEdit: () => void;
278
+ onSaveEdit: (messageId: string, text: string) => void;
279
+ onToggleReasoning: (messageId: string) => void;
280
+ scrollAnchorRef: react__default.RefObject<HTMLDivElement>;
281
+ hideReasoningContent?: boolean;
282
+ t: (key: keyof TranslationKeys) => string;
283
+ }
284
+ declare function MessageList({ messages, streaming, editingMessageId, editingMessageText, editingAttachments, error, actionStatuses, components, theme, resolvedColors, onEditingTextChange, onRemoveAttachment, onAddAttachments, uploading, onStartEdit, onCancelEdit, onSaveEdit, onToggleReasoning, scrollAnchorRef, hideReasoningContent, t }: MessageListProps): react_jsx_runtime.JSX.Element;
285
+
286
+ interface FloatingChatButtonProps {
287
+ show: boolean;
288
+ onClick: () => void;
289
+ resolvedColors: ThemeColors;
290
+ floatingButtonPosition: {
291
+ bottom?: number | string;
292
+ right?: number | string;
293
+ top?: number | string;
294
+ left?: number | string;
295
+ };
296
+ }
297
+ declare function FloatingChatButton({ show, onClick, resolvedColors, floatingButtonPosition }: FloatingChatButtonProps): react_jsx_runtime.JSX.Element | null;
37
298
 
38
299
  interface UseToggleReturn {
39
300
  /** Current toggle state */
@@ -54,7 +315,7 @@ interface UseToggleReturn {
54
315
  */
55
316
  declare function useToggle(initial?: boolean): UseToggleReturn;
56
317
 
57
- declare function useAutoScroll<T extends HTMLElement>(): React.MutableRefObject<T | null>;
318
+ declare function useAutoScroll<T extends HTMLElement>(): react.MutableRefObject<T | null>;
58
319
 
59
320
  /**
60
321
  * Handler function for custom actions that can be triggered by the AI agent
@@ -85,22 +346,22 @@ interface HsafaContextValue extends HsafaConfig {
85
346
  /** Registered custom actions */
86
347
  actions: Map<string, HsafaActionHandler>;
87
348
  /** Registered custom components */
88
- components: Map<string, React__default.ComponentType<any>>;
349
+ components: Map<string, react__default.ComponentType<any>>;
89
350
  /** Register a custom action handler */
90
351
  registerAction: (name: string, handler: HsafaActionHandler) => () => void;
91
352
  /** Unregister a custom action handler */
92
353
  unregisterAction: (name: string, handler?: HsafaActionHandler) => void;
93
354
  /** Register a custom component */
94
- registerComponent: (name: string, component: React__default.ComponentType<any>) => () => void;
355
+ registerComponent: (name: string, component: react__default.ComponentType<any>) => () => void;
95
356
  /** Unregister a custom component */
96
- unregisterComponent: (name: string, component?: React__default.ComponentType<any>) => void;
357
+ unregisterComponent: (name: string, component?: react__default.ComponentType<any>) => void;
97
358
  }
98
359
  /**
99
360
  * Props for the HsafaProvider component
100
361
  */
101
362
  interface HsafaProviderProps extends HsafaConfig {
102
363
  /** Child components that will have access to the Hsafa context */
103
- children: React__default.ReactNode;
364
+ children: react__default.ReactNode;
104
365
  }
105
366
  /**
106
367
  * Provider component that sets up the Hsafa context for the SDK.
@@ -143,46 +404,180 @@ declare function useHsafa(): HsafaContextValue;
143
404
  /**
144
405
  * Register an action handler by name within the nearest HsafaProvider.
145
406
  * The handler will be automatically unregistered on unmount.
407
+ *
408
+ * @param name - Unique name for the action
409
+ * @param handler - Function to execute when action is triggered
410
+ *
411
+ * @example
412
+ * ```tsx
413
+ * useHsafaAction('submitForm', async (params, meta) => {
414
+ * console.log('Form submitted:', params);
415
+ * return { success: true };
416
+ * });
417
+ * ```
146
418
  */
147
419
  declare function useHsafaAction(name: string, handler: HsafaActionHandler): void;
148
420
 
149
421
  /**
150
422
  * Register a UI component by name within the nearest HsafaProvider.
151
423
  * The component will be automatically unregistered on unmount.
424
+ *
425
+ * @param name - Unique name for the component (matches agent's component field)
426
+ * @param component - React component to render when agent requests this component
427
+ *
428
+ * @example
429
+ * ```tsx
430
+ * function ProductCard({ name, price }: { name: string; price: number }) {
431
+ * return <div>{name}: ${price}</div>;
432
+ * }
433
+ *
434
+ * useHsafaComponent('ProductCard', ProductCard);
435
+ * ```
152
436
  */
153
- declare function useHsafaComponent(name: string, component: ComponentType<any>): void;
437
+ declare function useHsafaComponent<T = any>(name: string, component: ComponentType<T>): void;
154
438
 
155
- interface HsafaChatProps {
156
- agentId: string;
157
- children?: React__default.ReactNode;
158
- theme?: 'dark' | 'light';
159
- primaryColor?: string;
160
- backgroundColor?: string;
161
- borderColor?: string;
162
- textColor?: string;
163
- accentColor?: string;
164
- width?: number | string;
165
- maxWidth?: number | string;
166
- height?: string;
167
- expandable?: boolean;
168
- alwaysOpen?: boolean;
169
- defaultOpen?: boolean;
170
- floatingButtonPosition?: {
171
- bottom?: number | string;
172
- right?: number | string;
173
- top?: number | string;
174
- left?: number | string;
175
- };
176
- enableBorderAnimation?: boolean;
177
- enableContentPadding?: boolean;
178
- borderRadius?: number | string;
179
- enableContentBorder?: boolean;
180
- placeholder?: string;
181
- title?: string;
182
- className?: string;
183
- chatContainerClassName?: string;
184
- dir?: 'rtl' | 'ltr';
439
+ interface ChatMeta {
440
+ id: string;
441
+ title: string;
442
+ createdAt: number;
443
+ updatedAt: number;
185
444
  }
186
- declare function HsafaChat({ agentId, children, theme, primaryColor, backgroundColor, borderColor, textColor, accentColor, width, maxWidth, height, expandable, alwaysOpen, defaultOpen, dir, floatingButtonPosition, enableBorderAnimation, enableContentPadding, borderRadius, enableContentBorder, placeholder, title, className, chatContainerClassName }: HsafaChatProps): react_jsx_runtime.JSX.Element;
445
+ interface ChatData {
446
+ id: string;
447
+ messages: ChatMessage[];
448
+ agentId?: string;
449
+ }
450
+ declare function useChatStorage(agentId: string): {
451
+ currentChatId: string | null;
452
+ setCurrentChatId: react.Dispatch<react.SetStateAction<string | null>>;
453
+ hasChatRecordRef: react.MutableRefObject<boolean>;
454
+ pendingFirstTitleRef: react.MutableRefObject<string | null>;
455
+ loadChatsIndex: () => ChatMeta[];
456
+ loadChat: (id: string) => ChatData | null;
457
+ saveChat: (data: ChatData) => void;
458
+ deleteChat: (id: string, onChatDeleted?: (wasCurrentChat: boolean) => void) => void;
459
+ loadChatPreferences: () => ChatMessage[];
460
+ persistChatData: (messages: ChatMessage[]) => void;
461
+ createNewChat: (firstMessage?: string) => string;
462
+ upsertChatMeta: (meta: ChatMeta) => void;
463
+ showChatKey: string;
464
+ };
465
+
466
+ declare function useStreaming(): {
467
+ streaming: boolean;
468
+ setStreaming: react.Dispatch<react.SetStateAction<boolean>>;
469
+ error: string | null;
470
+ setError: react.Dispatch<react.SetStateAction<string | null>>;
471
+ actionStatuses: Map<string, "executing" | "executed">;
472
+ setActionStatuses: react.Dispatch<react.SetStateAction<Map<string, "executing" | "executed">>>;
473
+ abortControllerRef: react.MutableRefObject<AbortController | null>;
474
+ actionExecMapRef: react.MutableRefObject<Record<string, boolean>>;
475
+ assistantMsgIdRef: react.MutableRefObject<string | undefined>;
476
+ calledFinalActionsRef: react.MutableRefObject<Set<string>>;
477
+ actionParamsHistoryRef: react.MutableRefObject<Map<string, any[]>>;
478
+ actionExecutionStatusRef: react.MutableRefObject<Map<string, "executing" | "executed">>;
479
+ processActions: (items: any[] | undefined, trigger: "partial" | "final", actions: Map<string, any>, currentChatId: string | null) => void;
480
+ handleStop: () => void;
481
+ resetActionTracking: () => void;
482
+ cleanupTimeouts: () => void;
483
+ hasActionParamsStabilized: (actionKey: string, currentParams: any) => boolean;
484
+ };
485
+
486
+ declare function useFileUpload(baseUrl: string): {
487
+ attachments: Attachment[];
488
+ uploading: boolean;
489
+ fileInputRef: react.MutableRefObject<HTMLInputElement | null>;
490
+ formatBytes: (bytes: number) => string;
491
+ handleRemoveAttachment: (id: string) => void;
492
+ handleFileSelection: (fileList: FileList | File[] | null, setError: (error: string | null) => void) => Promise<void>;
493
+ buildUserContent: (text: string, attachments: Attachment[]) => any[];
494
+ clearAttachments: () => void;
495
+ MAX_UPLOAD_SIZE: number;
496
+ };
497
+
498
+ /**
499
+ * Types matching the structure from getAgentStreamingResponse
500
+ */
501
+ type FirstAgentData = {
502
+ message: string;
503
+ continue: boolean;
504
+ startDate?: number;
505
+ endDate?: number;
506
+ durationMs?: number;
507
+ };
508
+ type MainAgentAction = {
509
+ type: 'reasoning';
510
+ reasoning: string;
511
+ status: 'streaming' | 'finished';
512
+ startDate?: number;
513
+ endDate?: number;
514
+ durationMs?: number;
515
+ } | {
516
+ type: 'tool-call';
517
+ toolCallId?: string;
518
+ toolName?: string;
519
+ input?: any;
520
+ inputText?: string;
521
+ output?: any;
522
+ status: 'input_streaming' | 'running' | 'finished' | 'error';
523
+ error?: string;
524
+ startDate?: number;
525
+ endDate?: number;
526
+ durationMs?: number;
527
+ } | {
528
+ type: 'step';
529
+ stepNumber?: number;
530
+ finishReason?: string;
531
+ usage?: any;
532
+ startDate?: number;
533
+ endDate?: number;
534
+ durationMs?: number;
535
+ } | {
536
+ type: 'text';
537
+ text: string;
538
+ status: 'streaming' | 'finished';
539
+ startDate?: number;
540
+ endDate?: number;
541
+ durationMs?: number;
542
+ } | {
543
+ type: 'source';
544
+ source: any;
545
+ durationMs?: number;
546
+ } | {
547
+ type: 'file';
548
+ file: any;
549
+ durationMs?: number;
550
+ } | {
551
+ type: 'response';
552
+ items: any[];
553
+ [key: string]: any;
554
+ startDate?: number;
555
+ endDate?: number;
556
+ durationMs?: number;
557
+ };
558
+ type AgentStreamData = {
559
+ first_agent: FirstAgentData;
560
+ main_agent: MainAgentAction[];
561
+ };
562
+ /**
563
+ * Hook to handle agent streaming responses
564
+ * Returns streaming state and a function to start streaming
565
+ */
566
+ declare function useAgentStreaming(): {
567
+ streaming: boolean;
568
+ error: string | null;
569
+ streamData: AgentStreamData | null;
570
+ startStreaming: ({ agentId, body, baseUrl, onUpdate, signal, }: {
571
+ agentId: string;
572
+ body: any;
573
+ baseUrl?: string;
574
+ onUpdate?: (data: AgentStreamData) => void;
575
+ signal?: AbortSignal;
576
+ }) => Promise<AgentStreamData | null>;
577
+ stopStreaming: () => void;
578
+ reset: () => void;
579
+ };
580
+
581
+ declare function HsafaChat(props: HsafaChatProps): react_jsx_runtime.JSX.Element;
187
582
 
188
- export { Button, type ButtonProps, HsafaChat, HsafaProvider, type UseToggleReturn, useAutoScroll, useHsafa, useHsafaAction, useHsafaComponent, useToggle };
583
+ export { type AgentStreamData, Button, type ButtonProps, type ChatData, type ChatMeta, type FirstAgentData, FloatingChatButton, HsafaChat, HsafaProvider, type MainAgentAction, MessageList, type UseToggleReturn, useAgentStreaming, useAutoScroll, useChatStorage, useFileUpload, useHsafa, useHsafaAction, useHsafaComponent, useStreaming, useToggle };