@agentuity/core 2.0.5 → 2.0.7

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.
@@ -115,6 +115,7 @@ export const TaskSchema = z.object({
115
115
  created_id: z.string().describe('ID of the user who created the task.'),
116
116
  assigned_id: z.string().optional().describe('ID of the user the task is assigned to.'),
117
117
  closed_id: z.string().optional().describe('ID of the user who closed the task.'),
118
+ deleted: z.boolean().optional().describe('Whether this task has been soft-deleted.'),
118
119
  creator: z
119
120
  .lazy(() => UserEntityRefSchema)
120
121
  .optional()
@@ -291,6 +292,18 @@ export const UpdateTaskParamsSchema = z.object({
291
292
  /** Reference to the project this task belongs to. */
292
293
  project: EntityRefSchema.optional().describe('Reference to the project this task belongs to.'),
293
294
  });
295
+ /**
296
+ * Additional fields to include in the task list response.
297
+ * By default, list returns a reduced summary shape for performance.
298
+ */
299
+ export const TaskIncludeFieldSchema = z.enum([
300
+ 'description',
301
+ 'metadata',
302
+ 'tags',
303
+ 'subtask_count',
304
+ 'created_id',
305
+ 'deleted',
306
+ ]);
294
307
  /**
295
308
  * Parameters for filtering and paginating the task list.
296
309
  */
@@ -317,6 +330,15 @@ export const ListTasksParamsSchema = z.object({
317
330
  * @default false
318
331
  */
319
332
  deleted: z.boolean().optional().describe('Filter for soft-deleted tasks.'),
333
+ /**
334
+ * Additional fields to include in the response.
335
+ * By default, list returns a reduced summary shape.
336
+ * Use this to include: description, metadata, tags, subtask_count, created_id, deleted.
337
+ */
338
+ include: z
339
+ .array(TaskIncludeFieldSchema)
340
+ .optional()
341
+ .describe('Additional fields to include in the response.'),
320
342
  /**
321
343
  * Sort field. Prefix with `-` for descending order.
322
344
  *
@@ -387,6 +409,151 @@ export const BatchDeleteTasksResultSchema = z.object({
387
409
  /** Total number of tasks deleted. */
388
410
  count: z.number().describe('Total number of tasks deleted.'),
389
411
  });
412
+ /**
413
+ * Parameters for batch-updating tasks by filter.
414
+ * At least one filter must be provided. At least one update field must be provided.
415
+ */
416
+ export const BatchUpdateTasksParamsSchema = z.object({
417
+ /** Filter by task status. */
418
+ status: TaskStatusSchema.optional().describe('Filter by task status.'),
419
+ /** Filter by task type. */
420
+ type: TaskTypeSchema.optional().describe('Filter by task type.'),
421
+ /** Filter by priority level. */
422
+ priority: TaskPrioritySchema.optional().describe('Filter by priority level.'),
423
+ /** Filter by parent task ID. */
424
+ parent_id: z.string().optional().describe('Filter by parent task ID.'),
425
+ /** Filter by creator ID. */
426
+ created_id: z.string().optional().describe('Filter by creator ID.'),
427
+ /** Filter by assigned user ID. */
428
+ assigned_id: z.string().optional().describe('Filter by assigned user ID.'),
429
+ /** Filter by project ID. */
430
+ project_id: z.string().optional().describe('Filter by project ID.'),
431
+ /** Filter by tag ID. */
432
+ tag_id: z.string().optional().describe('Filter by tag ID.'),
433
+ /**
434
+ * Filter for tasks older than this duration.
435
+ * Accepts Go-style duration strings: `'30m'`, `'24h'`, `'7d'`, `'2w'`.
436
+ */
437
+ older_than: z.string().optional().describe('Filter for tasks older than this duration.'),
438
+ /** Specific task IDs to update (alternative to filters). */
439
+ ids: z.array(z.string()).optional().describe('Specific task IDs to update.'),
440
+ /**
441
+ * Maximum number of tasks to update.
442
+ * @default 50
443
+ * @maximum 200
444
+ */
445
+ limit: z.number().optional().describe('Maximum number of tasks to update.'),
446
+ // Update fields - at least one must be provided
447
+ /** New status to set. */
448
+ new_status: TaskStatusSchema.optional().describe('New status to set.'),
449
+ /** New priority to set. */
450
+ new_priority: TaskPrioritySchema.optional().describe('New priority to set.'),
451
+ /** New assigned user ID to set. */
452
+ new_assigned_id: z.string().optional().describe('New assigned user ID to set.'),
453
+ /** New assignee entity reference. */
454
+ new_assignee: UserEntityRefSchema.optional().describe('New assignee entity reference.'),
455
+ /** New title to set. */
456
+ new_title: z.string().optional().describe('New title to set.'),
457
+ /** New description to set. */
458
+ new_description: z.string().optional().describe('New description to set.'),
459
+ /** New metadata to set (merged with existing). */
460
+ new_metadata: z.record(z.string(), z.unknown()).optional().describe('New metadata to set.'),
461
+ /** New type to set. */
462
+ new_type: TaskTypeSchema.optional().describe('New type to set.'),
463
+ /**
464
+ * Filter for tasks newer than this duration.
465
+ * Accepts Go-style duration strings: `'30m'`, `'24h'`, `'7d'`, `'2w'`.
466
+ */
467
+ newer_than: z.string().optional().describe('Filter for tasks newer than this duration.'),
468
+ /** Whether this is a dry run (preview only). */
469
+ dry_run: z.boolean().optional().describe('Whether this is a dry run (preview only).'),
470
+ });
471
+ /**
472
+ * A single task that was updated in a batch operation.
473
+ */
474
+ export const BatchUpdatedTaskSchema = z.object({
475
+ id: z.string().describe('The ID of the updated task.'),
476
+ title: z.string().describe('The title of the updated task.'),
477
+ status: TaskStatusSchema.describe('The new status of the task.'),
478
+ priority: TaskPrioritySchema.describe('The new priority of the task.'),
479
+ });
480
+ /**
481
+ * Result of a batch update operation.
482
+ */
483
+ export const BatchUpdateTasksResultSchema = z.object({
484
+ /** Array of tasks that were updated. */
485
+ updated: z.array(BatchUpdatedTaskSchema).describe('Array of tasks that were updated.'),
486
+ /** Total number of tasks updated. */
487
+ count: z.number().describe('Total number of tasks updated.'),
488
+ /** Whether this was a dry run. */
489
+ dry_run: z.boolean().describe('Whether this was a dry run.'),
490
+ });
491
+ /**
492
+ * Parameters for batch-closing tasks by filter.
493
+ * At least one filter must be provided.
494
+ */
495
+ export const BatchCloseTasksParamsSchema = z.object({
496
+ /** Filter by task status. */
497
+ status: TaskStatusSchema.optional().describe('Filter by task status.'),
498
+ /** Filter by task type. */
499
+ type: TaskTypeSchema.optional().describe('Filter by task type.'),
500
+ /** Filter by priority level. */
501
+ priority: TaskPrioritySchema.optional().describe('Filter by priority level.'),
502
+ /** Filter by parent task ID. */
503
+ parent_id: z.string().optional().describe('Filter by parent task ID.'),
504
+ /** Filter by creator ID. */
505
+ created_id: z.string().optional().describe('Filter by creator ID.'),
506
+ /** Filter by assigned user ID. */
507
+ assigned_id: z.string().optional().describe('Filter by assigned user ID.'),
508
+ /** Filter by project ID. */
509
+ project_id: z.string().optional().describe('Filter by project ID.'),
510
+ /** Filter by tag ID. */
511
+ tag_id: z.string().optional().describe('Filter by tag ID.'),
512
+ /**
513
+ * Filter for tasks older than this duration.
514
+ * Accepts Go-style duration strings: `'30m'`, `'24h'`, `'7d'`, `'2w'`.
515
+ */
516
+ older_than: z.string().optional().describe('Filter for tasks older than this duration.'),
517
+ /**
518
+ * Filter for tasks newer than this duration.
519
+ * Accepts Go-style duration strings: `'30m'`, `'24h'`, `'7d'`, `'2w'`.
520
+ */
521
+ newer_than: z.string().optional().describe('Filter for tasks newer than this duration.'),
522
+ /** Specific task IDs to close (alternative to filters). */
523
+ ids: z.array(z.string()).optional().describe('Specific task IDs to close.'),
524
+ /**
525
+ * Maximum number of tasks to close.
526
+ * @default 50
527
+ * @maximum 200
528
+ */
529
+ limit: z.number().optional().describe('Maximum number of tasks to close.'),
530
+ /** ID of the user closing the tasks. */
531
+ closed_id: z.string().optional().describe('ID of the user closing the tasks.'),
532
+ /** Closer entity reference. */
533
+ closer: UserEntityRefSchema.optional().describe('Closer entity reference.'),
534
+ /** Whether this is a dry run (preview only). */
535
+ dry_run: z.boolean().optional().describe('Whether this is a dry run (preview only).'),
536
+ });
537
+ /**
538
+ * A single task that was closed in a batch operation.
539
+ */
540
+ export const BatchClosedTaskSchema = z.object({
541
+ id: z.string().describe('The ID of the closed task.'),
542
+ title: z.string().describe('The title of the closed task.'),
543
+ status: TaskStatusSchema.describe('The status of the task (done).'),
544
+ closed_date: z.string().optional().describe('ISO 8601 timestamp when the task was closed.'),
545
+ });
546
+ /**
547
+ * Result of a batch close operation.
548
+ */
549
+ export const BatchCloseTasksResultSchema = z.object({
550
+ /** Array of tasks that were closed. */
551
+ closed: z.array(BatchClosedTaskSchema).describe('Array of tasks that were closed.'),
552
+ /** Total number of tasks closed. */
553
+ count: z.number().describe('Total number of tasks closed.'),
554
+ /** Whether this was a dry run. */
555
+ dry_run: z.boolean().describe('Whether this was a dry run.'),
556
+ });
390
557
  /**
391
558
  * Paginated list of changelog entries for a task.
392
559
  */
@@ -735,6 +902,9 @@ export class TaskStorageService {
735
902
  queryParams.set('tag_id', params.tag_id);
736
903
  if (params?.deleted !== undefined)
737
904
  queryParams.set('deleted', String(params.deleted));
905
+ if (params?.include && params.include.length > 0) {
906
+ queryParams.set('include', params.include.join(','));
907
+ }
738
908
  if (params?.sort)
739
909
  queryParams.set('sort', params.sort);
740
910
  if (params?.order)
@@ -1021,6 +1191,218 @@ export class TaskStorageService {
1021
1191
  }
1022
1192
  throw await toServiceException('POST', url, res.response);
1023
1193
  }
1194
+ /**
1195
+ * Batch update tasks matching the given filters.
1196
+ * At least one filter (or ids) must be provided. At least one update field must be provided.
1197
+ *
1198
+ * @param params - Filters to select tasks and fields to update
1199
+ * @returns The list of updated tasks and count
1200
+ * @throws {@link ServiceException} if the API request fails
1201
+ *
1202
+ * @example
1203
+ * ```typescript
1204
+ * const result = await tasks.batchUpdate({
1205
+ * status: 'open',
1206
+ * new_status: 'in_progress',
1207
+ * new_priority: 'high',
1208
+ * limit: 50,
1209
+ * });
1210
+ * console.log(`Updated ${result.count} tasks`);
1211
+ * ```
1212
+ */
1213
+ async batchUpdate(params) {
1214
+ const hasFilter = params.status ||
1215
+ params.type ||
1216
+ params.priority ||
1217
+ params.parent_id ||
1218
+ params.created_id ||
1219
+ params.assigned_id ||
1220
+ params.project_id ||
1221
+ params.tag_id ||
1222
+ params.older_than ||
1223
+ params.newer_than ||
1224
+ (params.ids && params.ids.length > 0);
1225
+ if (!hasFilter) {
1226
+ throw new Error('At least one filter or ids is required for batch update');
1227
+ }
1228
+ const hasUpdate = params.new_status ||
1229
+ params.new_priority ||
1230
+ params.new_assigned_id ||
1231
+ params.new_assignee ||
1232
+ params.new_title ||
1233
+ params.new_description ||
1234
+ params.new_metadata ||
1235
+ params.new_type;
1236
+ if (!hasUpdate) {
1237
+ throw new Error('At least one update field is required for batch update');
1238
+ }
1239
+ if (params.limit !== undefined && params.limit > MAX_BATCH_DELETE_LIMIT) {
1240
+ throw new Error(`Batch update limit must not exceed ${MAX_BATCH_DELETE_LIMIT} (got ${params.limit})`);
1241
+ }
1242
+ const url = buildUrl(this.#baseUrl, `/task/update/batch`);
1243
+ const signal = AbortSignal.timeout(60_000);
1244
+ const body = {};
1245
+ if (params.status)
1246
+ body.status = normalizeTaskStatus(params.status);
1247
+ if (params.type)
1248
+ body.type = params.type;
1249
+ if (params.priority)
1250
+ body.priority = params.priority;
1251
+ if (params.parent_id)
1252
+ body.parent_id = params.parent_id;
1253
+ if (params.created_id)
1254
+ body.created_id = params.created_id;
1255
+ if (params.assigned_id)
1256
+ body.assigned_id = params.assigned_id;
1257
+ if (params.project_id)
1258
+ body.project_id = params.project_id;
1259
+ if (params.tag_id)
1260
+ body.tag_id = params.tag_id;
1261
+ if (params.older_than)
1262
+ body.older_than = params.older_than;
1263
+ if (params.newer_than)
1264
+ body.newer_than = params.newer_than;
1265
+ if (params.ids && params.ids.length > 0)
1266
+ body.ids = params.ids;
1267
+ if (params.limit !== undefined)
1268
+ body.limit = params.limit;
1269
+ if (params.new_status)
1270
+ body.new_status = normalizeTaskStatus(params.new_status);
1271
+ if (params.new_priority)
1272
+ body.new_priority = params.new_priority;
1273
+ if (params.new_assigned_id)
1274
+ body.new_assigned_id = params.new_assigned_id;
1275
+ if (params.new_assignee)
1276
+ body.new_assignee = params.new_assignee;
1277
+ if (params.new_title)
1278
+ body.new_title = params.new_title;
1279
+ if (params.new_description)
1280
+ body.new_description = params.new_description;
1281
+ if (params.new_metadata)
1282
+ body.new_metadata = params.new_metadata;
1283
+ if (params.new_type)
1284
+ body.new_type = params.new_type;
1285
+ if (params.dry_run !== undefined)
1286
+ body.dry_run = params.dry_run;
1287
+ const res = await this.#adapter.invoke(url, {
1288
+ method: 'POST',
1289
+ body: safeStringify(body),
1290
+ headers: { 'Content-Type': 'application/json' },
1291
+ signal,
1292
+ telemetry: {
1293
+ name: 'agentuity.task.batchUpdate',
1294
+ attributes: {
1295
+ ...(params.status ? { status: normalizeTaskStatus(params.status) } : {}),
1296
+ ...(params.new_status ? { new_status: normalizeTaskStatus(params.new_status) } : {}),
1297
+ ...(params.dry_run !== undefined ? { dry_run: String(params.dry_run) } : {}),
1298
+ },
1299
+ },
1300
+ });
1301
+ if (res.ok) {
1302
+ if (res.data.success) {
1303
+ return res.data.data;
1304
+ }
1305
+ throw new TaskStorageResponseError({
1306
+ status: res.response.status,
1307
+ message: res.data.message,
1308
+ });
1309
+ }
1310
+ throw await toServiceException('POST', url, res.response);
1311
+ }
1312
+ /**
1313
+ * Batch close tasks matching the given filters.
1314
+ * At least one filter (or ids) must be provided. Sets status to done and records closed_date.
1315
+ *
1316
+ * @param params - Filters to select which tasks to close
1317
+ * @returns The list of closed tasks and count
1318
+ * @throws {@link ServiceException} if the API request fails
1319
+ *
1320
+ * @example
1321
+ * ```typescript
1322
+ * const result = await tasks.batchClose({
1323
+ * status: 'in_progress',
1324
+ * older_than: '7d',
1325
+ * limit: 50,
1326
+ * dry_run: true,
1327
+ * });
1328
+ * console.log(`Would close ${result.count} tasks`);
1329
+ * ```
1330
+ */
1331
+ async batchClose(params) {
1332
+ const hasFilter = params.status ||
1333
+ params.type ||
1334
+ params.priority ||
1335
+ params.parent_id ||
1336
+ params.created_id ||
1337
+ params.assigned_id ||
1338
+ params.project_id ||
1339
+ params.tag_id ||
1340
+ params.older_than ||
1341
+ params.newer_than ||
1342
+ (params.ids && params.ids.length > 0);
1343
+ if (!hasFilter) {
1344
+ throw new Error('At least one filter or ids is required for batch close');
1345
+ }
1346
+ if (params.limit !== undefined && params.limit > MAX_BATCH_DELETE_LIMIT) {
1347
+ throw new Error(`Batch close limit must not exceed ${MAX_BATCH_DELETE_LIMIT} (got ${params.limit})`);
1348
+ }
1349
+ const url = buildUrl(this.#baseUrl, `/task/close/batch`);
1350
+ const signal = AbortSignal.timeout(60_000);
1351
+ const body = {};
1352
+ if (params.status)
1353
+ body.status = normalizeTaskStatus(params.status);
1354
+ if (params.type)
1355
+ body.type = params.type;
1356
+ if (params.priority)
1357
+ body.priority = params.priority;
1358
+ if (params.parent_id)
1359
+ body.parent_id = params.parent_id;
1360
+ if (params.created_id)
1361
+ body.created_id = params.created_id;
1362
+ if (params.assigned_id)
1363
+ body.assigned_id = params.assigned_id;
1364
+ if (params.project_id)
1365
+ body.project_id = params.project_id;
1366
+ if (params.tag_id)
1367
+ body.tag_id = params.tag_id;
1368
+ if (params.older_than)
1369
+ body.older_than = params.older_than;
1370
+ if (params.newer_than)
1371
+ body.newer_than = params.newer_than;
1372
+ if (params.ids && params.ids.length > 0)
1373
+ body.ids = params.ids;
1374
+ if (params.limit !== undefined)
1375
+ body.limit = params.limit;
1376
+ if (params.closed_id)
1377
+ body.closed_id = params.closed_id;
1378
+ if (params.closer)
1379
+ body.closer = params.closer;
1380
+ if (params.dry_run !== undefined)
1381
+ body.dry_run = params.dry_run;
1382
+ const res = await this.#adapter.invoke(url, {
1383
+ method: 'POST',
1384
+ body: safeStringify(body),
1385
+ headers: { 'Content-Type': 'application/json' },
1386
+ signal,
1387
+ telemetry: {
1388
+ name: 'agentuity.task.batchClose',
1389
+ attributes: {
1390
+ ...(params.status ? { status: normalizeTaskStatus(params.status) } : {}),
1391
+ ...(params.dry_run !== undefined ? { dry_run: String(params.dry_run) } : {}),
1392
+ },
1393
+ },
1394
+ });
1395
+ if (res.ok) {
1396
+ if (res.data.success) {
1397
+ return res.data.data;
1398
+ }
1399
+ throw new TaskStorageResponseError({
1400
+ status: res.response.status,
1401
+ message: res.data.message,
1402
+ });
1403
+ }
1404
+ throw await toServiceException('POST', url, res.response);
1405
+ }
1024
1406
  /**
1025
1407
  * Create a comment on a task.
1026
1408
  *