@codeguide/core 0.0.24 → 0.0.26

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.
Files changed (29) hide show
  1. package/__tests__/services/codespace/codespace-models.test.ts +458 -0
  2. package/__tests__/services/security-keys.test.ts +587 -0
  3. package/codeguide.ts +3 -1
  4. package/dist/codeguide.d.ts +2 -1
  5. package/dist/codeguide.js +1 -0
  6. package/dist/examples/project-filtering-example.js +3 -3
  7. package/dist/services/codespace/codespace-service.d.ts +52 -1
  8. package/dist/services/codespace/codespace-service.js +87 -0
  9. package/dist/services/codespace/codespace-types.d.ts +45 -0
  10. package/dist/services/codespace/index.d.ts +1 -1
  11. package/dist/services/index.d.ts +2 -0
  12. package/dist/services/index.js +4 -1
  13. package/dist/services/projects/project-types.d.ts +4 -6
  14. package/dist/services/security-keys/index.d.ts +3 -0
  15. package/dist/services/security-keys/index.js +21 -0
  16. package/dist/services/security-keys/security-keys-service.d.ts +111 -0
  17. package/dist/services/security-keys/security-keys-service.js +190 -0
  18. package/dist/services/security-keys/security-keys-types.d.ts +105 -0
  19. package/dist/services/security-keys/security-keys-types.js +8 -0
  20. package/examples/project-filtering-example.ts +3 -3
  21. package/package.json +1 -1
  22. package/services/codespace/codespace-service.ts +104 -0
  23. package/services/codespace/codespace-types.ts +65 -1
  24. package/services/codespace/index.ts +12 -1
  25. package/services/index.ts +2 -0
  26. package/services/projects/project-types.ts +4 -6
  27. package/services/security-keys/index.ts +25 -0
  28. package/services/security-keys/security-keys-service.ts +229 -0
  29. package/services/security-keys/security-keys-types.ts +187 -0
@@ -0,0 +1,587 @@
1
+ import { SecurityKeysService } from '../../services/security-keys'
2
+ import { APIServiceConfig } from '../../types'
3
+ import {
4
+ CreateProviderAPIKeyRequest,
5
+ CreateGitHubTokenRequest
6
+ } from '../../services/security-keys/security-keys-types'
7
+ import axios from 'axios'
8
+ import axiosMockAdapter from 'axios-mock-adapter'
9
+
10
+ describe('SecurityKeysService', () => {
11
+ let service: SecurityKeysService
12
+ let mock: axiosMockAdapter
13
+
14
+ beforeEach(() => {
15
+ const config: APIServiceConfig = {
16
+ apiKey: 'test-api-key',
17
+ baseUrl: 'https://api.test.com',
18
+ timeout: 10000,
19
+ }
20
+
21
+ service = new SecurityKeysService(config)
22
+ mock = new axiosMockAdapter(axios)
23
+ })
24
+
25
+ afterEach(() => {
26
+ mock.reset()
27
+ })
28
+
29
+ // ============================================================================
30
+ // Provider API Key Tests
31
+ // ============================================================================
32
+
33
+ describe('Provider API Key Methods', () => {
34
+ describe('createProviderAPIKey', () => {
35
+ it('should create a provider API key successfully', async () => {
36
+ const request = {
37
+ provider_key: 'openai',
38
+ api_key: 'sk-1234567890abcdef1234567890abcdef12345678'
39
+ }
40
+
41
+ const expectedResponse = {
42
+ status: 'success',
43
+ data: {
44
+ id: '123e4567-e89b-12d3-a456-426614174000',
45
+ created_at: '2024-01-15T10:30:00.000Z',
46
+ user_id: 'user_abc123',
47
+ name: 'provider_api_key',
48
+ displayed_name: 'OpenAI API Key',
49
+ provider_id: 'openai',
50
+ provider_name: 'OpenAI',
51
+ provider_key: 'openai',
52
+ value_masked: '***************************************5678',
53
+ object_value: {
54
+ provider_id: 'openai'
55
+ },
56
+ encryption: 'fernet',
57
+ key_version: 'v1'
58
+ }
59
+ }
60
+
61
+ mock.onPost('/security-keys/provider-api-key', request).reply(201, expectedResponse)
62
+
63
+ const result = await service.createProviderAPIKey(request)
64
+
65
+ expect(result).toEqual(expectedResponse)
66
+ expect(mock.history.post[0].url).toBe('/security-keys/provider-api-key')
67
+ })
68
+
69
+ it('should throw error when provider_key is missing', async () => {
70
+ const request = {
71
+ provider_key: '',
72
+ api_key: 'sk-1234567890abcdef1234567890abcdef12345678'
73
+ } as CreateProviderAPIKeyRequest
74
+
75
+ await expect(service.createProviderAPIKey(request)).rejects.toThrow('provider_key is required')
76
+ })
77
+
78
+ it('should throw error when api_key is missing', async () => {
79
+ const request = {
80
+ provider_key: 'openai',
81
+ api_key: ''
82
+ } as CreateProviderAPIKeyRequest
83
+
84
+ await expect(service.createProviderAPIKey(request)).rejects.toThrow('api_key is required')
85
+ })
86
+
87
+ it('should throw error when api_key is too short', async () => {
88
+ const request = {
89
+ provider_key: 'openai',
90
+ api_key: 'short'
91
+ }
92
+
93
+ await expect(service.createProviderAPIKey(request)).rejects.toThrow('api_key must be at least 10 characters long')
94
+ })
95
+
96
+ it('should handle provider not found error', async () => {
97
+ const request = {
98
+ provider_key: 'invalid_provider',
99
+ api_key: 'sk-1234567890abcdef1234567890abcdef12345678'
100
+ }
101
+
102
+ const errorResponse = {
103
+ detail: "Provider 'invalid_provider' not found. Please choose a valid provider."
104
+ }
105
+
106
+ mock.onPost('/security-keys/provider-api-key', request).reply(400, errorResponse)
107
+
108
+ await expect(service.createProviderAPIKey(request)).rejects.toThrow("Provider 'invalid_provider' not found. Please choose a valid provider.")
109
+ })
110
+
111
+ it('should handle duplicate key error', async () => {
112
+ const request = {
113
+ provider_key: 'openai',
114
+ api_key: 'sk-1234567890abcdef1234567890abcdef12345678'
115
+ }
116
+
117
+ const errorResponse = {
118
+ detail: "API key for provider 'openai' already exists. Use update endpoint to change it."
119
+ }
120
+
121
+ mock.onPost('/security-keys/provider-api-key', request).reply(400, errorResponse)
122
+
123
+ await expect(service.createProviderAPIKey(request)).rejects.toThrow("API key for provider 'openai' already exists. Use update endpoint to change it.")
124
+ })
125
+ })
126
+
127
+ describe('getProviderAPIKey', () => {
128
+ it('should get a provider API key without revealing it', async () => {
129
+ const providerKey = 'openai'
130
+ const expectedResponse = {
131
+ status: 'success',
132
+ data: {
133
+ id: '123e4567-e89b-12d3-a456-426614174000',
134
+ created_at: '2024-01-15T10:30:00.000Z',
135
+ user_id: 'user_abc123',
136
+ name: 'provider_api_key',
137
+ displayed_name: 'OpenAI API Key',
138
+ provider_id: 'openai',
139
+ provider_name: 'OpenAI',
140
+ provider_key: 'openai',
141
+ value_masked: '***************************************5678',
142
+ object_value: {
143
+ provider_id: 'openai'
144
+ },
145
+ encryption: 'fernet',
146
+ key_version: 'v1'
147
+ }
148
+ }
149
+
150
+ mock.onGet(`/security-keys/provider-api-key/${providerKey}`).reply(200, expectedResponse)
151
+
152
+ const result = await service.getProviderAPIKey(providerKey)
153
+
154
+ expect(result).toEqual(expectedResponse)
155
+ expect(mock.history.get[0].url).toBe('/security-keys/provider-api-key/openai')
156
+ })
157
+
158
+ it('should get a provider API key with reveal=true', async () => {
159
+ const providerKey = 'openai'
160
+ const expectedResponse = {
161
+ status: 'success',
162
+ data: {
163
+ id: '123e4567-e89b-12d3-a456-426614174000',
164
+ created_at: '2024-01-15T10:30:00.000Z',
165
+ user_id: 'user_abc123',
166
+ name: 'provider_api_key',
167
+ displayed_name: 'OpenAI API Key',
168
+ provider_id: 'openai',
169
+ provider_name: 'OpenAI',
170
+ provider_key: 'openai',
171
+ value_masked: '***************************************5678',
172
+ value: 'sk-1234567890abcdef1234567890abcdef12345678',
173
+ object_value: {
174
+ provider_id: 'openai'
175
+ },
176
+ encryption: 'fernet',
177
+ key_version: 'v1'
178
+ }
179
+ }
180
+
181
+ mock.onGet(`/security-keys/provider-api-key/${providerKey}?reveal=true`).reply(200, expectedResponse)
182
+
183
+ const result = await service.getProviderAPIKey(providerKey, true)
184
+
185
+ expect(result).toEqual(expectedResponse)
186
+ expect(mock.history.get[0].url).toBe('/security-keys/provider-api-key/openai?reveal=true')
187
+ })
188
+
189
+ it('should handle key not found error', async () => {
190
+ const providerKey = 'anthropic'
191
+ const errorResponse = {
192
+ detail: "No API key found for provider 'anthropic'"
193
+ }
194
+
195
+ mock.onGet(`/security-keys/provider-api-key/${providerKey}`).reply(404, errorResponse)
196
+
197
+ await expect(service.getProviderAPIKey(providerKey)).rejects.toThrow("No API key found for provider 'anthropic'")
198
+ })
199
+
200
+ it('should throw error when provider_key is missing', async () => {
201
+ await expect(service.getProviderAPIKey('')).rejects.toThrow('provider_key is required')
202
+ })
203
+ })
204
+
205
+ describe('listProviderAPIKeys', () => {
206
+ it('should list all provider API keys', async () => {
207
+ const expectedResponse = {
208
+ status: 'success',
209
+ data: [
210
+ {
211
+ id: '123e4567-e89b-12d3-a456-426614174000',
212
+ created_at: '2024-01-15T10:30:00.000Z',
213
+ user_id: 'user_abc123',
214
+ name: 'provider_api_key',
215
+ displayed_name: 'OpenAI API Key',
216
+ provider_id: 'openai',
217
+ provider_name: 'OpenAI',
218
+ provider_key: 'openai',
219
+ provider_logo_src: 'https://cdn.openai.com/API/logo.png',
220
+ value_masked: '***************************************5678',
221
+ object_value: {
222
+ provider_id: 'openai'
223
+ },
224
+ encryption: 'fernet',
225
+ key_version: 'v1'
226
+ },
227
+ {
228
+ id: '456e7890-e89b-12d3-a456-426614174001',
229
+ created_at: '2024-01-15T11:15:00.000Z',
230
+ user_id: 'user_abc123',
231
+ name: 'provider_api_key',
232
+ displayed_name: 'Anthropic API Key',
233
+ provider_id: 'anthropic',
234
+ provider_name: 'Anthropic',
235
+ provider_key: 'anthropic',
236
+ provider_logo_src: 'https://anthropic.com/images/logo.png',
237
+ value_masked: '***************************************9012',
238
+ object_value: {
239
+ provider_id: 'anthropic'
240
+ },
241
+ encryption: 'fernet',
242
+ key_version: 'v1'
243
+ }
244
+ ]
245
+ }
246
+
247
+ mock.onGet('/security-keys/provider-api-keys').reply(200, expectedResponse)
248
+
249
+ const result = await service.listProviderAPIKeys()
250
+
251
+ expect(result).toEqual(expectedResponse)
252
+ expect(mock.history.get[0].url).toBe('/security-keys/provider-api-keys')
253
+ })
254
+
255
+ it('should handle empty list response', async () => {
256
+ const expectedResponse = {
257
+ status: 'success',
258
+ data: []
259
+ }
260
+
261
+ mock.onGet('/security-keys/provider-api-keys').reply(200, expectedResponse)
262
+
263
+ const result = await service.listProviderAPIKeys()
264
+
265
+ expect(result).toEqual(expectedResponse)
266
+ expect(result.data).toEqual([])
267
+ })
268
+
269
+ it('should list all provider API keys with reveal=true', async () => {
270
+ const expectedResponse = {
271
+ status: 'success',
272
+ data: [
273
+ {
274
+ id: '123e4567-e89b-12d3-a456-426614174000',
275
+ created_at: '2024-01-15T10:30:00.000Z',
276
+ user_id: 'user_123',
277
+ name: 'openai',
278
+ displayed_name: 'OpenAI API Key',
279
+ provider_id: 'provider_123',
280
+ provider_key: 'openai',
281
+ provider_name: 'OpenAI',
282
+ provider_logo_src: 'https://example.com/openai.png',
283
+ object_value: { "provider_id": "provider_123" },
284
+ encryption: 'fernet',
285
+ key_version: 'v1',
286
+ value_masked: 'sk-****CwVP',
287
+ value: 'sk-proj-AbCdEfGhIjKlMnOpQrStUvWxYz1234567890CwVP'
288
+ },
289
+ {
290
+ id: null,
291
+ created_at: null,
292
+ user_id: 'user_123',
293
+ name: null,
294
+ displayed_name: null,
295
+ provider_id: 'provider_456',
296
+ provider_key: 'anthropic',
297
+ provider_name: 'Anthropic',
298
+ provider_logo_src: 'https://example.com/anthropic.png',
299
+ object_value: null,
300
+ encryption: null,
301
+ key_version: null,
302
+ value_masked: null,
303
+ value: null
304
+ }
305
+ ]
306
+ }
307
+
308
+ mock.onGet('/security-keys/provider-api-keys?reveal=true').reply(200, expectedResponse)
309
+
310
+ const result = await service.listProviderAPIKeys(true)
311
+
312
+ expect(result).toEqual(expectedResponse)
313
+ expect(mock.history.get[0].url).toBe('/security-keys/provider-api-keys?reveal=true')
314
+ })
315
+
316
+ describe('revokeProviderAPIKey', () => {
317
+ it('should revoke a provider API key successfully', async () => {
318
+ const providerKey = 'openai'
319
+ const expectedResponse = {
320
+ status: 'success',
321
+ message: 'Provider API key deleted successfully',
322
+ revoked_provider_id: 'openai'
323
+ }
324
+
325
+ mock.onDelete(`/security-keys/provider-api-key/${providerKey}`).reply(200, expectedResponse)
326
+
327
+ const result = await service.revokeProviderAPIKey(providerKey)
328
+
329
+ expect(result).toEqual(expectedResponse)
330
+ expect(mock.history.delete[0].url).toBe('/security-keys/provider-api-key/openai')
331
+ })
332
+
333
+ it('should throw error when provider_key is missing', async () => {
334
+ await expect(service.revokeProviderAPIKey('')).rejects.toThrow('provider_key is required')
335
+ await expect(service.revokeProviderAPIKey(null as any)).rejects.toThrow('provider_key is required')
336
+ })
337
+
338
+ it('should handle provider API key not found error', async () => {
339
+ const providerKey = 'nonexistent'
340
+ const errorResponse = {
341
+ detail: "No API key found for provider 'nonexistent'"
342
+ }
343
+
344
+ mock.onDelete(`/security-keys/provider-api-key/${providerKey}`).reply(404, errorResponse)
345
+
346
+ await expect(service.revokeProviderAPIKey(providerKey)).rejects.toThrow("No API key found for provider 'nonexistent'")
347
+ })
348
+
349
+ it('should handle provider API key deletion error', async () => {
350
+ const providerKey = 'openai'
351
+ const errorResponse = {
352
+ detail: 'Failed to delete provider API key'
353
+ }
354
+
355
+ mock.onDelete(`/security-keys/provider-api-key/${providerKey}`).reply(500, errorResponse)
356
+
357
+ await expect(service.revokeProviderAPIKey(providerKey)).rejects.toThrow('Failed to delete provider API key')
358
+ })
359
+ })
360
+ })
361
+ })
362
+
363
+ // ============================================================================
364
+ // GitHub Token Tests
365
+ // ============================================================================
366
+
367
+ describe('GitHub Token Methods', () => {
368
+ describe('createGitHubToken', () => {
369
+ it('should create a GitHub token successfully', async () => {
370
+ const request = {
371
+ github_token: 'ghp_1234567890abcdef1234567890abcdef12345678'
372
+ }
373
+
374
+ const expectedResponse = {
375
+ status: 'success',
376
+ data: {
377
+ id: '789e0123-e89b-12d3-a456-426614174003',
378
+ created_at: '2024-01-15T12:30:00.000Z',
379
+ user_id: 'user_abc123',
380
+ name: 'github_token',
381
+ displayed_name: 'GitHub Token',
382
+ value_masked: '***************************************90ab',
383
+ object_value: {
384
+ token_type: 'personal_access_token'
385
+ },
386
+ encryption: 'fernet',
387
+ key_version: 'v1'
388
+ }
389
+ }
390
+
391
+ mock.onPost('/security-keys/github-token', request).reply(201, expectedResponse)
392
+
393
+ const result = await service.createGitHubToken(request)
394
+
395
+ expect(result).toEqual(expectedResponse)
396
+ expect(mock.history.post[0].url).toBe('/security-keys/github-token')
397
+ })
398
+
399
+ it('should throw error when github_token is missing', async () => {
400
+ const request = {} as CreateGitHubTokenRequest
401
+
402
+ await expect(service.createGitHubToken(request)).rejects.toThrow('github_token is required')
403
+ })
404
+
405
+ it('should throw error when github_token has invalid format', async () => {
406
+ const request = {
407
+ github_token: 'invalid_token'
408
+ }
409
+
410
+ await expect(service.createGitHubToken(request)).rejects.toThrow('Invalid GitHub token format. Expected format: ghp_*, gho_*, ghu_*, ghs_*, or ghr_* followed by 36 characters')
411
+ })
412
+
413
+ it('should throw error when github_token is too short', async () => {
414
+ const request = {
415
+ github_token: 'ghp_short'
416
+ }
417
+
418
+ await expect(service.createGitHubToken(request)).rejects.toThrow('GitHub token must be at least 40 characters long')
419
+ })
420
+
421
+ it('should handle GitHub token validation error', async () => {
422
+ const request = {
423
+ github_token: 'ghp_invalid1234567890abcdef1234567890'
424
+ }
425
+
426
+ const errorResponse = {
427
+ detail: 'GitHub token validation failed. Please check that the token is valid and has the necessary permissions.'
428
+ }
429
+
430
+ mock.onPost('/security-keys/github-token', request).reply(400, errorResponse)
431
+
432
+ await expect(service.createGitHubToken(request)).rejects.toThrow('GitHub token validation failed. Please check that the token is valid and has the necessary permissions.')
433
+ })
434
+
435
+ it('should handle duplicate GitHub token error', async () => {
436
+ const request = {
437
+ github_token: 'ghp_1234567890abcdef1234567890abcdef12345678'
438
+ }
439
+
440
+ const errorResponse = {
441
+ detail: 'GitHub token already exists. Use update endpoint to change it.'
442
+ }
443
+
444
+ mock.onPost('/security-keys/github-token', request).reply(400, errorResponse)
445
+
446
+ await expect(service.createGitHubToken(request)).rejects.toThrow('GitHub token already exists. Use update endpoint to change it.')
447
+ })
448
+ })
449
+
450
+ describe('getGitHubToken', () => {
451
+ it('should get GitHub token without revealing it', async () => {
452
+ const expectedResponse = {
453
+ status: 'success',
454
+ data: {
455
+ id: '789e0123-e89b-12d3-a456-426614174003',
456
+ created_at: '2024-01-15T12:30:00.000Z',
457
+ user_id: 'user_abc123',
458
+ name: 'github_token',
459
+ displayed_name: 'GitHub Token',
460
+ value_masked: '***************************************90ab',
461
+ object_value: {
462
+ token_type: 'personal_access_token'
463
+ },
464
+ encryption: 'fernet',
465
+ key_version: 'v1'
466
+ }
467
+ }
468
+
469
+ mock.onGet('/security-keys/github-token').reply(200, expectedResponse)
470
+
471
+ const result = await service.getGitHubToken()
472
+
473
+ expect(result).toEqual(expectedResponse)
474
+ expect(mock.history.get[0].url).toBe('/security-keys/github-token')
475
+ })
476
+
477
+ it('should get GitHub token with reveal=true', async () => {
478
+ const expectedResponse = {
479
+ status: 'success',
480
+ data: {
481
+ id: '789e0123-e89b-12d3-a456-426614174003',
482
+ created_at: '2024-01-15T12:30:00.000Z',
483
+ user_id: 'user_abc123',
484
+ name: 'github_token',
485
+ displayed_name: 'GitHub Token',
486
+ value_masked: '***************************************90ab',
487
+ value: 'ghp_1234567890abcdef1234567890abcdef12345678',
488
+ object_value: {
489
+ token_type: 'personal_access_token'
490
+ },
491
+ encryption: 'fernet',
492
+ key_version: 'v1'
493
+ }
494
+ }
495
+
496
+ mock.onGet('/security-keys/github-token?reveal=true').reply(200, expectedResponse)
497
+
498
+ const result = await service.getGitHubToken(true)
499
+
500
+ expect(result).toEqual(expectedResponse)
501
+ expect(mock.history.get[0].url).toBe('/security-keys/github-token?reveal=true')
502
+ })
503
+
504
+ it('should handle GitHub token not found error', async () => {
505
+ const errorResponse = {
506
+ detail: 'No GitHub token found'
507
+ }
508
+
509
+ mock.onGet('/security-keys/github-token').reply(404, errorResponse)
510
+
511
+ await expect(service.getGitHubToken()).rejects.toThrow('No GitHub token found')
512
+ })
513
+
514
+ describe('revokeGitHubToken', () => {
515
+ it('should revoke GitHub token successfully', async () => {
516
+ const expectedResponse = {
517
+ status: 'success',
518
+ message: 'GitHub token deleted successfully',
519
+ revoked_at: '2024-01-15T14:30:00.000Z'
520
+ }
521
+
522
+ mock.onDelete('/security-keys/github-token').reply(200, expectedResponse)
523
+
524
+ const result = await service.revokeGitHubToken()
525
+
526
+ expect(result).toEqual(expectedResponse)
527
+ expect(mock.history.delete[0].url).toBe('/security-keys/github-token')
528
+ })
529
+
530
+ it('should handle GitHub token not found error', async () => {
531
+ const errorResponse = {
532
+ detail: 'No GitHub token found'
533
+ }
534
+
535
+ mock.onDelete('/security-keys/github-token').reply(404, errorResponse)
536
+
537
+ await expect(service.revokeGitHubToken()).rejects.toThrow('No GitHub token found')
538
+ })
539
+
540
+ it('should handle GitHub token deletion error', async () => {
541
+ const errorResponse = {
542
+ detail: 'Failed to delete GitHub token'
543
+ }
544
+
545
+ mock.onDelete('/security-keys/github-token').reply(500, errorResponse)
546
+
547
+ await expect(service.revokeGitHubToken()).rejects.toThrow('Failed to delete GitHub token')
548
+ })
549
+ })
550
+ })
551
+ })
552
+
553
+ // ============================================================================
554
+ // Validation Tests
555
+ // ============================================================================
556
+
557
+ describe('Validation Tests', () => {
558
+ describe('GitHub Token Validation', () => {
559
+ it('should accept valid GitHub token prefixes', () => {
560
+ const validTokens = [
561
+ 'ghp_1234567890abcdef1234567890abcdef12345678',
562
+ 'gho_1234567890abcdef1234567890abcdef12345678',
563
+ 'ghu_1234567890abcdef1234567890abcdef12345678',
564
+ 'ghs_1234567890abcdef1234567890abcdef12345678',
565
+ 'ghr_1234567890abcdef1234567890abcdef12345678',
566
+ 'github_pat_1234567890abcdef1234567890abcdef12345678'
567
+ ]
568
+
569
+ validTokens.forEach(token => {
570
+ expect(() => service['validateGitHubTokenRequest']({ github_token: token })).not.toThrow()
571
+ })
572
+ })
573
+
574
+ it('should reject invalid GitHub token prefixes', () => {
575
+ const invalidTokens = [
576
+ 'invalid_1234567890abcdef1234567890abcdef12345678',
577
+ 'abc_1234567890abcdef1234567890abcdef12345678',
578
+ '1234567890abcdef1234567890abcdef12345678'
579
+ ]
580
+
581
+ invalidTokens.forEach(token => {
582
+ expect(() => service['validateGitHubTokenRequest']({ github_token: token })).toThrow('Invalid GitHub token format')
583
+ })
584
+ })
585
+ })
586
+ })
587
+ })
package/codeguide.ts CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  CancellationFunnelService,
18
18
  CodespaceService,
19
19
  ExternalTokenService,
20
+ SecurityKeysService,
20
21
  } from './services'
21
22
  import { APIServiceConfig, CodeGuideOptions } from './types'
22
23
 
@@ -31,6 +32,7 @@ export class CodeGuide {
31
32
  public cancellationFunnel: CancellationFunnelService
32
33
  public codespace: CodespaceService
33
34
  public externalTokens: ExternalTokenService
35
+ public securityKeys: SecurityKeysService
34
36
  private options: CodeGuideOptions
35
37
 
36
38
  constructor(config: APIServiceConfig, options: CodeGuideOptions = {}) {
@@ -47,6 +49,7 @@ export class CodeGuide {
47
49
  this.cancellationFunnel = new CancellationFunnelService(config)
48
50
  this.codespace = new CodespaceService(config)
49
51
  this.externalTokens = new ExternalTokenService(config)
52
+ this.securityKeys = new SecurityKeysService(config)
50
53
  }
51
54
 
52
55
  // Convenience method for backward compatibility
@@ -90,7 +93,6 @@ export class CodeGuide {
90
93
  return this.tasks.createTaskGroupWithCodespace(request, this.codespace)
91
94
  }
92
95
 
93
-
94
96
  setOptions(options: Partial<CodeGuideOptions>): void {
95
97
  this.options = { ...this.options, ...options }
96
98
  }
@@ -1,4 +1,4 @@
1
- import { GenerationService, ProjectService, UsageService, RepositoryAnalysisService, TaskService, ApiKeyEnhancedService, SubscriptionService, CancellationFunnelService, CodespaceService, ExternalTokenService } from './services';
1
+ import { GenerationService, ProjectService, UsageService, RepositoryAnalysisService, TaskService, ApiKeyEnhancedService, SubscriptionService, CancellationFunnelService, CodespaceService, ExternalTokenService, SecurityKeysService } from './services';
2
2
  import { APIServiceConfig, CodeGuideOptions } from './types';
3
3
  export declare class CodeGuide {
4
4
  generation: GenerationService;
@@ -11,6 +11,7 @@ export declare class CodeGuide {
11
11
  cancellationFunnel: CancellationFunnelService;
12
12
  codespace: CodespaceService;
13
13
  externalTokens: ExternalTokenService;
14
+ securityKeys: SecurityKeysService;
14
15
  private options;
15
16
  constructor(config: APIServiceConfig, options?: CodeGuideOptions);
16
17
  getGuidance(prompt: string): Promise<any>;
package/dist/codeguide.js CHANGED
@@ -26,6 +26,7 @@ class CodeGuide {
26
26
  this.cancellationFunnel = new services_1.CancellationFunnelService(config);
27
27
  this.codespace = new services_1.CodespaceService(config);
28
28
  this.externalTokens = new services_1.ExternalTokenService(config);
29
+ this.securityKeys = new services_1.SecurityKeysService(config);
29
30
  }
30
31
  // Convenience method for backward compatibility
31
32
  async getGuidance(prompt) {
@@ -49,8 +49,8 @@ async function demonstrateProjectFiltering() {
49
49
  status: 'active'
50
50
  };
51
51
  const paginatedResponse = await codeGuide.projects.getPaginatedProjects(paginatedRequest);
52
- console.log(`Page ${paginatedResponse.pagination.page} of ${paginatedResponse.pagination.total_pages}`);
53
- console.log(`Total projects with repositories: ${paginatedResponse.pagination.total}`);
52
+ console.log(`Page ${paginatedResponse.page} of ${paginatedResponse.total_pages}`);
53
+ console.log(`Total projects with repositories: ${paginatedResponse.count}`);
54
54
  console.log(`Showing ${paginatedResponse.data.length} projects:`);
55
55
  paginatedResponse.data.forEach((project) => {
56
56
  console.log(`- ${project.title}`);
@@ -74,7 +74,7 @@ async function demonstrateProjectFiltering() {
74
74
  sort_by_date: 'desc'
75
75
  };
76
76
  const filteredProjects = await codeGuide.projects.getPaginatedProjects(combinedFilters);
77
- console.log(`Found ${filteredProjects.pagination.total} projects matching filters:`);
77
+ console.log(`Found ${filteredProjects.count} projects matching filters:`);
78
78
  filteredProjects.data.forEach((project) => {
79
79
  console.log(`- ${project.title} (Updated: ${project.updated_at})`);
80
80
  });