@task-mcp/cli 1.0.10 → 1.0.11

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.10",
3
+ "version": "1.0.11",
4
4
  "description": "Zero-dependency CLI for task-mcp with Bun native visualization",
5
5
  "type": "module",
6
6
  "bin": {
package/src/ansi.ts CHANGED
@@ -136,7 +136,7 @@ export function box(content: string, options: {
136
136
  const { padding = 1, borderColor = "cyan", title, rounded = true } = options;
137
137
 
138
138
  const lines = content.split("\n");
139
- const maxLen = Math.max(...lines.map(l => stripAnsi(l).length), title ? title.length + 2 : 0);
139
+ const maxLen = Math.max(...lines.map(l => displayWidth(stripAnsi(l))), title ? title.length + 2 : 0);
140
140
  const innerWidth = maxLen + padding * 2;
141
141
 
142
142
  const tl = rounded ? BOX.rTopLeft : BOX.topLeft;
@@ -166,8 +166,8 @@ export function box(content: string, options: {
166
166
 
167
167
  // Content lines
168
168
  const contentLines = lines.map(line => {
169
- const stripped = stripAnsi(line);
170
- const padRight = innerWidth - stripped.length - padding;
169
+ const lineWidth = displayWidth(stripAnsi(line));
170
+ const padRight = innerWidth - lineWidth - padding;
171
171
  return applyBorder(v) + " ".repeat(padding) + line + " ".repeat(Math.max(0, padRight)) + applyBorder(v);
172
172
  });
173
173
 
@@ -113,55 +113,89 @@ function renderStatusWidget(tasks: Task[], projects: Project[]): string {
113
113
 
114
114
  async function renderActionsWidget(tasks: Task[]): Promise<string> {
115
115
  const nextTask = suggestNextTask(tasks);
116
- const pendingItems = await listInboxItems("pending");
117
116
 
118
117
  const lines: string[] = [];
119
118
 
120
- // Next tasks (top 2 suggestions)
119
+ // Next tasks (top 3 suggestions)
121
120
  const readyTasks = tasks
122
121
  .filter(t => t.status === "pending" && (!t.dependencies || t.dependencies.length === 0))
123
122
  .sort((a, b) => {
124
123
  const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
125
124
  return (priorityOrder[a.priority] ?? 2) - (priorityOrder[b.priority] ?? 2);
126
125
  })
127
- .slice(0, 3);
126
+ .slice(0, 4);
128
127
 
129
128
  if (readyTasks.length > 0) {
130
129
  for (const task of readyTasks) {
131
130
  const deps = task.dependencies?.length ?? 0;
132
131
  const depsInfo = deps > 0 ? `${deps} deps` : c.green("ready");
133
- lines.push(`${c.cyan("→")} ${truncate(task.title, 22)}`);
132
+ lines.push(`${c.cyan("→")} ${truncate(task.title, 24)}`);
134
133
  lines.push(` ${formatPriority(task.priority)}, ${depsInfo}`);
135
134
  }
136
135
  } else if (nextTask) {
137
136
  const deps = nextTask.dependencies?.length ?? 0;
138
137
  const depsInfo = deps > 0 ? `${deps} deps` : c.green("ready");
139
- lines.push(`${c.cyan("→")} ${truncate(nextTask.title, 22)}`);
138
+ lines.push(`${c.cyan("→")} ${truncate(nextTask.title, 24)}`);
140
139
  lines.push(` ${formatPriority(nextTask.priority)}, ${depsInfo}`);
141
140
  } else {
142
141
  lines.push(c.dim("No tasks ready"));
143
142
  }
144
143
 
145
- // Inbox summary
144
+ return box(lines.join("\n"), {
145
+ title: "Next Actions",
146
+ borderColor: "green",
147
+ padding: 1,
148
+ });
149
+ }
150
+
151
+ // =============================================================================
152
+ // Widget: Inbox
153
+ // =============================================================================
154
+
155
+ async function renderInboxWidget(): Promise<string | null> {
156
+ const pendingItems = await listInboxItems("pending");
157
+
158
+ if (pendingItems.length === 0) {
159
+ return null; // Don't show if empty
160
+ }
161
+
162
+ const lines: string[] = [];
163
+ lines.push(`${c.yellow("Pending")}: ${pendingItems.length} items`);
146
164
  lines.push("");
147
- if (pendingItems.length > 0) {
148
- lines.push(`${c.yellow("Inbox")}: ${pendingItems.length} items`);
149
- // Show first item preview
150
- const first = pendingItems[0];
151
- if (first) {
152
- lines.push(` ${c.dim(truncate(first.content, 20))}`);
153
- }
154
- } else {
155
- lines.push(c.dim("Inbox empty"));
165
+
166
+ // Show up to 3 items
167
+ for (const item of pendingItems.slice(0, 3)) {
168
+ const date = new Date(item.capturedAt);
169
+ const ago = getTimeAgo(date);
170
+ const tags = item.tags?.length ? c.dim(` #${item.tags[0]}`) : "";
171
+ lines.push(`${c.yellow("○")} ${truncate(item.content, 40)}${tags}`);
172
+ lines.push(` ${c.dim(ago)}`);
173
+ }
174
+
175
+ if (pendingItems.length > 3) {
176
+ lines.push(c.gray(`+${pendingItems.length - 3} more`));
156
177
  }
157
178
 
158
179
  return box(lines.join("\n"), {
159
- title: "Next Actions",
160
- borderColor: "green",
180
+ title: "Inbox",
181
+ borderColor: "yellow",
161
182
  padding: 1,
162
183
  });
163
184
  }
164
185
 
186
+ function getTimeAgo(date: Date): string {
187
+ const now = new Date();
188
+ const diffMs = now.getTime() - date.getTime();
189
+ const diffMins = Math.floor(diffMs / 60000);
190
+ const diffHours = Math.floor(diffMins / 60);
191
+ const diffDays = Math.floor(diffHours / 24);
192
+
193
+ if (diffMins < 60) return `${diffMins}m ago`;
194
+ if (diffHours < 24) return `${diffHours}h ago`;
195
+ if (diffDays < 7) return `${diffDays}d ago`;
196
+ return date.toLocaleDateString();
197
+ }
198
+
165
199
  // =============================================================================
166
200
  // Projects Table
167
201
  // =============================================================================
@@ -265,6 +299,13 @@ export async function dashboard(projectId?: string): Promise<void> {
265
299
  console.log(sideBySide([statusWidget, actionsWidget], 2));
266
300
  console.log();
267
301
 
302
+ // Inbox widget (if there are pending items)
303
+ const inboxWidget = await renderInboxWidget();
304
+ if (inboxWidget) {
305
+ console.log(inboxWidget);
306
+ console.log();
307
+ }
308
+
268
309
  // Projects table (only if showing all projects)
269
310
  if (!project && projects.length > 1) {
270
311
  console.log(c.bold("Projects"));