@hasna/todos 0.9.80 → 0.9.81
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 +136 -0
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/task-files.d.ts +26 -0
- package/dist/db/task-files.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +72 -0
- package/dist/mcp/index.js +136 -0
- package/dist/server/index.js +16 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2776,6 +2776,22 @@ var init_database = __esm(() => {
|
|
|
2776
2776
|
CREATE INDEX IF NOT EXISTS idx_resource_locks_type_id ON resource_locks(resource_type, resource_id);
|
|
2777
2777
|
CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id);
|
|
2778
2778
|
INSERT OR IGNORE INTO _migrations (id) VALUES (24);
|
|
2779
|
+
`,
|
|
2780
|
+
`
|
|
2781
|
+
CREATE TABLE IF NOT EXISTS task_files (
|
|
2782
|
+
id TEXT PRIMARY KEY,
|
|
2783
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
2784
|
+
path TEXT NOT NULL,
|
|
2785
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
2786
|
+
agent_id TEXT,
|
|
2787
|
+
note TEXT,
|
|
2788
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
2789
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2790
|
+
);
|
|
2791
|
+
CREATE INDEX IF NOT EXISTS idx_task_files_task ON task_files(task_id);
|
|
2792
|
+
CREATE INDEX IF NOT EXISTS idx_task_files_path ON task_files(path);
|
|
2793
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_files_task_path ON task_files(task_id, path);
|
|
2794
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (25);
|
|
2779
2795
|
`
|
|
2780
2796
|
];
|
|
2781
2797
|
});
|
|
@@ -9585,6 +9601,69 @@ var init_zod = __esm(() => {
|
|
|
9585
9601
|
init_external();
|
|
9586
9602
|
});
|
|
9587
9603
|
|
|
9604
|
+
// src/db/task-files.ts
|
|
9605
|
+
var exports_task_files = {};
|
|
9606
|
+
__export(exports_task_files, {
|
|
9607
|
+
updateTaskFileStatus: () => updateTaskFileStatus,
|
|
9608
|
+
removeTaskFile: () => removeTaskFile,
|
|
9609
|
+
listTaskFiles: () => listTaskFiles,
|
|
9610
|
+
getTaskFile: () => getTaskFile,
|
|
9611
|
+
findTasksByFile: () => findTasksByFile,
|
|
9612
|
+
bulkAddTaskFiles: () => bulkAddTaskFiles,
|
|
9613
|
+
addTaskFile: () => addTaskFile
|
|
9614
|
+
});
|
|
9615
|
+
function addTaskFile(input, db) {
|
|
9616
|
+
const d = db || getDatabase();
|
|
9617
|
+
const id = uuid();
|
|
9618
|
+
const timestamp = now();
|
|
9619
|
+
const existing = d.query("SELECT id FROM task_files WHERE task_id = ? AND path = ?").get(input.task_id, input.path);
|
|
9620
|
+
if (existing) {
|
|
9621
|
+
d.run("UPDATE task_files SET status = ?, agent_id = ?, note = ?, updated_at = ? WHERE id = ?", [input.status || "active", input.agent_id || null, input.note || null, timestamp, existing.id]);
|
|
9622
|
+
return getTaskFile(existing.id, d);
|
|
9623
|
+
}
|
|
9624
|
+
d.run(`INSERT INTO task_files (id, task_id, path, status, agent_id, note, created_at, updated_at)
|
|
9625
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, input.task_id, input.path, input.status || "active", input.agent_id || null, input.note || null, timestamp, timestamp]);
|
|
9626
|
+
return getTaskFile(id, d);
|
|
9627
|
+
}
|
|
9628
|
+
function getTaskFile(id, db) {
|
|
9629
|
+
const d = db || getDatabase();
|
|
9630
|
+
return d.query("SELECT * FROM task_files WHERE id = ?").get(id);
|
|
9631
|
+
}
|
|
9632
|
+
function listTaskFiles(taskId, db) {
|
|
9633
|
+
const d = db || getDatabase();
|
|
9634
|
+
return d.query("SELECT * FROM task_files WHERE task_id = ? ORDER BY path").all(taskId);
|
|
9635
|
+
}
|
|
9636
|
+
function findTasksByFile(path, db) {
|
|
9637
|
+
const d = db || getDatabase();
|
|
9638
|
+
return d.query("SELECT * FROM task_files WHERE path = ? AND status != 'removed' ORDER BY updated_at DESC").all(path);
|
|
9639
|
+
}
|
|
9640
|
+
function updateTaskFileStatus(taskId, path, status, agentId, db) {
|
|
9641
|
+
const d = db || getDatabase();
|
|
9642
|
+
const timestamp = now();
|
|
9643
|
+
d.run("UPDATE task_files SET status = ?, agent_id = COALESCE(?, agent_id), updated_at = ? WHERE task_id = ? AND path = ?", [status, agentId || null, timestamp, taskId, path]);
|
|
9644
|
+
const row = d.query("SELECT * FROM task_files WHERE task_id = ? AND path = ?").get(taskId, path);
|
|
9645
|
+
return row;
|
|
9646
|
+
}
|
|
9647
|
+
function removeTaskFile(taskId, path, db) {
|
|
9648
|
+
const d = db || getDatabase();
|
|
9649
|
+
const result = d.run("DELETE FROM task_files WHERE task_id = ? AND path = ?", [taskId, path]);
|
|
9650
|
+
return result.changes > 0;
|
|
9651
|
+
}
|
|
9652
|
+
function bulkAddTaskFiles(taskId, paths, agentId, db) {
|
|
9653
|
+
const d = db || getDatabase();
|
|
9654
|
+
const results = [];
|
|
9655
|
+
const tx = d.transaction(() => {
|
|
9656
|
+
for (const path of paths) {
|
|
9657
|
+
results.push(addTaskFile({ task_id: taskId, path, agent_id: agentId }, d));
|
|
9658
|
+
}
|
|
9659
|
+
});
|
|
9660
|
+
tx();
|
|
9661
|
+
return results;
|
|
9662
|
+
}
|
|
9663
|
+
var init_task_files = __esm(() => {
|
|
9664
|
+
init_database();
|
|
9665
|
+
});
|
|
9666
|
+
|
|
9588
9667
|
// src/db/handoffs.ts
|
|
9589
9668
|
var exports_handoffs = {};
|
|
9590
9669
|
__export(exports_handoffs, {
|
|
@@ -12187,6 +12266,63 @@ Claimed: ${formatTask(result.claimed)}`);
|
|
|
12187
12266
|
const agents = listAgents();
|
|
12188
12267
|
return { contents: [{ uri: "todos://agents", text: JSON.stringify(agents, null, 2), mimeType: "application/json" }] };
|
|
12189
12268
|
});
|
|
12269
|
+
if (shouldRegisterTool("add_task_file")) {
|
|
12270
|
+
server.tool("add_task_file", "Link a file path to a task. Tracks which files an agent is working on. Upserts if same task+path exists.", {
|
|
12271
|
+
task_id: exports_external.string().describe("Task ID"),
|
|
12272
|
+
path: exports_external.string().describe("File path (relative or absolute)"),
|
|
12273
|
+
paths: exports_external.array(exports_external.string()).optional().describe("Multiple file paths to add at once"),
|
|
12274
|
+
status: exports_external.enum(["planned", "active", "modified", "reviewed", "removed"]).optional().describe("File status (default: active)"),
|
|
12275
|
+
agent_id: exports_external.string().optional().describe("Agent working on this file"),
|
|
12276
|
+
note: exports_external.string().optional().describe("Note about why this file is linked")
|
|
12277
|
+
}, async ({ task_id, path, paths: multiplePaths, status, agent_id, note }) => {
|
|
12278
|
+
try {
|
|
12279
|
+
const { addTaskFile: addTaskFile2, bulkAddTaskFiles: bulkAddTaskFiles2 } = (init_task_files(), __toCommonJS(exports_task_files));
|
|
12280
|
+
const resolvedId = resolveId(task_id);
|
|
12281
|
+
if (multiplePaths && multiplePaths.length > 0) {
|
|
12282
|
+
const allPaths = path ? [path, ...multiplePaths] : multiplePaths;
|
|
12283
|
+
const files = bulkAddTaskFiles2(resolvedId, allPaths, agent_id);
|
|
12284
|
+
return { content: [{ type: "text", text: `${files.length} file(s) linked to task ${resolvedId.slice(0, 8)}` }] };
|
|
12285
|
+
}
|
|
12286
|
+
const file = addTaskFile2({ task_id: resolvedId, path, status, agent_id, note });
|
|
12287
|
+
return { content: [{ type: "text", text: `${file.status} ${file.path} \u2192 task ${resolvedId.slice(0, 8)}` }] };
|
|
12288
|
+
} catch (e) {
|
|
12289
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
12290
|
+
}
|
|
12291
|
+
});
|
|
12292
|
+
}
|
|
12293
|
+
if (shouldRegisterTool("list_task_files")) {
|
|
12294
|
+
server.tool("list_task_files", "List all files linked to a task.", { task_id: exports_external.string().describe("Task ID") }, async ({ task_id }) => {
|
|
12295
|
+
try {
|
|
12296
|
+
const { listTaskFiles: listTaskFiles2 } = (init_task_files(), __toCommonJS(exports_task_files));
|
|
12297
|
+
const resolvedId = resolveId(task_id);
|
|
12298
|
+
const files = listTaskFiles2(resolvedId);
|
|
12299
|
+
if (files.length === 0)
|
|
12300
|
+
return { content: [{ type: "text", text: "No files linked." }] };
|
|
12301
|
+
const lines = files.map((f) => `[${f.status}] ${f.path}${f.agent_id ? ` (${f.agent_id})` : ""}${f.note ? ` \u2014 ${f.note}` : ""}`);
|
|
12302
|
+
return { content: [{ type: "text", text: `${files.length} file(s):
|
|
12303
|
+
${lines.join(`
|
|
12304
|
+
`)}` }] };
|
|
12305
|
+
} catch (e) {
|
|
12306
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
12307
|
+
}
|
|
12308
|
+
});
|
|
12309
|
+
}
|
|
12310
|
+
if (shouldRegisterTool("find_tasks_by_file")) {
|
|
12311
|
+
server.tool("find_tasks_by_file", "Find which tasks are linked to a specific file path. Shows who's working on what files.", { path: exports_external.string().describe("File path to search for") }, async ({ path }) => {
|
|
12312
|
+
try {
|
|
12313
|
+
const { findTasksByFile: findTasksByFile2 } = (init_task_files(), __toCommonJS(exports_task_files));
|
|
12314
|
+
const files = findTasksByFile2(path);
|
|
12315
|
+
if (files.length === 0)
|
|
12316
|
+
return { content: [{ type: "text", text: `No tasks linked to ${path}` }] };
|
|
12317
|
+
const lines = files.map((f) => `${f.task_id.slice(0, 8)} [${f.status}]${f.agent_id ? ` (${f.agent_id})` : ""}`);
|
|
12318
|
+
return { content: [{ type: "text", text: `${files.length} task(s) linked to ${path}:
|
|
12319
|
+
${lines.join(`
|
|
12320
|
+
`)}` }] };
|
|
12321
|
+
} catch (e) {
|
|
12322
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
12323
|
+
}
|
|
12324
|
+
});
|
|
12325
|
+
}
|
|
12190
12326
|
if (shouldRegisterTool("create_handoff")) {
|
|
12191
12327
|
server.tool("create_handoff", "Create a session handoff note for agent coordination.", {
|
|
12192
12328
|
agent_id: exports_external.string().optional().describe("Agent creating the handoff"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,eAAO,MAAM,mBAAmB,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAwdtC,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAkBrD;AAgPD,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,GAAG,IAAI,MAAM,CAE5B;AAED,wBAAgB,IAAI,IAAI,MAAM,CAE7B;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAK9D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,SAAa,GAAG,MAAM,CAG3D;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAGpD;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0B9F"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
export interface TaskFile {
|
|
3
|
+
id: string;
|
|
4
|
+
task_id: string;
|
|
5
|
+
path: string;
|
|
6
|
+
status: "planned" | "active" | "modified" | "reviewed" | "removed";
|
|
7
|
+
agent_id: string | null;
|
|
8
|
+
note: string | null;
|
|
9
|
+
created_at: string;
|
|
10
|
+
updated_at: string;
|
|
11
|
+
}
|
|
12
|
+
export interface AddTaskFileInput {
|
|
13
|
+
task_id: string;
|
|
14
|
+
path: string;
|
|
15
|
+
status?: TaskFile["status"];
|
|
16
|
+
agent_id?: string;
|
|
17
|
+
note?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function addTaskFile(input: AddTaskFileInput, db?: Database): TaskFile;
|
|
20
|
+
export declare function getTaskFile(id: string, db?: Database): TaskFile | null;
|
|
21
|
+
export declare function listTaskFiles(taskId: string, db?: Database): TaskFile[];
|
|
22
|
+
export declare function findTasksByFile(path: string, db?: Database): TaskFile[];
|
|
23
|
+
export declare function updateTaskFileStatus(taskId: string, path: string, status: TaskFile["status"], agentId?: string, db?: Database): TaskFile | null;
|
|
24
|
+
export declare function removeTaskFile(taskId: string, path: string, db?: Database): boolean;
|
|
25
|
+
export declare function bulkAddTaskFiles(taskId: string, paths: string[], agentId?: string, db?: Database): TaskFile[];
|
|
26
|
+
//# sourceMappingURL=task-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-files.d.ts","sourceRoot":"","sources":["../../src/db/task-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;IACnE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAwB5E;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAGtE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAKvE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAKvE;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC1B,OAAO,CAAC,EAAE,MAAM,EAChB,EAAE,CAAC,EAAE,QAAQ,GACZ,QAAQ,GAAG,IAAI,CAWjB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAOnF;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,EAAE,CAAC,EAAE,QAAQ,GACZ,QAAQ,EAAE,CAUZ"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export { createTemplate, getTemplate, listTemplates, deleteTemplate, taskFromTem
|
|
|
16
16
|
export { getChecklist, addChecklistItem, checkChecklistItem, updateChecklistItemText, removeChecklistItem, clearChecklist, getChecklistStats, } from "./db/checklists.js";
|
|
17
17
|
export { createHandoff, listHandoffs, getLatestHandoff } from "./db/handoffs.js";
|
|
18
18
|
export type { Handoff, CreateHandoffInput } from "./db/handoffs.js";
|
|
19
|
+
export { addTaskFile, getTaskFile, listTaskFiles, findTasksByFile, updateTaskFileStatus, removeTaskFile, bulkAddTaskFiles } from "./db/task-files.js";
|
|
20
|
+
export type { TaskFile, AddTaskFileInput } from "./db/task-files.js";
|
|
19
21
|
export { acquireLock, releaseLock, checkLock, cleanExpiredLocks } from "./db/locks.js";
|
|
20
22
|
export type { ResourceLock } from "./db/locks.js";
|
|
21
23
|
export { createOrg, getOrg, getOrgByName, listOrgs, updateOrg, deleteOrg } from "./db/orgs.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -637,6 +637,22 @@ var MIGRATIONS = [
|
|
|
637
637
|
CREATE INDEX IF NOT EXISTS idx_resource_locks_type_id ON resource_locks(resource_type, resource_id);
|
|
638
638
|
CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id);
|
|
639
639
|
INSERT OR IGNORE INTO _migrations (id) VALUES (24);
|
|
640
|
+
`,
|
|
641
|
+
`
|
|
642
|
+
CREATE TABLE IF NOT EXISTS task_files (
|
|
643
|
+
id TEXT PRIMARY KEY,
|
|
644
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
645
|
+
path TEXT NOT NULL,
|
|
646
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
647
|
+
agent_id TEXT,
|
|
648
|
+
note TEXT,
|
|
649
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
650
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
651
|
+
);
|
|
652
|
+
CREATE INDEX IF NOT EXISTS idx_task_files_task ON task_files(task_id);
|
|
653
|
+
CREATE INDEX IF NOT EXISTS idx_task_files_path ON task_files(path);
|
|
654
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_files_task_path ON task_files(task_id, path);
|
|
655
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (25);
|
|
640
656
|
`
|
|
641
657
|
];
|
|
642
658
|
var _db = null;
|
|
@@ -3075,6 +3091,55 @@ function getLatestHandoff(agentId, projectId, db) {
|
|
|
3075
3091
|
const row = d.query(query).get(...params);
|
|
3076
3092
|
return row ? rowToHandoff(row) : null;
|
|
3077
3093
|
}
|
|
3094
|
+
// src/db/task-files.ts
|
|
3095
|
+
function addTaskFile(input, db) {
|
|
3096
|
+
const d = db || getDatabase();
|
|
3097
|
+
const id = uuid();
|
|
3098
|
+
const timestamp = now();
|
|
3099
|
+
const existing = d.query("SELECT id FROM task_files WHERE task_id = ? AND path = ?").get(input.task_id, input.path);
|
|
3100
|
+
if (existing) {
|
|
3101
|
+
d.run("UPDATE task_files SET status = ?, agent_id = ?, note = ?, updated_at = ? WHERE id = ?", [input.status || "active", input.agent_id || null, input.note || null, timestamp, existing.id]);
|
|
3102
|
+
return getTaskFile(existing.id, d);
|
|
3103
|
+
}
|
|
3104
|
+
d.run(`INSERT INTO task_files (id, task_id, path, status, agent_id, note, created_at, updated_at)
|
|
3105
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, input.task_id, input.path, input.status || "active", input.agent_id || null, input.note || null, timestamp, timestamp]);
|
|
3106
|
+
return getTaskFile(id, d);
|
|
3107
|
+
}
|
|
3108
|
+
function getTaskFile(id, db) {
|
|
3109
|
+
const d = db || getDatabase();
|
|
3110
|
+
return d.query("SELECT * FROM task_files WHERE id = ?").get(id);
|
|
3111
|
+
}
|
|
3112
|
+
function listTaskFiles(taskId, db) {
|
|
3113
|
+
const d = db || getDatabase();
|
|
3114
|
+
return d.query("SELECT * FROM task_files WHERE task_id = ? ORDER BY path").all(taskId);
|
|
3115
|
+
}
|
|
3116
|
+
function findTasksByFile(path, db) {
|
|
3117
|
+
const d = db || getDatabase();
|
|
3118
|
+
return d.query("SELECT * FROM task_files WHERE path = ? AND status != 'removed' ORDER BY updated_at DESC").all(path);
|
|
3119
|
+
}
|
|
3120
|
+
function updateTaskFileStatus(taskId, path, status, agentId, db) {
|
|
3121
|
+
const d = db || getDatabase();
|
|
3122
|
+
const timestamp = now();
|
|
3123
|
+
d.run("UPDATE task_files SET status = ?, agent_id = COALESCE(?, agent_id), updated_at = ? WHERE task_id = ? AND path = ?", [status, agentId || null, timestamp, taskId, path]);
|
|
3124
|
+
const row = d.query("SELECT * FROM task_files WHERE task_id = ? AND path = ?").get(taskId, path);
|
|
3125
|
+
return row;
|
|
3126
|
+
}
|
|
3127
|
+
function removeTaskFile(taskId, path, db) {
|
|
3128
|
+
const d = db || getDatabase();
|
|
3129
|
+
const result = d.run("DELETE FROM task_files WHERE task_id = ? AND path = ?", [taskId, path]);
|
|
3130
|
+
return result.changes > 0;
|
|
3131
|
+
}
|
|
3132
|
+
function bulkAddTaskFiles(taskId, paths, agentId, db) {
|
|
3133
|
+
const d = db || getDatabase();
|
|
3134
|
+
const results = [];
|
|
3135
|
+
const tx = d.transaction(() => {
|
|
3136
|
+
for (const path of paths) {
|
|
3137
|
+
results.push(addTaskFile({ task_id: taskId, path, agent_id: agentId }, d));
|
|
3138
|
+
}
|
|
3139
|
+
});
|
|
3140
|
+
tx();
|
|
3141
|
+
return results;
|
|
3142
|
+
}
|
|
3078
3143
|
// src/db/locks.ts
|
|
3079
3144
|
function acquireLock(resourceType, resourceId, agentId, lockType = "advisory", expiryMs = 5 * 60 * 1000, db) {
|
|
3080
3145
|
const d = db || getDatabase();
|
|
@@ -3785,6 +3850,7 @@ function syncWithAgents(agents, taskListIdByAgent, projectId, direction = "both"
|
|
|
3785
3850
|
export {
|
|
3786
3851
|
uuid,
|
|
3787
3852
|
updateTaskList,
|
|
3853
|
+
updateTaskFileStatus,
|
|
3788
3854
|
updateTask,
|
|
3789
3855
|
updateSessionActivity,
|
|
3790
3856
|
updateProject,
|
|
@@ -3804,6 +3870,7 @@ export {
|
|
|
3804
3870
|
searchTasks,
|
|
3805
3871
|
resolvePartialId,
|
|
3806
3872
|
resetDatabase,
|
|
3873
|
+
removeTaskFile,
|
|
3807
3874
|
removeProjectSource,
|
|
3808
3875
|
removeDependency,
|
|
3809
3876
|
removeChecklistItem,
|
|
@@ -3823,6 +3890,7 @@ export {
|
|
|
3823
3890
|
listTemplates,
|
|
3824
3891
|
listTasks,
|
|
3825
3892
|
listTaskLists,
|
|
3893
|
+
listTaskFiles,
|
|
3826
3894
|
listSessions,
|
|
3827
3895
|
listProjects,
|
|
3828
3896
|
listProjectSources,
|
|
@@ -3842,6 +3910,7 @@ export {
|
|
|
3842
3910
|
getTaskList,
|
|
3843
3911
|
getTaskHistory,
|
|
3844
3912
|
getTaskGraph,
|
|
3913
|
+
getTaskFile,
|
|
3845
3914
|
getTaskDependents,
|
|
3846
3915
|
getTaskDependencies,
|
|
3847
3916
|
getTask,
|
|
@@ -3869,6 +3938,7 @@ export {
|
|
|
3869
3938
|
getAgentByName,
|
|
3870
3939
|
getAgent,
|
|
3871
3940
|
getActiveWork,
|
|
3941
|
+
findTasksByFile,
|
|
3872
3942
|
failTask,
|
|
3873
3943
|
ensureTaskList,
|
|
3874
3944
|
ensureProject,
|
|
@@ -3907,6 +3977,8 @@ export {
|
|
|
3907
3977
|
checkChecklistItem,
|
|
3908
3978
|
bulkUpdateTasks,
|
|
3909
3979
|
bulkCreateTasks,
|
|
3980
|
+
bulkAddTaskFiles,
|
|
3981
|
+
addTaskFile,
|
|
3910
3982
|
addProjectSource,
|
|
3911
3983
|
addDependency,
|
|
3912
3984
|
addComment,
|
package/dist/mcp/index.js
CHANGED
|
@@ -705,6 +705,22 @@ var init_database = __esm(() => {
|
|
|
705
705
|
CREATE INDEX IF NOT EXISTS idx_resource_locks_type_id ON resource_locks(resource_type, resource_id);
|
|
706
706
|
CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id);
|
|
707
707
|
INSERT OR IGNORE INTO _migrations (id) VALUES (24);
|
|
708
|
+
`,
|
|
709
|
+
`
|
|
710
|
+
CREATE TABLE IF NOT EXISTS task_files (
|
|
711
|
+
id TEXT PRIMARY KEY,
|
|
712
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
713
|
+
path TEXT NOT NULL,
|
|
714
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
715
|
+
agent_id TEXT,
|
|
716
|
+
note TEXT,
|
|
717
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
718
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
719
|
+
);
|
|
720
|
+
CREATE INDEX IF NOT EXISTS idx_task_files_task ON task_files(task_id);
|
|
721
|
+
CREATE INDEX IF NOT EXISTS idx_task_files_path ON task_files(path);
|
|
722
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_files_task_path ON task_files(task_id, path);
|
|
723
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (25);
|
|
708
724
|
`
|
|
709
725
|
];
|
|
710
726
|
});
|
|
@@ -1036,6 +1052,69 @@ var init_agents = __esm(() => {
|
|
|
1036
1052
|
AGENT_ACTIVE_WINDOW_MS = 30 * 60 * 1000;
|
|
1037
1053
|
});
|
|
1038
1054
|
|
|
1055
|
+
// src/db/task-files.ts
|
|
1056
|
+
var exports_task_files = {};
|
|
1057
|
+
__export(exports_task_files, {
|
|
1058
|
+
updateTaskFileStatus: () => updateTaskFileStatus,
|
|
1059
|
+
removeTaskFile: () => removeTaskFile,
|
|
1060
|
+
listTaskFiles: () => listTaskFiles,
|
|
1061
|
+
getTaskFile: () => getTaskFile,
|
|
1062
|
+
findTasksByFile: () => findTasksByFile,
|
|
1063
|
+
bulkAddTaskFiles: () => bulkAddTaskFiles,
|
|
1064
|
+
addTaskFile: () => addTaskFile
|
|
1065
|
+
});
|
|
1066
|
+
function addTaskFile(input, db) {
|
|
1067
|
+
const d = db || getDatabase();
|
|
1068
|
+
const id = uuid();
|
|
1069
|
+
const timestamp = now();
|
|
1070
|
+
const existing = d.query("SELECT id FROM task_files WHERE task_id = ? AND path = ?").get(input.task_id, input.path);
|
|
1071
|
+
if (existing) {
|
|
1072
|
+
d.run("UPDATE task_files SET status = ?, agent_id = ?, note = ?, updated_at = ? WHERE id = ?", [input.status || "active", input.agent_id || null, input.note || null, timestamp, existing.id]);
|
|
1073
|
+
return getTaskFile(existing.id, d);
|
|
1074
|
+
}
|
|
1075
|
+
d.run(`INSERT INTO task_files (id, task_id, path, status, agent_id, note, created_at, updated_at)
|
|
1076
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, input.task_id, input.path, input.status || "active", input.agent_id || null, input.note || null, timestamp, timestamp]);
|
|
1077
|
+
return getTaskFile(id, d);
|
|
1078
|
+
}
|
|
1079
|
+
function getTaskFile(id, db) {
|
|
1080
|
+
const d = db || getDatabase();
|
|
1081
|
+
return d.query("SELECT * FROM task_files WHERE id = ?").get(id);
|
|
1082
|
+
}
|
|
1083
|
+
function listTaskFiles(taskId, db) {
|
|
1084
|
+
const d = db || getDatabase();
|
|
1085
|
+
return d.query("SELECT * FROM task_files WHERE task_id = ? ORDER BY path").all(taskId);
|
|
1086
|
+
}
|
|
1087
|
+
function findTasksByFile(path, db) {
|
|
1088
|
+
const d = db || getDatabase();
|
|
1089
|
+
return d.query("SELECT * FROM task_files WHERE path = ? AND status != 'removed' ORDER BY updated_at DESC").all(path);
|
|
1090
|
+
}
|
|
1091
|
+
function updateTaskFileStatus(taskId, path, status, agentId, db) {
|
|
1092
|
+
const d = db || getDatabase();
|
|
1093
|
+
const timestamp = now();
|
|
1094
|
+
d.run("UPDATE task_files SET status = ?, agent_id = COALESCE(?, agent_id), updated_at = ? WHERE task_id = ? AND path = ?", [status, agentId || null, timestamp, taskId, path]);
|
|
1095
|
+
const row = d.query("SELECT * FROM task_files WHERE task_id = ? AND path = ?").get(taskId, path);
|
|
1096
|
+
return row;
|
|
1097
|
+
}
|
|
1098
|
+
function removeTaskFile(taskId, path, db) {
|
|
1099
|
+
const d = db || getDatabase();
|
|
1100
|
+
const result = d.run("DELETE FROM task_files WHERE task_id = ? AND path = ?", [taskId, path]);
|
|
1101
|
+
return result.changes > 0;
|
|
1102
|
+
}
|
|
1103
|
+
function bulkAddTaskFiles(taskId, paths, agentId, db) {
|
|
1104
|
+
const d = db || getDatabase();
|
|
1105
|
+
const results = [];
|
|
1106
|
+
const tx = d.transaction(() => {
|
|
1107
|
+
for (const path of paths) {
|
|
1108
|
+
results.push(addTaskFile({ task_id: taskId, path, agent_id: agentId }, d));
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
tx();
|
|
1112
|
+
return results;
|
|
1113
|
+
}
|
|
1114
|
+
var init_task_files = __esm(() => {
|
|
1115
|
+
init_database();
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1039
1118
|
// src/db/handoffs.ts
|
|
1040
1119
|
var exports_handoffs = {};
|
|
1041
1120
|
__export(exports_handoffs, {
|
|
@@ -9901,6 +9980,63 @@ server.resource("agents", "todos://agents", { description: "All registered agent
|
|
|
9901
9980
|
const agents = listAgents();
|
|
9902
9981
|
return { contents: [{ uri: "todos://agents", text: JSON.stringify(agents, null, 2), mimeType: "application/json" }] };
|
|
9903
9982
|
});
|
|
9983
|
+
if (shouldRegisterTool("add_task_file")) {
|
|
9984
|
+
server.tool("add_task_file", "Link a file path to a task. Tracks which files an agent is working on. Upserts if same task+path exists.", {
|
|
9985
|
+
task_id: exports_external.string().describe("Task ID"),
|
|
9986
|
+
path: exports_external.string().describe("File path (relative or absolute)"),
|
|
9987
|
+
paths: exports_external.array(exports_external.string()).optional().describe("Multiple file paths to add at once"),
|
|
9988
|
+
status: exports_external.enum(["planned", "active", "modified", "reviewed", "removed"]).optional().describe("File status (default: active)"),
|
|
9989
|
+
agent_id: exports_external.string().optional().describe("Agent working on this file"),
|
|
9990
|
+
note: exports_external.string().optional().describe("Note about why this file is linked")
|
|
9991
|
+
}, async ({ task_id, path, paths: multiplePaths, status, agent_id, note }) => {
|
|
9992
|
+
try {
|
|
9993
|
+
const { addTaskFile: addTaskFile2, bulkAddTaskFiles: bulkAddTaskFiles2 } = (init_task_files(), __toCommonJS(exports_task_files));
|
|
9994
|
+
const resolvedId = resolveId(task_id);
|
|
9995
|
+
if (multiplePaths && multiplePaths.length > 0) {
|
|
9996
|
+
const allPaths = path ? [path, ...multiplePaths] : multiplePaths;
|
|
9997
|
+
const files = bulkAddTaskFiles2(resolvedId, allPaths, agent_id);
|
|
9998
|
+
return { content: [{ type: "text", text: `${files.length} file(s) linked to task ${resolvedId.slice(0, 8)}` }] };
|
|
9999
|
+
}
|
|
10000
|
+
const file = addTaskFile2({ task_id: resolvedId, path, status, agent_id, note });
|
|
10001
|
+
return { content: [{ type: "text", text: `${file.status} ${file.path} \u2192 task ${resolvedId.slice(0, 8)}` }] };
|
|
10002
|
+
} catch (e) {
|
|
10003
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
10004
|
+
}
|
|
10005
|
+
});
|
|
10006
|
+
}
|
|
10007
|
+
if (shouldRegisterTool("list_task_files")) {
|
|
10008
|
+
server.tool("list_task_files", "List all files linked to a task.", { task_id: exports_external.string().describe("Task ID") }, async ({ task_id }) => {
|
|
10009
|
+
try {
|
|
10010
|
+
const { listTaskFiles: listTaskFiles2 } = (init_task_files(), __toCommonJS(exports_task_files));
|
|
10011
|
+
const resolvedId = resolveId(task_id);
|
|
10012
|
+
const files = listTaskFiles2(resolvedId);
|
|
10013
|
+
if (files.length === 0)
|
|
10014
|
+
return { content: [{ type: "text", text: "No files linked." }] };
|
|
10015
|
+
const lines = files.map((f) => `[${f.status}] ${f.path}${f.agent_id ? ` (${f.agent_id})` : ""}${f.note ? ` \u2014 ${f.note}` : ""}`);
|
|
10016
|
+
return { content: [{ type: "text", text: `${files.length} file(s):
|
|
10017
|
+
${lines.join(`
|
|
10018
|
+
`)}` }] };
|
|
10019
|
+
} catch (e) {
|
|
10020
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
10021
|
+
}
|
|
10022
|
+
});
|
|
10023
|
+
}
|
|
10024
|
+
if (shouldRegisterTool("find_tasks_by_file")) {
|
|
10025
|
+
server.tool("find_tasks_by_file", "Find which tasks are linked to a specific file path. Shows who's working on what files.", { path: exports_external.string().describe("File path to search for") }, async ({ path }) => {
|
|
10026
|
+
try {
|
|
10027
|
+
const { findTasksByFile: findTasksByFile2 } = (init_task_files(), __toCommonJS(exports_task_files));
|
|
10028
|
+
const files = findTasksByFile2(path);
|
|
10029
|
+
if (files.length === 0)
|
|
10030
|
+
return { content: [{ type: "text", text: `No tasks linked to ${path}` }] };
|
|
10031
|
+
const lines = files.map((f) => `${f.task_id.slice(0, 8)} [${f.status}]${f.agent_id ? ` (${f.agent_id})` : ""}`);
|
|
10032
|
+
return { content: [{ type: "text", text: `${files.length} task(s) linked to ${path}:
|
|
10033
|
+
${lines.join(`
|
|
10034
|
+
`)}` }] };
|
|
10035
|
+
} catch (e) {
|
|
10036
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
10037
|
+
}
|
|
10038
|
+
});
|
|
10039
|
+
}
|
|
9904
10040
|
if (shouldRegisterTool("create_handoff")) {
|
|
9905
10041
|
server.tool("create_handoff", "Create a session handoff note for agent coordination.", {
|
|
9906
10042
|
agent_id: exports_external.string().optional().describe("Agent creating the handoff"),
|
package/dist/server/index.js
CHANGED
|
@@ -769,6 +769,22 @@ var init_database = __esm(() => {
|
|
|
769
769
|
CREATE INDEX IF NOT EXISTS idx_resource_locks_type_id ON resource_locks(resource_type, resource_id);
|
|
770
770
|
CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id);
|
|
771
771
|
INSERT OR IGNORE INTO _migrations (id) VALUES (24);
|
|
772
|
+
`,
|
|
773
|
+
`
|
|
774
|
+
CREATE TABLE IF NOT EXISTS task_files (
|
|
775
|
+
id TEXT PRIMARY KEY,
|
|
776
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
777
|
+
path TEXT NOT NULL,
|
|
778
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
779
|
+
agent_id TEXT,
|
|
780
|
+
note TEXT,
|
|
781
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
782
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
783
|
+
);
|
|
784
|
+
CREATE INDEX IF NOT EXISTS idx_task_files_task ON task_files(task_id);
|
|
785
|
+
CREATE INDEX IF NOT EXISTS idx_task_files_path ON task_files(path);
|
|
786
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_files_task_path ON task_files(task_id, path);
|
|
787
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (25);
|
|
772
788
|
`
|
|
773
789
|
];
|
|
774
790
|
});
|