@codeguide/core 0.0.33 → 0.0.35

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 (49) hide show
  1. package/__tests__/services/usage/usage-service.test.ts +53 -29
  2. package/codeguide.ts +3 -0
  3. package/dist/codeguide.d.ts +2 -1
  4. package/dist/codeguide.js +1 -0
  5. package/dist/index.d.ts +1 -1
  6. package/dist/services/chat/chat-service.d.ts +44 -0
  7. package/dist/services/chat/chat-service.js +85 -0
  8. package/dist/services/chat/chat-types.d.ts +88 -0
  9. package/dist/services/chat/chat-types.js +5 -0
  10. package/dist/services/chat/index.d.ts +2 -0
  11. package/dist/services/chat/index.js +20 -0
  12. package/dist/services/generation/generation-service.d.ts +7 -1
  13. package/dist/services/generation/generation-service.js +18 -0
  14. package/dist/services/generation/generation-types.d.ts +95 -0
  15. package/dist/services/index.d.ts +4 -0
  16. package/dist/services/index.js +7 -1
  17. package/dist/services/projects/project-service.d.ts +3 -1
  18. package/dist/services/projects/project-service.js +13 -1
  19. package/dist/services/projects/project-types.d.ts +24 -1
  20. package/dist/services/streaming/index.d.ts +2 -0
  21. package/dist/services/streaming/index.js +20 -0
  22. package/dist/services/streaming/streaming-service.d.ts +30 -0
  23. package/dist/services/streaming/streaming-service.js +107 -0
  24. package/dist/services/streaming/streaming-types.d.ts +14 -0
  25. package/dist/services/streaming/streaming-types.js +2 -0
  26. package/dist/services/tasks/task-service.d.ts +3 -1
  27. package/dist/services/tasks/task-service.js +8 -0
  28. package/dist/services/tasks/task-types.d.ts +15 -0
  29. package/dist/services/usage/usage-service.d.ts +35 -1
  30. package/dist/services/usage/usage-service.js +68 -0
  31. package/dist/services/usage/usage-types.d.ts +108 -33
  32. package/index.ts +3 -0
  33. package/package.json +1 -1
  34. package/services/chat/chat-service.ts +110 -0
  35. package/services/chat/chat-types.ts +145 -0
  36. package/services/chat/index.ts +2 -0
  37. package/services/generation/generation-service.ts +40 -0
  38. package/services/generation/generation-types.ts +110 -0
  39. package/services/index.ts +4 -0
  40. package/services/projects/README.md +54 -0
  41. package/services/projects/project-service.ts +20 -1
  42. package/services/projects/project-types.ts +27 -1
  43. package/services/streaming/index.ts +2 -0
  44. package/services/streaming/streaming-service.ts +123 -0
  45. package/services/streaming/streaming-types.ts +15 -0
  46. package/services/tasks/task-service.ts +30 -2
  47. package/services/tasks/task-types.ts +19 -1
  48. package/services/usage/usage-service.ts +81 -0
  49. package/services/usage/usage-types.ts +116 -36
@@ -0,0 +1,123 @@
1
+ import { BaseService } from '../base/base-service'
2
+ import { StreamTechSpecRequest, StreamChunk } from './streaming-types'
3
+
4
+ export class StreamingService extends BaseService {
5
+ /**
6
+ * Stream a tech-spec document for the given project.
7
+ *
8
+ * This method connects to the `/chat/tech-spec` endpoint and streams the response
9
+ * using Server-Sent Events (SSE) format. Each chunk is passed to the `onChunk`
10
+ * callback as it arrives, allowing for incremental UI updates.
11
+ *
12
+ * @param request - The request containing the project_id
13
+ * @param onChunk - Callback function invoked with each content chunk as it arrives
14
+ * @param onError - Optional callback function for handling errors
15
+ * @returns Promise that resolves to the full accumulated content when streaming completes
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const streamingService = new StreamingService(config);
20
+ * let fullContent = '';
21
+ *
22
+ * fullContent = await streamingService.streamTechSpec(
23
+ * { project_id: 'project-123' },
24
+ * (chunk) => {
25
+ * setContent(prev => prev + chunk); // Update UI incrementally
26
+ * }
27
+ * );
28
+ * ```
29
+ */
30
+ async streamTechSpec(
31
+ request: StreamTechSpecRequest,
32
+ onChunk: (content: string) => void,
33
+ onError?: (error: Error) => void
34
+ ): Promise<string> {
35
+ return new Promise<string>(async (resolve, reject) => {
36
+ let fullContent = ''
37
+
38
+ const fullUrl = `${this.client.defaults.baseURL}/chat/tech-spec`
39
+
40
+ try {
41
+ const response = await fetch(fullUrl, {
42
+ method: 'POST',
43
+ headers: {
44
+ ...Object.fromEntries(
45
+ Object.entries(this.client.defaults.headers).filter(
46
+ ([_, v]) => typeof v === 'string'
47
+ ) as [string, string][]
48
+ ),
49
+ Accept: 'text/event-stream',
50
+ 'Cache-Control': 'no-cache',
51
+ },
52
+ body: JSON.stringify(request),
53
+ })
54
+
55
+ if (!response.ok) {
56
+ const errorText = await response.text()
57
+ const error = new Error(`HTTP ${response.status}: ${errorText || response.statusText}`)
58
+ onError?.(error)
59
+ reject(error)
60
+ return
61
+ }
62
+
63
+ const reader = response.body?.getReader()
64
+ if (!reader) {
65
+ const error = new Error('Response body is not readable')
66
+ onError?.(error)
67
+ reject(error)
68
+ return
69
+ }
70
+
71
+ const decoder = new TextDecoder()
72
+ let buffer = ''
73
+
74
+ while (true) {
75
+ const { done, value } = await reader.read()
76
+
77
+ if (done) {
78
+ resolve(fullContent)
79
+ break
80
+ }
81
+
82
+ buffer += decoder.decode(value, { stream: true })
83
+ const lines = buffer.split('\n')
84
+ buffer = lines.pop() || '' // Keep incomplete line in buffer
85
+
86
+ for (const line of lines) {
87
+ if (line.startsWith('data: ')) {
88
+ const jsonStr = line.slice(6) // Remove 'data: ' prefix
89
+ if (jsonStr.trim()) {
90
+ try {
91
+ const chunk: StreamChunk = JSON.parse(jsonStr)
92
+
93
+ if (chunk.error) {
94
+ const error = new Error(chunk.error)
95
+ onError?.(error)
96
+ reject(error)
97
+ return
98
+ }
99
+
100
+ if (chunk.done) {
101
+ resolve(fullContent)
102
+ return
103
+ }
104
+
105
+ if (chunk.content) {
106
+ fullContent += chunk.content
107
+ onChunk(chunk.content)
108
+ }
109
+ } catch (parseError) {
110
+ console.warn('Failed to parse SSE data:', jsonStr, parseError)
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ } catch (error) {
117
+ const err = error instanceof Error ? error : new Error(String(error))
118
+ onError?.(err)
119
+ reject(err)
120
+ }
121
+ })
122
+ }
123
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Request type for streaming a tech-spec
3
+ */
4
+ export interface StreamTechSpecRequest {
5
+ project_id: string
6
+ }
7
+
8
+ /**
9
+ * A single chunk from the SSE stream
10
+ */
11
+ export interface StreamChunk {
12
+ content: string
13
+ done: boolean
14
+ error?: string
15
+ }
@@ -20,6 +20,10 @@ import {
20
20
  GetTasksByProjectResponse,
21
21
  UpdateTaskRequest,
22
22
  UpdateTaskResponse,
23
+ GenerateTasksCustomBackgroundRequest,
24
+ GenerateTasksCustomBackgroundResponse,
25
+ GeneratePromptRequest,
26
+ GeneratePromptResponse,
23
27
  } from './task-types'
24
28
 
25
29
  export class TaskService extends BaseService {
@@ -84,7 +88,10 @@ export class TaskService extends BaseService {
84
88
  })
85
89
  taskGroup = updateResponse
86
90
  } catch (error) {
87
- console.warn('Failed to create codespace task, but task group was created successfully:', error)
91
+ console.warn(
92
+ 'Failed to create codespace task, but task group was created successfully:',
93
+ error
94
+ )
88
95
  // Continue without codespace task if it fails
89
96
  }
90
97
  }
@@ -93,7 +100,10 @@ export class TaskService extends BaseService {
93
100
  }
94
101
 
95
102
  async updateTaskGroup(taskGroupId: string, request: UpdateTaskGroupRequest): Promise<TaskGroup> {
96
- const response = await this.put<TaskGroupResponse>(`/project-tasks/task-groups/${taskGroupId}`, request)
103
+ const response = await this.put<TaskGroupResponse>(
104
+ `/project-tasks/task-groups/${taskGroupId}`,
105
+ request
106
+ )
97
107
  return response.data
98
108
  }
99
109
 
@@ -158,6 +168,16 @@ export class TaskService extends BaseService {
158
168
  return this.post<GenerateTasksResponse>('/project-tasks/generate-tasks', request)
159
169
  }
160
170
 
171
+ // Generate Tasks Custom (Background)
172
+ async generateTasksCustomBackground(
173
+ request: GenerateTasksCustomBackgroundRequest
174
+ ): Promise<GenerateTasksCustomBackgroundResponse> {
175
+ return this.post<GenerateTasksCustomBackgroundResponse>(
176
+ '/project-tasks/generate-tasks-custom/background',
177
+ request
178
+ )
179
+ }
180
+
161
181
  // Get Tasks by Project
162
182
  async getTasksByProject(request: GetTasksByProjectRequest): Promise<GetTasksByProjectResponse> {
163
183
  const queryParams = new URLSearchParams()
@@ -183,4 +203,12 @@ export class TaskService extends BaseService {
183
203
  const url = `/project-tasks/by-codespace/${codespaceTaskId}`
184
204
  return this.get<ProjectTaskListResponse>(url)
185
205
  }
206
+
207
+ // Generate Prompt for a Project Task
208
+ async generatePrompt(
209
+ taskId: string,
210
+ request: GeneratePromptRequest = {}
211
+ ): Promise<GeneratePromptResponse> {
212
+ return this.post<GeneratePromptResponse>(`/project-tasks/${taskId}/generate-prompt`, request)
213
+ }
186
214
  }
@@ -179,7 +179,6 @@ export interface GetTasksByProjectResponse {
179
179
  }
180
180
  }
181
181
 
182
-
183
182
  export interface UpdateTaskRequest {
184
183
  status?: string
185
184
  ai_result?: string
@@ -194,3 +193,22 @@ export interface UpdateTaskResponse {
194
193
  task: ProjectTask
195
194
  }
196
195
  }
196
+
197
+ export interface GenerateTasksCustomBackgroundRequest {
198
+ project_id: string
199
+ }
200
+
201
+ export interface GenerateTasksCustomBackgroundResponse {
202
+ status: string
203
+ job_id: string
204
+ message: string
205
+ }
206
+
207
+ export interface GeneratePromptRequest {
208
+ additional_context?: string
209
+ }
210
+
211
+ export interface GeneratePromptResponse {
212
+ status: string
213
+ prompt: string
214
+ }
@@ -21,6 +21,14 @@ import {
21
21
  UsageDetailsResponse,
22
22
  ServiceBreakdownRequest,
23
23
  ServiceBreakdownResponse,
24
+ // Activity Heatmap types
25
+ ActivityHeatmapRequest,
26
+ ActivityHeatmapResponse,
27
+ // Repository Analysis types
28
+ RepositoryAnalysisSummaryRequest,
29
+ RepositoryAnalysisSummaryResponse,
30
+ RepositoryAnalysisTimelineRequest,
31
+ RepositoryAnalysisTimelineResponse,
24
32
  } from './usage-types'
25
33
 
26
34
  export class UsageService extends BaseService {
@@ -142,4 +150,77 @@ export class UsageService extends BaseService {
142
150
  const url = `/usage/dashboard/services${queryParams.toString() ? `?${queryParams.toString()}` : ''}`
143
151
  return this.get<ServiceBreakdownResponse>(url)
144
152
  }
153
+
154
+ // Activity Heatmap Methods
155
+
156
+ /**
157
+ * Get activity heatmap data based on codespace tasks created.
158
+ * Similar to GitHub's contribution graph.
159
+ *
160
+ * @param params - Optional request parameters
161
+ * @param params.period - Time period: '3m', '6m', '1y' (default: '3m')
162
+ * @param params.start_date - Custom start date in YYYY-MM-DD format
163
+ * @param params.end_date - Custom end date in YYYY-MM-DD format
164
+ * @returns Activity heatmap data with daily counts and levels
165
+ */
166
+ async getActivityHeatmap(params?: ActivityHeatmapRequest): Promise<ActivityHeatmapResponse> {
167
+ const queryParams = new URLSearchParams()
168
+
169
+ if (params?.period) queryParams.append('period', params.period)
170
+ if (params?.start_date) queryParams.append('start_date', params.start_date)
171
+ if (params?.end_date) queryParams.append('end_date', params.end_date)
172
+
173
+ const url = `/usage/dashboard/activity-heatmap${queryParams.toString() ? `?${queryParams.toString()}` : ''}`
174
+ return this.get<ActivityHeatmapResponse>(url)
175
+ }
176
+
177
+ // Repository Analysis Stats Methods
178
+
179
+ /**
180
+ * Get summary statistics for repository analysis.
181
+ * Provides aggregated metrics across all analyzed repositories.
182
+ *
183
+ * @param params - Optional request parameters
184
+ * @param params.period - Time period: '7d', '1w', '1m', '3m', '6m', '1y' (optional - defaults to all-time)
185
+ * @param params.start_date - Custom start date in YYYY-MM-DD format
186
+ * @param params.end_date - Custom end date in YYYY-MM-DD format
187
+ * @returns Summary statistics including total repos, lines, files, etc.
188
+ */
189
+ async getRepositoryAnalysisSummary(
190
+ params?: RepositoryAnalysisSummaryRequest
191
+ ): Promise<RepositoryAnalysisSummaryResponse> {
192
+ const queryParams = new URLSearchParams()
193
+
194
+ if (params?.period) queryParams.append('period', params.period)
195
+ if (params?.start_date) queryParams.append('start_date', params.start_date)
196
+ if (params?.end_date) queryParams.append('end_date', params.end_date)
197
+
198
+ const url = `/usage/dashboard/repo-analysis/summary${queryParams.toString() ? `?${queryParams.toString()}` : ''}`
199
+ return this.get<RepositoryAnalysisSummaryResponse>(url)
200
+ }
201
+
202
+ /**
203
+ * Get timeline data for repository analysis suitable for line graphs.
204
+ * Provides time-series data for visualization.
205
+ *
206
+ * @param params - Optional request parameters
207
+ * @param params.period - Time period: '7d', '1w', '1m', '3m', '6m', '1y' (default: '1m')
208
+ * @param params.start_date - Custom start date in YYYY-MM-DD format
209
+ * @param params.end_date - Custom end date in YYYY-MM-DD format
210
+ * @param params.granularity - Data granularity: 'daily', 'weekly', 'monthly' (default: 'daily')
211
+ * @returns Timeline data with repos analyzed, lines, files per period
212
+ */
213
+ async getRepositoryAnalysisTimeline(
214
+ params?: RepositoryAnalysisTimelineRequest
215
+ ): Promise<RepositoryAnalysisTimelineResponse> {
216
+ const queryParams = new URLSearchParams()
217
+
218
+ if (params?.period) queryParams.append('period', params.period)
219
+ if (params?.start_date) queryParams.append('start_date', params.start_date)
220
+ if (params?.end_date) queryParams.append('end_date', params.end_date)
221
+ if (params?.granularity) queryParams.append('granularity', params.granularity)
222
+
223
+ const url = `/usage/dashboard/repo-analysis/timeline${queryParams.toString() ? `?${queryParams.toString()}` : ''}`
224
+ return this.get<RepositoryAnalysisTimelineResponse>(url)
225
+ }
145
226
  }
@@ -51,8 +51,8 @@ export interface CreditBalance {
51
51
  remaining_credits: number
52
52
  is_over_limit: boolean
53
53
  utilization_percentage: number
54
- billing_cycle_start: string
55
- billing_cycle_end: string
54
+ billing_cycle_start?: string
55
+ billing_cycle_end?: string
56
56
  }
57
57
 
58
58
  export interface LimitInfo {
@@ -81,14 +81,14 @@ export interface PlanLimits {
81
81
  }
82
82
 
83
83
  export interface AuthorizationSubscription {
84
- id: string
85
- status: string
86
- interval: string
87
- current_period_start: string
88
- current_period_end: string
89
- price_id: string
90
- product_name: string | null
91
- plan_name: string
84
+ id?: string
85
+ status?: string
86
+ interval?: string
87
+ current_period_start?: string
88
+ current_period_end?: string
89
+ price_id?: string
90
+ product_name?: string | null
91
+ plan_name?: string
92
92
  }
93
93
 
94
94
  export interface AuthorizationData {
@@ -103,7 +103,7 @@ export interface AuthorizationData {
103
103
  can_create_tasks: boolean
104
104
  can_analyze_repos: boolean
105
105
  can_access_previous_projects: boolean
106
- plan_limits: PlanLimits
106
+ plan_limits?: PlanLimits | null
107
107
  codespace_task_limit: LimitInfo | null
108
108
  }
109
109
 
@@ -291,34 +291,13 @@ export interface UsageSummaryRequest {
291
291
  end_date?: string
292
292
  }
293
293
 
294
- export interface CurrentPeriodUsage {
295
- credits_consumed: number
296
- cost_usd: number
297
- requests_count: number
298
- }
299
-
300
- export interface PreviousPeriodUsage {
301
- credits_consumed: number
302
- cost_usd: number
303
- requests_count: number
304
- }
305
-
306
- export interface BillingCycleInfo {
307
- total_allotted: number
308
- total_consumed: number
309
- remaining_credits: number
310
- }
311
-
312
294
  export interface UsageSummaryResponse {
313
295
  status: string
314
296
  data: {
315
- current_period: CurrentPeriodUsage
316
- previous_period: PreviousPeriodUsage
317
- billing_cycle: BillingCycleInfo
318
- utilization_percentage: number
319
- remaining_credits: number
320
- daily_average: number
321
- projected_monthly: number
297
+ period: { start?: string; end?: string }
298
+ usage: { [key: string]: number }
299
+ breakdown: { [key: string]: number }
300
+ service_breakdown: Array<{ service_type: string; [key: string]: any }>
322
301
  }
323
302
  }
324
303
 
@@ -349,3 +328,104 @@ export interface ServiceBreakdownResponse {
349
328
  status: string
350
329
  data: ServiceBreakdownData
351
330
  }
331
+
332
+ // Activity Heatmap Types (GitHub-style contribution graph)
333
+ export type HeatmapPeriodType = '3m' | '6m' | '1y'
334
+ export type ActivityLevel = 0 | 1 | 2 | 3 | 4
335
+
336
+ export interface ActivityHeatmapRequest {
337
+ period?: HeatmapPeriodType
338
+ start_date?: string
339
+ end_date?: string
340
+ }
341
+
342
+ export interface HeatmapDayData {
343
+ date: string
344
+ count: number
345
+ level: ActivityLevel
346
+ }
347
+
348
+ export interface ActivityHeatmapData {
349
+ period: PeriodInfo
350
+ days: HeatmapDayData[]
351
+ total_tasks: number
352
+ most_active_day: string | null
353
+ max_daily_count: number
354
+ average_daily: number
355
+ active_days: number
356
+ }
357
+
358
+ export interface ActivityHeatmapResponse {
359
+ status: string
360
+ data: ActivityHeatmapData
361
+ }
362
+
363
+ // Repository Analysis Summary Types
364
+ export type RepoAnalysisPeriodType = '7d' | '1w' | '1m' | '3m' | '6m' | '1y'
365
+
366
+ export interface RepositoryAnalysisSummaryRequest {
367
+ period?: RepoAnalysisPeriodType
368
+ start_date?: string
369
+ end_date?: string
370
+ }
371
+
372
+ export interface RepositoryAnalysisSummaryData {
373
+ total_repositories: number
374
+ total_lines: number
375
+ total_files_processed: number
376
+ total_files_found: number
377
+ total_directories: number
378
+ total_characters: number
379
+ estimated_tokens_total: number
380
+ total_size_bytes: number
381
+ binary_files_skipped: number
382
+ large_files_skipped: number
383
+ encoding_errors: number
384
+ average_lines_per_repo: number
385
+ average_files_per_repo: number
386
+ period: PeriodInfo | null
387
+ }
388
+
389
+ export interface RepositoryAnalysisSummaryResponse {
390
+ status: string
391
+ data: RepositoryAnalysisSummaryData
392
+ }
393
+
394
+ // Repository Analysis Timeline Types
395
+ export type TimelineGranularity = 'daily' | 'weekly' | 'monthly'
396
+
397
+ export interface RepositoryAnalysisTimelineRequest {
398
+ period?: RepoAnalysisPeriodType
399
+ start_date?: string
400
+ end_date?: string
401
+ granularity?: TimelineGranularity
402
+ }
403
+
404
+ export interface RepositoryAnalysisTimelineItem {
405
+ date: string
406
+ repos_analyzed: number
407
+ total_lines: number
408
+ total_files: number
409
+ total_characters: number
410
+ estimated_tokens: number
411
+ }
412
+
413
+ export interface RepositoryAnalysisTimelineTotals {
414
+ repos_analyzed: number
415
+ total_lines: number
416
+ total_files: number
417
+ total_characters: number
418
+ estimated_tokens: number
419
+ }
420
+
421
+ export interface RepositoryAnalysisTimelineData {
422
+ period: PeriodInfo
423
+ granularity: TimelineGranularity
424
+ timeline: RepositoryAnalysisTimelineItem[]
425
+ totals: RepositoryAnalysisTimelineTotals
426
+ }
427
+
428
+ export interface RepositoryAnalysisTimelineResponse {
429
+ status: string
430
+ data: RepositoryAnalysisTimelineData
431
+ }