@hsafa/ui-sdk 0.1.4 → 0.1.6

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/docs/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # HSAFA UI SDK — Advanced Guide
2
+
3
+ Modern React SDK for integrating AI agents built with HSAFA AI Agent Studio into any web app. This guide covers architecture, setup, customization, streaming, actions, UI component injection, theming, i18n/RTL, persistence, and best practices.
4
+
5
+ - **Package**: `@hsafa/ui-sdk`
6
+ - **Entry point**: `sdk/src/index.ts`
7
+ - **Core building blocks**: `HsafaProvider`, `HsafaChat`, `useHsafaAction`, `useHsafaComponent`, `useHsafa`
8
+ - **Generated API reference**: `sdk/docs/api/` (TypeDoc)
9
+
10
+ ---
11
+
12
+ ## 1) Install
13
+
14
+ ```bash
15
+ pnpm add @hsafa/ui-sdk
16
+ # or
17
+ npm i @hsafa/ui-sdk
18
+ ```
19
+
20
+ Peer dependencies:
21
+ - react >= 18
22
+ - react-dom >= 18
23
+ - @tabler/icons-react (icons used by some components)
24
+
25
+ ---
26
+
27
+ ## 2) Quick start
28
+
29
+ Wrap your app with `HsafaProvider` and render `HsafaChat` anywhere. The `baseUrl` should point to your server that exposes the agent API endpoints.
30
+
31
+ ```tsx
32
+ import React from 'react';
33
+ import { HsafaProvider, HsafaChat } from '@hsafa/ui-sdk';
34
+
35
+ export default function App() {
36
+ return (
37
+ <HsafaProvider baseUrl={process.env.NEXT_PUBLIC_API_BASE || ''}>
38
+ <main style={{ height: '100vh' }}>
39
+ <HsafaChat agentId="my-agent-id" theme="dark" />
40
+ </main>
41
+ </HsafaProvider>
42
+ );
43
+ }
44
+ ```
45
+
46
+ What this does under the hood:
47
+ - Streams NDJSON from `POST {baseUrl}/api/run/:agentId` with `Accept: application/x-ndjson`.
48
+ - Uploads files to `POST {baseUrl}/api/uploads` and attaches them to prompts.
49
+ - Persists chat history and UI state in `localStorage` by `agentId`.
50
+
51
+ ---
52
+
53
+ ## 3) Architecture overview
54
+
55
+ - **Provider**: `HsafaProvider` stores SDK config and dynamic registries:
56
+ - `actions: Map<string, HsafaActionHandler>`
57
+ - `components: Map<string, React.ComponentType>`
58
+ - **Chat UI**: `HsafaChat` handles input, history, streaming, rendering of assistant responses, and attachments.
59
+ - **Streaming**: `useAgentStreaming()` parses NDJSON event stream into a structured timeline:
60
+ - `first-agent-*`, `main-agent-*` events, tool calls/results, reasoning, and final response items.
61
+ - **Action execution**: agent’s response items can include `type: 'action'`. Use `useHsafaAction()` to register handlers.
62
+ - **UI injection**: agent’s response items can include `type: 'ui'` to render custom components registered via `useHsafaComponent()`.
63
+
64
+ Server contract (by default used by `HsafaChat`):
65
+ - POST `{baseUrl}/api/run/:agentId` — streaming NDJSON
66
+ - POST `{baseUrl}/api/uploads` — file uploads
67
+
68
+ ---
69
+
70
+ ## 4) Provider API
71
+
72
+ `HsafaProvider` (see `sdk/src/providers/HsafaProvider.tsx`):
73
+ - Props:
74
+ - `baseUrl?: string` — base URL for API calls (e.g. `""` for same-origin or `"https://api.example.com"`).
75
+ - Context (`useHsafa()`):
76
+ - `baseUrl?: string`
77
+ - `actions: Map<string, HsafaActionHandler>`
78
+ - `components: Map<string, React.ComponentType<any>>`
79
+ - `registerAction(name, handler) => unregister()`
80
+ - `unregisterAction(name, handler?)`
81
+ - `registerComponent(name, component) => unregister()`
82
+ - `unregisterComponent(name, component?)`
83
+
84
+ Example using `useHsafa()` directly:
85
+ ```tsx
86
+ import { useHsafa } from '@hsafa/ui-sdk';
87
+
88
+ function Debug() {
89
+ const { actions, components, baseUrl } = useHsafa();
90
+ // inspect registries or baseUrl
91
+ return null;
92
+ }
93
+ ```
94
+
95
+ ---
96
+
97
+ ## 5) Chat component (`HsafaChat`)
98
+
99
+ Source: `sdk/src/components/HsafaChat.tsx`
100
+
101
+ Minimal usage:
102
+ ```tsx
103
+ <HsafaChat agentId="my-agent" />
104
+ ```
105
+
106
+ Important props (selected):
107
+ - `agentId: string` — required
108
+ - `theme?: 'light' | 'dark'` — default `dark`
109
+ - `language?: 'en' | 'ar'` — defaults by `dir` if not provided
110
+ - `dir?: 'ltr' | 'rtl'` — controls layout RTL/LTR
111
+ - Colors (override theme defaults): `primaryColor`, `backgroundColor`, `borderColor`, `textColor`, `accentColor`
112
+ - Layout: `width` (default 420), `height` (default `100vh`), `floatingButtonPosition`, `alwaysOpen`, `defaultOpen`, `expandable`, `maximized`
113
+ - Borders/animation: `enableBorderAnimation`, `enableContentPadding`, `enableContentBorder`, `borderRadius`
114
+ - UX copy: `placeholder`, `title`
115
+ - Advanced UI: `defaultReasoningOpen`, `hideReasoningContent`
116
+ - Styling hooks: `className`, `chatContainerClassName`
117
+ - Children: content beside the fixed chat panel (panel opens over the right/left edge)
118
+
119
+ Behavior highlights:
120
+ - Persists chat sessions under `localStorage` prefix `hsafaChat_${agentId}`.
121
+ - Supports file/image attachments with size checks and server upload.
122
+ - Streams partial updates; auto-scrolls intelligently; preserves scroll when toggling reasoning.
123
+ - Renders assistant "items" including markdown, mermaid diagrams, actions, and custom UI components.
124
+
125
+ ---
126
+
127
+ ## 6) Registering actions (agent -> app)
128
+
129
+ Use `useHsafaAction(name, handler)` to make functions callable by the agent. The handler receives `(params, meta)` where `meta` includes the `trigger` type:
130
+ - `'partial'` — called during streaming (when explicitly enabled by the agent/SDK logic)
131
+ - `'params_complete'` — parameters stabilized mid-stream (debounced and deduped)
132
+ - `'final'` — after finalization
133
+
134
+ ```tsx
135
+ import { useHsafaAction } from '@hsafa/ui-sdk';
136
+
137
+ export function CartActions() {
138
+ useHsafaAction('addToCart', async (params, meta) => {
139
+ // params: arbitrary JSON inferred by the agent
140
+ // meta: { name, trigger, index, assistantMessageId?, chatId? }
141
+ await fetch('/api/cart', { method: 'POST', body: JSON.stringify(params) });
142
+ return { success: true };
143
+ });
144
+ return null;
145
+ }
146
+ ```
147
+
148
+ Advanced execution behavior is implemented in `useActions()` / `useStreaming()` (parameter stabilization, debouncing, final guarantees). For most apps, just register via `useHsafaAction()`.
149
+
150
+ ---
151
+
152
+ ## 7) Registering UI components (agent-rendered UI)
153
+
154
+ Use `useHsafaComponent(name, Component)` to expose UI that the agent can render with an item of shape `{ type: 'ui', component: name, props: {...} }`.
155
+
156
+ ```tsx
157
+ import { useHsafaComponent } from '@hsafa/ui-sdk';
158
+
159
+ function ProductCard({ name, price }: { name: string; price: number }) {
160
+ return <div>{name}: ${price}</div>;
161
+ }
162
+
163
+ export function UIRegistry() {
164
+ useHsafaComponent('ProductCard', ProductCard);
165
+ return null;
166
+ }
167
+ ```
168
+
169
+ If an agent returns an unregistered component name, `HsafaChat` will render a helpful placeholder with the props payload so you can register it.
170
+
171
+ Relevant renderer: `sdk/src/components/AssistantMessageItems.tsx`.
172
+
173
+ ---
174
+
175
+ ## 8) What does the assistant response look like?
176
+
177
+ `HsafaChat` expects a streaming sequence from the server that ultimately yields a `response` with `items`:
178
+ - Strings are rendered as Markdown (`MarkdownRendererWithMermaid`).
179
+ - Objects with `type: 'ui'` render registered components via the provider registry.
180
+ - Objects with `type: 'action'` show execution status and trigger corresponding action handlers.
181
+ - Tool calls/results and reasoning are also visualized.
182
+
183
+ Example of a single final item payload (simplified):
184
+ ```json
185
+ {
186
+ "type": "ui",
187
+ "component": "ProductCard",
188
+ "props": { "name": "Laptop", "price": 1299 }
189
+ }
190
+ ```
191
+
192
+ ---
193
+
194
+ ## 9) Theming & styling
195
+
196
+ Theme presets (`light`/`dark`) with overridable colors. See `sdk/src/utils/chat-theme.ts`.
197
+
198
+ - Preset colors: `primaryColor`, `backgroundColor`, `borderColor`, `textColor`, `accentColor`, plus `mutedTextColor`, `inputBackground`, `cardBackground`, `hoverBackground` (derived).
199
+ - Override via `HsafaChat` props:
200
+
201
+ ```tsx
202
+ <HsafaChat
203
+ agentId="my-agent"
204
+ theme="light"
205
+ primaryColor="#3b82f6"
206
+ backgroundColor="#ffffff"
207
+ borderColor="#e5e7eb"
208
+ textColor="#111827"
209
+ accentColor="#F9FAFB"
210
+ />
211
+ ```
212
+
213
+ Markdown with Mermaid is supported via `MarkdownRenderer` / `MarkdownRendererWithMermaid` and `MermaidDiagram`.
214
+
215
+ ---
216
+
217
+ ## 10) i18n and RTL
218
+
219
+ - Supported languages: `'en' | 'ar'` (see `sdk/src/i18n/translations.ts`).
220
+ - You can pass `language` and/or `dir` to `HsafaChat`:
221
+
222
+ ```tsx
223
+ <HsafaChat agentId="my-agent" language="ar" dir="rtl" />
224
+ ```
225
+
226
+ Common UI strings for input/header/history are localized. You can still override `placeholder` and `title` directly.
227
+
228
+ ---
229
+
230
+ ## 11) Persistence & storage
231
+
232
+ `HsafaChat` uses `useChatStorage(agentId)` to persist:
233
+ - Chats index and message history under `localStorage` key prefix `hsafaChat_${agentId}`.
234
+ - Current chat ID and chat visibility (`.currentChatId`, `.showChat`).
235
+
236
+ Key API (see `sdk/src/hooks/useChatStorage.ts`):
237
+ - `createNewChat(firstMessage?)` — returns new chat id
238
+ - `persistChatData(messages)` — saves messages + updates meta
239
+ - `loadChatsIndex()`, `loadChat(id)`, `deleteChat(id, cb)`
240
+
241
+ ---
242
+
243
+ ## 12) Attachments & uploads
244
+
245
+ `HsafaChat` integrates `useFileUpload(baseUrl)` which:
246
+ - Validates size (default 25MB) and uploads to `{baseUrl}/api/uploads`.
247
+ - Adds uploaded assets to the user message content as `image` or `file` parts.
248
+
249
+ Server is expected to return:
250
+ ```json
251
+ { "id": "file-id", "name": "foo.png", "url": "https://...", "mimeType": "image/png", "size": 12345 }
252
+ ```
253
+
254
+ ---
255
+
256
+ ## 13) Streaming contract (server)
257
+
258
+ The server should stream NDJSON lines with event `type` keys consumed by `useAgentStreaming()` (see `sdk/src/hooks/useAgentStreaming.ts`). Common events include:
259
+ - `first-agent-start|partial|end`
260
+ - `main-agent-start|skipped|reasoning-start|reasoning-delta|reasoning-end`
261
+ - `main-agent-tool-call-start|tool-call|tool-result|tool-error`
262
+ - `main-agent-response-partial` (with `value.items`)
263
+ - `text-delta|text-end`
264
+ - `final` (with `value.items`)
265
+ - `error`
266
+
267
+ You can adopt any LLM/tooling backend as long as you conform to the above event stream and endpoints.
268
+
269
+ ---
270
+
271
+ ## 14) Full example
272
+
273
+ See ready-to-run examples in `sdk/examples/`:
274
+ - `getting-started.tsx`
275
+ - `ecommerce-agent.tsx`
276
+ - `nested-chat-example.tsx`
277
+
278
+ A minimal page:
279
+ ```tsx
280
+ import { HsafaProvider, HsafaChat, useHsafaAction, useHsafaComponent } from '@hsafa/ui-sdk';
281
+
282
+ function Registry() {
283
+ useHsafaAction('notify', async (params) => {
284
+ console.log('Notify', params);
285
+ });
286
+ useHsafaComponent('ProductCard', (p: any) => <div>{p.name}: ${p.price}</div>);
287
+ return null;
288
+ }
289
+
290
+ export default function Page() {
291
+ return (
292
+ <HsafaProvider baseUrl="">
293
+ <Registry />
294
+ <HsafaChat agentId="my-agent" theme="dark" />
295
+ </HsafaProvider>
296
+ );
297
+ }
298
+ ```
299
+
300
+ ---
301
+
302
+ ## 15) Troubleshooting
303
+
304
+ - Ensure your server responds to `POST /api/run/:agentId` with `Content-Type: application/x-ndjson` and streams events, not a single JSON.
305
+ - If attachments fail, verify `POST /api/uploads` exists and returns the required JSON fields.
306
+ - Unregistered UI component? Check the `component` name in items and make sure you called `useHsafaComponent(name, Comp)` under the same `HsafaProvider`.
307
+ - Actions not firing? Confirm the action name matches and that the agent actually emits `type: 'action'` items. Check browser console warnings from `useActions()`/`useStreaming()`.
308
+
309
+ ---
310
+
311
+ ## 16) API reference
312
+
313
+ The full API is generated from TypeScript types. Start here:
314
+ - `sdk/docs/api/README.md`
315
+ - `sdk/docs/api/functions/HsafaChat.md`
316
+ - `sdk/docs/api/functions/HsafaProvider.md`
317
+ - `sdk/docs/api/functions/useHsafa.md`
318
+ - `sdk/docs/api/functions/useHsafaAction.md`
319
+ - `sdk/docs/api/functions/useHsafaComponent.md`
320
+
321
+ ---
322
+
323
+ ## 17) License & links
324
+
325
+ - License: MIT
326
+ - Repo: https://github.com/husamabusafa/hsafa/tree/main/sdk
327
+ - Issues: https://github.com/husamabusafa/hsafa/issues
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hsafa/ui-sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "React SDK for integrating AI agents built with HSAFA AI Agent Studio",
5
5
  "type": "module",
6
6
  "files": [