oblien 1.1.1 → 1.1.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
@@ -25,9 +25,8 @@ import { OblienCredits } from 'oblien/credits';
25
25
 
26
26
  // Initialize client
27
27
  const client = new OblienClient({
28
- apiKey: 'your-client-id',
29
- apiSecret: 'your-client-secret',
30
- baseURL: 'https://api.oblien.com' // Optional
28
+ clientId: 'your-client-id',
29
+ clientSecret: 'your-client-secret'
31
30
  });
32
31
 
33
32
  // Use modules
@@ -88,7 +87,7 @@ const overview = await agentInstance.getOverview({ days: 7 });
88
87
 
89
88
  ### 💬 Chat Module
90
89
 
91
- Create and manage chat sessions with guest support.
90
+ Create sessions, send messages, and manage guests with streaming support.
92
91
 
93
92
  ```javascript
94
93
  import { OblienChat } from 'oblien/chat';
@@ -101,6 +100,27 @@ const session = await chat.createSession({
101
100
  namespace: 'production'
102
101
  });
103
102
 
103
+ // Send message with streaming
104
+ await chat.send({
105
+ token: session.token,
106
+ message: 'Tell me about AI',
107
+ stream: true,
108
+ onChunk: (data) => console.log(data)
109
+ });
110
+
111
+ // Upload files
112
+ const uploadResult = await chat.upload({
113
+ token: session.token,
114
+ files: fileArray
115
+ });
116
+
117
+ // Send message with uploaded files
118
+ await chat.send({
119
+ token: session.token,
120
+ message: 'Analyze these files',
121
+ uploadId: uploadResult.uploadId
122
+ });
123
+
104
124
  // Create guest session
105
125
  const guestSession = await chat.createGuestSession({
106
126
  ip: '192.168.1.1',
@@ -108,17 +128,20 @@ const guestSession = await chat.createGuestSession({
108
128
  agentId: 'agent-id'
109
129
  });
110
130
 
111
- // List sessions
112
- const sessions = await chat.listSessions({ limit: 20 });
131
+ // Get guest usage
132
+ const usage = await chat.getGuestUsage(guestSession.token);
113
133
  ```
114
134
 
115
135
  **Features:**
116
- - ✅ Session management
117
- - ✅ Guest sessions with fingerprint tracking
118
- - ✅ Token generation
119
- - ✅ Automatic guest ID generation
136
+ - ✅ Session management (create, list, delete)
137
+ - ✅ Message sending with streaming support
138
+ - ✅ File uploads for agent analysis
139
+ - ✅ Guest sessions with IP + fingerprint tracking
140
+ - ✅ Guest usage monitoring and rate limiting
141
+ - ✅ Hybrid mode (works with token or client credentials)
142
+ - ✅ Cache statistics for monitoring
120
143
 
121
- 📖 [Documentation](./docs/CHAT.md) | 💡 [Examples](./examples/chat-example.js)
144
+ 📖 [Full Documentation](./docs/CHAT.md) | 💡 [Examples](./examples/chat-example.js)
122
145
 
123
146
  ---
124
147
 
@@ -284,8 +307,8 @@ import { OblienSandboxes } from 'oblien/sandbox';
284
307
 
285
308
  // Initialize
286
309
  const client = new OblienClient({
287
- apiKey: 'your-client-id',
288
- apiSecret: 'your-client-secret'
310
+ clientId: 'your-client-id',
311
+ clientSecret: 'your-client-secret'
289
312
  });
290
313
 
291
314
  const agents = new OblienAgents(client);
@@ -384,8 +407,8 @@ All modules use client credentials authentication:
384
407
 
385
408
  ```javascript
386
409
  const client = new OblienClient({
387
- apiKey: 'your-client-id', // X-Client-ID header
388
- apiSecret: 'your-client-secret' // X-Client-Secret header
410
+ clientId: 'your-client-id', // X-Client-ID header
411
+ clientSecret: 'your-client-secret' // X-Client-Secret header
389
412
  });
390
413
  ```
391
414
 
@@ -409,8 +432,8 @@ import {
409
432
  } from 'oblien';
410
433
 
411
434
  const client: OblienClient = new OblienClient({
412
- apiKey: string,
413
- apiSecret: string
435
+ clientId: string,
436
+ clientSecret: string
414
437
  });
415
438
  ```
416
439
 
@@ -518,6 +541,14 @@ MIT License - see LICENSE file for details
518
541
 
519
542
  ## Changelog
520
543
 
544
+ ### v1.3.0 (Latest)
545
+ - ✅ Added `send()` method to Chat module with streaming support
546
+ - ✅ Added `upload()` method for file attachments
547
+ - ✅ Added guest usage monitoring (`getGuestUsage()`)
548
+ - ✅ Added cache statistics (`getCacheStatistics()`)
549
+ - ✅ Hybrid mode support (token or client credentials)
550
+ - ✅ Complete Chat documentation with examples
551
+
521
552
  ### v1.2.0
522
553
  - ✅ Added Sandboxes module
523
554
  - ✅ Enhanced Agents module with proper settings sections
package/index.d.ts CHANGED
@@ -5,10 +5,9 @@
5
5
  // ============ Client Types ============
6
6
 
7
7
  export interface OblienConfig {
8
- apiKey: string;
9
- apiSecret?: string;
8
+ clientId: string;
9
+ clientSecret: string;
10
10
  baseURL?: string;
11
- version?: string;
12
11
  }
13
12
 
14
13
  export class OblienClient {
@@ -101,6 +100,10 @@ export interface SessionOptions {
101
100
  isGuest?: boolean;
102
101
  namespace?: string;
103
102
  workspace?: Record<string, any>;
103
+ ipAddress?: string;
104
+ userAgent?: string;
105
+ fingerprint?: string;
106
+ endUserId?: string;
104
107
  }
105
108
 
106
109
  export interface SessionData {
@@ -136,6 +139,11 @@ export interface CreateSessionOptions {
136
139
  workflowId?: string;
137
140
  namespace?: string; // For authenticated users, typically user_id
138
141
  workspace?: Record<string, any>;
142
+ endUserId?: string;
143
+ isGuest?: boolean;
144
+ ipAddress?: string;
145
+ userAgent?: string;
146
+ fingerprint?: string;
139
147
  }
140
148
 
141
149
  export interface CreateGuestSessionOptions {
@@ -145,6 +153,7 @@ export interface CreateGuestSessionOptions {
145
153
  workflowId?: string;
146
154
  metadata?: Record<string, any>;
147
155
  workspace?: Record<string, any>;
156
+ endUserId?: string;
148
157
  }
149
158
 
150
159
  export interface GuestSessionData extends SessionData {
@@ -155,17 +164,60 @@ export interface GuestSessionData extends SessionData {
155
164
  };
156
165
  }
157
166
 
167
+ export interface SendMessageOptions {
168
+ token?: string;
169
+ message: string;
170
+ uploadId?: string;
171
+ files?: any[];
172
+ stream?: boolean;
173
+ onChunk?: (data: any) => void;
174
+ onError?: (error: Error) => void;
175
+ onComplete?: () => void;
176
+ metadata?: Record<string, any>;
177
+ }
178
+
179
+ export interface UploadOptions {
180
+ token?: string;
181
+ files: any[] | any;
182
+ metadata?: Record<string, any>;
183
+ }
184
+
185
+ export interface GuestUsageInfo {
186
+ success: boolean;
187
+ namespace: string;
188
+ requestCount: number;
189
+ limit: number;
190
+ remaining: number;
191
+ resetAt?: Date;
192
+ }
193
+
194
+ export interface CacheStatistics {
195
+ success: boolean;
196
+ cache: {
197
+ keys: number;
198
+ hits: number;
199
+ misses: number;
200
+ hitRate: number;
201
+ keysSize: number;
202
+ valuesSize: number;
203
+ };
204
+ }
205
+
158
206
  export class OblienChat {
159
207
  constructor(client: OblienClient, options?: ChatOptions);
160
208
 
161
209
  createSession(options: CreateSessionOptions): Promise<SessionData>;
162
210
  createGuestSession(options: CreateGuestSessionOptions): Promise<GuestSessionData>;
163
211
  getGuest(ip: string, fingerprint?: string): Promise<Guest | null>;
212
+ send(options: SendMessageOptions): Promise<any>;
213
+ upload(options: UploadOptions): Promise<any>;
164
214
  getSession(sessionId: string): Promise<any>;
165
215
  listSessions(options?: Record<string, any>): Promise<any[]>;
166
216
  deleteSession(sessionId: string): Promise<any>;
167
217
  getAllGuests(): Promise<Guest[]>;
168
218
  cleanupGuests(): Promise<number>;
219
+ getGuestUsage(token: string): Promise<GuestUsageInfo>;
220
+ getCacheStatistics(): Promise<CacheStatistics>;
169
221
  }
170
222
 
171
223
  // ============ Namespaces ============
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oblien",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Server-side SDK for Oblien AI Platform - Build AI-powered applications with chat, agents, and workflows",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/src/chat/index.js CHANGED
@@ -34,6 +34,12 @@ export class OblienChat {
34
34
  * @param {string} options.agentId - Agent ID to chat with
35
35
  * @param {string} [options.workflowId] - Workflow ID (if using workflow)
36
36
  * @param {Object} [options.workspace] - Workspace configuration
37
+ * @param {string} [options.endUserId] - End user ID (for client's end users)
38
+ * @param {string} [options.namespace] - Guest namespace for rate limiting
39
+ * @param {boolean} [options.isGuest] - Is this a guest session
40
+ * @param {string} [options.ipAddress] - IP address of the user
41
+ * @param {string} [options.userAgent] - User agent of the user
42
+ * @param {string} [options.fingerprint] - Fingerprint of the user
37
43
  * @returns {Promise<Object>} Session data with token
38
44
  */
39
45
  async createSession(options) {
@@ -54,10 +60,11 @@ export class OblienChat {
54
60
  * @param {string} [options.workflowId] - Workflow ID
55
61
  * @param {Object} [options.metadata] - Additional guest metadata
56
62
  * @param {Object} [options.workspace] - Workspace configuration
63
+ * @param {string} [options.endUserId] - End user ID (for client's end users)
57
64
  * @returns {Promise<Object>} Session data with token and guest info
58
65
  */
59
66
  async createGuestSession(options) {
60
- const { ip, fingerprint, agentId, workflowId, metadata = {}, workspace } = options;
67
+ const { ip, fingerprint, agentId, workflowId, metadata = {}, workspace, endUserId } = options;
61
68
 
62
69
  if (!ip) {
63
70
  throw new Error('IP address is required for guest sessions');
@@ -81,6 +88,7 @@ export class OblienChat {
81
88
  ipAddress: ip,
82
89
  userAgent: metadata.userAgent,
83
90
  fingerprint: fingerprint,
91
+ endUserId: endUserId,
84
92
  });
85
93
 
86
94
  const sessionData = await session.create();
@@ -130,6 +138,205 @@ export class OblienChat {
130
138
  return null;
131
139
  }
132
140
 
141
+ /**
142
+ * Send a message in a chat session
143
+ * Hybrid mode: Works with session token OR client credentials
144
+ *
145
+ * @param {Object} options - Send options
146
+ * @param {string} [options.token] - Session token (optional, uses client credentials if not provided)
147
+ * @param {string} options.message - Message to send
148
+ * @param {string} [options.uploadId] - Upload ID for attached files
149
+ * @param {Array} [options.files] - File attachments (alternative to uploadId)
150
+ * @param {boolean} [options.stream] - Enable streaming response
151
+ * @param {Function} [options.onChunk] - Callback for streaming chunks (data) => void
152
+ * @param {Function} [options.onError] - Callback for errors (error) => void
153
+ * @param {Function} [options.onComplete] - Callback when stream completes () => void
154
+ * @param {Object} [options.metadata] - Additional metadata
155
+ * @returns {Promise<Object>} Response data
156
+ */
157
+ async send(options = {}) {
158
+ const {
159
+ token,
160
+ message,
161
+ uploadId,
162
+ files,
163
+ stream = false,
164
+ onChunk,
165
+ onError,
166
+ onComplete,
167
+ metadata = {}
168
+ } = options;
169
+
170
+ if (!message || !message.trim()) {
171
+ throw new Error('Message is required');
172
+ }
173
+
174
+ const payload = {
175
+ message,
176
+ stream,
177
+ ...metadata,
178
+ };
179
+
180
+ if (uploadId) {
181
+ payload.upload_id = uploadId;
182
+ }
183
+
184
+ if (files) {
185
+ payload.files = files;
186
+ }
187
+
188
+ // Build headers - use token if provided, otherwise use client credentials
189
+ const headers = {
190
+ ...this.client.getAuthHeaders(),
191
+ 'Content-Type': 'application/json',
192
+ };
193
+
194
+ if (token) {
195
+ headers['Authorization'] = `Bearer ${token}`;
196
+ }
197
+
198
+ const url = this.client._buildURL('ai/chat/send');
199
+
200
+ if (stream) {
201
+ // Handle streaming response
202
+ const response = await fetch(url, {
203
+ method: 'POST',
204
+ headers,
205
+ body: JSON.stringify(payload),
206
+ });
207
+
208
+ if (!response.ok) {
209
+ const error = await response.text();
210
+ throw new Error(error || `API error: ${response.status}`);
211
+ }
212
+
213
+ // Process SSE stream
214
+ const reader = response.body.getReader();
215
+ const decoder = new TextDecoder();
216
+ let buffer = '';
217
+
218
+ try {
219
+ while (true) {
220
+ const { done, value } = await reader.read();
221
+
222
+ if (done) {
223
+ if (onComplete) onComplete();
224
+ break;
225
+ }
226
+
227
+ buffer += decoder.decode(value, { stream: true });
228
+ const lines = buffer.split('\n');
229
+ buffer = lines.pop() || '';
230
+
231
+ for (const line of lines) {
232
+ if (line.trim() === '') continue;
233
+
234
+ try {
235
+ const data = JSON.parse(line);
236
+ if (onChunk) onChunk(data);
237
+ } catch (e) {
238
+ // Skip non-JSON lines (SSE format)
239
+ if (line.startsWith('data: ')) {
240
+ try {
241
+ const jsonStr = line.substring(6);
242
+ const data = JSON.parse(jsonStr);
243
+ if (onChunk) onChunk(data);
244
+ } catch (parseError) {
245
+ console.warn('Failed to parse chunk:', line);
246
+ }
247
+ }
248
+ }
249
+ }
250
+ }
251
+
252
+ return { success: true, stream: true };
253
+ } catch (error) {
254
+ if (onError) onError(error);
255
+ throw error;
256
+ }
257
+ } else {
258
+ // Regular non-streaming request
259
+ const response = await fetch(url, {
260
+ method: 'POST',
261
+ headers,
262
+ body: JSON.stringify(payload),
263
+ });
264
+
265
+ if (!response.ok) {
266
+ const error = await response.json().catch(() => ({ message: response.statusText }));
267
+ throw new Error(error.message || error.error || `API error: ${response.status}`);
268
+ }
269
+
270
+ return await response.json();
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Upload files for a chat session
276
+ * Hybrid mode: Works with session token OR client credentials
277
+ *
278
+ * @param {Object} options - Upload options
279
+ * @param {string} [options.token] - Session token (optional, uses client credentials if not provided)
280
+ * @param {Array|Object} options.files - Files to upload
281
+ * @param {Object} [options.metadata] - Additional metadata
282
+ * @returns {Promise<Object>} Upload result with uploadId
283
+ */
284
+ async upload(options = {}) {
285
+ const { token, files, metadata } = options;
286
+
287
+ if (!files || (Array.isArray(files) && files.length === 0)) {
288
+ throw new Error('Files are required');
289
+ }
290
+
291
+ const formData = new FormData();
292
+
293
+ // Handle both single file and array of files
294
+ const fileArray = Array.isArray(files) ? files : [files];
295
+
296
+ fileArray.forEach((file, index) => {
297
+ if (file instanceof File || file instanceof Blob) {
298
+ formData.append('files', file);
299
+ } else if (file.path && file.buffer) {
300
+ // Node.js file object
301
+ formData.append('files', file.buffer, file.originalname || file.path);
302
+ } else {
303
+ throw new Error(`Invalid file at index ${index}`);
304
+ }
305
+ });
306
+
307
+ // Add any additional options
308
+ if (metadata) {
309
+ formData.append('metadata', JSON.stringify(metadata));
310
+ }
311
+
312
+ // Build headers - use token if provided, otherwise use client credentials
313
+ const headers = {
314
+ ...this.client.getAuthHeaders(),
315
+ };
316
+
317
+ if (token) {
318
+ headers['Authorization'] = `Bearer ${token}`;
319
+ }
320
+
321
+ // Remove Content-Type for FormData (browser will set it with boundary)
322
+ delete headers['Content-Type'];
323
+
324
+ const url = this.client._buildURL('ai/chat/upload');
325
+
326
+ const response = await fetch(url, {
327
+ method: 'POST',
328
+ headers,
329
+ body: formData,
330
+ });
331
+
332
+ if (!response.ok) {
333
+ const error = await response.json().catch(() => ({ message: response.statusText }));
334
+ throw new Error(error.message || error.error || `API error: ${response.status}`);
335
+ }
336
+
337
+ return await response.json();
338
+ }
339
+
133
340
  /**
134
341
  * Get session info
135
342
  * @param {string} sessionId - Session ID
@@ -173,6 +380,43 @@ export class OblienChat {
173
380
  async cleanupGuests() {
174
381
  return await this.guestManager.cleanup();
175
382
  }
383
+
384
+ /**
385
+ * Get guest usage information (requires session token)
386
+ * @param {string} token - Session token from guest session
387
+ * @returns {Promise<Object>} Usage information for the guest
388
+ */
389
+ async getGuestUsage(token) {
390
+ if (!token) {
391
+ throw new Error('Session token is required');
392
+ }
393
+
394
+ const headers = {
395
+ ...this.client.getAuthHeaders(),
396
+ 'Authorization': `Bearer ${token}`,
397
+ };
398
+
399
+ const response = await fetch(this.client._buildURL('ai/guest/usage'), {
400
+ method: 'GET',
401
+ headers,
402
+ });
403
+
404
+ if (!response.ok) {
405
+ const error = await response.json().catch(() => ({ message: response.statusText }));
406
+ throw new Error(error.message || error.error || `API error: ${response.status}`);
407
+ }
408
+
409
+ return await response.json();
410
+ }
411
+
412
+ /**
413
+ * Get cache statistics (admin/monitoring)
414
+ * @returns {Promise<Object>} Cache statistics
415
+ */
416
+ async getCacheStatistics() {
417
+ const data = await this.client.get('ai/guest/cache-stats');
418
+ return data;
419
+ }
176
420
  }
177
421
 
178
422
  export { ChatSession } from './session.js';
@@ -16,6 +16,7 @@ export class ChatSession {
16
16
  * @param {string} [options.ipAddress] - IP address of the user
17
17
  * @param {string} [options.userAgent] - User agent of the user
18
18
  * @param {string} [options.fingerprint] - Fingerprint of the user
19
+ * @param {string} [options.endUserId] - End user ID (for client's end users)
19
20
  */
20
21
  constructor(options) {
21
22
  if (!options.client) {
@@ -38,6 +39,7 @@ export class ChatSession {
38
39
  this.ipAddress = options.ipAddress || null;
39
40
  this.userAgent = options.userAgent || null;
40
41
  this.fingerprint = options.fingerprint || null;
42
+ this.endUserId = options.endUserId || null;
41
43
  }
42
44
 
43
45
  /**
@@ -54,6 +56,7 @@ export class ChatSession {
54
56
  ip_address: this.ipAddress,
55
57
  user_agent: this.userAgent,
56
58
  fingerprint: this.fingerprint,
59
+ end_user_id: this.endUserId,
57
60
  };
58
61
 
59
62
  this.data = await this.client.post('ai/session/create', payload);
package/src/client.js CHANGED
@@ -6,21 +6,19 @@
6
6
  export class OblienClient {
7
7
  /**
8
8
  * @param {Object} config - Configuration options
9
- * @param {string} config.apiKey - Your Oblien Client ID (x-client-id)
10
- * @param {string} config.apiSecret - Your Oblien Client Secret (x-client-secret)
11
- * @param {string} [config.baseURL] - Base URL for API (default: https://api.oblien.com)
12
- * @param {string} [config.version] - API version (default: v1)
9
+ * @param {string} config.clientId - Your Oblien Client ID (x-client-id)
10
+ * @param {string} config.clientSecret - Your Oblien Client Secret (x-client-secret)
13
11
  */
14
12
  constructor(config) {
15
- if (!config || !config.apiKey) {
16
- throw new Error('Oblien API key (client ID) is required');
13
+ if (!config || !config.clientId) {
14
+ throw new Error('Oblien client ID is required');
17
15
  }
18
- if (!config.apiSecret) {
19
- throw new Error('Oblien API secret (client secret) is required');
16
+ if (!config.clientSecret) {
17
+ throw new Error('Oblien client secret is required');
20
18
  }
21
19
 
22
- this.clientId = config.apiKey;
23
- this.clientSecret = config.apiSecret;
20
+ this.clientId = config.clientId;
21
+ this.clientSecret = config.clientSecret;
24
22
  this.baseURL = config.baseURL || 'https://api.oblien.com';
25
23
  }
26
24