@tostudy-ai/cli 0.6.0 → 0.7.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.
Files changed (3) hide show
  1. package/dist/cli.js +1460 -766
  2. package/dist/cli.js.map +4 -4
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -219,6 +219,47 @@ function getConfigDir(override) {
219
219
  }
220
220
  return path2.join(os2.homedir(), ".tostudy");
221
221
  }
222
+ function getCourseOnboardingPath(configDir) {
223
+ return path2.join(getConfigDir(configDir), "course-onboarding.json");
224
+ }
225
+ function readCourseOnboardingState(configDir) {
226
+ const onboardingPath = getCourseOnboardingPath(configDir);
227
+ if (!fs2.existsSync(onboardingPath)) return {};
228
+ return JSON.parse(fs2.readFileSync(onboardingPath, "utf-8"));
229
+ }
230
+ function writeCourseOnboardingState(state, configDir) {
231
+ const dir = getConfigDir(configDir);
232
+ fs2.mkdirSync(dir, { recursive: true });
233
+ fs2.writeFileSync(getCourseOnboardingPath(configDir), JSON.stringify(state, null, 2), {
234
+ mode: 384
235
+ });
236
+ }
237
+ async function getCourseOnboardingState(courseId, configDir) {
238
+ const state = readCourseOnboardingState(configDir);
239
+ return state[courseId] ?? null;
240
+ }
241
+ async function updateCourseOnboardingState(courseId, patch, configDir) {
242
+ const state = readCourseOnboardingState(configDir);
243
+ state[courseId] = {
244
+ ...state[courseId] ?? {},
245
+ ...patch
246
+ };
247
+ writeCourseOnboardingState(state, configDir);
248
+ }
249
+ async function setCourseWorkspacePath(courseId, workspacePath, configDir) {
250
+ await updateCourseOnboardingState(courseId, { workspacePath }, configDir);
251
+ }
252
+ async function saveCourseLearnerProfile(course, learnerProfile, artifacts, configDir) {
253
+ await updateCourseOnboardingState(
254
+ course.courseId,
255
+ {
256
+ enrollmentId: course.enrollmentId,
257
+ learnerProfile,
258
+ artifacts
259
+ },
260
+ configDir
261
+ );
262
+ }
222
263
  async function saveSession(session, configDir) {
223
264
  const dir = getConfigDir(configDir);
224
265
  fs2.mkdirSync(dir, { recursive: true });
@@ -263,6 +304,8 @@ async function clearSession(configDir) {
263
304
  if (fs2.existsSync(p)) fs2.unlinkSync(p);
264
305
  const ap = path2.join(dir, "active-course.json");
265
306
  if (fs2.existsSync(ap)) fs2.unlinkSync(ap);
307
+ const onboardingPath = getCourseOnboardingPath(configDir);
308
+ if (fs2.existsSync(onboardingPath)) fs2.unlinkSync(onboardingPath);
266
309
  await deleteStoredSessionSecrets(dir);
267
310
  }
268
311
  async function getActiveCourse(configDir) {
@@ -274,7 +317,9 @@ async function getActiveCourse(configDir) {
274
317
  async function setActiveCourse(course, configDir) {
275
318
  const dir = getConfigDir(configDir);
276
319
  fs2.mkdirSync(dir, { recursive: true });
277
- fs2.writeFileSync(path2.join(dir, "active-course.json"), JSON.stringify(course, null, 2), {
320
+ const onboardingState = await getCourseOnboardingState(course.courseId, configDir);
321
+ const persistedCourse = onboardingState?.initCompletedAt && !course.lastInitCourseId ? { ...course, lastInitCourseId: course.courseId } : course;
322
+ fs2.writeFileSync(path2.join(dir, "active-course.json"), JSON.stringify(persistedCourse, null, 2), {
278
323
  mode: 384
279
324
  });
280
325
  }
@@ -332,6 +377,13 @@ async function setLastInitCourseId(courseId, configDir) {
332
377
  const existing = await getActiveCourse(configDir);
333
378
  if (!existing) return;
334
379
  await setActiveCourse({ ...existing, lastInitCourseId: courseId }, configDir);
380
+ await updateCourseOnboardingState(
381
+ courseId,
382
+ {
383
+ initCompletedAt: (/* @__PURE__ */ new Date()).toISOString()
384
+ },
385
+ configDir
386
+ );
335
387
  }
336
388
  async function checkCourseDrift(configDir) {
337
389
  const course = await getActiveCourse(configDir);
@@ -400,9 +452,17 @@ function formatCourseList(courses3) {
400
452
  const lines = ["Seus cursos:", ""];
401
453
  courses3.forEach((course, idx) => {
402
454
  const bar = progressBar(course.progress);
455
+ const enrolledDate = course.enrolledAt ? new Date(course.enrolledAt).toLocaleDateString("pt-BR", {
456
+ year: "numeric",
457
+ month: "short",
458
+ day: "numeric"
459
+ }) : null;
403
460
  lines.push(` ${idx + 1}. ${course.title}`);
404
461
  lines.push(` ${bar}`);
405
462
  lines.push(` Professor: ${course.creatorName}`);
463
+ if (enrolledDate) {
464
+ lines.push(` Inscrito em: ${enrolledDate}`);
465
+ }
406
466
  lines.push("");
407
467
  });
408
468
  lines.push("\u2192 tostudy select <n\xFAmero> para ativar um curso");
@@ -768,6 +828,65 @@ var init_mcp_setup = __esm({
768
828
  }
769
829
  });
770
830
 
831
+ // src/workspace/resolve.ts
832
+ import fs4 from "node:fs/promises";
833
+ import path4 from "node:path";
834
+ import os4 from "node:os";
835
+ function courseSlug(title) {
836
+ return title.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
837
+ }
838
+ async function resolveWorkspace(courseTitle, basePath = DEFAULT_BASE) {
839
+ const slug = courseSlug(courseTitle);
840
+ const candidate = path4.join(basePath, slug);
841
+ try {
842
+ await fs4.access(path4.join(candidate, ".ana-config.json"));
843
+ return { found: true, workspacePath: candidate };
844
+ } catch {
845
+ return { found: false, workspacePath: null };
846
+ }
847
+ }
848
+ var DEFAULT_BASE;
849
+ var init_resolve = __esm({
850
+ "src/workspace/resolve.ts"() {
851
+ "use strict";
852
+ DEFAULT_BASE = path4.join(os4.homedir(), "study");
853
+ }
854
+ });
855
+
856
+ // src/onboarding/status.ts
857
+ import fs5 from "node:fs/promises";
858
+ import path5 from "node:path";
859
+ async function resolveStoredWorkspace(workspacePath) {
860
+ if (!workspacePath) return null;
861
+ try {
862
+ await fs5.access(path5.join(workspacePath, ".ana-config.json"));
863
+ return workspacePath;
864
+ } catch {
865
+ return null;
866
+ }
867
+ }
868
+ async function getCourseOnboardingStatus(activeCourse, configDir) {
869
+ const onboardingState = await getCourseOnboardingState(activeCourse.courseId, configDir);
870
+ const initReady = Boolean(onboardingState?.initCompletedAt);
871
+ let workspacePath = await resolveStoredWorkspace(onboardingState?.workspacePath);
872
+ if (!workspacePath) {
873
+ const resolvedWorkspace = await resolveWorkspace(activeCourse.courseTitle);
874
+ workspacePath = resolvedWorkspace.workspacePath;
875
+ }
876
+ return {
877
+ initReady,
878
+ workspaceReady: Boolean(workspacePath),
879
+ workspacePath
880
+ };
881
+ }
882
+ var init_status = __esm({
883
+ "src/onboarding/status.ts"() {
884
+ "use strict";
885
+ init_session();
886
+ init_resolve();
887
+ }
888
+ });
889
+
771
890
  // src/commands/setup.ts
772
891
  import { Command as Command3 } from "commander";
773
892
  async function runSetup(opts, deps = defaultDeps) {
@@ -821,8 +940,34 @@ async function runSetup(opts, deps = defaultDeps) {
821
940
  await deps.runMcpSetup(session, token2);
822
941
  deps.log(" \u2713 MCP configurado\n");
823
942
  }
943
+ const activeCourse = await deps.getActiveCourse();
944
+ if (!activeCourse) {
945
+ deps.log(" Ambiente validado, mas ainda falta selecionar um curso.");
946
+ deps.log(" Pr\xF3ximos passos obrigat\xF3rios:");
947
+ deps.log(" \u2192 tostudy courses");
948
+ deps.log(" \u2192 tostudy select <n\xFAmero>");
949
+ deps.log(" \u2192 tostudy init");
950
+ deps.log(" \u2192 tostudy workspace setup\n");
951
+ return;
952
+ }
953
+ const onboarding = await deps.getCourseOnboardingStatus(activeCourse);
954
+ if (!onboarding.initReady || !onboarding.workspaceReady) {
955
+ deps.log(
956
+ ` Ambiente validado para ${activeCourse.courseTitle}, mas o onboarding ainda n\xE3o terminou.`
957
+ );
958
+ deps.log(" Checklist obrigat\xF3rio antes do primeiro start:");
959
+ if (!onboarding.initReady) {
960
+ deps.log(" \u2192 tostudy init");
961
+ }
962
+ if (!onboarding.workspaceReady) {
963
+ deps.log(" \u2192 tostudy workspace setup");
964
+ }
965
+ deps.log(" \u2192 tostudy start ficar\xE1 dispon\xEDvel depois desses passos\n");
966
+ return;
967
+ }
824
968
  deps.log(" Setup completo!");
825
- deps.log(" \u2192 tostudy courses (ver cursos matriculados)");
969
+ deps.log(" \u2192 tostudy start (iniciar ou retomar o m\xF3dulo atual)");
970
+ deps.log(" \u2192 tostudy courses (ver cursos matriculados)");
826
971
  deps.log(" \u2192 tostudy doctor (diagn\xF3stico completo)\n");
827
972
  }
828
973
  async function runSetupMcpSubcommand() {
@@ -844,10 +989,13 @@ var init_setup = __esm({
844
989
  init_ide_detector();
845
990
  init_session();
846
991
  init_mcp_setup();
992
+ init_status();
847
993
  defaultDeps = {
848
994
  detectNode,
849
995
  detectIDEs,
850
996
  getSession,
997
+ getActiveCourse,
998
+ getCourseOnboardingStatus,
851
999
  exchangeCliSessionForMcpToken,
852
1000
  runMcpSetup,
853
1001
  log: (message = "") => {
@@ -872,20 +1020,20 @@ __export(update_checker_exports, {
872
1020
  fetchLatestVersion: () => fetchLatestVersion,
873
1021
  isNewerVersion: () => isNewerVersion
874
1022
  });
875
- import fs4 from "node:fs";
876
- import path4 from "node:path";
877
- import os4 from "node:os";
1023
+ import fs6 from "node:fs";
1024
+ import path6 from "node:path";
1025
+ import os5 from "node:os";
878
1026
  function getConfigDir2() {
879
1027
  if (process.platform === "linux" && process.env["XDG_CONFIG_HOME"]) {
880
- return path4.join(process.env["XDG_CONFIG_HOME"], "tostudy");
1028
+ return path6.join(process.env["XDG_CONFIG_HOME"], "tostudy");
881
1029
  }
882
- return path4.join(os4.homedir(), ".tostudy");
1030
+ return path6.join(os5.homedir(), ".tostudy");
883
1031
  }
884
1032
  function readCache() {
885
1033
  try {
886
- const p = path4.join(getConfigDir2(), CACHE_FILE);
887
- if (!fs4.existsSync(p)) return null;
888
- return JSON.parse(fs4.readFileSync(p, "utf-8"));
1034
+ const p = path6.join(getConfigDir2(), CACHE_FILE);
1035
+ if (!fs6.existsSync(p)) return null;
1036
+ return JSON.parse(fs6.readFileSync(p, "utf-8"));
889
1037
  } catch {
890
1038
  return null;
891
1039
  }
@@ -893,8 +1041,8 @@ function readCache() {
893
1041
  function writeCache(cache) {
894
1042
  try {
895
1043
  const dir = getConfigDir2();
896
- fs4.mkdirSync(dir, { recursive: true });
897
- fs4.writeFileSync(path4.join(dir, CACHE_FILE), JSON.stringify(cache));
1044
+ fs6.mkdirSync(dir, { recursive: true });
1045
+ fs6.writeFileSync(path6.join(dir, CACHE_FILE), JSON.stringify(cache));
898
1046
  } catch {
899
1047
  }
900
1048
  }
@@ -923,7 +1071,7 @@ function showUpdateNotification(current, latest) {
923
1071
  [
924
1072
  "",
925
1073
  ` Atualiza\xE7\xE3o dispon\xEDvel: ${current} \u2192 ${latest}`,
926
- " Atualize com: npm i -g @tostudy-ai/cli",
1074
+ " Atualize com: npm i -g @tostudy-ai/cli@latest",
927
1075
  ""
928
1076
  ].join("\n")
929
1077
  );
@@ -1058,7 +1206,7 @@ var init_doctor = __esm({
1058
1206
  ` ${upToDate ? "\u2713" : "\u2717"} \xDAltima ${versionInfo.latest}${versionInfo.updateAvailable ? " (atualiza\xE7\xE3o dispon\xEDvel)" : ""}`
1059
1207
  );
1060
1208
  if (versionInfo.updateAvailable) {
1061
- console.log(" \u2192 npm i -g @tostudy-ai/cli");
1209
+ console.log(" \u2192 npm i -g @tostudy-ai/cli@latest");
1062
1210
  }
1063
1211
  } else {
1064
1212
  console.log(" \u25CB \xDAltima n\xE3o foi poss\xEDvel verificar");
@@ -1140,7 +1288,7 @@ var init_context = __esm({
1140
1288
  // ../../packages/logger/src/formatters/json.ts
1141
1289
  function formatJson(entry) {
1142
1290
  const { timestamp: timestamp2, level, message, service, environment, context, data, error: error49 } = entry;
1143
- const output2 = {
1291
+ const output3 = {
1144
1292
  timestamp: timestamp2,
1145
1293
  level,
1146
1294
  message,
@@ -1150,9 +1298,9 @@ function formatJson(entry) {
1150
1298
  ...data
1151
1299
  };
1152
1300
  if (error49) {
1153
- output2.error = error49;
1301
+ output3.error = error49;
1154
1302
  }
1155
- return JSON.stringify(output2);
1303
+ return JSON.stringify(output3);
1156
1304
  }
1157
1305
  var init_json = __esm({
1158
1306
  "../../packages/logger/src/formatters/json.ts"() {
@@ -1167,8 +1315,8 @@ var require_picocolors = __commonJS({
1167
1315
  var argv = p.argv || [];
1168
1316
  var env = p.env || {};
1169
1317
  var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
1170
- var formatter = (open, close, replace = open) => (input) => {
1171
- let string4 = "" + input, index2 = string4.indexOf(close, open.length);
1318
+ var formatter = (open, close, replace = open) => (input2) => {
1319
+ let string4 = "" + input2, index2 = string4.indexOf(close, open.length);
1172
1320
  return ~index2 ? open + replaceClose(string4, close, replace, index2) + close : open + string4 + close;
1173
1321
  };
1174
1322
  var replaceClose = (string4, close, replace, index2) => {
@@ -1259,7 +1407,7 @@ function formatPretty(entry) {
1259
1407
  const lvl = formatLevel(level);
1260
1408
  const mod = context.module ? import_picocolors.default.dim(`[${context.module}]`) + " " : "";
1261
1409
  const svc = import_picocolors.default.dim(`[${service}]`) + " ";
1262
- let output2 = `${import_picocolors.default.dim(time4)} ${lvl} ${svc}${mod}${message}`;
1410
+ let output3 = `${import_picocolors.default.dim(time4)} ${lvl} ${svc}${mod}${message}`;
1263
1411
  const traceInfo = {};
1264
1412
  if (context.traceId) traceInfo.traceId = context.traceId;
1265
1413
  if (context.requestId && context.requestId !== context.traceId) {
@@ -1269,22 +1417,22 @@ function formatPretty(entry) {
1269
1417
  if (context.duration !== void 0) traceInfo.duration = `${context.duration}ms`;
1270
1418
  const allData = { ...traceInfo, ...data };
1271
1419
  if (Object.keys(allData).length > 0) {
1272
- output2 += formatData(allData);
1420
+ output3 += formatData(allData);
1273
1421
  }
1274
1422
  if (error49) {
1275
- output2 += "\n" + import_picocolors.default.red(` ${error49.name}: ${error49.message}`);
1423
+ output3 += "\n" + import_picocolors.default.red(` ${error49.name}: ${error49.message}`);
1276
1424
  if (error49.code) {
1277
- output2 += import_picocolors.default.dim(` (${error49.code})`);
1425
+ output3 += import_picocolors.default.dim(` (${error49.code})`);
1278
1426
  }
1279
1427
  if (error49.stack) {
1280
1428
  const stackLines = error49.stack.split("\n").slice(1, 4);
1281
- output2 += "\n" + stackLines.map((l) => import_picocolors.default.dim(` ${l.trim()}`)).join("\n");
1429
+ output3 += "\n" + stackLines.map((l) => import_picocolors.default.dim(` ${l.trim()}`)).join("\n");
1282
1430
  }
1283
1431
  if (error49.cause) {
1284
- output2 += "\n" + import_picocolors.default.dim(` Caused by: ${error49.cause.name}: ${error49.cause.message}`);
1432
+ output3 += "\n" + import_picocolors.default.dim(` Caused by: ${error49.cause.name}: ${error49.cause.message}`);
1285
1433
  }
1286
1434
  }
1287
- return output2;
1435
+ return output3;
1288
1436
  }
1289
1437
  var import_picocolors, LEVEL_COLORS, LEVEL_WIDTH;
1290
1438
  var init_pretty = __esm({
@@ -1372,6 +1520,22 @@ function isSensitiveKey(key) {
1372
1520
  return patterns.some((p) => lowerKey.includes(p));
1373
1521
  });
1374
1522
  }
1523
+ function serializeError(error49) {
1524
+ const serialized = {
1525
+ name: error49.name,
1526
+ message: error49.message
1527
+ };
1528
+ if (error49.stack) {
1529
+ serialized.stack = error49.stack;
1530
+ }
1531
+ if ("code" in error49 && typeof error49.code === "string") {
1532
+ serialized.code = error49.code;
1533
+ }
1534
+ if (error49.cause instanceof Error) {
1535
+ serialized.cause = serializeError(error49.cause);
1536
+ }
1537
+ return serialized;
1538
+ }
1375
1539
  function object(obj, additionalSensitiveKeys) {
1376
1540
  if (!obj || typeof obj !== "object") return obj;
1377
1541
  const sanitized = { ...obj };
@@ -1383,6 +1547,10 @@ function object(obj, additionalSensitiveKeys) {
1383
1547
  sanitized[key] = "[REDACTED]";
1384
1548
  continue;
1385
1549
  }
1550
+ if (value instanceof Error) {
1551
+ sanitized[key] = serializeError(value);
1552
+ continue;
1553
+ }
1386
1554
  if (value && typeof value === "object" && !Array.isArray(value)) {
1387
1555
  sanitized[key] = object(
1388
1556
  value,
@@ -1392,6 +1560,7 @@ function object(obj, additionalSensitiveKeys) {
1392
1560
  }
1393
1561
  if (Array.isArray(value)) {
1394
1562
  sanitized[key] = value.map((item) => {
1563
+ if (item instanceof Error) return serializeError(item);
1395
1564
  if (item && typeof item === "object" && !Array.isArray(item)) {
1396
1565
  return object(item, additionalSensitiveKeys);
1397
1566
  }
@@ -1402,13 +1571,7 @@ function object(obj, additionalSensitiveKeys) {
1402
1571
  return sanitized;
1403
1572
  }
1404
1573
  function headers(hdrs) {
1405
- const sensitiveHeaders = [
1406
- "authorization",
1407
- "x-api-key",
1408
- "x-auth-token",
1409
- "cookie",
1410
- "set-cookie"
1411
- ];
1574
+ const sensitiveHeaders = ["authorization", "x-api-key", "x-auth-token", "cookie", "set-cookie"];
1412
1575
  const sanitized = { ...hdrs };
1413
1576
  for (const key of Object.keys(sanitized)) {
1414
1577
  if (sensitiveHeaders.some((h) => key.toLowerCase() === h)) {
@@ -1986,9 +2149,9 @@ var init_src = __esm({
1986
2149
  });
1987
2150
 
1988
2151
  // ../../packages/tostudy-core/src/courses/list-courses.ts
1989
- async function listCourses(input, deps) {
1990
- deps.logger.info("tostudy-core: listCourses", { userId: input.userId });
1991
- return deps.data.courses.list(input.userId);
2152
+ async function listCourses(input2, deps) {
2153
+ deps.logger.info("tostudy-core: listCourses", { userId: input2.userId });
2154
+ return deps.data.courses.list(input2.userId);
1992
2155
  }
1993
2156
  var init_list_courses = __esm({
1994
2157
  "../../packages/tostudy-core/src/courses/list-courses.ts"() {
@@ -1997,9 +2160,9 @@ var init_list_courses = __esm({
1997
2160
  });
1998
2161
 
1999
2162
  // ../../packages/tostudy-core/src/courses/select-course.ts
2000
- async function selectCourse(input, deps) {
2001
- deps.logger.info("tostudy-core: selectCourse", input);
2002
- return deps.data.courses.select(input.userId, input.courseId);
2163
+ async function selectCourse(input2, deps) {
2164
+ deps.logger.info("tostudy-core: selectCourse", input2);
2165
+ return deps.data.courses.select(input2.userId, input2.courseId);
2003
2166
  }
2004
2167
  var init_select_course = __esm({
2005
2168
  "../../packages/tostudy-core/src/courses/select-course.ts"() {
@@ -2008,9 +2171,9 @@ var init_select_course = __esm({
2008
2171
  });
2009
2172
 
2010
2173
  // ../../packages/tostudy-core/src/courses/get-progress.ts
2011
- async function getProgress(input, deps) {
2012
- deps.logger.info("tostudy-core: getProgress", input);
2013
- return deps.data.courses.getProgress(input.enrollmentId);
2174
+ async function getProgress(input2, deps) {
2175
+ deps.logger.info("tostudy-core: getProgress", input2);
2176
+ return deps.data.courses.getProgress(input2.enrollmentId);
2014
2177
  }
2015
2178
  var init_get_progress = __esm({
2016
2179
  "../../packages/tostudy-core/src/courses/get-progress.ts"() {
@@ -2171,9 +2334,109 @@ var init_courses2 = __esm({
2171
2334
  }
2172
2335
  });
2173
2336
 
2337
+ // src/workspace/instruction-files.ts
2338
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "node:fs";
2339
+ import { join as join2 } from "node:path";
2340
+ function slugify(title) {
2341
+ return title.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
2342
+ }
2343
+ function buildInstructionContent(ctx, learner) {
2344
+ const sections = [];
2345
+ sections.push(`# ${ctx.courseTitle} \u2014 ToStudy
2346
+
2347
+ Voc\xEA \xE9 um tutor AI guiando o estudante neste curso.`);
2348
+ if (learner) {
2349
+ const levelLabels = {
2350
+ beginner: "Iniciante",
2351
+ intermediate: "Intermedi\xE1rio",
2352
+ advanced: "Avan\xE7ado"
2353
+ };
2354
+ sections.push(`## Contexto do Aluno
2355
+
2356
+ - **N\xEDvel**: ${levelLabels[learner.learnerLevel]}
2357
+ - **Objetivo**: ${learner.goal}
2358
+ - **Empresa**: ${learner.company}
2359
+ - **Segmento**: ${learner.segment}
2360
+ - **Produtos/Servi\xE7os**: ${learner.productsOrServices}
2361
+ - **Regi\xE3o**: ${learner.region}
2362
+ - **Time**: ${learner.team}
2363
+ - **Adaptar ao contexto real**: ${learner.adaptToRealContext ? "Sim \u2014 use exemplos do projeto real do aluno" : "N\xE3o \u2014 use exemplos gen\xE9ricos"}`);
2364
+ }
2365
+ sections.push(`## Progresso
2366
+
2367
+ - ${ctx.progress}% completo | ${ctx.moduleCount} m\xF3dulos | ${ctx.lessonCount} li\xE7\xF5es`);
2368
+ sections.push(`## Comandos Dispon\xEDveis
2369
+
2370
+ | Comando | Descri\xE7\xE3o |
2371
+ |---------|-----------|
2372
+ | \`tostudy start\` | Carrega o pr\xF3ximo m\xF3dulo |
2373
+ | \`tostudy next\` | Avan\xE7a para a pr\xF3xima li\xE7\xE3o |
2374
+ | \`tostudy lesson\` | Mostra a li\xE7\xE3o atual |
2375
+ | \`tostudy hint\` | Mostra dicas progressivas |
2376
+ | \`tostudy validate\` | Valida o exerc\xEDcio |
2377
+ | \`tostudy progress\` | Mostra o progresso |`);
2378
+ sections.push(`## Regras
2379
+
2380
+ - Sempre carregue a li\xE7\xE3o antes de propor exerc\xEDcios (\`tostudy lesson\`)
2381
+ - Use \`tostudy hint\` antes de entregar respostas diretas
2382
+ - Valide com \`tostudy validate\` antes de avan\xE7ar
2383
+ - Respeite a sequ\xEAncia dos m\xF3dulos${learner?.adaptToRealContext ? "\n- Adapte exemplos ao contexto real do projeto do estudante" : ""}`);
2384
+ sections.push(`<!-- tostudy-course-id: ${ctx.courseId} -->`);
2385
+ return sections.join("\n\n") + "\n";
2386
+ }
2387
+ function generateInstructionFiles(ctx, learner) {
2388
+ const cwd = process.cwd();
2389
+ const slug = slugify(ctx.courseTitle);
2390
+ const content = buildInstructionContent(ctx, learner);
2391
+ const written = [];
2392
+ const claudeDir = join2(cwd, ".claude", "commands");
2393
+ if (!existsSync2(claudeDir)) {
2394
+ mkdirSync2(claudeDir, { recursive: true });
2395
+ }
2396
+ const claudeFile = `tostudy-${slug}.md`;
2397
+ writeFileSync2(join2(claudeDir, claudeFile), content);
2398
+ written.push(`.claude/commands/${claudeFile}`);
2399
+ const cursorDir = join2(cwd, ".cursor", "rules");
2400
+ if (existsSync2(join2(cwd, ".cursor")) || existsSync2(cursorDir)) {
2401
+ if (!existsSync2(cursorDir)) {
2402
+ mkdirSync2(cursorDir, { recursive: true });
2403
+ }
2404
+ const mdcContent = `---
2405
+ description: ${ctx.courseTitle} \u2014 ToStudy Course Guide
2406
+ globs: ["**/*"]
2407
+ alwaysApply: true
2408
+ ---
2409
+
2410
+ ${content}`;
2411
+ const cursorFile = `tostudy-${slug}.mdc`;
2412
+ writeFileSync2(join2(cursorDir, cursorFile), mdcContent);
2413
+ written.push(`.cursor/rules/${cursorFile}`);
2414
+ }
2415
+ const courseDir = join2(cwd, ".tostudy", "courses", slug);
2416
+ if (!existsSync2(courseDir)) {
2417
+ mkdirSync2(courseDir, { recursive: true });
2418
+ }
2419
+ writeFileSync2(join2(courseDir, "AGENTS.md"), content);
2420
+ written.push(`.tostudy/courses/${slug}/AGENTS.md`);
2421
+ logger3.info("Generated instruction files", {
2422
+ slug,
2423
+ files: written,
2424
+ hasLearnerProfile: !!learner
2425
+ });
2426
+ return slug;
2427
+ }
2428
+ var logger3;
2429
+ var init_instruction_files = __esm({
2430
+ "src/workspace/instruction-files.ts"() {
2431
+ "use strict";
2432
+ init_src();
2433
+ logger3 = createLogger("cli:instruction-files");
2434
+ }
2435
+ });
2436
+
2174
2437
  // src/commands/select.ts
2175
2438
  import { Command as Command6 } from "commander";
2176
- var logger3, selectCommand;
2439
+ var logger4, selectCommand;
2177
2440
  var init_select = __esm({
2178
2441
  "src/commands/select.ts"() {
2179
2442
  "use strict";
@@ -2182,12 +2445,13 @@ var init_select = __esm({
2182
2445
  init_http2();
2183
2446
  init_session();
2184
2447
  init_formatter();
2185
- logger3 = createLogger("cli:select");
2448
+ init_instruction_files();
2449
+ logger4 = createLogger("cli:select");
2186
2450
  selectCommand = new Command6("select").description("Activate a course by ID or list index number").argument("<course>", "Course ID (UUID) or index number from `tostudy courses`").option("--json", "Output structured JSON").action(async (course, opts) => {
2187
2451
  try {
2188
2452
  const session = await requireSession();
2189
2453
  const data = createHttpProvider(session.apiUrl, session.token);
2190
- const deps = { data, logger: logger3 };
2454
+ const deps = { data, logger: logger4 };
2191
2455
  const courses3 = await listCourses({ userId: session.userId }, deps);
2192
2456
  let courseId = course;
2193
2457
  let enrollmentId = "";
@@ -2214,17 +2478,34 @@ var init_select = __esm({
2214
2478
  courseTags: matched?.tags,
2215
2479
  courseLevel: matched?.level
2216
2480
  });
2481
+ let courseSlug2 = "";
2482
+ try {
2483
+ courseSlug2 = generateInstructionFiles({
2484
+ courseTitle: detail.courseTitle,
2485
+ courseId: detail.courseId,
2486
+ progress: detail.progress,
2487
+ moduleCount: detail.moduleCount,
2488
+ lessonCount: detail.lessonCount
2489
+ });
2490
+ } catch (err) {
2491
+ logger4.warn("Failed to generate instruction files", {
2492
+ error: err instanceof Error ? err.message : String(err)
2493
+ });
2494
+ }
2217
2495
  if (opts.json) {
2218
- output({ ...detail, enrollmentId }, { json: true });
2496
+ output({ ...detail, enrollmentId, courseSlug: courseSlug2 }, { json: true });
2219
2497
  } else {
2498
+ const slashCmd = courseSlug2 ? `/tostudy-${courseSlug2}` : "/tostudy";
2220
2499
  output(
2221
2500
  [
2222
2501
  `\u2713 Curso ativado: ${detail.courseTitle}`,
2223
2502
  ` Progresso: ${detail.progress}% | ${detail.moduleCount} m\xF3dulos | ${detail.lessonCount} li\xE7\xF5es`,
2224
2503
  "",
2225
- "\u2192 tostudy progress para ver seu progresso detalhado",
2226
- "\u2192 tostudy start para come\xE7ar o m\xF3dulo atual",
2227
- "\u2192 tostudy next para avan\xE7ar para a pr\xF3xima li\xE7\xE3o"
2504
+ " Arquivos de contexto criados para seu assistente AI.",
2505
+ "",
2506
+ "\u2192 Abra sua plataforma (claude, codex, cursor...)",
2507
+ `\u2192 No Claude Code, digite: ${slashCmd}`,
2508
+ "\u2192 Em outras plataformas: tostudy init"
2228
2509
  ].join("\n"),
2229
2510
  { json: false }
2230
2511
  );
@@ -2239,7 +2520,7 @@ var init_select = __esm({
2239
2520
 
2240
2521
  // src/commands/progress.ts
2241
2522
  import { Command as Command7 } from "commander";
2242
- var logger4, progressCommand;
2523
+ var logger5, progressCommand;
2243
2524
  var init_progress = __esm({
2244
2525
  "src/commands/progress.ts"() {
2245
2526
  "use strict";
@@ -2248,7 +2529,7 @@ var init_progress = __esm({
2248
2529
  init_http2();
2249
2530
  init_session();
2250
2531
  init_formatter();
2251
- logger4 = createLogger("cli:progress");
2532
+ logger5 = createLogger("cli:progress");
2252
2533
  progressCommand = new Command7("progress").description("Show your progress in the active course").option("--json", "Output structured JSON").action(async (opts) => {
2253
2534
  try {
2254
2535
  const session = await requireSession();
@@ -2256,7 +2537,7 @@ var init_progress = __esm({
2256
2537
  const driftWarning = await checkCourseDrift();
2257
2538
  if (driftWarning) process.stderr.write(driftWarning + "\n");
2258
2539
  const data = createHttpProvider(session.apiUrl, session.token);
2259
- const deps = { data, logger: logger4 };
2540
+ const deps = { data, logger: logger5 };
2260
2541
  const progress3 = await getProgress({ enrollmentId: activeCourse.enrollmentId }, deps);
2261
2542
  if (opts.json) {
2262
2543
  output(progress3, { json: true });
@@ -2272,9 +2553,9 @@ var init_progress = __esm({
2272
2553
  });
2273
2554
 
2274
2555
  // ../../packages/tostudy-core/src/lessons/next-lesson.ts
2275
- async function nextLesson(input, deps) {
2276
- deps.logger.info("tostudy-core: nextLesson", { enrollmentId: input.enrollmentId });
2277
- return deps.data.lessons.next(input.enrollmentId, input.userConfirmation);
2556
+ async function nextLesson(input2, deps) {
2557
+ deps.logger.info("tostudy-core: nextLesson", { enrollmentId: input2.enrollmentId });
2558
+ return deps.data.lessons.next(input2.enrollmentId, input2.userConfirmation);
2278
2559
  }
2279
2560
  var init_next_lesson = __esm({
2280
2561
  "../../packages/tostudy-core/src/lessons/next-lesson.ts"() {
@@ -2283,9 +2564,9 @@ var init_next_lesson = __esm({
2283
2564
  });
2284
2565
 
2285
2566
  // ../../packages/tostudy-core/src/lessons/get-content.ts
2286
- async function getContent(input, deps) {
2287
- deps.logger.info("tostudy-core: getContent", { lessonId: input.lessonId });
2288
- return deps.data.lessons.getContent(input.lessonId, input.enrollmentId);
2567
+ async function getContent(input2, deps) {
2568
+ deps.logger.info("tostudy-core: getContent", { lessonId: input2.lessonId });
2569
+ return deps.data.lessons.getContent(input2.lessonId, input2.enrollmentId);
2289
2570
  }
2290
2571
  var init_get_content = __esm({
2291
2572
  "../../packages/tostudy-core/src/lessons/get-content.ts"() {
@@ -2294,9 +2575,9 @@ var init_get_content = __esm({
2294
2575
  });
2295
2576
 
2296
2577
  // ../../packages/tostudy-core/src/lessons/get-hint.ts
2297
- async function getHint(input, deps) {
2298
- deps.logger.info("tostudy-core: getHint", { userId: input.userId });
2299
- return deps.data.lessons.getHint(input.userId, input.enrollmentId);
2578
+ async function getHint(input2, deps) {
2579
+ deps.logger.info("tostudy-core: getHint", { userId: input2.userId });
2580
+ return deps.data.lessons.getHint(input2.userId, input2.enrollmentId);
2300
2581
  }
2301
2582
  var init_get_hint = __esm({
2302
2583
  "../../packages/tostudy-core/src/lessons/get-hint.ts"() {
@@ -2305,9 +2586,9 @@ var init_get_hint = __esm({
2305
2586
  });
2306
2587
 
2307
2588
  // ../../packages/tostudy-core/src/lessons/start-module.ts
2308
- async function startModule(input, deps) {
2309
- deps.logger.info("tostudy-core: startModule", { enrollmentId: input.enrollmentId });
2310
- return deps.data.lessons.startModule(input.enrollmentId);
2589
+ async function startModule(input2, deps) {
2590
+ deps.logger.info("tostudy-core: startModule", { enrollmentId: input2.enrollmentId });
2591
+ return deps.data.lessons.startModule(input2.enrollmentId);
2311
2592
  }
2312
2593
  var init_start_module = __esm({
2313
2594
  "../../packages/tostudy-core/src/lessons/start-module.ts"() {
@@ -2316,9 +2597,9 @@ var init_start_module = __esm({
2316
2597
  });
2317
2598
 
2318
2599
  // ../../packages/tostudy-core/src/lessons/start-next-module.ts
2319
- async function startNextModule(input, deps) {
2320
- deps.logger.info("tostudy-core: startNextModule", { enrollmentId: input.enrollmentId });
2321
- return deps.data.lessons.startNextModule(input.enrollmentId);
2600
+ async function startNextModule(input2, deps) {
2601
+ deps.logger.info("tostudy-core: startNextModule", { enrollmentId: input2.enrollmentId });
2602
+ return deps.data.lessons.startNextModule(input2.enrollmentId);
2322
2603
  }
2323
2604
  var init_start_next_module = __esm({
2324
2605
  "../../packages/tostudy-core/src/lessons/start-next-module.ts"() {
@@ -2955,8 +3236,8 @@ var init_common = __esm({
2955
3236
  function isPgEnum(obj) {
2956
3237
  return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
2957
3238
  }
2958
- function pgEnum(enumName, input) {
2959
- return Array.isArray(input) ? pgEnumWithSchema(enumName, [...input], void 0) : pgEnumObjectWithSchema(enumName, input, void 0);
3239
+ function pgEnum(enumName, input2) {
3240
+ return Array.isArray(input2) ? pgEnumWithSchema(enumName, [...input2], void 0) : pgEnumObjectWithSchema(enumName, input2, void 0);
2960
3241
  }
2961
3242
  function pgEnumWithSchema(enumName, values2, schema) {
2962
3243
  const enumInstance = Object.assign(
@@ -3515,7 +3796,7 @@ var init_sql = __esm({
3515
3796
  return new SQL([new StringChunk(str)]);
3516
3797
  }
3517
3798
  sql2.raw = raw;
3518
- function join2(chunks, separator) {
3799
+ function join3(chunks, separator) {
3519
3800
  const result = [];
3520
3801
  for (const [i, chunk] of chunks.entries()) {
3521
3802
  if (i > 0 && separator !== void 0) {
@@ -3525,7 +3806,7 @@ var init_sql = __esm({
3525
3806
  }
3526
3807
  return new SQL(result);
3527
3808
  }
3528
- sql2.join = join2;
3809
+ sql2.join = join3;
3529
3810
  function identifier(value) {
3530
3811
  return new Name(value);
3531
3812
  }
@@ -3817,7 +4098,7 @@ var init_query_promise = __esm({
3817
4098
  function mapResultRow(columns, row, joinsNotNullableMap) {
3818
4099
  const nullifyMap = {};
3819
4100
  const result = columns.reduce(
3820
- (result2, { path: path14, field }, columnIndex) => {
4101
+ (result2, { path: path15, field }, columnIndex) => {
3821
4102
  let decoder;
3822
4103
  if (is(field, Column)) {
3823
4104
  decoder = field;
@@ -3829,8 +4110,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
3829
4110
  decoder = field.sql.decoder;
3830
4111
  }
3831
4112
  let node = result2;
3832
- for (const [pathChunkIndex, pathChunk] of path14.entries()) {
3833
- if (pathChunkIndex < path14.length - 1) {
4113
+ for (const [pathChunkIndex, pathChunk] of path15.entries()) {
4114
+ if (pathChunkIndex < path15.length - 1) {
3834
4115
  if (!(pathChunk in node)) {
3835
4116
  node[pathChunk] = {};
3836
4117
  }
@@ -3838,8 +4119,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
3838
4119
  } else {
3839
4120
  const rawValue = row[columnIndex];
3840
4121
  const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
3841
- if (joinsNotNullableMap && is(field, Column) && path14.length === 2) {
3842
- const objectName = path14[0];
4122
+ if (joinsNotNullableMap && is(field, Column) && path15.length === 2) {
4123
+ const objectName = path15[0];
3843
4124
  if (!(objectName in nullifyMap)) {
3844
4125
  nullifyMap[objectName] = value === null ? getTableName(field.table) : false;
3845
4126
  } else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) {
@@ -7786,13 +8067,13 @@ function Subscribe(postgres2, options) {
7786
8067
  }
7787
8068
  }
7788
8069
  function handle(a, b2) {
7789
- const path14 = b2.relation.schema + "." + b2.relation.table;
8070
+ const path15 = b2.relation.schema + "." + b2.relation.table;
7790
8071
  call("*", a, b2);
7791
- call("*:" + path14, a, b2);
7792
- b2.relation.keys.length && call("*:" + path14 + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2);
8072
+ call("*:" + path15, a, b2);
8073
+ b2.relation.keys.length && call("*:" + path15 + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2);
7793
8074
  call(b2.command, a, b2);
7794
- call(b2.command + ":" + path14, a, b2);
7795
- b2.relation.keys.length && call(b2.command + ":" + path14 + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2);
8075
+ call(b2.command + ":" + path15, a, b2);
8076
+ b2.relation.keys.length && call(b2.command + ":" + path15 + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2);
7796
8077
  }
7797
8078
  function pong() {
7798
8079
  const x2 = Buffer.alloc(34);
@@ -7905,8 +8186,8 @@ function parseEvent(x) {
7905
8186
  const xs = x.match(/^(\*|insert|update|delete)?:?([^.]+?\.?[^=]+)?=?(.+)?/i) || [];
7906
8187
  if (!xs)
7907
8188
  throw new Error("Malformed subscribe pattern: " + x);
7908
- const [, command, path14, key] = xs;
7909
- return (command || "*") + (path14 ? ":" + (path14.indexOf(".") === -1 ? "public." + path14 : path14) : "") + (key ? "=" + key : "");
8189
+ const [, command, path15, key] = xs;
8190
+ return (command || "*") + (path15 ? ":" + (path15.indexOf(".") === -1 ? "public." + path15 : path15) : "") + (key ? "=" + key : "");
7910
8191
  }
7911
8192
  var noop2;
7912
8193
  var init_subscribe = __esm({
@@ -7987,8 +8268,8 @@ var init_large = __esm({
7987
8268
  });
7988
8269
 
7989
8270
  // ../../node_modules/postgres/src/index.js
7990
- import os5 from "os";
7991
- import fs5 from "fs";
8271
+ import os6 from "os";
8272
+ import fs7 from "fs";
7992
8273
  function Postgres(a, b2) {
7993
8274
  const options = parseOptions(a, b2), subscribe = options.no_subscribe || Subscribe(Postgres, { ...options });
7994
8275
  let ending = false;
@@ -8044,10 +8325,10 @@ function Postgres(a, b2) {
8044
8325
  });
8045
8326
  return query;
8046
8327
  }
8047
- function file2(path14, args = [], options2 = {}) {
8328
+ function file2(path15, args = [], options2 = {}) {
8048
8329
  arguments.length === 2 && !Array.isArray(args) && (options2 = args, args = []);
8049
8330
  const query = new Query([], args, (query2) => {
8050
- fs5.readFile(path14, "utf8", (err, string4) => {
8331
+ fs7.readFile(path15, "utf8", (err, string4) => {
8051
8332
  if (err)
8052
8333
  return query2.reject(err);
8053
8334
  query2.strings = [string4];
@@ -8365,7 +8646,7 @@ function parseUrl(url2) {
8365
8646
  }
8366
8647
  function osUsername() {
8367
8648
  try {
8368
- return os5.userInfo().username;
8649
+ return os6.userInfo().username;
8369
8650
  } catch (_) {
8370
8651
  return process.env.USERNAME || process.env.USER || process.env.LOGNAME;
8371
8652
  }
@@ -8717,19 +8998,19 @@ var init_view_common2 = __esm({
8717
8998
  });
8718
8999
 
8719
9000
  // ../../node_modules/drizzle-orm/casing.js
8720
- function toSnakeCase(input) {
8721
- const words = input.replace(/['\u2019]/g, "").match(/[\da-z]+|[A-Z]+(?![a-z])|[A-Z][\da-z]+/g) ?? [];
9001
+ function toSnakeCase(input2) {
9002
+ const words = input2.replace(/['\u2019]/g, "").match(/[\da-z]+|[A-Z]+(?![a-z])|[A-Z][\da-z]+/g) ?? [];
8722
9003
  return words.map((word) => word.toLowerCase()).join("_");
8723
9004
  }
8724
- function toCamelCase(input) {
8725
- const words = input.replace(/['\u2019]/g, "").match(/[\da-z]+|[A-Z]+(?![a-z])|[A-Z][\da-z]+/g) ?? [];
9005
+ function toCamelCase(input2) {
9006
+ const words = input2.replace(/['\u2019]/g, "").match(/[\da-z]+|[A-Z]+(?![a-z])|[A-Z][\da-z]+/g) ?? [];
8726
9007
  return words.reduce((acc, word, i) => {
8727
9008
  const formattedWord = i === 0 ? word.toLowerCase() : `${word[0].toUpperCase()}${word.slice(1)}`;
8728
9009
  return acc + formattedWord;
8729
9010
  }, "");
8730
9011
  }
8731
- function noopCase(input) {
8732
- return input;
9012
+ function noopCase(input2) {
9013
+ return input2;
8733
9014
  }
8734
9015
  var CasingCache;
8735
9016
  var init_casing = __esm({
@@ -10057,7 +10338,7 @@ var init_select3 = __esm({
10057
10338
  const baseTableName = this.tableName;
10058
10339
  const tableName = getTableLikeName(table);
10059
10340
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
10060
- if (typeof tableName === "string" && this.config.joins?.some((join2) => join2.alias === tableName)) {
10341
+ if (typeof tableName === "string" && this.config.joins?.some((join3) => join3.alias === tableName)) {
10061
10342
  throw new Error(`Alias "${tableName}" is already used in this query`);
10062
10343
  }
10063
10344
  if (!this.isPartialSelect) {
@@ -11584,7 +11865,7 @@ var init_update = __esm({
11584
11865
  createJoin(joinType) {
11585
11866
  return (table, on) => {
11586
11867
  const tableName = getTableLikeName(table);
11587
- if (typeof tableName === "string" && this.config.joins.some((join2) => join2.alias === tableName)) {
11868
+ if (typeof tableName === "string" && this.config.joins.some((join3) => join3.alias === tableName)) {
11588
11869
  throw new Error(`Alias "${tableName}" is already used in this query`);
11589
11870
  }
11590
11871
  if (typeof on === "function") {
@@ -11680,10 +11961,10 @@ var init_update = __esm({
11680
11961
  const fromFields = this.getTableLikeFields(this.config.from);
11681
11962
  fields[tableName] = fromFields;
11682
11963
  }
11683
- for (const join2 of this.config.joins) {
11684
- const tableName2 = getTableLikeName(join2.table);
11685
- if (typeof tableName2 === "string" && !is(join2.table, SQL)) {
11686
- const fromFields = this.getTableLikeFields(join2.table);
11964
+ for (const join3 of this.config.joins) {
11965
+ const tableName2 = getTableLikeName(join3.table);
11966
+ if (typeof tableName2 === "string" && !is(join3.table, SQL)) {
11967
+ const fromFields = this.getTableLikeFields(join3.table);
11687
11968
  fields[tableName2] = fromFields;
11688
11969
  }
11689
11970
  }
@@ -12382,12 +12663,12 @@ var init_schema = __esm({
12382
12663
  materializedView = (name, columns) => {
12383
12664
  return pgMaterializedViewWithSchema(name, columns, this.schemaName);
12384
12665
  };
12385
- enum(enumName, input) {
12386
- return Array.isArray(input) ? pgEnumWithSchema(
12666
+ enum(enumName, input2) {
12667
+ return Array.isArray(input2) ? pgEnumWithSchema(
12387
12668
  enumName,
12388
- [...input],
12669
+ [...input2],
12389
12670
  this.schemaName
12390
- ) : pgEnumObjectWithSchema(enumName, input, this.schemaName);
12671
+ ) : pgEnumObjectWithSchema(enumName, input2, this.schemaName);
12391
12672
  }
12392
12673
  sequence = (name, options) => {
12393
12674
  return pgSequenceWithSchema(name, options, this.schemaName);
@@ -12626,12 +12907,12 @@ var init_session3 = __esm({
12626
12907
  init_tracing();
12627
12908
  init_utils();
12628
12909
  PostgresJsPreparedQuery = class extends PgPreparedQuery {
12629
- constructor(client, queryString, params, logger16, cache, queryMetadata, cacheConfig, fields, _isResponseInArrayMode, customResultMapper) {
12910
+ constructor(client, queryString, params, logger17, cache, queryMetadata, cacheConfig, fields, _isResponseInArrayMode, customResultMapper) {
12630
12911
  super({ sql: queryString, params }, cache, queryMetadata, cacheConfig);
12631
12912
  this.client = client;
12632
12913
  this.queryString = queryString;
12633
12914
  this.params = params;
12634
- this.logger = logger16;
12915
+ this.logger = logger17;
12635
12916
  this.fields = fields;
12636
12917
  this._isResponseInArrayMode = _isResponseInArrayMode;
12637
12918
  this.customResultMapper = customResultMapper;
@@ -12772,11 +13053,11 @@ function construct(client, config2 = {}) {
12772
13053
  client.options.serializers["114"] = transparentParser;
12773
13054
  client.options.serializers["3802"] = transparentParser;
12774
13055
  const dialect = new PgDialect({ casing: config2.casing });
12775
- let logger16;
13056
+ let logger17;
12776
13057
  if (config2.logger === true) {
12777
- logger16 = new DefaultLogger();
13058
+ logger17 = new DefaultLogger();
12778
13059
  } else if (config2.logger !== false) {
12779
- logger16 = config2.logger;
13060
+ logger17 = config2.logger;
12780
13061
  }
12781
13062
  let schema;
12782
13063
  if (config2.schema) {
@@ -12790,7 +13071,7 @@ function construct(client, config2 = {}) {
12790
13071
  tableNamesMap: tablesConfig.tableNamesMap
12791
13072
  };
12792
13073
  }
12793
- const session = new PostgresJsSession(client, dialect, schema, { logger: logger16, cache: config2.cache });
13074
+ const session = new PostgresJsSession(client, dialect, schema, { logger: logger17, cache: config2.cache });
12794
13075
  const db2 = new PostgresJsDatabase(dialect, session, schema);
12795
13076
  db2.$client = client;
12796
13077
  db2.$cache = config2.cache;
@@ -12992,7 +13273,7 @@ __export(util_exports, {
12992
13273
  required: () => required,
12993
13274
  safeExtend: () => safeExtend,
12994
13275
  shallowClone: () => shallowClone,
12995
- slugify: () => slugify,
13276
+ slugify: () => slugify3,
12996
13277
  stringifyPrimitive: () => stringifyPrimitive,
12997
13278
  uint8ArrayToBase64: () => uint8ArrayToBase64,
12998
13279
  uint8ArrayToBase64url: () => uint8ArrayToBase64url,
@@ -13038,8 +13319,8 @@ function cached(getter) {
13038
13319
  }
13039
13320
  };
13040
13321
  }
13041
- function nullish(input) {
13042
- return input === null || input === void 0;
13322
+ function nullish(input2) {
13323
+ return input2 === null || input2 === void 0;
13043
13324
  }
13044
13325
  function cleanRegex(source) {
13045
13326
  const start = source.startsWith("^") ? 1 : 0;
@@ -13105,10 +13386,10 @@ function mergeDefs(...defs) {
13105
13386
  function cloneDef(schema) {
13106
13387
  return mergeDefs(schema._zod.def);
13107
13388
  }
13108
- function getElementAtPath(obj, path14) {
13109
- if (!path14)
13389
+ function getElementAtPath(obj, path15) {
13390
+ if (!path15)
13110
13391
  return obj;
13111
- return path14.reduce((acc, key) => acc?.[key], obj);
13392
+ return path15.reduce((acc, key) => acc?.[key], obj);
13112
13393
  }
13113
13394
  function promiseAllObject(promisesObj) {
13114
13395
  const keys = Object.keys(promisesObj);
@@ -13132,8 +13413,8 @@ function randomString(length = 10) {
13132
13413
  function esc(str) {
13133
13414
  return JSON.stringify(str);
13134
13415
  }
13135
- function slugify(input) {
13136
- return input.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
13416
+ function slugify3(input2) {
13417
+ return input2.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
13137
13418
  }
13138
13419
  function isObject(data) {
13139
13420
  return typeof data === "object" && data !== null && !Array.isArray(data);
@@ -13420,11 +13701,11 @@ function aborted(x, startIndex = 0) {
13420
13701
  }
13421
13702
  return false;
13422
13703
  }
13423
- function prefixIssues(path14, issues) {
13704
+ function prefixIssues(path15, issues) {
13424
13705
  return issues.map((iss) => {
13425
13706
  var _a2;
13426
13707
  (_a2 = iss).path ?? (_a2.path = []);
13427
- iss.path.unshift(path14);
13708
+ iss.path.unshift(path15);
13428
13709
  return iss;
13429
13710
  });
13430
13711
  }
@@ -13444,19 +13725,19 @@ function finalizeIssue(iss, ctx, config2) {
13444
13725
  }
13445
13726
  return full;
13446
13727
  }
13447
- function getSizableOrigin(input) {
13448
- if (input instanceof Set)
13728
+ function getSizableOrigin(input2) {
13729
+ if (input2 instanceof Set)
13449
13730
  return "set";
13450
- if (input instanceof Map)
13731
+ if (input2 instanceof Map)
13451
13732
  return "map";
13452
- if (input instanceof File)
13733
+ if (input2 instanceof File)
13453
13734
  return "file";
13454
13735
  return "unknown";
13455
13736
  }
13456
- function getLengthableOrigin(input) {
13457
- if (Array.isArray(input))
13737
+ function getLengthableOrigin(input2) {
13738
+ if (Array.isArray(input2))
13458
13739
  return "array";
13459
- if (typeof input === "string")
13740
+ if (typeof input2 === "string")
13460
13741
  return "string";
13461
13742
  return "unknown";
13462
13743
  }
@@ -13482,12 +13763,12 @@ function parsedType(data) {
13482
13763
  return t;
13483
13764
  }
13484
13765
  function issue(...args) {
13485
- const [iss, input, inst] = args;
13766
+ const [iss, input2, inst] = args;
13486
13767
  if (typeof iss === "string") {
13487
13768
  return {
13488
13769
  message: iss,
13489
13770
  code: "custom",
13490
- input,
13771
+ input: input2,
13491
13772
  inst
13492
13773
  };
13493
13774
  }
@@ -13666,7 +13947,7 @@ function formatError(error49, mapper = (issue2) => issue2.message) {
13666
13947
  }
13667
13948
  function treeifyError(error49, mapper = (issue2) => issue2.message) {
13668
13949
  const result = { errors: [] };
13669
- const processError = (error50, path14 = []) => {
13950
+ const processError = (error50, path15 = []) => {
13670
13951
  var _a2, _b;
13671
13952
  for (const issue2 of error50.issues) {
13672
13953
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -13676,7 +13957,7 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
13676
13957
  } else if (issue2.code === "invalid_element") {
13677
13958
  processError({ issues: issue2.issues }, issue2.path);
13678
13959
  } else {
13679
- const fullpath = [...path14, ...issue2.path];
13960
+ const fullpath = [...path15, ...issue2.path];
13680
13961
  if (fullpath.length === 0) {
13681
13962
  result.errors.push(mapper(issue2));
13682
13963
  continue;
@@ -13708,8 +13989,8 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
13708
13989
  }
13709
13990
  function toDotPath(_path) {
13710
13991
  const segs = [];
13711
- const path14 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
13712
- for (const seg of path14) {
13992
+ const path15 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
13993
+ for (const seg of path15) {
13713
13994
  if (typeof seg === "number")
13714
13995
  segs.push(`[${seg}]`);
13715
13996
  else if (typeof seg === "symbol")
@@ -14135,23 +14416,23 @@ var init_checks2 = __esm({
14135
14416
  bag.pattern = integer2;
14136
14417
  });
14137
14418
  inst._zod.check = (payload) => {
14138
- const input = payload.value;
14419
+ const input2 = payload.value;
14139
14420
  if (isInt) {
14140
- if (!Number.isInteger(input)) {
14421
+ if (!Number.isInteger(input2)) {
14141
14422
  payload.issues.push({
14142
14423
  expected: origin,
14143
14424
  format: def.format,
14144
14425
  code: "invalid_type",
14145
14426
  continue: false,
14146
- input,
14427
+ input: input2,
14147
14428
  inst
14148
14429
  });
14149
14430
  return;
14150
14431
  }
14151
- if (!Number.isSafeInteger(input)) {
14152
- if (input > 0) {
14432
+ if (!Number.isSafeInteger(input2)) {
14433
+ if (input2 > 0) {
14153
14434
  payload.issues.push({
14154
- input,
14435
+ input: input2,
14155
14436
  code: "too_big",
14156
14437
  maximum: Number.MAX_SAFE_INTEGER,
14157
14438
  note: "Integers must be within the safe integer range.",
@@ -14162,7 +14443,7 @@ var init_checks2 = __esm({
14162
14443
  });
14163
14444
  } else {
14164
14445
  payload.issues.push({
14165
- input,
14446
+ input: input2,
14166
14447
  code: "too_small",
14167
14448
  minimum: Number.MIN_SAFE_INTEGER,
14168
14449
  note: "Integers must be within the safe integer range.",
@@ -14175,10 +14456,10 @@ var init_checks2 = __esm({
14175
14456
  return;
14176
14457
  }
14177
14458
  }
14178
- if (input < minimum) {
14459
+ if (input2 < minimum) {
14179
14460
  payload.issues.push({
14180
14461
  origin: "number",
14181
- input,
14462
+ input: input2,
14182
14463
  code: "too_small",
14183
14464
  minimum,
14184
14465
  inclusive: true,
@@ -14186,10 +14467,10 @@ var init_checks2 = __esm({
14186
14467
  continue: !def.abort
14187
14468
  });
14188
14469
  }
14189
- if (input > maximum) {
14470
+ if (input2 > maximum) {
14190
14471
  payload.issues.push({
14191
14472
  origin: "number",
14192
- input,
14473
+ input: input2,
14193
14474
  code: "too_big",
14194
14475
  maximum,
14195
14476
  inclusive: true,
@@ -14209,11 +14490,11 @@ var init_checks2 = __esm({
14209
14490
  bag.maximum = maximum;
14210
14491
  });
14211
14492
  inst._zod.check = (payload) => {
14212
- const input = payload.value;
14213
- if (input < minimum) {
14493
+ const input2 = payload.value;
14494
+ if (input2 < minimum) {
14214
14495
  payload.issues.push({
14215
14496
  origin: "bigint",
14216
- input,
14497
+ input: input2,
14217
14498
  code: "too_small",
14218
14499
  minimum,
14219
14500
  inclusive: true,
@@ -14221,10 +14502,10 @@ var init_checks2 = __esm({
14221
14502
  continue: !def.abort
14222
14503
  });
14223
14504
  }
14224
- if (input > maximum) {
14505
+ if (input2 > maximum) {
14225
14506
  payload.issues.push({
14226
14507
  origin: "bigint",
14227
- input,
14508
+ input: input2,
14228
14509
  code: "too_big",
14229
14510
  maximum,
14230
14511
  inclusive: true,
@@ -14247,16 +14528,16 @@ var init_checks2 = __esm({
14247
14528
  inst2._zod.bag.maximum = def.maximum;
14248
14529
  });
14249
14530
  inst._zod.check = (payload) => {
14250
- const input = payload.value;
14251
- const size2 = input.size;
14531
+ const input2 = payload.value;
14532
+ const size2 = input2.size;
14252
14533
  if (size2 <= def.maximum)
14253
14534
  return;
14254
14535
  payload.issues.push({
14255
- origin: getSizableOrigin(input),
14536
+ origin: getSizableOrigin(input2),
14256
14537
  code: "too_big",
14257
14538
  maximum: def.maximum,
14258
14539
  inclusive: true,
14259
- input,
14540
+ input: input2,
14260
14541
  inst,
14261
14542
  continue: !def.abort
14262
14543
  });
@@ -14275,16 +14556,16 @@ var init_checks2 = __esm({
14275
14556
  inst2._zod.bag.minimum = def.minimum;
14276
14557
  });
14277
14558
  inst._zod.check = (payload) => {
14278
- const input = payload.value;
14279
- const size2 = input.size;
14559
+ const input2 = payload.value;
14560
+ const size2 = input2.size;
14280
14561
  if (size2 >= def.minimum)
14281
14562
  return;
14282
14563
  payload.issues.push({
14283
- origin: getSizableOrigin(input),
14564
+ origin: getSizableOrigin(input2),
14284
14565
  code: "too_small",
14285
14566
  minimum: def.minimum,
14286
14567
  inclusive: true,
14287
- input,
14568
+ input: input2,
14288
14569
  inst,
14289
14570
  continue: !def.abort
14290
14571
  });
@@ -14304,13 +14585,13 @@ var init_checks2 = __esm({
14304
14585
  bag.size = def.size;
14305
14586
  });
14306
14587
  inst._zod.check = (payload) => {
14307
- const input = payload.value;
14308
- const size2 = input.size;
14588
+ const input2 = payload.value;
14589
+ const size2 = input2.size;
14309
14590
  if (size2 === def.size)
14310
14591
  return;
14311
14592
  const tooBig = size2 > def.size;
14312
14593
  payload.issues.push({
14313
- origin: getSizableOrigin(input),
14594
+ origin: getSizableOrigin(input2),
14314
14595
  ...tooBig ? { code: "too_big", maximum: def.size } : { code: "too_small", minimum: def.size },
14315
14596
  inclusive: true,
14316
14597
  exact: true,
@@ -14333,17 +14614,17 @@ var init_checks2 = __esm({
14333
14614
  inst2._zod.bag.maximum = def.maximum;
14334
14615
  });
14335
14616
  inst._zod.check = (payload) => {
14336
- const input = payload.value;
14337
- const length = input.length;
14617
+ const input2 = payload.value;
14618
+ const length = input2.length;
14338
14619
  if (length <= def.maximum)
14339
14620
  return;
14340
- const origin = getLengthableOrigin(input);
14621
+ const origin = getLengthableOrigin(input2);
14341
14622
  payload.issues.push({
14342
14623
  origin,
14343
14624
  code: "too_big",
14344
14625
  maximum: def.maximum,
14345
14626
  inclusive: true,
14346
- input,
14627
+ input: input2,
14347
14628
  inst,
14348
14629
  continue: !def.abort
14349
14630
  });
@@ -14362,17 +14643,17 @@ var init_checks2 = __esm({
14362
14643
  inst2._zod.bag.minimum = def.minimum;
14363
14644
  });
14364
14645
  inst._zod.check = (payload) => {
14365
- const input = payload.value;
14366
- const length = input.length;
14646
+ const input2 = payload.value;
14647
+ const length = input2.length;
14367
14648
  if (length >= def.minimum)
14368
14649
  return;
14369
- const origin = getLengthableOrigin(input);
14650
+ const origin = getLengthableOrigin(input2);
14370
14651
  payload.issues.push({
14371
14652
  origin,
14372
14653
  code: "too_small",
14373
14654
  minimum: def.minimum,
14374
14655
  inclusive: true,
14375
- input,
14656
+ input: input2,
14376
14657
  inst,
14377
14658
  continue: !def.abort
14378
14659
  });
@@ -14392,11 +14673,11 @@ var init_checks2 = __esm({
14392
14673
  bag.length = def.length;
14393
14674
  });
14394
14675
  inst._zod.check = (payload) => {
14395
- const input = payload.value;
14396
- const length = input.length;
14676
+ const input2 = payload.value;
14677
+ const length = input2.length;
14397
14678
  if (length === def.length)
14398
14679
  return;
14399
- const origin = getLengthableOrigin(input);
14680
+ const origin = getLengthableOrigin(input2);
14400
14681
  const tooBig = length > def.length;
14401
14682
  payload.issues.push({
14402
14683
  origin,
@@ -14674,15 +14955,15 @@ function handleArrayResult(result, final, index2) {
14674
14955
  }
14675
14956
  final.value[index2] = result.value;
14676
14957
  }
14677
- function handlePropertyResult(result, final, key, input, isOptionalOut) {
14958
+ function handlePropertyResult(result, final, key, input2, isOptionalOut) {
14678
14959
  if (result.issues.length) {
14679
- if (isOptionalOut && !(key in input)) {
14960
+ if (isOptionalOut && !(key in input2)) {
14680
14961
  return;
14681
14962
  }
14682
14963
  final.issues.push(...prefixIssues(key, result.issues));
14683
14964
  }
14684
14965
  if (result.value === void 0) {
14685
- if (key in input) {
14966
+ if (key in input2) {
14686
14967
  final.value[key] = void 0;
14687
14968
  }
14688
14969
  } else {
@@ -14705,31 +14986,31 @@ function normalizeDef(def) {
14705
14986
  optionalKeys: new Set(okeys)
14706
14987
  };
14707
14988
  }
14708
- function handleCatchall(proms, input, payload, ctx, def, inst) {
14989
+ function handleCatchall(proms, input2, payload, ctx, def, inst) {
14709
14990
  const unrecognized = [];
14710
14991
  const keySet = def.keySet;
14711
14992
  const _catchall = def.catchall._zod;
14712
14993
  const t = _catchall.def.type;
14713
14994
  const isOptionalOut = _catchall.optout === "optional";
14714
- for (const key in input) {
14995
+ for (const key in input2) {
14715
14996
  if (keySet.has(key))
14716
14997
  continue;
14717
14998
  if (t === "never") {
14718
14999
  unrecognized.push(key);
14719
15000
  continue;
14720
15001
  }
14721
- const r = _catchall.run({ value: input[key], issues: [] }, ctx);
15002
+ const r = _catchall.run({ value: input2[key], issues: [] }, ctx);
14722
15003
  if (r instanceof Promise) {
14723
- proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input, isOptionalOut)));
15004
+ proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input2, isOptionalOut)));
14724
15005
  } else {
14725
- handlePropertyResult(r, payload, key, input, isOptionalOut);
15006
+ handlePropertyResult(r, payload, key, input2, isOptionalOut);
14726
15007
  }
14727
15008
  }
14728
15009
  if (unrecognized.length) {
14729
15010
  payload.issues.push({
14730
15011
  code: "unrecognized_keys",
14731
15012
  keys: unrecognized,
14732
- input,
15013
+ input: input2,
14733
15014
  inst
14734
15015
  });
14735
15016
  }
@@ -14872,7 +15153,7 @@ function handleTupleResult(result, final, index2) {
14872
15153
  }
14873
15154
  final.value[index2] = result.value;
14874
15155
  }
14875
- function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) {
15156
+ function handleMapResult(keyResult, valueResult, final, key, input2, inst, ctx) {
14876
15157
  if (keyResult.issues.length) {
14877
15158
  if (propertyKeyTypes.has(typeof key)) {
14878
15159
  final.issues.push(...prefixIssues(key, keyResult.issues));
@@ -14880,7 +15161,7 @@ function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) {
14880
15161
  final.issues.push({
14881
15162
  code: "invalid_key",
14882
15163
  origin: "map",
14883
- input,
15164
+ input: input2,
14884
15165
  inst,
14885
15166
  issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config()))
14886
15167
  });
@@ -14893,7 +15174,7 @@ function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) {
14893
15174
  final.issues.push({
14894
15175
  origin: "map",
14895
15176
  code: "invalid_element",
14896
- input,
15177
+ input: input2,
14897
15178
  inst,
14898
15179
  key,
14899
15180
  issues: valueResult.issues.map((iss) => finalizeIssue(iss, ctx, config()))
@@ -14908,8 +15189,8 @@ function handleSetResult(result, final) {
14908
15189
  }
14909
15190
  final.value.add(result.value);
14910
15191
  }
14911
- function handleOptionalResult(result, input) {
14912
- if (result.issues.length && input === void 0) {
15192
+ function handleOptionalResult(result, input2) {
15193
+ if (result.issues.length && input2 === void 0) {
14913
15194
  return { issues: [], value: void 0 };
14914
15195
  }
14915
15196
  return result;
@@ -14969,11 +15250,11 @@ function handleReadonlyResult(payload) {
14969
15250
  payload.value = Object.freeze(payload.value);
14970
15251
  return payload;
14971
15252
  }
14972
- function handleRefineResult(result, payload, input, inst) {
15253
+ function handleRefineResult(result, payload, input2, inst) {
14973
15254
  if (!result) {
14974
15255
  const _iss = {
14975
15256
  code: "custom",
14976
- input,
15257
+ input: input2,
14977
15258
  inst,
14978
15259
  // incorporates params.error into issue reporting
14979
15260
  path: [...inst._zod.def.path ?? []],
@@ -15386,15 +15667,15 @@ var init_schemas = __esm({
15386
15667
  payload.value = Number(payload.value);
15387
15668
  } catch (_) {
15388
15669
  }
15389
- const input = payload.value;
15390
- if (typeof input === "number" && !Number.isNaN(input) && Number.isFinite(input)) {
15670
+ const input2 = payload.value;
15671
+ if (typeof input2 === "number" && !Number.isNaN(input2) && Number.isFinite(input2)) {
15391
15672
  return payload;
15392
15673
  }
15393
- const received = typeof input === "number" ? Number.isNaN(input) ? "NaN" : !Number.isFinite(input) ? "Infinity" : void 0 : void 0;
15674
+ const received = typeof input2 === "number" ? Number.isNaN(input2) ? "NaN" : !Number.isFinite(input2) ? "Infinity" : void 0 : void 0;
15394
15675
  payload.issues.push({
15395
15676
  expected: "number",
15396
15677
  code: "invalid_type",
15397
- input,
15678
+ input: input2,
15398
15679
  inst,
15399
15680
  ...received ? { received } : {}
15400
15681
  });
@@ -15414,13 +15695,13 @@ var init_schemas = __esm({
15414
15695
  payload.value = Boolean(payload.value);
15415
15696
  } catch (_) {
15416
15697
  }
15417
- const input = payload.value;
15418
- if (typeof input === "boolean")
15698
+ const input2 = payload.value;
15699
+ if (typeof input2 === "boolean")
15419
15700
  return payload;
15420
15701
  payload.issues.push({
15421
15702
  expected: "boolean",
15422
15703
  code: "invalid_type",
15423
- input,
15704
+ input: input2,
15424
15705
  inst
15425
15706
  });
15426
15707
  return payload;
@@ -15453,13 +15734,13 @@ var init_schemas = __esm({
15453
15734
  $ZodSymbol = /* @__PURE__ */ $constructor("$ZodSymbol", (inst, def) => {
15454
15735
  $ZodType.init(inst, def);
15455
15736
  inst._zod.parse = (payload, _ctx) => {
15456
- const input = payload.value;
15457
- if (typeof input === "symbol")
15737
+ const input2 = payload.value;
15738
+ if (typeof input2 === "symbol")
15458
15739
  return payload;
15459
15740
  payload.issues.push({
15460
15741
  expected: "symbol",
15461
15742
  code: "invalid_type",
15462
- input,
15743
+ input: input2,
15463
15744
  inst
15464
15745
  });
15465
15746
  return payload;
@@ -15472,13 +15753,13 @@ var init_schemas = __esm({
15472
15753
  inst._zod.optin = "optional";
15473
15754
  inst._zod.optout = "optional";
15474
15755
  inst._zod.parse = (payload, _ctx) => {
15475
- const input = payload.value;
15476
- if (typeof input === "undefined")
15756
+ const input2 = payload.value;
15757
+ if (typeof input2 === "undefined")
15477
15758
  return payload;
15478
15759
  payload.issues.push({
15479
15760
  expected: "undefined",
15480
15761
  code: "invalid_type",
15481
- input,
15762
+ input: input2,
15482
15763
  inst
15483
15764
  });
15484
15765
  return payload;
@@ -15489,13 +15770,13 @@ var init_schemas = __esm({
15489
15770
  inst._zod.pattern = _null;
15490
15771
  inst._zod.values = /* @__PURE__ */ new Set([null]);
15491
15772
  inst._zod.parse = (payload, _ctx) => {
15492
- const input = payload.value;
15493
- if (input === null)
15773
+ const input2 = payload.value;
15774
+ if (input2 === null)
15494
15775
  return payload;
15495
15776
  payload.issues.push({
15496
15777
  expected: "null",
15497
15778
  code: "invalid_type",
15498
- input,
15779
+ input: input2,
15499
15780
  inst
15500
15781
  });
15501
15782
  return payload;
@@ -15524,13 +15805,13 @@ var init_schemas = __esm({
15524
15805
  $ZodVoid = /* @__PURE__ */ $constructor("$ZodVoid", (inst, def) => {
15525
15806
  $ZodType.init(inst, def);
15526
15807
  inst._zod.parse = (payload, _ctx) => {
15527
- const input = payload.value;
15528
- if (typeof input === "undefined")
15808
+ const input2 = payload.value;
15809
+ if (typeof input2 === "undefined")
15529
15810
  return payload;
15530
15811
  payload.issues.push({
15531
15812
  expected: "void",
15532
15813
  code: "invalid_type",
15533
- input,
15814
+ input: input2,
15534
15815
  inst
15535
15816
  });
15536
15817
  return payload;
@@ -15545,15 +15826,15 @@ var init_schemas = __esm({
15545
15826
  } catch (_err) {
15546
15827
  }
15547
15828
  }
15548
- const input = payload.value;
15549
- const isDate = input instanceof Date;
15550
- const isValidDate = isDate && !Number.isNaN(input.getTime());
15829
+ const input2 = payload.value;
15830
+ const isDate = input2 instanceof Date;
15831
+ const isValidDate = isDate && !Number.isNaN(input2.getTime());
15551
15832
  if (isValidDate)
15552
15833
  return payload;
15553
15834
  payload.issues.push({
15554
15835
  expected: "date",
15555
15836
  code: "invalid_type",
15556
- input,
15837
+ input: input2,
15557
15838
  ...isDate ? { received: "Invalid Date" } : {},
15558
15839
  inst
15559
15840
  });
@@ -15563,20 +15844,20 @@ var init_schemas = __esm({
15563
15844
  $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
15564
15845
  $ZodType.init(inst, def);
15565
15846
  inst._zod.parse = (payload, ctx) => {
15566
- const input = payload.value;
15567
- if (!Array.isArray(input)) {
15847
+ const input2 = payload.value;
15848
+ if (!Array.isArray(input2)) {
15568
15849
  payload.issues.push({
15569
15850
  expected: "array",
15570
15851
  code: "invalid_type",
15571
- input,
15852
+ input: input2,
15572
15853
  inst
15573
15854
  });
15574
15855
  return payload;
15575
15856
  }
15576
- payload.value = Array(input.length);
15857
+ payload.value = Array(input2.length);
15577
15858
  const proms = [];
15578
- for (let i = 0; i < input.length; i++) {
15579
- const item = input[i];
15859
+ for (let i = 0; i < input2.length; i++) {
15860
+ const item = input2[i];
15580
15861
  const result = def.element._zod.run({
15581
15862
  value: item,
15582
15863
  issues: []
@@ -15627,12 +15908,12 @@ var init_schemas = __esm({
15627
15908
  let value;
15628
15909
  inst._zod.parse = (payload, ctx) => {
15629
15910
  value ?? (value = _normalized.value);
15630
- const input = payload.value;
15631
- if (!isObject2(input)) {
15911
+ const input2 = payload.value;
15912
+ if (!isObject2(input2)) {
15632
15913
  payload.issues.push({
15633
15914
  expected: "object",
15634
15915
  code: "invalid_type",
15635
- input,
15916
+ input: input2,
15636
15917
  inst
15637
15918
  });
15638
15919
  return payload;
@@ -15643,17 +15924,17 @@ var init_schemas = __esm({
15643
15924
  for (const key of value.keys) {
15644
15925
  const el = shape[key];
15645
15926
  const isOptionalOut = el._zod.optout === "optional";
15646
- const r = el._zod.run({ value: input[key], issues: [] }, ctx);
15927
+ const r = el._zod.run({ value: input2[key], issues: [] }, ctx);
15647
15928
  if (r instanceof Promise) {
15648
- proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input, isOptionalOut)));
15929
+ proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input2, isOptionalOut)));
15649
15930
  } else {
15650
- handlePropertyResult(r, payload, key, input, isOptionalOut);
15931
+ handlePropertyResult(r, payload, key, input2, isOptionalOut);
15651
15932
  }
15652
15933
  }
15653
15934
  if (!catchall) {
15654
15935
  return proms.length ? Promise.all(proms).then(() => payload) : payload;
15655
15936
  }
15656
- return handleCatchall(proms, input, payload, ctx, _normalized.value, inst);
15937
+ return handleCatchall(proms, input2, payload, ctx, _normalized.value, inst);
15657
15938
  };
15658
15939
  });
15659
15940
  $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) => {
@@ -15734,12 +16015,12 @@ var init_schemas = __esm({
15734
16015
  let value;
15735
16016
  inst._zod.parse = (payload, ctx) => {
15736
16017
  value ?? (value = _normalized.value);
15737
- const input = payload.value;
15738
- if (!isObject2(input)) {
16018
+ const input2 = payload.value;
16019
+ if (!isObject2(input2)) {
15739
16020
  payload.issues.push({
15740
16021
  expected: "object",
15741
16022
  code: "invalid_type",
15742
- input,
16023
+ input: input2,
15743
16024
  inst
15744
16025
  });
15745
16026
  return payload;
@@ -15750,7 +16031,7 @@ var init_schemas = __esm({
15750
16031
  payload = fastpass(payload, ctx);
15751
16032
  if (!catchall)
15752
16033
  return payload;
15753
- return handleCatchall([], input, payload, ctx, value, inst);
16034
+ return handleCatchall([], input2, payload, ctx, value, inst);
15754
16035
  }
15755
16036
  return superParse(payload, ctx);
15756
16037
  };
@@ -15868,17 +16149,17 @@ var init_schemas = __esm({
15868
16149
  return map2;
15869
16150
  });
15870
16151
  inst._zod.parse = (payload, ctx) => {
15871
- const input = payload.value;
15872
- if (!isObject(input)) {
16152
+ const input2 = payload.value;
16153
+ if (!isObject(input2)) {
15873
16154
  payload.issues.push({
15874
16155
  code: "invalid_type",
15875
16156
  expected: "object",
15876
- input,
16157
+ input: input2,
15877
16158
  inst
15878
16159
  });
15879
16160
  return payload;
15880
16161
  }
15881
- const opt = disc.value.get(input?.[def.discriminator]);
16162
+ const opt = disc.value.get(input2?.[def.discriminator]);
15882
16163
  if (opt) {
15883
16164
  return opt._zod.run(payload, ctx);
15884
16165
  }
@@ -15890,7 +16171,7 @@ var init_schemas = __esm({
15890
16171
  errors: [],
15891
16172
  note: "No matching discriminator",
15892
16173
  discriminator: def.discriminator,
15893
- input,
16174
+ input: input2,
15894
16175
  path: [def.discriminator],
15895
16176
  inst
15896
16177
  });
@@ -15900,9 +16181,9 @@ var init_schemas = __esm({
15900
16181
  $ZodIntersection = /* @__PURE__ */ $constructor("$ZodIntersection", (inst, def) => {
15901
16182
  $ZodType.init(inst, def);
15902
16183
  inst._zod.parse = (payload, ctx) => {
15903
- const input = payload.value;
15904
- const left = def.left._zod.run({ value: input, issues: [] }, ctx);
15905
- const right = def.right._zod.run({ value: input, issues: [] }, ctx);
16184
+ const input2 = payload.value;
16185
+ const left = def.left._zod.run({ value: input2, issues: [] }, ctx);
16186
+ const right = def.right._zod.run({ value: input2, issues: [] }, ctx);
15906
16187
  const async = left instanceof Promise || right instanceof Promise;
15907
16188
  if (async) {
15908
16189
  return Promise.all([left, right]).then(([left2, right2]) => {
@@ -15916,10 +16197,10 @@ var init_schemas = __esm({
15916
16197
  $ZodType.init(inst, def);
15917
16198
  const items = def.items;
15918
16199
  inst._zod.parse = (payload, ctx) => {
15919
- const input = payload.value;
15920
- if (!Array.isArray(input)) {
16200
+ const input2 = payload.value;
16201
+ if (!Array.isArray(input2)) {
15921
16202
  payload.issues.push({
15922
- input,
16203
+ input: input2,
15923
16204
  inst,
15924
16205
  expected: "tuple",
15925
16206
  code: "invalid_type"
@@ -15931,12 +16212,12 @@ var init_schemas = __esm({
15931
16212
  const reversedIndex = [...items].reverse().findIndex((item) => item._zod.optin !== "optional");
15932
16213
  const optStart = reversedIndex === -1 ? 0 : items.length - reversedIndex;
15933
16214
  if (!def.rest) {
15934
- const tooBig = input.length > items.length;
15935
- const tooSmall = input.length < optStart - 1;
16215
+ const tooBig = input2.length > items.length;
16216
+ const tooSmall = input2.length < optStart - 1;
15936
16217
  if (tooBig || tooSmall) {
15937
16218
  payload.issues.push({
15938
16219
  ...tooBig ? { code: "too_big", maximum: items.length, inclusive: true } : { code: "too_small", minimum: items.length },
15939
- input,
16220
+ input: input2,
15940
16221
  inst,
15941
16222
  origin: "array"
15942
16223
  });
@@ -15946,12 +16227,12 @@ var init_schemas = __esm({
15946
16227
  let i = -1;
15947
16228
  for (const item of items) {
15948
16229
  i++;
15949
- if (i >= input.length) {
16230
+ if (i >= input2.length) {
15950
16231
  if (i >= optStart)
15951
16232
  continue;
15952
16233
  }
15953
16234
  const result = item._zod.run({
15954
- value: input[i],
16235
+ value: input2[i],
15955
16236
  issues: []
15956
16237
  }, ctx);
15957
16238
  if (result instanceof Promise) {
@@ -15961,7 +16242,7 @@ var init_schemas = __esm({
15961
16242
  }
15962
16243
  }
15963
16244
  if (def.rest) {
15964
- const rest = input.slice(items.length);
16245
+ const rest = input2.slice(items.length);
15965
16246
  for (const el of rest) {
15966
16247
  i++;
15967
16248
  const result = def.rest._zod.run({
@@ -15983,12 +16264,12 @@ var init_schemas = __esm({
15983
16264
  $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
15984
16265
  $ZodType.init(inst, def);
15985
16266
  inst._zod.parse = (payload, ctx) => {
15986
- const input = payload.value;
15987
- if (!isPlainObject(input)) {
16267
+ const input2 = payload.value;
16268
+ if (!isPlainObject(input2)) {
15988
16269
  payload.issues.push({
15989
16270
  expected: "record",
15990
16271
  code: "invalid_type",
15991
- input,
16272
+ input: input2,
15992
16273
  inst
15993
16274
  });
15994
16275
  return payload;
@@ -16001,7 +16282,7 @@ var init_schemas = __esm({
16001
16282
  for (const key of values2) {
16002
16283
  if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
16003
16284
  recordKeys.add(typeof key === "number" ? key.toString() : key);
16004
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
16285
+ const result = def.valueType._zod.run({ value: input2[key], issues: [] }, ctx);
16005
16286
  if (result instanceof Promise) {
16006
16287
  proms.push(result.then((result2) => {
16007
16288
  if (result2.issues.length) {
@@ -16018,7 +16299,7 @@ var init_schemas = __esm({
16018
16299
  }
16019
16300
  }
16020
16301
  let unrecognized;
16021
- for (const key in input) {
16302
+ for (const key in input2) {
16022
16303
  if (!recordKeys.has(key)) {
16023
16304
  unrecognized = unrecognized ?? [];
16024
16305
  unrecognized.push(key);
@@ -16027,14 +16308,14 @@ var init_schemas = __esm({
16027
16308
  if (unrecognized && unrecognized.length > 0) {
16028
16309
  payload.issues.push({
16029
16310
  code: "unrecognized_keys",
16030
- input,
16311
+ input: input2,
16031
16312
  inst,
16032
16313
  keys: unrecognized
16033
16314
  });
16034
16315
  }
16035
16316
  } else {
16036
16317
  payload.value = {};
16037
- for (const key of Reflect.ownKeys(input)) {
16318
+ for (const key of Reflect.ownKeys(input2)) {
16038
16319
  if (key === "__proto__")
16039
16320
  continue;
16040
16321
  let keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
@@ -16053,7 +16334,7 @@ var init_schemas = __esm({
16053
16334
  }
16054
16335
  if (keyResult.issues.length) {
16055
16336
  if (def.mode === "loose") {
16056
- payload.value[key] = input[key];
16337
+ payload.value[key] = input2[key];
16057
16338
  } else {
16058
16339
  payload.issues.push({
16059
16340
  code: "invalid_key",
@@ -16066,7 +16347,7 @@ var init_schemas = __esm({
16066
16347
  }
16067
16348
  continue;
16068
16349
  }
16069
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
16350
+ const result = def.valueType._zod.run({ value: input2[key], issues: [] }, ctx);
16070
16351
  if (result instanceof Promise) {
16071
16352
  proms.push(result.then((result2) => {
16072
16353
  if (result2.issues.length) {
@@ -16091,27 +16372,27 @@ var init_schemas = __esm({
16091
16372
  $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
16092
16373
  $ZodType.init(inst, def);
16093
16374
  inst._zod.parse = (payload, ctx) => {
16094
- const input = payload.value;
16095
- if (!(input instanceof Map)) {
16375
+ const input2 = payload.value;
16376
+ if (!(input2 instanceof Map)) {
16096
16377
  payload.issues.push({
16097
16378
  expected: "map",
16098
16379
  code: "invalid_type",
16099
- input,
16380
+ input: input2,
16100
16381
  inst
16101
16382
  });
16102
16383
  return payload;
16103
16384
  }
16104
16385
  const proms = [];
16105
16386
  payload.value = /* @__PURE__ */ new Map();
16106
- for (const [key, value] of input) {
16387
+ for (const [key, value] of input2) {
16107
16388
  const keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
16108
16389
  const valueResult = def.valueType._zod.run({ value, issues: [] }, ctx);
16109
16390
  if (keyResult instanceof Promise || valueResult instanceof Promise) {
16110
16391
  proms.push(Promise.all([keyResult, valueResult]).then(([keyResult2, valueResult2]) => {
16111
- handleMapResult(keyResult2, valueResult2, payload, key, input, inst, ctx);
16392
+ handleMapResult(keyResult2, valueResult2, payload, key, input2, inst, ctx);
16112
16393
  }));
16113
16394
  } else {
16114
- handleMapResult(keyResult, valueResult, payload, key, input, inst, ctx);
16395
+ handleMapResult(keyResult, valueResult, payload, key, input2, inst, ctx);
16115
16396
  }
16116
16397
  }
16117
16398
  if (proms.length)
@@ -16122,10 +16403,10 @@ var init_schemas = __esm({
16122
16403
  $ZodSet = /* @__PURE__ */ $constructor("$ZodSet", (inst, def) => {
16123
16404
  $ZodType.init(inst, def);
16124
16405
  inst._zod.parse = (payload, ctx) => {
16125
- const input = payload.value;
16126
- if (!(input instanceof Set)) {
16406
+ const input2 = payload.value;
16407
+ if (!(input2 instanceof Set)) {
16127
16408
  payload.issues.push({
16128
- input,
16409
+ input: input2,
16129
16410
  inst,
16130
16411
  expected: "set",
16131
16412
  code: "invalid_type"
@@ -16134,7 +16415,7 @@ var init_schemas = __esm({
16134
16415
  }
16135
16416
  const proms = [];
16136
16417
  payload.value = /* @__PURE__ */ new Set();
16137
- for (const item of input) {
16418
+ for (const item of input2) {
16138
16419
  const result = def.valueType._zod.run({ value: item, issues: [] }, ctx);
16139
16420
  if (result instanceof Promise) {
16140
16421
  proms.push(result.then((result2) => handleSetResult(result2, payload)));
@@ -16153,14 +16434,14 @@ var init_schemas = __esm({
16153
16434
  inst._zod.values = valuesSet;
16154
16435
  inst._zod.pattern = new RegExp(`^(${values2.filter((k) => propertyKeyTypes.has(typeof k)).map((o) => typeof o === "string" ? escapeRegex(o) : o.toString()).join("|")})$`);
16155
16436
  inst._zod.parse = (payload, _ctx) => {
16156
- const input = payload.value;
16157
- if (valuesSet.has(input)) {
16437
+ const input2 = payload.value;
16438
+ if (valuesSet.has(input2)) {
16158
16439
  return payload;
16159
16440
  }
16160
16441
  payload.issues.push({
16161
16442
  code: "invalid_value",
16162
16443
  values: values2,
16163
- input,
16444
+ input: input2,
16164
16445
  inst
16165
16446
  });
16166
16447
  return payload;
@@ -16175,14 +16456,14 @@ var init_schemas = __esm({
16175
16456
  inst._zod.values = values2;
16176
16457
  inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$`);
16177
16458
  inst._zod.parse = (payload, _ctx) => {
16178
- const input = payload.value;
16179
- if (values2.has(input)) {
16459
+ const input2 = payload.value;
16460
+ if (values2.has(input2)) {
16180
16461
  return payload;
16181
16462
  }
16182
16463
  payload.issues.push({
16183
16464
  code: "invalid_value",
16184
16465
  values: def.values,
16185
- input,
16466
+ input: input2,
16186
16467
  inst
16187
16468
  });
16188
16469
  return payload;
@@ -16191,13 +16472,13 @@ var init_schemas = __esm({
16191
16472
  $ZodFile = /* @__PURE__ */ $constructor("$ZodFile", (inst, def) => {
16192
16473
  $ZodType.init(inst, def);
16193
16474
  inst._zod.parse = (payload, _ctx) => {
16194
- const input = payload.value;
16195
- if (input instanceof File)
16475
+ const input2 = payload.value;
16476
+ if (input2 instanceof File)
16196
16477
  return payload;
16197
16478
  payload.issues.push({
16198
16479
  expected: "file",
16199
16480
  code: "invalid_type",
16200
- input,
16481
+ input: input2,
16201
16482
  inst
16202
16483
  });
16203
16484
  return payload;
@@ -16211,9 +16492,9 @@ var init_schemas = __esm({
16211
16492
  }
16212
16493
  const _out = def.transform(payload.value, payload);
16213
16494
  if (ctx.async) {
16214
- const output2 = _out instanceof Promise ? _out : Promise.resolve(_out);
16215
- return output2.then((output3) => {
16216
- payload.value = output3;
16495
+ const output3 = _out instanceof Promise ? _out : Promise.resolve(_out);
16496
+ return output3.then((output4) => {
16497
+ payload.value = output4;
16217
16498
  return payload;
16218
16499
  });
16219
16500
  }
@@ -16565,12 +16846,12 @@ var init_schemas = __esm({
16565
16846
  output: inst._def.output
16566
16847
  });
16567
16848
  };
16568
- inst.output = (output2) => {
16849
+ inst.output = (output3) => {
16569
16850
  const F = inst.constructor;
16570
16851
  return new F({
16571
16852
  type: "function",
16572
16853
  input: inst._def.input,
16573
- output: output2
16854
+ output: output3
16574
16855
  });
16575
16856
  };
16576
16857
  return inst;
@@ -16600,12 +16881,12 @@ var init_schemas = __esm({
16600
16881
  return payload;
16601
16882
  };
16602
16883
  inst._zod.check = (payload) => {
16603
- const input = payload.value;
16604
- const r = def.fn(input);
16884
+ const input2 = payload.value;
16885
+ const r = def.fn(input2);
16605
16886
  if (r instanceof Promise) {
16606
- return r.then((r2) => handleRefineResult(r2, payload, input, inst));
16887
+ return r.then((r2) => handleRefineResult(r2, payload, input2, inst));
16607
16888
  }
16608
- handleRefineResult(r, payload, input, inst);
16889
+ handleRefineResult(r, payload, input2, inst);
16609
16890
  return;
16610
16891
  };
16611
16892
  });
@@ -23250,23 +23531,23 @@ function _overwrite(tx) {
23250
23531
  }
23251
23532
  // @__NO_SIDE_EFFECTS__
23252
23533
  function _normalize(form) {
23253
- return /* @__PURE__ */ _overwrite((input) => input.normalize(form));
23534
+ return /* @__PURE__ */ _overwrite((input2) => input2.normalize(form));
23254
23535
  }
23255
23536
  // @__NO_SIDE_EFFECTS__
23256
23537
  function _trim() {
23257
- return /* @__PURE__ */ _overwrite((input) => input.trim());
23538
+ return /* @__PURE__ */ _overwrite((input2) => input2.trim());
23258
23539
  }
23259
23540
  // @__NO_SIDE_EFFECTS__
23260
23541
  function _toLowerCase() {
23261
- return /* @__PURE__ */ _overwrite((input) => input.toLowerCase());
23542
+ return /* @__PURE__ */ _overwrite((input2) => input2.toLowerCase());
23262
23543
  }
23263
23544
  // @__NO_SIDE_EFFECTS__
23264
23545
  function _toUpperCase() {
23265
- return /* @__PURE__ */ _overwrite((input) => input.toUpperCase());
23546
+ return /* @__PURE__ */ _overwrite((input2) => input2.toUpperCase());
23266
23547
  }
23267
23548
  // @__NO_SIDE_EFFECTS__
23268
23549
  function _slugify() {
23269
- return /* @__PURE__ */ _overwrite((input) => slugify(input));
23550
+ return /* @__PURE__ */ _overwrite((input2) => slugify3(input2));
23270
23551
  }
23271
23552
  // @__NO_SIDE_EFFECTS__
23272
23553
  function _array(Class2, element, params) {
@@ -23571,8 +23852,8 @@ function _stringbool(Classes, _params) {
23571
23852
  type: "pipe",
23572
23853
  in: stringSchema,
23573
23854
  out: booleanSchema,
23574
- transform: ((input, payload) => {
23575
- let data = input;
23855
+ transform: ((input2, payload) => {
23856
+ let data = input2;
23576
23857
  if (params.case !== "sensitive")
23577
23858
  data = data.toLowerCase();
23578
23859
  if (truthySet.has(data)) {
@@ -23591,8 +23872,8 @@ function _stringbool(Classes, _params) {
23591
23872
  return {};
23592
23873
  }
23593
23874
  }),
23594
- reverseTransform: ((input, _payload) => {
23595
- if (input === true) {
23875
+ reverseTransform: ((input2, _payload) => {
23876
+ if (input2 === true) {
23596
23877
  return truthyArray[0] || "true";
23597
23878
  } else {
23598
23879
  return falsyArray[0] || "false";
@@ -23995,9 +24276,9 @@ var init_to_json_schema = __esm({
23995
24276
  });
23996
24277
 
23997
24278
  // ../../node_modules/zod/v4/core/json-schema-processors.js
23998
- function toJSONSchema(input, params) {
23999
- if ("_idmap" in input) {
24000
- const registry2 = input;
24279
+ function toJSONSchema(input2, params) {
24280
+ if ("_idmap" in input2) {
24281
+ const registry2 = input2;
24001
24282
  const ctx2 = initializeContext({ ...params, processors: allProcessors });
24002
24283
  const defs = {};
24003
24284
  for (const entry of registry2._idmap.entries()) {
@@ -24025,9 +24306,9 @@ function toJSONSchema(input, params) {
24025
24306
  return { schemas };
24026
24307
  }
24027
24308
  const ctx = initializeContext({ ...params, processors: allProcessors });
24028
- process2(input, ctx);
24029
- extractDefs(ctx, input);
24030
- return finalize(ctx, input);
24309
+ process2(input2, ctx);
24310
+ extractDefs(ctx, input2);
24311
+ return finalize(ctx, input2);
24031
24312
  }
24032
24313
  var formatMap, stringProcessor, numberProcessor, booleanProcessor, bigintProcessor, symbolProcessor, nullProcessor, undefinedProcessor, voidProcessor, neverProcessor, anyProcessor, unknownProcessor, dateProcessor, enumProcessor, literalProcessor, nanProcessor, templateLiteralProcessor, fileProcessor, successProcessor, customProcessor, functionProcessor, transformProcessor, mapProcessor, setProcessor, arrayProcessor, objectProcessor, unionProcessor, intersectionProcessor, tupleProcessor, recordProcessor, nullableProcessor, nonoptionalProcessor, defaultProcessor, prefaultProcessor, catchProcessor, pipeProcessor, readonlyProcessor, promiseProcessor, optionalProcessor, lazyProcessor, allProcessors;
24033
24314
  var init_json_schema_processors = __esm({
@@ -26233,14 +26514,14 @@ var init_schemas2 = __esm({
26233
26514
  payload.issues.push(util_exports.issue(_issue));
26234
26515
  }
26235
26516
  };
26236
- const output2 = def.transform(payload.value, payload);
26237
- if (output2 instanceof Promise) {
26238
- return output2.then((output3) => {
26239
- payload.value = output3;
26517
+ const output3 = def.transform(payload.value, payload);
26518
+ if (output3 instanceof Promise) {
26519
+ return output3.then((output4) => {
26520
+ payload.value = output4;
26240
26521
  return payload;
26241
26522
  });
26242
26523
  }
26243
- payload.value = output2;
26524
+ payload.value = output3;
26244
26525
  return payload;
26245
26526
  };
26246
26527
  });
@@ -26403,13 +26684,13 @@ function resolveRef(ref, ctx) {
26403
26684
  if (!ref.startsWith("#")) {
26404
26685
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
26405
26686
  }
26406
- const path14 = ref.slice(1).split("/").filter(Boolean);
26407
- if (path14.length === 0) {
26687
+ const path15 = ref.slice(1).split("/").filter(Boolean);
26688
+ if (path15.length === 0) {
26408
26689
  return ctx.rootSchema;
26409
26690
  }
26410
26691
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
26411
- if (path14[0] === defsKey) {
26412
- const key = path14[1];
26692
+ if (path15[0] === defsKey) {
26693
+ const key = path15[1];
26413
26694
  if (!key || !ctx.defs[key]) {
26414
26695
  throw new Error(`Reference not found: ${ref}`);
26415
26696
  }
@@ -27331,6 +27612,10 @@ var init_users = __esm({
27331
27612
  // Public portfolio active
27332
27613
  followerDiscountPct: smallint("follower_discount_pct").default(0).notNull(),
27333
27614
  // Follower discount: 0, 5, 10, 15, 20
27615
+ // Stripe Integration
27616
+ stripeCustomerId: varchar("stripe_customer_id", { length: 255 }),
27617
+ // Stripe Customer ID (cus_xxx) for payment method reuse
27618
+ metadata: jsonb("metadata").$type().default({}),
27334
27619
  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
27335
27620
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
27336
27621
  },
@@ -28209,7 +28494,8 @@ var init_enrollments = __esm({
28209
28494
  expiresAt: timestamp("expires_at"),
28210
28495
  // Story 3.5: Preview expiration (enrolledAt + 7 days)
28211
28496
  setupChecklist: jsonb("setup_checklist").$type(),
28212
- updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
28497
+ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
28498
+ metadata: jsonb("metadata").$type().default({})
28213
28499
  },
28214
28500
  (table) => ({
28215
28501
  userIdIdx: index("enrollments_user_id_idx").on(table.userId),
@@ -33789,77 +34075,6 @@ var init_marketing = __esm({
33789
34075
  }
33790
34076
  });
33791
34077
 
33792
- // ../../packages/database/src/schema/user-credits.ts
33793
- var transactionTypeEnum, userCredits2, creditTransactions2;
33794
- var init_user_credits = __esm({
33795
- "../../packages/database/src/schema/user-credits.ts"() {
33796
- "use strict";
33797
- init_pg_core();
33798
- init_users();
33799
- transactionTypeEnum = pgEnum("transaction_type", [
33800
- "initial_grant",
33801
- // Credito inicial de $5
33802
- "purchase",
33803
- // Compra de creditos
33804
- "consumption",
33805
- // Consumo por uso de IA
33806
- "refund",
33807
- // Reembolso
33808
- "adjustment"
33809
- // Ajuste manual admin
33810
- ]);
33811
- userCredits2 = pgTable(
33812
- "user_credits",
33813
- {
33814
- id: uuid("id").primaryKey().defaultRandom(),
33815
- userId: uuid("user_id").references(() => users.id, { onDelete: "cascade" }).notNull().unique(),
33816
- /** Current balance in USD */
33817
- balance: decimal("balance", { precision: 10, scale: 4 }).notNull().default("0"),
33818
- /** Total consumed in USD (absolute value, always positive) */
33819
- totalConsumed: decimal("total_consumed", { precision: 10, scale: 4 }).notNull().default("0"),
33820
- /** Total purchased in USD */
33821
- totalPurchased: decimal("total_purchased", { precision: 10, scale: 4 }).notNull().default("0"),
33822
- createdAt: timestamp("created_at").defaultNow().notNull(),
33823
- updatedAt: timestamp("updated_at").defaultNow().notNull()
33824
- },
33825
- (table) => ({
33826
- userIdIdx: index("user_credits_user_id_idx").on(table.userId)
33827
- })
33828
- );
33829
- creditTransactions2 = pgTable(
33830
- "credit_transactions",
33831
- {
33832
- id: uuid("id").primaryKey().defaultRandom(),
33833
- userId: uuid("user_id").references(() => users.id, { onDelete: "restrict" }).notNull(),
33834
- type: transactionTypeEnum("type").notNull(),
33835
- /** Amount in USD (negative for consumption, positive for purchase/grant) */
33836
- amount: decimal("amount", { precision: 10, scale: 4 }).notNull(),
33837
- /** Balance after this transaction in USD */
33838
- balanceAfter: decimal("balance_after", { precision: 10, scale: 4 }).notNull(),
33839
- description: text("description"),
33840
- metadata: text("metadata"),
33841
- // JSON com detalhes (tokens, modelo, etc)
33842
- // Granular usage tracking columns
33843
- operation: varchar("operation", { length: 50 }),
33844
- // 'brainstorm_message', 'generation_outline', etc.
33845
- model: varchar("model", { length: 100 }),
33846
- // 'claude-sonnet-4-5-20250929'
33847
- inputTokens: integer("input_tokens"),
33848
- outputTokens: integer("output_tokens"),
33849
- latencyMs: integer("latency_ms"),
33850
- // DB FK to course_proposals preserved in migration; Drizzle ref removed for schema archival
33851
- proposalId: uuid("proposal_id"),
33852
- sessionId: uuid("session_id"),
33853
- createdAt: timestamp("created_at").defaultNow().notNull()
33854
- },
33855
- (table) => ({
33856
- userIdIdx: index("credit_transactions_user_id_idx").on(table.userId),
33857
- createdAtIdx: index("credit_transactions_created_at_idx").on(table.createdAt)
33858
- })
33859
- );
33860
- }
33861
- });
33862
-
33863
34078
  // ../../packages/database/src/schema/usage-quotas.ts
33864
34079
  var quotaChangeHistory, userUsageQuotas2, usageTierLimits2;
33865
34080
  var init_usage_quotas = __esm({
@@ -34305,74 +34520,72 @@ var init_course_variants = __esm({
34305
34520
  }
34306
34521
  });
34307
34522
 
34308
- // ../../packages/database/src/schema/_archived/matrix-translations.ts
34309
- var translationStatusEnum, translationEntityTypeEnum, matrixTranslations;
34310
- var init_matrix_translations = __esm({
34311
- "../../packages/database/src/schema/_archived/matrix-translations.ts"() {
34523
+ // ../../packages/database/src/schema/_archived/user-credits.ts
34524
+ var transactionTypeEnum, userCredits2, creditTransactions2;
34525
+ var init_user_credits = __esm({
34526
+ "../../packages/database/src/schema/_archived/user-credits.ts"() {
34312
34527
  "use strict";
34313
34528
  init_pg_core();
34314
34529
  init_users();
34315
- init_course_matrices();
34316
- translationStatusEnum = pgEnum("translation_status", [
34317
- "pending",
34318
- // Translation requested
34319
- "generating",
34320
- // AI translation in progress
34321
- "draft",
34322
- // AI generated, awaiting review
34323
- "approved",
34324
- // Creator approved
34325
- "rejected"
34326
- // Creator rejected, needs regeneration
34327
- ]);
34328
- translationEntityTypeEnum = pgEnum("translation_entity_type", [
34329
- "matrix",
34330
- // CourseMatrix (title, description, coreDocument)
34331
- "module",
34332
- // MatrixModule (title, description, lessonsContent)
34333
- "variant"
34334
- // CourseVariant (name, description)
34530
+ transactionTypeEnum = pgEnum("transaction_type", [
34531
+ "initial_grant",
34532
+ // Credito inicial de $5
34533
+ "purchase",
34534
+ // Compra de creditos
34535
+ "consumption",
34536
+ // Consumo por uso de IA
34537
+ "refund",
34538
+ // Reembolso
34539
+ "adjustment"
34540
+ // Ajuste manual admin
34335
34541
  ]);
34336
- matrixTranslations = pgTable(
34337
- "matrix_translations",
34542
+ userCredits2 = pgTable(
34543
+ "user_credits",
34338
34544
  {
34339
34545
  id: uuid("id").primaryKey().defaultRandom(),
34340
- matrixId: uuid("matrix_id").notNull().references(() => courseMatrices.id, { onDelete: "cascade" }),
34341
- creatorId: uuid("creator_id").notNull().references(() => users.id),
34342
- // Target entity
34343
- entityType: translationEntityTypeEnum("entity_type").notNull(),
34344
- entityId: uuid("entity_id").notNull(),
34345
- // ID of matrix, module, or variant
34346
- // Language
34347
- sourceLanguage: text("source_language").notNull().default("en"),
34348
- targetLanguage: text("target_language").notNull(),
34349
- // Field being translated
34350
- field: text("field").notNull(),
34351
- // 'title', 'description', 'content', 'coreDocument', etc.
34352
- // Translation content
34353
- originalContent: text("original_content").notNull(),
34354
- translatedContent: text("translated_content"),
34355
- // Status
34356
- status: translationStatusEnum("status").notNull().default("pending"),
34357
- // Review
34358
- reviewedAt: timestamp("reviewed_at"),
34359
- reviewNotes: text("review_notes"),
34360
- // Timestamps
34546
+ userId: uuid("user_id").references(() => users.id, { onDelete: "cascade" }).notNull().unique(),
34547
+ /** Current balance in USD */
34548
+ balance: decimal("balance", { precision: 10, scale: 4 }).notNull().default("0"),
34549
+ /** Total consumed in USD (absolute value, always positive) */
34550
+ totalConsumed: decimal("total_consumed", { precision: 10, scale: 4 }).notNull().default("0"),
34551
+ /** Total purchased in USD */
34552
+ totalPurchased: decimal("total_purchased", { precision: 10, scale: 4 }).notNull().default("0"),
34361
34553
  createdAt: timestamp("created_at").defaultNow().notNull(),
34362
34554
  updatedAt: timestamp("updated_at").defaultNow().notNull()
34363
34555
  },
34364
34556
  (table) => ({
34365
- matrixIdIdx: index("matrix_translations_matrix_id_idx").on(table.matrixId),
34366
- entityIdx: index("matrix_translations_entity_idx").on(table.entityType, table.entityId),
34367
- languageIdx: index("matrix_translations_language_idx").on(table.targetLanguage),
34368
- statusIdx: index("matrix_translations_status_idx").on(table.status),
34369
- // Unique constraint: one translation per entity/field/language combination
34370
- entityFieldLangUniq: uniqueIndex("matrix_translations_entity_field_lang_uniq").on(
34371
- table.entityType,
34372
- table.entityId,
34373
- table.field,
34374
- table.targetLanguage
34375
- )
34557
+ userIdIdx: index("user_credits_user_id_idx").on(table.userId)
34558
+ })
34559
+ );
34560
+ creditTransactions2 = pgTable(
34561
+ "credit_transactions",
34562
+ {
34563
+ id: uuid("id").primaryKey().defaultRandom(),
34564
+ userId: uuid("user_id").references(() => users.id, { onDelete: "restrict" }).notNull(),
34565
+ type: transactionTypeEnum("type").notNull(),
34566
+ /** Amount in USD (negative for consumption, positive for purchase/grant) */
34567
+ amount: decimal("amount", { precision: 10, scale: 4 }).notNull(),
34568
+ /** Balance after this transaction in USD */
34569
+ balanceAfter: decimal("balance_after", { precision: 10, scale: 4 }).notNull(),
34570
+ description: text("description"),
34571
+ metadata: text("metadata"),
34572
+ // JSON com detalhes (tokens, modelo, etc)
34573
+ // Granular usage tracking columns
34574
+ operation: varchar("operation", { length: 50 }),
34575
+ // 'brainstorm_message', 'generation_outline', etc.
34576
+ model: varchar("model", { length: 100 }),
34577
+ // 'claude-sonnet-4-5-20250929'
34578
+ inputTokens: integer("input_tokens"),
34579
+ outputTokens: integer("output_tokens"),
34580
+ latencyMs: integer("latency_ms"),
34581
+ // DB FK to course_proposals preserved in migration; Drizzle ref removed for schema archival
34582
+ proposalId: uuid("proposal_id"),
34583
+ sessionId: uuid("session_id"),
34584
+ createdAt: timestamp("created_at").defaultNow().notNull()
34585
+ },
34586
+ (table) => ({
34587
+ userIdIdx: index("credit_transactions_user_id_idx").on(table.userId),
34588
+ createdAtIdx: index("credit_transactions_created_at_idx").on(table.createdAt)
34376
34589
  })
34377
34590
  );
34378
34591
  }
@@ -34386,7 +34599,7 @@ var init_archived = __esm({
34386
34599
  init_course_matrices();
34387
34600
  init_matrix_modules();
34388
34601
  init_course_variants();
34389
- init_matrix_translations();
34602
+ init_user_credits();
34390
34603
  }
34391
34604
  });
34392
34605
 
@@ -35161,76 +35374,89 @@ var init_llm_analytics = __esm({
35161
35374
  init_users();
35162
35375
  init_courses3();
35163
35376
  init_llm_pricing();
35164
- llmInteractions = pgTable("llm_interactions", {
35165
- id: uuid("id").primaryKey().defaultRandom(),
35166
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
35167
- // Operation type
35168
- operationType: varchar("operation_type", { length: 50 }).notNull(),
35169
- // Provider (references llm_provider enum from llm-pricing.ts)
35170
- provider: llmProviderEnum("provider").notNull().default("anthropic"),
35171
- // Tracing
35172
- correlationId: varchar("correlation_id", { length: 64 }),
35173
- // Relationships
35174
- userId: uuid("user_id").references(() => users.id, { onDelete: "set null" }),
35175
- creatorId: uuid("creator_id").references(() => users.id, { onDelete: "set null" }),
35176
- courseId: uuid("course_id").references(() => courses.id, { onDelete: "set null" }),
35177
- sessionId: uuid("session_id"),
35178
- variantId: uuid("variant_id"),
35179
- // Denormalized from metadata for faster queries
35180
- // Request
35181
- model: varchar("model", { length: 50 }).notNull(),
35182
- promptText: text("prompt_text"),
35183
- promptTokens: integer("prompt_tokens").notNull(),
35184
- // Response
35185
- responseText: text("response_text"),
35186
- responseTokens: integer("response_tokens").notNull(),
35187
- // Cost & Revenue
35188
- costUsd: decimal("cost_usd", { precision: 10, scale: 6 }).notNull(),
35189
- revenueUsd: decimal("revenue_usd", { precision: 10, scale: 6 }).notNull().default("0"),
35190
- // Cache metrics (prompt caching)
35191
- cacheCreationTokens: integer("cache_creation_tokens").default(0),
35192
- cacheReadTokens: integer("cache_read_tokens").default(0),
35193
- cacheHit: integer("cache_hit").default(0),
35194
- // 0 = false, 1 = true (SQLite-compatible)
35195
- // Performance
35196
- latencyMs: integer("latency_ms").notNull(),
35197
- status: varchar("status", { length: 20 }).notNull(),
35198
- errorMessage: text("error_message"),
35199
- // Streaming metrics (null for non-streaming calls)
35200
- timeToFirstTokenMs: integer("time_to_first_token_ms"),
35201
- streamDurationMs: integer("stream_duration_ms"),
35202
- // Model version and metadata
35203
- modelVersion: varchar("model_version", { length: 100 }),
35204
- metadata: jsonb("metadata").$type()
35205
- }, (table) => ({
35206
- creatorIdx: index("idx_llm_interactions_creator").on(table.creatorId, table.createdAt),
35207
- operationIdx: index("idx_llm_interactions_operation").on(table.operationType, table.createdAt),
35208
- correlationIdx: index("idx_llm_interactions_correlation").on(table.correlationId),
35209
- providerIdx: index("idx_llm_interactions_provider").on(table.provider),
35210
- variantIdx: index("idx_llm_interactions_variant").on(table.variantId),
35211
- creatorVariantDateIdx: index("idx_llm_interactions_creator_variant_date").on(table.creatorId, table.variantId, table.createdAt)
35212
- }));
35213
- llmUsageDaily = pgTable("llm_usage_daily", {
35214
- date: timestamp("date", { mode: "date" }).notNull(),
35215
- operationType: varchar("operation_type", { length: 50 }).notNull(),
35216
- creatorId: uuid("creator_id").references(() => users.id, { onDelete: "restrict" }).notNull(),
35217
- // Aggregated metrics
35218
- totalRequests: integer("total_requests").notNull().default(0),
35219
- totalPromptTokens: integer("total_prompt_tokens").notNull().default(0),
35220
- totalResponseTokens: integer("total_response_tokens").notNull().default(0),
35221
- totalCostUsd: decimal("total_cost_usd", { precision: 12, scale: 4 }).notNull().default("0"),
35222
- totalRevenueUsd: decimal("total_revenue_usd", { precision: 12, scale: 4 }).notNull().default("0"),
35223
- avgLatencyMs: integer("avg_latency_ms"),
35224
- errorCount: integer("error_count").notNull().default(0),
35225
- // Cache aggregated metrics
35226
- totalCacheCreationTokens: integer("total_cache_creation_tokens").notNull().default(0),
35227
- totalCacheReadTokens: integer("total_cache_read_tokens").notNull().default(0),
35228
- totalCacheHits: integer("total_cache_hits").notNull().default(0)
35229
- }, (table) => ({
35230
- pk: primaryKey({ columns: [table.date, table.operationType, table.creatorId] }),
35231
- dateIdx: index("idx_llm_usage_daily_date").on(table.date),
35232
- creatorIdx: index("idx_llm_usage_daily_creator").on(table.creatorId, table.date)
35233
- }));
35377
+ llmInteractions = pgTable(
35378
+ "llm_interactions",
35379
+ {
35380
+ id: uuid("id").primaryKey().defaultRandom(),
35381
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
35382
+ // Operation type
35383
+ operationType: varchar("operation_type", { length: 50 }).notNull(),
35384
+ // Provider (references llm_provider enum from llm-pricing.ts)
35385
+ provider: llmProviderEnum("provider").notNull().default("anthropic"),
35386
+ // Tracing
35387
+ correlationId: varchar("correlation_id", { length: 64 }),
35388
+ // Relationships
35389
+ userId: uuid("user_id").references(() => users.id, { onDelete: "set null" }),
35390
+ creatorId: uuid("creator_id").references(() => users.id, { onDelete: "set null" }),
35391
+ courseId: uuid("course_id").references(() => courses.id, { onDelete: "set null" }),
35392
+ sessionId: uuid("session_id"),
35393
+ variantId: uuid("variant_id"),
35394
+ // Denormalized from metadata for faster queries
35395
+ // Request
35396
+ model: varchar("model", { length: 50 }).notNull(),
35397
+ promptText: text("prompt_text"),
35398
+ promptTokens: integer("prompt_tokens").notNull(),
35399
+ // Response
35400
+ responseText: text("response_text"),
35401
+ responseTokens: integer("response_tokens").notNull(),
35402
+ // Cost & Revenue
35403
+ costUsd: decimal("cost_usd", { precision: 10, scale: 6 }).notNull(),
35404
+ revenueUsd: decimal("revenue_usd", { precision: 10, scale: 6 }).notNull().default("0"),
35405
+ // Cache metrics (prompt caching)
35406
+ cacheCreationTokens: integer("cache_creation_tokens").default(0),
35407
+ cacheReadTokens: integer("cache_read_tokens").default(0),
35408
+ cacheHit: integer("cache_hit").default(0),
35409
+ // 0 = false, 1 = true (SQLite-compatible)
35410
+ // Performance
35411
+ latencyMs: integer("latency_ms").notNull(),
35412
+ status: varchar("status", { length: 20 }).notNull(),
35413
+ errorMessage: text("error_message"),
35414
+ // Streaming metrics (null for non-streaming calls)
35415
+ timeToFirstTokenMs: integer("time_to_first_token_ms"),
35416
+ streamDurationMs: integer("stream_duration_ms"),
35417
+ // Model version and metadata
35418
+ modelVersion: varchar("model_version", { length: 100 }),
35419
+ metadata: jsonb("metadata").$type()
35420
+ },
35421
+ (table) => ({
35422
+ creatorIdx: index("idx_llm_interactions_creator").on(table.creatorId, table.createdAt),
35423
+ operationIdx: index("idx_llm_interactions_operation").on(table.operationType, table.createdAt),
35424
+ correlationIdx: index("idx_llm_interactions_correlation").on(table.correlationId),
35425
+ providerIdx: index("idx_llm_interactions_provider").on(table.provider),
35426
+ variantIdx: index("idx_llm_interactions_variant").on(table.variantId),
35427
+ creatorVariantDateIdx: index("idx_llm_interactions_creator_variant_date").on(
35428
+ table.creatorId,
35429
+ table.variantId,
35430
+ table.createdAt
35431
+ )
35432
+ })
35433
+ );
35434
+ llmUsageDaily = pgTable(
35435
+ "llm_usage_daily",
35436
+ {
35437
+ date: timestamp("date", { mode: "date" }).notNull(),
35438
+ operationType: varchar("operation_type", { length: 50 }).notNull(),
35439
+ creatorId: uuid("creator_id").notNull(),
35440
+ // No FK — sentinel UUID '00000000-...' used for system-level aggregation
35441
+ // Aggregated metrics
35442
+ totalRequests: integer("total_requests").notNull().default(0),
35443
+ totalPromptTokens: integer("total_prompt_tokens").notNull().default(0),
35444
+ totalResponseTokens: integer("total_response_tokens").notNull().default(0),
35445
+ totalCostUsd: decimal("total_cost_usd", { precision: 12, scale: 4 }).notNull().default("0"),
35446
+ totalRevenueUsd: decimal("total_revenue_usd", { precision: 12, scale: 4 }).notNull().default("0"),
35447
+ avgLatencyMs: integer("avg_latency_ms"),
35448
+ errorCount: integer("error_count").notNull().default(0),
35449
+ // Cache aggregated metrics
35450
+ totalCacheCreationTokens: integer("total_cache_creation_tokens").notNull().default(0),
35451
+ totalCacheReadTokens: integer("total_cache_read_tokens").notNull().default(0),
35452
+ totalCacheHits: integer("total_cache_hits").notNull().default(0)
35453
+ },
35454
+ (table) => ({
35455
+ pk: primaryKey({ columns: [table.date, table.operationType, table.creatorId] }),
35456
+ dateIdx: index("idx_llm_usage_daily_date").on(table.date),
35457
+ creatorIdx: index("idx_llm_usage_daily_creator").on(table.creatorId, table.date)
35458
+ })
35459
+ );
35234
35460
  }
35235
35461
  });
35236
35462
 
@@ -36053,6 +36279,80 @@ var init_student_course_memory = __esm({
36053
36279
  }
36054
36280
  });
36055
36281
 
36282
+ // ../../packages/database/src/schema/student-feedback.ts
36283
+ var studentFeedbackKindEnum, studentFeedbackSurfaceEnum, studentFeedbackCategoryEnum, studentFeedback;
36284
+ var init_student_feedback = __esm({
36285
+ "../../packages/database/src/schema/student-feedback.ts"() {
36286
+ "use strict";
36287
+ init_drizzle_orm();
36288
+ init_pg_core();
36289
+ init_courses3();
36290
+ init_lessons();
36291
+ init_module_exercises();
36292
+ init_study_module_sessions();
36293
+ init_users();
36294
+ studentFeedbackKindEnum = pgEnum("student_feedback_kind", [
36295
+ "free_text",
36296
+ "lesson_pulse"
36297
+ ]);
36298
+ studentFeedbackSurfaceEnum = pgEnum("student_feedback_surface", [
36299
+ "lesson",
36300
+ "exercise",
36301
+ "chatstudy"
36302
+ ]);
36303
+ studentFeedbackCategoryEnum = pgEnum("student_feedback_category", [
36304
+ "BUG",
36305
+ "UX",
36306
+ "FEAT",
36307
+ "CONTENT",
36308
+ "PERF",
36309
+ "INTEG"
36310
+ ]);
36311
+ studentFeedback = pgTable(
36312
+ "student_feedback",
36313
+ {
36314
+ id: uuid("id").defaultRandom().primaryKey(),
36315
+ studentId: uuid("student_id").references(() => users.id, { onDelete: "cascade" }).notNull(),
36316
+ courseId: uuid("course_id").references(() => courses.id, { onDelete: "cascade" }).notNull(),
36317
+ surface: studentFeedbackSurfaceEnum("surface").notNull(),
36318
+ routeOrSlug: text("route_or_slug").notNull(),
36319
+ kind: studentFeedbackKindEnum("kind").notNull().default("free_text"),
36320
+ category: studentFeedbackCategoryEnum("category"),
36321
+ comment: text("comment"),
36322
+ rating: integer("rating"),
36323
+ lessonId: uuid("lesson_id").references(() => lessons.id, { onDelete: "set null" }),
36324
+ exerciseId: uuid("exercise_id").references(() => moduleExercises.id, { onDelete: "set null" }),
36325
+ // Current fullscreen student flow uses v2 module sessions.
36326
+ chatSessionId: uuid("chat_session_id").references(() => studyModuleSessions.id, {
36327
+ onDelete: "set null"
36328
+ }),
36329
+ capturedAt: timestamp("captured_at", { withTimezone: true }).defaultNow().notNull(),
36330
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
36331
+ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
36332
+ },
36333
+ (table) => ({
36334
+ courseCapturedAtIdx: index("student_feedback_course_captured_at_idx").on(
36335
+ table.courseId,
36336
+ table.capturedAt
36337
+ ),
36338
+ surfaceCapturedAtIdx: index("student_feedback_surface_captured_at_idx").on(
36339
+ table.surface,
36340
+ table.capturedAt
36341
+ ),
36342
+ categoryCapturedAtIdx: index("student_feedback_category_captured_at_idx").on(
36343
+ table.category,
36344
+ table.capturedAt
36345
+ ),
36346
+ studentCapturedAtIdx: index("student_feedback_student_captured_at_idx").on(
36347
+ table.studentId,
36348
+ table.capturedAt
36349
+ ),
36350
+ lessonPulseUniqueIdx: uniqueIndex("student_feedback_lesson_pulse_unique_idx").on(table.studentId, table.lessonId).where(sql`${table.kind} = 'lesson_pulse' AND ${table.lessonId} IS NOT NULL`)
36351
+ })
36352
+ );
36353
+ }
36354
+ });
36355
+
36056
36356
  // ../../packages/database/src/schema/student-module-progress.ts
36057
36357
  var moduleProgressStatusEnum, studentModuleProgress;
36058
36358
  var init_student_module_progress = __esm({
@@ -36720,7 +37020,12 @@ var init_video_intros = __esm({
36720
37020
  "minimal-dark",
36721
37021
  "gradient-bold",
36722
37022
  "corporate-clean",
36723
- "warm-organic"
37023
+ "warm-organic",
37024
+ "neon-tech",
37025
+ "playful-bright",
37026
+ "culinary-warm",
37027
+ "academic-serif",
37028
+ "music-rhythm"
36724
37029
  ]);
36725
37030
  renderJobStatusEnum = pgEnum("render_job_status", [
36726
37031
  "queued",
@@ -36746,6 +37051,8 @@ var init_video_intros = __esm({
36746
37051
  durationSeconds: integer("duration_seconds"),
36747
37052
  metadata: jsonb("metadata"),
36748
37053
  sceneConfig: jsonb("scene_config").$type(),
37054
+ generationHistory: jsonb("generation_history").default([]).$type(),
37055
+ themeOverrides: jsonb("theme_overrides").$type(),
36749
37056
  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
36750
37057
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
36751
37058
  },
@@ -37979,7 +38286,6 @@ __export(schema_exports, {
37979
38286
  creditSubscriptionStatusEnum: () => creditSubscriptionStatusEnum,
37980
38287
  creditSubscriptions: () => creditSubscriptions,
37981
38288
  creditTransactions: () => creditTransactions2,
37982
- creditTransactionsRelations: () => creditTransactionsRelations2,
37983
38289
  creditWalletTransactionTypeEnum: () => creditWalletTransactionTypeEnum,
37984
38290
  creditWalletTransactions: () => creditWalletTransactions,
37985
38291
  creditWallets: () => creditWallets,
@@ -38060,7 +38366,6 @@ __export(schema_exports, {
38060
38366
  marketingContentTypeEnum: () => marketingContentTypeEnum,
38061
38367
  matrixModules: () => matrixModules,
38062
38368
  matrixStatusEnum: () => matrixStatusEnum,
38063
- matrixTranslations: () => matrixTranslations,
38064
38369
  mcpSessions: () => mcpSessions2,
38065
38370
  mcpSessionsRelations: () => mcpSessionsRelations2,
38066
38371
  mediaAssetDomainEnum: () => mediaAssetDomainEnum,
@@ -38230,6 +38535,10 @@ __export(schema_exports, {
38230
38535
  stringifySettingValue: () => stringifySettingValue,
38231
38536
  studentCourseMemory: () => studentCourseMemory,
38232
38537
  studentCourseMemoryRelations: () => studentCourseMemoryRelations,
38538
+ studentFeedback: () => studentFeedback,
38539
+ studentFeedbackCategoryEnum: () => studentFeedbackCategoryEnum,
38540
+ studentFeedbackKindEnum: () => studentFeedbackKindEnum,
38541
+ studentFeedbackSurfaceEnum: () => studentFeedbackSurfaceEnum,
38233
38542
  studentModuleProgress: () => studentModuleProgress,
38234
38543
  studentNotes: () => studentNotes2,
38235
38544
  studentNotesRelations: () => studentNotesRelations2,
@@ -38267,8 +38576,6 @@ __export(schema_exports, {
38267
38576
  transactionsRelations: () => transactionsRelations2,
38268
38577
  transferStatusEnum: () => transferStatusEnum,
38269
38578
  transferTypeEnum: () => transferTypeEnum,
38270
- translationEntityTypeEnum: () => translationEntityTypeEnum,
38271
- translationStatusEnum: () => translationStatusEnum,
38272
38579
  tutorContentIssues: () => tutorContentIssues,
38273
38580
  tutorContentIssuesRelations: () => tutorContentIssuesRelations,
38274
38581
  tutorEvaluations: () => tutorEvaluations,
@@ -38282,7 +38589,6 @@ __export(schema_exports, {
38282
38589
  userChallengeScores: () => userChallengeScores,
38283
38590
  userChallengeScoresRelations: () => userChallengeScoresRelations,
38284
38591
  userCredits: () => userCredits2,
38285
- userCreditsRelations: () => userCreditsRelations2,
38286
38592
  userFollows: () => userFollows2,
38287
38593
  userFollowsRelations: () => userFollowsRelations2,
38288
38594
  userPathEnrollments: () => userPathEnrollments,
@@ -38319,7 +38625,7 @@ __export(schema_exports, {
38319
38625
  webhookEvents: () => webhookEvents2,
38320
38626
  wishlists: () => wishlists
38321
38627
  });
38322
- var usersRelations2, onboardingAnalyticsRelations2, accountsRelations2, sessionsRelations2, browserSessionsRelations, courseCategoriesRelations, coursesRelations2, certificatesRelations2, enrollmentsRelations2, modulesRelations2, lessonsRelations2, progressRelations2, mentorshipThreadsRelations2, mentorshipMessagesRelations2, reviewsRelations2, payoutsRelations2, payoutTransactionsRelations2, creatorApplicationsRelations2, transactionsRelations2, couponsRelations2, couponUsagesRelations2, userPreferencesRelations2, mcpSessionsRelations2, syncLogsRelations2, slashCommandAnalyticsRelations2, conceptsRelations2, badgesRelations2, userBadgesRelations2, validationAttemptsRelations2, notificationLogsRelations2, mentorshipTemplatesRelations2, notificationsRelations2, funnelEventsRelations2, courseReviewsRelations2, courseReportsRelations2, mentorshipServicesRelations2, mentorAvailabilityRelations2, mentorAvailabilityExceptionsRelations2, mentorshipSessionsRelations2, sessionParticipantsRelations2, sessionResourcesRelations2, sessionWaitlistRelations2, mentorshipTransactionsRelations2, mentorshipPackagesRelations2, mentorshipCreditsRelations2, refundAuditLogRelations2, sessionReviewsRelations2, sessionReviewVotesRelations2, communityPostsRelations2, communityCommentsRelations2, communityLikesRelations2, userFollowsRelations2, sparkChatSessionsRelations2, studyChatSessionsRelations, studyChatMessagesRelations, studyChatArtifactsRelations, studyModuleSessionsIndexRelations, studyLessonContextsIndexRelations, studyChatMessagesV2Relations, generationStateRelations2, creatorTestimonialsRelations2, marketingContentRelations2, userCreditsRelations2, creditTransactionsRelations2, brainstormingsRelations, ideasRelations, coursePublicationsRelations, publicationReviewHistoryRelations, studentNotesRelations2, learningStreaksRelations, dailyGoalsRelations, dailyGoalProgressRelations, countriesRelations, userRegionalSettingsRelations, courseProjectsRelations, sourceExtractionsRelations, projectGenerationStatesRelations, projectContentPoolRelations, projectVariantModulesRelations, exchangeRatesRelations, lessonRefinementsRelations, courseReviewSnapshotsRelations, learningPathsRelations2, pathCoursesRelations2, pathMilestonesRelations2, userPathEnrollmentsRelations, courseGraphsRelations, graphNodesRelations, graphEdgesRelations, projectTopicsRelations, graphNodeProgressRelations, creatorPortfolioCoursesRelations, portfolioViewsRelations, variationAxesRelations, creatorVariationAxesRelations, courseQaReportsRelations, studentWorkspacesRelations, projectSnapshotsRelations, tutorEvaluationsRelations, tutorContentIssuesRelations, mobileRefreshTokensRelations;
38628
+ var usersRelations2, onboardingAnalyticsRelations2, accountsRelations2, sessionsRelations2, browserSessionsRelations, courseCategoriesRelations, coursesRelations2, certificatesRelations2, enrollmentsRelations2, modulesRelations2, lessonsRelations2, progressRelations2, mentorshipThreadsRelations2, mentorshipMessagesRelations2, reviewsRelations2, payoutsRelations2, payoutTransactionsRelations2, creatorApplicationsRelations2, transactionsRelations2, couponsRelations2, couponUsagesRelations2, userPreferencesRelations2, mcpSessionsRelations2, syncLogsRelations2, slashCommandAnalyticsRelations2, conceptsRelations2, badgesRelations2, userBadgesRelations2, validationAttemptsRelations2, notificationLogsRelations2, mentorshipTemplatesRelations2, notificationsRelations2, funnelEventsRelations2, courseReviewsRelations2, courseReportsRelations2, mentorshipServicesRelations2, mentorAvailabilityRelations2, mentorAvailabilityExceptionsRelations2, mentorshipSessionsRelations2, sessionParticipantsRelations2, sessionResourcesRelations2, sessionWaitlistRelations2, mentorshipTransactionsRelations2, mentorshipPackagesRelations2, mentorshipCreditsRelations2, refundAuditLogRelations2, sessionReviewsRelations2, sessionReviewVotesRelations2, communityPostsRelations2, communityCommentsRelations2, communityLikesRelations2, userFollowsRelations2, sparkChatSessionsRelations2, studyChatSessionsRelations, studyChatMessagesRelations, studyChatArtifactsRelations, studyModuleSessionsIndexRelations, studyLessonContextsIndexRelations, studyChatMessagesV2Relations, generationStateRelations2, creatorTestimonialsRelations2, marketingContentRelations2, brainstormingsRelations, ideasRelations, coursePublicationsRelations, publicationReviewHistoryRelations, studentNotesRelations2, learningStreaksRelations, dailyGoalsRelations, dailyGoalProgressRelations, countriesRelations, userRegionalSettingsRelations, courseProjectsRelations, sourceExtractionsRelations, projectGenerationStatesRelations, projectContentPoolRelations, projectVariantModulesRelations, exchangeRatesRelations, lessonRefinementsRelations, courseReviewSnapshotsRelations, learningPathsRelations2, pathCoursesRelations2, pathMilestonesRelations2, userPathEnrollmentsRelations, courseGraphsRelations, graphNodesRelations, graphEdgesRelations, projectTopicsRelations, graphNodeProgressRelations, creatorPortfolioCoursesRelations, portfolioViewsRelations, variationAxesRelations, creatorVariationAxesRelations, courseQaReportsRelations, studentWorkspacesRelations, projectSnapshotsRelations, tutorEvaluationsRelations, tutorContentIssuesRelations, mobileRefreshTokensRelations;
38323
38629
  var init_schema3 = __esm({
38324
38630
  "../../packages/database/src/schema/index.ts"() {
38325
38631
  "use strict";
@@ -38379,7 +38685,6 @@ var init_schema3 = __esm({
38379
38685
  init_generation_state();
38380
38686
  init_security_audit_log();
38381
38687
  init_marketing();
38382
- init_user_credits();
38383
38688
  init_usage_quotas();
38384
38689
  init_brainstormings();
38385
38690
  init_ideas();
@@ -38402,6 +38707,7 @@ var init_schema3 = __esm({
38402
38707
  init_exercise_materials();
38403
38708
  init_course_knowledge_bases();
38404
38709
  init_student_course_memory();
38710
+ init_student_feedback();
38405
38711
  init_student_module_progress();
38406
38712
  init_course_projects();
38407
38713
  init_source_extractions();
@@ -38478,7 +38784,6 @@ var init_schema3 = __esm({
38478
38784
  init_study_module_sessions();
38479
38785
  init_generation_state();
38480
38786
  init_marketing();
38481
- init_user_credits();
38482
38787
  init_brainstormings();
38483
38788
  init_ideas();
38484
38789
  init_course_publications();
@@ -38592,9 +38897,6 @@ var init_schema3 = __esm({
38592
38897
  // Users this user follows
38593
38898
  // Story 21.1: Spark chat sessions
38594
38899
  sparkChatSessions: many(sparkChatSessions2),
38595
- // Creator flow: Token credits
38596
- credits: one(userCredits2),
38597
- creditTransactions: many(creditTransactions2),
38598
38900
  // Creator flow: New brainstormings
38599
38901
  brainstormings: many(brainstormings),
38600
38902
  // Creator flow: Ideas notepad
@@ -39343,18 +39645,6 @@ var init_schema3 = __esm({
39343
39645
  references: [users.id]
39344
39646
  })
39345
39647
  }));
39346
- userCreditsRelations2 = relations(userCredits2, ({ one }) => ({
39347
- user: one(users, {
39348
- fields: [userCredits2.userId],
39349
- references: [users.id]
39350
- })
39351
- }));
39352
- creditTransactionsRelations2 = relations(creditTransactions2, ({ one }) => ({
39353
- user: one(users, {
39354
- fields: [creditTransactions2.userId],
39355
- references: [users.id]
39356
- })
39357
- }));
39358
39648
  brainstormingsRelations = relations(brainstormings, ({ one }) => ({
39359
39649
  creator: one(users, {
39360
39650
  fields: [brainstormings.creatorId],
@@ -39781,7 +40071,6 @@ var init_src4 = __esm({
39781
40071
  init_platform_settings();
39782
40072
  init_marketing();
39783
40073
  init_security_audit_log();
39784
- init_user_credits();
39785
40074
  init_gamification();
39786
40075
  init_creator_portfolio_courses();
39787
40076
  init_portfolio_views();
@@ -39850,6 +40139,32 @@ var init_exercise_types = __esm({
39850
40139
  }
39851
40140
  });
39852
40141
 
40142
+ // ../../packages/tostudy-core/src/workspace/lesson-exercise-data.ts
40143
+ var init_lesson_exercise_data = __esm({
40144
+ "../../packages/tostudy-core/src/workspace/lesson-exercise-data.ts"() {
40145
+ "use strict";
40146
+ }
40147
+ });
40148
+
40149
+ // ../../packages/tostudy-core/src/learning/sync-enrollment-progress.ts
40150
+ var init_sync_enrollment_progress = __esm({
40151
+ "../../packages/tostudy-core/src/learning/sync-enrollment-progress.ts"() {
40152
+ "use strict";
40153
+ init_src4();
40154
+ init_src();
40155
+ }
40156
+ });
40157
+
40158
+ // ../../packages/tostudy-core/src/learning/study-state-sync.ts
40159
+ var DEFAULT_MAX_SESSION_TIME_SECONDS;
40160
+ var init_study_state_sync = __esm({
40161
+ "../../packages/tostudy-core/src/learning/study-state-sync.ts"() {
40162
+ "use strict";
40163
+ init_src4();
40164
+ DEFAULT_MAX_SESSION_TIME_SECONDS = 2 * 60 * 60;
40165
+ }
40166
+ });
40167
+
39853
40168
  // ../../packages/tostudy-core/src/learning/start-module-full.ts
39854
40169
  var init_start_module_full = __esm({
39855
40170
  "../../packages/tostudy-core/src/learning/start-module-full.ts"() {
@@ -39857,6 +40172,9 @@ var init_start_module_full = __esm({
39857
40172
  init_src4();
39858
40173
  init_parser();
39859
40174
  init_exercise_types();
40175
+ init_lesson_exercise_data();
40176
+ init_sync_enrollment_progress();
40177
+ init_study_state_sync();
39860
40178
  }
39861
40179
  });
39862
40180
 
@@ -39866,6 +40184,18 @@ var init_next_lesson_full = __esm({
39866
40184
  "use strict";
39867
40185
  init_src4();
39868
40186
  init_parser();
40187
+ init_lesson_exercise_data();
40188
+ init_sync_enrollment_progress();
40189
+ init_study_state_sync();
40190
+ }
40191
+ });
40192
+
40193
+ // ../../packages/tostudy-core/src/memory/student-memory.ts
40194
+ var init_student_memory = __esm({
40195
+ "../../packages/tostudy-core/src/memory/student-memory.ts"() {
40196
+ "use strict";
40197
+ init_src4();
40198
+ init_src();
39869
40199
  }
39870
40200
  });
39871
40201
 
@@ -39876,6 +40206,9 @@ var init_validate_solution_full = __esm({
39876
40206
  init_src4();
39877
40207
  init_parser();
39878
40208
  init_exercise_types();
40209
+ init_study_state_sync();
40210
+ init_sync_enrollment_progress();
40211
+ init_student_memory();
39879
40212
  }
39880
40213
  });
39881
40214
 
@@ -39935,6 +40268,7 @@ var init_learning = __esm({
39935
40268
  init_get_lesson_content_full();
39936
40269
  init_get_hint_full();
39937
40270
  init_explain_concept();
40271
+ init_sync_enrollment_progress();
39938
40272
  }
39939
40273
  });
39940
40274
 
@@ -39953,7 +40287,50 @@ var init_lessons2 = __esm({
39953
40287
 
39954
40288
  // src/commands/start.ts
39955
40289
  import { Command as Command8 } from "commander";
39956
- var logger5, startCommand;
40290
+ function buildOnboardingBlockerMessage(courseTitle, onboarding) {
40291
+ const lines = [`Onboarding obrigat\xF3rio pendente para "${courseTitle}".`];
40292
+ if (!onboarding.initReady) {
40293
+ lines.push("Execute `tostudy init` primeiro para configurar o tutor deste curso.");
40294
+ }
40295
+ if (!onboarding.workspaceReady) {
40296
+ lines.push("Execute `tostudy workspace setup` para criar o workspace local antes de iniciar.");
40297
+ }
40298
+ return lines.join("\n");
40299
+ }
40300
+ async function runStart(opts, deps = defaultDeps2) {
40301
+ try {
40302
+ const session = await deps.requireSession();
40303
+ const activeCourse = await deps.requireActiveCourse();
40304
+ const onboarding = await deps.getCourseOnboardingStatus(activeCourse);
40305
+ if (!onboarding.initReady || !onboarding.workspaceReady) {
40306
+ throw new StartBlockedError(
40307
+ buildOnboardingBlockerMessage(activeCourse.courseTitle, onboarding)
40308
+ );
40309
+ }
40310
+ const driftWarning = await deps.checkCourseDrift();
40311
+ if (driftWarning) deps.stderrWrite(driftWarning + "\n");
40312
+ const data = deps.createHttpProvider(session.apiUrl, session.token);
40313
+ const moduleData = await deps.startModule(
40314
+ { enrollmentId: activeCourse.enrollmentId },
40315
+ { data, logger: deps.logger }
40316
+ );
40317
+ await deps.setActiveCourse({ ...activeCourse, currentLessonId: moduleData.firstLesson.id });
40318
+ if (opts.json) {
40319
+ deps.output(moduleData, { json: true });
40320
+ } else {
40321
+ deps.output(deps.formatModuleStart(moduleData), { json: false });
40322
+ }
40323
+ } catch (err) {
40324
+ if (err instanceof CliApiError && err.status === 403 && err.message === "CHANNEL_MISMATCH") {
40325
+ process.stderr.write("Este curso n\xE3o est\xE1 dispon\xEDvel via CLI.\n");
40326
+ process.stderr.write("Acesse tostudy.ai para estudar este curso pelo ChatStudy.\n");
40327
+ process.exit(1);
40328
+ }
40329
+ const msg = err instanceof Error ? err.message : String(err);
40330
+ deps.error(msg);
40331
+ }
40332
+ }
40333
+ var logger6, defaultDeps2, StartBlockedError, startCommand;
39957
40334
  var init_start = __esm({
39958
40335
  "src/commands/start.ts"() {
39959
40336
  "use strict";
@@ -39961,39 +40338,34 @@ var init_start = __esm({
39961
40338
  init_lessons2();
39962
40339
  init_http2();
39963
40340
  init_session();
40341
+ init_status();
39964
40342
  init_formatter();
39965
- logger5 = createLogger("cli:start");
40343
+ logger6 = createLogger("cli:start");
40344
+ defaultDeps2 = {
40345
+ requireSession,
40346
+ requireActiveCourse,
40347
+ checkCourseDrift,
40348
+ getCourseOnboardingStatus,
40349
+ createHttpProvider,
40350
+ startModule,
40351
+ setActiveCourse,
40352
+ formatModuleStart,
40353
+ output,
40354
+ error,
40355
+ stderrWrite: (message) => process.stderr.write(message),
40356
+ logger: logger6
40357
+ };
40358
+ StartBlockedError = class extends Error {
40359
+ };
39966
40360
  startCommand = new Command8("start").description("Start (or resume) the current module of the active course").option("--json", "Output structured JSON").action(async (opts) => {
39967
- try {
39968
- const session = await requireSession();
39969
- const activeCourse = await requireActiveCourse();
39970
- const driftWarning = await checkCourseDrift();
39971
- if (driftWarning) process.stderr.write(driftWarning + "\n");
39972
- const data = createHttpProvider(session.apiUrl, session.token);
39973
- const deps = { data, logger: logger5 };
39974
- const moduleData = await startModule({ enrollmentId: activeCourse.enrollmentId }, deps);
39975
- await setActiveCourse({ ...activeCourse, currentLessonId: moduleData.firstLesson.id });
39976
- if (opts.json) {
39977
- output(moduleData, { json: true });
39978
- } else {
39979
- output(formatModuleStart(moduleData), { json: false });
39980
- }
39981
- } catch (err) {
39982
- if (err instanceof CliApiError && err.status === 403 && err.message === "CHANNEL_MISMATCH") {
39983
- process.stderr.write("Este curso n\xE3o est\xE1 dispon\xEDvel via CLI.\n");
39984
- process.stderr.write("Acesse tostudy.ai para estudar este curso pelo ChatStudy.\n");
39985
- process.exit(1);
39986
- }
39987
- const msg = err instanceof Error ? err.message : String(err);
39988
- error(msg);
39989
- }
40361
+ await runStart(opts);
39990
40362
  });
39991
40363
  }
39992
40364
  });
39993
40365
 
39994
40366
  // src/commands/start-next.ts
39995
40367
  import { Command as Command9 } from "commander";
39996
- var logger6, startNextCommand;
40368
+ var logger7, startNextCommand;
39997
40369
  var init_start_next = __esm({
39998
40370
  "src/commands/start-next.ts"() {
39999
40371
  "use strict";
@@ -40002,7 +40374,7 @@ var init_start_next = __esm({
40002
40374
  init_http2();
40003
40375
  init_session();
40004
40376
  init_formatter();
40005
- logger6 = createLogger("cli:start-next");
40377
+ logger7 = createLogger("cli:start-next");
40006
40378
  startNextCommand = new Command9("start-next").description("Transition to the next module after completing the current one").option("--json", "Output structured JSON").action(async (opts) => {
40007
40379
  try {
40008
40380
  const session = await requireSession();
@@ -40010,7 +40382,7 @@ var init_start_next = __esm({
40010
40382
  const driftWarning = await checkCourseDrift();
40011
40383
  if (driftWarning) process.stderr.write(driftWarning + "\n");
40012
40384
  const data = createHttpProvider(session.apiUrl, session.token);
40013
- const deps = { data, logger: logger6 };
40385
+ const deps = { data, logger: logger7 };
40014
40386
  const moduleData = await startNextModule({ enrollmentId: activeCourse.enrollmentId }, deps);
40015
40387
  await setActiveCourse({ ...activeCourse, currentLessonId: moduleData.firstLesson.id });
40016
40388
  if (opts.json) {
@@ -40033,7 +40405,7 @@ var init_start_next = __esm({
40033
40405
 
40034
40406
  // src/commands/next.ts
40035
40407
  import { Command as Command10 } from "commander";
40036
- var logger7, nextCommand;
40408
+ var logger8, nextCommand;
40037
40409
  var init_next = __esm({
40038
40410
  "src/commands/next.ts"() {
40039
40411
  "use strict";
@@ -40042,7 +40414,7 @@ var init_next = __esm({
40042
40414
  init_http2();
40043
40415
  init_session();
40044
40416
  init_formatter();
40045
- logger7 = createLogger("cli:next");
40417
+ logger8 = createLogger("cli:next");
40046
40418
  nextCommand = new Command10("next").description("Advance to the next lesson in the active course").option("--json", "Output structured JSON").action(async (opts) => {
40047
40419
  try {
40048
40420
  const session = await requireSession();
@@ -40050,7 +40422,7 @@ var init_next = __esm({
40050
40422
  const driftWarning = await checkCourseDrift();
40051
40423
  if (driftWarning) process.stderr.write(driftWarning + "\n");
40052
40424
  const data = createHttpProvider(session.apiUrl, session.token);
40053
- const deps = { data, logger: logger7 };
40425
+ const deps = { data, logger: logger8 };
40054
40426
  const lessonData = await nextLesson(
40055
40427
  { enrollmentId: activeCourse.enrollmentId, userConfirmation: "cli-next" },
40056
40428
  deps
@@ -40091,31 +40463,6 @@ var init_next = __esm({
40091
40463
  }
40092
40464
  });
40093
40465
 
40094
- // src/workspace/resolve.ts
40095
- import fs6 from "node:fs/promises";
40096
- import path5 from "node:path";
40097
- import os6 from "node:os";
40098
- function courseSlug(title) {
40099
- return title.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
40100
- }
40101
- async function resolveWorkspace(courseTitle, basePath = DEFAULT_BASE) {
40102
- const slug = courseSlug(courseTitle);
40103
- const candidate = path5.join(basePath, slug);
40104
- try {
40105
- await fs6.access(path5.join(candidate, ".ana-config.json"));
40106
- return { found: true, workspacePath: candidate };
40107
- } catch {
40108
- return { found: false, workspacePath: null };
40109
- }
40110
- }
40111
- var DEFAULT_BASE;
40112
- var init_resolve = __esm({
40113
- "src/workspace/resolve.ts"() {
40114
- "use strict";
40115
- DEFAULT_BASE = path5.join(os6.homedir(), "study");
40116
- }
40117
- });
40118
-
40119
40466
  // src/commands/lesson.ts
40120
40467
  import { Command as Command11 } from "commander";
40121
40468
  function adjustTimeEstimate(type, baseMinutes) {
@@ -40156,7 +40503,7 @@ function formatLessonContent(data) {
40156
40503
  }
40157
40504
  return lines.join("\n");
40158
40505
  }
40159
- var logger8, lessonCommand;
40506
+ var logger9, lessonCommand;
40160
40507
  var init_lesson = __esm({
40161
40508
  "src/commands/lesson.ts"() {
40162
40509
  "use strict";
@@ -40166,7 +40513,7 @@ var init_lesson = __esm({
40166
40513
  init_session();
40167
40514
  init_formatter();
40168
40515
  init_resolve();
40169
- logger8 = createLogger("cli:lesson");
40516
+ logger9 = createLogger("cli:lesson");
40170
40517
  lessonCommand = new Command11("lesson").description("Show the content of the current lesson").option("--json", "Output structured JSON").action(async (opts) => {
40171
40518
  try {
40172
40519
  const session = await requireSession();
@@ -40174,7 +40521,7 @@ var init_lesson = __esm({
40174
40521
  const driftWarning = await checkCourseDrift();
40175
40522
  if (driftWarning) process.stderr.write(driftWarning + "\n");
40176
40523
  const data = createHttpProvider(session.apiUrl, session.token);
40177
- const deps = { data, logger: logger8 };
40524
+ const deps = { data, logger: logger9 };
40178
40525
  const lessonId = activeCourse.currentLessonId;
40179
40526
  if (!lessonId) {
40180
40527
  error("Nenhuma li\xE7\xE3o ativa encontrada. Rode: tostudy start ou tostudy next");
@@ -40203,7 +40550,7 @@ var init_lesson = __esm({
40203
40550
 
40204
40551
  // src/commands/hint.ts
40205
40552
  import { Command as Command12 } from "commander";
40206
- var logger9, hintCommand;
40553
+ var logger10, hintCommand;
40207
40554
  var init_hint = __esm({
40208
40555
  "src/commands/hint.ts"() {
40209
40556
  "use strict";
@@ -40212,7 +40559,7 @@ var init_hint = __esm({
40212
40559
  init_http2();
40213
40560
  init_session();
40214
40561
  init_formatter();
40215
- logger9 = createLogger("cli:hint");
40562
+ logger10 = createLogger("cli:hint");
40216
40563
  hintCommand = new Command12("hint").description("Get a progressive hint for the current exercise").option("--json", "Output structured JSON").action(async (opts) => {
40217
40564
  try {
40218
40565
  const session = await requireSession();
@@ -40220,7 +40567,7 @@ var init_hint = __esm({
40220
40567
  const driftWarning = await checkCourseDrift();
40221
40568
  if (driftWarning) process.stderr.write(driftWarning + "\n");
40222
40569
  const data = createHttpProvider(session.apiUrl, session.token);
40223
- const deps = { data, logger: logger9 };
40570
+ const deps = { data, logger: logger10 };
40224
40571
  const hint = await getHint(
40225
40572
  { userId: session.userId, enrollmentId: activeCourse.enrollmentId },
40226
40573
  deps
@@ -40239,13 +40586,13 @@ var init_hint = __esm({
40239
40586
  });
40240
40587
 
40241
40588
  // ../../packages/tostudy-core/src/exercises/validate-solution.ts
40242
- async function validateSolution(input, deps) {
40243
- deps.logger.info("tostudy-core: validateSolution", { lessonId: input.lessonId });
40589
+ async function validateSolution(input2, deps) {
40590
+ deps.logger.info("tostudy-core: validateSolution", { lessonId: input2.lessonId });
40244
40591
  return deps.data.exercises.validate(
40245
- input.lessonId,
40246
- input.solution,
40247
- input.userId,
40248
- input.enrollmentId
40592
+ input2.lessonId,
40593
+ input2.solution,
40594
+ input2.userId,
40595
+ input2.enrollmentId
40249
40596
  );
40250
40597
  }
40251
40598
  var init_validate_solution = __esm({
@@ -40371,6 +40718,109 @@ function buildInitTemplate(userName, course, progress3) {
40371
40718
  lines.push("- Instru\xE7\xF5es do ToStudy \u2192 fluxo de estudo (navega\xE7\xE3o, exerc\xEDcios, valida\xE7\xE3o)");
40372
40719
  return lines.join("\n");
40373
40720
  }
40721
+ function resolveTutorMode(level) {
40722
+ if (level === "beginner") return "guided";
40723
+ if (level === "advanced") return "direct";
40724
+ return "balanced";
40725
+ }
40726
+ function formatTutorMode(mode) {
40727
+ const map2 = {
40728
+ guided: "Guiado",
40729
+ balanced: "Equilibrado",
40730
+ direct: "Direto"
40731
+ };
40732
+ return map2[mode];
40733
+ }
40734
+ function buildTutorPersonalizationSection(course, learnerProfile) {
40735
+ const mode = resolveTutorMode(course.level);
40736
+ const lines = [];
40737
+ lines.push("## 6. Personaliza\xE7\xE3o do Tutor");
40738
+ lines.push(`- Modo inicial do tutor: ${formatTutorMode(mode)}`);
40739
+ lines.push(
40740
+ "- Na primeira intera\xE7\xE3o, apresente a escolha entre cen\xE1rio fict\xEDcio do curso e adapta\xE7\xE3o ao contexto real do aluno."
40741
+ );
40742
+ lines.push(
40743
+ `- O aluno atual j\xE1 optou por: ${learnerProfile.adaptToRealContext ? "Adaptar para o contexto real" : "Manter o cen\xE1rio fict\xEDcio"}`
40744
+ );
40745
+ lines.push(`- Segmento: ${learnerProfile.segment}`);
40746
+ lines.push(`- Empresa: ${learnerProfile.company}`);
40747
+ lines.push(`- Produtos/servi\xE7os: ${learnerProfile.productsOrServices}`);
40748
+ lines.push(`- Regi\xE3o: ${learnerProfile.region}`);
40749
+ lines.push(`- Equipe: ${learnerProfile.team}`);
40750
+ lines.push(`- Objetivo: ${learnerProfile.goal}`);
40751
+ lines.push(`- N\xEDvel declarado do aluno: ${formatCourseLevel(learnerProfile.learnerLevel)}`);
40752
+ if (learnerProfile.adaptToRealContext) {
40753
+ lines.push(
40754
+ "- Use o contexto do aluno como padr\xE3o para explica\xE7\xF5es, exemplos, exerc\xEDcios e framing."
40755
+ );
40756
+ lines.push(
40757
+ "- Troque nomes, entreg\xE1veis e restri\xE7\xF5es do cen\xE1rio fict\xEDcio por equivalentes reais."
40758
+ );
40759
+ lines.push(
40760
+ "- Preserve objetivos pedag\xF3gicos, crit\xE9rios de valida\xE7\xE3o e progress\xE3o de dificuldade."
40761
+ );
40762
+ } else {
40763
+ lines.push(
40764
+ "- Preserve o cen\xE1rio fict\xEDcio como padr\xE3o e conecte os conceitos ao neg\xF3cio real quando isso ajudar."
40765
+ );
40766
+ lines.push(
40767
+ "- Se o aluno quiser migrar para o contexto real depois, oriente a rodar `tostudy init` novamente."
40768
+ );
40769
+ }
40770
+ if (mode === "guided") {
40771
+ lines.push(
40772
+ "- No modo guiado, explique o porqu\xEA de cada passo, proponha checkpoints curtos e confirme entendimento antes de avan\xE7ar."
40773
+ );
40774
+ } else if (mode === "direct") {
40775
+ lines.push(
40776
+ "- Mesmo no modo mais direto, continue sem dar a resposta pronta e preserve a progress\xE3o pedag\xF3gica."
40777
+ );
40778
+ } else {
40779
+ lines.push(
40780
+ "- No modo equilibrado, combine explica\xE7\xF5es curtas com autonomia entre checkpoints."
40781
+ );
40782
+ }
40783
+ return lines.join("\n");
40784
+ }
40785
+ function buildLearnerBrief(userName, course, learnerProfile) {
40786
+ const lines = [];
40787
+ lines.push("# ToStudy CLI \u2014 Brief do Aluno");
40788
+ lines.push("");
40789
+ lines.push("Este documento resume o contexto real do aluno para orientar exemplos e exercicios.");
40790
+ lines.push("");
40791
+ lines.push("## 1. Identificacao");
40792
+ lines.push(`- Aluno: ${userName}`);
40793
+ lines.push(`- Curso: "${course.title}"`);
40794
+ lines.push(`- Segmento: ${learnerProfile.segment}`);
40795
+ lines.push(`- Empresa: ${learnerProfile.company}`);
40796
+ lines.push(`- Produtos/servicos: ${learnerProfile.productsOrServices}`);
40797
+ lines.push(`- Regiao: ${learnerProfile.region}`);
40798
+ lines.push(`- Equipe: ${learnerProfile.team}`);
40799
+ lines.push("");
40800
+ lines.push("## 2. Objetivo e Contexto");
40801
+ lines.push(`- Objetivo principal: ${learnerProfile.goal}`);
40802
+ lines.push(`- Nivel do aluno: ${formatCourseLevel(learnerProfile.learnerLevel)}`);
40803
+ lines.push(
40804
+ `- Adaptar curso ao contexto real: ${learnerProfile.adaptToRealContext ? "Sim" : "Nao"}`
40805
+ );
40806
+ lines.push("");
40807
+ lines.push("## 3. Como usar este brief");
40808
+ lines.push("- Reutilize este contexto para adaptar exemplos, cenarios e exercicios.");
40809
+ lines.push("- Preserve a proposta pedagogica do curso antes de customizar o contexto.");
40810
+ lines.push(
40811
+ "- Se algo mudar no negocio do aluno, rode `tostudy init` novamente para atualizar o brief."
40812
+ );
40813
+ return lines.join("\n");
40814
+ }
40815
+ function buildInitArtifacts(userName, course, progress3, learnerProfile) {
40816
+ return {
40817
+ tutorInstructions: [
40818
+ buildInitTemplate(userName, course, progress3),
40819
+ buildTutorPersonalizationSection(course, learnerProfile)
40820
+ ].join("\n\n"),
40821
+ learnerBrief: buildLearnerBrief(userName, course, learnerProfile)
40822
+ };
40823
+ }
40374
40824
  var LANGUAGE_TAGS;
40375
40825
  var init_init_template = __esm({
40376
40826
  "src/output/init-template.ts"() {
@@ -40405,10 +40855,10 @@ var init_init_template = __esm({
40405
40855
  });
40406
40856
 
40407
40857
  // src/commands/validate.ts
40408
- import fs7 from "node:fs";
40409
- import path6 from "node:path";
40858
+ import fs8 from "node:fs";
40859
+ import path7 from "node:path";
40410
40860
  import { Command as Command13 } from "commander";
40411
- var logger10, validateCommand;
40861
+ var logger11, validateCommand;
40412
40862
  var init_validate = __esm({
40413
40863
  "src/commands/validate.ts"() {
40414
40864
  "use strict";
@@ -40418,7 +40868,7 @@ var init_validate = __esm({
40418
40868
  init_session();
40419
40869
  init_formatter();
40420
40870
  init_init_template();
40421
- logger10 = createLogger("cli:validate");
40871
+ logger11 = createLogger("cli:validate");
40422
40872
  validateCommand = new Command13("validate").description("Validate your solution for the current exercise").argument("[file]", "Path to the solution file to read").option("--stdin", "Read solution from stdin instead of a file").option("--json", "Output structured JSON").action(async (file2, opts) => {
40423
40873
  try {
40424
40874
  const session = await requireSession();
@@ -40431,17 +40881,17 @@ var init_validate = __esm({
40431
40881
  }
40432
40882
  let solution;
40433
40883
  if (opts.stdin) {
40434
- solution = fs7.readFileSync("/dev/stdin", "utf-8");
40884
+ solution = fs8.readFileSync("/dev/stdin", "utf-8");
40435
40885
  } else if (file2) {
40436
- if (!fs7.existsSync(file2)) {
40886
+ if (!fs8.existsSync(file2)) {
40437
40887
  error(`Arquivo n\xE3o encontrado: ${file2}`);
40438
40888
  }
40439
- solution = fs7.readFileSync(file2, "utf-8");
40889
+ solution = fs8.readFileSync(file2, "utf-8");
40440
40890
  } else {
40441
40891
  error("Forne\xE7a um arquivo ou use --stdin.\n\nExemplo: tostudy validate resposta.md");
40442
40892
  }
40443
40893
  if (file2 && activeCourse.courseTags?.length) {
40444
- const ext = path6.extname(file2).toLowerCase();
40894
+ const ext = path7.extname(file2).toLowerCase();
40445
40895
  const LANG_EXTENSIONS = {
40446
40896
  ".html": ["html", "html5"],
40447
40897
  ".css": ["css"],
@@ -40477,7 +40927,7 @@ var init_validate = __esm({
40477
40927
  }
40478
40928
  }
40479
40929
  const data = createHttpProvider(session.apiUrl, session.token);
40480
- const deps = { data, logger: logger10 };
40930
+ const deps = { data, logger: logger11 };
40481
40931
  const result = await validateSolution(
40482
40932
  {
40483
40933
  lessonId,
@@ -40565,9 +41015,290 @@ var init_menu = __esm({
40565
41015
  }
40566
41016
  });
40567
41017
 
41018
+ // src/onboarding/learner-context.ts
41019
+ import readline from "node:readline/promises";
41020
+ import { stdin as input, stdout as output2 } from "node:process";
41021
+ async function askNonEmpty(question, deps, defaultValue) {
41022
+ while (true) {
41023
+ const answer = (await deps.ask(question)).trim();
41024
+ if (answer.length > 0) return answer;
41025
+ if (defaultValue) return defaultValue;
41026
+ }
41027
+ }
41028
+ async function askChoice(question, choices, deps, defaultChoice) {
41029
+ while (true) {
41030
+ const rawAnswer = (await deps.ask(question)).trim().toLowerCase();
41031
+ if (rawAnswer.length === 0 && defaultChoice) return defaultChoice;
41032
+ const answer = rawAnswer;
41033
+ if (choices.includes(answer)) return answer;
41034
+ }
41035
+ }
41036
+ function createPromptDeps() {
41037
+ const rl = readline.createInterface({ input, output: output2 });
41038
+ return {
41039
+ ask: (question) => rl.question(question),
41040
+ write: (content) => output2.write(content),
41041
+ close: () => rl.close()
41042
+ };
41043
+ }
41044
+ async function collectLearnerContextProfileWithDeps(input2, deps) {
41045
+ const existingProfile = input2.existingProfile;
41046
+ if (existingProfile) {
41047
+ deps.write(
41048
+ [
41049
+ "",
41050
+ `Brief existente encontrado (${input2.existingSource === "web" ? "web" : "CLI"}):`,
41051
+ `- Segmento: ${existingProfile.segment}`,
41052
+ `- Empresa: ${existingProfile.company}`,
41053
+ `- Produtos/servicos: ${existingProfile.productsOrServices}`,
41054
+ `- Regiao: ${existingProfile.region}`,
41055
+ `- Equipe: ${existingProfile.team}`,
41056
+ `- Objetivo: ${existingProfile.goal}`,
41057
+ `- Nivel: ${existingProfile.learnerLevel}`,
41058
+ `- Contexto real: ${existingProfile.adaptToRealContext ? "sim" : "nao"}`,
41059
+ ""
41060
+ ].join("\n")
41061
+ );
41062
+ }
41063
+ const action = existingProfile ? await askChoice(
41064
+ "Manter este brief ou editar? (keep/edit): ",
41065
+ ["keep", "edit"],
41066
+ deps,
41067
+ "keep"
41068
+ ) : "edit";
41069
+ const baseProfile = existingProfile;
41070
+ const segment = action === "keep" && baseProfile ? baseProfile.segment : await askNonEmpty(
41071
+ baseProfile ? `Segmento ou nicho do aluno [${baseProfile.segment}]: ` : "Segmento ou nicho do aluno: ",
41072
+ deps,
41073
+ baseProfile?.segment
41074
+ );
41075
+ const company = action === "keep" && baseProfile ? baseProfile.company : await askNonEmpty(
41076
+ baseProfile ? `Empresa ou tipo de negocio [${baseProfile.company}]: ` : "Empresa ou tipo de negocio: ",
41077
+ deps,
41078
+ baseProfile?.company
41079
+ );
41080
+ const productsOrServices = action === "keep" && baseProfile ? baseProfile.productsOrServices : await askNonEmpty(
41081
+ baseProfile ? `Produtos ou servicos principais [${baseProfile.productsOrServices}]: ` : "Produtos ou servicos principais: ",
41082
+ deps,
41083
+ baseProfile?.productsOrServices
41084
+ );
41085
+ const region = action === "keep" && baseProfile ? baseProfile.region : await askNonEmpty(
41086
+ baseProfile ? `Regiao de atuacao [${baseProfile.region}]: ` : "Regiao de atuacao: ",
41087
+ deps,
41088
+ baseProfile?.region
41089
+ );
41090
+ const team = action === "keep" && baseProfile ? baseProfile.team : await askNonEmpty(
41091
+ baseProfile ? `Equipe envolvida neste contexto [${baseProfile.team}]: ` : "Equipe envolvida neste contexto: ",
41092
+ deps,
41093
+ baseProfile?.team
41094
+ );
41095
+ const goal = action === "keep" && baseProfile ? baseProfile.goal : await askNonEmpty(
41096
+ baseProfile ? `Objetivo principal com este curso [${baseProfile.goal}]: ` : "Objetivo principal com este curso: ",
41097
+ deps,
41098
+ baseProfile?.goal
41099
+ );
41100
+ const learnerLevel = action === "keep" && baseProfile ? baseProfile.learnerLevel : await askChoice(
41101
+ baseProfile ? `Nivel do aluno (beginner/intermediate/advanced) [${baseProfile.learnerLevel}]: ` : "Nivel do aluno (beginner/intermediate/advanced): ",
41102
+ ["beginner", "intermediate", "advanced"],
41103
+ deps,
41104
+ baseProfile?.learnerLevel
41105
+ );
41106
+ const adaptToRealContext = await askChoice(
41107
+ baseProfile ? `Quer que o tutor adapte exemplos ao seu contexto real ou prefere usar os cenarios ficticios do curso? (yes/no) [${baseProfile.adaptToRealContext ? "yes" : "no"}]: ` : "Quer que o tutor adapte exemplos ao seu contexto real ou prefere usar os cenarios ficticios do curso? (yes/no): ",
41108
+ ["yes", "no"],
41109
+ deps,
41110
+ baseProfile ? baseProfile.adaptToRealContext ? "yes" : "no" : void 0
41111
+ ) === "yes";
41112
+ return {
41113
+ segment,
41114
+ company,
41115
+ productsOrServices,
41116
+ region,
41117
+ team,
41118
+ goal,
41119
+ learnerLevel,
41120
+ adaptToRealContext
41121
+ };
41122
+ }
41123
+ async function collectLearnerContextProfile(input2) {
41124
+ const deps = createPromptDeps();
41125
+ try {
41126
+ return await collectLearnerContextProfileWithDeps(input2, deps);
41127
+ } finally {
41128
+ deps.close();
41129
+ }
41130
+ }
41131
+ var init_learner_context = __esm({
41132
+ "src/onboarding/learner-context.ts"() {
41133
+ "use strict";
41134
+ }
41135
+ });
41136
+
41137
+ // src/onboarding/api.ts
41138
+ async function apiFetch2(url2, token2, init) {
41139
+ const response = await fetch(url2, {
41140
+ ...init,
41141
+ headers: {
41142
+ "Content-Type": "application/json",
41143
+ Authorization: `Bearer ${token2}`,
41144
+ ...init?.headers
41145
+ }
41146
+ });
41147
+ const body = await response.json();
41148
+ if (!response.ok) {
41149
+ throw new CliApiError(body.error ?? `API error ${response.status}`, response.status);
41150
+ }
41151
+ return body;
41152
+ }
41153
+ async function getRemoteEnrollmentOnboarding(input2) {
41154
+ const url2 = new URL(`${input2.apiUrl}/api/cli/onboarding`);
41155
+ url2.searchParams.set("enrollmentId", input2.enrollmentId);
41156
+ const response = await apiFetch2(
41157
+ url2.toString(),
41158
+ input2.token
41159
+ );
41160
+ return response.onboarding;
41161
+ }
41162
+ async function saveRemoteEnrollmentOnboarding(input2) {
41163
+ const response = await apiFetch2(
41164
+ `${input2.apiUrl}/api/cli/onboarding`,
41165
+ input2.token,
41166
+ {
41167
+ method: "POST",
41168
+ body: JSON.stringify({
41169
+ enrollmentId: input2.enrollmentId,
41170
+ learnerBrief: input2.learnerBrief,
41171
+ learnerProfile: input2.learnerProfile
41172
+ })
41173
+ }
41174
+ );
41175
+ return response.onboarding;
41176
+ }
41177
+ var init_api2 = __esm({
41178
+ "src/onboarding/api.ts"() {
41179
+ "use strict";
41180
+ init_http2();
41181
+ }
41182
+ });
41183
+
40568
41184
  // src/commands/init.ts
40569
41185
  import { Command as Command15 } from "commander";
40570
- var logger11, initCommand;
41186
+ async function runInit(deps = defaultDeps3) {
41187
+ const session = await deps.getSession();
41188
+ if (!session) {
41189
+ deps.output("Nao autenticado. Rode `tostudy login` para comecar.", { json: false });
41190
+ return;
41191
+ }
41192
+ const data = deps.createHttpProvider(session.apiUrl, session.token);
41193
+ const apiDeps = { data, logger: deps.logger };
41194
+ const activeCourse = await deps.getActiveCourse();
41195
+ if (!activeCourse) {
41196
+ try {
41197
+ const courses3 = await deps.listCourses({ userId: session.userId }, apiDeps);
41198
+ const courseListStr = courses3.length > 0 ? courses3.map((c, i) => ` ${i + 1}. ${c.title} (${c.progress}%)`).join("\n") : " (nenhum curso encontrado)";
41199
+ deps.output(
41200
+ `Nenhum curso ativo.
41201
+
41202
+ Seus cursos:
41203
+ ${courseListStr}
41204
+
41205
+ Rode \`tostudy select <n\xFAmero>\` para ativar um curso.`,
41206
+ { json: false }
41207
+ );
41208
+ } catch {
41209
+ deps.output("Nenhum curso ativo. Rode `tostudy courses` e `tostudy select <n\xFAmero>`.", {
41210
+ json: false
41211
+ });
41212
+ }
41213
+ return;
41214
+ }
41215
+ let matchedCourse = null;
41216
+ try {
41217
+ const courses3 = await deps.listCourses({ userId: session.userId }, apiDeps);
41218
+ matchedCourse = courses3.find((course) => course.courseId === activeCourse.courseId) ?? null;
41219
+ } catch (err) {
41220
+ deps.logger.warn("Failed to fetch course metadata for init", { error: err });
41221
+ }
41222
+ if (!matchedCourse) {
41223
+ matchedCourse = {
41224
+ enrollmentId: activeCourse.enrollmentId,
41225
+ courseId: activeCourse.courseId,
41226
+ title: activeCourse.courseTitle,
41227
+ progress: 0,
41228
+ creatorName: "Desconhecido",
41229
+ teachingApproach: "hybrid",
41230
+ enrolledAt: /* @__PURE__ */ new Date()
41231
+ };
41232
+ }
41233
+ let progressData = null;
41234
+ try {
41235
+ progressData = await deps.getProgress({ enrollmentId: activeCourse.enrollmentId }, apiDeps);
41236
+ } catch (err) {
41237
+ deps.logger.warn("Failed to fetch progress for init", { error: err });
41238
+ }
41239
+ let remoteOnboarding = null;
41240
+ try {
41241
+ remoteOnboarding = await deps.getRemoteEnrollmentOnboarding({
41242
+ apiUrl: session.apiUrl,
41243
+ token: session.token,
41244
+ enrollmentId: activeCourse.enrollmentId
41245
+ });
41246
+ } catch (err) {
41247
+ deps.logger.warn("Failed to fetch remote enrollment onboarding", { error: err });
41248
+ }
41249
+ const onboardingState = await deps.getCourseOnboardingState(activeCourse.courseId);
41250
+ const existingProfile = remoteOnboarding?.learnerProfile ?? onboardingState?.learnerProfile;
41251
+ const existingSource = remoteOnboarding?.source ?? (onboardingState?.learnerProfile ? "cli" : void 0);
41252
+ const learnerProfile = await deps.collectLearnerContextProfile({
41253
+ userName: session.userName,
41254
+ course: matchedCourse,
41255
+ activeCourse,
41256
+ ...existingProfile ? {
41257
+ existingProfile,
41258
+ existingSource
41259
+ } : {}
41260
+ });
41261
+ const artifacts = deps.buildInitArtifacts(
41262
+ session.userName,
41263
+ matchedCourse,
41264
+ progressData,
41265
+ learnerProfile
41266
+ );
41267
+ await deps.saveRemoteEnrollmentOnboarding({
41268
+ apiUrl: session.apiUrl,
41269
+ token: session.token,
41270
+ enrollmentId: activeCourse.enrollmentId,
41271
+ learnerBrief: artifacts.learnerBrief,
41272
+ learnerProfile,
41273
+ source: "cli"
41274
+ });
41275
+ await deps.saveCourseLearnerProfile(activeCourse, learnerProfile, artifacts);
41276
+ try {
41277
+ generateInstructionFiles(
41278
+ {
41279
+ courseTitle: matchedCourse.title,
41280
+ courseId: activeCourse.courseId,
41281
+ progress: progressData?.coursePercent ?? matchedCourse.progress ?? 0,
41282
+ moduleCount: progressData?.currentModule?.totalModules ?? 0,
41283
+ lessonCount: progressData?.currentLesson?.totalLessons ?? 0
41284
+ },
41285
+ learnerProfile
41286
+ );
41287
+ deps.logger.info("Instruction files enriched with learner profile");
41288
+ } catch (err) {
41289
+ deps.logger.warn("Failed to update instruction files", {
41290
+ error: err instanceof Error ? err.message : String(err)
41291
+ });
41292
+ }
41293
+ try {
41294
+ await deps.setLastInitCourseId(activeCourse.courseId);
41295
+ } catch (err) {
41296
+ deps.logger.warn("Failed to save lastInitCourseId", { error: err });
41297
+ }
41298
+ deps.output(artifacts.tutorInstructions, { json: false });
41299
+ deps.output(artifacts.learnerBrief, { json: false });
41300
+ }
41301
+ var logger12, defaultDeps3, initCommand;
40571
41302
  var init_init = __esm({
40572
41303
  "src/commands/init.ts"() {
40573
41304
  "use strict";
@@ -40577,92 +41308,53 @@ var init_init = __esm({
40577
41308
  init_session();
40578
41309
  init_formatter();
40579
41310
  init_init_template();
40580
- logger11 = createLogger("cli:init");
40581
- initCommand = new Command15("init").description("Generate LLM tutor instructions for the active course").action(async () => {
40582
- const session = await getSession();
40583
- if (!session) {
40584
- output("N\xE3o autenticado. Rode `tostudy login` para come\xE7ar.", { json: false });
40585
- return;
40586
- }
40587
- const data = createHttpProvider(session.apiUrl, session.token);
40588
- const deps = { data, logger: logger11 };
40589
- const activeCourse = await getActiveCourse();
40590
- if (!activeCourse) {
40591
- try {
40592
- const courses3 = await listCourses({ userId: session.userId }, deps);
40593
- const courseListStr = courses3.length > 0 ? courses3.map((c, i) => ` ${i + 1}. ${c.title} (${c.progress}%)`).join("\n") : " (nenhum curso encontrado)";
40594
- output(
40595
- `Nenhum curso ativo.
40596
-
40597
- Seus cursos:
40598
- ${courseListStr}
40599
-
40600
- Rode \`tostudy select <n\xFAmero>\` para ativar um curso.`,
40601
- { json: false }
40602
- );
40603
- } catch {
40604
- output("Nenhum curso ativo. Rode `tostudy courses` e `tostudy select <n\xFAmero>`.", {
40605
- json: false
40606
- });
40607
- }
40608
- return;
40609
- }
40610
- let matchedCourse = null;
40611
- try {
40612
- const courses3 = await listCourses({ userId: session.userId }, deps);
40613
- matchedCourse = courses3.find((c) => c.courseId === activeCourse.courseId) ?? null;
40614
- } catch (err) {
40615
- logger11.warn("Failed to fetch course metadata for init", { error: err });
40616
- }
40617
- if (!matchedCourse) {
40618
- matchedCourse = {
40619
- enrollmentId: activeCourse.enrollmentId,
40620
- courseId: activeCourse.courseId,
40621
- title: activeCourse.courseTitle,
40622
- progress: 0,
40623
- creatorName: "Desconhecido",
40624
- teachingApproach: "hybrid",
40625
- enrolledAt: /* @__PURE__ */ new Date()
40626
- };
40627
- }
40628
- let progressData = null;
40629
- try {
40630
- progressData = await getProgress({ enrollmentId: activeCourse.enrollmentId }, deps);
40631
- } catch (err) {
40632
- logger11.warn("Failed to fetch progress for init", { error: err });
40633
- }
40634
- try {
40635
- await setLastInitCourseId(activeCourse.courseId);
40636
- } catch (err) {
40637
- logger11.warn("Failed to save lastInitCourseId", { error: err });
40638
- }
40639
- const template = buildInitTemplate(session.userName, matchedCourse, progressData);
40640
- output(template, { json: false });
41311
+ init_learner_context();
41312
+ init_api2();
41313
+ init_instruction_files();
41314
+ logger12 = createLogger("cli:init");
41315
+ defaultDeps3 = {
41316
+ getSession,
41317
+ getActiveCourse,
41318
+ listCourses,
41319
+ getProgress,
41320
+ getRemoteEnrollmentOnboarding,
41321
+ saveRemoteEnrollmentOnboarding,
41322
+ setLastInitCourseId,
41323
+ getCourseOnboardingState,
41324
+ collectLearnerContextProfile,
41325
+ saveCourseLearnerProfile,
41326
+ buildInitArtifacts,
41327
+ output,
41328
+ logger: logger12,
41329
+ createHttpProvider
41330
+ };
41331
+ initCommand = new Command15("init").description("Generate tutor instructions and learner brief for the active course").action(async () => {
41332
+ await runInit();
40641
41333
  });
40642
41334
  }
40643
41335
  });
40644
41336
 
40645
41337
  // ../../packages/tostudy-core/src/workspace/setup-workspace.ts
40646
- import fs8 from "node:fs/promises";
40647
- import path7 from "node:path";
40648
- async function setupWorkspace(input) {
40649
- const workspacePath = path7.join(input.basePath, input.courseSlug);
41338
+ import fs9 from "node:fs/promises";
41339
+ import path8 from "node:path";
41340
+ async function setupWorkspace(input2) {
41341
+ const workspacePath = path8.join(input2.basePath, input2.courseSlug);
40650
41342
  for (const dir of WORKSPACE_DIRS) {
40651
- await fs8.mkdir(path7.join(workspacePath, dir), { recursive: true });
41343
+ await fs9.mkdir(path8.join(workspacePath, dir), { recursive: true });
40652
41344
  }
40653
- const configPath = path7.join(workspacePath, ".ana-config.json");
41345
+ const configPath = path8.join(workspacePath, ".ana-config.json");
40654
41346
  const config2 = {
40655
- courseId: input.courseId,
40656
- courseSlug: input.courseSlug,
40657
- courseName: input.courseName,
41347
+ courseId: input2.courseId,
41348
+ courseSlug: input2.courseSlug,
41349
+ courseName: input2.courseName,
40658
41350
  workspacePath,
40659
- locale: input.locale,
41351
+ locale: input2.locale,
40660
41352
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
40661
41353
  lastAccessedAt: (/* @__PURE__ */ new Date()).toISOString()
40662
41354
  };
40663
- await fs8.writeFile(configPath, JSON.stringify(config2, null, 2), "utf-8");
41355
+ await fs9.writeFile(configPath, JSON.stringify(config2, null, 2), "utf-8");
40664
41356
  const readme = [
40665
- `# ${input.courseName}`,
41357
+ `# ${input2.courseName}`,
40666
41358
  "",
40667
41359
  "Workspace de estudo gerado pelo ToStudy.",
40668
41360
  "",
@@ -40685,7 +41377,7 @@ async function setupWorkspace(input) {
40685
41377
  "tostudy vault sync # Sincronizar progresso",
40686
41378
  "```"
40687
41379
  ].join("\n");
40688
- await fs8.writeFile(path7.join(workspacePath, "README.md"), readme, "utf-8");
41380
+ await fs9.writeFile(path8.join(workspacePath, "README.md"), readme, "utf-8");
40689
41381
  return { workspacePath, directories: WORKSPACE_DIRS, configPath };
40690
41382
  }
40691
41383
  var WORKSPACE_DIRS;
@@ -40786,8 +41478,8 @@ var init_templates = __esm({
40786
41478
  });
40787
41479
 
40788
41480
  // ../../packages/tostudy-core/src/workspace/extract-exercise.ts
40789
- import fs9 from "node:fs/promises";
40790
- import path8 from "node:path";
41481
+ import fs10 from "node:fs/promises";
41482
+ import path9 from "node:path";
40791
41483
  function padOrder(n) {
40792
41484
  return String(n).padStart(2, "0");
40793
41485
  }
@@ -40807,20 +41499,20 @@ function getStarterCode(structuredData) {
40807
41499
  const data = sd.data;
40808
41500
  return data?.starterCode ?? null;
40809
41501
  }
40810
- async function extractExercise(input) {
40811
- const { lessonData, exerciseTier, workspacePath } = input;
41502
+ async function extractExercise(input2) {
41503
+ const { lessonData, exerciseTier, workspacePath } = input2;
40812
41504
  const moduleDir = `${padOrder(lessonData.moduleOrder)}-${lessonData.moduleSlug}`;
40813
41505
  const lessonDir = `${padOrder(lessonData.lessonOrder)}-${lessonData.lessonSlug}`;
40814
- const exercisePath = path8.join(workspacePath, "exercises", moduleDir, lessonDir);
40815
- await fs9.mkdir(exercisePath, { recursive: true });
41506
+ const exercisePath = path9.join(workspacePath, "exercises", moduleDir, lessonDir);
41507
+ await fs10.mkdir(exercisePath, { recursive: true });
40816
41508
  const extractedFiles = [];
40817
41509
  let hasStarterCode = false;
40818
41510
  if (lessonData.sandpackConfig?.files) {
40819
41511
  for (const [filePath, fileData] of Object.entries(lessonData.sandpackConfig.files)) {
40820
41512
  const cleanPath = filePath.startsWith("/") ? filePath.slice(1) : filePath;
40821
- const fullPath = path8.join(exercisePath, cleanPath);
40822
- await fs9.mkdir(path8.dirname(fullPath), { recursive: true });
40823
- await fs9.writeFile(fullPath, fileData.code, "utf-8");
41513
+ const fullPath = path9.join(exercisePath, cleanPath);
41514
+ await fs10.mkdir(path9.dirname(fullPath), { recursive: true });
41515
+ await fs10.writeFile(fullPath, fileData.code, "utf-8");
40824
41516
  extractedFiles.push(cleanPath);
40825
41517
  hasStarterCode = true;
40826
41518
  }
@@ -40828,13 +41520,13 @@ async function extractExercise(input) {
40828
41520
  const tierData = getTierData(lessonData.structuredData, exerciseTier);
40829
41521
  const tierCode = tierData?.code;
40830
41522
  if (tierCode) {
40831
- await fs9.writeFile(path8.join(exercisePath, "exercise.js"), tierCode, "utf-8");
41523
+ await fs10.writeFile(path9.join(exercisePath, "exercise.js"), tierCode, "utf-8");
40832
41524
  extractedFiles.push("exercise.js");
40833
41525
  hasStarterCode = true;
40834
41526
  } else {
40835
41527
  const starter = getStarterCode(lessonData.structuredData);
40836
41528
  if (starter) {
40837
- await fs9.writeFile(path8.join(exercisePath, "exercise.js"), starter, "utf-8");
41529
+ await fs10.writeFile(path9.join(exercisePath, "exercise.js"), starter, "utf-8");
40838
41530
  extractedFiles.push("exercise.js");
40839
41531
  hasStarterCode = true;
40840
41532
  }
@@ -40852,8 +41544,8 @@ async function extractExercise(input) {
40852
41544
  ...exerciseDeps
40853
41545
  }
40854
41546
  };
40855
- await fs9.writeFile(
40856
- path8.join(exercisePath, "package.json"),
41547
+ await fs10.writeFile(
41548
+ path9.join(exercisePath, "package.json"),
40857
41549
  JSON.stringify(pkgJson, null, 2),
40858
41550
  "utf-8"
40859
41551
  );
@@ -40865,20 +41557,20 @@ async function extractExercise(input) {
40865
41557
  );
40866
41558
  for (const [configFile, configContent] of Object.entries(scaffold.configs)) {
40867
41559
  if (!sandpackFileNames.has(configFile)) {
40868
- await fs9.writeFile(path8.join(exercisePath, configFile), configContent, "utf-8");
41560
+ await fs10.writeFile(path9.join(exercisePath, configFile), configContent, "utf-8");
40869
41561
  extractedFiles.push(configFile);
40870
41562
  }
40871
41563
  }
40872
41564
  const setupSh = `#!/bin/sh
40873
41565
  ${scaffold.setupScript}
40874
41566
  `;
40875
- await fs9.writeFile(path8.join(exercisePath, "setup.sh"), setupSh, "utf-8");
41567
+ await fs10.writeFile(path9.join(exercisePath, "setup.sh"), setupSh, "utf-8");
40876
41568
  extractedFiles.push("setup.sh");
40877
41569
  }
40878
41570
  }
40879
41571
  const readme = generateReadme(lessonData, exerciseTier);
40880
- const readmePath = path8.join(exercisePath, "README.md");
40881
- await fs9.writeFile(readmePath, readme, "utf-8");
41572
+ const readmePath = path9.join(exercisePath, "README.md");
41573
+ await fs10.writeFile(readmePath, readme, "utf-8");
40882
41574
  extractedFiles.push("README.md");
40883
41575
  return {
40884
41576
  exercisePath,
@@ -40944,26 +41636,27 @@ var init_workspace = __esm({
40944
41636
  init_extract_exercise();
40945
41637
  init_export_artifact();
40946
41638
  init_templates();
41639
+ init_lesson_exercise_data();
40947
41640
  }
40948
41641
  });
40949
41642
 
40950
41643
  // src/commands/workspace.ts
40951
41644
  import { Command as Command16 } from "commander";
40952
- import path9 from "node:path";
41645
+ import path10 from "node:path";
40953
41646
  import os7 from "node:os";
40954
- import fs10 from "node:fs/promises";
40955
- var logger12, workspaceCommand;
41647
+ import fs11 from "node:fs/promises";
41648
+ var logger13, workspaceCommand;
40956
41649
  var init_workspace2 = __esm({
40957
41650
  "src/commands/workspace.ts"() {
40958
41651
  "use strict";
40959
41652
  init_src();
40960
41653
  init_workspace();
40961
41654
  init_session();
40962
- logger12 = createLogger("cli:workspace");
41655
+ logger13 = createLogger("cli:workspace");
40963
41656
  workspaceCommand = new Command16("workspace").description(
40964
41657
  "Gerenciar workspace de estudo local"
40965
41658
  );
40966
- workspaceCommand.command("setup").description("Criar estrutura do workspace para o curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path9.join(os7.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
41659
+ workspaceCommand.command("setup").description("Criar estrutura do workspace para o curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path10.join(os7.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
40967
41660
  try {
40968
41661
  await requireSession();
40969
41662
  const activeCourse = await requireActiveCourse();
@@ -40974,6 +41667,7 @@ var init_workspace2 = __esm({
40974
41667
  basePath: opts.path,
40975
41668
  locale: "pt-BR"
40976
41669
  });
41670
+ await setCourseWorkspacePath(activeCourse.courseId, result.workspacePath);
40977
41671
  if (opts.json) {
40978
41672
  process.stdout.write(JSON.stringify(result, null, 2) + "\n");
40979
41673
  } else {
@@ -40989,20 +41683,20 @@ Pr\xF3ximo passo: tostudy export
40989
41683
  );
40990
41684
  }
40991
41685
  } catch (err) {
40992
- logger12.error("workspace setup failed", { error: err });
41686
+ logger13.error("workspace setup failed", { error: err });
40993
41687
  process.stderr.write(`\u274C ${err instanceof Error ? err.message : String(err)}
40994
41688
  `);
40995
41689
  process.exit(1);
40996
41690
  }
40997
41691
  });
40998
- workspaceCommand.command("status").description("Mostrar status do workspace do curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path9.join(os7.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
41692
+ workspaceCommand.command("status").description("Mostrar status do workspace do curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path10.join(os7.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
40999
41693
  try {
41000
41694
  const activeCourse = await requireActiveCourse();
41001
41695
  const courseSlug2 = activeCourse.courseTitle.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
41002
- const workspacePath = path9.join(opts.path, courseSlug2);
41696
+ const workspacePath = path10.join(opts.path, courseSlug2);
41003
41697
  let configData = null;
41004
41698
  try {
41005
- const raw = await fs10.readFile(path9.join(workspacePath, ".ana-config.json"), "utf-8");
41699
+ const raw = await fs11.readFile(path10.join(workspacePath, ".ana-config.json"), "utf-8");
41006
41700
  configData = JSON.parse(raw);
41007
41701
  } catch {
41008
41702
  process.stderr.write(
@@ -41010,42 +41704,42 @@ Pr\xF3ximo passo: tostudy export
41010
41704
  );
41011
41705
  process.exit(1);
41012
41706
  }
41013
- const exercisesDir = path9.join(workspacePath, "exercises");
41707
+ const exercisesDir = path10.join(workspacePath, "exercises");
41014
41708
  let exerciseCount = 0;
41015
41709
  try {
41016
- const moduleDirs = await fs10.readdir(exercisesDir);
41710
+ const moduleDirs = await fs11.readdir(exercisesDir);
41017
41711
  for (const modDir of moduleDirs) {
41018
- const modPath = path9.join(exercisesDir, modDir);
41019
- const stat = await fs10.stat(modPath);
41712
+ const modPath = path10.join(exercisesDir, modDir);
41713
+ const stat = await fs11.stat(modPath);
41020
41714
  if (stat.isDirectory()) {
41021
- const lessonDirs = await fs10.readdir(modPath);
41715
+ const lessonDirs = await fs11.readdir(modPath);
41022
41716
  for (const lessonDir of lessonDirs) {
41023
- const lessonPath = path9.join(modPath, lessonDir);
41024
- const lstat = await fs10.stat(lessonPath);
41717
+ const lessonPath = path10.join(modPath, lessonDir);
41718
+ const lstat = await fs11.stat(lessonPath);
41025
41719
  if (lstat.isDirectory()) exerciseCount++;
41026
41720
  }
41027
41721
  }
41028
41722
  }
41029
41723
  } catch {
41030
41724
  }
41031
- const generatedDir = path9.join(workspacePath, "generated");
41725
+ const generatedDir = path10.join(workspacePath, "generated");
41032
41726
  let artifactCount = 0;
41033
41727
  try {
41034
- const files = await fs10.readdir(generatedDir);
41728
+ const files = await fs11.readdir(generatedDir);
41035
41729
  artifactCount = files.length;
41036
41730
  } catch {
41037
41731
  }
41038
- const diagramsDir = path9.join(workspacePath, "diagrams");
41732
+ const diagramsDir = path10.join(workspacePath, "diagrams");
41039
41733
  let diagramCount = 0;
41040
41734
  try {
41041
- const files = await fs10.readdir(diagramsDir);
41735
+ const files = await fs11.readdir(diagramsDir);
41042
41736
  diagramCount = files.length;
41043
41737
  } catch {
41044
41738
  }
41045
- const vaultDir = path9.join(workspacePath, "vault");
41739
+ const vaultDir = path10.join(workspacePath, "vault");
41046
41740
  let hasVault = false;
41047
41741
  try {
41048
- await fs10.access(path9.join(vaultDir, ".ana-vault.json"));
41742
+ await fs11.access(path10.join(vaultDir, ".ana-vault.json"));
41049
41743
  hasVault = true;
41050
41744
  } catch {
41051
41745
  }
@@ -41089,9 +41783,9 @@ Pr\xF3ximo passo: tostudy export
41089
41783
 
41090
41784
  // src/commands/export.ts
41091
41785
  import { Command as Command17 } from "commander";
41092
- import path10 from "node:path";
41786
+ import path11 from "node:path";
41093
41787
  import os8 from "node:os";
41094
- var logger13, exportCommand;
41788
+ var logger14, exportCommand;
41095
41789
  var init_export = __esm({
41096
41790
  "src/commands/export.ts"() {
41097
41791
  "use strict";
@@ -41100,8 +41794,8 @@ var init_export = __esm({
41100
41794
  init_http2();
41101
41795
  init_session();
41102
41796
  init_resolve();
41103
- logger13 = createLogger("cli:export");
41104
- exportCommand = new Command17("export").description("Extrair exerc\xEDcio atual para o workspace local").option("--tier <tier>", "Tier do exerc\xEDcio: guided, semiGuided, challenging", "guided").option("--path <dir>", "Diret\xF3rio base do workspace", path10.join(os8.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
41797
+ logger14 = createLogger("cli:export");
41798
+ exportCommand = new Command17("export").description("Extrair exerc\xEDcio atual para o workspace local").option("--tier <tier>", "Tier do exerc\xEDcio: guided, semiGuided, challenging", "guided").option("--path <dir>", "Diret\xF3rio base do workspace", path11.join(os8.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
41105
41799
  try {
41106
41800
  const session = await requireSession();
41107
41801
  const activeCourse = await requireActiveCourse();
@@ -41145,7 +41839,7 @@ ${result.files.map((f) => ` \u{1F4C4} ${f}`).join("\n")}
41145
41839
  );
41146
41840
  }
41147
41841
  } catch (err) {
41148
- logger13.error("export failed", { error: err });
41842
+ logger14.error("export failed", { error: err });
41149
41843
  process.stderr.write(`\u274C ${err instanceof Error ? err.message : String(err)}
41150
41844
  `);
41151
41845
  process.exit(1);
@@ -41157,27 +41851,27 @@ ${result.files.map((f) => ` \u{1F4C4} ${f}`).join("\n")}
41157
41851
  // src/commands/open.ts
41158
41852
  import { Command as Command18 } from "commander";
41159
41853
  import { execFile as execFile3 } from "node:child_process";
41160
- import fs11 from "node:fs/promises";
41161
- import path11 from "node:path";
41854
+ import fs12 from "node:fs/promises";
41855
+ import path12 from "node:path";
41162
41856
  import os9 from "node:os";
41163
41857
  async function findWorkspacePath(courseTitle, basePath) {
41164
41858
  const slug = courseTitle.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
41165
- const candidate = path11.join(basePath, slug);
41859
+ const candidate = path12.join(basePath, slug);
41166
41860
  try {
41167
- await fs11.access(path11.join(candidate, ".ana-config.json"));
41861
+ await fs12.access(path12.join(candidate, ".ana-config.json"));
41168
41862
  return candidate;
41169
41863
  } catch {
41170
41864
  return null;
41171
41865
  }
41172
41866
  }
41173
- var logger14, openCommand;
41867
+ var logger15, openCommand;
41174
41868
  var init_open = __esm({
41175
41869
  "src/commands/open.ts"() {
41176
41870
  "use strict";
41177
41871
  init_src();
41178
41872
  init_session();
41179
- logger14 = createLogger("cli:open");
41180
- openCommand = new Command18("open").description("Abrir workspace do curso na IDE").option("--path <dir>", "Diret\xF3rio base do workspace", path11.join(os9.homedir(), "study")).action(async (opts) => {
41873
+ logger15 = createLogger("cli:open");
41874
+ openCommand = new Command18("open").description("Abrir workspace do curso na IDE").option("--path <dir>", "Diret\xF3rio base do workspace", path12.join(os9.homedir(), "study")).action(async (opts) => {
41181
41875
  try {
41182
41876
  const activeCourse = await requireActiveCourse();
41183
41877
  const workspacePath = await findWorkspacePath(activeCourse.courseTitle, opts.path);
@@ -41190,7 +41884,7 @@ var init_open = __esm({
41190
41884
  const editor = process.env["EDITOR"] ?? "code";
41191
41885
  execFile3(editor, [workspacePath], (err) => {
41192
41886
  if (err) {
41193
- logger14.error("open failed", { editor, workspacePath });
41887
+ logger15.error("open failed", { editor, workspacePath });
41194
41888
  process.stderr.write(`\u274C Falha ao abrir: ${err.message}
41195
41889
  `);
41196
41890
  process.exit(1);
@@ -41199,7 +41893,7 @@ var init_open = __esm({
41199
41893
  `);
41200
41894
  });
41201
41895
  } catch (err) {
41202
- logger14.error("open command failed", { error: err });
41896
+ logger15.error("open command failed", { error: err });
41203
41897
  process.stderr.write(`\u274C ${err instanceof Error ? err.message : String(err)}
41204
41898
  `);
41205
41899
  process.exit(1);
@@ -41226,24 +41920,24 @@ var init_types3 = __esm({
41226
41920
  });
41227
41921
 
41228
41922
  // ../../packages/tostudy-core/src/vault/write-vault.ts
41229
- import fs12 from "node:fs/promises";
41230
- import path12 from "node:path";
41923
+ import fs13 from "node:fs/promises";
41924
+ import path13 from "node:path";
41231
41925
  async function writeVaultFiles(files, outputPath, courseId, courseSlug2) {
41232
41926
  for (const file2 of files) {
41233
- const fullPath = path12.join(outputPath, file2.relativePath);
41234
- await fs12.mkdir(path12.dirname(fullPath), { recursive: true });
41235
- await fs12.writeFile(fullPath, file2.content, "utf-8");
41927
+ const fullPath = path13.join(outputPath, file2.relativePath);
41928
+ await fs13.mkdir(path13.dirname(fullPath), { recursive: true });
41929
+ await fs13.writeFile(fullPath, file2.content, "utf-8");
41236
41930
  }
41237
- const vaultPath = path12.join(outputPath, courseSlug2);
41931
+ const vaultPath = path13.join(outputPath, courseSlug2);
41238
41932
  const marker = {
41239
41933
  courseId,
41240
41934
  courseSlug: courseSlug2,
41241
41935
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
41242
41936
  version: VAULT_MARKER_VERSION
41243
41937
  };
41244
- await fs12.mkdir(vaultPath, { recursive: true });
41245
- await fs12.writeFile(
41246
- path12.join(vaultPath, VAULT_MARKER_FILENAME),
41938
+ await fs13.mkdir(vaultPath, { recursive: true });
41939
+ await fs13.writeFile(
41940
+ path13.join(vaultPath, VAULT_MARKER_FILENAME),
41247
41941
  JSON.stringify(marker, null, 2),
41248
41942
  "utf-8"
41249
41943
  );
@@ -41268,10 +41962,10 @@ var init_vault = __esm({
41268
41962
 
41269
41963
  // src/commands/vault.ts
41270
41964
  import { Command as Command19 } from "commander";
41271
- import path13 from "node:path";
41965
+ import path14 from "node:path";
41272
41966
  import os10 from "node:os";
41273
- import fs13 from "node:fs/promises";
41274
- var logger15, vaultCommand;
41967
+ import fs14 from "node:fs/promises";
41968
+ var logger16, vaultCommand;
41275
41969
  var init_vault2 = __esm({
41276
41970
  "src/commands/vault.ts"() {
41277
41971
  "use strict";
@@ -41280,17 +41974,17 @@ var init_vault2 = __esm({
41280
41974
  init_courses();
41281
41975
  init_http2();
41282
41976
  init_session();
41283
- logger15 = createLogger("cli:vault");
41977
+ logger16 = createLogger("cli:vault");
41284
41978
  vaultCommand = new Command19("vault").description("Gerenciar vault Obsidian do curso");
41285
- vaultCommand.command("init").description("Gerar vault Obsidian para o curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path13.join(os10.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
41979
+ vaultCommand.command("init").description("Gerar vault Obsidian para o curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path14.join(os10.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
41286
41980
  try {
41287
41981
  const session = await requireSession();
41288
41982
  const activeCourse = await requireActiveCourse();
41289
41983
  const driftWarning = await checkCourseDrift();
41290
41984
  if (driftWarning) process.stderr.write(driftWarning + "\n");
41291
41985
  const courseSlug2 = activeCourse.courseTitle.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
41292
- const workspacePath = path13.join(opts.path, courseSlug2);
41293
- const vaultOutputPath = path13.join(workspacePath, "vault");
41986
+ const workspacePath = path14.join(opts.path, courseSlug2);
41987
+ const vaultOutputPath = path14.join(workspacePath, "vault");
41294
41988
  const res = await fetch(`${session.apiUrl}/api/cli/vault/init`, {
41295
41989
  method: "POST",
41296
41990
  headers: {
@@ -41314,7 +42008,7 @@ var init_vault2 = __esm({
41314
42008
  activeCourse.courseId,
41315
42009
  courseSlug2
41316
42010
  );
41317
- logger15.info("Vault generated", {
42011
+ logger16.info("Vault generated", {
41318
42012
  courseId: activeCourse.courseId,
41319
42013
  vaultPath: result.vaultPath,
41320
42014
  filesWritten: result.filesWritten
@@ -41347,31 +42041,31 @@ Para visualizar:
41347
42041
  );
41348
42042
  }
41349
42043
  } catch (err) {
41350
- logger15.error("vault init failed", { error: err });
42044
+ logger16.error("vault init failed", { error: err });
41351
42045
  process.stderr.write(`\u274C ${err instanceof Error ? err.message : String(err)}
41352
42046
  `);
41353
42047
  process.exit(1);
41354
42048
  }
41355
42049
  });
41356
- vaultCommand.command("sync").description("Sincronizar progresso do curso com o vault local").option("--path <dir>", "Diret\xF3rio base do workspace", path13.join(os10.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
42050
+ vaultCommand.command("sync").description("Sincronizar progresso do curso com o vault local").option("--path <dir>", "Diret\xF3rio base do workspace", path14.join(os10.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
41357
42051
  try {
41358
42052
  const session = await requireSession();
41359
42053
  const activeCourse = await requireActiveCourse();
41360
42054
  const driftWarning = await checkCourseDrift();
41361
42055
  if (driftWarning) process.stderr.write(driftWarning + "\n");
41362
42056
  const courseSlug2 = activeCourse.courseTitle.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
41363
- const vaultPath = path13.join(opts.path, courseSlug2, "vault");
42057
+ const vaultPath = path14.join(opts.path, courseSlug2, "vault");
41364
42058
  try {
41365
- await fs13.access(path13.join(vaultPath, ".ana-vault.json"));
42059
+ await fs14.access(path14.join(vaultPath, ".ana-vault.json"));
41366
42060
  } catch {
41367
42061
  process.stderr.write("\u274C Vault n\xE3o encontrado. Execute 'tostudy vault init' primeiro.\n");
41368
42062
  process.exit(1);
41369
42063
  }
41370
42064
  const data = createHttpProvider(session.apiUrl, session.token);
41371
- const deps = { data, logger: logger15 };
42065
+ const deps = { data, logger: logger16 };
41372
42066
  const progress3 = await getProgress({ enrollmentId: activeCourse.enrollmentId }, deps);
41373
- const markerPath = path13.join(vaultPath, ".ana-vault.json");
41374
- const markerRaw = await fs13.readFile(markerPath, "utf-8");
42067
+ const markerPath = path14.join(vaultPath, ".ana-vault.json");
42068
+ const markerRaw = await fs14.readFile(markerPath, "utf-8");
41375
42069
  const marker = JSON.parse(markerRaw);
41376
42070
  marker.lastSyncedAt = (/* @__PURE__ */ new Date()).toISOString();
41377
42071
  marker.progress = {
@@ -41379,10 +42073,10 @@ Para visualizar:
41379
42073
  currentModule: progress3.currentModule.title,
41380
42074
  currentLesson: progress3.currentLesson.title
41381
42075
  };
41382
- await fs13.writeFile(markerPath, JSON.stringify(marker, null, 2), "utf-8");
41383
- const courseIndexPath = path13.join(vaultPath, courseSlug2, "index.md");
42076
+ await fs14.writeFile(markerPath, JSON.stringify(marker, null, 2), "utf-8");
42077
+ const courseIndexPath = path14.join(vaultPath, courseSlug2, "index.md");
41384
42078
  try {
41385
- let indexContent = await fs13.readFile(courseIndexPath, "utf-8");
42079
+ let indexContent = await fs14.readFile(courseIndexPath, "utf-8");
41386
42080
  indexContent = indexContent.replace(/\n---\n\n> 📊 Progresso:.*\n/g, "");
41387
42081
  const titleEnd = indexContent.indexOf("\n");
41388
42082
  if (titleEnd !== -1) {
@@ -41393,7 +42087,7 @@ Para visualizar:
41393
42087
  `;
41394
42088
  indexContent = indexContent.slice(0, titleEnd) + banner + indexContent.slice(titleEnd);
41395
42089
  }
41396
- await fs13.writeFile(courseIndexPath, indexContent, "utf-8");
42090
+ await fs14.writeFile(courseIndexPath, indexContent, "utf-8");
41397
42091
  } catch {
41398
42092
  }
41399
42093
  const syncedAt = marker.lastSyncedAt;
@@ -41422,7 +42116,7 @@ Para visualizar:
41422
42116
  );
41423
42117
  }
41424
42118
  } catch (err) {
41425
- logger15.error("vault sync failed", { error: err });
42119
+ logger16.error("vault sync failed", { error: err });
41426
42120
  process.stderr.write(`\u274C ${err instanceof Error ? err.message : String(err)}
41427
42121
  `);
41428
42122
  process.exit(1);
@@ -41485,7 +42179,7 @@ var init_cli = __esm({
41485
42179
  init_export();
41486
42180
  init_open();
41487
42181
  init_vault2();
41488
- CLI_VERSION = "0.6.0";
42182
+ CLI_VERSION = true ? "0.7.1" : "0.7.1";
41489
42183
  }
41490
42184
  });
41491
42185