@hasna/todos 0.10.1 → 0.10.3
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 +143 -73
- package/dist/db/agents.d.ts +8 -1
- package/dist/db/agents.d.ts.map +1 -1
- package/dist/db/database.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -24
- package/dist/lib/config.d.ts +2 -7
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/mcp/index.js +141 -70
- package/dist/server/index.js +38 -41
- package/dist/types/index.d.ts +3 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2212,6 +2212,7 @@ function ensureSchema(db) {
|
|
|
2212
2212
|
CREATE TABLE agents (
|
|
2213
2213
|
id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, description TEXT,
|
|
2214
2214
|
role TEXT DEFAULT 'agent', permissions TEXT DEFAULT '["*"]',
|
|
2215
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'archived')),
|
|
2215
2216
|
metadata TEXT DEFAULT '{}',
|
|
2216
2217
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
2217
2218
|
last_seen_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
@@ -2870,6 +2871,11 @@ var init_database = __esm(() => {
|
|
|
2870
2871
|
`
|
|
2871
2872
|
ALTER TABLE agents ADD COLUMN capabilities TEXT DEFAULT '[]';
|
|
2872
2873
|
INSERT OR IGNORE INTO _migrations (id) VALUES (29);
|
|
2874
|
+
`,
|
|
2875
|
+
`
|
|
2876
|
+
ALTER TABLE agents ADD COLUMN status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'archived'));
|
|
2877
|
+
CREATE INDEX IF NOT EXISTS idx_agents_status ON agents(status);
|
|
2878
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (30);
|
|
2873
2879
|
`
|
|
2874
2880
|
];
|
|
2875
2881
|
});
|
|
@@ -3206,8 +3212,7 @@ __export(exports_config, {
|
|
|
3206
3212
|
getCompletionGuardConfig: () => getCompletionGuardConfig,
|
|
3207
3213
|
getAgentTasksDir: () => getAgentTasksDir,
|
|
3208
3214
|
getAgentTaskListId: () => getAgentTaskListId,
|
|
3209
|
-
getAgentPoolForProject: () => getAgentPoolForProject
|
|
3210
|
-
DEFAULT_AGENT_POOL: () => DEFAULT_AGENT_POOL
|
|
3215
|
+
getAgentPoolForProject: () => getAgentPoolForProject
|
|
3211
3216
|
});
|
|
3212
3217
|
import { existsSync as existsSync3 } from "fs";
|
|
3213
3218
|
import { join as join3 } from "path";
|
|
@@ -3267,7 +3272,7 @@ function getAgentPoolForProject(workingDir) {
|
|
|
3267
3272
|
return config.project_pools[bestKey];
|
|
3268
3273
|
}
|
|
3269
3274
|
}
|
|
3270
|
-
return config.agent_pool ||
|
|
3275
|
+
return config.agent_pool || null;
|
|
3271
3276
|
}
|
|
3272
3277
|
function getCompletionGuardConfig(projectPath) {
|
|
3273
3278
|
const config = loadConfig();
|
|
@@ -3277,26 +3282,9 @@ function getCompletionGuardConfig(projectPath) {
|
|
|
3277
3282
|
}
|
|
3278
3283
|
return global;
|
|
3279
3284
|
}
|
|
3280
|
-
var
|
|
3285
|
+
var cached = null, GUARD_DEFAULTS;
|
|
3281
3286
|
var init_config = __esm(() => {
|
|
3282
3287
|
init_sync_utils();
|
|
3283
|
-
DEFAULT_AGENT_POOL = [
|
|
3284
|
-
"maximus",
|
|
3285
|
-
"cassius",
|
|
3286
|
-
"aurelius",
|
|
3287
|
-
"brutus",
|
|
3288
|
-
"titus",
|
|
3289
|
-
"nero",
|
|
3290
|
-
"cicero",
|
|
3291
|
-
"seneca",
|
|
3292
|
-
"cato",
|
|
3293
|
-
"julius",
|
|
3294
|
-
"marcus",
|
|
3295
|
-
"lucius",
|
|
3296
|
-
"quintus",
|
|
3297
|
-
"gaius",
|
|
3298
|
-
"publius"
|
|
3299
|
-
];
|
|
3300
3288
|
GUARD_DEFAULTS = {
|
|
3301
3289
|
enabled: false,
|
|
3302
3290
|
min_work_seconds: 30,
|
|
@@ -4747,6 +4735,7 @@ var exports_agents = {};
|
|
|
4747
4735
|
__export(exports_agents, {
|
|
4748
4736
|
updateAgentActivity: () => updateAgentActivity,
|
|
4749
4737
|
updateAgent: () => updateAgent,
|
|
4738
|
+
unarchiveAgent: () => unarchiveAgent,
|
|
4750
4739
|
registerAgent: () => registerAgent,
|
|
4751
4740
|
matchCapabilities: () => matchCapabilities,
|
|
4752
4741
|
listAgents: () => listAgents,
|
|
@@ -4757,11 +4746,12 @@ __export(exports_agents, {
|
|
|
4757
4746
|
getAvailableNamesFromPool: () => getAvailableNamesFromPool,
|
|
4758
4747
|
getAgentByName: () => getAgentByName,
|
|
4759
4748
|
getAgent: () => getAgent,
|
|
4760
|
-
deleteAgent: () => deleteAgent
|
|
4749
|
+
deleteAgent: () => deleteAgent,
|
|
4750
|
+
archiveAgent: () => archiveAgent
|
|
4761
4751
|
});
|
|
4762
4752
|
function getAvailableNamesFromPool(pool, db) {
|
|
4763
4753
|
const cutoff = new Date(Date.now() - AGENT_ACTIVE_WINDOW_MS).toISOString();
|
|
4764
|
-
const activeNames = new Set(db.query("SELECT name FROM agents WHERE last_seen_at > ?").all(cutoff).map((r) => r.name.toLowerCase()));
|
|
4754
|
+
const activeNames = new Set(db.query("SELECT name FROM agents WHERE status = 'active' AND last_seen_at > ?").all(cutoff).map((r) => r.name.toLowerCase()));
|
|
4765
4755
|
return pool.filter((name) => !activeNames.has(name.toLowerCase()));
|
|
4766
4756
|
}
|
|
4767
4757
|
function shortUuid() {
|
|
@@ -4772,30 +4762,13 @@ function rowToAgent(row) {
|
|
|
4772
4762
|
...row,
|
|
4773
4763
|
permissions: JSON.parse(row.permissions || '["*"]'),
|
|
4774
4764
|
capabilities: JSON.parse(row.capabilities || "[]"),
|
|
4765
|
+
status: row.status || "active",
|
|
4775
4766
|
metadata: JSON.parse(row.metadata || "{}")
|
|
4776
4767
|
};
|
|
4777
4768
|
}
|
|
4778
4769
|
function registerAgent(input, db) {
|
|
4779
4770
|
const d = db || getDatabase();
|
|
4780
4771
|
const normalizedName = input.name.trim().toLowerCase();
|
|
4781
|
-
if (input.pool && input.pool.length > 0) {
|
|
4782
|
-
const poolLower = input.pool.map((n) => n.toLowerCase());
|
|
4783
|
-
if (!poolLower.includes(normalizedName)) {
|
|
4784
|
-
const available = getAvailableNamesFromPool(input.pool, d);
|
|
4785
|
-
const suggestion = available.length > 0 ? available[0] : null;
|
|
4786
|
-
return {
|
|
4787
|
-
conflict: true,
|
|
4788
|
-
pool_violation: true,
|
|
4789
|
-
existing_id: "",
|
|
4790
|
-
existing_name: normalizedName,
|
|
4791
|
-
last_seen_at: "",
|
|
4792
|
-
session_hint: null,
|
|
4793
|
-
working_dir: input.working_dir || null,
|
|
4794
|
-
suggestions: available.slice(0, 5),
|
|
4795
|
-
message: `"${normalizedName}" is not in this project's agent pool [${input.pool.join(", ")}]. ${available.length > 0 ? `Try: ${available.slice(0, 3).join(", ")}` : "No names are currently available \u2014 wait for an active agent to go stale."}${suggestion ? ` Suggested: ${suggestion}` : ""}`
|
|
4796
|
-
};
|
|
4797
|
-
}
|
|
4798
|
-
}
|
|
4799
4772
|
const existing = getAgentByName(normalizedName, d);
|
|
4800
4773
|
if (existing) {
|
|
4801
4774
|
const lastSeenMs = new Date(existing.last_seen_at).getTime();
|
|
@@ -4816,7 +4789,7 @@ function registerAgent(input, db) {
|
|
|
4816
4789
|
message: `Agent "${normalizedName}" is already active (last seen ${minutesAgo}m ago, session ${existing.session_id?.slice(0, 8)}\u2026, dir: ${existing.working_dir ?? "unknown"}). Are you that agent? If so, pass session_id="${existing.session_id}" to reclaim it. Otherwise choose a different name.${suggestions.length > 0 ? ` Available: ${suggestions.slice(0, 3).join(", ")}` : ""}`
|
|
4817
4790
|
};
|
|
4818
4791
|
}
|
|
4819
|
-
const updates = ["last_seen_at = ?"];
|
|
4792
|
+
const updates = ["last_seen_at = ?", "status = 'active'"];
|
|
4820
4793
|
const params = [now()];
|
|
4821
4794
|
if (input.session_id && !sameSession) {
|
|
4822
4795
|
updates.push("session_id = ?");
|
|
@@ -4870,9 +4843,19 @@ function getAgentByName(name, db) {
|
|
|
4870
4843
|
const row = d.query("SELECT * FROM agents WHERE LOWER(name) = ?").get(normalizedName);
|
|
4871
4844
|
return row ? rowToAgent(row) : null;
|
|
4872
4845
|
}
|
|
4873
|
-
function listAgents(db) {
|
|
4874
|
-
|
|
4875
|
-
|
|
4846
|
+
function listAgents(opts, db) {
|
|
4847
|
+
let d;
|
|
4848
|
+
let includeArchived = false;
|
|
4849
|
+
if (opts && typeof opts === "object" && "query" in opts) {
|
|
4850
|
+
d = opts;
|
|
4851
|
+
} else {
|
|
4852
|
+
includeArchived = opts?.include_archived ?? false;
|
|
4853
|
+
d = db || getDatabase();
|
|
4854
|
+
}
|
|
4855
|
+
if (includeArchived) {
|
|
4856
|
+
return d.query("SELECT * FROM agents ORDER BY name").all().map(rowToAgent);
|
|
4857
|
+
}
|
|
4858
|
+
return d.query("SELECT * FROM agents WHERE status = 'active' ORDER BY name").all().map(rowToAgent);
|
|
4876
4859
|
}
|
|
4877
4860
|
function updateAgentActivity(id, db) {
|
|
4878
4861
|
const d = db || getDatabase();
|
|
@@ -4931,7 +4914,17 @@ function updateAgent(id, input, db) {
|
|
|
4931
4914
|
}
|
|
4932
4915
|
function deleteAgent(id, db) {
|
|
4933
4916
|
const d = db || getDatabase();
|
|
4934
|
-
return d.run("
|
|
4917
|
+
return d.run("UPDATE agents SET status = 'archived', last_seen_at = ? WHERE id = ?", [now(), id]).changes > 0;
|
|
4918
|
+
}
|
|
4919
|
+
function archiveAgent(id, db) {
|
|
4920
|
+
const d = db || getDatabase();
|
|
4921
|
+
d.run("UPDATE agents SET status = 'archived', last_seen_at = ? WHERE id = ?", [now(), id]);
|
|
4922
|
+
return getAgent(id, d);
|
|
4923
|
+
}
|
|
4924
|
+
function unarchiveAgent(id, db) {
|
|
4925
|
+
const d = db || getDatabase();
|
|
4926
|
+
d.run("UPDATE agents SET status = 'active', last_seen_at = ? WHERE id = ?", [now(), id]);
|
|
4927
|
+
return getAgent(id, d);
|
|
4935
4928
|
}
|
|
4936
4929
|
function getDirectReports(agentId, db) {
|
|
4937
4930
|
const d = db || getDatabase();
|
|
@@ -10664,13 +10657,15 @@ var init_mcp = __esm(() => {
|
|
|
10664
10657
|
"add_comment",
|
|
10665
10658
|
"get_next_task",
|
|
10666
10659
|
"bootstrap",
|
|
10667
|
-
"get_tasks_changed_since"
|
|
10660
|
+
"get_tasks_changed_since",
|
|
10661
|
+
"heartbeat"
|
|
10668
10662
|
]);
|
|
10669
10663
|
STANDARD_EXCLUDED = new Set([
|
|
10670
10664
|
"get_org_chart",
|
|
10671
10665
|
"set_reports_to",
|
|
10672
10666
|
"rename_agent",
|
|
10673
10667
|
"delete_agent",
|
|
10668
|
+
"unarchive_agent",
|
|
10674
10669
|
"create_webhook",
|
|
10675
10670
|
"list_webhooks",
|
|
10676
10671
|
"delete_webhook",
|
|
@@ -11516,8 +11511,8 @@ ${text}` }] };
|
|
|
11516
11511
|
});
|
|
11517
11512
|
}
|
|
11518
11513
|
if (shouldRegisterTool("register_agent")) {
|
|
11519
|
-
server.tool("register_agent", "Register an agent.
|
|
11520
|
-
name: exports_external.string().describe("Agent name \u2014
|
|
11514
|
+
server.tool("register_agent", "Register an agent. Any name is allowed \u2014 the configured pool is advisory, not enforced. Returns a conflict error if the name is held by a recently-active agent.", {
|
|
11515
|
+
name: exports_external.string().describe("Agent name \u2014 any name is allowed. Use suggest_agent_name to see pool suggestions and avoid conflicts."),
|
|
11521
11516
|
description: exports_external.string().optional(),
|
|
11522
11517
|
capabilities: exports_external.array(exports_external.string()).optional().describe("Agent capabilities/skills for task routing (e.g. ['typescript', 'testing', 'devops'])"),
|
|
11523
11518
|
session_id: exports_external.string().optional().describe("Unique ID for this coding session (e.g. process PID + timestamp, or env var). Used to detect name collisions across sessions. Store it and pass on every register_agent call."),
|
|
@@ -11525,17 +11520,19 @@ ${text}` }] };
|
|
|
11525
11520
|
}, async ({ name, description, capabilities, session_id, working_dir }) => {
|
|
11526
11521
|
try {
|
|
11527
11522
|
const pool = getAgentPoolForProject(working_dir);
|
|
11528
|
-
const result = registerAgent({ name, description, capabilities, session_id, working_dir, pool });
|
|
11523
|
+
const result = registerAgent({ name, description, capabilities, session_id, working_dir, pool: pool || undefined });
|
|
11529
11524
|
if (isAgentConflict(result)) {
|
|
11530
11525
|
const suggestLine = result.suggestions && result.suggestions.length > 0 ? `
|
|
11531
11526
|
Available names: ${result.suggestions.join(", ")}` : "";
|
|
11532
|
-
const hint =
|
|
11527
|
+
const hint = `CONFLICT: ${result.message}${suggestLine}`;
|
|
11533
11528
|
return {
|
|
11534
11529
|
content: [{ type: "text", text: hint }],
|
|
11535
11530
|
isError: true
|
|
11536
11531
|
};
|
|
11537
11532
|
}
|
|
11538
11533
|
const agent = result;
|
|
11534
|
+
const poolLine = pool ? `
|
|
11535
|
+
Pool: [${pool.join(", ")}]` : "";
|
|
11539
11536
|
return {
|
|
11540
11537
|
content: [{
|
|
11541
11538
|
type: "text",
|
|
@@ -11543,8 +11540,7 @@ Available names: ${result.suggestions.join(", ")}` : "";
|
|
|
11543
11540
|
ID: ${agent.id}
|
|
11544
11541
|
Name: ${agent.name}${agent.description ? `
|
|
11545
11542
|
Description: ${agent.description}` : ""}
|
|
11546
|
-
Session: ${agent.session_id ?? "unbound"}
|
|
11547
|
-
Pool: [${pool.join(", ")}]
|
|
11543
|
+
Session: ${agent.session_id ?? "unbound"}${poolLine}
|
|
11548
11544
|
Created: ${agent.created_at}
|
|
11549
11545
|
Last seen: ${agent.last_seen_at}`
|
|
11550
11546
|
}]
|
|
@@ -11555,21 +11551,32 @@ Last seen: ${agent.last_seen_at}`
|
|
|
11555
11551
|
});
|
|
11556
11552
|
}
|
|
11557
11553
|
if (shouldRegisterTool("suggest_agent_name")) {
|
|
11558
|
-
server.tool("suggest_agent_name", "Get available agent names for a project.
|
|
11559
|
-
working_dir: exports_external.string().optional().describe("Your working directory \u2014 used to look up the project's allowed name pool")
|
|
11554
|
+
server.tool("suggest_agent_name", "Get available agent names for a project. Shows configured pool, active agents, and suggestions. If no pool is configured, any name is allowed.", {
|
|
11555
|
+
working_dir: exports_external.string().optional().describe("Your working directory \u2014 used to look up the project's allowed name pool from config")
|
|
11560
11556
|
}, async ({ working_dir }) => {
|
|
11561
11557
|
try {
|
|
11562
11558
|
const pool = getAgentPoolForProject(working_dir);
|
|
11563
|
-
const available = getAvailableNamesFromPool(pool, getDatabase());
|
|
11564
11559
|
const cutoff = new Date(Date.now() - 30 * 60 * 1000).toISOString();
|
|
11565
|
-
const
|
|
11560
|
+
const allActive = listAgents().filter((a) => a.last_seen_at > cutoff);
|
|
11561
|
+
if (!pool) {
|
|
11562
|
+
const lines2 = [
|
|
11563
|
+
"No agent pool configured \u2014 any name is allowed.",
|
|
11564
|
+
allActive.length > 0 ? `Active agents (avoid these names): ${allActive.map((a) => `${a.name} (seen ${Math.round((Date.now() - new Date(a.last_seen_at).getTime()) / 60000)}m ago)`).join(", ")}` : "No active agents.",
|
|
11565
|
+
`
|
|
11566
|
+
To restrict names, configure agent_pool or project_pools in ~/.todos/config.json`
|
|
11567
|
+
];
|
|
11568
|
+
return { content: [{ type: "text", text: lines2.join(`
|
|
11569
|
+
`) }] };
|
|
11570
|
+
}
|
|
11571
|
+
const available = getAvailableNamesFromPool(pool, getDatabase());
|
|
11572
|
+
const activeInPool = allActive.filter((a) => pool.map((n) => n.toLowerCase()).includes(a.name));
|
|
11566
11573
|
const lines = [
|
|
11567
11574
|
`Project pool: ${pool.join(", ")}`,
|
|
11568
11575
|
`Available now (${available.length}): ${available.length > 0 ? available.join(", ") : "none \u2014 all names in use"}`,
|
|
11569
|
-
|
|
11576
|
+
activeInPool.length > 0 ? `Active agents: ${activeInPool.map((a) => `${a.name} (seen ${Math.round((Date.now() - new Date(a.last_seen_at).getTime()) / 60000)}m ago)`).join(", ")}` : "Active agents: none",
|
|
11570
11577
|
available.length > 0 ? `
|
|
11571
11578
|
Suggested: ${available[0]}` : `
|
|
11572
|
-
No names available
|
|
11579
|
+
No names available. Wait for an active agent to go stale (30min timeout).`
|
|
11573
11580
|
];
|
|
11574
11581
|
return { content: [{ type: "text", text: lines.join(`
|
|
11575
11582
|
`) }] };
|
|
@@ -11579,14 +11586,17 @@ No names available yet. Wait for an active agent to go stale (30min timeout).`
|
|
|
11579
11586
|
});
|
|
11580
11587
|
}
|
|
11581
11588
|
if (shouldRegisterTool("list_agents")) {
|
|
11582
|
-
server.tool("list_agents", "List all registered agents
|
|
11589
|
+
server.tool("list_agents", "List all registered agents. By default shows only active agents \u2014 set include_archived to see archived ones too.", {
|
|
11590
|
+
include_archived: exports_external.boolean().optional().describe("Include archived agents in the list (default: false)")
|
|
11591
|
+
}, async ({ include_archived }) => {
|
|
11583
11592
|
try {
|
|
11584
|
-
const agents = listAgents();
|
|
11593
|
+
const agents = listAgents({ include_archived: include_archived ?? false });
|
|
11585
11594
|
if (agents.length === 0) {
|
|
11586
11595
|
return { content: [{ type: "text", text: "No agents registered." }] };
|
|
11587
11596
|
}
|
|
11588
11597
|
const text = agents.map((a) => {
|
|
11589
|
-
|
|
11598
|
+
const statusTag = a.status === "archived" ? " [archived]" : "";
|
|
11599
|
+
return `${a.id} | ${a.name}${statusTag}${a.description ? ` - ${a.description}` : ""} (last seen: ${a.last_seen_at})`;
|
|
11590
11600
|
}).join(`
|
|
11591
11601
|
`);
|
|
11592
11602
|
return { content: [{ type: "text", text: `${agents.length} agent(s):
|
|
@@ -11654,7 +11664,7 @@ ID: ${updated.id}`
|
|
|
11654
11664
|
});
|
|
11655
11665
|
}
|
|
11656
11666
|
if (shouldRegisterTool("delete_agent")) {
|
|
11657
|
-
server.tool("delete_agent", "
|
|
11667
|
+
server.tool("delete_agent", "Archive an agent (soft delete). The agent is hidden from list_agents but preserved for task history. Use unarchive_agent to restore. Resolve by id or name.", {
|
|
11658
11668
|
id: exports_external.string().optional(),
|
|
11659
11669
|
name: exports_external.string().optional()
|
|
11660
11670
|
}, async ({ id, name }) => {
|
|
@@ -11666,13 +11676,63 @@ ID: ${updated.id}`
|
|
|
11666
11676
|
if (!agent) {
|
|
11667
11677
|
return { content: [{ type: "text", text: `Agent not found: ${id || name}` }], isError: true };
|
|
11668
11678
|
}
|
|
11669
|
-
const
|
|
11679
|
+
const archived = archiveAgent(agent.id);
|
|
11670
11680
|
return {
|
|
11671
11681
|
content: [{
|
|
11672
11682
|
type: "text",
|
|
11673
|
-
text:
|
|
11683
|
+
text: archived ? `Agent archived: ${agent.name} (${agent.id}). Use unarchive_agent to restore.` : `Failed to archive agent: ${agent.name}`
|
|
11674
11684
|
}],
|
|
11675
|
-
isError: !
|
|
11685
|
+
isError: !archived
|
|
11686
|
+
};
|
|
11687
|
+
} catch (e) {
|
|
11688
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
11689
|
+
}
|
|
11690
|
+
});
|
|
11691
|
+
}
|
|
11692
|
+
if (shouldRegisterTool("unarchive_agent")) {
|
|
11693
|
+
server.tool("unarchive_agent", "Restore an archived agent back to active status. Resolve by id or name.", {
|
|
11694
|
+
id: exports_external.string().optional(),
|
|
11695
|
+
name: exports_external.string().optional()
|
|
11696
|
+
}, async ({ id, name }) => {
|
|
11697
|
+
try {
|
|
11698
|
+
if (!id && !name) {
|
|
11699
|
+
return { content: [{ type: "text", text: "Provide either id or name." }], isError: true };
|
|
11700
|
+
}
|
|
11701
|
+
const agent = id ? getAgent(id) : getAgentByName(name);
|
|
11702
|
+
if (!agent) {
|
|
11703
|
+
return { content: [{ type: "text", text: `Agent not found: ${id || name}` }], isError: true };
|
|
11704
|
+
}
|
|
11705
|
+
if (agent.status === "active") {
|
|
11706
|
+
return { content: [{ type: "text", text: `Agent ${agent.name} is already active.` }] };
|
|
11707
|
+
}
|
|
11708
|
+
const restored = unarchiveAgent(agent.id);
|
|
11709
|
+
return {
|
|
11710
|
+
content: [{
|
|
11711
|
+
type: "text",
|
|
11712
|
+
text: restored ? `Agent restored: ${agent.name} (${agent.id}) is now active.` : `Failed to restore agent: ${agent.name}`
|
|
11713
|
+
}],
|
|
11714
|
+
isError: !restored
|
|
11715
|
+
};
|
|
11716
|
+
} catch (e) {
|
|
11717
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
11718
|
+
}
|
|
11719
|
+
});
|
|
11720
|
+
}
|
|
11721
|
+
if (shouldRegisterTool("heartbeat")) {
|
|
11722
|
+
server.tool("heartbeat", "Update your last_seen_at timestamp to signal you're still active. Call periodically during long tasks to prevent being marked stale.", {
|
|
11723
|
+
agent_id: exports_external.string().describe("Your agent ID or name.")
|
|
11724
|
+
}, async ({ agent_id }) => {
|
|
11725
|
+
try {
|
|
11726
|
+
const agent = getAgent(agent_id) || getAgentByName(agent_id);
|
|
11727
|
+
if (!agent) {
|
|
11728
|
+
return { content: [{ type: "text", text: `Agent not found: ${agent_id}` }], isError: true };
|
|
11729
|
+
}
|
|
11730
|
+
updateAgentActivity(agent.id);
|
|
11731
|
+
return {
|
|
11732
|
+
content: [{
|
|
11733
|
+
type: "text",
|
|
11734
|
+
text: `Heartbeat: ${agent.name} (${agent.id}) \u2014 last_seen_at updated to ${new Date().toISOString()}`
|
|
11735
|
+
}]
|
|
11676
11736
|
};
|
|
11677
11737
|
} catch (e) {
|
|
11678
11738
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
@@ -12775,6 +12835,8 @@ Claimed: ${formatTask(result.claimed)}`);
|
|
|
12775
12835
|
"get_agent",
|
|
12776
12836
|
"rename_agent",
|
|
12777
12837
|
"delete_agent",
|
|
12838
|
+
"unarchive_agent",
|
|
12839
|
+
"heartbeat",
|
|
12778
12840
|
"get_my_tasks",
|
|
12779
12841
|
"get_org_chart",
|
|
12780
12842
|
"set_reports_to",
|
|
@@ -12912,22 +12974,30 @@ Claimed: ${formatTask(result.claimed)}`);
|
|
|
12912
12974
|
delete_plan: `Delete a plan. Tasks in the plan are orphaned, not deleted.
|
|
12913
12975
|
Params: id(string, req)
|
|
12914
12976
|
Example: {id: 'a1b2c3d4'}`,
|
|
12915
|
-
suggest_agent_name: `
|
|
12916
|
-
Params: working_dir(string \u2014 your working directory, used to look up project pool)
|
|
12977
|
+
suggest_agent_name: `Check available agent names before registering. Shows active agents and, if a pool is configured, which pool names are free.
|
|
12978
|
+
Params: working_dir(string \u2014 your working directory, used to look up project pool from config)
|
|
12917
12979
|
Example: {working_dir: '/workspace/platform'}`,
|
|
12918
|
-
register_agent: `Register an agent.
|
|
12919
|
-
Params: name(string, req), description(string), session_id(string \u2014 unique per session
|
|
12920
|
-
Example: {name: '
|
|
12921
|
-
list_agents:
|
|
12980
|
+
register_agent: `Register an agent. Any name is allowed \u2014 pool is advisory. Returns CONFLICT if name is held by a recently-active agent.
|
|
12981
|
+
Params: name(string, req), description(string), capabilities(string[]), session_id(string \u2014 unique per session), working_dir(string \u2014 used to determine project pool)
|
|
12982
|
+
Example: {name: 'my-agent', session_id: 'abc123-1741952000', working_dir: '/workspace/platform'}`,
|
|
12983
|
+
list_agents: `List all registered agents (active by default). Set include_archived: true to see archived agents.
|
|
12984
|
+
Params: include_archived(boolean, optional)
|
|
12985
|
+
Example: {include_archived: true}`,
|
|
12922
12986
|
get_agent: `Get agent details by ID or name. Provide one of id or name.
|
|
12923
12987
|
Params: id(string), name(string)
|
|
12924
12988
|
Example: {name: 'maximus'}`,
|
|
12925
12989
|
rename_agent: `Rename an agent. Resolve by id or current name.
|
|
12926
12990
|
Params: id(string), name(string \u2014 current name), new_name(string, req)
|
|
12927
12991
|
Example: {name: 'old-name', new_name: 'new-name'}`,
|
|
12928
|
-
delete_agent: `
|
|
12992
|
+
delete_agent: `Archive an agent (soft delete). Agent is preserved for task history but hidden from list_agents. Use unarchive_agent to restore.
|
|
12993
|
+
Params: id(string), name(string)
|
|
12994
|
+
Example: {name: 'maximus'}`,
|
|
12995
|
+
unarchive_agent: `Restore an archived agent back to active status.
|
|
12929
12996
|
Params: id(string), name(string)
|
|
12930
12997
|
Example: {name: 'maximus'}`,
|
|
12998
|
+
heartbeat: `Update last_seen_at timestamp to signal you're still active. Call periodically during long tasks.
|
|
12999
|
+
Params: agent_id(string, req \u2014 your agent ID or name)
|
|
13000
|
+
Example: {agent_id: 'maximus'}`,
|
|
12931
13001
|
get_my_tasks: `Get all tasks assigned to/created by an agent, with stats (pending/active/done/rate).
|
|
12932
13002
|
Params: agent_name(string, req)
|
|
12933
13003
|
Example: {agent_name: 'maximus'}`,
|
package/dist/db/agents.d.ts
CHANGED
|
@@ -19,7 +19,9 @@ export declare function registerAgent(input: RegisterAgentInput, db?: Database):
|
|
|
19
19
|
export declare function isAgentConflict(result: Agent | AgentConflictError): result is AgentConflictError;
|
|
20
20
|
export declare function getAgent(id: string, db?: Database): Agent | null;
|
|
21
21
|
export declare function getAgentByName(name: string, db?: Database): Agent | null;
|
|
22
|
-
export declare function listAgents(
|
|
22
|
+
export declare function listAgents(opts?: {
|
|
23
|
+
include_archived?: boolean;
|
|
24
|
+
} | Database, db?: Database): Agent[];
|
|
23
25
|
export declare function updateAgentActivity(id: string, db?: Database): void;
|
|
24
26
|
export declare function updateAgent(id: string, input: {
|
|
25
27
|
name?: string;
|
|
@@ -33,7 +35,12 @@ export declare function updateAgent(id: string, input: {
|
|
|
33
35
|
org_id?: string | null;
|
|
34
36
|
metadata?: Record<string, unknown>;
|
|
35
37
|
}, db?: Database): Agent;
|
|
38
|
+
/** Soft-delete: archives the agent instead of removing it. Tasks referencing this agent are preserved. */
|
|
36
39
|
export declare function deleteAgent(id: string, db?: Database): boolean;
|
|
40
|
+
/** Archive an agent (soft delete). */
|
|
41
|
+
export declare function archiveAgent(id: string, db?: Database): Agent | null;
|
|
42
|
+
/** Restore an archived agent. */
|
|
43
|
+
export declare function unarchiveAgent(id: string, db?: Database): Agent | null;
|
|
37
44
|
/** Get direct reports of an agent. */
|
|
38
45
|
export declare function getDirectReports(agentId: string, db?: Database): Agent[];
|
|
39
46
|
/** Get the full org tree starting from top-level agents (reports_to IS NULL). */
|
package/dist/db/agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/db/agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/db/agents.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,eAAO,MAAM,mBAAmB,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AA8gBtC,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAkBrD;AAyRD,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,GAAG,IAAI,MAAM,CAE5B;AAED,wBAAgB,IAAI,IAAI,MAAM,CAE7B;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAK9D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,SAAa,GAAG,MAAM,CAG3D;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAGpD;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0B9F"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type { TaskGraphNode, TaskGraph, BulkCreateTaskInput, ActiveWorkItem, Sta
|
|
|
6
6
|
export { createProject, getProject, getProjectByPath, getProjectWithSources, listProjects, updateProject, deleteProject, ensureProject, nextTaskShortId, slugify, addProjectSource, removeProjectSource, listProjectSources, } from "./db/projects.js";
|
|
7
7
|
export { createPlan, getPlan, listPlans, updatePlan, deletePlan, } from "./db/plans.js";
|
|
8
8
|
export { addComment, getComment, listComments, deleteComment, logProgress, } from "./db/comments.js";
|
|
9
|
-
export { registerAgent, isAgentConflict, getAgent, getAgentByName, listAgents, updateAgent, updateAgentActivity, deleteAgent, getDirectReports, getOrgChart, matchCapabilities, getCapableAgents, } from "./db/agents.js";
|
|
9
|
+
export { registerAgent, isAgentConflict, getAgent, getAgentByName, listAgents, updateAgent, updateAgentActivity, deleteAgent, archiveAgent, unarchiveAgent, getDirectReports, getOrgChart, matchCapabilities, getCapableAgents, } from "./db/agents.js";
|
|
10
10
|
export type { OrgNode } from "./db/agents.js";
|
|
11
11
|
export { createTaskList, getTaskList, getTaskListBySlug, listTaskLists, updateTaskList, deleteTaskList, ensureTaskList, } from "./db/task-lists.js";
|
|
12
12
|
export { createSession, getSession, listSessions, updateSessionActivity, deleteSession, } from "./db/sessions.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -697,6 +697,11 @@ var MIGRATIONS = [
|
|
|
697
697
|
`
|
|
698
698
|
ALTER TABLE agents ADD COLUMN capabilities TEXT DEFAULT '[]';
|
|
699
699
|
INSERT OR IGNORE INTO _migrations (id) VALUES (29);
|
|
700
|
+
`,
|
|
701
|
+
`
|
|
702
|
+
ALTER TABLE agents ADD COLUMN status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'archived'));
|
|
703
|
+
CREATE INDEX IF NOT EXISTS idx_agents_status ON agents(status);
|
|
704
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (30);
|
|
700
705
|
`
|
|
701
706
|
];
|
|
702
707
|
var _db = null;
|
|
@@ -764,6 +769,7 @@ function ensureSchema(db) {
|
|
|
764
769
|
CREATE TABLE agents (
|
|
765
770
|
id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, description TEXT,
|
|
766
771
|
role TEXT DEFAULT 'agent', permissions TEXT DEFAULT '["*"]',
|
|
772
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'archived')),
|
|
767
773
|
metadata TEXT DEFAULT '{}',
|
|
768
774
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
769
775
|
last_seen_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
@@ -2830,7 +2836,7 @@ function deleteComment(id, db) {
|
|
|
2830
2836
|
var AGENT_ACTIVE_WINDOW_MS = 30 * 60 * 1000;
|
|
2831
2837
|
function getAvailableNamesFromPool(pool, db) {
|
|
2832
2838
|
const cutoff = new Date(Date.now() - AGENT_ACTIVE_WINDOW_MS).toISOString();
|
|
2833
|
-
const activeNames = new Set(db.query("SELECT name FROM agents WHERE last_seen_at > ?").all(cutoff).map((r) => r.name.toLowerCase()));
|
|
2839
|
+
const activeNames = new Set(db.query("SELECT name FROM agents WHERE status = 'active' AND last_seen_at > ?").all(cutoff).map((r) => r.name.toLowerCase()));
|
|
2834
2840
|
return pool.filter((name) => !activeNames.has(name.toLowerCase()));
|
|
2835
2841
|
}
|
|
2836
2842
|
function shortUuid() {
|
|
@@ -2841,30 +2847,13 @@ function rowToAgent(row) {
|
|
|
2841
2847
|
...row,
|
|
2842
2848
|
permissions: JSON.parse(row.permissions || '["*"]'),
|
|
2843
2849
|
capabilities: JSON.parse(row.capabilities || "[]"),
|
|
2850
|
+
status: row.status || "active",
|
|
2844
2851
|
metadata: JSON.parse(row.metadata || "{}")
|
|
2845
2852
|
};
|
|
2846
2853
|
}
|
|
2847
2854
|
function registerAgent(input, db) {
|
|
2848
2855
|
const d = db || getDatabase();
|
|
2849
2856
|
const normalizedName = input.name.trim().toLowerCase();
|
|
2850
|
-
if (input.pool && input.pool.length > 0) {
|
|
2851
|
-
const poolLower = input.pool.map((n) => n.toLowerCase());
|
|
2852
|
-
if (!poolLower.includes(normalizedName)) {
|
|
2853
|
-
const available = getAvailableNamesFromPool(input.pool, d);
|
|
2854
|
-
const suggestion = available.length > 0 ? available[0] : null;
|
|
2855
|
-
return {
|
|
2856
|
-
conflict: true,
|
|
2857
|
-
pool_violation: true,
|
|
2858
|
-
existing_id: "",
|
|
2859
|
-
existing_name: normalizedName,
|
|
2860
|
-
last_seen_at: "",
|
|
2861
|
-
session_hint: null,
|
|
2862
|
-
working_dir: input.working_dir || null,
|
|
2863
|
-
suggestions: available.slice(0, 5),
|
|
2864
|
-
message: `"${normalizedName}" is not in this project's agent pool [${input.pool.join(", ")}]. ${available.length > 0 ? `Try: ${available.slice(0, 3).join(", ")}` : "No names are currently available \u2014 wait for an active agent to go stale."}${suggestion ? ` Suggested: ${suggestion}` : ""}`
|
|
2865
|
-
};
|
|
2866
|
-
}
|
|
2867
|
-
}
|
|
2868
2857
|
const existing = getAgentByName(normalizedName, d);
|
|
2869
2858
|
if (existing) {
|
|
2870
2859
|
const lastSeenMs = new Date(existing.last_seen_at).getTime();
|
|
@@ -2885,7 +2874,7 @@ function registerAgent(input, db) {
|
|
|
2885
2874
|
message: `Agent "${normalizedName}" is already active (last seen ${minutesAgo}m ago, session ${existing.session_id?.slice(0, 8)}\u2026, dir: ${existing.working_dir ?? "unknown"}). Are you that agent? If so, pass session_id="${existing.session_id}" to reclaim it. Otherwise choose a different name.${suggestions.length > 0 ? ` Available: ${suggestions.slice(0, 3).join(", ")}` : ""}`
|
|
2886
2875
|
};
|
|
2887
2876
|
}
|
|
2888
|
-
const updates = ["last_seen_at = ?"];
|
|
2877
|
+
const updates = ["last_seen_at = ?", "status = 'active'"];
|
|
2889
2878
|
const params = [now()];
|
|
2890
2879
|
if (input.session_id && !sameSession) {
|
|
2891
2880
|
updates.push("session_id = ?");
|
|
@@ -2939,9 +2928,19 @@ function getAgentByName(name, db) {
|
|
|
2939
2928
|
const row = d.query("SELECT * FROM agents WHERE LOWER(name) = ?").get(normalizedName);
|
|
2940
2929
|
return row ? rowToAgent(row) : null;
|
|
2941
2930
|
}
|
|
2942
|
-
function listAgents(db) {
|
|
2943
|
-
|
|
2944
|
-
|
|
2931
|
+
function listAgents(opts, db) {
|
|
2932
|
+
let d;
|
|
2933
|
+
let includeArchived = false;
|
|
2934
|
+
if (opts && typeof opts === "object" && "query" in opts) {
|
|
2935
|
+
d = opts;
|
|
2936
|
+
} else {
|
|
2937
|
+
includeArchived = opts?.include_archived ?? false;
|
|
2938
|
+
d = db || getDatabase();
|
|
2939
|
+
}
|
|
2940
|
+
if (includeArchived) {
|
|
2941
|
+
return d.query("SELECT * FROM agents ORDER BY name").all().map(rowToAgent);
|
|
2942
|
+
}
|
|
2943
|
+
return d.query("SELECT * FROM agents WHERE status = 'active' ORDER BY name").all().map(rowToAgent);
|
|
2945
2944
|
}
|
|
2946
2945
|
function updateAgentActivity(id, db) {
|
|
2947
2946
|
const d = db || getDatabase();
|
|
@@ -3000,7 +2999,17 @@ function updateAgent(id, input, db) {
|
|
|
3000
2999
|
}
|
|
3001
3000
|
function deleteAgent(id, db) {
|
|
3002
3001
|
const d = db || getDatabase();
|
|
3003
|
-
return d.run("
|
|
3002
|
+
return d.run("UPDATE agents SET status = 'archived', last_seen_at = ? WHERE id = ?", [now(), id]).changes > 0;
|
|
3003
|
+
}
|
|
3004
|
+
function archiveAgent(id, db) {
|
|
3005
|
+
const d = db || getDatabase();
|
|
3006
|
+
d.run("UPDATE agents SET status = 'archived', last_seen_at = ? WHERE id = ?", [now(), id]);
|
|
3007
|
+
return getAgent(id, d);
|
|
3008
|
+
}
|
|
3009
|
+
function unarchiveAgent(id, db) {
|
|
3010
|
+
const d = db || getDatabase();
|
|
3011
|
+
d.run("UPDATE agents SET status = 'active', last_seen_at = ? WHERE id = ?", [now(), id]);
|
|
3012
|
+
return getAgent(id, d);
|
|
3004
3013
|
}
|
|
3005
3014
|
function getDirectReports(agentId, db) {
|
|
3006
3015
|
const d = db || getDatabase();
|
|
@@ -4524,6 +4533,7 @@ export {
|
|
|
4524
4533
|
updateAgentActivity,
|
|
4525
4534
|
updateAgent,
|
|
4526
4535
|
unlockTask,
|
|
4536
|
+
unarchiveAgent,
|
|
4527
4537
|
taskFromTemplate,
|
|
4528
4538
|
syncWithAgents,
|
|
4529
4539
|
syncWithAgent,
|
|
@@ -4661,6 +4671,7 @@ export {
|
|
|
4661
4671
|
bulkCreateTasks,
|
|
4662
4672
|
bulkAddTaskFiles,
|
|
4663
4673
|
autoDetectFileRelationships,
|
|
4674
|
+
archiveAgent,
|
|
4664
4675
|
addTaskRelationship,
|
|
4665
4676
|
addTaskFile,
|
|
4666
4677
|
addProjectSource,
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -29,11 +29,6 @@ export interface TodosConfig {
|
|
|
29
29
|
/** Per-project agent name pools, keyed by working directory path prefix. */
|
|
30
30
|
project_pools?: Record<string, string[]>;
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Built-in default agent name pool (Roman names convention).
|
|
34
|
-
* Used when no pool is configured in config.json.
|
|
35
|
-
*/
|
|
36
|
-
export declare const DEFAULT_AGENT_POOL: string[];
|
|
37
32
|
export declare function loadConfig(): TodosConfig;
|
|
38
33
|
export declare function getSyncAgentsFromConfig(): string[] | null;
|
|
39
34
|
export declare function getAgentTaskListId(agent: string): string | null;
|
|
@@ -42,8 +37,8 @@ export declare function getTaskPrefixConfig(): TaskPrefixConfig | null;
|
|
|
42
37
|
/**
|
|
43
38
|
* Get the agent name pool for a given working directory.
|
|
44
39
|
* Checks project_pools for the longest matching path prefix, then falls back
|
|
45
|
-
* to agent_pool
|
|
40
|
+
* to agent_pool. Returns null if no pool is configured (no name restriction).
|
|
46
41
|
*/
|
|
47
|
-
export declare function getAgentPoolForProject(workingDir?: string): string[];
|
|
42
|
+
export declare function getAgentPoolForProject(workingDir?: string): string[] | null;
|
|
48
43
|
export declare function getCompletionGuardConfig(projectPath?: string | null): Required<CompletionGuardConfig>;
|
|
49
44
|
//# sourceMappingURL=config.d.ts.map
|