@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.
- package/README.md +409 -409
- package/lib/commands/audit.js +15 -15
- package/lib/commands/breakToken.js +19 -19
- package/lib/commands/clean.js +3 -3
- package/lib/commands/init.js +41 -41
- package/lib/commands/logout.js +3 -3
- package/lib/commands/serve.js +127 -70
- package/lib/creatorDist/assets/index-BfLyIQVh.js +10223 -10342
- package/lib/managers/config/index.js +77 -77
- package/lib/models/creator.d.ts +7 -0
- package/lib/utils/api.d.ts +1 -0
- package/lib/utils/api.js +2 -1
- package/lib/utils/creatorUtilities.js +14 -14
- package/package.json +1 -1
- package/src/commands/audit.ts +487 -487
- package/src/commands/breakToken.ts +67 -67
- package/src/commands/clean.ts +30 -30
- package/src/commands/init.ts +650 -650
- package/src/commands/logout.ts +38 -38
- package/src/commands/publish.ts +522 -522
- package/src/commands/serve.ts +162 -107
- package/src/commands/start.ts +333 -333
- package/src/commands/translate.ts +123 -123
- package/src/creator/README.md +54 -54
- package/src/creator/eslint.config.js +28 -28
- package/src/creator/src/components/syllabus/ContentIndex.tsx +312 -312
- package/src/creator/src/i18n.ts +28 -28
- package/src/creator/src/index.css +217 -217
- package/src/creator/src/locales/en.json +126 -126
- package/src/creator/src/locales/es.json +126 -126
- package/src/creator/src/utils/configTypes.ts +122 -122
- package/src/creator/src/utils/constants.ts +13 -13
- package/src/creator/src/utils/creatorUtils.ts +46 -46
- package/src/creator/src/utils/eventBus.ts +2 -2
- package/src/creator/src/utils/lib.ts +468 -468
- package/src/creator/src/utils/socket.ts +61 -61
- package/src/creator/src/utils/store.ts +222 -222
- package/src/creator/src/vite-env.d.ts +1 -1
- package/src/creator/vite.config.ts +13 -13
- package/src/creatorDist/assets/index-BfLyIQVh.js +10223 -10342
- package/src/managers/config/defaults.ts +49 -49
- package/src/managers/config/exercise.ts +364 -364
- package/src/managers/config/index.ts +775 -775
- package/src/managers/file.ts +236 -236
- package/src/managers/server/routes.ts +554 -554
- package/src/managers/session.ts +182 -182
- package/src/managers/telemetry.ts +188 -188
- package/src/models/action.ts +13 -13
- package/src/models/config-manager.ts +28 -28
- package/src/models/config.ts +106 -106
- package/src/models/creator.ts +47 -40
- package/src/models/exercise-obj.ts +30 -30
- package/src/models/session.ts +39 -39
- package/src/models/socket.ts +61 -61
- package/src/models/status.ts +16 -16
- package/src/ui/_app/app.js +141 -141
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/BaseCommand.ts +56 -56
- package/src/utils/api.ts +31 -30
- package/src/utils/audit.ts +392 -392
- package/src/utils/checkNotInstalled.ts +267 -267
- package/src/utils/configBuilder.ts +82 -82
- package/src/utils/convertCreds.js +34 -34
- package/src/utils/creatorUtilities.ts +504 -504
- package/src/utils/incrementVersion.js +74 -74
- package/src/utils/misc.ts +58 -58
- package/src/utils/rigoActions.ts +500 -500
- package/src/utils/sidebarGenerator.ts +195 -195
- package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
- package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
package/src/commands/serve.ts
CHANGED
@@ -44,11 +44,8 @@ import {
|
|
44
44
|
// import { handleAssetCreation } from "./publish"
|
45
45
|
import axios from "axios"
|
46
46
|
import * as FormData from "form-data"
|
47
|
-
import api, { RIGOBOT_HOST } from "../utils/api"
|
48
|
-
import {
|
49
|
-
createUploadMiddleware,
|
50
|
-
minutesToISO8601Duration,
|
51
|
-
} from "../utils/misc"
|
47
|
+
import api, { RIGOBOT_HOST, RIGOBOT_REALTIME_HOST } from "../utils/api"
|
48
|
+
import { createUploadMiddleware, minutesToISO8601Duration } from "../utils/misc"
|
52
49
|
import { buildConfig, ConfigResponse } from "../utils/configBuilder"
|
53
50
|
import { checkReadability, slugify } from "../utils/creatorUtilities"
|
54
51
|
import { checkAndFixSidebarPure } from "../utils/sidebarGenerator"
|
@@ -128,7 +125,6 @@ export const processImage = async (
|
|
128
125
|
callbackUrl: webhookUrl,
|
129
126
|
})
|
130
127
|
|
131
|
-
// console.log("✅ Image", imagePath, "generated successfully!")
|
132
128
|
return true
|
133
129
|
} catch {
|
134
130
|
return false
|
@@ -237,7 +233,7 @@ async function startExerciseGeneration(
|
|
237
233
|
courseSlug: string,
|
238
234
|
purposeSlug: string,
|
239
235
|
lastLesson = ""
|
240
|
-
): Promise<
|
236
|
+
): Promise<number> {
|
241
237
|
const exSlug = slugify(exercise.id + "-" + exercise.title)
|
242
238
|
console.log("Starting generation of", exSlug)
|
243
239
|
|
@@ -263,6 +259,7 @@ async function startExerciseGeneration(
|
|
263
259
|
)
|
264
260
|
|
265
261
|
console.log("README CREATOR RES", res)
|
262
|
+
return res.id
|
266
263
|
}
|
267
264
|
|
268
265
|
async function createInitialReadme(
|
@@ -649,7 +646,7 @@ export default class ServeCommand extends SessionCommand {
|
|
649
646
|
}
|
650
647
|
}
|
651
648
|
|
652
|
-
await startExerciseGeneration(
|
649
|
+
const completionId = await startExerciseGeneration(
|
653
650
|
rigoToken,
|
654
651
|
syllabusJson.lessons,
|
655
652
|
syllabusJson.courseInfo,
|
@@ -662,6 +659,14 @@ export default class ServeCommand extends SessionCommand {
|
|
662
659
|
)
|
663
660
|
|
664
661
|
syllabusJson.lessons[parseInt(position)].status = "GENERATING"
|
662
|
+
syllabusJson.lessons[parseInt(position)].translations = {
|
663
|
+
[syllabusJson.courseInfo.language || "en"]: {
|
664
|
+
completionId,
|
665
|
+
startedAt: Date.now(),
|
666
|
+
completedAt: 0,
|
667
|
+
},
|
668
|
+
}
|
669
|
+
console.log("Lesson", syllabusJson.lessons[parseInt(position)])
|
665
670
|
if (
|
666
671
|
syllabusJson.feedback &&
|
667
672
|
typeof syllabusJson.feedback === "string"
|
@@ -681,6 +686,27 @@ export default class ServeCommand extends SessionCommand {
|
|
681
686
|
}
|
682
687
|
)
|
683
688
|
|
689
|
+
app.post("/actions/generate-image/:courseSlug", async (req, res) => {
|
690
|
+
const rigoToken = req.header("x-rigo-token")
|
691
|
+
const { courseSlug } = req.params
|
692
|
+
const { image } = req.body
|
693
|
+
|
694
|
+
if (!image) {
|
695
|
+
return res.status(400).json({
|
696
|
+
error: "Image is required",
|
697
|
+
})
|
698
|
+
}
|
699
|
+
|
700
|
+
if (!rigoToken) {
|
701
|
+
return res.status(400).json({
|
702
|
+
error: "Rigo token is required. x-rigo-token header is missing",
|
703
|
+
})
|
704
|
+
}
|
705
|
+
|
706
|
+
await processImage(image.url, image.alt, rigoToken, courseSlug)
|
707
|
+
res.json({ status: "QUEUED" })
|
708
|
+
})
|
709
|
+
|
684
710
|
app.post(
|
685
711
|
"/webhooks/:courseSlug/exercise-processor/:lessonID/:rigoToken",
|
686
712
|
async (req, res) => {
|
@@ -772,7 +798,7 @@ export default class ServeCommand extends SessionCommand {
|
|
772
798
|
})
|
773
799
|
}
|
774
800
|
|
775
|
-
let
|
801
|
+
let nextCompletionId: number | null = null
|
776
802
|
if (
|
777
803
|
nextExercise &&
|
778
804
|
(exerciseIndex === 0 || !(exerciseIndex % 3 === 0))
|
@@ -782,7 +808,7 @@ export default class ServeCommand extends SessionCommand {
|
|
782
808
|
feedback = `\n\nThe user added the following feedback with relation to the previous generations: ${syllabusJson.feedback}`
|
783
809
|
}
|
784
810
|
|
785
|
-
startExerciseGeneration(
|
811
|
+
nextCompletionId = await startExerciseGeneration(
|
786
812
|
rigoToken,
|
787
813
|
syllabusJson.lessons,
|
788
814
|
syllabusJson.courseInfo,
|
@@ -791,7 +817,6 @@ export default class ServeCommand extends SessionCommand {
|
|
791
817
|
syllabusJson.courseInfo.purpose,
|
792
818
|
readme.parsed.content + "\n\n" + feedback
|
793
819
|
)
|
794
|
-
nextStarted = true
|
795
820
|
} else {
|
796
821
|
console.log(
|
797
822
|
"Stopping generation process at",
|
@@ -805,32 +830,60 @@ export default class ServeCommand extends SessionCommand {
|
|
805
830
|
readability.newMarkdown
|
806
831
|
)
|
807
832
|
|
808
|
-
if (imagesArray.length > 0) {
|
809
|
-
emitToCourse(courseSlug, "course-creation", {
|
810
|
-
lesson: exSlug,
|
811
|
-
status: "pending",
|
812
|
-
log: `🔄 Generating images for ${exercise.title}`,
|
813
|
-
})
|
814
|
-
for (const image of imagesArray) {
|
815
|
-
// eslint-disable-next-line no-await-in-loop
|
816
|
-
await processImage(image.url, image.alt, rigoToken, courseSlug)
|
817
|
-
}
|
818
|
-
}
|
819
|
-
|
820
833
|
const newSyllabus = {
|
821
834
|
...syllabusJson,
|
822
835
|
lessons: syllabusJson.lessons.map((lesson, index) => {
|
823
836
|
if (index === exerciseIndex) {
|
824
|
-
|
837
|
+
const currentTranslations = lesson.translations || {}
|
838
|
+
let currentTranslation =
|
839
|
+
currentTranslations[syllabusJson.courseInfo.language || "en"]
|
840
|
+
if (currentTranslation) {
|
841
|
+
currentTranslation.completedAt = Date.now()
|
842
|
+
} else {
|
843
|
+
currentTranslation = {
|
844
|
+
completionId: readme.id,
|
845
|
+
startedAt: Date.now(),
|
846
|
+
completedAt: Date.now(),
|
847
|
+
}
|
848
|
+
}
|
849
|
+
|
850
|
+
currentTranslations[syllabusJson.courseInfo.language || "en"] =
|
851
|
+
currentTranslation
|
852
|
+
return {
|
853
|
+
...lesson,
|
854
|
+
generated: true,
|
855
|
+
status: "DONE",
|
856
|
+
translations: {
|
857
|
+
[syllabusJson.courseInfo.language || "en"]: {
|
858
|
+
completionId: nextCompletionId,
|
859
|
+
completedAt: Date.now(),
|
860
|
+
},
|
861
|
+
},
|
862
|
+
}
|
825
863
|
}
|
826
864
|
|
827
|
-
if (
|
828
|
-
|
865
|
+
if (
|
866
|
+
nextExercise &&
|
867
|
+
nextExercise.id === lesson.id &&
|
868
|
+
nextCompletionId
|
869
|
+
) {
|
870
|
+
return {
|
871
|
+
...lesson,
|
872
|
+
generated: false,
|
873
|
+
status: "GENERATING",
|
874
|
+
translations: {
|
875
|
+
[syllabusJson.courseInfo.language || "en"]: {
|
876
|
+
completionId: nextCompletionId,
|
877
|
+
startedAt: Date.now(),
|
878
|
+
},
|
879
|
+
},
|
880
|
+
}
|
829
881
|
}
|
830
882
|
|
831
883
|
return { ...lesson }
|
832
884
|
}),
|
833
885
|
}
|
886
|
+
console.log("New syllabus", newSyllabus)
|
834
887
|
await uploadFileToBucket(
|
835
888
|
bucket,
|
836
889
|
JSON.stringify(newSyllabus),
|
@@ -1441,7 +1494,7 @@ export default class ServeCommand extends SessionCommand {
|
|
1441
1494
|
|
1442
1495
|
const lastResult = "---"
|
1443
1496
|
|
1444
|
-
await startExerciseGeneration(
|
1497
|
+
const completionId = await startExerciseGeneration(
|
1445
1498
|
rigoToken,
|
1446
1499
|
syllabus.lessons,
|
1447
1500
|
syllabus.courseInfo,
|
@@ -1450,6 +1503,15 @@ export default class ServeCommand extends SessionCommand {
|
|
1450
1503
|
syllabus.courseInfo.purpose,
|
1451
1504
|
lastResult
|
1452
1505
|
)
|
1506
|
+
if (firstLesson) {
|
1507
|
+
firstLesson.translations = {
|
1508
|
+
[syllabus.courseInfo.language || "en"]: {
|
1509
|
+
completionId,
|
1510
|
+
startedAt: Date.now(),
|
1511
|
+
completedAt: 0,
|
1512
|
+
},
|
1513
|
+
}
|
1514
|
+
}
|
1453
1515
|
|
1454
1516
|
await createInitialReadme(
|
1455
1517
|
JSON.stringify(syllabus.courseInfo),
|
@@ -1479,52 +1541,52 @@ export default class ServeCommand extends SessionCommand {
|
|
1479
1541
|
}
|
1480
1542
|
})
|
1481
1543
|
|
1482
|
-
app.post("/actions/continue-course/:courseSlug", async (req, res) => {
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
})
|
1544
|
+
// app.post("/actions/continue-course/:courseSlug", async (req, res) => {
|
1545
|
+
// console.log("POST /actions/continue-course/:courseSlug")
|
1546
|
+
// const { courseSlug } = req.params
|
1547
|
+
|
1548
|
+
// const { feedback }: { feedback: string } = req.body
|
1549
|
+
|
1550
|
+
// const rigoToken = req.header("x-rigo-token")
|
1551
|
+
// const bcToken = req.header("x-breathecode-token")
|
1552
|
+
// if (!rigoToken || !bcToken) {
|
1553
|
+
// return res.status(400).json({ error: "Missing tokens" })
|
1554
|
+
// }
|
1555
|
+
|
1556
|
+
// const syllabus = await bucket.file(
|
1557
|
+
// `courses/${courseSlug}/.learn/initialSyllabus.json`
|
1558
|
+
// )
|
1559
|
+
// const [content] = await syllabus.download()
|
1560
|
+
// const syllabusJson: Syllabus = JSON.parse(content.toString())
|
1561
|
+
// const notGeneratedLessons = syllabusJson.lessons.filter(
|
1562
|
+
// lesson => !lesson.generated
|
1563
|
+
// )
|
1564
|
+
|
1565
|
+
// const lastGeneratedLesson = findLast(
|
1566
|
+
// syllabusJson.lessons,
|
1567
|
+
// lesson => lesson.generated ?? false
|
1568
|
+
// )
|
1569
|
+
|
1570
|
+
// console.log("ABout to generate", notGeneratedLessons.length, "lessons")
|
1571
|
+
|
1572
|
+
// const firstLessonToGenerate = notGeneratedLessons[0]
|
1573
|
+
|
1574
|
+
// const completionId = await startExerciseGeneration(
|
1575
|
+
// rigoToken,
|
1576
|
+
// syllabusJson.lessons,
|
1577
|
+
// syllabusJson.courseInfo,
|
1578
|
+
// firstLessonToGenerate,
|
1579
|
+
// courseSlug,
|
1580
|
+
// syllabusJson.courseInfo.purpose,
|
1581
|
+
// JSON.stringify(lastGeneratedLesson) +
|
1582
|
+
// `\n\nThe user provided this feedback in relation to the course: ${feedback}`
|
1583
|
+
// )
|
1584
|
+
|
1585
|
+
// return res.json({
|
1586
|
+
// message: "Course continued",
|
1587
|
+
// slug: courseSlug,
|
1588
|
+
// })
|
1589
|
+
// })
|
1528
1590
|
|
1529
1591
|
app.get(
|
1530
1592
|
"/courses/:courseSlug/exercises/:exerciseSlug/",
|
@@ -1746,11 +1808,9 @@ export default class ServeCommand extends SessionCommand {
|
|
1746
1808
|
return res.send(content.toString("utf-8"))
|
1747
1809
|
} catch (error) {
|
1748
1810
|
console.error("❌ Error fetching file:", error)
|
1749
|
-
return res
|
1750
|
-
|
1751
|
-
|
1752
|
-
error: (error as Error).message || "Unable to fetch file",
|
1753
|
-
})
|
1811
|
+
return res.status(500).json({
|
1812
|
+
error: (error as Error).message || "Unable to fetch file",
|
1813
|
+
})
|
1754
1814
|
}
|
1755
1815
|
}
|
1756
1816
|
)
|
@@ -1766,38 +1826,35 @@ export default class ServeCommand extends SessionCommand {
|
|
1766
1826
|
|
1767
1827
|
if (ytMatch) {
|
1768
1828
|
const videoId = ytMatch[1]
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
console.log("
|
1773
|
-
const transcript =
|
1774
|
-
|
1775
|
-
let meta: any = null
|
1776
|
-
try {
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
} catch (error) {
|
1785
|
-
|
1786
|
-
|
1787
|
-
}
|
1788
|
-
|
1789
|
-
throw new Error("test")
|
1829
|
+
const resFromRigo = await axios.get(
|
1830
|
+
`${RIGOBOT_REALTIME_HOST}/actions/youtube-transcript/${videoId}`
|
1831
|
+
)
|
1832
|
+
console.log("RES FROM RIGO", resFromRigo.data)
|
1833
|
+
const transcript = resFromRigo.data.transcript
|
1834
|
+
|
1835
|
+
// let meta: any = null
|
1836
|
+
// try {
|
1837
|
+
// const { data: meta } = await axios.get(
|
1838
|
+
// "https://www.youtube.com/oembed",
|
1839
|
+
// {
|
1840
|
+
// params: { url: decoded, format: "json" },
|
1841
|
+
// }
|
1842
|
+
// )
|
1843
|
+
// console.log("META", meta)
|
1844
|
+
// } catch (error) {
|
1845
|
+
// console.error("ERROR FETCHING META", error)
|
1846
|
+
// meta = null
|
1847
|
+
// }
|
1790
1848
|
|
1791
1849
|
return res.json({
|
1792
1850
|
url: decoded,
|
1793
|
-
title:
|
1794
|
-
author:
|
1795
|
-
thumbnail: meta?.thumbnail_url || null,
|
1851
|
+
title: resFromRigo.data.title || null,
|
1852
|
+
author: resFromRigo.data.author || null,
|
1796
1853
|
transcript,
|
1797
1854
|
})
|
1798
1855
|
}
|
1799
|
-
|
1800
|
-
|
1856
|
+
|
1857
|
+
console.log("NOT A YOUTUBE LINK", decoded)
|
1801
1858
|
|
1802
1859
|
const response = await axios.get(decoded, { responseType: "text" })
|
1803
1860
|
const html = response.data as string
|
@@ -1812,9 +1869,7 @@ export default class ServeCommand extends SessionCommand {
|
|
1812
1869
|
})
|
1813
1870
|
} catch (error: any) {
|
1814
1871
|
console.error("❌ /actions/fetch error:", error.message || error)
|
1815
|
-
res
|
1816
|
-
.status(500)
|
1817
|
-
.json({ error: error.message || "Failed to fetch link" })
|
1872
|
+
res.status(500).json({ error: error.message || "Failed to fetch link" })
|
1818
1873
|
}
|
1819
1874
|
})
|
1820
1875
|
app.delete("/packages/:slug", async (req, res) => {
|