@hasna/todos 0.13.10 → 0.13.12
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/assignee-guard.d.ts +8 -1
- package/dist/cli/assignee-guard.d.ts.map +1 -1
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/query-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +153 -102
- package/dist/contracts.js +92 -67
- package/dist/db/agent-metrics.d.ts.map +1 -1
- package/dist/db/audit.d.ts.map +1 -1
- package/dist/db/budgets.d.ts.map +1 -1
- package/dist/db/database.d.ts +44 -0
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/handoffs.d.ts.map +1 -1
- package/dist/db/task-crud.d.ts +1 -0
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/db/task-files.d.ts.map +1 -1
- package/dist/db/task-lifecycle.d.ts.map +1 -1
- package/dist/db/task-relations.d.ts.map +1 -1
- package/dist/db/task-status.d.ts.map +1 -1
- package/dist/db/webhooks.d.ts.map +1 -1
- package/dist/index.js +119 -85
- package/dist/lib/assignee-validation.d.ts +22 -0
- package/dist/lib/assignee-validation.d.ts.map +1 -1
- package/dist/lib/capacity-forecasts.d.ts.map +1 -1
- package/dist/lib/completion-guard.d.ts.map +1 -1
- package/dist/lib/local-notifications.d.ts.map +1 -1
- package/dist/lib/local-reports.d.ts.map +1 -1
- package/dist/lib/notification-reminders.d.ts.map +1 -1
- package/dist/lib/search.d.ts.map +1 -1
- package/dist/lib/usage-ledger.d.ts.map +1 -1
- package/dist/mcp/index.js +138 -93
- package/dist/mcp/tools/agents.d.ts.map +1 -1
- package/dist/mcp/tools/task-adv-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-auto-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-resources.d.ts.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/registry.js +92 -67
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +138 -93
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/storage.js +57 -42
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -4111,14 +4111,17 @@ var exports_database = {};
|
|
|
4111
4111
|
__export(exports_database, {
|
|
4112
4112
|
uuid: () => uuid,
|
|
4113
4113
|
resolvePartialId: () => resolvePartialId,
|
|
4114
|
+
resolveAssignedToAliases: () => resolveAssignedToAliases,
|
|
4114
4115
|
resetDatabase: () => resetDatabase,
|
|
4115
4116
|
now: () => now,
|
|
4117
|
+
lowerInClause: () => lowerInClause,
|
|
4116
4118
|
lockExpiryCutoff: () => lockExpiryCutoff,
|
|
4117
4119
|
isLockExpired: () => isLockExpired,
|
|
4118
4120
|
getDatabasePath: () => getDatabasePath,
|
|
4119
4121
|
getDatabase: () => getDatabase,
|
|
4120
4122
|
closeDatabase: () => closeDatabase,
|
|
4121
4123
|
clearExpiredLocks: () => clearExpiredLocks,
|
|
4124
|
+
assignedToAliasSet: () => assignedToAliasSet,
|
|
4122
4125
|
LOCK_EXPIRY_MINUTES: () => LOCK_EXPIRY_MINUTES
|
|
4123
4126
|
});
|
|
4124
4127
|
import { Database } from "bun:sqlite";
|
|
@@ -4347,6 +4350,33 @@ function resolvePartialId(db, table, partialId) {
|
|
|
4347
4350
|
}
|
|
4348
4351
|
return null;
|
|
4349
4352
|
}
|
|
4353
|
+
function resolveAssignedToAliases(db, ref) {
|
|
4354
|
+
const aliases = new Set([ref]);
|
|
4355
|
+
let agentId;
|
|
4356
|
+
try {
|
|
4357
|
+
agentId = resolvePartialId(db, "agents", ref);
|
|
4358
|
+
} catch (err) {
|
|
4359
|
+
if (!(err instanceof IdentityAliasAmbiguousError))
|
|
4360
|
+
throw err;
|
|
4361
|
+
agentId = null;
|
|
4362
|
+
}
|
|
4363
|
+
if (agentId) {
|
|
4364
|
+
aliases.add(agentId);
|
|
4365
|
+
const row = db.query("SELECT name FROM agents WHERE id = ?").get(agentId);
|
|
4366
|
+
if (row?.name)
|
|
4367
|
+
aliases.add(row.name);
|
|
4368
|
+
}
|
|
4369
|
+
return [...aliases];
|
|
4370
|
+
}
|
|
4371
|
+
function assignedToAliasSet(db, ref) {
|
|
4372
|
+
return new Set(resolveAssignedToAliases(db, ref).map((a) => a.toLowerCase()));
|
|
4373
|
+
}
|
|
4374
|
+
function lowerInClause(column, values, params) {
|
|
4375
|
+
if (values.length === 0)
|
|
4376
|
+
return "1=0";
|
|
4377
|
+
params.push(...values.map((v) => v.toLowerCase()));
|
|
4378
|
+
return `LOWER(${column}) IN (${values.map(() => "?").join(",")})`;
|
|
4379
|
+
}
|
|
4350
4380
|
var LOCK_EXPIRY_MINUTES = 30, _db = null, _dbPath = null, ALLOWED_TABLES;
|
|
4351
4381
|
var init_database = __esm(() => {
|
|
4352
4382
|
init_schema();
|
|
@@ -9991,17 +10021,19 @@ function checkCompletionGuard(task, agentId, db, configOverride) {
|
|
|
9991
10021
|
throw new CompletionGuardError(`Too fast: task was started ${Math.floor(elapsedSeconds)}s ago. Minimum work duration is ${config.min_work_seconds}s. Wait ${remaining}s.`, remaining);
|
|
9992
10022
|
}
|
|
9993
10023
|
}
|
|
10024
|
+
const assignedAliasParams = [];
|
|
10025
|
+
const assignedInClause = agent ? lowerInClause("assigned_to", resolveAssignedToAliases(db, agent), assignedAliasParams) : "";
|
|
9994
10026
|
if (agent && config.max_completions_per_window && config.window_minutes) {
|
|
9995
10027
|
const windowStart = new Date(Date.now() - config.window_minutes * 60 * 1000).toISOString();
|
|
9996
10028
|
const result = db.query(`SELECT COUNT(*) as count FROM tasks
|
|
9997
|
-
WHERE completed_at > ? AND (
|
|
10029
|
+
WHERE completed_at > ? AND (${assignedInClause} OR agent_id = ?)`).get(windowStart, ...assignedAliasParams, agent);
|
|
9998
10030
|
if (result.count >= config.max_completions_per_window) {
|
|
9999
10031
|
throw new CompletionGuardError(`Rate limit: ${result.count} tasks completed in the last ${config.window_minutes} minutes (max ${config.max_completions_per_window}). Slow down.`);
|
|
10000
10032
|
}
|
|
10001
10033
|
}
|
|
10002
10034
|
if (agent && config.cooldown_seconds) {
|
|
10003
10035
|
const result = db.query(`SELECT MAX(completed_at) as last_completed FROM tasks
|
|
10004
|
-
WHERE completed_at IS NOT NULL AND (
|
|
10036
|
+
WHERE completed_at IS NOT NULL AND (${assignedInClause} OR agent_id = ?) AND id != ?`).get(...assignedAliasParams, agent, task.id);
|
|
10005
10037
|
if (result.last_completed) {
|
|
10006
10038
|
const elapsedSeconds = (Date.now() - new Date(result.last_completed).getTime()) / 1000;
|
|
10007
10039
|
if (elapsedSeconds < config.cooldown_seconds) {
|
|
@@ -10015,6 +10047,7 @@ var init_completion_guard = __esm(() => {
|
|
|
10015
10047
|
init_types();
|
|
10016
10048
|
init_config2();
|
|
10017
10049
|
init_projects();
|
|
10050
|
+
init_database();
|
|
10018
10051
|
});
|
|
10019
10052
|
|
|
10020
10053
|
// src/lib/event-emission-safety.ts
|
|
@@ -12013,13 +12046,17 @@ function logDelivery(d, webhookId, event, payload, statusCode, response, attempt
|
|
|
12013
12046
|
const id = uuid();
|
|
12014
12047
|
d.run(`INSERT INTO webhook_deliveries (id, webhook_id, event, payload, status_code, response, attempt, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, webhookId, event, payload, statusCode, response, attempt, now()]);
|
|
12015
12048
|
}
|
|
12016
|
-
function matchesScope(wh, payload) {
|
|
12049
|
+
function matchesScope(wh, payload, db) {
|
|
12017
12050
|
if (wh.project_id && payload.project_id !== wh.project_id)
|
|
12018
12051
|
return false;
|
|
12019
12052
|
if (wh.task_list_id && payload.task_list_id !== wh.task_list_id)
|
|
12020
12053
|
return false;
|
|
12021
|
-
if (wh.agent_id && payload.agent_id !== wh.agent_id
|
|
12022
|
-
|
|
12054
|
+
if (wh.agent_id && payload.agent_id !== wh.agent_id) {
|
|
12055
|
+
const aliasSet = assignedToAliasSet(db, wh.agent_id);
|
|
12056
|
+
const assignedTo = typeof payload.assigned_to === "string" ? payload.assigned_to.toLowerCase() : "";
|
|
12057
|
+
if (!aliasSet.has(assignedTo))
|
|
12058
|
+
return false;
|
|
12059
|
+
}
|
|
12023
12060
|
if (wh.task_id && payload.id !== wh.task_id)
|
|
12024
12061
|
return false;
|
|
12025
12062
|
return true;
|
|
@@ -12086,7 +12123,7 @@ async function dispatchWebhook2(event, payload, db) {
|
|
|
12086
12123
|
const webhooks = listWebhooks(d).filter((w) => w.active && (w.events.length === 0 || w.events.includes(event)));
|
|
12087
12124
|
const payloadObj = typeof payload === "object" && payload !== null ? payload : {};
|
|
12088
12125
|
for (const wh of webhooks) {
|
|
12089
|
-
if (!matchesScope(wh, payloadObj))
|
|
12126
|
+
if (!matchesScope(wh, payloadObj, d))
|
|
12090
12127
|
continue;
|
|
12091
12128
|
const body = JSON.stringify({ event, payload, timestamp: now() });
|
|
12092
12129
|
deliverWebhook(wh, event, body, 1, d).catch((err) => {
|
|
@@ -13202,14 +13239,16 @@ function getNextTask(agentId, filters, db) {
|
|
|
13202
13239
|
conditions.push("id NOT IN (SELECT td.task_id FROM task_dependencies td JOIN tasks dep ON dep.id = td.depends_on WHERE dep.status != 'completed')");
|
|
13203
13240
|
const where = conditions.join(" AND ");
|
|
13204
13241
|
let recentProjectIds = [];
|
|
13242
|
+
const assignedAliasParams = [];
|
|
13243
|
+
const assignedInClause = agentId ? lowerInClause("assigned_to", resolveAssignedToAliases(d, agentId), assignedAliasParams) : "";
|
|
13205
13244
|
if (agentId) {
|
|
13206
|
-
const recentRows = d.query(`SELECT DISTINCT project_id FROM tasks WHERE
|
|
13245
|
+
const recentRows = d.query(`SELECT DISTINCT project_id FROM tasks WHERE ${assignedInClause} AND status = 'completed' AND project_id IS NOT NULL ORDER BY completed_at DESC LIMIT 3`).all(...assignedAliasParams);
|
|
13207
13246
|
recentProjectIds = recentRows.map((r) => r.project_id);
|
|
13208
13247
|
}
|
|
13209
13248
|
let sql = `SELECT * FROM tasks WHERE ${where} ORDER BY `;
|
|
13210
13249
|
if (agentId) {
|
|
13211
|
-
sql += `CASE WHEN
|
|
13212
|
-
params.push(
|
|
13250
|
+
sql += `CASE WHEN ${assignedInClause} THEN 0 WHEN assigned_to IS NULL THEN 1 ELSE 2 END, `;
|
|
13251
|
+
params.push(...assignedAliasParams);
|
|
13213
13252
|
}
|
|
13214
13253
|
if (recentProjectIds.length > 0) {
|
|
13215
13254
|
const placeholders = recentProjectIds.map(() => "?").join(",");
|
|
@@ -13603,30 +13642,6 @@ function getTaskWithRelations(id, db) {
|
|
|
13603
13642
|
checklist
|
|
13604
13643
|
};
|
|
13605
13644
|
}
|
|
13606
|
-
function resolveAssignedToAliases(db, ref) {
|
|
13607
|
-
const aliases = new Set([ref]);
|
|
13608
|
-
let agentId;
|
|
13609
|
-
try {
|
|
13610
|
-
agentId = resolvePartialId(db, "agents", ref);
|
|
13611
|
-
} catch (err) {
|
|
13612
|
-
if (!(err instanceof IdentityAliasAmbiguousError))
|
|
13613
|
-
throw err;
|
|
13614
|
-
agentId = null;
|
|
13615
|
-
}
|
|
13616
|
-
if (agentId) {
|
|
13617
|
-
aliases.add(agentId);
|
|
13618
|
-
const row = db.query("SELECT name FROM agents WHERE id = ?").get(agentId);
|
|
13619
|
-
if (row?.name)
|
|
13620
|
-
aliases.add(row.name);
|
|
13621
|
-
}
|
|
13622
|
-
return [...aliases];
|
|
13623
|
-
}
|
|
13624
|
-
function lowerInClause(column, values, params) {
|
|
13625
|
-
if (values.length === 0)
|
|
13626
|
-
return "1=0";
|
|
13627
|
-
params.push(...values.map((v) => v.toLowerCase()));
|
|
13628
|
-
return `LOWER(${column}) IN (${values.map(() => "?").join(",")})`;
|
|
13629
|
-
}
|
|
13630
13645
|
function listTasks(filter = {}, db) {
|
|
13631
13646
|
const d = db || getDatabase();
|
|
13632
13647
|
const { clearExpiredLocks: clearExpiredLocks2 } = (init_database(), __toCommonJS(exports_database));
|
|
@@ -14099,6 +14114,7 @@ function deleteTask(id, db) {
|
|
|
14099
14114
|
var init_task_crud = __esm(() => {
|
|
14100
14115
|
init_types();
|
|
14101
14116
|
init_database();
|
|
14117
|
+
init_database();
|
|
14102
14118
|
init_completion_guard();
|
|
14103
14119
|
init_event_emission_safety();
|
|
14104
14120
|
init_event_hooks();
|
|
@@ -14261,8 +14277,8 @@ function getTaskStats(filters, db) {
|
|
|
14261
14277
|
params.push(filters.task_list_id);
|
|
14262
14278
|
}
|
|
14263
14279
|
if (filters?.agent_id) {
|
|
14264
|
-
|
|
14265
|
-
|
|
14280
|
+
params.push(filters.agent_id);
|
|
14281
|
+
conditions.push(`(agent_id = ? OR ${lowerInClause("assigned_to", resolveAssignedToAliases(d, filters.agent_id), params)})`);
|
|
14266
14282
|
}
|
|
14267
14283
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
14268
14284
|
const totalRow = d.query(`SELECT COUNT(*) as count FROM tasks ${where}`).get(...params);
|
|
@@ -14445,8 +14461,7 @@ function getEscalatedTasks(opts = {}, db, at = new Date) {
|
|
|
14445
14461
|
params.push(opts.project_id);
|
|
14446
14462
|
}
|
|
14447
14463
|
if (opts.agent_id) {
|
|
14448
|
-
conditions.push("assigned_to
|
|
14449
|
-
params.push(opts.agent_id);
|
|
14464
|
+
conditions.push(lowerInClause("assigned_to", resolveAssignedToAliases(d, opts.agent_id), params));
|
|
14450
14465
|
}
|
|
14451
14466
|
const rows = d.query(`SELECT * FROM tasks WHERE ${conditions.join(" AND ")} ORDER BY due_at ASC, created_at ASC`).all(...params);
|
|
14452
14467
|
return rows.map(rowToTask).map((task) => {
|
|
@@ -14494,8 +14509,7 @@ function notifyUpcomingDeadlines(opts = {}, db) {
|
|
|
14494
14509
|
params.push(opts.project_id);
|
|
14495
14510
|
}
|
|
14496
14511
|
if (opts.agent_id) {
|
|
14497
|
-
conditions.push("assigned_to
|
|
14498
|
-
params.push(opts.agent_id);
|
|
14512
|
+
conditions.push(lowerInClause("assigned_to", resolveAssignedToAliases(d, opts.agent_id), params));
|
|
14499
14513
|
}
|
|
14500
14514
|
const rows = d.query(`SELECT * FROM tasks WHERE ${conditions.join(" AND ")} ORDER BY due_at ASC`).all(...params);
|
|
14501
14515
|
return rows.map(rowToTask);
|
|
@@ -14753,13 +14767,14 @@ function getTimeReport(opts, db) {
|
|
|
14753
14767
|
params.push(opts.plan_id);
|
|
14754
14768
|
}
|
|
14755
14769
|
if (opts?.agent_id) {
|
|
14770
|
+
const assignedInClause = lowerInClause("t.assigned_to", resolveAssignedToAliases(d, opts.agent_id), params);
|
|
14756
14771
|
conditions.push(`(
|
|
14757
|
-
|
|
14772
|
+
${assignedInClause}
|
|
14758
14773
|
OR t.agent_id = ?
|
|
14759
14774
|
OR EXISTS (SELECT 1 FROM task_time_logs ttl WHERE ttl.task_id = t.id AND ttl.agent_id = ?)
|
|
14760
14775
|
OR EXISTS (SELECT 1 FROM focus_sessions fs WHERE fs.task_id = t.id AND fs.agent_id = ?)
|
|
14761
14776
|
)`);
|
|
14762
|
-
params.push(opts.agent_id, opts.agent_id, opts.agent_id
|
|
14777
|
+
params.push(opts.agent_id, opts.agent_id, opts.agent_id);
|
|
14763
14778
|
}
|
|
14764
14779
|
if (opts?.since) {
|
|
14765
14780
|
conditions.push("(t.completed_at >= ? OR t.updated_at >= ?)");
|
|
@@ -15755,7 +15770,7 @@ function listActiveFiles(db) {
|
|
|
15755
15770
|
a.name AS agent_name
|
|
15756
15771
|
FROM task_files tf
|
|
15757
15772
|
JOIN tasks t ON tf.task_id = t.id
|
|
15758
|
-
LEFT JOIN agents a ON (tf.agent_id = a.id OR (tf.agent_id IS NULL AND t.assigned_to = a.id))
|
|
15773
|
+
LEFT JOIN agents a ON (tf.agent_id = a.id OR (tf.agent_id IS NULL AND (t.assigned_to = a.id OR LOWER(t.assigned_to) = LOWER(a.name))))
|
|
15759
15774
|
WHERE t.status = 'in_progress'
|
|
15760
15775
|
AND tf.status != 'removed'
|
|
15761
15776
|
ORDER BY tf.updated_at DESC
|
|
@@ -18012,10 +18027,11 @@ function validateAssignee(input, ctx) {
|
|
|
18012
18027
|
if (ctx.allowSeat) {
|
|
18013
18028
|
return { ok: true, assignee: byId ? byId.name : raw, agentId: byId?.id, isSeat: true };
|
|
18014
18029
|
}
|
|
18030
|
+
const hint = ctx.seatHint?.(raw);
|
|
18015
18031
|
return {
|
|
18016
18032
|
ok: false,
|
|
18017
18033
|
reason: "seat",
|
|
18018
|
-
message: `'${raw}' is a durable SEAT, and a task assigned to a seat is assigned to nobody \u2014 no session is watching that queue. ` + `Assign a specific agent, use --unassigned to file it with no owner on purpose, or
|
|
18034
|
+
message: `'${raw}' is a durable SEAT, and a task assigned to a seat is assigned to nobody \u2014 no session is watching that queue. ` + `Assign a specific agent, use --unassigned to file it with no owner on purpose, or repeat the command with --assign-seat added to confirm the seat is deliberate` + (hint ? `: ${hint}` : " (see --help for this command's exact form).")
|
|
18019
18035
|
};
|
|
18020
18036
|
}
|
|
18021
18037
|
if (byId) {
|
|
@@ -23055,11 +23071,12 @@ function runAlerts(input, db, checkedAt, quieted) {
|
|
|
23055
23071
|
if (input.include_runs === false)
|
|
23056
23072
|
return [];
|
|
23057
23073
|
const since = Date.parse(input.run_since || new Date(Date.parse(checkedAt) - 24 * 60 * 60000).toISOString());
|
|
23074
|
+
const runAlertAliases = input.agent_id ? assignedToAliasSet(db, input.agent_id) : null;
|
|
23058
23075
|
return listTaskRuns(undefined, db).filter((run) => run.completed_at && Date.parse(run.completed_at) >= since).map((run) => {
|
|
23059
23076
|
const task = getTask(run.task_id, db);
|
|
23060
23077
|
if (input.project_id && task?.project_id !== input.project_id)
|
|
23061
23078
|
return null;
|
|
23062
|
-
if (input.agent_id && run.agent_id !== input.agent_id && task?.assigned_to
|
|
23079
|
+
if (input.agent_id && run.agent_id !== input.agent_id && !(runAlertAliases && runAlertAliases.has((task?.assigned_to ?? "").toLowerCase())))
|
|
23063
23080
|
return null;
|
|
23064
23081
|
const failed = ["failed", "cancelled"].includes(run.status);
|
|
23065
23082
|
return {
|
|
@@ -23104,6 +23121,7 @@ async function checkLocalNotifications(input = {}, db) {
|
|
|
23104
23121
|
const warnings = [];
|
|
23105
23122
|
if (Number.isNaN(checkedMs))
|
|
23106
23123
|
warnings.push("Invalid check timestamp; due-soon window may be incomplete.");
|
|
23124
|
+
const notifyAgentAliases = input.agent_id ? assignedToAliasSet(d, input.agent_id) : null;
|
|
23107
23125
|
const alerts = [];
|
|
23108
23126
|
for (const escalation of getEscalatedTasks({ project_id: input.project_id, agent_id: input.agent_id }, d, new Date(checkedAt))) {
|
|
23109
23127
|
for (const reason of escalation.reasons) {
|
|
@@ -23115,7 +23133,7 @@ async function checkLocalNotifications(input = {}, db) {
|
|
|
23115
23133
|
for (const task of listTasks({ project_id: input.project_id, include_archived: false, limit: 5000 }, d)) {
|
|
23116
23134
|
if (!unfinished(task) || !task.due_at)
|
|
23117
23135
|
continue;
|
|
23118
|
-
if (input.agent_id && task.
|
|
23136
|
+
if (input.agent_id && task.agent_id !== input.agent_id && !(notifyAgentAliases && notifyAgentAliases.has((task.assigned_to ?? "").toLowerCase())))
|
|
23119
23137
|
continue;
|
|
23120
23138
|
if (task.due_at > checkedAt && task.due_at <= dueSoonUntil) {
|
|
23121
23139
|
alerts.push(taskAlert(task, "task_due_soon", "task.due_soon", "warning", `Due soon: ${task.title}`, task.due_at, quieted));
|
|
@@ -23123,7 +23141,7 @@ async function checkLocalNotifications(input = {}, db) {
|
|
|
23123
23141
|
}
|
|
23124
23142
|
}
|
|
23125
23143
|
for (const task of getStaleTasks(staleMinutes, { project_id: input.project_id }, d)) {
|
|
23126
|
-
if (input.agent_id && task.
|
|
23144
|
+
if (input.agent_id && task.agent_id !== input.agent_id && !(notifyAgentAliases && notifyAgentAliases.has((task.assigned_to ?? "").toLowerCase())))
|
|
23127
23145
|
continue;
|
|
23128
23146
|
alerts.push(taskAlert(task, "task_stale", "task.stale", "warning", `Stale task: ${task.title}`, checkedAt, quieted, { stale_minutes: staleMinutes }));
|
|
23129
23147
|
}
|
|
@@ -25143,10 +25161,12 @@ function matchesProfile(profile, query) {
|
|
|
25143
25161
|
return false;
|
|
25144
25162
|
return true;
|
|
25145
25163
|
}
|
|
25146
|
-
function taskMatchesAgent(task, agentId) {
|
|
25164
|
+
function taskMatchesAgent(task, agentId, aliasSet) {
|
|
25147
25165
|
if (!agentId)
|
|
25148
25166
|
return true;
|
|
25149
|
-
|
|
25167
|
+
if (task.agent_id === agentId)
|
|
25168
|
+
return true;
|
|
25169
|
+
return aliasSet ? aliasSet.has((task.assigned_to ?? "").toLowerCase()) : task.assigned_to === agentId;
|
|
25150
25170
|
}
|
|
25151
25171
|
function estimateRemaining(task) {
|
|
25152
25172
|
if (task.status === "completed" || task.status === "cancelled")
|
|
@@ -25216,7 +25236,8 @@ function removeCapacityProfile(idOrAgent, projectId) {
|
|
|
25216
25236
|
}
|
|
25217
25237
|
function getPlanningForecast(input = {}, db) {
|
|
25218
25238
|
const startDate = input.start_date ? dateOnly(input.start_date) : todayIso();
|
|
25219
|
-
const
|
|
25239
|
+
const aliasSet = input.agent_id ? assignedToAliasSet(db || getDatabase(), input.agent_id) : undefined;
|
|
25240
|
+
const tasks = listTasks({ project_id: input.project_id, plan_id: input.plan_id, limit: 1e4 }, db).filter((task) => taskMatchesAgent(task, input.agent_id, aliasSet));
|
|
25220
25241
|
const reportByTask = new Map(getTimeReport({ project_id: input.project_id, plan_id: input.plan_id, agent_id: input.agent_id, include_open: true }, db).map((entry) => [entry.task_id, entry]));
|
|
25221
25242
|
const profiles = listCapacityProfiles({ agent_id: input.agent_id, project_id: input.project_id });
|
|
25222
25243
|
const globalProfiles = input.project_id ? listCapacityProfiles({ agent_id: input.agent_id }).filter((profile) => profile.project_id === null) : [];
|
|
@@ -25314,6 +25335,7 @@ function renderPlanningForecastMarkdown(forecast) {
|
|
|
25314
25335
|
}
|
|
25315
25336
|
var LOCAL_CAPACITY_SCHEMA_VERSION = 1;
|
|
25316
25337
|
var init_capacity_forecasts = __esm(() => {
|
|
25338
|
+
init_database();
|
|
25317
25339
|
init_tasks();
|
|
25318
25340
|
init_task_relations();
|
|
25319
25341
|
init_config2();
|
|
@@ -25975,8 +25997,7 @@ function searchTasks(options, projectId, taskListId, db) {
|
|
|
25975
25997
|
}
|
|
25976
25998
|
}
|
|
25977
25999
|
if (opts.assigned_to) {
|
|
25978
|
-
sql +=
|
|
25979
|
-
params.push(opts.assigned_to);
|
|
26000
|
+
sql += ` AND ${lowerInClause("t.assigned_to", resolveAssignedToAliases(d, opts.assigned_to), params)}`;
|
|
25980
26001
|
}
|
|
25981
26002
|
if (opts.agent_id) {
|
|
25982
26003
|
sql += " AND t.agent_id = ?";
|
|
@@ -28907,8 +28928,10 @@ function getLatestHandoff(agentId, projectId, db) {
|
|
|
28907
28928
|
function createSessionRecoveryHandoff(input, db) {
|
|
28908
28929
|
const d = db || getDatabase();
|
|
28909
28930
|
const limit = input.limit || 20;
|
|
28910
|
-
const
|
|
28911
|
-
const
|
|
28931
|
+
const params = [];
|
|
28932
|
+
const assignedInClause = lowerInClause("assigned_to", resolveAssignedToAliases(d, input.agent_id), params);
|
|
28933
|
+
const conditions = ["status = 'in_progress'", `(${assignedInClause} OR agent_id = ? OR locked_by = ?)`];
|
|
28934
|
+
params.push(input.agent_id, input.agent_id);
|
|
28912
28935
|
if (input.session_id) {
|
|
28913
28936
|
conditions.push("session_id = ?");
|
|
28914
28937
|
params.push(input.session_id);
|
|
@@ -30132,7 +30155,8 @@ function registerTaskAutoTools(server, ctx) {
|
|
|
30132
30155
|
const assigned = listTasks3({ assigned_to: effectiveAgentId, limit: 500 }, undefined);
|
|
30133
30156
|
const now4 = Date.now();
|
|
30134
30157
|
const dueSoonCutoff = now4 + 24 * 60 * 60 * 1000;
|
|
30135
|
-
const
|
|
30158
|
+
const blockedAliases = assignedToAliasSet(getDatabase(), effectiveAgentId);
|
|
30159
|
+
const blocked = getBlockedTasks2().filter((t) => blockedAliases.has((t.assigned_to ?? "").toLowerCase()));
|
|
30136
30160
|
const workload = {
|
|
30137
30161
|
in_progress: assigned.filter((t) => t.status === "in_progress").length,
|
|
30138
30162
|
pending: assigned.filter((t) => t.status === "pending").length,
|
|
@@ -30169,17 +30193,25 @@ function registerTaskAutoTools(server, ctx) {
|
|
|
30169
30193
|
if (agents.length === 0)
|
|
30170
30194
|
return { content: [{ type: "text", text: "No active agents available for rebalancing." }] };
|
|
30171
30195
|
const activeTasks = listTasks3({ project_id: resolvedProjectId, status: ["pending", "in_progress"], limit: 1000 }, undefined);
|
|
30172
|
-
const
|
|
30196
|
+
const agentKeyByAlias = new Map;
|
|
30197
|
+
for (const agent of agents) {
|
|
30198
|
+
agentKeyByAlias.set(String(agent.id).toLowerCase(), agent.id);
|
|
30199
|
+
if (agent.name)
|
|
30200
|
+
agentKeyByAlias.set(String(agent.name).toLowerCase(), agent.id);
|
|
30201
|
+
}
|
|
30202
|
+
const canonicalAgentKey = (assignedTo) => assignedTo ? agentKeyByAlias.get(assignedTo.toLowerCase()) : undefined;
|
|
30203
|
+
const load = new Map(agents.map((agent) => [agent.id, activeTasks.filter((t) => canonicalAgentKey(t.assigned_to) === agent.id).length]));
|
|
30173
30204
|
let moved = 0;
|
|
30174
30205
|
let skipped = 0;
|
|
30175
|
-
for (const task of activeTasks.filter((t) => t.status === "pending" && t.assigned_to && (load.get(t.assigned_to) ?? 0) > limit)) {
|
|
30176
|
-
const
|
|
30206
|
+
for (const task of activeTasks.filter((t) => t.status === "pending" && canonicalAgentKey(t.assigned_to) && (load.get(canonicalAgentKey(t.assigned_to)) ?? 0) > limit)) {
|
|
30207
|
+
const currentAgentKey = canonicalAgentKey(task.assigned_to);
|
|
30208
|
+
const target = agents.filter((agent) => agent.id !== currentAgentKey).sort((a, b) => (load.get(a.id) ?? 0) - (load.get(b.id) ?? 0))[0];
|
|
30177
30209
|
if (!target || (load.get(target.id) ?? 0) >= limit) {
|
|
30178
30210
|
skipped++;
|
|
30179
30211
|
continue;
|
|
30180
30212
|
}
|
|
30181
30213
|
updateTask2(task.id, { assigned_to: target.id, version: task.version });
|
|
30182
|
-
load.set(
|
|
30214
|
+
load.set(currentAgentKey, (load.get(currentAgentKey) ?? 1) - 1);
|
|
30183
30215
|
load.set(target.id, (load.get(target.id) ?? 0) + 1);
|
|
30184
30216
|
moved++;
|
|
30185
30217
|
}
|
|
@@ -30358,6 +30390,7 @@ ${lines.join(`
|
|
|
30358
30390
|
var init_task_auto_tools = __esm(() => {
|
|
30359
30391
|
init_zod();
|
|
30360
30392
|
init_cloud_router();
|
|
30393
|
+
init_database();
|
|
30361
30394
|
});
|
|
30362
30395
|
|
|
30363
30396
|
// src/lib/context-packs.ts
|
|
@@ -31537,7 +31570,8 @@ ${JSON.stringify(task.metadata, null, 2)}` : null
|
|
|
31537
31570
|
}, undefined);
|
|
31538
31571
|
const completedYesterday = completed.filter((t) => t.completed_at && t.completed_at.startsWith(yesterdayStr));
|
|
31539
31572
|
const { getBlockedTasks: getBlockedTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
|
|
31540
|
-
const
|
|
31573
|
+
const blockedAliases = effectiveAgentId ? assignedToAliasSet(getDatabase(), effectiveAgentId) : null;
|
|
31574
|
+
const blocked = getBlockedTasks2(effectiveProjectId ? resolveId(effectiveProjectId, "projects") : undefined).filter((t) => blockedAliases ? blockedAliases.has((t.assigned_to ?? "").toLowerCase()) : false);
|
|
31541
31575
|
const lines = [
|
|
31542
31576
|
`Standup for ${effectiveAgentId} (${effectiveProjectId ? `project: ${effectiveProjectId.slice(0, 8)}` : "all projects"})`,
|
|
31543
31577
|
inProgress.length > 0 ? `
|
|
@@ -31765,6 +31799,7 @@ var init_task_adv_tools = __esm(() => {
|
|
|
31765
31799
|
init_zod();
|
|
31766
31800
|
init_token_utils();
|
|
31767
31801
|
init_cloud_router();
|
|
31802
|
+
init_database();
|
|
31768
31803
|
});
|
|
31769
31804
|
|
|
31770
31805
|
// src/mcp/tools/task-meta-tools.ts
|
|
@@ -33682,27 +33717,29 @@ function getAgentMetrics(agentId, opts, db) {
|
|
|
33682
33717
|
const agent = d.query("SELECT id, name FROM agents WHERE id = ? OR LOWER(name) = LOWER(?)").get(agentId, agentId);
|
|
33683
33718
|
if (!agent)
|
|
33684
33719
|
return null;
|
|
33720
|
+
const assignedAliases = resolveAssignedToAliases(d, agent.id).map((a) => a.toLowerCase());
|
|
33721
|
+
const assignedInClause = `LOWER(assigned_to) IN (${assignedAliases.map(() => "?").join(",")})`;
|
|
33685
33722
|
let projectFilter = "";
|
|
33686
|
-
const params = [agent.id,
|
|
33723
|
+
const params = [agent.id, ...assignedAliases];
|
|
33687
33724
|
if (opts?.project_id) {
|
|
33688
33725
|
projectFilter = " AND project_id = ?";
|
|
33689
33726
|
params.push(opts.project_id);
|
|
33690
33727
|
}
|
|
33691
|
-
const completed = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR
|
|
33692
|
-
const failed = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR
|
|
33693
|
-
const inProgress = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR
|
|
33728
|
+
const completed = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'completed'${projectFilter}`).get(...params).count;
|
|
33729
|
+
const failed = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'failed'${projectFilter}`).get(...params).count;
|
|
33730
|
+
const inProgress = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'in_progress'${projectFilter}`).get(...params).count;
|
|
33694
33731
|
const total = completed + failed;
|
|
33695
33732
|
const completionRate = total > 0 ? completed / total : 0;
|
|
33696
33733
|
const avgTime = d.query(`SELECT AVG(
|
|
33697
33734
|
(julianday(completed_at) - julianday(created_at)) * 24 * 60
|
|
33698
33735
|
) as avg_minutes
|
|
33699
33736
|
FROM tasks
|
|
33700
|
-
WHERE (agent_id = ? OR
|
|
33737
|
+
WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'completed' AND completed_at IS NOT NULL${projectFilter}`).get(...params);
|
|
33701
33738
|
const avgConf = d.query(`SELECT AVG(confidence) as avg_confidence
|
|
33702
33739
|
FROM tasks
|
|
33703
|
-
WHERE (agent_id = ? OR
|
|
33740
|
+
WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'completed' AND confidence IS NOT NULL${projectFilter}`).get(...params);
|
|
33704
33741
|
const reviewTasks = d.query(`SELECT metadata FROM tasks
|
|
33705
|
-
WHERE (agent_id = ? OR
|
|
33742
|
+
WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'completed'${projectFilter}
|
|
33706
33743
|
AND metadata LIKE '%_review_score%'`).all(...params);
|
|
33707
33744
|
let reviewScoreAvg = null;
|
|
33708
33745
|
if (reviewTasks.length > 0) {
|
|
@@ -34166,14 +34203,15 @@ function millisBetween(start, end) {
|
|
|
34166
34203
|
return 0;
|
|
34167
34204
|
return endMs - startMs;
|
|
34168
34205
|
}
|
|
34169
|
-
function addTaskScope(where, params, options, alias = "t") {
|
|
34206
|
+
function addTaskScope(where, params, options, db, alias = "t") {
|
|
34170
34207
|
if (options.project_id) {
|
|
34171
34208
|
where.push(`${alias}.project_id = ?`);
|
|
34172
34209
|
params.push(options.project_id);
|
|
34173
34210
|
}
|
|
34174
34211
|
if (options.agent_id) {
|
|
34175
|
-
|
|
34176
|
-
|
|
34212
|
+
params.push(options.agent_id);
|
|
34213
|
+
const assignedInClause = lowerInClause(`${alias}.assigned_to`, resolveAssignedToAliases(db, options.agent_id), params);
|
|
34214
|
+
where.push(`(${alias}.agent_id = ? OR ${assignedInClause})`);
|
|
34177
34215
|
}
|
|
34178
34216
|
if (options.since) {
|
|
34179
34217
|
where.push(`${alias}.created_at >= ?`);
|
|
@@ -34184,14 +34222,15 @@ function addTaskScope(where, params, options, alias = "t") {
|
|
|
34184
34222
|
params.push(options.until);
|
|
34185
34223
|
}
|
|
34186
34224
|
}
|
|
34187
|
-
function addRunScope(where, params, options, runAlias = "r", taskAlias = "t") {
|
|
34225
|
+
function addRunScope(where, params, options, db, runAlias = "r", taskAlias = "t") {
|
|
34188
34226
|
if (options.project_id) {
|
|
34189
34227
|
where.push(`${taskAlias}.project_id = ?`);
|
|
34190
34228
|
params.push(options.project_id);
|
|
34191
34229
|
}
|
|
34192
34230
|
if (options.agent_id) {
|
|
34193
|
-
|
|
34194
|
-
|
|
34231
|
+
params.push(options.agent_id, options.agent_id);
|
|
34232
|
+
const assignedInClause = lowerInClause(`${taskAlias}.assigned_to`, resolveAssignedToAliases(db, options.agent_id), params);
|
|
34233
|
+
where.push(`(${runAlias}.agent_id = ? OR ${taskAlias}.agent_id = ? OR ${assignedInClause})`);
|
|
34195
34234
|
}
|
|
34196
34235
|
if (options.since) {
|
|
34197
34236
|
where.push(`${runAlias}.started_at >= ?`);
|
|
@@ -34202,14 +34241,15 @@ function addRunScope(where, params, options, runAlias = "r", taskAlias = "t") {
|
|
|
34202
34241
|
params.push(options.until);
|
|
34203
34242
|
}
|
|
34204
34243
|
}
|
|
34205
|
-
function addTraceScope(where, params, options, traceAlias = "tr", taskAlias = "t") {
|
|
34244
|
+
function addTraceScope(where, params, options, db, traceAlias = "tr", taskAlias = "t") {
|
|
34206
34245
|
if (options.project_id) {
|
|
34207
34246
|
where.push(`${taskAlias}.project_id = ?`);
|
|
34208
34247
|
params.push(options.project_id);
|
|
34209
34248
|
}
|
|
34210
34249
|
if (options.agent_id) {
|
|
34211
|
-
|
|
34212
|
-
|
|
34250
|
+
params.push(options.agent_id, options.agent_id);
|
|
34251
|
+
const assignedInClause = lowerInClause(`${taskAlias}.assigned_to`, resolveAssignedToAliases(db, options.agent_id), params);
|
|
34252
|
+
where.push(`(${traceAlias}.agent_id = ? OR ${taskAlias}.agent_id = ? OR ${assignedInClause})`);
|
|
34213
34253
|
}
|
|
34214
34254
|
if (options.since) {
|
|
34215
34255
|
where.push(`${traceAlias}.created_at >= ?`);
|
|
@@ -34269,7 +34309,7 @@ function createLocalUsageLedger(options = {}, db) {
|
|
|
34269
34309
|
const generatedAt = options.generated_at || new Date().toISOString();
|
|
34270
34310
|
const taskWhere = [];
|
|
34271
34311
|
const taskParams = [];
|
|
34272
|
-
addTaskScope(taskWhere, taskParams, options);
|
|
34312
|
+
addTaskScope(taskWhere, taskParams, options, d);
|
|
34273
34313
|
const taskClause = taskWhere.length ? `WHERE ${taskWhere.join(" AND ")}` : "";
|
|
34274
34314
|
const taskTotals = queryOne(d, `SELECT COUNT(*) as tasks, COALESCE(SUM(cost_tokens), 0) as task_tokens, COALESCE(SUM(cost_usd), 0) as task_cost_usd FROM tasks t ${taskClause}`, taskParams);
|
|
34275
34315
|
let projectCount = 0;
|
|
@@ -34278,14 +34318,14 @@ function createLocalUsageLedger(options = {}, db) {
|
|
|
34278
34318
|
} else if (options.agent_id) {
|
|
34279
34319
|
const projectWhere = ["t.project_id IS NOT NULL"];
|
|
34280
34320
|
const projectParams = [];
|
|
34281
|
-
addTaskScope(projectWhere, projectParams, options);
|
|
34321
|
+
addTaskScope(projectWhere, projectParams, options, d);
|
|
34282
34322
|
projectCount = queryOne(d, `SELECT COUNT(DISTINCT t.project_id) as count FROM tasks t WHERE ${projectWhere.join(" AND ")}`, projectParams).count;
|
|
34283
34323
|
} else {
|
|
34284
34324
|
projectCount = queryOne(d, "SELECT COUNT(*) as count FROM projects", []).count;
|
|
34285
34325
|
}
|
|
34286
34326
|
const runWhere = [];
|
|
34287
34327
|
const runParams = [];
|
|
34288
|
-
addRunScope(runWhere, runParams, options);
|
|
34328
|
+
addRunScope(runWhere, runParams, options, d);
|
|
34289
34329
|
const runClause = runWhere.length ? `WHERE ${runWhere.join(" AND ")}` : "";
|
|
34290
34330
|
const runs = queryAll(d, `SELECT r.id, r.started_at, r.completed_at, r.metadata
|
|
34291
34331
|
FROM task_runs r JOIN tasks t ON t.id = r.task_id
|
|
@@ -34302,7 +34342,7 @@ function createLocalUsageLedger(options = {}, db) {
|
|
|
34302
34342
|
${runClause}`, runParams);
|
|
34303
34343
|
const traceWhere = [];
|
|
34304
34344
|
const traceParams = [];
|
|
34305
|
-
addTraceScope(traceWhere, traceParams, options);
|
|
34345
|
+
addTraceScope(traceWhere, traceParams, options, d);
|
|
34306
34346
|
const traceClause = traceWhere.length ? `WHERE ${traceWhere.join(" AND ")}` : "";
|
|
34307
34347
|
const traceTotals = queryOne(d, `SELECT COUNT(*) as traces,
|
|
34308
34348
|
COALESCE(SUM(tr.tokens), 0) as tokens,
|
|
@@ -34446,10 +34486,12 @@ function limitValue(value) {
|
|
|
34446
34486
|
function isTerminal(task) {
|
|
34447
34487
|
return task.status === "completed" || task.status === "failed" || task.status === "cancelled";
|
|
34448
34488
|
}
|
|
34449
|
-
function sameAgent(task, agentId) {
|
|
34489
|
+
function sameAgent(task, agentId, aliasSet) {
|
|
34450
34490
|
if (!agentId)
|
|
34451
34491
|
return true;
|
|
34452
|
-
|
|
34492
|
+
if (task.agent_id === agentId)
|
|
34493
|
+
return true;
|
|
34494
|
+
return aliasSet ? aliasSet.has((task.assigned_to ?? "").toLowerCase()) : task.assigned_to === agentId;
|
|
34453
34495
|
}
|
|
34454
34496
|
function withinTaskWindow(task, options) {
|
|
34455
34497
|
const time = Date.parse(task.updated_at);
|
|
@@ -34462,11 +34504,12 @@ function withinTaskWindow(task, options) {
|
|
|
34462
34504
|
return true;
|
|
34463
34505
|
}
|
|
34464
34506
|
function scopedTasks(options, db) {
|
|
34507
|
+
const aliasSet = options.agent_id ? assignedToAliasSet(db, options.agent_id) : undefined;
|
|
34465
34508
|
return listTasks({
|
|
34466
34509
|
project_id: options.project_id,
|
|
34467
34510
|
plan_id: options.plan_id,
|
|
34468
34511
|
include_archived: false
|
|
34469
|
-
}, db).filter((task) => sameAgent(task, options.agent_id) && withinTaskWindow(task, options));
|
|
34512
|
+
}, db).filter((task) => sameAgent(task, options.agent_id, aliasSet) && withinTaskWindow(task, options));
|
|
34470
34513
|
}
|
|
34471
34514
|
function summarizeTask(task) {
|
|
34472
34515
|
return {
|
|
@@ -34532,7 +34575,7 @@ function initialAgentSummary(agentId) {
|
|
|
34532
34575
|
}
|
|
34533
34576
|
};
|
|
34534
34577
|
}
|
|
34535
|
-
function addScopeClauses(where, params, options, timeColumn) {
|
|
34578
|
+
function addScopeClauses(where, params, options, timeColumn, db) {
|
|
34536
34579
|
if (options.project_id) {
|
|
34537
34580
|
where.push("t.project_id = ?");
|
|
34538
34581
|
params.push(options.project_id);
|
|
@@ -34542,8 +34585,9 @@ function addScopeClauses(where, params, options, timeColumn) {
|
|
|
34542
34585
|
params.push(options.plan_id);
|
|
34543
34586
|
}
|
|
34544
34587
|
if (options.agent_id) {
|
|
34545
|
-
|
|
34546
|
-
|
|
34588
|
+
params.push(options.agent_id, options.agent_id);
|
|
34589
|
+
const assignedInClause = lowerInClause("t.assigned_to", resolveAssignedToAliases(db, options.agent_id), params);
|
|
34590
|
+
where.push(`(r.agent_id = ? OR t.agent_id = ? OR ${assignedInClause})`);
|
|
34547
34591
|
}
|
|
34548
34592
|
if (options.since) {
|
|
34549
34593
|
where.push(`${timeColumn} >= ?`);
|
|
@@ -34557,7 +34601,7 @@ function addScopeClauses(where, params, options, timeColumn) {
|
|
|
34557
34601
|
function loadRuns(options, db) {
|
|
34558
34602
|
const where = ["t.archived_at IS NULL"];
|
|
34559
34603
|
const params = [];
|
|
34560
|
-
addScopeClauses(where, params, options, "r.started_at");
|
|
34604
|
+
addScopeClauses(where, params, options, "r.started_at", db);
|
|
34561
34605
|
return db.query(`
|
|
34562
34606
|
SELECT
|
|
34563
34607
|
r.id,
|
|
@@ -34597,8 +34641,9 @@ function loadVerifications(options, db) {
|
|
|
34597
34641
|
params.push(options.plan_id);
|
|
34598
34642
|
}
|
|
34599
34643
|
if (options.agent_id) {
|
|
34600
|
-
|
|
34601
|
-
|
|
34644
|
+
params.push(options.agent_id, options.agent_id);
|
|
34645
|
+
const assignedInClause = lowerInClause("t.assigned_to", resolveAssignedToAliases(db, options.agent_id), params);
|
|
34646
|
+
where.push(`(v.agent_id = ? OR t.agent_id = ? OR ${assignedInClause})`);
|
|
34602
34647
|
}
|
|
34603
34648
|
if (options.since) {
|
|
34604
34649
|
where.push("v.run_at >= ?");
|
|
@@ -34820,7 +34865,6 @@ function renderLocalReportMarkdown(report) {
|
|
|
34820
34865
|
}
|
|
34821
34866
|
var LOCAL_REPORT_SCHEMA_VERSION = 1, LOCAL_REPORT_TYPES;
|
|
34822
34867
|
var init_local_reports = __esm(() => {
|
|
34823
|
-
init_database();
|
|
34824
34868
|
init_database();
|
|
34825
34869
|
init_plans();
|
|
34826
34870
|
init_tasks();
|
|
@@ -34842,7 +34886,7 @@ var package_default;
|
|
|
34842
34886
|
var init_package = __esm(() => {
|
|
34843
34887
|
package_default = {
|
|
34844
34888
|
name: "@hasna/todos",
|
|
34845
|
-
version: "0.13.
|
|
34889
|
+
version: "0.13.12",
|
|
34846
34890
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
34847
34891
|
type: "module",
|
|
34848
34892
|
main: "dist/index.js",
|
|
@@ -39059,7 +39103,7 @@ ${lines.join(`
|
|
|
39059
39103
|
a.name AS agent_name
|
|
39060
39104
|
FROM task_files tf
|
|
39061
39105
|
JOIN tasks t ON tf.task_id = t.id
|
|
39062
|
-
LEFT JOIN agents a ON (tf.agent_id = a.id OR (tf.agent_id IS NULL AND t.assigned_to = a.id))
|
|
39106
|
+
LEFT JOIN agents a ON (tf.agent_id = a.id OR (tf.agent_id IS NULL AND (t.assigned_to = a.id OR LOWER(t.assigned_to) = LOWER(a.name))))
|
|
39063
39107
|
WHERE t.status = 'in_progress'
|
|
39064
39108
|
AND tf.status != 'removed'
|
|
39065
39109
|
AND t.project_id = ?
|
|
@@ -42823,7 +42867,7 @@ ${text2}` }] };
|
|
|
42823
42867
|
const oldName = agent.name;
|
|
42824
42868
|
const updated = updateAgent(agent.id, { name: new_name });
|
|
42825
42869
|
const db = getDatabase();
|
|
42826
|
-
const tasksResult = db.run("UPDATE tasks SET assigned_to = ? WHERE assigned_to = ?", [new_name, oldName]);
|
|
42870
|
+
const tasksResult = db.run("UPDATE tasks SET assigned_to = ? WHERE LOWER(assigned_to) = LOWER(?)", [new_name, oldName]);
|
|
42827
42871
|
const taskNote = tasksResult.changes > 0 ? `
|
|
42828
42872
|
Updated assigned_to on ${tasksResult.changes} task(s).` : "";
|
|
42829
42873
|
return {
|
|
@@ -48681,8 +48725,9 @@ async function handleAgentMe(_req, url, _ctx, json2, taskToSummary2) {
|
|
|
48681
48725
|
}
|
|
48682
48726
|
}
|
|
48683
48727
|
function handleAgentQueue(agentId, _ctx, json2, taskToSummary2) {
|
|
48728
|
+
const aliasSet = assignedToAliasSet(getDatabase(), agentId);
|
|
48684
48729
|
const pending = listTasks({ status: "pending" });
|
|
48685
|
-
const queue = pending.filter((t) => t.assigned_to
|
|
48730
|
+
const queue = pending.filter((t) => aliasSet.has((t.assigned_to ?? "").toLowerCase()) || t.agent_id === agentId || !t.assigned_to && !t.locked_by);
|
|
48686
48731
|
const order = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
48687
48732
|
queue.sort((a, b) => (order[a.priority] ?? 4) - (order[b.priority] ?? 4) || new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
|
|
48688
48733
|
return json2(queue.map((t) => taskToSummary2(t)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,KAAK,OAAO,GAAG;IACb,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9C,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,WAAW,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IACpC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;CAC5D,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,KAAK,OAAO,GAAG;IACb,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9C,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,WAAW,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IACpC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;CAC5D,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,EAAE,OAAO,GAAG,IAAI,CAqfjJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-adv-tools.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/task-adv-tools.ts"],"names":[],"mappings":"AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"task-adv-tools.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/task-adv-tools.ts"],"names":[],"mappings":"AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAKjD,UAAU,cAAc;IACtB,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9C,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzD,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;IACxC,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IACnC,gBAAgB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,mBAAmB,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACvE,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CAC3F;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,cAAc,QA2nB1E"}
|