@task-mcp/cli 1.0.21 → 1.0.22
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/index.js +818 -0
- package/package.json +7 -5
- package/src/__tests__/ansi.test.ts +0 -221
- package/src/__tests__/dashboard.test.ts +0 -226
- package/src/__tests__/inbox.test.ts +0 -307
- package/src/__tests__/index.test.ts +0 -140
- package/src/__tests__/list.test.ts +0 -347
- package/src/__tests__/storage.test.ts +0 -271
- package/src/ansi.ts +0 -50
- package/src/commands/dashboard.ts +0 -92
- package/src/commands/inbox.ts +0 -229
- package/src/commands/list.ts +0 -106
- package/src/constants.ts +0 -59
- package/src/index.ts +0 -277
- package/src/interactive.ts +0 -254
- package/src/storage.ts +0 -221
package/src/index.ts
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
/**
|
|
3
|
-
* Task MCP CLI - Zero-dependency terminal visualization
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* task # Show dashboard (default)
|
|
7
|
-
* task dashboard [ws] # Show workspace dashboard
|
|
8
|
-
* task d [ws] # Alias for dashboard
|
|
9
|
-
* task list # List tasks
|
|
10
|
-
* task ls # Alias for list
|
|
11
|
-
* task workspaces # List workspaces
|
|
12
|
-
* task ws # Alias for workspaces
|
|
13
|
-
* task help # Show help
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { c, banner } from "./ansi.js";
|
|
17
|
-
import { dashboard } from "./commands/dashboard.js";
|
|
18
|
-
import { listTasksCmd, listWorkspacesCmd } from "./commands/list.js";
|
|
19
|
-
import { startInteractive } from "./interactive.js";
|
|
20
|
-
import {
|
|
21
|
-
inboxAddCmd,
|
|
22
|
-
inboxListCmd,
|
|
23
|
-
inboxGetCmd,
|
|
24
|
-
inboxPromoteCmd,
|
|
25
|
-
inboxDiscardCmd,
|
|
26
|
-
inboxDeleteCmd,
|
|
27
|
-
inboxCountCmd,
|
|
28
|
-
} from "./commands/inbox.js";
|
|
29
|
-
|
|
30
|
-
import pkg from "../package.json" with { type: "json" };
|
|
31
|
-
export const VERSION = pkg.version;
|
|
32
|
-
|
|
33
|
-
export interface ParsedArgs {
|
|
34
|
-
command: string;
|
|
35
|
-
args: string[];
|
|
36
|
-
flags: Record<string, string | boolean>;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function parseArgs(argv: string[]): ParsedArgs {
|
|
40
|
-
const args = argv.slice(2); // Skip bun and script path
|
|
41
|
-
const flags: Record<string, string | boolean> = {};
|
|
42
|
-
const positional: string[] = [];
|
|
43
|
-
|
|
44
|
-
for (let i = 0; i < args.length; i++) {
|
|
45
|
-
const arg = args[i]!;
|
|
46
|
-
if (arg.startsWith("--")) {
|
|
47
|
-
const [key, value] = arg.slice(2).split("=");
|
|
48
|
-
if (value !== undefined) {
|
|
49
|
-
flags[key!] = value;
|
|
50
|
-
} else if (args[i + 1] && !args[i + 1]!.startsWith("-")) {
|
|
51
|
-
flags[key!] = args[++i]!;
|
|
52
|
-
} else {
|
|
53
|
-
flags[key!] = true;
|
|
54
|
-
}
|
|
55
|
-
} else if (arg.startsWith("-") && arg.length === 2) {
|
|
56
|
-
const key = arg.slice(1);
|
|
57
|
-
if (args[i + 1] && !args[i + 1]!.startsWith("-")) {
|
|
58
|
-
flags[key] = args[++i]!;
|
|
59
|
-
} else {
|
|
60
|
-
flags[key] = true;
|
|
61
|
-
}
|
|
62
|
-
} else {
|
|
63
|
-
positional.push(arg);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
command: positional[0] ?? "dashboard",
|
|
69
|
-
args: positional.slice(1),
|
|
70
|
-
flags,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function showHelp(): void {
|
|
75
|
-
console.log(`
|
|
76
|
-
${c.cyan(c.bold("Task MCP CLI"))} ${c.gray(`v${VERSION}`)}
|
|
77
|
-
${c.dim("Zero-dependency terminal visualization for task-mcp")}
|
|
78
|
-
|
|
79
|
-
${c.yellow("USAGE")}
|
|
80
|
-
${c.bold("task")} [command] [options]
|
|
81
|
-
|
|
82
|
-
${c.yellow("COMMANDS")}
|
|
83
|
-
${c.cyan("dashboard")} [workspace] Show workspace dashboard (default)
|
|
84
|
-
${c.cyan("d")} [workspace] Alias for dashboard
|
|
85
|
-
${c.cyan("list")} List all tasks
|
|
86
|
-
${c.cyan("ls")} Alias for list
|
|
87
|
-
${c.cyan("workspaces")} List all workspaces
|
|
88
|
-
${c.cyan("ws")} Alias for workspaces
|
|
89
|
-
${c.cyan("inbox")} <subcommand> Manage inbox (add/list/get/promote/discard)
|
|
90
|
-
${c.cyan("interactive")} Start interactive mode
|
|
91
|
-
${c.cyan("i")} Alias for interactive
|
|
92
|
-
${c.cyan("help")} Show this help message
|
|
93
|
-
${c.cyan("version")} Show version
|
|
94
|
-
|
|
95
|
-
${c.yellow("INBOX SUBCOMMANDS")}
|
|
96
|
-
${c.cyan("inbox")} "content" Quick capture to inbox
|
|
97
|
-
${c.cyan("inbox add")} "content" Add item with natural language
|
|
98
|
-
${c.cyan("inbox list")} List pending items
|
|
99
|
-
${c.cyan("inbox get")} <id> Show item details
|
|
100
|
-
${c.cyan("inbox promote")} <id> Promote to task
|
|
101
|
-
${c.cyan("inbox discard")} <id> Discard item
|
|
102
|
-
${c.cyan("inbox count")} Show pending count
|
|
103
|
-
|
|
104
|
-
${c.yellow("OPTIONS")}
|
|
105
|
-
${c.cyan("-i, --interactive")} Start interactive mode
|
|
106
|
-
${c.cyan("--status")} <status> Filter tasks by status (pending,in_progress,blocked,completed,cancelled)
|
|
107
|
-
${c.cyan("--priority")} <priority> Filter tasks by priority (critical,high,medium,low)
|
|
108
|
-
${c.cyan("--all")} Include completed/cancelled tasks
|
|
109
|
-
|
|
110
|
-
${c.yellow("EXAMPLES")}
|
|
111
|
-
${c.dim("# Show dashboard for all projects")}
|
|
112
|
-
task
|
|
113
|
-
|
|
114
|
-
${c.dim("# Show dashboard for a specific project")}
|
|
115
|
-
task dashboard proj_abc123
|
|
116
|
-
|
|
117
|
-
${c.dim("# List pending high-priority tasks")}
|
|
118
|
-
task list --status pending --priority high
|
|
119
|
-
|
|
120
|
-
${c.dim("# List all workspaces")}
|
|
121
|
-
task workspaces --all
|
|
122
|
-
`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function showVersion(): void {
|
|
126
|
-
console.log(`task-mcp-cli v${VERSION}`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async function handleInboxCommand(
|
|
130
|
-
args: string[],
|
|
131
|
-
flags: Record<string, string | boolean>
|
|
132
|
-
): Promise<void> {
|
|
133
|
-
const subcommand = args[0];
|
|
134
|
-
|
|
135
|
-
// If first arg is not a subcommand, treat it as content for quick capture
|
|
136
|
-
const subcommands = ["add", "list", "ls", "get", "promote", "discard", "delete", "count"];
|
|
137
|
-
if (subcommand && !subcommands.includes(subcommand)) {
|
|
138
|
-
// Quick capture: task inbox "content here"
|
|
139
|
-
await inboxAddCmd({ content: args.join(" ") });
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
switch (subcommand) {
|
|
144
|
-
case "add":
|
|
145
|
-
if (!args[1]) {
|
|
146
|
-
console.log(c.error("Usage: task inbox add \"content\""));
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
await inboxAddCmd({ content: args.slice(1).join(" ") });
|
|
150
|
-
break;
|
|
151
|
-
|
|
152
|
-
case "list":
|
|
153
|
-
case "ls":
|
|
154
|
-
await inboxListCmd({
|
|
155
|
-
all: flags.all === true,
|
|
156
|
-
status: flags.status as "pending" | "promoted" | "discarded" | undefined,
|
|
157
|
-
});
|
|
158
|
-
break;
|
|
159
|
-
|
|
160
|
-
case "get":
|
|
161
|
-
if (!args[1]) {
|
|
162
|
-
console.log(c.error("Usage: task inbox get <item-id>"));
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
await inboxGetCmd(args[1]);
|
|
166
|
-
break;
|
|
167
|
-
|
|
168
|
-
case "promote":
|
|
169
|
-
if (!args[1]) {
|
|
170
|
-
console.log(c.error("Usage: task inbox promote <item-id> [--priority <p>]"));
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
await inboxPromoteCmd({
|
|
174
|
-
itemId: args[1],
|
|
175
|
-
title: flags.title as string | undefined,
|
|
176
|
-
priority: flags.priority as "critical" | "high" | "medium" | "low" | undefined,
|
|
177
|
-
});
|
|
178
|
-
break;
|
|
179
|
-
|
|
180
|
-
case "discard":
|
|
181
|
-
if (!args[1]) {
|
|
182
|
-
console.log(c.error("Usage: task inbox discard <item-id>"));
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
await inboxDiscardCmd(args[1]);
|
|
186
|
-
break;
|
|
187
|
-
|
|
188
|
-
case "delete":
|
|
189
|
-
if (!args[1]) {
|
|
190
|
-
console.log(c.error("Usage: task inbox delete <item-id>"));
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
await inboxDeleteCmd(args[1]);
|
|
194
|
-
break;
|
|
195
|
-
|
|
196
|
-
case "count":
|
|
197
|
-
await inboxCountCmd();
|
|
198
|
-
break;
|
|
199
|
-
|
|
200
|
-
default:
|
|
201
|
-
// No subcommand = list pending
|
|
202
|
-
await inboxListCmd({ all: false });
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
async function main(): Promise<void> {
|
|
208
|
-
const { command, args, flags } = parseArgs(process.argv);
|
|
209
|
-
|
|
210
|
-
// Handle -i flag for interactive mode
|
|
211
|
-
if (flags.i === true || flags.interactive === true) {
|
|
212
|
-
await startInteractive();
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
try {
|
|
217
|
-
switch (command) {
|
|
218
|
-
case "dashboard":
|
|
219
|
-
case "d":
|
|
220
|
-
await dashboard(args[0]);
|
|
221
|
-
break;
|
|
222
|
-
|
|
223
|
-
case "list":
|
|
224
|
-
case "ls":
|
|
225
|
-
await listTasksCmd({
|
|
226
|
-
workspace: args[0],
|
|
227
|
-
status: flags.status as string | undefined,
|
|
228
|
-
priority: flags.priority as string | undefined,
|
|
229
|
-
all: flags.all === true,
|
|
230
|
-
});
|
|
231
|
-
break;
|
|
232
|
-
|
|
233
|
-
case "workspaces":
|
|
234
|
-
case "ws":
|
|
235
|
-
await listWorkspacesCmd();
|
|
236
|
-
break;
|
|
237
|
-
|
|
238
|
-
case "interactive":
|
|
239
|
-
case "i":
|
|
240
|
-
await startInteractive();
|
|
241
|
-
break;
|
|
242
|
-
|
|
243
|
-
case "inbox":
|
|
244
|
-
await handleInboxCommand(args, flags);
|
|
245
|
-
break;
|
|
246
|
-
|
|
247
|
-
case "help":
|
|
248
|
-
case "-h":
|
|
249
|
-
case "--help":
|
|
250
|
-
showHelp();
|
|
251
|
-
break;
|
|
252
|
-
|
|
253
|
-
case "version":
|
|
254
|
-
case "-v":
|
|
255
|
-
case "--version":
|
|
256
|
-
showVersion();
|
|
257
|
-
break;
|
|
258
|
-
|
|
259
|
-
default:
|
|
260
|
-
console.log(c.error(`Unknown command: ${command}`));
|
|
261
|
-
console.log(c.dim("Run 'task help' for usage information."));
|
|
262
|
-
process.exit(1);
|
|
263
|
-
}
|
|
264
|
-
} catch (error) {
|
|
265
|
-
if (error instanceof Error) {
|
|
266
|
-
console.error(c.error(`Error: ${error.message}`));
|
|
267
|
-
} else {
|
|
268
|
-
console.error(c.error("An unexpected error occurred"));
|
|
269
|
-
}
|
|
270
|
-
process.exit(1);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Only run main when directly executed, not when imported
|
|
275
|
-
if (import.meta.main) {
|
|
276
|
-
main();
|
|
277
|
-
}
|
package/src/interactive.ts
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interactive Mode for Task MCP CLI
|
|
3
|
-
* Zero-dependency implementation using Bun native capabilities
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { c, banner } from "./ansi.js";
|
|
7
|
-
import { dashboard } from "./commands/dashboard.js";
|
|
8
|
-
import { listTasksCmd, listWorkspacesCmd } from "./commands/list.js";
|
|
9
|
-
import * as readline from "node:readline";
|
|
10
|
-
import {
|
|
11
|
-
MENU_SEPARATOR_WIDTH,
|
|
12
|
-
ERROR_MESSAGE_DELAY_MS,
|
|
13
|
-
WELCOME_SCREEN_DELAY_MS,
|
|
14
|
-
} from "./constants.js";
|
|
15
|
-
|
|
16
|
-
interface MenuOption {
|
|
17
|
-
key: string;
|
|
18
|
-
label: string;
|
|
19
|
-
description?: string;
|
|
20
|
-
action: () => Promise<void> | void;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Simple prompt for user input
|
|
25
|
-
*/
|
|
26
|
-
async function prompt(question: string): Promise<string> {
|
|
27
|
-
const rl = readline.createInterface({
|
|
28
|
-
input: process.stdin,
|
|
29
|
-
output: process.stdout,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
return new Promise((resolve) => {
|
|
33
|
-
rl.question(question, (answer) => {
|
|
34
|
-
rl.close();
|
|
35
|
-
resolve(answer.trim());
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Display menu and get user selection
|
|
42
|
-
*/
|
|
43
|
-
async function showMenu(title: string, options: MenuOption[]): Promise<void> {
|
|
44
|
-
console.clear();
|
|
45
|
-
console.log(banner("TASK MCP"));
|
|
46
|
-
console.log();
|
|
47
|
-
console.log(c.bold(c.cyan(title)));
|
|
48
|
-
console.log(c.dim("─".repeat(MENU_SEPARATOR_WIDTH)));
|
|
49
|
-
console.log();
|
|
50
|
-
|
|
51
|
-
for (const opt of options) {
|
|
52
|
-
const desc = opt.description ? c.dim(` - ${opt.description}`) : "";
|
|
53
|
-
console.log(` ${c.yellow(opt.key)} ${opt.label}${desc}`);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
console.log();
|
|
57
|
-
const choice = await prompt(c.cyan("Select option: "));
|
|
58
|
-
|
|
59
|
-
const selected = options.find((o) => o.key.toLowerCase() === choice.toLowerCase());
|
|
60
|
-
if (selected) {
|
|
61
|
-
await selected.action();
|
|
62
|
-
} else if (choice !== "") {
|
|
63
|
-
console.log(c.error(`Invalid option: ${choice}`));
|
|
64
|
-
await sleep(ERROR_MESSAGE_DELAY_MS);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Sleep utility
|
|
70
|
-
*/
|
|
71
|
-
function sleep(ms: number): Promise<void> {
|
|
72
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Wait for any key press
|
|
77
|
-
*/
|
|
78
|
-
async function waitForKey(message: string = "Press Enter to continue..."): Promise<void> {
|
|
79
|
-
await prompt(c.dim(message));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Main Menu
|
|
84
|
-
*/
|
|
85
|
-
async function mainMenu(): Promise<boolean> {
|
|
86
|
-
const options: MenuOption[] = [
|
|
87
|
-
{
|
|
88
|
-
key: "d",
|
|
89
|
-
label: "Dashboard",
|
|
90
|
-
description: "View workspace dashboard",
|
|
91
|
-
action: async () => {
|
|
92
|
-
await dashboardMenu();
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
key: "w",
|
|
97
|
-
label: "Workspaces",
|
|
98
|
-
description: "List workspaces",
|
|
99
|
-
action: async () => {
|
|
100
|
-
await workspacesMenu();
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
key: "t",
|
|
105
|
-
label: "Tasks",
|
|
106
|
-
description: "List and filter tasks",
|
|
107
|
-
action: async () => {
|
|
108
|
-
await tasksMenu();
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
key: "x",
|
|
113
|
-
label: "Exit",
|
|
114
|
-
description: "Exit interactive mode",
|
|
115
|
-
action: () => {
|
|
116
|
-
console.log(c.dim("Goodbye!"));
|
|
117
|
-
process.exit(0);
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
];
|
|
121
|
-
|
|
122
|
-
await showMenu("Main Menu", options);
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Dashboard Menu
|
|
128
|
-
*/
|
|
129
|
-
async function dashboardMenu(): Promise<void> {
|
|
130
|
-
console.clear();
|
|
131
|
-
console.log(c.bold(c.cyan("Dashboard")));
|
|
132
|
-
console.log(c.dim("─".repeat(MENU_SEPARATOR_WIDTH)));
|
|
133
|
-
console.log();
|
|
134
|
-
|
|
135
|
-
const workspace = await prompt(c.cyan("Workspace name (Enter for current): "));
|
|
136
|
-
|
|
137
|
-
console.log();
|
|
138
|
-
await dashboard(workspace || undefined);
|
|
139
|
-
console.log();
|
|
140
|
-
await waitForKey();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Workspaces Menu
|
|
145
|
-
*/
|
|
146
|
-
async function workspacesMenu(): Promise<void> {
|
|
147
|
-
const options: MenuOption[] = [
|
|
148
|
-
{
|
|
149
|
-
key: "l",
|
|
150
|
-
label: "List Workspaces",
|
|
151
|
-
action: async () => {
|
|
152
|
-
console.clear();
|
|
153
|
-
await listWorkspacesCmd();
|
|
154
|
-
console.log();
|
|
155
|
-
await waitForKey();
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
key: "b",
|
|
160
|
-
label: "Back to Main Menu",
|
|
161
|
-
action: () => {},
|
|
162
|
-
},
|
|
163
|
-
];
|
|
164
|
-
|
|
165
|
-
await showMenu("Workspaces", options);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Tasks Menu
|
|
170
|
-
*/
|
|
171
|
-
async function tasksMenu(): Promise<void> {
|
|
172
|
-
const options: MenuOption[] = [
|
|
173
|
-
{
|
|
174
|
-
key: "l",
|
|
175
|
-
label: "List All Tasks",
|
|
176
|
-
action: async () => {
|
|
177
|
-
console.clear();
|
|
178
|
-
await listTasksCmd({ all: false });
|
|
179
|
-
console.log();
|
|
180
|
-
await waitForKey();
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
key: "p",
|
|
185
|
-
label: "Filter by Priority",
|
|
186
|
-
action: async () => {
|
|
187
|
-
console.clear();
|
|
188
|
-
const priority = await prompt(c.cyan("Priority (critical/high/medium/low): "));
|
|
189
|
-
if (priority) {
|
|
190
|
-
await listTasksCmd({ priority });
|
|
191
|
-
}
|
|
192
|
-
console.log();
|
|
193
|
-
await waitForKey();
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
key: "s",
|
|
198
|
-
label: "Filter by Status",
|
|
199
|
-
action: async () => {
|
|
200
|
-
console.clear();
|
|
201
|
-
const status = await prompt(c.cyan("Status (pending/in_progress/blocked/completed): "));
|
|
202
|
-
if (status) {
|
|
203
|
-
await listTasksCmd({ status });
|
|
204
|
-
}
|
|
205
|
-
console.log();
|
|
206
|
-
await waitForKey();
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
key: "a",
|
|
211
|
-
label: "All (include completed)",
|
|
212
|
-
action: async () => {
|
|
213
|
-
console.clear();
|
|
214
|
-
await listTasksCmd({ all: true });
|
|
215
|
-
console.log();
|
|
216
|
-
await waitForKey();
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
key: "b",
|
|
221
|
-
label: "Back to Main Menu",
|
|
222
|
-
action: () => {},
|
|
223
|
-
},
|
|
224
|
-
];
|
|
225
|
-
|
|
226
|
-
await showMenu("Tasks", options);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Start interactive mode
|
|
231
|
-
*/
|
|
232
|
-
export async function startInteractive(): Promise<void> {
|
|
233
|
-
console.clear();
|
|
234
|
-
console.log(banner("TASK MCP"));
|
|
235
|
-
console.log();
|
|
236
|
-
console.log(c.bold("Welcome to Task MCP Interactive Mode"));
|
|
237
|
-
console.log(c.dim("Navigate using keyboard shortcuts"));
|
|
238
|
-
console.log();
|
|
239
|
-
await sleep(WELCOME_SCREEN_DELAY_MS);
|
|
240
|
-
|
|
241
|
-
while (true) {
|
|
242
|
-
try {
|
|
243
|
-
await mainMenu();
|
|
244
|
-
} catch (error) {
|
|
245
|
-
if (error instanceof Error && error.message.includes("readline was closed")) {
|
|
246
|
-
// User pressed Ctrl+C or Ctrl+D
|
|
247
|
-
console.log();
|
|
248
|
-
console.log(c.dim("Goodbye!"));
|
|
249
|
-
process.exit(0);
|
|
250
|
-
}
|
|
251
|
-
throw error;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|