@tostudy-ai/cli 0.18.13 → 0.18.16

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/main.js CHANGED
@@ -2405,10 +2405,10 @@ ${content}`;
2405
2405
  function detectedSlashHints(slug, home, cwd) {
2406
2406
  return RUNTIMES.filter((r) => r.slashHint && r.detect(home, cwd)).map((r) => r.slashHint(slug));
2407
2407
  }
2408
- function slashHintLines(slug, home, cwd, fallbackCommand) {
2408
+ function slashHintLines(slug, home, cwd) {
2409
2409
  const hints = slug ? detectedSlashHints(slug, home, cwd) : [];
2410
2410
  if (hints.length > 0) return hints.map((h) => `\u2192 ${h}`);
2411
- return [`\u2192 Na sua plataforma, digite: ${fallbackCommand}`];
2411
+ return ["\u2192 Na sua plataforma, pe\xE7a: vamos estudar (no terminal: tostudy menu)"];
2412
2412
  }
2413
2413
  function needsRootAgentsConsent(cwd) {
2414
2414
  const filePath = join2(cwd, "AGENTS.md");
@@ -2428,7 +2428,7 @@ function upsertRootAgentsBlock(cwd, ctx) {
2428
2428
  "",
2429
2429
  `- **Course:** ${ctx.courseTitle} (${ctx.progress}% complete)`,
2430
2430
  `- Read \`.tostudy/courses/${slug}/AGENTS.md\` for the full tutor instructions.`,
2431
- "- Study commands: run `/tostudy` (or `tostudy menu` in the terminal).",
2431
+ '- To study, ask in plain language (e.g. "vamos estudar"). In Claude Code or OpenCode you can also run `/tostudy`; in the terminal, `tostudy menu`.',
2432
2432
  "",
2433
2433
  "<!-- tostudy:end -->"
2434
2434
  ].join("\n");
@@ -2522,7 +2522,10 @@ var init_runtime_registry = __esm({
2522
2522
  const file2 = join2(home, ".codex", "prompts", "tostudy.md");
2523
2523
  writeFile2(join2(home, ".codex", "prompts"), "tostudy.md", content);
2524
2524
  return [file2];
2525
- }
2525
+ },
2526
+ // GH-2351: Codex never reads ~/.codex/prompts, so there is no /tostudy there;
2527
+ // asking in plain language works (it reads AGENTS.md and finds the course skill).
2528
+ slashHint: () => "No Codex, abra o Codex e pe\xE7a: vamos estudar"
2526
2529
  },
2527
2530
  {
2528
2531
  id: "opencode",
@@ -3739,27 +3742,57 @@ import { Command as Command3 } from "commander";
3739
3742
 
3740
3743
  // src/installer/mcp-setup.ts
3741
3744
  import { spawn } from "node:child_process";
3742
- async function exchangeCliSessionForMcpToken(session, fetchImpl = fetch) {
3743
- const res = await fetchImpl(`${session.apiUrl}/api/mcp/token`, {
3744
- method: "POST",
3745
- headers: {
3746
- Authorization: `Bearer ${session.token}`
3747
- }
3748
- });
3745
+ import { hostname } from "node:os";
3746
+
3747
+ // src/version.ts
3748
+ var CLI_VERSION = true ? "0.18.16" : "0.7.1";
3749
+
3750
+ // src/installer/mcp-setup.ts
3751
+ function safeServerError(text2) {
3752
+ if (typeof text2 !== "string" || text2.length === 0 || text2.length > 200) return null;
3753
+ return ["Bearer", "mcp_", "eyJ"].some((m) => text2.includes(m)) ? null : text2;
3754
+ }
3755
+ async function createMcpApiKey(session, fetchImpl = fetch) {
3756
+ let res;
3757
+ try {
3758
+ res = await fetchImpl(`${session.apiUrl}/api/mcp/sessions`, {
3759
+ method: "POST",
3760
+ headers: {
3761
+ Authorization: `Bearer ${session.token}`,
3762
+ "Content-Type": "application/json"
3763
+ },
3764
+ body: JSON.stringify({
3765
+ clientInfo: {
3766
+ source: "tostudy-cli-setup",
3767
+ hostname: hostname(),
3768
+ os: process.platform,
3769
+ version: CLI_VERSION
3770
+ }
3771
+ })
3772
+ });
3773
+ } catch {
3774
+ throw new Error("Falha ao criar a chave MCP: erro de rede");
3775
+ }
3749
3776
  if (!res.ok) {
3750
3777
  const body = await res.json().catch(() => ({}));
3751
- throw new Error(body.error ?? `Falha ao obter token MCP (${res.status})`);
3778
+ throw new Error(
3779
+ `Falha ao criar a chave MCP: ${safeServerError(body.error) ?? `HTTP ${res.status}`}`
3780
+ );
3752
3781
  }
3753
- return res.json();
3782
+ const { apiKey } = await res.json().catch(() => ({}));
3783
+ if (typeof apiKey !== "string" || !apiKey.startsWith("mcp_")) {
3784
+ throw new Error("Falha ao criar a chave MCP: resposta inv\xE1lida do servidor");
3785
+ }
3786
+ return apiKey;
3754
3787
  }
3755
- async function runMcpSetup(session, token, spawnImpl = spawn) {
3788
+ async function runMcpSetup(session, apiKey, spawnImpl = spawn) {
3756
3789
  const command = process.platform === "win32" ? "npx.cmd" : "npx";
3757
3790
  await new Promise((resolve, reject) => {
3758
3791
  const child = spawnImpl(command, ["-y", "@tostudy-ai/mcp-setup", "--url", session.apiUrl], {
3759
3792
  stdio: "inherit",
3760
3793
  env: {
3761
3794
  ...process.env,
3762
- TOSTUDY_API_KEY: token
3795
+ TOSTUDY_API_KEY: apiKey
3763
3796
  }
3764
3797
  });
3765
3798
  child.once("error", reject);
@@ -3794,8 +3827,15 @@ async function runSetupMcpSubcommand() {
3794
3827
  const session = await requireSession();
3795
3828
  console.log(` \u2713 Logado como ${session.userName}
3796
3829
  `);
3797
- const { token } = await exchangeCliSessionForMcpToken(session);
3798
- await runMcpSetup(session, token);
3830
+ const apiKey = await createMcpApiKey(session);
3831
+ try {
3832
+ await runMcpSetup(session, apiKey);
3833
+ } catch (error49) {
3834
+ console.error(
3835
+ " Instala\xE7\xE3o incompleta: a chave MCP criada aparece em Configura\xE7\xF5es \u203A MCP e pode ser revogada."
3836
+ );
3837
+ throw error49;
3838
+ }
3799
3839
  console.log("\n Setup MCP completo!");
3800
3840
  console.log(" \u2192 Reinicie o IDE para ativar o servidor MCP");
3801
3841
  console.log(" \u2192 tostudy doctor (verificar conex\xE3o)\n");
@@ -3849,9 +3889,6 @@ init_session_store();
3849
3889
  init_workspace_state();
3850
3890
  init_formatter();
3851
3891
 
3852
- // src/version.ts
3853
- var CLI_VERSION = true ? "0.18.13" : "0.7.1";
3854
-
3855
3892
  // src/update-checker.ts
3856
3893
  init_config_dir();
3857
3894
  import fs8 from "node:fs";
@@ -5210,7 +5247,6 @@ var selectCommand = new Command8("select").description("Activate a course by ID
5210
5247
  { json: true }
5211
5248
  );
5212
5249
  } else {
5213
- const slashCmd = courseSlug2 ? `/tostudy-${courseSlug2}` : "/tostudy";
5214
5250
  const home = os7.homedir();
5215
5251
  const cwd = process.cwd();
5216
5252
  const namespacedPath = `${cwd}/.tostudy`;
@@ -5242,7 +5278,7 @@ var selectCommand = new Command8("select").description("Activate a course by ID
5242
5278
  lines.push(rootAgentsSkippedHint());
5243
5279
  }
5244
5280
  lines.push("", "\u2192 Abra sua plataforma (claude, codex, cursor...)");
5245
- lines.push(...slashHintLines(courseSlug2, home, cwd, slashCmd));
5281
+ lines.push(...slashHintLines(courseSlug2, home, cwd));
5246
5282
  lines.push("\u2192 Em outras plataformas: tostudy init");
5247
5283
  output(lines.join("\n"), { json: false });
5248
5284
  }
@@ -5931,7 +5967,7 @@ __export(external_exports, {
5931
5967
  guid: () => guid2,
5932
5968
  hash: () => hash,
5933
5969
  hex: () => hex2,
5934
- hostname: () => hostname2,
5970
+ hostname: () => hostname3,
5935
5971
  httpUrl: () => httpUrl,
5936
5972
  includes: () => _includes,
5937
5973
  instanceof: () => _instanceof,
@@ -7318,7 +7354,7 @@ __export(regexes_exports, {
7318
7354
  extendedDuration: () => extendedDuration,
7319
7355
  guid: () => guid,
7320
7356
  hex: () => hex,
7321
- hostname: () => hostname,
7357
+ hostname: () => hostname2,
7322
7358
  html5Email: () => html5Email,
7323
7359
  idnEmail: () => idnEmail,
7324
7360
  integer: () => integer,
@@ -7395,7 +7431,7 @@ var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]
7395
7431
  var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
7396
7432
  var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
7397
7433
  var base64url = /^[A-Za-z0-9_-]*$/;
7398
- var hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
7434
+ var hostname2 = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
7399
7435
  var domain = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
7400
7436
  var e164 = /^\+[1-9]\d{6,14}$/;
7401
7437
  var dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
@@ -17765,7 +17801,7 @@ __export(schemas_exports2, {
17765
17801
  guid: () => guid2,
17766
17802
  hash: () => hash,
17767
17803
  hex: () => hex2,
17768
- hostname: () => hostname2,
17804
+ hostname: () => hostname3,
17769
17805
  httpUrl: () => httpUrl,
17770
17806
  instanceof: () => _instanceof,
17771
17807
  int: () => int,
@@ -18269,7 +18305,7 @@ var ZodCustomStringFormat = /* @__PURE__ */ $constructor("ZodCustomStringFormat"
18269
18305
  function stringFormat(format, fnOrRegex, _params = {}) {
18270
18306
  return _stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params);
18271
18307
  }
18272
- function hostname2(_params) {
18308
+ function hostname3(_params) {
18273
18309
  return _stringFormat(ZodCustomStringFormat, "hostname", regexes_exports.hostname, _params);
18274
18310
  }
18275
18311
  function hex2(_params) {