@hasna/todos 0.11.23 → 0.11.25
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 +69 -21
- package/dist/index.js +12 -9
- package/dist/mcp/index.js +12 -9
- package/dist/server/index.js +12 -9
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3623,7 +3623,9 @@ function getTodosGlobalDir() {
|
|
|
3623
3623
|
const home = process.env["HOME"] || HOME;
|
|
3624
3624
|
const newDir = join3(home, ".hasna", "todos");
|
|
3625
3625
|
const legacyDir = join3(home, ".todos");
|
|
3626
|
-
|
|
3626
|
+
const newConfig = join3(newDir, "config.json");
|
|
3627
|
+
const legacyConfig = join3(legacyDir, "config.json");
|
|
3628
|
+
if (!existsSync3(newConfig) && existsSync3(legacyConfig))
|
|
3627
3629
|
return legacyDir;
|
|
3628
3630
|
return newDir;
|
|
3629
3631
|
}
|
|
@@ -4426,15 +4428,16 @@ function taskFromTemplate(templateId, overrides = {}, db) {
|
|
|
4426
4428
|
const t = getTemplate(templateId, db);
|
|
4427
4429
|
if (!t)
|
|
4428
4430
|
throw new Error(`Template not found: ${templateId}`);
|
|
4431
|
+
const cleanOverrides = Object.fromEntries(Object.entries(overrides).filter(([, v]) => v !== undefined));
|
|
4429
4432
|
return {
|
|
4430
|
-
title:
|
|
4431
|
-
description:
|
|
4432
|
-
priority:
|
|
4433
|
-
tags:
|
|
4434
|
-
project_id:
|
|
4435
|
-
plan_id:
|
|
4436
|
-
metadata:
|
|
4437
|
-
...
|
|
4433
|
+
title: cleanOverrides.title || t.title_pattern,
|
|
4434
|
+
description: cleanOverrides.description ?? t.description ?? undefined,
|
|
4435
|
+
priority: cleanOverrides.priority ?? t.priority,
|
|
4436
|
+
tags: cleanOverrides.tags ?? t.tags,
|
|
4437
|
+
project_id: cleanOverrides.project_id ?? t.project_id ?? undefined,
|
|
4438
|
+
plan_id: cleanOverrides.plan_id ?? t.plan_id ?? undefined,
|
|
4439
|
+
metadata: cleanOverrides.metadata ?? t.metadata,
|
|
4440
|
+
...cleanOverrides
|
|
4438
4441
|
};
|
|
4439
4442
|
}
|
|
4440
4443
|
function addTemplateTasks(templateId, tasks, db) {
|
|
@@ -32726,6 +32729,29 @@ function autoDetectProject(opts) {
|
|
|
32726
32729
|
function autoProject(opts) {
|
|
32727
32730
|
return autoDetectProject(opts)?.id;
|
|
32728
32731
|
}
|
|
32732
|
+
function normalizeStatus(s) {
|
|
32733
|
+
switch (s.toLowerCase().trim()) {
|
|
32734
|
+
case "done":
|
|
32735
|
+
return "completed";
|
|
32736
|
+
case "complete":
|
|
32737
|
+
return "completed";
|
|
32738
|
+
case "active":
|
|
32739
|
+
return "in_progress";
|
|
32740
|
+
case "wip":
|
|
32741
|
+
return "in_progress";
|
|
32742
|
+
case "cancelled":
|
|
32743
|
+
return "cancelled";
|
|
32744
|
+
case "canceled":
|
|
32745
|
+
return "cancelled";
|
|
32746
|
+
default:
|
|
32747
|
+
return s;
|
|
32748
|
+
}
|
|
32749
|
+
}
|
|
32750
|
+
function normalizeStatusList(statuses) {
|
|
32751
|
+
if (Array.isArray(statuses))
|
|
32752
|
+
return statuses.map(normalizeStatus);
|
|
32753
|
+
return normalizeStatus(statuses);
|
|
32754
|
+
}
|
|
32729
32755
|
function output(data, jsonMode) {
|
|
32730
32756
|
if (jsonMode) {
|
|
32731
32757
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -32784,7 +32810,7 @@ program2.command("add <title>").description("Create a new task").option("-d, --d
|
|
|
32784
32810
|
return id;
|
|
32785
32811
|
})() : undefined,
|
|
32786
32812
|
assigned_to: opts.assign,
|
|
32787
|
-
status: opts.status,
|
|
32813
|
+
status: opts.status ? normalizeStatus(opts.status) : undefined,
|
|
32788
32814
|
task_list_id: taskListId,
|
|
32789
32815
|
agent_id: globalOpts.agent,
|
|
32790
32816
|
session_id: globalOpts.session,
|
|
@@ -32821,7 +32847,7 @@ program2.command("list").description("List tasks").option("-s, --status <status>
|
|
|
32821
32847
|
filter["task_list_id"] = listId;
|
|
32822
32848
|
}
|
|
32823
32849
|
if (opts.status) {
|
|
32824
|
-
filter["status"] = opts.status.includes(",") ? opts.status.split(",").map((s) => s.trim()) : opts.status;
|
|
32850
|
+
filter["status"] = opts.status.includes(",") ? opts.status.split(",").map((s) => normalizeStatus(s.trim())) : normalizeStatus(opts.status);
|
|
32825
32851
|
} else if (!opts.all) {
|
|
32826
32852
|
filter["status"] = ["pending", "in_progress"];
|
|
32827
32853
|
}
|
|
@@ -33198,7 +33224,7 @@ program2.command("update <id>").description("Update a task").option("--title <te
|
|
|
33198
33224
|
version: current.version,
|
|
33199
33225
|
title: opts.title,
|
|
33200
33226
|
description: opts.description,
|
|
33201
|
-
status: opts.status,
|
|
33227
|
+
status: opts.status ? normalizeStatus(opts.status) : undefined,
|
|
33202
33228
|
priority: opts.priority,
|
|
33203
33229
|
assigned_to: opts.assign,
|
|
33204
33230
|
tags: opts.tags ? opts.tags.split(",").map((t) => t.trim()) : undefined,
|
|
@@ -33484,7 +33510,7 @@ program2.command("plans").description("List and manage plans").option("--add <na
|
|
|
33484
33510
|
console.log(`${chalk3.dim(p.id.slice(0, 8))} ${chalk3.bold(p.name)} ${chalk3.cyan(`[${p.status}]`)}${desc}`);
|
|
33485
33511
|
}
|
|
33486
33512
|
});
|
|
33487
|
-
program2.command("templates").description("List and manage task templates").option("--add <name>", "Create a template").option("--title <pattern>", "Title pattern (with --add)").option("-d, --description <text>", "Default description").option("-p, --priority <level>", "Default priority").option("-t, --tags <tags>", "Default tags (comma-separated)").option("--delete <id>", "Delete a template").option("--update <id>", "Update a template").option("--use <id>", "Create a task from a template").action((opts) => {
|
|
33513
|
+
program2.command("templates").description("List and manage task templates").option("--add <name>", "Create a template").option("--title <pattern>", "Title pattern (with --add)").option("-d, --description <text>", "Default description").option("-p, --priority <level>", "Default priority").option("-t, --tags <tags>", "Default tags (comma-separated)").option("--delete <id>", "Delete a template").option("--update <id>", "Update a template").option("--use <id>", "Create a task from a template").option("--var <vars...>", "Variable substitutions: key=value (e.g. --var feature=login)").action((opts) => {
|
|
33488
33514
|
const globalOpts = program2.opts();
|
|
33489
33515
|
const { createTemplate: createTemplate2, listTemplates: listTemplates2, deleteTemplate: deleteTemplate2, updateTemplate: updateTemplate2, taskFromTemplate: taskFromTemplate2 } = (init_templates(), __toCommonJS(exports_templates));
|
|
33490
33516
|
if (opts.add) {
|
|
@@ -33546,12 +33572,30 @@ program2.command("templates").description("List and manage task templates").opti
|
|
|
33546
33572
|
}
|
|
33547
33573
|
if (opts.use) {
|
|
33548
33574
|
try {
|
|
33575
|
+
const variables = {};
|
|
33576
|
+
if (opts.var) {
|
|
33577
|
+
for (const v of opts.var) {
|
|
33578
|
+
const eq = v.indexOf("=");
|
|
33579
|
+
if (eq === -1) {
|
|
33580
|
+
console.error(chalk3.red(`Invalid variable format: ${v} (expected key=value)`));
|
|
33581
|
+
process.exit(1);
|
|
33582
|
+
}
|
|
33583
|
+
variables[v.slice(0, eq)] = v.slice(eq + 1);
|
|
33584
|
+
}
|
|
33585
|
+
}
|
|
33549
33586
|
const input = taskFromTemplate2(opts.use, {
|
|
33550
33587
|
title: opts.title,
|
|
33551
33588
|
description: opts.description,
|
|
33552
33589
|
priority: opts.priority
|
|
33553
33590
|
});
|
|
33554
|
-
|
|
33591
|
+
if (input.title) {
|
|
33592
|
+
let title = input.title;
|
|
33593
|
+
for (const [k, v] of Object.entries(variables)) {
|
|
33594
|
+
title = title.replace(new RegExp(`\\{${k}\\}`, "g"), v);
|
|
33595
|
+
}
|
|
33596
|
+
input.title = title;
|
|
33597
|
+
}
|
|
33598
|
+
const task = createTask({ ...input, agent_id: globalOpts.agent, project_id: input.project_id || autoProject(globalOpts) });
|
|
33555
33599
|
if (globalOpts.json) {
|
|
33556
33600
|
output(task, true);
|
|
33557
33601
|
} else {
|
|
@@ -33640,16 +33684,17 @@ program2.command("template-export <id>").alias("templates-export").description("
|
|
|
33640
33684
|
handleError(e);
|
|
33641
33685
|
}
|
|
33642
33686
|
});
|
|
33643
|
-
program2.command("template-import").alias("templates-import").description("Import a template from a JSON file").option("--file <path>", "Path to template JSON file").action((opts) => {
|
|
33687
|
+
program2.command("template-import [file]").alias("templates-import").description("Import a template from a JSON file").option("--file <path>", "Path to template JSON file (alternative to positional arg)").action((file, opts) => {
|
|
33644
33688
|
const globalOpts = program2.opts();
|
|
33645
33689
|
const { importTemplate: importTemplate2 } = (init_templates(), __toCommonJS(exports_templates));
|
|
33646
33690
|
const { readFileSync: readFileSync8 } = __require("fs");
|
|
33647
33691
|
try {
|
|
33648
|
-
|
|
33649
|
-
|
|
33692
|
+
const filePath = file || opts.file;
|
|
33693
|
+
if (!filePath) {
|
|
33694
|
+
console.error(chalk3.red("Provide a file path: todos template-import <file> or --file <path>"));
|
|
33650
33695
|
process.exit(1);
|
|
33651
33696
|
}
|
|
33652
|
-
const content = readFileSync8(
|
|
33697
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
33653
33698
|
const json2 = JSON.parse(content);
|
|
33654
33699
|
const template = importTemplate2(json2);
|
|
33655
33700
|
if (globalOpts.json) {
|
|
@@ -33708,7 +33753,7 @@ program2.command("search <query>").description("Search tasks").option("--status
|
|
|
33708
33753
|
const projectId = autoProject(globalOpts);
|
|
33709
33754
|
const searchOpts = { query, project_id: projectId };
|
|
33710
33755
|
if (opts.status)
|
|
33711
|
-
searchOpts.status = opts.status;
|
|
33756
|
+
searchOpts.status = normalizeStatusList(opts.status);
|
|
33712
33757
|
if (opts.priority)
|
|
33713
33758
|
searchOpts.priority = opts.priority;
|
|
33714
33759
|
if (opts.assigned)
|
|
@@ -34735,7 +34780,10 @@ Updated to ${latestVersion}!`));
|
|
|
34735
34780
|
});
|
|
34736
34781
|
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) => {
|
|
34737
34782
|
const globalOpts = program2.opts();
|
|
34738
|
-
const
|
|
34783
|
+
const home = process.env["HOME"] || "~";
|
|
34784
|
+
const newPath = join12(home, ".hasna", "todos", "config.json");
|
|
34785
|
+
const legacyPath = join12(home, ".todos", "config.json");
|
|
34786
|
+
const configPath = !existsSync10(newPath) && existsSync10(legacyPath) ? legacyPath : newPath;
|
|
34739
34787
|
if (opts.get) {
|
|
34740
34788
|
const config2 = loadConfig();
|
|
34741
34789
|
const keys = opts.get.split(".");
|
|
@@ -34810,7 +34858,7 @@ program2.command("watch").description("Live-updating task list (refreshes every
|
|
|
34810
34858
|
const globalOpts = program2.opts();
|
|
34811
34859
|
const projectId = autoProject(globalOpts);
|
|
34812
34860
|
const interval = parseInt(opts.interval, 10) * 1000;
|
|
34813
|
-
const statusFilter = opts.status ? opts.status.split(",").map((s) => s.trim()) : ["pending", "in_progress"];
|
|
34861
|
+
const statusFilter = opts.status ? opts.status.split(",").map((s) => normalizeStatus(s.trim())) : ["pending", "in_progress"];
|
|
34814
34862
|
function render2() {
|
|
34815
34863
|
const tasks = listTasks({ project_id: projectId, status: statusFilter });
|
|
34816
34864
|
const all = listTasks({ project_id: projectId });
|
package/dist/index.js
CHANGED
|
@@ -1850,7 +1850,9 @@ function getTodosGlobalDir() {
|
|
|
1850
1850
|
const home = process.env["HOME"] || HOME;
|
|
1851
1851
|
const newDir = join3(home, ".hasna", "todos");
|
|
1852
1852
|
const legacyDir = join3(home, ".todos");
|
|
1853
|
-
|
|
1853
|
+
const newConfig = join3(newDir, "config.json");
|
|
1854
|
+
const legacyConfig = join3(legacyDir, "config.json");
|
|
1855
|
+
if (!existsSync3(newConfig) && existsSync3(legacyConfig))
|
|
1854
1856
|
return legacyDir;
|
|
1855
1857
|
return newDir;
|
|
1856
1858
|
}
|
|
@@ -2553,15 +2555,16 @@ function taskFromTemplate(templateId, overrides = {}, db) {
|
|
|
2553
2555
|
const t = getTemplate(templateId, db);
|
|
2554
2556
|
if (!t)
|
|
2555
2557
|
throw new Error(`Template not found: ${templateId}`);
|
|
2558
|
+
const cleanOverrides = Object.fromEntries(Object.entries(overrides).filter(([, v]) => v !== undefined));
|
|
2556
2559
|
return {
|
|
2557
|
-
title:
|
|
2558
|
-
description:
|
|
2559
|
-
priority:
|
|
2560
|
-
tags:
|
|
2561
|
-
project_id:
|
|
2562
|
-
plan_id:
|
|
2563
|
-
metadata:
|
|
2564
|
-
...
|
|
2560
|
+
title: cleanOverrides.title || t.title_pattern,
|
|
2561
|
+
description: cleanOverrides.description ?? t.description ?? undefined,
|
|
2562
|
+
priority: cleanOverrides.priority ?? t.priority,
|
|
2563
|
+
tags: cleanOverrides.tags ?? t.tags,
|
|
2564
|
+
project_id: cleanOverrides.project_id ?? t.project_id ?? undefined,
|
|
2565
|
+
plan_id: cleanOverrides.plan_id ?? t.plan_id ?? undefined,
|
|
2566
|
+
metadata: cleanOverrides.metadata ?? t.metadata,
|
|
2567
|
+
...cleanOverrides
|
|
2565
2568
|
};
|
|
2566
2569
|
}
|
|
2567
2570
|
function addTemplateTasks(templateId, tasks, db) {
|
package/dist/mcp/index.js
CHANGED
|
@@ -12602,7 +12602,9 @@ function getTodosGlobalDir() {
|
|
|
12602
12602
|
const home = process.env["HOME"] || HOME;
|
|
12603
12603
|
const newDir = join9(home, ".hasna", "todos");
|
|
12604
12604
|
const legacyDir = join9(home, ".todos");
|
|
12605
|
-
|
|
12605
|
+
const newConfig = join9(newDir, "config.json");
|
|
12606
|
+
const legacyConfig = join9(legacyDir, "config.json");
|
|
12607
|
+
if (!existsSync9(newConfig) && existsSync9(legacyConfig))
|
|
12606
12608
|
return legacyDir;
|
|
12607
12609
|
return newDir;
|
|
12608
12610
|
}
|
|
@@ -13283,15 +13285,16 @@ function taskFromTemplate(templateId, overrides = {}, db) {
|
|
|
13283
13285
|
const t = getTemplate(templateId, db);
|
|
13284
13286
|
if (!t)
|
|
13285
13287
|
throw new Error(`Template not found: ${templateId}`);
|
|
13288
|
+
const cleanOverrides = Object.fromEntries(Object.entries(overrides).filter(([, v]) => v !== undefined));
|
|
13286
13289
|
return {
|
|
13287
|
-
title:
|
|
13288
|
-
description:
|
|
13289
|
-
priority:
|
|
13290
|
-
tags:
|
|
13291
|
-
project_id:
|
|
13292
|
-
plan_id:
|
|
13293
|
-
metadata:
|
|
13294
|
-
...
|
|
13290
|
+
title: cleanOverrides.title || t.title_pattern,
|
|
13291
|
+
description: cleanOverrides.description ?? t.description ?? undefined,
|
|
13292
|
+
priority: cleanOverrides.priority ?? t.priority,
|
|
13293
|
+
tags: cleanOverrides.tags ?? t.tags,
|
|
13294
|
+
project_id: cleanOverrides.project_id ?? t.project_id ?? undefined,
|
|
13295
|
+
plan_id: cleanOverrides.plan_id ?? t.plan_id ?? undefined,
|
|
13296
|
+
metadata: cleanOverrides.metadata ?? t.metadata,
|
|
13297
|
+
...cleanOverrides
|
|
13295
13298
|
};
|
|
13296
13299
|
}
|
|
13297
13300
|
function addTemplateTasks(templateId, tasks, db) {
|
package/dist/server/index.js
CHANGED
|
@@ -1403,7 +1403,9 @@ function getTodosGlobalDir() {
|
|
|
1403
1403
|
const home = process.env["HOME"] || HOME;
|
|
1404
1404
|
const newDir = join2(home, ".hasna", "todos");
|
|
1405
1405
|
const legacyDir = join2(home, ".todos");
|
|
1406
|
-
|
|
1406
|
+
const newConfig = join2(newDir, "config.json");
|
|
1407
|
+
const legacyConfig = join2(legacyDir, "config.json");
|
|
1408
|
+
if (!existsSync3(newConfig) && existsSync3(legacyConfig))
|
|
1407
1409
|
return legacyDir;
|
|
1408
1410
|
return newDir;
|
|
1409
1411
|
}
|
|
@@ -2151,15 +2153,16 @@ function taskFromTemplate(templateId, overrides = {}, db) {
|
|
|
2151
2153
|
const t = getTemplate(templateId, db);
|
|
2152
2154
|
if (!t)
|
|
2153
2155
|
throw new Error(`Template not found: ${templateId}`);
|
|
2156
|
+
const cleanOverrides = Object.fromEntries(Object.entries(overrides).filter(([, v]) => v !== undefined));
|
|
2154
2157
|
return {
|
|
2155
|
-
title:
|
|
2156
|
-
description:
|
|
2157
|
-
priority:
|
|
2158
|
-
tags:
|
|
2159
|
-
project_id:
|
|
2160
|
-
plan_id:
|
|
2161
|
-
metadata:
|
|
2162
|
-
...
|
|
2158
|
+
title: cleanOverrides.title || t.title_pattern,
|
|
2159
|
+
description: cleanOverrides.description ?? t.description ?? undefined,
|
|
2160
|
+
priority: cleanOverrides.priority ?? t.priority,
|
|
2161
|
+
tags: cleanOverrides.tags ?? t.tags,
|
|
2162
|
+
project_id: cleanOverrides.project_id ?? t.project_id ?? undefined,
|
|
2163
|
+
plan_id: cleanOverrides.plan_id ?? t.plan_id ?? undefined,
|
|
2164
|
+
metadata: cleanOverrides.metadata ?? t.metadata,
|
|
2165
|
+
...cleanOverrides
|
|
2163
2166
|
};
|
|
2164
2167
|
}
|
|
2165
2168
|
function addTemplateTasks(templateId, tasks, db) {
|