@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/dist/index.js ADDED
@@ -0,0 +1,189 @@
1
+ // src/types.ts
2
+ var MessageRole = /* @__PURE__ */ ((MessageRole2) => {
3
+ MessageRole2["USER"] = "user";
4
+ MessageRole2["ASSISTANT"] = "assistant";
5
+ MessageRole2["SYSTEM"] = "system";
6
+ return MessageRole2;
7
+ })(MessageRole || {});
8
+ var ChatResponseType = /* @__PURE__ */ ((ChatResponseType2) => {
9
+ ChatResponseType2["MESSAGE"] = "message";
10
+ ChatResponseType2["REFERENCE"] = "reference";
11
+ ChatResponseType2["STATE_UPDATE"] = "state_update";
12
+ ChatResponseType2["TEXT"] = "text";
13
+ ChatResponseType2["MESSAGE_ID"] = "message_id";
14
+ ChatResponseType2["CONVERSATION_ID"] = "conversation_id";
15
+ ChatResponseType2["LIVE_UPDATE"] = "live_update";
16
+ ChatResponseType2["FOLLOWUP_MESSAGES"] = "followup_messages";
17
+ return ChatResponseType2;
18
+ })(ChatResponseType || {});
19
+ var FeedbackType = /* @__PURE__ */ ((FeedbackType2) => {
20
+ FeedbackType2["LIKE"] = "like";
21
+ FeedbackType2["DISLIKE"] = "dislike";
22
+ return FeedbackType2;
23
+ })(FeedbackType || {});
24
+ var LiveUpdateType = /* @__PURE__ */ ((LiveUpdateType2) => {
25
+ LiveUpdateType2["START"] = "START";
26
+ LiveUpdateType2["FINISH"] = "FINISH";
27
+ return LiveUpdateType2;
28
+ })(LiveUpdateType || {});
29
+
30
+ // src/index.ts
31
+ var RagbitsClient = class {
32
+ /**
33
+ * @param config - Configuration object
34
+ */
35
+ constructor(config = {}) {
36
+ this.baseUrl = config.baseUrl || "http://127.0.0.1:8000";
37
+ try {
38
+ new URL(this.baseUrl);
39
+ } catch {
40
+ throw new Error(
41
+ `Invalid base URL: ${this.baseUrl}. Please provide a valid URL.`
42
+ );
43
+ }
44
+ if (this.baseUrl.endsWith("/")) {
45
+ this.baseUrl = this.baseUrl.slice(0, -1);
46
+ }
47
+ }
48
+ /**
49
+ * Get the base URL used by this client
50
+ */
51
+ getBaseUrl() {
52
+ return this.baseUrl;
53
+ }
54
+ /**
55
+ * Build full API URL from path
56
+ * @private
57
+ */
58
+ _buildApiUrl(path) {
59
+ return `${this.baseUrl}${path}`;
60
+ }
61
+ /**
62
+ * Make a request to the API
63
+ * @private
64
+ */
65
+ async _makeRequest(url, options = {}) {
66
+ const defaultOptions = {
67
+ headers: {
68
+ "Content-Type": "application/json"
69
+ }
70
+ };
71
+ const response = await fetch(url, { ...defaultOptions, ...options });
72
+ if (!response.ok) {
73
+ throw new Error(`HTTP error! status: ${response.status}`);
74
+ }
75
+ return response;
76
+ }
77
+ /**
78
+ * Method to make API requests to known endpoints only
79
+ * @param endpoint - API endpoint path (must be predefined)
80
+ * @param options - Typed request options for the specific endpoint
81
+ */
82
+ async makeRequest(endpoint, options) {
83
+ const {
84
+ method = "GET",
85
+ body,
86
+ headers = {},
87
+ ...restOptions
88
+ } = options || {};
89
+ const requestOptions = {
90
+ method,
91
+ headers,
92
+ ...restOptions
93
+ // This will include signal and other fetch options
94
+ };
95
+ if (body && method !== "GET") {
96
+ requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
97
+ }
98
+ const response = await this._makeRequest(
99
+ this._buildApiUrl(endpoint),
100
+ requestOptions
101
+ );
102
+ return response.json();
103
+ }
104
+ /**
105
+ * Method for streaming requests to known endpoints only
106
+ * @param endpoint - Streaming endpoint path (must be predefined)
107
+ * @param data - Request data
108
+ * @param callbacks - Stream callbacks
109
+ * @param signal - Optional AbortSignal for cancelling the request
110
+ */
111
+ makeStreamRequest(endpoint, data, callbacks, signal) {
112
+ let isCancelled = false;
113
+ const processStream = async (response) => {
114
+ const reader = response.body?.pipeThrough(new TextDecoderStream()).getReader();
115
+ if (!reader) {
116
+ throw new Error("Response body is null");
117
+ }
118
+ while (!isCancelled && !signal?.aborted) {
119
+ try {
120
+ const { value, done } = await reader.read();
121
+ if (done) {
122
+ callbacks.onClose?.();
123
+ break;
124
+ }
125
+ const lines = value.split("\n");
126
+ for (const line of lines) {
127
+ if (!line.startsWith("data: ")) continue;
128
+ try {
129
+ const jsonString = line.replace("data: ", "").trim();
130
+ const parsedData = JSON.parse(
131
+ jsonString
132
+ );
133
+ await callbacks.onMessage(parsedData);
134
+ } catch (parseError) {
135
+ console.error("Error parsing JSON:", parseError);
136
+ await callbacks.onError(
137
+ new Error("Error processing server response")
138
+ );
139
+ }
140
+ }
141
+ } catch (streamError) {
142
+ console.error("Stream error:", streamError);
143
+ await callbacks.onError(new Error("Error reading stream"));
144
+ break;
145
+ }
146
+ }
147
+ };
148
+ const startStream = async () => {
149
+ try {
150
+ const response = await fetch(this._buildApiUrl(endpoint), {
151
+ method: "POST",
152
+ headers: {
153
+ "Content-Type": "application/json",
154
+ Accept: "text/event-stream"
155
+ },
156
+ body: JSON.stringify(data),
157
+ signal
158
+ });
159
+ if (!response.ok) {
160
+ throw new Error(`HTTP error! status: ${response.status}`);
161
+ }
162
+ await processStream(response);
163
+ } catch (error) {
164
+ if (signal?.aborted) {
165
+ return;
166
+ }
167
+ console.error("Request error:", error);
168
+ const errorMessage = error instanceof Error ? error.message : "Error connecting to server";
169
+ await callbacks.onError(new Error(errorMessage));
170
+ }
171
+ };
172
+ try {
173
+ startStream();
174
+ } catch (error) {
175
+ const errorMessage = error instanceof Error ? error.message : "Failed to start stream";
176
+ callbacks.onError(new Error(errorMessage));
177
+ }
178
+ return () => {
179
+ isCancelled = true;
180
+ };
181
+ }
182
+ };
183
+ export {
184
+ ChatResponseType,
185
+ FeedbackType,
186
+ LiveUpdateType,
187
+ MessageRole,
188
+ RagbitsClient
189
+ };
@@ -0,0 +1,238 @@
1
+ import { RJSFSchema } from '@rjsf/utils';
2
+ /**
3
+ * Message roles for chat conversations
4
+ */
5
+ export declare enum MessageRole {
6
+ USER = "user",
7
+ ASSISTANT = "assistant",
8
+ SYSTEM = "system"
9
+ }
10
+ /**
11
+ * Message structure for chat conversations
12
+ */
13
+ export interface Message {
14
+ role: MessageRole;
15
+ content: string;
16
+ id?: string;
17
+ }
18
+ /**
19
+ * Reference structure for document references
20
+ */
21
+ export interface Reference {
22
+ title: string;
23
+ content: string;
24
+ url?: string;
25
+ }
26
+ /**
27
+ * Response types from the API
28
+ */
29
+ export declare enum ChatResponseType {
30
+ MESSAGE = "message",
31
+ REFERENCE = "reference",
32
+ STATE_UPDATE = "state_update",
33
+ TEXT = "text",
34
+ MESSAGE_ID = "message_id",
35
+ CONVERSATION_ID = "conversation_id",
36
+ LIVE_UPDATE = "live_update",
37
+ FOLLOWUP_MESSAGES = "followup_messages"
38
+ }
39
+ /**
40
+ * Feedback types for user feedback
41
+ */
42
+ export declare enum FeedbackType {
43
+ LIKE = "like",
44
+ DISLIKE = "dislike"
45
+ }
46
+ /**
47
+ * Server state interface for state updates
48
+ */
49
+ export interface ServerState {
50
+ state: Record<string, unknown>;
51
+ signature: string;
52
+ }
53
+ export declare enum LiveUpdateType {
54
+ START = "START",
55
+ FINISH = "FINISH"
56
+ }
57
+ export interface LiveUpdate {
58
+ update_id: string;
59
+ type: LiveUpdateType;
60
+ content: {
61
+ label: string;
62
+ description?: string;
63
+ };
64
+ }
65
+ /**
66
+ * Specific chat response types
67
+ */
68
+ interface MessageIdChatResponse {
69
+ type: ChatResponseType.MESSAGE_ID;
70
+ content: string;
71
+ }
72
+ interface TextChatResponse {
73
+ type: ChatResponseType.TEXT;
74
+ content: string;
75
+ }
76
+ interface ReferenceChatResponse {
77
+ type: ChatResponseType.REFERENCE;
78
+ content: Reference;
79
+ }
80
+ interface ConversationIdChatResponse {
81
+ type: ChatResponseType.CONVERSATION_ID;
82
+ content: string;
83
+ }
84
+ interface StateUpdateChatResponse {
85
+ type: ChatResponseType.STATE_UPDATE;
86
+ content: ServerState;
87
+ }
88
+ interface LiveUpdateChatResponse {
89
+ type: ChatResponseType.LIVE_UPDATE;
90
+ content: LiveUpdate;
91
+ }
92
+ interface FollowupMessagesChatResponse {
93
+ type: ChatResponseType.FOLLOWUP_MESSAGES;
94
+ content: string[];
95
+ }
96
+ /**
97
+ * Typed chat response union
98
+ */
99
+ export type TypedChatResponse = TextChatResponse | ReferenceChatResponse | MessageIdChatResponse | ConversationIdChatResponse | StateUpdateChatResponse | LiveUpdateChatResponse | FollowupMessagesChatResponse;
100
+ /**
101
+ * Base chat request to the API
102
+ */
103
+ export interface ChatRequest {
104
+ message: string;
105
+ history: Message[];
106
+ context?: Record<string, unknown>;
107
+ }
108
+ /**
109
+ * Feedback request to the API
110
+ */
111
+ export interface FeedbackRequest {
112
+ message_id: string;
113
+ feedback: FeedbackType;
114
+ payload: Record<string, unknown> | null;
115
+ }
116
+ /**
117
+ * Feedback response from the API
118
+ */
119
+ export interface FeedbackResponse {
120
+ status: string;
121
+ }
122
+ /**
123
+ * UI customization configuration
124
+ */
125
+ export interface UICustomization {
126
+ header: {
127
+ title?: string;
128
+ subtitle?: string;
129
+ logo?: string;
130
+ };
131
+ welcome_message?: string;
132
+ }
133
+ /**
134
+ * Configuration response from the API
135
+ */
136
+ export interface ConfigResponse {
137
+ feedback: {
138
+ like: {
139
+ enabled: boolean;
140
+ form: RJSFSchema | null;
141
+ };
142
+ dislike: {
143
+ enabled: boolean;
144
+ form: RJSFSchema | null;
145
+ };
146
+ };
147
+ customization: UICustomization | null;
148
+ }
149
+ /**
150
+ * Configuration for the client
151
+ */
152
+ export interface ClientConfig {
153
+ baseUrl?: string;
154
+ }
155
+ /**
156
+ * Callbacks for handling streaming responses
157
+ */
158
+ export interface StreamCallbacks<T, E = Error> {
159
+ onMessage: (data: T) => void | Promise<void>;
160
+ onError: (error: E) => void | Promise<void>;
161
+ onClose?: () => void | Promise<void>;
162
+ }
163
+ /**
164
+ * Regular API endpoint definitions with their request/response types
165
+ */
166
+ export interface ApiEndpoints {
167
+ '/api/config': {
168
+ method: 'GET';
169
+ request: never;
170
+ response: ConfigResponse;
171
+ };
172
+ '/api/feedback': {
173
+ method: 'POST';
174
+ request: FeedbackRequest;
175
+ response: FeedbackResponse;
176
+ };
177
+ }
178
+ /**
179
+ * Streaming API endpoint definitions with their request/stream response types
180
+ */
181
+ export interface StreamingEndpoints {
182
+ '/api/chat': {
183
+ method: 'POST';
184
+ request: ChatRequest;
185
+ stream: TypedChatResponse;
186
+ };
187
+ }
188
+ /**
189
+ * Extract endpoint paths as a union type
190
+ */
191
+ export type ApiEndpointPath = keyof ApiEndpoints;
192
+ /**
193
+ * Extract streaming endpoint paths as a union type
194
+ */
195
+ export type StreamingEndpointPath = keyof StreamingEndpoints;
196
+ /**
197
+ * Extract request type for a specific API endpoint
198
+ */
199
+ export type ApiEndpointRequest<T extends ApiEndpointPath> = ApiEndpoints[T]['request'];
200
+ /**
201
+ * Extract response type for a specific API endpoint
202
+ */
203
+ export type ApiEndpointResponse<T extends ApiEndpointPath> = ApiEndpoints[T]['response'];
204
+ /**
205
+ * Extract HTTP method for a specific API endpoint
206
+ */
207
+ export type ApiEndpointMethod<T extends ApiEndpointPath> = ApiEndpoints[T]['method'];
208
+ /**
209
+ * Extract request type for a specific streaming endpoint
210
+ */
211
+ export type StreamingEndpointRequest<T extends StreamingEndpointPath> = StreamingEndpoints[T]['request'];
212
+ /**
213
+ * Extract stream response type for a specific streaming endpoint
214
+ */
215
+ export type StreamingEndpointStream<T extends StreamingEndpointPath> = StreamingEndpoints[T]['stream'];
216
+ /**
217
+ * Extract HTTP method for a specific streaming endpoint
218
+ */
219
+ export type StreamingEndpointMethod<T extends StreamingEndpointPath> = StreamingEndpoints[T]['method'];
220
+ /**
221
+ * Generic request options for API endpoints with typed methods and body
222
+ */
223
+ export interface TypedApiRequestOptions<T extends ApiEndpointPath> {
224
+ method?: ApiEndpointMethod<T>;
225
+ body?: ApiEndpointRequest<T> extends never ? undefined : ApiEndpointRequest<T>;
226
+ headers?: Record<string, string>;
227
+ signal?: AbortSignal;
228
+ }
229
+ /**
230
+ * Typed request options for specific streaming endpoints
231
+ */
232
+ export interface TypedStreamRequestOptions<T extends StreamingEndpointPath> {
233
+ method?: StreamingEndpointMethod<T>;
234
+ body?: StreamingEndpointRequest<T>;
235
+ headers?: Record<string, string>;
236
+ signal?: AbortSignal;
237
+ }
238
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ragbits/api-client",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "JavaScript client for the Ragbits API",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -14,14 +14,15 @@
14
14
  }
15
15
  },
16
16
  "scripts": {
17
- "build": "tsup src/index.ts --format cjs,esm --dts",
18
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
17
+ "build": "npm run clean && tsup src/index.ts --format cjs,esm && tsc --emitDeclarationOnly --declaration --project tsconfig.json",
18
+ "dev": "tsc -b . --watch",
19
19
  "test": "vitest",
20
20
  "test:run": "vitest run",
21
21
  "test:coverage": "vitest run --coverage",
22
22
  "lint": "eslint .",
23
23
  "format": "prettier --write .",
24
- "format:check": "prettier --check ."
24
+ "format:check": "prettier --check .",
25
+ "clean": "rm -rf ./dist"
25
26
  },
26
27
  "keywords": [
27
28
  "ragbits",
package/eslint.config.js DELETED
@@ -1,21 +0,0 @@
1
- import js from '@eslint/js'
2
- import globals from 'globals'
3
- import tseslint from 'typescript-eslint'
4
-
5
- export default tseslint.config(
6
- { ignores: ['dist', 'coverage'] },
7
- {
8
- extends: [js.configs.recommended, ...tseslint.configs.recommended],
9
- files: ['**/*.{ts,tsx}'],
10
- languageOptions: {
11
- ecmaVersion: 2020,
12
- globals: globals.node,
13
- },
14
- rules: {
15
- '@typescript-eslint/no-unused-vars': [
16
- 'error',
17
- { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
18
- ],
19
- },
20
- }
21
- )
@@ -1,6 +0,0 @@
1
- export default {
2
- trailingComma: 'es5',
3
- tabWidth: 4,
4
- semi: false,
5
- singleQuote: true,
6
- }
package/src/index.ts DELETED
@@ -1,213 +0,0 @@
1
- import type {
2
- ClientConfig,
3
- StreamCallbacks,
4
- ApiEndpointPath,
5
- ApiEndpointResponse,
6
- TypedApiRequestOptions,
7
- StreamingEndpointPath,
8
- StreamingEndpointRequest,
9
- StreamingEndpointStream,
10
- } from './types'
11
-
12
- /**
13
- * Client for communicating with the Ragbits API
14
- */
15
- export class RagbitsClient {
16
- private readonly baseUrl: string
17
-
18
- /**
19
- * @param config - Configuration object
20
- */
21
- constructor(config: ClientConfig = {}) {
22
- this.baseUrl = config.baseUrl || 'http://127.0.0.1:8000'
23
-
24
- // Validate the base URL
25
- try {
26
- new URL(this.baseUrl)
27
- } catch {
28
- throw new Error(
29
- `Invalid base URL: ${this.baseUrl}. Please provide a valid URL.`
30
- )
31
- }
32
-
33
- if (this.baseUrl.endsWith('/')) {
34
- this.baseUrl = this.baseUrl.slice(0, -1)
35
- }
36
- }
37
-
38
- /**
39
- * Get the base URL used by this client
40
- */
41
- getBaseUrl(): string {
42
- return this.baseUrl
43
- }
44
-
45
- /**
46
- * Build full API URL from path
47
- * @private
48
- */
49
- private _buildApiUrl(path: string): string {
50
- return `${this.baseUrl}${path}`
51
- }
52
-
53
- /**
54
- * Make a request to the API
55
- * @private
56
- */
57
- private async _makeRequest(
58
- url: string,
59
- options: RequestInit = {}
60
- ): Promise<Response> {
61
- const defaultOptions: RequestInit = {
62
- headers: {
63
- 'Content-Type': 'application/json',
64
- },
65
- }
66
-
67
- const response = await fetch(url, { ...defaultOptions, ...options })
68
- if (!response.ok) {
69
- throw new Error(`HTTP error! status: ${response.status}`)
70
- }
71
- return response
72
- }
73
-
74
- /**
75
- * Method to make API requests to known endpoints only
76
- * @param endpoint - API endpoint path (must be predefined)
77
- * @param options - Typed request options for the specific endpoint
78
- */
79
- async makeRequest<T extends ApiEndpointPath>(
80
- endpoint: T,
81
- options?: TypedApiRequestOptions<T>
82
- ): Promise<ApiEndpointResponse<T>> {
83
- const {
84
- method = 'GET',
85
- body,
86
- headers = {},
87
- ...restOptions
88
- } = options || {}
89
-
90
- const requestOptions: RequestInit = {
91
- method,
92
- headers,
93
- ...restOptions, // This will include signal and other fetch options
94
- }
95
-
96
- if (body && method !== 'GET') {
97
- requestOptions.body =
98
- typeof body === 'string' ? body : JSON.stringify(body)
99
- }
100
-
101
- const response = await this._makeRequest(
102
- this._buildApiUrl(endpoint),
103
- requestOptions
104
- )
105
- return response.json()
106
- }
107
-
108
- /**
109
- * Method for streaming requests to known endpoints only
110
- * @param endpoint - Streaming endpoint path (must be predefined)
111
- * @param data - Request data
112
- * @param callbacks - Stream callbacks
113
- * @param signal - Optional AbortSignal for cancelling the request
114
- */
115
- makeStreamRequest<T extends StreamingEndpointPath>(
116
- endpoint: T,
117
- data: StreamingEndpointRequest<T>,
118
- callbacks: StreamCallbacks<StreamingEndpointStream<T>>,
119
- signal?: AbortSignal
120
- ): () => void {
121
- let isCancelled = false
122
-
123
- const processStream = async (response: Response): Promise<void> => {
124
- const reader = response.body
125
- ?.pipeThrough(new TextDecoderStream())
126
- .getReader()
127
-
128
- if (!reader) {
129
- throw new Error('Response body is null')
130
- }
131
-
132
- while (!isCancelled && !signal?.aborted) {
133
- try {
134
- const { value, done } = await reader.read()
135
- if (done) {
136
- callbacks.onClose?.()
137
- break
138
- }
139
-
140
- const lines = value.split('\n')
141
- for (const line of lines) {
142
- if (!line.startsWith('data: ')) continue
143
-
144
- try {
145
- const jsonString = line.replace('data: ', '').trim()
146
- const parsedData = JSON.parse(
147
- jsonString
148
- ) as StreamingEndpointStream<T>
149
- await callbacks.onMessage(parsedData)
150
- } catch (parseError) {
151
- console.error('Error parsing JSON:', parseError)
152
- await callbacks.onError(
153
- new Error('Error processing server response')
154
- )
155
- }
156
- }
157
- } catch (streamError) {
158
- console.error('Stream error:', streamError)
159
- await callbacks.onError(new Error('Error reading stream'))
160
- break
161
- }
162
- }
163
- }
164
-
165
- const startStream = async (): Promise<void> => {
166
- try {
167
- const response = await fetch(this._buildApiUrl(endpoint), {
168
- method: 'POST',
169
- headers: {
170
- 'Content-Type': 'application/json',
171
- Accept: 'text/event-stream',
172
- },
173
- body: JSON.stringify(data),
174
- signal,
175
- })
176
-
177
- if (!response.ok) {
178
- throw new Error(`HTTP error! status: ${response.status}`)
179
- }
180
-
181
- await processStream(response)
182
- } catch (error) {
183
- if (signal?.aborted) {
184
- return
185
- }
186
-
187
- console.error('Request error:', error)
188
- const errorMessage =
189
- error instanceof Error
190
- ? error.message
191
- : 'Error connecting to server'
192
- await callbacks.onError(new Error(errorMessage))
193
- }
194
- }
195
-
196
- try {
197
- startStream()
198
- } catch (error) {
199
- const errorMessage =
200
- error instanceof Error
201
- ? error.message
202
- : 'Failed to start stream'
203
- callbacks.onError(new Error(errorMessage))
204
- }
205
-
206
- return () => {
207
- isCancelled = true
208
- }
209
- }
210
- }
211
-
212
- // Re-export types
213
- export * from './types'