oblien 1.1.2 → 1.1.4
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 +40 -8
- package/index.d.ts +43 -0
- package/package.json +1 -1
- package/src/chat/index.js +254 -6
- package/src/chat/session.js +36 -55
- package/src/chat/sessionQuota.js +99 -0
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ const overview = await agentInstance.getOverview({ days: 7 });
|
|
|
87
87
|
|
|
88
88
|
### 💬 Chat Module
|
|
89
89
|
|
|
90
|
-
Create and manage
|
|
90
|
+
Create sessions, send messages, and manage guests with streaming support.
|
|
91
91
|
|
|
92
92
|
```javascript
|
|
93
93
|
import { OblienChat } from 'oblien/chat';
|
|
@@ -100,6 +100,27 @@ const session = await chat.createSession({
|
|
|
100
100
|
namespace: 'production'
|
|
101
101
|
});
|
|
102
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
|
+
|
|
103
124
|
// Create guest session
|
|
104
125
|
const guestSession = await chat.createGuestSession({
|
|
105
126
|
ip: '192.168.1.1',
|
|
@@ -107,17 +128,20 @@ const guestSession = await chat.createGuestSession({
|
|
|
107
128
|
agentId: 'agent-id'
|
|
108
129
|
});
|
|
109
130
|
|
|
110
|
-
//
|
|
111
|
-
const
|
|
131
|
+
// Get guest usage
|
|
132
|
+
const usage = await chat.getGuestUsage(guestSession.token);
|
|
112
133
|
```
|
|
113
134
|
|
|
114
135
|
**Features:**
|
|
115
|
-
- ✅ Session management
|
|
116
|
-
- ✅
|
|
117
|
-
- ✅
|
|
118
|
-
- ✅
|
|
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
|
|
119
143
|
|
|
120
|
-
📖 [Documentation](./docs/CHAT.md) | 💡 [Examples](./examples/chat-example.js)
|
|
144
|
+
📖 [Full Documentation](./docs/CHAT.md) | 💡 [Examples](./examples/chat-example.js)
|
|
121
145
|
|
|
122
146
|
---
|
|
123
147
|
|
|
@@ -517,6 +541,14 @@ MIT License - see LICENSE file for details
|
|
|
517
541
|
|
|
518
542
|
## Changelog
|
|
519
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
|
+
|
|
520
552
|
### v1.2.0
|
|
521
553
|
- ✅ Added Sandboxes module
|
|
522
554
|
- ✅ Enhanced Agents module with proper settings sections
|
package/index.d.ts
CHANGED
|
@@ -164,17 +164,60 @@ export interface GuestSessionData extends SessionData {
|
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
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
|
+
|
|
167
206
|
export class OblienChat {
|
|
168
207
|
constructor(client: OblienClient, options?: ChatOptions);
|
|
169
208
|
|
|
170
209
|
createSession(options: CreateSessionOptions): Promise<SessionData>;
|
|
171
210
|
createGuestSession(options: CreateGuestSessionOptions): Promise<GuestSessionData>;
|
|
172
211
|
getGuest(ip: string, fingerprint?: string): Promise<Guest | null>;
|
|
212
|
+
send(options: SendMessageOptions): Promise<any>;
|
|
213
|
+
upload(options: UploadOptions): Promise<any>;
|
|
173
214
|
getSession(sessionId: string): Promise<any>;
|
|
174
215
|
listSessions(options?: Record<string, any>): Promise<any[]>;
|
|
175
216
|
deleteSession(sessionId: string): Promise<any>;
|
|
176
217
|
getAllGuests(): Promise<Guest[]>;
|
|
177
218
|
cleanupGuests(): Promise<number>;
|
|
219
|
+
getGuestUsage(token: string): Promise<GuestUsageInfo>;
|
|
220
|
+
getCacheStatistics(): Promise<CacheStatistics>;
|
|
178
221
|
}
|
|
179
222
|
|
|
180
223
|
// ============ Namespaces ============
|
package/package.json
CHANGED
package/src/chat/index.js
CHANGED
|
@@ -45,10 +45,9 @@ export class OblienChat {
|
|
|
45
45
|
async createSession(options) {
|
|
46
46
|
const session = new ChatSession({
|
|
47
47
|
client: this.client,
|
|
48
|
-
...options,
|
|
49
48
|
});
|
|
50
49
|
|
|
51
|
-
return await session.create();
|
|
50
|
+
return await session.create(options);
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
/**
|
|
@@ -80,6 +79,9 @@ export class OblienChat {
|
|
|
80
79
|
// Create session
|
|
81
80
|
const session = new ChatSession({
|
|
82
81
|
client: this.client,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const sessionData = await session.create({
|
|
83
85
|
agentId,
|
|
84
86
|
workflowId,
|
|
85
87
|
workspace,
|
|
@@ -91,8 +93,6 @@ export class OblienChat {
|
|
|
91
93
|
endUserId: endUserId,
|
|
92
94
|
});
|
|
93
95
|
|
|
94
|
-
const sessionData = await session.create();
|
|
95
|
-
|
|
96
96
|
// Link session to guest
|
|
97
97
|
await this.guestManager.addSession(guest.id, sessionData.sessionId);
|
|
98
98
|
|
|
@@ -138,6 +138,205 @@ export class OblienChat {
|
|
|
138
138
|
return null;
|
|
139
139
|
}
|
|
140
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
|
+
|
|
141
340
|
/**
|
|
142
341
|
* Get session info
|
|
143
342
|
* @param {string} sessionId - Session ID
|
|
@@ -150,11 +349,23 @@ export class OblienChat {
|
|
|
150
349
|
/**
|
|
151
350
|
* List sessions
|
|
152
351
|
* @param {Object} [options] - Query options
|
|
352
|
+
* @param {string} [options.namespace] - Filter by namespace
|
|
353
|
+
* @param {string} [options.agentId] - Filter by agent ID
|
|
354
|
+
* @param {string} [options.endUserId] - Filter by end user ID
|
|
355
|
+
* @param {number} [options.limit] - Number of results (max 100)
|
|
356
|
+
* @param {number} [options.offset] - Offset for pagination
|
|
357
|
+
* @param {string} [options.search] - Search in title and user ID
|
|
358
|
+
* @param {string} [options.sortBy] - Sort by 'time' or 'tokens'
|
|
359
|
+
* @param {string} [options.sortOrder] - 'asc' or 'desc'
|
|
360
|
+
* @param {boolean} [options.includeStats] - Include message count and tokens
|
|
153
361
|
* @returns {Promise<Array>} Array of sessions
|
|
154
362
|
*/
|
|
155
363
|
async listSessions(options = {}) {
|
|
156
|
-
const
|
|
157
|
-
|
|
364
|
+
const session = new ChatSession({
|
|
365
|
+
client: this.client,
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
return await session.list(options);
|
|
158
369
|
}
|
|
159
370
|
|
|
160
371
|
/**
|
|
@@ -181,6 +392,43 @@ export class OblienChat {
|
|
|
181
392
|
async cleanupGuests() {
|
|
182
393
|
return await this.guestManager.cleanup();
|
|
183
394
|
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Get guest usage information (requires session token)
|
|
398
|
+
* @param {string} token - Session token from guest session
|
|
399
|
+
* @returns {Promise<Object>} Usage information for the guest
|
|
400
|
+
*/
|
|
401
|
+
async getGuestUsage(token) {
|
|
402
|
+
if (!token) {
|
|
403
|
+
throw new Error('Session token is required');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const headers = {
|
|
407
|
+
...this.client.getAuthHeaders(),
|
|
408
|
+
'Authorization': `Bearer ${token}`,
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
const response = await fetch(this.client._buildURL('ai/guest/usage'), {
|
|
412
|
+
method: 'GET',
|
|
413
|
+
headers,
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
if (!response.ok) {
|
|
417
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
418
|
+
throw new Error(error.message || error.error || `API error: ${response.status}`);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return await response.json();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Get cache statistics (admin/monitoring)
|
|
426
|
+
* @returns {Promise<Object>} Cache statistics
|
|
427
|
+
*/
|
|
428
|
+
async getCacheStatistics() {
|
|
429
|
+
const data = await this.client.get('ai/guest/cache-stats');
|
|
430
|
+
return data;
|
|
431
|
+
}
|
|
184
432
|
}
|
|
185
433
|
|
|
186
434
|
export { ChatSession } from './session.js';
|
package/src/chat/session.js
CHANGED
|
@@ -8,6 +8,19 @@ export class ChatSession {
|
|
|
8
8
|
* @param {Object} options - Session options
|
|
9
9
|
* @param {import('../client.js').OblienClient} options.client - Oblien client instance
|
|
10
10
|
* @param {string} [options.sessionId] - Existing session ID
|
|
11
|
+
*/
|
|
12
|
+
constructor({ client, sessionId = null }) {
|
|
13
|
+
if (!client) {
|
|
14
|
+
throw new Error('Oblien client is required');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
this.client = client;
|
|
18
|
+
this.sessionId = sessionId;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create session and get token for client
|
|
23
|
+
* @param {Object} options - Session creation options
|
|
11
24
|
* @param {string} options.agentId - Agent ID to chat with
|
|
12
25
|
* @param {string} [options.workflowId] - Workflow ID (if using workflow)
|
|
13
26
|
* @param {boolean} [options.isGuest] - Is this a guest session
|
|
@@ -17,71 +30,30 @@ export class ChatSession {
|
|
|
17
30
|
* @param {string} [options.userAgent] - User agent of the user
|
|
18
31
|
* @param {string} [options.fingerprint] - Fingerprint of the user
|
|
19
32
|
* @param {string} [options.endUserId] - End user ID (for client's end users)
|
|
33
|
+
* @returns {Promise<Object>} Session data with token for browser
|
|
20
34
|
*/
|
|
21
|
-
|
|
22
|
-
if (!options.client) {
|
|
23
|
-
throw new Error('Oblien client is required');
|
|
24
|
-
}
|
|
25
|
-
|
|
35
|
+
async create(options) {
|
|
26
36
|
if (!options.agentId && !options.workflowId) {
|
|
27
37
|
throw new Error('Either agentId or workflowId is required');
|
|
28
38
|
}
|
|
29
39
|
|
|
30
|
-
this.client
|
|
31
|
-
|
|
32
|
-
this.agentId = options.agentId;
|
|
33
|
-
this.workflowId = options.workflowId;
|
|
34
|
-
this.isGuest = options.isGuest || false;
|
|
35
|
-
this.namespace = options.namespace;
|
|
36
|
-
this.workspace = options.workspace;
|
|
37
|
-
this.token = null;
|
|
38
|
-
this.data = null;
|
|
39
|
-
this.ipAddress = options.ipAddress || null;
|
|
40
|
-
this.userAgent = options.userAgent || null;
|
|
41
|
-
this.fingerprint = options.fingerprint || null;
|
|
42
|
-
this.endUserId = options.endUserId || null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Create session and get token for client
|
|
47
|
-
* @returns {Promise<Object>} Session data with token for browser
|
|
48
|
-
*/
|
|
49
|
-
async create() {
|
|
50
|
-
const payload = {
|
|
51
|
-
agent_id: this.agentId,
|
|
52
|
-
app_id: this.workflowId, // Backend uses app_id for workflow_id
|
|
53
|
-
is_guest: this.isGuest,
|
|
54
|
-
namespace: this.namespace,
|
|
55
|
-
workspace: this.workspace,
|
|
56
|
-
ip_address: this.ipAddress,
|
|
57
|
-
user_agent: this.userAgent,
|
|
58
|
-
fingerprint: this.fingerprint,
|
|
59
|
-
end_user_id: this.endUserId,
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
this.data = await this.client.post('ai/session/create', payload);
|
|
63
|
-
this.sessionId = this.data.sessionId || this.data.session_id;
|
|
64
|
-
this.token = this.data.token || this.data.accessToken || this.data.tokens?.token;
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
sessionId: this.sessionId,
|
|
68
|
-
token: this.token,
|
|
69
|
-
agentId: this.data.agentId || this.agentId,
|
|
70
|
-
workflowId: this.data.workflowId || this.data.appId || this.workflowId,
|
|
71
|
-
namespace: this.namespace,
|
|
72
|
-
};
|
|
40
|
+
const data = await this.client.post('ai/session/create', options);
|
|
41
|
+
return data
|
|
73
42
|
}
|
|
74
43
|
|
|
75
44
|
/**
|
|
76
45
|
* Get existing session info
|
|
77
|
-
* @param {string} sessionId - Session ID
|
|
46
|
+
* @param {string} [sessionId] - Session ID (uses instance sessionId if not provided)
|
|
78
47
|
* @returns {Promise<Object>} Session details
|
|
79
48
|
*/
|
|
80
49
|
async get(sessionId) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
50
|
+
const id = sessionId || this.sessionId;
|
|
51
|
+
if (!id) {
|
|
52
|
+
throw new Error('Session ID required');
|
|
53
|
+
}
|
|
84
54
|
|
|
55
|
+
return await this.client.get(`ai/session/${id}`);
|
|
56
|
+
}
|
|
85
57
|
|
|
86
58
|
/**
|
|
87
59
|
* Delete session
|
|
@@ -100,12 +72,21 @@ export class ChatSession {
|
|
|
100
72
|
/**
|
|
101
73
|
* List all sessions
|
|
102
74
|
* @param {Object} [options] - Query options
|
|
75
|
+
* @param {string} [options.namespace] - Filter by namespace
|
|
76
|
+
* @param {string} [options.agentId] - Filter by agent ID
|
|
77
|
+
* @param {string} [options.endUserId] - Filter by end user ID
|
|
78
|
+
* @param {number} [options.limit] - Number of results (max 100)
|
|
79
|
+
* @param {number} [options.offset] - Offset for pagination
|
|
80
|
+
* @param {string} [options.search] - Search in title and user ID
|
|
81
|
+
* @param {string} [options.sortBy] - Sort by 'time' or 'tokens'
|
|
82
|
+
* @param {string} [options.sortOrder] - 'asc' or 'desc'
|
|
83
|
+
* @param {boolean} [options.includeStats] - Include message count and tokens
|
|
103
84
|
* @returns {Promise<Array>} Array of sessions
|
|
104
85
|
*/
|
|
105
86
|
async list(options = {}) {
|
|
106
|
-
const data = await this.client.get('ai/session', options);
|
|
107
|
-
return data
|
|
87
|
+
const data = await this.client.get('ai/session/list', options);
|
|
88
|
+
return data;
|
|
108
89
|
}
|
|
109
90
|
}
|
|
110
91
|
|
|
111
|
-
export default ChatSession;
|
|
92
|
+
export default ChatSession;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Quota Manager
|
|
3
|
+
* Manages per-session quota limits and tracking
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class SessionQuota {
|
|
7
|
+
/**
|
|
8
|
+
* @param {Object} options
|
|
9
|
+
* @param {import('../client.js').OblienClient} options.client - Oblien client instance
|
|
10
|
+
* @param {string} options.sessionId - Session ID
|
|
11
|
+
*/
|
|
12
|
+
constructor({ client, sessionId }) {
|
|
13
|
+
if (!client) {
|
|
14
|
+
throw new Error('Oblien client is required');
|
|
15
|
+
}
|
|
16
|
+
if (!sessionId) {
|
|
17
|
+
throw new Error('Session ID is required');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
this.client = client;
|
|
21
|
+
this.sessionId = sessionId;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get session quota status
|
|
26
|
+
* @returns {Promise<Object>} Quota status
|
|
27
|
+
*/
|
|
28
|
+
async get() {
|
|
29
|
+
const data = await this.client.get(`ai/session/${this.sessionId}/quota`);
|
|
30
|
+
return data.quota || data;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Set session quota limit (manual override)
|
|
35
|
+
* @param {number} limit - Quota limit (null for unlimited)
|
|
36
|
+
* @param {string} [period] - Quota period: 'daily', 'monthly', 'unlimited'
|
|
37
|
+
* @returns {Promise<Object>} Updated quota status
|
|
38
|
+
*/
|
|
39
|
+
async set(limit, period = 'unlimited') {
|
|
40
|
+
const data = await this.client.post(`ai/session/${this.sessionId}/quota`, {
|
|
41
|
+
limit,
|
|
42
|
+
period
|
|
43
|
+
});
|
|
44
|
+
return data.quota || data;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Reset session quota usage
|
|
49
|
+
* @returns {Promise<Object>} Reset result
|
|
50
|
+
*/
|
|
51
|
+
async reset() {
|
|
52
|
+
return await this.client.post(`ai/session/${this.sessionId}/quota/reset`, {});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if session can use credits (validation before action)
|
|
57
|
+
* @param {number} amount - Amount of credits to check
|
|
58
|
+
* @returns {Promise<Object>} { canUse, quota, reason }
|
|
59
|
+
*/
|
|
60
|
+
async canUse(amount) {
|
|
61
|
+
const data = await this.client.post(`ai/session/${this.sessionId}/quota/can-use`, {
|
|
62
|
+
amount
|
|
63
|
+
});
|
|
64
|
+
return {
|
|
65
|
+
canUse: data.canUse,
|
|
66
|
+
quota: data.quota,
|
|
67
|
+
reason: data.reason
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get quota transaction history
|
|
73
|
+
* @param {Object} [options] - Query options
|
|
74
|
+
* @param {number} [options.limit] - Number of results (max 100)
|
|
75
|
+
* @param {number} [options.offset] - Offset for pagination
|
|
76
|
+
* @returns {Promise<Array>} Array of transactions
|
|
77
|
+
*/
|
|
78
|
+
async getTransactions(options = {}) {
|
|
79
|
+
const data = await this.client.get(`ai/session/${this.sessionId}/quota/transactions`, options);
|
|
80
|
+
return data.transactions || data;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get current usage
|
|
85
|
+
* @returns {Promise<Object>} { used, limit, available }
|
|
86
|
+
*/
|
|
87
|
+
async getUsage() {
|
|
88
|
+
const quota = await this.get();
|
|
89
|
+
return {
|
|
90
|
+
used: quota.used || 0,
|
|
91
|
+
limit: quota.limit,
|
|
92
|
+
available: quota.available,
|
|
93
|
+
enabled: quota.enabled
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default SessionQuota;
|
|
99
|
+
|