@task-mcp/cli 1.0.5 → 1.0.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@task-mcp/cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Zero-dependency CLI for task-mcp with Bun native visualization",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,6 +29,10 @@
29
29
  "url": "git+https://github.com/addsalt1t/task-mcp.git",
30
30
  "directory": "packages/cli"
31
31
  },
32
+ "dependencies": {
33
+ "@task-mcp/mcp-server": "^1.0.9",
34
+ "@task-mcp/shared": "^1.0.8"
35
+ },
32
36
  "devDependencies": {
33
37
  "@types/bun": "^1.1.14",
34
38
  "typescript": "^5.7.2"
package/src/ansi.ts CHANGED
@@ -407,16 +407,3 @@ export function banner(text: string): string {
407
407
  return lines.map(l => c.cyan(l)).join("\n");
408
408
  }
409
409
 
410
- /**
411
- * Clear screen
412
- */
413
- export function clearScreen(): void {
414
- process.stdout.write("\x1b[2J\x1b[H");
415
- }
416
-
417
- /**
418
- * Move cursor
419
- */
420
- export function moveCursor(row: number, col: number): void {
421
- process.stdout.write(`\x1b[${row};${col}H`);
422
- }
@@ -4,10 +4,8 @@
4
4
  */
5
5
 
6
6
  import { c } from "../ansi.js";
7
- import { InboxStore } from "../../../mcp-server/src/storage/inbox-store.js";
8
- import { TaskStore } from "../../../mcp-server/src/storage/task-store.js";
9
- import { ProjectStore } from "../../../mcp-server/src/storage/project-store.js";
10
- import { parseInboxInput } from "../../../shared/src/utils/natural-language.js";
7
+ import { InboxStore, TaskStore, ProjectStore } from "@task-mcp/mcp-server/storage";
8
+ import { parseInboxInput } from "@task-mcp/shared";
11
9
 
12
10
  const inboxStore = new InboxStore();
13
11
  const taskStore = new TaskStore();
@@ -84,7 +82,7 @@ export async function inboxListCmd(options: InboxListOptions): Promise<void> {
84
82
 
85
83
  const date = new Date(item.capturedAt).toLocaleDateString();
86
84
  const tags = item.tags?.length
87
- ? " " + item.tags.map((t) => c.dim("#" + t)).join(" ")
85
+ ? " " + item.tags.map((t: string) => c.dim("#" + t)).join(" ")
88
86
  : "";
89
87
 
90
88
  console.log(`${statusIcon} ${c.cyan(item.id)} ${c.dim("(" + date + ")")}`);
@@ -121,7 +119,7 @@ export async function inboxGetCmd(itemId: string): Promise<void> {
121
119
  console.log(" " + c.dim("Source:") + " " + item.source);
122
120
  }
123
121
  if (item.tags?.length) {
124
- console.log(" " + c.dim("Tags:") + " " + item.tags.map((t) => c.yellow("#" + t)).join(" "));
122
+ console.log(" " + c.dim("Tags:") + " " + item.tags.map((t: string) => c.yellow("#" + t)).join(" "));
125
123
  }
126
124
  console.log();
127
125
  console.log(c.bold("Content:"));
package/src/index.ts CHANGED
@@ -27,7 +27,8 @@ import {
27
27
  inboxCountCmd,
28
28
  } from "./commands/inbox.js";
29
29
 
30
- export const VERSION = "1.0.4";
30
+ import pkg from "../package.json" with { type: "json" };
31
+ export const VERSION = pkg.version;
31
32
 
32
33
  export interface ParsedArgs {
33
34
  command: string;
package/src/storage.ts CHANGED
@@ -81,23 +81,6 @@ function isValidProjectId(id: string): boolean {
81
81
  return /^proj_[a-z0-9]+$/.test(id);
82
82
  }
83
83
 
84
- /**
85
- * Validate a task ID format.
86
- * Valid format: task_[alphanumeric only]
87
- */
88
- function isValidTaskId(id: string): boolean {
89
- return /^task_[a-z0-9]+$/.test(id);
90
- }
91
-
92
- async function fileExists(path: string): Promise<boolean> {
93
- try {
94
- await readFile(path);
95
- return true;
96
- } catch {
97
- return false;
98
- }
99
- }
100
-
101
84
  async function readJson<T>(path: string): Promise<T | null> {
102
85
  try {
103
86
  const content = await readFile(path, "utf-8");
@@ -118,39 +101,30 @@ async function listDirs(path: string): Promise<string[]> {
118
101
 
119
102
  /**
120
103
  * List all projects
121
- * Uses Promise.all for parallel I/O instead of sequential reads
104
+ * Uses Promise.allSettled for parallel I/O with graceful error handling
122
105
  */
123
106
  export async function listProjects(includeArchived = false): Promise<Project[]> {
124
107
  const projectsDir = join(getTasksDir(), "projects");
125
108
  const projectIds = await listDirs(projectsDir);
126
109
 
127
- // Parallel reads instead of sequential for better performance
128
- const projectResults = await Promise.all(
110
+ // Use allSettled to handle individual project read failures gracefully
111
+ const results = await Promise.allSettled(
129
112
  projectIds.map((id) => readJson<Project>(join(projectsDir, id, "project.json")))
130
113
  );
131
114
 
132
- const projects = projectResults.filter(
133
- (project): project is Project =>
134
- project !== null && (includeArchived || project.status !== "archived")
135
- );
115
+ const projects = results
116
+ .filter((r): r is PromiseFulfilledResult<Project | null> => r.status === "fulfilled")
117
+ .map((r) => r.value)
118
+ .filter(
119
+ (project): project is Project =>
120
+ project !== null && (includeArchived || project.status !== "archived")
121
+ );
136
122
 
137
123
  return projects.sort(
138
124
  (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
139
125
  );
140
126
  }
141
127
 
142
- /**
143
- * Get a project by ID
144
- */
145
- export async function getProject(projectId: string): Promise<Project | null> {
146
- // Validate project ID to prevent path traversal
147
- if (!isValidProjectId(projectId)) {
148
- console.error(`Invalid project ID format: ${projectId}`);
149
- return null;
150
- }
151
- const path = join(getTasksDir(), "projects", projectId, "project.json");
152
- return readJson<Project>(path);
153
- }
154
128
 
155
129
  /**
156
130
  * List tasks for a project