@waniwani/cli 0.0.38 → 0.0.39

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/README.md CHANGED
@@ -44,8 +44,8 @@ Requires Node.js 20 or later.
44
44
  # Authenticate
45
45
  waniwani login
46
46
 
47
- # Create an MCP sandbox
48
- waniwani mcp create my-server
47
+ # Create an MCP project
48
+ waniwani mcp init my-server
49
49
 
50
50
  # Send tasks to Claude
51
51
  waniwani task "Add a weather tool"
@@ -63,7 +63,7 @@ waniwani mcp publish
63
63
  |---------|-------------|
64
64
  | `login` | Authenticate with WaniWani |
65
65
  | `logout` | Clear local credentials |
66
- | `mcp create <name>` | Create a new MCP sandbox |
66
+ | `mcp init <name>` | Create a new MCP project |
67
67
  | `mcp list` | List your MCPs |
68
68
  | `mcp use <name>` | Select active MCP |
69
69
  | `mcp status` | Show current MCP status |
package/dist/index.js CHANGED
@@ -1097,18 +1097,142 @@ var writeCommand = new Command8("write").description("Write a file to the MCP sa
1097
1097
  var fileCommand = new Command9("file").description("File operations in MCP sandbox").addCommand(readCommand).addCommand(writeCommand).addCommand(listCommand);
1098
1098
 
1099
1099
  // src/commands/mcp/init.ts
1100
- import { existsSync as existsSync3, mkdirSync } from "fs";
1101
- import { readFile as readFile3 } from "fs/promises";
1102
- import { join as join3 } from "path";
1100
+ import { existsSync as existsSync4, mkdirSync } from "fs";
1101
+ import { readFile as readFile4 } from "fs/promises";
1102
+ import { join as join4 } from "path";
1103
1103
  import { Command as Command10 } from "commander";
1104
1104
  import ora6 from "ora";
1105
+
1106
+ // src/lib/sync.ts
1107
+ import { existsSync as existsSync3 } from "fs";
1108
+ import { mkdir as mkdir2, readdir, readFile as readFile3, stat, writeFile as writeFile3 } from "fs/promises";
1109
+ import { dirname, join as join3, relative } from "path";
1110
+ import ignore from "ignore";
1111
+ var PROJECT_DIR = ".waniwani";
1112
+ async function findProjectRoot(startDir) {
1113
+ let current = startDir;
1114
+ const root = dirname(current);
1115
+ while (current !== root) {
1116
+ if (existsSync3(join3(current, PROJECT_DIR))) {
1117
+ return current;
1118
+ }
1119
+ const parent = dirname(current);
1120
+ if (parent === current) break;
1121
+ current = parent;
1122
+ }
1123
+ if (existsSync3(join3(current, PROJECT_DIR))) {
1124
+ return current;
1125
+ }
1126
+ return null;
1127
+ }
1128
+ var DEFAULT_IGNORE_PATTERNS = [
1129
+ ".waniwani",
1130
+ ".git",
1131
+ "node_modules",
1132
+ ".env",
1133
+ ".env.*",
1134
+ ".DS_Store",
1135
+ "*.log",
1136
+ ".cache",
1137
+ "dist",
1138
+ "coverage",
1139
+ ".turbo",
1140
+ ".next",
1141
+ ".nuxt",
1142
+ ".vercel"
1143
+ ];
1144
+ async function loadIgnorePatterns(projectRoot) {
1145
+ const ig = ignore();
1146
+ ig.add(DEFAULT_IGNORE_PATTERNS);
1147
+ const gitignorePath = join3(projectRoot, ".gitignore");
1148
+ if (existsSync3(gitignorePath)) {
1149
+ try {
1150
+ const content = await readFile3(gitignorePath, "utf-8");
1151
+ ig.add(content);
1152
+ } catch {
1153
+ }
1154
+ }
1155
+ return ig;
1156
+ }
1157
+ async function collectFiles(projectRoot) {
1158
+ const ig = await loadIgnorePatterns(projectRoot);
1159
+ const files = [];
1160
+ async function walk(dir) {
1161
+ const entries = await readdir(dir, { withFileTypes: true });
1162
+ for (const entry of entries) {
1163
+ const fullPath = join3(dir, entry.name);
1164
+ const relativePath = relative(projectRoot, fullPath);
1165
+ if (ig.ignores(relativePath)) {
1166
+ continue;
1167
+ }
1168
+ if (entry.isDirectory()) {
1169
+ await walk(fullPath);
1170
+ } else if (entry.isFile()) {
1171
+ try {
1172
+ const content = await readFile3(fullPath);
1173
+ const isBinary = isBinaryPath(fullPath) || detectBinary(content);
1174
+ files.push({
1175
+ path: relativePath,
1176
+ content: isBinary ? content.toString("base64") : content.toString("utf8"),
1177
+ encoding: isBinary ? "base64" : "utf8"
1178
+ });
1179
+ } catch {
1180
+ }
1181
+ }
1182
+ }
1183
+ }
1184
+ await walk(projectRoot);
1185
+ return files;
1186
+ }
1187
+ async function pullFilesFromGithub(mcpId, targetDir) {
1188
+ const result = await api.get(
1189
+ `/api/mcp/repositories/${mcpId}/files`
1190
+ );
1191
+ const writtenFiles = [];
1192
+ for (const file of result.files) {
1193
+ const localPath = join3(targetDir, file.path);
1194
+ const dir = dirname(localPath);
1195
+ await mkdir2(dir, { recursive: true });
1196
+ if (file.encoding === "base64") {
1197
+ await writeFile3(localPath, Buffer.from(file.content, "base64"));
1198
+ } else {
1199
+ await writeFile3(localPath, file.content, "utf8");
1200
+ }
1201
+ writtenFiles.push(file.path);
1202
+ }
1203
+ return { count: writtenFiles.length, files: writtenFiles };
1204
+ }
1205
+ async function collectSingleFile(projectRoot, filePath) {
1206
+ const fullPath = join3(projectRoot, filePath);
1207
+ const relativePath = relative(projectRoot, fullPath);
1208
+ if (!existsSync3(fullPath)) {
1209
+ return null;
1210
+ }
1211
+ try {
1212
+ const fileStat = await stat(fullPath);
1213
+ if (!fileStat.isFile()) {
1214
+ return null;
1215
+ }
1216
+ const content = await readFile3(fullPath);
1217
+ const isBinary = isBinaryPath(fullPath) || detectBinary(content);
1218
+ return {
1219
+ path: relativePath,
1220
+ content: isBinary ? content.toString("base64") : content.toString("utf8"),
1221
+ encoding: isBinary ? "base64" : "utf8"
1222
+ };
1223
+ } catch {
1224
+ return null;
1225
+ }
1226
+ }
1227
+
1228
+ // src/commands/mcp/init.ts
1105
1229
  async function loadParentConfig(cwd) {
1106
- const parentConfigPath = join3(cwd, LOCAL_CONFIG_DIR, CONFIG_FILE_NAME);
1107
- if (!existsSync3(parentConfigPath)) {
1230
+ const parentConfigPath = join4(cwd, LOCAL_CONFIG_DIR, CONFIG_FILE_NAME);
1231
+ if (!existsSync4(parentConfigPath)) {
1108
1232
  return null;
1109
1233
  }
1110
1234
  try {
1111
- const content = await readFile3(parentConfigPath, "utf-8");
1235
+ const content = await readFile4(parentConfigPath, "utf-8");
1112
1236
  const config2 = JSON.parse(content);
1113
1237
  const { mcpId: _, sessionId: __, ...rest } = config2;
1114
1238
  return rest;
@@ -1121,8 +1245,8 @@ var initCommand = new Command10("init").description("Create a new MCP project").
1121
1245
  const json = globalOptions.json ?? false;
1122
1246
  try {
1123
1247
  const cwd = process.cwd();
1124
- const projectDir = join3(cwd, name);
1125
- if (existsSync3(projectDir)) {
1248
+ const projectDir = join4(cwd, name);
1249
+ if (existsSync4(projectDir)) {
1126
1250
  if (json) {
1127
1251
  formatOutput(
1128
1252
  {
@@ -1147,12 +1271,16 @@ var initCommand = new Command10("init").description("Create a new MCP project").
1147
1271
  mcpId: result.id
1148
1272
  });
1149
1273
  spinner.succeed("MCP project created");
1274
+ spinner.start("Pulling template files...");
1275
+ const syncResult = await pullFilesFromGithub(result.id, projectDir);
1276
+ spinner.succeed(`Pulled ${syncResult.count} files`);
1150
1277
  if (json) {
1151
1278
  formatOutput(
1152
1279
  {
1153
1280
  success: true,
1154
1281
  projectDir,
1155
- mcpId: result.id
1282
+ mcpId: result.id,
1283
+ files: syncResult.files
1156
1284
  },
1157
1285
  true
1158
1286
  );
@@ -1162,7 +1290,6 @@ var initCommand = new Command10("init").description("Create a new MCP project").
1162
1290
  console.log();
1163
1291
  console.log("Next steps:");
1164
1292
  console.log(` cd ${name}`);
1165
- console.log(" waniwani mcp sync # Pull template files");
1166
1293
  console.log(" waniwani mcp preview # Start developing");
1167
1294
  }
1168
1295
  } catch (error) {
@@ -1378,130 +1505,6 @@ Error: ${event.error}`));
1378
1505
  import { watch } from "chokidar";
1379
1506
  import { Command as Command13 } from "commander";
1380
1507
  import ora9 from "ora";
1381
-
1382
- // src/lib/sync.ts
1383
- import { existsSync as existsSync4 } from "fs";
1384
- import { mkdir as mkdir2, readdir, readFile as readFile4, stat, writeFile as writeFile3 } from "fs/promises";
1385
- import { dirname, join as join4, relative } from "path";
1386
- import ignore from "ignore";
1387
- var PROJECT_DIR = ".waniwani";
1388
- async function findProjectRoot(startDir) {
1389
- let current = startDir;
1390
- const root = dirname(current);
1391
- while (current !== root) {
1392
- if (existsSync4(join4(current, PROJECT_DIR))) {
1393
- return current;
1394
- }
1395
- const parent = dirname(current);
1396
- if (parent === current) break;
1397
- current = parent;
1398
- }
1399
- if (existsSync4(join4(current, PROJECT_DIR))) {
1400
- return current;
1401
- }
1402
- return null;
1403
- }
1404
- var DEFAULT_IGNORE_PATTERNS = [
1405
- ".waniwani",
1406
- ".git",
1407
- "node_modules",
1408
- ".env",
1409
- ".env.*",
1410
- ".DS_Store",
1411
- "*.log",
1412
- ".cache",
1413
- "dist",
1414
- "coverage",
1415
- ".turbo",
1416
- ".next",
1417
- ".nuxt",
1418
- ".vercel"
1419
- ];
1420
- async function loadIgnorePatterns(projectRoot) {
1421
- const ig = ignore();
1422
- ig.add(DEFAULT_IGNORE_PATTERNS);
1423
- const gitignorePath = join4(projectRoot, ".gitignore");
1424
- if (existsSync4(gitignorePath)) {
1425
- try {
1426
- const content = await readFile4(gitignorePath, "utf-8");
1427
- ig.add(content);
1428
- } catch {
1429
- }
1430
- }
1431
- return ig;
1432
- }
1433
- async function collectFiles(projectRoot) {
1434
- const ig = await loadIgnorePatterns(projectRoot);
1435
- const files = [];
1436
- async function walk(dir) {
1437
- const entries = await readdir(dir, { withFileTypes: true });
1438
- for (const entry of entries) {
1439
- const fullPath = join4(dir, entry.name);
1440
- const relativePath = relative(projectRoot, fullPath);
1441
- if (ig.ignores(relativePath)) {
1442
- continue;
1443
- }
1444
- if (entry.isDirectory()) {
1445
- await walk(fullPath);
1446
- } else if (entry.isFile()) {
1447
- try {
1448
- const content = await readFile4(fullPath);
1449
- const isBinary = isBinaryPath(fullPath) || detectBinary(content);
1450
- files.push({
1451
- path: relativePath,
1452
- content: isBinary ? content.toString("base64") : content.toString("utf8"),
1453
- encoding: isBinary ? "base64" : "utf8"
1454
- });
1455
- } catch {
1456
- }
1457
- }
1458
- }
1459
- }
1460
- await walk(projectRoot);
1461
- return files;
1462
- }
1463
- async function pullFilesFromGithub(mcpId, targetDir) {
1464
- const result = await api.get(
1465
- `/api/mcp/repositories/${mcpId}/files`
1466
- );
1467
- const writtenFiles = [];
1468
- for (const file of result.files) {
1469
- const localPath = join4(targetDir, file.path);
1470
- const dir = dirname(localPath);
1471
- await mkdir2(dir, { recursive: true });
1472
- if (file.encoding === "base64") {
1473
- await writeFile3(localPath, Buffer.from(file.content, "base64"));
1474
- } else {
1475
- await writeFile3(localPath, file.content, "utf8");
1476
- }
1477
- writtenFiles.push(file.path);
1478
- }
1479
- return { count: writtenFiles.length, files: writtenFiles };
1480
- }
1481
- async function collectSingleFile(projectRoot, filePath) {
1482
- const fullPath = join4(projectRoot, filePath);
1483
- const relativePath = relative(projectRoot, fullPath);
1484
- if (!existsSync4(fullPath)) {
1485
- return null;
1486
- }
1487
- try {
1488
- const fileStat = await stat(fullPath);
1489
- if (!fileStat.isFile()) {
1490
- return null;
1491
- }
1492
- const content = await readFile4(fullPath);
1493
- const isBinary = isBinaryPath(fullPath) || detectBinary(content);
1494
- return {
1495
- path: relativePath,
1496
- content: isBinary ? content.toString("base64") : content.toString("utf8"),
1497
- encoding: isBinary ? "base64" : "utf8"
1498
- };
1499
- } catch {
1500
- return null;
1501
- }
1502
- }
1503
-
1504
- // src/commands/mcp/preview.ts
1505
1508
  var previewCommand = new Command13("preview").description("Start live development with sandbox and file watching").option("--mcp-id <id>", "Specific MCP ID").option("--no-watch", "Skip file watching").option("--no-logs", "Don't stream logs to terminal").action(async (options, command) => {
1506
1509
  const globalOptions = command.optsWithGlobals();
1507
1510
  const json = globalOptions.json ?? false;
@@ -1526,12 +1529,14 @@ var previewCommand = new Command13("preview").description("Start live developmen
1526
1529
  const spinner = ora9("Starting development environment...").start();
1527
1530
  spinner.text = "Starting session...";
1528
1531
  let sessionId;
1532
+ let previewUrl;
1529
1533
  try {
1530
1534
  const sessionResponse = await api.post(
1531
1535
  `/api/mcp/repositories/${mcpId}/session`,
1532
1536
  {}
1533
1537
  );
1534
1538
  sessionId = sessionResponse.sandbox.id;
1539
+ previewUrl = sessionResponse.previewUrl;
1535
1540
  } catch {
1536
1541
  const existing = await api.get(
1537
1542
  `/api/mcp/repositories/${mcpId}/session`
@@ -1540,6 +1545,7 @@ var previewCommand = new Command13("preview").description("Start live developmen
1540
1545
  throw new CLIError("Failed to start session", "SESSION_ERROR");
1541
1546
  }
1542
1547
  sessionId = existing.id;
1548
+ previewUrl = existing.previewUrl;
1543
1549
  }
1544
1550
  await config.setSessionId(sessionId);
1545
1551
  spinner.text = "Syncing files to sandbox...";
@@ -1550,20 +1556,15 @@ var previewCommand = new Command13("preview").description("Start live developmen
1550
1556
  { files }
1551
1557
  );
1552
1558
  }
1553
- spinner.text = "Starting MCP server...";
1554
- const serverResult = await api.post(
1555
- `/api/mcp/sessions/${sessionId}/server`,
1556
- { action: "start" }
1557
- );
1558
1559
  spinner.succeed("Development environment ready");
1559
1560
  console.log();
1560
1561
  formatSuccess("Live preview started!", false);
1561
1562
  console.log();
1562
- console.log(` Preview URL: ${serverResult.previewUrl}`);
1563
+ console.log(` Preview URL: ${previewUrl}`);
1563
1564
  console.log();
1564
1565
  console.log(` MCP Inspector:`);
1565
1566
  console.log(
1566
- ` npx @anthropic-ai/mcp-inspector@latest "${serverResult.previewUrl}/mcp"`
1567
+ ` npx @anthropic-ai/mcp-inspector@latest "${previewUrl}/mcp"`
1567
1568
  );
1568
1569
  console.log();
1569
1570
  if (options.watch !== false) {
@@ -1839,7 +1840,7 @@ var stopCommand = new Command17("stop").description("Stop the development enviro
1839
1840
  // src/commands/mcp/sync.ts
1840
1841
  import { Command as Command18 } from "commander";
1841
1842
  import ora14 from "ora";
1842
- var syncCommand = new Command18("sync").description("Pull files from GitHub to local project").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
1843
+ var syncCommand = new Command18("sync").description("Pull template files to local project").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
1843
1844
  const globalOptions = command.optsWithGlobals();
1844
1845
  const json = globalOptions.json ?? false;
1845
1846
  try {
@@ -1851,14 +1852,14 @@ var syncCommand = new Command18("sync").description("Pull files from GitHub to l
1851
1852
  "NOT_IN_PROJECT"
1852
1853
  );
1853
1854
  }
1854
- const spinner = ora14("Pulling files from GitHub...").start();
1855
+ const spinner = ora14("Pulling files...").start();
1855
1856
  const result = await pullFilesFromGithub(mcpId, projectRoot);
1856
- spinner.succeed(`Pulled ${result.count} files from GitHub`);
1857
+ spinner.succeed(`Pulled ${result.count} files`);
1857
1858
  if (json) {
1858
1859
  formatOutput({ files: result.files }, true);
1859
1860
  } else {
1860
1861
  console.log();
1861
- formatSuccess("Files synced from GitHub!", false);
1862
+ formatSuccess("Files synced!", false);
1862
1863
  if (result.files.length > 0 && result.files.length <= 10) {
1863
1864
  console.log();
1864
1865
  for (const file of result.files) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/commands/config/index.ts","../src/commands/config/init.ts","../src/lib/config.ts","../src/lib/errors.ts","../src/lib/output.ts","../src/commands/login.ts","../src/lib/auth.ts","../src/commands/logout.ts","../src/commands/mcp/index.ts","../src/commands/mcp/delete.ts","../src/lib/api.ts","../src/lib/utils.ts","../src/commands/mcp/file/index.ts","../src/commands/mcp/file/list.ts","../src/commands/mcp/file/read.ts","../src/commands/mcp/file/write.ts","../src/commands/mcp/init.ts","../src/commands/mcp/list.ts","../src/commands/mcp/logs.ts","../src/commands/mcp/preview.ts","../src/lib/sync.ts","../src/commands/mcp/publish.ts","../src/commands/mcp/run-command.ts","../src/commands/mcp/status.ts","../src/commands/mcp/stop.ts","../src/commands/mcp/sync.ts","../src/commands/mcp/use.ts","../src/commands/org/index.ts","../src/commands/org/list.ts","../src/commands/org/switch.ts","../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { Command } from \"commander\";\nimport { configCommand } from \"./commands/config/index.js\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { logoutCommand } from \"./commands/logout.js\";\nimport { mcpCommand } from \"./commands/mcp/index.js\";\nimport { orgCommand } from \"./commands/org/index.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nexport const program = new Command()\n\t.name(\"waniwani\")\n\t.description(\"WaniWani CLI for MCP development workflow\")\n\t.version(version)\n\t.option(\"--json\", \"Output results as JSON\")\n\t.option(\"--verbose\", \"Enable verbose logging\");\n\n// Auth commands\nprogram.addCommand(loginCommand);\nprogram.addCommand(logoutCommand);\n\n// Main commands\nprogram.addCommand(mcpCommand);\nprogram.addCommand(orgCommand);\nprogram.addCommand(configCommand);\n","import { Command } from \"commander\";\nimport { configInitCommand } from \"./init.js\";\n\nexport const configCommand = new Command(\"config\")\n\t.description(\"Manage WaniWani configuration\")\n\t.addCommand(configInitCommand);\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport {\n\tCONFIG_FILE_NAME,\n\tinitConfigAt,\n\tLOCAL_CONFIG_DIR,\n} from \"../../lib/config.js\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\n\nexport const configInitCommand = new Command(\"init\")\n\t.description(\"Initialize .waniwani config in the current directory\")\n\t.option(\"--force\", \"Overwrite existing config\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst cwd = process.cwd();\n\t\t\tconst configPath = join(cwd, LOCAL_CONFIG_DIR, CONFIG_FILE_NAME);\n\n\t\t\t// Check if config already exists\n\t\t\tif (existsSync(configPath) && !options.force) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t`Config already exists at ${configPath}. Use --force to overwrite.`,\n\t\t\t\t\t\"CONFIG_EXISTS\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Create .waniwani/settings.json with defaults\n\t\t\tconst result = await initConfigAt(cwd);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ created: result.path, config: result.config }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(`Created ${result.path}`, false);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\n\nexport const LOCAL_CONFIG_DIR = \".waniwani\";\nexport const CONFIG_FILE_NAME = \"settings.json\";\n\nconst LOCAL_DIR = join(process.cwd(), LOCAL_CONFIG_DIR);\nconst LOCAL_FILE = join(LOCAL_DIR, CONFIG_FILE_NAME);\nconst DEFAULT_API_URL = \"https://app.waniwani.ai\";\n\nconst ConfigSchema = z.object({\n\t// Settings\n\tsessionId: z.string().nullable().default(null),\n\tmcpId: z.string().nullable().default(null),\n\tapiUrl: z.string().default(DEFAULT_API_URL),\n\t// Auth (merged from auth.json)\n\taccessToken: z.string().nullable().default(null),\n\trefreshToken: z.string().nullable().default(null),\n\texpiresAt: z.string().nullable().default(null),\n\tclientId: z.string().nullable().default(null),\n});\n\ntype ConfigData = z.infer<typeof ConfigSchema>;\n\nclass Config {\n\tprivate dir: string;\n\tprivate file: string;\n\tprivate cache: ConfigData | null = null;\n\n\tconstructor() {\n\t\tthis.dir = LOCAL_DIR;\n\t\tthis.file = LOCAL_FILE;\n\t}\n\n\tprivate async load(): Promise<ConfigData> {\n\t\tif (!this.cache) {\n\t\t\ttry {\n\t\t\t\tthis.cache = ConfigSchema.parse(\n\t\t\t\t\tJSON.parse(await readFile(this.file, \"utf-8\")),\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\tthis.cache = ConfigSchema.parse({});\n\t\t\t}\n\t\t}\n\t\treturn this.cache;\n\t}\n\n\tprivate async save(data: ConfigData): Promise<void> {\n\t\tthis.cache = data;\n\t\tawait mkdir(this.dir, { recursive: true });\n\t\tawait writeFile(this.file, JSON.stringify(data, null, \"\\t\"));\n\t}\n\n\t/**\n\t * Ensure the .waniwani directory exists in cwd.\n\t * Used by login to create config before saving tokens.\n\t */\n\tasync ensureConfigDir(): Promise<void> {\n\t\tawait mkdir(this.dir, { recursive: true });\n\t}\n\n\t/**\n\t * Check if a .waniwani config directory exists in cwd.\n\t */\n\thasConfig(): boolean {\n\t\treturn existsSync(this.dir);\n\t}\n\n\t// --- Settings methods ---\n\n\tasync getMcpId() {\n\t\treturn (await this.load()).mcpId;\n\t}\n\n\tasync setMcpId(id: string | null) {\n\t\tconst data = await this.load();\n\t\tdata.mcpId = id;\n\t\tawait this.save(data);\n\t}\n\n\tasync getSessionId() {\n\t\treturn (await this.load()).sessionId;\n\t}\n\n\tasync setSessionId(id: string | null) {\n\t\tconst data = await this.load();\n\t\tdata.sessionId = id;\n\t\tawait this.save(data);\n\t}\n\n\tasync getApiUrl() {\n\t\tif (process.env.WANIWANI_API_URL) return process.env.WANIWANI_API_URL;\n\t\treturn (await this.load()).apiUrl;\n\t}\n\n\tasync clear() {\n\t\tawait this.save(ConfigSchema.parse({}));\n\t}\n\n\t// --- Auth methods ---\n\n\tasync getAccessToken(): Promise<string | null> {\n\t\treturn (await this.load()).accessToken;\n\t}\n\n\tasync getRefreshToken(): Promise<string | null> {\n\t\treturn (await this.load()).refreshToken;\n\t}\n\n\tasync getClientId(): Promise<string | null> {\n\t\treturn (await this.load()).clientId;\n\t}\n\n\tasync setTokens(\n\t\taccessToken: string,\n\t\trefreshToken: string,\n\t\texpiresIn: number,\n\t\tclientId?: string,\n\t): Promise<void> {\n\t\tconst expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString();\n\t\tconst data = await this.load();\n\t\tdata.accessToken = accessToken;\n\t\tdata.refreshToken = refreshToken;\n\t\tdata.expiresAt = expiresAt;\n\t\tif (clientId) {\n\t\t\tdata.clientId = clientId;\n\t\t}\n\t\tawait this.save(data);\n\t}\n\n\tasync clearAuth(): Promise<void> {\n\t\tconst data = await this.load();\n\t\tdata.accessToken = null;\n\t\tdata.refreshToken = null;\n\t\tdata.expiresAt = null;\n\t\tdata.clientId = null;\n\t\tawait this.save(data);\n\t}\n\n\tasync isTokenExpired(): Promise<boolean> {\n\t\tconst data = await this.load();\n\t\tif (!data.expiresAt) return true;\n\t\t// Consider expired 5 minutes before actual expiry\n\t\treturn new Date(data.expiresAt).getTime() - 5 * 60 * 1000 < Date.now();\n\t}\n}\n\nexport const config = new Config();\n\n/**\n * Initialize a .waniwani/settings.json at the given directory.\n * Returns the created config data and path.\n */\nexport async function initConfigAt(\n\tdir: string,\n\toverrides: Partial<ConfigData> = {},\n): Promise<{ path: string; config: ConfigData }> {\n\tconst configDir = join(dir, LOCAL_CONFIG_DIR);\n\tconst configPath = join(configDir, CONFIG_FILE_NAME);\n\n\tawait mkdir(configDir, { recursive: true });\n\n\tconst data = ConfigSchema.parse(overrides);\n\tawait writeFile(configPath, JSON.stringify(data, null, \"\\t\"), \"utf-8\");\n\n\treturn { path: configPath, config: data };\n}\n","import chalk from \"chalk\";\nimport { ZodError } from \"zod\";\n\nexport class CLIError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic code: string,\n\t\tpublic details?: Record<string, unknown>,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CLIError\";\n\t}\n}\n\nexport class ConfigError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"CONFIG_ERROR\", details);\n\t}\n}\n\nexport class AuthError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"AUTH_ERROR\", details);\n\t}\n}\n\nexport class SandboxError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"SANDBOX_ERROR\", details);\n\t}\n}\n\nexport class GitHubError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"GITHUB_ERROR\", details);\n\t}\n}\n\nexport class McpError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"MCP_ERROR\", details);\n\t}\n}\n\nexport function handleError(error: unknown, json: boolean): void {\n\tif (error instanceof ZodError) {\n\t\tconst message = error.issues\n\t\t\t.map((e) => `${e.path.join(\".\")}: ${e.message}`)\n\t\t\t.join(\", \");\n\t\toutputError(\"VALIDATION_ERROR\", `Invalid input: ${message}`, json);\n\t} else if (error instanceof CLIError) {\n\t\toutputError(error.code, error.message, json, error.details);\n\t} else if (error instanceof Error) {\n\t\toutputError(\"UNKNOWN_ERROR\", error.message, json);\n\t} else {\n\t\toutputError(\"UNKNOWN_ERROR\", String(error), json);\n\t}\n}\n\nfunction outputError(\n\tcode: string,\n\tmessage: string,\n\tjson: boolean,\n\tdetails?: Record<string, unknown>,\n): void {\n\tif (json) {\n\t\tconsole.error(\n\t\t\tJSON.stringify({ success: false, error: { code, message, details } }),\n\t\t);\n\t} else {\n\t\tconsole.error(chalk.red(`Error [${code}]:`), message);\n\t\tif (details) {\n\t\t\tconsole.error(chalk.gray(\"Details:\"), JSON.stringify(details, null, 2));\n\t\t}\n\t}\n}\n","import chalk from \"chalk\";\n\nexport function formatOutput<T>(data: T, json: boolean): void {\n\tif (json) {\n\t\tconsole.log(JSON.stringify({ success: true, data }, null, 2));\n\t} else {\n\t\tprettyPrint(data);\n\t}\n}\n\nexport function formatSuccess(message: string, json: boolean): void {\n\tif (json) {\n\t\tconsole.log(JSON.stringify({ success: true, message }));\n\t} else {\n\t\tconsole.log(chalk.green(\"✓\"), message);\n\t}\n}\n\nexport function formatError(error: Error | string, json: boolean): void {\n\tconst message = error instanceof Error ? error.message : error;\n\tif (json) {\n\t\tconsole.error(JSON.stringify({ success: false, error: message }));\n\t} else {\n\t\tconsole.error(chalk.red(\"✗\"), message);\n\t}\n}\n\nexport function formatTable(\n\theaders: string[],\n\trows: string[][],\n\tjson: boolean,\n): void {\n\tif (json) {\n\t\tconst data = rows.map((row) =>\n\t\t\tObject.fromEntries(headers.map((header, i) => [header, row[i]])),\n\t\t);\n\t\tconsole.log(JSON.stringify({ success: true, data }, null, 2));\n\t} else {\n\t\t// Simple table formatting without external dependency\n\t\tconst colWidths = headers.map((h, i) =>\n\t\t\tMath.max(h.length, ...rows.map((r) => (r[i] || \"\").length)),\n\t\t);\n\n\t\tconst separator = colWidths.map((w) => \"-\".repeat(w + 2)).join(\"+\");\n\t\tconst formatRow = (row: string[]) =>\n\t\t\trow.map((cell, i) => ` ${(cell || \"\").padEnd(colWidths[i])} `).join(\"|\");\n\n\t\tconsole.log(chalk.cyan(formatRow(headers)));\n\t\tconsole.log(separator);\n\t\tfor (const row of rows) {\n\t\t\tconsole.log(formatRow(row));\n\t\t}\n\t}\n}\n\nexport function formatList(\n\titems: Array<{ label: string; value: string }>,\n\tjson: boolean,\n): void {\n\tif (json) {\n\t\tconst data = Object.fromEntries(\n\t\t\titems.map((item) => [item.label, item.value]),\n\t\t);\n\t\tconsole.log(JSON.stringify({ success: true, data }, null, 2));\n\t} else {\n\t\tconst maxLabelLength = Math.max(...items.map((i) => i.label.length));\n\t\titems.forEach((item) => {\n\t\t\tconsole.log(\n\t\t\t\t`${chalk.gray(item.label.padEnd(maxLabelLength))} ${chalk.white(item.value)}`,\n\t\t\t);\n\t\t});\n\t}\n}\n\nfunction prettyPrint(data: unknown, indent = 0): void {\n\tconst prefix = \" \".repeat(indent);\n\n\tif (Array.isArray(data)) {\n\t\tdata.forEach((item, index) => {\n\t\t\tconsole.log(`${prefix}${chalk.gray(`[${index}]`)}`);\n\t\t\tprettyPrint(item, indent + 1);\n\t\t});\n\t} else if (typeof data === \"object\" && data !== null) {\n\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\t\tconsole.log(`${prefix}${chalk.gray(key)}:`);\n\t\t\t\tprettyPrint(value, indent + 1);\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`${prefix}${chalk.gray(key)}: ${chalk.white(String(value))}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconsole.log(`${prefix}${chalk.white(String(data))}`);\n\t}\n}\n","import { spawn } from \"node:child_process\";\nimport { createServer, type Server } from \"node:http\";\nimport type { Socket } from \"node:net\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { auth } from \"../lib/auth.js\";\nimport { config } from \"../lib/config.js\";\nimport { CLIError, handleError } from \"../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../lib/output.js\";\nimport type {\n\tOAuthClientRegistrationResponse,\n\tOAuthTokenResponse,\n} from \"../types/index.js\";\n\nconst CALLBACK_PORT = 54321;\nconst CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;\nconst CLIENT_NAME = \"waniwani-cli\";\n\nfunction generateCodeVerifier(): string {\n\tconst array = new Uint8Array(32);\n\tcrypto.getRandomValues(array);\n\treturn btoa(String.fromCharCode(...array))\n\t\t.replace(/\\+/g, \"-\")\n\t\t.replace(/\\//g, \"_\")\n\t\t.replace(/=+$/, \"\");\n}\n\nasync function generateCodeChallenge(verifier: string): Promise<string> {\n\tconst encoder = new TextEncoder();\n\tconst data = encoder.encode(verifier);\n\tconst hash = await crypto.subtle.digest(\"SHA-256\", data);\n\treturn btoa(String.fromCharCode(...new Uint8Array(hash)))\n\t\t.replace(/\\+/g, \"-\")\n\t\t.replace(/\\//g, \"_\")\n\t\t.replace(/=+$/, \"\");\n}\n\nfunction generateState(): string {\n\tconst array = new Uint8Array(16);\n\tcrypto.getRandomValues(array);\n\treturn Array.from(array, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nasync function registerClient(): Promise<OAuthClientRegistrationResponse> {\n\tconst apiUrl = await config.getApiUrl();\n\tconst response = await fetch(`${apiUrl}/api/auth/oauth2/register`, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tclient_name: CLIENT_NAME,\n\t\t\tredirect_uris: [CALLBACK_URL],\n\t\t\tgrant_types: [\"authorization_code\", \"refresh_token\"],\n\t\t\tresponse_types: [\"code\"],\n\t\t\ttoken_endpoint_auth_method: \"none\",\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.json().catch(() => ({}));\n\t\tthrow new CLIError(\n\t\t\t(error as { error_description?: string }).error_description ||\n\t\t\t\t\"Failed to register OAuth client\",\n\t\t\t\"CLIENT_REGISTRATION_FAILED\",\n\t\t);\n\t}\n\n\treturn response.json() as Promise<OAuthClientRegistrationResponse>;\n}\n\nasync function openBrowser(url: string): Promise<void> {\n\tconst [cmd, ...args] =\n\t\tprocess.platform === \"darwin\"\n\t\t\t? [\"open\", url]\n\t\t\t: process.platform === \"win32\"\n\t\t\t\t? [\"cmd\", \"/c\", \"start\", url]\n\t\t\t\t: [\"xdg-open\", url];\n\n\tspawn(cmd, args, { stdio: \"ignore\", detached: true }).unref();\n}\n\nasync function waitForCallback(\n\texpectedState: string,\n\ttimeoutMs: number = 300000,\n): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet server: Server | null = null;\n\t\tconst sockets = new Set<Socket>();\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tcleanup();\n\t\t\treject(new CLIError(\"Login timed out\", \"LOGIN_TIMEOUT\"));\n\t\t}, timeoutMs);\n\n\t\tconst cleanup = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\t// Destroy all active connections to allow process to exit\n\t\t\tfor (const socket of sockets) {\n\t\t\t\tsocket.destroy();\n\t\t\t}\n\t\t\tsockets.clear();\n\t\t\tserver?.close();\n\t\t};\n\n\t\tconst htmlResponse = (title: string, message: string, isSuccess: boolean) =>\n\t\t\t`<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${title} - WaniWani</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #fafafa;\n position: relative;\n overflow: hidden;\n }\n .blob {\n position: absolute;\n border-radius: 50%;\n filter: blur(60px);\n pointer-events: none;\n }\n .blob-1 {\n top: 0;\n left: 25%;\n width: 24rem;\n height: 24rem;\n background: linear-gradient(to bottom right, rgba(253, 224, 71, 0.3), rgba(251, 146, 60, 0.3));\n }\n .blob-2 {\n bottom: 0;\n right: 25%;\n width: 24rem;\n height: 24rem;\n background: linear-gradient(to bottom right, rgba(134, 239, 172, 0.3), rgba(52, 211, 153, 0.3));\n }\n .blob-3 {\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 40rem;\n height: 40rem;\n background: linear-gradient(to bottom right, rgba(255, 237, 213, 0.2), rgba(254, 249, 195, 0.2));\n }\n .container {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2rem;\n padding: 2rem;\n z-index: 10;\n text-align: center;\n }\n .logo {\n font-size: 1.75rem;\n font-weight: 700;\n color: #1e293b;\n letter-spacing: -0.025em;\n }\n .icon-circle {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: ${isSuccess ? \"rgba(52, 211, 153, 0.15)\" : \"rgba(239, 68, 68, 0.15)\"};\n }\n .icon {\n width: 40px;\n height: 40px;\n color: ${isSuccess ? \"#10b981\" : \"#ef4444\"};\n }\n h1 {\n font-size: 2rem;\n font-weight: 700;\n color: #1e293b;\n }\n p {\n font-size: 1.125rem;\n color: #64748b;\n max-width: 400px;\n }\n </style>\n</head>\n<body>\n <div class=\"blob blob-1\"></div>\n <div class=\"blob blob-2\"></div>\n <div class=\"blob blob-3\"></div>\n <div class=\"container\">\n <span class=\"logo\">WaniWani</span>\n <div class=\"icon-circle\">\n ${\n\t\t\t\tisSuccess\n\t\t\t\t\t? '<svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"></path></svg>'\n\t\t\t\t\t: '<svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6 6 18\"></path><path d=\"m6 6 12 12\"></path></svg>'\n\t\t\t}\n </div>\n <h1>${title}</h1>\n <p>${message}</p>\n </div>\n</body>\n</html>`;\n\n\t\ttry {\n\t\t\tserver = createServer((req, res) => {\n\t\t\t\tconst url = new URL(\n\t\t\t\t\treq.url || \"/\",\n\t\t\t\t\t`http://localhost:${CALLBACK_PORT}`,\n\t\t\t\t);\n\n\t\t\t\tif (url.pathname === \"/callback\") {\n\t\t\t\t\tconst code = url.searchParams.get(\"code\");\n\t\t\t\t\tconst state = url.searchParams.get(\"state\");\n\t\t\t\t\tconst error = url.searchParams.get(\"error\");\n\n\t\t\t\t\tres.setHeader(\"Content-Type\", \"text/html\");\n\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tres.statusCode = 400;\n\t\t\t\t\t\tres.end(htmlResponse(\"Login Failed\", `Error: ${error}`, false));\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\treject(new CLIError(`OAuth error: ${error}`, \"OAUTH_ERROR\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (state !== expectedState) {\n\t\t\t\t\t\tres.statusCode = 400;\n\t\t\t\t\t\tres.end(\n\t\t\t\t\t\t\thtmlResponse(\n\t\t\t\t\t\t\t\t\"Login Failed\",\n\t\t\t\t\t\t\t\t\"Invalid state parameter. Please try again.\",\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\treject(new CLIError(\"Invalid state parameter\", \"INVALID_STATE\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!code) {\n\t\t\t\t\t\tres.statusCode = 400;\n\t\t\t\t\t\tres.end(\n\t\t\t\t\t\t\thtmlResponse(\n\t\t\t\t\t\t\t\t\"Login Failed\",\n\t\t\t\t\t\t\t\t\"No authorization code received.\",\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\treject(new CLIError(\"No authorization code\", \"NO_CODE\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tres.statusCode = 200;\n\t\t\t\t\tres.end(\n\t\t\t\t\t\thtmlResponse(\n\t\t\t\t\t\t\t\"Login Successful!\",\n\t\t\t\t\t\t\t\"You can close this window and return to the terminal.\",\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\n\t\t\t\t\t// Schedule cleanup after response is sent\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\tresolve(code);\n\t\t\t\t\t}, 100);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tres.statusCode = 404;\n\t\t\t\tres.end(\"Not found\");\n\t\t\t});\n\n\t\t\t// Track connections so we can force-close them\n\t\t\tserver.on(\"connection\", (socket) => {\n\t\t\t\tsockets.add(socket);\n\t\t\t\tsocket.on(\"close\", () => sockets.delete(socket));\n\t\t\t});\n\n\t\t\tserver.on(\"error\", (err: NodeJS.ErrnoException) => {\n\t\t\t\tcleanup();\n\t\t\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew CLIError(\n\t\t\t\t\t\t\t`Port ${CALLBACK_PORT} is already in use. Close any other WaniWani CLI instances and try again.`,\n\t\t\t\t\t\t\t\"PORT_IN_USE\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tserver.listen(CALLBACK_PORT);\n\t\t} catch (err: unknown) {\n\t\t\tcleanup();\n\t\t\treject(err);\n\t\t}\n\t});\n}\n\nasync function exchangeCodeForToken(\n\tcode: string,\n\tcodeVerifier: string,\n\tclientId: string,\n\tresource: string,\n): Promise<OAuthTokenResponse> {\n\tconst apiUrl = await config.getApiUrl();\n\tconst response = await fetch(`${apiUrl}/api/auth/oauth2/token`, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tcode,\n\t\t\tredirect_uri: CALLBACK_URL,\n\t\t\tclient_id: clientId,\n\t\t\tcode_verifier: codeVerifier,\n\t\t\tresource, // RFC 8707 - required to get JWT token\n\t\t}).toString(),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.json().catch(() => ({}));\n\t\tthrow new CLIError(\n\t\t\t(error as { error_description?: string }).error_description ||\n\t\t\t\t\"Failed to exchange code for token\",\n\t\t\t\"TOKEN_EXCHANGE_FAILED\",\n\t\t);\n\t}\n\n\treturn response.json() as Promise<OAuthTokenResponse>;\n}\n\nexport const loginCommand = new Command(\"login\")\n\t.description(\"Log in to WaniWani\")\n\t.option(\"--no-browser\", \"Don't open the browser automatically\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\t// Check if already logged in with a valid session\n\t\t\tif (await auth.isLoggedIn()) {\n\t\t\t\t// Check if token is expired\n\t\t\t\tif (await auth.isTokenExpired()) {\n\t\t\t\t\t// Try to refresh the token\n\t\t\t\t\tconst refreshed = await auth.tryRefreshToken();\n\t\t\t\t\tif (refreshed) {\n\t\t\t\t\t\tif (json) {\n\t\t\t\t\t\t\tformatOutput({ alreadyLoggedIn: true, refreshed: true }, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\tchalk.green(\"Session refreshed. You're still logged in.\"),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Refresh failed, clear and proceed with login\n\t\t\t\t\tif (!json) {\n\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\tchalk.yellow(\"Session expired. Starting new login flow...\"),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait auth.clear();\n\t\t\t\t} else {\n\t\t\t\t\t// Token is valid\n\t\t\t\t\tif (json) {\n\t\t\t\t\t\tformatOutput({ alreadyLoggedIn: true }, true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\tchalk.yellow(\n\t\t\t\t\t\t\t\t\"Already logged in. Use 'waniwani logout' to log out first.\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!json) {\n\t\t\t\tconsole.log(chalk.bold(\"\\nWaniWani CLI Login\\n\"));\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Registering client...\").start();\n\n\t\t\t// Register OAuth client dynamically\n\t\t\tconst { client_id: clientId } = await registerClient();\n\n\t\t\tspinner.text = \"Preparing authentication...\";\n\n\t\t\t// Generate PKCE values\n\t\t\tconst codeVerifier = generateCodeVerifier();\n\t\t\tconst codeChallenge = await generateCodeChallenge(codeVerifier);\n\t\t\tconst state = generateState();\n\n\t\t\t// Build authorization URL\n\t\t\tconst apiUrl = await config.getApiUrl();\n\t\t\tconst authUrl = new URL(`${apiUrl}/api/auth/oauth2/authorize`);\n\t\t\tauthUrl.searchParams.set(\"client_id\", clientId);\n\t\t\tauthUrl.searchParams.set(\"redirect_uri\", CALLBACK_URL);\n\t\t\tauthUrl.searchParams.set(\"response_type\", \"code\");\n\t\t\tauthUrl.searchParams.set(\"code_challenge\", codeChallenge);\n\t\t\tauthUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n\t\t\tauthUrl.searchParams.set(\"state\", state);\n\t\t\tauthUrl.searchParams.set(\"resource\", apiUrl); // RFC 8707 - request JWT token\n\n\t\t\tspinner.stop();\n\n\t\t\tif (!json) {\n\t\t\t\tconsole.log(\"Opening browser for authentication...\\n\");\n\t\t\t\tconsole.log(`If the browser doesn't open, visit:\\n`);\n\t\t\t\tconsole.log(chalk.cyan(` ${authUrl.toString()}`));\n\t\t\t\tconsole.log();\n\t\t\t}\n\n\t\t\t// Start callback server and open browser\n\t\t\tconst callbackPromise = waitForCallback(state);\n\n\t\t\tif (options.browser !== false) {\n\t\t\t\tawait openBrowser(authUrl.toString());\n\t\t\t}\n\n\t\t\tspinner.start(\"Waiting for authorization...\");\n\n\t\t\t// Wait for callback with auth code\n\t\t\tconst code = await callbackPromise;\n\n\t\t\tspinner.text = \"Exchanging code for token...\";\n\n\t\t\t// Exchange code for token\n\t\t\tconst tokenResponse = await exchangeCodeForToken(\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tclientId,\n\t\t\t\tapiUrl, // RFC 8707 resource parameter\n\t\t\t);\n\n\t\t\t// Ensure .waniwani/ exists in cwd before storing tokens\n\t\t\tawait config.ensureConfigDir();\n\n\t\t\t// Store tokens and client ID for refresh\n\t\t\tawait auth.setTokens(\n\t\t\t\ttokenResponse.access_token,\n\t\t\t\ttokenResponse.refresh_token,\n\t\t\t\ttokenResponse.expires_in,\n\t\t\t\tclientId,\n\t\t\t);\n\n\t\t\tspinner.succeed(\"Logged in successfully!\");\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ success: true, loggedIn: true }, true);\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t\tformatSuccess(\"You're now logged in to WaniWani!\", false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Get started:\");\n\t\t\t\tconsole.log(\n\t\t\t\t\t\" waniwani mcp create my-server Create a new MCP sandbox\",\n\t\t\t\t);\n\t\t\t\tconsole.log(' waniwani task \"Add a tool\" Send tasks to Claude');\n\t\t\t\tconsole.log(\n\t\t\t\t\t\" waniwani org list View your organizations\",\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { config } from \"./config.js\";\n\n/**\n * AuthManager delegates all storage to the config module.\n * Auth tokens are stored in .waniwani/settings.json alongside other config.\n */\nclass AuthManager {\n\tasync isLoggedIn(): Promise<boolean> {\n\t\tconst token = await config.getAccessToken();\n\t\treturn !!token;\n\t}\n\n\tasync getAccessToken(): Promise<string | null> {\n\t\treturn config.getAccessToken();\n\t}\n\n\tasync getRefreshToken(): Promise<string | null> {\n\t\treturn config.getRefreshToken();\n\t}\n\n\tasync setTokens(\n\t\taccessToken: string,\n\t\trefreshToken: string,\n\t\texpiresIn: number,\n\t\tclientId?: string,\n\t): Promise<void> {\n\t\treturn config.setTokens(accessToken, refreshToken, expiresIn, clientId);\n\t}\n\n\tasync clear(): Promise<void> {\n\t\treturn config.clearAuth();\n\t}\n\n\tasync isTokenExpired(): Promise<boolean> {\n\t\treturn config.isTokenExpired();\n\t}\n\n\tasync tryRefreshToken(): Promise<boolean> {\n\t\tconst refreshToken = await config.getRefreshToken();\n\t\tconst clientId = await config.getClientId();\n\t\tif (!refreshToken || !clientId) return false;\n\n\t\ttry {\n\t\t\tconst apiUrl = await config.getApiUrl();\n\t\t\tconst response = await fetch(`${apiUrl}/api/auth/oauth2/token`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\t\trefresh_token: refreshToken,\n\t\t\t\t\tclient_id: clientId,\n\t\t\t\t}).toString(),\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tawait this.clear();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst data = (await response.json()) as {\n\t\t\t\taccess_token: string;\n\t\t\t\trefresh_token: string;\n\t\t\t\texpires_in: number;\n\t\t\t};\n\n\t\t\tawait this.setTokens(\n\t\t\t\tdata.access_token,\n\t\t\t\tdata.refresh_token,\n\t\t\t\tdata.expires_in,\n\t\t\t);\n\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tawait this.clear();\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\nexport const auth = new AuthManager();\n","import { Command } from \"commander\";\nimport { auth } from \"../lib/auth.js\";\nimport { handleError } from \"../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../lib/output.js\";\n\nexport const logoutCommand = new Command(\"logout\")\n\t.description(\"Log out from WaniWani\")\n\t.action(async (_, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tif (!(await auth.isLoggedIn())) {\n\t\t\t\tif (json) {\n\t\t\t\t\tformatOutput({ alreadyLoggedOut: true }, true);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(\"Not currently logged in.\");\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Clear auth tokens only (keep config like apiUrl intact)\n\t\t\tawait auth.clear();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ success: true }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(\"You have been logged out.\", false);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport { deleteCommand } from \"./delete.js\";\nimport { fileCommand } from \"./file/index.js\";\nimport { initCommand } from \"./init.js\";\nimport { listCommand } from \"./list.js\";\nimport { logsCommand } from \"./logs.js\";\nimport { previewCommand } from \"./preview.js\";\nimport { publishCommand } from \"./publish.js\";\nimport { runCommandCommand } from \"./run-command.js\";\nimport { statusCommand } from \"./status.js\";\nimport { stopCommand } from \"./stop.js\";\nimport { syncCommand } from \"./sync.js\";\nimport { useCommand } from \"./use.js\";\n\nexport const mcpCommand = new Command(\"mcp\")\n\t.description(\"MCP management commands\")\n\t.addCommand(initCommand)\n\t.addCommand(listCommand)\n\t.addCommand(useCommand)\n\t.addCommand(statusCommand)\n\t.addCommand(previewCommand)\n\t.addCommand(stopCommand)\n\t.addCommand(logsCommand)\n\t.addCommand(syncCommand)\n\t.addCommand(publishCommand)\n\t.addCommand(deleteCommand)\n\t.addCommand(fileCommand)\n\t.addCommand(runCommandCommand);\n","import { confirm } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { requireMcpId } from \"../../lib/utils.js\";\nimport type { McpRepository } from \"../../types/index.js\";\n\nexport const deleteCommand = new Command(\"delete\")\n\t.description(\"Delete the MCP (includes all associated resources)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--force\", \"Skip confirmation prompt\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst mcpId = await requireMcpId(options.mcpId);\n\n\t\t\t// Get MCP details for confirmation\n\t\t\tconst mcp = await api.get<McpRepository>(\n\t\t\t\t`/api/mcp/repositories/${mcpId}`,\n\t\t\t);\n\n\t\t\t// Require confirmation unless --force\n\t\t\tif (!options.force && !json) {\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(chalk.yellow(\"This will permanently delete:\"));\n\t\t\t\tconsole.log(` - MCP: ${mcp.name}`);\n\t\t\t\tif (mcp.activeSandbox) {\n\t\t\t\t\tconsole.log(\" - Active sandbox\");\n\t\t\t\t}\n\t\t\t\tconsole.log();\n\n\t\t\t\tconst confirmed = await confirm({\n\t\t\t\t\tmessage: `Delete \"${mcp.name}\"?`,\n\t\t\t\t\tdefault: false,\n\t\t\t\t});\n\n\t\t\t\tif (!confirmed) {\n\t\t\t\t\tconsole.log(\"Cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Deleting MCP...\").start();\n\t\t\tawait api.delete(`/api/mcp/repositories/${mcpId}`);\n\t\t\tspinner.succeed(\"MCP deleted\");\n\n\t\t\t// Clear active MCP and session if it was the one we deleted\n\t\t\tif ((await config.getMcpId()) === mcpId) {\n\t\t\t\tawait config.setMcpId(null);\n\t\t\t\tawait config.setSessionId(null);\n\t\t\t}\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ deleted: mcpId }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(\"MCP deleted.\", false);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { auth } from \"./auth.js\";\nimport { config } from \"./config.js\";\nimport { AuthError, CLIError } from \"./errors.js\";\n\nexport interface ApiResponse<T> {\n\tsuccess: boolean;\n\tdata?: T;\n\terror?: {\n\t\tcode: string;\n\t\tmessage: string;\n\t\tdetails?: Record<string, unknown>;\n\t};\n}\n\nexport class ApiError extends CLIError {\n\tconstructor(\n\t\tmessage: string,\n\t\tcode: string,\n\t\tpublic statusCode: number,\n\t\tdetails?: Record<string, unknown>,\n\t) {\n\t\tsuper(message, code, details);\n\t\tthis.name = \"ApiError\";\n\t}\n}\n\nasync function request<T>(\n\tmethod: string,\n\tpath: string,\n\toptions?: {\n\t\tbody?: unknown;\n\t\trequireAuth?: boolean;\n\t\theaders?: Record<string, string>;\n\t},\n): Promise<T> {\n\tconst {\n\t\tbody,\n\t\trequireAuth = true,\n\t\theaders: extraHeaders = {},\n\t} = options || {};\n\n\tconst headers: Record<string, string> = {\n\t\t\"Content-Type\": \"application/json\",\n\t\t...extraHeaders,\n\t};\n\n\tif (requireAuth) {\n\t\tconst token = await auth.getAccessToken();\n\t\tif (!token) {\n\t\t\tthrow new AuthError(\n\t\t\t\t\"Not logged in. Run 'waniwani login' to authenticate.\",\n\t\t\t);\n\t\t}\n\t\theaders.Authorization = `Bearer ${token}`;\n\t}\n\n\tconst baseUrl = await config.getApiUrl();\n\tconst url = `${baseUrl}${path}`;\n\n\tconst response = await fetch(url, {\n\t\tmethod,\n\t\theaders,\n\t\tbody: body ? JSON.stringify(body) : undefined,\n\t});\n\n\t// Handle empty responses (204 No Content)\n\tif (response.status === 204) {\n\t\treturn undefined as T;\n\t}\n\n\tlet data: ApiResponse<T>;\n\tlet rawBody: string | undefined;\n\n\ttry {\n\t\trawBody = await response.text();\n\t\tdata = JSON.parse(rawBody) as ApiResponse<T>;\n\t} catch {\n\t\t// JSON parsing failed - use raw body as error message\n\t\tthrow new ApiError(\n\t\t\trawBody || `Request failed with status ${response.status}`,\n\t\t\t\"API_ERROR\",\n\t\t\tresponse.status,\n\t\t\t{ statusText: response.statusText },\n\t\t);\n\t}\n\n\tif (!response.ok || data.error) {\n\t\t// Try to extract error message from various possible response formats\n\t\tconst errorMessage =\n\t\t\tdata.error?.message ||\n\t\t\t(data as unknown as { message?: string }).message ||\n\t\t\t(data as unknown as { error?: string }).error ||\n\t\t\trawBody ||\n\t\t\t`Request failed with status ${response.status}`;\n\n\t\tconst errorCode =\n\t\t\tdata.error?.code ||\n\t\t\t(data as unknown as { code?: string }).code ||\n\t\t\t\"API_ERROR\";\n\n\t\tconst errorDetails = {\n\t\t\t...data.error?.details,\n\t\t\tstatusText: response.statusText,\n\t\t\t...(data.error ? {} : { rawResponse: data }),\n\t\t};\n\n\t\tconst error = {\n\t\t\tcode: errorCode,\n\t\t\tmessage: errorMessage,\n\t\t\tdetails: errorDetails,\n\t\t};\n\n\t\t// Handle token expiration\n\t\tif (response.status === 401) {\n\t\t\tconst refreshed = await auth.tryRefreshToken();\n\t\t\tif (refreshed) {\n\t\t\t\t// Retry with new token\n\t\t\t\treturn request<T>(method, path, options);\n\t\t\t}\n\t\t\tthrow new AuthError(\n\t\t\t\t\"Session expired. Run 'waniwani login' to re-authenticate.\",\n\t\t\t);\n\t\t}\n\n\t\tthrow new ApiError(\n\t\t\terror.message,\n\t\t\terror.code,\n\t\t\tresponse.status,\n\t\t\terror.details,\n\t\t);\n\t}\n\n\treturn data.data as T;\n}\n\nexport const api = {\n\tget: <T>(path: string, options?: { requireAuth?: boolean }) =>\n\t\trequest<T>(\"GET\", path, options),\n\n\tpost: <T>(\n\t\tpath: string,\n\t\tbody?: unknown,\n\t\toptions?: { requireAuth?: boolean; headers?: Record<string, string> },\n\t) => request<T>(\"POST\", path, { body, ...options }),\n\n\tdelete: <T>(path: string, options?: { requireAuth?: boolean }) =>\n\t\trequest<T>(\"DELETE\", path, options),\n\n\tgetBaseUrl: () => config.getApiUrl(),\n};\n","import { config } from \"./config.js\";\nimport { McpError } from \"./errors.js\";\n\n/**\n * Requires an MCP ID, falling back to the active MCP from config.\n * Throws McpError if no MCP is available.\n */\nexport async function requireMcpId(mcpId?: string): Promise<string> {\n\tif (mcpId) return mcpId;\n\n\tconst configMcpId = await config.getMcpId();\n\tif (!configMcpId) {\n\t\tthrow new McpError(\n\t\t\t\"No active MCP. Run 'waniwani mcp init <name>' or 'waniwani mcp use <name>'.\",\n\t\t);\n\t}\n\treturn configMcpId;\n}\n\n/**\n * Get the active session ID from config.\n * Throws McpError if no session ID is stored.\n */\nexport async function requireSessionId(): Promise<string> {\n\tconst sessionId = await config.getSessionId();\n\n\tif (!sessionId) {\n\t\tthrow new McpError(\n\t\t\t\"No active session. Run 'waniwani mcp preview' to start development.\",\n\t\t);\n\t}\n\n\treturn sessionId;\n}\n\n/**\n * Binary file extensions that should be base64 encoded\n */\nconst BINARY_EXTENSIONS = new Set([\n\t\".png\",\n\t\".jpg\",\n\t\".jpeg\",\n\t\".gif\",\n\t\".ico\",\n\t\".webp\",\n\t\".svg\",\n\t\".woff\",\n\t\".woff2\",\n\t\".ttf\",\n\t\".eot\",\n\t\".otf\",\n\t\".zip\",\n\t\".tar\",\n\t\".gz\",\n\t\".pdf\",\n\t\".exe\",\n\t\".dll\",\n\t\".so\",\n\t\".dylib\",\n\t\".bin\",\n\t\".mp3\",\n\t\".mp4\",\n\t\".wav\",\n\t\".ogg\",\n\t\".webm\",\n]);\n\n/**\n * Check if a file path is likely a binary file based on extension\n */\nexport function isBinaryPath(filePath: string): boolean {\n\tconst ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n\treturn BINARY_EXTENSIONS.has(ext);\n}\n\n/**\n * Detect if a buffer contains binary data by checking for null bytes\n */\nexport function detectBinary(buffer: Buffer): boolean {\n\t// Check first 8KB for null bytes\n\tconst sample = buffer.subarray(0, 8192);\n\treturn sample.includes(0);\n}\n","import { Command } from \"commander\";\nimport { listCommand } from \"./list.js\";\nimport { readCommand } from \"./read.js\";\nimport { writeCommand } from \"./write.js\";\n\nexport const fileCommand = new Command(\"file\")\n\t.description(\"File operations in MCP sandbox\")\n\t.addCommand(readCommand)\n\t.addCommand(writeCommand)\n\t.addCommand(listCommand);\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../../lib/api.js\";\nimport { handleError } from \"../../../lib/errors.js\";\nimport { formatOutput, formatTable } from \"../../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../../lib/utils.js\";\nimport type { ListFilesResponse } from \"../../../types/index.js\";\n\nexport const listCommand = new Command(\"list\")\n\t.description(\"List files in the MCP sandbox\")\n\t.argument(\"[path]\", \"Directory path (defaults to /app)\", \"/app\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (path: string, options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst spinner = ora(`Listing ${path}...`).start();\n\n\t\t\tconst result = await api.get<ListFilesResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/files/list?path=${encodeURIComponent(path)}`,\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\tconsole.log(chalk.bold(`\\nDirectory: ${result.path}\\n`));\n\n\t\t\t\tif (result.entries.length === 0) {\n\t\t\t\t\tconsole.log(\" (empty)\");\n\t\t\t\t} else {\n\t\t\t\t\tconst rows = result.entries.map((entry) => {\n\t\t\t\t\t\tconst name =\n\t\t\t\t\t\t\tentry.type === \"directory\"\n\t\t\t\t\t\t\t\t? chalk.blue(`${entry.name}/`)\n\t\t\t\t\t\t\t\t: entry.name;\n\t\t\t\t\t\tconst size =\n\t\t\t\t\t\t\tentry.type === \"directory\"\n\t\t\t\t\t\t\t\t? chalk.gray(\"<dir>\")\n\t\t\t\t\t\t\t\t: formatSize(entry.size);\n\t\t\t\t\t\treturn [name, size];\n\t\t\t\t\t});\n\n\t\t\t\t\tformatTable([\"Name\", \"Size\"], rows, false);\n\t\t\t\t}\n\t\t\t\tconsole.log();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nfunction formatSize(bytes?: number): string {\n\tif (bytes === undefined) return \"\";\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../../lib/api.js\";\nimport { handleError, McpError } from \"../../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../../lib/utils.js\";\nimport type { ReadFileResponse } from \"../../../types/index.js\";\n\nexport const readCommand = new Command(\"read\")\n\t.description(\"Read a file from the MCP sandbox\")\n\t.argument(\"<path>\", \"Path in sandbox (e.g., /app/src/index.ts)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--output <file>\", \"Write to local file instead of stdout\")\n\t.option(\"--base64\", \"Output as base64 (for binary files)\")\n\t.action(async (path: string, options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst encoding = options.base64 ? \"base64\" : \"utf8\";\n\t\t\tconst spinner = ora(`Reading ${path}...`).start();\n\n\t\t\tconst result = await api.get<ReadFileResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/files?path=${encodeURIComponent(path)}&encoding=${encoding}`,\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\tif (!result.exists) {\n\t\t\t\tthrow new McpError(`File not found: ${path}`);\n\t\t\t}\n\n\t\t\tif (options.output) {\n\t\t\t\t// Write to local file\n\t\t\t\tconst buffer =\n\t\t\t\t\tresult.encoding === \"base64\"\n\t\t\t\t\t\t? Buffer.from(result.content, \"base64\")\n\t\t\t\t\t\t: Buffer.from(result.content, \"utf8\");\n\t\t\t\tawait writeFile(options.output, buffer);\n\t\t\t\tif (json) {\n\t\t\t\t\tformatOutput({ path, savedTo: options.output }, true);\n\t\t\t\t} else {\n\t\t\t\t\tformatSuccess(`Saved to ${options.output}`, false);\n\t\t\t\t}\n\t\t\t} else if (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\t// Print to stdout\n\t\t\t\tprocess.stdout.write(result.content);\n\t\t\t\t// Add newline if content doesn't end with one\n\t\t\t\tif (!result.content.endsWith(\"\\n\")) {\n\t\t\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { readFile } from \"node:fs/promises\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../../lib/api.js\";\nimport { CLIError, handleError } from \"../../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../../lib/utils.js\";\nimport type { WriteFilesResponse } from \"../../../types/index.js\";\n\nexport const writeCommand = new Command(\"write\")\n\t.description(\"Write a file to the MCP sandbox\")\n\t.argument(\"<path>\", \"Path in sandbox (e.g., /app/src/index.ts)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--content <content>\", \"Content to write\")\n\t.option(\"--file <localFile>\", \"Local file to upload\")\n\t.option(\"--base64\", \"Treat content as base64 encoded\")\n\t.action(async (path: string, options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\t// Get content from --content or --file\n\t\t\tlet content: string;\n\t\t\tlet encoding: \"utf8\" | \"base64\" = \"utf8\";\n\n\t\t\tif (options.content) {\n\t\t\t\tcontent = options.content;\n\t\t\t\tif (options.base64) {\n\t\t\t\t\tencoding = \"base64\";\n\t\t\t\t}\n\t\t\t} else if (options.file) {\n\t\t\t\tconst fileBuffer = await readFile(options.file);\n\t\t\t\tif (options.base64) {\n\t\t\t\t\tcontent = fileBuffer.toString(\"base64\");\n\t\t\t\t\tencoding = \"base64\";\n\t\t\t\t} else {\n\t\t\t\t\tcontent = fileBuffer.toString(\"utf8\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"Either --content or --file is required\",\n\t\t\t\t\t\"MISSING_CONTENT\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst spinner = ora(`Writing ${path}...`).start();\n\n\t\t\tconst result = await api.post<WriteFilesResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/files`,\n\t\t\t\t{\n\t\t\t\t\tfiles: [{ path, content, encoding }],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tspinner.succeed(`Wrote ${path}`);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(`File written: ${path}`, false);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { existsSync, mkdirSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport {\n\tCONFIG_FILE_NAME,\n\tinitConfigAt,\n\tLOCAL_CONFIG_DIR,\n} from \"../../lib/config.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport type { McpRepository } from \"../../types/index.js\";\n\n/**\n * Load parent .waniwani/settings.json if it exists.\n * Copies all settings including auth tokens, but excludes mcpId (new project gets its own).\n */\nasync function loadParentConfig(\n\tcwd: string,\n): Promise<Record<string, unknown> | null> {\n\tconst parentConfigPath = join(cwd, LOCAL_CONFIG_DIR, CONFIG_FILE_NAME);\n\tif (!existsSync(parentConfigPath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst content = await readFile(parentConfigPath, \"utf-8\");\n\t\tconst config = JSON.parse(content);\n\t\t// Remove mcpId from parent - the new project gets its own\n\t\t// Keep auth tokens so user doesn't need to re-login\n\t\tconst { mcpId: _, sessionId: __, ...rest } = config;\n\t\treturn rest;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport const initCommand = new Command(\"init\")\n\t.description(\"Create a new MCP project\")\n\t.argument(\"<name>\", \"Name for the MCP project\")\n\t.action(async (name: string, _options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst cwd = process.cwd();\n\t\t\tconst projectDir = join(cwd, name);\n\n\t\t\t// Check if directory already exists\n\t\t\tif (existsSync(projectDir)) {\n\t\t\t\tif (json) {\n\t\t\t\t\tformatOutput(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\terror: `Directory \"${name}\" already exists`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(`Error: Directory \"${name}\" already exists`);\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Create repository on backend (GitHub repo created immediately)\n\t\t\tconst spinner = ora(\"Creating MCP...\").start();\n\n\t\t\tconst result = await api.post<McpRepository>(\"/api/mcp/repositories\", {\n\t\t\t\tname,\n\t\t\t});\n\n\t\t\t// Create local project directory\n\t\t\tmkdirSync(projectDir, { recursive: true });\n\n\t\t\t// Create .waniwani/settings.json with mcpId\n\t\t\tconst parentConfig = await loadParentConfig(cwd);\n\t\t\tawait initConfigAt(projectDir, {\n\t\t\t\t...parentConfig,\n\t\t\t\tmcpId: result.id,\n\t\t\t});\n\n\t\t\tspinner.succeed(\"MCP project created\");\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(\n\t\t\t\t\t{\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tprojectDir,\n\t\t\t\t\t\tmcpId: result.id,\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t\tformatSuccess(`MCP \"${name}\" created!`, false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Next steps:\");\n\t\t\t\tconsole.log(` cd ${name}`);\n\t\t\t\tconsole.log(\" waniwani mcp sync # Pull template files\");\n\t\t\t\tconsole.log(\" waniwani mcp preview # Start developing\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatTable } from \"../../lib/output.js\";\nimport type {\n\tMcpRepository,\n\tMcpRepositoryListResponse,\n} from \"../../types/index.js\";\n\nexport const listCommand = new Command(\"list\")\n\t.description(\"List all MCPs in your organization\")\n\t.action(async (_, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst spinner = ora(\"Fetching MCPs...\").start();\n\n\t\t\tconst mcps = await api.get<McpRepositoryListResponse>(\n\t\t\t\t\"/api/mcp/repositories\",\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\tconst activeMcpId = await config.getMcpId();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(\n\t\t\t\t\t{\n\t\t\t\t\t\tmcps: mcps.map((m: McpRepository) => ({\n\t\t\t\t\t\t\t...m,\n\t\t\t\t\t\t\tisActive: m.id === activeMcpId,\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tactiveMcpId,\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tif (mcps.length === 0) {\n\t\t\t\t\tconsole.log(\"No MCPs found.\");\n\t\t\t\t\tconsole.log(\"\\nCreate a new MCP: waniwani mcp init <name>\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconsole.log(chalk.bold(\"\\nMCPs:\\n\"));\n\n\t\t\t\tconst rows = mcps.map((m: McpRepository) => {\n\t\t\t\t\tconst isActive = m.id === activeMcpId;\n\t\t\t\t\tconst deployStatus = m.deployedAt\n\t\t\t\t\t\t? chalk.green(\"Deployed\")\n\t\t\t\t\t\t: chalk.yellow(\"Pending\");\n\t\t\t\t\tconst sandboxStatus = m.activeSandbox\n\t\t\t\t\t\t? chalk.green(\"Active\")\n\t\t\t\t\t\t: chalk.gray(\"None\");\n\t\t\t\t\tconst lastDeploy = m.deployedAt\n\t\t\t\t\t\t? new Date(m.deployedAt).toLocaleDateString()\n\t\t\t\t\t\t: chalk.gray(\"Never\");\n\n\t\t\t\t\treturn [\n\t\t\t\t\t\tisActive ? chalk.cyan(`* ${m.name}`) : ` ${m.name}`,\n\t\t\t\t\t\tdeployStatus,\n\t\t\t\t\t\tsandboxStatus,\n\t\t\t\t\t\tlastDeploy,\n\t\t\t\t\t];\n\t\t\t\t});\n\n\t\t\t\tformatTable([\"Name\", \"Status\", \"Sandbox\", \"Last Deploy\"], rows, false);\n\n\t\t\t\tconsole.log();\n\t\t\t\tif (activeMcpId) {\n\t\t\t\t\tconst activeMcp = mcps.find((m) => m.id === activeMcpId);\n\t\t\t\t\tif (activeMcp) {\n\t\t\t\t\t\tconsole.log(`Active MCP: ${chalk.cyan(activeMcp.name)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconsole.log(\"\\nSelect an MCP: waniwani mcp use <name>\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { auth } from \"../../lib/auth.js\";\nimport { AuthError, handleError, McpError } from \"../../lib/errors.js\";\nimport { formatOutput } from \"../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../lib/utils.js\";\nimport type { LogEvent, ServerStatusResponse } from \"../../types/index.js\";\n\nexport const logsCommand = new Command(\"logs\")\n\t.description(\"Stream logs from the MCP server\")\n\t.argument(\"[cmdId]\", \"Command ID (defaults to running server)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"-f, --follow\", \"Keep streaming logs (default)\", true)\n\t.option(\"--no-follow\", \"Fetch logs and exit\")\n\t.action(async (cmdIdArg: string | undefined, options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\tlet reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n\n\t\t// Handle Ctrl+C gracefully\n\t\tconst cleanup = () => {\n\t\t\tif (reader) {\n\t\t\t\treader.cancel().catch(() => {});\n\t\t\t}\n\t\t\tprocess.exit(0);\n\t\t};\n\t\tprocess.on(\"SIGINT\", cleanup);\n\t\tprocess.on(\"SIGTERM\", cleanup);\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst token = await auth.getAccessToken();\n\t\t\tif (!token) {\n\t\t\t\tthrow new AuthError(\n\t\t\t\t\t\"Not logged in. Run 'waniwani login' to authenticate.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet cmdId = cmdIdArg;\n\n\t\t\t// If no cmdId provided, get it from server status\n\t\t\tif (!cmdId) {\n\t\t\t\tconst spinner = ora(\"Getting server status...\").start();\n\t\t\t\tconst status = await api.post<ServerStatusResponse>(\n\t\t\t\t\t`/api/mcp/sessions/${sessionId}/server`,\n\t\t\t\t\t{ action: \"status\" },\n\t\t\t\t);\n\t\t\t\tspinner.stop();\n\n\t\t\t\tif (!status.running || !status.cmdId) {\n\t\t\t\t\tthrow new McpError(\n\t\t\t\t\t\t\"No server is running. Run 'waniwani mcp preview' first.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcmdId = status.cmdId;\n\t\t\t}\n\n\t\t\tconst baseUrl = await api.getBaseUrl();\n\t\t\tconst streamParam = options.follow ? \"?stream=true\" : \"\";\n\t\t\tconst url = `${baseUrl}/api/mcp/sessions/${sessionId}/commands/${cmdId}${streamParam}`;\n\n\t\t\tif (!json) {\n\t\t\t\tconsole.log(chalk.gray(`Streaming logs for command ${cmdId}...`));\n\t\t\t\tconsole.log(chalk.gray(\"Press Ctrl+C to stop\\n\"));\n\t\t\t}\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"GET\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\t\tAccept: options.follow ? \"text/event-stream\" : \"application/json\",\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst error = await response\n\t\t\t\t\t.json()\n\t\t\t\t\t.catch(() => ({ message: response.statusText }));\n\t\t\t\tthrow new Error(\n\t\t\t\t\terror.message || `Request failed with status ${response.status}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Non-streaming mode\n\t\t\tif (!options.follow) {\n\t\t\t\tconst data = await response.json();\n\t\t\t\tif (json) {\n\t\t\t\t\tformatOutput(data, true);\n\t\t\t\t} else {\n\t\t\t\t\tif (data.stdout) {\n\t\t\t\t\t\tprocess.stdout.write(data.stdout);\n\t\t\t\t\t}\n\t\t\t\t\tif (data.stderr) {\n\t\t\t\t\t\tprocess.stderr.write(chalk.red(data.stderr));\n\t\t\t\t\t}\n\t\t\t\t\tif (data.exitCode !== undefined) {\n\t\t\t\t\t\tconsole.log(chalk.gray(`\\nExit code: ${data.exitCode}`));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Streaming mode\n\t\t\treader = response.body?.getReader();\n\t\t\tif (!reader) {\n\t\t\t\tthrow new Error(\"No response body\");\n\t\t\t}\n\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = \"\";\n\t\t\tconst collectedLogs: LogEvent[] = [];\n\n\t\t\twhile (true) {\n\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\tif (done) break;\n\n\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\t\tbuffer = lines.pop() || \"\";\n\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tif (line.startsWith(\"event: \")) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (line.startsWith(\"data: \")) {\n\t\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\t\tif (!data || data === \"[DONE]\") continue;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst event = JSON.parse(data) as LogEvent;\n\t\t\t\t\t\t\tcollectedLogs.push(event);\n\n\t\t\t\t\t\t\tif (json) {\n\t\t\t\t\t\t\t\t// In JSON mode, we'll output at the end\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Handle different event types\n\t\t\t\t\t\t\tif (event.cmdId) {\n\t\t\t\t\t\t\t\t// Initial event with cmdId\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (event.stream && event.data !== undefined) {\n\t\t\t\t\t\t\t\tif (event.stream === \"stdout\") {\n\t\t\t\t\t\t\t\t\tprocess.stdout.write(event.data);\n\t\t\t\t\t\t\t\t} else if (event.stream === \"stderr\") {\n\t\t\t\t\t\t\t\t\tprocess.stderr.write(chalk.red(event.data));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (event.exitCode !== undefined) {\n\t\t\t\t\t\t\t\tconst exitColor =\n\t\t\t\t\t\t\t\t\tevent.exitCode === 0 ? chalk.green : chalk.red;\n\t\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\t\texitColor(`\\nProcess exited with code ${event.exitCode}`),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (event.error) {\n\t\t\t\t\t\t\t\tconsole.error(chalk.red(`\\nError: ${event.error}`));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Ignore malformed JSON\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Output collected logs in JSON mode\n\t\t\tif (json) {\n\t\t\t\tformatOutput(collectedLogs, true);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t} finally {\n\t\t\tprocess.off(\"SIGINT\", cleanup);\n\t\t\tprocess.off(\"SIGTERM\", cleanup);\n\t\t}\n\t});\n","import { watch } from \"chokidar\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatSuccess } from \"../../lib/output.js\";\nimport {\n\tcollectFiles,\n\tcollectSingleFile,\n\tfindProjectRoot,\n\tloadIgnorePatterns,\n} from \"../../lib/sync.js\";\nimport type {\n\tMcpSandbox,\n\tSandboxStartResponse,\n\tServerStartResponse,\n\tWriteFilesResponse,\n} from \"../../types/index.js\";\n\nexport const previewCommand = new Command(\"preview\")\n\t.description(\"Start live development with sandbox and file watching\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--no-watch\", \"Skip file watching\")\n\t.option(\"--no-logs\", \"Don't stream logs to terminal\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\t// Find project root and MCP ID\n\t\t\tconst projectRoot = await findProjectRoot(process.cwd());\n\t\t\tif (!projectRoot) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"Not in a WaniWani project. Run 'waniwani mcp init <name>' first.\",\n\t\t\t\t\t\"NOT_IN_PROJECT\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet mcpId = options.mcpId;\n\t\t\tif (!mcpId) {\n\t\t\t\tmcpId = await config.getMcpId();\n\t\t\t}\n\t\t\tif (!mcpId) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"No MCP found. Run 'waniwani mcp init <name>' or use --mcp-id.\",\n\t\t\t\t\t\"NO_MCP\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Starting development environment...\").start();\n\n\t\t\t// Step 1: Create or get session\n\t\t\tspinner.text = \"Starting session...\";\n\t\t\tlet sessionId: string;\n\t\t\ttry {\n\t\t\t\tconst sessionResponse = await api.post<SandboxStartResponse>(\n\t\t\t\t\t`/api/mcp/repositories/${mcpId}/session`,\n\t\t\t\t\t{},\n\t\t\t\t);\n\t\t\t\tsessionId = sessionResponse.sandbox.id;\n\t\t\t} catch {\n\t\t\t\t// Session might already exist, try to get it\n\t\t\t\tconst existing = await api.get<McpSandbox | null>(\n\t\t\t\t\t`/api/mcp/repositories/${mcpId}/session`,\n\t\t\t\t);\n\t\t\t\tif (!existing) {\n\t\t\t\t\tthrow new CLIError(\"Failed to start session\", \"SESSION_ERROR\");\n\t\t\t\t}\n\t\t\t\tsessionId = existing.id;\n\t\t\t}\n\n\t\t\t// Store session ID in config\n\t\t\tawait config.setSessionId(sessionId);\n\n\t\t\t// Step 2: Sync current files to sandbox\n\t\t\tspinner.text = \"Syncing files to sandbox...\";\n\t\t\tconst files = await collectFiles(projectRoot);\n\t\t\tif (files.length > 0) {\n\t\t\t\tawait api.post<WriteFilesResponse>(\n\t\t\t\t\t`/api/mcp/sessions/${sessionId}/files`,\n\t\t\t\t\t{ files },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Step 3: Start MCP server\n\t\t\tspinner.text = \"Starting MCP server...\";\n\t\t\tconst serverResult = await api.post<ServerStartResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/server`,\n\t\t\t\t{ action: \"start\" },\n\t\t\t);\n\n\t\t\tspinner.succeed(\"Development environment ready\");\n\n\t\t\tconsole.log();\n\t\t\tformatSuccess(\"Live preview started!\", false);\n\t\t\tconsole.log();\n\t\t\tconsole.log(` Preview URL: ${serverResult.previewUrl}`);\n\t\t\tconsole.log();\n\t\t\tconsole.log(` MCP Inspector:`);\n\t\t\tconsole.log(\n\t\t\t\t` npx @anthropic-ai/mcp-inspector@latest \"${serverResult.previewUrl}/mcp\"`,\n\t\t\t);\n\t\t\tconsole.log();\n\n\t\t\tif (options.watch !== false) {\n\t\t\t\tconsole.log(\"Watching for file changes... (Ctrl+C to stop)\");\n\t\t\t\tconsole.log();\n\n\t\t\t\t// Step 4: Start file watcher\n\t\t\t\tconst ig = await loadIgnorePatterns(projectRoot);\n\n\t\t\t\tconst watcher = watch(projectRoot, {\n\t\t\t\t\tignored: (path) => {\n\t\t\t\t\t\t// Get relative path from project root\n\t\t\t\t\t\tconst relative = path.replace(`${projectRoot}/`, \"\");\n\t\t\t\t\t\tif (relative === path) return false; // Don't ignore the root\n\t\t\t\t\t\treturn ig.ignores(relative);\n\t\t\t\t\t},\n\t\t\t\t\tpersistent: true,\n\t\t\t\t\tignoreInitial: true,\n\t\t\t\t\tawaitWriteFinish: {\n\t\t\t\t\t\tstabilityThreshold: 100,\n\t\t\t\t\t\tpollInterval: 50,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tconst syncFile = async (filePath: string) => {\n\t\t\t\t\tconst relativePath = filePath.replace(`${projectRoot}/`, \"\");\n\t\t\t\t\tconst file = await collectSingleFile(projectRoot, relativePath);\n\t\t\t\t\tif (file) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait api.post<WriteFilesResponse>(\n\t\t\t\t\t\t\t\t`/api/mcp/sessions/${sessionId}/files`,\n\t\t\t\t\t\t\t\t{ files: [file] },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tconsole.log(` Synced: ${relativePath}`);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tconsole.error(` Failed to sync: ${relativePath}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\twatcher.on(\"add\", syncFile);\n\t\t\t\twatcher.on(\"change\", syncFile);\n\t\t\t\twatcher.on(\"unlink\", (filePath) => {\n\t\t\t\t\tconst relativePath = filePath.replace(`${projectRoot}/`, \"\");\n\t\t\t\t\tconsole.log(` Deleted: ${relativePath}`);\n\t\t\t\t});\n\n\t\t\t\t// Handle Ctrl+C gracefully\n\t\t\t\tprocess.on(\"SIGINT\", async () => {\n\t\t\t\t\tconsole.log();\n\t\t\t\t\tconsole.log(\"Stopping development environment...\");\n\t\t\t\t\tawait watcher.close();\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t});\n\n\t\t\t\t// Keep the process running\n\t\t\t\tawait new Promise(() => {});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative } from \"node:path\";\nimport ignore from \"ignore\";\nimport type { PullFilesResponse } from \"../types/index.js\";\nimport { api } from \"./api.js\";\nimport { detectBinary, isBinaryPath } from \"./utils.js\";\n\nconst PROJECT_DIR = \".waniwani\";\n\n/**\n * Find the project root by walking up from the given directory\n * looking for a .waniwani directory\n */\nexport async function findProjectRoot(\n\tstartDir: string,\n): Promise<string | null> {\n\tlet current = startDir;\n\tconst root = dirname(current);\n\n\twhile (current !== root) {\n\t\tif (existsSync(join(current, PROJECT_DIR))) {\n\t\t\treturn current;\n\t\t}\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) break;\n\t\tcurrent = parent;\n\t}\n\n\t// Check root as well\n\tif (existsSync(join(current, PROJECT_DIR))) {\n\t\treturn current;\n\t}\n\n\treturn null;\n}\n\n/**\n * Default patterns to always ignore\n */\nconst DEFAULT_IGNORE_PATTERNS = [\n\t\".waniwani\",\n\t\".git\",\n\t\"node_modules\",\n\t\".env\",\n\t\".env.*\",\n\t\".DS_Store\",\n\t\"*.log\",\n\t\".cache\",\n\t\"dist\",\n\t\"coverage\",\n\t\".turbo\",\n\t\".next\",\n\t\".nuxt\",\n\t\".vercel\",\n];\n\n/**\n * Load ignore patterns from .gitignore and add defaults\n */\nexport async function loadIgnorePatterns(\n\tprojectRoot: string,\n): Promise<ReturnType<typeof ignore>> {\n\tconst ig = ignore();\n\n\t// Add default patterns\n\tig.add(DEFAULT_IGNORE_PATTERNS);\n\n\t// Load .gitignore if it exists\n\tconst gitignorePath = join(projectRoot, \".gitignore\");\n\tif (existsSync(gitignorePath)) {\n\t\ttry {\n\t\t\tconst content = await readFile(gitignorePath, \"utf-8\");\n\t\t\tig.add(content);\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn ig;\n}\n\nexport interface FileToSync {\n\tpath: string;\n\tcontent: string;\n\tencoding: \"utf8\" | \"base64\";\n}\n\n/**\n * Collect all files in a directory that should be synced\n * Respects .gitignore and default ignore patterns\n */\nexport async function collectFiles(projectRoot: string): Promise<FileToSync[]> {\n\tconst ig = await loadIgnorePatterns(projectRoot);\n\tconst files: FileToSync[] = [];\n\n\tasync function walk(dir: string) {\n\t\tconst entries = await readdir(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(dir, entry.name);\n\t\t\tconst relativePath = relative(projectRoot, fullPath);\n\n\t\t\t// Check if path is ignored\n\t\t\tif (ig.ignores(relativePath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tawait walk(fullPath);\n\t\t\t} else if (entry.isFile()) {\n\t\t\t\ttry {\n\t\t\t\t\tconst content = await readFile(fullPath);\n\t\t\t\t\tconst isBinary = isBinaryPath(fullPath) || detectBinary(content);\n\n\t\t\t\t\tfiles.push({\n\t\t\t\t\t\tpath: relativePath,\n\t\t\t\t\t\tcontent: isBinary\n\t\t\t\t\t\t\t? content.toString(\"base64\")\n\t\t\t\t\t\t\t: content.toString(\"utf8\"),\n\t\t\t\t\t\tencoding: isBinary ? \"base64\" : \"utf8\",\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\t// Skip files that can't be read\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tawait walk(projectRoot);\n\treturn files;\n}\n\n/**\n * Pull all files from GitHub to a local directory.\n * Uses a single API call to fetch all files from the repository.\n */\nexport async function pullFilesFromGithub(\n\tmcpId: string,\n\ttargetDir: string,\n): Promise<{ count: number; files: string[] }> {\n\t// Fetch all files from GitHub in one request\n\tconst result = await api.get<PullFilesResponse>(\n\t\t`/api/mcp/repositories/${mcpId}/files`,\n\t);\n\n\tconst writtenFiles: string[] = [];\n\n\tfor (const file of result.files) {\n\t\tconst localPath = join(targetDir, file.path);\n\t\tconst dir = dirname(localPath);\n\n\t\t// Ensure directory exists\n\t\tawait mkdir(dir, { recursive: true });\n\n\t\t// Write file content\n\t\tif (file.encoding === \"base64\") {\n\t\t\tawait writeFile(localPath, Buffer.from(file.content, \"base64\"));\n\t\t} else {\n\t\t\tawait writeFile(localPath, file.content, \"utf8\");\n\t\t}\n\n\t\twrittenFiles.push(file.path);\n\t}\n\n\treturn { count: writtenFiles.length, files: writtenFiles };\n}\n\n/**\n * Collect a single file for syncing\n */\nexport async function collectSingleFile(\n\tprojectRoot: string,\n\tfilePath: string,\n): Promise<FileToSync | null> {\n\tconst fullPath = join(projectRoot, filePath);\n\tconst relativePath = relative(projectRoot, fullPath);\n\n\t// Check if file exists\n\tif (!existsSync(fullPath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst fileStat = await stat(fullPath);\n\t\tif (!fileStat.isFile()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst content = await readFile(fullPath);\n\t\tconst isBinary = isBinaryPath(fullPath) || detectBinary(content);\n\n\t\treturn {\n\t\t\tpath: relativePath,\n\t\t\tcontent: isBinary ? content.toString(\"base64\") : content.toString(\"utf8\"),\n\t\t\tencoding: isBinary ? \"base64\" : \"utf8\",\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n","import { input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { collectFiles, findProjectRoot } from \"../../lib/sync.js\";\nimport { requireMcpId } from \"../../lib/utils.js\";\nimport type { DeployToGithubResponse } from \"../../types/index.js\";\n\nexport const publishCommand = new Command(\"publish\")\n\t.description(\"Push local files to GitHub and trigger deployment\")\n\t.option(\"-m, --message <msg>\", \"Commit message\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst mcpId = await requireMcpId(options.mcpId);\n\n\t\t\t// Find project root\n\t\t\tconst projectRoot = await findProjectRoot(process.cwd());\n\t\t\tif (!projectRoot) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"Not in a WaniWani project. Run 'waniwani mcp init <name>' first.\",\n\t\t\t\t\t\"NOT_IN_PROJECT\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get commit message\n\t\t\tlet message = options.message;\n\t\t\tif (!message) {\n\t\t\t\tmessage = await input({\n\t\t\t\t\tmessage: \"Commit message:\",\n\t\t\t\t\tvalidate: (value) =>\n\t\t\t\t\t\tvalue.trim() ? true : \"Commit message is required\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Collecting files...\").start();\n\n\t\t\t// Collect all files from the project\n\t\t\tconst files = await collectFiles(projectRoot);\n\n\t\t\tif (files.length === 0) {\n\t\t\t\tspinner.fail(\"No files to deploy\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tspinner.text = `Pushing ${files.length} files to GitHub...`;\n\n\t\t\tconst result = await api.post<DeployToGithubResponse>(\n\t\t\t\t`/api/mcp/repositories/${mcpId}/deploy`,\n\t\t\t\t{ files, message },\n\t\t\t);\n\n\t\t\tspinner.succeed(`Pushed to GitHub (${result.commitSha.slice(0, 7)})`);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t\tformatSuccess(\"Files pushed to GitHub!\", false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Deployment will start automatically via webhook.\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput } from \"../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../lib/utils.js\";\nimport type { RunCommandResponse } from \"../../types/index.js\";\n\nexport const runCommandCommand = new Command(\"run-command\")\n\t.description(\"Run a command in the MCP sandbox\")\n\t.argument(\"<command>\", \"Command to run\")\n\t.argument(\"[args...]\", \"Command arguments\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--cwd <path>\", \"Working directory\")\n\t.option(\n\t\t\"--timeout <ms>\",\n\t\t\"Command timeout in milliseconds (default: 30000, max: 300000)\",\n\t)\n\t.action(async (cmd: string, args: string[], options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst timeout = options.timeout\n\t\t\t\t? Number.parseInt(options.timeout, 10)\n\t\t\t\t: undefined;\n\n\t\t\tconst spinner = ora(`Running: ${cmd} ${args.join(\" \")}`.trim()).start();\n\n\t\t\tconst result = await api.post<RunCommandResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/commands`,\n\t\t\t\t{\n\t\t\t\t\tcommand: cmd,\n\t\t\t\t\targs: args.length > 0 ? args : undefined,\n\t\t\t\t\tcwd: options.cwd,\n\t\t\t\t\ttimeout,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\t// Show command\n\t\t\t\tconst cmdLine = [cmd, ...args].join(\" \");\n\t\t\t\tconsole.log(chalk.gray(`$ ${cmdLine}`));\n\t\t\t\tconsole.log();\n\n\t\t\t\t// Show stdout\n\t\t\t\tif (result.stdout) {\n\t\t\t\t\tprocess.stdout.write(result.stdout);\n\t\t\t\t\tif (!result.stdout.endsWith(\"\\n\")) {\n\t\t\t\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Show stderr\n\t\t\t\tif (result.stderr) {\n\t\t\t\t\tprocess.stderr.write(chalk.red(result.stderr));\n\t\t\t\t\tif (!result.stderr.endsWith(\"\\n\")) {\n\t\t\t\t\t\tprocess.stderr.write(\"\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Show exit code and duration\n\t\t\t\tconsole.log();\n\t\t\t\tconst exitColor = result.exitCode === 0 ? chalk.green : chalk.red;\n\t\t\t\tconsole.log(\n\t\t\t\t\texitColor(`Exit code: ${result.exitCode}`),\n\t\t\t\t\tchalk.gray(`(${(result.duration / 1000).toFixed(2)}s)`),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Exit with the command's exit code\n\t\t\tif (result.exitCode !== 0) {\n\t\t\t\tprocess.exit(result.exitCode);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatList, formatOutput } from \"../../lib/output.js\";\nimport { requireMcpId } from \"../../lib/utils.js\";\nimport type { McpRepository, ServerStatusResponse } from \"../../types/index.js\";\n\nexport const statusCommand = new Command(\"status\")\n\t.description(\"Show current MCP status\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst mcpId = await requireMcpId(options.mcpId);\n\n\t\t\tconst spinner = ora(\"Fetching MCP status...\").start();\n\n\t\t\tconst result = await api.get<McpRepository>(\n\t\t\t\t`/api/mcp/repositories/${mcpId}`,\n\t\t\t);\n\n\t\t\t// Fetch server status if sandbox is active\n\t\t\tlet serverStatus: ServerStatusResponse | null = null;\n\t\t\tif (result.activeSandbox) {\n\t\t\t\tserverStatus = await api\n\t\t\t\t\t.post<ServerStatusResponse>(\n\t\t\t\t\t\t`/api/mcp/sessions/${result.activeSandbox.id}/server`,\n\t\t\t\t\t\t{ action: \"status\" },\n\t\t\t\t\t)\n\t\t\t\t\t.catch(() => null);\n\t\t\t}\n\n\t\t\tspinner.stop();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ ...result, server: serverStatus }, true);\n\t\t\t} else {\n\t\t\t\tconst deployStatus = result.deployedAt\n\t\t\t\t\t? chalk.green(\"Deployed\")\n\t\t\t\t\t: chalk.yellow(\"Pending\");\n\n\t\t\t\tconst items = [\n\t\t\t\t\t{ label: \"Name\", value: result.name },\n\t\t\t\t\t{ label: \"MCP ID\", value: result.id },\n\t\t\t\t\t{ label: \"Status\", value: deployStatus },\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Last Deploy\",\n\t\t\t\t\t\tvalue: result.deployedAt\n\t\t\t\t\t\t\t? new Date(result.deployedAt).toLocaleString()\n\t\t\t\t\t\t\t: chalk.gray(\"Never\"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Created\",\n\t\t\t\t\t\tvalue: new Date(result.createdAt).toLocaleString(),\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\t// Add sandbox info if active\n\t\t\t\tif (result.activeSandbox) {\n\t\t\t\t\tconst sandbox = result.activeSandbox;\n\t\t\t\t\tconst serverRunning = serverStatus?.running ?? sandbox.serverRunning;\n\t\t\t\t\tconst serverStatusColor = serverRunning ? chalk.green : chalk.yellow;\n\n\t\t\t\t\titems.push(\n\t\t\t\t\t\t{ label: \"\", value: \"\" }, // Separator\n\t\t\t\t\t\t{ label: \"Sandbox\", value: chalk.green(\"Active\") },\n\t\t\t\t\t\t{ label: \"Preview URL\", value: sandbox.previewUrl },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Server\",\n\t\t\t\t\t\t\tvalue: serverStatusColor(serverRunning ? \"Running\" : \"Stopped\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Expires\",\n\t\t\t\t\t\t\tvalue: sandbox.expiresAt\n\t\t\t\t\t\t\t\t? new Date(sandbox.expiresAt).toLocaleString()\n\t\t\t\t\t\t\t\t: chalk.gray(\"N/A\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\titems.push(\n\t\t\t\t\t\t{ label: \"\", value: \"\" }, // Separator\n\t\t\t\t\t\t{ label: \"Sandbox\", value: chalk.gray(\"None\") },\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tformatList(items, false);\n\n\t\t\t\tconsole.log();\n\t\t\t\tif (!result.activeSandbox) {\n\t\t\t\t\tconsole.log(\"Start development: waniwani mcp preview\");\n\t\t\t\t} else if (!serverStatus?.running) {\n\t\t\t\t\tconsole.log(\"View logs: waniwani mcp logs\");\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../lib/utils.js\";\n\nexport const stopCommand = new Command(\"stop\")\n\t.description(\"Stop the development environment (sandbox + server)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst spinner = ora(\"Stopping development environment...\").start();\n\n\t\t\t// Stop server first\n\t\t\ttry {\n\t\t\t\tawait api.post(`/api/mcp/sessions/${sessionId}/server`, {\n\t\t\t\t\taction: \"stop\",\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\t// Server might not be running, continue\n\t\t\t}\n\n\t\t\t// Delete session\n\t\t\tawait api.delete(`/api/mcp/sessions/${sessionId}`);\n\n\t\t\t// Clear session from config\n\t\t\tawait config.setSessionId(null);\n\n\t\t\tspinner.succeed(\"Development environment stopped\");\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ stopped: true }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(\"Sandbox stopped.\", false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Start again: waniwani mcp preview\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { findProjectRoot, pullFilesFromGithub } from \"../../lib/sync.js\";\nimport { requireMcpId } from \"../../lib/utils.js\";\n\nexport const syncCommand = new Command(\"sync\")\n\t.description(\"Pull files from GitHub to local project\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst mcpId = await requireMcpId(options.mcpId);\n\n\t\t\t// Find project root\n\t\t\tconst projectRoot = await findProjectRoot(process.cwd());\n\t\t\tif (!projectRoot) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"Not in a WaniWani project. Run 'waniwani mcp init <name>' first.\",\n\t\t\t\t\t\"NOT_IN_PROJECT\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Pulling files from GitHub...\").start();\n\n\t\t\tconst result = await pullFilesFromGithub(mcpId, projectRoot);\n\n\t\t\tspinner.succeed(`Pulled ${result.count} files from GitHub`);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ files: result.files }, true);\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t\tformatSuccess(\"Files synced from GitHub!\", false);\n\t\t\t\tif (result.files.length > 0 && result.files.length <= 10) {\n\t\t\t\t\tconsole.log();\n\t\t\t\t\tfor (const file of result.files) {\n\t\t\t\t\t\tconsole.log(` ${file}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { handleError, McpError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport type {\n\tMcpRepository,\n\tMcpRepositoryListResponse,\n} from \"../../types/index.js\";\n\nexport const useCommand = new Command(\"use\")\n\t.description(\"Select an MCP to use for subsequent commands\")\n\t.argument(\"<name>\", \"Name of the MCP to use\")\n\t.action(async (name: string, _options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst spinner = ora(\"Fetching MCPs...\").start();\n\n\t\t\t// Fetch all MCPs\n\t\t\tconst mcps = await api.get<McpRepositoryListResponse>(\n\t\t\t\t\"/api/mcp/repositories\",\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\t// Find MCP by name\n\t\t\tconst mcp = mcps.find((m: McpRepository) => m.name === name);\n\n\t\t\tif (!mcp) {\n\t\t\t\tthrow new McpError(\n\t\t\t\t\t`MCP \"${name}\" not found. Run 'waniwani mcp list' to see available MCPs.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tawait config.setMcpId(mcp.id);\n\t\t\t// Clear session since we're switching MCPs\n\t\t\tawait config.setSessionId(null);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ selected: mcp }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(`Now using MCP \"${name}\"`, false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(` MCP ID: ${mcp.id}`);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Next steps:\");\n\t\t\t\tconsole.log(\" waniwani mcp preview # Start live preview\");\n\t\t\t\tconsole.log(\" waniwani mcp status # Check status\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport { listCommand } from \"./list.js\";\nimport { switchCommand } from \"./switch.js\";\n\nexport const orgCommand = new Command(\"org\")\n\t.description(\"Organization management commands\")\n\t.addCommand(listCommand)\n\t.addCommand(switchCommand);\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatTable } from \"../../lib/output.js\";\nimport type { Org, OrgListResponse } from \"../../types/index.js\";\n\nexport const listCommand = new Command(\"list\")\n\t.description(\"List your organizations\")\n\t.action(async (_, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst spinner = ora(\"Fetching organizations...\").start();\n\n\t\t\tconst result = await api.get<OrgListResponse>(\"/api/oauth/orgs\");\n\n\t\t\tspinner.stop();\n\n\t\t\tconst { orgs, activeOrgId } = result;\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(\n\t\t\t\t\t{\n\t\t\t\t\t\torgs: orgs.map((o: Org) => ({\n\t\t\t\t\t\t\t...o,\n\t\t\t\t\t\t\tisActive: o.id === activeOrgId,\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tactiveOrgId,\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tif (orgs.length === 0) {\n\t\t\t\t\tconsole.log(\"No organizations found.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconsole.log(chalk.bold(\"\\nOrganizations:\\n\"));\n\n\t\t\t\tconst rows = orgs.map((o: Org) => {\n\t\t\t\t\tconst isActive = o.id === activeOrgId;\n\t\t\t\t\treturn [\n\t\t\t\t\t\tisActive ? chalk.cyan(`* ${o.name}`) : ` ${o.name}`,\n\t\t\t\t\t\to.slug,\n\t\t\t\t\t\to.role,\n\t\t\t\t\t];\n\t\t\t\t});\n\n\t\t\t\tformatTable([\"Name\", \"Slug\", \"Role\"], rows, false);\n\n\t\t\t\tconsole.log();\n\t\t\t\tif (activeOrgId) {\n\t\t\t\t\tconst activeOrg = orgs.find((o: Org) => o.id === activeOrgId);\n\t\t\t\t\tif (activeOrg) {\n\t\t\t\t\t\tconsole.log(`Active organization: ${chalk.cyan(activeOrg.name)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconsole.log(\"\\nSwitch organization: waniwani org switch <name>\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport type {\n\tOrg,\n\tOrgListResponse,\n\tOrgSwitchResponse,\n} from \"../../types/index.js\";\n\nexport const switchCommand = new Command(\"switch\")\n\t.description(\"Switch to a different organization\")\n\t.argument(\"<name>\", \"Name or slug of the organization to switch to\")\n\t.action(async (name: string, _, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst spinner = ora(\"Fetching organizations...\").start();\n\n\t\t\t// First fetch orgs to find the org ID\n\t\t\tconst { orgs } = await api.get<OrgListResponse>(\"/api/oauth/orgs\");\n\n\t\t\t// Find org by name or slug\n\t\t\tconst org = orgs.find((o: Org) => o.name === name || o.slug === name);\n\n\t\t\tif (!org) {\n\t\t\t\tspinner.stop();\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t`Organization \"${name}\" not found. Run 'waniwani org list' to see available organizations.`,\n\t\t\t\t\t\"ORG_NOT_FOUND\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tspinner.text = \"Switching organization...\";\n\n\t\t\t// Switch to the org\n\t\t\tawait api.post<OrgSwitchResponse>(\"/api/oauth/orgs/switch\", {\n\t\t\t\torgId: org.id,\n\t\t\t});\n\n\t\t\tspinner.succeed(\"Organization switched\");\n\n\t\t\t// Clear local MCP selection since we switched orgs\n\t\t\tconfig.setMcpId(null);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ switched: org }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(`Switched to organization \"${org.name}\"`, false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Note: Active MCP selection has been cleared.\");\n\t\t\t\tconsole.log(\n\t\t\t\t\t\"Run 'waniwani mcp list' to see MCPs in this organization.\",\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { program } from \"./cli.js\";\n\nprogram.parse(process.argv);\n"],"mappings":"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","names":["Command","Command","existsSync","join","chalk","chalk","join","existsSync","Command","chalk","Command","Command","chalk","Command","Command","Command","chalk","Command","ora","Command","chalk","ora","Command","chalk","Command","ora","Command","ora","chalk","writeFile","Command","ora","Command","ora","writeFile","readFile","Command","ora","Command","readFile","ora","Command","existsSync","readFile","join","Command","ora","join","existsSync","readFile","config","Command","ora","chalk","Command","ora","listCommand","Command","ora","chalk","chalk","Command","ora","Command","ora","chalk","Command","ora","existsSync","mkdir","readFile","writeFile","join","existsSync","join","readFile","mkdir","writeFile","Command","ora","relative","Command","ora","Command","ora","chalk","Command","ora","Command","ora","chalk","chalk","Command","ora","Command","ora","chalk","Command","ora","Command","ora","Command","ora","Command","ora","Command","ora","Command","ora","Command","listCommand","Command","chalk","Command","ora","listCommand","Command","ora","chalk","Command","ora","Command","ora","Command","listCommand","require","Command"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/config/index.ts","../src/commands/config/init.ts","../src/lib/config.ts","../src/lib/errors.ts","../src/lib/output.ts","../src/commands/login.ts","../src/lib/auth.ts","../src/commands/logout.ts","../src/commands/mcp/index.ts","../src/commands/mcp/delete.ts","../src/lib/api.ts","../src/lib/utils.ts","../src/commands/mcp/file/index.ts","../src/commands/mcp/file/list.ts","../src/commands/mcp/file/read.ts","../src/commands/mcp/file/write.ts","../src/commands/mcp/init.ts","../src/lib/sync.ts","../src/commands/mcp/list.ts","../src/commands/mcp/logs.ts","../src/commands/mcp/preview.ts","../src/commands/mcp/publish.ts","../src/commands/mcp/run-command.ts","../src/commands/mcp/status.ts","../src/commands/mcp/stop.ts","../src/commands/mcp/sync.ts","../src/commands/mcp/use.ts","../src/commands/org/index.ts","../src/commands/org/list.ts","../src/commands/org/switch.ts","../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { Command } from \"commander\";\nimport { configCommand } from \"./commands/config/index.js\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { logoutCommand } from \"./commands/logout.js\";\nimport { mcpCommand } from \"./commands/mcp/index.js\";\nimport { orgCommand } from \"./commands/org/index.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nexport const program = new Command()\n\t.name(\"waniwani\")\n\t.description(\"WaniWani CLI for MCP development workflow\")\n\t.version(version)\n\t.option(\"--json\", \"Output results as JSON\")\n\t.option(\"--verbose\", \"Enable verbose logging\");\n\n// Auth commands\nprogram.addCommand(loginCommand);\nprogram.addCommand(logoutCommand);\n\n// Main commands\nprogram.addCommand(mcpCommand);\nprogram.addCommand(orgCommand);\nprogram.addCommand(configCommand);\n","import { Command } from \"commander\";\nimport { configInitCommand } from \"./init.js\";\n\nexport const configCommand = new Command(\"config\")\n\t.description(\"Manage WaniWani configuration\")\n\t.addCommand(configInitCommand);\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport {\n\tCONFIG_FILE_NAME,\n\tinitConfigAt,\n\tLOCAL_CONFIG_DIR,\n} from \"../../lib/config.js\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\n\nexport const configInitCommand = new Command(\"init\")\n\t.description(\"Initialize .waniwani config in the current directory\")\n\t.option(\"--force\", \"Overwrite existing config\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst cwd = process.cwd();\n\t\t\tconst configPath = join(cwd, LOCAL_CONFIG_DIR, CONFIG_FILE_NAME);\n\n\t\t\t// Check if config already exists\n\t\t\tif (existsSync(configPath) && !options.force) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t`Config already exists at ${configPath}. Use --force to overwrite.`,\n\t\t\t\t\t\"CONFIG_EXISTS\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Create .waniwani/settings.json with defaults\n\t\t\tconst result = await initConfigAt(cwd);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ created: result.path, config: result.config }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(`Created ${result.path}`, false);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\n\nexport const LOCAL_CONFIG_DIR = \".waniwani\";\nexport const CONFIG_FILE_NAME = \"settings.json\";\n\nconst LOCAL_DIR = join(process.cwd(), LOCAL_CONFIG_DIR);\nconst LOCAL_FILE = join(LOCAL_DIR, CONFIG_FILE_NAME);\nconst DEFAULT_API_URL = \"https://app.waniwani.ai\";\n\nconst ConfigSchema = z.object({\n\t// Settings\n\tsessionId: z.string().nullable().default(null),\n\tmcpId: z.string().nullable().default(null),\n\tapiUrl: z.string().default(DEFAULT_API_URL),\n\t// Auth (merged from auth.json)\n\taccessToken: z.string().nullable().default(null),\n\trefreshToken: z.string().nullable().default(null),\n\texpiresAt: z.string().nullable().default(null),\n\tclientId: z.string().nullable().default(null),\n});\n\ntype ConfigData = z.infer<typeof ConfigSchema>;\n\nclass Config {\n\tprivate dir: string;\n\tprivate file: string;\n\tprivate cache: ConfigData | null = null;\n\n\tconstructor() {\n\t\tthis.dir = LOCAL_DIR;\n\t\tthis.file = LOCAL_FILE;\n\t}\n\n\tprivate async load(): Promise<ConfigData> {\n\t\tif (!this.cache) {\n\t\t\ttry {\n\t\t\t\tthis.cache = ConfigSchema.parse(\n\t\t\t\t\tJSON.parse(await readFile(this.file, \"utf-8\")),\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\tthis.cache = ConfigSchema.parse({});\n\t\t\t}\n\t\t}\n\t\treturn this.cache;\n\t}\n\n\tprivate async save(data: ConfigData): Promise<void> {\n\t\tthis.cache = data;\n\t\tawait mkdir(this.dir, { recursive: true });\n\t\tawait writeFile(this.file, JSON.stringify(data, null, \"\\t\"));\n\t}\n\n\t/**\n\t * Ensure the .waniwani directory exists in cwd.\n\t * Used by login to create config before saving tokens.\n\t */\n\tasync ensureConfigDir(): Promise<void> {\n\t\tawait mkdir(this.dir, { recursive: true });\n\t}\n\n\t/**\n\t * Check if a .waniwani config directory exists in cwd.\n\t */\n\thasConfig(): boolean {\n\t\treturn existsSync(this.dir);\n\t}\n\n\t// --- Settings methods ---\n\n\tasync getMcpId() {\n\t\treturn (await this.load()).mcpId;\n\t}\n\n\tasync setMcpId(id: string | null) {\n\t\tconst data = await this.load();\n\t\tdata.mcpId = id;\n\t\tawait this.save(data);\n\t}\n\n\tasync getSessionId() {\n\t\treturn (await this.load()).sessionId;\n\t}\n\n\tasync setSessionId(id: string | null) {\n\t\tconst data = await this.load();\n\t\tdata.sessionId = id;\n\t\tawait this.save(data);\n\t}\n\n\tasync getApiUrl() {\n\t\tif (process.env.WANIWANI_API_URL) return process.env.WANIWANI_API_URL;\n\t\treturn (await this.load()).apiUrl;\n\t}\n\n\tasync clear() {\n\t\tawait this.save(ConfigSchema.parse({}));\n\t}\n\n\t// --- Auth methods ---\n\n\tasync getAccessToken(): Promise<string | null> {\n\t\treturn (await this.load()).accessToken;\n\t}\n\n\tasync getRefreshToken(): Promise<string | null> {\n\t\treturn (await this.load()).refreshToken;\n\t}\n\n\tasync getClientId(): Promise<string | null> {\n\t\treturn (await this.load()).clientId;\n\t}\n\n\tasync setTokens(\n\t\taccessToken: string,\n\t\trefreshToken: string,\n\t\texpiresIn: number,\n\t\tclientId?: string,\n\t): Promise<void> {\n\t\tconst expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString();\n\t\tconst data = await this.load();\n\t\tdata.accessToken = accessToken;\n\t\tdata.refreshToken = refreshToken;\n\t\tdata.expiresAt = expiresAt;\n\t\tif (clientId) {\n\t\t\tdata.clientId = clientId;\n\t\t}\n\t\tawait this.save(data);\n\t}\n\n\tasync clearAuth(): Promise<void> {\n\t\tconst data = await this.load();\n\t\tdata.accessToken = null;\n\t\tdata.refreshToken = null;\n\t\tdata.expiresAt = null;\n\t\tdata.clientId = null;\n\t\tawait this.save(data);\n\t}\n\n\tasync isTokenExpired(): Promise<boolean> {\n\t\tconst data = await this.load();\n\t\tif (!data.expiresAt) return true;\n\t\t// Consider expired 5 minutes before actual expiry\n\t\treturn new Date(data.expiresAt).getTime() - 5 * 60 * 1000 < Date.now();\n\t}\n}\n\nexport const config = new Config();\n\n/**\n * Initialize a .waniwani/settings.json at the given directory.\n * Returns the created config data and path.\n */\nexport async function initConfigAt(\n\tdir: string,\n\toverrides: Partial<ConfigData> = {},\n): Promise<{ path: string; config: ConfigData }> {\n\tconst configDir = join(dir, LOCAL_CONFIG_DIR);\n\tconst configPath = join(configDir, CONFIG_FILE_NAME);\n\n\tawait mkdir(configDir, { recursive: true });\n\n\tconst data = ConfigSchema.parse(overrides);\n\tawait writeFile(configPath, JSON.stringify(data, null, \"\\t\"), \"utf-8\");\n\n\treturn { path: configPath, config: data };\n}\n","import chalk from \"chalk\";\nimport { ZodError } from \"zod\";\n\nexport class CLIError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic code: string,\n\t\tpublic details?: Record<string, unknown>,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CLIError\";\n\t}\n}\n\nexport class ConfigError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"CONFIG_ERROR\", details);\n\t}\n}\n\nexport class AuthError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"AUTH_ERROR\", details);\n\t}\n}\n\nexport class SandboxError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"SANDBOX_ERROR\", details);\n\t}\n}\n\nexport class GitHubError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"GITHUB_ERROR\", details);\n\t}\n}\n\nexport class McpError extends CLIError {\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, \"MCP_ERROR\", details);\n\t}\n}\n\nexport function handleError(error: unknown, json: boolean): void {\n\tif (error instanceof ZodError) {\n\t\tconst message = error.issues\n\t\t\t.map((e) => `${e.path.join(\".\")}: ${e.message}`)\n\t\t\t.join(\", \");\n\t\toutputError(\"VALIDATION_ERROR\", `Invalid input: ${message}`, json);\n\t} else if (error instanceof CLIError) {\n\t\toutputError(error.code, error.message, json, error.details);\n\t} else if (error instanceof Error) {\n\t\toutputError(\"UNKNOWN_ERROR\", error.message, json);\n\t} else {\n\t\toutputError(\"UNKNOWN_ERROR\", String(error), json);\n\t}\n}\n\nfunction outputError(\n\tcode: string,\n\tmessage: string,\n\tjson: boolean,\n\tdetails?: Record<string, unknown>,\n): void {\n\tif (json) {\n\t\tconsole.error(\n\t\t\tJSON.stringify({ success: false, error: { code, message, details } }),\n\t\t);\n\t} else {\n\t\tconsole.error(chalk.red(`Error [${code}]:`), message);\n\t\tif (details) {\n\t\t\tconsole.error(chalk.gray(\"Details:\"), JSON.stringify(details, null, 2));\n\t\t}\n\t}\n}\n","import chalk from \"chalk\";\n\nexport function formatOutput<T>(data: T, json: boolean): void {\n\tif (json) {\n\t\tconsole.log(JSON.stringify({ success: true, data }, null, 2));\n\t} else {\n\t\tprettyPrint(data);\n\t}\n}\n\nexport function formatSuccess(message: string, json: boolean): void {\n\tif (json) {\n\t\tconsole.log(JSON.stringify({ success: true, message }));\n\t} else {\n\t\tconsole.log(chalk.green(\"✓\"), message);\n\t}\n}\n\nexport function formatError(error: Error | string, json: boolean): void {\n\tconst message = error instanceof Error ? error.message : error;\n\tif (json) {\n\t\tconsole.error(JSON.stringify({ success: false, error: message }));\n\t} else {\n\t\tconsole.error(chalk.red(\"✗\"), message);\n\t}\n}\n\nexport function formatTable(\n\theaders: string[],\n\trows: string[][],\n\tjson: boolean,\n): void {\n\tif (json) {\n\t\tconst data = rows.map((row) =>\n\t\t\tObject.fromEntries(headers.map((header, i) => [header, row[i]])),\n\t\t);\n\t\tconsole.log(JSON.stringify({ success: true, data }, null, 2));\n\t} else {\n\t\t// Simple table formatting without external dependency\n\t\tconst colWidths = headers.map((h, i) =>\n\t\t\tMath.max(h.length, ...rows.map((r) => (r[i] || \"\").length)),\n\t\t);\n\n\t\tconst separator = colWidths.map((w) => \"-\".repeat(w + 2)).join(\"+\");\n\t\tconst formatRow = (row: string[]) =>\n\t\t\trow.map((cell, i) => ` ${(cell || \"\").padEnd(colWidths[i])} `).join(\"|\");\n\n\t\tconsole.log(chalk.cyan(formatRow(headers)));\n\t\tconsole.log(separator);\n\t\tfor (const row of rows) {\n\t\t\tconsole.log(formatRow(row));\n\t\t}\n\t}\n}\n\nexport function formatList(\n\titems: Array<{ label: string; value: string }>,\n\tjson: boolean,\n): void {\n\tif (json) {\n\t\tconst data = Object.fromEntries(\n\t\t\titems.map((item) => [item.label, item.value]),\n\t\t);\n\t\tconsole.log(JSON.stringify({ success: true, data }, null, 2));\n\t} else {\n\t\tconst maxLabelLength = Math.max(...items.map((i) => i.label.length));\n\t\titems.forEach((item) => {\n\t\t\tconsole.log(\n\t\t\t\t`${chalk.gray(item.label.padEnd(maxLabelLength))} ${chalk.white(item.value)}`,\n\t\t\t);\n\t\t});\n\t}\n}\n\nfunction prettyPrint(data: unknown, indent = 0): void {\n\tconst prefix = \" \".repeat(indent);\n\n\tif (Array.isArray(data)) {\n\t\tdata.forEach((item, index) => {\n\t\t\tconsole.log(`${prefix}${chalk.gray(`[${index}]`)}`);\n\t\t\tprettyPrint(item, indent + 1);\n\t\t});\n\t} else if (typeof data === \"object\" && data !== null) {\n\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\t\tconsole.log(`${prefix}${chalk.gray(key)}:`);\n\t\t\t\tprettyPrint(value, indent + 1);\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`${prefix}${chalk.gray(key)}: ${chalk.white(String(value))}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconsole.log(`${prefix}${chalk.white(String(data))}`);\n\t}\n}\n","import { spawn } from \"node:child_process\";\nimport { createServer, type Server } from \"node:http\";\nimport type { Socket } from \"node:net\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { auth } from \"../lib/auth.js\";\nimport { config } from \"../lib/config.js\";\nimport { CLIError, handleError } from \"../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../lib/output.js\";\nimport type {\n\tOAuthClientRegistrationResponse,\n\tOAuthTokenResponse,\n} from \"../types/index.js\";\n\nconst CALLBACK_PORT = 54321;\nconst CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;\nconst CLIENT_NAME = \"waniwani-cli\";\n\nfunction generateCodeVerifier(): string {\n\tconst array = new Uint8Array(32);\n\tcrypto.getRandomValues(array);\n\treturn btoa(String.fromCharCode(...array))\n\t\t.replace(/\\+/g, \"-\")\n\t\t.replace(/\\//g, \"_\")\n\t\t.replace(/=+$/, \"\");\n}\n\nasync function generateCodeChallenge(verifier: string): Promise<string> {\n\tconst encoder = new TextEncoder();\n\tconst data = encoder.encode(verifier);\n\tconst hash = await crypto.subtle.digest(\"SHA-256\", data);\n\treturn btoa(String.fromCharCode(...new Uint8Array(hash)))\n\t\t.replace(/\\+/g, \"-\")\n\t\t.replace(/\\//g, \"_\")\n\t\t.replace(/=+$/, \"\");\n}\n\nfunction generateState(): string {\n\tconst array = new Uint8Array(16);\n\tcrypto.getRandomValues(array);\n\treturn Array.from(array, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nasync function registerClient(): Promise<OAuthClientRegistrationResponse> {\n\tconst apiUrl = await config.getApiUrl();\n\tconst response = await fetch(`${apiUrl}/api/auth/oauth2/register`, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tclient_name: CLIENT_NAME,\n\t\t\tredirect_uris: [CALLBACK_URL],\n\t\t\tgrant_types: [\"authorization_code\", \"refresh_token\"],\n\t\t\tresponse_types: [\"code\"],\n\t\t\ttoken_endpoint_auth_method: \"none\",\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.json().catch(() => ({}));\n\t\tthrow new CLIError(\n\t\t\t(error as { error_description?: string }).error_description ||\n\t\t\t\t\"Failed to register OAuth client\",\n\t\t\t\"CLIENT_REGISTRATION_FAILED\",\n\t\t);\n\t}\n\n\treturn response.json() as Promise<OAuthClientRegistrationResponse>;\n}\n\nasync function openBrowser(url: string): Promise<void> {\n\tconst [cmd, ...args] =\n\t\tprocess.platform === \"darwin\"\n\t\t\t? [\"open\", url]\n\t\t\t: process.platform === \"win32\"\n\t\t\t\t? [\"cmd\", \"/c\", \"start\", url]\n\t\t\t\t: [\"xdg-open\", url];\n\n\tspawn(cmd, args, { stdio: \"ignore\", detached: true }).unref();\n}\n\nasync function waitForCallback(\n\texpectedState: string,\n\ttimeoutMs: number = 300000,\n): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet server: Server | null = null;\n\t\tconst sockets = new Set<Socket>();\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tcleanup();\n\t\t\treject(new CLIError(\"Login timed out\", \"LOGIN_TIMEOUT\"));\n\t\t}, timeoutMs);\n\n\t\tconst cleanup = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\t// Destroy all active connections to allow process to exit\n\t\t\tfor (const socket of sockets) {\n\t\t\t\tsocket.destroy();\n\t\t\t}\n\t\t\tsockets.clear();\n\t\t\tserver?.close();\n\t\t};\n\n\t\tconst htmlResponse = (title: string, message: string, isSuccess: boolean) =>\n\t\t\t`<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${title} - WaniWani</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #fafafa;\n position: relative;\n overflow: hidden;\n }\n .blob {\n position: absolute;\n border-radius: 50%;\n filter: blur(60px);\n pointer-events: none;\n }\n .blob-1 {\n top: 0;\n left: 25%;\n width: 24rem;\n height: 24rem;\n background: linear-gradient(to bottom right, rgba(253, 224, 71, 0.3), rgba(251, 146, 60, 0.3));\n }\n .blob-2 {\n bottom: 0;\n right: 25%;\n width: 24rem;\n height: 24rem;\n background: linear-gradient(to bottom right, rgba(134, 239, 172, 0.3), rgba(52, 211, 153, 0.3));\n }\n .blob-3 {\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 40rem;\n height: 40rem;\n background: linear-gradient(to bottom right, rgba(255, 237, 213, 0.2), rgba(254, 249, 195, 0.2));\n }\n .container {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2rem;\n padding: 2rem;\n z-index: 10;\n text-align: center;\n }\n .logo {\n font-size: 1.75rem;\n font-weight: 700;\n color: #1e293b;\n letter-spacing: -0.025em;\n }\n .icon-circle {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: ${isSuccess ? \"rgba(52, 211, 153, 0.15)\" : \"rgba(239, 68, 68, 0.15)\"};\n }\n .icon {\n width: 40px;\n height: 40px;\n color: ${isSuccess ? \"#10b981\" : \"#ef4444\"};\n }\n h1 {\n font-size: 2rem;\n font-weight: 700;\n color: #1e293b;\n }\n p {\n font-size: 1.125rem;\n color: #64748b;\n max-width: 400px;\n }\n </style>\n</head>\n<body>\n <div class=\"blob blob-1\"></div>\n <div class=\"blob blob-2\"></div>\n <div class=\"blob blob-3\"></div>\n <div class=\"container\">\n <span class=\"logo\">WaniWani</span>\n <div class=\"icon-circle\">\n ${\n\t\t\t\tisSuccess\n\t\t\t\t\t? '<svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"></path></svg>'\n\t\t\t\t\t: '<svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6 6 18\"></path><path d=\"m6 6 12 12\"></path></svg>'\n\t\t\t}\n </div>\n <h1>${title}</h1>\n <p>${message}</p>\n </div>\n</body>\n</html>`;\n\n\t\ttry {\n\t\t\tserver = createServer((req, res) => {\n\t\t\t\tconst url = new URL(\n\t\t\t\t\treq.url || \"/\",\n\t\t\t\t\t`http://localhost:${CALLBACK_PORT}`,\n\t\t\t\t);\n\n\t\t\t\tif (url.pathname === \"/callback\") {\n\t\t\t\t\tconst code = url.searchParams.get(\"code\");\n\t\t\t\t\tconst state = url.searchParams.get(\"state\");\n\t\t\t\t\tconst error = url.searchParams.get(\"error\");\n\n\t\t\t\t\tres.setHeader(\"Content-Type\", \"text/html\");\n\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tres.statusCode = 400;\n\t\t\t\t\t\tres.end(htmlResponse(\"Login Failed\", `Error: ${error}`, false));\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\treject(new CLIError(`OAuth error: ${error}`, \"OAUTH_ERROR\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (state !== expectedState) {\n\t\t\t\t\t\tres.statusCode = 400;\n\t\t\t\t\t\tres.end(\n\t\t\t\t\t\t\thtmlResponse(\n\t\t\t\t\t\t\t\t\"Login Failed\",\n\t\t\t\t\t\t\t\t\"Invalid state parameter. Please try again.\",\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\treject(new CLIError(\"Invalid state parameter\", \"INVALID_STATE\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!code) {\n\t\t\t\t\t\tres.statusCode = 400;\n\t\t\t\t\t\tres.end(\n\t\t\t\t\t\t\thtmlResponse(\n\t\t\t\t\t\t\t\t\"Login Failed\",\n\t\t\t\t\t\t\t\t\"No authorization code received.\",\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\treject(new CLIError(\"No authorization code\", \"NO_CODE\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tres.statusCode = 200;\n\t\t\t\t\tres.end(\n\t\t\t\t\t\thtmlResponse(\n\t\t\t\t\t\t\t\"Login Successful!\",\n\t\t\t\t\t\t\t\"You can close this window and return to the terminal.\",\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\n\t\t\t\t\t// Schedule cleanup after response is sent\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\tresolve(code);\n\t\t\t\t\t}, 100);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tres.statusCode = 404;\n\t\t\t\tres.end(\"Not found\");\n\t\t\t});\n\n\t\t\t// Track connections so we can force-close them\n\t\t\tserver.on(\"connection\", (socket) => {\n\t\t\t\tsockets.add(socket);\n\t\t\t\tsocket.on(\"close\", () => sockets.delete(socket));\n\t\t\t});\n\n\t\t\tserver.on(\"error\", (err: NodeJS.ErrnoException) => {\n\t\t\t\tcleanup();\n\t\t\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew CLIError(\n\t\t\t\t\t\t\t`Port ${CALLBACK_PORT} is already in use. Close any other WaniWani CLI instances and try again.`,\n\t\t\t\t\t\t\t\"PORT_IN_USE\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tserver.listen(CALLBACK_PORT);\n\t\t} catch (err: unknown) {\n\t\t\tcleanup();\n\t\t\treject(err);\n\t\t}\n\t});\n}\n\nasync function exchangeCodeForToken(\n\tcode: string,\n\tcodeVerifier: string,\n\tclientId: string,\n\tresource: string,\n): Promise<OAuthTokenResponse> {\n\tconst apiUrl = await config.getApiUrl();\n\tconst response = await fetch(`${apiUrl}/api/auth/oauth2/token`, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tcode,\n\t\t\tredirect_uri: CALLBACK_URL,\n\t\t\tclient_id: clientId,\n\t\t\tcode_verifier: codeVerifier,\n\t\t\tresource, // RFC 8707 - required to get JWT token\n\t\t}).toString(),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.json().catch(() => ({}));\n\t\tthrow new CLIError(\n\t\t\t(error as { error_description?: string }).error_description ||\n\t\t\t\t\"Failed to exchange code for token\",\n\t\t\t\"TOKEN_EXCHANGE_FAILED\",\n\t\t);\n\t}\n\n\treturn response.json() as Promise<OAuthTokenResponse>;\n}\n\nexport const loginCommand = new Command(\"login\")\n\t.description(\"Log in to WaniWani\")\n\t.option(\"--no-browser\", \"Don't open the browser automatically\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\t// Check if already logged in with a valid session\n\t\t\tif (await auth.isLoggedIn()) {\n\t\t\t\t// Check if token is expired\n\t\t\t\tif (await auth.isTokenExpired()) {\n\t\t\t\t\t// Try to refresh the token\n\t\t\t\t\tconst refreshed = await auth.tryRefreshToken();\n\t\t\t\t\tif (refreshed) {\n\t\t\t\t\t\tif (json) {\n\t\t\t\t\t\t\tformatOutput({ alreadyLoggedIn: true, refreshed: true }, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\tchalk.green(\"Session refreshed. You're still logged in.\"),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Refresh failed, clear and proceed with login\n\t\t\t\t\tif (!json) {\n\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\tchalk.yellow(\"Session expired. Starting new login flow...\"),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait auth.clear();\n\t\t\t\t} else {\n\t\t\t\t\t// Token is valid\n\t\t\t\t\tif (json) {\n\t\t\t\t\t\tformatOutput({ alreadyLoggedIn: true }, true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\tchalk.yellow(\n\t\t\t\t\t\t\t\t\"Already logged in. Use 'waniwani logout' to log out first.\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!json) {\n\t\t\t\tconsole.log(chalk.bold(\"\\nWaniWani CLI Login\\n\"));\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Registering client...\").start();\n\n\t\t\t// Register OAuth client dynamically\n\t\t\tconst { client_id: clientId } = await registerClient();\n\n\t\t\tspinner.text = \"Preparing authentication...\";\n\n\t\t\t// Generate PKCE values\n\t\t\tconst codeVerifier = generateCodeVerifier();\n\t\t\tconst codeChallenge = await generateCodeChallenge(codeVerifier);\n\t\t\tconst state = generateState();\n\n\t\t\t// Build authorization URL\n\t\t\tconst apiUrl = await config.getApiUrl();\n\t\t\tconst authUrl = new URL(`${apiUrl}/api/auth/oauth2/authorize`);\n\t\t\tauthUrl.searchParams.set(\"client_id\", clientId);\n\t\t\tauthUrl.searchParams.set(\"redirect_uri\", CALLBACK_URL);\n\t\t\tauthUrl.searchParams.set(\"response_type\", \"code\");\n\t\t\tauthUrl.searchParams.set(\"code_challenge\", codeChallenge);\n\t\t\tauthUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n\t\t\tauthUrl.searchParams.set(\"state\", state);\n\t\t\tauthUrl.searchParams.set(\"resource\", apiUrl); // RFC 8707 - request JWT token\n\n\t\t\tspinner.stop();\n\n\t\t\tif (!json) {\n\t\t\t\tconsole.log(\"Opening browser for authentication...\\n\");\n\t\t\t\tconsole.log(`If the browser doesn't open, visit:\\n`);\n\t\t\t\tconsole.log(chalk.cyan(` ${authUrl.toString()}`));\n\t\t\t\tconsole.log();\n\t\t\t}\n\n\t\t\t// Start callback server and open browser\n\t\t\tconst callbackPromise = waitForCallback(state);\n\n\t\t\tif (options.browser !== false) {\n\t\t\t\tawait openBrowser(authUrl.toString());\n\t\t\t}\n\n\t\t\tspinner.start(\"Waiting for authorization...\");\n\n\t\t\t// Wait for callback with auth code\n\t\t\tconst code = await callbackPromise;\n\n\t\t\tspinner.text = \"Exchanging code for token...\";\n\n\t\t\t// Exchange code for token\n\t\t\tconst tokenResponse = await exchangeCodeForToken(\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tclientId,\n\t\t\t\tapiUrl, // RFC 8707 resource parameter\n\t\t\t);\n\n\t\t\t// Ensure .waniwani/ exists in cwd before storing tokens\n\t\t\tawait config.ensureConfigDir();\n\n\t\t\t// Store tokens and client ID for refresh\n\t\t\tawait auth.setTokens(\n\t\t\t\ttokenResponse.access_token,\n\t\t\t\ttokenResponse.refresh_token,\n\t\t\t\ttokenResponse.expires_in,\n\t\t\t\tclientId,\n\t\t\t);\n\n\t\t\tspinner.succeed(\"Logged in successfully!\");\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ success: true, loggedIn: true }, true);\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t\tformatSuccess(\"You're now logged in to WaniWani!\", false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Get started:\");\n\t\t\t\tconsole.log(\n\t\t\t\t\t\" waniwani mcp create my-server Create a new MCP sandbox\",\n\t\t\t\t);\n\t\t\t\tconsole.log(' waniwani task \"Add a tool\" Send tasks to Claude');\n\t\t\t\tconsole.log(\n\t\t\t\t\t\" waniwani org list View your organizations\",\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { config } from \"./config.js\";\n\n/**\n * AuthManager delegates all storage to the config module.\n * Auth tokens are stored in .waniwani/settings.json alongside other config.\n */\nclass AuthManager {\n\tasync isLoggedIn(): Promise<boolean> {\n\t\tconst token = await config.getAccessToken();\n\t\treturn !!token;\n\t}\n\n\tasync getAccessToken(): Promise<string | null> {\n\t\treturn config.getAccessToken();\n\t}\n\n\tasync getRefreshToken(): Promise<string | null> {\n\t\treturn config.getRefreshToken();\n\t}\n\n\tasync setTokens(\n\t\taccessToken: string,\n\t\trefreshToken: string,\n\t\texpiresIn: number,\n\t\tclientId?: string,\n\t): Promise<void> {\n\t\treturn config.setTokens(accessToken, refreshToken, expiresIn, clientId);\n\t}\n\n\tasync clear(): Promise<void> {\n\t\treturn config.clearAuth();\n\t}\n\n\tasync isTokenExpired(): Promise<boolean> {\n\t\treturn config.isTokenExpired();\n\t}\n\n\tasync tryRefreshToken(): Promise<boolean> {\n\t\tconst refreshToken = await config.getRefreshToken();\n\t\tconst clientId = await config.getClientId();\n\t\tif (!refreshToken || !clientId) return false;\n\n\t\ttry {\n\t\t\tconst apiUrl = await config.getApiUrl();\n\t\t\tconst response = await fetch(`${apiUrl}/api/auth/oauth2/token`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\t\trefresh_token: refreshToken,\n\t\t\t\t\tclient_id: clientId,\n\t\t\t\t}).toString(),\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tawait this.clear();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst data = (await response.json()) as {\n\t\t\t\taccess_token: string;\n\t\t\t\trefresh_token: string;\n\t\t\t\texpires_in: number;\n\t\t\t};\n\n\t\t\tawait this.setTokens(\n\t\t\t\tdata.access_token,\n\t\t\t\tdata.refresh_token,\n\t\t\t\tdata.expires_in,\n\t\t\t);\n\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tawait this.clear();\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\nexport const auth = new AuthManager();\n","import { Command } from \"commander\";\nimport { auth } from \"../lib/auth.js\";\nimport { handleError } from \"../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../lib/output.js\";\n\nexport const logoutCommand = new Command(\"logout\")\n\t.description(\"Log out from WaniWani\")\n\t.action(async (_, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tif (!(await auth.isLoggedIn())) {\n\t\t\t\tif (json) {\n\t\t\t\t\tformatOutput({ alreadyLoggedOut: true }, true);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(\"Not currently logged in.\");\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Clear auth tokens only (keep config like apiUrl intact)\n\t\t\tawait auth.clear();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ success: true }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(\"You have been logged out.\", false);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport { deleteCommand } from \"./delete.js\";\nimport { fileCommand } from \"./file/index.js\";\nimport { initCommand } from \"./init.js\";\nimport { listCommand } from \"./list.js\";\nimport { logsCommand } from \"./logs.js\";\nimport { previewCommand } from \"./preview.js\";\nimport { publishCommand } from \"./publish.js\";\nimport { runCommandCommand } from \"./run-command.js\";\nimport { statusCommand } from \"./status.js\";\nimport { stopCommand } from \"./stop.js\";\nimport { syncCommand } from \"./sync.js\";\nimport { useCommand } from \"./use.js\";\n\nexport const mcpCommand = new Command(\"mcp\")\n\t.description(\"MCP management commands\")\n\t.addCommand(initCommand)\n\t.addCommand(listCommand)\n\t.addCommand(useCommand)\n\t.addCommand(statusCommand)\n\t.addCommand(previewCommand)\n\t.addCommand(stopCommand)\n\t.addCommand(logsCommand)\n\t.addCommand(syncCommand)\n\t.addCommand(publishCommand)\n\t.addCommand(deleteCommand)\n\t.addCommand(fileCommand)\n\t.addCommand(runCommandCommand);\n","import { confirm } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { requireMcpId } from \"../../lib/utils.js\";\nimport type { McpRepository } from \"../../types/index.js\";\n\nexport const deleteCommand = new Command(\"delete\")\n\t.description(\"Delete the MCP (includes all associated resources)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--force\", \"Skip confirmation prompt\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst mcpId = await requireMcpId(options.mcpId);\n\n\t\t\t// Get MCP details for confirmation\n\t\t\tconst mcp = await api.get<McpRepository>(\n\t\t\t\t`/api/mcp/repositories/${mcpId}`,\n\t\t\t);\n\n\t\t\t// Require confirmation unless --force\n\t\t\tif (!options.force && !json) {\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(chalk.yellow(\"This will permanently delete:\"));\n\t\t\t\tconsole.log(` - MCP: ${mcp.name}`);\n\t\t\t\tif (mcp.activeSandbox) {\n\t\t\t\t\tconsole.log(\" - Active sandbox\");\n\t\t\t\t}\n\t\t\t\tconsole.log();\n\n\t\t\t\tconst confirmed = await confirm({\n\t\t\t\t\tmessage: `Delete \"${mcp.name}\"?`,\n\t\t\t\t\tdefault: false,\n\t\t\t\t});\n\n\t\t\t\tif (!confirmed) {\n\t\t\t\t\tconsole.log(\"Cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Deleting MCP...\").start();\n\t\t\tawait api.delete(`/api/mcp/repositories/${mcpId}`);\n\t\t\tspinner.succeed(\"MCP deleted\");\n\n\t\t\t// Clear active MCP and session if it was the one we deleted\n\t\t\tif ((await config.getMcpId()) === mcpId) {\n\t\t\t\tawait config.setMcpId(null);\n\t\t\t\tawait config.setSessionId(null);\n\t\t\t}\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ deleted: mcpId }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(\"MCP deleted.\", false);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { auth } from \"./auth.js\";\nimport { config } from \"./config.js\";\nimport { AuthError, CLIError } from \"./errors.js\";\n\nexport interface ApiResponse<T> {\n\tsuccess: boolean;\n\tdata?: T;\n\terror?: {\n\t\tcode: string;\n\t\tmessage: string;\n\t\tdetails?: Record<string, unknown>;\n\t};\n}\n\nexport class ApiError extends CLIError {\n\tconstructor(\n\t\tmessage: string,\n\t\tcode: string,\n\t\tpublic statusCode: number,\n\t\tdetails?: Record<string, unknown>,\n\t) {\n\t\tsuper(message, code, details);\n\t\tthis.name = \"ApiError\";\n\t}\n}\n\nasync function request<T>(\n\tmethod: string,\n\tpath: string,\n\toptions?: {\n\t\tbody?: unknown;\n\t\trequireAuth?: boolean;\n\t\theaders?: Record<string, string>;\n\t},\n): Promise<T> {\n\tconst {\n\t\tbody,\n\t\trequireAuth = true,\n\t\theaders: extraHeaders = {},\n\t} = options || {};\n\n\tconst headers: Record<string, string> = {\n\t\t\"Content-Type\": \"application/json\",\n\t\t...extraHeaders,\n\t};\n\n\tif (requireAuth) {\n\t\tconst token = await auth.getAccessToken();\n\t\tif (!token) {\n\t\t\tthrow new AuthError(\n\t\t\t\t\"Not logged in. Run 'waniwani login' to authenticate.\",\n\t\t\t);\n\t\t}\n\t\theaders.Authorization = `Bearer ${token}`;\n\t}\n\n\tconst baseUrl = await config.getApiUrl();\n\tconst url = `${baseUrl}${path}`;\n\n\tconst response = await fetch(url, {\n\t\tmethod,\n\t\theaders,\n\t\tbody: body ? JSON.stringify(body) : undefined,\n\t});\n\n\t// Handle empty responses (204 No Content)\n\tif (response.status === 204) {\n\t\treturn undefined as T;\n\t}\n\n\tlet data: ApiResponse<T>;\n\tlet rawBody: string | undefined;\n\n\ttry {\n\t\trawBody = await response.text();\n\t\tdata = JSON.parse(rawBody) as ApiResponse<T>;\n\t} catch {\n\t\t// JSON parsing failed - use raw body as error message\n\t\tthrow new ApiError(\n\t\t\trawBody || `Request failed with status ${response.status}`,\n\t\t\t\"API_ERROR\",\n\t\t\tresponse.status,\n\t\t\t{ statusText: response.statusText },\n\t\t);\n\t}\n\n\tif (!response.ok || data.error) {\n\t\t// Try to extract error message from various possible response formats\n\t\tconst errorMessage =\n\t\t\tdata.error?.message ||\n\t\t\t(data as unknown as { message?: string }).message ||\n\t\t\t(data as unknown as { error?: string }).error ||\n\t\t\trawBody ||\n\t\t\t`Request failed with status ${response.status}`;\n\n\t\tconst errorCode =\n\t\t\tdata.error?.code ||\n\t\t\t(data as unknown as { code?: string }).code ||\n\t\t\t\"API_ERROR\";\n\n\t\tconst errorDetails = {\n\t\t\t...data.error?.details,\n\t\t\tstatusText: response.statusText,\n\t\t\t...(data.error ? {} : { rawResponse: data }),\n\t\t};\n\n\t\tconst error = {\n\t\t\tcode: errorCode,\n\t\t\tmessage: errorMessage,\n\t\t\tdetails: errorDetails,\n\t\t};\n\n\t\t// Handle token expiration\n\t\tif (response.status === 401) {\n\t\t\tconst refreshed = await auth.tryRefreshToken();\n\t\t\tif (refreshed) {\n\t\t\t\t// Retry with new token\n\t\t\t\treturn request<T>(method, path, options);\n\t\t\t}\n\t\t\tthrow new AuthError(\n\t\t\t\t\"Session expired. Run 'waniwani login' to re-authenticate.\",\n\t\t\t);\n\t\t}\n\n\t\tthrow new ApiError(\n\t\t\terror.message,\n\t\t\terror.code,\n\t\t\tresponse.status,\n\t\t\terror.details,\n\t\t);\n\t}\n\n\treturn data.data as T;\n}\n\nexport const api = {\n\tget: <T>(path: string, options?: { requireAuth?: boolean }) =>\n\t\trequest<T>(\"GET\", path, options),\n\n\tpost: <T>(\n\t\tpath: string,\n\t\tbody?: unknown,\n\t\toptions?: { requireAuth?: boolean; headers?: Record<string, string> },\n\t) => request<T>(\"POST\", path, { body, ...options }),\n\n\tdelete: <T>(path: string, options?: { requireAuth?: boolean }) =>\n\t\trequest<T>(\"DELETE\", path, options),\n\n\tgetBaseUrl: () => config.getApiUrl(),\n};\n","import { config } from \"./config.js\";\nimport { McpError } from \"./errors.js\";\n\n/**\n * Requires an MCP ID, falling back to the active MCP from config.\n * Throws McpError if no MCP is available.\n */\nexport async function requireMcpId(mcpId?: string): Promise<string> {\n\tif (mcpId) return mcpId;\n\n\tconst configMcpId = await config.getMcpId();\n\tif (!configMcpId) {\n\t\tthrow new McpError(\n\t\t\t\"No active MCP. Run 'waniwani mcp init <name>' or 'waniwani mcp use <name>'.\",\n\t\t);\n\t}\n\treturn configMcpId;\n}\n\n/**\n * Get the active session ID from config.\n * Throws McpError if no session ID is stored.\n */\nexport async function requireSessionId(): Promise<string> {\n\tconst sessionId = await config.getSessionId();\n\n\tif (!sessionId) {\n\t\tthrow new McpError(\n\t\t\t\"No active session. Run 'waniwani mcp preview' to start development.\",\n\t\t);\n\t}\n\n\treturn sessionId;\n}\n\n/**\n * Binary file extensions that should be base64 encoded\n */\nconst BINARY_EXTENSIONS = new Set([\n\t\".png\",\n\t\".jpg\",\n\t\".jpeg\",\n\t\".gif\",\n\t\".ico\",\n\t\".webp\",\n\t\".svg\",\n\t\".woff\",\n\t\".woff2\",\n\t\".ttf\",\n\t\".eot\",\n\t\".otf\",\n\t\".zip\",\n\t\".tar\",\n\t\".gz\",\n\t\".pdf\",\n\t\".exe\",\n\t\".dll\",\n\t\".so\",\n\t\".dylib\",\n\t\".bin\",\n\t\".mp3\",\n\t\".mp4\",\n\t\".wav\",\n\t\".ogg\",\n\t\".webm\",\n]);\n\n/**\n * Check if a file path is likely a binary file based on extension\n */\nexport function isBinaryPath(filePath: string): boolean {\n\tconst ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n\treturn BINARY_EXTENSIONS.has(ext);\n}\n\n/**\n * Detect if a buffer contains binary data by checking for null bytes\n */\nexport function detectBinary(buffer: Buffer): boolean {\n\t// Check first 8KB for null bytes\n\tconst sample = buffer.subarray(0, 8192);\n\treturn sample.includes(0);\n}\n","import { Command } from \"commander\";\nimport { listCommand } from \"./list.js\";\nimport { readCommand } from \"./read.js\";\nimport { writeCommand } from \"./write.js\";\n\nexport const fileCommand = new Command(\"file\")\n\t.description(\"File operations in MCP sandbox\")\n\t.addCommand(readCommand)\n\t.addCommand(writeCommand)\n\t.addCommand(listCommand);\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../../lib/api.js\";\nimport { handleError } from \"../../../lib/errors.js\";\nimport { formatOutput, formatTable } from \"../../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../../lib/utils.js\";\nimport type { ListFilesResponse } from \"../../../types/index.js\";\n\nexport const listCommand = new Command(\"list\")\n\t.description(\"List files in the MCP sandbox\")\n\t.argument(\"[path]\", \"Directory path (defaults to /app)\", \"/app\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (path: string, options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst spinner = ora(`Listing ${path}...`).start();\n\n\t\t\tconst result = await api.get<ListFilesResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/files/list?path=${encodeURIComponent(path)}`,\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\tconsole.log(chalk.bold(`\\nDirectory: ${result.path}\\n`));\n\n\t\t\t\tif (result.entries.length === 0) {\n\t\t\t\t\tconsole.log(\" (empty)\");\n\t\t\t\t} else {\n\t\t\t\t\tconst rows = result.entries.map((entry) => {\n\t\t\t\t\t\tconst name =\n\t\t\t\t\t\t\tentry.type === \"directory\"\n\t\t\t\t\t\t\t\t? chalk.blue(`${entry.name}/`)\n\t\t\t\t\t\t\t\t: entry.name;\n\t\t\t\t\t\tconst size =\n\t\t\t\t\t\t\tentry.type === \"directory\"\n\t\t\t\t\t\t\t\t? chalk.gray(\"<dir>\")\n\t\t\t\t\t\t\t\t: formatSize(entry.size);\n\t\t\t\t\t\treturn [name, size];\n\t\t\t\t\t});\n\n\t\t\t\t\tformatTable([\"Name\", \"Size\"], rows, false);\n\t\t\t\t}\n\t\t\t\tconsole.log();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nfunction formatSize(bytes?: number): string {\n\tif (bytes === undefined) return \"\";\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../../lib/api.js\";\nimport { handleError, McpError } from \"../../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../../lib/utils.js\";\nimport type { ReadFileResponse } from \"../../../types/index.js\";\n\nexport const readCommand = new Command(\"read\")\n\t.description(\"Read a file from the MCP sandbox\")\n\t.argument(\"<path>\", \"Path in sandbox (e.g., /app/src/index.ts)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--output <file>\", \"Write to local file instead of stdout\")\n\t.option(\"--base64\", \"Output as base64 (for binary files)\")\n\t.action(async (path: string, options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst encoding = options.base64 ? \"base64\" : \"utf8\";\n\t\t\tconst spinner = ora(`Reading ${path}...`).start();\n\n\t\t\tconst result = await api.get<ReadFileResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/files?path=${encodeURIComponent(path)}&encoding=${encoding}`,\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\tif (!result.exists) {\n\t\t\t\tthrow new McpError(`File not found: ${path}`);\n\t\t\t}\n\n\t\t\tif (options.output) {\n\t\t\t\t// Write to local file\n\t\t\t\tconst buffer =\n\t\t\t\t\tresult.encoding === \"base64\"\n\t\t\t\t\t\t? Buffer.from(result.content, \"base64\")\n\t\t\t\t\t\t: Buffer.from(result.content, \"utf8\");\n\t\t\t\tawait writeFile(options.output, buffer);\n\t\t\t\tif (json) {\n\t\t\t\t\tformatOutput({ path, savedTo: options.output }, true);\n\t\t\t\t} else {\n\t\t\t\t\tformatSuccess(`Saved to ${options.output}`, false);\n\t\t\t\t}\n\t\t\t} else if (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\t// Print to stdout\n\t\t\t\tprocess.stdout.write(result.content);\n\t\t\t\t// Add newline if content doesn't end with one\n\t\t\t\tif (!result.content.endsWith(\"\\n\")) {\n\t\t\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { readFile } from \"node:fs/promises\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../../lib/api.js\";\nimport { CLIError, handleError } from \"../../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../../lib/utils.js\";\nimport type { WriteFilesResponse } from \"../../../types/index.js\";\n\nexport const writeCommand = new Command(\"write\")\n\t.description(\"Write a file to the MCP sandbox\")\n\t.argument(\"<path>\", \"Path in sandbox (e.g., /app/src/index.ts)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--content <content>\", \"Content to write\")\n\t.option(\"--file <localFile>\", \"Local file to upload\")\n\t.option(\"--base64\", \"Treat content as base64 encoded\")\n\t.action(async (path: string, options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\t// Get content from --content or --file\n\t\t\tlet content: string;\n\t\t\tlet encoding: \"utf8\" | \"base64\" = \"utf8\";\n\n\t\t\tif (options.content) {\n\t\t\t\tcontent = options.content;\n\t\t\t\tif (options.base64) {\n\t\t\t\t\tencoding = \"base64\";\n\t\t\t\t}\n\t\t\t} else if (options.file) {\n\t\t\t\tconst fileBuffer = await readFile(options.file);\n\t\t\t\tif (options.base64) {\n\t\t\t\t\tcontent = fileBuffer.toString(\"base64\");\n\t\t\t\t\tencoding = \"base64\";\n\t\t\t\t} else {\n\t\t\t\t\tcontent = fileBuffer.toString(\"utf8\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"Either --content or --file is required\",\n\t\t\t\t\t\"MISSING_CONTENT\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst spinner = ora(`Writing ${path}...`).start();\n\n\t\t\tconst result = await api.post<WriteFilesResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/files`,\n\t\t\t\t{\n\t\t\t\t\tfiles: [{ path, content, encoding }],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tspinner.succeed(`Wrote ${path}`);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(`File written: ${path}`, false);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { existsSync, mkdirSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport {\n\tCONFIG_FILE_NAME,\n\tinitConfigAt,\n\tLOCAL_CONFIG_DIR,\n} from \"../../lib/config.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { pullFilesFromGithub } from \"../../lib/sync.js\";\nimport type { McpRepository } from \"../../types/index.js\";\n\n/**\n * Load parent .waniwani/settings.json if it exists.\n * Copies all settings including auth tokens, but excludes mcpId (new project gets its own).\n */\nasync function loadParentConfig(\n\tcwd: string,\n): Promise<Record<string, unknown> | null> {\n\tconst parentConfigPath = join(cwd, LOCAL_CONFIG_DIR, CONFIG_FILE_NAME);\n\tif (!existsSync(parentConfigPath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst content = await readFile(parentConfigPath, \"utf-8\");\n\t\tconst config = JSON.parse(content);\n\t\t// Remove mcpId from parent - the new project gets its own\n\t\t// Keep auth tokens so user doesn't need to re-login\n\t\tconst { mcpId: _, sessionId: __, ...rest } = config;\n\t\treturn rest;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport const initCommand = new Command(\"init\")\n\t.description(\"Create a new MCP project\")\n\t.argument(\"<name>\", \"Name for the MCP project\")\n\t.action(async (name: string, _options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst cwd = process.cwd();\n\t\t\tconst projectDir = join(cwd, name);\n\n\t\t\t// Check if directory already exists\n\t\t\tif (existsSync(projectDir)) {\n\t\t\t\tif (json) {\n\t\t\t\t\tformatOutput(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\terror: `Directory \"${name}\" already exists`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(`Error: Directory \"${name}\" already exists`);\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Create repository on backend (GitHub repo created immediately)\n\t\t\tconst spinner = ora(\"Creating MCP...\").start();\n\n\t\t\tconst result = await api.post<McpRepository>(\"/api/mcp/repositories\", {\n\t\t\t\tname,\n\t\t\t});\n\n\t\t\t// Create local project directory\n\t\t\tmkdirSync(projectDir, { recursive: true });\n\n\t\t\t// Create .waniwani/settings.json with mcpId\n\t\t\tconst parentConfig = await loadParentConfig(cwd);\n\t\t\tawait initConfigAt(projectDir, {\n\t\t\t\t...parentConfig,\n\t\t\t\tmcpId: result.id,\n\t\t\t});\n\n\t\t\tspinner.succeed(\"MCP project created\");\n\n\t\t\t// Pull template files\n\t\t\tspinner.start(\"Pulling template files...\");\n\t\t\tconst syncResult = await pullFilesFromGithub(result.id, projectDir);\n\t\t\tspinner.succeed(`Pulled ${syncResult.count} files`);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(\n\t\t\t\t\t{\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tprojectDir,\n\t\t\t\t\t\tmcpId: result.id,\n\t\t\t\t\t\tfiles: syncResult.files,\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t\tformatSuccess(`MCP \"${name}\" created!`, false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Next steps:\");\n\t\t\t\tconsole.log(` cd ${name}`);\n\t\t\t\tconsole.log(\" waniwani mcp preview # Start developing\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative } from \"node:path\";\nimport ignore from \"ignore\";\nimport type { PullFilesResponse } from \"../types/index.js\";\nimport { api } from \"./api.js\";\nimport { detectBinary, isBinaryPath } from \"./utils.js\";\n\nconst PROJECT_DIR = \".waniwani\";\n\n/**\n * Find the project root by walking up from the given directory\n * looking for a .waniwani directory\n */\nexport async function findProjectRoot(\n\tstartDir: string,\n): Promise<string | null> {\n\tlet current = startDir;\n\tconst root = dirname(current);\n\n\twhile (current !== root) {\n\t\tif (existsSync(join(current, PROJECT_DIR))) {\n\t\t\treturn current;\n\t\t}\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) break;\n\t\tcurrent = parent;\n\t}\n\n\t// Check root as well\n\tif (existsSync(join(current, PROJECT_DIR))) {\n\t\treturn current;\n\t}\n\n\treturn null;\n}\n\n/**\n * Default patterns to always ignore\n */\nconst DEFAULT_IGNORE_PATTERNS = [\n\t\".waniwani\",\n\t\".git\",\n\t\"node_modules\",\n\t\".env\",\n\t\".env.*\",\n\t\".DS_Store\",\n\t\"*.log\",\n\t\".cache\",\n\t\"dist\",\n\t\"coverage\",\n\t\".turbo\",\n\t\".next\",\n\t\".nuxt\",\n\t\".vercel\",\n];\n\n/**\n * Load ignore patterns from .gitignore and add defaults\n */\nexport async function loadIgnorePatterns(\n\tprojectRoot: string,\n): Promise<ReturnType<typeof ignore>> {\n\tconst ig = ignore();\n\n\t// Add default patterns\n\tig.add(DEFAULT_IGNORE_PATTERNS);\n\n\t// Load .gitignore if it exists\n\tconst gitignorePath = join(projectRoot, \".gitignore\");\n\tif (existsSync(gitignorePath)) {\n\t\ttry {\n\t\t\tconst content = await readFile(gitignorePath, \"utf-8\");\n\t\t\tig.add(content);\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn ig;\n}\n\nexport interface FileToSync {\n\tpath: string;\n\tcontent: string;\n\tencoding: \"utf8\" | \"base64\";\n}\n\n/**\n * Collect all files in a directory that should be synced\n * Respects .gitignore and default ignore patterns\n */\nexport async function collectFiles(projectRoot: string): Promise<FileToSync[]> {\n\tconst ig = await loadIgnorePatterns(projectRoot);\n\tconst files: FileToSync[] = [];\n\n\tasync function walk(dir: string) {\n\t\tconst entries = await readdir(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(dir, entry.name);\n\t\t\tconst relativePath = relative(projectRoot, fullPath);\n\n\t\t\t// Check if path is ignored\n\t\t\tif (ig.ignores(relativePath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tawait walk(fullPath);\n\t\t\t} else if (entry.isFile()) {\n\t\t\t\ttry {\n\t\t\t\t\tconst content = await readFile(fullPath);\n\t\t\t\t\tconst isBinary = isBinaryPath(fullPath) || detectBinary(content);\n\n\t\t\t\t\tfiles.push({\n\t\t\t\t\t\tpath: relativePath,\n\t\t\t\t\t\tcontent: isBinary\n\t\t\t\t\t\t\t? content.toString(\"base64\")\n\t\t\t\t\t\t\t: content.toString(\"utf8\"),\n\t\t\t\t\t\tencoding: isBinary ? \"base64\" : \"utf8\",\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\t// Skip files that can't be read\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tawait walk(projectRoot);\n\treturn files;\n}\n\n/**\n * Pull all files from GitHub to a local directory.\n * Uses a single API call to fetch all files from the repository.\n */\nexport async function pullFilesFromGithub(\n\tmcpId: string,\n\ttargetDir: string,\n): Promise<{ count: number; files: string[] }> {\n\t// Fetch all files from GitHub in one request\n\tconst result = await api.get<PullFilesResponse>(\n\t\t`/api/mcp/repositories/${mcpId}/files`,\n\t);\n\n\tconst writtenFiles: string[] = [];\n\n\tfor (const file of result.files) {\n\t\tconst localPath = join(targetDir, file.path);\n\t\tconst dir = dirname(localPath);\n\n\t\t// Ensure directory exists\n\t\tawait mkdir(dir, { recursive: true });\n\n\t\t// Write file content\n\t\tif (file.encoding === \"base64\") {\n\t\t\tawait writeFile(localPath, Buffer.from(file.content, \"base64\"));\n\t\t} else {\n\t\t\tawait writeFile(localPath, file.content, \"utf8\");\n\t\t}\n\n\t\twrittenFiles.push(file.path);\n\t}\n\n\treturn { count: writtenFiles.length, files: writtenFiles };\n}\n\n/**\n * Collect a single file for syncing\n */\nexport async function collectSingleFile(\n\tprojectRoot: string,\n\tfilePath: string,\n): Promise<FileToSync | null> {\n\tconst fullPath = join(projectRoot, filePath);\n\tconst relativePath = relative(projectRoot, fullPath);\n\n\t// Check if file exists\n\tif (!existsSync(fullPath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst fileStat = await stat(fullPath);\n\t\tif (!fileStat.isFile()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst content = await readFile(fullPath);\n\t\tconst isBinary = isBinaryPath(fullPath) || detectBinary(content);\n\n\t\treturn {\n\t\t\tpath: relativePath,\n\t\t\tcontent: isBinary ? content.toString(\"base64\") : content.toString(\"utf8\"),\n\t\t\tencoding: isBinary ? \"base64\" : \"utf8\",\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatTable } from \"../../lib/output.js\";\nimport type {\n\tMcpRepository,\n\tMcpRepositoryListResponse,\n} from \"../../types/index.js\";\n\nexport const listCommand = new Command(\"list\")\n\t.description(\"List all MCPs in your organization\")\n\t.action(async (_, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst spinner = ora(\"Fetching MCPs...\").start();\n\n\t\t\tconst mcps = await api.get<McpRepositoryListResponse>(\n\t\t\t\t\"/api/mcp/repositories\",\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\tconst activeMcpId = await config.getMcpId();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(\n\t\t\t\t\t{\n\t\t\t\t\t\tmcps: mcps.map((m: McpRepository) => ({\n\t\t\t\t\t\t\t...m,\n\t\t\t\t\t\t\tisActive: m.id === activeMcpId,\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tactiveMcpId,\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tif (mcps.length === 0) {\n\t\t\t\t\tconsole.log(\"No MCPs found.\");\n\t\t\t\t\tconsole.log(\"\\nCreate a new MCP: waniwani mcp init <name>\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconsole.log(chalk.bold(\"\\nMCPs:\\n\"));\n\n\t\t\t\tconst rows = mcps.map((m: McpRepository) => {\n\t\t\t\t\tconst isActive = m.id === activeMcpId;\n\t\t\t\t\tconst deployStatus = m.deployedAt\n\t\t\t\t\t\t? chalk.green(\"Deployed\")\n\t\t\t\t\t\t: chalk.yellow(\"Pending\");\n\t\t\t\t\tconst sandboxStatus = m.activeSandbox\n\t\t\t\t\t\t? chalk.green(\"Active\")\n\t\t\t\t\t\t: chalk.gray(\"None\");\n\t\t\t\t\tconst lastDeploy = m.deployedAt\n\t\t\t\t\t\t? new Date(m.deployedAt).toLocaleDateString()\n\t\t\t\t\t\t: chalk.gray(\"Never\");\n\n\t\t\t\t\treturn [\n\t\t\t\t\t\tisActive ? chalk.cyan(`* ${m.name}`) : ` ${m.name}`,\n\t\t\t\t\t\tdeployStatus,\n\t\t\t\t\t\tsandboxStatus,\n\t\t\t\t\t\tlastDeploy,\n\t\t\t\t\t];\n\t\t\t\t});\n\n\t\t\t\tformatTable([\"Name\", \"Status\", \"Sandbox\", \"Last Deploy\"], rows, false);\n\n\t\t\t\tconsole.log();\n\t\t\t\tif (activeMcpId) {\n\t\t\t\t\tconst activeMcp = mcps.find((m) => m.id === activeMcpId);\n\t\t\t\t\tif (activeMcp) {\n\t\t\t\t\t\tconsole.log(`Active MCP: ${chalk.cyan(activeMcp.name)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconsole.log(\"\\nSelect an MCP: waniwani mcp use <name>\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { auth } from \"../../lib/auth.js\";\nimport { AuthError, handleError, McpError } from \"../../lib/errors.js\";\nimport { formatOutput } from \"../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../lib/utils.js\";\nimport type { LogEvent, ServerStatusResponse } from \"../../types/index.js\";\n\nexport const logsCommand = new Command(\"logs\")\n\t.description(\"Stream logs from the MCP server\")\n\t.argument(\"[cmdId]\", \"Command ID (defaults to running server)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"-f, --follow\", \"Keep streaming logs (default)\", true)\n\t.option(\"--no-follow\", \"Fetch logs and exit\")\n\t.action(async (cmdIdArg: string | undefined, options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\tlet reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n\n\t\t// Handle Ctrl+C gracefully\n\t\tconst cleanup = () => {\n\t\t\tif (reader) {\n\t\t\t\treader.cancel().catch(() => {});\n\t\t\t}\n\t\t\tprocess.exit(0);\n\t\t};\n\t\tprocess.on(\"SIGINT\", cleanup);\n\t\tprocess.on(\"SIGTERM\", cleanup);\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst token = await auth.getAccessToken();\n\t\t\tif (!token) {\n\t\t\t\tthrow new AuthError(\n\t\t\t\t\t\"Not logged in. Run 'waniwani login' to authenticate.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet cmdId = cmdIdArg;\n\n\t\t\t// If no cmdId provided, get it from server status\n\t\t\tif (!cmdId) {\n\t\t\t\tconst spinner = ora(\"Getting server status...\").start();\n\t\t\t\tconst status = await api.post<ServerStatusResponse>(\n\t\t\t\t\t`/api/mcp/sessions/${sessionId}/server`,\n\t\t\t\t\t{ action: \"status\" },\n\t\t\t\t);\n\t\t\t\tspinner.stop();\n\n\t\t\t\tif (!status.running || !status.cmdId) {\n\t\t\t\t\tthrow new McpError(\n\t\t\t\t\t\t\"No server is running. Run 'waniwani mcp preview' first.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcmdId = status.cmdId;\n\t\t\t}\n\n\t\t\tconst baseUrl = await api.getBaseUrl();\n\t\t\tconst streamParam = options.follow ? \"?stream=true\" : \"\";\n\t\t\tconst url = `${baseUrl}/api/mcp/sessions/${sessionId}/commands/${cmdId}${streamParam}`;\n\n\t\t\tif (!json) {\n\t\t\t\tconsole.log(chalk.gray(`Streaming logs for command ${cmdId}...`));\n\t\t\t\tconsole.log(chalk.gray(\"Press Ctrl+C to stop\\n\"));\n\t\t\t}\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"GET\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\t\tAccept: options.follow ? \"text/event-stream\" : \"application/json\",\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst error = await response\n\t\t\t\t\t.json()\n\t\t\t\t\t.catch(() => ({ message: response.statusText }));\n\t\t\t\tthrow new Error(\n\t\t\t\t\terror.message || `Request failed with status ${response.status}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Non-streaming mode\n\t\t\tif (!options.follow) {\n\t\t\t\tconst data = await response.json();\n\t\t\t\tif (json) {\n\t\t\t\t\tformatOutput(data, true);\n\t\t\t\t} else {\n\t\t\t\t\tif (data.stdout) {\n\t\t\t\t\t\tprocess.stdout.write(data.stdout);\n\t\t\t\t\t}\n\t\t\t\t\tif (data.stderr) {\n\t\t\t\t\t\tprocess.stderr.write(chalk.red(data.stderr));\n\t\t\t\t\t}\n\t\t\t\t\tif (data.exitCode !== undefined) {\n\t\t\t\t\t\tconsole.log(chalk.gray(`\\nExit code: ${data.exitCode}`));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Streaming mode\n\t\t\treader = response.body?.getReader();\n\t\t\tif (!reader) {\n\t\t\t\tthrow new Error(\"No response body\");\n\t\t\t}\n\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = \"\";\n\t\t\tconst collectedLogs: LogEvent[] = [];\n\n\t\t\twhile (true) {\n\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\tif (done) break;\n\n\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\t\tbuffer = lines.pop() || \"\";\n\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tif (line.startsWith(\"event: \")) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (line.startsWith(\"data: \")) {\n\t\t\t\t\t\tconst data = line.slice(6);\n\t\t\t\t\t\tif (!data || data === \"[DONE]\") continue;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst event = JSON.parse(data) as LogEvent;\n\t\t\t\t\t\t\tcollectedLogs.push(event);\n\n\t\t\t\t\t\t\tif (json) {\n\t\t\t\t\t\t\t\t// In JSON mode, we'll output at the end\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Handle different event types\n\t\t\t\t\t\t\tif (event.cmdId) {\n\t\t\t\t\t\t\t\t// Initial event with cmdId\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (event.stream && event.data !== undefined) {\n\t\t\t\t\t\t\t\tif (event.stream === \"stdout\") {\n\t\t\t\t\t\t\t\t\tprocess.stdout.write(event.data);\n\t\t\t\t\t\t\t\t} else if (event.stream === \"stderr\") {\n\t\t\t\t\t\t\t\t\tprocess.stderr.write(chalk.red(event.data));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (event.exitCode !== undefined) {\n\t\t\t\t\t\t\t\tconst exitColor =\n\t\t\t\t\t\t\t\t\tevent.exitCode === 0 ? chalk.green : chalk.red;\n\t\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\t\texitColor(`\\nProcess exited with code ${event.exitCode}`),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (event.error) {\n\t\t\t\t\t\t\t\tconsole.error(chalk.red(`\\nError: ${event.error}`));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Ignore malformed JSON\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Output collected logs in JSON mode\n\t\t\tif (json) {\n\t\t\t\tformatOutput(collectedLogs, true);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t} finally {\n\t\t\tprocess.off(\"SIGINT\", cleanup);\n\t\t\tprocess.off(\"SIGTERM\", cleanup);\n\t\t}\n\t});\n","import { watch } from \"chokidar\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatSuccess } from \"../../lib/output.js\";\nimport {\n\tcollectFiles,\n\tcollectSingleFile,\n\tfindProjectRoot,\n\tloadIgnorePatterns,\n} from \"../../lib/sync.js\";\nimport type {\n\tMcpSandbox,\n\tSandboxStartResponse,\n\tWriteFilesResponse,\n} from \"../../types/index.js\";\n\nexport const previewCommand = new Command(\"preview\")\n\t.description(\"Start live development with sandbox and file watching\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--no-watch\", \"Skip file watching\")\n\t.option(\"--no-logs\", \"Don't stream logs to terminal\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\t// Find project root and MCP ID\n\t\t\tconst projectRoot = await findProjectRoot(process.cwd());\n\t\t\tif (!projectRoot) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"Not in a WaniWani project. Run 'waniwani mcp init <name>' first.\",\n\t\t\t\t\t\"NOT_IN_PROJECT\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet mcpId = options.mcpId;\n\t\t\tif (!mcpId) {\n\t\t\t\tmcpId = await config.getMcpId();\n\t\t\t}\n\t\t\tif (!mcpId) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"No MCP found. Run 'waniwani mcp init <name>' or use --mcp-id.\",\n\t\t\t\t\t\"NO_MCP\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Starting development environment...\").start();\n\n\t\t\t// Step 1: Create or get session (this also starts the sandbox)\n\t\t\tspinner.text = \"Starting session...\";\n\t\t\tlet sessionId: string;\n\t\t\tlet previewUrl: string;\n\t\t\ttry {\n\t\t\t\tconst sessionResponse = await api.post<SandboxStartResponse>(\n\t\t\t\t\t`/api/mcp/repositories/${mcpId}/session`,\n\t\t\t\t\t{},\n\t\t\t\t);\n\t\t\t\tsessionId = sessionResponse.sandbox.id;\n\t\t\t\tpreviewUrl = sessionResponse.previewUrl;\n\t\t\t} catch {\n\t\t\t\t// Session might already exist, try to get it\n\t\t\t\tconst existing = await api.get<McpSandbox | null>(\n\t\t\t\t\t`/api/mcp/repositories/${mcpId}/session`,\n\t\t\t\t);\n\t\t\t\tif (!existing) {\n\t\t\t\t\tthrow new CLIError(\"Failed to start session\", \"SESSION_ERROR\");\n\t\t\t\t}\n\t\t\t\tsessionId = existing.id;\n\t\t\t\tpreviewUrl = existing.previewUrl;\n\t\t\t}\n\n\t\t\t// Store session ID in config\n\t\t\tawait config.setSessionId(sessionId);\n\n\t\t\t// Step 2: Sync current files to sandbox\n\t\t\tspinner.text = \"Syncing files to sandbox...\";\n\t\t\tconst files = await collectFiles(projectRoot);\n\t\t\tif (files.length > 0) {\n\t\t\t\tawait api.post<WriteFilesResponse>(\n\t\t\t\t\t`/api/mcp/sessions/${sessionId}/files`,\n\t\t\t\t\t{ files },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tspinner.succeed(\"Development environment ready\");\n\n\t\t\tconsole.log();\n\t\t\tformatSuccess(\"Live preview started!\", false);\n\t\t\tconsole.log();\n\t\t\tconsole.log(` Preview URL: ${previewUrl}`);\n\t\t\tconsole.log();\n\t\t\tconsole.log(` MCP Inspector:`);\n\t\t\tconsole.log(\n\t\t\t\t` npx @anthropic-ai/mcp-inspector@latest \"${previewUrl}/mcp\"`,\n\t\t\t);\n\t\t\tconsole.log();\n\n\t\t\tif (options.watch !== false) {\n\t\t\t\tconsole.log(\"Watching for file changes... (Ctrl+C to stop)\");\n\t\t\t\tconsole.log();\n\n\t\t\t\t// Step 4: Start file watcher\n\t\t\t\tconst ig = await loadIgnorePatterns(projectRoot);\n\n\t\t\t\tconst watcher = watch(projectRoot, {\n\t\t\t\t\tignored: (path) => {\n\t\t\t\t\t\t// Get relative path from project root\n\t\t\t\t\t\tconst relative = path.replace(`${projectRoot}/`, \"\");\n\t\t\t\t\t\tif (relative === path) return false; // Don't ignore the root\n\t\t\t\t\t\treturn ig.ignores(relative);\n\t\t\t\t\t},\n\t\t\t\t\tpersistent: true,\n\t\t\t\t\tignoreInitial: true,\n\t\t\t\t\tawaitWriteFinish: {\n\t\t\t\t\t\tstabilityThreshold: 100,\n\t\t\t\t\t\tpollInterval: 50,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tconst syncFile = async (filePath: string) => {\n\t\t\t\t\tconst relativePath = filePath.replace(`${projectRoot}/`, \"\");\n\t\t\t\t\tconst file = await collectSingleFile(projectRoot, relativePath);\n\t\t\t\t\tif (file) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait api.post<WriteFilesResponse>(\n\t\t\t\t\t\t\t\t`/api/mcp/sessions/${sessionId}/files`,\n\t\t\t\t\t\t\t\t{ files: [file] },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tconsole.log(` Synced: ${relativePath}`);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tconsole.error(` Failed to sync: ${relativePath}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\twatcher.on(\"add\", syncFile);\n\t\t\t\twatcher.on(\"change\", syncFile);\n\t\t\t\twatcher.on(\"unlink\", (filePath) => {\n\t\t\t\t\tconst relativePath = filePath.replace(`${projectRoot}/`, \"\");\n\t\t\t\t\tconsole.log(` Deleted: ${relativePath}`);\n\t\t\t\t});\n\n\t\t\t\t// Handle Ctrl+C gracefully\n\t\t\t\tprocess.on(\"SIGINT\", async () => {\n\t\t\t\t\tconsole.log();\n\t\t\t\t\tconsole.log(\"Stopping development environment...\");\n\t\t\t\t\tawait watcher.close();\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t});\n\n\t\t\t\t// Keep the process running\n\t\t\t\tawait new Promise(() => {});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { collectFiles, findProjectRoot } from \"../../lib/sync.js\";\nimport { requireMcpId } from \"../../lib/utils.js\";\nimport type { DeployToGithubResponse } from \"../../types/index.js\";\n\nexport const publishCommand = new Command(\"publish\")\n\t.description(\"Push local files to GitHub and trigger deployment\")\n\t.option(\"-m, --message <msg>\", \"Commit message\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst mcpId = await requireMcpId(options.mcpId);\n\n\t\t\t// Find project root\n\t\t\tconst projectRoot = await findProjectRoot(process.cwd());\n\t\t\tif (!projectRoot) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"Not in a WaniWani project. Run 'waniwani mcp init <name>' first.\",\n\t\t\t\t\t\"NOT_IN_PROJECT\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get commit message\n\t\t\tlet message = options.message;\n\t\t\tif (!message) {\n\t\t\t\tmessage = await input({\n\t\t\t\t\tmessage: \"Commit message:\",\n\t\t\t\t\tvalidate: (value) =>\n\t\t\t\t\t\tvalue.trim() ? true : \"Commit message is required\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Collecting files...\").start();\n\n\t\t\t// Collect all files from the project\n\t\t\tconst files = await collectFiles(projectRoot);\n\n\t\t\tif (files.length === 0) {\n\t\t\t\tspinner.fail(\"No files to deploy\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tspinner.text = `Pushing ${files.length} files to GitHub...`;\n\n\t\t\tconst result = await api.post<DeployToGithubResponse>(\n\t\t\t\t`/api/mcp/repositories/${mcpId}/deploy`,\n\t\t\t\t{ files, message },\n\t\t\t);\n\n\t\t\tspinner.succeed(`Pushed to GitHub (${result.commitSha.slice(0, 7)})`);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t\tformatSuccess(\"Files pushed to GitHub!\", false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Deployment will start automatically via webhook.\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput } from \"../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../lib/utils.js\";\nimport type { RunCommandResponse } from \"../../types/index.js\";\n\nexport const runCommandCommand = new Command(\"run-command\")\n\t.description(\"Run a command in the MCP sandbox\")\n\t.argument(\"<command>\", \"Command to run\")\n\t.argument(\"[args...]\", \"Command arguments\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.option(\"--cwd <path>\", \"Working directory\")\n\t.option(\n\t\t\"--timeout <ms>\",\n\t\t\"Command timeout in milliseconds (default: 30000, max: 300000)\",\n\t)\n\t.action(async (cmd: string, args: string[], options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst timeout = options.timeout\n\t\t\t\t? Number.parseInt(options.timeout, 10)\n\t\t\t\t: undefined;\n\n\t\t\tconst spinner = ora(`Running: ${cmd} ${args.join(\" \")}`.trim()).start();\n\n\t\t\tconst result = await api.post<RunCommandResponse>(\n\t\t\t\t`/api/mcp/sessions/${sessionId}/commands`,\n\t\t\t\t{\n\t\t\t\t\tcommand: cmd,\n\t\t\t\t\targs: args.length > 0 ? args : undefined,\n\t\t\t\t\tcwd: options.cwd,\n\t\t\t\t\ttimeout,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(result, true);\n\t\t\t} else {\n\t\t\t\t// Show command\n\t\t\t\tconst cmdLine = [cmd, ...args].join(\" \");\n\t\t\t\tconsole.log(chalk.gray(`$ ${cmdLine}`));\n\t\t\t\tconsole.log();\n\n\t\t\t\t// Show stdout\n\t\t\t\tif (result.stdout) {\n\t\t\t\t\tprocess.stdout.write(result.stdout);\n\t\t\t\t\tif (!result.stdout.endsWith(\"\\n\")) {\n\t\t\t\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Show stderr\n\t\t\t\tif (result.stderr) {\n\t\t\t\t\tprocess.stderr.write(chalk.red(result.stderr));\n\t\t\t\t\tif (!result.stderr.endsWith(\"\\n\")) {\n\t\t\t\t\t\tprocess.stderr.write(\"\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Show exit code and duration\n\t\t\t\tconsole.log();\n\t\t\t\tconst exitColor = result.exitCode === 0 ? chalk.green : chalk.red;\n\t\t\t\tconsole.log(\n\t\t\t\t\texitColor(`Exit code: ${result.exitCode}`),\n\t\t\t\t\tchalk.gray(`(${(result.duration / 1000).toFixed(2)}s)`),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Exit with the command's exit code\n\t\t\tif (result.exitCode !== 0) {\n\t\t\t\tprocess.exit(result.exitCode);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatList, formatOutput } from \"../../lib/output.js\";\nimport { requireMcpId } from \"../../lib/utils.js\";\nimport type { McpRepository, ServerStatusResponse } from \"../../types/index.js\";\n\nexport const statusCommand = new Command(\"status\")\n\t.description(\"Show current MCP status\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst mcpId = await requireMcpId(options.mcpId);\n\n\t\t\tconst spinner = ora(\"Fetching MCP status...\").start();\n\n\t\t\tconst result = await api.get<McpRepository>(\n\t\t\t\t`/api/mcp/repositories/${mcpId}`,\n\t\t\t);\n\n\t\t\t// Fetch server status if sandbox is active\n\t\t\tlet serverStatus: ServerStatusResponse | null = null;\n\t\t\tif (result.activeSandbox) {\n\t\t\t\tserverStatus = await api\n\t\t\t\t\t.post<ServerStatusResponse>(\n\t\t\t\t\t\t`/api/mcp/sessions/${result.activeSandbox.id}/server`,\n\t\t\t\t\t\t{ action: \"status\" },\n\t\t\t\t\t)\n\t\t\t\t\t.catch(() => null);\n\t\t\t}\n\n\t\t\tspinner.stop();\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ ...result, server: serverStatus }, true);\n\t\t\t} else {\n\t\t\t\tconst deployStatus = result.deployedAt\n\t\t\t\t\t? chalk.green(\"Deployed\")\n\t\t\t\t\t: chalk.yellow(\"Pending\");\n\n\t\t\t\tconst items = [\n\t\t\t\t\t{ label: \"Name\", value: result.name },\n\t\t\t\t\t{ label: \"MCP ID\", value: result.id },\n\t\t\t\t\t{ label: \"Status\", value: deployStatus },\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Last Deploy\",\n\t\t\t\t\t\tvalue: result.deployedAt\n\t\t\t\t\t\t\t? new Date(result.deployedAt).toLocaleString()\n\t\t\t\t\t\t\t: chalk.gray(\"Never\"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Created\",\n\t\t\t\t\t\tvalue: new Date(result.createdAt).toLocaleString(),\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\t// Add sandbox info if active\n\t\t\t\tif (result.activeSandbox) {\n\t\t\t\t\tconst sandbox = result.activeSandbox;\n\t\t\t\t\tconst serverRunning = serverStatus?.running ?? sandbox.serverRunning;\n\t\t\t\t\tconst serverStatusColor = serverRunning ? chalk.green : chalk.yellow;\n\n\t\t\t\t\titems.push(\n\t\t\t\t\t\t{ label: \"\", value: \"\" }, // Separator\n\t\t\t\t\t\t{ label: \"Sandbox\", value: chalk.green(\"Active\") },\n\t\t\t\t\t\t{ label: \"Preview URL\", value: sandbox.previewUrl },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Server\",\n\t\t\t\t\t\t\tvalue: serverStatusColor(serverRunning ? \"Running\" : \"Stopped\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Expires\",\n\t\t\t\t\t\t\tvalue: sandbox.expiresAt\n\t\t\t\t\t\t\t\t? new Date(sandbox.expiresAt).toLocaleString()\n\t\t\t\t\t\t\t\t: chalk.gray(\"N/A\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\titems.push(\n\t\t\t\t\t\t{ label: \"\", value: \"\" }, // Separator\n\t\t\t\t\t\t{ label: \"Sandbox\", value: chalk.gray(\"None\") },\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tformatList(items, false);\n\n\t\t\t\tconsole.log();\n\t\t\t\tif (!result.activeSandbox) {\n\t\t\t\t\tconsole.log(\"Start development: waniwani mcp preview\");\n\t\t\t\t} else if (!serverStatus?.running) {\n\t\t\t\t\tconsole.log(\"View logs: waniwani mcp logs\");\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { requireMcpId, requireSessionId } from \"../../lib/utils.js\";\n\nexport const stopCommand = new Command(\"stop\")\n\t.description(\"Stop the development environment (sandbox + server)\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tawait requireMcpId(options.mcpId);\n\t\t\tconst sessionId = await requireSessionId();\n\n\t\t\tconst spinner = ora(\"Stopping development environment...\").start();\n\n\t\t\t// Stop server first\n\t\t\ttry {\n\t\t\t\tawait api.post(`/api/mcp/sessions/${sessionId}/server`, {\n\t\t\t\t\taction: \"stop\",\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\t// Server might not be running, continue\n\t\t\t}\n\n\t\t\t// Delete session\n\t\t\tawait api.delete(`/api/mcp/sessions/${sessionId}`);\n\n\t\t\t// Clear session from config\n\t\t\tawait config.setSessionId(null);\n\n\t\t\tspinner.succeed(\"Development environment stopped\");\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ stopped: true }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(\"Sandbox stopped.\", false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Start again: waniwani mcp preview\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport { findProjectRoot, pullFilesFromGithub } from \"../../lib/sync.js\";\nimport { requireMcpId } from \"../../lib/utils.js\";\n\nexport const syncCommand = new Command(\"sync\")\n\t.description(\"Pull template files to local project\")\n\t.option(\"--mcp-id <id>\", \"Specific MCP ID\")\n\t.action(async (options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst mcpId = await requireMcpId(options.mcpId);\n\n\t\t\t// Find project root\n\t\t\tconst projectRoot = await findProjectRoot(process.cwd());\n\t\t\tif (!projectRoot) {\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t\"Not in a WaniWani project. Run 'waniwani mcp init <name>' first.\",\n\t\t\t\t\t\"NOT_IN_PROJECT\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst spinner = ora(\"Pulling files...\").start();\n\n\t\t\tconst result = await pullFilesFromGithub(mcpId, projectRoot);\n\n\t\t\tspinner.succeed(`Pulled ${result.count} files`);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ files: result.files }, true);\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t\tformatSuccess(\"Files synced!\", false);\n\t\t\t\tif (result.files.length > 0 && result.files.length <= 10) {\n\t\t\t\t\tconsole.log();\n\t\t\t\t\tfor (const file of result.files) {\n\t\t\t\t\t\tconsole.log(` ${file}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { handleError, McpError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport type {\n\tMcpRepository,\n\tMcpRepositoryListResponse,\n} from \"../../types/index.js\";\n\nexport const useCommand = new Command(\"use\")\n\t.description(\"Select an MCP to use for subsequent commands\")\n\t.argument(\"<name>\", \"Name of the MCP to use\")\n\t.action(async (name: string, _options, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst spinner = ora(\"Fetching MCPs...\").start();\n\n\t\t\t// Fetch all MCPs\n\t\t\tconst mcps = await api.get<McpRepositoryListResponse>(\n\t\t\t\t\"/api/mcp/repositories\",\n\t\t\t);\n\n\t\t\tspinner.stop();\n\n\t\t\t// Find MCP by name\n\t\t\tconst mcp = mcps.find((m: McpRepository) => m.name === name);\n\n\t\t\tif (!mcp) {\n\t\t\t\tthrow new McpError(\n\t\t\t\t\t`MCP \"${name}\" not found. Run 'waniwani mcp list' to see available MCPs.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tawait config.setMcpId(mcp.id);\n\t\t\t// Clear session since we're switching MCPs\n\t\t\tawait config.setSessionId(null);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ selected: mcp }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(`Now using MCP \"${name}\"`, false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(` MCP ID: ${mcp.id}`);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Next steps:\");\n\t\t\t\tconsole.log(\" waniwani mcp preview # Start live preview\");\n\t\t\t\tconsole.log(\" waniwani mcp status # Check status\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport { listCommand } from \"./list.js\";\nimport { switchCommand } from \"./switch.js\";\n\nexport const orgCommand = new Command(\"org\")\n\t.description(\"Organization management commands\")\n\t.addCommand(listCommand)\n\t.addCommand(switchCommand);\n","import chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatTable } from \"../../lib/output.js\";\nimport type { Org, OrgListResponse } from \"../../types/index.js\";\n\nexport const listCommand = new Command(\"list\")\n\t.description(\"List your organizations\")\n\t.action(async (_, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst spinner = ora(\"Fetching organizations...\").start();\n\n\t\t\tconst result = await api.get<OrgListResponse>(\"/api/oauth/orgs\");\n\n\t\t\tspinner.stop();\n\n\t\t\tconst { orgs, activeOrgId } = result;\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput(\n\t\t\t\t\t{\n\t\t\t\t\t\torgs: orgs.map((o: Org) => ({\n\t\t\t\t\t\t\t...o,\n\t\t\t\t\t\t\tisActive: o.id === activeOrgId,\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tactiveOrgId,\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tif (orgs.length === 0) {\n\t\t\t\t\tconsole.log(\"No organizations found.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconsole.log(chalk.bold(\"\\nOrganizations:\\n\"));\n\n\t\t\t\tconst rows = orgs.map((o: Org) => {\n\t\t\t\t\tconst isActive = o.id === activeOrgId;\n\t\t\t\t\treturn [\n\t\t\t\t\t\tisActive ? chalk.cyan(`* ${o.name}`) : ` ${o.name}`,\n\t\t\t\t\t\to.slug,\n\t\t\t\t\t\to.role,\n\t\t\t\t\t];\n\t\t\t\t});\n\n\t\t\t\tformatTable([\"Name\", \"Slug\", \"Role\"], rows, false);\n\n\t\t\t\tconsole.log();\n\t\t\t\tif (activeOrgId) {\n\t\t\t\t\tconst activeOrg = orgs.find((o: Org) => o.id === activeOrgId);\n\t\t\t\t\tif (activeOrg) {\n\t\t\t\t\t\tconsole.log(`Active organization: ${chalk.cyan(activeOrg.name)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconsole.log(\"\\nSwitch organization: waniwani org switch <name>\");\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { Command } from \"commander\";\nimport ora from \"ora\";\nimport { api } from \"../../lib/api.js\";\nimport { config } from \"../../lib/config.js\";\nimport { CLIError, handleError } from \"../../lib/errors.js\";\nimport { formatOutput, formatSuccess } from \"../../lib/output.js\";\nimport type {\n\tOrg,\n\tOrgListResponse,\n\tOrgSwitchResponse,\n} from \"../../types/index.js\";\n\nexport const switchCommand = new Command(\"switch\")\n\t.description(\"Switch to a different organization\")\n\t.argument(\"<name>\", \"Name or slug of the organization to switch to\")\n\t.action(async (name: string, _, command) => {\n\t\tconst globalOptions = command.optsWithGlobals();\n\t\tconst json = globalOptions.json ?? false;\n\n\t\ttry {\n\t\t\tconst spinner = ora(\"Fetching organizations...\").start();\n\n\t\t\t// First fetch orgs to find the org ID\n\t\t\tconst { orgs } = await api.get<OrgListResponse>(\"/api/oauth/orgs\");\n\n\t\t\t// Find org by name or slug\n\t\t\tconst org = orgs.find((o: Org) => o.name === name || o.slug === name);\n\n\t\t\tif (!org) {\n\t\t\t\tspinner.stop();\n\t\t\t\tthrow new CLIError(\n\t\t\t\t\t`Organization \"${name}\" not found. Run 'waniwani org list' to see available organizations.`,\n\t\t\t\t\t\"ORG_NOT_FOUND\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tspinner.text = \"Switching organization...\";\n\n\t\t\t// Switch to the org\n\t\t\tawait api.post<OrgSwitchResponse>(\"/api/oauth/orgs/switch\", {\n\t\t\t\torgId: org.id,\n\t\t\t});\n\n\t\t\tspinner.succeed(\"Organization switched\");\n\n\t\t\t// Clear local MCP selection since we switched orgs\n\t\t\tconfig.setMcpId(null);\n\n\t\t\tif (json) {\n\t\t\t\tformatOutput({ switched: org }, true);\n\t\t\t} else {\n\t\t\t\tformatSuccess(`Switched to organization \"${org.name}\"`, false);\n\t\t\t\tconsole.log();\n\t\t\t\tconsole.log(\"Note: Active MCP selection has been cleared.\");\n\t\t\t\tconsole.log(\n\t\t\t\t\t\"Run 'waniwani mcp list' to see MCPs in this organization.\",\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\thandleError(error, json);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n","import { program } from \"./cli.js\";\n\nprogram.parse(process.argv);\n"],"mappings":"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","names":["Command","Command","existsSync","join","chalk","chalk","join","existsSync","Command","chalk","Command","Command","chalk","Command","Command","Command","chalk","Command","ora","Command","chalk","ora","Command","chalk","Command","ora","Command","ora","chalk","writeFile","Command","ora","Command","ora","writeFile","readFile","Command","ora","Command","readFile","ora","Command","existsSync","readFile","join","Command","ora","existsSync","mkdir","readFile","writeFile","join","existsSync","join","readFile","mkdir","writeFile","join","existsSync","readFile","config","Command","ora","chalk","Command","ora","listCommand","Command","ora","chalk","chalk","Command","ora","Command","ora","chalk","Command","ora","Command","ora","relative","Command","ora","Command","ora","chalk","Command","ora","Command","ora","chalk","chalk","Command","ora","Command","ora","chalk","Command","ora","Command","ora","Command","ora","Command","ora","Command","ora","Command","ora","Command","listCommand","Command","chalk","Command","ora","listCommand","Command","ora","chalk","Command","ora","Command","ora","Command","listCommand","require","Command"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waniwani/cli",
3
- "version": "0.0.38",
3
+ "version": "0.0.39",
4
4
  "description": "WaniWani CLI for MCP development workflow",
5
5
  "type": "module",
6
6
  "exports": {