@hasna/todos 0.11.36 → 0.11.37

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.
@@ -1,6 +1,7 @@
1
1
  import { Command } from "commander";
2
+ import { getPackageVersion } from "../lib/package-version.js";
2
3
  import type { Project, Task } from "../types/index.js";
3
- export declare function getPackageVersion(): string;
4
+ export { getPackageVersion };
4
5
  export declare function handleError(e: unknown): never;
5
6
  export declare function setProgramRef(p: Command): void;
6
7
  export declare function resolveTaskId(partialId: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEvD,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAc7C;AAID,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,QAA4B;AAEpE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAcvD;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAM7C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,GAAG,SAAS,CAUjF;AAMD,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAUjD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAGlF;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAI7D;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAM9D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAKhE,CAAC;AAEF,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAQ9C"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAE7B,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAc7C;AAID,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,QAA4B;AAEpE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAcvD;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAM7C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,GAAG,SAAS,CAUjF;AAMD,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAUjD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAGlF;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAI7D;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAM9D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAKhE,CAAC;AAEF,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAQ9C"}
package/dist/cli/index.js CHANGED
@@ -4063,6 +4063,30 @@ var init_projects = __esm(() => {
4063
4063
  init_machines();
4064
4064
  });
4065
4065
 
4066
+ // src/lib/package-version.ts
4067
+ import { existsSync as existsSync2, readFileSync } from "fs";
4068
+ import { dirname as dirname2, join as join2 } from "path";
4069
+ import { fileURLToPath } from "url";
4070
+ function getPackageVersion(fromUrl = import.meta.url) {
4071
+ try {
4072
+ let dir = dirname2(fileURLToPath(fromUrl));
4073
+ for (let i = 0;i < 5; i++) {
4074
+ const pkgPath = join2(dir, "package.json");
4075
+ if (existsSync2(pkgPath)) {
4076
+ return JSON.parse(readFileSync(pkgPath, "utf-8")).version || "0.0.0";
4077
+ }
4078
+ const parent = dirname2(dir);
4079
+ if (parent === dir)
4080
+ break;
4081
+ dir = parent;
4082
+ }
4083
+ } catch {
4084
+ return "0.0.0";
4085
+ }
4086
+ return "0.0.0";
4087
+ }
4088
+ var init_package_version = () => {};
4089
+
4066
4090
  // src/cli/helpers.ts
4067
4091
  var exports_helpers = {};
4068
4092
  __export(exports_helpers, {
@@ -4082,17 +4106,7 @@ __export(exports_helpers, {
4082
4106
  });
4083
4107
  import chalk from "chalk";
4084
4108
  import { execSync } from "child_process";
4085
- import { readFileSync } from "fs";
4086
- import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
4087
- import { fileURLToPath } from "url";
4088
- function getPackageVersion() {
4089
- try {
4090
- const pkgPath = join2(dirname2(fileURLToPath(import.meta.url)), "..", "..", "package.json");
4091
- return JSON.parse(readFileSync(pkgPath, "utf-8")).version || "0.0.0";
4092
- } catch {
4093
- return "0.0.0";
4094
- }
4095
- }
4109
+ import { resolve as resolve2 } from "path";
4096
4110
  function handleError(e) {
4097
4111
  let jsonMode = false;
4098
4112
  try {
@@ -4189,6 +4203,7 @@ var programForOptions = null, statusColors, priorityColors;
4189
4203
  var init_helpers = __esm(() => {
4190
4204
  init_database();
4191
4205
  init_projects();
4206
+ init_package_version();
4192
4207
  statusColors = {
4193
4208
  pending: chalk.yellow,
4194
4209
  in_progress: chalk.blue,
@@ -4205,14 +4220,14 @@ var init_helpers = __esm(() => {
4205
4220
  });
4206
4221
 
4207
4222
  // src/lib/sync-utils.ts
4208
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, statSync, writeFileSync } from "fs";
4223
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, statSync, writeFileSync } from "fs";
4209
4224
  import { join as join3 } from "path";
4210
4225
  function ensureDir2(dir) {
4211
- if (!existsSync2(dir))
4226
+ if (!existsSync3(dir))
4212
4227
  mkdirSync2(dir, { recursive: true });
4213
4228
  }
4214
4229
  function listJsonFiles(dir) {
4215
- if (!existsSync2(dir))
4230
+ if (!existsSync3(dir))
4216
4231
  return [];
4217
4232
  return readdirSync(dir).filter((f) => f.endsWith(".json"));
4218
4233
  }
@@ -4229,7 +4244,7 @@ function writeJsonFile(path, data) {
4229
4244
  }
4230
4245
  function readHighWaterMark(dir) {
4231
4246
  const path = join3(dir, ".highwatermark");
4232
- if (!existsSync2(path))
4247
+ if (!existsSync3(path))
4233
4248
  return 1;
4234
4249
  const val = parseInt(readFileSync2(path, "utf-8").trim(), 10);
4235
4250
  return isNaN(val) ? 1 : val;
@@ -4272,7 +4287,7 @@ __export(exports_config, {
4272
4287
  getAgentTaskListId: () => getAgentTaskListId,
4273
4288
  getAgentPoolForProject: () => getAgentPoolForProject
4274
4289
  });
4275
- import { existsSync as existsSync3 } from "fs";
4290
+ import { existsSync as existsSync4 } from "fs";
4276
4291
  import { join as join4 } from "path";
4277
4292
  function getTodosGlobalDir() {
4278
4293
  const home = process.env["HOME"] || HOME;
@@ -4280,7 +4295,7 @@ function getTodosGlobalDir() {
4280
4295
  const legacyDir = join4(home, ".todos");
4281
4296
  const newConfig = join4(newDir, "config.json");
4282
4297
  const legacyConfig = join4(legacyDir, "config.json");
4283
- if (!existsSync3(newConfig) && existsSync3(legacyConfig))
4298
+ if (!existsSync4(newConfig) && existsSync4(legacyConfig))
4284
4299
  return legacyDir;
4285
4300
  return newDir;
4286
4301
  }
@@ -4296,7 +4311,7 @@ function normalizeAgent(agent) {
4296
4311
  function loadConfig() {
4297
4312
  if (cached)
4298
4313
  return cached;
4299
- if (!existsSync3(getConfigPath())) {
4314
+ if (!existsSync4(getConfigPath())) {
4300
4315
  cached = {};
4301
4316
  return cached;
4302
4317
  }
@@ -8990,7 +9005,7 @@ __export(exports_serve, {
8990
9005
  SECURITY_HEADERS: () => SECURITY_HEADERS,
8991
9006
  MIME_TYPES: () => MIME_TYPES
8992
9007
  });
8993
- import { existsSync as existsSync6 } from "fs";
9008
+ import { existsSync as existsSync7 } from "fs";
8994
9009
  import { join as join9, dirname as dirname3, extname } from "path";
8995
9010
  import { fileURLToPath as fileURLToPath2 } from "url";
8996
9011
  function resolveDashboardDir() {
@@ -9007,7 +9022,7 @@ function resolveDashboardDir() {
9007
9022
  }
9008
9023
  candidates.push(join9(process.cwd(), "dashboard", "dist"));
9009
9024
  for (const candidate of candidates) {
9010
- if (existsSync6(candidate))
9025
+ if (existsSync7(candidate))
9011
9026
  return candidate;
9012
9027
  }
9013
9028
  return join9(process.cwd(), "dashboard", "dist");
@@ -9060,7 +9075,7 @@ function json(data, status = 200, headers) {
9060
9075
  });
9061
9076
  }
9062
9077
  function serveStaticFile(filePath) {
9063
- if (!existsSync6(filePath))
9078
+ if (!existsSync7(filePath))
9064
9079
  return null;
9065
9080
  const ext = extname(filePath);
9066
9081
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
@@ -9139,7 +9154,7 @@ data: ${data}
9139
9154
  filteredSseClients.delete(client);
9140
9155
  }
9141
9156
  const dashboardDir = resolveDashboardDir();
9142
- const dashboardExists = existsSync6(dashboardDir);
9157
+ const dashboardExists = existsSync7(dashboardDir);
9143
9158
  if (!dashboardExists) {
9144
9159
  console.error(`
9145
9160
  Dashboard not found at: ${dashboardDir}`);
@@ -11082,7 +11097,7 @@ __export(exports_dist, {
11082
11097
  import { createRequire } from "module";
11083
11098
  import { Database as Database2 } from "bun:sqlite";
11084
11099
  import {
11085
- existsSync as existsSync8,
11100
+ existsSync as existsSync9,
11086
11101
  mkdirSync as mkdirSync4,
11087
11102
  readdirSync as readdirSync3,
11088
11103
  copyFileSync
@@ -11996,9 +12011,9 @@ function getDbPath2(serviceName) {
11996
12011
  function migrateDotfile(serviceName) {
11997
12012
  const legacyDir = join11(homedir(), `.${serviceName}`);
11998
12013
  const newDir = join11(HASNA_DIR, serviceName);
11999
- if (!existsSync8(legacyDir))
12014
+ if (!existsSync9(legacyDir))
12000
12015
  return [];
12001
- if (existsSync8(newDir))
12016
+ if (existsSync9(newDir))
12002
12017
  return [];
12003
12018
  mkdirSync4(newDir, { recursive: true });
12004
12019
  const migrated = [];
@@ -12020,7 +12035,7 @@ function copyDirRecursive(src, dest, root, migrated) {
12020
12035
  }
12021
12036
  }
12022
12037
  function hasLegacyDotfile(serviceName) {
12023
- return existsSync8(join11(homedir(), `.${serviceName}`));
12038
+ return existsSync9(join11(homedir(), `.${serviceName}`));
12024
12039
  }
12025
12040
  function getHasnaDir() {
12026
12041
  mkdirSync4(HASNA_DIR, { recursive: true });
@@ -31694,23 +31709,11 @@ __export(exports_mcp, {
31694
31709
  });
31695
31710
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
31696
31711
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
31697
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
31698
- import { join as join12, dirname as dirname6 } from "path";
31699
- import { fileURLToPath as fileURLToPath3 } from "url";
31700
31712
  function getMcpVersion() {
31701
- try {
31702
- let dir = dirname6(fileURLToPath3(import.meta.url));
31703
- for (let i = 0;i < 4; i++) {
31704
- const pkgPath = join12(dir, "package.json");
31705
- if (existsSync9(pkgPath)) {
31706
- return JSON.parse(readFileSync7(pkgPath, "utf-8")).version || "0.0.0";
31707
- }
31708
- dir = dirname6(dir);
31709
- }
31710
- } catch {
31711
- return "0.0.0";
31712
- }
31713
- return "0.0.0";
31713
+ return getPackageVersion(import.meta.url);
31714
+ }
31715
+ function hasVersionFlag() {
31716
+ return process.argv.includes("--version") || process.argv.includes("-V");
31714
31717
  }
31715
31718
  function shouldRegisterTool(name) {
31716
31719
  if (TODOS_PROFILE === "minimal")
@@ -31872,6 +31875,11 @@ var init_mcp = __esm(() => {
31872
31875
  init_code_tools();
31873
31876
  init_machines2();
31874
31877
  init_agents2();
31878
+ init_package_version();
31879
+ if (hasVersionFlag()) {
31880
+ console.log(getMcpVersion());
31881
+ process.exit(0);
31882
+ }
31875
31883
  server = new McpServer({
31876
31884
  name: "todos",
31877
31885
  version: getMcpVersion()
@@ -33034,7 +33042,7 @@ import { basename as basename2, resolve as resolve4 } from "path";
33034
33042
  init_tasks();
33035
33043
  init_config();
33036
33044
  init_sync_utils();
33037
- import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync2 } from "fs";
33045
+ import { existsSync as existsSync5, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync2 } from "fs";
33038
33046
  import { join as join5 } from "path";
33039
33047
  function getTaskListDir(taskListId) {
33040
33048
  return join5(HOME, ".claude", "tasks", taskListId);
@@ -33056,7 +33064,7 @@ function toSqliteStatus(status) {
33056
33064
  }
33057
33065
  function readPrefixCounter(dir) {
33058
33066
  const path = join5(dir, ".prefix-counter");
33059
- if (!existsSync4(path))
33067
+ if (!existsSync5(path))
33060
33068
  return 0;
33061
33069
  const val = parseInt(readFileSync3(path, "utf-8").trim(), 10);
33062
33070
  return isNaN(val) ? 0 : val;
@@ -33089,7 +33097,7 @@ function taskToClaudeTask(task, claudeTaskId, existingMeta) {
33089
33097
  }
33090
33098
  function pushToClaudeTaskList(taskListId, projectId, options = {}) {
33091
33099
  const dir = getTaskListDir(taskListId);
33092
- if (!existsSync4(dir))
33100
+ if (!existsSync5(dir))
33093
33101
  ensureDir2(dir);
33094
33102
  const filter = {};
33095
33103
  if (projectId)
@@ -33185,7 +33193,7 @@ function pushToClaudeTaskList(taskListId, projectId, options = {}) {
33185
33193
  }
33186
33194
  function pullFromClaudeTaskList(taskListId, projectId, options = {}) {
33187
33195
  const dir = getTaskListDir(taskListId);
33188
- if (!existsSync4(dir)) {
33196
+ if (!existsSync5(dir)) {
33189
33197
  return { pushed: 0, pulled: 0, errors: [`Task list directory not found: ${dir}`] };
33190
33198
  }
33191
33199
  const files = readdirSync2(dir).filter((f) => f.endsWith(".json"));
@@ -33276,12 +33284,12 @@ function syncClaudeTaskList(taskListId, projectId, options = {}) {
33276
33284
  init_tasks();
33277
33285
  init_sync_utils();
33278
33286
  init_config();
33279
- import { existsSync as existsSync5 } from "fs";
33287
+ import { existsSync as existsSync6 } from "fs";
33280
33288
  import { join as join6 } from "path";
33281
33289
  function getTodosGlobalDir2() {
33282
33290
  const newDir = join6(HOME, ".hasna", "todos");
33283
33291
  const legacyDir = join6(HOME, ".todos");
33284
- if (!existsSync5(newDir) && existsSync5(legacyDir))
33292
+ if (!existsSync6(newDir) && existsSync6(legacyDir))
33285
33293
  return legacyDir;
33286
33294
  return newDir;
33287
33295
  }
@@ -33321,7 +33329,7 @@ function metadataKey(agent) {
33321
33329
  }
33322
33330
  function pushToAgentTaskList(agent, taskListId, projectId, options = {}) {
33323
33331
  const dir = getTaskListDir2(agent, taskListId);
33324
- if (!existsSync5(dir))
33332
+ if (!existsSync6(dir))
33325
33333
  ensureDir2(dir);
33326
33334
  const filter = {};
33327
33335
  if (projectId)
@@ -33404,7 +33412,7 @@ function pushToAgentTaskList(agent, taskListId, projectId, options = {}) {
33404
33412
  }
33405
33413
  function pullFromAgentTaskList(agent, taskListId, projectId, options = {}) {
33406
33414
  const dir = getTaskListDir2(agent, taskListId);
33407
- if (!existsSync5(dir)) {
33415
+ if (!existsSync6(dir)) {
33408
33416
  return { pushed: 0, pulled: 0, errors: [`Task list directory not found: ${dir}`] };
33409
33417
  }
33410
33418
  const files = listJsonFiles(dir);
@@ -34298,7 +34306,7 @@ init_tasks();
34298
34306
  init_config();
34299
34307
  init_helpers();
34300
34308
  import chalk6 from "chalk";
34301
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
34309
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
34302
34310
  import { dirname as dirname4, join as join10 } from "path";
34303
34311
  function registerConfigServeCommands(program2) {
34304
34312
  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) => {
@@ -34306,7 +34314,7 @@ function registerConfigServeCommands(program2) {
34306
34314
  const home = process.env["HOME"] || "~";
34307
34315
  const newPath = join10(home, ".hasna", "todos", "config.json");
34308
34316
  const legacyPath = join10(home, ".todos", "config.json");
34309
- const configPath = !existsSync7(newPath) && existsSync7(legacyPath) ? legacyPath : newPath;
34317
+ const configPath = !existsSync8(newPath) && existsSync8(legacyPath) ? legacyPath : newPath;
34310
34318
  if (opts.get) {
34311
34319
  const config2 = loadConfig();
34312
34320
  const keys = opts.get.split(".");
@@ -34343,7 +34351,7 @@ function registerConfigServeCommands(program2) {
34343
34351
  }
34344
34352
  obj[keys[keys.length - 1]] = parsedValue;
34345
34353
  const dir = dirname4(configPath);
34346
- if (!existsSync7(dir))
34354
+ if (!existsSync8(dir))
34347
34355
  mkdirSync3(dir, { recursive: true });
34348
34356
  writeFileSync3(configPath, JSON.stringify(config2, null, 2));
34349
34357
  if (globalOpts.json) {
@@ -36056,8 +36064,8 @@ init_tasks();
36056
36064
  init_helpers();
36057
36065
  import chalk9 from "chalk";
36058
36066
  import { execSync as execSync3 } from "child_process";
36059
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, chmodSync } from "fs";
36060
- import { dirname as dirname7, join as join13 } from "path";
36067
+ import { existsSync as existsSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, chmodSync } from "fs";
36068
+ import { dirname as dirname6, join as join12 } from "path";
36061
36069
  var HOME2 = process.env["HOME"] || process.env["USERPROFILE"] || "~";
36062
36070
  function getMcpBinaryPath() {
36063
36071
  try {
@@ -36065,7 +36073,7 @@ function getMcpBinaryPath() {
36065
36073
  if (p)
36066
36074
  return p;
36067
36075
  } catch {}
36068
- const bunBin = join13(HOME2, ".bun", "bin", "todos-mcp");
36076
+ const bunBin = join12(HOME2, ".bun", "bin", "todos-mcp");
36069
36077
  if (existsSync10(bunBin))
36070
36078
  return bunBin;
36071
36079
  return "todos-mcp";
@@ -36074,13 +36082,13 @@ function readJsonFile2(path) {
36074
36082
  if (!existsSync10(path))
36075
36083
  return {};
36076
36084
  try {
36077
- return JSON.parse(readFileSync8(path, "utf-8"));
36085
+ return JSON.parse(readFileSync7(path, "utf-8"));
36078
36086
  } catch {
36079
36087
  return {};
36080
36088
  }
36081
36089
  }
36082
36090
  function writeJsonFile2(path, data) {
36083
- const dir = dirname7(path);
36091
+ const dir = dirname6(path);
36084
36092
  if (!existsSync10(dir))
36085
36093
  mkdirSync5(dir, { recursive: true });
36086
36094
  writeFileSync5(path, JSON.stringify(data, null, 2) + `
@@ -36089,10 +36097,10 @@ function writeJsonFile2(path, data) {
36089
36097
  function readTomlFile(path) {
36090
36098
  if (!existsSync10(path))
36091
36099
  return "";
36092
- return readFileSync8(path, "utf-8");
36100
+ return readFileSync7(path, "utf-8");
36093
36101
  }
36094
36102
  function writeTomlFile(path, content) {
36095
- const dir = dirname7(path);
36103
+ const dir = dirname6(path);
36096
36104
  if (!existsSync10(dir))
36097
36105
  mkdirSync5(dir, { recursive: true });
36098
36106
  writeFileSync5(path, content);
@@ -36139,7 +36147,7 @@ function unregisterClaude(_global) {
36139
36147
  }
36140
36148
  }
36141
36149
  function registerCodex(binPath) {
36142
- const configPath = join13(HOME2, ".codex", "config.toml");
36150
+ const configPath = join12(HOME2, ".codex", "config.toml");
36143
36151
  let content = readTomlFile(configPath);
36144
36152
  content = removeTomlBlock(content, "mcp_servers.todos");
36145
36153
  const block = `
@@ -36153,7 +36161,7 @@ args = []
36153
36161
  console.log(chalk9.green(`Codex CLI: registered in ${configPath}`));
36154
36162
  }
36155
36163
  function unregisterCodex() {
36156
- const configPath = join13(HOME2, ".codex", "config.toml");
36164
+ const configPath = join12(HOME2, ".codex", "config.toml");
36157
36165
  let content = readTomlFile(configPath);
36158
36166
  if (!content.includes("[mcp_servers.todos]")) {
36159
36167
  console.log(chalk9.dim(`Codex CLI: todos not found in ${configPath}`));
@@ -36165,7 +36173,7 @@ function unregisterCodex() {
36165
36173
  console.log(chalk9.green(`Codex CLI: unregistered from ${configPath}`));
36166
36174
  }
36167
36175
  function registerGemini(binPath) {
36168
- const configPath = join13(HOME2, ".gemini", "settings.json");
36176
+ const configPath = join12(HOME2, ".gemini", "settings.json");
36169
36177
  const config = readJsonFile2(configPath);
36170
36178
  if (!config["mcpServers"]) {
36171
36179
  config["mcpServers"] = {};
@@ -36179,7 +36187,7 @@ function registerGemini(binPath) {
36179
36187
  console.log(chalk9.green(`Gemini CLI: registered in ${configPath}`));
36180
36188
  }
36181
36189
  function unregisterGemini() {
36182
- const configPath = join13(HOME2, ".gemini", "settings.json");
36190
+ const configPath = join12(HOME2, ".gemini", "settings.json");
36183
36191
  const config = readJsonFile2(configPath);
36184
36192
  const servers = config["mcpServers"];
36185
36193
  if (!servers || !("todos" in servers)) {
@@ -36236,7 +36244,7 @@ function registerMcpHooksCommands(program2) {
36236
36244
  if (p)
36237
36245
  todosBin = p;
36238
36246
  } catch {}
36239
- const hooksDir = join13(process.cwd(), ".claude", "hooks");
36247
+ const hooksDir = join12(process.cwd(), ".claude", "hooks");
36240
36248
  if (!existsSync10(hooksDir))
36241
36249
  mkdirSync5(hooksDir, { recursive: true });
36242
36250
  const hookScript = `#!/usr/bin/env bash
@@ -36262,11 +36270,11 @@ esac
36262
36270
 
36263
36271
  exit 0
36264
36272
  `;
36265
- const hookPath = join13(hooksDir, "todos-sync.sh");
36273
+ const hookPath = join12(hooksDir, "todos-sync.sh");
36266
36274
  writeFileSync5(hookPath, hookScript);
36267
36275
  execSync3(`chmod +x "${hookPath}"`);
36268
36276
  console.log(chalk9.green(`Hook script created: ${hookPath}`));
36269
- const settingsPath = join13(process.cwd(), ".claude", "settings.json");
36277
+ const settingsPath = join12(process.cwd(), ".claude", "settings.json");
36270
36278
  const settings = readJsonFile2(settingsPath);
36271
36279
  if (!settings["hooks"]) {
36272
36280
  settings["hooks"] = {};
@@ -36360,7 +36368,7 @@ exit 0
36360
36368
  const hookPath = `${gitDir}/hooks/post-commit`;
36361
36369
  const marker = "# todos-auto-link";
36362
36370
  if (existsSync10(hookPath)) {
36363
- const existing = readFileSync8(hookPath, "utf-8");
36371
+ const existing = readFileSync7(hookPath, "utf-8");
36364
36372
  if (existing.includes(marker)) {
36365
36373
  console.log(chalk9.yellow("Hook already installed."));
36366
36374
  return;
@@ -36391,7 +36399,7 @@ $(dirname "$0")/../../scripts/post-commit-hook.sh
36391
36399
  console.log(chalk9.dim("No post-commit hook found."));
36392
36400
  return;
36393
36401
  }
36394
- const content = readFileSync8(hookPath, "utf-8");
36402
+ const content = readFileSync7(hookPath, "utf-8");
36395
36403
  if (!content.includes(marker)) {
36396
36404
  console.log(chalk9.dim("Hook not managed by todos."));
36397
36405
  return;
@@ -36555,7 +36563,7 @@ import chalk11 from "chalk";
36555
36563
  import { execSync as execSync4 } from "child_process";
36556
36564
  import { writeFileSync as writeFileSync6 } from "fs";
36557
36565
  import { tmpdir } from "os";
36558
- import { join as join14 } from "path";
36566
+ import { join as join13 } from "path";
36559
36567
  function getOrCreateLocalMachineName() {
36560
36568
  return process.env["TODOS_MACHINE_NAME"] || __require("os").hostname() || "unknown";
36561
36569
  }
@@ -36749,7 +36757,7 @@ Warning: No primary machine set.`));
36749
36757
  if (opts.push) {
36750
36758
  try {
36751
36759
  const localTasks = listTasks3();
36752
- const tmpFile = join14(tmpdir(), `todos-export-${uuid()}.json`);
36760
+ const tmpFile = join13(tmpdir(), `todos-export-${uuid()}.json`);
36753
36761
  writeFileSync6(tmpFile, JSON.stringify(localTasks, null, 2));
36754
36762
  execSync4(`scp ${tmpFile} ${ssh}:/tmp/todos-import.json`, { timeout: 15000 });
36755
36763
  const importCmd = `ssh ${ssh} 'node -e "const fs=require(\\'fs\\');const tasks=JSON.parse(fs.readFileSync(\\'/tmp/todos-import.json\\',\\'utf-8\\'));console.log(JSON.stringify(tasks.length))"'`;
@@ -0,0 +1,2 @@
1
+ export declare function getPackageVersion(fromUrl?: string): string;
2
+ //# sourceMappingURL=package-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../../src/lib/package-version.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,OAAO,SAAkB,GAAG,MAAM,CAgBnE"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AAuGA,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAO9E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AAoGA,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAO9E"}
package/dist/mcp/index.js CHANGED
@@ -22383,9 +22383,6 @@ async function logError(message, opts) {
22383
22383
 
22384
22384
  // src/mcp/index.ts
22385
22385
  init_types2();
22386
- import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
22387
- import { join as join10, dirname as dirname3 } from "path";
22388
- import { fileURLToPath } from "url";
22389
22386
 
22390
22387
  // src/mcp/tools/dispatch.ts
22391
22388
  init_dispatches();
@@ -26062,22 +26059,40 @@ ID: ${updated.id}${taskNote}`
26062
26059
  }
26063
26060
  }
26064
26061
 
26065
- // src/mcp/index.ts
26066
- function getMcpVersion() {
26062
+ // src/lib/package-version.ts
26063
+ import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
26064
+ import { dirname as dirname3, join as join10 } from "path";
26065
+ import { fileURLToPath } from "url";
26066
+ function getPackageVersion(fromUrl = import.meta.url) {
26067
26067
  try {
26068
- let dir = dirname3(fileURLToPath(import.meta.url));
26069
- for (let i = 0;i < 4; i++) {
26068
+ let dir = dirname3(fileURLToPath(fromUrl));
26069
+ for (let i = 0;i < 5; i++) {
26070
26070
  const pkgPath = join10(dir, "package.json");
26071
26071
  if (existsSync10(pkgPath)) {
26072
26072
  return JSON.parse(readFileSync6(pkgPath, "utf-8")).version || "0.0.0";
26073
26073
  }
26074
- dir = dirname3(dir);
26074
+ const parent = dirname3(dir);
26075
+ if (parent === dir)
26076
+ break;
26077
+ dir = parent;
26075
26078
  }
26076
26079
  } catch {
26077
26080
  return "0.0.0";
26078
26081
  }
26079
26082
  return "0.0.0";
26080
26083
  }
26084
+
26085
+ // src/mcp/index.ts
26086
+ function getMcpVersion() {
26087
+ return getPackageVersion(import.meta.url);
26088
+ }
26089
+ function hasVersionFlag() {
26090
+ return process.argv.includes("--version") || process.argv.includes("-V");
26091
+ }
26092
+ if (hasVersionFlag()) {
26093
+ console.log(getMcpVersion());
26094
+ process.exit(0);
26095
+ }
26081
26096
  var server = new McpServer({
26082
26097
  name: "todos",
26083
26098
  version: getMcpVersion()
@@ -1369,18 +1369,18 @@ __export(exports_database, {
1369
1369
  LOCK_EXPIRY_MINUTES: () => LOCK_EXPIRY_MINUTES
1370
1370
  });
1371
1371
  import { Database } from "bun:sqlite";
1372
- import { existsSync, mkdirSync } from "fs";
1373
- import { dirname, join, resolve } from "path";
1372
+ import { existsSync as existsSync2, mkdirSync } from "fs";
1373
+ import { dirname as dirname2, join as join2, resolve } from "path";
1374
1374
  function isInMemoryDb(path) {
1375
1375
  return path === ":memory:" || path.startsWith("file::memory:");
1376
1376
  }
1377
1377
  function findNearestTodosDb(startDir) {
1378
1378
  let dir = resolve(startDir);
1379
1379
  while (true) {
1380
- const candidate = join(dir, ".todos", "todos.db");
1381
- if (existsSync(candidate))
1380
+ const candidate = join2(dir, ".todos", "todos.db");
1381
+ if (existsSync2(candidate))
1382
1382
  return candidate;
1383
- const parent = dirname(dir);
1383
+ const parent = dirname2(dir);
1384
1384
  if (parent === dir)
1385
1385
  break;
1386
1386
  dir = parent;
@@ -1390,9 +1390,9 @@ function findNearestTodosDb(startDir) {
1390
1390
  function findGitRoot(startDir) {
1391
1391
  let dir = resolve(startDir);
1392
1392
  while (true) {
1393
- if (existsSync(join(dir, ".git")))
1393
+ if (existsSync2(join2(dir, ".git")))
1394
1394
  return dir;
1395
- const parent = dirname(dir);
1395
+ const parent = dirname2(dir);
1396
1396
  if (parent === dir)
1397
1397
  break;
1398
1398
  dir = parent;
@@ -1413,13 +1413,13 @@ function getDbPath() {
1413
1413
  if (process.env["TODOS_DB_SCOPE"] === "project") {
1414
1414
  const gitRoot = findGitRoot(cwd);
1415
1415
  if (gitRoot) {
1416
- return join(gitRoot, ".todos", "todos.db");
1416
+ return join2(gitRoot, ".todos", "todos.db");
1417
1417
  }
1418
1418
  }
1419
1419
  const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
1420
- const newPath = join(home, ".hasna", "todos", "todos.db");
1421
- const legacyPath = join(home, ".todos", "todos.db");
1422
- if (!existsSync(newPath) && existsSync(legacyPath)) {
1420
+ const newPath = join2(home, ".hasna", "todos", "todos.db");
1421
+ const legacyPath = join2(home, ".todos", "todos.db");
1422
+ if (!existsSync2(newPath) && existsSync2(legacyPath)) {
1423
1423
  return legacyPath;
1424
1424
  }
1425
1425
  return newPath;
@@ -1427,8 +1427,8 @@ function getDbPath() {
1427
1427
  function ensureDir(filePath) {
1428
1428
  if (isInMemoryDb(filePath))
1429
1429
  return;
1430
- const dir = dirname(resolve(filePath));
1431
- if (!existsSync(dir)) {
1430
+ const dir = dirname2(resolve(filePath));
1431
+ if (!existsSync2(dir)) {
1432
1432
  mkdirSync(dir, { recursive: true });
1433
1433
  }
1434
1434
  }
@@ -1516,11 +1516,34 @@ var init_database = __esm(() => {
1516
1516
  ALLOWED_TABLES = new Set(["tasks", "projects", "agents", "plans", "task_lists", "task_templates"]);
1517
1517
  });
1518
1518
 
1519
+ // src/lib/package-version.ts
1520
+ import { existsSync, readFileSync } from "fs";
1521
+ import { dirname, join } from "path";
1522
+ import { fileURLToPath } from "url";
1523
+ function getPackageVersion(fromUrl = import.meta.url) {
1524
+ try {
1525
+ let dir = dirname(fileURLToPath(fromUrl));
1526
+ for (let i = 0;i < 5; i++) {
1527
+ const pkgPath = join(dir, "package.json");
1528
+ if (existsSync(pkgPath)) {
1529
+ return JSON.parse(readFileSync(pkgPath, "utf-8")).version || "0.0.0";
1530
+ }
1531
+ const parent = dirname(dir);
1532
+ if (parent === dir)
1533
+ break;
1534
+ dir = parent;
1535
+ }
1536
+ } catch {
1537
+ return "0.0.0";
1538
+ }
1539
+ return "0.0.0";
1540
+ }
1541
+
1519
1542
  // src/server/serve.ts
1520
1543
  init_database();
1521
- import { existsSync as existsSync4 } from "fs";
1522
- import { join as join4, dirname as dirname2, extname } from "path";
1523
- import { fileURLToPath } from "url";
1544
+ import { existsSync as existsSync5 } from "fs";
1545
+ import { join as join5, dirname as dirname3, extname } from "path";
1546
+ import { fileURLToPath as fileURLToPath2 } from "url";
1524
1547
 
1525
1548
  // src/db/api-keys.ts
1526
1549
  init_database();
@@ -1629,15 +1652,15 @@ class CompletionGuardError extends Error {
1629
1652
  init_database();
1630
1653
 
1631
1654
  // src/lib/config.ts
1632
- import { existsSync as existsSync3 } from "fs";
1633
- import { join as join2 } from "path";
1655
+ import { existsSync as existsSync4 } from "fs";
1656
+ import { join as join3 } from "path";
1634
1657
 
1635
1658
  // src/lib/sync-utils.ts
1636
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
1659
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, statSync, writeFileSync } from "fs";
1637
1660
  var HOME = process.env["HOME"] || process.env["USERPROFILE"] || "~";
1638
1661
  function readJsonFile(path) {
1639
1662
  try {
1640
- return JSON.parse(readFileSync(path, "utf-8"));
1663
+ return JSON.parse(readFileSync2(path, "utf-8"));
1641
1664
  } catch {
1642
1665
  return null;
1643
1666
  }
@@ -1646,22 +1669,22 @@ function readJsonFile(path) {
1646
1669
  // src/lib/config.ts
1647
1670
  function getTodosGlobalDir() {
1648
1671
  const home = process.env["HOME"] || HOME;
1649
- const newDir = join2(home, ".hasna", "todos");
1650
- const legacyDir = join2(home, ".todos");
1651
- const newConfig = join2(newDir, "config.json");
1652
- const legacyConfig = join2(legacyDir, "config.json");
1653
- if (!existsSync3(newConfig) && existsSync3(legacyConfig))
1672
+ const newDir = join3(home, ".hasna", "todos");
1673
+ const legacyDir = join3(home, ".todos");
1674
+ const newConfig = join3(newDir, "config.json");
1675
+ const legacyConfig = join3(legacyDir, "config.json");
1676
+ if (!existsSync4(newConfig) && existsSync4(legacyConfig))
1654
1677
  return legacyDir;
1655
1678
  return newDir;
1656
1679
  }
1657
1680
  function getConfigPath() {
1658
- return join2(getTodosGlobalDir(), "config.json");
1681
+ return join3(getTodosGlobalDir(), "config.json");
1659
1682
  }
1660
1683
  var cached = null;
1661
1684
  function loadConfig() {
1662
1685
  if (cached)
1663
1686
  return cached;
1664
- if (!existsSync3(getConfigPath())) {
1687
+ if (!existsSync4(getConfigPath())) {
1665
1688
  cached = {};
1666
1689
  return cached;
1667
1690
  }
@@ -3612,7 +3635,7 @@ function listComments(taskId, db) {
3612
3635
  }
3613
3636
 
3614
3637
  // src/server/routes.ts
3615
- import { join as join3, resolve as resolve2, sep } from "path";
3638
+ import { join as join4, resolve as resolve2, sep } from "path";
3616
3639
  function handleSseEvents(_req, url, ctx) {
3617
3640
  const agentId = url.searchParams.get("agent_id") || undefined;
3618
3641
  const projectId = url.searchParams.get("project_id") || undefined;
@@ -4288,7 +4311,7 @@ function handleStaticFiles(path, method, ctx, json2, serveStaticFile2) {
4288
4311
  if (!ctx.dashboardExists || method !== "GET" && method !== "HEAD")
4289
4312
  return null;
4290
4313
  if (path !== "/") {
4291
- const filePath = join3(ctx.dashboardDir, path);
4314
+ const filePath = join4(ctx.dashboardDir, path);
4292
4315
  const resolvedFile = resolve2(filePath);
4293
4316
  const resolvedBase = resolve2(ctx.dashboardDir);
4294
4317
  if (!resolvedFile.startsWith(resolvedBase + sep) && resolvedFile !== resolvedBase) {
@@ -4298,7 +4321,7 @@ function handleStaticFiles(path, method, ctx, json2, serveStaticFile2) {
4298
4321
  if (res2)
4299
4322
  return res2;
4300
4323
  }
4301
- const indexPath = join3(ctx.dashboardDir, "index.html");
4324
+ const indexPath = join4(ctx.dashboardDir, "index.html");
4302
4325
  const res = serveStaticFile2(indexPath);
4303
4326
  if (res)
4304
4327
  return res;
@@ -4309,21 +4332,21 @@ function handleStaticFiles(path, method, ctx, json2, serveStaticFile2) {
4309
4332
  function resolveDashboardDir() {
4310
4333
  const candidates = [];
4311
4334
  try {
4312
- const scriptDir = dirname2(fileURLToPath(import.meta.url));
4313
- candidates.push(join4(scriptDir, "..", "dashboard", "dist"));
4314
- candidates.push(join4(scriptDir, "..", "..", "dashboard", "dist"));
4335
+ const scriptDir = dirname3(fileURLToPath2(import.meta.url));
4336
+ candidates.push(join5(scriptDir, "..", "dashboard", "dist"));
4337
+ candidates.push(join5(scriptDir, "..", "..", "dashboard", "dist"));
4315
4338
  } catch {}
4316
4339
  if (process.argv[1]) {
4317
- const mainDir = dirname2(process.argv[1]);
4318
- candidates.push(join4(mainDir, "..", "dashboard", "dist"));
4319
- candidates.push(join4(mainDir, "..", "..", "dashboard", "dist"));
4340
+ const mainDir = dirname3(process.argv[1]);
4341
+ candidates.push(join5(mainDir, "..", "dashboard", "dist"));
4342
+ candidates.push(join5(mainDir, "..", "..", "dashboard", "dist"));
4320
4343
  }
4321
- candidates.push(join4(process.cwd(), "dashboard", "dist"));
4344
+ candidates.push(join5(process.cwd(), "dashboard", "dist"));
4322
4345
  for (const candidate of candidates) {
4323
- if (existsSync4(candidate))
4346
+ if (existsSync5(candidate))
4324
4347
  return candidate;
4325
4348
  }
4326
- return join4(process.cwd(), "dashboard", "dist");
4349
+ return join5(process.cwd(), "dashboard", "dist");
4327
4350
  }
4328
4351
  var MIME_TYPES = {
4329
4352
  ".html": "text/html; charset=utf-8",
@@ -4395,7 +4418,7 @@ function json(data, status = 200, headers) {
4395
4418
  });
4396
4419
  }
4397
4420
  function serveStaticFile(filePath) {
4398
- if (!existsSync4(filePath))
4421
+ if (!existsSync5(filePath))
4399
4422
  return null;
4400
4423
  const ext = extname(filePath);
4401
4424
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
@@ -4474,7 +4497,7 @@ data: ${data}
4474
4497
  filteredSseClients.delete(client);
4475
4498
  }
4476
4499
  const dashboardDir = resolveDashboardDir();
4477
- const dashboardExists = existsSync4(dashboardDir);
4500
+ const dashboardExists = existsSync5(dashboardDir);
4478
4501
  if (!dashboardExists) {
4479
4502
  console.error(`
4480
4503
  Dashboard not found at: ${dashboardDir}`);
@@ -4748,6 +4771,9 @@ Dashboard not found at: ${dashboardDir}`);
4748
4771
 
4749
4772
  // src/server/index.ts
4750
4773
  var DEFAULT_PORT = 19427;
4774
+ function hasVersionFlag() {
4775
+ return process.argv.includes("--version") || process.argv.includes("-V");
4776
+ }
4751
4777
  function parsePort() {
4752
4778
  const portArg = process.argv.find((a) => a === "--port" || a.startsWith("--port="));
4753
4779
  if (portArg) {
@@ -4779,6 +4805,10 @@ async function findFreePort(start) {
4779
4805
  return start;
4780
4806
  }
4781
4807
  async function main() {
4808
+ if (hasVersionFlag()) {
4809
+ console.log(getPackageVersion());
4810
+ return;
4811
+ }
4782
4812
  const requestedPort = parsePort();
4783
4813
  const port = await findFreePort(requestedPort);
4784
4814
  if (port !== requestedPort) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/todos",
3
- "version": "0.11.36",
3
+ "version": "0.11.37",
4
4
  "description": "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",