@arbidocs/react 0.3.16 → 0.3.17
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 +75 -111
- package/dist/index.cjs +1051 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -1
- package/dist/index.d.ts +116 -1
- package/dist/index.js +1055 -5
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
# @arbidocs/react
|
|
2
2
|
|
|
3
|
-
React hooks and provider for
|
|
3
|
+
React hooks and provider for building ARBI-powered apps. Includes `@arbidocs/sdk` and `@tanstack/react-query` — one install gets you everything.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quickstart
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @arbidocs/react
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Wrap your app with `ArbiProvider` and a React Query `QueryClientProvider`:
|
|
11
|
+
### 1. Set up providers
|
|
14
12
|
|
|
15
13
|
```tsx
|
|
16
14
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
@@ -21,142 +19,108 @@ const queryClient = new QueryClient()
|
|
|
21
19
|
function App() {
|
|
22
20
|
return (
|
|
23
21
|
<QueryClientProvider client={queryClient}>
|
|
24
|
-
<ArbiProvider url="https://
|
|
25
|
-
<
|
|
22
|
+
<ArbiProvider url="https://www.arbidocs.com">
|
|
23
|
+
<Chat />
|
|
26
24
|
</ArbiProvider>
|
|
27
25
|
</QueryClientProvider>
|
|
28
26
|
)
|
|
29
27
|
}
|
|
30
28
|
```
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
### 2. Build a streaming chat
|
|
33
31
|
|
|
34
32
|
```tsx
|
|
35
|
-
import {
|
|
33
|
+
import { useState, useRef } from 'react'
|
|
34
|
+
import { useArbi, useDocuments, useAssistantQuery } from '@arbidocs/react'
|
|
36
35
|
|
|
37
|
-
function
|
|
36
|
+
function Chat() {
|
|
38
37
|
const arbi = useArbi()
|
|
39
|
-
const
|
|
38
|
+
const [workspaceId, setWorkspaceId] = useState<string>()
|
|
39
|
+
|
|
40
|
+
if (!workspaceId) {
|
|
41
|
+
return (
|
|
42
|
+
<button onClick={async () => {
|
|
43
|
+
await arbi.login('user@example.com', 'password')
|
|
44
|
+
const ws = await arbi.workspaces.list()
|
|
45
|
+
await arbi.selectWorkspace(ws[0].external_id)
|
|
46
|
+
setWorkspaceId(ws[0].external_id)
|
|
47
|
+
}}>
|
|
48
|
+
Connect
|
|
49
|
+
</button>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return <ChatWindow workspaceId={workspaceId} />
|
|
54
|
+
}
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
function ChatWindow({ workspaceId }: { workspaceId: string }) {
|
|
57
|
+
const { data: docs } = useDocuments(workspaceId)
|
|
58
|
+
const mutation = useAssistantQuery()
|
|
59
|
+
const [input, setInput] = useState('')
|
|
60
|
+
const [response, setResponse] = useState('')
|
|
61
|
+
const lastId = useRef<string | null>(null)
|
|
42
62
|
|
|
43
63
|
return (
|
|
44
|
-
<
|
|
45
|
-
{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
64
|
+
<div>
|
|
65
|
+
<div>{response}</div>
|
|
66
|
+
<form onSubmit={(e) => {
|
|
67
|
+
e.preventDefault()
|
|
68
|
+
setResponse('')
|
|
69
|
+
mutation.mutate({
|
|
70
|
+
question: input,
|
|
71
|
+
docIds: docs?.map((d) => d.external_id) ?? [],
|
|
72
|
+
previousResponseId: lastId.current,
|
|
73
|
+
onToken: (t) => setResponse((r) => r + t),
|
|
74
|
+
onStreamStart: ({ assistant_message_ext_id }) => {
|
|
75
|
+
lastId.current = assistant_message_ext_id
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
setInput('')
|
|
79
|
+
}}>
|
|
80
|
+
<input value={input} onChange={(e) => setInput(e.target.value)} />
|
|
81
|
+
<button type="submit" disabled={mutation.isPending}>Send</button>
|
|
82
|
+
</form>
|
|
83
|
+
</div>
|
|
49
84
|
)
|
|
50
85
|
}
|
|
51
86
|
```
|
|
52
87
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
### `useArbi()`
|
|
56
|
-
|
|
57
|
-
Returns the `Arbi` instance from context. Use this for imperative operations like login, workspace selection, and direct API calls.
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
const arbi = useArbi()
|
|
61
|
-
|
|
62
|
-
await arbi.login('user@example.com', 'password')
|
|
63
|
-
await arbi.selectWorkspace('wrk-123')
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### `useWorkspaces(options?)`
|
|
67
|
-
|
|
68
|
-
Fetches the user's workspaces. Automatically enabled when logged in.
|
|
69
|
-
|
|
70
|
-
```tsx
|
|
71
|
-
const { data, isLoading, error } = useWorkspaces()
|
|
72
|
-
const { data } = useWorkspaces({ enabled: false }) // manual control
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### `useDocuments(workspaceId, options?)`
|
|
76
|
-
|
|
77
|
-
Fetches documents for a workspace. Automatically disabled when `workspaceId` is undefined.
|
|
78
|
-
|
|
79
|
-
```tsx
|
|
80
|
-
const { data: docs } = useDocuments('wrk-123')
|
|
81
|
-
const { data: docs } = useDocuments(undefined) // won't fetch
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### `useConversations(workspaceId, options?)`
|
|
85
|
-
|
|
86
|
-
Fetches conversations for a workspace.
|
|
87
|
-
|
|
88
|
-
```tsx
|
|
89
|
-
const { data: conversations } = useConversations('wrk-123')
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### `useTags(workspaceId, options?)`
|
|
93
|
-
|
|
94
|
-
Fetches tags for a workspace.
|
|
88
|
+
That's it — three hooks and you have a streaming RAG chat.
|
|
95
89
|
|
|
96
|
-
|
|
97
|
-
const { data: tags } = useTags('wrk-123')
|
|
98
|
-
```
|
|
90
|
+
## Hooks
|
|
99
91
|
|
|
100
|
-
|
|
92
|
+
| Hook | Returns | Auto-enabled when |
|
|
93
|
+
|------|---------|-------------------|
|
|
94
|
+
| `useArbi()` | `Arbi` instance | Always |
|
|
95
|
+
| `useWorkspaces()` | User's workspaces | Logged in |
|
|
96
|
+
| `useDocuments(workspaceId)` | Workspace documents | Workspace selected |
|
|
97
|
+
| `useConversations(workspaceId)` | Workspace conversations | Workspace selected |
|
|
98
|
+
| `useTags(workspaceId)` | Workspace tags | Workspace selected |
|
|
99
|
+
| `useAssistantQuery()` | Streaming mutation | Call `.mutate()` |
|
|
100
|
+
| `useHealth()` | Backend status | Pass `{ enabled: true }` |
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
## Streaming callbacks
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
const { data } = useHealth({ enabled: true })
|
|
106
|
-
// { status: 'ok' }
|
|
107
|
-
```
|
|
104
|
+
Pass these to `mutation.mutate()` alongside `question` and `docIds`:
|
|
108
105
|
|
|
109
|
-
|
|
106
|
+
| Callback | Description |
|
|
107
|
+
|----------|-------------|
|
|
108
|
+
| `onToken(token)` | Each text chunk as it streams |
|
|
109
|
+
| `onStreamStart({ assistant_message_ext_id })` | Stream started — save the ID for follow-up queries |
|
|
110
|
+
| `onAgentStep(step)` | Agent tool usage (searching, reading, etc.) |
|
|
111
|
+
| `onError(message)` | Error during streaming |
|
|
112
|
+
| `onComplete()` | Stream finished |
|
|
110
113
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
```tsx
|
|
114
|
-
const mutation = useAssistantQuery()
|
|
115
|
-
|
|
116
|
-
const handleAsk = () => {
|
|
117
|
-
mutation.mutate({
|
|
118
|
-
question: 'What does section 3 say?',
|
|
119
|
-
docIds: ['doc-123'],
|
|
120
|
-
onToken: (token) => setResponse((prev) => prev + token),
|
|
121
|
-
onComplete: () => console.log('Done'),
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Query Keys
|
|
127
|
-
|
|
128
|
-
All hooks use the `arbiQueryKeys` factory for cache management:
|
|
114
|
+
## Cache invalidation
|
|
129
115
|
|
|
130
116
|
```tsx
|
|
131
117
|
import { arbiQueryKeys } from '@arbidocs/react'
|
|
132
118
|
import { useQueryClient } from '@tanstack/react-query'
|
|
133
119
|
|
|
134
120
|
const queryClient = useQueryClient()
|
|
135
|
-
|
|
136
|
-
// Invalidate all documents
|
|
137
|
-
queryClient.invalidateQueries({ queryKey: arbiQueryKeys.documents('wrk-123') })
|
|
138
|
-
|
|
139
|
-
// Available keys:
|
|
140
|
-
arbiQueryKeys.workspaces() // ['arbi', 'workspaces']
|
|
141
|
-
arbiQueryKeys.documents(workspaceId) // ['arbi', 'documents', workspaceId]
|
|
142
|
-
arbiQueryKeys.conversations(workspaceId)
|
|
143
|
-
arbiQueryKeys.tags(workspaceId)
|
|
144
|
-
arbiQueryKeys.health()
|
|
121
|
+
queryClient.invalidateQueries({ queryKey: arbiQueryKeys.documents(workspaceId) })
|
|
145
122
|
```
|
|
146
123
|
|
|
147
|
-
##
|
|
148
|
-
|
|
149
|
-
The package re-exports key types from `@arbidocs/sdk/browser` for convenience:
|
|
150
|
-
|
|
151
|
-
```tsx
|
|
152
|
-
import { Arbi, ArbiError } from '@arbidocs/react'
|
|
153
|
-
import type { ArbiOptions, QueryOptions, SSEStreamResult, SSEStreamCallbacks } from '@arbidocs/react'
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## Examples
|
|
157
|
-
|
|
158
|
-
See the **[React Chat App](../../examples/react-chat/)** for a complete working example with login, workspace selection, document picker, and streaming chat.
|
|
159
|
-
|
|
160
|
-
## Peer Dependencies
|
|
124
|
+
## Peer dependencies
|
|
161
125
|
|
|
162
126
|
- `react` >= 18
|