@ragbits/api-client 0.0.1 → 0.0.3

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 CHANGED
@@ -1,17 +1,26 @@
1
- # Ragbits API Client
1
+ # @ragbits/api-client
2
2
 
3
- A TypeScript client for communicating with the Ragbits API. This client provides methods for both regular HTTP requests and server-sent events (streaming) functionality.
3
+ A TypeScript client for communicating with the Ragbits API. This client provides type-safe methods for both regular HTTP requests and server-sent events (streaming) functionality.
4
+
5
+ ## Features
6
+
7
+ - **Type-safe API calls** - Full TypeScript support with predefined endpoints
8
+ - **Streaming support** - Real-time server-sent events with proper error handling
9
+ - **Modern JavaScript** - ES modules and CommonJS support
10
+ - **Abortable requests** - Cancel ongoing requests and streams
11
+ - **Error handling** - Comprehensive error handling with detailed error messages
12
+ - **Zero dependencies** - Lightweight with no runtime dependencies
4
13
 
5
14
  ## Installation
6
15
 
7
16
  ```bash
8
- npm install ragbits-api-client
17
+ npm install @ragbits/api-client
9
18
  ```
10
19
 
11
- ## Usage
20
+ ## Quick Start
12
21
 
13
22
  ```typescript
14
- import { RagbitsClient, type ChatResponse } from 'ragbits-api-client'
23
+ import { RagbitsClient } from '@ragbits/api-client'
15
24
 
16
25
  // Initialize the client
17
26
  const client = new RagbitsClient({
@@ -19,20 +28,21 @@ const client = new RagbitsClient({
19
28
  })
20
29
 
21
30
  // Get API configuration
22
- const config = await client.getConfig()
31
+ const config = await client.makeRequest('/api/config')
23
32
 
24
33
  // Send a chat message with streaming response
25
- const cleanup = client.sendChatMessage(
34
+ const cleanup = client.makeStreamRequest(
35
+ '/api/chat',
26
36
  {
27
37
  message: 'Hello!',
28
38
  history: [],
29
39
  context: {}, // Optional
30
40
  },
31
41
  {
32
- onMessage: (data: ChatResponse) => {
42
+ onMessage: (data) => {
33
43
  console.log('Received message:', data)
34
44
  },
35
- onError: (error: string) => {
45
+ onError: (error) => {
36
46
  console.error('Error:', error)
37
47
  },
38
48
  onClose: () => {
@@ -45,10 +55,13 @@ const cleanup = client.sendChatMessage(
45
55
  cleanup()
46
56
 
47
57
  // Send feedback
48
- await client.sendFeedback({
49
- message_id: 'message-123',
50
- feedback: 'like',
51
- payload: { reason: 'helpful' },
58
+ await client.makeRequest('/api/feedback', {
59
+ method: 'POST',
60
+ body: {
61
+ message_id: 'message-123',
62
+ feedback: 'like',
63
+ payload: { reason: 'helpful' },
64
+ },
52
65
  })
53
66
  ```
54
67
 
@@ -61,86 +74,267 @@ The main client class for interacting with the Ragbits API.
61
74
  #### Constructor
62
75
 
63
76
  ```typescript
64
- new RagbitsClient(config?: { baseUrl?: string })
77
+ new RagbitsClient(config?: ClientConfig)
65
78
  ```
66
79
 
80
+ **Parameters:**
81
+
67
82
  - `config.baseUrl` (optional): Base URL for the API. Defaults to 'http://127.0.0.1:8000'
68
83
 
84
+ **Throws:** `Error` if the base URL is invalid
85
+
69
86
  #### Methods
70
87
 
71
- ##### `getConfig()`
88
+ ##### `getBaseUrl(): string`
89
+
90
+ Get the base URL used by this client.
91
+
92
+ **Returns:** The configured base URL
93
+
94
+ ##### `makeRequest<T>(endpoint, options?): Promise<T>`
95
+
96
+ Make a type-safe API request to predefined endpoints.
97
+
98
+ **Parameters:**
72
99
 
73
- Get the API configuration.
100
+ - `endpoint`: Predefined API endpoint path (e.g., '/api/config', '/api/feedback')
101
+ - `options` (optional): Request options
102
+ - `method`: HTTP method (defaults to endpoint's predefined method)
103
+ - `body`: Request body (typed based on endpoint)
104
+ - `headers`: Additional headers
105
+ - `signal`: AbortSignal for cancelling the request
74
106
 
75
- - Returns: `Promise<Record<string, unknown>>` - API configuration object
107
+ **Returns:** Promise with the typed response
76
108
 
77
- ##### `sendChatMessage(chatRequest, callbacks)`
109
+ **Example:**
78
110
 
79
- Send a chat message and receive streaming responses.
111
+ ```typescript
112
+ // GET request
113
+ const config = await client.makeRequest('/api/config')
114
+
115
+ // POST request
116
+ const feedback = await client.makeRequest('/api/feedback', {
117
+ method: 'POST',
118
+ body: {
119
+ message_id: 'msg-123',
120
+ feedback: 'like',
121
+ payload: { rating: 5 },
122
+ },
123
+ })
124
+ ```
125
+
126
+ ##### `makeStreamRequest<T>(endpoint, data, callbacks, signal?): () => void`
80
127
 
81
- - Parameters:
82
- - `chatRequest`: ChatRequest
83
- - `message`: string - User message
84
- - `history`: Array<{ role: string; content: string; id?: string }> - Chat history
85
- - `context`: Record<string, unknown> (optional) - Additional context
86
- - `callbacks`: StreamCallbacks
87
- - `onMessage`: (data: ChatResponse) => void | Promise<void> - Called when a message chunk is received
88
- - `onError`: (error: string) => void | Promise<void> - Called when an error occurs
89
- - `onClose`: () => void | Promise<void> (optional) - Called when the stream closes
90
- - Returns: `() => void` - Cleanup function to cancel the stream
128
+ Make a type-safe streaming request to predefined streaming endpoints.
91
129
 
92
- ##### `sendFeedback(feedbackData)`
130
+ **Parameters:**
93
131
 
94
- Send feedback for a message.
132
+ - `endpoint`: Predefined streaming endpoint path (e.g., '/api/chat')
133
+ - `data`: Request data (typed based on endpoint)
134
+ - `callbacks`: Stream callbacks
135
+ - `onMessage`: Called when a message chunk is received
136
+ - `onError`: Called when an error occurs
137
+ - `onClose`: Called when the stream closes (optional)
138
+ - `signal` (optional): AbortSignal for cancelling the stream
95
139
 
96
- - Parameters:
97
- - `feedbackData`: FeedbackRequest
98
- - `message_id`: string - ID of the message to provide feedback for
99
- - `feedback`: string - Type of feedback
100
- - `payload`: Record<string, unknown> | null - Additional feedback data
101
- - Returns: `Promise<Record<string, unknown>>` - Feedback submission response
140
+ **Returns:** Cleanup function to cancel the stream
141
+
142
+ **Example:**
143
+
144
+ ```typescript
145
+ const cleanup = client.makeStreamRequest(
146
+ '/api/chat',
147
+ {
148
+ message: 'Tell me about AI',
149
+ history: [
150
+ { role: 'user', content: 'Hello', id: 'msg-1' },
151
+ { role: 'assistant', content: 'Hi there!', id: 'msg-2' },
152
+ ],
153
+ context: { user_id: 'user-123' },
154
+ },
155
+ {
156
+ onMessage: (data) => {
157
+ switch (data.type) {
158
+ case 'text':
159
+ console.log('Text:', data.content)
160
+ break
161
+ case 'reference':
162
+ console.log('Reference:', data.content.title)
163
+ break
164
+ case 'message_id':
165
+ console.log('Message ID:', data.content)
166
+ break
167
+ }
168
+ },
169
+ onError: (error) => {
170
+ console.error('Stream error:', error)
171
+ },
172
+ onClose: () => {
173
+ console.log('Stream completed')
174
+ },
175
+ }
176
+ )
177
+
178
+ // Cancel stream
179
+ cleanup()
180
+ ```
102
181
 
103
182
  ## Types
104
183
 
105
- ### ChatResponse
184
+ ### Core Types
185
+
186
+ #### `ClientConfig`
106
187
 
107
188
  ```typescript
108
- {
109
- type: 'message' | 'reference' | 'state_update' | 'text' | 'message_id'
110
- content: any
189
+ interface ClientConfig {
190
+ baseUrl?: string
111
191
  }
112
192
  ```
113
193
 
114
- ### ChatRequest
194
+ #### `Message`
115
195
 
116
196
  ```typescript
117
- {
118
- message: string;
119
- history: Array<{
120
- role: string;
121
- content: string;
122
- id?: string;
123
- }>;
124
- context?: Record<string, unknown>;
197
+ interface Message {
198
+ role: MessageRole
199
+ content: string
200
+ id?: string
201
+ }
202
+
203
+ enum MessageRole {
204
+ USER = 'user',
205
+ ASSISTANT = 'assistant',
206
+ SYSTEM = 'system',
125
207
  }
126
208
  ```
127
209
 
128
- ### FeedbackRequest
210
+ #### `ChatRequest`
211
+
212
+ ```typescript
213
+ interface ChatRequest {
214
+ message: string
215
+ history: Message[]
216
+ context?: Record<string, unknown>
217
+ }
218
+ ```
219
+
220
+ #### `TypedChatResponse`
221
+
222
+ Union type for all possible chat response types:
223
+
224
+ ```typescript
225
+ type TypedChatResponse =
226
+ | { type: 'text'; content: string }
227
+ | { type: 'reference'; content: Reference }
228
+ | { type: 'message_id'; content: string }
229
+ | { type: 'conversation_id'; content: string }
230
+ | { type: 'state_update'; content: ServerState }
231
+ ```
232
+
233
+ #### `FeedbackRequest`
129
234
 
130
235
  ```typescript
131
- {
236
+ interface FeedbackRequest {
132
237
  message_id: string
133
- feedback: string
238
+ feedback: FeedbackType
134
239
  payload: Record<string, unknown> | null
135
240
  }
241
+
242
+ enum FeedbackType {
243
+ LIKE = 'like',
244
+ DISLIKE = 'dislike',
245
+ }
246
+ ```
247
+
248
+ #### `ConfigResponse`
249
+
250
+ ```typescript
251
+ interface ConfigResponse {
252
+ feedback: {
253
+ like: { enabled: boolean; form: RJSFSchema | null }
254
+ dislike: { enabled: boolean; form: RJSFSchema | null }
255
+ }
256
+ customization: UICustomization | null
257
+ }
136
258
  ```
137
259
 
138
- ### StreamCallbacks
260
+ #### `StreamCallbacks<T, E>`
139
261
 
140
262
  ```typescript
141
- {
142
- onMessage: (data: ChatResponse) => void | Promise<void>;
143
- onError: (error: string) => void | Promise<void>;
144
- onClose?: () => void | Promise<void>;
263
+ interface StreamCallbacks<T, E = Error> {
264
+ onMessage: (data: T) => void | Promise<void>
265
+ onError: (error: E) => void | Promise<void>
266
+ onClose?: () => void | Promise<void>
145
267
  }
146
268
  ```
269
+
270
+ ### Advanced Types
271
+
272
+ The package provides extensive TypeScript support with predefined endpoint types:
273
+
274
+ - `ApiEndpointPath` - Union of all available API endpoints
275
+ - `StreamingEndpointPath` - Union of all available streaming endpoints
276
+ - `ApiEndpointResponse<T>` - Response type for a specific endpoint
277
+ - `StreamingEndpointStream<T>` - Stream response type for a specific endpoint
278
+
279
+ ## Error Handling
280
+
281
+ The client provides comprehensive error handling:
282
+
283
+ ```typescript
284
+ try {
285
+ const config = await client.makeRequest('/api/config')
286
+ } catch (error) {
287
+ if (error instanceof Error) {
288
+ console.error('API Error:', error.message)
289
+ }
290
+ }
291
+ ```
292
+
293
+ Common error scenarios:
294
+
295
+ - **Network errors** - Connection failures, timeouts
296
+ - **HTTP errors** - 4xx/5xx status codes
297
+ - **Invalid URLs** - Malformed base URL
298
+ - **Stream errors** - Connection drops, parsing errors
299
+
300
+ ## Aborting Requests
301
+
302
+ Both regular requests and streams can be aborted:
303
+
304
+ ```typescript
305
+ // Abort regular request
306
+ const controller = new AbortController()
307
+ const request = client.makeRequest('/api/config', {
308
+ signal: controller.signal,
309
+ })
310
+ controller.abort() // Cancels the request
311
+
312
+ // Abort stream
313
+ const cleanup = client.makeStreamRequest(
314
+ '/api/chat',
315
+ data,
316
+ callbacks,
317
+ controller.signal
318
+ )
319
+ controller.abort() // Cancels the stream
320
+ cleanup() // Also cancels the stream
321
+ ```
322
+
323
+ ## Browser Support
324
+
325
+ This package supports all modern browsers with fetch API support:
326
+
327
+ - Chrome 42+
328
+ - Firefox 39+
329
+ - Safari 10.1+
330
+ - Edge 14+
331
+
332
+ ## Node.js Support
333
+
334
+ For Node.js environments, you'll need:
335
+
336
+ - Node.js 18+
337
+
338
+ ## License
339
+
340
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ChatResponseType: () => ChatResponseType,
24
+ FeedbackType: () => FeedbackType,
25
+ LiveUpdateType: () => LiveUpdateType,
26
+ MessageRole: () => MessageRole,
27
+ RagbitsClient: () => RagbitsClient
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/types.ts
32
+ var MessageRole = /* @__PURE__ */ ((MessageRole2) => {
33
+ MessageRole2["USER"] = "user";
34
+ MessageRole2["ASSISTANT"] = "assistant";
35
+ MessageRole2["SYSTEM"] = "system";
36
+ return MessageRole2;
37
+ })(MessageRole || {});
38
+ var ChatResponseType = /* @__PURE__ */ ((ChatResponseType2) => {
39
+ ChatResponseType2["MESSAGE"] = "message";
40
+ ChatResponseType2["REFERENCE"] = "reference";
41
+ ChatResponseType2["STATE_UPDATE"] = "state_update";
42
+ ChatResponseType2["TEXT"] = "text";
43
+ ChatResponseType2["MESSAGE_ID"] = "message_id";
44
+ ChatResponseType2["CONVERSATION_ID"] = "conversation_id";
45
+ ChatResponseType2["LIVE_UPDATE"] = "live_update";
46
+ ChatResponseType2["FOLLOWUP_MESSAGES"] = "followup_messages";
47
+ return ChatResponseType2;
48
+ })(ChatResponseType || {});
49
+ var FeedbackType = /* @__PURE__ */ ((FeedbackType2) => {
50
+ FeedbackType2["LIKE"] = "like";
51
+ FeedbackType2["DISLIKE"] = "dislike";
52
+ return FeedbackType2;
53
+ })(FeedbackType || {});
54
+ var LiveUpdateType = /* @__PURE__ */ ((LiveUpdateType2) => {
55
+ LiveUpdateType2["START"] = "START";
56
+ LiveUpdateType2["FINISH"] = "FINISH";
57
+ return LiveUpdateType2;
58
+ })(LiveUpdateType || {});
59
+
60
+ // src/index.ts
61
+ var RagbitsClient = class {
62
+ /**
63
+ * @param config - Configuration object
64
+ */
65
+ constructor(config = {}) {
66
+ this.baseUrl = config.baseUrl || "http://127.0.0.1:8000";
67
+ try {
68
+ new URL(this.baseUrl);
69
+ } catch {
70
+ throw new Error(
71
+ `Invalid base URL: ${this.baseUrl}. Please provide a valid URL.`
72
+ );
73
+ }
74
+ if (this.baseUrl.endsWith("/")) {
75
+ this.baseUrl = this.baseUrl.slice(0, -1);
76
+ }
77
+ }
78
+ /**
79
+ * Get the base URL used by this client
80
+ */
81
+ getBaseUrl() {
82
+ return this.baseUrl;
83
+ }
84
+ /**
85
+ * Build full API URL from path
86
+ * @private
87
+ */
88
+ _buildApiUrl(path) {
89
+ return `${this.baseUrl}${path}`;
90
+ }
91
+ /**
92
+ * Make a request to the API
93
+ * @private
94
+ */
95
+ async _makeRequest(url, options = {}) {
96
+ const defaultOptions = {
97
+ headers: {
98
+ "Content-Type": "application/json"
99
+ }
100
+ };
101
+ const response = await fetch(url, { ...defaultOptions, ...options });
102
+ if (!response.ok) {
103
+ throw new Error(`HTTP error! status: ${response.status}`);
104
+ }
105
+ return response;
106
+ }
107
+ /**
108
+ * Method to make API requests to known endpoints only
109
+ * @param endpoint - API endpoint path (must be predefined)
110
+ * @param options - Typed request options for the specific endpoint
111
+ */
112
+ async makeRequest(endpoint, options) {
113
+ const {
114
+ method = "GET",
115
+ body,
116
+ headers = {},
117
+ ...restOptions
118
+ } = options || {};
119
+ const requestOptions = {
120
+ method,
121
+ headers,
122
+ ...restOptions
123
+ // This will include signal and other fetch options
124
+ };
125
+ if (body && method !== "GET") {
126
+ requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
127
+ }
128
+ const response = await this._makeRequest(
129
+ this._buildApiUrl(endpoint),
130
+ requestOptions
131
+ );
132
+ return response.json();
133
+ }
134
+ /**
135
+ * Method for streaming requests to known endpoints only
136
+ * @param endpoint - Streaming endpoint path (must be predefined)
137
+ * @param data - Request data
138
+ * @param callbacks - Stream callbacks
139
+ * @param signal - Optional AbortSignal for cancelling the request
140
+ */
141
+ makeStreamRequest(endpoint, data, callbacks, signal) {
142
+ let isCancelled = false;
143
+ const processStream = async (response) => {
144
+ const reader = response.body?.pipeThrough(new TextDecoderStream()).getReader();
145
+ if (!reader) {
146
+ throw new Error("Response body is null");
147
+ }
148
+ while (!isCancelled && !signal?.aborted) {
149
+ try {
150
+ const { value, done } = await reader.read();
151
+ if (done) {
152
+ callbacks.onClose?.();
153
+ break;
154
+ }
155
+ const lines = value.split("\n");
156
+ for (const line of lines) {
157
+ if (!line.startsWith("data: ")) continue;
158
+ try {
159
+ const jsonString = line.replace("data: ", "").trim();
160
+ const parsedData = JSON.parse(
161
+ jsonString
162
+ );
163
+ await callbacks.onMessage(parsedData);
164
+ } catch (parseError) {
165
+ console.error("Error parsing JSON:", parseError);
166
+ await callbacks.onError(
167
+ new Error("Error processing server response")
168
+ );
169
+ }
170
+ }
171
+ } catch (streamError) {
172
+ console.error("Stream error:", streamError);
173
+ await callbacks.onError(new Error("Error reading stream"));
174
+ break;
175
+ }
176
+ }
177
+ };
178
+ const startStream = async () => {
179
+ try {
180
+ const response = await fetch(this._buildApiUrl(endpoint), {
181
+ method: "POST",
182
+ headers: {
183
+ "Content-Type": "application/json",
184
+ Accept: "text/event-stream"
185
+ },
186
+ body: JSON.stringify(data),
187
+ signal
188
+ });
189
+ if (!response.ok) {
190
+ throw new Error(`HTTP error! status: ${response.status}`);
191
+ }
192
+ await processStream(response);
193
+ } catch (error) {
194
+ if (signal?.aborted) {
195
+ return;
196
+ }
197
+ console.error("Request error:", error);
198
+ const errorMessage = error instanceof Error ? error.message : "Error connecting to server";
199
+ await callbacks.onError(new Error(errorMessage));
200
+ }
201
+ };
202
+ try {
203
+ startStream();
204
+ } catch (error) {
205
+ const errorMessage = error instanceof Error ? error.message : "Failed to start stream";
206
+ callbacks.onError(new Error(errorMessage));
207
+ }
208
+ return () => {
209
+ isCancelled = true;
210
+ };
211
+ }
212
+ };
213
+ // Annotate the CommonJS export names for ESM import in node:
214
+ 0 && (module.exports = {
215
+ ChatResponseType,
216
+ FeedbackType,
217
+ LiveUpdateType,
218
+ MessageRole,
219
+ RagbitsClient
220
+ });
@@ -0,0 +1,40 @@
1
+ import type { ClientConfig, StreamCallbacks, ApiEndpointPath, ApiEndpointResponse, TypedApiRequestOptions, StreamingEndpointPath, StreamingEndpointRequest, StreamingEndpointStream } from './types';
2
+ /**
3
+ * Client for communicating with the Ragbits API
4
+ */
5
+ export declare class RagbitsClient {
6
+ private readonly baseUrl;
7
+ /**
8
+ * @param config - Configuration object
9
+ */
10
+ constructor(config?: ClientConfig);
11
+ /**
12
+ * Get the base URL used by this client
13
+ */
14
+ getBaseUrl(): string;
15
+ /**
16
+ * Build full API URL from path
17
+ * @private
18
+ */
19
+ private _buildApiUrl;
20
+ /**
21
+ * Make a request to the API
22
+ * @private
23
+ */
24
+ private _makeRequest;
25
+ /**
26
+ * Method to make API requests to known endpoints only
27
+ * @param endpoint - API endpoint path (must be predefined)
28
+ * @param options - Typed request options for the specific endpoint
29
+ */
30
+ makeRequest<T extends ApiEndpointPath>(endpoint: T, options?: TypedApiRequestOptions<T>): Promise<ApiEndpointResponse<T>>;
31
+ /**
32
+ * Method for streaming requests to known endpoints only
33
+ * @param endpoint - Streaming endpoint path (must be predefined)
34
+ * @param data - Request data
35
+ * @param callbacks - Stream callbacks
36
+ * @param signal - Optional AbortSignal for cancelling the request
37
+ */
38
+ makeStreamRequest<T extends StreamingEndpointPath>(endpoint: T, data: StreamingEndpointRequest<T>, callbacks: StreamCallbacks<StreamingEndpointStream<T>>, signal?: AbortSignal): () => void;
39
+ }
40
+ export * from './types';