@hasna/todos 0.11.27 → 0.11.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 +424 -91
- package/dist/db/agents.d.ts.map +1 -1
- package/dist/db/pg-migrations.d.ts.map +1 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/tasks.d.ts +26 -1
- package/dist/db/tasks.d.ts.map +1 -1
- package/dist/db/webhooks.d.ts +5 -0
- package/dist/db/webhooks.d.ts.map +1 -1
- package/dist/index.js +144 -13
- package/dist/mcp/index.js +362 -34
- package/dist/mcp/tools/webhooks.d.ts.map +1 -1
- package/dist/server/index.js +181 -8
- package/dist/types/index.d.ts +28 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -6,60 +6,39 @@ var __defProp = Object.defineProperty;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
function __accessProp(key) {
|
|
10
|
-
return this[key];
|
|
11
|
-
}
|
|
12
|
-
var __toESMCache_node;
|
|
13
|
-
var __toESMCache_esm;
|
|
14
9
|
var __toESM = (mod, isNodeMode, target) => {
|
|
15
|
-
var canCache = mod != null && typeof mod === "object";
|
|
16
|
-
if (canCache) {
|
|
17
|
-
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
18
|
-
var cached = cache.get(mod);
|
|
19
|
-
if (cached)
|
|
20
|
-
return cached;
|
|
21
|
-
}
|
|
22
10
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
23
11
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
24
12
|
for (let key of __getOwnPropNames(mod))
|
|
25
13
|
if (!__hasOwnProp.call(to, key))
|
|
26
14
|
__defProp(to, key, {
|
|
27
|
-
get:
|
|
15
|
+
get: () => mod[key],
|
|
28
16
|
enumerable: true
|
|
29
17
|
});
|
|
30
|
-
if (canCache)
|
|
31
|
-
cache.set(mod, to);
|
|
32
18
|
return to;
|
|
33
19
|
};
|
|
20
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
34
21
|
var __toCommonJS = (from) => {
|
|
35
|
-
var entry =
|
|
22
|
+
var entry = __moduleCache.get(from), desc;
|
|
36
23
|
if (entry)
|
|
37
24
|
return entry;
|
|
38
25
|
entry = __defProp({}, "__esModule", { value: true });
|
|
39
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
45
|
-
});
|
|
46
|
-
}
|
|
26
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
27
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
28
|
+
get: () => from[key],
|
|
29
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
30
|
+
}));
|
|
47
31
|
__moduleCache.set(from, entry);
|
|
48
32
|
return entry;
|
|
49
33
|
};
|
|
50
|
-
var __moduleCache;
|
|
51
34
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
52
|
-
var __returnValue = (v) => v;
|
|
53
|
-
function __exportSetter(name, newValue) {
|
|
54
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
55
|
-
}
|
|
56
35
|
var __export = (target, all) => {
|
|
57
36
|
for (var name in all)
|
|
58
37
|
__defProp(target, name, {
|
|
59
38
|
get: all[name],
|
|
60
39
|
enumerable: true,
|
|
61
40
|
configurable: true,
|
|
62
|
-
set:
|
|
41
|
+
set: (newValue) => all[name] = () => newValue
|
|
63
42
|
});
|
|
64
43
|
};
|
|
65
44
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -2444,6 +2423,32 @@ function ensureSchema(db) {
|
|
|
2444
2423
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_synced ON tasks(synced_at)");
|
|
2445
2424
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_projects_machine ON projects(machine_id)");
|
|
2446
2425
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_agents_machine ON agents(machine_id)");
|
|
2426
|
+
ensureTable("task_time_logs", `
|
|
2427
|
+
CREATE TABLE task_time_logs (
|
|
2428
|
+
id TEXT PRIMARY KEY,
|
|
2429
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
2430
|
+
agent_id TEXT,
|
|
2431
|
+
started_at TEXT,
|
|
2432
|
+
ended_at TEXT,
|
|
2433
|
+
minutes INTEGER NOT NULL,
|
|
2434
|
+
notes TEXT,
|
|
2435
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2436
|
+
)`);
|
|
2437
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_time_logs_task ON task_time_logs(task_id)");
|
|
2438
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_time_logs_agent ON task_time_logs(agent_id)");
|
|
2439
|
+
ensureColumn("tasks", "actual_minutes", "INTEGER");
|
|
2440
|
+
ensureTable("task_watchers", `
|
|
2441
|
+
CREATE TABLE task_watchers (
|
|
2442
|
+
id TEXT PRIMARY KEY,
|
|
2443
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
2444
|
+
agent_id TEXT NOT NULL,
|
|
2445
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
2446
|
+
UNIQUE(task_id, agent_id)
|
|
2447
|
+
)`);
|
|
2448
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_watchers_task ON task_watchers(task_id)");
|
|
2449
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_watchers_agent ON task_watchers(agent_id)");
|
|
2450
|
+
ensureColumn("task_dependencies", "external_project_id", "TEXT");
|
|
2451
|
+
ensureColumn("task_dependencies", "external_task_id", "TEXT");
|
|
2447
2452
|
}
|
|
2448
2453
|
function backfillTaskTags(db) {
|
|
2449
2454
|
try {
|
|
@@ -3171,6 +3176,39 @@ var init_schema = __esm(() => {
|
|
|
3171
3176
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_short_id ON tasks(short_id, machine_id) WHERE short_id IS NOT NULL AND machine_id IS NOT NULL;
|
|
3172
3177
|
CREATE INDEX IF NOT EXISTS idx_tasks_short_id_lookup ON tasks(short_id) WHERE short_id IS NOT NULL;
|
|
3173
3178
|
INSERT OR IGNORE INTO _migrations (id) VALUES (44);
|
|
3179
|
+
`,
|
|
3180
|
+
`
|
|
3181
|
+
CREATE TABLE IF NOT EXISTS task_time_logs (
|
|
3182
|
+
id TEXT PRIMARY KEY,
|
|
3183
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
3184
|
+
agent_id TEXT,
|
|
3185
|
+
started_at TEXT,
|
|
3186
|
+
ended_at TEXT,
|
|
3187
|
+
minutes INTEGER NOT NULL,
|
|
3188
|
+
notes TEXT,
|
|
3189
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
3190
|
+
);
|
|
3191
|
+
CREATE INDEX IF NOT EXISTS idx_task_time_logs_task ON task_time_logs(task_id);
|
|
3192
|
+
CREATE INDEX IF NOT EXISTS idx_task_time_logs_agent ON task_time_logs(agent_id);
|
|
3193
|
+
ALTER TABLE tasks ADD COLUMN actual_minutes INTEGER;
|
|
3194
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (45);
|
|
3195
|
+
`,
|
|
3196
|
+
`
|
|
3197
|
+
CREATE TABLE IF NOT EXISTS task_watchers (
|
|
3198
|
+
id TEXT PRIMARY KEY,
|
|
3199
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
3200
|
+
agent_id TEXT NOT NULL,
|
|
3201
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
3202
|
+
UNIQUE(task_id, agent_id)
|
|
3203
|
+
);
|
|
3204
|
+
CREATE INDEX IF NOT EXISTS idx_task_watchers_task ON task_watchers(task_id);
|
|
3205
|
+
CREATE INDEX IF NOT EXISTS idx_task_watchers_agent ON task_watchers(agent_id);
|
|
3206
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (46);
|
|
3207
|
+
`,
|
|
3208
|
+
`
|
|
3209
|
+
ALTER TABLE task_dependencies ADD COLUMN external_project_id TEXT;
|
|
3210
|
+
ALTER TABLE task_dependencies ADD COLUMN external_task_id TEXT;
|
|
3211
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (47);
|
|
3174
3212
|
`
|
|
3175
3213
|
];
|
|
3176
3214
|
});
|
|
@@ -4161,6 +4199,7 @@ var init_recurrence = __esm(() => {
|
|
|
4161
4199
|
// src/db/webhooks.ts
|
|
4162
4200
|
var exports_webhooks = {};
|
|
4163
4201
|
__export(exports_webhooks, {
|
|
4202
|
+
validateWebhookUrl: () => validateWebhookUrl,
|
|
4164
4203
|
listWebhooks: () => listWebhooks,
|
|
4165
4204
|
listDeliveries: () => listDeliveries,
|
|
4166
4205
|
getWebhook: () => getWebhook,
|
|
@@ -4168,6 +4207,40 @@ __export(exports_webhooks, {
|
|
|
4168
4207
|
deleteWebhook: () => deleteWebhook,
|
|
4169
4208
|
createWebhook: () => createWebhook
|
|
4170
4209
|
});
|
|
4210
|
+
function validateWebhookUrl(urlString) {
|
|
4211
|
+
try {
|
|
4212
|
+
const url = new URL(urlString);
|
|
4213
|
+
if (url.protocol !== "https:") {
|
|
4214
|
+
throw new Error("Webhook URLs must use HTTPS");
|
|
4215
|
+
}
|
|
4216
|
+
const hostname = url.hostname.toLowerCase();
|
|
4217
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "0.0.0.0") {
|
|
4218
|
+
throw new Error("Webhook URLs cannot target localhost");
|
|
4219
|
+
}
|
|
4220
|
+
if (hostname === "169.254.169.254" || hostname.startsWith("169.254.")) {
|
|
4221
|
+
throw new Error("Webhook URLs cannot target cloud metadata endpoints");
|
|
4222
|
+
}
|
|
4223
|
+
const privateRanges = [
|
|
4224
|
+
/^10\./,
|
|
4225
|
+
/^172\.(1[6-9]|2\d|3[01])\./,
|
|
4226
|
+
/^192\.168\./,
|
|
4227
|
+
/^127\./,
|
|
4228
|
+
/^169\.254\./,
|
|
4229
|
+
/^fc00:/i,
|
|
4230
|
+
/^fe80:/i
|
|
4231
|
+
];
|
|
4232
|
+
for (const range of privateRanges) {
|
|
4233
|
+
if (range.test(hostname)) {
|
|
4234
|
+
throw new Error("Webhook URLs cannot target private IP ranges");
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
} catch (e) {
|
|
4238
|
+
if (e instanceof Error && e.message.startsWith("Webhook URLs")) {
|
|
4239
|
+
throw e;
|
|
4240
|
+
}
|
|
4241
|
+
throw new Error(`Invalid webhook URL: ${urlString}`);
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4171
4244
|
function rowToWebhook(row) {
|
|
4172
4245
|
return {
|
|
4173
4246
|
...row,
|
|
@@ -4181,6 +4254,7 @@ function rowToWebhook(row) {
|
|
|
4181
4254
|
}
|
|
4182
4255
|
function createWebhook(input, db) {
|
|
4183
4256
|
const d = db || getDatabase();
|
|
4257
|
+
validateWebhookUrl(input.url);
|
|
4184
4258
|
const id = uuid();
|
|
4185
4259
|
d.run(`INSERT INTO webhooks (id, url, events, secret, project_id, task_list_id, agent_id, task_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
4186
4260
|
id,
|
|
@@ -4779,7 +4853,9 @@ var init_checklists = __esm(() => {
|
|
|
4779
4853
|
// src/db/tasks.ts
|
|
4780
4854
|
var exports_tasks = {};
|
|
4781
4855
|
__export(exports_tasks, {
|
|
4856
|
+
watchTask: () => watchTask,
|
|
4782
4857
|
updateTask: () => updateTask,
|
|
4858
|
+
unwatchTask: () => unwatchTask,
|
|
4783
4859
|
unlockTask: () => unlockTask,
|
|
4784
4860
|
unarchiveTask: () => unarchiveTask,
|
|
4785
4861
|
stealTask: () => stealTask,
|
|
@@ -4788,12 +4864,17 @@ __export(exports_tasks, {
|
|
|
4788
4864
|
setTaskPriority: () => setTaskPriority,
|
|
4789
4865
|
removeDependency: () => removeDependency,
|
|
4790
4866
|
redistributeStaleTasks: () => redistributeStaleTasks,
|
|
4867
|
+
notifyWatchers: () => notifyWatchers,
|
|
4791
4868
|
moveTask: () => moveTask,
|
|
4869
|
+
logTime: () => logTime,
|
|
4792
4870
|
logCost: () => logCost,
|
|
4793
4871
|
lockTask: () => lockTask,
|
|
4794
4872
|
listTasks: () => listTasks,
|
|
4873
|
+
getTimeReport: () => getTimeReport,
|
|
4874
|
+
getTimeLogs: () => getTimeLogs,
|
|
4795
4875
|
getTasksChangedSince: () => getTasksChangedSince,
|
|
4796
4876
|
getTaskWithRelations: () => getTaskWithRelations,
|
|
4877
|
+
getTaskWatchers: () => getTaskWatchers,
|
|
4797
4878
|
getTaskStats: () => getTaskStats,
|
|
4798
4879
|
getTaskGraph: () => getTaskGraph,
|
|
4799
4880
|
getTaskDependents: () => getTaskDependents,
|
|
@@ -5976,6 +6057,58 @@ function getOverdueTasks(projectId, db) {
|
|
|
5976
6057
|
const rows = d.query(query).all(...params);
|
|
5977
6058
|
return rows.map(rowToTask);
|
|
5978
6059
|
}
|
|
6060
|
+
function logTime(input, db) {
|
|
6061
|
+
const d = db || getDatabase();
|
|
6062
|
+
const id = uuid();
|
|
6063
|
+
const ts = now();
|
|
6064
|
+
d.run(`INSERT INTO task_time_logs (id, task_id, agent_id, minutes, started_at, ended_at, notes, created_at)
|
|
6065
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, input.task_id, input.agent_id || null, input.minutes, input.started_at || null, input.ended_at || null, input.notes || null, ts]);
|
|
6066
|
+
return { id, task_id: input.task_id, agent_id: input.agent_id || null, minutes: input.minutes, started_at: input.started_at || null, ended_at: input.ended_at || null, notes: input.notes || null, created_at: ts };
|
|
6067
|
+
}
|
|
6068
|
+
function getTimeLogs(taskId, db) {
|
|
6069
|
+
const d = db || getDatabase();
|
|
6070
|
+
return d.query(`SELECT * FROM task_time_logs WHERE task_id = ? ORDER BY created_at DESC`).all(taskId);
|
|
6071
|
+
}
|
|
6072
|
+
function getTimeReport(opts, db) {
|
|
6073
|
+
const d = db || getDatabase();
|
|
6074
|
+
let query = `SELECT t.id as task_id, t.title, t.estimated_minutes, t.actual_minutes FROM tasks t WHERE t.status = 'completed'`;
|
|
6075
|
+
const params = [];
|
|
6076
|
+
if (opts?.project_id) {
|
|
6077
|
+
query += ` AND t.project_id = ?`;
|
|
6078
|
+
params.push(opts.project_id);
|
|
6079
|
+
}
|
|
6080
|
+
if (opts?.agent_id) {
|
|
6081
|
+
query += ` AND t.assigned_to = ?`;
|
|
6082
|
+
params.push(opts.agent_id);
|
|
6083
|
+
}
|
|
6084
|
+
if (opts?.since) {
|
|
6085
|
+
query += ` AND t.completed_at >= ?`;
|
|
6086
|
+
params.push(opts.since);
|
|
6087
|
+
}
|
|
6088
|
+
const rows = d.query(query).all(...params);
|
|
6089
|
+
return rows.map((row) => ({ ...row, time_logs: getTimeLogs(row.task_id, d) }));
|
|
6090
|
+
}
|
|
6091
|
+
function watchTask(taskId, agentId, db) {
|
|
6092
|
+
const d = db || getDatabase();
|
|
6093
|
+
const id = uuid();
|
|
6094
|
+
const ts = now();
|
|
6095
|
+
d.run(`INSERT OR IGNORE INTO task_watchers (id, task_id, agent_id, created_at) VALUES (?, ?, ?, ?)`, [id, taskId, agentId, ts]);
|
|
6096
|
+
const existing = d.query(`SELECT * FROM task_watchers WHERE task_id = ? AND agent_id = ?`).get(taskId, agentId);
|
|
6097
|
+
return existing;
|
|
6098
|
+
}
|
|
6099
|
+
function unwatchTask(taskId, agentId, db) {
|
|
6100
|
+
const d = db || getDatabase();
|
|
6101
|
+
const result = d.run(`DELETE FROM task_watchers WHERE task_id = ? AND agent_id = ?`, [taskId, agentId]);
|
|
6102
|
+
return result.changes > 0;
|
|
6103
|
+
}
|
|
6104
|
+
function getTaskWatchers(taskId, db) {
|
|
6105
|
+
const d = db || getDatabase();
|
|
6106
|
+
return d.query(`SELECT * FROM task_watchers WHERE task_id = ?`).all(taskId);
|
|
6107
|
+
}
|
|
6108
|
+
function notifyWatchers(taskId, event, data, db) {
|
|
6109
|
+
const watchers = getTaskWatchers(taskId, db);
|
|
6110
|
+
dispatchWebhook(`task.watcher.${event}`, { task_id: taskId, watchers: watchers.map((w) => w.agent_id), ...data }, db).catch(() => {});
|
|
6111
|
+
}
|
|
5979
6112
|
var init_tasks = __esm(() => {
|
|
5980
6113
|
init_types();
|
|
5981
6114
|
init_database();
|
|
@@ -6062,6 +6195,9 @@ function registerAgent(input, db) {
|
|
|
6062
6195
|
if (callerHasNoSession && existingHasActiveSession) {
|
|
6063
6196
|
return buildConflictError(existing, lastSeenMs, input.pool, d);
|
|
6064
6197
|
}
|
|
6198
|
+
if (input.project_id && existing.session_id && isActive && existing.active_project_id && existing.active_project_id !== input.project_id) {
|
|
6199
|
+
return buildConflictError(existing, lastSeenMs, input.pool, d);
|
|
6200
|
+
}
|
|
6065
6201
|
}
|
|
6066
6202
|
const updates = ["last_seen_at = ?", "status = 'active'"];
|
|
6067
6203
|
const params = [now()];
|
|
@@ -6077,14 +6213,18 @@ function registerAgent(input, db) {
|
|
|
6077
6213
|
updates.push("description = ?");
|
|
6078
6214
|
params.push(input.description);
|
|
6079
6215
|
}
|
|
6216
|
+
if (input.project_id && input.session_id) {
|
|
6217
|
+
updates.push("active_project_id = ?");
|
|
6218
|
+
params.push(input.project_id);
|
|
6219
|
+
}
|
|
6080
6220
|
params.push(existing.id);
|
|
6081
6221
|
d.run(`UPDATE agents SET ${updates.join(", ")} WHERE id = ?`, params);
|
|
6082
6222
|
return getAgent(existing.id, d);
|
|
6083
6223
|
}
|
|
6084
6224
|
const id = shortUuid();
|
|
6085
6225
|
const timestamp = now();
|
|
6086
|
-
d.run(`INSERT INTO agents (id, name, description, role, title, level, permissions, capabilities, reports_to, org_id, metadata, created_at, last_seen_at, session_id, working_dir)
|
|
6087
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
6226
|
+
d.run(`INSERT INTO agents (id, name, description, role, title, level, permissions, capabilities, reports_to, org_id, metadata, created_at, last_seen_at, session_id, working_dir, active_project_id)
|
|
6227
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
6088
6228
|
id,
|
|
6089
6229
|
normalizedName,
|
|
6090
6230
|
input.description || null,
|
|
@@ -6099,7 +6239,8 @@ function registerAgent(input, db) {
|
|
|
6099
6239
|
timestamp,
|
|
6100
6240
|
timestamp,
|
|
6101
6241
|
input.session_id || null,
|
|
6102
|
-
input.working_dir || null
|
|
6242
|
+
input.working_dir || null,
|
|
6243
|
+
input.project_id && input.session_id ? input.project_id : null
|
|
6103
6244
|
]);
|
|
6104
6245
|
return getAgent(id, d);
|
|
6105
6246
|
}
|
|
@@ -11889,7 +12030,7 @@ var init_zod = __esm(() => {
|
|
|
11889
12030
|
init_external();
|
|
11890
12031
|
});
|
|
11891
12032
|
|
|
11892
|
-
// node_modules/@hasna/cloud/dist/index.js
|
|
12033
|
+
// ../../../../node_modules/@hasna/cloud/dist/index.js
|
|
11893
12034
|
var exports_dist = {};
|
|
11894
12035
|
__export(exports_dist, {
|
|
11895
12036
|
translateSql: () => translateSql,
|
|
@@ -11984,11 +12125,11 @@ import { join as join52 } from "path";
|
|
|
11984
12125
|
import { join as join62, dirname as dirname2 } from "path";
|
|
11985
12126
|
import { existsSync as existsSync62, writeFileSync as writeFileSync22, unlinkSync, mkdirSync as mkdirSync32 } from "fs";
|
|
11986
12127
|
import { homedir as homedir5, platform } from "os";
|
|
11987
|
-
function
|
|
12128
|
+
function __accessProp(key) {
|
|
11988
12129
|
return this[key];
|
|
11989
12130
|
}
|
|
11990
|
-
function
|
|
11991
|
-
this[name] =
|
|
12131
|
+
function __exportSetter(name, newValue) {
|
|
12132
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
11992
12133
|
}
|
|
11993
12134
|
function translateSql(sql, dialect) {
|
|
11994
12135
|
if (dialect === "sqlite")
|
|
@@ -14445,7 +14586,7 @@ async function ensureAllPgDatabases() {
|
|
|
14445
14586
|
}
|
|
14446
14587
|
return results;
|
|
14447
14588
|
}
|
|
14448
|
-
function registerCloudTools(server, serviceName) {
|
|
14589
|
+
function registerCloudTools(server, serviceName, opts = {}) {
|
|
14449
14590
|
server.tool(`${serviceName}_cloud_status`, "Show cloud configuration and connection health", {}, async () => {
|
|
14450
14591
|
const config = getCloudConfig();
|
|
14451
14592
|
const lines = [
|
|
@@ -14478,8 +14619,13 @@ function registerCloudTools(server, serviceName) {
|
|
|
14478
14619
|
isError: true
|
|
14479
14620
|
};
|
|
14480
14621
|
}
|
|
14481
|
-
const local = new SqliteAdapter(getDbPath2(serviceName));
|
|
14622
|
+
const local = new SqliteAdapter(opts.dbPath ?? getDbPath2(serviceName));
|
|
14482
14623
|
const cloud = new PgAdapterAsync(getConnectionString(serviceName));
|
|
14624
|
+
if (opts.migrations?.length) {
|
|
14625
|
+
for (const sql of opts.migrations) {
|
|
14626
|
+
await cloud.run(sql);
|
|
14627
|
+
}
|
|
14628
|
+
}
|
|
14483
14629
|
const tableList = tablesStr ? tablesStr.split(",").map((t) => t.trim()) : listSqliteTables(local);
|
|
14484
14630
|
const results = await syncPush(local, cloud, { tables: tableList });
|
|
14485
14631
|
local.close();
|
|
@@ -14501,7 +14647,7 @@ function registerCloudTools(server, serviceName) {
|
|
|
14501
14647
|
isError: true
|
|
14502
14648
|
};
|
|
14503
14649
|
}
|
|
14504
|
-
const local = new SqliteAdapter(getDbPath2(serviceName));
|
|
14650
|
+
const local = new SqliteAdapter(opts.dbPath ?? getDbPath2(serviceName));
|
|
14505
14651
|
const cloud = new PgAdapterAsync(getConnectionString(serviceName));
|
|
14506
14652
|
let tableList;
|
|
14507
14653
|
if (tablesStr) {
|
|
@@ -14624,10 +14770,10 @@ function registerCloudCommands(program2, serviceName) {
|
|
|
14624
14770
|
}
|
|
14625
14771
|
});
|
|
14626
14772
|
}
|
|
14627
|
-
var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2,
|
|
14773
|
+
var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2, __toESMCache_node, __toESMCache_esm, __toESM2 = (mod, isNodeMode, target) => {
|
|
14628
14774
|
var canCache = mod != null && typeof mod === "object";
|
|
14629
14775
|
if (canCache) {
|
|
14630
|
-
var cache = isNodeMode ?
|
|
14776
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
14631
14777
|
var cached2 = cache.get(mod);
|
|
14632
14778
|
if (cached2)
|
|
14633
14779
|
return cached2;
|
|
@@ -14637,19 +14783,19 @@ var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2, __t
|
|
|
14637
14783
|
for (let key of __getOwnPropNames2(mod))
|
|
14638
14784
|
if (!__hasOwnProp2.call(to, key))
|
|
14639
14785
|
__defProp2(to, key, {
|
|
14640
|
-
get:
|
|
14786
|
+
get: __accessProp.bind(mod, key),
|
|
14641
14787
|
enumerable: true
|
|
14642
14788
|
});
|
|
14643
14789
|
if (canCache)
|
|
14644
14790
|
cache.set(mod, to);
|
|
14645
14791
|
return to;
|
|
14646
|
-
}, __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports),
|
|
14792
|
+
}, __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports), __returnValue = (v) => v, __export2 = (target, all) => {
|
|
14647
14793
|
for (var name in all)
|
|
14648
14794
|
__defProp2(target, name, {
|
|
14649
14795
|
get: all[name],
|
|
14650
14796
|
enumerable: true,
|
|
14651
14797
|
configurable: true,
|
|
14652
|
-
set:
|
|
14798
|
+
set: __exportSetter.bind(all, name)
|
|
14653
14799
|
});
|
|
14654
14800
|
}, __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), __require2, require_postgres_array, require_arrayParser, require_postgres_date, require_mutable, require_postgres_interval, require_postgres_bytea, require_textParsers, require_pg_int8, require_binaryParsers, require_builtins, require_pg_types, require_defaults, require_utils, require_utils_legacy, require_utils_webcrypto, require_utils2, require_cert_signatures, require_sasl, require_type_overrides, require_pg_connection_string, require_connection_parameters, require_result, require_query, require_messages, require_buffer_writer, require_serializer, require_buffer_reader, require_parser, require_dist, require_empty, require_stream, require_connection, require_split2, require_helper, require_lib, require_client, require_pg_pool, require_query2, require_client2, require_lib2, import_lib, Client, Pool, Connection, types2, Query, DatabaseError, escapeIdentifier, escapeLiteral, Result, TypeOverrides, defaults, esm_default, init_esm, init_adapter, util3, objectUtil2, ZodParsedType2, getParsedType2 = (data) => {
|
|
14655
14801
|
const t = typeof data;
|
|
@@ -23710,7 +23856,8 @@ function registerWebhookTools(server, { shouldRegisterTool, formatError }) {
|
|
|
23710
23856
|
task_id: exports_external.string().optional().describe("Only fire for events on this specific task")
|
|
23711
23857
|
}, async (params) => {
|
|
23712
23858
|
try {
|
|
23713
|
-
const { createWebhook: createWebhook2 } = await Promise.resolve().then(() => (init_webhooks(), exports_webhooks));
|
|
23859
|
+
const { createWebhook: createWebhook2, validateWebhookUrl: validateWebhookUrl2 } = await Promise.resolve().then(() => (init_webhooks(), exports_webhooks));
|
|
23860
|
+
validateWebhookUrl2(params.url);
|
|
23714
23861
|
const wh = createWebhook2(params);
|
|
23715
23862
|
const scope = [wh.project_id && `project:${wh.project_id}`, wh.task_list_id && `list:${wh.task_list_id}`, wh.agent_id && `agent:${wh.agent_id}`, wh.task_id && `task:${wh.task_id}`].filter(Boolean).join(", ");
|
|
23716
23863
|
return { content: [{ type: "text", text: `Webhook created: ${wh.id.slice(0, 8)} | ${wh.url} | events: ${wh.events.length === 0 ? "all" : wh.events.join(",")}${scope ? ` | scope: ${scope}` : ""}` }] };
|
|
@@ -25979,6 +26126,39 @@ var init_pg_migrations = __esm(() => {
|
|
|
25979
26126
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_short_id ON tasks(short_id, machine_id) WHERE short_id IS NOT NULL AND machine_id IS NOT NULL;
|
|
25980
26127
|
CREATE INDEX IF NOT EXISTS idx_tasks_short_id_lookup ON tasks(short_id) WHERE short_id IS NOT NULL;
|
|
25981
26128
|
INSERT INTO _migrations (id) VALUES (40) ON CONFLICT DO NOTHING;
|
|
26129
|
+
`,
|
|
26130
|
+
`
|
|
26131
|
+
CREATE TABLE IF NOT EXISTS task_time_logs (
|
|
26132
|
+
id TEXT PRIMARY KEY,
|
|
26133
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
26134
|
+
agent_id TEXT,
|
|
26135
|
+
started_at TIMESTAMPTZ,
|
|
26136
|
+
ended_at TIMESTAMPTZ,
|
|
26137
|
+
minutes INTEGER NOT NULL,
|
|
26138
|
+
notes TEXT,
|
|
26139
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
26140
|
+
);
|
|
26141
|
+
CREATE INDEX IF NOT EXISTS idx_task_time_logs_task ON task_time_logs(task_id);
|
|
26142
|
+
CREATE INDEX IF NOT EXISTS idx_task_time_logs_agent ON task_time_logs(agent_id);
|
|
26143
|
+
ALTER TABLE tasks ADD COLUMN actual_minutes INTEGER;
|
|
26144
|
+
INSERT INTO _migrations (id) VALUES (41) ON CONFLICT DO NOTHING;
|
|
26145
|
+
`,
|
|
26146
|
+
`
|
|
26147
|
+
CREATE TABLE IF NOT EXISTS task_watchers (
|
|
26148
|
+
id TEXT PRIMARY KEY,
|
|
26149
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
26150
|
+
agent_id TEXT NOT NULL,
|
|
26151
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
26152
|
+
UNIQUE(task_id, agent_id)
|
|
26153
|
+
);
|
|
26154
|
+
CREATE INDEX IF NOT EXISTS idx_task_watchers_task ON task_watchers(task_id);
|
|
26155
|
+
CREATE INDEX IF NOT EXISTS idx_task_watchers_agent ON task_watchers(agent_id);
|
|
26156
|
+
INSERT INTO _migrations (id) VALUES (42) ON CONFLICT DO NOTHING;
|
|
26157
|
+
`,
|
|
26158
|
+
`
|
|
26159
|
+
ALTER TABLE task_dependencies ADD COLUMN external_project_id TEXT;
|
|
26160
|
+
ALTER TABLE task_dependencies ADD COLUMN external_task_id TEXT;
|
|
26161
|
+
INSERT INTO _migrations (id) VALUES (43) ON CONFLICT DO NOTHING;
|
|
25982
26162
|
`
|
|
25983
26163
|
];
|
|
25984
26164
|
});
|
|
@@ -27968,7 +28148,7 @@ Blocks:
|
|
|
27968
28148
|
}
|
|
27969
28149
|
if (shouldRegisterTool("bulk_create_tasks")) {
|
|
27970
28150
|
server.tool("bulk_create_tasks", "Create multiple tasks atomically with dependency support.", {
|
|
27971
|
-
tasks: exports_external.array(exports_external.object({
|
|
28151
|
+
tasks: exports_external.preprocess((val) => typeof val === "string" ? JSON.parse(val) : val, exports_external.array(exports_external.object({
|
|
27972
28152
|
temp_id: exports_external.string().optional(),
|
|
27973
28153
|
title: exports_external.string(),
|
|
27974
28154
|
description: exports_external.string().optional(),
|
|
@@ -27982,7 +28162,7 @@ Blocks:
|
|
|
27982
28162
|
tags: exports_external.array(exports_external.string()).optional(),
|
|
27983
28163
|
estimated_minutes: exports_external.number().optional(),
|
|
27984
28164
|
depends_on_temp_ids: exports_external.array(exports_external.string()).optional()
|
|
27985
|
-
})),
|
|
28165
|
+
}))),
|
|
27986
28166
|
project_id: exports_external.string().optional(),
|
|
27987
28167
|
plan_id: exports_external.string().optional(),
|
|
27988
28168
|
task_list_id: exports_external.string().optional()
|
|
@@ -29718,6 +29898,143 @@ ${lines.join(`
|
|
|
29718
29898
|
}
|
|
29719
29899
|
});
|
|
29720
29900
|
}
|
|
29901
|
+
if (shouldRegisterTool("log_time")) {
|
|
29902
|
+
server.tool("log_time", "Log time spent on a task.", {
|
|
29903
|
+
task_id: exports_external.string().describe("Task ID to log time against"),
|
|
29904
|
+
minutes: exports_external.number().min(1).describe("Minutes spent"),
|
|
29905
|
+
agent_id: exports_external.string().optional().describe("Agent logging the time"),
|
|
29906
|
+
started_at: exports_external.string().optional().describe("ISO timestamp when work started"),
|
|
29907
|
+
ended_at: exports_external.string().optional().describe("ISO timestamp when work ended"),
|
|
29908
|
+
notes: exports_external.string().optional().describe("Notes about what was done")
|
|
29909
|
+
}, async ({ task_id, minutes, agent_id, started_at, ended_at, notes }) => {
|
|
29910
|
+
try {
|
|
29911
|
+
const { logTime: logTime2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
29912
|
+
logTime2({ task_id: resolveId(task_id), minutes, agent_id, started_at, ended_at, notes });
|
|
29913
|
+
return { content: [{ type: "text", text: `Logged ${minutes} min on task ${task_id.slice(0, 8)}` }] };
|
|
29914
|
+
} catch (e) {
|
|
29915
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
29916
|
+
}
|
|
29917
|
+
});
|
|
29918
|
+
}
|
|
29919
|
+
if (shouldRegisterTool("get_time_report")) {
|
|
29920
|
+
server.tool("get_time_report", "Get time tracking report: actual vs estimated minutes for completed tasks.", {
|
|
29921
|
+
project_id: exports_external.string().optional().describe("Filter by project"),
|
|
29922
|
+
agent_id: exports_external.string().optional().describe("Filter by assignee"),
|
|
29923
|
+
since: exports_external.string().optional().describe("ISO date \u2014 only tasks completed after this date")
|
|
29924
|
+
}, async ({ project_id, agent_id, since }) => {
|
|
29925
|
+
try {
|
|
29926
|
+
const { getTimeReport: getTimeReport2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
29927
|
+
const report = getTimeReport2({ project_id: project_id ? resolveId(project_id, "projects") : undefined, agent_id, since });
|
|
29928
|
+
if (report.length === 0)
|
|
29929
|
+
return { content: [{ type: "text", text: "No completed tasks found." }] };
|
|
29930
|
+
const lines = report.map((r) => {
|
|
29931
|
+
const est = r.estimated_minutes ?? "?";
|
|
29932
|
+
const actual = r.actual_minutes ?? "?";
|
|
29933
|
+
const diff = r.estimated_minutes != null && r.actual_minutes != null ? ` (${r.actual_minutes - r.estimated_minutes >= 0 ? "+" : ""}${r.actual_minutes - r.estimated_minutes})` : "";
|
|
29934
|
+
return `${r.title.slice(0, 50)}: estimated ${est}min, actual ${actual}min${diff}`;
|
|
29935
|
+
});
|
|
29936
|
+
return { content: [{ type: "text", text: `Time Report:
|
|
29937
|
+
${lines.join(`
|
|
29938
|
+
`)}` }] };
|
|
29939
|
+
} catch (e) {
|
|
29940
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
29941
|
+
}
|
|
29942
|
+
});
|
|
29943
|
+
}
|
|
29944
|
+
if (shouldRegisterTool("watch_task")) {
|
|
29945
|
+
server.tool("watch_task", "Subscribe to notifications for a task.", {
|
|
29946
|
+
task_id: exports_external.string().describe("Task ID to watch"),
|
|
29947
|
+
agent_id: exports_external.string().optional().describe("Agent subscribing (defaults to context agent)")
|
|
29948
|
+
}, async ({ task_id, agent_id }) => {
|
|
29949
|
+
try {
|
|
29950
|
+
const { watchTask: watchTask2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
29951
|
+
watchTask2(resolveId(task_id), agent_id || "");
|
|
29952
|
+
return { content: [{ type: "text", text: `Now watching task ${task_id.slice(0, 8)}` }] };
|
|
29953
|
+
} catch (e) {
|
|
29954
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
29955
|
+
}
|
|
29956
|
+
});
|
|
29957
|
+
}
|
|
29958
|
+
if (shouldRegisterTool("unwatch_task")) {
|
|
29959
|
+
server.tool("unwatch_task", "Unsubscribe from notifications for a task.", {
|
|
29960
|
+
task_id: exports_external.string().describe("Task ID to unwatch"),
|
|
29961
|
+
agent_id: exports_external.string().optional().describe("Agent unsubscribing (defaults to context agent)")
|
|
29962
|
+
}, async ({ task_id, agent_id }) => {
|
|
29963
|
+
try {
|
|
29964
|
+
const { unwatchTask: unwatchTask2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
29965
|
+
unwatchTask2(resolveId(task_id), agent_id || "");
|
|
29966
|
+
return { content: [{ type: "text", text: `Stopped watching task ${task_id.slice(0, 8)}` }] };
|
|
29967
|
+
} catch (e) {
|
|
29968
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
29969
|
+
}
|
|
29970
|
+
});
|
|
29971
|
+
}
|
|
29972
|
+
if (shouldRegisterTool("get_task_watchers")) {
|
|
29973
|
+
server.tool("get_task_watchers", "List agents watching a task.", {
|
|
29974
|
+
task_id: exports_external.string().describe("Task ID")
|
|
29975
|
+
}, async ({ task_id }) => {
|
|
29976
|
+
try {
|
|
29977
|
+
const { getTaskWatchers: getTaskWatchers2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
29978
|
+
const watchers = getTaskWatchers2(resolveId(task_id));
|
|
29979
|
+
if (watchers.length === 0)
|
|
29980
|
+
return { content: [{ type: "text", text: "No watchers." }] };
|
|
29981
|
+
return { content: [{ type: "text", text: `Watching (${watchers.length}): ${watchers.map((w) => w.agent_id).join(", ")}` }] };
|
|
29982
|
+
} catch (e) {
|
|
29983
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
29984
|
+
}
|
|
29985
|
+
});
|
|
29986
|
+
}
|
|
29987
|
+
if (shouldRegisterTool("todos_retro")) {
|
|
29988
|
+
server.tool("todos_retro", "Post-completion retrospective: stats on completed tasks, low-confidence completions, avg time vs estimate, and patterns.", {
|
|
29989
|
+
project_id: exports_external.string().optional().describe("Filter by project"),
|
|
29990
|
+
plan_id: exports_external.string().optional().describe("Filter by plan"),
|
|
29991
|
+
task_list_id: exports_external.string().optional().describe("Filter by task list"),
|
|
29992
|
+
since: exports_external.string().optional().describe("ISO date \u2014 only tasks completed after this date"),
|
|
29993
|
+
agent_id: exports_external.string().optional().describe("Filter by assignee")
|
|
29994
|
+
}, async ({ project_id, plan_id, task_list_id, since, agent_id }) => {
|
|
29995
|
+
try {
|
|
29996
|
+
const { listTasks: listTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
29997
|
+
const { patrolTasks: patrolTasks2 } = (init_patrol(), __toCommonJS(exports_patrol));
|
|
29998
|
+
const completed = listTasks2({ status: "completed", project_id, plan_id, task_list_id, assigned_to: agent_id, limit: 500 }, undefined);
|
|
29999
|
+
const filtered = since ? completed.filter((t) => t.completed_at && t.completed_at >= since) : completed;
|
|
30000
|
+
const total = filtered.length;
|
|
30001
|
+
const lowConf = filtered.filter((t) => t.confidence != null && t.confidence < 0.7).length;
|
|
30002
|
+
const withEstimate = filtered.filter((t) => t.estimated_minutes != null && t.actual_minutes != null);
|
|
30003
|
+
const avgDiff = withEstimate.length > 0 ? withEstimate.reduce((acc, t) => acc + (t.actual_minutes - t.estimated_minutes), 0) / withEstimate.length : 0;
|
|
30004
|
+
const patrolResult = patrolTasks2({ project_id: project_id ? resolveId(project_id, "projects") : undefined });
|
|
30005
|
+
const stuck = patrolResult.issues.filter((i) => i.type === "stuck").length;
|
|
30006
|
+
const lines = [
|
|
30007
|
+
`Retro (${total} completed tasks${since ? ` since ${since}` : ""})`,
|
|
30008
|
+
`Low confidence: ${lowConf}/${total}`,
|
|
30009
|
+
`Avg time vs estimate: ${avgDiff >= 0 ? "+" : ""}${avgDiff.toFixed(1)}min`,
|
|
30010
|
+
`Currently stuck: ${stuck}`
|
|
30011
|
+
];
|
|
30012
|
+
return { content: [{ type: "text", text: lines.join(`
|
|
30013
|
+
`) }] };
|
|
30014
|
+
} catch (e) {
|
|
30015
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
30016
|
+
}
|
|
30017
|
+
});
|
|
30018
|
+
}
|
|
30019
|
+
if (shouldRegisterTool("todos_inbox")) {
|
|
30020
|
+
server.tool("todos_inbox", "Get unassigned tasks (GTD inbox) \u2014 tasks with no assignee, not yet started.", {
|
|
30021
|
+
project_id: exports_external.string().optional().describe("Filter by project"),
|
|
30022
|
+
limit: exports_external.number().optional().describe("Max results (default: 20)")
|
|
30023
|
+
}, async ({ project_id, limit }) => {
|
|
30024
|
+
try {
|
|
30025
|
+
const { listTasks: listTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
30026
|
+
const tasks = listTasks2({ status: "pending", project_id, assigned_to: "", limit: limit || 20 }, undefined);
|
|
30027
|
+
if (tasks.length === 0)
|
|
30028
|
+
return { content: [{ type: "text", text: "Inbox is empty." }] };
|
|
30029
|
+
const lines = tasks.map((t) => `[${t.priority}] ${t.title.slice(0, 60)} (${t.id.slice(0, 8)})`);
|
|
30030
|
+
return { content: [{ type: "text", text: `Inbox (${tasks.length}):
|
|
30031
|
+
${lines.join(`
|
|
30032
|
+
`)}` }] };
|
|
30033
|
+
} catch (e) {
|
|
30034
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
30035
|
+
}
|
|
30036
|
+
});
|
|
30037
|
+
}
|
|
29721
30038
|
if (shouldRegisterTool("get_agent_metrics")) {
|
|
29722
30039
|
server.tool("get_agent_metrics", "Get performance metrics for an agent: completion rate, speed, confidence, review scores.", {
|
|
29723
30040
|
agent_id: exports_external.string().describe("Agent ID or name"),
|
|
@@ -32779,7 +33096,7 @@ function formatTaskLine(t) {
|
|
|
32779
33096
|
const plan = t.plan_id ? chalk3.magenta(` [plan:${t.plan_id.slice(0, 8)}]`) : "";
|
|
32780
33097
|
return `${chalk3.dim(t.id.slice(0, 8))} ${statusFn(t.status.padEnd(11))} ${priorityFn(t.priority.padEnd(8))} ${t.title}${assigned}${lock}${tags}${plan}`;
|
|
32781
33098
|
}
|
|
32782
|
-
program2.name("todos").description("Universal task management for AI coding agents").version(getPackageVersion()).option("--project <path>", "Project path").option("--json", "Output as JSON").option("--agent <name>", "Agent name").option("--session <id>", "Session ID");
|
|
33099
|
+
program2.name("todos").description("Universal task management for AI coding agents").version(getPackageVersion()).option("--project <path>", "Project path").option("-j, --json", "Output as JSON").option("--agent <name>", "Agent name").option("--session <id>", "Session ID");
|
|
32783
33100
|
program2.command("add <title>").description("Create a new task").option("-d, --description <text>", "Task description").option("-p, --priority <level>", "Priority: low, medium, high, critical").option("--parent <id>", "Parent task ID").option("-t, --tags <tags>", "Comma-separated tags").option("--tag <tags>", "Comma-separated tags (alias for --tags)").option("--plan <id>", "Assign to a plan").option("--assign <agent>", "Assign to agent").option("--status <status>", "Initial status").option("--list <id>", "Task list ID").option("--task-list <id>", "Task list ID (alias for --list)").option("--estimated <minutes>", "Estimated time in minutes").option("--approval", "Require approval before completion").option("--recurrence <rule>", "Recurrence rule, e.g. 'every day', 'every weekday', 'every 2 weeks'").option("--due <date>", "Due date (ISO string or YYYY-MM-DD)").option("--reason <text>", "Why this task exists").action((title, opts) => {
|
|
32784
33101
|
const globalOpts = program2.opts();
|
|
32785
33102
|
const projectId = autoProject(globalOpts);
|
|
@@ -32836,6 +33153,16 @@ program2.command("list").description("List tasks").option("-s, --status <status>
|
|
|
32836
33153
|
const projectId = autoProject(globalOpts);
|
|
32837
33154
|
const hasAssignedFilter = Boolean(opts.assigned || opts.agentName);
|
|
32838
33155
|
const hasExplicitProjectFilter = Boolean(globalOpts.project || opts.projectName);
|
|
33156
|
+
const allowedSortFields = new Set(["updated", "created", "priority", "status"]);
|
|
33157
|
+
if (opts.sort && !allowedSortFields.has(opts.sort)) {
|
|
33158
|
+
console.error(chalk3.red(`Invalid --sort value: ${opts.sort}. Allowed values: updated, created, priority, status.`));
|
|
33159
|
+
process.exit(1);
|
|
33160
|
+
}
|
|
33161
|
+
const allowedFormats = new Set(["table", "compact", "csv", "json"]);
|
|
33162
|
+
if (opts.format && !allowedFormats.has(opts.format)) {
|
|
33163
|
+
console.error(chalk3.red(`Invalid --format value: ${opts.format}. Allowed values: table, compact, csv, json.`));
|
|
33164
|
+
process.exit(1);
|
|
33165
|
+
}
|
|
32839
33166
|
const filter = {};
|
|
32840
33167
|
if (projectId && !(hasAssignedFilter && !hasExplicitProjectFilter)) {
|
|
32841
33168
|
filter["project_id"] = projectId;
|
|
@@ -32875,8 +33202,14 @@ program2.command("list").description("List tasks").option("-s, --status <status>
|
|
|
32875
33202
|
}
|
|
32876
33203
|
if (opts.recurring)
|
|
32877
33204
|
filter["has_recurrence"] = true;
|
|
32878
|
-
if (opts.limit)
|
|
32879
|
-
|
|
33205
|
+
if (opts.limit !== undefined) {
|
|
33206
|
+
const parsedLimit = Number.parseInt(String(opts.limit), 10);
|
|
33207
|
+
if (!Number.isInteger(parsedLimit) || parsedLimit <= 0) {
|
|
33208
|
+
console.error(chalk3.red(`Invalid --limit value: ${opts.limit}. Must be a positive integer.`));
|
|
33209
|
+
process.exit(1);
|
|
33210
|
+
}
|
|
33211
|
+
filter["limit"] = parsedLimit;
|
|
33212
|
+
}
|
|
32880
33213
|
let tasks = listTasks(filter);
|
|
32881
33214
|
if (opts.dueToday) {
|
|
32882
33215
|
const todayEnd = new Date;
|
|
@@ -33877,7 +34210,7 @@ program2.command("projects").description("List and manage projects").option("--a
|
|
|
33877
34210
|
console.log(`${chalk3.dim(p.id.slice(0, 8))} ${chalk3.bold(p.name)} ${chalk3.dim(p.path)}${taskList}${p.description ? ` - ${p.description}` : ""}`);
|
|
33878
34211
|
}
|
|
33879
34212
|
});
|
|
33880
|
-
program2.command("project-rename <id-or-slug> <new-slug>").description("Rename a project slug. Cascades to matching task lists. Task prefixes (e.g. APP-00001) are unchanged.").option("--name <name>", "Also update the project display name").option("--json", "Output as JSON").action((idOrSlug, newSlug, opts) => {
|
|
34213
|
+
program2.command("project-rename <id-or-slug> <new-slug>").description("Rename a project slug. Cascades to matching task lists. Task prefixes (e.g. APP-00001) are unchanged.").option("--name <name>", "Also update the project display name").option("-j, --json", "Output as JSON").action((idOrSlug, newSlug, opts) => {
|
|
33881
34214
|
const globalOpts = program2.opts();
|
|
33882
34215
|
const useJson = opts.json || globalOpts.json;
|
|
33883
34216
|
try {
|
|
@@ -33907,7 +34240,7 @@ program2.command("project-rename <id-or-slug> <new-slug>").description("Rename a
|
|
|
33907
34240
|
}
|
|
33908
34241
|
});
|
|
33909
34242
|
var projectsPathCmd = program2.command("projects-path").description("Manage machine-local path overrides for projects");
|
|
33910
|
-
projectsPathCmd.command("set <project-id> <path>").description("Set the local path for a project on this machine").option("--json", "Output as JSON").action((projectId, projectPath, opts) => {
|
|
34243
|
+
projectsPathCmd.command("set <project-id> <path>").description("Set the local path for a project on this machine").option("-j, --json", "Output as JSON").action((projectId, projectPath, opts) => {
|
|
33911
34244
|
const globalOpts = program2.opts();
|
|
33912
34245
|
const useJson = opts.json || globalOpts.json;
|
|
33913
34246
|
try {
|
|
@@ -33929,7 +34262,7 @@ projectsPathCmd.command("set <project-id> <path>").description("Set the local pa
|
|
|
33929
34262
|
process.exit(1);
|
|
33930
34263
|
}
|
|
33931
34264
|
});
|
|
33932
|
-
projectsPathCmd.command("list <project-id>").description("List all machine path overrides for a project").option("--json", "Output as JSON").action((projectId, opts) => {
|
|
34265
|
+
projectsPathCmd.command("list <project-id>").description("List all machine path overrides for a project").option("-j, --json", "Output as JSON").action((projectId, opts) => {
|
|
33933
34266
|
const globalOpts = program2.opts();
|
|
33934
34267
|
const useJson = opts.json || globalOpts.json;
|
|
33935
34268
|
try {
|
|
@@ -34581,7 +34914,7 @@ program2.command("agent-update <name>").alias("agents-update").description("Upda
|
|
|
34581
34914
|
handleError(e);
|
|
34582
34915
|
}
|
|
34583
34916
|
});
|
|
34584
|
-
program2.command("agent <name>").description("Show all info about an agent: tasks, status, last seen, stats").option("--json", "Output as JSON").action((name, opts) => {
|
|
34917
|
+
program2.command("agent <name>").description("Show all info about an agent: tasks, status, last seen, stats").option("-j, --json", "Output as JSON").action((name, opts) => {
|
|
34585
34918
|
const globalOpts = program2.opts();
|
|
34586
34919
|
const { getAgentByName: findByName } = (init_agents(), __toCommonJS(exports_agents));
|
|
34587
34920
|
const agent = findByName(name);
|
|
@@ -35014,7 +35347,7 @@ program2.command("dashboard").description("Live-updating dashboard showing proje
|
|
|
35014
35347
|
const projectId = opts.project || autoProject(globalOpts) || undefined;
|
|
35015
35348
|
render2(React.createElement(Dashboard2, { projectId, refreshMs: parseInt(opts.refresh, 10) }));
|
|
35016
35349
|
});
|
|
35017
|
-
program2.command("next").description("Show the best pending task to work on next").option("--agent <id>", "Prefer tasks assigned to this agent").option("--project <id>", "Filter to project").option("--json", "Output as JSON").action(async (opts) => {
|
|
35350
|
+
program2.command("next").description("Show the best pending task to work on next").option("--agent <id>", "Prefer tasks assigned to this agent").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35018
35351
|
const globalOpts = program2.opts();
|
|
35019
35352
|
const db = getDatabase();
|
|
35020
35353
|
const filters = {};
|
|
@@ -35038,7 +35371,7 @@ program2.command("next").description("Show the best pending task to work on next
|
|
|
35038
35371
|
if (task.description)
|
|
35039
35372
|
console.log(chalk3.dim(` ${task.description.slice(0, 100)}`));
|
|
35040
35373
|
});
|
|
35041
|
-
program2.command("claim <agent>").description("Atomically claim the best pending task for an agent").option("--project <id>", "Filter to project").option("--json", "Output as JSON").action(async (agent, opts) => {
|
|
35374
|
+
program2.command("claim <agent>").description("Atomically claim the best pending task for an agent").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (agent, opts) => {
|
|
35042
35375
|
const db = getDatabase();
|
|
35043
35376
|
const filters = {};
|
|
35044
35377
|
if (opts.project)
|
|
@@ -35068,7 +35401,7 @@ program2.command("steal <agent>").description("Work-stealing: take the highest-p
|
|
|
35068
35401
|
}
|
|
35069
35402
|
console.log(chalk3.green(`Stolen: ${task.short_id || task.id.slice(0, 8)} | ${task.priority} | ${task.title}`));
|
|
35070
35403
|
});
|
|
35071
|
-
program2.command("status").description("Show full project health snapshot").option("--agent <id>", "Include next task for this agent").option("--project <id>", "Filter to project").option("--json", "Output as JSON").action(async (opts) => {
|
|
35404
|
+
program2.command("status").description("Show full project health snapshot").option("--agent <id>", "Include next task for this agent").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35072
35405
|
const db = getDatabase();
|
|
35073
35406
|
const filters = {};
|
|
35074
35407
|
if (opts.project)
|
|
@@ -35212,7 +35545,7 @@ Blocked:`));
|
|
|
35212
35545
|
}
|
|
35213
35546
|
console.log();
|
|
35214
35547
|
});
|
|
35215
|
-
program2.command("fail <id>").description("Mark a task as failed with optional reason and retry").option("--reason <text>", "Why it failed").option("--agent <id>", "Agent reporting the failure").option("--retry", "Auto-create a retry copy").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
35548
|
+
program2.command("fail <id>").description("Mark a task as failed with optional reason and retry").option("--reason <text>", "Why it failed").option("--agent <id>", "Agent reporting the failure").option("--retry", "Auto-create a retry copy").option("-j, --json", "Output as JSON").action(async (id, opts) => {
|
|
35216
35549
|
const db = getDatabase();
|
|
35217
35550
|
const resolvedId = resolvePartialId(db, "tasks", id);
|
|
35218
35551
|
if (!resolvedId) {
|
|
@@ -35230,7 +35563,7 @@ program2.command("fail <id>").description("Mark a task as failed with optional r
|
|
|
35230
35563
|
if (result.retryTask)
|
|
35231
35564
|
console.log(chalk3.yellow(`Retry created: ${result.retryTask.short_id || result.retryTask.id.slice(0, 8)} | ${result.retryTask.title}`));
|
|
35232
35565
|
});
|
|
35233
|
-
program2.command("active").description("Show all currently in-progress tasks").option("--project <id>", "Filter to project").option("--json", "Output as JSON").action(async (opts) => {
|
|
35566
|
+
program2.command("active").description("Show all currently in-progress tasks").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35234
35567
|
const db = getDatabase();
|
|
35235
35568
|
const filters = {};
|
|
35236
35569
|
if (opts.project)
|
|
@@ -35251,7 +35584,7 @@ program2.command("active").description("Show all currently in-progress tasks").o
|
|
|
35251
35584
|
console.log(` ${chalk3.cyan(id)} | ${chalk3.yellow(w.priority)} | ${agent.padEnd(12)} | ${w.title}`);
|
|
35252
35585
|
}
|
|
35253
35586
|
});
|
|
35254
|
-
program2.command("stale").description("Find tasks stuck in_progress with no recent activity").option("--minutes <n>", "Stale threshold in minutes", "30").option("--project <id>", "Filter to project").option("--json", "Output as JSON").action(async (opts) => {
|
|
35587
|
+
program2.command("stale").description("Find tasks stuck in_progress with no recent activity").option("--minutes <n>", "Stale threshold in minutes", "30").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35255
35588
|
const db = getDatabase();
|
|
35256
35589
|
const filters = {};
|
|
35257
35590
|
if (opts.project)
|
|
@@ -35272,7 +35605,7 @@ program2.command("stale").description("Find tasks stuck in_progress with no rece
|
|
|
35272
35605
|
console.log(` ${chalk3.cyan(id)} | ${t.locked_by || t.assigned_to || "?"} | ${t.title} ${chalk3.dim(`(${staleMin}min stale)`)}`);
|
|
35273
35606
|
}
|
|
35274
35607
|
});
|
|
35275
|
-
program2.command("redistribute <agent>").description("Release stale in-progress tasks and claim the best one (work-stealing)").option("--max-age <minutes>", "Stale threshold in minutes", "60").option("--project <id>", "Limit to a specific project").option("--limit <n>", "Max stale tasks to release").option("--json", "Output as JSON").action(async (agent, opts) => {
|
|
35608
|
+
program2.command("redistribute <agent>").description("Release stale in-progress tasks and claim the best one (work-stealing)").option("--max-age <minutes>", "Stale threshold in minutes", "60").option("--project <id>", "Limit to a specific project").option("--limit <n>", "Max stale tasks to release").option("-j, --json", "Output as JSON").action(async (agent, opts) => {
|
|
35276
35609
|
const globalOpts = program2.opts();
|
|
35277
35610
|
const db = getDatabase();
|
|
35278
35611
|
const projectId = opts.project ? resolveTaskId(opts.project) : autoProject(globalOpts) ?? undefined;
|
|
@@ -35299,7 +35632,7 @@ Claimed: ${chalk3.cyan(id)} ${result.claimed.title}`));
|
|
|
35299
35632
|
No task claimed (nothing available).`));
|
|
35300
35633
|
}
|
|
35301
35634
|
});
|
|
35302
|
-
program2.command("assign <id> <agent>").description("Assign a task to an agent").option("--json", "Output as JSON").action((id, agent, opts) => {
|
|
35635
|
+
program2.command("assign <id> <agent>").description("Assign a task to an agent").option("-j, --json", "Output as JSON").action((id, agent, opts) => {
|
|
35303
35636
|
const globalOpts = program2.opts();
|
|
35304
35637
|
const resolvedId = resolveTaskId(id);
|
|
35305
35638
|
const db = getDatabase();
|
|
@@ -35319,7 +35652,7 @@ program2.command("assign <id> <agent>").description("Assign a task to an agent")
|
|
|
35319
35652
|
handleError(new Error("Failed to assign"));
|
|
35320
35653
|
}
|
|
35321
35654
|
});
|
|
35322
|
-
program2.command("unassign <id>").description("Remove task assignment").option("--json", "Output as JSON").action((id, opts) => {
|
|
35655
|
+
program2.command("unassign <id>").description("Remove task assignment").option("-j, --json", "Output as JSON").action((id, opts) => {
|
|
35323
35656
|
const globalOpts = program2.opts();
|
|
35324
35657
|
const resolvedId = resolveTaskId(id);
|
|
35325
35658
|
const db = getDatabase();
|
|
@@ -35339,7 +35672,7 @@ program2.command("unassign <id>").description("Remove task assignment").option("
|
|
|
35339
35672
|
handleError(new Error("Failed to unassign"));
|
|
35340
35673
|
}
|
|
35341
35674
|
});
|
|
35342
|
-
program2.command("tag <id> <tag>").description("Add a tag to a task").option("--json", "Output as JSON").action((id, tag, opts) => {
|
|
35675
|
+
program2.command("tag <id> <tag>").description("Add a tag to a task").option("-j, --json", "Output as JSON").action((id, tag, opts) => {
|
|
35343
35676
|
const globalOpts = program2.opts();
|
|
35344
35677
|
const resolvedId = resolveTaskId(id);
|
|
35345
35678
|
const db = getDatabase();
|
|
@@ -35360,7 +35693,7 @@ program2.command("tag <id> <tag>").description("Add a tag to a task").option("--
|
|
|
35360
35693
|
handleError(new Error("Failed to tag"));
|
|
35361
35694
|
}
|
|
35362
35695
|
});
|
|
35363
|
-
program2.command("untag <id> <tag>").description("Remove a tag from a task").option("--json", "Output as JSON").action((id, tag, opts) => {
|
|
35696
|
+
program2.command("untag <id> <tag>").description("Remove a tag from a task").option("-j, --json", "Output as JSON").action((id, tag, opts) => {
|
|
35364
35697
|
const globalOpts = program2.opts();
|
|
35365
35698
|
const resolvedId = resolveTaskId(id);
|
|
35366
35699
|
const db = getDatabase();
|
|
@@ -35381,7 +35714,7 @@ program2.command("untag <id> <tag>").description("Remove a tag from a task").opt
|
|
|
35381
35714
|
handleError(new Error("Failed to untag"));
|
|
35382
35715
|
}
|
|
35383
35716
|
});
|
|
35384
|
-
program2.command("pin <id>").description("Escalate task to critical priority").option("--json", "Output as JSON").action((id, opts) => {
|
|
35717
|
+
program2.command("pin <id>").description("Escalate task to critical priority").option("-j, --json", "Output as JSON").action((id, opts) => {
|
|
35385
35718
|
const globalOpts = program2.opts();
|
|
35386
35719
|
const resolvedId = resolveTaskId(id);
|
|
35387
35720
|
const db = getDatabase();
|
|
@@ -35397,7 +35730,7 @@ program2.command("pin <id>").description("Escalate task to critical priority").o
|
|
|
35397
35730
|
handleError(new Error("Failed to pin"));
|
|
35398
35731
|
}
|
|
35399
35732
|
});
|
|
35400
|
-
program2.command("summary").description("Generate a markdown summary of recent task activity").option("--days <n>", "Days of history to include", "7").option("--project <id>", "Filter to project").option("--agent <id>", "Filter to agent").option("--json", "Output as JSON").action(async (opts) => {
|
|
35733
|
+
program2.command("summary").description("Generate a markdown summary of recent task activity").option("--days <n>", "Days of history to include", "7").option("--project <id>", "Filter to project").option("--agent <id>", "Filter to agent").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35401
35734
|
const globalOpts = program2.opts();
|
|
35402
35735
|
const db = getDatabase();
|
|
35403
35736
|
const days = parseInt(opts.days, 10);
|
|
@@ -35452,7 +35785,7 @@ program2.command("summary").description("Generate a markdown summary of recent t
|
|
|
35452
35785
|
console.log(lines.join(`
|
|
35453
35786
|
`));
|
|
35454
35787
|
});
|
|
35455
|
-
program2.command("doctor").description("Diagnose common task data issues").option("--fix", "Auto-fix recoverable issues where possible").option("--json", "Output as JSON").action(async (opts) => {
|
|
35788
|
+
program2.command("doctor").description("Diagnose common task data issues").option("--fix", "Auto-fix recoverable issues where possible").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35456
35789
|
const globalOpts = program2.opts();
|
|
35457
35790
|
const db = getDatabase();
|
|
35458
35791
|
const issues = [];
|
|
@@ -35494,7 +35827,7 @@ program2.command("doctor").description("Diagnose common task data issues").optio
|
|
|
35494
35827
|
console.log(chalk3[errors2 > 0 ? "red" : "yellow"](`
|
|
35495
35828
|
${errors2} error(s), ${warns} warning(s). Run with --fix to auto-resolve where possible.`));
|
|
35496
35829
|
});
|
|
35497
|
-
program2.command("health").description("Check todos system health \u2014 database, config, connectivity").option("--json", "Output as JSON").action(async (opts) => {
|
|
35830
|
+
program2.command("health").description("Check todos system health \u2014 database, config, connectivity").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35498
35831
|
const globalOpts = program2.opts();
|
|
35499
35832
|
const checks = [];
|
|
35500
35833
|
try {
|
|
@@ -35549,7 +35882,7 @@ program2.command("health").description("Check todos system health \u2014 databas
|
|
|
35549
35882
|
console.log(`
|
|
35550
35883
|
${allOk ? chalk3.green("All checks passed.") : chalk3.yellow("Some checks need attention.")}`);
|
|
35551
35884
|
});
|
|
35552
|
-
program2.command("report").description("Analytics report: task activity, completion rates, agent breakdown").option("--days <n>", "Days to include in report", "7").option("--project <id>", "Filter to project").option("--markdown", "Output as markdown").option("--json", "Output as JSON").action(async (opts) => {
|
|
35885
|
+
program2.command("report").description("Analytics report: task activity, completion rates, agent breakdown").option("--days <n>", "Days to include in report", "7").option("--project <id>", "Filter to project").option("--markdown", "Output as markdown").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35553
35886
|
const globalOpts = program2.opts();
|
|
35554
35887
|
const db = getDatabase();
|
|
35555
35888
|
const days = parseInt(opts.days, 10);
|
|
@@ -35614,7 +35947,7 @@ program2.command("report").description("Analytics report: task activity, complet
|
|
|
35614
35947
|
console.log(lines.join(`
|
|
35615
35948
|
`));
|
|
35616
35949
|
});
|
|
35617
|
-
program2.command("today").description("Show task activity from today").option("--json", "Output as JSON").action(async (opts) => {
|
|
35950
|
+
program2.command("today").description("Show task activity from today").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35618
35951
|
const globalOpts = program2.opts();
|
|
35619
35952
|
const db = getDatabase();
|
|
35620
35953
|
const { getTasksChangedSince: getTasksChangedSince2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -35644,7 +35977,7 @@ program2.command("today").description("Show task activity from today").option("-
|
|
|
35644
35977
|
if (completed.length === 0 && started.length === 0)
|
|
35645
35978
|
console.log(chalk3.dim(" No activity today."));
|
|
35646
35979
|
});
|
|
35647
|
-
program2.command("yesterday").description("Show task activity from yesterday").option("--json", "Output as JSON").action(async (opts) => {
|
|
35980
|
+
program2.command("yesterday").description("Show task activity from yesterday").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35648
35981
|
const globalOpts = program2.opts();
|
|
35649
35982
|
const db = getDatabase();
|
|
35650
35983
|
const { getTasksChangedSince: getTasksChangedSince2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -35677,7 +36010,7 @@ program2.command("yesterday").description("Show task activity from yesterday").o
|
|
|
35677
36010
|
if (completed.length === 0 && started.length === 0)
|
|
35678
36011
|
console.log(chalk3.dim(" No activity yesterday."));
|
|
35679
36012
|
});
|
|
35680
|
-
program2.command("mine").description("Show tasks assigned to you, grouped by status").argument("<agent>", "Agent name or ID").option("--json", "Output as JSON").action(async (agent, opts) => {
|
|
36013
|
+
program2.command("mine").description("Show tasks assigned to you, grouped by status").argument("<agent>", "Agent name or ID").option("-j, --json", "Output as JSON").action(async (agent, opts) => {
|
|
35681
36014
|
const globalOpts = program2.opts();
|
|
35682
36015
|
const db = getDatabase();
|
|
35683
36016
|
const { listTasks: listTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -35728,7 +36061,7 @@ program2.command("mine").description("Show tasks assigned to you, grouped by sta
|
|
|
35728
36061
|
if (tasks.length === 0)
|
|
35729
36062
|
console.log(chalk3.dim(` No tasks assigned to ${agent}.`));
|
|
35730
36063
|
});
|
|
35731
|
-
program2.command("blocked").description("Show tasks blocked by incomplete dependencies").option("--json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
|
|
36064
|
+
program2.command("blocked").description("Show tasks blocked by incomplete dependencies").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
|
|
35732
36065
|
const globalOpts = program2.opts();
|
|
35733
36066
|
const db = getDatabase();
|
|
35734
36067
|
const { listTasks: listTasks2, getBlockingDeps: getBlockingDeps2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -35760,7 +36093,7 @@ program2.command("blocked").description("Show tasks blocked by incomplete depend
|
|
|
35760
36093
|
}
|
|
35761
36094
|
}
|
|
35762
36095
|
});
|
|
35763
|
-
program2.command("overdue").description("Show tasks past their due date").option("--json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
|
|
36096
|
+
program2.command("overdue").description("Show tasks past their due date").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
|
|
35764
36097
|
const globalOpts = program2.opts();
|
|
35765
36098
|
const projectId = autoProject(globalOpts) || opts.project || undefined;
|
|
35766
36099
|
const { getOverdueTasks: getOverdueTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -35782,7 +36115,7 @@ program2.command("overdue").description("Show tasks past their due date").option
|
|
|
35782
36115
|
console.log(` ${urgency} ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk3.dim(` \u2014 ${t.assigned_to}`) : ""} ${chalk3.dim(`(due ${dueDate})`)}`);
|
|
35783
36116
|
}
|
|
35784
36117
|
});
|
|
35785
|
-
program2.command("week").description("Show task activity from the past 7 days").option("--json", "Output as JSON").action(async (opts) => {
|
|
36118
|
+
program2.command("week").description("Show task activity from the past 7 days").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35786
36119
|
const globalOpts = program2.opts();
|
|
35787
36120
|
const db = getDatabase();
|
|
35788
36121
|
const { getTasksChangedSince: getTasksChangedSince2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -35835,7 +36168,7 @@ program2.command("week").description("Show task activity from the past 7 days").
|
|
|
35835
36168
|
if (tasks.length === 0)
|
|
35836
36169
|
console.log(chalk3.dim(" No activity this week."));
|
|
35837
36170
|
});
|
|
35838
|
-
program2.command("burndown").description("Show task completion velocity over the past 7 days").option("--days <n>", "Number of days", "7").option("--json", "Output as JSON").action(async (opts) => {
|
|
36171
|
+
program2.command("burndown").description("Show task completion velocity over the past 7 days").option("--days <n>", "Number of days", "7").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35839
36172
|
const globalOpts = program2.opts();
|
|
35840
36173
|
const db = getDatabase();
|
|
35841
36174
|
const { getRecentActivity: getRecentActivity2 } = (init_audit(), __toCommonJS(exports_audit));
|
|
@@ -35877,7 +36210,7 @@ program2.command("burndown").description("Show task completion velocity over the
|
|
|
35877
36210
|
console.log(chalk3.dim(`
|
|
35878
36211
|
Velocity: ${velocity}/day \xB7 ${totalCompleted} done \xB7 ${totalCreated} created`));
|
|
35879
36212
|
});
|
|
35880
|
-
program2.command("log").description("Show recent task activity log (git-log style)").option("--limit <n>", "Number of entries", "30").option("--json", "Output as JSON").action(async (opts) => {
|
|
36213
|
+
program2.command("log").description("Show recent task activity log (git-log style)").option("--limit <n>", "Number of entries", "30").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
35881
36214
|
const globalOpts = program2.opts();
|
|
35882
36215
|
const db = getDatabase();
|
|
35883
36216
|
const { getRecentActivity: getRecentActivity2 } = (init_audit(), __toCommonJS(exports_audit));
|
|
@@ -35921,7 +36254,7 @@ program2.command("log").description("Show recent task activity log (git-log styl
|
|
|
35921
36254
|
console.log(` ${chalk3.dim(time)} ${icon} ${e.action.padEnd(8)} ${taskRef}${detail}${agent}`);
|
|
35922
36255
|
}
|
|
35923
36256
|
});
|
|
35924
|
-
program2.command("ready").description("Show all tasks ready to be claimed (pending, unblocked, unlocked)").option("--json", "Output as JSON").option("--project <id>", "Filter to project").option("--limit <n>", "Max tasks to show", "20").action(async (opts) => {
|
|
36257
|
+
program2.command("ready").description("Show all tasks ready to be claimed (pending, unblocked, unlocked)").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").option("--limit <n>", "Max tasks to show", "20").action(async (opts) => {
|
|
35925
36258
|
const globalOpts = program2.opts();
|
|
35926
36259
|
const db = getDatabase();
|
|
35927
36260
|
const { listTasks: listTasks2, getBlockingDeps: getBlockingDeps2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -35954,7 +36287,7 @@ program2.command("ready").description("Show all tasks ready to be claimed (pendi
|
|
|
35954
36287
|
console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title} ${pri}${due}`);
|
|
35955
36288
|
}
|
|
35956
36289
|
});
|
|
35957
|
-
program2.command("sprint").description("Sprint dashboard: in-progress, next up, blockers, and overdue").option("--json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
|
|
36290
|
+
program2.command("sprint").description("Sprint dashboard: in-progress, next up, blockers, and overdue").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
|
|
35958
36291
|
const globalOpts = program2.opts();
|
|
35959
36292
|
const db = getDatabase();
|
|
35960
36293
|
const { listTasks: listTasks2, getBlockingDeps: getBlockingDeps2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -36015,7 +36348,7 @@ program2.command("sprint").description("Sprint dashboard: in-progress, next up,
|
|
|
36015
36348
|
console.log(chalk3.dim(`
|
|
36016
36349
|
${inProgress.length} active \xB7 ${pending.length} pending \xB7 ${blocked.length} blocked \xB7 ${overdue.length} overdue`));
|
|
36017
36350
|
});
|
|
36018
|
-
program2.command("handoff").description("Create or view agent session handoffs").option("--create", "Create a new handoff").option("--agent <name>", "Agent name").option("--summary <text>", "Handoff summary").option("--completed <items>", "Comma-separated completed items").option("--in-progress <items>", "Comma-separated in-progress items").option("--blockers <items>", "Comma-separated blockers").option("--next <items>", "Comma-separated next steps").option("--json", "Output as JSON").option("--limit <n>", "Number of handoffs to show", "5").action(async (opts) => {
|
|
36351
|
+
program2.command("handoff").description("Create or view agent session handoffs").option("--create", "Create a new handoff").option("--agent <name>", "Agent name").option("--summary <text>", "Handoff summary").option("--completed <items>", "Comma-separated completed items").option("--in-progress <items>", "Comma-separated in-progress items").option("--blockers <items>", "Comma-separated blockers").option("--next <items>", "Comma-separated next steps").option("-j, --json", "Output as JSON").option("--limit <n>", "Number of handoffs to show", "5").action(async (opts) => {
|
|
36019
36352
|
const globalOpts = program2.opts();
|
|
36020
36353
|
const db = getDatabase();
|
|
36021
36354
|
const { createHandoff: createHandoff2, listHandoffs: listHandoffs2 } = (init_handoffs(), __toCommonJS(exports_handoffs));
|
|
@@ -36077,7 +36410,7 @@ program2.command("handoff").description("Create or view agent session handoffs")
|
|
|
36077
36410
|
}
|
|
36078
36411
|
}
|
|
36079
36412
|
});
|
|
36080
|
-
program2.command("priorities").description("Show task counts grouped by priority").option("--json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
|
|
36413
|
+
program2.command("priorities").description("Show task counts grouped by priority").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
|
|
36081
36414
|
const globalOpts = program2.opts();
|
|
36082
36415
|
const db = getDatabase();
|
|
36083
36416
|
const { countTasks: countTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -36109,7 +36442,7 @@ program2.command("priorities").description("Show task counts grouped by priority
|
|
|
36109
36442
|
console.log(` ${color(p.padEnd(9))} ${String(c.total).padStart(4)} total ${chalk3.green(String(c.completed).padStart(3))} done ${chalk3.blue(String(c.in_progress).padStart(3))} active ${chalk3.dim(String(c.pending).padStart(3))} pending ${bar}`);
|
|
36110
36443
|
}
|
|
36111
36444
|
});
|
|
36112
|
-
program2.command("context").description("Session start context: status, latest handoff, next task, overdue").option("--agent <name>", "Agent name for handoff lookup").option("--json", "Output as JSON").action(async (opts) => {
|
|
36445
|
+
program2.command("context").description("Session start context: status, latest handoff, next task, overdue").option("--agent <name>", "Agent name for handoff lookup").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
36113
36446
|
const globalOpts = program2.opts();
|
|
36114
36447
|
const db = getDatabase();
|
|
36115
36448
|
const { getStatus: getStatus2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
@@ -36151,7 +36484,7 @@ program2.command("context").description("Session start context: status, latest h
|
|
|
36151
36484
|
console.log(chalk3.dim(`
|
|
36152
36485
|
as_of: ${new Date().toISOString()}`));
|
|
36153
36486
|
});
|
|
36154
|
-
program2.command("report-failure").description("Create a task from a test/build/typecheck failure and auto-assign it").requiredOption("--error <message>", "Error message or summary").option("--type <type>", "Failure type: test, build, typecheck, runtime, other", "test").option("--file <path>", "File where failure occurred").option("--stack <trace>", "Stack trace or detailed output").option("--title <title>", "Custom task title (auto-generated if omitted)").option("--priority <p>", "Priority: low, medium, high, critical").option("--json", "Output as JSON").action(async (opts) => {
|
|
36487
|
+
program2.command("report-failure").description("Create a task from a test/build/typecheck failure and auto-assign it").requiredOption("--error <message>", "Error message or summary").option("--type <type>", "Failure type: test, build, typecheck, runtime, other", "test").option("--file <path>", "File where failure occurred").option("--stack <trace>", "Stack trace or detailed output").option("--title <title>", "Custom task title (auto-generated if omitted)").option("--priority <p>", "Priority: low, medium, high, critical").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
36155
36488
|
const globalOpts = program2.opts();
|
|
36156
36489
|
const { createTask: createTask2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
36157
36490
|
const { autoAssignTask: autoAssignTask2 } = await Promise.resolve().then(() => (init_auto_assign(), exports_auto_assign));
|
|
@@ -36210,7 +36543,7 @@ program2.action(async () => {
|
|
|
36210
36543
|
});
|
|
36211
36544
|
program2.addCommand(makeBrainsCommand());
|
|
36212
36545
|
var dbCmd = program2.command("db").description("Database management commands");
|
|
36213
|
-
dbCmd.command("migrate-pg").description("Apply PostgreSQL migrations to the configured RDS instance").option("--connection-string <url>", "PostgreSQL connection string (overrides cloud config)").option("--json", "Output as JSON").action(async (opts) => {
|
|
36546
|
+
dbCmd.command("migrate-pg").description("Apply PostgreSQL migrations to the configured RDS instance").option("--connection-string <url>", "PostgreSQL connection string (overrides cloud config)").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
36214
36547
|
const globalOpts = program2.opts();
|
|
36215
36548
|
const useJson = opts.json || globalOpts.json;
|
|
36216
36549
|
let connStr;
|
|
@@ -36263,7 +36596,7 @@ dbCmd.command("migrate-pg").description("Apply PostgreSQL migrations to the conf
|
|
|
36263
36596
|
}
|
|
36264
36597
|
});
|
|
36265
36598
|
var cloudCmd = program2.command("cloud").description("Cloud sync commands");
|
|
36266
|
-
cloudCmd.command("status").description("Show cloud config, connection health, machine registry, and sync status").option("--json", "Output as JSON").action(async (opts) => {
|
|
36599
|
+
cloudCmd.command("status").description("Show cloud config, connection health, machine registry, and sync status").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
36267
36600
|
const globalOpts = program2.opts();
|
|
36268
36601
|
const useJson = opts.json || globalOpts.json;
|
|
36269
36602
|
try {
|
|
@@ -36354,7 +36687,7 @@ Conflicts`));
|
|
|
36354
36687
|
}
|
|
36355
36688
|
}
|
|
36356
36689
|
});
|
|
36357
|
-
cloudCmd.command("push").description("Push local data to cloud PostgreSQL").option("--tables <tables>", "Comma-separated table names (default: all)").option("--json", "Output as JSON").action(async (opts) => {
|
|
36690
|
+
cloudCmd.command("push").description("Push local data to cloud PostgreSQL").option("--tables <tables>", "Comma-separated table names (default: all)").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
36358
36691
|
const globalOpts = program2.opts();
|
|
36359
36692
|
const useJson = opts.json || globalOpts.json;
|
|
36360
36693
|
try {
|
|
@@ -36414,7 +36747,7 @@ cloudCmd.command("push").description("Push local data to cloud PostgreSQL").opti
|
|
|
36414
36747
|
process.exit(1);
|
|
36415
36748
|
}
|
|
36416
36749
|
});
|
|
36417
|
-
cloudCmd.command("pull").description("Pull cloud data to local \u2014 merges by primary key").option("--tables <tables>", "Comma-separated table names (default: all)").option("--json", "Output as JSON").action(async (opts) => {
|
|
36750
|
+
cloudCmd.command("pull").description("Pull cloud data to local \u2014 merges by primary key").option("--tables <tables>", "Comma-separated table names (default: all)").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
36418
36751
|
const globalOpts = program2.opts();
|
|
36419
36752
|
const useJson = opts.json || globalOpts.json;
|
|
36420
36753
|
try {
|
|
@@ -36472,7 +36805,7 @@ cloudCmd.command("pull").description("Pull cloud data to local \u2014 merges by
|
|
|
36472
36805
|
process.exit(1);
|
|
36473
36806
|
}
|
|
36474
36807
|
});
|
|
36475
|
-
cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote changes then push local changes").option("--tables <tables>", "Comma-separated table names (default: all)").option("--json", "Output as JSON").action(async (opts) => {
|
|
36808
|
+
cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote changes then push local changes").option("--tables <tables>", "Comma-separated table names (default: all)").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
36476
36809
|
const globalOpts = program2.opts();
|
|
36477
36810
|
const useJson = opts.json || globalOpts.json;
|
|
36478
36811
|
try {
|
|
@@ -36548,7 +36881,7 @@ cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote chan
|
|
|
36548
36881
|
process.exit(1);
|
|
36549
36882
|
}
|
|
36550
36883
|
});
|
|
36551
|
-
cloudCmd.command("conflicts").description("List sync conflicts detected during push/pull").option("--resolved", "Show resolved conflicts instead of unresolved").option("--table <table>", "Filter by table name").option("--limit <n>", "Max conflicts to show", "20").option("--json", "Output as JSON").action(async (opts) => {
|
|
36884
|
+
cloudCmd.command("conflicts").description("List sync conflicts detected during push/pull").option("--resolved", "Show resolved conflicts instead of unresolved").option("--table <table>", "Filter by table name").option("--limit <n>", "Max conflicts to show", "20").option("-j, --json", "Output as JSON").action(async (opts) => {
|
|
36552
36885
|
const globalOpts = program2.opts();
|
|
36553
36886
|
const useJson = opts.json || globalOpts.json;
|
|
36554
36887
|
try {
|