@waniwani/cli 0.0.30 → 0.0.32
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 +279 -551
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command25 } from "commander";
|
|
5
5
|
|
|
6
|
-
// src/commands/
|
|
7
|
-
import {
|
|
8
|
-
import chalk2 from "chalk";
|
|
9
|
-
import chokidar from "chokidar";
|
|
10
|
-
import { Command } from "commander";
|
|
11
|
-
import ora from "ora";
|
|
6
|
+
// src/commands/config/index.ts
|
|
7
|
+
import { Command as Command2 } from "commander";
|
|
12
8
|
|
|
13
|
-
// src/
|
|
14
|
-
import {
|
|
15
|
-
import { homedir as homedir2 } from "os";
|
|
9
|
+
// src/commands/config/init.ts
|
|
10
|
+
import { existsSync as existsSync2 } from "fs";
|
|
16
11
|
import { join as join2 } from "path";
|
|
17
|
-
import {
|
|
12
|
+
import { Command } from "commander";
|
|
18
13
|
|
|
19
14
|
// src/lib/config.ts
|
|
20
15
|
import { existsSync } from "fs";
|
|
@@ -22,13 +17,14 @@ import { mkdir, readFile, writeFile } from "fs/promises";
|
|
|
22
17
|
import { homedir } from "os";
|
|
23
18
|
import { join } from "path";
|
|
24
19
|
import { z } from "zod";
|
|
25
|
-
var
|
|
26
|
-
var
|
|
27
|
-
var
|
|
28
|
-
var
|
|
20
|
+
var LOCAL_CONFIG_DIR = ".waniwani";
|
|
21
|
+
var CONFIG_FILE_NAME = "settings.json";
|
|
22
|
+
var LOCAL_DIR = join(process.cwd(), LOCAL_CONFIG_DIR);
|
|
23
|
+
var LOCAL_FILE = join(LOCAL_DIR, CONFIG_FILE_NAME);
|
|
24
|
+
var GLOBAL_DIR = join(homedir(), LOCAL_CONFIG_DIR);
|
|
25
|
+
var GLOBAL_FILE = join(GLOBAL_DIR, CONFIG_FILE_NAME);
|
|
29
26
|
var DEFAULT_API_URL = "https://app.waniwani.ai";
|
|
30
27
|
var ConfigSchema = z.object({
|
|
31
|
-
defaults: z.object({ model: z.string(), maxSteps: z.number() }).default({ model: "claude-sonnet-4-20250514", maxSteps: 10 }),
|
|
32
28
|
mcpId: z.string().nullable().default(null),
|
|
33
29
|
apiUrl: z.string().nullable().default(null)
|
|
34
30
|
});
|
|
@@ -60,14 +56,6 @@ var Config = class {
|
|
|
60
56
|
await mkdir(this.dir, { recursive: true });
|
|
61
57
|
await writeFile(this.file, JSON.stringify(data, null, " "));
|
|
62
58
|
}
|
|
63
|
-
async getDefaults() {
|
|
64
|
-
return (await this.load()).defaults;
|
|
65
|
-
}
|
|
66
|
-
async setDefaults(defaults) {
|
|
67
|
-
const data = await this.load();
|
|
68
|
-
data.defaults = { ...data.defaults, ...defaults };
|
|
69
|
-
await this.save(data);
|
|
70
|
-
}
|
|
71
59
|
async getMcpId() {
|
|
72
60
|
return (await this.load()).mcpId;
|
|
73
61
|
}
|
|
@@ -91,10 +79,176 @@ var Config = class {
|
|
|
91
79
|
};
|
|
92
80
|
var config = new Config();
|
|
93
81
|
var globalConfig = new Config(true);
|
|
82
|
+
async function initConfigAt(dir, overrides = {}) {
|
|
83
|
+
const configDir = join(dir, LOCAL_CONFIG_DIR);
|
|
84
|
+
const configPath = join(configDir, CONFIG_FILE_NAME);
|
|
85
|
+
await mkdir(configDir, { recursive: true });
|
|
86
|
+
const data = ConfigSchema.parse(overrides);
|
|
87
|
+
await writeFile(configPath, JSON.stringify(data, null, " "), "utf-8");
|
|
88
|
+
return { path: configPath, config: data };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/lib/errors.ts
|
|
92
|
+
import chalk from "chalk";
|
|
93
|
+
import { ZodError } from "zod";
|
|
94
|
+
var CLIError = class extends Error {
|
|
95
|
+
constructor(message, code, details) {
|
|
96
|
+
super(message);
|
|
97
|
+
this.code = code;
|
|
98
|
+
this.details = details;
|
|
99
|
+
this.name = "CLIError";
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var AuthError = class extends CLIError {
|
|
103
|
+
constructor(message, details) {
|
|
104
|
+
super(message, "AUTH_ERROR", details);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var McpError = class extends CLIError {
|
|
108
|
+
constructor(message, details) {
|
|
109
|
+
super(message, "MCP_ERROR", details);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
function handleError(error, json) {
|
|
113
|
+
if (error instanceof ZodError) {
|
|
114
|
+
const message = error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
115
|
+
outputError("VALIDATION_ERROR", `Invalid input: ${message}`, json);
|
|
116
|
+
} else if (error instanceof CLIError) {
|
|
117
|
+
outputError(error.code, error.message, json, error.details);
|
|
118
|
+
} else if (error instanceof Error) {
|
|
119
|
+
outputError("UNKNOWN_ERROR", error.message, json);
|
|
120
|
+
} else {
|
|
121
|
+
outputError("UNKNOWN_ERROR", String(error), json);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function outputError(code, message, json, details) {
|
|
125
|
+
if (json) {
|
|
126
|
+
console.error(
|
|
127
|
+
JSON.stringify({ success: false, error: { code, message, details } })
|
|
128
|
+
);
|
|
129
|
+
} else {
|
|
130
|
+
console.error(chalk.red(`Error [${code}]:`), message);
|
|
131
|
+
if (details) {
|
|
132
|
+
console.error(chalk.gray("Details:"), JSON.stringify(details, null, 2));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/lib/output.ts
|
|
138
|
+
import chalk2 from "chalk";
|
|
139
|
+
function formatOutput(data, json) {
|
|
140
|
+
if (json) {
|
|
141
|
+
console.log(JSON.stringify({ success: true, data }, null, 2));
|
|
142
|
+
} else {
|
|
143
|
+
prettyPrint(data);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function formatSuccess(message, json) {
|
|
147
|
+
if (json) {
|
|
148
|
+
console.log(JSON.stringify({ success: true, message }));
|
|
149
|
+
} else {
|
|
150
|
+
console.log(chalk2.green("\u2713"), message);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function formatTable(headers, rows, json) {
|
|
154
|
+
if (json) {
|
|
155
|
+
const data = rows.map(
|
|
156
|
+
(row) => Object.fromEntries(headers.map((header, i) => [header, row[i]]))
|
|
157
|
+
);
|
|
158
|
+
console.log(JSON.stringify({ success: true, data }, null, 2));
|
|
159
|
+
} else {
|
|
160
|
+
const colWidths = headers.map(
|
|
161
|
+
(h, i) => Math.max(h.length, ...rows.map((r) => (r[i] || "").length))
|
|
162
|
+
);
|
|
163
|
+
const separator = colWidths.map((w) => "-".repeat(w + 2)).join("+");
|
|
164
|
+
const formatRow = (row) => row.map((cell, i) => ` ${(cell || "").padEnd(colWidths[i])} `).join("|");
|
|
165
|
+
console.log(chalk2.cyan(formatRow(headers)));
|
|
166
|
+
console.log(separator);
|
|
167
|
+
for (const row of rows) {
|
|
168
|
+
console.log(formatRow(row));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function formatList(items, json) {
|
|
173
|
+
if (json) {
|
|
174
|
+
const data = Object.fromEntries(
|
|
175
|
+
items.map((item) => [item.label, item.value])
|
|
176
|
+
);
|
|
177
|
+
console.log(JSON.stringify({ success: true, data }, null, 2));
|
|
178
|
+
} else {
|
|
179
|
+
const maxLabelLength = Math.max(...items.map((i) => i.label.length));
|
|
180
|
+
items.forEach((item) => {
|
|
181
|
+
console.log(
|
|
182
|
+
`${chalk2.gray(item.label.padEnd(maxLabelLength))} ${chalk2.white(item.value)}`
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function prettyPrint(data, indent = 0) {
|
|
188
|
+
const prefix = " ".repeat(indent);
|
|
189
|
+
if (Array.isArray(data)) {
|
|
190
|
+
data.forEach((item, index) => {
|
|
191
|
+
console.log(`${prefix}${chalk2.gray(`[${index}]`)}`);
|
|
192
|
+
prettyPrint(item, indent + 1);
|
|
193
|
+
});
|
|
194
|
+
} else if (typeof data === "object" && data !== null) {
|
|
195
|
+
for (const [key, value] of Object.entries(data)) {
|
|
196
|
+
if (typeof value === "object" && value !== null) {
|
|
197
|
+
console.log(`${prefix}${chalk2.gray(key)}:`);
|
|
198
|
+
prettyPrint(value, indent + 1);
|
|
199
|
+
} else {
|
|
200
|
+
console.log(
|
|
201
|
+
`${prefix}${chalk2.gray(key)}: ${chalk2.white(String(value))}`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
console.log(`${prefix}${chalk2.white(String(data))}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/commands/config/init.ts
|
|
211
|
+
var configInitCommand = new Command("init").description("Initialize .waniwani config in the current directory").option("--force", "Overwrite existing config").action(async (options, command) => {
|
|
212
|
+
const globalOptions = command.optsWithGlobals();
|
|
213
|
+
const json = globalOptions.json ?? false;
|
|
214
|
+
try {
|
|
215
|
+
const cwd = process.cwd();
|
|
216
|
+
const configPath = join2(cwd, LOCAL_CONFIG_DIR, CONFIG_FILE_NAME);
|
|
217
|
+
if (existsSync2(configPath) && !options.force) {
|
|
218
|
+
throw new CLIError(
|
|
219
|
+
`Config already exists at ${configPath}. Use --force to overwrite.`,
|
|
220
|
+
"CONFIG_EXISTS"
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const result = await initConfigAt(cwd);
|
|
224
|
+
if (json) {
|
|
225
|
+
formatOutput({ created: result.path, config: result.config }, true);
|
|
226
|
+
} else {
|
|
227
|
+
formatSuccess(`Created ${result.path}`, false);
|
|
228
|
+
}
|
|
229
|
+
} catch (error) {
|
|
230
|
+
handleError(error, json);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// src/commands/config/index.ts
|
|
236
|
+
var configCommand = new Command2("config").description("Manage WaniWani configuration").addCommand(configInitCommand);
|
|
237
|
+
|
|
238
|
+
// src/commands/dev.ts
|
|
239
|
+
import { relative as relative2 } from "path";
|
|
240
|
+
import chalk3 from "chalk";
|
|
241
|
+
import chokidar from "chokidar";
|
|
242
|
+
import { Command as Command3 } from "commander";
|
|
243
|
+
import ora from "ora";
|
|
94
244
|
|
|
95
245
|
// src/lib/auth.ts
|
|
96
|
-
|
|
97
|
-
|
|
246
|
+
import { access, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
247
|
+
import { homedir as homedir2 } from "os";
|
|
248
|
+
import { join as join3 } from "path";
|
|
249
|
+
import { z as z2 } from "zod";
|
|
250
|
+
var CONFIG_DIR = join3(homedir2(), ".waniwani");
|
|
251
|
+
var AUTH_FILE = join3(CONFIG_DIR, "auth.json");
|
|
98
252
|
var AuthStoreSchema = z2.object({
|
|
99
253
|
accessToken: z2.string().nullable().default(null),
|
|
100
254
|
refreshToken: z2.string().nullable().default(null),
|
|
@@ -196,57 +350,6 @@ var AuthManager = class {
|
|
|
196
350
|
};
|
|
197
351
|
var auth = new AuthManager();
|
|
198
352
|
|
|
199
|
-
// src/lib/errors.ts
|
|
200
|
-
import chalk from "chalk";
|
|
201
|
-
import { ZodError } from "zod";
|
|
202
|
-
var CLIError = class extends Error {
|
|
203
|
-
constructor(message, code, details) {
|
|
204
|
-
super(message);
|
|
205
|
-
this.code = code;
|
|
206
|
-
this.details = details;
|
|
207
|
-
this.name = "CLIError";
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
var AuthError = class extends CLIError {
|
|
211
|
-
constructor(message, details) {
|
|
212
|
-
super(message, "AUTH_ERROR", details);
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
var SandboxError = class extends CLIError {
|
|
216
|
-
constructor(message, details) {
|
|
217
|
-
super(message, "SANDBOX_ERROR", details);
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
var McpError = class extends CLIError {
|
|
221
|
-
constructor(message, details) {
|
|
222
|
-
super(message, "MCP_ERROR", details);
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
function handleError(error, json) {
|
|
226
|
-
if (error instanceof ZodError) {
|
|
227
|
-
const message = error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
228
|
-
outputError("VALIDATION_ERROR", `Invalid input: ${message}`, json);
|
|
229
|
-
} else if (error instanceof CLIError) {
|
|
230
|
-
outputError(error.code, error.message, json, error.details);
|
|
231
|
-
} else if (error instanceof Error) {
|
|
232
|
-
outputError("UNKNOWN_ERROR", error.message, json);
|
|
233
|
-
} else {
|
|
234
|
-
outputError("UNKNOWN_ERROR", String(error), json);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
function outputError(code, message, json, details) {
|
|
238
|
-
if (json) {
|
|
239
|
-
console.error(
|
|
240
|
-
JSON.stringify({ success: false, error: { code, message, details } })
|
|
241
|
-
);
|
|
242
|
-
} else {
|
|
243
|
-
console.error(chalk.red(`Error [${code}]:`), message);
|
|
244
|
-
if (details) {
|
|
245
|
-
console.error(chalk.gray("Details:"), JSON.stringify(details, null, 2));
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
353
|
// src/lib/api.ts
|
|
251
354
|
var ApiError = class extends CLIError {
|
|
252
355
|
constructor(message, code, statusCode, details) {
|
|
@@ -336,9 +439,9 @@ var api = {
|
|
|
336
439
|
};
|
|
337
440
|
|
|
338
441
|
// src/lib/sync.ts
|
|
339
|
-
import { existsSync as
|
|
442
|
+
import { existsSync as existsSync3 } from "fs";
|
|
340
443
|
import { mkdir as mkdir3, readdir, readFile as readFile3, stat, writeFile as writeFile3 } from "fs/promises";
|
|
341
|
-
import { dirname, join as
|
|
444
|
+
import { dirname, join as join4, relative } from "path";
|
|
342
445
|
import ignore from "ignore";
|
|
343
446
|
|
|
344
447
|
// src/lib/utils.ts
|
|
@@ -393,20 +496,20 @@ async function findProjectRoot(startDir) {
|
|
|
393
496
|
let current = startDir;
|
|
394
497
|
const root = dirname(current);
|
|
395
498
|
while (current !== root) {
|
|
396
|
-
if (
|
|
499
|
+
if (existsSync3(join4(current, PROJECT_DIR))) {
|
|
397
500
|
return current;
|
|
398
501
|
}
|
|
399
502
|
const parent = dirname(current);
|
|
400
503
|
if (parent === current) break;
|
|
401
504
|
current = parent;
|
|
402
505
|
}
|
|
403
|
-
if (
|
|
506
|
+
if (existsSync3(join4(current, PROJECT_DIR))) {
|
|
404
507
|
return current;
|
|
405
508
|
}
|
|
406
509
|
return null;
|
|
407
510
|
}
|
|
408
511
|
async function loadProjectMcpId(projectRoot) {
|
|
409
|
-
const settingsPath =
|
|
512
|
+
const settingsPath = join4(projectRoot, PROJECT_DIR, SETTINGS_FILE);
|
|
410
513
|
try {
|
|
411
514
|
const content = await readFile3(settingsPath, "utf-8");
|
|
412
515
|
const settings = JSON.parse(content);
|
|
@@ -434,8 +537,8 @@ var DEFAULT_IGNORE_PATTERNS = [
|
|
|
434
537
|
async function loadIgnorePatterns(projectRoot) {
|
|
435
538
|
const ig = ignore();
|
|
436
539
|
ig.add(DEFAULT_IGNORE_PATTERNS);
|
|
437
|
-
const gitignorePath =
|
|
438
|
-
if (
|
|
540
|
+
const gitignorePath = join4(projectRoot, ".gitignore");
|
|
541
|
+
if (existsSync3(gitignorePath)) {
|
|
439
542
|
try {
|
|
440
543
|
const content = await readFile3(gitignorePath, "utf-8");
|
|
441
544
|
ig.add(content);
|
|
@@ -450,7 +553,7 @@ async function collectFiles(projectRoot) {
|
|
|
450
553
|
async function walk(dir) {
|
|
451
554
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
452
555
|
for (const entry of entries) {
|
|
453
|
-
const fullPath =
|
|
556
|
+
const fullPath = join4(dir, entry.name);
|
|
454
557
|
const relativePath = relative(projectRoot, fullPath);
|
|
455
558
|
if (ig.ignores(relativePath)) {
|
|
456
559
|
continue;
|
|
@@ -480,7 +583,7 @@ async function pullFilesFromSandbox(mcpId, targetDir) {
|
|
|
480
583
|
);
|
|
481
584
|
const writtenFiles = [];
|
|
482
585
|
for (const file of result.files) {
|
|
483
|
-
const localPath =
|
|
586
|
+
const localPath = join4(targetDir, file.path);
|
|
484
587
|
const dir = dirname(localPath);
|
|
485
588
|
await mkdir3(dir, { recursive: true });
|
|
486
589
|
if (file.encoding === "base64") {
|
|
@@ -493,9 +596,9 @@ async function pullFilesFromSandbox(mcpId, targetDir) {
|
|
|
493
596
|
return { count: writtenFiles.length, files: writtenFiles };
|
|
494
597
|
}
|
|
495
598
|
async function collectSingleFile(projectRoot, filePath) {
|
|
496
|
-
const fullPath =
|
|
599
|
+
const fullPath = join4(projectRoot, filePath);
|
|
497
600
|
const relativePath = relative(projectRoot, fullPath);
|
|
498
|
-
if (!
|
|
601
|
+
if (!existsSync3(fullPath)) {
|
|
499
602
|
return null;
|
|
500
603
|
}
|
|
501
604
|
try {
|
|
@@ -518,7 +621,7 @@ async function collectSingleFile(projectRoot, filePath) {
|
|
|
518
621
|
// src/commands/dev.ts
|
|
519
622
|
var BATCH_SIZE = 50;
|
|
520
623
|
var DEFAULT_DEBOUNCE_MS = 300;
|
|
521
|
-
var devCommand = new
|
|
624
|
+
var devCommand = new Command3("dev").description("Watch and sync files to MCP sandbox").option("--no-initial-sync", "Skip initial sync of all files").option(
|
|
522
625
|
"--debounce <ms>",
|
|
523
626
|
"Debounce delay in milliseconds",
|
|
524
627
|
String(DEFAULT_DEBOUNCE_MS)
|
|
@@ -576,7 +679,7 @@ var devCommand = new Command("dev").description("Watch and sync files to MCP san
|
|
|
576
679
|
}
|
|
577
680
|
const file = await collectSingleFile(projectRoot, relativePath);
|
|
578
681
|
if (!file) {
|
|
579
|
-
console.log(
|
|
682
|
+
console.log(chalk3.yellow("Skipped:"), relativePath);
|
|
580
683
|
return;
|
|
581
684
|
}
|
|
582
685
|
try {
|
|
@@ -592,17 +695,17 @@ var devCommand = new Command("dev").description("Watch and sync files to MCP san
|
|
|
592
695
|
]
|
|
593
696
|
}
|
|
594
697
|
);
|
|
595
|
-
console.log(
|
|
698
|
+
console.log(chalk3.green("Synced:"), relativePath);
|
|
596
699
|
} catch (error) {
|
|
597
|
-
console.log(
|
|
700
|
+
console.log(chalk3.red("Failed:"), relativePath);
|
|
598
701
|
if (globalOptions.verbose) {
|
|
599
702
|
console.error(error);
|
|
600
703
|
}
|
|
601
704
|
}
|
|
602
705
|
}, debounceMs);
|
|
603
706
|
console.log();
|
|
604
|
-
console.log(
|
|
605
|
-
console.log(
|
|
707
|
+
console.log(chalk3.bold("Watching for changes..."));
|
|
708
|
+
console.log(chalk3.dim("Press Ctrl+C to stop"));
|
|
606
709
|
console.log();
|
|
607
710
|
const watcher = chokidar.watch(projectRoot, {
|
|
608
711
|
ignored: (path) => {
|
|
@@ -618,11 +721,11 @@ var devCommand = new Command("dev").description("Watch and sync files to MCP san
|
|
|
618
721
|
});
|
|
619
722
|
watcher.on("add", (path) => syncFile(path)).on("change", (path) => syncFile(path)).on("unlink", (path) => {
|
|
620
723
|
const relativePath = relative2(projectRoot, path);
|
|
621
|
-
console.log(
|
|
724
|
+
console.log(chalk3.yellow("Deleted (local only):"), relativePath);
|
|
622
725
|
});
|
|
623
726
|
const cleanup = () => {
|
|
624
727
|
console.log();
|
|
625
|
-
console.log(
|
|
728
|
+
console.log(chalk3.dim("Stopping watcher..."));
|
|
626
729
|
watcher.close().then(() => {
|
|
627
730
|
process.exit(0);
|
|
628
731
|
});
|
|
@@ -636,97 +739,14 @@ var devCommand = new Command("dev").description("Watch and sync files to MCP san
|
|
|
636
739
|
});
|
|
637
740
|
|
|
638
741
|
// src/commands/init.ts
|
|
639
|
-
import { existsSync as
|
|
640
|
-
import { mkdir as mkdir4, readFile as readFile4
|
|
641
|
-
import { join as
|
|
642
|
-
import { Command as
|
|
742
|
+
import { existsSync as existsSync4 } from "fs";
|
|
743
|
+
import { mkdir as mkdir4, readFile as readFile4 } from "fs/promises";
|
|
744
|
+
import { join as join5 } from "path";
|
|
745
|
+
import { Command as Command4 } from "commander";
|
|
643
746
|
import ora2 from "ora";
|
|
644
|
-
|
|
645
|
-
// src/lib/output.ts
|
|
646
|
-
import chalk3 from "chalk";
|
|
647
|
-
function formatOutput(data, json) {
|
|
648
|
-
if (json) {
|
|
649
|
-
console.log(JSON.stringify({ success: true, data }, null, 2));
|
|
650
|
-
} else {
|
|
651
|
-
prettyPrint(data);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
function formatSuccess(message, json) {
|
|
655
|
-
if (json) {
|
|
656
|
-
console.log(JSON.stringify({ success: true, message }));
|
|
657
|
-
} else {
|
|
658
|
-
console.log(chalk3.green("\u2713"), message);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
function formatTable(headers, rows, json) {
|
|
662
|
-
if (json) {
|
|
663
|
-
const data = rows.map(
|
|
664
|
-
(row) => Object.fromEntries(headers.map((header, i) => [header, row[i]]))
|
|
665
|
-
);
|
|
666
|
-
console.log(JSON.stringify({ success: true, data }, null, 2));
|
|
667
|
-
} else {
|
|
668
|
-
const colWidths = headers.map(
|
|
669
|
-
(h, i) => Math.max(h.length, ...rows.map((r) => (r[i] || "").length))
|
|
670
|
-
);
|
|
671
|
-
const separator = colWidths.map((w) => "-".repeat(w + 2)).join("+");
|
|
672
|
-
const formatRow = (row) => row.map((cell, i) => ` ${(cell || "").padEnd(colWidths[i])} `).join("|");
|
|
673
|
-
console.log(chalk3.cyan(formatRow(headers)));
|
|
674
|
-
console.log(separator);
|
|
675
|
-
for (const row of rows) {
|
|
676
|
-
console.log(formatRow(row));
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
function formatList(items, json) {
|
|
681
|
-
if (json) {
|
|
682
|
-
const data = Object.fromEntries(
|
|
683
|
-
items.map((item) => [item.label, item.value])
|
|
684
|
-
);
|
|
685
|
-
console.log(JSON.stringify({ success: true, data }, null, 2));
|
|
686
|
-
} else {
|
|
687
|
-
const maxLabelLength = Math.max(...items.map((i) => i.label.length));
|
|
688
|
-
items.forEach((item) => {
|
|
689
|
-
console.log(
|
|
690
|
-
`${chalk3.gray(item.label.padEnd(maxLabelLength))} ${chalk3.white(item.value)}`
|
|
691
|
-
);
|
|
692
|
-
});
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
function prettyPrint(data, indent = 0) {
|
|
696
|
-
const prefix = " ".repeat(indent);
|
|
697
|
-
if (Array.isArray(data)) {
|
|
698
|
-
data.forEach((item, index) => {
|
|
699
|
-
console.log(`${prefix}${chalk3.gray(`[${index}]`)}`);
|
|
700
|
-
prettyPrint(item, indent + 1);
|
|
701
|
-
});
|
|
702
|
-
} else if (typeof data === "object" && data !== null) {
|
|
703
|
-
for (const [key, value] of Object.entries(data)) {
|
|
704
|
-
if (typeof value === "object" && value !== null) {
|
|
705
|
-
console.log(`${prefix}${chalk3.gray(key)}:`);
|
|
706
|
-
prettyPrint(value, indent + 1);
|
|
707
|
-
} else {
|
|
708
|
-
console.log(
|
|
709
|
-
`${prefix}${chalk3.gray(key)}: ${chalk3.white(String(value))}`
|
|
710
|
-
);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
} else {
|
|
714
|
-
console.log(`${prefix}${chalk3.white(String(data))}`);
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// src/commands/init.ts
|
|
719
|
-
var PROJECT_CONFIG_DIR = ".waniwani";
|
|
720
|
-
var PROJECT_CONFIG_FILE = "settings.json";
|
|
721
|
-
var DEFAULT_PROJECT_CONFIG = {
|
|
722
|
-
defaults: {
|
|
723
|
-
model: "claude-sonnet-4-20250514",
|
|
724
|
-
maxSteps: 10
|
|
725
|
-
}
|
|
726
|
-
};
|
|
727
747
|
async function loadParentConfig(cwd) {
|
|
728
|
-
const parentConfigPath =
|
|
729
|
-
if (!
|
|
748
|
+
const parentConfigPath = join5(cwd, LOCAL_CONFIG_DIR, CONFIG_FILE_NAME);
|
|
749
|
+
if (!existsSync4(parentConfigPath)) {
|
|
730
750
|
return null;
|
|
731
751
|
}
|
|
732
752
|
try {
|
|
@@ -738,13 +758,13 @@ async function loadParentConfig(cwd) {
|
|
|
738
758
|
return null;
|
|
739
759
|
}
|
|
740
760
|
}
|
|
741
|
-
var initCommand = new
|
|
761
|
+
var initCommand = new Command4("init").description("Create a new MCP project from template").argument("<name>", "Name for the MCP project").action(async (name, _, command) => {
|
|
742
762
|
const globalOptions = command.optsWithGlobals();
|
|
743
763
|
const json = globalOptions.json ?? false;
|
|
744
764
|
try {
|
|
745
765
|
const cwd = process.cwd();
|
|
746
|
-
const projectDir =
|
|
747
|
-
if (
|
|
766
|
+
const projectDir = join5(cwd, name);
|
|
767
|
+
if (existsSync4(projectDir)) {
|
|
748
768
|
if (json) {
|
|
749
769
|
formatOutput(
|
|
750
770
|
{
|
|
@@ -766,21 +786,12 @@ var initCommand = new Command2("init").description("Create a new MCP project fro
|
|
|
766
786
|
await mkdir4(projectDir, { recursive: true });
|
|
767
787
|
await pullFilesFromSandbox(result.id, projectDir);
|
|
768
788
|
spinner.text = "Setting up project config...";
|
|
769
|
-
const configDir = join4(projectDir, PROJECT_CONFIG_DIR);
|
|
770
|
-
const configPath = join4(configDir, PROJECT_CONFIG_FILE);
|
|
771
|
-
await mkdir4(configDir, { recursive: true });
|
|
772
789
|
const parentConfig = await loadParentConfig(cwd);
|
|
773
|
-
|
|
774
|
-
...DEFAULT_PROJECT_CONFIG,
|
|
790
|
+
await initConfigAt(projectDir, {
|
|
775
791
|
...parentConfig,
|
|
776
792
|
mcpId: result.id
|
|
777
793
|
// Always use the new sandbox's mcpId
|
|
778
|
-
};
|
|
779
|
-
await writeFile4(
|
|
780
|
-
configPath,
|
|
781
|
-
JSON.stringify(projectConfig, null, " "),
|
|
782
|
-
"utf-8"
|
|
783
|
-
);
|
|
794
|
+
});
|
|
784
795
|
spinner.succeed("MCP project created");
|
|
785
796
|
if (json) {
|
|
786
797
|
formatOutput(
|
|
@@ -817,7 +828,7 @@ var initCommand = new Command2("init").description("Create a new MCP project fro
|
|
|
817
828
|
import { spawn } from "child_process";
|
|
818
829
|
import { createServer } from "http";
|
|
819
830
|
import chalk4 from "chalk";
|
|
820
|
-
import { Command as
|
|
831
|
+
import { Command as Command5 } from "commander";
|
|
821
832
|
import ora3 from "ora";
|
|
822
833
|
var CALLBACK_PORT = 54321;
|
|
823
834
|
var CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;
|
|
@@ -1093,7 +1104,7 @@ async function exchangeCodeForToken(code, codeVerifier, clientId, resource) {
|
|
|
1093
1104
|
}
|
|
1094
1105
|
return response.json();
|
|
1095
1106
|
}
|
|
1096
|
-
var loginCommand = new
|
|
1107
|
+
var loginCommand = new Command5("login").description("Log in to WaniWani").option("--no-browser", "Don't open the browser automatically").action(async (options, command) => {
|
|
1097
1108
|
const globalOptions = command.optsWithGlobals();
|
|
1098
1109
|
const json = globalOptions.json ?? false;
|
|
1099
1110
|
try {
|
|
@@ -1198,8 +1209,8 @@ var loginCommand = new Command3("login").description("Log in to WaniWani").optio
|
|
|
1198
1209
|
});
|
|
1199
1210
|
|
|
1200
1211
|
// src/commands/logout.ts
|
|
1201
|
-
import { Command as
|
|
1202
|
-
var logoutCommand = new
|
|
1212
|
+
import { Command as Command6 } from "commander";
|
|
1213
|
+
var logoutCommand = new Command6("logout").description("Log out from WaniWani").action(async (_, command) => {
|
|
1203
1214
|
const globalOptions = command.optsWithGlobals();
|
|
1204
1215
|
const json = globalOptions.json ?? false;
|
|
1205
1216
|
try {
|
|
@@ -1226,46 +1237,10 @@ var logoutCommand = new Command4("logout").description("Log out from WaniWani").
|
|
|
1226
1237
|
// src/commands/mcp/index.ts
|
|
1227
1238
|
import { Command as Command20 } from "commander";
|
|
1228
1239
|
|
|
1229
|
-
// src/commands/mcp/clear.ts
|
|
1230
|
-
import { rm } from "fs/promises";
|
|
1231
|
-
import { Command as Command5 } from "commander";
|
|
1232
|
-
import ora4 from "ora";
|
|
1233
|
-
var clearCommand = new Command5("clear").description("Delete the local MCP project folder").option("--force", "Skip confirmation").action(async (_options, command) => {
|
|
1234
|
-
const globalOptions = command.optsWithGlobals();
|
|
1235
|
-
const json = globalOptions.json ?? false;
|
|
1236
|
-
try {
|
|
1237
|
-
const cwd = process.cwd();
|
|
1238
|
-
const projectRoot = await findProjectRoot(cwd);
|
|
1239
|
-
if (!projectRoot) {
|
|
1240
|
-
throw new CLIError(
|
|
1241
|
-
"Not in a WaniWani project. No .waniwani directory found.",
|
|
1242
|
-
"NOT_IN_PROJECT"
|
|
1243
|
-
);
|
|
1244
|
-
}
|
|
1245
|
-
if (projectRoot === "/" || projectRoot === process.env.HOME) {
|
|
1246
|
-
throw new CLIError(
|
|
1247
|
-
"Refusing to delete home or root directory.",
|
|
1248
|
-
"UNSAFE_DELETE"
|
|
1249
|
-
);
|
|
1250
|
-
}
|
|
1251
|
-
const spinner = ora4(`Deleting ${projectRoot}...`).start();
|
|
1252
|
-
await rm(projectRoot, { recursive: true, force: true });
|
|
1253
|
-
spinner.succeed("Project folder deleted");
|
|
1254
|
-
if (json) {
|
|
1255
|
-
formatOutput({ deleted: projectRoot }, true);
|
|
1256
|
-
} else {
|
|
1257
|
-
formatSuccess(`Deleted: ${projectRoot}`, false);
|
|
1258
|
-
}
|
|
1259
|
-
} catch (error) {
|
|
1260
|
-
handleError(error, json);
|
|
1261
|
-
process.exit(1);
|
|
1262
|
-
}
|
|
1263
|
-
});
|
|
1264
|
-
|
|
1265
1240
|
// src/commands/mcp/delete.ts
|
|
1266
|
-
import { Command as
|
|
1267
|
-
import
|
|
1268
|
-
var deleteCommand = new
|
|
1241
|
+
import { Command as Command7 } from "commander";
|
|
1242
|
+
import ora4 from "ora";
|
|
1243
|
+
var deleteCommand = new Command7("delete").description("Delete the MCP sandbox").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
1269
1244
|
const globalOptions = command.optsWithGlobals();
|
|
1270
1245
|
const json = globalOptions.json ?? false;
|
|
1271
1246
|
try {
|
|
@@ -1276,7 +1251,7 @@ var deleteCommand = new Command6("delete").description("Delete the MCP sandbox")
|
|
|
1276
1251
|
throw new McpError("No active MCP. Use --mcp-id to specify one.");
|
|
1277
1252
|
}
|
|
1278
1253
|
}
|
|
1279
|
-
const spinner =
|
|
1254
|
+
const spinner = ora4("Deleting MCP sandbox...").start();
|
|
1280
1255
|
await api.delete(`/api/mcp/sandboxes/${mcpId}`);
|
|
1281
1256
|
spinner.succeed("MCP sandbox deleted");
|
|
1282
1257
|
if (await config.getMcpId() === mcpId) {
|
|
@@ -1294,9 +1269,9 @@ var deleteCommand = new Command6("delete").description("Delete the MCP sandbox")
|
|
|
1294
1269
|
});
|
|
1295
1270
|
|
|
1296
1271
|
// src/commands/mcp/deploy.ts
|
|
1297
|
-
import { Command as
|
|
1298
|
-
import
|
|
1299
|
-
var deployCommand = new
|
|
1272
|
+
import { Command as Command8 } from "commander";
|
|
1273
|
+
import ora5 from "ora";
|
|
1274
|
+
var deployCommand = new Command8("deploy").description("Deploy MCP server to GitHub + Vercel from sandbox").option("--repo <name>", "GitHub repository name").option("--org <name>", "GitHub organization").option("--private", "Create private repository").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
1300
1275
|
const globalOptions = command.optsWithGlobals();
|
|
1301
1276
|
const json = globalOptions.json ?? false;
|
|
1302
1277
|
try {
|
|
@@ -1309,7 +1284,7 @@ var deployCommand = new Command7("deploy").description("Deploy MCP server to Git
|
|
|
1309
1284
|
);
|
|
1310
1285
|
}
|
|
1311
1286
|
}
|
|
1312
|
-
const spinner =
|
|
1287
|
+
const spinner = ora5("Deploying to GitHub...").start();
|
|
1313
1288
|
const result = await api.post(
|
|
1314
1289
|
`/api/admin/mcps/${mcpId}/deploy`,
|
|
1315
1290
|
{
|
|
@@ -1341,13 +1316,13 @@ var deployCommand = new Command7("deploy").description("Deploy MCP server to Git
|
|
|
1341
1316
|
});
|
|
1342
1317
|
|
|
1343
1318
|
// src/commands/mcp/file/index.ts
|
|
1344
|
-
import { Command as
|
|
1319
|
+
import { Command as Command12 } from "commander";
|
|
1345
1320
|
|
|
1346
1321
|
// src/commands/mcp/file/list.ts
|
|
1347
1322
|
import chalk5 from "chalk";
|
|
1348
|
-
import { Command as
|
|
1349
|
-
import
|
|
1350
|
-
var listCommand = new
|
|
1323
|
+
import { Command as Command9 } from "commander";
|
|
1324
|
+
import ora6 from "ora";
|
|
1325
|
+
var listCommand = new Command9("list").description("List files in the MCP sandbox").argument("[path]", "Directory path (defaults to /app)", "/app").option("--mcp-id <id>", "Specific MCP ID").action(async (path, options, command) => {
|
|
1351
1326
|
const globalOptions = command.optsWithGlobals();
|
|
1352
1327
|
const json = globalOptions.json ?? false;
|
|
1353
1328
|
try {
|
|
@@ -1360,7 +1335,7 @@ var listCommand = new Command8("list").description("List files in the MCP sandbo
|
|
|
1360
1335
|
);
|
|
1361
1336
|
}
|
|
1362
1337
|
}
|
|
1363
|
-
const spinner =
|
|
1338
|
+
const spinner = ora6(`Listing ${path}...`).start();
|
|
1364
1339
|
const result = await api.get(
|
|
1365
1340
|
`/api/mcp/sandboxes/${mcpId}/files/list?path=${encodeURIComponent(path)}`
|
|
1366
1341
|
);
|
|
@@ -1396,10 +1371,10 @@ function formatSize(bytes) {
|
|
|
1396
1371
|
}
|
|
1397
1372
|
|
|
1398
1373
|
// src/commands/mcp/file/read.ts
|
|
1399
|
-
import { writeFile as
|
|
1400
|
-
import { Command as
|
|
1401
|
-
import
|
|
1402
|
-
var readCommand = new
|
|
1374
|
+
import { writeFile as writeFile4 } from "fs/promises";
|
|
1375
|
+
import { Command as Command10 } from "commander";
|
|
1376
|
+
import ora7 from "ora";
|
|
1377
|
+
var readCommand = new Command10("read").description("Read a file from the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--output <file>", "Write to local file instead of stdout").option("--base64", "Output as base64 (for binary files)").action(async (path, options, command) => {
|
|
1403
1378
|
const globalOptions = command.optsWithGlobals();
|
|
1404
1379
|
const json = globalOptions.json ?? false;
|
|
1405
1380
|
try {
|
|
@@ -1413,7 +1388,7 @@ var readCommand = new Command9("read").description("Read a file from the MCP san
|
|
|
1413
1388
|
}
|
|
1414
1389
|
}
|
|
1415
1390
|
const encoding = options.base64 ? "base64" : "utf8";
|
|
1416
|
-
const spinner =
|
|
1391
|
+
const spinner = ora7(`Reading ${path}...`).start();
|
|
1417
1392
|
const result = await api.get(
|
|
1418
1393
|
`/api/mcp/sandboxes/${mcpId}/files?path=${encodeURIComponent(path)}&encoding=${encoding}`
|
|
1419
1394
|
);
|
|
@@ -1423,7 +1398,7 @@ var readCommand = new Command9("read").description("Read a file from the MCP san
|
|
|
1423
1398
|
}
|
|
1424
1399
|
if (options.output) {
|
|
1425
1400
|
const buffer = result.encoding === "base64" ? Buffer.from(result.content, "base64") : Buffer.from(result.content, "utf8");
|
|
1426
|
-
await
|
|
1401
|
+
await writeFile4(options.output, buffer);
|
|
1427
1402
|
if (json) {
|
|
1428
1403
|
formatOutput({ path, savedTo: options.output }, true);
|
|
1429
1404
|
} else {
|
|
@@ -1445,9 +1420,9 @@ var readCommand = new Command9("read").description("Read a file from the MCP san
|
|
|
1445
1420
|
|
|
1446
1421
|
// src/commands/mcp/file/write.ts
|
|
1447
1422
|
import { readFile as readFile5 } from "fs/promises";
|
|
1448
|
-
import { Command as
|
|
1449
|
-
import
|
|
1450
|
-
var writeCommand = new
|
|
1423
|
+
import { Command as Command11 } from "commander";
|
|
1424
|
+
import ora8 from "ora";
|
|
1425
|
+
var writeCommand = new Command11("write").description("Write a file to the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--content <content>", "Content to write").option("--file <localFile>", "Local file to upload").option("--base64", "Treat content as base64 encoded").action(async (path, options, command) => {
|
|
1451
1426
|
const globalOptions = command.optsWithGlobals();
|
|
1452
1427
|
const json = globalOptions.json ?? false;
|
|
1453
1428
|
try {
|
|
@@ -1481,7 +1456,7 @@ var writeCommand = new Command10("write").description("Write a file to the MCP s
|
|
|
1481
1456
|
"MISSING_CONTENT"
|
|
1482
1457
|
);
|
|
1483
1458
|
}
|
|
1484
|
-
const spinner =
|
|
1459
|
+
const spinner = ora8(`Writing ${path}...`).start();
|
|
1485
1460
|
const result = await api.post(
|
|
1486
1461
|
`/api/mcp/sandboxes/${mcpId}/files`,
|
|
1487
1462
|
{
|
|
@@ -1501,17 +1476,17 @@ var writeCommand = new Command10("write").description("Write a file to the MCP s
|
|
|
1501
1476
|
});
|
|
1502
1477
|
|
|
1503
1478
|
// src/commands/mcp/file/index.ts
|
|
1504
|
-
var fileCommand = new
|
|
1479
|
+
var fileCommand = new Command12("file").description("File operations in MCP sandbox").addCommand(readCommand).addCommand(writeCommand).addCommand(listCommand);
|
|
1505
1480
|
|
|
1506
1481
|
// src/commands/mcp/list.ts
|
|
1507
1482
|
import chalk6 from "chalk";
|
|
1508
|
-
import { Command as
|
|
1509
|
-
import
|
|
1510
|
-
var listCommand2 = new
|
|
1483
|
+
import { Command as Command13 } from "commander";
|
|
1484
|
+
import ora9 from "ora";
|
|
1485
|
+
var listCommand2 = new Command13("list").description("List all MCPs in your organization").option("--all", "Include stopped/expired MCPs").action(async (options, command) => {
|
|
1511
1486
|
const globalOptions = command.optsWithGlobals();
|
|
1512
1487
|
const json = globalOptions.json ?? false;
|
|
1513
1488
|
try {
|
|
1514
|
-
const spinner =
|
|
1489
|
+
const spinner = ora9("Fetching MCPs...").start();
|
|
1515
1490
|
const mcps = await api.get(
|
|
1516
1491
|
`/api/mcp/sandboxes${options.all ? "?all=true" : ""}`
|
|
1517
1492
|
);
|
|
@@ -1565,9 +1540,9 @@ var listCommand2 = new Command12("list").description("List all MCPs in your orga
|
|
|
1565
1540
|
|
|
1566
1541
|
// src/commands/mcp/logs.ts
|
|
1567
1542
|
import chalk7 from "chalk";
|
|
1568
|
-
import { Command as
|
|
1569
|
-
import
|
|
1570
|
-
var logsCommand = new
|
|
1543
|
+
import { Command as Command14 } from "commander";
|
|
1544
|
+
import ora10 from "ora";
|
|
1545
|
+
var logsCommand = new Command14("logs").description("Stream logs from the MCP server").argument("[cmdId]", "Command ID (defaults to running server)").option("--mcp-id <id>", "Specific MCP ID").option("-f, --follow", "Keep streaming logs (default)", true).option("--no-follow", "Fetch logs and exit").action(async (cmdIdArg, options, command) => {
|
|
1571
1546
|
const globalOptions = command.optsWithGlobals();
|
|
1572
1547
|
const json = globalOptions.json ?? false;
|
|
1573
1548
|
let reader;
|
|
@@ -1598,7 +1573,7 @@ var logsCommand = new Command13("logs").description("Stream logs from the MCP se
|
|
|
1598
1573
|
}
|
|
1599
1574
|
let cmdId = cmdIdArg;
|
|
1600
1575
|
if (!cmdId) {
|
|
1601
|
-
const spinner =
|
|
1576
|
+
const spinner = ora10("Getting server status...").start();
|
|
1602
1577
|
const status = await api.post(
|
|
1603
1578
|
`/api/mcp/sandboxes/${mcpId}/server`,
|
|
1604
1579
|
{ action: "status" }
|
|
@@ -1715,9 +1690,9 @@ Error: ${event.error}`));
|
|
|
1715
1690
|
|
|
1716
1691
|
// src/commands/mcp/run-command.ts
|
|
1717
1692
|
import chalk8 from "chalk";
|
|
1718
|
-
import { Command as
|
|
1719
|
-
import
|
|
1720
|
-
var runCommandCommand = new
|
|
1693
|
+
import { Command as Command15 } from "commander";
|
|
1694
|
+
import ora11 from "ora";
|
|
1695
|
+
var runCommandCommand = new Command15("run-command").description("Run a command in the MCP sandbox").argument("<command>", "Command to run").argument("[args...]", "Command arguments").option("--mcp-id <id>", "Specific MCP ID").option("--cwd <path>", "Working directory").option(
|
|
1721
1696
|
"--timeout <ms>",
|
|
1722
1697
|
"Command timeout in milliseconds (default: 30000, max: 300000)"
|
|
1723
1698
|
).action(async (cmd, args, options, command) => {
|
|
@@ -1734,7 +1709,7 @@ var runCommandCommand = new Command14("run-command").description("Run a command
|
|
|
1734
1709
|
}
|
|
1735
1710
|
}
|
|
1736
1711
|
const timeout = options.timeout ? Number.parseInt(options.timeout, 10) : void 0;
|
|
1737
|
-
const spinner =
|
|
1712
|
+
const spinner = ora11(`Running: ${cmd} ${args.join(" ")}`.trim()).start();
|
|
1738
1713
|
const result = await api.post(
|
|
1739
1714
|
`/api/mcp/sandboxes/${mcpId}/commands`,
|
|
1740
1715
|
{
|
|
@@ -1781,9 +1756,9 @@ var runCommandCommand = new Command14("run-command").description("Run a command
|
|
|
1781
1756
|
|
|
1782
1757
|
// src/commands/mcp/start.ts
|
|
1783
1758
|
import chalk9 from "chalk";
|
|
1784
|
-
import { Command as
|
|
1785
|
-
import
|
|
1786
|
-
var startCommand = new
|
|
1759
|
+
import { Command as Command16 } from "commander";
|
|
1760
|
+
import ora12 from "ora";
|
|
1761
|
+
var startCommand = new Command16("start").description("Start the MCP server (npm run dev)").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
1787
1762
|
const globalOptions = command.optsWithGlobals();
|
|
1788
1763
|
const json = globalOptions.json ?? false;
|
|
1789
1764
|
try {
|
|
@@ -1796,7 +1771,7 @@ var startCommand = new Command15("start").description("Start the MCP server (npm
|
|
|
1796
1771
|
);
|
|
1797
1772
|
}
|
|
1798
1773
|
}
|
|
1799
|
-
const spinner =
|
|
1774
|
+
const spinner = ora12("Starting MCP server...").start();
|
|
1800
1775
|
const result = await api.post(
|
|
1801
1776
|
`/api/mcp/sandboxes/${mcpId}/server`,
|
|
1802
1777
|
{ action: "start" }
|
|
@@ -1831,9 +1806,9 @@ var startCommand = new Command15("start").description("Start the MCP server (npm
|
|
|
1831
1806
|
|
|
1832
1807
|
// src/commands/mcp/status.ts
|
|
1833
1808
|
import chalk10 from "chalk";
|
|
1834
|
-
import { Command as
|
|
1835
|
-
import
|
|
1836
|
-
var statusCommand = new
|
|
1809
|
+
import { Command as Command17 } from "commander";
|
|
1810
|
+
import ora13 from "ora";
|
|
1811
|
+
var statusCommand = new Command17("status").description("Show current MCP sandbox status").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
1837
1812
|
const globalOptions = command.optsWithGlobals();
|
|
1838
1813
|
const json = globalOptions.json ?? false;
|
|
1839
1814
|
try {
|
|
@@ -1846,7 +1821,7 @@ var statusCommand = new Command16("status").description("Show current MCP sandbo
|
|
|
1846
1821
|
);
|
|
1847
1822
|
}
|
|
1848
1823
|
}
|
|
1849
|
-
const spinner =
|
|
1824
|
+
const spinner = ora13("Fetching MCP status...").start();
|
|
1850
1825
|
const [result, serverStatus] = await Promise.all([
|
|
1851
1826
|
api.get(`/api/mcp/sandboxes/${mcpId}`),
|
|
1852
1827
|
api.post(`/api/mcp/sandboxes/${mcpId}/server`, {
|
|
@@ -1889,9 +1864,9 @@ var statusCommand = new Command16("status").description("Show current MCP sandbo
|
|
|
1889
1864
|
});
|
|
1890
1865
|
|
|
1891
1866
|
// src/commands/mcp/stop.ts
|
|
1892
|
-
import { Command as
|
|
1893
|
-
import
|
|
1894
|
-
var stopCommand = new
|
|
1867
|
+
import { Command as Command18 } from "commander";
|
|
1868
|
+
import ora14 from "ora";
|
|
1869
|
+
var stopCommand = new Command18("stop").description("Stop the MCP server process").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
1895
1870
|
const globalOptions = command.optsWithGlobals();
|
|
1896
1871
|
const json = globalOptions.json ?? false;
|
|
1897
1872
|
try {
|
|
@@ -1904,7 +1879,7 @@ var stopCommand = new Command17("stop").description("Stop the MCP server process
|
|
|
1904
1879
|
);
|
|
1905
1880
|
}
|
|
1906
1881
|
}
|
|
1907
|
-
const spinner =
|
|
1882
|
+
const spinner = ora14("Stopping MCP server...").start();
|
|
1908
1883
|
const result = await api.post(
|
|
1909
1884
|
`/api/mcp/sandboxes/${mcpId}/server`,
|
|
1910
1885
|
{ action: "stop" }
|
|
@@ -1925,105 +1900,14 @@ var stopCommand = new Command17("stop").description("Stop the MCP server process
|
|
|
1925
1900
|
}
|
|
1926
1901
|
});
|
|
1927
1902
|
|
|
1928
|
-
// src/commands/mcp/test.ts
|
|
1929
|
-
import chalk11 from "chalk";
|
|
1930
|
-
import { Command as Command18 } from "commander";
|
|
1931
|
-
import ora16 from "ora";
|
|
1932
|
-
var testCommand = new Command18("test").description("Test MCP tools via the sandbox").argument("[tool]", "Tool name to test (lists tools if omitted)").argument("[args...]", "JSON arguments for the tool").option("--mcp-id <id>", "Specific MCP ID").action(
|
|
1933
|
-
async (tool, args, options, command) => {
|
|
1934
|
-
const globalOptions = command.optsWithGlobals();
|
|
1935
|
-
const json = globalOptions.json ?? false;
|
|
1936
|
-
try {
|
|
1937
|
-
let mcpId = options.mcpId;
|
|
1938
|
-
if (!mcpId) {
|
|
1939
|
-
mcpId = await config.getMcpId();
|
|
1940
|
-
if (!mcpId) {
|
|
1941
|
-
throw new McpError(
|
|
1942
|
-
"No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
|
|
1943
|
-
);
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
if (!tool) {
|
|
1947
|
-
const spinner = ora16("Fetching available tools...").start();
|
|
1948
|
-
const result = await api.post(
|
|
1949
|
-
`/api/mcp/sandboxes/${mcpId}/test`,
|
|
1950
|
-
{ action: "list" }
|
|
1951
|
-
);
|
|
1952
|
-
spinner.stop();
|
|
1953
|
-
const tools = result.tools;
|
|
1954
|
-
if (json) {
|
|
1955
|
-
formatOutput({ tools }, true);
|
|
1956
|
-
} else {
|
|
1957
|
-
if (tools.length === 0) {
|
|
1958
|
-
console.log("No tools available.");
|
|
1959
|
-
} else {
|
|
1960
|
-
console.log(chalk11.bold("\nAvailable Tools:\n"));
|
|
1961
|
-
formatTable(
|
|
1962
|
-
["Name", "Description"],
|
|
1963
|
-
tools.map((t) => [t.name, t.description || "No description"]),
|
|
1964
|
-
false
|
|
1965
|
-
);
|
|
1966
|
-
console.log(
|
|
1967
|
-
`
|
|
1968
|
-
Test a tool: waniwani mcp test <tool-name> '{"arg": "value"}'`
|
|
1969
|
-
);
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
} else {
|
|
1973
|
-
let toolArgs = {};
|
|
1974
|
-
if (args.length > 0) {
|
|
1975
|
-
try {
|
|
1976
|
-
toolArgs = JSON.parse(args.join(" "));
|
|
1977
|
-
} catch {
|
|
1978
|
-
throw new SandboxError(
|
|
1979
|
-
`Invalid JSON arguments. Expected format: '{"key": "value"}'`
|
|
1980
|
-
);
|
|
1981
|
-
}
|
|
1982
|
-
}
|
|
1983
|
-
const spinner = ora16(`Calling tool "${tool}"...`).start();
|
|
1984
|
-
const startTime = Date.now();
|
|
1985
|
-
const result = await api.post(
|
|
1986
|
-
`/api/mcp/sandboxes/${mcpId}/test`,
|
|
1987
|
-
{
|
|
1988
|
-
action: "call",
|
|
1989
|
-
tool,
|
|
1990
|
-
args: toolArgs
|
|
1991
|
-
}
|
|
1992
|
-
);
|
|
1993
|
-
const duration = result.duration || Date.now() - startTime;
|
|
1994
|
-
spinner.stop();
|
|
1995
|
-
const output = {
|
|
1996
|
-
tool,
|
|
1997
|
-
input: toolArgs,
|
|
1998
|
-
result: result.result,
|
|
1999
|
-
duration
|
|
2000
|
-
};
|
|
2001
|
-
if (json) {
|
|
2002
|
-
formatOutput(output, true);
|
|
2003
|
-
} else {
|
|
2004
|
-
console.log(chalk11.bold("\nTool Result:\n"));
|
|
2005
|
-
console.log(chalk11.gray("Tool:"), tool);
|
|
2006
|
-
console.log(chalk11.gray("Input:"), JSON.stringify(toolArgs));
|
|
2007
|
-
console.log(chalk11.gray("Duration:"), `${duration}ms`);
|
|
2008
|
-
console.log(chalk11.gray("Result:"));
|
|
2009
|
-
console.log(JSON.stringify(result.result, null, 2));
|
|
2010
|
-
}
|
|
2011
|
-
}
|
|
2012
|
-
} catch (error) {
|
|
2013
|
-
handleError(error, json);
|
|
2014
|
-
process.exit(1);
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
);
|
|
2018
|
-
|
|
2019
1903
|
// src/commands/mcp/use.ts
|
|
2020
1904
|
import { Command as Command19 } from "commander";
|
|
2021
|
-
import
|
|
1905
|
+
import ora15 from "ora";
|
|
2022
1906
|
var useCommand = new Command19("use").description("Select an MCP to use for subsequent commands").argument("<name>", "Name of the MCP to use").option("--global", "Save to global config instead of project config").action(async (name, options, command) => {
|
|
2023
1907
|
const globalOptions = command.optsWithGlobals();
|
|
2024
1908
|
const json = globalOptions.json ?? false;
|
|
2025
1909
|
try {
|
|
2026
|
-
const spinner =
|
|
1910
|
+
const spinner = ora15("Fetching MCPs...").start();
|
|
2027
1911
|
const mcps = await api.get("/api/admin/mcps");
|
|
2028
1912
|
spinner.stop();
|
|
2029
1913
|
const mcp = mcps.find((m) => m.name === name);
|
|
@@ -2059,20 +1943,20 @@ var useCommand = new Command19("use").description("Select an MCP to use for subs
|
|
|
2059
1943
|
});
|
|
2060
1944
|
|
|
2061
1945
|
// src/commands/mcp/index.ts
|
|
2062
|
-
var mcpCommand = new Command20("mcp").description("MCP sandbox management commands").addCommand(listCommand2).addCommand(useCommand).addCommand(statusCommand).addCommand(startCommand).addCommand(stopCommand).addCommand(logsCommand).addCommand(deleteCommand).addCommand(
|
|
1946
|
+
var mcpCommand = new Command20("mcp").description("MCP sandbox management commands").addCommand(listCommand2).addCommand(useCommand).addCommand(statusCommand).addCommand(startCommand).addCommand(stopCommand).addCommand(logsCommand).addCommand(deleteCommand).addCommand(deployCommand).addCommand(fileCommand).addCommand(runCommandCommand);
|
|
2063
1947
|
|
|
2064
1948
|
// src/commands/org/index.ts
|
|
2065
1949
|
import { Command as Command23 } from "commander";
|
|
2066
1950
|
|
|
2067
1951
|
// src/commands/org/list.ts
|
|
2068
|
-
import
|
|
1952
|
+
import chalk11 from "chalk";
|
|
2069
1953
|
import { Command as Command21 } from "commander";
|
|
2070
|
-
import
|
|
1954
|
+
import ora16 from "ora";
|
|
2071
1955
|
var listCommand3 = new Command21("list").description("List your organizations").action(async (_, command) => {
|
|
2072
1956
|
const globalOptions = command.optsWithGlobals();
|
|
2073
1957
|
const json = globalOptions.json ?? false;
|
|
2074
1958
|
try {
|
|
2075
|
-
const spinner =
|
|
1959
|
+
const spinner = ora16("Fetching organizations...").start();
|
|
2076
1960
|
const result = await api.get("/api/oauth/orgs");
|
|
2077
1961
|
spinner.stop();
|
|
2078
1962
|
const { orgs, activeOrgId } = result;
|
|
@@ -2092,11 +1976,11 @@ var listCommand3 = new Command21("list").description("List your organizations").
|
|
|
2092
1976
|
console.log("No organizations found.");
|
|
2093
1977
|
return;
|
|
2094
1978
|
}
|
|
2095
|
-
console.log(
|
|
1979
|
+
console.log(chalk11.bold("\nOrganizations:\n"));
|
|
2096
1980
|
const rows = orgs.map((o) => {
|
|
2097
1981
|
const isActive = o.id === activeOrgId;
|
|
2098
1982
|
return [
|
|
2099
|
-
isActive ?
|
|
1983
|
+
isActive ? chalk11.cyan(`* ${o.name}`) : ` ${o.name}`,
|
|
2100
1984
|
o.slug,
|
|
2101
1985
|
o.role
|
|
2102
1986
|
];
|
|
@@ -2106,7 +1990,7 @@ var listCommand3 = new Command21("list").description("List your organizations").
|
|
|
2106
1990
|
if (activeOrgId) {
|
|
2107
1991
|
const activeOrg = orgs.find((o) => o.id === activeOrgId);
|
|
2108
1992
|
if (activeOrg) {
|
|
2109
|
-
console.log(`Active organization: ${
|
|
1993
|
+
console.log(`Active organization: ${chalk11.cyan(activeOrg.name)}`);
|
|
2110
1994
|
}
|
|
2111
1995
|
}
|
|
2112
1996
|
console.log("\nSwitch organization: waniwani org switch <name>");
|
|
@@ -2119,12 +2003,12 @@ var listCommand3 = new Command21("list").description("List your organizations").
|
|
|
2119
2003
|
|
|
2120
2004
|
// src/commands/org/switch.ts
|
|
2121
2005
|
import { Command as Command22 } from "commander";
|
|
2122
|
-
import
|
|
2006
|
+
import ora17 from "ora";
|
|
2123
2007
|
var switchCommand = new Command22("switch").description("Switch to a different organization").argument("<name>", "Name or slug of the organization to switch to").action(async (name, _, command) => {
|
|
2124
2008
|
const globalOptions = command.optsWithGlobals();
|
|
2125
2009
|
const json = globalOptions.json ?? false;
|
|
2126
2010
|
try {
|
|
2127
|
-
const spinner =
|
|
2011
|
+
const spinner = ora17("Fetching organizations...").start();
|
|
2128
2012
|
const { orgs } = await api.get("/api/oauth/orgs");
|
|
2129
2013
|
const org = orgs.find((o) => o.name === name || o.slug === name);
|
|
2130
2014
|
if (!org) {
|
|
@@ -2160,9 +2044,9 @@ var switchCommand = new Command22("switch").description("Switch to a different o
|
|
|
2160
2044
|
var orgCommand = new Command23("org").description("Organization management commands").addCommand(listCommand3).addCommand(switchCommand);
|
|
2161
2045
|
|
|
2162
2046
|
// src/commands/push.ts
|
|
2163
|
-
import
|
|
2047
|
+
import chalk12 from "chalk";
|
|
2164
2048
|
import { Command as Command24 } from "commander";
|
|
2165
|
-
import
|
|
2049
|
+
import ora18 from "ora";
|
|
2166
2050
|
var BATCH_SIZE2 = 50;
|
|
2167
2051
|
var pushCommand = new Command24("push").description("Sync local files to MCP sandbox").option("--dry-run", "Show what would be synced without uploading").action(async (options, command) => {
|
|
2168
2052
|
const globalOptions = command.optsWithGlobals();
|
|
@@ -2183,7 +2067,7 @@ var pushCommand = new Command24("push").description("Sync local files to MCP san
|
|
|
2183
2067
|
"NO_MCP_ID"
|
|
2184
2068
|
);
|
|
2185
2069
|
}
|
|
2186
|
-
const spinner =
|
|
2070
|
+
const spinner = ora18("Collecting files...").start();
|
|
2187
2071
|
const files = await collectFiles(projectRoot);
|
|
2188
2072
|
if (files.length === 0) {
|
|
2189
2073
|
spinner.info("No files to sync");
|
|
@@ -2196,7 +2080,7 @@ var pushCommand = new Command24("push").description("Sync local files to MCP san
|
|
|
2196
2080
|
if (options.dryRun) {
|
|
2197
2081
|
spinner.stop();
|
|
2198
2082
|
console.log();
|
|
2199
|
-
console.log(
|
|
2083
|
+
console.log(chalk12.bold("Files that would be synced:"));
|
|
2200
2084
|
for (const file of files) {
|
|
2201
2085
|
console.log(` ${file.path}`);
|
|
2202
2086
|
}
|
|
@@ -2240,173 +2124,17 @@ var pushCommand = new Command24("push").description("Sync local files to MCP san
|
|
|
2240
2124
|
}
|
|
2241
2125
|
});
|
|
2242
2126
|
|
|
2243
|
-
// src/commands/task.ts
|
|
2244
|
-
import chalk14 from "chalk";
|
|
2245
|
-
import { Command as Command25 } from "commander";
|
|
2246
|
-
import ora21 from "ora";
|
|
2247
|
-
var taskCommand = new Command25("task").description("Send a task to Claude running in the sandbox").argument("<prompt>", "Task description/prompt").option("--mcp-id <id>", "Specific MCP ID").option("--model <model>", "Claude model to use").option("--max-steps <n>", "Maximum tool use steps").action(async (prompt, options, command) => {
|
|
2248
|
-
const globalOptions = command.optsWithGlobals();
|
|
2249
|
-
const json = globalOptions.json ?? false;
|
|
2250
|
-
try {
|
|
2251
|
-
let mcpId = options.mcpId;
|
|
2252
|
-
if (!mcpId) {
|
|
2253
|
-
mcpId = await config.getMcpId();
|
|
2254
|
-
if (!mcpId) {
|
|
2255
|
-
throw new McpError(
|
|
2256
|
-
"No active MCP. Run 'waniwani init' then 'waniwani mcp use <name>'."
|
|
2257
|
-
);
|
|
2258
|
-
}
|
|
2259
|
-
}
|
|
2260
|
-
const token = await auth.getAccessToken();
|
|
2261
|
-
if (!token) {
|
|
2262
|
-
throw new AuthError(
|
|
2263
|
-
"Not logged in. Run 'waniwani login' to authenticate."
|
|
2264
|
-
);
|
|
2265
|
-
}
|
|
2266
|
-
const defaults = await config.getDefaults();
|
|
2267
|
-
const model = options.model ?? defaults.model;
|
|
2268
|
-
const maxSteps = options.maxSteps ? Number.parseInt(options.maxSteps, 10) : defaults.maxSteps;
|
|
2269
|
-
if (!json) {
|
|
2270
|
-
console.log();
|
|
2271
|
-
console.log(chalk14.bold("Task:"), prompt);
|
|
2272
|
-
console.log();
|
|
2273
|
-
}
|
|
2274
|
-
const spinner = ora21("Starting task...").start();
|
|
2275
|
-
const baseUrl = await api.getBaseUrl();
|
|
2276
|
-
const response = await fetch(
|
|
2277
|
-
`${baseUrl}/api/mcp/sandboxes/${mcpId}/task`,
|
|
2278
|
-
{
|
|
2279
|
-
method: "POST",
|
|
2280
|
-
headers: {
|
|
2281
|
-
"Content-Type": "application/json",
|
|
2282
|
-
Authorization: `Bearer ${token}`,
|
|
2283
|
-
Accept: "text/event-stream"
|
|
2284
|
-
},
|
|
2285
|
-
body: JSON.stringify({
|
|
2286
|
-
prompt,
|
|
2287
|
-
model,
|
|
2288
|
-
maxSteps
|
|
2289
|
-
})
|
|
2290
|
-
}
|
|
2291
|
-
);
|
|
2292
|
-
if (!response.ok) {
|
|
2293
|
-
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
2294
|
-
spinner.fail("Task failed");
|
|
2295
|
-
throw new Error(
|
|
2296
|
-
error.message || `Request failed with status ${response.status}`
|
|
2297
|
-
);
|
|
2298
|
-
}
|
|
2299
|
-
spinner.stop();
|
|
2300
|
-
const steps = [];
|
|
2301
|
-
let stepCount = 0;
|
|
2302
|
-
let maxStepsReached = false;
|
|
2303
|
-
const reader = response.body?.getReader();
|
|
2304
|
-
if (!reader) {
|
|
2305
|
-
throw new Error("No response body");
|
|
2306
|
-
}
|
|
2307
|
-
const decoder = new TextDecoder();
|
|
2308
|
-
let buffer = "";
|
|
2309
|
-
while (true) {
|
|
2310
|
-
const { done, value } = await reader.read();
|
|
2311
|
-
if (done) break;
|
|
2312
|
-
buffer += decoder.decode(value, { stream: true });
|
|
2313
|
-
const lines = buffer.split("\n");
|
|
2314
|
-
buffer = lines.pop() || "";
|
|
2315
|
-
for (const line of lines) {
|
|
2316
|
-
if (line.startsWith("event: ")) {
|
|
2317
|
-
continue;
|
|
2318
|
-
}
|
|
2319
|
-
if (line.startsWith("data: ")) {
|
|
2320
|
-
const data = line.slice(6);
|
|
2321
|
-
if (!data || data === "[DONE]") continue;
|
|
2322
|
-
try {
|
|
2323
|
-
const parsed = JSON.parse(data);
|
|
2324
|
-
if (parsed.type === "text") {
|
|
2325
|
-
const event = parsed;
|
|
2326
|
-
steps.push({ type: "text", text: event.content });
|
|
2327
|
-
if (!json && event.content) {
|
|
2328
|
-
console.log(chalk14.white(event.content));
|
|
2329
|
-
}
|
|
2330
|
-
} else if (parsed.type === "tool_call") {
|
|
2331
|
-
const event = parsed;
|
|
2332
|
-
steps.push({
|
|
2333
|
-
type: "tool_call",
|
|
2334
|
-
tool: event.tool,
|
|
2335
|
-
input: event.input,
|
|
2336
|
-
output: event.output
|
|
2337
|
-
});
|
|
2338
|
-
if (!json) {
|
|
2339
|
-
console.log(chalk14.cyan(`> Using tool: ${event.tool}`));
|
|
2340
|
-
if (event.input?.command) {
|
|
2341
|
-
console.log(chalk14.gray(` $ ${event.input.command}`));
|
|
2342
|
-
}
|
|
2343
|
-
if (event.output) {
|
|
2344
|
-
const outputLines = event.output.split("\n");
|
|
2345
|
-
if (outputLines.length > 10) {
|
|
2346
|
-
console.log(
|
|
2347
|
-
chalk14.gray(outputLines.slice(0, 5).join("\n"))
|
|
2348
|
-
);
|
|
2349
|
-
console.log(
|
|
2350
|
-
chalk14.gray(
|
|
2351
|
-
` ... (${outputLines.length - 10} more lines)`
|
|
2352
|
-
)
|
|
2353
|
-
);
|
|
2354
|
-
console.log(chalk14.gray(outputLines.slice(-5).join("\n")));
|
|
2355
|
-
} else {
|
|
2356
|
-
console.log(chalk14.gray(event.output));
|
|
2357
|
-
}
|
|
2358
|
-
}
|
|
2359
|
-
console.log();
|
|
2360
|
-
}
|
|
2361
|
-
} else if (parsed.success !== void 0) {
|
|
2362
|
-
const doneEvent = parsed;
|
|
2363
|
-
stepCount = doneEvent.stepCount;
|
|
2364
|
-
maxStepsReached = doneEvent.maxStepsReached || false;
|
|
2365
|
-
}
|
|
2366
|
-
} catch {
|
|
2367
|
-
}
|
|
2368
|
-
}
|
|
2369
|
-
}
|
|
2370
|
-
}
|
|
2371
|
-
const result = {
|
|
2372
|
-
success: true,
|
|
2373
|
-
steps,
|
|
2374
|
-
stepCount,
|
|
2375
|
-
maxStepsReached
|
|
2376
|
-
};
|
|
2377
|
-
const finalStepCount = stepCount ?? steps.length;
|
|
2378
|
-
if (json) {
|
|
2379
|
-
formatOutput({ ...result, stepCount: finalStepCount }, true);
|
|
2380
|
-
} else {
|
|
2381
|
-
console.log();
|
|
2382
|
-
console.log(
|
|
2383
|
-
chalk14.green("\u2713"),
|
|
2384
|
-
`Task completed in ${finalStepCount} steps.`
|
|
2385
|
-
);
|
|
2386
|
-
if (maxStepsReached) {
|
|
2387
|
-
console.log(
|
|
2388
|
-
chalk14.yellow("\u26A0"),
|
|
2389
|
-
"Maximum steps reached. Task may be incomplete."
|
|
2390
|
-
);
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
} catch (error) {
|
|
2394
|
-
handleError(error, json);
|
|
2395
|
-
process.exit(1);
|
|
2396
|
-
}
|
|
2397
|
-
});
|
|
2398
|
-
|
|
2399
2127
|
// src/cli.ts
|
|
2400
2128
|
var version = "0.1.0";
|
|
2401
|
-
var program = new
|
|
2129
|
+
var program = new Command25().name("waniwani").description("WaniWani CLI for MCP development workflow").version(version).option("--json", "Output results as JSON").option("--verbose", "Enable verbose logging");
|
|
2402
2130
|
program.addCommand(loginCommand);
|
|
2403
2131
|
program.addCommand(logoutCommand);
|
|
2404
2132
|
program.addCommand(initCommand);
|
|
2405
2133
|
program.addCommand(pushCommand);
|
|
2406
2134
|
program.addCommand(devCommand);
|
|
2407
2135
|
program.addCommand(mcpCommand);
|
|
2408
|
-
program.addCommand(taskCommand);
|
|
2409
2136
|
program.addCommand(orgCommand);
|
|
2137
|
+
program.addCommand(configCommand);
|
|
2410
2138
|
|
|
2411
2139
|
// src/index.ts
|
|
2412
2140
|
program.parse(process.argv);
|