@hasna/todos 0.9.28 → 0.9.29
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.
- package/dist/cli/index.js +141 -129
- package/dist/index.js +22 -10
- package/dist/mcp/index.js +22 -10
- package/dist/server/index.js +22 -10
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3198,7 +3198,18 @@ function updateTask(id, input, db) {
|
|
|
3198
3198
|
logTaskChange(id, "update", "assigned_to", task.assigned_to, input.assigned_to, agentId, d);
|
|
3199
3199
|
if (input.approved_by !== undefined)
|
|
3200
3200
|
logTaskChange(id, "approve", "approved_by", null, input.approved_by, agentId, d);
|
|
3201
|
-
return
|
|
3201
|
+
return {
|
|
3202
|
+
...task,
|
|
3203
|
+
...Object.fromEntries(Object.entries(input).filter(([, v]) => v !== undefined)),
|
|
3204
|
+
tags: input.tags ?? task.tags,
|
|
3205
|
+
metadata: input.metadata ?? task.metadata,
|
|
3206
|
+
version: task.version + 1,
|
|
3207
|
+
updated_at: now(),
|
|
3208
|
+
completed_at: input.status === "completed" ? now() : task.completed_at,
|
|
3209
|
+
requires_approval: input.requires_approval !== undefined ? input.requires_approval : task.requires_approval,
|
|
3210
|
+
approved_by: input.approved_by ?? task.approved_by,
|
|
3211
|
+
approved_at: input.approved_by ? now() : task.approved_at
|
|
3212
|
+
};
|
|
3202
3213
|
}
|
|
3203
3214
|
function deleteTask(id, db) {
|
|
3204
3215
|
const d = db || getDatabase();
|
|
@@ -3220,6 +3231,9 @@ function getBlockingDeps(id, db) {
|
|
|
3220
3231
|
}
|
|
3221
3232
|
function startTask(id, agentId, db) {
|
|
3222
3233
|
const d = db || getDatabase();
|
|
3234
|
+
const task = getTask(id, d);
|
|
3235
|
+
if (!task)
|
|
3236
|
+
throw new TaskNotFoundError(id);
|
|
3223
3237
|
const blocking = getBlockingDeps(id, d);
|
|
3224
3238
|
if (blocking.length > 0) {
|
|
3225
3239
|
const blockerIds = blocking.map((b) => b.id.slice(0, 8)).join(", ");
|
|
@@ -3230,15 +3244,12 @@ function startTask(id, agentId, db) {
|
|
|
3230
3244
|
const result = d.run(`UPDATE tasks SET status = 'in_progress', assigned_to = ?, locked_by = ?, locked_at = ?, version = version + 1, updated_at = ?
|
|
3231
3245
|
WHERE id = ? AND (locked_by IS NULL OR locked_by = ? OR locked_at < ?)`, [agentId, agentId, timestamp, timestamp, id, agentId, cutoff]);
|
|
3232
3246
|
if (result.changes === 0) {
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
throw new TaskNotFoundError(id);
|
|
3236
|
-
if (current.locked_by && current.locked_by !== agentId && !isLockExpired(current.locked_at)) {
|
|
3237
|
-
throw new LockError(id, current.locked_by);
|
|
3247
|
+
if (task.locked_by && task.locked_by !== agentId && !isLockExpired(task.locked_at)) {
|
|
3248
|
+
throw new LockError(id, task.locked_by);
|
|
3238
3249
|
}
|
|
3239
3250
|
}
|
|
3240
3251
|
logTaskChange(id, "start", "status", "pending", "in_progress", agentId, d);
|
|
3241
|
-
return
|
|
3252
|
+
return { ...task, status: "in_progress", assigned_to: agentId, locked_by: agentId, locked_at: timestamp, version: task.version + 1, updated_at: timestamp };
|
|
3242
3253
|
}
|
|
3243
3254
|
function completeTask(id, agentId, db, evidence) {
|
|
3244
3255
|
const d = db || getDatabase();
|
|
@@ -3250,14 +3261,15 @@ function completeTask(id, agentId, db, evidence) {
|
|
|
3250
3261
|
}
|
|
3251
3262
|
checkCompletionGuard(task, agentId || null, d);
|
|
3252
3263
|
if (evidence) {
|
|
3253
|
-
const
|
|
3254
|
-
d.run("UPDATE tasks SET metadata = ? WHERE id = ?", [JSON.stringify(
|
|
3264
|
+
const meta2 = { ...task.metadata, _evidence: evidence };
|
|
3265
|
+
d.run("UPDATE tasks SET metadata = ? WHERE id = ?", [JSON.stringify(meta2), id]);
|
|
3255
3266
|
}
|
|
3256
3267
|
const timestamp = now();
|
|
3257
3268
|
d.run(`UPDATE tasks SET status = 'completed', locked_by = NULL, locked_at = NULL, completed_at = ?, version = version + 1, updated_at = ?
|
|
3258
3269
|
WHERE id = ?`, [timestamp, timestamp, id]);
|
|
3259
3270
|
logTaskChange(id, "complete", "status", task.status, "completed", agentId || null, d);
|
|
3260
|
-
|
|
3271
|
+
const meta = evidence ? { ...task.metadata, _evidence: evidence } : task.metadata;
|
|
3272
|
+
return { ...task, status: "completed", locked_by: null, locked_at: null, completed_at: timestamp, version: task.version + 1, updated_at: timestamp, metadata: meta };
|
|
3261
3273
|
}
|
|
3262
3274
|
function lockTask(id, agentId, db) {
|
|
3263
3275
|
const d = db || getDatabase();
|
|
@@ -8363,22 +8375,22 @@ var init_mcp = __esm(() => {
|
|
|
8363
8375
|
version: "0.9.15"
|
|
8364
8376
|
});
|
|
8365
8377
|
server.tool("create_task", "Create a new task", {
|
|
8366
|
-
title: exports_external.string()
|
|
8367
|
-
description: exports_external.string().optional()
|
|
8368
|
-
project_id: exports_external.string().optional()
|
|
8369
|
-
parent_id: exports_external.string().optional()
|
|
8370
|
-
priority: exports_external.enum(["low", "medium", "high", "critical"]).optional()
|
|
8371
|
-
status: exports_external.enum(["pending", "in_progress", "completed", "failed", "cancelled"]).optional()
|
|
8372
|
-
agent_id: exports_external.string().optional()
|
|
8373
|
-
assigned_to: exports_external.string().optional()
|
|
8374
|
-
session_id: exports_external.string().optional()
|
|
8375
|
-
working_dir: exports_external.string().optional()
|
|
8376
|
-
plan_id: exports_external.string().optional()
|
|
8377
|
-
task_list_id: exports_external.string().optional()
|
|
8378
|
-
tags: exports_external.array(exports_external.string()).optional()
|
|
8379
|
-
metadata: exports_external.record(exports_external.unknown()).optional()
|
|
8380
|
-
estimated_minutes: exports_external.number().optional()
|
|
8381
|
-
requires_approval: exports_external.boolean().optional()
|
|
8378
|
+
title: exports_external.string(),
|
|
8379
|
+
description: exports_external.string().optional(),
|
|
8380
|
+
project_id: exports_external.string().optional(),
|
|
8381
|
+
parent_id: exports_external.string().optional(),
|
|
8382
|
+
priority: exports_external.enum(["low", "medium", "high", "critical"]).optional(),
|
|
8383
|
+
status: exports_external.enum(["pending", "in_progress", "completed", "failed", "cancelled"]).optional(),
|
|
8384
|
+
agent_id: exports_external.string().optional(),
|
|
8385
|
+
assigned_to: exports_external.string().optional(),
|
|
8386
|
+
session_id: exports_external.string().optional(),
|
|
8387
|
+
working_dir: exports_external.string().optional(),
|
|
8388
|
+
plan_id: exports_external.string().optional(),
|
|
8389
|
+
task_list_id: exports_external.string().optional(),
|
|
8390
|
+
tags: exports_external.array(exports_external.string()).optional(),
|
|
8391
|
+
metadata: exports_external.record(exports_external.unknown()).optional(),
|
|
8392
|
+
estimated_minutes: exports_external.number().optional(),
|
|
8393
|
+
requires_approval: exports_external.boolean().optional()
|
|
8382
8394
|
}, async (params) => {
|
|
8383
8395
|
try {
|
|
8384
8396
|
const resolved = { ...params };
|
|
@@ -8397,19 +8409,19 @@ var init_mcp = __esm(() => {
|
|
|
8397
8409
|
}
|
|
8398
8410
|
});
|
|
8399
8411
|
server.tool("list_tasks", "List tasks with optional filters", {
|
|
8400
|
-
project_id: exports_external.string().optional()
|
|
8412
|
+
project_id: exports_external.string().optional(),
|
|
8401
8413
|
status: exports_external.union([
|
|
8402
8414
|
exports_external.enum(["pending", "in_progress", "completed", "failed", "cancelled"]),
|
|
8403
8415
|
exports_external.array(exports_external.enum(["pending", "in_progress", "completed", "failed", "cancelled"]))
|
|
8404
|
-
]).optional()
|
|
8416
|
+
]).optional(),
|
|
8405
8417
|
priority: exports_external.union([
|
|
8406
8418
|
exports_external.enum(["low", "medium", "high", "critical"]),
|
|
8407
8419
|
exports_external.array(exports_external.enum(["low", "medium", "high", "critical"]))
|
|
8408
|
-
]).optional()
|
|
8409
|
-
assigned_to: exports_external.string().optional()
|
|
8410
|
-
tags: exports_external.array(exports_external.string()).optional()
|
|
8411
|
-
plan_id: exports_external.string().optional()
|
|
8412
|
-
task_list_id: exports_external.string().optional()
|
|
8420
|
+
]).optional(),
|
|
8421
|
+
assigned_to: exports_external.string().optional(),
|
|
8422
|
+
tags: exports_external.array(exports_external.string()).optional(),
|
|
8423
|
+
plan_id: exports_external.string().optional(),
|
|
8424
|
+
task_list_id: exports_external.string().optional()
|
|
8413
8425
|
}, async (params) => {
|
|
8414
8426
|
try {
|
|
8415
8427
|
const resolved = { ...params };
|
|
@@ -8436,7 +8448,7 @@ ${text}` }] };
|
|
|
8436
8448
|
}
|
|
8437
8449
|
});
|
|
8438
8450
|
server.tool("get_task", "Get full task details with relations", {
|
|
8439
|
-
id: exports_external.string()
|
|
8451
|
+
id: exports_external.string()
|
|
8440
8452
|
}, async ({ id }) => {
|
|
8441
8453
|
try {
|
|
8442
8454
|
const resolvedId = resolveId(id);
|
|
@@ -8484,17 +8496,17 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8484
8496
|
}
|
|
8485
8497
|
});
|
|
8486
8498
|
server.tool("update_task", "Update task fields. Version required for optimistic locking.", {
|
|
8487
|
-
id: exports_external.string()
|
|
8488
|
-
version: exports_external.number()
|
|
8489
|
-
title: exports_external.string().optional()
|
|
8490
|
-
description: exports_external.string().optional()
|
|
8491
|
-
status: exports_external.enum(["pending", "in_progress", "completed", "failed", "cancelled"]).optional()
|
|
8492
|
-
priority: exports_external.enum(["low", "medium", "high", "critical"]).optional()
|
|
8493
|
-
assigned_to: exports_external.string().optional()
|
|
8494
|
-
tags: exports_external.array(exports_external.string()).optional()
|
|
8495
|
-
metadata: exports_external.record(exports_external.unknown()).optional()
|
|
8496
|
-
plan_id: exports_external.string().optional()
|
|
8497
|
-
task_list_id: exports_external.string().optional()
|
|
8499
|
+
id: exports_external.string(),
|
|
8500
|
+
version: exports_external.number(),
|
|
8501
|
+
title: exports_external.string().optional(),
|
|
8502
|
+
description: exports_external.string().optional(),
|
|
8503
|
+
status: exports_external.enum(["pending", "in_progress", "completed", "failed", "cancelled"]).optional(),
|
|
8504
|
+
priority: exports_external.enum(["low", "medium", "high", "critical"]).optional(),
|
|
8505
|
+
assigned_to: exports_external.string().optional(),
|
|
8506
|
+
tags: exports_external.array(exports_external.string()).optional(),
|
|
8507
|
+
metadata: exports_external.record(exports_external.unknown()).optional(),
|
|
8508
|
+
plan_id: exports_external.string().optional(),
|
|
8509
|
+
task_list_id: exports_external.string().optional()
|
|
8498
8510
|
}, async ({ id, ...rest }) => {
|
|
8499
8511
|
try {
|
|
8500
8512
|
const resolvedId = resolveId(id);
|
|
@@ -8505,7 +8517,7 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8505
8517
|
}
|
|
8506
8518
|
});
|
|
8507
8519
|
server.tool("delete_task", "Delete a task permanently", {
|
|
8508
|
-
id: exports_external.string()
|
|
8520
|
+
id: exports_external.string()
|
|
8509
8521
|
}, async ({ id }) => {
|
|
8510
8522
|
try {
|
|
8511
8523
|
const resolvedId = resolveId(id);
|
|
@@ -8521,8 +8533,8 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8521
8533
|
}
|
|
8522
8534
|
});
|
|
8523
8535
|
server.tool("start_task", "Claim, lock, and set task status to in_progress.", {
|
|
8524
|
-
id: exports_external.string()
|
|
8525
|
-
agent_id: exports_external.string()
|
|
8536
|
+
id: exports_external.string(),
|
|
8537
|
+
agent_id: exports_external.string()
|
|
8526
8538
|
}, async ({ id, agent_id }) => {
|
|
8527
8539
|
try {
|
|
8528
8540
|
const resolvedId = resolveId(id);
|
|
@@ -8533,8 +8545,8 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8533
8545
|
}
|
|
8534
8546
|
});
|
|
8535
8547
|
server.tool("complete_task", "Mark task completed and release lock.", {
|
|
8536
|
-
id: exports_external.string()
|
|
8537
|
-
agent_id: exports_external.string().optional()
|
|
8548
|
+
id: exports_external.string(),
|
|
8549
|
+
agent_id: exports_external.string().optional()
|
|
8538
8550
|
}, async ({ id, agent_id }) => {
|
|
8539
8551
|
try {
|
|
8540
8552
|
const resolvedId = resolveId(id);
|
|
@@ -8545,8 +8557,8 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8545
8557
|
}
|
|
8546
8558
|
});
|
|
8547
8559
|
server.tool("lock_task", "Acquire exclusive lock on a task", {
|
|
8548
|
-
id: exports_external.string()
|
|
8549
|
-
agent_id: exports_external.string()
|
|
8560
|
+
id: exports_external.string(),
|
|
8561
|
+
agent_id: exports_external.string()
|
|
8550
8562
|
}, async ({ id, agent_id }) => {
|
|
8551
8563
|
try {
|
|
8552
8564
|
const resolvedId = resolveId(id);
|
|
@@ -8560,8 +8572,8 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8560
8572
|
}
|
|
8561
8573
|
});
|
|
8562
8574
|
server.tool("unlock_task", "Release exclusive lock on a task", {
|
|
8563
|
-
id: exports_external.string()
|
|
8564
|
-
agent_id: exports_external.string().optional()
|
|
8575
|
+
id: exports_external.string(),
|
|
8576
|
+
agent_id: exports_external.string().optional()
|
|
8565
8577
|
}, async ({ id, agent_id }) => {
|
|
8566
8578
|
try {
|
|
8567
8579
|
const resolvedId = resolveId(id);
|
|
@@ -8572,8 +8584,8 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8572
8584
|
}
|
|
8573
8585
|
});
|
|
8574
8586
|
server.tool("add_dependency", "Add a dependency: task_id depends on depends_on.", {
|
|
8575
|
-
task_id: exports_external.string()
|
|
8576
|
-
depends_on: exports_external.string()
|
|
8587
|
+
task_id: exports_external.string(),
|
|
8588
|
+
depends_on: exports_external.string()
|
|
8577
8589
|
}, async ({ task_id, depends_on }) => {
|
|
8578
8590
|
try {
|
|
8579
8591
|
const resolvedTaskId = resolveId(task_id);
|
|
@@ -8585,8 +8597,8 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8585
8597
|
}
|
|
8586
8598
|
});
|
|
8587
8599
|
server.tool("remove_dependency", "Remove a dependency between tasks", {
|
|
8588
|
-
task_id: exports_external.string()
|
|
8589
|
-
depends_on: exports_external.string()
|
|
8600
|
+
task_id: exports_external.string(),
|
|
8601
|
+
depends_on: exports_external.string()
|
|
8590
8602
|
}, async ({ task_id, depends_on }) => {
|
|
8591
8603
|
try {
|
|
8592
8604
|
const resolvedTaskId = resolveId(task_id);
|
|
@@ -8603,10 +8615,10 @@ Parent: ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
|
|
|
8603
8615
|
}
|
|
8604
8616
|
});
|
|
8605
8617
|
server.tool("add_comment", "Add a comment/note to a task", {
|
|
8606
|
-
task_id: exports_external.string()
|
|
8607
|
-
content: exports_external.string()
|
|
8608
|
-
agent_id: exports_external.string().optional()
|
|
8609
|
-
session_id: exports_external.string().optional()
|
|
8618
|
+
task_id: exports_external.string(),
|
|
8619
|
+
content: exports_external.string(),
|
|
8620
|
+
agent_id: exports_external.string().optional(),
|
|
8621
|
+
session_id: exports_external.string().optional()
|
|
8610
8622
|
}, async ({ task_id, ...rest }) => {
|
|
8611
8623
|
try {
|
|
8612
8624
|
const resolvedId = resolveId(task_id);
|
|
@@ -8634,10 +8646,10 @@ ${text}` }] };
|
|
|
8634
8646
|
}
|
|
8635
8647
|
});
|
|
8636
8648
|
server.tool("create_project", "Register a new project", {
|
|
8637
|
-
name: exports_external.string()
|
|
8638
|
-
path: exports_external.string()
|
|
8639
|
-
description: exports_external.string().optional()
|
|
8640
|
-
task_list_id: exports_external.string().optional()
|
|
8649
|
+
name: exports_external.string(),
|
|
8650
|
+
path: exports_external.string(),
|
|
8651
|
+
description: exports_external.string().optional(),
|
|
8652
|
+
task_list_id: exports_external.string().optional()
|
|
8641
8653
|
}, async (params) => {
|
|
8642
8654
|
try {
|
|
8643
8655
|
const project = createProject(params);
|
|
@@ -8653,12 +8665,12 @@ ${text}` }] };
|
|
|
8653
8665
|
}
|
|
8654
8666
|
});
|
|
8655
8667
|
server.tool("create_plan", "Create a new plan", {
|
|
8656
|
-
name: exports_external.string()
|
|
8657
|
-
project_id: exports_external.string().optional()
|
|
8658
|
-
description: exports_external.string().optional()
|
|
8659
|
-
status: exports_external.enum(["active", "completed", "archived"]).optional()
|
|
8660
|
-
task_list_id: exports_external.string().optional()
|
|
8661
|
-
agent_id: exports_external.string().optional()
|
|
8668
|
+
name: exports_external.string(),
|
|
8669
|
+
project_id: exports_external.string().optional(),
|
|
8670
|
+
description: exports_external.string().optional(),
|
|
8671
|
+
status: exports_external.enum(["active", "completed", "archived"]).optional(),
|
|
8672
|
+
task_list_id: exports_external.string().optional(),
|
|
8673
|
+
agent_id: exports_external.string().optional()
|
|
8662
8674
|
}, async (params) => {
|
|
8663
8675
|
try {
|
|
8664
8676
|
const resolved = { ...params };
|
|
@@ -8678,7 +8690,7 @@ ${text}` }] };
|
|
|
8678
8690
|
}
|
|
8679
8691
|
});
|
|
8680
8692
|
server.tool("list_plans", "List plans with optional project filter", {
|
|
8681
|
-
project_id: exports_external.string().optional()
|
|
8693
|
+
project_id: exports_external.string().optional()
|
|
8682
8694
|
}, async ({ project_id }) => {
|
|
8683
8695
|
try {
|
|
8684
8696
|
const resolvedProjectId = project_id ? resolveId(project_id, "projects") : undefined;
|
|
@@ -8698,7 +8710,7 @@ ${text}` }] };
|
|
|
8698
8710
|
}
|
|
8699
8711
|
});
|
|
8700
8712
|
server.tool("get_plan", "Get plan details", {
|
|
8701
|
-
id: exports_external.string()
|
|
8713
|
+
id: exports_external.string()
|
|
8702
8714
|
}, async ({ id }) => {
|
|
8703
8715
|
try {
|
|
8704
8716
|
const resolvedId = resolveId(id, "plans");
|
|
@@ -8723,12 +8735,12 @@ ${text}` }] };
|
|
|
8723
8735
|
}
|
|
8724
8736
|
});
|
|
8725
8737
|
server.tool("update_plan", "Update a plan", {
|
|
8726
|
-
id: exports_external.string()
|
|
8727
|
-
name: exports_external.string().optional()
|
|
8728
|
-
description: exports_external.string().optional()
|
|
8729
|
-
status: exports_external.enum(["active", "completed", "archived"]).optional()
|
|
8730
|
-
task_list_id: exports_external.string().optional()
|
|
8731
|
-
agent_id: exports_external.string().optional()
|
|
8738
|
+
id: exports_external.string(),
|
|
8739
|
+
name: exports_external.string().optional(),
|
|
8740
|
+
description: exports_external.string().optional(),
|
|
8741
|
+
status: exports_external.enum(["active", "completed", "archived"]).optional(),
|
|
8742
|
+
task_list_id: exports_external.string().optional(),
|
|
8743
|
+
agent_id: exports_external.string().optional()
|
|
8732
8744
|
}, async ({ id, ...rest }) => {
|
|
8733
8745
|
try {
|
|
8734
8746
|
const resolvedId = resolveId(id, "plans");
|
|
@@ -8747,7 +8759,7 @@ ${text}` }] };
|
|
|
8747
8759
|
}
|
|
8748
8760
|
});
|
|
8749
8761
|
server.tool("delete_plan", "Delete a plan", {
|
|
8750
|
-
id: exports_external.string()
|
|
8762
|
+
id: exports_external.string()
|
|
8751
8763
|
}, async ({ id }) => {
|
|
8752
8764
|
try {
|
|
8753
8765
|
const resolvedId = resolveId(id, "plans");
|
|
@@ -8763,9 +8775,9 @@ ${text}` }] };
|
|
|
8763
8775
|
}
|
|
8764
8776
|
});
|
|
8765
8777
|
server.tool("search_tasks", "Full-text search across task titles, descriptions, tags.", {
|
|
8766
|
-
query: exports_external.string()
|
|
8767
|
-
project_id: exports_external.string().optional()
|
|
8768
|
-
task_list_id: exports_external.string().optional()
|
|
8778
|
+
query: exports_external.string(),
|
|
8779
|
+
project_id: exports_external.string().optional(),
|
|
8780
|
+
task_list_id: exports_external.string().optional()
|
|
8769
8781
|
}, async ({ query, project_id, task_list_id }) => {
|
|
8770
8782
|
try {
|
|
8771
8783
|
const resolvedProjectId = project_id ? resolveId(project_id, "projects") : undefined;
|
|
@@ -8783,12 +8795,12 @@ ${text}` }] };
|
|
|
8783
8795
|
}
|
|
8784
8796
|
});
|
|
8785
8797
|
server.tool("sync", "Sync tasks with an agent task list.", {
|
|
8786
|
-
task_list_id: exports_external.string().optional()
|
|
8787
|
-
agent: exports_external.string().optional()
|
|
8788
|
-
all_agents: exports_external.boolean().optional()
|
|
8789
|
-
project_id: exports_external.string().optional()
|
|
8790
|
-
direction: exports_external.enum(["push", "pull", "both"]).optional()
|
|
8791
|
-
prefer: exports_external.enum(["local", "remote"]).optional()
|
|
8798
|
+
task_list_id: exports_external.string().optional(),
|
|
8799
|
+
agent: exports_external.string().optional(),
|
|
8800
|
+
all_agents: exports_external.boolean().optional(),
|
|
8801
|
+
project_id: exports_external.string().optional(),
|
|
8802
|
+
direction: exports_external.enum(["push", "pull", "both"]).optional(),
|
|
8803
|
+
prefer: exports_external.enum(["local", "remote"]).optional()
|
|
8792
8804
|
}, async ({ task_list_id, agent, all_agents, project_id, direction, prefer }) => {
|
|
8793
8805
|
try {
|
|
8794
8806
|
const resolvedProjectId = project_id ? resolveId(project_id, "projects") : undefined;
|
|
@@ -8831,8 +8843,8 @@ ${text}` }] };
|
|
|
8831
8843
|
}
|
|
8832
8844
|
});
|
|
8833
8845
|
server.tool("register_agent", "Register an agent (idempotent by name).", {
|
|
8834
|
-
name: exports_external.string()
|
|
8835
|
-
description: exports_external.string().optional()
|
|
8846
|
+
name: exports_external.string(),
|
|
8847
|
+
description: exports_external.string().optional()
|
|
8836
8848
|
}, async ({ name, description }) => {
|
|
8837
8849
|
try {
|
|
8838
8850
|
const agent = registerAgent({ name, description });
|
|
@@ -8868,8 +8880,8 @@ ${text}` }] };
|
|
|
8868
8880
|
}
|
|
8869
8881
|
});
|
|
8870
8882
|
server.tool("get_agent", "Get agent details by ID or name", {
|
|
8871
|
-
id: exports_external.string().optional()
|
|
8872
|
-
name: exports_external.string().optional()
|
|
8883
|
+
id: exports_external.string().optional(),
|
|
8884
|
+
name: exports_external.string().optional()
|
|
8873
8885
|
}, async ({ id, name }) => {
|
|
8874
8886
|
try {
|
|
8875
8887
|
if (!id && !name) {
|
|
@@ -8896,10 +8908,10 @@ ${text}` }] };
|
|
|
8896
8908
|
}
|
|
8897
8909
|
});
|
|
8898
8910
|
server.tool("create_task_list", "Create a new task list", {
|
|
8899
|
-
name: exports_external.string()
|
|
8900
|
-
slug: exports_external.string().optional()
|
|
8901
|
-
project_id: exports_external.string().optional()
|
|
8902
|
-
description: exports_external.string().optional()
|
|
8911
|
+
name: exports_external.string(),
|
|
8912
|
+
slug: exports_external.string().optional(),
|
|
8913
|
+
project_id: exports_external.string().optional(),
|
|
8914
|
+
description: exports_external.string().optional()
|
|
8903
8915
|
}, async (params) => {
|
|
8904
8916
|
try {
|
|
8905
8917
|
const resolved = { ...params };
|
|
@@ -8922,7 +8934,7 @@ Description: ${list.description}` : ""}`
|
|
|
8922
8934
|
}
|
|
8923
8935
|
});
|
|
8924
8936
|
server.tool("list_task_lists", "List task lists, optionally filtered by project", {
|
|
8925
|
-
project_id: exports_external.string().optional()
|
|
8937
|
+
project_id: exports_external.string().optional()
|
|
8926
8938
|
}, async ({ project_id }) => {
|
|
8927
8939
|
try {
|
|
8928
8940
|
const resolvedProjectId = project_id ? resolveId(project_id, "projects") : undefined;
|
|
@@ -8942,7 +8954,7 @@ ${text}` }] };
|
|
|
8942
8954
|
}
|
|
8943
8955
|
});
|
|
8944
8956
|
server.tool("get_task_list", "Get task list details", {
|
|
8945
|
-
id: exports_external.string()
|
|
8957
|
+
id: exports_external.string()
|
|
8946
8958
|
}, async ({ id }) => {
|
|
8947
8959
|
try {
|
|
8948
8960
|
const resolvedId = resolveId(id, "task_lists");
|
|
@@ -8970,9 +8982,9 @@ ${text}` }] };
|
|
|
8970
8982
|
}
|
|
8971
8983
|
});
|
|
8972
8984
|
server.tool("update_task_list", "Update a task list", {
|
|
8973
|
-
id: exports_external.string()
|
|
8974
|
-
name: exports_external.string().optional()
|
|
8975
|
-
description: exports_external.string().optional()
|
|
8985
|
+
id: exports_external.string(),
|
|
8986
|
+
name: exports_external.string().optional(),
|
|
8987
|
+
description: exports_external.string().optional()
|
|
8976
8988
|
}, async ({ id, ...rest }) => {
|
|
8977
8989
|
try {
|
|
8978
8990
|
const resolvedId = resolveId(id, "task_lists");
|
|
@@ -8991,7 +9003,7 @@ Slug: ${list.slug}`
|
|
|
8991
9003
|
}
|
|
8992
9004
|
});
|
|
8993
9005
|
server.tool("delete_task_list", "Delete a task list. Tasks lose association but keep data.", {
|
|
8994
|
-
id: exports_external.string()
|
|
9006
|
+
id: exports_external.string()
|
|
8995
9007
|
}, async ({ id }) => {
|
|
8996
9008
|
try {
|
|
8997
9009
|
const resolvedId = resolveId(id, "task_lists");
|
|
@@ -9007,7 +9019,7 @@ Slug: ${list.slug}`
|
|
|
9007
9019
|
}
|
|
9008
9020
|
});
|
|
9009
9021
|
server.tool("get_task_history", "Get audit log for a task.", {
|
|
9010
|
-
task_id: exports_external.string()
|
|
9022
|
+
task_id: exports_external.string()
|
|
9011
9023
|
}, async ({ task_id }) => {
|
|
9012
9024
|
try {
|
|
9013
9025
|
const resolvedId = resolveId(task_id);
|
|
@@ -9024,7 +9036,7 @@ ${text}` }] };
|
|
|
9024
9036
|
}
|
|
9025
9037
|
});
|
|
9026
9038
|
server.tool("get_recent_activity", "Get recent task changes across all tasks.", {
|
|
9027
|
-
limit: exports_external.number().optional()
|
|
9039
|
+
limit: exports_external.number().optional()
|
|
9028
9040
|
}, async ({ limit }) => {
|
|
9029
9041
|
try {
|
|
9030
9042
|
const { getRecentActivity: getRecentActivity2 } = await Promise.resolve().then(() => (init_audit(), exports_audit));
|
|
@@ -9040,9 +9052,9 @@ ${text}` }] };
|
|
|
9040
9052
|
}
|
|
9041
9053
|
});
|
|
9042
9054
|
server.tool("create_webhook", "Register a webhook to receive task change events.", {
|
|
9043
|
-
url: exports_external.string()
|
|
9044
|
-
events: exports_external.array(exports_external.string()).optional()
|
|
9045
|
-
secret: exports_external.string().optional()
|
|
9055
|
+
url: exports_external.string(),
|
|
9056
|
+
events: exports_external.array(exports_external.string()).optional(),
|
|
9057
|
+
secret: exports_external.string().optional()
|
|
9046
9058
|
}, async (params) => {
|
|
9047
9059
|
try {
|
|
9048
9060
|
const { createWebhook: createWebhook2 } = await Promise.resolve().then(() => (init_webhooks(), exports_webhooks));
|
|
@@ -9067,7 +9079,7 @@ ${text}` }] };
|
|
|
9067
9079
|
}
|
|
9068
9080
|
});
|
|
9069
9081
|
server.tool("delete_webhook", "Delete a webhook", {
|
|
9070
|
-
id: exports_external.string()
|
|
9082
|
+
id: exports_external.string()
|
|
9071
9083
|
}, async ({ id }) => {
|
|
9072
9084
|
try {
|
|
9073
9085
|
const { deleteWebhook: deleteWebhook2 } = await Promise.resolve().then(() => (init_webhooks(), exports_webhooks));
|
|
@@ -9078,13 +9090,13 @@ ${text}` }] };
|
|
|
9078
9090
|
}
|
|
9079
9091
|
});
|
|
9080
9092
|
server.tool("create_template", "Create a reusable task template.", {
|
|
9081
|
-
name: exports_external.string()
|
|
9082
|
-
title_pattern: exports_external.string()
|
|
9083
|
-
description: exports_external.string().optional()
|
|
9084
|
-
priority: exports_external.enum(["low", "medium", "high", "critical"]).optional()
|
|
9085
|
-
tags: exports_external.array(exports_external.string()).optional()
|
|
9086
|
-
project_id: exports_external.string().optional()
|
|
9087
|
-
plan_id: exports_external.string().optional()
|
|
9093
|
+
name: exports_external.string(),
|
|
9094
|
+
title_pattern: exports_external.string(),
|
|
9095
|
+
description: exports_external.string().optional(),
|
|
9096
|
+
priority: exports_external.enum(["low", "medium", "high", "critical"]).optional(),
|
|
9097
|
+
tags: exports_external.array(exports_external.string()).optional(),
|
|
9098
|
+
project_id: exports_external.string().optional(),
|
|
9099
|
+
plan_id: exports_external.string().optional()
|
|
9088
9100
|
}, async (params) => {
|
|
9089
9101
|
try {
|
|
9090
9102
|
const { createTemplate: createTemplate2 } = await Promise.resolve().then(() => (init_templates(), exports_templates));
|
|
@@ -9109,12 +9121,12 @@ ${text}` }] };
|
|
|
9109
9121
|
}
|
|
9110
9122
|
});
|
|
9111
9123
|
server.tool("create_task_from_template", "Create a task from a template with optional overrides.", {
|
|
9112
|
-
template_id: exports_external.string()
|
|
9113
|
-
title: exports_external.string().optional()
|
|
9114
|
-
description: exports_external.string().optional()
|
|
9115
|
-
priority: exports_external.enum(["low", "medium", "high", "critical"]).optional()
|
|
9116
|
-
assigned_to: exports_external.string().optional()
|
|
9117
|
-
project_id: exports_external.string().optional()
|
|
9124
|
+
template_id: exports_external.string(),
|
|
9125
|
+
title: exports_external.string().optional(),
|
|
9126
|
+
description: exports_external.string().optional(),
|
|
9127
|
+
priority: exports_external.enum(["low", "medium", "high", "critical"]).optional(),
|
|
9128
|
+
assigned_to: exports_external.string().optional(),
|
|
9129
|
+
project_id: exports_external.string().optional()
|
|
9118
9130
|
}, async (params) => {
|
|
9119
9131
|
try {
|
|
9120
9132
|
const { taskFromTemplate: taskFromTemplate2 } = await Promise.resolve().then(() => (init_templates(), exports_templates));
|
|
@@ -9132,7 +9144,7 @@ ${task.id.slice(0, 8)} | ${task.priority} | ${task.title}` }] };
|
|
|
9132
9144
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
9133
9145
|
}
|
|
9134
9146
|
});
|
|
9135
|
-
server.tool("delete_template", "Delete a task template", { id: exports_external.string()
|
|
9147
|
+
server.tool("delete_template", "Delete a task template", { id: exports_external.string() }, async ({ id }) => {
|
|
9136
9148
|
try {
|
|
9137
9149
|
const { deleteTemplate: deleteTemplate2 } = await Promise.resolve().then(() => (init_templates(), exports_templates));
|
|
9138
9150
|
const deleted = deleteTemplate2(id);
|
|
@@ -9142,8 +9154,8 @@ ${task.id.slice(0, 8)} | ${task.priority} | ${task.title}` }] };
|
|
|
9142
9154
|
}
|
|
9143
9155
|
});
|
|
9144
9156
|
server.tool("approve_task", "Approve a task that requires approval.", {
|
|
9145
|
-
id: exports_external.string()
|
|
9146
|
-
agent_id: exports_external.string().optional()
|
|
9157
|
+
id: exports_external.string(),
|
|
9158
|
+
agent_id: exports_external.string().optional()
|
|
9147
9159
|
}, async ({ id, agent_id }) => {
|
|
9148
9160
|
try {
|
|
9149
9161
|
const resolvedId = resolveId(id);
|
|
@@ -9161,7 +9173,7 @@ ${task.id.slice(0, 8)} | ${task.priority} | ${task.title}` }] };
|
|
|
9161
9173
|
}
|
|
9162
9174
|
});
|
|
9163
9175
|
server.tool("get_my_tasks", "Get assigned tasks and stats for an agent.", {
|
|
9164
|
-
agent_name: exports_external.string()
|
|
9176
|
+
agent_name: exports_external.string()
|
|
9165
9177
|
}, async ({ agent_name }) => {
|
|
9166
9178
|
try {
|
|
9167
9179
|
const agent = registerAgent({ name: agent_name });
|
|
@@ -9193,7 +9205,7 @@ In Progress:`);
|
|
|
9193
9205
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
9194
9206
|
}
|
|
9195
9207
|
});
|
|
9196
|
-
server.tool("search_tools", "List tool names matching a query.", { query: exports_external.string().optional()
|
|
9208
|
+
server.tool("search_tools", "List tool names matching a query.", { query: exports_external.string().optional() }, async ({ query }) => {
|
|
9197
9209
|
const all = [
|
|
9198
9210
|
"create_task",
|
|
9199
9211
|
"list_tasks",
|
|
@@ -9242,7 +9254,7 @@ In Progress:`);
|
|
|
9242
9254
|
const matches = q ? all.filter((n) => n.includes(q)) : all;
|
|
9243
9255
|
return { content: [{ type: "text", text: matches.join(", ") }] };
|
|
9244
9256
|
});
|
|
9245
|
-
server.tool("describe_tools", "Get descriptions for specific tools by name.", { names: exports_external.array(exports_external.string())
|
|
9257
|
+
server.tool("describe_tools", "Get descriptions for specific tools by name.", { names: exports_external.array(exports_external.string()) }, async ({ names }) => {
|
|
9246
9258
|
const descriptions = {
|
|
9247
9259
|
create_task: "Create a task. Params: title(req), description, priority, project_id, plan_id, tags, assigned_to, estimated_minutes, requires_approval",
|
|
9248
9260
|
list_tasks: "List tasks. Params: status, priority, project_id, plan_id, assigned_to, tags, limit",
|
package/dist/index.js
CHANGED
|
@@ -1115,7 +1115,18 @@ function updateTask(id, input, db) {
|
|
|
1115
1115
|
logTaskChange(id, "update", "assigned_to", task.assigned_to, input.assigned_to, agentId, d);
|
|
1116
1116
|
if (input.approved_by !== undefined)
|
|
1117
1117
|
logTaskChange(id, "approve", "approved_by", null, input.approved_by, agentId, d);
|
|
1118
|
-
return
|
|
1118
|
+
return {
|
|
1119
|
+
...task,
|
|
1120
|
+
...Object.fromEntries(Object.entries(input).filter(([, v]) => v !== undefined)),
|
|
1121
|
+
tags: input.tags ?? task.tags,
|
|
1122
|
+
metadata: input.metadata ?? task.metadata,
|
|
1123
|
+
version: task.version + 1,
|
|
1124
|
+
updated_at: now(),
|
|
1125
|
+
completed_at: input.status === "completed" ? now() : task.completed_at,
|
|
1126
|
+
requires_approval: input.requires_approval !== undefined ? input.requires_approval : task.requires_approval,
|
|
1127
|
+
approved_by: input.approved_by ?? task.approved_by,
|
|
1128
|
+
approved_at: input.approved_by ? now() : task.approved_at
|
|
1129
|
+
};
|
|
1119
1130
|
}
|
|
1120
1131
|
function deleteTask(id, db) {
|
|
1121
1132
|
const d = db || getDatabase();
|
|
@@ -1137,6 +1148,9 @@ function getBlockingDeps(id, db) {
|
|
|
1137
1148
|
}
|
|
1138
1149
|
function startTask(id, agentId, db) {
|
|
1139
1150
|
const d = db || getDatabase();
|
|
1151
|
+
const task = getTask(id, d);
|
|
1152
|
+
if (!task)
|
|
1153
|
+
throw new TaskNotFoundError(id);
|
|
1140
1154
|
const blocking = getBlockingDeps(id, d);
|
|
1141
1155
|
if (blocking.length > 0) {
|
|
1142
1156
|
const blockerIds = blocking.map((b) => b.id.slice(0, 8)).join(", ");
|
|
@@ -1147,15 +1161,12 @@ function startTask(id, agentId, db) {
|
|
|
1147
1161
|
const result = d.run(`UPDATE tasks SET status = 'in_progress', assigned_to = ?, locked_by = ?, locked_at = ?, version = version + 1, updated_at = ?
|
|
1148
1162
|
WHERE id = ? AND (locked_by IS NULL OR locked_by = ? OR locked_at < ?)`, [agentId, agentId, timestamp, timestamp, id, agentId, cutoff]);
|
|
1149
1163
|
if (result.changes === 0) {
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
throw new TaskNotFoundError(id);
|
|
1153
|
-
if (current.locked_by && current.locked_by !== agentId && !isLockExpired(current.locked_at)) {
|
|
1154
|
-
throw new LockError(id, current.locked_by);
|
|
1164
|
+
if (task.locked_by && task.locked_by !== agentId && !isLockExpired(task.locked_at)) {
|
|
1165
|
+
throw new LockError(id, task.locked_by);
|
|
1155
1166
|
}
|
|
1156
1167
|
}
|
|
1157
1168
|
logTaskChange(id, "start", "status", "pending", "in_progress", agentId, d);
|
|
1158
|
-
return
|
|
1169
|
+
return { ...task, status: "in_progress", assigned_to: agentId, locked_by: agentId, locked_at: timestamp, version: task.version + 1, updated_at: timestamp };
|
|
1159
1170
|
}
|
|
1160
1171
|
function completeTask(id, agentId, db, evidence) {
|
|
1161
1172
|
const d = db || getDatabase();
|
|
@@ -1167,14 +1178,15 @@ function completeTask(id, agentId, db, evidence) {
|
|
|
1167
1178
|
}
|
|
1168
1179
|
checkCompletionGuard(task, agentId || null, d);
|
|
1169
1180
|
if (evidence) {
|
|
1170
|
-
const
|
|
1171
|
-
d.run("UPDATE tasks SET metadata = ? WHERE id = ?", [JSON.stringify(
|
|
1181
|
+
const meta2 = { ...task.metadata, _evidence: evidence };
|
|
1182
|
+
d.run("UPDATE tasks SET metadata = ? WHERE id = ?", [JSON.stringify(meta2), id]);
|
|
1172
1183
|
}
|
|
1173
1184
|
const timestamp = now();
|
|
1174
1185
|
d.run(`UPDATE tasks SET status = 'completed', locked_by = NULL, locked_at = NULL, completed_at = ?, version = version + 1, updated_at = ?
|
|
1175
1186
|
WHERE id = ?`, [timestamp, timestamp, id]);
|
|
1176
1187
|
logTaskChange(id, "complete", "status", task.status, "completed", agentId || null, d);
|
|
1177
|
-
|
|
1188
|
+
const meta = evidence ? { ...task.metadata, _evidence: evidence } : task.metadata;
|
|
1189
|
+
return { ...task, status: "completed", locked_by: null, locked_at: null, completed_at: timestamp, version: task.version + 1, updated_at: timestamp, metadata: meta };
|
|
1178
1190
|
}
|
|
1179
1191
|
function lockTask(id, agentId, db) {
|
|
1180
1192
|
const d = db || getDatabase();
|
package/dist/mcp/index.js
CHANGED
|
@@ -5154,7 +5154,18 @@ function updateTask(id, input, db) {
|
|
|
5154
5154
|
logTaskChange(id, "update", "assigned_to", task.assigned_to, input.assigned_to, agentId, d);
|
|
5155
5155
|
if (input.approved_by !== undefined)
|
|
5156
5156
|
logTaskChange(id, "approve", "approved_by", null, input.approved_by, agentId, d);
|
|
5157
|
-
return
|
|
5157
|
+
return {
|
|
5158
|
+
...task,
|
|
5159
|
+
...Object.fromEntries(Object.entries(input).filter(([, v]) => v !== undefined)),
|
|
5160
|
+
tags: input.tags ?? task.tags,
|
|
5161
|
+
metadata: input.metadata ?? task.metadata,
|
|
5162
|
+
version: task.version + 1,
|
|
5163
|
+
updated_at: now(),
|
|
5164
|
+
completed_at: input.status === "completed" ? now() : task.completed_at,
|
|
5165
|
+
requires_approval: input.requires_approval !== undefined ? input.requires_approval : task.requires_approval,
|
|
5166
|
+
approved_by: input.approved_by ?? task.approved_by,
|
|
5167
|
+
approved_at: input.approved_by ? now() : task.approved_at
|
|
5168
|
+
};
|
|
5158
5169
|
}
|
|
5159
5170
|
function deleteTask(id, db) {
|
|
5160
5171
|
const d = db || getDatabase();
|
|
@@ -5176,6 +5187,9 @@ function getBlockingDeps(id, db) {
|
|
|
5176
5187
|
}
|
|
5177
5188
|
function startTask(id, agentId, db) {
|
|
5178
5189
|
const d = db || getDatabase();
|
|
5190
|
+
const task = getTask(id, d);
|
|
5191
|
+
if (!task)
|
|
5192
|
+
throw new TaskNotFoundError(id);
|
|
5179
5193
|
const blocking = getBlockingDeps(id, d);
|
|
5180
5194
|
if (blocking.length > 0) {
|
|
5181
5195
|
const blockerIds = blocking.map((b) => b.id.slice(0, 8)).join(", ");
|
|
@@ -5186,15 +5200,12 @@ function startTask(id, agentId, db) {
|
|
|
5186
5200
|
const result = d.run(`UPDATE tasks SET status = 'in_progress', assigned_to = ?, locked_by = ?, locked_at = ?, version = version + 1, updated_at = ?
|
|
5187
5201
|
WHERE id = ? AND (locked_by IS NULL OR locked_by = ? OR locked_at < ?)`, [agentId, agentId, timestamp, timestamp, id, agentId, cutoff]);
|
|
5188
5202
|
if (result.changes === 0) {
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
throw new TaskNotFoundError(id);
|
|
5192
|
-
if (current.locked_by && current.locked_by !== agentId && !isLockExpired(current.locked_at)) {
|
|
5193
|
-
throw new LockError(id, current.locked_by);
|
|
5203
|
+
if (task.locked_by && task.locked_by !== agentId && !isLockExpired(task.locked_at)) {
|
|
5204
|
+
throw new LockError(id, task.locked_by);
|
|
5194
5205
|
}
|
|
5195
5206
|
}
|
|
5196
5207
|
logTaskChange(id, "start", "status", "pending", "in_progress", agentId, d);
|
|
5197
|
-
return
|
|
5208
|
+
return { ...task, status: "in_progress", assigned_to: agentId, locked_by: agentId, locked_at: timestamp, version: task.version + 1, updated_at: timestamp };
|
|
5198
5209
|
}
|
|
5199
5210
|
function completeTask(id, agentId, db, evidence) {
|
|
5200
5211
|
const d = db || getDatabase();
|
|
@@ -5206,14 +5217,15 @@ function completeTask(id, agentId, db, evidence) {
|
|
|
5206
5217
|
}
|
|
5207
5218
|
checkCompletionGuard(task, agentId || null, d);
|
|
5208
5219
|
if (evidence) {
|
|
5209
|
-
const
|
|
5210
|
-
d.run("UPDATE tasks SET metadata = ? WHERE id = ?", [JSON.stringify(
|
|
5220
|
+
const meta2 = { ...task.metadata, _evidence: evidence };
|
|
5221
|
+
d.run("UPDATE tasks SET metadata = ? WHERE id = ?", [JSON.stringify(meta2), id]);
|
|
5211
5222
|
}
|
|
5212
5223
|
const timestamp = now();
|
|
5213
5224
|
d.run(`UPDATE tasks SET status = 'completed', locked_by = NULL, locked_at = NULL, completed_at = ?, version = version + 1, updated_at = ?
|
|
5214
5225
|
WHERE id = ?`, [timestamp, timestamp, id]);
|
|
5215
5226
|
logTaskChange(id, "complete", "status", task.status, "completed", agentId || null, d);
|
|
5216
|
-
|
|
5227
|
+
const meta = evidence ? { ...task.metadata, _evidence: evidence } : task.metadata;
|
|
5228
|
+
return { ...task, status: "completed", locked_by: null, locked_at: null, completed_at: timestamp, version: task.version + 1, updated_at: timestamp, metadata: meta };
|
|
5217
5229
|
}
|
|
5218
5230
|
function lockTask(id, agentId, db) {
|
|
5219
5231
|
const d = db || getDatabase();
|
package/dist/server/index.js
CHANGED
|
@@ -1233,7 +1233,18 @@ function updateTask(id, input, db) {
|
|
|
1233
1233
|
logTaskChange(id, "update", "assigned_to", task.assigned_to, input.assigned_to, agentId, d);
|
|
1234
1234
|
if (input.approved_by !== undefined)
|
|
1235
1235
|
logTaskChange(id, "approve", "approved_by", null, input.approved_by, agentId, d);
|
|
1236
|
-
return
|
|
1236
|
+
return {
|
|
1237
|
+
...task,
|
|
1238
|
+
...Object.fromEntries(Object.entries(input).filter(([, v]) => v !== undefined)),
|
|
1239
|
+
tags: input.tags ?? task.tags,
|
|
1240
|
+
metadata: input.metadata ?? task.metadata,
|
|
1241
|
+
version: task.version + 1,
|
|
1242
|
+
updated_at: now(),
|
|
1243
|
+
completed_at: input.status === "completed" ? now() : task.completed_at,
|
|
1244
|
+
requires_approval: input.requires_approval !== undefined ? input.requires_approval : task.requires_approval,
|
|
1245
|
+
approved_by: input.approved_by ?? task.approved_by,
|
|
1246
|
+
approved_at: input.approved_by ? now() : task.approved_at
|
|
1247
|
+
};
|
|
1237
1248
|
}
|
|
1238
1249
|
function deleteTask(id, db) {
|
|
1239
1250
|
const d = db || getDatabase();
|
|
@@ -1255,6 +1266,9 @@ function getBlockingDeps(id, db) {
|
|
|
1255
1266
|
}
|
|
1256
1267
|
function startTask(id, agentId, db) {
|
|
1257
1268
|
const d = db || getDatabase();
|
|
1269
|
+
const task = getTask(id, d);
|
|
1270
|
+
if (!task)
|
|
1271
|
+
throw new TaskNotFoundError(id);
|
|
1258
1272
|
const blocking = getBlockingDeps(id, d);
|
|
1259
1273
|
if (blocking.length > 0) {
|
|
1260
1274
|
const blockerIds = blocking.map((b) => b.id.slice(0, 8)).join(", ");
|
|
@@ -1265,15 +1279,12 @@ function startTask(id, agentId, db) {
|
|
|
1265
1279
|
const result = d.run(`UPDATE tasks SET status = 'in_progress', assigned_to = ?, locked_by = ?, locked_at = ?, version = version + 1, updated_at = ?
|
|
1266
1280
|
WHERE id = ? AND (locked_by IS NULL OR locked_by = ? OR locked_at < ?)`, [agentId, agentId, timestamp, timestamp, id, agentId, cutoff]);
|
|
1267
1281
|
if (result.changes === 0) {
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
throw new TaskNotFoundError(id);
|
|
1271
|
-
if (current.locked_by && current.locked_by !== agentId && !isLockExpired(current.locked_at)) {
|
|
1272
|
-
throw new LockError(id, current.locked_by);
|
|
1282
|
+
if (task.locked_by && task.locked_by !== agentId && !isLockExpired(task.locked_at)) {
|
|
1283
|
+
throw new LockError(id, task.locked_by);
|
|
1273
1284
|
}
|
|
1274
1285
|
}
|
|
1275
1286
|
logTaskChange(id, "start", "status", "pending", "in_progress", agentId, d);
|
|
1276
|
-
return
|
|
1287
|
+
return { ...task, status: "in_progress", assigned_to: agentId, locked_by: agentId, locked_at: timestamp, version: task.version + 1, updated_at: timestamp };
|
|
1277
1288
|
}
|
|
1278
1289
|
function completeTask(id, agentId, db, evidence) {
|
|
1279
1290
|
const d = db || getDatabase();
|
|
@@ -1285,14 +1296,15 @@ function completeTask(id, agentId, db, evidence) {
|
|
|
1285
1296
|
}
|
|
1286
1297
|
checkCompletionGuard(task, agentId || null, d);
|
|
1287
1298
|
if (evidence) {
|
|
1288
|
-
const
|
|
1289
|
-
d.run("UPDATE tasks SET metadata = ? WHERE id = ?", [JSON.stringify(
|
|
1299
|
+
const meta2 = { ...task.metadata, _evidence: evidence };
|
|
1300
|
+
d.run("UPDATE tasks SET metadata = ? WHERE id = ?", [JSON.stringify(meta2), id]);
|
|
1290
1301
|
}
|
|
1291
1302
|
const timestamp = now();
|
|
1292
1303
|
d.run(`UPDATE tasks SET status = 'completed', locked_by = NULL, locked_at = NULL, completed_at = ?, version = version + 1, updated_at = ?
|
|
1293
1304
|
WHERE id = ?`, [timestamp, timestamp, id]);
|
|
1294
1305
|
logTaskChange(id, "complete", "status", task.status, "completed", agentId || null, d);
|
|
1295
|
-
|
|
1306
|
+
const meta = evidence ? { ...task.metadata, _evidence: evidence } : task.metadata;
|
|
1307
|
+
return { ...task, status: "completed", locked_by: null, locked_at: null, completed_at: timestamp, version: task.version + 1, updated_at: timestamp, metadata: meta };
|
|
1296
1308
|
}
|
|
1297
1309
|
function getTaskDependencies(taskId, db) {
|
|
1298
1310
|
const d = db || getDatabase();
|