@agentuity/core 2.0.6 → 2.0.8

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 (112) hide show
  1. package/dist/services/coder/api-reference.d.ts +4 -0
  2. package/dist/services/coder/api-reference.d.ts.map +1 -0
  3. package/dist/services/coder/api-reference.js +199 -0
  4. package/dist/services/coder/api-reference.js.map +1 -0
  5. package/dist/services/coder/client.d.ts +128 -0
  6. package/dist/services/coder/client.d.ts.map +1 -0
  7. package/dist/services/coder/client.js +265 -0
  8. package/dist/services/coder/client.js.map +1 -0
  9. package/dist/services/coder/discover.d.ts +13 -0
  10. package/dist/services/coder/discover.d.ts.map +1 -0
  11. package/dist/services/coder/discover.js +18 -0
  12. package/dist/services/coder/discover.js.map +1 -0
  13. package/dist/services/coder/github.d.ts +13 -0
  14. package/dist/services/coder/github.d.ts.map +1 -0
  15. package/dist/services/coder/github.js +15 -0
  16. package/dist/services/coder/github.js.map +1 -0
  17. package/dist/services/coder/index.d.ts +19 -0
  18. package/dist/services/coder/index.d.ts.map +1 -0
  19. package/dist/services/coder/index.js +13 -0
  20. package/dist/services/coder/index.js.map +1 -0
  21. package/dist/services/coder/loop-state.d.ts +10 -0
  22. package/dist/services/coder/loop-state.d.ts.map +1 -0
  23. package/dist/services/coder/loop-state.js +13 -0
  24. package/dist/services/coder/loop-state.js.map +1 -0
  25. package/dist/services/coder/session-data.d.ts +28 -0
  26. package/dist/services/coder/session-data.d.ts.map +1 -0
  27. package/dist/services/coder/session-data.js +28 -0
  28. package/dist/services/coder/session-data.js.map +1 -0
  29. package/dist/services/coder/sessions.d.ts +155 -0
  30. package/dist/services/coder/sessions.d.ts.map +1 -0
  31. package/dist/services/coder/sessions.js +125 -0
  32. package/dist/services/coder/sessions.js.map +1 -0
  33. package/dist/services/coder/skills.d.ts +17 -0
  34. package/dist/services/coder/skills.d.ts.map +1 -0
  35. package/dist/services/coder/skills.js +43 -0
  36. package/dist/services/coder/skills.js.map +1 -0
  37. package/dist/services/coder/types.d.ts +1066 -0
  38. package/dist/services/coder/types.d.ts.map +1 -0
  39. package/dist/services/coder/types.js +573 -0
  40. package/dist/services/coder/types.js.map +1 -0
  41. package/dist/services/coder/users.d.ts +12 -0
  42. package/dist/services/coder/users.d.ts.map +1 -0
  43. package/dist/services/coder/users.js +35 -0
  44. package/dist/services/coder/users.js.map +1 -0
  45. package/dist/services/coder/util.d.ts +82 -0
  46. package/dist/services/coder/util.d.ts.map +1 -0
  47. package/dist/services/coder/util.js +60 -0
  48. package/dist/services/coder/util.js.map +1 -0
  49. package/dist/services/coder/workspaces.d.ts +13 -0
  50. package/dist/services/coder/workspaces.d.ts.map +1 -0
  51. package/dist/services/coder/workspaces.js +37 -0
  52. package/dist/services/coder/workspaces.js.map +1 -0
  53. package/dist/services/index.d.ts +1 -0
  54. package/dist/services/index.d.ts.map +1 -1
  55. package/dist/services/index.js +1 -0
  56. package/dist/services/index.js.map +1 -1
  57. package/dist/services/oauth/types.d.ts +1 -0
  58. package/dist/services/oauth/types.d.ts.map +1 -1
  59. package/dist/services/oauth/types.js +1 -0
  60. package/dist/services/oauth/types.js.map +1 -1
  61. package/dist/services/project/deploy.d.ts +1 -1
  62. package/dist/services/queue/service.d.ts +28 -0
  63. package/dist/services/queue/service.d.ts.map +1 -1
  64. package/dist/services/queue/service.js +54 -9
  65. package/dist/services/queue/service.js.map +1 -1
  66. package/dist/services/sandbox/cli-list.d.ts +1 -1
  67. package/dist/services/sandbox/client.d.ts +10 -4
  68. package/dist/services/sandbox/client.d.ts.map +1 -1
  69. package/dist/services/sandbox/client.js +2 -2
  70. package/dist/services/sandbox/client.js.map +1 -1
  71. package/dist/services/sandbox/create.d.ts +2 -2
  72. package/dist/services/sandbox/execute.d.ts +2 -2
  73. package/dist/services/sandbox/execution.d.ts +4 -4
  74. package/dist/services/sandbox/files.d.ts +10 -2
  75. package/dist/services/sandbox/files.d.ts.map +1 -1
  76. package/dist/services/sandbox/files.js +14 -0
  77. package/dist/services/sandbox/files.js.map +1 -1
  78. package/dist/services/sandbox/get.d.ts +2 -2
  79. package/dist/services/sandbox/list.d.ts +5 -5
  80. package/dist/services/sandbox/run.d.ts +1 -1
  81. package/dist/services/sandbox/types.d.ts +20 -12
  82. package/dist/services/sandbox/types.d.ts.map +1 -1
  83. package/dist/services/sandbox/types.js +4 -4
  84. package/dist/services/sandbox/types.js.map +1 -1
  85. package/dist/services/session/events.d.ts +2 -2
  86. package/dist/services/session/list.d.ts +1 -1
  87. package/dist/services/task/service.d.ts +290 -0
  88. package/dist/services/task/service.d.ts.map +1 -1
  89. package/dist/services/task/service.js +382 -0
  90. package/dist/services/task/service.js.map +1 -1
  91. package/dist/services/workflow/types.d.ts +8 -8
  92. package/package.json +2 -2
  93. package/src/services/coder/api-reference.ts +207 -0
  94. package/src/services/coder/client.ts +378 -0
  95. package/src/services/coder/discover.ts +23 -0
  96. package/src/services/coder/github.ts +33 -0
  97. package/src/services/coder/index.ts +72 -0
  98. package/src/services/coder/loop-state.ts +19 -0
  99. package/src/services/coder/session-data.ts +63 -0
  100. package/src/services/coder/sessions.ts +237 -0
  101. package/src/services/coder/skills.ts +102 -0
  102. package/src/services/coder/types.ts +670 -0
  103. package/src/services/coder/users.ts +59 -0
  104. package/src/services/coder/util.ts +87 -0
  105. package/src/services/coder/workspaces.ts +77 -0
  106. package/src/services/index.ts +1 -0
  107. package/src/services/oauth/types.ts +1 -0
  108. package/src/services/queue/service.ts +56 -13
  109. package/src/services/sandbox/client.ts +10 -8
  110. package/src/services/sandbox/files.ts +28 -2
  111. package/src/services/sandbox/types.ts +8 -6
  112. package/src/services/task/service.ts +446 -0
@@ -138,6 +138,7 @@ export const TaskSchema = z.object({
138
138
  created_id: z.string().describe('ID of the user who created the task.'),
139
139
  assigned_id: z.string().optional().describe('ID of the user the task is assigned to.'),
140
140
  closed_id: z.string().optional().describe('ID of the user who closed the task.'),
141
+ deleted: z.boolean().optional().describe('Whether this task has been soft-deleted.'),
141
142
  creator: z
142
143
  .lazy(() => UserEntityRefSchema)
143
144
  .optional()
@@ -371,6 +372,21 @@ export const UpdateTaskParamsSchema = z.object({
371
372
 
372
373
  export type UpdateTaskParams = z.infer<typeof UpdateTaskParamsSchema>;
373
374
 
375
+ /**
376
+ * Additional fields to include in the task list response.
377
+ * By default, list returns a reduced summary shape for performance.
378
+ */
379
+ export const TaskIncludeFieldSchema = z.enum([
380
+ 'description',
381
+ 'metadata',
382
+ 'tags',
383
+ 'subtask_count',
384
+ 'created_id',
385
+ 'deleted',
386
+ ]);
387
+
388
+ export type TaskIncludeField = z.infer<typeof TaskIncludeFieldSchema>;
389
+
374
390
  /**
375
391
  * Parameters for filtering and paginating the task list.
376
392
  */
@@ -406,6 +422,16 @@ export const ListTasksParamsSchema = z.object({
406
422
  */
407
423
  deleted: z.boolean().optional().describe('Filter for soft-deleted tasks.'),
408
424
 
425
+ /**
426
+ * Additional fields to include in the response.
427
+ * By default, list returns a reduced summary shape.
428
+ * Use this to include: description, metadata, tags, subtask_count, created_id, deleted.
429
+ */
430
+ include: z
431
+ .array(TaskIncludeFieldSchema)
432
+ .optional()
433
+ .describe('Additional fields to include in the response.'),
434
+
409
435
  /**
410
436
  * Sort field. Prefix with `-` for descending order.
411
437
  *
@@ -522,6 +548,207 @@ export const BatchDeleteTasksResultSchema = z.object({
522
548
 
523
549
  export type BatchDeleteTasksResult = z.infer<typeof BatchDeleteTasksResultSchema>;
524
550
 
551
+ /**
552
+ * Parameters for batch-updating tasks by filter.
553
+ * At least one filter must be provided. At least one update field must be provided.
554
+ */
555
+ export const BatchUpdateTasksParamsSchema = z.object({
556
+ /** Filter by task status. */
557
+ status: TaskStatusSchema.optional().describe('Filter by task status.'),
558
+
559
+ /** Filter by task type. */
560
+ type: TaskTypeSchema.optional().describe('Filter by task type.'),
561
+
562
+ /** Filter by priority level. */
563
+ priority: TaskPrioritySchema.optional().describe('Filter by priority level.'),
564
+
565
+ /** Filter by parent task ID. */
566
+ parent_id: z.string().optional().describe('Filter by parent task ID.'),
567
+
568
+ /** Filter by creator ID. */
569
+ created_id: z.string().optional().describe('Filter by creator ID.'),
570
+
571
+ /** Filter by assigned user ID. */
572
+ assigned_id: z.string().optional().describe('Filter by assigned user ID.'),
573
+
574
+ /** Filter by project ID. */
575
+ project_id: z.string().optional().describe('Filter by project ID.'),
576
+
577
+ /** Filter by tag ID. */
578
+ tag_id: z.string().optional().describe('Filter by tag ID.'),
579
+
580
+ /**
581
+ * Filter for tasks older than this duration.
582
+ * Accepts Go-style duration strings: `'30m'`, `'24h'`, `'7d'`, `'2w'`.
583
+ */
584
+ older_than: z.string().optional().describe('Filter for tasks older than this duration.'),
585
+
586
+ /** Specific task IDs to update (alternative to filters). */
587
+ ids: z.array(z.string()).optional().describe('Specific task IDs to update.'),
588
+
589
+ /**
590
+ * Maximum number of tasks to update.
591
+ * @default 50
592
+ * @maximum 200
593
+ */
594
+ limit: z.number().optional().describe('Maximum number of tasks to update.'),
595
+
596
+ // Update fields - at least one must be provided
597
+ /** New status to set. */
598
+ new_status: TaskStatusSchema.optional().describe('New status to set.'),
599
+
600
+ /** New priority to set. */
601
+ new_priority: TaskPrioritySchema.optional().describe('New priority to set.'),
602
+
603
+ /** New assigned user ID to set. */
604
+ new_assigned_id: z.string().optional().describe('New assigned user ID to set.'),
605
+
606
+ /** New assignee entity reference. */
607
+ new_assignee: UserEntityRefSchema.optional().describe('New assignee entity reference.'),
608
+
609
+ /** New title to set. */
610
+ new_title: z.string().optional().describe('New title to set.'),
611
+
612
+ /** New description to set. */
613
+ new_description: z.string().optional().describe('New description to set.'),
614
+
615
+ /** New metadata to set (merged with existing). */
616
+ new_metadata: z.record(z.string(), z.unknown()).optional().describe('New metadata to set.'),
617
+
618
+ /** New type to set. */
619
+ new_type: TaskTypeSchema.optional().describe('New type to set.'),
620
+
621
+ /**
622
+ * Filter for tasks newer than this duration.
623
+ * Accepts Go-style duration strings: `'30m'`, `'24h'`, `'7d'`, `'2w'`.
624
+ */
625
+ newer_than: z.string().optional().describe('Filter for tasks newer than this duration.'),
626
+
627
+ /** Whether this is a dry run (preview only). */
628
+ dry_run: z.boolean().optional().describe('Whether this is a dry run (preview only).'),
629
+ });
630
+
631
+ export type BatchUpdateTasksParams = z.infer<typeof BatchUpdateTasksParamsSchema>;
632
+
633
+ /**
634
+ * A single task that was updated in a batch operation.
635
+ */
636
+ export const BatchUpdatedTaskSchema = z.object({
637
+ id: z.string().describe('The ID of the updated task.'),
638
+ title: z.string().describe('The title of the updated task.'),
639
+ status: TaskStatusSchema.describe('The new status of the task.'),
640
+ priority: TaskPrioritySchema.describe('The new priority of the task.'),
641
+ });
642
+
643
+ export type BatchUpdatedTask = z.infer<typeof BatchUpdatedTaskSchema>;
644
+
645
+ /**
646
+ * Result of a batch update operation.
647
+ */
648
+ export const BatchUpdateTasksResultSchema = z.object({
649
+ /** Array of tasks that were updated. */
650
+ updated: z.array(BatchUpdatedTaskSchema).describe('Array of tasks that were updated.'),
651
+
652
+ /** Total number of tasks updated. */
653
+ count: z.number().describe('Total number of tasks updated.'),
654
+
655
+ /** Whether this was a dry run. */
656
+ dry_run: z.boolean().describe('Whether this was a dry run.'),
657
+ });
658
+
659
+ export type BatchUpdateTasksResult = z.infer<typeof BatchUpdateTasksResultSchema>;
660
+
661
+ /**
662
+ * Parameters for batch-closing tasks by filter.
663
+ * At least one filter must be provided.
664
+ */
665
+ export const BatchCloseTasksParamsSchema = z.object({
666
+ /** Filter by task status. */
667
+ status: TaskStatusSchema.optional().describe('Filter by task status.'),
668
+
669
+ /** Filter by task type. */
670
+ type: TaskTypeSchema.optional().describe('Filter by task type.'),
671
+
672
+ /** Filter by priority level. */
673
+ priority: TaskPrioritySchema.optional().describe('Filter by priority level.'),
674
+
675
+ /** Filter by parent task ID. */
676
+ parent_id: z.string().optional().describe('Filter by parent task ID.'),
677
+
678
+ /** Filter by creator ID. */
679
+ created_id: z.string().optional().describe('Filter by creator ID.'),
680
+
681
+ /** Filter by assigned user ID. */
682
+ assigned_id: z.string().optional().describe('Filter by assigned user ID.'),
683
+
684
+ /** Filter by project ID. */
685
+ project_id: z.string().optional().describe('Filter by project ID.'),
686
+
687
+ /** Filter by tag ID. */
688
+ tag_id: z.string().optional().describe('Filter by tag ID.'),
689
+
690
+ /**
691
+ * Filter for tasks older than this duration.
692
+ * Accepts Go-style duration strings: `'30m'`, `'24h'`, `'7d'`, `'2w'`.
693
+ */
694
+ older_than: z.string().optional().describe('Filter for tasks older than this duration.'),
695
+
696
+ /**
697
+ * Filter for tasks newer than this duration.
698
+ * Accepts Go-style duration strings: `'30m'`, `'24h'`, `'7d'`, `'2w'`.
699
+ */
700
+ newer_than: z.string().optional().describe('Filter for tasks newer than this duration.'),
701
+
702
+ /** Specific task IDs to close (alternative to filters). */
703
+ ids: z.array(z.string()).optional().describe('Specific task IDs to close.'),
704
+
705
+ /**
706
+ * Maximum number of tasks to close.
707
+ * @default 50
708
+ * @maximum 200
709
+ */
710
+ limit: z.number().optional().describe('Maximum number of tasks to close.'),
711
+
712
+ /** ID of the user closing the tasks. */
713
+ closed_id: z.string().optional().describe('ID of the user closing the tasks.'),
714
+
715
+ /** Closer entity reference. */
716
+ closer: UserEntityRefSchema.optional().describe('Closer entity reference.'),
717
+
718
+ /** Whether this is a dry run (preview only). */
719
+ dry_run: z.boolean().optional().describe('Whether this is a dry run (preview only).'),
720
+ });
721
+
722
+ export type BatchCloseTasksParams = z.infer<typeof BatchCloseTasksParamsSchema>;
723
+
724
+ /**
725
+ * A single task that was closed in a batch operation.
726
+ */
727
+ export const BatchClosedTaskSchema = z.object({
728
+ id: z.string().describe('The ID of the closed task.'),
729
+ title: z.string().describe('The title of the closed task.'),
730
+ status: TaskStatusSchema.describe('The status of the task (done).'),
731
+ closed_date: z.string().optional().describe('ISO 8601 timestamp when the task was closed.'),
732
+ });
733
+
734
+ export type BatchClosedTask = z.infer<typeof BatchClosedTaskSchema>;
735
+
736
+ /**
737
+ * Result of a batch close operation.
738
+ */
739
+ export const BatchCloseTasksResultSchema = z.object({
740
+ /** Array of tasks that were closed. */
741
+ closed: z.array(BatchClosedTaskSchema).describe('Array of tasks that were closed.'),
742
+
743
+ /** Total number of tasks closed. */
744
+ count: z.number().describe('Total number of tasks closed.'),
745
+
746
+ /** Whether this was a dry run. */
747
+ dry_run: z.boolean().describe('Whether this was a dry run.'),
748
+ });
749
+
750
+ export type BatchCloseTasksResult = z.infer<typeof BatchCloseTasksResultSchema>;
751
+
525
752
  /**
526
753
  * Paginated list of changelog entries for a task.
527
754
  */
@@ -769,6 +996,24 @@ export interface TaskStorage {
769
996
  */
770
997
  batchDelete(params: BatchDeleteTasksParams): Promise<BatchDeleteTasksResult>;
771
998
 
999
+ /**
1000
+ * Batch update tasks matching the given filters.
1001
+ * At least one filter must be provided. At least one update field must be provided.
1002
+ *
1003
+ * @param params - Filters to select tasks and fields to update
1004
+ * @returns The list of updated tasks and count
1005
+ */
1006
+ batchUpdate(params: BatchUpdateTasksParams): Promise<BatchUpdateTasksResult>;
1007
+
1008
+ /**
1009
+ * Batch close tasks matching the given filters.
1010
+ * At least one filter must be provided. Sets status to done and records closed_date.
1011
+ *
1012
+ * @param params - Filters to select which tasks to close
1013
+ * @returns The list of closed tasks and count
1014
+ */
1015
+ batchClose(params: BatchCloseTasksParams): Promise<BatchCloseTasksResult>;
1016
+
772
1017
  /**
773
1018
  * Get the changelog (audit trail) for a task.
774
1019
  *
@@ -1295,6 +1540,9 @@ export class TaskStorageService implements TaskStorage {
1295
1540
  if (params?.project_id) queryParams.set('project_id', params.project_id);
1296
1541
  if (params?.tag_id) queryParams.set('tag_id', params.tag_id);
1297
1542
  if (params?.deleted !== undefined) queryParams.set('deleted', String(params.deleted));
1543
+ if (params?.include && params.include.length > 0) {
1544
+ queryParams.set('include', params.include.join(','));
1545
+ }
1298
1546
  if (params?.sort) queryParams.set('sort', params.sort);
1299
1547
  if (params?.order) queryParams.set('order', params.order);
1300
1548
  if (params?.limit !== undefined) queryParams.set('limit', String(params.limit));
@@ -1611,6 +1859,204 @@ export class TaskStorageService implements TaskStorage {
1611
1859
  throw await toServiceException('POST', url, res.response);
1612
1860
  }
1613
1861
 
1862
+ /**
1863
+ * Batch update tasks matching the given filters.
1864
+ * At least one filter (or ids) must be provided. At least one update field must be provided.
1865
+ *
1866
+ * @param params - Filters to select tasks and fields to update
1867
+ * @returns The list of updated tasks and count
1868
+ * @throws {@link ServiceException} if the API request fails
1869
+ *
1870
+ * @example
1871
+ * ```typescript
1872
+ * const result = await tasks.batchUpdate({
1873
+ * status: 'open',
1874
+ * new_status: 'in_progress',
1875
+ * new_priority: 'high',
1876
+ * limit: 50,
1877
+ * });
1878
+ * console.log(`Updated ${result.count} tasks`);
1879
+ * ```
1880
+ */
1881
+ async batchUpdate(params: BatchUpdateTasksParams): Promise<BatchUpdateTasksResult> {
1882
+ const hasFilter =
1883
+ params.status ||
1884
+ params.type ||
1885
+ params.priority ||
1886
+ params.parent_id ||
1887
+ params.created_id ||
1888
+ params.assigned_id ||
1889
+ params.project_id ||
1890
+ params.tag_id ||
1891
+ params.older_than ||
1892
+ params.newer_than ||
1893
+ (params.ids && params.ids.length > 0);
1894
+ if (!hasFilter) {
1895
+ throw new Error('At least one filter or ids is required for batch update');
1896
+ }
1897
+
1898
+ const hasUpdate =
1899
+ params.new_status ||
1900
+ params.new_priority ||
1901
+ params.new_assigned_id ||
1902
+ params.new_assignee ||
1903
+ params.new_title ||
1904
+ params.new_description ||
1905
+ params.new_metadata ||
1906
+ params.new_type;
1907
+ if (!hasUpdate) {
1908
+ throw new Error('At least one update field is required for batch update');
1909
+ }
1910
+
1911
+ if (params.limit !== undefined && params.limit > MAX_BATCH_DELETE_LIMIT) {
1912
+ throw new Error(
1913
+ `Batch update limit must not exceed ${MAX_BATCH_DELETE_LIMIT} (got ${params.limit})`
1914
+ );
1915
+ }
1916
+
1917
+ const url = buildUrl(this.#baseUrl, `/task/update/batch`);
1918
+ const signal = AbortSignal.timeout(60_000);
1919
+
1920
+ const body: Record<string, unknown> = {};
1921
+ if (params.status) body.status = normalizeTaskStatus(params.status);
1922
+ if (params.type) body.type = params.type;
1923
+ if (params.priority) body.priority = params.priority;
1924
+ if (params.parent_id) body.parent_id = params.parent_id;
1925
+ if (params.created_id) body.created_id = params.created_id;
1926
+ if (params.assigned_id) body.assigned_id = params.assigned_id;
1927
+ if (params.project_id) body.project_id = params.project_id;
1928
+ if (params.tag_id) body.tag_id = params.tag_id;
1929
+ if (params.older_than) body.older_than = params.older_than;
1930
+ if (params.newer_than) body.newer_than = params.newer_than;
1931
+ if (params.ids && params.ids.length > 0) body.ids = params.ids;
1932
+ if (params.limit !== undefined) body.limit = params.limit;
1933
+ if (params.new_status) body.new_status = normalizeTaskStatus(params.new_status);
1934
+ if (params.new_priority) body.new_priority = params.new_priority;
1935
+ if (params.new_assigned_id) body.new_assigned_id = params.new_assigned_id;
1936
+ if (params.new_assignee) body.new_assignee = params.new_assignee;
1937
+ if (params.new_title) body.new_title = params.new_title;
1938
+ if (params.new_description) body.new_description = params.new_description;
1939
+ if (params.new_metadata) body.new_metadata = params.new_metadata;
1940
+ if (params.new_type) body.new_type = params.new_type;
1941
+ if (params.dry_run !== undefined) body.dry_run = params.dry_run;
1942
+
1943
+ const res = await this.#adapter.invoke<TaskResponse<BatchUpdateTasksResult>>(url, {
1944
+ method: 'POST',
1945
+ body: safeStringify(body),
1946
+ headers: { 'Content-Type': 'application/json' },
1947
+ signal,
1948
+ telemetry: {
1949
+ name: 'agentuity.task.batchUpdate',
1950
+ attributes: {
1951
+ ...(params.status ? { status: normalizeTaskStatus(params.status) } : {}),
1952
+ ...(params.new_status ? { new_status: normalizeTaskStatus(params.new_status) } : {}),
1953
+ ...(params.dry_run !== undefined ? { dry_run: String(params.dry_run) } : {}),
1954
+ },
1955
+ },
1956
+ });
1957
+
1958
+ if (res.ok) {
1959
+ if (res.data.success) {
1960
+ return res.data.data;
1961
+ }
1962
+ throw new TaskStorageResponseError({
1963
+ status: res.response.status,
1964
+ message: res.data.message,
1965
+ });
1966
+ }
1967
+
1968
+ throw await toServiceException('POST', url, res.response);
1969
+ }
1970
+
1971
+ /**
1972
+ * Batch close tasks matching the given filters.
1973
+ * At least one filter (or ids) must be provided. Sets status to done and records closed_date.
1974
+ *
1975
+ * @param params - Filters to select which tasks to close
1976
+ * @returns The list of closed tasks and count
1977
+ * @throws {@link ServiceException} if the API request fails
1978
+ *
1979
+ * @example
1980
+ * ```typescript
1981
+ * const result = await tasks.batchClose({
1982
+ * status: 'in_progress',
1983
+ * older_than: '7d',
1984
+ * limit: 50,
1985
+ * dry_run: true,
1986
+ * });
1987
+ * console.log(`Would close ${result.count} tasks`);
1988
+ * ```
1989
+ */
1990
+ async batchClose(params: BatchCloseTasksParams): Promise<BatchCloseTasksResult> {
1991
+ const hasFilter =
1992
+ params.status ||
1993
+ params.type ||
1994
+ params.priority ||
1995
+ params.parent_id ||
1996
+ params.created_id ||
1997
+ params.assigned_id ||
1998
+ params.project_id ||
1999
+ params.tag_id ||
2000
+ params.older_than ||
2001
+ params.newer_than ||
2002
+ (params.ids && params.ids.length > 0);
2003
+ if (!hasFilter) {
2004
+ throw new Error('At least one filter or ids is required for batch close');
2005
+ }
2006
+
2007
+ if (params.limit !== undefined && params.limit > MAX_BATCH_DELETE_LIMIT) {
2008
+ throw new Error(
2009
+ `Batch close limit must not exceed ${MAX_BATCH_DELETE_LIMIT} (got ${params.limit})`
2010
+ );
2011
+ }
2012
+
2013
+ const url = buildUrl(this.#baseUrl, `/task/close/batch`);
2014
+ const signal = AbortSignal.timeout(60_000);
2015
+
2016
+ const body: Record<string, unknown> = {};
2017
+ if (params.status) body.status = normalizeTaskStatus(params.status);
2018
+ if (params.type) body.type = params.type;
2019
+ if (params.priority) body.priority = params.priority;
2020
+ if (params.parent_id) body.parent_id = params.parent_id;
2021
+ if (params.created_id) body.created_id = params.created_id;
2022
+ if (params.assigned_id) body.assigned_id = params.assigned_id;
2023
+ if (params.project_id) body.project_id = params.project_id;
2024
+ if (params.tag_id) body.tag_id = params.tag_id;
2025
+ if (params.older_than) body.older_than = params.older_than;
2026
+ if (params.newer_than) body.newer_than = params.newer_than;
2027
+ if (params.ids && params.ids.length > 0) body.ids = params.ids;
2028
+ if (params.limit !== undefined) body.limit = params.limit;
2029
+ if (params.closed_id) body.closed_id = params.closed_id;
2030
+ if (params.closer) body.closer = params.closer;
2031
+ if (params.dry_run !== undefined) body.dry_run = params.dry_run;
2032
+
2033
+ const res = await this.#adapter.invoke<TaskResponse<BatchCloseTasksResult>>(url, {
2034
+ method: 'POST',
2035
+ body: safeStringify(body),
2036
+ headers: { 'Content-Type': 'application/json' },
2037
+ signal,
2038
+ telemetry: {
2039
+ name: 'agentuity.task.batchClose',
2040
+ attributes: {
2041
+ ...(params.status ? { status: normalizeTaskStatus(params.status) } : {}),
2042
+ ...(params.dry_run !== undefined ? { dry_run: String(params.dry_run) } : {}),
2043
+ },
2044
+ },
2045
+ });
2046
+
2047
+ if (res.ok) {
2048
+ if (res.data.success) {
2049
+ return res.data.data;
2050
+ }
2051
+ throw new TaskStorageResponseError({
2052
+ status: res.response.status,
2053
+ message: res.data.message,
2054
+ });
2055
+ }
2056
+
2057
+ throw await toServiceException('POST', url, res.response);
2058
+ }
2059
+
1614
2060
  /**
1615
2061
  * Create a comment on a task.
1616
2062
  *