@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.
Files changed (85) hide show
  1. package/__tests__/services/codespace/codespace-v2.test.ts +53 -0
  2. package/__tests__/services/usage/usage-service.test.ts +458 -104
  3. package/codeguide.ts +3 -0
  4. package/dist/codeguide.d.ts +2 -1
  5. package/dist/codeguide.js +1 -0
  6. package/dist/index.d.ts +4 -3
  7. package/dist/services/base/base-service.d.ts +21 -0
  8. package/dist/services/base/base-service.js +114 -0
  9. package/dist/services/codespace/codespace-service.d.ts +64 -1
  10. package/dist/services/codespace/codespace-service.js +272 -0
  11. package/dist/services/codespace/codespace-types.d.ts +213 -12
  12. package/dist/services/codespace/index.d.ts +1 -1
  13. package/dist/services/index.d.ts +2 -0
  14. package/dist/services/index.js +4 -1
  15. package/dist/services/projects/project-types.d.ts +66 -32
  16. package/dist/services/starter-kits/index.d.ts +2 -0
  17. package/dist/services/starter-kits/index.js +20 -0
  18. package/dist/services/starter-kits/starter-kits-service.d.ts +13 -0
  19. package/dist/services/starter-kits/starter-kits-service.js +27 -0
  20. package/dist/services/starter-kits/starter-kits-types.d.ts +34 -0
  21. package/dist/services/starter-kits/starter-kits-types.js +2 -0
  22. package/dist/services/subscriptions/subscription-service.d.ts +11 -1
  23. package/dist/services/subscriptions/subscription-service.js +14 -0
  24. package/dist/services/tasks/task-service.d.ts +2 -1
  25. package/dist/services/tasks/task-service.js +8 -0
  26. package/dist/services/tasks/task-types.d.ts +26 -7
  27. package/dist/services/usage/usage-service.d.ts +5 -2
  28. package/dist/services/usage/usage-service.js +58 -9
  29. package/dist/services/usage/usage-types.d.ts +157 -34
  30. package/dist/types.d.ts +18 -2
  31. package/docs/.vitepress/README.md +51 -0
  32. package/docs/.vitepress/config.ts +139 -0
  33. package/docs/.vitepress/theme/custom.css +80 -0
  34. package/docs/.vitepress/theme/index.ts +13 -0
  35. package/docs/.vitepress/tsconfig.json +19 -0
  36. package/docs/QUICKSTART.md +77 -0
  37. package/docs/README.md +134 -0
  38. package/docs/README_SETUP.md +46 -0
  39. package/docs/authentication.md +351 -0
  40. package/docs/codeguide-client.md +350 -0
  41. package/docs/codespace-models.md +1004 -0
  42. package/docs/codespace-service.md +444 -0
  43. package/docs/index.md +135 -0
  44. package/docs/package.json +14 -0
  45. package/docs/projects-service.md +688 -0
  46. package/docs/security-keys-service.md +773 -0
  47. package/docs/starter-kits-service.md +249 -0
  48. package/docs/task-service.md +955 -0
  49. package/docs/testsprite_tests/TC001_Homepage_Load_and_Hero_Section_Display.py +70 -0
  50. package/docs/testsprite_tests/TC002_Sidebar_Navigation_ExpandCollapse_Functionality.py +73 -0
  51. package/docs/testsprite_tests/TC003_Full_Text_Local_Search_with_Keyboard_Shortcut.py +90 -0
  52. package/docs/testsprite_tests/TC004_Dark_Mode_Toggle_and_Persistence.py +73 -0
  53. package/docs/testsprite_tests/TC005_Mobile_Responsiveness_and_Touch_Navigation.py +113 -0
  54. package/docs/testsprite_tests/TC006_GitHub_Integration_Edit_this_page_Links.py +73 -0
  55. package/docs/testsprite_tests/TC007_Syntax_Highlighting_and_Code_Copy_Functionality.py +73 -0
  56. package/docs/testsprite_tests/TC008_Auto_Generated_Table_of_Contents_Accuracy.py +73 -0
  57. package/docs/testsprite_tests/TC009_SEO_and_Content_Discoverability_Verification.py +73 -0
  58. package/docs/testsprite_tests/TC010_Accessibility_Compliance_WCAG_AA.py +73 -0
  59. package/docs/testsprite_tests/TC011_Local_Development_Workflow_Build_and_Hot_Reload.py +74 -0
  60. package/docs/testsprite_tests/TC012_Performance_Metrics_Compliance.py +73 -0
  61. package/docs/testsprite_tests/standard_prd.json +122 -0
  62. package/docs/testsprite_tests/testsprite-mcp-test-report.html +2508 -0
  63. package/docs/testsprite_tests/testsprite-mcp-test-report.md +273 -0
  64. package/docs/testsprite_tests/testsprite_frontend_test_plan.json +390 -0
  65. package/docs/usage-service.md +291 -1
  66. package/index.ts +11 -3
  67. package/package.json +17 -2
  68. package/plans/CODESPACE_LOGS_STREAMING_GUIDE.md +320 -0
  69. package/plans/CODESPACE_TASK_LOGS_API_COMPLETE_GUIDE.md +821 -0
  70. package/services/base/base-service.ts +130 -0
  71. package/services/codespace/codespace-service.ts +359 -0
  72. package/services/codespace/codespace-types.ts +295 -13
  73. package/services/codespace/index.ts +21 -1
  74. package/services/index.ts +2 -0
  75. package/services/projects/README.md +107 -34
  76. package/services/projects/project-types.ts +69 -32
  77. package/services/starter-kits/index.ts +2 -0
  78. package/services/starter-kits/starter-kits-service.ts +33 -0
  79. package/services/starter-kits/starter-kits-types.ts +38 -0
  80. package/services/subscriptions/subscription-service.ts +23 -5
  81. package/services/tasks/task-service.ts +10 -0
  82. package/services/tasks/task-types.ts +29 -7
  83. package/services/usage/usage-service.ts +59 -10
  84. package/services/usage/usage-types.ts +186 -36
  85. package/types.ts +22 -2
package/codeguide.ts CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  ExternalTokenService,
20
20
  SecurityKeysService,
21
21
  UserService,
22
+ StarterKitsService,
22
23
  } from './services'
23
24
  import { APIServiceConfig, CodeGuideOptions } from './types'
24
25
 
@@ -35,6 +36,7 @@ export class CodeGuide {
35
36
  public externalTokens: ExternalTokenService
36
37
  public securityKeys: SecurityKeysService
37
38
  public users: UserService
39
+ public starterKits: StarterKitsService
38
40
  private options: CodeGuideOptions
39
41
 
40
42
  constructor(config: APIServiceConfig, options: CodeGuideOptions = {}) {
@@ -53,6 +55,7 @@ export class CodeGuide {
53
55
  this.externalTokens = new ExternalTokenService(config)
54
56
  this.securityKeys = new SecurityKeysService(config)
55
57
  this.users = new UserService(config)
58
+ this.starterKits = new StarterKitsService(config)
56
59
  }
57
60
 
58
61
  // Convenience method for backward compatibility
@@ -1,4 +1,4 @@
1
- import { GenerationService, ProjectService, UsageService, RepositoryAnalysisService, TaskService, ApiKeyEnhancedService, SubscriptionService, CancellationFunnelService, CodespaceService, ExternalTokenService, SecurityKeysService, UserService } from './services';
1
+ import { GenerationService, ProjectService, UsageService, RepositoryAnalysisService, TaskService, ApiKeyEnhancedService, SubscriptionService, CancellationFunnelService, CodespaceService, ExternalTokenService, SecurityKeysService, UserService, StarterKitsService } from './services';
2
2
  import { APIServiceConfig, CodeGuideOptions } from './types';
3
3
  export declare class CodeGuide {
4
4
  generation: GenerationService;
@@ -13,6 +13,7 @@ export declare class CodeGuide {
13
13
  externalTokens: ExternalTokenService;
14
14
  securityKeys: SecurityKeysService;
15
15
  users: UserService;
16
+ starterKits: StarterKitsService;
16
17
  private options;
17
18
  constructor(config: APIServiceConfig, options?: CodeGuideOptions);
18
19
  getGuidance(prompt: string): Promise<any>;
package/dist/codeguide.js CHANGED
@@ -28,6 +28,7 @@ class CodeGuide {
28
28
  this.externalTokens = new services_1.ExternalTokenService(config);
29
29
  this.securityKeys = new services_1.SecurityKeysService(config);
30
30
  this.users = new services_1.UserService(config);
31
+ this.starterKits = new services_1.StarterKitsService(config);
31
32
  }
32
33
  // Convenience method for backward compatibility
33
34
  async getGuidance(prompt) {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { CodeGuide } from './codeguide';
2
2
  export * from './services';
3
3
  export * from './types';
4
- export type { ConnectRepositoryRequest, ConnectRepositoryResponse, ProjectRepository, GetProjectsRequest, PaginatedProjectsRequest, PaginatedProjectsResponse } from './services/projects/project-types';
5
- export type { CreateCodespaceTaskRequestV2 as CreateCodespaceTaskRequest, CreateCodespaceTaskResponseV2 as CreateCodespaceTaskResponse, CreateBackgroundCodespaceTaskRequest, CreateBackgroundCodespaceTaskResponse, ModelApiKey, Attachment, GetCodespaceTaskResponse, CodespaceTaskData, TechnicalDocument, GetProjectTasksByCodespaceResponse } from './services/codespace/codespace-types';
6
- export type { StoreExternalTokenRequest, StoreExternalTokenResponse, ListTokensQuery, ListTokensResponse, ValidateTokenRequest, ValidateTokenResponse, FindBestMatchRequest, FindBestMatchResponse, Platform, TokenType } from './services/external-tokens/external-tokens-types';
4
+ export type { ConnectRepositoryRequest, ConnectRepositoryResponse, ProjectRepository, GetProjectsRequest, PaginatedProjectsRequest, PaginatedProjectsResponse, } from './services/projects/project-types';
5
+ export type { CreateCodespaceTaskRequestV2 as CreateCodespaceTaskRequest, CreateCodespaceTaskResponseV2 as CreateCodespaceTaskResponse, CreateBackgroundCodespaceTaskRequest, CreateBackgroundCodespaceTaskResponse, ModelApiKey, Attachment, GetCodespaceTaskResponse, CodespaceTaskData, TechnicalDocument, GetProjectTasksByCodespaceResponse, } from './services/codespace/codespace-types';
6
+ export type { StoreExternalTokenRequest, StoreExternalTokenResponse, ListTokensQuery, ListTokensResponse, ValidateTokenRequest, ValidateTokenResponse, FindBestMatchRequest, FindBestMatchResponse, Platform, TokenType, } from './services/external-tokens/external-tokens-types';
7
+ export type { StarterKit, StarterKitMetadata, GetStarterKitsRequest, GetStarterKitsResponse, } from './services/starter-kits/starter-kits-types';
@@ -25,6 +25,27 @@ export declare abstract class BaseService {
25
25
  private formatErrorMessage;
26
26
  protected post<T>(url: string, data?: any, config?: any): Promise<T>;
27
27
  protected put<T>(url: string, data?: any, config?: any): Promise<T>;
28
+ protected patch<T>(url: string, data?: any, config?: any): Promise<T>;
28
29
  protected delete<T>(url: string, config?: any): Promise<T>;
29
30
  protected buildUrl(endpoint: string): string;
31
+ /**
32
+ * Create a streaming connection for Server-Sent Events (SSE)
33
+ *
34
+ * @param url - The endpoint URL for streaming
35
+ * @param config - Optional configuration for the stream request
36
+ * @returns Promise that resolves to EventSource for SSE streaming
37
+ */
38
+ protected createStream(url: string, config?: any): Promise<EventSource>;
39
+ /**
40
+ * Alternative streaming method using fetch for environments where EventSource is not available
41
+ * or when custom headers are needed for authentication
42
+ *
43
+ * @param url - The endpoint URL for streaming
44
+ * @param onMessage - Callback function for handling stream messages
45
+ * @param onError - Callback function for handling stream errors
46
+ * @param onComplete - Callback function for when stream completes
47
+ * @param config - Optional configuration for the stream request
48
+ * @returns Promise that resolves to a cleanup function
49
+ */
50
+ protected createStreamWithFetch(url: string, onMessage: (data: any) => void, onError?: (error: any) => void, onComplete?: () => void, config?: any): Promise<() => void>;
30
51
  }
@@ -192,6 +192,10 @@ class BaseService {
192
192
  const response = await this.client.put(url, data, config);
193
193
  return response.data;
194
194
  }
195
+ async patch(url, data, config) {
196
+ const response = await this.client.patch(url, data, config);
197
+ return response.data;
198
+ }
195
199
  async delete(url, config) {
196
200
  const response = await this.client.delete(url, config);
197
201
  return response.data;
@@ -199,5 +203,115 @@ class BaseService {
199
203
  buildUrl(endpoint) {
200
204
  return endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
201
205
  }
206
+ /**
207
+ * Create a streaming connection for Server-Sent Events (SSE)
208
+ *
209
+ * @param url - The endpoint URL for streaming
210
+ * @param config - Optional configuration for the stream request
211
+ * @returns Promise that resolves to EventSource for SSE streaming
212
+ */
213
+ async createStream(url, config) {
214
+ // Build full URL
215
+ const fullUrl = `${this.client.defaults.baseURL}${this.buildUrl(url)}`;
216
+ // For SSE, we need to use EventSource API directly
217
+ // However, we need to handle authentication differently since EventSource doesn't support custom headers
218
+ // We'll pass auth info as query parameters for SSE endpoints
219
+ return new Promise((resolve, reject) => {
220
+ try {
221
+ const eventSource = new EventSource(fullUrl);
222
+ resolve(eventSource);
223
+ }
224
+ catch (error) {
225
+ reject(error);
226
+ }
227
+ });
228
+ }
229
+ /**
230
+ * Alternative streaming method using fetch for environments where EventSource is not available
231
+ * or when custom headers are needed for authentication
232
+ *
233
+ * @param url - The endpoint URL for streaming
234
+ * @param onMessage - Callback function for handling stream messages
235
+ * @param onError - Callback function for handling stream errors
236
+ * @param onComplete - Callback function for when stream completes
237
+ * @param config - Optional configuration for the stream request
238
+ * @returns Promise that resolves to a cleanup function
239
+ */
240
+ async createStreamWithFetch(url, onMessage, onError, onComplete, config) {
241
+ const streamConfig = {
242
+ ...config,
243
+ headers: {
244
+ ...this.client.defaults.headers,
245
+ 'Accept': 'text/event-stream',
246
+ 'Cache-Control': 'no-cache',
247
+ ...config?.headers,
248
+ },
249
+ };
250
+ const fullUrl = `${this.client.defaults.baseURL}${this.buildUrl(url)}`;
251
+ try {
252
+ const response = await fetch(fullUrl, streamConfig);
253
+ if (!response.ok) {
254
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
255
+ }
256
+ const reader = response.body?.getReader();
257
+ if (!reader) {
258
+ throw new Error('Response body is not readable');
259
+ }
260
+ const decoder = new TextDecoder();
261
+ let buffer = '';
262
+ const processStream = async () => {
263
+ try {
264
+ while (true) {
265
+ const { done, value } = await reader.read();
266
+ if (done) {
267
+ onComplete?.();
268
+ break;
269
+ }
270
+ buffer += decoder.decode(value, { stream: true });
271
+ const lines = buffer.split('\n');
272
+ buffer = lines.pop() || ''; // Keep incomplete line in buffer
273
+ for (const line of lines) {
274
+ if (line.startsWith('data: ')) {
275
+ const data = line.slice(6); // Remove 'data: ' prefix
276
+ if (data.trim()) {
277
+ try {
278
+ const parsedData = JSON.parse(data);
279
+ onMessage(parsedData);
280
+ }
281
+ catch (parseError) {
282
+ console.warn('Failed to parse SSE data:', data, parseError);
283
+ }
284
+ }
285
+ }
286
+ else if (line.startsWith('event: ')) {
287
+ const eventType = line.slice(7); // Remove 'event: ' prefix
288
+ // Handle different event types if needed
289
+ if (eventType === 'complete') {
290
+ onComplete?.();
291
+ return;
292
+ }
293
+ else if (eventType === 'error') {
294
+ onError?.(new Error('Stream error event received'));
295
+ return;
296
+ }
297
+ }
298
+ }
299
+ }
300
+ }
301
+ catch (error) {
302
+ onError?.(error);
303
+ }
304
+ };
305
+ processStream();
306
+ // Return cleanup function
307
+ return () => {
308
+ reader.cancel().catch(console.warn);
309
+ };
310
+ }
311
+ catch (error) {
312
+ onError?.(error);
313
+ return () => { }; // Return empty cleanup function on error
314
+ }
315
+ }
202
316
  }
203
317
  exports.BaseService = BaseService;
@@ -1,5 +1,5 @@
1
1
  import { BaseService } from '../base/base-service';
2
- import { GenerateTaskTitleRequest, GenerateTaskTitleResponse, CreateCodespaceTaskRequest, CreateCodespaceTaskResponse, CreateCodespaceTaskRequestV2, CreateCodespaceTaskResponseV2, CreateBackgroundCodespaceTaskRequest, CreateBackgroundCodespaceTaskResponse, GetCodespaceTaskResponse, GetProjectTasksByCodespaceResponse, GetCodespaceTasksByProjectRequest, GetCodespaceTasksByProjectResponse, CodespaceTaskDetailedResponse, CodespaceQuestionnaireRequest, CodespaceQuestionnaireResponse, GetCodespaceModelsQuery, GetCodespaceModelsResponse, GetCodespaceModelResponse, GetLLMModelProvidersResponse, GetLLMModelProviderResponse, GetModelsByProviderResponse } from './codespace-types';
2
+ import { GenerateTaskTitleRequest, GenerateTaskTitleResponse, CreateCodespaceTaskRequest, CreateCodespaceTaskResponse, CreateCodespaceTaskRequestV2, CreateCodespaceTaskResponseV2, CreateBackgroundCodespaceTaskRequest, CreateBackgroundCodespaceTaskResponse, GetCodespaceTaskResponse, GetProjectTasksByCodespaceResponse, GetCodespaceTasksByProjectRequest, GetCodespaceTasksByProjectResponse, CodespaceTaskDetailedResponse, CodespaceQuestionnaireRequest, CodespaceQuestionnaireResponse, GetCodespaceModelsQuery, GetCodespaceModelsResponse, GetCodespaceModelResponse, GetLLMModelProvidersResponse, GetLLMModelProviderResponse, GetModelsByProviderResponse, GetCodespaceTasksRequest, GetCodespaceTasksResponse, GetTasksByCodespaceIdRequest, GetTasksByCodespaceIdResponse, UpdateFinalReportPopupStateRequest, UpdateFinalReportPopupStateResponse, GetCodespaceTaskLogsRequest, CodespaceTaskLogsResponse, StreamCodespaceTaskLogsRequest, CodespaceLogStreamEvent, GetCodespaceProjectSummaryRequest, GetCodespaceProjectSummaryResponse } from './codespace-types';
3
3
  export declare class CodespaceService extends BaseService {
4
4
  generateTaskTitle(request: GenerateTaskTitleRequest): Promise<GenerateTaskTitleResponse>;
5
5
  generateQuestionnaire(request: CodespaceQuestionnaireRequest): Promise<CodespaceQuestionnaireResponse>;
@@ -9,7 +9,67 @@ export declare class CodespaceService extends BaseService {
9
9
  getCodespaceTask(codespaceTaskId: string): Promise<GetCodespaceTaskResponse>;
10
10
  getProjectTasksByCodespace(codespaceTaskId: string): Promise<GetProjectTasksByCodespaceResponse>;
11
11
  getCodespaceTasksByProject(params: GetCodespaceTasksByProjectRequest): Promise<GetCodespaceTasksByProjectResponse>;
12
+ /**
13
+ * Get aggregated statistics for all codespace tasks within a project
14
+ *
15
+ * GET /codespace/project/{project_id}/summary
16
+ *
17
+ * @param params - Request parameters including project_id
18
+ * @returns Promise resolving to aggregated task statistics by status
19
+ */
20
+ getCodespaceProjectSummary(params: GetCodespaceProjectSummaryRequest): Promise<GetCodespaceProjectSummaryResponse>;
12
21
  getCodespaceTaskDetailed(codespaceTaskId: string): Promise<CodespaceTaskDetailedResponse>;
22
+ /**
23
+ * Get tasks by codespace task ID with optional pagination and sorting
24
+ *
25
+ * GET /tasks/by-codespace-id/{codespace_task_id}
26
+ *
27
+ * @param params - Request parameters including codespace_task_id and optional pagination/sorting
28
+ * @returns Promise resolving to paginated list of tasks associated with the codespace task ID
29
+ */
30
+ getTasksByCodespaceId(params: GetTasksByCodespaceIdRequest): Promise<GetTasksByCodespaceIdResponse>;
31
+ /**
32
+ * Get codespace tasks with optional filtering and pagination
33
+ *
34
+ * GET /codespace/tasks
35
+ *
36
+ * @param params - Optional query parameters for filtering, sorting, and pagination
37
+ * @returns Promise resolving to paginated list of codespace tasks with model and attachment info
38
+ */
39
+ getCodespaceTasks(params?: GetCodespaceTasksRequest): Promise<GetCodespaceTasksResponse>;
40
+ /**
41
+ * Update the final report popup state for a codespace task
42
+ *
43
+ * PATCH /codespace/task/{codespace_task_id}/final-report-popup-state
44
+ *
45
+ * @param codespaceTaskId - The ID of the codespace task
46
+ * @param request - The request body containing the new popup state
47
+ * @returns Promise resolving to the updated popup state response
48
+ */
49
+ updateFinalReportPopupState(codespaceTaskId: string, request: UpdateFinalReportPopupStateRequest): Promise<UpdateFinalReportPopupStateResponse>;
50
+ /**
51
+ * Get paginated logs for a codespace task with optional filtering and sorting
52
+ *
53
+ * GET /codespace/task/{codespace_task_id}/logs
54
+ *
55
+ * @param request - Request parameters including codespace_task_id and optional filters
56
+ * @returns Promise resolving to paginated logs response
57
+ */
58
+ getCodespaceTaskLogs(request: GetCodespaceTaskLogsRequest): Promise<CodespaceTaskLogsResponse>;
59
+ /**
60
+ * Stream real-time logs from a codespace task using Server-Sent Events (SSE)
61
+ *
62
+ * GET /codespace/task/{codespace_task_id}/logs/stream
63
+ *
64
+ * @param request - Request parameters including codespace_task_id and optional streaming parameters
65
+ * @param onLog - Callback function for handling log events
66
+ * @param onHeartbeat - Callback function for handling heartbeat events
67
+ * @param onComplete - Callback function for handling completion events
68
+ * @param onError - Callback function for handling error events
69
+ * @param onTimeout - Callback function for handling timeout events
70
+ * @returns Promise resolving to a cleanup function to stop streaming
71
+ */
72
+ streamCodespaceTaskLogs(request: StreamCodespaceTaskLogsRequest, onLog: (log: CodespaceLogStreamEvent) => void, onHeartbeat?: (data: any) => void, onComplete?: (data: any) => void, onError?: (error: any) => void, onTimeout?: (data: any) => void): Promise<() => void>;
13
73
  /**
14
74
  * Get all codespace models with optional filtering
15
75
  *
@@ -63,4 +123,7 @@ export declare class CodespaceService extends BaseService {
63
123
  private buildQueryParams;
64
124
  private validateCodespaceTaskRequest;
65
125
  private validateQuestionnaireRequest;
126
+ private validateGetLogsRequest;
127
+ private validateStreamLogsRequest;
128
+ private validateGetTasksByCodespaceIdRequest;
66
129
  }
@@ -51,12 +51,188 @@ class CodespaceService extends base_service_1.BaseService {
51
51
  const url = `/codespace/tasks/project/${params.project_id}${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
52
52
  return this.get(url);
53
53
  }
54
+ /**
55
+ * Get aggregated statistics for all codespace tasks within a project
56
+ *
57
+ * GET /codespace/project/{project_id}/summary
58
+ *
59
+ * @param params - Request parameters including project_id
60
+ * @returns Promise resolving to aggregated task statistics by status
61
+ */
62
+ async getCodespaceProjectSummary(params) {
63
+ if (!params.project_id) {
64
+ throw new Error('project_id is required');
65
+ }
66
+ const url = `/codespace/project/${params.project_id}/summary`;
67
+ return this.get(url);
68
+ }
54
69
  async getCodespaceTaskDetailed(codespaceTaskId) {
55
70
  if (!codespaceTaskId) {
56
71
  throw new Error('codespace_task_id is required');
57
72
  }
58
73
  return this.get(`/codespace/task/${codespaceTaskId}/detailed`);
59
74
  }
75
+ /**
76
+ * Get tasks by codespace task ID with optional pagination and sorting
77
+ *
78
+ * GET /tasks/by-codespace-id/{codespace_task_id}
79
+ *
80
+ * @param params - Request parameters including codespace_task_id and optional pagination/sorting
81
+ * @returns Promise resolving to paginated list of tasks associated with the codespace task ID
82
+ */
83
+ async getTasksByCodespaceId(params) {
84
+ this.validateGetTasksByCodespaceIdRequest(params);
85
+ const queryParams = new URLSearchParams();
86
+ // Add pagination parameters
87
+ if (params.limit !== undefined) {
88
+ queryParams.append('limit', params.limit.toString());
89
+ }
90
+ if (params.offset !== undefined) {
91
+ queryParams.append('offset', params.offset.toString());
92
+ }
93
+ // Add sorting parameters
94
+ if (params.sort_by) {
95
+ queryParams.append('sort_by', params.sort_by);
96
+ }
97
+ if (params.sort_order) {
98
+ queryParams.append('sort_order', params.sort_order);
99
+ }
100
+ const url = `/codespace/tasks/by-codespace-id/${params.codespace_task_id}${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
101
+ return this.get(url);
102
+ }
103
+ /**
104
+ * Get codespace tasks with optional filtering and pagination
105
+ *
106
+ * GET /codespace/tasks
107
+ *
108
+ * @param params - Optional query parameters for filtering, sorting, and pagination
109
+ * @returns Promise resolving to paginated list of codespace tasks with model and attachment info
110
+ */
111
+ async getCodespaceTasks(params) {
112
+ const queryParams = new URLSearchParams();
113
+ if (params?.task_status)
114
+ queryParams.append('task_status', params.task_status);
115
+ if (params?.project_id)
116
+ queryParams.append('project_id', params.project_id);
117
+ if (params?.limit !== undefined) {
118
+ // Validate limit is between 1 and 100
119
+ if (params.limit < 1 || params.limit > 100) {
120
+ throw new Error('limit must be between 1 and 100');
121
+ }
122
+ queryParams.append('limit', params.limit.toString());
123
+ }
124
+ if (params?.offset !== undefined) {
125
+ // Validate offset is non-negative
126
+ if (params.offset < 0) {
127
+ throw new Error('offset must be 0 or greater');
128
+ }
129
+ queryParams.append('offset', params.offset.toString());
130
+ }
131
+ if (params?.sort_by)
132
+ queryParams.append('sort_by', params.sort_by);
133
+ if (params?.sort_order)
134
+ queryParams.append('sort_order', params.sort_order);
135
+ const url = `/codespace/tasks${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
136
+ return this.get(url);
137
+ }
138
+ // ============================================================================
139
+ // Task Status Update Methods
140
+ // ============================================================================
141
+ /**
142
+ * Update the final report popup state for a codespace task
143
+ *
144
+ * PATCH /codespace/task/{codespace_task_id}/final-report-popup-state
145
+ *
146
+ * @param codespaceTaskId - The ID of the codespace task
147
+ * @param request - The request body containing the new popup state
148
+ * @returns Promise resolving to the updated popup state response
149
+ */
150
+ async updateFinalReportPopupState(codespaceTaskId, request) {
151
+ if (!codespaceTaskId) {
152
+ throw new Error('codespace_task_id is required');
153
+ }
154
+ // Validate the popup state value
155
+ if (!['not_ready', 'open', 'closed'].includes(request.final_report_popup_state)) {
156
+ throw new Error('final_report_popup_state must be "not_ready", "open", or "closed"');
157
+ }
158
+ return this.patch(`/codespace/task/${codespaceTaskId}/final-report-popup-state`, request);
159
+ }
160
+ // ============================================================================
161
+ // Codespace Task Logs Methods
162
+ // ============================================================================
163
+ /**
164
+ * Get paginated logs for a codespace task with optional filtering and sorting
165
+ *
166
+ * GET /codespace/task/{codespace_task_id}/logs
167
+ *
168
+ * @param request - Request parameters including codespace_task_id and optional filters
169
+ * @returns Promise resolving to paginated logs response
170
+ */
171
+ async getCodespaceTaskLogs(request) {
172
+ this.validateGetLogsRequest(request);
173
+ const queryParams = new URLSearchParams();
174
+ // Add pagination parameters
175
+ if (request.limit !== undefined) {
176
+ queryParams.append('limit', request.limit.toString());
177
+ }
178
+ if (request.offset !== undefined) {
179
+ queryParams.append('offset', request.offset.toString());
180
+ }
181
+ // Add filter parameters
182
+ if (request.log_type) {
183
+ queryParams.append('log_type', request.log_type);
184
+ }
185
+ if (request.step_name) {
186
+ queryParams.append('step_name', request.step_name);
187
+ }
188
+ if (request.search) {
189
+ queryParams.append('search', request.search);
190
+ }
191
+ if (request.since) {
192
+ queryParams.append('since', request.since);
193
+ }
194
+ // Add sorting parameters
195
+ if (request.sort_by) {
196
+ queryParams.append('sort_by', request.sort_by);
197
+ }
198
+ if (request.sort_order) {
199
+ queryParams.append('sort_order', request.sort_order);
200
+ }
201
+ const url = `/codespace/task/${request.codespace_task_id}/logs${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
202
+ return this.get(url);
203
+ }
204
+ /**
205
+ * Stream real-time logs from a codespace task using Server-Sent Events (SSE)
206
+ *
207
+ * GET /codespace/task/{codespace_task_id}/logs/stream
208
+ *
209
+ * @param request - Request parameters including codespace_task_id and optional streaming parameters
210
+ * @param onLog - Callback function for handling log events
211
+ * @param onHeartbeat - Callback function for handling heartbeat events
212
+ * @param onComplete - Callback function for handling completion events
213
+ * @param onError - Callback function for handling error events
214
+ * @param onTimeout - Callback function for handling timeout events
215
+ * @returns Promise resolving to a cleanup function to stop streaming
216
+ */
217
+ async streamCodespaceTaskLogs(request, onLog, onHeartbeat, onComplete, onError, onTimeout) {
218
+ this.validateStreamLogsRequest(request);
219
+ const queryParams = new URLSearchParams();
220
+ // Add streaming parameters
221
+ if (request.since) {
222
+ queryParams.append('since', request.since);
223
+ }
224
+ if (request.timeout !== undefined) {
225
+ queryParams.append('timeout', request.timeout.toString());
226
+ }
227
+ const url = `/codespace/task/${request.codespace_task_id}/logs/stream${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
228
+ // Use the fetch-based streaming method since it supports custom headers for authentication
229
+ return this.createStreamWithFetch(url, data => {
230
+ // Handle different types of events based on the context
231
+ // The server will send different event types through the same data channel
232
+ onLog(data);
233
+ }, onError, () => onComplete?.({}) // Call onComplete with empty data when stream completes
234
+ );
235
+ }
60
236
  // ============================================================================
61
237
  // Codespace Models Methods
62
238
  // ============================================================================
@@ -217,5 +393,101 @@ class CodespaceService extends base_service_1.BaseService {
217
393
  }
218
394
  }
219
395
  }
396
+ validateGetLogsRequest(request) {
397
+ if (!request.codespace_task_id) {
398
+ throw new Error('codespace_task_id is required');
399
+ }
400
+ // Validate limit
401
+ if (request.limit !== undefined) {
402
+ if (!Number.isInteger(request.limit)) {
403
+ throw new Error('limit must be an integer');
404
+ }
405
+ if (request.limit < 1 || request.limit > 500) {
406
+ throw new Error('limit must be between 1 and 500');
407
+ }
408
+ }
409
+ // Validate offset
410
+ if (request.offset !== undefined) {
411
+ if (!Number.isInteger(request.offset)) {
412
+ throw new Error('offset must be an integer');
413
+ }
414
+ if (request.offset < 0) {
415
+ throw new Error('offset must be 0 or greater');
416
+ }
417
+ }
418
+ // Validate sort_by
419
+ if (request.sort_by && !['created_at', 'step_name', 'log_type'].includes(request.sort_by)) {
420
+ throw new Error('sort_by must be one of: created_at, step_name, log_type');
421
+ }
422
+ // Validate sort_order
423
+ if (request.sort_order && !['asc', 'desc'].includes(request.sort_order)) {
424
+ throw new Error('sort_order must be either "asc" or "desc"');
425
+ }
426
+ // Validate log_type
427
+ const validLogTypes = ['thinking', 'coding', 'info', 'error', 'success'];
428
+ if (request.log_type && !validLogTypes.includes(request.log_type)) {
429
+ throw new Error(`log_type must be one of: ${validLogTypes.join(', ')}`);
430
+ }
431
+ // Validate since timestamp format (basic ISO format check)
432
+ if (request.since) {
433
+ const sinceDate = new Date(request.since);
434
+ if (isNaN(sinceDate.getTime())) {
435
+ throw new Error('since must be a valid ISO timestamp');
436
+ }
437
+ }
438
+ }
439
+ validateStreamLogsRequest(request) {
440
+ if (!request.codespace_task_id) {
441
+ throw new Error('codespace_task_id is required');
442
+ }
443
+ // Validate timeout
444
+ if (request.timeout !== undefined) {
445
+ if (!Number.isInteger(request.timeout)) {
446
+ throw new Error('timeout must be an integer');
447
+ }
448
+ if (request.timeout < 30 || request.timeout > 1800) {
449
+ throw new Error('timeout must be between 30 and 1800 seconds');
450
+ }
451
+ }
452
+ // Validate since timestamp format (basic ISO format check)
453
+ if (request.since) {
454
+ const sinceDate = new Date(request.since);
455
+ if (isNaN(sinceDate.getTime())) {
456
+ throw new Error('since must be a valid ISO timestamp');
457
+ }
458
+ }
459
+ }
460
+ validateGetTasksByCodespaceIdRequest(request) {
461
+ if (!request.codespace_task_id) {
462
+ throw new Error('codespace_task_id is required');
463
+ }
464
+ // Validate limit
465
+ if (request.limit !== undefined) {
466
+ if (!Number.isInteger(request.limit)) {
467
+ throw new Error('limit must be an integer');
468
+ }
469
+ if (request.limit < 1 || request.limit > 100) {
470
+ throw new Error('limit must be between 1 and 100');
471
+ }
472
+ }
473
+ // Validate offset
474
+ if (request.offset !== undefined) {
475
+ if (!Number.isInteger(request.offset)) {
476
+ throw new Error('offset must be an integer');
477
+ }
478
+ if (request.offset < 0) {
479
+ throw new Error('offset must be 0 or greater');
480
+ }
481
+ }
482
+ // Validate sort_by
483
+ if (request.sort_by &&
484
+ !['created_at', 'updated_at', 'status', 'title'].includes(request.sort_by)) {
485
+ throw new Error('sort_by must be one of: created_at, updated_at, status, title');
486
+ }
487
+ // Validate sort_order
488
+ if (request.sort_order && !['asc', 'desc'].includes(request.sort_order)) {
489
+ throw new Error('sort_order must be either "asc" or "desc"');
490
+ }
491
+ }
220
492
  }
221
493
  exports.CodespaceService = CodespaceService;