@hasna/todos 0.11.83 → 0.11.85
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/cloud-router.d.ts +199 -1
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/agent-commands.d.ts.map +1 -1
- package/dist/cli/commands/mcp-hooks-commands.d.ts.map +1 -1
- package/dist/cli/commands/plan-template-commands.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 +931 -165
- package/dist/index.js +90 -8
- package/dist/mcp/index.js +265 -2
- package/dist/mcp/tools/agents.d.ts.map +1 -1
- package/dist/release-provenance.json +3 -3
- package/dist/server/index.js +274 -11
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/interfaces.d.ts +73 -0
- package/dist/storage/interfaces.d.ts.map +1 -1
- package/dist/storage/postgres-adapter.d.ts.map +1 -1
- package/dist/storage.js +84 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23532,12 +23532,23 @@ function createPostgresTodosStorageAdapter(options) {
|
|
|
23532
23532
|
dependencies: {
|
|
23533
23533
|
add: (taskId, dependsOn, context) => addDependency2(taskId, dependsOn, store, context),
|
|
23534
23534
|
remove: (taskId, dependsOn) => removeDependency2(taskId, dependsOn, store),
|
|
23535
|
-
list: (taskId) => listDependencies(taskId, store)
|
|
23535
|
+
list: (taskId) => listDependencies(taskId, store),
|
|
23536
|
+
listAll: () => store.list("dependencies")
|
|
23536
23537
|
},
|
|
23537
23538
|
verifications: {
|
|
23538
23539
|
add: (input, context) => addVerification(input, store, context),
|
|
23539
23540
|
list: (taskId) => listVerifications(taskId, store)
|
|
23540
23541
|
},
|
|
23542
|
+
commits: {
|
|
23543
|
+
add: (input, context) => addCommit(input, store, context),
|
|
23544
|
+
list: (taskId) => listCommits(taskId, store),
|
|
23545
|
+
find: (sha) => findCommit(sha, store)
|
|
23546
|
+
},
|
|
23547
|
+
gitRefs: {
|
|
23548
|
+
add: (input, context) => addGitRef(input, store, context),
|
|
23549
|
+
list: (taskId) => listGitRefs(taskId, store),
|
|
23550
|
+
find: (ref) => findGitRefs(ref, store)
|
|
23551
|
+
},
|
|
23541
23552
|
projects: {
|
|
23542
23553
|
create: (input, context) => createProject2(input, store, context),
|
|
23543
23554
|
get: (id) => store.get("projects", id),
|
|
@@ -23558,7 +23569,9 @@ function createPostgresTodosStorageAdapter(options) {
|
|
|
23558
23569
|
get: (id) => store.get("agents", id),
|
|
23559
23570
|
getByName: async (name) => (await store.list("agents")).find((agent) => agent.name === name) ?? null,
|
|
23560
23571
|
list: async (options2) => (await store.list("agents")).filter((agent) => options2?.include_archived || agent.status !== "archived").sort((a, b) => a.name.localeCompare(b.name)),
|
|
23561
|
-
update: (id, input) => updateAgent2(id, input, store)
|
|
23572
|
+
update: (id, input) => updateAgent2(id, input, store),
|
|
23573
|
+
heartbeat: (idOrName, context) => heartbeatAgent(idOrName, store, context),
|
|
23574
|
+
release: (idOrName, sessionId, context) => releaseAgent2(idOrName, sessionId, store, context)
|
|
23562
23575
|
},
|
|
23563
23576
|
taskLists: {
|
|
23564
23577
|
create: (input, context) => createTaskList2(input, store, context),
|
|
@@ -24089,6 +24102,53 @@ async function addVerification(input, store, context) {
|
|
|
24089
24102
|
async function listVerifications(taskId, store) {
|
|
24090
24103
|
return (await store.list("verifications")).filter((verification) => verification.task_id === taskId).sort((a, b) => b.run_at.localeCompare(a.run_at));
|
|
24091
24104
|
}
|
|
24105
|
+
async function addCommit(input, store, context) {
|
|
24106
|
+
if (!await store.get("tasks", input.task_id))
|
|
24107
|
+
throw new Error(`Task not found: ${input.task_id}`);
|
|
24108
|
+
const timestamp2 = new Date().toISOString();
|
|
24109
|
+
const commit = {
|
|
24110
|
+
id: randomUUID3(),
|
|
24111
|
+
task_id: input.task_id,
|
|
24112
|
+
sha: input.sha,
|
|
24113
|
+
message: input.message ?? null,
|
|
24114
|
+
author: input.author ?? null,
|
|
24115
|
+
files_changed: input.files_changed ?? null,
|
|
24116
|
+
created_at: timestamp2
|
|
24117
|
+
};
|
|
24118
|
+
await store.upsert("commits", { ...commit, updated_at: timestamp2 }, context);
|
|
24119
|
+
return commit;
|
|
24120
|
+
}
|
|
24121
|
+
async function listCommits(taskId, store) {
|
|
24122
|
+
return (await store.list("commits")).filter((commit) => commit.task_id === taskId).sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
24123
|
+
}
|
|
24124
|
+
async function findCommit(sha, store) {
|
|
24125
|
+
const matches = (await store.list("commits")).filter((commit) => commit.sha === sha || commit.sha.startsWith(sha) || sha.startsWith(commit.sha)).sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
24126
|
+
return matches[0] ?? null;
|
|
24127
|
+
}
|
|
24128
|
+
async function addGitRef(input, store, context) {
|
|
24129
|
+
if (!await store.get("tasks", input.task_id))
|
|
24130
|
+
throw new Error(`Task not found: ${input.task_id}`);
|
|
24131
|
+
const timestamp2 = new Date().toISOString();
|
|
24132
|
+
const gitRef = {
|
|
24133
|
+
id: randomUUID3(),
|
|
24134
|
+
task_id: input.task_id,
|
|
24135
|
+
ref_type: input.ref_type,
|
|
24136
|
+
name: input.name,
|
|
24137
|
+
url: input.url ?? null,
|
|
24138
|
+
provider: input.provider ?? null,
|
|
24139
|
+
metadata: input.metadata ?? {},
|
|
24140
|
+
created_at: timestamp2,
|
|
24141
|
+
updated_at: timestamp2
|
|
24142
|
+
};
|
|
24143
|
+
await store.upsert("refs", gitRef, context);
|
|
24144
|
+
return gitRef;
|
|
24145
|
+
}
|
|
24146
|
+
async function listGitRefs(taskId, store) {
|
|
24147
|
+
return (await store.list("refs")).filter((ref) => ref.task_id === taskId).sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
24148
|
+
}
|
|
24149
|
+
async function findGitRefs(ref, store) {
|
|
24150
|
+
return (await store.list("refs")).filter((r) => r.name === ref).sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
24151
|
+
}
|
|
24092
24152
|
var TASK_ORDER_BY = "ORDER BY CASE payload->>'priority' WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END ASC, payload->>'created_at' ASC, payload->>'id' ASC";
|
|
24093
24153
|
function toFilterArray(value) {
|
|
24094
24154
|
return Array.isArray(value) ? value : [value];
|
|
@@ -24236,6 +24296,28 @@ async function updateAgent2(id, input, store) {
|
|
|
24236
24296
|
last_seen_at: new Date().toISOString()
|
|
24237
24297
|
});
|
|
24238
24298
|
}
|
|
24299
|
+
async function resolveAgent(idOrName, store) {
|
|
24300
|
+
const byId = await store.get("agents", idOrName);
|
|
24301
|
+
if (byId)
|
|
24302
|
+
return byId;
|
|
24303
|
+
return (await store.list("agents")).find((agent) => agent.name === idOrName) ?? null;
|
|
24304
|
+
}
|
|
24305
|
+
async function heartbeatAgent(idOrName, store, context) {
|
|
24306
|
+
const agent = await resolveAgent(idOrName, store);
|
|
24307
|
+
if (!agent)
|
|
24308
|
+
return null;
|
|
24309
|
+
return store.upsert("agents", { ...agent, last_seen_at: new Date().toISOString() }, context);
|
|
24310
|
+
}
|
|
24311
|
+
async function releaseAgent2(idOrName, sessionId, store, context) {
|
|
24312
|
+
const agent = await resolveAgent(idOrName, store);
|
|
24313
|
+
if (!agent)
|
|
24314
|
+
return null;
|
|
24315
|
+
if (sessionId && agent.session_id && agent.session_id !== sessionId) {
|
|
24316
|
+
return { agent, released: false };
|
|
24317
|
+
}
|
|
24318
|
+
const updated = await store.upsert("agents", { ...agent, session_id: null, last_seen_at: new Date().toISOString() }, context);
|
|
24319
|
+
return { agent: updated, released: true };
|
|
24320
|
+
}
|
|
24239
24321
|
async function createTaskList2(input, store, context) {
|
|
24240
24322
|
const timestamp2 = new Date().toISOString();
|
|
24241
24323
|
return store.upsert("task_lists", {
|
|
@@ -31316,7 +31398,7 @@ function resolveRun(parsed, db) {
|
|
|
31316
31398
|
}
|
|
31317
31399
|
return resolution;
|
|
31318
31400
|
}
|
|
31319
|
-
function
|
|
31401
|
+
function resolveAgent2(parsed, db) {
|
|
31320
31402
|
const resolution = blankResolution(parsed);
|
|
31321
31403
|
const id = resolvePartialId(db, "agents", parsed.target);
|
|
31322
31404
|
const agent = id ? getAgent(id, db) : getAgentByName(parsed.target, db);
|
|
@@ -31353,7 +31435,7 @@ function resolveTask(parsed, db) {
|
|
|
31353
31435
|
function resolveUnknown(parsed, workspace, db, maxSymbolMatches) {
|
|
31354
31436
|
const attempts = [
|
|
31355
31437
|
() => resolveTask({ ...parsed, kind: "task" }, db),
|
|
31356
|
-
() =>
|
|
31438
|
+
() => resolveAgent2({ ...parsed, kind: "agent" }, db),
|
|
31357
31439
|
() => resolvePlan({ ...parsed, kind: "plan" }, db),
|
|
31358
31440
|
() => resolveSymbol({ ...parsed, kind: "symbol" }, workspace, maxSymbolMatches)
|
|
31359
31441
|
];
|
|
@@ -31388,7 +31470,7 @@ function resolveMentions(input, db) {
|
|
|
31388
31470
|
case "run":
|
|
31389
31471
|
return resolveRun(parsed, d);
|
|
31390
31472
|
case "agent":
|
|
31391
|
-
return
|
|
31473
|
+
return resolveAgent2(parsed, d);
|
|
31392
31474
|
case "task":
|
|
31393
31475
|
return resolveTask(parsed, d);
|
|
31394
31476
|
default:
|
|
@@ -42206,7 +42288,7 @@ function resolveProjectId(value, db) {
|
|
|
42206
42288
|
return null;
|
|
42207
42289
|
return resolvePartialId(db, "projects", value) || value;
|
|
42208
42290
|
}
|
|
42209
|
-
function
|
|
42291
|
+
function resolveAgent3(agentId, db) {
|
|
42210
42292
|
return db.query("SELECT id, name FROM agents WHERE id = ? OR LOWER(name) = LOWER(?)").get(agentId, agentId);
|
|
42211
42293
|
}
|
|
42212
42294
|
function agentTaskWhere(agent, options, db) {
|
|
@@ -42250,7 +42332,7 @@ function scoreHandoffs(created, withTaskRefs, withBlockers) {
|
|
|
42250
42332
|
}
|
|
42251
42333
|
function getAgentReliabilityScorecard(agentId, options = {}, db) {
|
|
42252
42334
|
const d = db || getDatabase();
|
|
42253
|
-
const agent =
|
|
42335
|
+
const agent = resolveAgent3(agentId, d);
|
|
42254
42336
|
if (!agent)
|
|
42255
42337
|
return null;
|
|
42256
42338
|
const generatedAt = now();
|
|
@@ -42419,7 +42501,7 @@ function getAgentReliabilityScorecard(agentId, options = {}, db) {
|
|
|
42419
42501
|
}
|
|
42420
42502
|
function listAgentReliabilityScorecards(options = {}, db) {
|
|
42421
42503
|
const d = db || getDatabase();
|
|
42422
|
-
const agents = options.agent_id ?
|
|
42504
|
+
const agents = options.agent_id ? resolveAgent3(options.agent_id, d) ? [resolveAgent3(options.agent_id, d)] : [] : d.query("SELECT id, name FROM agents ORDER BY name").all();
|
|
42423
42505
|
const limit = Number.isFinite(options.limit) && options.limit > 0 ? Math.min(Math.floor(options.limit), 500) : 50;
|
|
42424
42506
|
return agents.map((agent) => getAgentReliabilityScorecard(agent.id, options, d)).filter((scorecard) => Boolean(scorecard)).filter((scorecard) => {
|
|
42425
42507
|
const signals = scorecard.signals;
|
package/dist/mcp/index.js
CHANGED
|
@@ -22870,6 +22870,18 @@ async function cloudRegisterAgent(client, input) {
|
|
|
22870
22870
|
}
|
|
22871
22871
|
return raw;
|
|
22872
22872
|
}
|
|
22873
|
+
async function cloudHeartbeatAgent(client, idOrName) {
|
|
22874
|
+
const raw = await client.transport.post(`/agents/${encodeURIComponent(idOrName)}/heartbeat`, {});
|
|
22875
|
+
if (raw && typeof raw === "object" && "agent" in raw) {
|
|
22876
|
+
return raw.agent;
|
|
22877
|
+
}
|
|
22878
|
+
return raw ?? null;
|
|
22879
|
+
}
|
|
22880
|
+
async function cloudReleaseAgent(client, idOrName, sessionId) {
|
|
22881
|
+
const raw = await client.transport.post(`/agents/${encodeURIComponent(idOrName)}/release`, sessionId ? { session_id: sessionId } : {});
|
|
22882
|
+
const env = raw ?? {};
|
|
22883
|
+
return { agent: env.agent ?? null, released: env.released !== false };
|
|
22884
|
+
}
|
|
22873
22885
|
var _cache;
|
|
22874
22886
|
var init_cloud_router = __esm(() => {
|
|
22875
22887
|
init_storage();
|
|
@@ -44496,6 +44508,19 @@ ID: ${updated.id}${taskNote}`
|
|
|
44496
44508
|
agent_id: exports_external.string().describe("Your agent ID or name.")
|
|
44497
44509
|
}, async ({ agent_id }) => {
|
|
44498
44510
|
try {
|
|
44511
|
+
const cloud = getTodosCloudClient();
|
|
44512
|
+
if (cloud) {
|
|
44513
|
+
const a = await cloudHeartbeatAgent(cloud, agent_id);
|
|
44514
|
+
if (!a) {
|
|
44515
|
+
return { content: [{ type: "text", text: `Agent not found: ${agent_id}` }], isError: true };
|
|
44516
|
+
}
|
|
44517
|
+
return {
|
|
44518
|
+
content: [{
|
|
44519
|
+
type: "text",
|
|
44520
|
+
text: `Heartbeat: ${a.name} (${a.id}) \u2014 last_seen_at updated to ${a.last_seen_at}`
|
|
44521
|
+
}]
|
|
44522
|
+
};
|
|
44523
|
+
}
|
|
44499
44524
|
const agent = getAgent(agent_id) || getAgentByName(agent_id);
|
|
44500
44525
|
if (!agent) {
|
|
44501
44526
|
return { content: [{ type: "text", text: `Agent not found: ${agent_id}` }], isError: true };
|
|
@@ -44518,6 +44543,22 @@ ID: ${updated.id}${taskNote}`
|
|
|
44518
44543
|
session_id: exports_external.string().optional().describe("Your session ID \u2014 if provided, release only succeeds if it matches (prevents other sessions from releasing your agent).")
|
|
44519
44544
|
}, async ({ agent_id, session_id }) => {
|
|
44520
44545
|
try {
|
|
44546
|
+
const cloud = getTodosCloudClient();
|
|
44547
|
+
if (cloud) {
|
|
44548
|
+
const result = await cloudReleaseAgent(cloud, agent_id, session_id);
|
|
44549
|
+
if (!result.agent) {
|
|
44550
|
+
return { content: [{ type: "text", text: `Agent not found: ${agent_id}` }], isError: true };
|
|
44551
|
+
}
|
|
44552
|
+
if (!result.released) {
|
|
44553
|
+
return { content: [{ type: "text", text: `Release denied: session_id does not match agent's current session.` }], isError: true };
|
|
44554
|
+
}
|
|
44555
|
+
return {
|
|
44556
|
+
content: [{
|
|
44557
|
+
type: "text",
|
|
44558
|
+
text: `Agent released: ${result.agent.name} (${result.agent.id}) \u2014 session cleared, name is now available.`
|
|
44559
|
+
}]
|
|
44560
|
+
};
|
|
44561
|
+
}
|
|
44521
44562
|
const agent = getAgent(agent_id) || getAgentByName(agent_id);
|
|
44522
44563
|
if (!agent) {
|
|
44523
44564
|
return { content: [{ type: "text", text: `Agent not found: ${agent_id}` }], isError: true };
|
|
@@ -48135,12 +48176,23 @@ function createPostgresTodosStorageAdapter(options) {
|
|
|
48135
48176
|
dependencies: {
|
|
48136
48177
|
add: (taskId, dependsOn, context) => addDependency2(taskId, dependsOn, store, context),
|
|
48137
48178
|
remove: (taskId, dependsOn) => removeDependency2(taskId, dependsOn, store),
|
|
48138
|
-
list: (taskId) => listDependencies(taskId, store)
|
|
48179
|
+
list: (taskId) => listDependencies(taskId, store),
|
|
48180
|
+
listAll: () => store.list("dependencies")
|
|
48139
48181
|
},
|
|
48140
48182
|
verifications: {
|
|
48141
48183
|
add: (input, context) => addVerification(input, store, context),
|
|
48142
48184
|
list: (taskId) => listVerifications(taskId, store)
|
|
48143
48185
|
},
|
|
48186
|
+
commits: {
|
|
48187
|
+
add: (input, context) => addCommit(input, store, context),
|
|
48188
|
+
list: (taskId) => listCommits(taskId, store),
|
|
48189
|
+
find: (sha) => findCommit(sha, store)
|
|
48190
|
+
},
|
|
48191
|
+
gitRefs: {
|
|
48192
|
+
add: (input, context) => addGitRef(input, store, context),
|
|
48193
|
+
list: (taskId) => listGitRefs(taskId, store),
|
|
48194
|
+
find: (ref) => findGitRefs(ref, store)
|
|
48195
|
+
},
|
|
48144
48196
|
projects: {
|
|
48145
48197
|
create: (input, context) => createProject2(input, store, context),
|
|
48146
48198
|
get: (id) => store.get("projects", id),
|
|
@@ -48161,7 +48213,9 @@ function createPostgresTodosStorageAdapter(options) {
|
|
|
48161
48213
|
get: (id) => store.get("agents", id),
|
|
48162
48214
|
getByName: async (name) => (await store.list("agents")).find((agent) => agent.name === name) ?? null,
|
|
48163
48215
|
list: async (options2) => (await store.list("agents")).filter((agent) => options2?.include_archived || agent.status !== "archived").sort((a, b) => a.name.localeCompare(b.name)),
|
|
48164
|
-
update: (id, input) => updateAgent2(id, input, store)
|
|
48216
|
+
update: (id, input) => updateAgent2(id, input, store),
|
|
48217
|
+
heartbeat: (idOrName, context) => heartbeatAgent(idOrName, store, context),
|
|
48218
|
+
release: (idOrName, sessionId, context) => releaseAgent2(idOrName, sessionId, store, context)
|
|
48165
48219
|
},
|
|
48166
48220
|
taskLists: {
|
|
48167
48221
|
create: (input, context) => createTaskList2(input, store, context),
|
|
@@ -48691,6 +48745,53 @@ async function addVerification(input, store, context) {
|
|
|
48691
48745
|
async function listVerifications(taskId, store) {
|
|
48692
48746
|
return (await store.list("verifications")).filter((verification) => verification.task_id === taskId).sort((a, b) => b.run_at.localeCompare(a.run_at));
|
|
48693
48747
|
}
|
|
48748
|
+
async function addCommit(input, store, context) {
|
|
48749
|
+
if (!await store.get("tasks", input.task_id))
|
|
48750
|
+
throw new Error(`Task not found: ${input.task_id}`);
|
|
48751
|
+
const timestamp3 = new Date().toISOString();
|
|
48752
|
+
const commit = {
|
|
48753
|
+
id: randomUUID3(),
|
|
48754
|
+
task_id: input.task_id,
|
|
48755
|
+
sha: input.sha,
|
|
48756
|
+
message: input.message ?? null,
|
|
48757
|
+
author: input.author ?? null,
|
|
48758
|
+
files_changed: input.files_changed ?? null,
|
|
48759
|
+
created_at: timestamp3
|
|
48760
|
+
};
|
|
48761
|
+
await store.upsert("commits", { ...commit, updated_at: timestamp3 }, context);
|
|
48762
|
+
return commit;
|
|
48763
|
+
}
|
|
48764
|
+
async function listCommits(taskId, store) {
|
|
48765
|
+
return (await store.list("commits")).filter((commit) => commit.task_id === taskId).sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
48766
|
+
}
|
|
48767
|
+
async function findCommit(sha, store) {
|
|
48768
|
+
const matches = (await store.list("commits")).filter((commit) => commit.sha === sha || commit.sha.startsWith(sha) || sha.startsWith(commit.sha)).sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
48769
|
+
return matches[0] ?? null;
|
|
48770
|
+
}
|
|
48771
|
+
async function addGitRef(input, store, context) {
|
|
48772
|
+
if (!await store.get("tasks", input.task_id))
|
|
48773
|
+
throw new Error(`Task not found: ${input.task_id}`);
|
|
48774
|
+
const timestamp3 = new Date().toISOString();
|
|
48775
|
+
const gitRef = {
|
|
48776
|
+
id: randomUUID3(),
|
|
48777
|
+
task_id: input.task_id,
|
|
48778
|
+
ref_type: input.ref_type,
|
|
48779
|
+
name: input.name,
|
|
48780
|
+
url: input.url ?? null,
|
|
48781
|
+
provider: input.provider ?? null,
|
|
48782
|
+
metadata: input.metadata ?? {},
|
|
48783
|
+
created_at: timestamp3,
|
|
48784
|
+
updated_at: timestamp3
|
|
48785
|
+
};
|
|
48786
|
+
await store.upsert("refs", gitRef, context);
|
|
48787
|
+
return gitRef;
|
|
48788
|
+
}
|
|
48789
|
+
async function listGitRefs(taskId, store) {
|
|
48790
|
+
return (await store.list("refs")).filter((ref) => ref.task_id === taskId).sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
48791
|
+
}
|
|
48792
|
+
async function findGitRefs(ref, store) {
|
|
48793
|
+
return (await store.list("refs")).filter((r) => r.name === ref).sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
48794
|
+
}
|
|
48694
48795
|
function toFilterArray(value) {
|
|
48695
48796
|
return Array.isArray(value) ? value : [value];
|
|
48696
48797
|
}
|
|
@@ -48837,6 +48938,28 @@ async function updateAgent2(id, input, store) {
|
|
|
48837
48938
|
last_seen_at: new Date().toISOString()
|
|
48838
48939
|
});
|
|
48839
48940
|
}
|
|
48941
|
+
async function resolveAgent3(idOrName, store) {
|
|
48942
|
+
const byId = await store.get("agents", idOrName);
|
|
48943
|
+
if (byId)
|
|
48944
|
+
return byId;
|
|
48945
|
+
return (await store.list("agents")).find((agent) => agent.name === idOrName) ?? null;
|
|
48946
|
+
}
|
|
48947
|
+
async function heartbeatAgent(idOrName, store, context) {
|
|
48948
|
+
const agent = await resolveAgent3(idOrName, store);
|
|
48949
|
+
if (!agent)
|
|
48950
|
+
return null;
|
|
48951
|
+
return store.upsert("agents", { ...agent, last_seen_at: new Date().toISOString() }, context);
|
|
48952
|
+
}
|
|
48953
|
+
async function releaseAgent2(idOrName, sessionId, store, context) {
|
|
48954
|
+
const agent = await resolveAgent3(idOrName, store);
|
|
48955
|
+
if (!agent)
|
|
48956
|
+
return null;
|
|
48957
|
+
if (sessionId && agent.session_id && agent.session_id !== sessionId) {
|
|
48958
|
+
return { agent, released: false };
|
|
48959
|
+
}
|
|
48960
|
+
const updated = await store.upsert("agents", { ...agent, session_id: null, last_seen_at: new Date().toISOString() }, context);
|
|
48961
|
+
return { agent: updated, released: true };
|
|
48962
|
+
}
|
|
48840
48963
|
async function createTaskList2(input, store, context) {
|
|
48841
48964
|
const timestamp3 = new Date().toISOString();
|
|
48842
48965
|
return store.upsert("task_lists", {
|
|
@@ -49721,6 +49844,70 @@ async function handleV1Request(req, url) {
|
|
|
49721
49844
|
}
|
|
49722
49845
|
return error(405, `method ${method} not allowed on /v1/tasks/:id/verifications`);
|
|
49723
49846
|
}
|
|
49847
|
+
if (action === "commits") {
|
|
49848
|
+
if (!store.commits)
|
|
49849
|
+
return error(501, "commit links are not supported by this storage backend");
|
|
49850
|
+
if (method === "GET") {
|
|
49851
|
+
if (!await store.tasks.get(id))
|
|
49852
|
+
return error(404, "task not found");
|
|
49853
|
+
const commits = await store.commits.list(id);
|
|
49854
|
+
return json2({ commits, count: commits.length });
|
|
49855
|
+
}
|
|
49856
|
+
if (method === "POST") {
|
|
49857
|
+
const body2 = await readJson(req) ?? {};
|
|
49858
|
+
if (typeof body2.sha !== "string" || !body2.sha.trim())
|
|
49859
|
+
return error(400, "sha is required");
|
|
49860
|
+
try {
|
|
49861
|
+
const commit = await store.commits.add({
|
|
49862
|
+
task_id: id,
|
|
49863
|
+
sha: body2.sha,
|
|
49864
|
+
message: body2.message,
|
|
49865
|
+
author: body2.author,
|
|
49866
|
+
files_changed: Array.isArray(body2.files_changed) ? body2.files_changed : undefined
|
|
49867
|
+
}, contextFromPrincipal(principal));
|
|
49868
|
+
return json2({ commit }, 201);
|
|
49869
|
+
} catch (e) {
|
|
49870
|
+
const msg = e.message || "";
|
|
49871
|
+
if (msg.includes("not found"))
|
|
49872
|
+
return error(404, msg);
|
|
49873
|
+
throw e;
|
|
49874
|
+
}
|
|
49875
|
+
}
|
|
49876
|
+
return error(405, `method ${method} not allowed on /v1/tasks/:id/commits`);
|
|
49877
|
+
}
|
|
49878
|
+
if (action === "refs") {
|
|
49879
|
+
if (!store.gitRefs)
|
|
49880
|
+
return error(501, "git ref links are not supported by this storage backend");
|
|
49881
|
+
if (method === "GET") {
|
|
49882
|
+
if (!await store.tasks.get(id))
|
|
49883
|
+
return error(404, "task not found");
|
|
49884
|
+
const refs = await store.gitRefs.list(id);
|
|
49885
|
+
return json2({ refs, count: refs.length });
|
|
49886
|
+
}
|
|
49887
|
+
if (method === "POST") {
|
|
49888
|
+
const body2 = await readJson(req) ?? {};
|
|
49889
|
+
const refType = body2.ref_type === "pull_request" || body2.ref_type === "branch" ? body2.ref_type : "branch";
|
|
49890
|
+
if (typeof body2.name !== "string" || !body2.name.trim())
|
|
49891
|
+
return error(400, "name is required");
|
|
49892
|
+
try {
|
|
49893
|
+
const ref = await store.gitRefs.add({
|
|
49894
|
+
task_id: id,
|
|
49895
|
+
ref_type: refType,
|
|
49896
|
+
name: body2.name,
|
|
49897
|
+
url: body2.url,
|
|
49898
|
+
provider: body2.provider,
|
|
49899
|
+
metadata: body2.metadata
|
|
49900
|
+
}, contextFromPrincipal(principal));
|
|
49901
|
+
return json2({ ref }, 201);
|
|
49902
|
+
} catch (e) {
|
|
49903
|
+
const msg = e.message || "";
|
|
49904
|
+
if (msg.includes("not found"))
|
|
49905
|
+
return error(404, msg);
|
|
49906
|
+
throw e;
|
|
49907
|
+
}
|
|
49908
|
+
}
|
|
49909
|
+
return error(405, `method ${method} not allowed on /v1/tasks/:id/refs`);
|
|
49910
|
+
}
|
|
49724
49911
|
const body = await readJson(req) ?? {};
|
|
49725
49912
|
const agentId = body.agent_id || principal.agent || "todos-serve";
|
|
49726
49913
|
if (action === "start" && method === "POST") {
|
|
@@ -49833,11 +50020,87 @@ async function handleV1Request(req, url) {
|
|
|
49833
50020
|
}
|
|
49834
50021
|
return json2({ agent: result }, 201);
|
|
49835
50022
|
}
|
|
50023
|
+
if (id && action === "heartbeat") {
|
|
50024
|
+
if (method !== "POST")
|
|
50025
|
+
return error(405, `method ${method} not allowed on /v1/agents/:id/heartbeat`);
|
|
50026
|
+
if (typeof store.agents.heartbeat !== "function") {
|
|
50027
|
+
return error(501, "agent heartbeat is not supported by this storage backend");
|
|
50028
|
+
}
|
|
50029
|
+
const agent = await store.agents.heartbeat(id, contextFromPrincipal(principal));
|
|
50030
|
+
return agent ? json2({ agent }) : error(404, "agent not found");
|
|
50031
|
+
}
|
|
50032
|
+
if (id && action === "release") {
|
|
50033
|
+
if (method !== "POST")
|
|
50034
|
+
return error(405, `method ${method} not allowed on /v1/agents/:id/release`);
|
|
50035
|
+
if (typeof store.agents.release !== "function") {
|
|
50036
|
+
return error(501, "agent release is not supported by this storage backend");
|
|
50037
|
+
}
|
|
50038
|
+
const body = await readJson(req) ?? {};
|
|
50039
|
+
const result = await store.agents.release(id, body.session_id, contextFromPrincipal(principal));
|
|
50040
|
+
if (!result)
|
|
50041
|
+
return error(404, "agent not found");
|
|
50042
|
+
if (!result.released) {
|
|
50043
|
+
return error(409, "release denied: session_id does not match agent's current session", { released: false });
|
|
50044
|
+
}
|
|
50045
|
+
return json2({ agent: result.agent, released: true });
|
|
50046
|
+
}
|
|
49836
50047
|
if (id && method === "GET") {
|
|
49837
50048
|
const agent = await store.agents.get(id);
|
|
49838
50049
|
return agent ? json2({ agent }) : error(404, "agent not found");
|
|
49839
50050
|
}
|
|
49840
50051
|
}
|
|
50052
|
+
if (resource === "activity" && !id) {
|
|
50053
|
+
if (method !== "GET")
|
|
50054
|
+
return error(405, `method ${method} not allowed on /v1/activity`);
|
|
50055
|
+
const limitParam = url.searchParams.get("limit");
|
|
50056
|
+
const limit = limitParam ? Math.max(1, Math.min(1e4, Number(limitParam) || 50)) : 50;
|
|
50057
|
+
const activity = await store.audit.getRecentActivity(limit);
|
|
50058
|
+
return json2({ activity, count: activity.length });
|
|
50059
|
+
}
|
|
50060
|
+
if (resource === "task-lists" && !id) {
|
|
50061
|
+
if (method !== "GET")
|
|
50062
|
+
return error(405, `method ${method} not allowed on /v1/task-lists`);
|
|
50063
|
+
const projectId = url.searchParams.get("project_id") ?? undefined;
|
|
50064
|
+
const taskLists = await store.taskLists.list(projectId);
|
|
50065
|
+
return json2({ task_lists: taskLists, count: taskLists.length });
|
|
50066
|
+
}
|
|
50067
|
+
if (resource === "dependencies" && !id) {
|
|
50068
|
+
if (method !== "GET")
|
|
50069
|
+
return error(405, `method ${method} not allowed on /v1/dependencies`);
|
|
50070
|
+
if (typeof store.dependencies?.listAll !== "function") {
|
|
50071
|
+
return error(501, "dependency edge listing is not supported by this storage backend");
|
|
50072
|
+
}
|
|
50073
|
+
const dependencies = await store.dependencies.listAll();
|
|
50074
|
+
return json2({ dependencies, count: dependencies.length });
|
|
50075
|
+
}
|
|
50076
|
+
if (resource === "commits" && id) {
|
|
50077
|
+
if (method !== "GET")
|
|
50078
|
+
return error(405, `method ${method} not allowed on /v1/commits/:sha`);
|
|
50079
|
+
if (!store.commits)
|
|
50080
|
+
return error(501, "commit links are not supported by this storage backend");
|
|
50081
|
+
const commit = await store.commits.find(id);
|
|
50082
|
+
return json2({ commit: commit ?? null });
|
|
50083
|
+
}
|
|
50084
|
+
if (resource === "refs" && id) {
|
|
50085
|
+
if (method !== "GET")
|
|
50086
|
+
return error(405, `method ${method} not allowed on /v1/refs/:ref`);
|
|
50087
|
+
if (!store.gitRefs)
|
|
50088
|
+
return error(501, "git ref links are not supported by this storage backend");
|
|
50089
|
+
const refs = await store.gitRefs.find(id);
|
|
50090
|
+
return json2({ refs, count: refs.length });
|
|
50091
|
+
}
|
|
50092
|
+
if (resource === "next" && !id) {
|
|
50093
|
+
if (method !== "GET")
|
|
50094
|
+
return error(405, `method ${method} not allowed on /v1/next`);
|
|
50095
|
+
const agent = url.searchParams.get("agent") ?? undefined;
|
|
50096
|
+
const filters = {
|
|
50097
|
+
...url.searchParams.get("project_id") ? { project_id: url.searchParams.get("project_id") } : {},
|
|
50098
|
+
...url.searchParams.get("task_list_id") ? { task_list_id: url.searchParams.get("task_list_id") } : {},
|
|
50099
|
+
...url.searchParams.get("plan_id") ? { plan_id: url.searchParams.get("plan_id") } : {}
|
|
50100
|
+
};
|
|
50101
|
+
const task2 = await store.tasks.getNext(agent, filters);
|
|
50102
|
+
return json2({ task: task2 ?? null });
|
|
50103
|
+
}
|
|
49841
50104
|
if (resource === "stats" && method === "GET") {
|
|
49842
50105
|
const [tasks, tasksAll, projects] = await Promise.all([
|
|
49843
50106
|
store.tasks.count(),
|
|
@@ -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,CA+ejJ"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "@hasna/todos",
|
|
3
|
-
"packageVersion": "0.11.
|
|
3
|
+
"packageVersion": "0.11.85",
|
|
4
4
|
"repository": "https://github.com/hasna/todos.git",
|
|
5
|
-
"gitCommit": "
|
|
6
|
-
"generatedAt": "2026-07-
|
|
5
|
+
"gitCommit": "51d25377a0dd06b9a3f535abe61f49c881b49bd3",
|
|
6
|
+
"generatedAt": "2026-07-08T16:10:52.301Z"
|
|
7
7
|
}
|