@hasna/todos 0.9.53 → 0.9.54
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 +58 -33
- package/dist/mcp/index.js +13 -1
- package/dist/server/index.js +13 -0
- package/dist/server/serve.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -9154,6 +9154,18 @@ var init_zod = __esm(() => {
|
|
|
9154
9154
|
var exports_mcp = {};
|
|
9155
9155
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9156
9156
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9157
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
9158
|
+
import { join as join6, dirname as dirname2 } from "path";
|
|
9159
|
+
import { fileURLToPath } from "url";
|
|
9160
|
+
function getMcpVersion() {
|
|
9161
|
+
try {
|
|
9162
|
+
const __dir = dirname2(fileURLToPath(import.meta.url));
|
|
9163
|
+
const pkgPath = join6(__dir, "..", "package.json");
|
|
9164
|
+
return JSON.parse(readFileSync3(pkgPath, "utf-8")).version || "0.0.0";
|
|
9165
|
+
} catch {
|
|
9166
|
+
return "0.0.0";
|
|
9167
|
+
}
|
|
9168
|
+
}
|
|
9157
9169
|
function shouldRegisterTool(name) {
|
|
9158
9170
|
if (TODOS_PROFILE === "minimal")
|
|
9159
9171
|
return MINIMAL_TOOLS.has(name);
|
|
@@ -9273,7 +9285,7 @@ var init_mcp = __esm(() => {
|
|
|
9273
9285
|
init_types();
|
|
9274
9286
|
server = new McpServer({
|
|
9275
9287
|
name: "todos",
|
|
9276
|
-
version:
|
|
9288
|
+
version: getMcpVersion()
|
|
9277
9289
|
});
|
|
9278
9290
|
TODOS_PROFILE = (process.env["TODOS_PROFILE"] || "full").toLowerCase();
|
|
9279
9291
|
MINIMAL_TOOLS = new Set([
|
|
@@ -11229,26 +11241,26 @@ __export(exports_serve, {
|
|
|
11229
11241
|
startServer: () => startServer
|
|
11230
11242
|
});
|
|
11231
11243
|
import { existsSync as existsSync6 } from "fs";
|
|
11232
|
-
import { join as
|
|
11233
|
-
import { fileURLToPath } from "url";
|
|
11244
|
+
import { join as join7, dirname as dirname3, extname, resolve as resolve2, sep } from "path";
|
|
11245
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11234
11246
|
function resolveDashboardDir() {
|
|
11235
11247
|
const candidates = [];
|
|
11236
11248
|
try {
|
|
11237
|
-
const scriptDir =
|
|
11238
|
-
candidates.push(
|
|
11239
|
-
candidates.push(
|
|
11249
|
+
const scriptDir = dirname3(fileURLToPath2(import.meta.url));
|
|
11250
|
+
candidates.push(join7(scriptDir, "..", "dashboard", "dist"));
|
|
11251
|
+
candidates.push(join7(scriptDir, "..", "..", "dashboard", "dist"));
|
|
11240
11252
|
} catch {}
|
|
11241
11253
|
if (process.argv[1]) {
|
|
11242
|
-
const mainDir =
|
|
11243
|
-
candidates.push(
|
|
11244
|
-
candidates.push(
|
|
11254
|
+
const mainDir = dirname3(process.argv[1]);
|
|
11255
|
+
candidates.push(join7(mainDir, "..", "dashboard", "dist"));
|
|
11256
|
+
candidates.push(join7(mainDir, "..", "..", "dashboard", "dist"));
|
|
11245
11257
|
}
|
|
11246
|
-
candidates.push(
|
|
11258
|
+
candidates.push(join7(process.cwd(), "dashboard", "dist"));
|
|
11247
11259
|
for (const candidate of candidates) {
|
|
11248
11260
|
if (existsSync6(candidate))
|
|
11249
11261
|
return candidate;
|
|
11250
11262
|
}
|
|
11251
|
-
return
|
|
11263
|
+
return join7(process.cwd(), "dashboard", "dist");
|
|
11252
11264
|
}
|
|
11253
11265
|
function json(data, status = 200, port) {
|
|
11254
11266
|
return new Response(JSON.stringify(data), {
|
|
@@ -11648,6 +11660,19 @@ data: ${JSON.stringify({ type: "connected", agent_id: agentId, timestamp: new Da
|
|
|
11648
11660
|
return json({ error: e instanceof Error ? e.message : "Failed to start task" }, 500, port);
|
|
11649
11661
|
}
|
|
11650
11662
|
}
|
|
11663
|
+
const failMatch = path.match(/^\/api\/tasks\/([^/]+)\/fail$/);
|
|
11664
|
+
if (failMatch && method === "POST") {
|
|
11665
|
+
const id = failMatch[1];
|
|
11666
|
+
try {
|
|
11667
|
+
const body = await req.json().catch(() => ({}));
|
|
11668
|
+
const { failTask: failTask2 } = await Promise.resolve().then(() => (init_tasks(), exports_tasks));
|
|
11669
|
+
const result = failTask2(id, body.agent_id, body.reason, { retry: body.retry, error_code: body.error_code });
|
|
11670
|
+
broadcastEvent({ type: "task", task_id: id, action: "failed", agent_id: body.agent_id || null });
|
|
11671
|
+
return json({ task: taskToSummary(result.task), retry_task: result.retryTask ? taskToSummary(result.retryTask) : null }, 200, port);
|
|
11672
|
+
} catch (e) {
|
|
11673
|
+
return json({ error: e instanceof Error ? e.message : "Failed to fail task" }, 500, port);
|
|
11674
|
+
}
|
|
11675
|
+
}
|
|
11651
11676
|
const completeMatch = path.match(/^\/api\/tasks\/([^/]+)\/complete$/);
|
|
11652
11677
|
if (completeMatch && method === "POST") {
|
|
11653
11678
|
const id = completeMatch[1];
|
|
@@ -11960,7 +11985,7 @@ data: ${JSON.stringify({ type: "connected", agent_id: agentId, timestamp: new Da
|
|
|
11960
11985
|
}
|
|
11961
11986
|
if (dashboardExists && (method === "GET" || method === "HEAD")) {
|
|
11962
11987
|
if (path !== "/") {
|
|
11963
|
-
const filePath =
|
|
11988
|
+
const filePath = join7(dashboardDir, path);
|
|
11964
11989
|
const resolvedFile = resolve2(filePath);
|
|
11965
11990
|
const resolvedBase = resolve2(dashboardDir);
|
|
11966
11991
|
if (!resolvedFile.startsWith(resolvedBase + sep) && resolvedFile !== resolvedBase) {
|
|
@@ -11970,7 +11995,7 @@ data: ${JSON.stringify({ type: "connected", agent_id: agentId, timestamp: new Da
|
|
|
11970
11995
|
if (res2)
|
|
11971
11996
|
return res2;
|
|
11972
11997
|
}
|
|
11973
|
-
const indexPath =
|
|
11998
|
+
const indexPath = join7(dashboardDir, "index.html");
|
|
11974
11999
|
const res = serveStaticFile(indexPath);
|
|
11975
12000
|
if (res)
|
|
11976
12001
|
return res;
|
|
@@ -13105,13 +13130,13 @@ init_sync();
|
|
|
13105
13130
|
init_config();
|
|
13106
13131
|
import chalk from "chalk";
|
|
13107
13132
|
import { execSync } from "child_process";
|
|
13108
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as
|
|
13109
|
-
import { basename, dirname as
|
|
13110
|
-
import { fileURLToPath as
|
|
13133
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
13134
|
+
import { basename, dirname as dirname4, join as join8, resolve as resolve3 } from "path";
|
|
13135
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
13111
13136
|
function getPackageVersion() {
|
|
13112
13137
|
try {
|
|
13113
|
-
const pkgPath =
|
|
13114
|
-
return JSON.parse(
|
|
13138
|
+
const pkgPath = join8(dirname4(fileURLToPath3(import.meta.url)), "..", "..", "package.json");
|
|
13139
|
+
return JSON.parse(readFileSync4(pkgPath, "utf-8")).version || "0.0.0";
|
|
13115
13140
|
} catch {
|
|
13116
13141
|
return "0.0.0";
|
|
13117
13142
|
}
|
|
@@ -14016,7 +14041,7 @@ hooks.command("install").description("Install Claude Code hooks for auto-sync").
|
|
|
14016
14041
|
if (p)
|
|
14017
14042
|
todosBin = p;
|
|
14018
14043
|
} catch {}
|
|
14019
|
-
const hooksDir =
|
|
14044
|
+
const hooksDir = join8(process.cwd(), ".claude", "hooks");
|
|
14020
14045
|
if (!existsSync7(hooksDir))
|
|
14021
14046
|
mkdirSync3(hooksDir, { recursive: true });
|
|
14022
14047
|
const hookScript = `#!/usr/bin/env bash
|
|
@@ -14042,11 +14067,11 @@ esac
|
|
|
14042
14067
|
|
|
14043
14068
|
exit 0
|
|
14044
14069
|
`;
|
|
14045
|
-
const hookPath =
|
|
14070
|
+
const hookPath = join8(hooksDir, "todos-sync.sh");
|
|
14046
14071
|
writeFileSync3(hookPath, hookScript);
|
|
14047
14072
|
execSync(`chmod +x "${hookPath}"`);
|
|
14048
14073
|
console.log(chalk.green(`Hook script created: ${hookPath}`));
|
|
14049
|
-
const settingsPath =
|
|
14074
|
+
const settingsPath = join8(process.cwd(), ".claude", "settings.json");
|
|
14050
14075
|
const settings = readJsonFile2(settingsPath);
|
|
14051
14076
|
if (!settings["hooks"]) {
|
|
14052
14077
|
settings["hooks"] = {};
|
|
@@ -14093,7 +14118,7 @@ function getMcpBinaryPath() {
|
|
|
14093
14118
|
if (p)
|
|
14094
14119
|
return p;
|
|
14095
14120
|
} catch {}
|
|
14096
|
-
const bunBin =
|
|
14121
|
+
const bunBin = join8(HOME2, ".bun", "bin", "todos-mcp");
|
|
14097
14122
|
if (existsSync7(bunBin))
|
|
14098
14123
|
return bunBin;
|
|
14099
14124
|
return "todos-mcp";
|
|
@@ -14102,13 +14127,13 @@ function readJsonFile2(path) {
|
|
|
14102
14127
|
if (!existsSync7(path))
|
|
14103
14128
|
return {};
|
|
14104
14129
|
try {
|
|
14105
|
-
return JSON.parse(
|
|
14130
|
+
return JSON.parse(readFileSync4(path, "utf-8"));
|
|
14106
14131
|
} catch {
|
|
14107
14132
|
return {};
|
|
14108
14133
|
}
|
|
14109
14134
|
}
|
|
14110
14135
|
function writeJsonFile2(path, data) {
|
|
14111
|
-
const dir =
|
|
14136
|
+
const dir = dirname4(path);
|
|
14112
14137
|
if (!existsSync7(dir))
|
|
14113
14138
|
mkdirSync3(dir, { recursive: true });
|
|
14114
14139
|
writeFileSync3(path, JSON.stringify(data, null, 2) + `
|
|
@@ -14117,10 +14142,10 @@ function writeJsonFile2(path, data) {
|
|
|
14117
14142
|
function readTomlFile(path) {
|
|
14118
14143
|
if (!existsSync7(path))
|
|
14119
14144
|
return "";
|
|
14120
|
-
return
|
|
14145
|
+
return readFileSync4(path, "utf-8");
|
|
14121
14146
|
}
|
|
14122
14147
|
function writeTomlFile(path, content) {
|
|
14123
|
-
const dir =
|
|
14148
|
+
const dir = dirname4(path);
|
|
14124
14149
|
if (!existsSync7(dir))
|
|
14125
14150
|
mkdirSync3(dir, { recursive: true });
|
|
14126
14151
|
writeFileSync3(path, content);
|
|
@@ -14148,7 +14173,7 @@ function unregisterClaude(_global) {
|
|
|
14148
14173
|
}
|
|
14149
14174
|
}
|
|
14150
14175
|
function registerCodex(binPath) {
|
|
14151
|
-
const configPath =
|
|
14176
|
+
const configPath = join8(HOME2, ".codex", "config.toml");
|
|
14152
14177
|
let content = readTomlFile(configPath);
|
|
14153
14178
|
content = removeTomlBlock(content, "mcp_servers.todos");
|
|
14154
14179
|
const block = `
|
|
@@ -14162,7 +14187,7 @@ args = []
|
|
|
14162
14187
|
console.log(chalk.green(`Codex CLI: registered in ${configPath}`));
|
|
14163
14188
|
}
|
|
14164
14189
|
function unregisterCodex() {
|
|
14165
|
-
const configPath =
|
|
14190
|
+
const configPath = join8(HOME2, ".codex", "config.toml");
|
|
14166
14191
|
let content = readTomlFile(configPath);
|
|
14167
14192
|
if (!content.includes("[mcp_servers.todos]")) {
|
|
14168
14193
|
console.log(chalk.dim(`Codex CLI: todos not found in ${configPath}`));
|
|
@@ -14195,7 +14220,7 @@ function removeTomlBlock(content, blockName) {
|
|
|
14195
14220
|
`);
|
|
14196
14221
|
}
|
|
14197
14222
|
function registerGemini(binPath) {
|
|
14198
|
-
const configPath =
|
|
14223
|
+
const configPath = join8(HOME2, ".gemini", "settings.json");
|
|
14199
14224
|
const config = readJsonFile2(configPath);
|
|
14200
14225
|
if (!config["mcpServers"]) {
|
|
14201
14226
|
config["mcpServers"] = {};
|
|
@@ -14209,7 +14234,7 @@ function registerGemini(binPath) {
|
|
|
14209
14234
|
console.log(chalk.green(`Gemini CLI: registered in ${configPath}`));
|
|
14210
14235
|
}
|
|
14211
14236
|
function unregisterGemini() {
|
|
14212
|
-
const configPath =
|
|
14237
|
+
const configPath = join8(HOME2, ".gemini", "settings.json");
|
|
14213
14238
|
const config = readJsonFile2(configPath);
|
|
14214
14239
|
const servers = config["mcpServers"];
|
|
14215
14240
|
if (!servers || !("todos" in servers)) {
|
|
@@ -14422,7 +14447,7 @@ Updated to ${latestVersion}!`));
|
|
|
14422
14447
|
});
|
|
14423
14448
|
program2.command("config").description("View or update configuration").option("--get <key>", "Get a config value").option("--set <key=value>", "Set a config value (e.g. completion_guard.enabled=true)").action((opts) => {
|
|
14424
14449
|
const globalOpts = program2.opts();
|
|
14425
|
-
const configPath =
|
|
14450
|
+
const configPath = join8(process.env["HOME"] || "~", ".todos", "config.json");
|
|
14426
14451
|
if (opts.get) {
|
|
14427
14452
|
const config2 = loadConfig();
|
|
14428
14453
|
const keys = opts.get.split(".");
|
|
@@ -14448,7 +14473,7 @@ program2.command("config").description("View or update configuration").option("-
|
|
|
14448
14473
|
}
|
|
14449
14474
|
let config2 = {};
|
|
14450
14475
|
try {
|
|
14451
|
-
config2 = JSON.parse(
|
|
14476
|
+
config2 = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
14452
14477
|
} catch {}
|
|
14453
14478
|
const keys = key.split(".");
|
|
14454
14479
|
let obj = config2;
|
|
@@ -14458,7 +14483,7 @@ program2.command("config").description("View or update configuration").option("-
|
|
|
14458
14483
|
obj = obj[keys[i]];
|
|
14459
14484
|
}
|
|
14460
14485
|
obj[keys[keys.length - 1]] = parsedValue;
|
|
14461
|
-
const dir =
|
|
14486
|
+
const dir = dirname4(configPath);
|
|
14462
14487
|
if (!existsSync7(dir))
|
|
14463
14488
|
mkdirSync3(dir, { recursive: true });
|
|
14464
14489
|
writeFileSync3(configPath, JSON.stringify(config2, null, 2));
|
package/dist/mcp/index.js
CHANGED
|
@@ -6946,9 +6946,21 @@ function syncWithAgents(agents, taskListIdByAgent, projectId, direction = "both"
|
|
|
6946
6946
|
|
|
6947
6947
|
// src/mcp/index.ts
|
|
6948
6948
|
init_database();
|
|
6949
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
6950
|
+
import { join as join6, dirname as dirname2 } from "path";
|
|
6951
|
+
import { fileURLToPath } from "url";
|
|
6952
|
+
function getMcpVersion() {
|
|
6953
|
+
try {
|
|
6954
|
+
const __dir = dirname2(fileURLToPath(import.meta.url));
|
|
6955
|
+
const pkgPath = join6(__dir, "..", "package.json");
|
|
6956
|
+
return JSON.parse(readFileSync3(pkgPath, "utf-8")).version || "0.0.0";
|
|
6957
|
+
} catch {
|
|
6958
|
+
return "0.0.0";
|
|
6959
|
+
}
|
|
6960
|
+
}
|
|
6949
6961
|
var server = new McpServer({
|
|
6950
6962
|
name: "todos",
|
|
6951
|
-
version:
|
|
6963
|
+
version: getMcpVersion()
|
|
6952
6964
|
});
|
|
6953
6965
|
var TODOS_PROFILE = (process.env["TODOS_PROFILE"] || "full").toLowerCase();
|
|
6954
6966
|
var MINIMAL_TOOLS = new Set([
|
package/dist/server/index.js
CHANGED
|
@@ -2855,6 +2855,19 @@ data: ${JSON.stringify({ type: "connected", agent_id: agentId, timestamp: new Da
|
|
|
2855
2855
|
return json({ error: e instanceof Error ? e.message : "Failed to start task" }, 500, port);
|
|
2856
2856
|
}
|
|
2857
2857
|
}
|
|
2858
|
+
const failMatch = path.match(/^\/api\/tasks\/([^/]+)\/fail$/);
|
|
2859
|
+
if (failMatch && method === "POST") {
|
|
2860
|
+
const id = failMatch[1];
|
|
2861
|
+
try {
|
|
2862
|
+
const body = await req.json().catch(() => ({}));
|
|
2863
|
+
const { failTask: failTask2 } = await Promise.resolve().then(() => (init_tasks(), exports_tasks));
|
|
2864
|
+
const result = failTask2(id, body.agent_id, body.reason, { retry: body.retry, error_code: body.error_code });
|
|
2865
|
+
broadcastEvent({ type: "task", task_id: id, action: "failed", agent_id: body.agent_id || null });
|
|
2866
|
+
return json({ task: taskToSummary(result.task), retry_task: result.retryTask ? taskToSummary(result.retryTask) : null }, 200, port);
|
|
2867
|
+
} catch (e) {
|
|
2868
|
+
return json({ error: e instanceof Error ? e.message : "Failed to fail task" }, 500, port);
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2858
2871
|
const completeMatch = path.match(/^\/api\/tasks\/([^/]+)\/complete$/);
|
|
2859
2872
|
if (completeMatch && method === "POST") {
|
|
2860
2873
|
const id = completeMatch[1];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/server/serve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiHH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/server/serve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiHH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4wB1G"}
|