@learnpack/learnpack 5.0.274 → 5.0.275

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 (70) hide show
  1. package/README.md +409 -409
  2. package/lib/commands/audit.js +15 -15
  3. package/lib/commands/breakToken.js +19 -19
  4. package/lib/commands/clean.js +3 -3
  5. package/lib/commands/init.js +41 -41
  6. package/lib/commands/logout.js +3 -3
  7. package/lib/commands/serve.js +127 -70
  8. package/lib/creatorDist/assets/index-BfLyIQVh.js +10223 -10342
  9. package/lib/managers/config/index.js +77 -77
  10. package/lib/models/creator.d.ts +7 -0
  11. package/lib/utils/api.d.ts +1 -0
  12. package/lib/utils/api.js +2 -1
  13. package/lib/utils/creatorUtilities.js +14 -14
  14. package/package.json +1 -1
  15. package/src/commands/audit.ts +487 -487
  16. package/src/commands/breakToken.ts +67 -67
  17. package/src/commands/clean.ts +30 -30
  18. package/src/commands/init.ts +650 -650
  19. package/src/commands/logout.ts +38 -38
  20. package/src/commands/publish.ts +522 -522
  21. package/src/commands/serve.ts +162 -107
  22. package/src/commands/start.ts +333 -333
  23. package/src/commands/translate.ts +123 -123
  24. package/src/creator/README.md +54 -54
  25. package/src/creator/eslint.config.js +28 -28
  26. package/src/creator/src/components/syllabus/ContentIndex.tsx +312 -312
  27. package/src/creator/src/i18n.ts +28 -28
  28. package/src/creator/src/index.css +217 -217
  29. package/src/creator/src/locales/en.json +126 -126
  30. package/src/creator/src/locales/es.json +126 -126
  31. package/src/creator/src/utils/configTypes.ts +122 -122
  32. package/src/creator/src/utils/constants.ts +13 -13
  33. package/src/creator/src/utils/creatorUtils.ts +46 -46
  34. package/src/creator/src/utils/eventBus.ts +2 -2
  35. package/src/creator/src/utils/lib.ts +468 -468
  36. package/src/creator/src/utils/socket.ts +61 -61
  37. package/src/creator/src/utils/store.ts +222 -222
  38. package/src/creator/src/vite-env.d.ts +1 -1
  39. package/src/creator/vite.config.ts +13 -13
  40. package/src/creatorDist/assets/index-BfLyIQVh.js +10223 -10342
  41. package/src/managers/config/defaults.ts +49 -49
  42. package/src/managers/config/exercise.ts +364 -364
  43. package/src/managers/config/index.ts +775 -775
  44. package/src/managers/file.ts +236 -236
  45. package/src/managers/server/routes.ts +554 -554
  46. package/src/managers/session.ts +182 -182
  47. package/src/managers/telemetry.ts +188 -188
  48. package/src/models/action.ts +13 -13
  49. package/src/models/config-manager.ts +28 -28
  50. package/src/models/config.ts +106 -106
  51. package/src/models/creator.ts +47 -40
  52. package/src/models/exercise-obj.ts +30 -30
  53. package/src/models/session.ts +39 -39
  54. package/src/models/socket.ts +61 -61
  55. package/src/models/status.ts +16 -16
  56. package/src/ui/_app/app.js +141 -141
  57. package/src/ui/app.tar.gz +0 -0
  58. package/src/utils/BaseCommand.ts +56 -56
  59. package/src/utils/api.ts +31 -30
  60. package/src/utils/audit.ts +392 -392
  61. package/src/utils/checkNotInstalled.ts +267 -267
  62. package/src/utils/configBuilder.ts +82 -82
  63. package/src/utils/convertCreds.js +34 -34
  64. package/src/utils/creatorUtilities.ts +504 -504
  65. package/src/utils/incrementVersion.js +74 -74
  66. package/src/utils/misc.ts +58 -58
  67. package/src/utils/rigoActions.ts +500 -500
  68. package/src/utils/sidebarGenerator.ts +195 -195
  69. package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  70. package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
@@ -369,21 +369,21 @@ class AuditCommand extends SessionCommand_1.default {
369
369
  }
370
370
  }
371
371
  }
372
- AuditCommand.description = `learnpack audit is the command in charge of creating an auditory of the repository
373
- ...
374
- learnpack audit checks for the following information in a repository:
375
- 1. The configuration object has slug, repository and description. (Error)
376
- 2. The command learnpack clean has been run. (Error)
377
- 3. If a markdown or test file doesn't have any content. (Error)
378
- 4. The links are accessing to valid servers. (Error)
379
- 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)
380
- 6. The external images are working (If they are pointing to a valid server). (Error)
381
- 7. The exercises directory names are valid. (Error)
382
- 8. If an exercise doesn't have a README file. (Error)
383
- 9. The exercises array (Of the config file) has content. (Error)
384
- 10. The exercses have the same translations. (Warning)
385
- 11. The .gitignore file exists. (Warning)
386
- 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
372
+ AuditCommand.description = `learnpack audit is the command in charge of creating an auditory of the repository
373
+ ...
374
+ learnpack audit checks for the following information in a repository:
375
+ 1. The configuration object has slug, repository and description. (Error)
376
+ 2. The command learnpack clean has been run. (Error)
377
+ 3. If a markdown or test file doesn't have any content. (Error)
378
+ 4. The links are accessing to valid servers. (Error)
379
+ 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)
380
+ 6. The external images are working (If they are pointing to a valid server). (Error)
381
+ 7. The exercises directory names are valid. (Error)
382
+ 8. If an exercise doesn't have a README file. (Error)
383
+ 9. The exercises array (Of the config file) has content. (Error)
384
+ 10. The exercses have the same translations. (Warning)
385
+ 11. The .gitignore file exists. (Warning)
386
+ 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
387
387
  `;
388
388
  AuditCommand.flags = {
389
389
  strict: command_1.flags.boolean({
@@ -4,25 +4,25 @@ const command_1 = require("@oclif/command");
4
4
  const BaseCommand_1 = require("../utils/BaseCommand");
5
5
  const console_1 = require("../utils/console");
6
6
  const creatorUtilities_1 = require("../utils/creatorUtilities");
7
- const exampleMd = `# How to Install Node.js
8
-
9
- Node.js lets you run JavaScript outside a web browser.
10
-
11
- ## Step 1: Download Node.js
12
-
13
- Get the Node.js installer from the [official site](https://nodejs.org/en/download/).
14
-
15
- ## Step 2: Install Node.js
16
-
17
- Open the installer and follow the steps to finish.
18
-
19
- ## Step 3: Verify the Installation
20
-
21
- Open a terminal and type:
22
-
23
- \`\`\`bash
24
- node -v
25
- \`\`\`
7
+ const exampleMd = `# How to Install Node.js
8
+
9
+ Node.js lets you run JavaScript outside a web browser.
10
+
11
+ ## Step 1: Download Node.js
12
+
13
+ Get the Node.js installer from the [official site](https://nodejs.org/en/download/).
14
+
15
+ ## Step 2: Install Node.js
16
+
17
+ Open the installer and follow the steps to finish.
18
+
19
+ ## Step 3: Verify the Installation
20
+
21
+ Open a terminal and type:
22
+
23
+ \`\`\`bash
24
+ node -v
25
+ \`\`\`
26
26
  `;
27
27
  class BreakTokenCommand extends BaseCommand_1.default {
28
28
  async run() {
@@ -16,9 +16,9 @@ class CleanCommand extends SessionCommand_1.default {
16
16
  console_1.default.success("Package cleaned successfully, ready to publish");
17
17
  }
18
18
  }
19
- CleanCommand.description = `Clean the configuration object
20
- ...
21
- Extra documentation goes here
19
+ CleanCommand.description = `Clean the configuration object
20
+ ...
21
+ Extra documentation goes here
22
22
  `;
23
23
  CleanCommand.flags = {
24
24
  // name: flags.string({char: 'n', description: 'name to print'}),
@@ -107,9 +107,9 @@ const initializeInteractiveCreation = async (rigoToken, courseInfo) => {
107
107
  while (!isReady) {
108
108
  const spinner = (0, ora_1.default)("Thinking...").start();
109
109
  let wholeInfo = courseInfo;
110
- wholeInfo += `
111
- Current title: ${currentTitle}
112
- Current description: ${currentDescription}
110
+ wholeInfo += `
111
+ Current title: ${currentTitle}
112
+ Current description: ${currentDescription}
113
113
  `;
114
114
  // eslint-disable-next-line
115
115
  const res = await (0, rigoActions_1.interactiveCreation)(rigoToken, {
@@ -200,56 +200,56 @@ const handleAILogic = async (tutorialDir, packageInfo) => {
200
200
  fs.mkdirSync(rulesDir, { recursive: true });
201
201
  fs.writeFileSync(path.join(rulesDir, "airules.txt"), airules);
202
202
  }
203
- let packageContext = `
204
- \n
205
- Title: "${packageInfo.title.us}"
206
- Description: "${packageInfo.description.us}"
207
- Target Audience: "${targetAudience}"
208
- Estimated Duration: "${estimatedDuration} minutes"
209
-
203
+ let packageContext = `
204
+ \n
205
+ Title: "${packageInfo.title.us}"
206
+ Description: "${packageInfo.description.us}"
207
+ Target Audience: "${targetAudience}"
208
+ Estimated Duration: "${estimatedDuration} minutes"
209
+
210
210
  ${contentIndex ?
211
- `Content Index submitted by the user, use this to guide your creation. Keep in mind that your tutorial should contain these topics:
212
- ---
213
- ${contentIndex}
214
- ---
211
+ `Content Index submitted by the user, use this to guide your creation. Keep in mind that your tutorial should contain these topics:
212
+ ---
213
+ ${contentIndex}
214
+ ---
215
215
  ` :
216
- ""}
217
-
218
- This is the duration for each type of step, use it to estimate the number of steps to create:
216
+ ""}
217
+
218
+ This is the duration for each type of step, use it to estimate the number of steps to create:
219
219
  ${Object.entries(durationByKind)
220
220
  .map(([key, value]) => `${key}: ${value} minutes`)
221
- .join("\n")}
222
-
223
-
224
- Within the estimated duration, is possible to have the following activities:
225
- Format=
226
- Activity: Maximum number of steps for duration
227
-
228
- Estimated activities:
229
- ${JSON.stringify(estimateActivities(estimatedDuration))}
230
-
231
- You should create a tutorial that is engaging and fun to follow.
232
-
233
-
221
+ .join("\n")}
222
+
223
+
224
+ Within the estimated duration, is possible to have the following activities:
225
+ Format=
226
+ Activity: Maximum number of steps for duration
227
+
228
+ Estimated activities:
229
+ ${JSON.stringify(estimateActivities(estimatedDuration))}
230
+
231
+ You should create a tutorial that is engaging and fun to follow.
232
+
233
+
234
234
  ${airules ?
235
- `
236
- This is a list of rules you need to follow when creating the tutorial:
237
- ${airules}
235
+ `
236
+ This is a list of rules you need to follow when creating the tutorial:
237
+ ${airules}
238
238
  ` :
239
- ""}
239
+ ""}
240
240
  `;
241
241
  const { steps, title, description, duration, difficulty } = await initializeInteractiveCreation(rigoToken, packageContext);
242
242
  packageInfo.title.us = title;
243
243
  packageInfo.description.us = description;
244
244
  packageInfo.duration = duration;
245
245
  packageInfo.difficulty = difficulty;
246
- packageContext = `
247
- Title: "${title}"
248
- Description: "${description}"
249
- Target Audience: "${targetAudience}"
250
- List of exercises: ${steps.join(", ")}
251
-
252
- AI Rules: ${airules}
246
+ packageContext = `
247
+ Title: "${title}"
248
+ Description: "${description}"
249
+ Target Audience: "${targetAudience}"
250
+ List of exercises: ${steps.join(", ")}
251
+
252
+ AI Rules: ${airules}
253
253
  `;
254
254
  const exercisesDir = path.join(tutorialDir, "exercises");
255
255
  fs.ensureDirSync(exercisesDir);
@@ -14,9 +14,9 @@ class LogoutCommand extends SessionCommand_1.default {
14
14
  session_1.default.destroy();
15
15
  }
16
16
  }
17
- LogoutCommand.description = `Describe the command here
18
- ...
19
- Extra documentation goes here
17
+ LogoutCommand.description = `Describe the command here
18
+ ...
19
+ Extra documentation goes here
20
20
  `;
21
21
  LogoutCommand.flags = {
22
22
  // name: flags.string({char: 'n', description: 'name to print'}),
@@ -4,7 +4,6 @@ exports.processImage = exports.createLearnJson = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const command_1 = require("@oclif/command");
6
6
  const buffer_1 = require("buffer");
7
- const youtube_transcript_1 = require("youtube-transcript");
8
7
  const express = require("express");
9
8
  const cors = require("cors");
10
9
  const path = require("path");
@@ -82,7 +81,6 @@ const processImage = async (url, description, rigoToken, courseSlug) => {
82
81
  prompt: description,
83
82
  callbackUrl: webhookUrl,
84
83
  });
85
- // console.log("✅ Image", imagePath, "generated successfully!")
86
84
  return true;
87
85
  }
88
86
  catch (_a) {
@@ -147,6 +145,7 @@ async function startExerciseGeneration(rigoToken, steps, packageContext, exercis
147
145
  last_lesson: lastLesson,
148
146
  }, purposeSlug, webhookUrl);
149
147
  console.log("README CREATOR RES", res);
148
+ return res.id;
150
149
  }
151
150
  async function createInitialReadme(tutorialInfo, tutorialSlug, rigoToken) {
152
151
  const webhookUrl = `${process.env.HOST}/webhooks/${tutorialSlug}/initial-readme-processor`;
@@ -432,10 +431,18 @@ class ServeCommand extends SessionCommand_1.default {
432
431
  previousReadme = content.toString();
433
432
  }
434
433
  }
435
- await startExerciseGeneration(rigoToken, syllabusJson.lessons, syllabusJson.courseInfo, exercise, courseSlug, syllabusJson.courseInfo.purpose, previousReadme +
434
+ const completionId = await startExerciseGeneration(rigoToken, syllabusJson.lessons, syllabusJson.courseInfo, exercise, courseSlug, syllabusJson.courseInfo.purpose, previousReadme +
436
435
  "\n\nThe user provided the following feedback related to the content of the course so far: \n\n" +
437
436
  feedback);
438
437
  syllabusJson.lessons[parseInt(position)].status = "GENERATING";
438
+ syllabusJson.lessons[parseInt(position)].translations = {
439
+ [syllabusJson.courseInfo.language || "en"]: {
440
+ completionId,
441
+ startedAt: Date.now(),
442
+ completedAt: 0,
443
+ },
444
+ };
445
+ console.log("Lesson", syllabusJson.lessons[parseInt(position)]);
439
446
  if (syllabusJson.feedback &&
440
447
  typeof syllabusJson.feedback === "string") {
441
448
  syllabusJson.feedback += "\n\n" + feedback;
@@ -446,6 +453,23 @@ class ServeCommand extends SessionCommand_1.default {
446
453
  await uploadFileToBucket(bucket, JSON.stringify(syllabusJson), `courses/${courseSlug}/.learn/initialSyllabus.json`);
447
454
  res.json({ status: "SUCCESS" });
448
455
  });
456
+ app.post("/actions/generate-image/:courseSlug", async (req, res) => {
457
+ const rigoToken = req.header("x-rigo-token");
458
+ const { courseSlug } = req.params;
459
+ const { image } = req.body;
460
+ if (!image) {
461
+ return res.status(400).json({
462
+ error: "Image is required",
463
+ });
464
+ }
465
+ if (!rigoToken) {
466
+ return res.status(400).json({
467
+ error: "Rigo token is required. x-rigo-token header is missing",
468
+ });
469
+ }
470
+ await (0, exports.processImage)(image.url, image.alt, rigoToken, courseSlug);
471
+ res.json({ status: "QUEUED" });
472
+ });
449
473
  app.post("/webhooks/:courseSlug/exercise-processor/:lessonID/:rigoToken", async (req, res) => {
450
474
  // console.log("Receiving a webhook to exercise processor")
451
475
  const { courseSlug, lessonID, rigoToken } = req.params;
@@ -498,40 +522,55 @@ class ServeCommand extends SessionCommand_1.default {
498
522
  log: `✅ Code file created for ${exercise.title}`,
499
523
  });
500
524
  }
501
- let nextStarted = false;
525
+ let nextCompletionId = null;
502
526
  if (nextExercise &&
503
527
  (exerciseIndex === 0 || !(exerciseIndex % 3 === 0))) {
504
528
  let feedback = "";
505
529
  if (syllabusJson.feedback) {
506
530
  feedback = `\n\nThe user added the following feedback with relation to the previous generations: ${syllabusJson.feedback}`;
507
531
  }
508
- startExerciseGeneration(rigoToken, syllabusJson.lessons, syllabusJson.courseInfo, nextExercise, courseSlug, syllabusJson.courseInfo.purpose, readme.parsed.content + "\n\n" + feedback);
509
- nextStarted = true;
532
+ nextCompletionId = await startExerciseGeneration(rigoToken, syllabusJson.lessons, syllabusJson.courseInfo, nextExercise, courseSlug, syllabusJson.courseInfo.purpose, readme.parsed.content + "\n\n" + feedback);
510
533
  }
511
534
  else {
512
535
  console.log("Stopping generation process at", exerciseIndex, exercise.title, "because it's a multiple of 3");
513
536
  }
514
537
  const imagesArray = (0, creatorUtilities_1.extractImagesFromMarkdown)(readability.newMarkdown);
515
- if (imagesArray.length > 0) {
516
- (0, creatorSocket_1.emitToCourse)(courseSlug, "course-creation", {
517
- lesson: exSlug,
518
- status: "pending",
519
- log: `🔄 Generating images for ${exercise.title}`,
520
- });
521
- for (const image of imagesArray) {
522
- // eslint-disable-next-line no-await-in-loop
523
- await (0, exports.processImage)(image.url, image.alt, rigoToken, courseSlug);
524
- }
525
- }
526
538
  const newSyllabus = Object.assign(Object.assign({}, syllabusJson), { lessons: syllabusJson.lessons.map((lesson, index) => {
527
539
  if (index === exerciseIndex) {
528
- return Object.assign(Object.assign({}, lesson), { generated: true, status: "DONE" });
540
+ const currentTranslations = lesson.translations || {};
541
+ let currentTranslation = currentTranslations[syllabusJson.courseInfo.language || "en"];
542
+ if (currentTranslation) {
543
+ currentTranslation.completedAt = Date.now();
544
+ }
545
+ else {
546
+ currentTranslation = {
547
+ completionId: readme.id,
548
+ startedAt: Date.now(),
549
+ completedAt: Date.now(),
550
+ };
551
+ }
552
+ currentTranslations[syllabusJson.courseInfo.language || "en"] =
553
+ currentTranslation;
554
+ return Object.assign(Object.assign({}, lesson), { generated: true, status: "DONE", translations: {
555
+ [syllabusJson.courseInfo.language || "en"]: {
556
+ completionId: nextCompletionId,
557
+ completedAt: Date.now(),
558
+ },
559
+ } });
529
560
  }
530
- if (nextExercise && nextExercise.id === lesson.id && nextStarted) {
531
- return Object.assign(Object.assign({}, lesson), { generated: false, status: "GENERATING" });
561
+ if (nextExercise &&
562
+ nextExercise.id === lesson.id &&
563
+ nextCompletionId) {
564
+ return Object.assign(Object.assign({}, lesson), { generated: false, status: "GENERATING", translations: {
565
+ [syllabusJson.courseInfo.language || "en"]: {
566
+ completionId: nextCompletionId,
567
+ startedAt: Date.now(),
568
+ },
569
+ } });
532
570
  }
533
571
  return Object.assign({}, lesson);
534
572
  }) });
573
+ console.log("New syllabus", newSyllabus);
535
574
  await uploadFileToBucket(bucket, JSON.stringify(newSyllabus), `courses/${courseSlug}/.learn/initialSyllabus.json`);
536
575
  (0, creatorSocket_1.emitToCourse)(courseSlug, "course-creation", {
537
576
  lesson: exSlug,
@@ -936,7 +975,16 @@ class ServeCommand extends SessionCommand_1.default {
936
975
  await uploadFileToBucket(bucket, JSON.stringify(sidebar), `${tutorialDir}/.learn/sidebar.json`);
937
976
  const firstLesson = syllabus.lessons[0];
938
977
  const lastResult = "---";
939
- await startExerciseGeneration(rigoToken, syllabus.lessons, syllabus.courseInfo, firstLesson, courseSlug, syllabus.courseInfo.purpose, lastResult);
978
+ const completionId = await startExerciseGeneration(rigoToken, syllabus.lessons, syllabus.courseInfo, firstLesson, courseSlug, syllabus.courseInfo.purpose, lastResult);
979
+ if (firstLesson) {
980
+ firstLesson.translations = {
981
+ [syllabus.courseInfo.language || "en"]: {
982
+ completionId,
983
+ startedAt: Date.now(),
984
+ completedAt: 0,
985
+ },
986
+ };
987
+ }
940
988
  await createInitialReadme(JSON.stringify(syllabus.courseInfo), courseSlug, rigoToken);
941
989
  return res.json({
942
990
  message: "Course generation started",
@@ -957,29 +1005,44 @@ class ServeCommand extends SessionCommand_1.default {
957
1005
  return res.status(500).json({ error: "Error getting syllabus" });
958
1006
  }
959
1007
  });
960
- app.post("/actions/continue-course/:courseSlug", async (req, res) => {
961
- console.log("POST /actions/continue-course/:courseSlug");
962
- const { courseSlug } = req.params;
963
- const { feedback } = req.body;
964
- const rigoToken = req.header("x-rigo-token");
965
- const bcToken = req.header("x-breathecode-token");
966
- if (!rigoToken || !bcToken) {
967
- return res.status(400).json({ error: "Missing tokens" });
968
- }
969
- const syllabus = await bucket.file(`courses/${courseSlug}/.learn/initialSyllabus.json`);
970
- const [content] = await syllabus.download();
971
- const syllabusJson = JSON.parse(content.toString());
972
- const notGeneratedLessons = syllabusJson.lessons.filter(lesson => !lesson.generated);
973
- const lastGeneratedLesson = findLast(syllabusJson.lessons, lesson => { var _a; return (_a = lesson.generated) !== null && _a !== void 0 ? _a : false; });
974
- console.log("ABout to generate", notGeneratedLessons.length, "lessons");
975
- const firstLessonToGenerate = notGeneratedLessons[0];
976
- await startExerciseGeneration(rigoToken, syllabusJson.lessons, syllabusJson.courseInfo, firstLessonToGenerate, courseSlug, syllabusJson.courseInfo.purpose, JSON.stringify(lastGeneratedLesson) +
977
- `\n\nThe user provided this feedback in relation to the course: ${feedback}`);
978
- return res.json({
979
- message: "Course continued",
980
- slug: courseSlug,
981
- });
982
- });
1008
+ // app.post("/actions/continue-course/:courseSlug", async (req, res) => {
1009
+ // console.log("POST /actions/continue-course/:courseSlug")
1010
+ // const { courseSlug } = req.params
1011
+ // const { feedback }: { feedback: string } = req.body
1012
+ // const rigoToken = req.header("x-rigo-token")
1013
+ // const bcToken = req.header("x-breathecode-token")
1014
+ // if (!rigoToken || !bcToken) {
1015
+ // return res.status(400).json({ error: "Missing tokens" })
1016
+ // }
1017
+ // const syllabus = await bucket.file(
1018
+ // `courses/${courseSlug}/.learn/initialSyllabus.json`
1019
+ // )
1020
+ // const [content] = await syllabus.download()
1021
+ // const syllabusJson: Syllabus = JSON.parse(content.toString())
1022
+ // const notGeneratedLessons = syllabusJson.lessons.filter(
1023
+ // lesson => !lesson.generated
1024
+ // )
1025
+ // const lastGeneratedLesson = findLast(
1026
+ // syllabusJson.lessons,
1027
+ // lesson => lesson.generated ?? false
1028
+ // )
1029
+ // console.log("ABout to generate", notGeneratedLessons.length, "lessons")
1030
+ // const firstLessonToGenerate = notGeneratedLessons[0]
1031
+ // const completionId = await startExerciseGeneration(
1032
+ // rigoToken,
1033
+ // syllabusJson.lessons,
1034
+ // syllabusJson.courseInfo,
1035
+ // firstLessonToGenerate,
1036
+ // courseSlug,
1037
+ // syllabusJson.courseInfo.purpose,
1038
+ // JSON.stringify(lastGeneratedLesson) +
1039
+ // `\n\nThe user provided this feedback in relation to the course: ${feedback}`
1040
+ // )
1041
+ // return res.json({
1042
+ // message: "Course continued",
1043
+ // slug: courseSlug,
1044
+ // })
1045
+ // })
983
1046
  app.get("/courses/:courseSlug/exercises/:exerciseSlug/", async (req, res) => {
984
1047
  var _a;
985
1048
  console.log("GET /courses/:courseSlug/exercises/:exerciseSlug/");
@@ -1134,9 +1197,7 @@ class ServeCommand extends SessionCommand_1.default {
1134
1197
  }
1135
1198
  catch (error) {
1136
1199
  console.error("❌ Error fetching file:", error);
1137
- return res
1138
- .status(500)
1139
- .json({
1200
+ return res.status(500).json({
1140
1201
  error: error.message || "Unable to fetch file",
1141
1202
  });
1142
1203
  }
@@ -1150,28 +1211,26 @@ class ServeCommand extends SessionCommand_1.default {
1150
1211
  const ytMatch = decoded.match(YT_REGEX);
1151
1212
  if (ytMatch) {
1152
1213
  const videoId = ytMatch[1];
1153
- console.log("VIDEO ID", videoId);
1154
- // fetch metadata
1155
- const items = await youtube_transcript_1.YoutubeTranscript.fetchTranscript(videoId);
1156
- console.log("ITEMS FROM YOUTUBE TRANSCRIPT", items);
1157
- const transcript = items.map(i => i.text).join(" ");
1158
- let meta = null;
1159
- try {
1160
- const { data: meta } = await axios_1.default.get("https://www.youtube.com/oembed", {
1161
- params: { url: decoded, format: "json" },
1162
- });
1163
- console.log("META", meta);
1164
- }
1165
- catch (error) {
1166
- console.error("ERROR FETCHING META", error);
1167
- meta = null;
1168
- }
1169
- throw new Error("test");
1214
+ const resFromRigo = await axios_1.default.get(`${api_1.RIGOBOT_REALTIME_HOST}/actions/youtube-transcript/${videoId}`);
1215
+ console.log("RES FROM RIGO", resFromRigo.data);
1216
+ const transcript = resFromRigo.data.transcript;
1217
+ // let meta: any = null
1218
+ // try {
1219
+ // const { data: meta } = await axios.get(
1220
+ // "https://www.youtube.com/oembed",
1221
+ // {
1222
+ // params: { url: decoded, format: "json" },
1223
+ // }
1224
+ // )
1225
+ // console.log("META", meta)
1226
+ // } catch (error) {
1227
+ // console.error("ERROR FETCHING META", error)
1228
+ // meta = null
1229
+ // }
1170
1230
  return res.json({
1171
1231
  url: decoded,
1172
- title: (meta === null || meta === void 0 ? void 0 : meta.title) || null,
1173
- author: (meta === null || meta === void 0 ? void 0 : meta.author_name) || null,
1174
- thumbnail: (meta === null || meta === void 0 ? void 0 : meta.thumbnail_url) || null,
1232
+ title: resFromRigo.data.title || null,
1233
+ author: resFromRigo.data.author || null,
1175
1234
  transcript,
1176
1235
  });
1177
1236
  }
@@ -1189,9 +1248,7 @@ class ServeCommand extends SessionCommand_1.default {
1189
1248
  }
1190
1249
  catch (error) {
1191
1250
  console.error("❌ /actions/fetch error:", error.message || error);
1192
- res
1193
- .status(500)
1194
- .json({ error: error.message || "Failed to fetch link" });
1251
+ res.status(500).json({ error: error.message || "Failed to fetch link" });
1195
1252
  }
1196
1253
  });
1197
1254
  app.delete("/packages/:slug", async (req, res) => {