@tostudy-ai/mcp-setup 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2018,7 +2018,7 @@ var IDE_DETECTION_RULES = [
2018
2018
  envVars: ["VSCODE_PID", "VSCODE_IPC_HOOK"]
2019
2019
  }
2020
2020
  ];
2021
- async function detectRunningIDE() {
2021
+ function detectRunningIDE() {
2022
2022
  for (const rule of IDE_DETECTION_RULES) {
2023
2023
  if (rule.envVars.some((envVar) => process.env[envVar] !== void 0)) {
2024
2024
  return {
@@ -2044,7 +2044,7 @@ import * as childProcess from "child_process";
2044
2044
  // ../mcp-cli-core/src/detect-workspace.ts
2045
2045
  import { existsSync as existsSync12 } from "fs";
2046
2046
  import { join as join9 } from "path";
2047
- async function detectWorkspaceScenario(cwd) {
2047
+ function detectWorkspaceScenario(cwd) {
2048
2048
  const hasAgentsMd = existsSync12(join9(cwd, "AGENTS.md")) || existsSync12(join9(cwd, "CLAUDE.md"));
2049
2049
  const hasCursorRules = existsSync12(join9(cwd, ".cursor", "rules"));
2050
2050
  const hasCopilotInstructions = existsSync12(join9(cwd, ".github", "copilot-instructions.md"));
@@ -2219,6 +2219,10 @@ function renderForIDE(content, ide, scenario) {
2219
2219
  }
2220
2220
 
2221
2221
  // src/commands/shared.ts
2222
+ function println4(message = "") {
2223
+ process.stdout.write(`${message}
2224
+ `);
2225
+ }
2222
2226
  var COURSE_ID_COMMENT_PREFIX = "<!-- tostudy-course-id:";
2223
2227
  var DEFAULT_AVAILABLE_TOOLS = [
2224
2228
  { command: "start_module", description: "Carrega o pr\xF3ximo m\xF3dulo", category: "learning" },
@@ -2271,6 +2275,22 @@ async function fetchCourses(apiKey, platformUrl) {
2271
2275
  }
2272
2276
  }
2273
2277
  async function fetchCourseContext(courseId, apiKey, platformUrl) {
2278
+ try {
2279
+ const baseUrl = platformUrl.replace(/\/$/, "");
2280
+ const response = await fetch(`${baseUrl}/api/mcp/courses/${courseId}`, {
2281
+ headers: {
2282
+ Authorization: `Bearer ${apiKey}`,
2283
+ "Content-Type": "application/json"
2284
+ }
2285
+ });
2286
+ if (response.ok) {
2287
+ const data = await response.json();
2288
+ if (data.course) {
2289
+ return normalizeCourseContext(data.course);
2290
+ }
2291
+ }
2292
+ } catch {
2293
+ }
2274
2294
  const courses = await fetchCourses(apiKey, platformUrl);
2275
2295
  return courses.find((course) => course.id === courseId) ?? null;
2276
2296
  }
@@ -2303,10 +2323,6 @@ function resolveDetectedIde(ide) {
2303
2323
  }
2304
2324
 
2305
2325
  // src/commands/init.ts
2306
- function println4(message = "") {
2307
- process.stdout.write(`${message}
2308
- `);
2309
- }
2310
2326
  async function runInit(options, dependencies = {}) {
2311
2327
  const cwd = dependencies.cwd ?? process.cwd();
2312
2328
  const detectRunningIDE2 = dependencies.detectRunningIDE ?? detectRunningIDE;
@@ -2384,10 +2400,6 @@ async function runInit(options, dependencies = {}) {
2384
2400
  import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
2385
2401
  import { dirname as dirname10, join as join11 } from "path";
2386
2402
  import chalk5 from "chalk";
2387
- function println5(message = "") {
2388
- process.stdout.write(`${message}
2389
- `);
2390
- }
2391
2403
  var INSTRUCTION_CANDIDATES = [
2392
2404
  "AGENTS.md",
2393
2405
  ".tostudy/AGENTS.md",
@@ -2412,14 +2424,14 @@ async function runSync(options, dependencies = {}) {
2412
2424
  const fetchCourse = dependencies.fetchCourse ?? fetchCourseContext;
2413
2425
  const existing = findExistingInstruction(cwd);
2414
2426
  if (!existing) {
2415
- println5(
2427
+ println4(
2416
2428
  chalk5.yellow(' Nenhum arquivo ToStudy encontrado. Rode "tostudy-mcp-setup init" primeiro.')
2417
2429
  );
2418
2430
  return { ok: false, reason: "instruction_missing" };
2419
2431
  }
2420
2432
  const courseId = options.courseId ?? extractCourseId(existing.content);
2421
2433
  if (!courseId) {
2422
- println5(
2434
+ println4(
2423
2435
  chalk5.yellow(
2424
2436
  ' Metadata do curso ausente. Rode "tostudy-mcp-setup init --course <id>" novamente.'
2425
2437
  )
@@ -2429,7 +2441,7 @@ async function runSync(options, dependencies = {}) {
2429
2441
  const mode = await detectInstructionMode(options.apiKey, options.platformUrl, verify);
2430
2442
  const course = await fetchCourse(courseId, options.apiKey, options.platformUrl);
2431
2443
  if (!course) {
2432
- println5(chalk5.red(` N\xE3o foi poss\xEDvel sincronizar o curso ${courseId}.`));
2444
+ println4(chalk5.red(` N\xE3o foi poss\xEDvel sincronizar o curso ${courseId}.`));
2433
2445
  return { ok: false, reason: "course_not_found" };
2434
2446
  }
2435
2447
  const target = inferInstructionTarget(existing.relativePath);
@@ -2445,7 +2457,7 @@ async function runSync(options, dependencies = {}) {
2445
2457
  const outputPath = join11(cwd, rendered.filePath);
2446
2458
  mkdirSync10(dirname10(outputPath), { recursive: true });
2447
2459
  writeFileSync10(outputPath, rendered.content, "utf-8");
2448
- println5(chalk5.green(` \u2713 ${rendered.filePath} sincronizado`));
2460
+ println4(chalk5.green(` \u2713 ${rendered.filePath} sincronizado`));
2449
2461
  return {
2450
2462
  ok: true,
2451
2463
  outputPath,
@@ -2458,7 +2470,7 @@ async function runSync(options, dependencies = {}) {
2458
2470
  var VERSION = "1.3.0";
2459
2471
  var DEFAULT_PLATFORM_URL2 = "https://tostudy.ai";
2460
2472
  var OAUTH_PORT = 9877;
2461
- function println6(message = "") {
2473
+ function println5(message = "") {
2462
2474
  process.stdout.write(`${message}
2463
2475
  `);
2464
2476
  }
@@ -2467,13 +2479,13 @@ function eprintln(message = "") {
2467
2479
  `);
2468
2480
  }
2469
2481
  function printBanner() {
2470
- println6();
2471
- println6(chalk6.cyan(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2472
- println6(
2482
+ println5();
2483
+ println5(chalk6.cyan(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2484
+ println5(
2473
2485
  chalk6.cyan(" \u2551") + chalk6.white.bold(" ToStudy MCP Setup ") + chalk6.cyan("\u2551")
2474
2486
  );
2475
- println6(chalk6.cyan(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2476
- println6();
2487
+ println5(chalk6.cyan(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2488
+ println5();
2477
2489
  }
2478
2490
  async function validateApiKey(apiKey, platformUrl) {
2479
2491
  try {
@@ -2487,8 +2499,8 @@ async function validateApiKey(apiKey, platformUrl) {
2487
2499
  });
2488
2500
  return response.ok || response.status === 204;
2489
2501
  } catch {
2490
- println6(chalk6.yellow("! N\xE3o foi poss\xEDvel validar a API key (servidor offline?)"));
2491
- println6(chalk6.yellow(" A configura\xE7\xE3o ser\xE1 salva mesmo assim."));
2502
+ println5(chalk6.yellow("! N\xE3o foi poss\xEDvel validar a API key (servidor offline?)"));
2503
+ println5(chalk6.yellow(" A configura\xE7\xE3o ser\xE1 salva mesmo assim."));
2492
2504
  return true;
2493
2505
  }
2494
2506
  }
@@ -2509,16 +2521,16 @@ async function configureIDEs(token, platformUrl) {
2509
2521
  const allDetected = await detectInstalledIDEs();
2510
2522
  const installedIDEs = allDetected.filter((h) => h.id !== "manual");
2511
2523
  if (installedIDEs.length === 0) {
2512
- println6(chalk6.yellow(" Nenhuma IDE suportada detectada."));
2513
- println6(chalk6.gray(" Use: npx @tostudy-ai/mcp-setup install --ide <nome> --key <token>"));
2524
+ println5(chalk6.yellow(" Nenhuma IDE suportada detectada."));
2525
+ println5(chalk6.gray(" Use: npx @tostudy-ai/mcp-setup install --ide <nome> --key <token>"));
2514
2526
  return 0;
2515
2527
  }
2516
- println6(chalk6.white(" IDEs detectadas:\n"));
2528
+ println5(chalk6.white(" IDEs detectadas:\n"));
2517
2529
  for (let i = 0; i < installedIDEs.length; i++) {
2518
- println6(` ${chalk6.cyan(String(i + 1))}. ${installedIDEs[i].name}`);
2530
+ println5(` ${chalk6.cyan(String(i + 1))}. ${installedIDEs[i].name}`);
2519
2531
  }
2520
- println6(` ${chalk6.cyan("a")}. Todas`);
2521
- println6();
2532
+ println5(` ${chalk6.cyan("a")}. Todas`);
2533
+ println5();
2522
2534
  const answer = await prompt(
2523
2535
  " Quais configurar? (n\xFAmeros separados por v\xEDrgula, ou 'a' para todas) "
2524
2536
  );
@@ -2529,17 +2541,17 @@ async function configureIDEs(token, platformUrl) {
2529
2541
  } else {
2530
2542
  const indices = trimmed.split(/[,\s]+/).map((s) => parseInt(s, 10) - 1).filter((i) => i >= 0 && i < installedIDEs.length);
2531
2543
  if (indices.length === 0) {
2532
- println6(chalk6.yellow(" Nenhuma IDE selecionada."));
2544
+ println5(chalk6.yellow(" Nenhuma IDE selecionada."));
2533
2545
  return 0;
2534
2546
  }
2535
2547
  selectedIDEs = indices.map((i) => installedIDEs[i]);
2536
2548
  }
2537
- println6();
2549
+ println5();
2538
2550
  const claudeCodeHandler = selectedIDEs.find((h) => h.id === "claude-code");
2539
2551
  let claudeCodeScope = "user";
2540
2552
  if (claudeCodeHandler) {
2541
2553
  claudeCodeScope = await promptClaudeCodeScope();
2542
- println6();
2554
+ println5();
2543
2555
  }
2544
2556
  let configured = 0;
2545
2557
  for (const handler of selectedIDEs) {
@@ -2550,10 +2562,10 @@ async function configureIDEs(token, platformUrl) {
2550
2562
  } else {
2551
2563
  await handler.writeConfig(token, mcpUrl);
2552
2564
  }
2553
- println6(chalk6.green("OK"));
2565
+ println5(chalk6.green("OK"));
2554
2566
  configured++;
2555
2567
  } catch (error) {
2556
- println6(chalk6.red("FALHOU"));
2568
+ println5(chalk6.red("FALHOU"));
2557
2569
  eprintln(chalk6.gray(` ${error instanceof Error ? error.message : String(error)}`));
2558
2570
  }
2559
2571
  }
@@ -2567,60 +2579,62 @@ async function writeClaudeCodeConfig(_handler, token, mcpUrl, scope) {
2567
2579
  execFileSync5("claude", removeArgs, { stdio: "ignore" });
2568
2580
  } catch {
2569
2581
  }
2570
- execFileSync5("claude", addArgs, { stdio: "inherit" });
2582
+ execFileSync5("claude", addArgs, { stdio: "pipe" });
2571
2583
  }
2572
2584
  function printSuccessBanner(configuredCount) {
2573
- println6();
2585
+ println5();
2574
2586
  if (configuredCount > 0) {
2575
- println6(chalk6.green(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2576
- println6(
2587
+ println5(chalk6.green(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2588
+ println5(
2577
2589
  chalk6.green(" \u2551") + chalk6.white.bold(
2578
2590
  ` ${configuredCount} IDE${configuredCount > 1 ? "s" : ""} configurada${configuredCount > 1 ? "s" : ""} com sucesso!`.padEnd(
2579
2591
  42
2580
2592
  )
2581
2593
  ) + chalk6.green("\u2551")
2582
2594
  );
2583
- println6(chalk6.green(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2595
+ println5(chalk6.green(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2584
2596
  } else {
2585
- println6(chalk6.yellow(" Nenhuma IDE foi configurada."));
2586
- println6(chalk6.gray(" Use: npx @tostudy-ai/mcp-setup install --ide <nome> --key <token>"));
2587
- }
2588
- println6();
2589
- println6(chalk6.white(NEXT_STEPS_TITLE));
2590
- println6(chalk6.gray(" 1.") + " Reinicie as IDEs configuradas");
2591
- println6(chalk6.gray(" 2.") + ASSISTANT_COURSES_PROMPT.trimStart());
2592
- println6();
2593
- println6(chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2594
- println6();
2595
- println6(chalk6.white(" Prefere estudar pelo terminal?"));
2596
- println6(chalk6.gray(" ") + chalk6.cyan("npm install -g @tostudy-ai/cli"));
2597
- println6(
2597
+ println5(chalk6.yellow(" Nenhuma IDE foi configurada."));
2598
+ println5(chalk6.gray(" Use: npx @tostudy-ai/mcp-setup install --ide <nome> --key <token>"));
2599
+ }
2600
+ println5();
2601
+ println5(chalk6.white(NEXT_STEPS_TITLE));
2602
+ println5(chalk6.gray(" 1.") + " Reinicie as IDEs configuradas");
2603
+ println5(chalk6.gray(" 2. ") + ASSISTANT_COURSES_PROMPT.trimStart());
2604
+ println5();
2605
+ println5(chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2606
+ println5();
2607
+ println5(chalk6.white(" Prefere estudar pelo terminal?"));
2608
+ println5(chalk6.gray(" ") + chalk6.cyan("npm install -g @tostudy-ai/cli@latest"));
2609
+ println5(
2598
2610
  chalk6.gray(" ") + chalk6.cyan("tostudy login") + chalk6.gray(" \u2192 ") + chalk6.cyan("tostudy courses")
2599
2611
  );
2600
- println6();
2612
+ println5();
2601
2613
  }
2602
2614
  async function setup(apiKey, platformUrl) {
2603
2615
  printBanner();
2604
2616
  const url = platformUrl || process.env.TOSTUDY_PLATFORM_URL || DEFAULT_PLATFORM_URL2;
2605
2617
  if (apiKey || process.env.TOSTUDY_API_KEY) {
2606
2618
  const key = apiKey || process.env.TOSTUDY_API_KEY;
2607
- println6(chalk6.yellow(` ${API_KEY_DEPRECATION_WARNING}`));
2608
- println6();
2609
- println6(chalk6.gray(" Usando API key fornecida..."));
2619
+ if (apiKey) {
2620
+ println5(chalk6.yellow(` ${API_KEY_DEPRECATION_WARNING}`));
2621
+ println5();
2622
+ }
2623
+ println5(chalk6.gray(" Usando API key fornecida..."));
2610
2624
  process.stdout.write(chalk6.gray(" Validando... "));
2611
2625
  const valid = await validateApiKey(key, url);
2612
2626
  if (!valid) {
2613
- println6(chalk6.red("FALHOU"));
2614
- println6(chalk6.red(" API key inv\xE1lida ou expirada."));
2627
+ println5(chalk6.red("FALHOU"));
2628
+ println5(chalk6.red(" API key inv\xE1lida ou expirada."));
2615
2629
  process.exit(1);
2616
2630
  }
2617
- println6(chalk6.green("OK"));
2618
- println6();
2631
+ println5(chalk6.green("OK"));
2632
+ println5();
2619
2633
  const configured2 = await configureIDEs(key, url);
2620
2634
  printSuccessBanner(configured2);
2621
2635
  return;
2622
2636
  }
2623
- println6(chalk6.gray(" Abrindo browser para autentica\xE7\xE3o...\n"));
2637
+ println5(chalk6.gray(" Abrindo browser para autentica\xE7\xE3o...\n"));
2624
2638
  let code;
2625
2639
  try {
2626
2640
  const serverPromise = startCallbackServer(OAUTH_PORT);
@@ -2629,8 +2643,8 @@ async function setup(apiKey, platformUrl) {
2629
2643
  const openArgs = process.platform === "win32" ? ["", authUrl] : [authUrl];
2630
2644
  execFile(openCmd, openArgs, (err) => {
2631
2645
  if (err) {
2632
- println6(chalk6.yellow(" N\xE3o foi poss\xEDvel abrir o browser automaticamente."));
2633
- println6(chalk6.gray(` Abra manualmente: ${authUrl}
2646
+ println5(chalk6.yellow(" N\xE3o foi poss\xEDvel abrir o browser automaticamente."));
2647
+ println5(chalk6.gray(` Abra manualmente: ${authUrl}
2634
2648
  `));
2635
2649
  }
2636
2650
  });
@@ -2648,144 +2662,146 @@ async function setup(apiKey, platformUrl) {
2648
2662
  const result = await exchangeCodeForToken(code, url, "mcp");
2649
2663
  token = result.token;
2650
2664
  userName = result.userName;
2651
- println6(chalk6.green("OK"));
2652
- println6(chalk6.green(` Logado como ${userName}
2665
+ println5(chalk6.green("OK"));
2666
+ println5(chalk6.green(` Logado como ${userName}
2653
2667
  `));
2654
2668
  } catch (err) {
2655
- println6(chalk6.red("FALHOU"));
2669
+ println5(chalk6.red("FALHOU"));
2656
2670
  eprintln(chalk6.red(` ${err instanceof Error ? err.message : String(err)}`));
2657
2671
  process.exit(1);
2658
2672
  }
2659
- println6(chalk6.gray(" Detectando IDEs...\n"));
2673
+ println5(chalk6.gray(" Detectando IDEs...\n"));
2660
2674
  const configured = await configureIDEs(token, url);
2661
2675
  printSuccessBanner(configured);
2662
2676
  }
2663
2677
  async function uninstall() {
2664
2678
  printBanner();
2665
2679
  if (!isTostudyMcpConfigured()) {
2666
- println6(chalk6.yellow("ToStudy MCP n\xE3o est\xE1 configurado."));
2680
+ println5(chalk6.yellow("ToStudy MCP n\xE3o est\xE1 configurado."));
2667
2681
  process.exit(0);
2668
2682
  }
2669
2683
  const shouldUninstall = await confirm("Remover configura\xE7\xE3o do ToStudy MCP?", false);
2670
2684
  if (!shouldUninstall) {
2671
- println6(chalk6.gray("Opera\xE7\xE3o cancelada."));
2685
+ println5(chalk6.gray("Opera\xE7\xE3o cancelada."));
2672
2686
  process.exit(0);
2673
2687
  }
2674
2688
  process.stdout.write(chalk6.gray("Removendo configura\xE7\xE3o... "));
2675
2689
  try {
2676
2690
  removeTostudyMcpServer();
2677
- println6(chalk6.green("OK"));
2678
- println6();
2679
- println6(chalk6.green("Configura\xE7\xE3o removida com sucesso."));
2680
- println6(chalk6.gray("Reinicie o Claude Code para aplicar as mudan\xE7as."));
2681
- println6();
2691
+ println5(chalk6.green("OK"));
2692
+ println5();
2693
+ println5(chalk6.green("Configura\xE7\xE3o removida com sucesso."));
2694
+ println5(chalk6.gray("Reinicie o Claude Code para aplicar as mudan\xE7as."));
2695
+ println5();
2682
2696
  } catch (error) {
2683
- println6(chalk6.red("FALHOU"));
2697
+ println5(chalk6.red("FALHOU"));
2684
2698
  eprintln(error instanceof Error ? error.message : String(error));
2685
2699
  process.exit(1);
2686
2700
  }
2687
2701
  }
2688
2702
  function printStep(step, total, title) {
2689
- println6();
2690
- println6(chalk6.cyan(`\u2501\u2501\u2501 Passo ${step}/${total}: ${title} \u2501\u2501\u2501`));
2691
- println6();
2703
+ println5();
2704
+ println5(chalk6.cyan(`\u2501\u2501\u2501 Passo ${step}/${total}: ${title} \u2501\u2501\u2501`));
2705
+ println5();
2692
2706
  }
2693
2707
  function printIDEDetection(installedIDEs) {
2694
2708
  if (installedIDEs.length === 0) {
2695
- println6(chalk6.yellow(" Nenhuma IDE suportada detectada."));
2696
- println6(chalk6.gray(" O setup continuar\xE1 para Claude Code."));
2709
+ println5(chalk6.yellow(" Nenhuma IDE suportada detectada."));
2710
+ println5(chalk6.gray(" O setup continuar\xE1 para Claude Code."));
2697
2711
  } else {
2698
- println6(chalk6.green(" IDEs detectadas:"));
2712
+ println5(chalk6.green(" IDEs detectadas:"));
2699
2713
  for (const ide of installedIDEs) {
2700
2714
  const version = ide.version ? chalk6.gray(` (${ide.version})`) : "";
2701
- println6(` ${chalk6.green("\u2713")} ${ide.name}${version}`);
2715
+ println5(` ${chalk6.green("\u2713")} ${ide.name}${version}`);
2702
2716
  }
2703
2717
  }
2704
2718
  }
2705
2719
  async function wizard(options) {
2706
2720
  const TOTAL_STEPS = 4;
2707
- println6();
2708
- println6(chalk6.cyan(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2709
- println6(
2721
+ println5();
2722
+ println5(chalk6.cyan(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2723
+ println5(
2710
2724
  chalk6.cyan(" \u2551") + chalk6.white.bold(" ToStudy MCP Setup Wizard ") + chalk6.cyan("\u2551")
2711
2725
  );
2712
- println6(
2726
+ println5(
2713
2727
  chalk6.cyan(" \u2551") + chalk6.gray(" Configura\xE7\xE3o guiada passo a passo ") + chalk6.cyan("\u2551")
2714
2728
  );
2715
- println6(chalk6.cyan(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2716
- println6();
2717
- println6(chalk6.gray(" Este assistente vai configurar o Claude Code para"));
2718
- println6(chalk6.gray(" conectar ao servidor MCP da plataforma ToStudy."));
2719
- println6();
2729
+ println5(chalk6.cyan(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2730
+ println5();
2731
+ println5(chalk6.gray(" Este assistente vai configurar o Claude Code para"));
2732
+ println5(chalk6.gray(" conectar ao servidor MCP da plataforma ToStudy."));
2733
+ println5();
2720
2734
  printStep(1, TOTAL_STEPS, "Detectando ambiente");
2721
2735
  process.stdout.write(" Verificando Claude Code... ");
2722
2736
  if (!isClaudeInstalled()) {
2723
- println6(chalk6.red("N\xC3O ENCONTRADO"));
2724
- println6();
2725
- println6(chalk6.red(" Claude Code n\xE3o est\xE1 instalado."));
2726
- println6();
2727
- println6(" Por favor, instale primeiro:");
2728
- println6(chalk6.cyan(" https://claude.ai/download"));
2729
- println6();
2737
+ println5(chalk6.red("N\xC3O ENCONTRADO"));
2738
+ println5();
2739
+ println5(chalk6.red(" Claude Code n\xE3o est\xE1 instalado."));
2740
+ println5();
2741
+ println5(" Por favor, instale primeiro:");
2742
+ println5(chalk6.cyan(" https://claude.ai/download"));
2743
+ println5();
2730
2744
  process.exit(1);
2731
2745
  }
2732
- println6(chalk6.green("OK"));
2746
+ println5(chalk6.green("OK"));
2733
2747
  const configPath = getClaudeConfigPath();
2734
- println6(chalk6.gray(` Config: ${configPath}`));
2748
+ println5(chalk6.gray(` Config: ${configPath}`));
2735
2749
  process.stdout.write(" Detectando IDEs... ");
2736
2750
  const installedIDEs = getInstalledIDEs();
2737
- println6(chalk6.green("OK"));
2751
+ println5(chalk6.green("OK"));
2738
2752
  printIDEDetection(installedIDEs);
2739
2753
  process.stdout.write(" Verificando configura\xE7\xE3o atual... ");
2740
2754
  const alreadyConfigured = isTostudyMcpConfigured();
2741
2755
  if (alreadyConfigured) {
2742
- println6(chalk6.yellow("J\xC1 CONFIGURADO"));
2743
- println6();
2756
+ println5(chalk6.yellow("J\xC1 CONFIGURADO"));
2757
+ println5();
2744
2758
  const overwrite = await confirm(" Deseja reconfigurar?", false);
2745
2759
  if (!overwrite) {
2746
- println6();
2747
- println6(chalk6.gray(" Opera\xE7\xE3o cancelada."));
2760
+ println5();
2761
+ println5(chalk6.gray(" Opera\xE7\xE3o cancelada."));
2748
2762
  process.exit(0);
2749
2763
  }
2750
2764
  } else {
2751
- println6(chalk6.gray("N\xE3o configurado"));
2765
+ println5(chalk6.gray("N\xE3o configurado"));
2752
2766
  }
2753
2767
  printStep(2, TOTAL_STEPS, "Configurando API Key");
2754
- println6(chalk6.gray(" A API key conecta o Claude Code a sua conta na plataforma."));
2755
- println6();
2768
+ println5(chalk6.gray(" A API key conecta o Claude Code a sua conta na plataforma."));
2769
+ println5();
2756
2770
  let apiKey = options.apiKey || process.env.TOSTUDY_API_KEY;
2757
2771
  if (!apiKey) {
2758
- println6(" Acesse sua API key em:");
2759
- println6(chalk6.cyan(` ${options.url || DEFAULT_PLATFORM_URL2}/student/settings/mcp`));
2760
- println6();
2772
+ println5(" Acesse sua API key em:");
2773
+ println5(chalk6.cyan(` ${options.url || DEFAULT_PLATFORM_URL2}/student/settings/mcp`));
2774
+ println5();
2761
2775
  apiKey = await promptApiKey();
2762
2776
  } else {
2763
- println6(chalk6.yellow(` ${API_KEY_DEPRECATION_WARNING}`));
2764
- println6();
2765
- println6(chalk6.green(" \u2713 API key fornecida via par\xE2metro ou ambiente"));
2777
+ if (options.apiKey) {
2778
+ println5(chalk6.yellow(` ${API_KEY_DEPRECATION_WARNING}`));
2779
+ println5();
2780
+ }
2781
+ println5(chalk6.green(" \u2713 API key fornecida via par\xE2metro ou ambiente"));
2766
2782
  }
2767
2783
  const platformUrl = options.url || process.env.TOSTUDY_PLATFORM_URL || DEFAULT_PLATFORM_URL2;
2768
- println6();
2784
+ println5();
2769
2785
  process.stdout.write(chalk6.gray(" Validando API key... "));
2770
2786
  const valid = await validateApiKey(apiKey, platformUrl);
2771
2787
  if (!valid) {
2772
- println6(chalk6.red("FALHOU"));
2773
- println6();
2774
- println6(chalk6.red(" API key inv\xE1lida ou expirada."));
2775
- println6();
2776
- println6(" Para gerar uma nova API key:");
2777
- println6(chalk6.cyan(` ${platformUrl}/student/settings/mcp`));
2778
- println6();
2788
+ println5(chalk6.red("FALHOU"));
2789
+ println5();
2790
+ println5(chalk6.red(" API key inv\xE1lida ou expirada."));
2791
+ println5();
2792
+ println5(" Para gerar uma nova API key:");
2793
+ println5(chalk6.cyan(` ${platformUrl}/student/settings/mcp`));
2794
+ println5();
2779
2795
  process.exit(1);
2780
2796
  }
2781
- println6(chalk6.green("OK"));
2797
+ println5(chalk6.green("OK"));
2782
2798
  printStep(3, TOTAL_STEPS, "Salvando configura\xE7\xE3o");
2783
2799
  process.stdout.write(" Configurando Claude Code... ");
2784
2800
  try {
2785
2801
  addTostudyMcpServer(apiKey, platformUrl);
2786
- println6(chalk6.green("OK"));
2802
+ println5(chalk6.green("OK"));
2787
2803
  } catch (error) {
2788
- println6(chalk6.red("FALHOU"));
2804
+ println5(chalk6.red("FALHOU"));
2789
2805
  eprintln();
2790
2806
  eprintln(chalk6.red(" Erro ao salvar configura\xE7\xE3o:"));
2791
2807
  eprintln(" " + (error instanceof Error ? error.message : String(error)));
@@ -2795,66 +2811,66 @@ async function wizard(options) {
2795
2811
  if (!options.skipDiagnostics) {
2796
2812
  process.stdout.write(" Executando diagn\xF3stico... ");
2797
2813
  const report = await runDiagnostics();
2798
- println6(chalk6.green("OK"));
2799
- println6();
2814
+ println5(chalk6.green("OK"));
2815
+ println5();
2800
2816
  const remainingIssues = report.issues.filter(
2801
2817
  (issue) => !["mcp-not-configured", "config-missing"].includes(issue.id)
2802
2818
  );
2803
2819
  if (remainingIssues.length > 0) {
2804
- println6(chalk6.yellow(" Avisos encontrados:"));
2820
+ println5(chalk6.yellow(" Avisos encontrados:"));
2805
2821
  for (const issue of remainingIssues) {
2806
2822
  const icon = issue.severity === "critical" ? chalk6.red("\u25CF") : issue.severity === "warning" ? chalk6.yellow("\u25CF") : chalk6.blue("\u25CF");
2807
- println6(` ${icon} ${issue.title}`);
2823
+ println5(` ${icon} ${issue.title}`);
2808
2824
  }
2809
- println6();
2825
+ println5();
2810
2826
  if (options.autoRepair) {
2811
2827
  process.stdout.write(" Tentando reparar automaticamente... ");
2812
2828
  const repairReport = repairAllIssues(report, apiKey, platformUrl);
2813
2829
  if (repairReport.repairsSucceeded > 0) {
2814
- println6(chalk6.green(`${repairReport.repairsSucceeded} corrigido(s)`));
2830
+ println5(chalk6.green(`${repairReport.repairsSucceeded} corrigido(s)`));
2815
2831
  } else {
2816
- println6(chalk6.yellow("Nenhum reparo aplicado"));
2832
+ println5(chalk6.yellow("Nenhum reparo aplicado"));
2817
2833
  }
2818
2834
  } else {
2819
- println6(
2835
+ println5(
2820
2836
  chalk6.gray(' Dica: Execute "npx @tostudy-ai/mcp-setup diagnose" para mais detalhes.')
2821
2837
  );
2822
2838
  }
2823
2839
  } else {
2824
- println6(chalk6.green(" \u2713 Nenhum problema encontrado!"));
2840
+ println5(chalk6.green(" \u2713 Nenhum problema encontrado!"));
2825
2841
  }
2826
2842
  } else {
2827
- println6(chalk6.gray(" Diagn\xF3stico ignorado (--skip-diagnostics)"));
2843
+ println5(chalk6.gray(" Diagn\xF3stico ignorado (--skip-diagnostics)"));
2828
2844
  }
2829
- println6();
2830
- println6(chalk6.green(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2831
- println6(
2845
+ println5();
2846
+ println5(chalk6.green(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2847
+ println5(
2832
2848
  chalk6.green(" \u2551") + chalk6.white.bold(" Configura\xE7\xE3o conclu\xEDda com sucesso! ") + chalk6.green("\u2551")
2833
2849
  );
2834
- println6(chalk6.green(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2835
- println6();
2836
- println6(chalk6.white(NEXT_STEPS_TITLE));
2837
- println6();
2838
- println6(chalk6.gray(" 1.") + " Reinicie o Claude Code");
2839
- println6(chalk6.gray(" 2.") + " O servidor MCP iniciar\xE1 automaticamente");
2840
- println6(chalk6.gray(" 3.") + COURSES_TOOL_HINT.trimStart());
2841
- println6();
2842
- println6(chalk6.gray(" Comandos \xFAteis:"));
2843
- println6(
2850
+ println5(chalk6.green(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2851
+ println5();
2852
+ println5(chalk6.white(NEXT_STEPS_TITLE));
2853
+ println5();
2854
+ println5(chalk6.gray(" 1.") + " Reinicie o Claude Code");
2855
+ println5(chalk6.gray(" 2.") + " O servidor MCP iniciar\xE1 automaticamente");
2856
+ println5(chalk6.gray(" 3. ") + COURSES_TOOL_HINT.trimStart());
2857
+ println5();
2858
+ println5(chalk6.gray(" Comandos \xFAteis:"));
2859
+ println5(
2844
2860
  chalk6.gray(" ") + chalk6.cyan("npx @tostudy-ai/mcp-setup diagnose") + chalk6.gray(" - Verificar problemas")
2845
2861
  );
2846
- println6(
2862
+ println5(
2847
2863
  chalk6.gray(" ") + chalk6.cyan("npx @tostudy-ai/mcp-setup repair") + chalk6.gray(" - Reparar automaticamente")
2848
2864
  );
2849
- println6();
2850
- println6(chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2851
- println6();
2852
- println6(chalk6.white(" Prefere estudar pelo terminal?"));
2853
- println6(chalk6.gray(" ") + chalk6.cyan("npm install -g @tostudy-ai/cli"));
2854
- println6(
2865
+ println5();
2866
+ println5(chalk6.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2867
+ println5();
2868
+ println5(chalk6.white(" Prefere estudar pelo terminal?"));
2869
+ println5(chalk6.gray(" ") + chalk6.cyan("npm install -g @tostudy-ai/cli@latest"));
2870
+ println5(
2855
2871
  chalk6.gray(" ") + chalk6.cyan("tostudy login") + chalk6.gray(" \u2192 ") + chalk6.cyan("tostudy courses")
2856
2872
  );
2857
- println6();
2873
+ println5();
2858
2874
  }
2859
2875
  program.name("tostudy-mcp-setup").description("Configura o Claude Code para usar o ToStudy MCP server").version(VERSION);
2860
2876
  program.option("-k, --api-key <key>", "(deprecated) API key \u2014 use OAuth flow instead").option("-u, --url <url>", "URL da plataforma (default: https://tostudy.ai)").option("--uninstall", "Remove a configura\xE7\xE3o do ToStudy MCP").action(async (options) => {
@@ -2888,7 +2904,7 @@ program.command("diagnose").description("Executa diagn\xF3stico de problemas na
2888
2904
  try {
2889
2905
  const report = await runDiagnostics();
2890
2906
  if (options.json) {
2891
- println6(JSON.stringify(report, null, 2));
2907
+ println5(JSON.stringify(report, null, 2));
2892
2908
  } else {
2893
2909
  printDiagnosticReport(report);
2894
2910
  }
@@ -2907,7 +2923,7 @@ program.command("repair").description("Repara problemas de configura\xE7\xE3o au
2907
2923
  const diagnostic = await runDiagnostics();
2908
2924
  const repair = repairAllIssues(diagnostic, apiKey, platformUrl);
2909
2925
  if (options.json) {
2910
- println6(JSON.stringify({ diagnostic, repair }, null, 2));
2926
+ println5(JSON.stringify({ diagnostic, repair }, null, 2));
2911
2927
  } else {
2912
2928
  printRepairReport(repair);
2913
2929
  }
@@ -2943,27 +2959,27 @@ program.command("install").description("Install MCP config for a specific IDE (u
2943
2959
  }
2944
2960
  const handler = getIDEHandler(ide);
2945
2961
  const mcpUrl = resolveMcpServerUrl(options.url);
2946
- println6();
2947
- println6(chalk6.cyan(` Installing MCP config for ${handler.name}...`));
2962
+ println5();
2963
+ println5(chalk6.cyan(` Installing MCP config for ${handler.name}...`));
2948
2964
  process.stdout.write(chalk6.gray(" Writing config... "));
2949
2965
  await handler.writeConfig(options.key, mcpUrl);
2950
- println6(chalk6.green("OK"));
2966
+ println5(chalk6.green("OK"));
2951
2967
  if (ide !== "manual") {
2952
- println6(chalk6.gray(` Config: ${handler.getConfigPath()}`));
2968
+ println5(chalk6.gray(` Config: ${handler.getConfigPath()}`));
2953
2969
  }
2954
2970
  process.stdout.write(chalk6.gray(" Verifying connection... "));
2955
2971
  const verified = await handler.verify(options.key, options.url);
2956
2972
  if (verified) {
2957
- println6(chalk6.green("OK"));
2973
+ println5(chalk6.green("OK"));
2958
2974
  } else {
2959
- println6(chalk6.yellow("SKIPPED (server not reachable)"));
2960
- println6(
2975
+ println5(chalk6.yellow("SKIPPED (server not reachable)"));
2976
+ println5(
2961
2977
  chalk6.gray(" The config was saved. Connection will work when the server is available.")
2962
2978
  );
2963
2979
  }
2964
- println6();
2965
- println6(chalk6.green.bold(" Done! Restart your IDE to activate the MCP server."));
2966
- println6();
2980
+ println5();
2981
+ println5(chalk6.green.bold(" Done! Restart your IDE to activate the MCP server."));
2982
+ println5();
2967
2983
  } catch (error) {
2968
2984
  eprintln();
2969
2985
  eprintln(