@codeguide/core 0.0.28 → 0.0.33
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/__tests__/services/codespace/codespace-v2.test.ts +53 -0
- package/__tests__/services/usage/usage-service.test.ts +458 -104
- package/codeguide.ts +3 -0
- package/dist/codeguide.d.ts +2 -1
- package/dist/codeguide.js +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/services/base/base-service.d.ts +21 -0
- package/dist/services/base/base-service.js +114 -0
- package/dist/services/codespace/codespace-service.d.ts +64 -1
- package/dist/services/codespace/codespace-service.js +272 -0
- package/dist/services/codespace/codespace-types.d.ts +213 -12
- package/dist/services/codespace/index.d.ts +1 -1
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +4 -1
- package/dist/services/projects/project-types.d.ts +66 -32
- package/dist/services/starter-kits/index.d.ts +2 -0
- package/dist/services/starter-kits/index.js +20 -0
- package/dist/services/starter-kits/starter-kits-service.d.ts +13 -0
- package/dist/services/starter-kits/starter-kits-service.js +27 -0
- package/dist/services/starter-kits/starter-kits-types.d.ts +34 -0
- package/dist/services/starter-kits/starter-kits-types.js +2 -0
- package/dist/services/subscriptions/subscription-service.d.ts +11 -1
- package/dist/services/subscriptions/subscription-service.js +14 -0
- package/dist/services/tasks/task-service.d.ts +2 -1
- package/dist/services/tasks/task-service.js +8 -0
- package/dist/services/tasks/task-types.d.ts +26 -7
- package/dist/services/usage/usage-service.d.ts +5 -2
- package/dist/services/usage/usage-service.js +58 -9
- package/dist/services/usage/usage-types.d.ts +157 -34
- package/dist/types.d.ts +18 -2
- package/docs/.vitepress/README.md +51 -0
- package/docs/.vitepress/config.ts +139 -0
- package/docs/.vitepress/theme/custom.css +80 -0
- package/docs/.vitepress/theme/index.ts +13 -0
- package/docs/.vitepress/tsconfig.json +19 -0
- package/docs/QUICKSTART.md +77 -0
- package/docs/README.md +134 -0
- package/docs/README_SETUP.md +46 -0
- package/docs/authentication.md +351 -0
- package/docs/codeguide-client.md +350 -0
- package/docs/codespace-models.md +1004 -0
- package/docs/codespace-service.md +444 -0
- package/docs/index.md +135 -0
- package/docs/package.json +14 -0
- package/docs/projects-service.md +688 -0
- package/docs/security-keys-service.md +773 -0
- package/docs/starter-kits-service.md +249 -0
- package/docs/task-service.md +955 -0
- package/docs/testsprite_tests/TC001_Homepage_Load_and_Hero_Section_Display.py +70 -0
- package/docs/testsprite_tests/TC002_Sidebar_Navigation_ExpandCollapse_Functionality.py +73 -0
- package/docs/testsprite_tests/TC003_Full_Text_Local_Search_with_Keyboard_Shortcut.py +90 -0
- package/docs/testsprite_tests/TC004_Dark_Mode_Toggle_and_Persistence.py +73 -0
- package/docs/testsprite_tests/TC005_Mobile_Responsiveness_and_Touch_Navigation.py +113 -0
- package/docs/testsprite_tests/TC006_GitHub_Integration_Edit_this_page_Links.py +73 -0
- package/docs/testsprite_tests/TC007_Syntax_Highlighting_and_Code_Copy_Functionality.py +73 -0
- package/docs/testsprite_tests/TC008_Auto_Generated_Table_of_Contents_Accuracy.py +73 -0
- package/docs/testsprite_tests/TC009_SEO_and_Content_Discoverability_Verification.py +73 -0
- package/docs/testsprite_tests/TC010_Accessibility_Compliance_WCAG_AA.py +73 -0
- package/docs/testsprite_tests/TC011_Local_Development_Workflow_Build_and_Hot_Reload.py +74 -0
- package/docs/testsprite_tests/TC012_Performance_Metrics_Compliance.py +73 -0
- package/docs/testsprite_tests/standard_prd.json +122 -0
- package/docs/testsprite_tests/testsprite-mcp-test-report.html +2508 -0
- package/docs/testsprite_tests/testsprite-mcp-test-report.md +273 -0
- package/docs/testsprite_tests/testsprite_frontend_test_plan.json +390 -0
- package/docs/usage-service.md +291 -1
- package/index.ts +11 -3
- package/package.json +17 -2
- package/plans/CODESPACE_LOGS_STREAMING_GUIDE.md +320 -0
- package/plans/CODESPACE_TASK_LOGS_API_COMPLETE_GUIDE.md +821 -0
- package/services/base/base-service.ts +130 -0
- package/services/codespace/codespace-service.ts +359 -0
- package/services/codespace/codespace-types.ts +295 -13
- package/services/codespace/index.ts +21 -1
- package/services/index.ts +2 -0
- package/services/projects/README.md +107 -34
- package/services/projects/project-types.ts +69 -32
- package/services/starter-kits/index.ts +2 -0
- package/services/starter-kits/starter-kits-service.ts +33 -0
- package/services/starter-kits/starter-kits-types.ts +38 -0
- package/services/subscriptions/subscription-service.ts +23 -5
- package/services/tasks/task-service.ts +10 -0
- package/services/tasks/task-types.ts +29 -7
- package/services/usage/usage-service.ts +59 -10
- package/services/usage/usage-types.ts +186 -36
- package/types.ts +22 -2
|
@@ -6,12 +6,19 @@ import {
|
|
|
6
6
|
TrackUsageRequest,
|
|
7
7
|
TrackUsageResponse,
|
|
8
8
|
CreditBalanceResponse,
|
|
9
|
+
CreditBalanceData,
|
|
9
10
|
CreditCheckResponse,
|
|
10
11
|
UsageSummaryResponse,
|
|
11
12
|
AuthorizationResponse,
|
|
12
13
|
CalculateUsageResponse,
|
|
13
14
|
TrackCodespaceUsageResponse,
|
|
14
15
|
CodespaceTaskUsageResponse,
|
|
16
|
+
DashboardAnalyticsRequest,
|
|
17
|
+
DashboardAnalyticsResponse,
|
|
18
|
+
UsageDetailsRequest,
|
|
19
|
+
UsageDetailsResponse,
|
|
20
|
+
ServiceBreakdownRequest,
|
|
21
|
+
ServiceBreakdownResponse,
|
|
15
22
|
} from '../../../services/usage/usage-types'
|
|
16
23
|
|
|
17
24
|
describe('UsageService', () => {
|
|
@@ -20,12 +27,12 @@ describe('UsageService', () => {
|
|
|
20
27
|
let config: APIServiceConfig
|
|
21
28
|
|
|
22
29
|
beforeEach(() => {
|
|
23
|
-
mockAxios = new MockAdapter(axios)
|
|
24
30
|
config = {
|
|
25
31
|
baseUrl: 'https://api.codeguide.app',
|
|
26
32
|
databaseApiKey: 'sk_test123',
|
|
27
33
|
}
|
|
28
34
|
usageService = new UsageService(config)
|
|
35
|
+
mockAxios = new MockAdapter((usageService as any).client)
|
|
29
36
|
})
|
|
30
37
|
|
|
31
38
|
afterEach(() => {
|
|
@@ -49,7 +56,7 @@ describe('UsageService', () => {
|
|
|
49
56
|
message: 'Usage tracked successfully',
|
|
50
57
|
}
|
|
51
58
|
|
|
52
|
-
mockAxios.onPost('/
|
|
59
|
+
mockAxios.onPost('/usage/track', request).reply(200, response)
|
|
53
60
|
|
|
54
61
|
const result = await usageService.trackUsage(request)
|
|
55
62
|
|
|
@@ -63,7 +70,7 @@ describe('UsageService', () => {
|
|
|
63
70
|
output_tokens: 50,
|
|
64
71
|
}
|
|
65
72
|
|
|
66
|
-
mockAxios.onPost('/
|
|
73
|
+
mockAxios.onPost('/usage/track', request).reply(400, {
|
|
67
74
|
detail: 'Invalid request',
|
|
68
75
|
})
|
|
69
76
|
|
|
@@ -73,7 +80,7 @@ describe('UsageService', () => {
|
|
|
73
80
|
|
|
74
81
|
describe('getCreditBalance', () => {
|
|
75
82
|
it('should get credit balance successfully', async () => {
|
|
76
|
-
const
|
|
83
|
+
const creditBalanceData: CreditBalanceData = {
|
|
77
84
|
user_id: 'user123',
|
|
78
85
|
total_consumed: 10.5,
|
|
79
86
|
total_allotted: 100,
|
|
@@ -87,7 +94,11 @@ describe('UsageService', () => {
|
|
|
87
94
|
},
|
|
88
95
|
}
|
|
89
96
|
|
|
90
|
-
|
|
97
|
+
const response: CreditBalanceResponse = {
|
|
98
|
+
data: creditBalanceData,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
mockAxios.onGet('/usage/credit-balance').reply(200, response)
|
|
91
102
|
|
|
92
103
|
const result = await usageService.getCreditBalance()
|
|
93
104
|
|
|
@@ -113,7 +124,7 @@ describe('UsageService', () => {
|
|
|
113
124
|
|
|
114
125
|
mockAxios
|
|
115
126
|
.onGet(
|
|
116
|
-
'/
|
|
127
|
+
'/usage/credit-check?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2'
|
|
117
128
|
)
|
|
118
129
|
.reply(200, response)
|
|
119
130
|
|
|
@@ -135,9 +146,7 @@ describe('UsageService', () => {
|
|
|
135
146
|
model_key: 'gpt-4',
|
|
136
147
|
}
|
|
137
148
|
|
|
138
|
-
mockAxios
|
|
139
|
-
.onGet('/v1/usage/credit-check?model_key=gpt-4&input_tokens=100')
|
|
140
|
-
.reply(200, response)
|
|
149
|
+
mockAxios.onGet('/usage/credit-check?model_key=gpt-4&input_tokens=100').reply(200, response)
|
|
141
150
|
|
|
142
151
|
const result = await usageService.checkCredits(params)
|
|
143
152
|
|
|
@@ -145,73 +154,6 @@ describe('UsageService', () => {
|
|
|
145
154
|
})
|
|
146
155
|
})
|
|
147
156
|
|
|
148
|
-
describe('getUsageSummary', () => {
|
|
149
|
-
it('should get usage summary with date range', async () => {
|
|
150
|
-
const params = {
|
|
151
|
-
start_date: '2024-01-01',
|
|
152
|
-
end_date: '2024-01-31',
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const response: UsageSummaryResponse = {
|
|
156
|
-
user_id: 'user123',
|
|
157
|
-
period: {
|
|
158
|
-
start_date: '2024-01-01',
|
|
159
|
-
end_date: '2024-01-31',
|
|
160
|
-
},
|
|
161
|
-
usage_summary: {
|
|
162
|
-
total_credits_used: 15.5,
|
|
163
|
-
total_calls: 42,
|
|
164
|
-
model_breakdown: {
|
|
165
|
-
'gpt-4': { calls: 20, credits: 12.0 },
|
|
166
|
-
'gpt-3.5': { calls: 22, credits: 3.5 },
|
|
167
|
-
},
|
|
168
|
-
daily_usage: [
|
|
169
|
-
{ date: '2024-01-01', credits_used: 1.5, calls: 5 },
|
|
170
|
-
{ date: '2024-01-02', credits_used: 2.0, calls: 8 },
|
|
171
|
-
],
|
|
172
|
-
},
|
|
173
|
-
subscription: {
|
|
174
|
-
plan: 'pro',
|
|
175
|
-
status: 'active',
|
|
176
|
-
},
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
mockAxios
|
|
180
|
-
.onGet('/v1/usage/summary?start_date=2024-01-01&end_date=2024-01-31')
|
|
181
|
-
.reply(200, response)
|
|
182
|
-
|
|
183
|
-
const result = await usageService.getUsageSummary(params)
|
|
184
|
-
|
|
185
|
-
expect(result).toEqual(response)
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
it('should get usage summary without date range', async () => {
|
|
189
|
-
const response: UsageSummaryResponse = {
|
|
190
|
-
user_id: 'user123',
|
|
191
|
-
period: {
|
|
192
|
-
start_date: '2024-01-01',
|
|
193
|
-
end_date: '2024-01-31',
|
|
194
|
-
},
|
|
195
|
-
usage_summary: {
|
|
196
|
-
total_credits_used: 15.5,
|
|
197
|
-
total_calls: 42,
|
|
198
|
-
model_breakdown: {},
|
|
199
|
-
daily_usage: [],
|
|
200
|
-
},
|
|
201
|
-
subscription: {
|
|
202
|
-
plan: 'pro',
|
|
203
|
-
status: 'active',
|
|
204
|
-
},
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
mockAxios.onGet('/v1/usage/summary').reply(200, response)
|
|
208
|
-
|
|
209
|
-
const result = await usageService.getUsageSummary()
|
|
210
|
-
|
|
211
|
-
expect(result).toEqual(response)
|
|
212
|
-
})
|
|
213
|
-
})
|
|
214
|
-
|
|
215
157
|
describe('getAuthorization', () => {
|
|
216
158
|
it('should get authorization info successfully', async () => {
|
|
217
159
|
const response: AuthorizationResponse = {
|
|
@@ -291,7 +233,7 @@ describe('UsageService', () => {
|
|
|
291
233
|
message: 'Authorization status retrieved successfully',
|
|
292
234
|
}
|
|
293
235
|
|
|
294
|
-
mockAxios.onGet('/
|
|
236
|
+
mockAxios.onGet('/usage/authorization').reply(200, response)
|
|
295
237
|
|
|
296
238
|
const result = await usageService.getAuthorization()
|
|
297
239
|
|
|
@@ -375,7 +317,7 @@ describe('UsageService', () => {
|
|
|
375
317
|
message: 'Authorization status retrieved successfully',
|
|
376
318
|
}
|
|
377
319
|
|
|
378
|
-
mockAxios.onGet('/
|
|
320
|
+
mockAxios.onGet('/usage/authorization').reply(200, response)
|
|
379
321
|
|
|
380
322
|
const result = await usageService.getAuthorization()
|
|
381
323
|
|
|
@@ -397,7 +339,7 @@ describe('UsageService', () => {
|
|
|
397
339
|
credits_expire_at: '2024-12-31',
|
|
398
340
|
}
|
|
399
341
|
|
|
400
|
-
mockAxios.onGet('/
|
|
342
|
+
mockAxios.onGet('/usage/free-user-status').reply(200, response)
|
|
401
343
|
|
|
402
344
|
const result = await usageService.getFreeUserStatus()
|
|
403
345
|
|
|
@@ -428,7 +370,7 @@ describe('UsageService', () => {
|
|
|
428
370
|
|
|
429
371
|
mockAxios
|
|
430
372
|
.onGet(
|
|
431
|
-
'/
|
|
373
|
+
'/usage/calculate?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2&cost_amount=0.05'
|
|
432
374
|
)
|
|
433
375
|
.reply(200, response)
|
|
434
376
|
|
|
@@ -461,7 +403,7 @@ describe('UsageService', () => {
|
|
|
461
403
|
created_at: '2024-01-01T00:00:00Z',
|
|
462
404
|
}
|
|
463
405
|
|
|
464
|
-
mockAxios.onPost('/
|
|
406
|
+
mockAxios.onPost('/usage/codespace/track', request).reply(200, response)
|
|
465
407
|
|
|
466
408
|
const result = await usageService.trackCodespaceUsage(request)
|
|
467
409
|
|
|
@@ -472,29 +414,15 @@ describe('UsageService', () => {
|
|
|
472
414
|
describe('getCodespaceTaskUsage', () => {
|
|
473
415
|
it('should get codespace task usage successfully', async () => {
|
|
474
416
|
const response: CodespaceTaskUsageResponse = {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
total_cost: 0.1,
|
|
417
|
+
status: 'success',
|
|
418
|
+
data: {
|
|
419
|
+
total_records: 2,
|
|
420
|
+
total_credits_consumed: 49.428799,
|
|
421
|
+
latest_usage: '2025-11-24T07:50:58.150274+00:00',
|
|
481
422
|
},
|
|
482
|
-
usage_records: [
|
|
483
|
-
{
|
|
484
|
-
id: 'usage123',
|
|
485
|
-
codespace_task_id: 'task123',
|
|
486
|
-
user_id: 'user123',
|
|
487
|
-
model_key: 'gpt-4',
|
|
488
|
-
input_tokens: 100,
|
|
489
|
-
output_tokens: 50,
|
|
490
|
-
call_seconds: 2,
|
|
491
|
-
cost_amount: 0.05,
|
|
492
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
493
|
-
},
|
|
494
|
-
],
|
|
495
423
|
}
|
|
496
424
|
|
|
497
|
-
mockAxios.onGet('/
|
|
425
|
+
mockAxios.onGet('/usage/codespace/task/task123').reply(200, response)
|
|
498
426
|
|
|
499
427
|
const result = await usageService.getCodespaceTaskUsage('task123')
|
|
500
428
|
|
|
@@ -504,7 +432,7 @@ describe('UsageService', () => {
|
|
|
504
432
|
|
|
505
433
|
describe('healthCheck', () => {
|
|
506
434
|
it('should return true when API is healthy', async () => {
|
|
507
|
-
mockAxios.onGet('/
|
|
435
|
+
mockAxios.onGet('/usage/health').reply(200, {
|
|
508
436
|
status: 'healthy',
|
|
509
437
|
timestamp: '2024-01-01T00:00:00Z',
|
|
510
438
|
version: '1.0.0',
|
|
@@ -516,7 +444,7 @@ describe('UsageService', () => {
|
|
|
516
444
|
})
|
|
517
445
|
|
|
518
446
|
it('should return false when API is not healthy', async () => {
|
|
519
|
-
mockAxios.onGet('/
|
|
447
|
+
mockAxios.onGet('/usage/health').reply(200, {
|
|
520
448
|
status: 'unhealthy',
|
|
521
449
|
timestamp: '2024-01-01T00:00:00Z',
|
|
522
450
|
version: '1.0.0',
|
|
@@ -528,11 +456,437 @@ describe('UsageService', () => {
|
|
|
528
456
|
})
|
|
529
457
|
|
|
530
458
|
it('should return false when health check fails', async () => {
|
|
531
|
-
mockAxios.onGet('/
|
|
459
|
+
mockAxios.onGet('/usage/health').reply(500)
|
|
532
460
|
|
|
533
461
|
const result = await usageService.healthCheck()
|
|
534
462
|
|
|
535
463
|
expect(result).toBe(false)
|
|
536
464
|
})
|
|
537
465
|
})
|
|
466
|
+
|
|
467
|
+
// Dashboard Analytics Tests
|
|
468
|
+
describe('getDashboardAnalytics', () => {
|
|
469
|
+
it('should get dashboard analytics with period parameter', async () => {
|
|
470
|
+
const params: DashboardAnalyticsRequest = {
|
|
471
|
+
period: '7d',
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const response: DashboardAnalyticsResponse = {
|
|
475
|
+
status: 'success',
|
|
476
|
+
data: {
|
|
477
|
+
period: {
|
|
478
|
+
start: '2024-01-25',
|
|
479
|
+
end: '2024-01-31',
|
|
480
|
+
label: '7d',
|
|
481
|
+
},
|
|
482
|
+
daily_usage: [
|
|
483
|
+
{
|
|
484
|
+
date: '2024-01-25',
|
|
485
|
+
credits_consumed: 1250,
|
|
486
|
+
cost_usd: 3.75,
|
|
487
|
+
requests_count: 15,
|
|
488
|
+
average_credits_per_request: 83.33,
|
|
489
|
+
},
|
|
490
|
+
],
|
|
491
|
+
totals: {
|
|
492
|
+
credits_consumed: 13870,
|
|
493
|
+
cost_usd: 41.61,
|
|
494
|
+
requests_count: 142,
|
|
495
|
+
},
|
|
496
|
+
averages: {
|
|
497
|
+
daily_credits: 1981.43,
|
|
498
|
+
daily_requests: 20.29,
|
|
499
|
+
},
|
|
500
|
+
trends: {
|
|
501
|
+
credits_consumed: 15.7,
|
|
502
|
+
requests_count: 8.3,
|
|
503
|
+
},
|
|
504
|
+
top_services: [
|
|
505
|
+
{
|
|
506
|
+
service_type: 'docs',
|
|
507
|
+
credits_consumed: 5230,
|
|
508
|
+
requests_count: 58,
|
|
509
|
+
},
|
|
510
|
+
],
|
|
511
|
+
},
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
mockAxios.onGet('/usage/dashboard/analytics?period=7d').reply(200, response)
|
|
515
|
+
|
|
516
|
+
const result = await usageService.getDashboardAnalytics(params)
|
|
517
|
+
|
|
518
|
+
expect(result).toEqual(response)
|
|
519
|
+
})
|
|
520
|
+
|
|
521
|
+
it('should get dashboard analytics with all parameters', async () => {
|
|
522
|
+
const params: DashboardAnalyticsRequest = {
|
|
523
|
+
start_date: '2024-01-01',
|
|
524
|
+
end_date: '2024-01-31',
|
|
525
|
+
service_type: 'docs',
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const response: DashboardAnalyticsResponse = {
|
|
529
|
+
status: 'success',
|
|
530
|
+
data: {
|
|
531
|
+
period: {
|
|
532
|
+
start: '2024-01-01',
|
|
533
|
+
end: '2024-01-31',
|
|
534
|
+
label: 'custom',
|
|
535
|
+
},
|
|
536
|
+
daily_usage: [],
|
|
537
|
+
totals: {
|
|
538
|
+
credits_consumed: 5000,
|
|
539
|
+
cost_usd: 15.0,
|
|
540
|
+
requests_count: 45,
|
|
541
|
+
},
|
|
542
|
+
averages: {
|
|
543
|
+
daily_credits: 161.29,
|
|
544
|
+
daily_requests: 1.45,
|
|
545
|
+
},
|
|
546
|
+
trends: {
|
|
547
|
+
credits_consumed: 12.5,
|
|
548
|
+
requests_count: 5.2,
|
|
549
|
+
},
|
|
550
|
+
top_services: [
|
|
551
|
+
{
|
|
552
|
+
service_type: 'docs',
|
|
553
|
+
credits_consumed: 5000,
|
|
554
|
+
requests_count: 45,
|
|
555
|
+
},
|
|
556
|
+
],
|
|
557
|
+
},
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
mockAxios
|
|
561
|
+
.onGet(
|
|
562
|
+
'/usage/dashboard/analytics?start_date=2024-01-01&end_date=2024-01-31&service_type=docs'
|
|
563
|
+
)
|
|
564
|
+
.reply(200, response)
|
|
565
|
+
|
|
566
|
+
const result = await usageService.getDashboardAnalytics(params)
|
|
567
|
+
|
|
568
|
+
expect(result).toEqual(response)
|
|
569
|
+
})
|
|
570
|
+
|
|
571
|
+
it('should get dashboard analytics without parameters', async () => {
|
|
572
|
+
const response: DashboardAnalyticsResponse = {
|
|
573
|
+
status: 'success',
|
|
574
|
+
data: {
|
|
575
|
+
period: {
|
|
576
|
+
start: '2024-01-01',
|
|
577
|
+
end: '2024-01-07',
|
|
578
|
+
label: '7d',
|
|
579
|
+
},
|
|
580
|
+
daily_usage: [],
|
|
581
|
+
totals: {
|
|
582
|
+
credits_consumed: 1000,
|
|
583
|
+
cost_usd: 3.0,
|
|
584
|
+
requests_count: 10,
|
|
585
|
+
},
|
|
586
|
+
averages: {
|
|
587
|
+
daily_credits: 142.86,
|
|
588
|
+
daily_requests: 1.43,
|
|
589
|
+
},
|
|
590
|
+
trends: {
|
|
591
|
+
credits_consumed: 5.0,
|
|
592
|
+
requests_count: 2.0,
|
|
593
|
+
},
|
|
594
|
+
top_services: [],
|
|
595
|
+
},
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
mockAxios.onGet('/usage/dashboard/analytics').reply(200, response)
|
|
599
|
+
|
|
600
|
+
const result = await usageService.getDashboardAnalytics()
|
|
601
|
+
|
|
602
|
+
expect(result).toEqual(response)
|
|
603
|
+
})
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
describe('getUsageDetails', () => {
|
|
607
|
+
it('should get usage details with pagination parameters', async () => {
|
|
608
|
+
const params: UsageDetailsRequest = {
|
|
609
|
+
page: 1,
|
|
610
|
+
page_size: 25,
|
|
611
|
+
sort_by: 'credits_consumed',
|
|
612
|
+
sort_order: 'desc',
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const response: UsageDetailsResponse = {
|
|
616
|
+
status: 'success',
|
|
617
|
+
data: [
|
|
618
|
+
{
|
|
619
|
+
id: 'rec_123456789',
|
|
620
|
+
created_at: '2024-01-31T14:30:15.123Z',
|
|
621
|
+
service_type: 'docs',
|
|
622
|
+
model_name: 'GPT-4',
|
|
623
|
+
usage_type: 'output_tokens',
|
|
624
|
+
units_consumed: 1250,
|
|
625
|
+
credits_consumed: 156,
|
|
626
|
+
cost_amount: 0.468,
|
|
627
|
+
},
|
|
628
|
+
],
|
|
629
|
+
pagination: {
|
|
630
|
+
page: 1,
|
|
631
|
+
page_size: 25,
|
|
632
|
+
total_count: 142,
|
|
633
|
+
total_pages: 6,
|
|
634
|
+
has_next: true,
|
|
635
|
+
has_prev: false,
|
|
636
|
+
},
|
|
637
|
+
filters: {
|
|
638
|
+
period: null,
|
|
639
|
+
start_date: null,
|
|
640
|
+
end_date: null,
|
|
641
|
+
service_type: null,
|
|
642
|
+
},
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
mockAxios
|
|
646
|
+
.onGet(
|
|
647
|
+
'/usage/dashboard/details?page=1&page_size=25&sort_by=credits_consumed&sort_order=desc'
|
|
648
|
+
)
|
|
649
|
+
.reply(200, response)
|
|
650
|
+
|
|
651
|
+
const result = await usageService.getUsageDetails(params)
|
|
652
|
+
|
|
653
|
+
expect(result).toEqual(response)
|
|
654
|
+
})
|
|
655
|
+
|
|
656
|
+
it('should get usage details with filtering parameters', async () => {
|
|
657
|
+
const params: UsageDetailsRequest = {
|
|
658
|
+
period: '1m',
|
|
659
|
+
service_type: 'chat',
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const response: UsageDetailsResponse = {
|
|
663
|
+
status: 'success',
|
|
664
|
+
data: [
|
|
665
|
+
{
|
|
666
|
+
id: 'rec_123456790',
|
|
667
|
+
created_at: '2024-01-30T10:15:20.456Z',
|
|
668
|
+
service_type: 'chat',
|
|
669
|
+
model_name: 'GPT-3.5 Turbo',
|
|
670
|
+
usage_type: 'input_tokens',
|
|
671
|
+
units_consumed: 890,
|
|
672
|
+
credits_consumed: 89,
|
|
673
|
+
cost_amount: null,
|
|
674
|
+
},
|
|
675
|
+
],
|
|
676
|
+
pagination: {
|
|
677
|
+
page: 1,
|
|
678
|
+
page_size: 50,
|
|
679
|
+
total_count: 25,
|
|
680
|
+
total_pages: 1,
|
|
681
|
+
has_next: false,
|
|
682
|
+
has_prev: false,
|
|
683
|
+
},
|
|
684
|
+
filters: {
|
|
685
|
+
period: '1m',
|
|
686
|
+
start_date: null,
|
|
687
|
+
end_date: null,
|
|
688
|
+
service_type: 'chat',
|
|
689
|
+
},
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
mockAxios.onGet('/usage/dashboard/details?period=1m&service_type=chat').reply(200, response)
|
|
693
|
+
|
|
694
|
+
const result = await usageService.getUsageDetails(params)
|
|
695
|
+
|
|
696
|
+
expect(result).toEqual(response)
|
|
697
|
+
})
|
|
698
|
+
})
|
|
699
|
+
|
|
700
|
+
describe('getUsageSummary', () => {
|
|
701
|
+
it('should get usage summary dashboard with period parameter', async () => {
|
|
702
|
+
const params = {
|
|
703
|
+
period: '7d' as const,
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
const response: UsageSummaryResponse = {
|
|
707
|
+
status: 'success',
|
|
708
|
+
data: {
|
|
709
|
+
current_period: {
|
|
710
|
+
credits_consumed: 13870,
|
|
711
|
+
cost_usd: 41.61,
|
|
712
|
+
requests_count: 142,
|
|
713
|
+
},
|
|
714
|
+
previous_period: {
|
|
715
|
+
credits_consumed: 11990,
|
|
716
|
+
cost_usd: 35.97,
|
|
717
|
+
requests_count: 131,
|
|
718
|
+
},
|
|
719
|
+
billing_cycle: {
|
|
720
|
+
total_allotted: 50000,
|
|
721
|
+
total_consumed: 28450,
|
|
722
|
+
remaining_credits: 21550,
|
|
723
|
+
},
|
|
724
|
+
utilization_percentage: 56.9,
|
|
725
|
+
remaining_credits: 21550,
|
|
726
|
+
daily_average: 1981.43,
|
|
727
|
+
projected_monthly: 59443,
|
|
728
|
+
},
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
mockAxios.onGet('/usage/dashboard/summary?period=7d').reply(200, response)
|
|
732
|
+
|
|
733
|
+
const result = await usageService.getUsageSummary(params)
|
|
734
|
+
|
|
735
|
+
expect(result).toEqual(response)
|
|
736
|
+
})
|
|
737
|
+
|
|
738
|
+
it('should get usage summary dashboard with custom date range', async () => {
|
|
739
|
+
const params = {
|
|
740
|
+
start_date: '2024-01-01',
|
|
741
|
+
end_date: '2024-01-31',
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
const response: UsageSummaryResponse = {
|
|
745
|
+
status: 'success',
|
|
746
|
+
data: {
|
|
747
|
+
current_period: {
|
|
748
|
+
credits_consumed: 25000,
|
|
749
|
+
cost_usd: 75.0,
|
|
750
|
+
requests_count: 300,
|
|
751
|
+
},
|
|
752
|
+
previous_period: {
|
|
753
|
+
credits_consumed: 22000,
|
|
754
|
+
cost_usd: 66.0,
|
|
755
|
+
requests_count: 275,
|
|
756
|
+
},
|
|
757
|
+
billing_cycle: {
|
|
758
|
+
total_allotted: 50000,
|
|
759
|
+
total_consumed: 47000,
|
|
760
|
+
remaining_credits: 3000,
|
|
761
|
+
},
|
|
762
|
+
utilization_percentage: 94.0,
|
|
763
|
+
remaining_credits: 3000,
|
|
764
|
+
daily_average: 806.45,
|
|
765
|
+
projected_monthly: 25000,
|
|
766
|
+
},
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
mockAxios
|
|
770
|
+
.onGet('/usage/dashboard/summary?start_date=2024-01-01&end_date=2024-01-31')
|
|
771
|
+
.reply(200, response)
|
|
772
|
+
|
|
773
|
+
const result = await usageService.getUsageSummary(params)
|
|
774
|
+
|
|
775
|
+
expect(result).toEqual(response)
|
|
776
|
+
})
|
|
777
|
+
})
|
|
778
|
+
|
|
779
|
+
describe('getServiceBreakdown', () => {
|
|
780
|
+
it('should get service breakdown with period parameter', async () => {
|
|
781
|
+
const params: ServiceBreakdownRequest = {
|
|
782
|
+
period: '7d',
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
const response: ServiceBreakdownResponse = {
|
|
786
|
+
status: 'success',
|
|
787
|
+
data: {
|
|
788
|
+
period: {
|
|
789
|
+
start: '2024-01-25',
|
|
790
|
+
end: '2024-01-31',
|
|
791
|
+
label: '7d',
|
|
792
|
+
},
|
|
793
|
+
services: [
|
|
794
|
+
{
|
|
795
|
+
service_type: 'docs',
|
|
796
|
+
credits_consumed: 5230,
|
|
797
|
+
percentage: 37.71,
|
|
798
|
+
cost_usd: 15.69,
|
|
799
|
+
requests_count: 58,
|
|
800
|
+
trend: 12.5,
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
service_type: 'chat',
|
|
804
|
+
credits_consumed: 4120,
|
|
805
|
+
percentage: 29.71,
|
|
806
|
+
cost_usd: 12.36,
|
|
807
|
+
requests_count: 47,
|
|
808
|
+
trend: -5.2,
|
|
809
|
+
},
|
|
810
|
+
],
|
|
811
|
+
total_credits: 13870,
|
|
812
|
+
total_cost: 41.61,
|
|
813
|
+
},
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
mockAxios.onGet('/usage/dashboard/services?period=7d').reply(200, response)
|
|
817
|
+
|
|
818
|
+
const result = await usageService.getServiceBreakdown(params)
|
|
819
|
+
|
|
820
|
+
expect(result).toEqual(response)
|
|
821
|
+
})
|
|
822
|
+
|
|
823
|
+
it('should get service breakdown with custom date range', async () => {
|
|
824
|
+
const params: ServiceBreakdownRequest = {
|
|
825
|
+
start_date: '2024-01-01',
|
|
826
|
+
end_date: '2024-01-31',
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
const response: ServiceBreakdownResponse = {
|
|
830
|
+
status: 'success',
|
|
831
|
+
data: {
|
|
832
|
+
period: {
|
|
833
|
+
start: '2024-01-01',
|
|
834
|
+
end: '2024-01-31',
|
|
835
|
+
label: 'custom',
|
|
836
|
+
},
|
|
837
|
+
services: [
|
|
838
|
+
{
|
|
839
|
+
service_type: 'codespace_task',
|
|
840
|
+
credits_consumed: 15000,
|
|
841
|
+
percentage: 60.0,
|
|
842
|
+
cost_usd: 45.0,
|
|
843
|
+
requests_count: 25,
|
|
844
|
+
trend: 28.4,
|
|
845
|
+
},
|
|
846
|
+
],
|
|
847
|
+
total_credits: 25000,
|
|
848
|
+
total_cost: 75.0,
|
|
849
|
+
},
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
mockAxios
|
|
853
|
+
.onGet('/usage/dashboard/services?start_date=2024-01-01&end_date=2024-01-31')
|
|
854
|
+
.reply(200, response)
|
|
855
|
+
|
|
856
|
+
const result = await usageService.getServiceBreakdown(params)
|
|
857
|
+
|
|
858
|
+
expect(result).toEqual(response)
|
|
859
|
+
})
|
|
860
|
+
|
|
861
|
+
it('should get service breakdown without parameters', async () => {
|
|
862
|
+
const response: ServiceBreakdownResponse = {
|
|
863
|
+
status: 'success',
|
|
864
|
+
data: {
|
|
865
|
+
period: {
|
|
866
|
+
start: '2024-01-01',
|
|
867
|
+
end: '2024-01-07',
|
|
868
|
+
label: '7d',
|
|
869
|
+
},
|
|
870
|
+
services: [
|
|
871
|
+
{
|
|
872
|
+
service_type: 'api',
|
|
873
|
+
credits_consumed: 700,
|
|
874
|
+
percentage: 100.0,
|
|
875
|
+
cost_usd: 2.1,
|
|
876
|
+
requests_count: 5,
|
|
877
|
+
trend: 0.0,
|
|
878
|
+
},
|
|
879
|
+
],
|
|
880
|
+
total_credits: 700,
|
|
881
|
+
total_cost: 2.1,
|
|
882
|
+
},
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
mockAxios.onGet('/usage/dashboard/services').reply(200, response)
|
|
886
|
+
|
|
887
|
+
const result = await usageService.getServiceBreakdown()
|
|
888
|
+
|
|
889
|
+
expect(result).toEqual(response)
|
|
890
|
+
})
|
|
891
|
+
})
|
|
538
892
|
})
|