@syncagent/react 0.1.9 → 0.2.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 +116 -112
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,9 +8,7 @@ React SDK for [SyncAgent](https://syncagent.dev) — drop-in AI database chat wi
|
|
|
8
8
|
npm install @syncagent/react @syncagent/js
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
The fastest way to add an AI assistant to your app:
|
|
11
|
+
## Quick Start
|
|
14
12
|
|
|
15
13
|
```tsx
|
|
16
14
|
import { SyncAgentChat } from "@syncagent/react";
|
|
@@ -21,85 +19,103 @@ export default function App() {
|
|
|
21
19
|
config={{
|
|
22
20
|
apiKey: "sa_your_api_key",
|
|
23
21
|
connectionString: process.env.DATABASE_URL,
|
|
22
|
+
// baseUrl: "http://localhost:3100", // dev only
|
|
24
23
|
}}
|
|
25
24
|
/>
|
|
26
25
|
);
|
|
27
26
|
}
|
|
28
27
|
```
|
|
29
28
|
|
|
30
|
-
This renders a floating chat button (bottom-right) that opens a chat panel. Your database URL is sent at runtime and never stored on SyncAgent servers.
|
|
31
|
-
|
|
32
29
|
## `<SyncAgentChat>` Props
|
|
33
30
|
|
|
34
|
-
| Prop | Type | Default
|
|
35
|
-
| ---------------- | --------------------------------- |
|
|
36
|
-
| `config` | `SyncAgentConfig` | Required*
|
|
37
|
-
| `mode` | `"floating" \| "inline"` | `"floating"`
|
|
38
|
-
| `position` | `"bottom-right" \| "bottom-left"` | `"bottom-right"`
|
|
39
|
-
| `defaultOpen` | `boolean` | `false`
|
|
40
|
-
| `title` | `string` | `"
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
|
|
47
|
-
|
|
31
|
+
| Prop | Type | Default | Description |
|
|
32
|
+
| ---------------- | --------------------------------- | -------------------------- | ------------------------------------------------ |
|
|
33
|
+
| `config` | `SyncAgentConfig` | Required* | API key, connection string, tools, baseUrl |
|
|
34
|
+
| `mode` | `"floating" \| "inline"` | `"floating"` | Floating FAB or embedded inline panel |
|
|
35
|
+
| `position` | `"bottom-right" \| "bottom-left"` | `"bottom-right"` | FAB position (floating mode only) |
|
|
36
|
+
| `defaultOpen` | `boolean` | `false` | Start with the panel open |
|
|
37
|
+
| `title` | `string` | `"SyncAgent"` | Header title |
|
|
38
|
+
| `subtitle` | `string` | `"AI Database Assistant"` | Header subtitle (replaced by status while active)|
|
|
39
|
+
| `placeholder` | `string` | `"Ask anything..."` | Input placeholder |
|
|
40
|
+
| `welcomeMessage` | `string` | `"Hi! I can query..."` | Empty state message |
|
|
41
|
+
| `accentColor` | `string` | `"#10b981"` | Brand color for header, FAB, send button |
|
|
42
|
+
| `suggestions` | `string[]` | `["Show all records", ...]`| Quick-start suggestion chips |
|
|
43
|
+
| `persistKey` | `string` | — | localStorage key for conversation persistence |
|
|
44
|
+
| `context` | `Record<string, any>` | — | Extra context injected into every message |
|
|
45
|
+
| `onReaction` | `(idx, reaction, content) => void`| — | Called when user reacts 👍/👎 to a message |
|
|
46
|
+
| `onData` | `(data: ToolData) => void` | — | Called when a DB tool returns structured data |
|
|
47
|
+
| `className` | `string` | — | CSS class on the panel container |
|
|
48
|
+
| `style` | `CSSProperties` | — | Inline styles on the panel container |
|
|
49
|
+
|
|
50
|
+
*`config` is required unless wrapped in `<SyncAgentProvider>`.
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- **Live status** — header subtitle shows `● Querying users...` while the agent works
|
|
55
|
+
- **Markdown rendering** — tables, code blocks, bold, italic, lists, headers
|
|
56
|
+
- **Streaming cursor** — blinking cursor while text streams in
|
|
57
|
+
- **Copy button** — on every AI response
|
|
58
|
+
- **Reactions** — 👍/👎 on AI messages, fires `onReaction`
|
|
59
|
+
- **Retry** — retry button on failed messages
|
|
60
|
+
- **Conversation persistence** — pass `persistKey` to save history to localStorage
|
|
61
|
+
- **New conversation** — "New" button in header clears history
|
|
62
|
+
- **Suggestion chips** — configurable quick-start prompts, with pin/unpin to localStorage
|
|
63
|
+
- **Query history** — ↑/↓ in input to cycle through previous messages
|
|
64
|
+
- **Export CSV** — "⬇ CSV" button on messages containing markdown tables
|
|
65
|
+
- **Bar charts** — auto-renders aggregation results as a mini bar chart
|
|
66
|
+
- **Resize handle** — drag the top edge to resize the floating panel
|
|
67
|
+
- **Mobile responsive** — full-width on small screens
|
|
68
|
+
- **Dark mode** — respects `prefers-color-scheme`
|
|
69
|
+
|
|
70
|
+
## Conversation Persistence
|
|
48
71
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
| `tools` | `Record<string, ToolDefinition>` | — | Custom tools the agent can call client-side |
|
|
72
|
+
```tsx
|
|
73
|
+
<SyncAgentChat
|
|
74
|
+
config={{ apiKey: "...", connectionString: "..." }}
|
|
75
|
+
persistKey="project-123" // unique per project/user
|
|
76
|
+
/>
|
|
77
|
+
```
|
|
56
78
|
|
|
57
|
-
|
|
79
|
+
History saves to `localStorage` under `sa_chat_project-123`. The "New" button clears it.
|
|
58
80
|
|
|
59
|
-
|
|
81
|
+
## Context injection
|
|
60
82
|
|
|
61
83
|
```tsx
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/>
|
|
67
|
-
</div>
|
|
84
|
+
<SyncAgentChat
|
|
85
|
+
config={{ apiKey: "...", connectionString: "..." }}
|
|
86
|
+
context={{ userId: currentUser.id, page: "orders" }}
|
|
87
|
+
/>
|
|
68
88
|
```
|
|
69
89
|
|
|
70
|
-
##
|
|
90
|
+
## `onData` — react to query results
|
|
71
91
|
|
|
72
92
|
```tsx
|
|
73
93
|
<SyncAgentChat
|
|
74
94
|
config={{ apiKey: "...", connectionString: "..." }}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
95
|
+
onData={(data) => {
|
|
96
|
+
// Update your own table when the agent queries data
|
|
97
|
+
if (data.collection === "orders") setOrders(data.data);
|
|
98
|
+
}}
|
|
78
99
|
/>
|
|
79
100
|
```
|
|
80
101
|
|
|
81
102
|
## Custom Tools
|
|
82
103
|
|
|
83
|
-
Give the agent capabilities beyond your database. Tools run entirely in your app — SyncAgent only sees the schema and the result you return.
|
|
84
|
-
|
|
85
104
|
```tsx
|
|
86
|
-
import { SyncAgentChat } from "@syncagent/react";
|
|
87
|
-
|
|
88
105
|
<SyncAgentChat
|
|
89
106
|
config={{
|
|
90
|
-
apiKey: "
|
|
107
|
+
apiKey: "sa_your_key",
|
|
91
108
|
connectionString: process.env.DATABASE_URL,
|
|
92
109
|
tools: {
|
|
93
|
-
|
|
94
|
-
description: "
|
|
110
|
+
createInvoice: {
|
|
111
|
+
description: "Create a Stripe invoice for a customer",
|
|
95
112
|
inputSchema: {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
body: { type: "string", description: "Email body" },
|
|
113
|
+
customerId: { type: "string", description: "Stripe customer ID" },
|
|
114
|
+
amount: { type: "number", description: "Amount in cents" },
|
|
99
115
|
},
|
|
100
|
-
execute: async ({
|
|
101
|
-
await
|
|
102
|
-
return {
|
|
116
|
+
execute: async ({ customerId, amount }) => {
|
|
117
|
+
const inv = await stripe.invoices.create({ customer: customerId });
|
|
118
|
+
return { invoiceId: inv.id };
|
|
103
119
|
},
|
|
104
120
|
},
|
|
105
121
|
},
|
|
@@ -109,13 +125,10 @@ import { SyncAgentChat } from "@syncagent/react";
|
|
|
109
125
|
|
|
110
126
|
## Custom UI with `useSyncAgent`
|
|
111
127
|
|
|
112
|
-
Build your own chat UI using the hook:
|
|
113
|
-
|
|
114
128
|
```tsx
|
|
115
129
|
import { SyncAgentProvider, useSyncAgent } from "@syncagent/react";
|
|
116
130
|
|
|
117
|
-
|
|
118
|
-
function App() {
|
|
131
|
+
export default function App() {
|
|
119
132
|
return (
|
|
120
133
|
<SyncAgentProvider config={{ apiKey: "...", connectionString: "..." }}>
|
|
121
134
|
<MyChat />
|
|
@@ -123,22 +136,17 @@ function App() {
|
|
|
123
136
|
);
|
|
124
137
|
}
|
|
125
138
|
|
|
126
|
-
// 2. Use the hook inside
|
|
127
139
|
function MyChat() {
|
|
128
|
-
const { messages, isLoading, error, sendMessage, stop, reset } = useSyncAgent();
|
|
129
|
-
const [input, setInput] = useState("");
|
|
140
|
+
const { messages, isLoading, error, status, lastData, sendMessage, stop, reset } = useSyncAgent();
|
|
130
141
|
|
|
131
142
|
return (
|
|
132
143
|
<div>
|
|
144
|
+
{/* status.label shows "Querying users..." etc. */}
|
|
145
|
+
{status && <div>⏳ {status.label}</div>}
|
|
133
146
|
{messages.map((msg, i) => (
|
|
134
|
-
<div key={i}
|
|
135
|
-
{msg.content}
|
|
136
|
-
</div>
|
|
147
|
+
<div key={i}><strong>{msg.role}:</strong> {msg.content}</div>
|
|
137
148
|
))}
|
|
138
|
-
{
|
|
139
|
-
{error && <div>Error: {error.message}</div>}
|
|
140
|
-
<input value={input} onChange={(e) => setInput(e.target.value)} />
|
|
141
|
-
<button onClick={() => { sendMessage(input); setInput(""); }}>Send</button>
|
|
149
|
+
<button onClick={() => sendMessage("Show all users")}>Ask</button>
|
|
142
150
|
<button onClick={stop}>Stop</button>
|
|
143
151
|
<button onClick={reset}>Clear</button>
|
|
144
152
|
</div>
|
|
@@ -146,64 +154,60 @@ function MyChat() {
|
|
|
146
154
|
}
|
|
147
155
|
```
|
|
148
156
|
|
|
149
|
-
### `useSyncAgent`
|
|
157
|
+
### `useSyncAgent` options
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
useSyncAgent({
|
|
161
|
+
client?: SyncAgentClient, // pass directly instead of using Provider
|
|
162
|
+
context?: Record<string, any>, // injected into every message
|
|
163
|
+
onData?: (data: ToolData) => void, // called on DB tool results
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### `useSyncAgent` returns
|
|
150
168
|
|
|
151
169
|
| Return | Type | Description |
|
|
152
170
|
| ------------- | ---------------------------- | ------------------------------------ |
|
|
153
171
|
| `messages` | `Message[]` | Full conversation history |
|
|
154
172
|
| `isLoading` | `boolean` | `true` while streaming |
|
|
155
|
-
| `error` | `Error \| null` | Last error
|
|
173
|
+
| `error` | `Error \| null` | Last error |
|
|
174
|
+
| `status` | `{ step, label } \| null` | Live status while agent is working |
|
|
175
|
+
| `lastData` | `ToolData \| null` | Last structured data from a DB tool |
|
|
156
176
|
| `sendMessage` | `(content: string) => void` | Send a user message |
|
|
157
|
-
| `stop` | `() => void` | Abort the current
|
|
158
|
-
| `reset` | `() => void` | Clear all messages
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
177
|
+
| `stop` | `() => void` | Abort the current stream |
|
|
178
|
+
| `reset` | `() => void` | Clear all messages |
|
|
179
|
+
|
|
180
|
+
## Vanilla JS Widget
|
|
181
|
+
|
|
182
|
+
No npm required — drop a script tag into any HTML page:
|
|
183
|
+
|
|
184
|
+
```html
|
|
185
|
+
<script src="https://syncagent.dev/api/v1/widget"></script>
|
|
186
|
+
<script>
|
|
187
|
+
SyncAgent.init({
|
|
188
|
+
apiKey: "sa_your_key",
|
|
189
|
+
connectionString: "your_database_url",
|
|
190
|
+
position: "right", // "right" or "left"
|
|
191
|
+
accentColor: "#10b981", // brand color
|
|
192
|
+
title: "AI Assistant",
|
|
193
|
+
persistKey: "my-app", // localStorage persistence
|
|
194
|
+
open: false,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Programmatic control
|
|
198
|
+
SyncAgent.open();
|
|
199
|
+
SyncAgent.close();
|
|
200
|
+
SyncAgent.toggle();
|
|
201
|
+
SyncAgent.clearHistory();
|
|
202
|
+
</script>
|
|
175
203
|
```
|
|
176
204
|
|
|
177
|
-
##
|
|
178
|
-
|
|
179
|
-
Provides a shared `SyncAgentClient` instance to all child components via context.
|
|
180
|
-
|
|
181
|
-
```tsx
|
|
182
|
-
import { SyncAgentProvider, useSyncAgentClient } from "@syncagent/react";
|
|
183
|
-
|
|
184
|
-
<SyncAgentProvider config={{ apiKey: "...", connectionString: "..." }}>
|
|
185
|
-
<App />
|
|
186
|
-
</SyncAgentProvider>
|
|
187
|
-
|
|
188
|
-
// Access the raw client anywhere inside
|
|
189
|
-
function Somewhere() {
|
|
190
|
-
const client = useSyncAgentClient();
|
|
191
|
-
// client.chat(...), client.getSchema(), etc.
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
## TypeScript Types
|
|
196
|
-
|
|
197
|
-
All types are re-exported from `@syncagent/js` for convenience:
|
|
205
|
+
## TypeScript types
|
|
198
206
|
|
|
199
207
|
```typescript
|
|
200
208
|
import type {
|
|
201
|
-
SyncAgentConfig,
|
|
202
|
-
|
|
203
|
-
ChatOptions,
|
|
204
|
-
ToolDefinition,
|
|
205
|
-
ToolParameter,
|
|
206
|
-
SyncAgentChatProps,
|
|
209
|
+
SyncAgentConfig, Message, ChatOptions, ToolDefinition,
|
|
210
|
+
ToolParameter, ToolData, SyncAgentChatProps,
|
|
207
211
|
} from "@syncagent/react";
|
|
208
212
|
```
|
|
209
213
|
|