projects-plus-sdk 0.1.0

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.
@@ -0,0 +1,674 @@
1
+ interface HttpClientConfig {
2
+ apiKey: string;
3
+ baseUrl: string;
4
+ timeout: number;
5
+ retries: number;
6
+ retryDelay: number;
7
+ }
8
+ interface RequestOptions {
9
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
10
+ body?: unknown;
11
+ params?: Record<string, string | number | boolean | undefined>;
12
+ headers?: Record<string, string>;
13
+ skipRetry?: boolean;
14
+ }
15
+ declare class HttpClient {
16
+ private config;
17
+ constructor(config: HttpClientConfig);
18
+ /**
19
+ * Make an HTTP request with automatic retries
20
+ */
21
+ request<T>(path: string, options?: RequestOptions): Promise<T>;
22
+ /**
23
+ * Build URL with query parameters
24
+ */
25
+ private buildUrl;
26
+ /**
27
+ * Fetch with timeout
28
+ */
29
+ private fetchWithTimeout;
30
+ /**
31
+ * Handle response and parse JSON
32
+ */
33
+ private handleResponse;
34
+ /**
35
+ * Extract error message from response data
36
+ */
37
+ private extractErrorMessage;
38
+ /**
39
+ * Calculate retry delay with exponential backoff
40
+ */
41
+ private calculateRetryDelay;
42
+ /**
43
+ * Sleep for the specified duration
44
+ */
45
+ private sleep;
46
+ }
47
+
48
+ interface Task {
49
+ id: string;
50
+ themeId: string;
51
+ projectId: string;
52
+ title: string;
53
+ description: string;
54
+ status: TaskStatus;
55
+ ownerId: string | null;
56
+ memberIds: string[];
57
+ memberCompletions: Record<string, boolean>;
58
+ dueDate: string | null;
59
+ order: number;
60
+ createdAt: string;
61
+ updatedAt: string;
62
+ }
63
+ type TaskStatus = 'active' | 'paused' | 'archived';
64
+ interface Project {
65
+ id: string;
66
+ themeId: string;
67
+ title: string;
68
+ description: string;
69
+ status: ProjectStatus;
70
+ createdAt: string;
71
+ updatedAt: string;
72
+ }
73
+ type ProjectStatus = 'active' | 'paused' | 'archived';
74
+ interface Comment {
75
+ id: string;
76
+ content: string;
77
+ commentedBy: string;
78
+ commentedAt: string;
79
+ mentionedUserIds: string[];
80
+ updatedAt: string | null;
81
+ }
82
+ interface Session {
83
+ id: string;
84
+ ai: string;
85
+ startedAt: string;
86
+ status: SessionStatus;
87
+ handoffNote: string | null;
88
+ endedAt: string | null;
89
+ }
90
+ type SessionStatus = 'active' | 'ended';
91
+ interface Theme {
92
+ id: string;
93
+ name: string;
94
+ description: string;
95
+ status: ThemeStatus;
96
+ createdAt: string;
97
+ updatedAt: string;
98
+ }
99
+ type ThemeStatus = 'active' | 'paused' | 'archived';
100
+ interface ThemeContext {
101
+ theme: ThemeSummary;
102
+ projects: ProjectWithTasks[];
103
+ stats: ThemeStats;
104
+ }
105
+ interface ThemeSummary {
106
+ id: string;
107
+ name: string;
108
+ description: string;
109
+ }
110
+ interface ProjectWithTasks {
111
+ id: string;
112
+ title: string;
113
+ description: string;
114
+ status: ProjectStatus;
115
+ tasks: TaskSummary[];
116
+ }
117
+ interface TaskSummary {
118
+ id: string;
119
+ title: string;
120
+ description: string;
121
+ status: TaskStatus;
122
+ ownerId: string | null;
123
+ dueDate: string | null;
124
+ }
125
+ interface ThemeStats {
126
+ totalProjects: number;
127
+ activeProjects: number;
128
+ totalTasks: number;
129
+ activeTasks: number;
130
+ pausedTasks: number;
131
+ archivedTasks: number;
132
+ }
133
+ interface ApiResponse<T> {
134
+ success: boolean;
135
+ data?: T;
136
+ error?: string;
137
+ message?: string;
138
+ }
139
+ interface PaginatedResponse<T> {
140
+ data: T[];
141
+ pagination: {
142
+ total: number;
143
+ page: number;
144
+ pageSize: number;
145
+ hasMore: boolean;
146
+ };
147
+ }
148
+ interface StartSessionRequest {
149
+ ai: string;
150
+ }
151
+ interface StartSessionResponse {
152
+ session: Session;
153
+ }
154
+ interface EndSessionRequest {
155
+ handoffNote?: string;
156
+ }
157
+ interface EndSessionResponse {
158
+ session: Session;
159
+ }
160
+ interface ListTasksParams {
161
+ status?: TaskStatus;
162
+ projectId?: string;
163
+ ownerId?: string;
164
+ page?: number;
165
+ pageSize?: number;
166
+ }
167
+ interface CompleteTaskRequest {
168
+ projectId: string;
169
+ }
170
+ interface CreateCommentRequest {
171
+ projectId: string;
172
+ taskId: string;
173
+ content: string;
174
+ aiName?: string;
175
+ }
176
+ interface CreateCommentResponse {
177
+ comment: Comment;
178
+ }
179
+ interface WorkflowStartResult {
180
+ session: Session;
181
+ context: ThemeContext;
182
+ }
183
+ interface ReportProgressParams {
184
+ projectId: string;
185
+ changes?: string[];
186
+ testResults?: {
187
+ passed?: number;
188
+ failed?: number;
189
+ skipped?: number;
190
+ };
191
+ note?: string;
192
+ }
193
+ interface ProjectsPlusConfig {
194
+ apiKey: string;
195
+ baseUrl?: string;
196
+ timeout?: number;
197
+ retries?: number;
198
+ retryDelay?: number;
199
+ }
200
+
201
+ /**
202
+ * Context resource for getting theme overview
203
+ */
204
+ declare class ContextResource {
205
+ private http;
206
+ constructor(http: HttpClient);
207
+ /**
208
+ * Get theme context including all projects and tasks
209
+ *
210
+ * @example
211
+ * ```ts
212
+ * const context = await pp.context.get();
213
+ * console.log(context.theme.name);
214
+ * console.log(context.projects);
215
+ * ```
216
+ */
217
+ get(): Promise<ThemeContext>;
218
+ }
219
+
220
+ /**
221
+ * Sessions resource for managing AI development sessions
222
+ */
223
+ declare class SessionsResource {
224
+ private http;
225
+ constructor(http: HttpClient);
226
+ /**
227
+ * Start a new AI development session
228
+ *
229
+ * @param params - Session parameters
230
+ * @returns The created session
231
+ *
232
+ * @example
233
+ * ```ts
234
+ * const session = await pp.sessions.start({ ai: 'claude' });
235
+ * console.log(session.id);
236
+ * ```
237
+ */
238
+ start(params: StartSessionRequest): Promise<Session>;
239
+ /**
240
+ * End the current AI development session
241
+ *
242
+ * @param params - Optional handoff note
243
+ * @returns The ended session
244
+ *
245
+ * @example
246
+ * ```ts
247
+ * const session = await pp.sessions.end({
248
+ * handoffNote: 'Completed tasks X, Y, Z. Remaining: A, B.'
249
+ * });
250
+ * ```
251
+ */
252
+ end(params?: EndSessionRequest): Promise<Session>;
253
+ /**
254
+ * Get the current active session if any
255
+ *
256
+ * @returns The current session or null
257
+ */
258
+ current(): Promise<Session | null>;
259
+ }
260
+
261
+ /**
262
+ * Tasks resource for managing tasks
263
+ */
264
+ declare class TasksResource {
265
+ private http;
266
+ constructor(http: HttpClient);
267
+ /**
268
+ * List tasks with optional filters
269
+ *
270
+ * @param params - Filter parameters
271
+ * @returns List of tasks
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * // Get all active tasks
276
+ * const tasks = await pp.tasks.list({ status: 'active' });
277
+ *
278
+ * // Get tasks for a specific project
279
+ * const projectTasks = await pp.tasks.list({
280
+ * projectId: 'proj-123',
281
+ * status: 'active'
282
+ * });
283
+ * ```
284
+ */
285
+ list(params?: ListTasksParams): Promise<Task[]>;
286
+ /**
287
+ * Get a specific task
288
+ *
289
+ * @param taskId - Task ID
290
+ * @param params - Additional parameters (projectId required)
291
+ * @returns The task
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * const task = await pp.tasks.get('task-123', {
296
+ * projectId: 'proj-123'
297
+ * });
298
+ * ```
299
+ */
300
+ get(taskId: string, params: {
301
+ projectId: string;
302
+ }): Promise<Task>;
303
+ /**
304
+ * Mark a task as completed (archived)
305
+ *
306
+ * @param taskId - Task ID
307
+ * @param params - Additional parameters (projectId required)
308
+ * @returns The updated task
309
+ *
310
+ * @example
311
+ * ```ts
312
+ * await pp.tasks.complete('task-123', {
313
+ * projectId: 'proj-123'
314
+ * });
315
+ * ```
316
+ */
317
+ complete(taskId: string, params: CompleteTaskRequest): Promise<Task>;
318
+ /**
319
+ * Update task status
320
+ *
321
+ * @param taskId - Task ID
322
+ * @param params - Status and projectId
323
+ * @returns The updated task
324
+ *
325
+ * @example
326
+ * ```ts
327
+ * await pp.tasks.updateStatus('task-123', {
328
+ * projectId: 'proj-123',
329
+ * status: 'paused'
330
+ * });
331
+ * ```
332
+ */
333
+ updateStatus(taskId: string, params: {
334
+ projectId: string;
335
+ status: 'active' | 'paused' | 'archived';
336
+ }): Promise<Task>;
337
+ }
338
+
339
+ /**
340
+ * Projects resource for managing projects
341
+ */
342
+ declare class ProjectsResource {
343
+ private http;
344
+ constructor(http: HttpClient);
345
+ /**
346
+ * List all projects
347
+ *
348
+ * @param params - Filter parameters
349
+ * @returns List of projects
350
+ *
351
+ * @example
352
+ * ```ts
353
+ * const projects = await pp.projects.list();
354
+ *
355
+ * // Filter by status
356
+ * const activeProjects = await pp.projects.list({ status: 'active' });
357
+ * ```
358
+ */
359
+ list(params?: {
360
+ status?: 'active' | 'paused' | 'archived';
361
+ }): Promise<Project[]>;
362
+ /**
363
+ * Get a specific project
364
+ *
365
+ * @param projectId - Project ID
366
+ * @returns The project
367
+ *
368
+ * @example
369
+ * ```ts
370
+ * const project = await pp.projects.get('proj-123');
371
+ * ```
372
+ */
373
+ get(projectId: string): Promise<Project>;
374
+ /**
375
+ * Get tasks for a specific project
376
+ *
377
+ * @param projectId - Project ID
378
+ * @param params - Filter parameters
379
+ * @returns List of tasks
380
+ *
381
+ * @example
382
+ * ```ts
383
+ * const tasks = await pp.projects.getTasks('proj-123');
384
+ *
385
+ * // Filter by status
386
+ * const activeTasks = await pp.projects.getTasks('proj-123', {
387
+ * status: 'active'
388
+ * });
389
+ * ```
390
+ */
391
+ getTasks(projectId: string, params?: {
392
+ status?: 'active' | 'paused' | 'archived';
393
+ }): Promise<Task[]>;
394
+ }
395
+
396
+ /**
397
+ * Comments resource for managing task comments
398
+ */
399
+ declare class CommentsResource {
400
+ private http;
401
+ constructor(http: HttpClient);
402
+ /**
403
+ * List comments for a task
404
+ *
405
+ * @param params - Task identifiers
406
+ * @returns List of comments
407
+ *
408
+ * @example
409
+ * ```ts
410
+ * const comments = await pp.comments.list({
411
+ * projectId: 'proj-123',
412
+ * taskId: 'task-123'
413
+ * });
414
+ * ```
415
+ */
416
+ list(params: {
417
+ projectId: string;
418
+ taskId: string;
419
+ }): Promise<Comment[]>;
420
+ /**
421
+ * Create a new comment on a task
422
+ *
423
+ * @param params - Comment data
424
+ * @returns The created comment
425
+ *
426
+ * @example
427
+ * ```ts
428
+ * await pp.comments.create({
429
+ * projectId: 'proj-123',
430
+ * taskId: 'task-123',
431
+ * content: '## 実装完了\n\n### 変更内容\n- file1.ts\n- file2.ts',
432
+ * aiName: 'Claude'
433
+ * });
434
+ * ```
435
+ */
436
+ create(params: CreateCommentRequest): Promise<Comment>;
437
+ /**
438
+ * Delete a comment
439
+ *
440
+ * @param commentId - Comment ID
441
+ * @param params - Task identifiers
442
+ *
443
+ * @example
444
+ * ```ts
445
+ * await pp.comments.delete('comment-123', {
446
+ * projectId: 'proj-123',
447
+ * taskId: 'task-123'
448
+ * });
449
+ * ```
450
+ */
451
+ delete(commentId: string, params: {
452
+ projectId: string;
453
+ taskId: string;
454
+ }): Promise<void>;
455
+ }
456
+
457
+ /**
458
+ * Workflow helper for common development patterns
459
+ *
460
+ * @example
461
+ * ```ts
462
+ * const workflow = pp.workflow({ ai: 'claude' });
463
+ *
464
+ * const { session, context } = await workflow.start();
465
+ * await workflow.reportProgress('task-id', {
466
+ * projectId: 'proj-id',
467
+ * changes: ['file1.ts'],
468
+ * testResults: { passed: 10 },
469
+ * });
470
+ * await workflow.completeAndRefresh('task-id', { projectId: 'proj-id' });
471
+ * await workflow.end('Summary');
472
+ * ```
473
+ */
474
+ declare class Workflow {
475
+ private client;
476
+ private ai;
477
+ private currentSession;
478
+ private currentContext;
479
+ constructor(client: ProjectsPlus, ai: string);
480
+ /**
481
+ * Start session and get context in one call
482
+ *
483
+ * @returns Session and context
484
+ */
485
+ start(): Promise<WorkflowStartResult>;
486
+ /**
487
+ * Report progress with auto-formatted markdown comment
488
+ *
489
+ * @param taskId - Task ID
490
+ * @param params - Progress details
491
+ */
492
+ reportProgress(taskId: string, params: ReportProgressParams): Promise<void>;
493
+ /**
494
+ * Complete a task and refresh context
495
+ *
496
+ * @param taskId - Task ID
497
+ * @param params - Project ID
498
+ * @returns Updated context
499
+ */
500
+ completeAndRefresh(taskId: string, params: {
501
+ projectId: string;
502
+ }): Promise<ThemeContext>;
503
+ /**
504
+ * Refresh context without completing a task
505
+ *
506
+ * @returns Updated context
507
+ */
508
+ refresh(): Promise<ThemeContext>;
509
+ /**
510
+ * End the session with optional handoff note
511
+ *
512
+ * @param handoffNote - Summary for next session
513
+ * @returns Ended session
514
+ */
515
+ end(handoffNote?: string): Promise<Session>;
516
+ /**
517
+ * Get the current session
518
+ */
519
+ getSession(): Session | null;
520
+ /**
521
+ * Get the current context
522
+ */
523
+ getContext(): ThemeContext | null;
524
+ /**
525
+ * Format a progress comment from params
526
+ */
527
+ private formatProgressComment;
528
+ }
529
+
530
+ /**
531
+ * Projects Plus SDK Client
532
+ *
533
+ * @example
534
+ * ```ts
535
+ * import { ProjectsPlus } from '@projects-plus/sdk';
536
+ *
537
+ * const pp = new ProjectsPlus({
538
+ * apiKey: process.env.PROJECTS_PLUS_API_KEY,
539
+ * });
540
+ *
541
+ * // Start session
542
+ * await pp.sessions.start({ ai: 'claude' });
543
+ *
544
+ * // Get context
545
+ * const context = await pp.context.get();
546
+ *
547
+ * // List tasks
548
+ * const tasks = await pp.tasks.list({ status: 'active' });
549
+ *
550
+ * // Add comment
551
+ * await pp.comments.create({
552
+ * projectId: 'proj-id',
553
+ * taskId: 'task-id',
554
+ * content: '## Done\n\nImplemented feature X',
555
+ * aiName: 'Claude'
556
+ * });
557
+ *
558
+ * // Complete task
559
+ * await pp.tasks.complete('task-id', { projectId: 'proj-id' });
560
+ *
561
+ * // End session
562
+ * await pp.sessions.end({ handoffNote: 'Summary...' });
563
+ * ```
564
+ */
565
+ declare class ProjectsPlus {
566
+ private http;
567
+ /** Context resource for getting theme overview */
568
+ readonly context: ContextResource;
569
+ /** Sessions resource for managing AI development sessions */
570
+ readonly sessions: SessionsResource;
571
+ /** Tasks resource for managing tasks */
572
+ readonly tasks: TasksResource;
573
+ /** Projects resource for managing projects */
574
+ readonly projects: ProjectsResource;
575
+ /** Comments resource for managing task comments */
576
+ readonly comments: CommentsResource;
577
+ /**
578
+ * Create a new Projects Plus client
579
+ *
580
+ * @param config - Client configuration
581
+ */
582
+ constructor(config: ProjectsPlusConfig);
583
+ /**
584
+ * Create a workflow helper for common development patterns
585
+ *
586
+ * @param params - Workflow parameters
587
+ * @returns Workflow instance
588
+ *
589
+ * @example
590
+ * ```ts
591
+ * const workflow = pp.workflow({ ai: 'claude' });
592
+ *
593
+ * // Start session and get context in one call
594
+ * const { session, context } = await workflow.start();
595
+ *
596
+ * // Report progress with auto-formatted markdown
597
+ * await workflow.reportProgress('task-id', {
598
+ * projectId: 'proj-id',
599
+ * changes: ['file1.ts', 'file2.ts'],
600
+ * testResults: { passed: 10, failed: 0 },
601
+ * });
602
+ *
603
+ * // Complete task and refresh context
604
+ * const newContext = await workflow.completeAndRefresh('task-id', {
605
+ * projectId: 'proj-id'
606
+ * });
607
+ *
608
+ * // End session
609
+ * await workflow.end('Summary...');
610
+ * ```
611
+ */
612
+ workflow(params: {
613
+ ai: string;
614
+ }): Workflow;
615
+ }
616
+
617
+ /**
618
+ * Base error class for all API errors
619
+ */
620
+ declare class ApiError extends Error {
621
+ readonly status: number;
622
+ readonly code?: string | undefined;
623
+ readonly details?: unknown | undefined;
624
+ constructor(message: string, status: number, code?: string | undefined, details?: unknown | undefined);
625
+ }
626
+ /**
627
+ * Thrown when the API key is invalid or missing
628
+ */
629
+ declare class AuthenticationError extends ApiError {
630
+ constructor(message?: string);
631
+ }
632
+ /**
633
+ * Thrown when rate limit is exceeded
634
+ */
635
+ declare class RateLimitError extends ApiError {
636
+ readonly retryAfter?: number | undefined;
637
+ constructor(message?: string, retryAfter?: number | undefined);
638
+ }
639
+ /**
640
+ * Thrown when the requested resource is not found
641
+ */
642
+ declare class NotFoundError extends ApiError {
643
+ constructor(message?: string);
644
+ }
645
+ /**
646
+ * Thrown when the request is invalid
647
+ */
648
+ declare class ValidationError extends ApiError {
649
+ constructor(message?: string, details?: unknown);
650
+ }
651
+ /**
652
+ * Thrown when there's a server error
653
+ */
654
+ declare class ServerError extends ApiError {
655
+ constructor(message?: string);
656
+ }
657
+ /**
658
+ * Thrown when the request times out
659
+ */
660
+ declare class TimeoutError extends ApiError {
661
+ constructor(message?: string);
662
+ }
663
+ /**
664
+ * Thrown when the network is unavailable
665
+ */
666
+ declare class NetworkError extends ApiError {
667
+ constructor(message?: string);
668
+ }
669
+ /**
670
+ * Create the appropriate error based on status code
671
+ */
672
+ declare function createApiError(status: number, message: string, details?: unknown): ApiError;
673
+
674
+ export { ApiError, type ApiResponse, AuthenticationError, type Comment, type CompleteTaskRequest, type CreateCommentRequest, type CreateCommentResponse, type EndSessionRequest, type EndSessionResponse, type ListTasksParams, NetworkError, NotFoundError, type PaginatedResponse, type Project, type ProjectStatus, type ProjectWithTasks, ProjectsPlus, type ProjectsPlusConfig, RateLimitError, type ReportProgressParams, ServerError, type Session, type SessionStatus, type StartSessionRequest, type StartSessionResponse, type Task, type TaskStatus, type TaskSummary, type Theme, type ThemeContext, type ThemeStats, type ThemeStatus, type ThemeSummary, TimeoutError, ValidationError, Workflow, type WorkflowStartResult, createApiError };