@hasna/todos 0.9.46 → 0.9.48

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 CHANGED
@@ -4455,6 +4455,14 @@ var init_plans = __esm(() => {
4455
4455
  });
4456
4456
 
4457
4457
  // src/db/comments.ts
4458
+ var exports_comments = {};
4459
+ __export(exports_comments, {
4460
+ logProgress: () => logProgress,
4461
+ listComments: () => listComments,
4462
+ getComment: () => getComment,
4463
+ deleteComment: () => deleteComment,
4464
+ addComment: () => addComment
4465
+ });
4458
4466
  function addComment(input, db) {
4459
4467
  const d = db || getDatabase();
4460
4468
  if (!getTask(input.task_id, d)) {
@@ -4482,6 +4490,15 @@ function getComment(id, db) {
4482
4490
  const d = db || getDatabase();
4483
4491
  return d.query("SELECT * FROM task_comments WHERE id = ?").get(id);
4484
4492
  }
4493
+ function listComments(taskId, db) {
4494
+ const d = db || getDatabase();
4495
+ return d.query("SELECT * FROM task_comments WHERE task_id = ? ORDER BY created_at").all(taskId);
4496
+ }
4497
+ function deleteComment(id, db) {
4498
+ const d = db || getDatabase();
4499
+ const result = d.run("DELETE FROM task_comments WHERE id = ?", [id]);
4500
+ return result.changes > 0;
4501
+ }
4485
4502
  var init_comments = __esm(() => {
4486
4503
  init_types();
4487
4504
  init_database();
@@ -11264,7 +11281,8 @@ function taskToSummary(task, fields) {
11264
11281
  created_at: task.created_at,
11265
11282
  updated_at: task.updated_at,
11266
11283
  completed_at: task.completed_at,
11267
- due_at: task.due_at
11284
+ due_at: task.due_at,
11285
+ recurrence_rule: task.recurrence_rule
11268
11286
  };
11269
11287
  if (!fields || fields.length === 0)
11270
11288
  return full;
@@ -11555,6 +11573,18 @@ data: ${JSON.stringify({ type: "connected", agent_id: agentId, timestamp: new Da
11555
11573
  return json({ error: e instanceof Error ? e.message : "Failed" }, 500, port);
11556
11574
  }
11557
11575
  }
11576
+ const progressMatch = path.match(/^\/api\/tasks\/([^/]+)\/progress$/);
11577
+ if (progressMatch && method === "GET") {
11578
+ const id = progressMatch[1];
11579
+ const task = getTask(id);
11580
+ if (!task)
11581
+ return json({ error: "Task not found" }, 404, port);
11582
+ const { listComments: listComments2 } = await Promise.resolve().then(() => (init_comments(), exports_comments));
11583
+ const all = listComments2(id);
11584
+ const progress = all.filter((c) => c.type === "progress");
11585
+ const latest = progress[progress.length - 1] || null;
11586
+ return json({ task_id: id, progress_entries: progress, latest, count: progress.length }, 200, port);
11587
+ }
11558
11588
  const taskMatch = path.match(/^\/api\/tasks\/([^/]+)$/);
11559
11589
  if (taskMatch) {
11560
11590
  const id = taskMatch[1];
@@ -14777,6 +14807,61 @@ program2.command("pin <id>").description("Escalate task to critical priority").o
14777
14807
  handleError(new Error("Failed to pin"));
14778
14808
  }
14779
14809
  });
14810
+ program2.command("summary").description("Generate a markdown summary of recent task activity").option("--days <n>", "Days of history to include", "7").option("--project <id>", "Filter to project").option("--agent <id>", "Filter to agent").option("--json", "Output as JSON").action(async (opts) => {
14811
+ const globalOpts = program2.opts();
14812
+ const db = getDatabase();
14813
+ const days = parseInt(opts.days, 10);
14814
+ const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
14815
+ const projectId = opts.project || autoProject(globalOpts);
14816
+ const filter = {};
14817
+ if (projectId)
14818
+ filter.project_id = projectId;
14819
+ if (opts.agent)
14820
+ filter.assigned_to = opts.agent;
14821
+ const { getTasksChangedSince: getTasksChangedSince2 } = (init_tasks(), __toCommonJS(exports_tasks));
14822
+ const changed = getTasksChangedSince2(since, Object.keys(filter).length ? filter : undefined, db);
14823
+ const completed = changed.filter((t) => t.status === "completed");
14824
+ const inProgress = changed.filter((t) => t.status === "in_progress");
14825
+ const failed = changed.filter((t) => t.status === "failed");
14826
+ const allTasks = listTasks({ ...filter, status: "pending" });
14827
+ if (opts.json || globalOpts.json) {
14828
+ console.log(JSON.stringify({ completed, in_progress: inProgress, failed, pending: allTasks.length, period_days: days }, null, 2));
14829
+ return;
14830
+ }
14831
+ const lines = [];
14832
+ lines.push(`## Task Summary \u2014 Last ${days} day${days !== 1 ? "s" : ""}`);
14833
+ lines.push(`*${new Date().toLocaleDateString()}*
14834
+ `);
14835
+ if (completed.length > 0) {
14836
+ lines.push(`### \u2705 Completed (${completed.length})`);
14837
+ for (const t of completed) {
14838
+ const id = t.short_id || t.id.slice(0, 8);
14839
+ const who = t.assigned_to ? ` \u2014 ${t.assigned_to}` : "";
14840
+ lines.push(`- **${id}**: ${t.title}${who}`);
14841
+ }
14842
+ lines.push("");
14843
+ }
14844
+ if (inProgress.length > 0) {
14845
+ lines.push(`### \uD83D\uDD04 In Progress (${inProgress.length})`);
14846
+ for (const t of inProgress) {
14847
+ const id = t.short_id || t.id.slice(0, 8);
14848
+ const who = t.assigned_to ? ` \u2014 ${t.assigned_to}` : "";
14849
+ lines.push(`- **${id}**: ${t.title}${who}`);
14850
+ }
14851
+ lines.push("");
14852
+ }
14853
+ if (failed.length > 0) {
14854
+ lines.push(`### \u274C Failed (${failed.length})`);
14855
+ for (const t of failed) {
14856
+ const id = t.short_id || t.id.slice(0, 8);
14857
+ lines.push(`- **${id}**: ${t.title}`);
14858
+ }
14859
+ lines.push("");
14860
+ }
14861
+ lines.push(`### \uD83D\uDCCB Pending: ${allTasks.length} task${allTasks.length !== 1 ? "s" : ""} remaining`);
14862
+ console.log(lines.join(`
14863
+ `));
14864
+ });
14780
14865
  program2.action(async () => {
14781
14866
  if (process.stdout.isTTY) {
14782
14867
  try {
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export { TodosClient, createClient } from "./sdk.js";
2
+ export type { TodosClientOptions } from "./sdk.js";
1
3
  export { getDatabase, closeDatabase, resetDatabase, resolvePartialId, now, uuid } from "./db/database.js";
2
4
  export { createTask, getTask, getTaskWithRelations, listTasks, countTasks, updateTask, deleteTask, startTask, completeTask, lockTask, unlockTask, addDependency, removeDependency, getTaskDependencies, getTaskDependents, getBlockingDeps, bulkUpdateTasks, bulkCreateTasks, cloneTask, getTaskStats, getTaskGraph, moveTask, getNextTask, claimNextTask, getActiveWork, failTask, getTasksChangedSince, getStaleTasks, getStatus, decomposeTasks, setTaskStatus, setTaskPriority, } from "./db/tasks.js";
3
5
  export type { TaskGraphNode, TaskGraph, BulkCreateTaskInput, ActiveWorkItem, StatusSummary, DecomposeSubtaskInput } from "./db/tasks.js";
@@ -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
@@ -1,4 +1,95 @@
1
1
  // @bun
2
+ // src/sdk.ts
3
+ class TodosClient {
4
+ baseUrl;
5
+ timeout;
6
+ constructor(options = {}) {
7
+ this.baseUrl = options.baseUrl || process.env["TODOS_URL"] || "http://localhost:19427";
8
+ this.timeout = options.timeout || 1e4;
9
+ }
10
+ static fromEnv() {
11
+ return new TodosClient({ baseUrl: process.env["TODOS_URL"] });
12
+ }
13
+ async fetch(path, init) {
14
+ const controller = new AbortController;
15
+ const timer = setTimeout(() => controller.abort(), this.timeout);
16
+ try {
17
+ const res = await fetch(`${this.baseUrl}${path}`, { ...init, signal: controller.signal });
18
+ if (!res.ok) {
19
+ const err = await res.json().catch(() => ({ error: res.statusText }));
20
+ throw new Error(err.error || `HTTP ${res.status}`);
21
+ }
22
+ return res.json();
23
+ } finally {
24
+ clearTimeout(timer);
25
+ }
26
+ }
27
+ async isAlive() {
28
+ try {
29
+ await this.fetch("/api/stats");
30
+ return true;
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+ async getStatus(projectId, agentId) {
36
+ const params = new URLSearchParams;
37
+ if (projectId)
38
+ params.set("project_id", projectId);
39
+ if (agentId)
40
+ params.set("agent_id", agentId);
41
+ return this.fetch(`/api/tasks/status?${params}`);
42
+ }
43
+ async listTasks(filter = {}) {
44
+ const params = new URLSearchParams;
45
+ for (const [k, v] of Object.entries(filter)) {
46
+ if (v !== undefined)
47
+ params.set(k, String(v));
48
+ }
49
+ return this.fetch(`/api/tasks?${params}`);
50
+ }
51
+ async getTask(id) {
52
+ return this.fetch(`/api/tasks/${id}`);
53
+ }
54
+ async getTaskHistory(id) {
55
+ return this.fetch(`/api/tasks/${id}/history`);
56
+ }
57
+ async getTaskProgress(id) {
58
+ return this.fetch(`/api/tasks/${id}/progress`);
59
+ }
60
+ async claimNextTask(agentId, projectId) {
61
+ return this.fetch("/api/tasks/claim", {
62
+ method: "POST",
63
+ headers: { "Content-Type": "application/json" },
64
+ body: JSON.stringify({ agent_id: agentId, project_id: projectId })
65
+ });
66
+ }
67
+ async completeTask(id, agentId) {
68
+ return this.fetch(`/api/tasks/${id}/complete`, {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify({ agent_id: agentId })
72
+ });
73
+ }
74
+ async getStats() {
75
+ return this.fetch("/api/stats");
76
+ }
77
+ async getActiveWork(projectId) {
78
+ const params = new URLSearchParams;
79
+ if (projectId)
80
+ params.set("project_id", projectId);
81
+ return this.fetch(`/api/tasks/active?${params}`);
82
+ }
83
+ async getTasksChangedSince(since, projectId) {
84
+ const params = new URLSearchParams({ since });
85
+ if (projectId)
86
+ params.set("project_id", projectId);
87
+ return this.fetch(`/api/tasks/changed?${params}`);
88
+ }
89
+ }
90
+ function createClient(options) {
91
+ return new TodosClient(options);
92
+ }
2
93
  // src/db/database.ts
3
94
  import { Database } from "bun:sqlite";
4
95
  import { existsSync, mkdirSync } from "fs";
@@ -3180,6 +3271,7 @@ export {
3180
3271
  createProject,
3181
3272
  createPlan,
3182
3273
  createOrg,
3274
+ createClient,
3183
3275
  countTasks,
3184
3276
  completeTask,
3185
3277
  closeDatabase,
@@ -3191,6 +3283,7 @@ export {
3191
3283
  addDependency,
3192
3284
  addComment,
3193
3285
  VersionConflictError,
3286
+ TodosClient,
3194
3287
  TaskNotFoundError,
3195
3288
  TaskListNotFoundError,
3196
3289
  TASK_STATUSES,
package/dist/sdk.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @hasna/todos REST SDK Client
3
+ * Zero-dependency HTTP client for the todos REST API (todos serve).
4
+ * Use when you need to interact with todos from another machine or process.
5
+ */
6
+ export interface TodosClientOptions {
7
+ baseUrl?: string;
8
+ timeout?: number;
9
+ }
10
+ export declare class TodosClient {
11
+ private baseUrl;
12
+ private timeout;
13
+ constructor(options?: TodosClientOptions);
14
+ static fromEnv(): TodosClient;
15
+ private fetch;
16
+ isAlive(): Promise<boolean>;
17
+ getStatus(projectId?: string, agentId?: string): Promise<any>;
18
+ listTasks(filter?: {
19
+ status?: string;
20
+ project_id?: string;
21
+ assigned_to?: string;
22
+ limit?: number;
23
+ offset?: number;
24
+ session_id?: string;
25
+ }): Promise<any[]>;
26
+ getTask(id: string): Promise<any>;
27
+ getTaskHistory(id: string): Promise<any[]>;
28
+ getTaskProgress(id: string): Promise<any>;
29
+ claimNextTask(agentId: string, projectId?: string): Promise<any>;
30
+ completeTask(id: string, agentId?: string): Promise<any>;
31
+ getStats(): Promise<any>;
32
+ getActiveWork(projectId?: string): Promise<any[]>;
33
+ getTasksChangedSince(since: string, projectId?: string): Promise<any>;
34
+ }
35
+ export declare function createClient(options?: TodosClientOptions): TodosClient;
36
+ //# sourceMappingURL=sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,kBAAuB;IAK5C,MAAM,CAAC,OAAO,IAAI,WAAW;YAIf,KAAK;IAeb,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAO3B,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAO7D,SAAS,CAAC,MAAM,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAQ5J,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIjC,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAI1C,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIzC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAQhE,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAQxD,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC;IAIxB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAMjD,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CAK5E;AAED,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAEtE"}
@@ -2159,6 +2159,57 @@ var init_agents = __esm(() => {
2159
2159
  init_database();
2160
2160
  });
2161
2161
 
2162
+ // src/db/comments.ts
2163
+ var exports_comments = {};
2164
+ __export(exports_comments, {
2165
+ logProgress: () => logProgress,
2166
+ listComments: () => listComments,
2167
+ getComment: () => getComment,
2168
+ deleteComment: () => deleteComment,
2169
+ addComment: () => addComment
2170
+ });
2171
+ function addComment(input, db) {
2172
+ const d = db || getDatabase();
2173
+ if (!getTask(input.task_id, d)) {
2174
+ throw new TaskNotFoundError(input.task_id);
2175
+ }
2176
+ const id = uuid();
2177
+ const timestamp = now();
2178
+ d.run(`INSERT INTO task_comments (id, task_id, agent_id, session_id, content, type, progress_pct, created_at)
2179
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
2180
+ id,
2181
+ input.task_id,
2182
+ input.agent_id || null,
2183
+ input.session_id || null,
2184
+ input.content,
2185
+ input.type || "comment",
2186
+ input.progress_pct ?? null,
2187
+ timestamp
2188
+ ]);
2189
+ return getComment(id, d);
2190
+ }
2191
+ function logProgress(taskId, message, pct, agentId, db) {
2192
+ return addComment({ task_id: taskId, content: message, type: "progress", progress_pct: pct, agent_id: agentId }, db);
2193
+ }
2194
+ function getComment(id, db) {
2195
+ const d = db || getDatabase();
2196
+ return d.query("SELECT * FROM task_comments WHERE id = ?").get(id);
2197
+ }
2198
+ function listComments(taskId, db) {
2199
+ const d = db || getDatabase();
2200
+ return d.query("SELECT * FROM task_comments WHERE task_id = ? ORDER BY created_at").all(taskId);
2201
+ }
2202
+ function deleteComment(id, db) {
2203
+ const d = db || getDatabase();
2204
+ const result = d.run("DELETE FROM task_comments WHERE id = ?", [id]);
2205
+ return result.changes > 0;
2206
+ }
2207
+ var init_comments = __esm(() => {
2208
+ init_types();
2209
+ init_database();
2210
+ init_tasks();
2211
+ });
2212
+
2162
2213
  // src/db/orgs.ts
2163
2214
  var exports_orgs = {};
2164
2215
  __export(exports_orgs, {
@@ -2444,7 +2495,8 @@ function taskToSummary(task, fields) {
2444
2495
  created_at: task.created_at,
2445
2496
  updated_at: task.updated_at,
2446
2497
  completed_at: task.completed_at,
2447
- due_at: task.due_at
2498
+ due_at: task.due_at,
2499
+ recurrence_rule: task.recurrence_rule
2448
2500
  };
2449
2501
  if (!fields || fields.length === 0)
2450
2502
  return full;
@@ -2735,6 +2787,18 @@ data: ${JSON.stringify({ type: "connected", agent_id: agentId, timestamp: new Da
2735
2787
  return json({ error: e instanceof Error ? e.message : "Failed" }, 500, port);
2736
2788
  }
2737
2789
  }
2790
+ const progressMatch = path.match(/^\/api\/tasks\/([^/]+)\/progress$/);
2791
+ if (progressMatch && method === "GET") {
2792
+ const id = progressMatch[1];
2793
+ const task = getTask(id);
2794
+ if (!task)
2795
+ return json({ error: "Task not found" }, 404, port);
2796
+ const { listComments: listComments2 } = await Promise.resolve().then(() => (init_comments(), exports_comments));
2797
+ const all = listComments2(id);
2798
+ const progress = all.filter((c) => c.type === "progress");
2799
+ const latest = progress[progress.length - 1] || null;
2800
+ return json({ task_id: id, progress_entries: progress, latest, count: progress.length }, 200, port);
2801
+ }
2738
2802
  const taskMatch = path.match(/^\/api\/tasks\/([^/]+)$/);
2739
2803
  if (taskMatch) {
2740
2804
  const id = taskMatch[1];
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/server/serve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgHH,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,CA6tB1G"}
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,CA0uB1G"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/todos",
3
- "version": "0.9.46",
3
+ "version": "0.9.48",
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",