openrag-sdk 0.1.0

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 ADDED
@@ -0,0 +1,320 @@
1
+ # OpenRAG TypeScript SDK
2
+
3
+ Official TypeScript/JavaScript SDK for the [OpenRAG](https://openr.ag) API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install openrag-sdk
9
+ # or
10
+ yarn add openrag-sdk
11
+ # or
12
+ pnpm add openrag-sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { OpenRAGClient } from "openrag-sdk";
19
+
20
+ // Client auto-discovers OPENRAG_API_KEY and OPENRAG_URL from environment
21
+ const client = new OpenRAGClient();
22
+
23
+ // Simple chat
24
+ const response = await client.chat.create({ message: "What is RAG?" });
25
+ console.log(response.response);
26
+ console.log(`Chat ID: ${response.chatId}`);
27
+ ```
28
+
29
+ ## Configuration
30
+
31
+ The SDK can be configured via environment variables or constructor arguments:
32
+
33
+ | Environment Variable | Constructor Option | Description |
34
+ |---------------------|-------------------|-------------|
35
+ | `OPENRAG_API_KEY` | `apiKey` | API key for authentication (required) |
36
+ | `OPENRAG_URL` | `baseUrl` | Base URL for the API (default: `http://localhost:8080`) |
37
+
38
+ ```typescript
39
+ // Using environment variables
40
+ const client = new OpenRAGClient();
41
+
42
+ // Using explicit arguments
43
+ const client = new OpenRAGClient({
44
+ apiKey: "orag_...",
45
+ baseUrl: "https://api.example.com",
46
+ });
47
+ ```
48
+
49
+ ## Chat
50
+
51
+ ### Non-streaming
52
+
53
+ ```typescript
54
+ const response = await client.chat.create({ message: "What is RAG?" });
55
+ console.log(response.response);
56
+ console.log(`Chat ID: ${response.chatId}`);
57
+
58
+ // Continue conversation
59
+ const followup = await client.chat.create({
60
+ message: "Tell me more",
61
+ chatId: response.chatId,
62
+ });
63
+ ```
64
+
65
+ ### Streaming with `create({ stream: true })`
66
+
67
+ Returns an async iterator directly:
68
+
69
+ ```typescript
70
+ let chatId: string | null = null;
71
+ for await (const event of await client.chat.create({
72
+ message: "Explain RAG",
73
+ stream: true,
74
+ })) {
75
+ if (event.type === "content") {
76
+ process.stdout.write(event.delta);
77
+ } else if (event.type === "sources") {
78
+ for (const source of event.sources) {
79
+ console.log(`\nSource: ${source.filename}`);
80
+ }
81
+ } else if (event.type === "done") {
82
+ chatId = event.chatId;
83
+ }
84
+ }
85
+ ```
86
+
87
+ ### Streaming with `stream()`
88
+
89
+ Provides additional helpers for convenience:
90
+
91
+ ```typescript
92
+ // Full event iteration
93
+ const stream = await client.chat.stream({ message: "Explain RAG" });
94
+ try {
95
+ for await (const event of stream) {
96
+ if (event.type === "content") {
97
+ process.stdout.write(event.delta);
98
+ }
99
+ }
100
+
101
+ // Access aggregated data after iteration
102
+ console.log(`\nChat ID: ${stream.chatId}`);
103
+ console.log(`Full text: ${stream.text}`);
104
+ console.log(`Sources: ${stream.sources}`);
105
+ } finally {
106
+ stream.close();
107
+ }
108
+
109
+ // Just text deltas
110
+ const stream = await client.chat.stream({ message: "Explain RAG" });
111
+ try {
112
+ for await (const text of stream.textStream) {
113
+ process.stdout.write(text);
114
+ }
115
+ } finally {
116
+ stream.close();
117
+ }
118
+
119
+ // Get final text directly
120
+ const stream = await client.chat.stream({ message: "Explain RAG" });
121
+ try {
122
+ const text = await stream.finalText();
123
+ console.log(text);
124
+ } finally {
125
+ stream.close();
126
+ }
127
+ ```
128
+
129
+ ### Conversation History
130
+
131
+ ```typescript
132
+ // List all conversations
133
+ const conversations = await client.chat.list();
134
+ for (const conv of conversations.conversations) {
135
+ console.log(`${conv.chatId}: ${conv.title}`);
136
+ }
137
+
138
+ // Get specific conversation with messages
139
+ const conversation = await client.chat.get(chatId);
140
+ for (const msg of conversation.messages) {
141
+ console.log(`${msg.role}: ${msg.content}`);
142
+ }
143
+
144
+ // Delete conversation
145
+ await client.chat.delete(chatId);
146
+ ```
147
+
148
+ ## Search
149
+
150
+ ```typescript
151
+ // Basic search
152
+ const results = await client.search.query("document processing");
153
+ for (const result of results.results) {
154
+ console.log(`${result.filename} (score: ${result.score})`);
155
+ console.log(` ${result.text.slice(0, 100)}...`);
156
+ }
157
+
158
+ // Search with filters
159
+ const results = await client.search.query("API documentation", {
160
+ filters: {
161
+ data_sources: ["api-docs.pdf"],
162
+ document_types: ["application/pdf"],
163
+ },
164
+ limit: 5,
165
+ scoreThreshold: 0.5,
166
+ });
167
+ ```
168
+
169
+ ## Documents
170
+
171
+ ```typescript
172
+ // Ingest a file (waits for completion by default)
173
+ const result = await client.documents.ingest({
174
+ filePath: "./report.pdf",
175
+ });
176
+ console.log(`Status: ${result.status}`);
177
+ console.log(`Successful files: ${result.successful_files}`);
178
+
179
+ // Ingest without waiting (returns immediately with task_id)
180
+ const result = await client.documents.ingest({
181
+ filePath: "./report.pdf",
182
+ wait: false,
183
+ });
184
+ console.log(`Task ID: ${result.task_id}`);
185
+
186
+ // Poll for completion manually
187
+ const finalStatus = await client.documents.waitForTask(result.task_id);
188
+ console.log(`Status: ${finalStatus.status}`);
189
+ console.log(`Successful files: ${finalStatus.successful_files}`);
190
+
191
+ // Ingest from File object (browser)
192
+ const file = new File([...], "report.pdf");
193
+ const result = await client.documents.ingest({
194
+ file,
195
+ filename: "report.pdf",
196
+ });
197
+
198
+ // Delete a document
199
+ const result = await client.documents.delete("report.pdf");
200
+ console.log(`Success: ${result.success}`);
201
+ ```
202
+
203
+ ## Settings
204
+
205
+ ```typescript
206
+ // Get settings
207
+ const settings = await client.settings.get();
208
+ console.log(`LLM Provider: ${settings.agent.llm_provider}`);
209
+ console.log(`LLM Model: ${settings.agent.llm_model}`);
210
+ console.log(`Embedding Model: ${settings.knowledge.embedding_model}`);
211
+
212
+ // Update settings
213
+ await client.settings.update({
214
+ chunk_size: 1000,
215
+ chunk_overlap: 200,
216
+ });
217
+ ```
218
+
219
+ ## Knowledge Filters
220
+
221
+ Knowledge filters are reusable, named filter configurations that can be applied to chat and search operations.
222
+
223
+ ```typescript
224
+ // Create a knowledge filter
225
+ const result = await client.knowledgeFilters.create({
226
+ name: "Technical Docs",
227
+ description: "Filter for technical documentation",
228
+ queryData: {
229
+ query: "technical",
230
+ filters: {
231
+ document_types: ["application/pdf"],
232
+ },
233
+ limit: 10,
234
+ scoreThreshold: 0.5,
235
+ },
236
+ });
237
+ const filterId = result.id;
238
+
239
+ // Search for filters
240
+ const filters = await client.knowledgeFilters.search("Technical");
241
+ for (const filter of filters) {
242
+ console.log(`${filter.name}: ${filter.description}`);
243
+ }
244
+
245
+ // Get a specific filter
246
+ const filter = await client.knowledgeFilters.get(filterId);
247
+
248
+ // Update a filter
249
+ await client.knowledgeFilters.update(filterId, {
250
+ description: "Updated description",
251
+ });
252
+
253
+ // Delete a filter
254
+ await client.knowledgeFilters.delete(filterId);
255
+
256
+ // Use filter in chat
257
+ const response = await client.chat.create({
258
+ message: "Explain the API",
259
+ filterId,
260
+ });
261
+
262
+ // Use filter in search
263
+ const results = await client.search.query("API endpoints", { filterId });
264
+ ```
265
+
266
+ ## Error Handling
267
+
268
+ ```typescript
269
+ import {
270
+ OpenRAGError,
271
+ AuthenticationError,
272
+ NotFoundError,
273
+ ValidationError,
274
+ RateLimitError,
275
+ ServerError,
276
+ } from "openrag-sdk";
277
+
278
+ try {
279
+ const response = await client.chat.create({ message: "Hello" });
280
+ } catch (e) {
281
+ if (e instanceof AuthenticationError) {
282
+ console.log(`Invalid API key: ${e.message}`);
283
+ } else if (e instanceof NotFoundError) {
284
+ console.log(`Resource not found: ${e.message}`);
285
+ } else if (e instanceof ValidationError) {
286
+ console.log(`Invalid request: ${e.message}`);
287
+ } else if (e instanceof RateLimitError) {
288
+ console.log(`Rate limited: ${e.message}`);
289
+ } else if (e instanceof ServerError) {
290
+ console.log(`Server error: ${e.message}`);
291
+ } else if (e instanceof OpenRAGError) {
292
+ console.log(`API error: ${e.message} (status: ${e.statusCode})`);
293
+ }
294
+ }
295
+ ```
296
+
297
+ ## Browser Support
298
+
299
+ This SDK works in both Node.js and browser environments. The main difference is file ingestion:
300
+
301
+ - **Node.js**: Use `filePath` option
302
+ - **Browser**: Use `file` option with a `File` or `Blob` object
303
+
304
+ ## TypeScript
305
+
306
+ This SDK is written in TypeScript and provides full type definitions. All types are exported from the main module:
307
+
308
+ ```typescript
309
+ import type {
310
+ ChatResponse,
311
+ StreamEvent,
312
+ SearchResponse,
313
+ IngestResponse,
314
+ SettingsResponse,
315
+ } from "openrag-sdk";
316
+ ```
317
+
318
+ ## License
319
+
320
+ MIT