oblien 1.1.4 → 1.1.6
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/index.d.ts +129 -6
- package/package.json +1 -1
- package/src/chat/index.js +242 -9
- package/src/client.js +10 -3
- package/src/credits/index.js +181 -0
- package/src/chat/sessionQuota.js +0 -99
package/index.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ export interface SessionOptions {
|
|
|
99
99
|
workflowId?: string;
|
|
100
100
|
isGuest?: boolean;
|
|
101
101
|
namespace?: string;
|
|
102
|
+
guestNamespace?: string; // Guest's auto-generated namespace
|
|
102
103
|
workspace?: Record<string, any>;
|
|
103
104
|
ipAddress?: string;
|
|
104
105
|
userAgent?: string;
|
|
@@ -108,7 +109,10 @@ export interface SessionOptions {
|
|
|
108
109
|
|
|
109
110
|
export interface SessionData {
|
|
110
111
|
sessionId: string;
|
|
111
|
-
token
|
|
112
|
+
token?: string; // Legacy field
|
|
113
|
+
accessToken?: string; // New field
|
|
114
|
+
refreshToken?: string; // New field
|
|
115
|
+
expiresIn?: number; // Token expiration in seconds
|
|
112
116
|
agentId?: string;
|
|
113
117
|
workflowId?: string;
|
|
114
118
|
namespace?: string;
|
|
@@ -123,7 +127,7 @@ export class ChatSession {
|
|
|
123
127
|
create(): Promise<SessionData>;
|
|
124
128
|
get(sessionId?: string): Promise<any>;
|
|
125
129
|
delete(sessionId?: string): Promise<any>;
|
|
126
|
-
list(options?:
|
|
130
|
+
list(options?: ListSessionsOptions): Promise<any[]>;
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
// ============ Chat Manager ============
|
|
@@ -151,9 +155,10 @@ export interface CreateGuestSessionOptions {
|
|
|
151
155
|
fingerprint?: string;
|
|
152
156
|
agentId: string;
|
|
153
157
|
workflowId?: string;
|
|
158
|
+
namespace?: string;
|
|
159
|
+
endUserId?: string;
|
|
154
160
|
metadata?: Record<string, any>;
|
|
155
161
|
workspace?: Record<string, any>;
|
|
156
|
-
endUserId?: string;
|
|
157
162
|
}
|
|
158
163
|
|
|
159
164
|
export interface GuestSessionData extends SessionData {
|
|
@@ -203,17 +208,87 @@ export interface CacheStatistics {
|
|
|
203
208
|
};
|
|
204
209
|
}
|
|
205
210
|
|
|
211
|
+
export interface SessionTokenData {
|
|
212
|
+
accessToken: string;
|
|
213
|
+
refreshToken: string;
|
|
214
|
+
expiresIn: number;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface SessionHistoryOptions {
|
|
218
|
+
limit?: number; // Max 100
|
|
219
|
+
offset?: number;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface BanUserOptions {
|
|
223
|
+
reason?: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface LockSessionOptions {
|
|
227
|
+
locked?: boolean; // true to lock, false to unlock
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface RefreshTokenOptions {
|
|
231
|
+
refreshToken: string;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export interface PrepareSessionOptions {
|
|
235
|
+
token: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface GetHistoryOptions {
|
|
239
|
+
token: string;
|
|
240
|
+
namespace?: string;
|
|
241
|
+
limit?: number; // Max 50
|
|
242
|
+
offset?: number;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface ListSessionsOptions {
|
|
246
|
+
namespace?: string;
|
|
247
|
+
agentId?: string;
|
|
248
|
+
endUserId?: string;
|
|
249
|
+
limit?: number; // Max 100
|
|
250
|
+
offset?: number;
|
|
251
|
+
search?: string;
|
|
252
|
+
sortBy?: 'time' | 'tokens';
|
|
253
|
+
sortOrder?: 'asc' | 'desc';
|
|
254
|
+
includeStats?: boolean;
|
|
255
|
+
}
|
|
256
|
+
|
|
206
257
|
export class OblienChat {
|
|
207
258
|
constructor(client: OblienClient, options?: ChatOptions);
|
|
208
259
|
|
|
260
|
+
// Session Creation
|
|
209
261
|
createSession(options: CreateSessionOptions): Promise<SessionData>;
|
|
210
262
|
createGuestSession(options: CreateGuestSessionOptions): Promise<GuestSessionData>;
|
|
211
263
|
getGuest(ip: string, fingerprint?: string): Promise<Guest | null>;
|
|
212
|
-
|
|
213
|
-
|
|
264
|
+
|
|
265
|
+
// Session Token Management (Server-side)
|
|
266
|
+
createSessionToken(sessionId: string): Promise<SessionTokenData>;
|
|
267
|
+
revokeSessionToken(sessionId: string): Promise<any>;
|
|
268
|
+
|
|
269
|
+
// Session Token Management (Client-side)
|
|
270
|
+
refreshToken(options: RefreshTokenOptions): Promise<SessionTokenData>;
|
|
271
|
+
prepareSession(options: PrepareSessionOptions): Promise<any>;
|
|
272
|
+
|
|
273
|
+
// Session Management (Server-side)
|
|
214
274
|
getSession(sessionId: string): Promise<any>;
|
|
215
|
-
|
|
275
|
+
getSessionHistory(sessionId: string, options?: SessionHistoryOptions): Promise<any>;
|
|
276
|
+
listSessions(options?: ListSessionsOptions): Promise<any[]>;
|
|
216
277
|
deleteSession(sessionId: string): Promise<any>;
|
|
278
|
+
|
|
279
|
+
// Security & Moderation (Server-side)
|
|
280
|
+
banUser(sessionId: string, options?: BanUserOptions): Promise<any>;
|
|
281
|
+
unbanUser(sessionId: string): Promise<any>;
|
|
282
|
+
lockSession(sessionId: string, options?: LockSessionOptions): Promise<any>;
|
|
283
|
+
|
|
284
|
+
// Chat Operations
|
|
285
|
+
send(options: SendMessageOptions): Promise<any>;
|
|
286
|
+
upload(options: UploadOptions): Promise<any>;
|
|
287
|
+
|
|
288
|
+
// History (Client-side)
|
|
289
|
+
getHistory(options: GetHistoryOptions): Promise<any>;
|
|
290
|
+
|
|
291
|
+
// Guest Management
|
|
217
292
|
getAllGuests(): Promise<Guest[]>;
|
|
218
293
|
cleanupGuests(): Promise<number>;
|
|
219
294
|
getGuestUsage(token: string): Promise<GuestUsageInfo>;
|
|
@@ -396,6 +471,42 @@ export interface SetQuotaOptions {
|
|
|
396
471
|
period?: 'daily' | 'monthly' | 'unlimited';
|
|
397
472
|
}
|
|
398
473
|
|
|
474
|
+
export interface SetEndUserQuotaOptions {
|
|
475
|
+
namespace: string;
|
|
476
|
+
endUserId: string;
|
|
477
|
+
service: string;
|
|
478
|
+
quotaLimit: number;
|
|
479
|
+
period?: 'daily' | 'monthly' | 'unlimited';
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export interface EndUserQuota {
|
|
483
|
+
limit: number;
|
|
484
|
+
used: number;
|
|
485
|
+
remaining: number;
|
|
486
|
+
period: string;
|
|
487
|
+
enabled: boolean;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
export interface SetDefaultQuotaOptions {
|
|
491
|
+
level: 'namespace' | 'end_user';
|
|
492
|
+
service: string;
|
|
493
|
+
quotaLimit: number | null;
|
|
494
|
+
period?: 'daily' | 'monthly' | 'unlimited';
|
|
495
|
+
autoApply?: boolean;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export interface DefaultQuotaConfig {
|
|
499
|
+
id: number;
|
|
500
|
+
level: 'namespace' | 'end_user';
|
|
501
|
+
service: string;
|
|
502
|
+
quotaLimit: number | null;
|
|
503
|
+
period: string;
|
|
504
|
+
autoApply: boolean;
|
|
505
|
+
enabled: boolean;
|
|
506
|
+
createdAt: string;
|
|
507
|
+
updatedAt: string;
|
|
508
|
+
}
|
|
509
|
+
|
|
399
510
|
export interface HistoryOptions {
|
|
400
511
|
namespace?: string;
|
|
401
512
|
endUserId?: string;
|
|
@@ -457,6 +568,18 @@ export class OblienCredits {
|
|
|
457
568
|
setQuota(options: SetQuotaOptions): Promise<QuotaData>;
|
|
458
569
|
resetQuota(namespace: string, service: string): Promise<any>;
|
|
459
570
|
|
|
571
|
+
// End User Quota Management (Optional Third Level)
|
|
572
|
+
setEndUserQuota(options: SetEndUserQuotaOptions): Promise<any>;
|
|
573
|
+
getEndUserQuota(namespace: string, endUserId: string, service: string): Promise<{ success: boolean; quota: EndUserQuota | null }>;
|
|
574
|
+
resetEndUserQuota(namespace: string, endUserId: string, service: string): Promise<any>;
|
|
575
|
+
|
|
576
|
+
// Default Quota Configuration (Dynamic, per client)
|
|
577
|
+
setDefaultQuota(options: SetDefaultQuotaOptions): Promise<any>;
|
|
578
|
+
getDefaultQuota(level: 'namespace' | 'end_user', service: string): Promise<{ success: boolean; config: DefaultQuotaConfig | null }>;
|
|
579
|
+
getAllDefaultQuotas(level?: 'namespace' | 'end_user'): Promise<{ success: boolean; configs: DefaultQuotaConfig[] }>;
|
|
580
|
+
deleteDefaultQuota(level: 'namespace' | 'end_user', service: string): Promise<any>;
|
|
581
|
+
toggleDefaultQuotaAutoApply(level: 'namespace' | 'end_user', service: string, autoApply: boolean): Promise<any>;
|
|
582
|
+
|
|
460
583
|
// Usage History & Transactions
|
|
461
584
|
getHistory(options?: HistoryOptions): Promise<{ success: boolean; data: CreditTransaction[]; pagination: any }>;
|
|
462
585
|
getHistoryFilters(): Promise<{ namespaces: string[]; services: string[] }>;
|
package/package.json
CHANGED
package/src/chat/index.js
CHANGED
|
@@ -52,23 +52,60 @@ export class OblienChat {
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Create a guest session based on IP and fingerprint (dual-layer identification)
|
|
55
|
+
*
|
|
56
|
+
* Namespace handling:
|
|
57
|
+
* - If `namespace` is provided: Uses it as the session namespace
|
|
58
|
+
* - If `namespace` is NOT provided: Uses guest's auto-generated namespace (based on IP)
|
|
59
|
+
* - `endUserId`: Optional identifier for your end user (tracked separately)
|
|
60
|
+
*
|
|
55
61
|
* @param {Object} options - Guest session options
|
|
56
|
-
* @param {string} options.ip - Client IP address
|
|
62
|
+
* @param {string} options.ip - Client IP address (required)
|
|
57
63
|
* @param {string} [options.fingerprint] - Client fingerprint for identification
|
|
58
64
|
* @param {string} options.agentId - Agent ID to chat with
|
|
59
65
|
* @param {string} [options.workflowId] - Workflow ID
|
|
60
|
-
* @param {
|
|
66
|
+
* @param {string} [options.namespace] - Custom namespace (e.g., 'my-app-guests'). If not provided, uses auto-generated guest namespace
|
|
67
|
+
* @param {string} [options.endUserId] - Your end user's ID (e.g., from your database)
|
|
68
|
+
* @param {Object} [options.metadata] - Additional guest metadata (userAgent, etc.)
|
|
61
69
|
* @param {Object} [options.workspace] - Workspace configuration
|
|
62
|
-
* @param {string} [options.endUserId] - End user ID (for client's end users)
|
|
63
70
|
* @returns {Promise<Object>} Session data with token and guest info
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Simple guest session (auto namespace)
|
|
74
|
+
* await chat.createGuestSession({
|
|
75
|
+
* ip: '1.2.3.4',
|
|
76
|
+
* agentId: 'my-agent-id'
|
|
77
|
+
* });
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* // With custom namespace and end user ID
|
|
81
|
+
* await chat.createGuestSession({
|
|
82
|
+
* ip: '1.2.3.4',
|
|
83
|
+
* fingerprint: 'abc123',
|
|
84
|
+
* agentId: 'my-agent-id',
|
|
85
|
+
* namespace: 'my-app-guests',
|
|
86
|
+
* endUserId: 'user_12345'
|
|
87
|
+
* });
|
|
64
88
|
*/
|
|
65
89
|
async createGuestSession(options) {
|
|
66
|
-
const {
|
|
90
|
+
const {
|
|
91
|
+
ip,
|
|
92
|
+
fingerprint,
|
|
93
|
+
agentId,
|
|
94
|
+
workflowId,
|
|
95
|
+
namespace,
|
|
96
|
+
endUserId,
|
|
97
|
+
metadata = {},
|
|
98
|
+
workspace
|
|
99
|
+
} = options;
|
|
67
100
|
|
|
68
101
|
if (!ip) {
|
|
69
102
|
throw new Error('IP address is required for guest sessions');
|
|
70
103
|
}
|
|
71
104
|
|
|
105
|
+
if (!agentId) {
|
|
106
|
+
throw new Error('Agent ID is required for guest sessions');
|
|
107
|
+
}
|
|
108
|
+
|
|
72
109
|
// Get or create guest user (handles fingerprint and IP mapping internally)
|
|
73
110
|
const guest = await this.guestManager.getOrCreateGuest(ip, fingerprint, {
|
|
74
111
|
...metadata,
|
|
@@ -81,16 +118,20 @@ export class OblienChat {
|
|
|
81
118
|
client: this.client,
|
|
82
119
|
});
|
|
83
120
|
|
|
121
|
+
// Use custom namespace if provided, otherwise use guest's default namespace
|
|
122
|
+
const sessionNamespace = namespace || guest.namespace;
|
|
123
|
+
|
|
84
124
|
const sessionData = await session.create({
|
|
85
125
|
agentId,
|
|
86
126
|
workflowId,
|
|
87
127
|
workspace,
|
|
88
128
|
isGuest: true,
|
|
89
|
-
namespace:
|
|
129
|
+
namespace: sessionNamespace,
|
|
90
130
|
ipAddress: ip,
|
|
91
131
|
userAgent: metadata.userAgent,
|
|
132
|
+
guestNamespace: guest.namespace,
|
|
92
133
|
fingerprint: fingerprint,
|
|
93
|
-
endUserId: endUserId,
|
|
134
|
+
endUserId: endUserId, // Optional: Your end user identifier
|
|
94
135
|
});
|
|
95
136
|
|
|
96
137
|
// Link session to guest
|
|
@@ -338,16 +379,104 @@ export class OblienChat {
|
|
|
338
379
|
}
|
|
339
380
|
|
|
340
381
|
/**
|
|
341
|
-
* Get session info
|
|
382
|
+
* Get session info (server-side)
|
|
342
383
|
* @param {string} sessionId - Session ID
|
|
343
384
|
* @returns {Promise<Object>} Session details
|
|
344
385
|
*/
|
|
345
386
|
async getSession(sessionId) {
|
|
387
|
+
if (!sessionId) {
|
|
388
|
+
throw new Error('Session ID is required');
|
|
389
|
+
}
|
|
346
390
|
return await this.client.get(`ai/session/${sessionId}`);
|
|
347
391
|
}
|
|
348
392
|
|
|
349
393
|
/**
|
|
350
|
-
*
|
|
394
|
+
* Create a session token for client-side access (server-side)
|
|
395
|
+
* @param {string} sessionId - Session ID
|
|
396
|
+
* @returns {Promise<Object>} Token data (accessToken, refreshToken)
|
|
397
|
+
*/
|
|
398
|
+
async createSessionToken(sessionId) {
|
|
399
|
+
if (!sessionId) {
|
|
400
|
+
throw new Error('Session ID is required');
|
|
401
|
+
}
|
|
402
|
+
return await this.client.post(`ai/session/${sessionId}/token/create`);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Revoke a session token (server-side)
|
|
407
|
+
* @param {string} sessionId - Session ID
|
|
408
|
+
* @returns {Promise<Object>} Revocation result
|
|
409
|
+
*/
|
|
410
|
+
async revokeSessionToken(sessionId) {
|
|
411
|
+
if (!sessionId) {
|
|
412
|
+
throw new Error('Session ID is required');
|
|
413
|
+
}
|
|
414
|
+
return await this.client.post(`ai/session/${sessionId}/token/revoke`);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Get session history by session ID (server-side)
|
|
419
|
+
* @param {string} sessionId - Session ID
|
|
420
|
+
* @param {Object} [options] - Query options
|
|
421
|
+
* @param {number} [options.limit] - Number of messages (max 100)
|
|
422
|
+
* @param {number} [options.offset] - Offset for pagination
|
|
423
|
+
* @returns {Promise<Object>} Session history with messages
|
|
424
|
+
*/
|
|
425
|
+
async getSessionHistory(sessionId, options = {}) {
|
|
426
|
+
if (!sessionId) {
|
|
427
|
+
throw new Error('Session ID is required');
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const params = new URLSearchParams();
|
|
431
|
+
if (options.limit) params.append('limit', Math.min(options.limit, 100).toString());
|
|
432
|
+
if (options.offset) params.append('offset', Math.max(options.offset, 0).toString());
|
|
433
|
+
|
|
434
|
+
const url = `ai/session/${sessionId}/history${params.toString() ? `?${params.toString()}` : ''}`;
|
|
435
|
+
return await this.client.get(url);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Ban a user from a session (server-side)
|
|
440
|
+
* @param {string} sessionId - Session ID
|
|
441
|
+
* @param {Object} [options] - Ban options
|
|
442
|
+
* @param {string} [options.reason] - Reason for ban
|
|
443
|
+
* @returns {Promise<Object>} Ban result
|
|
444
|
+
*/
|
|
445
|
+
async banUser(sessionId, options = {}) {
|
|
446
|
+
if (!sessionId) {
|
|
447
|
+
throw new Error('Session ID is required');
|
|
448
|
+
}
|
|
449
|
+
return await this.client.post(`ai/session/${sessionId}/ban`, options);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Unban a user from a session (server-side)
|
|
454
|
+
* @param {string} sessionId - Session ID
|
|
455
|
+
* @returns {Promise<Object>} Unban result
|
|
456
|
+
*/
|
|
457
|
+
async unbanUser(sessionId) {
|
|
458
|
+
if (!sessionId) {
|
|
459
|
+
throw new Error('Session ID is required');
|
|
460
|
+
}
|
|
461
|
+
return await this.client.post(`ai/session/${sessionId}/unban`);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Lock or unlock a session (server-side)
|
|
466
|
+
* @param {string} sessionId - Session ID
|
|
467
|
+
* @param {Object} [options] - Lock options
|
|
468
|
+
* @param {boolean} [options.locked] - Lock state (true to lock, false to unlock)
|
|
469
|
+
* @returns {Promise<Object>} Lock result
|
|
470
|
+
*/
|
|
471
|
+
async lockSession(sessionId, options = {}) {
|
|
472
|
+
if (!sessionId) {
|
|
473
|
+
throw new Error('Session ID is required');
|
|
474
|
+
}
|
|
475
|
+
return await this.client.post(`ai/session/${sessionId}/lock`, options);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* List sessions (server-side)
|
|
351
480
|
* @param {Object} [options] - Query options
|
|
352
481
|
* @param {string} [options.namespace] - Filter by namespace
|
|
353
482
|
* @param {string} [options.agentId] - Filter by agent ID
|
|
@@ -369,11 +498,14 @@ export class OblienChat {
|
|
|
369
498
|
}
|
|
370
499
|
|
|
371
500
|
/**
|
|
372
|
-
* Delete a session
|
|
501
|
+
* Delete a session (server-side)
|
|
373
502
|
* @param {string} sessionId - Session ID to delete
|
|
374
503
|
* @returns {Promise<Object>} Deletion result
|
|
375
504
|
*/
|
|
376
505
|
async deleteSession(sessionId) {
|
|
506
|
+
if (!sessionId) {
|
|
507
|
+
throw new Error('Session ID is required');
|
|
508
|
+
}
|
|
377
509
|
return await this.client.delete(`ai/session/${sessionId}`);
|
|
378
510
|
}
|
|
379
511
|
|
|
@@ -429,6 +561,107 @@ export class OblienChat {
|
|
|
429
561
|
const data = await this.client.get('ai/guest/cache-stats');
|
|
430
562
|
return data;
|
|
431
563
|
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Refresh session token (client-side)
|
|
567
|
+
* Uses refresh token to get new access token
|
|
568
|
+
*
|
|
569
|
+
* @param {string} refreshToken - Refresh token from session
|
|
570
|
+
* @returns {Promise<Object>} New tokens
|
|
571
|
+
*/
|
|
572
|
+
async refreshToken(refreshToken) {
|
|
573
|
+
if (!refreshToken) {
|
|
574
|
+
throw new Error('Refresh token is required');
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
const url = this.client._buildURL('ai/session/token/refresh');
|
|
578
|
+
const response = await fetch(url, {
|
|
579
|
+
method: 'POST',
|
|
580
|
+
headers: {
|
|
581
|
+
'Authorization': `Bearer ${refreshToken}`,
|
|
582
|
+
'Content-Type': 'application/json',
|
|
583
|
+
},
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
if (!response.ok) {
|
|
587
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
588
|
+
throw new Error(error.message || error.error || `API error: ${response.status}`);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return await response.json();
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Get chat history (client-side)
|
|
596
|
+
* Uses session token to get chat history
|
|
597
|
+
*
|
|
598
|
+
* @param {Object} options - History options
|
|
599
|
+
* @param {string} options.token - Session token (required for client-side)
|
|
600
|
+
* @param {string} [options.namespace] - Namespace filter
|
|
601
|
+
* @param {number} [options.limit] - Number of messages (max 50)
|
|
602
|
+
* @param {number} [options.offset] - Offset for pagination
|
|
603
|
+
* @returns {Promise<Object>} Chat history with messages
|
|
604
|
+
*/
|
|
605
|
+
async getHistory(options = {}) {
|
|
606
|
+
const { token, namespace, limit = 50, offset = 0 } = options;
|
|
607
|
+
|
|
608
|
+
if (!token) {
|
|
609
|
+
throw new Error('Session token is required for client-side history');
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
const params = new URLSearchParams();
|
|
613
|
+
if (namespace) params.append('namespace', namespace);
|
|
614
|
+
params.append('limit', Math.min(limit, 50).toString());
|
|
615
|
+
params.append('offset', Math.max(offset, 0).toString());
|
|
616
|
+
|
|
617
|
+
const url = `${this.client._buildURL('ai/session/history')}?${params.toString()}`;
|
|
618
|
+
const response = await fetch(url, {
|
|
619
|
+
method: 'GET',
|
|
620
|
+
headers: {
|
|
621
|
+
'Authorization': `Bearer ${token}`,
|
|
622
|
+
'Content-Type': 'application/json',
|
|
623
|
+
},
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
if (!response.ok) {
|
|
627
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
628
|
+
throw new Error(error.message || error.error || `API error: ${response.status}`);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return await response.json();
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Prepare session (client-side)
|
|
636
|
+
* Prepares session for app/container usage
|
|
637
|
+
*
|
|
638
|
+
* @param {Object} options - Prepare options
|
|
639
|
+
* @param {string} options.token - Session token (required for client-side)
|
|
640
|
+
* @returns {Promise<Object>} Preparation result
|
|
641
|
+
*/
|
|
642
|
+
async prepareSession(options = {}) {
|
|
643
|
+
const { token } = options;
|
|
644
|
+
|
|
645
|
+
if (!token) {
|
|
646
|
+
throw new Error('Session token is required for client-side prepare');
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const url = this.client._buildURL('ai/session/prepare');
|
|
650
|
+
const response = await fetch(url, {
|
|
651
|
+
method: 'POST',
|
|
652
|
+
headers: {
|
|
653
|
+
'Authorization': `Bearer ${token}`,
|
|
654
|
+
'Content-Type': 'application/json',
|
|
655
|
+
},
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
if (!response.ok) {
|
|
659
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
660
|
+
throw new Error(error.message || error.error || `API error: ${response.status}`);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
return await response.json();
|
|
664
|
+
}
|
|
432
665
|
}
|
|
433
666
|
|
|
434
667
|
export { ChatSession } from './session.js';
|
package/src/client.js
CHANGED
|
@@ -126,15 +126,22 @@ export class OblienClient {
|
|
|
126
126
|
/**
|
|
127
127
|
* Make DELETE request
|
|
128
128
|
* @param {string} path - API path
|
|
129
|
+
* @param {Object} [body] - Request body
|
|
129
130
|
* @returns {Promise<any>} Response data
|
|
130
131
|
*/
|
|
131
|
-
async delete(path) {
|
|
132
|
+
async delete(path, body = null) {
|
|
132
133
|
const headers = this.getAuthHeaders();
|
|
133
134
|
|
|
134
|
-
const
|
|
135
|
+
const options = {
|
|
135
136
|
method: 'DELETE',
|
|
136
137
|
headers,
|
|
137
|
-
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
if (body) {
|
|
141
|
+
options.body = JSON.stringify(body);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const response = await fetch(this._buildURL(path), options);
|
|
138
145
|
|
|
139
146
|
return this._handleResponse(response);
|
|
140
147
|
}
|
package/src/credits/index.js
CHANGED
|
@@ -122,6 +122,187 @@ export class OblienCredits {
|
|
|
122
122
|
return response;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
// =============================================================================
|
|
126
|
+
// End User Quota Management (Optional Third Level)
|
|
127
|
+
// =============================================================================
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Set quota for an end user within a namespace
|
|
131
|
+
* @param {Object} options - Quota options
|
|
132
|
+
* @param {string} options.namespace - Namespace slug
|
|
133
|
+
* @param {string} options.endUserId - End user ID
|
|
134
|
+
* @param {string} options.service - Service name (e.g., 'ai_chat', 'deployment', 'sandbox')
|
|
135
|
+
* @param {number} options.quotaLimit - Quota limit (null or 0 for unlimited)
|
|
136
|
+
* @param {string} [options.period] - Quota period: 'daily', 'monthly', 'unlimited'
|
|
137
|
+
* @returns {Promise<Object>} Created/updated end user quota
|
|
138
|
+
*/
|
|
139
|
+
async setEndUserQuota(options) {
|
|
140
|
+
if (!options.namespace || !options.endUserId || !options.service) {
|
|
141
|
+
throw new Error('namespace, endUserId, and service are required');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (options.quotaLimit === undefined) {
|
|
145
|
+
throw new Error('quotaLimit is required');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const response = await this.client.post('credits/end-users/quota', {
|
|
149
|
+
namespace: options.namespace,
|
|
150
|
+
endUserId: options.endUserId,
|
|
151
|
+
service: options.service,
|
|
152
|
+
quotaLimit: options.quotaLimit,
|
|
153
|
+
period: options.period || 'unlimited'
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return response;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get end user quota
|
|
161
|
+
* @param {string} namespace - Namespace slug
|
|
162
|
+
* @param {string} endUserId - End user ID
|
|
163
|
+
* @param {string} service - Service name
|
|
164
|
+
* @returns {Promise<Object>} End user quota details
|
|
165
|
+
*/
|
|
166
|
+
async getEndUserQuota(namespace, endUserId, service) {
|
|
167
|
+
if (!namespace || !endUserId || !service) {
|
|
168
|
+
throw new Error('namespace, endUserId, and service are required');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const response = await this.client.get('credits/end-users/quota', {
|
|
172
|
+
namespace,
|
|
173
|
+
endUserId,
|
|
174
|
+
service
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return response;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Reset end user quota usage
|
|
182
|
+
* @param {string} namespace - Namespace slug
|
|
183
|
+
* @param {string} endUserId - End user ID
|
|
184
|
+
* @param {string} service - Service name
|
|
185
|
+
* @returns {Promise<Object>} Reset result
|
|
186
|
+
*/
|
|
187
|
+
async resetEndUserQuota(namespace, endUserId, service) {
|
|
188
|
+
if (!namespace || !endUserId || !service) {
|
|
189
|
+
throw new Error('namespace, endUserId, and service are required');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const response = await this.client.post('credits/end-users/reset', {
|
|
193
|
+
namespace,
|
|
194
|
+
endUserId,
|
|
195
|
+
service
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
return response;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// =============================================================================
|
|
202
|
+
// Default Quota Configuration (Dynamic, per client)
|
|
203
|
+
// =============================================================================
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Set default quota configuration
|
|
207
|
+
* @param {Object} options - Configuration options
|
|
208
|
+
* @param {string} options.level - 'namespace' or 'end_user'
|
|
209
|
+
* @param {string} options.service - Service name (e.g., 'ai_chat', 'deployment')
|
|
210
|
+
* @param {number} options.quotaLimit - Default quota limit (null for unlimited)
|
|
211
|
+
* @param {string} [options.period] - 'daily', 'monthly', or 'unlimited'
|
|
212
|
+
* @param {boolean} [options.autoApply] - Auto-apply to new namespaces/users
|
|
213
|
+
* @returns {Promise<Object>} Configuration result
|
|
214
|
+
*/
|
|
215
|
+
async setDefaultQuota(options) {
|
|
216
|
+
if (!options.level || !options.service || options.quotaLimit === undefined) {
|
|
217
|
+
throw new Error('level, service, and quotaLimit are required');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (!['namespace', 'end_user'].includes(options.level)) {
|
|
221
|
+
throw new Error('level must be "namespace" or "end_user"');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const response = await this.client.post('credits/defaults', {
|
|
225
|
+
level: options.level,
|
|
226
|
+
service: options.service,
|
|
227
|
+
quotaLimit: options.quotaLimit,
|
|
228
|
+
period: options.period || 'unlimited',
|
|
229
|
+
autoApply: options.autoApply !== undefined ? options.autoApply : true,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
return response;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get default quota configuration
|
|
237
|
+
* @param {string} level - 'namespace' or 'end_user'
|
|
238
|
+
* @param {string} service - Service name
|
|
239
|
+
* @returns {Promise<Object>} Configuration details
|
|
240
|
+
*/
|
|
241
|
+
async getDefaultQuota(level, service) {
|
|
242
|
+
if (!level || !service) {
|
|
243
|
+
throw new Error('level and service are required');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const response = await this.client.get('credits/defaults', {
|
|
247
|
+
level,
|
|
248
|
+
service,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
return response;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Get all default quota configurations
|
|
256
|
+
* @param {string} [level] - Optional: filter by 'namespace' or 'end_user'
|
|
257
|
+
* @returns {Promise<Object>} All configurations
|
|
258
|
+
*/
|
|
259
|
+
async getAllDefaultQuotas(level = null) {
|
|
260
|
+
const params = level ? { level } : {};
|
|
261
|
+
const response = await this.client.get('credits/defaults/all', params);
|
|
262
|
+
return response;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Delete default quota configuration
|
|
267
|
+
* @param {string} level - 'namespace' or 'end_user'
|
|
268
|
+
* @param {string} service - Service name
|
|
269
|
+
* @returns {Promise<Object>} Deletion result
|
|
270
|
+
*/
|
|
271
|
+
async deleteDefaultQuota(level, service) {
|
|
272
|
+
if (!level || !service) {
|
|
273
|
+
throw new Error('level and service are required');
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// DELETE with body
|
|
277
|
+
const response = await this.client.delete('credits/defaults', {
|
|
278
|
+
level,
|
|
279
|
+
service,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
return response;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Toggle auto-apply for default quota
|
|
287
|
+
* @param {string} level - 'namespace' or 'end_user'
|
|
288
|
+
* @param {string} service - Service name
|
|
289
|
+
* @param {boolean} autoApply - Enable/disable auto-apply
|
|
290
|
+
* @returns {Promise<Object>} Toggle result
|
|
291
|
+
*/
|
|
292
|
+
async toggleDefaultQuotaAutoApply(level, service, autoApply) {
|
|
293
|
+
if (!level || !service || autoApply === undefined) {
|
|
294
|
+
throw new Error('level, service, and autoApply are required');
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const response = await this.client.post('credits/defaults/toggle-auto-apply', {
|
|
298
|
+
level,
|
|
299
|
+
service,
|
|
300
|
+
autoApply,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
return response;
|
|
304
|
+
}
|
|
305
|
+
|
|
125
306
|
// =============================================================================
|
|
126
307
|
// Usage History & Transactions
|
|
127
308
|
// =============================================================================
|
package/src/chat/sessionQuota.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
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
|
-
|