@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 +183 -167
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
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
|
-
|
|
2476
|
-
|
|
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
|
-
|
|
2491
|
-
|
|
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
|
-
|
|
2513
|
-
|
|
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
|
-
|
|
2528
|
+
println5(chalk6.white(" IDEs detectadas:\n"));
|
|
2517
2529
|
for (let i = 0; i < installedIDEs.length; i++) {
|
|
2518
|
-
|
|
2530
|
+
println5(` ${chalk6.cyan(String(i + 1))}. ${installedIDEs[i].name}`);
|
|
2519
2531
|
}
|
|
2520
|
-
|
|
2521
|
-
|
|
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
|
-
|
|
2544
|
+
println5(chalk6.yellow(" Nenhuma IDE selecionada."));
|
|
2533
2545
|
return 0;
|
|
2534
2546
|
}
|
|
2535
2547
|
selectedIDEs = indices.map((i) => installedIDEs[i]);
|
|
2536
2548
|
}
|
|
2537
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2565
|
+
println5(chalk6.green("OK"));
|
|
2554
2566
|
configured++;
|
|
2555
2567
|
} catch (error) {
|
|
2556
|
-
|
|
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: "
|
|
2582
|
+
execFileSync5("claude", addArgs, { stdio: "pipe" });
|
|
2571
2583
|
}
|
|
2572
2584
|
function printSuccessBanner(configuredCount) {
|
|
2573
|
-
|
|
2585
|
+
println5();
|
|
2574
2586
|
if (configuredCount > 0) {
|
|
2575
|
-
|
|
2576
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2586
|
-
|
|
2587
|
-
}
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
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
|
-
|
|
2614
|
-
|
|
2627
|
+
println5(chalk6.red("FALHOU"));
|
|
2628
|
+
println5(chalk6.red(" API key inv\xE1lida ou expirada."));
|
|
2615
2629
|
process.exit(1);
|
|
2616
2630
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2633
|
-
|
|
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
|
-
|
|
2652
|
-
|
|
2665
|
+
println5(chalk6.green("OK"));
|
|
2666
|
+
println5(chalk6.green(` Logado como ${userName}
|
|
2653
2667
|
`));
|
|
2654
2668
|
} catch (err) {
|
|
2655
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
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
|
-
|
|
2696
|
-
|
|
2709
|
+
println5(chalk6.yellow(" Nenhuma IDE suportada detectada."));
|
|
2710
|
+
println5(chalk6.gray(" O setup continuar\xE1 para Claude Code."));
|
|
2697
2711
|
} else {
|
|
2698
|
-
|
|
2712
|
+
println5(chalk6.green(" IDEs detectadas:"));
|
|
2699
2713
|
for (const ide of installedIDEs) {
|
|
2700
2714
|
const version = ide.version ? chalk6.gray(` (${ide.version})`) : "";
|
|
2701
|
-
|
|
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
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
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
|
-
|
|
2726
|
+
println5(
|
|
2713
2727
|
chalk6.cyan(" \u2551") + chalk6.gray(" Configura\xE7\xE3o guiada passo a passo ") + chalk6.cyan("\u2551")
|
|
2714
2728
|
);
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
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
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
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
|
-
|
|
2746
|
+
println5(chalk6.green("OK"));
|
|
2733
2747
|
const configPath = getClaudeConfigPath();
|
|
2734
|
-
|
|
2748
|
+
println5(chalk6.gray(` Config: ${configPath}`));
|
|
2735
2749
|
process.stdout.write(" Detectando IDEs... ");
|
|
2736
2750
|
const installedIDEs = getInstalledIDEs();
|
|
2737
|
-
|
|
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
|
-
|
|
2743
|
-
|
|
2756
|
+
println5(chalk6.yellow("J\xC1 CONFIGURADO"));
|
|
2757
|
+
println5();
|
|
2744
2758
|
const overwrite = await confirm(" Deseja reconfigurar?", false);
|
|
2745
2759
|
if (!overwrite) {
|
|
2746
|
-
|
|
2747
|
-
|
|
2760
|
+
println5();
|
|
2761
|
+
println5(chalk6.gray(" Opera\xE7\xE3o cancelada."));
|
|
2748
2762
|
process.exit(0);
|
|
2749
2763
|
}
|
|
2750
2764
|
} else {
|
|
2751
|
-
|
|
2765
|
+
println5(chalk6.gray("N\xE3o configurado"));
|
|
2752
2766
|
}
|
|
2753
2767
|
printStep(2, TOTAL_STEPS, "Configurando API Key");
|
|
2754
|
-
|
|
2755
|
-
|
|
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
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
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
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2802
|
+
println5(chalk6.green("OK"));
|
|
2787
2803
|
} catch (error) {
|
|
2788
|
-
|
|
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
|
-
|
|
2799
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2823
|
+
println5(` ${icon} ${issue.title}`);
|
|
2808
2824
|
}
|
|
2809
|
-
|
|
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
|
-
|
|
2830
|
+
println5(chalk6.green(`${repairReport.repairsSucceeded} corrigido(s)`));
|
|
2815
2831
|
} else {
|
|
2816
|
-
|
|
2832
|
+
println5(chalk6.yellow("Nenhum reparo aplicado"));
|
|
2817
2833
|
}
|
|
2818
2834
|
} else {
|
|
2819
|
-
|
|
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
|
-
|
|
2840
|
+
println5(chalk6.green(" \u2713 Nenhum problema encontrado!"));
|
|
2825
2841
|
}
|
|
2826
2842
|
} else {
|
|
2827
|
-
|
|
2843
|
+
println5(chalk6.gray(" Diagn\xF3stico ignorado (--skip-diagnostics)"));
|
|
2828
2844
|
}
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
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
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
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
|
-
|
|
2862
|
+
println5(
|
|
2847
2863
|
chalk6.gray(" ") + chalk6.cyan("npx @tostudy-ai/mcp-setup repair") + chalk6.gray(" - Reparar automaticamente")
|
|
2848
2864
|
);
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2947
|
-
|
|
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
|
-
|
|
2966
|
+
println5(chalk6.green("OK"));
|
|
2951
2967
|
if (ide !== "manual") {
|
|
2952
|
-
|
|
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
|
-
|
|
2973
|
+
println5(chalk6.green("OK"));
|
|
2958
2974
|
} else {
|
|
2959
|
-
|
|
2960
|
-
|
|
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
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
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(
|