@learnpack/learnpack 5.0.238 → 5.0.244
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/lib/commands/init.js +7 -2
- package/lib/commands/publish.d.ts +1 -1
- package/lib/commands/publish.js +22 -16
- package/lib/commands/serve.d.ts +1 -2
- package/lib/commands/serve.js +128 -71
- package/lib/creatorDist/assets/{index-x_kA-1DY.js → index-BWHp9KF3.js} +3045 -3040
- package/lib/creatorDist/index.html +1 -1
- package/lib/models/creator.d.ts +1 -0
- package/lib/utils/api.d.ts +2 -0
- package/lib/utils/api.js +1 -0
- package/lib/utils/creatorSocket.d.ts +1 -1
- package/lib/utils/creatorSocket.js +10 -3
- package/lib/utils/rigoActions.d.ts +11 -1
- package/lib/utils/rigoActions.js +29 -2
- package/package.json +1 -1
- package/src/commands/init.ts +12 -2
- package/src/commands/publish.ts +36 -26
- package/src/commands/serve.ts +223 -106
- package/src/creator/src/App.tsx +3 -1
- package/src/creator/src/components/NotificationListener.tsx +1 -1
- package/src/creator/src/components/syllabus/SyllabusEditor.tsx +11 -13
- package/src/creator/src/utils/rigo.ts +4 -2
- package/src/creator/src/utils/store.ts +4 -1
- package/src/creatorDist/assets/{index-x_kA-1DY.js → index-BWHp9KF3.js} +3045 -3040
- package/src/creatorDist/index.html +1 -1
- package/src/models/creator.ts +1 -0
- package/src/ui/_app/app.js +232 -232
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/api.ts +3 -0
- package/src/utils/creatorSocket.ts +22 -16
- package/src/utils/rigoActions.ts +54 -1
- package/oclif.manifest.json +0 -1
@@ -10,7 +10,7 @@
|
|
10
10
|
/>
|
11
11
|
|
12
12
|
<title>Learnpack Creator: Craft tutorials in seconds!</title>
|
13
|
-
<script type="module" crossorigin src="/creator/assets/index-
|
13
|
+
<script type="module" crossorigin src="/creator/assets/index-BWHp9KF3.js"></script>
|
14
14
|
<link rel="stylesheet" crossorigin href="/creator/assets/index-DmpsXknz.css">
|
15
15
|
</head>
|
16
16
|
<body>
|
package/lib/models/creator.d.ts
CHANGED
package/lib/utils/api.d.ts
CHANGED
@@ -22,6 +22,8 @@ type TAssetMissing = {
|
|
22
22
|
owner: number;
|
23
23
|
author: number;
|
24
24
|
preview: string;
|
25
|
+
readme_raw: string;
|
26
|
+
all_translations: string[];
|
25
27
|
};
|
26
28
|
export declare const createAsset: (token: string, asset: TAssetMissing) => Promise<any>;
|
27
29
|
export declare const doesAssetExists: (token: string, assetSlug: string) => Promise<{
|
package/lib/utils/api.js
CHANGED
@@ -353,6 +353,7 @@ const createAsset = async (token, asset) => {
|
|
353
353
|
translations: [asset.lang],
|
354
354
|
learnpack_deploy_url: asset.learnpack_deploy_url,
|
355
355
|
technologies: asset.technologies,
|
356
|
+
readme_raw: asset.readme_raw,
|
356
357
|
};
|
357
358
|
const url = `https://breathecode.herokuapp.com/v1/registry/asset/me`;
|
358
359
|
const headers = {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Server as SocketIOServer } from "socket.io";
|
2
2
|
export declare function initSocketIO(server: any): SocketIOServer<import("socket.io/dist/typed-events").DefaultEventsMap, import("socket.io/dist/typed-events").DefaultEventsMap, import("socket.io/dist/typed-events").DefaultEventsMap, any>;
|
3
3
|
export declare function emitToCourse(courseSlug: string, event: string, payload: any): void;
|
4
|
-
export declare function emitToNotification(notificationId: string, payload: any): void;
|
4
|
+
export declare function emitToNotification(notificationId: string, payload: any, retry?: number): void;
|
5
5
|
export declare function getSocketIO(): SocketIOServer<import("socket.io/dist/typed-events").DefaultEventsMap, import("socket.io/dist/typed-events").DefaultEventsMap, import("socket.io/dist/typed-events").DefaultEventsMap, any>;
|
@@ -62,11 +62,18 @@ function emitToCourse(courseSlug, event, payload) {
|
|
62
62
|
socket.emit(event, payload);
|
63
63
|
}
|
64
64
|
}
|
65
|
-
function emitToNotification(notificationId, payload) {
|
66
|
-
console.log("Emitting to notification", notificationId, payload);
|
65
|
+
function emitToNotification(notificationId, payload, retry = 0) {
|
67
66
|
const socketIds = notificationSocketMap.get(notificationId);
|
68
|
-
if (!socketIds || socketIds.size === 0)
|
67
|
+
if (!socketIds || socketIds.size === 0) {
|
68
|
+
if (retry > 3) {
|
69
|
+
console.log("❌ Notification", notificationId, "not found");
|
70
|
+
return;
|
71
|
+
}
|
72
|
+
setTimeout(() => {
|
73
|
+
emitToNotification(notificationId, payload, retry + 1);
|
74
|
+
}, 3000);
|
69
75
|
return;
|
76
|
+
}
|
70
77
|
for (const id of socketIds) {
|
71
78
|
const socket = socketStore.get(id);
|
72
79
|
if (socket)
|
@@ -12,8 +12,9 @@ export declare const createReadme: (token: string, inputs: TCreateReadmeInputs,
|
|
12
12
|
export declare const hasCreatorPermission: (token: string) => Promise<boolean>;
|
13
13
|
type TGenerateImageParams = {
|
14
14
|
prompt: string;
|
15
|
+
callbackUrl: string;
|
15
16
|
};
|
16
|
-
export declare const generateImage: (token: string, { prompt }: TGenerateImageParams) => Promise<any>;
|
17
|
+
export declare const generateImage: (token: string, { prompt, callbackUrl }: TGenerateImageParams) => Promise<any>;
|
17
18
|
export declare function downloadImage(imageUrl: string, savePath: string): Promise<void>;
|
18
19
|
type TTranslateInputs = {
|
19
20
|
text_to_translate: string;
|
@@ -55,6 +56,15 @@ type TReadmeCreatorInputs = {
|
|
55
56
|
last_lesson: string;
|
56
57
|
};
|
57
58
|
export declare const readmeCreator: (token: string, inputs: TReadmeCreatorInputs, purpose: string, webhookUrl?: string) => Promise<any>;
|
59
|
+
type TCreateStructuredPreviewReadmeInputs = {
|
60
|
+
tutorial_info: string;
|
61
|
+
};
|
62
|
+
export declare const createStructuredPreviewReadme: (token: string, inputs: TCreateStructuredPreviewReadmeInputs, webhookUrl?: string) => Promise<any>;
|
63
|
+
export declare const translateCourseMetadata: (token: string, inputs: {
|
64
|
+
title: string;
|
65
|
+
description: string;
|
66
|
+
destination_lang_code: string;
|
67
|
+
}) => Promise<any>;
|
58
68
|
export declare function createPreviewReadme(tutorialDir: string, packageInfo: PackageInfo, rigoToken: string, readmeContents: string[]): Promise<void>;
|
59
69
|
type TReduceReadmeInputs = {
|
60
70
|
lesson: string;
|
package/lib/utils/rigoActions.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.isPackageAuthor = exports.fillSidebarJSON = exports.generateCourseShortName = exports.isValidRigoToken = exports.readmeCreator = exports.createCodingReadme = exports.createCodeFile = exports.interactiveCreation = exports.generateCourseIntroduction = exports.translateExercise = exports.generateImage = exports.hasCreatorPermission = exports.createReadme = void 0;
|
3
|
+
exports.isPackageAuthor = exports.fillSidebarJSON = exports.generateCourseShortName = exports.isValidRigoToken = exports.translateCourseMetadata = exports.createStructuredPreviewReadme = exports.readmeCreator = exports.createCodingReadme = exports.createCodeFile = exports.interactiveCreation = exports.generateCourseIntroduction = exports.translateExercise = exports.generateImage = exports.hasCreatorPermission = exports.createReadme = void 0;
|
4
4
|
exports.downloadImage = downloadImage;
|
5
5
|
exports.createPreviewReadme = createPreviewReadme;
|
6
6
|
exports.makeReadmeReadable = makeReadmeReadable;
|
@@ -53,10 +53,13 @@ const hasCreatorPermission = async (token) => {
|
|
53
53
|
}
|
54
54
|
};
|
55
55
|
exports.hasCreatorPermission = hasCreatorPermission;
|
56
|
-
const generateImage = async (token, { prompt }) => {
|
56
|
+
const generateImage = async (token, { prompt, callbackUrl }) => {
|
57
57
|
try {
|
58
58
|
const response = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/learnpack/tools/images`, {
|
59
59
|
prompt,
|
60
|
+
webhook_callback_url: callbackUrl,
|
61
|
+
provider: "bfl",
|
62
|
+
model: "flux-pro-1.1",
|
60
63
|
}, {
|
61
64
|
headers: {
|
62
65
|
"Content-Type": "application/json",
|
@@ -174,6 +177,30 @@ const readmeCreator = async (token, inputs, purpose, webhookUrl) => {
|
|
174
177
|
throw new Error("Invalid kind of lesson");
|
175
178
|
};
|
176
179
|
exports.readmeCreator = readmeCreator;
|
180
|
+
const createStructuredPreviewReadme = async (token, inputs, webhookUrl) => {
|
181
|
+
const response = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/prompting/completion/write-course-introduction-readme/`, {
|
182
|
+
inputs: inputs,
|
183
|
+
include_purpose_objective: false,
|
184
|
+
webhook_url: webhookUrl,
|
185
|
+
}, {
|
186
|
+
headers: {
|
187
|
+
"Content-Type": "application/json",
|
188
|
+
Authorization: "Token " + token,
|
189
|
+
},
|
190
|
+
});
|
191
|
+
return response.data;
|
192
|
+
};
|
193
|
+
exports.createStructuredPreviewReadme = createStructuredPreviewReadme;
|
194
|
+
const translateCourseMetadata = async (token, inputs) => {
|
195
|
+
const response = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/prompting/completion/translate-course-metadata/`, { inputs, include_purpose_objective: false, execute_async: false }, {
|
196
|
+
headers: {
|
197
|
+
"Content-Type": "application/json",
|
198
|
+
Authorization: "Token " + token,
|
199
|
+
},
|
200
|
+
});
|
201
|
+
return response.data;
|
202
|
+
};
|
203
|
+
exports.translateCourseMetadata = translateCourseMetadata;
|
177
204
|
async function createPreviewReadme(tutorialDir, packageInfo, rigoToken, readmeContents) {
|
178
205
|
const readmeFilename = `README.md`;
|
179
206
|
const readmeContent = await (0, exports.generateCourseIntroduction)(rigoToken, {
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@learnpack/learnpack",
|
3
3
|
"description": "Seamlessly build, sell and/or take interactive & auto-graded tutorials, start learning now or build a new tutorial to your audience.",
|
4
|
-
"version": "5.0.
|
4
|
+
"version": "5.0.244",
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
6
6
|
"contributors": [
|
7
7
|
{
|
package/src/commands/init.ts
CHANGED
@@ -35,6 +35,7 @@ import {
|
|
35
35
|
estimateDuration,
|
36
36
|
appendContentIndex,
|
37
37
|
appendAIRules,
|
38
|
+
slugify,
|
38
39
|
} from "../utils/creatorUtilities"
|
39
40
|
import SessionManager from "../managers/session"
|
40
41
|
|
@@ -407,10 +408,16 @@ const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
|
|
407
408
|
const imagePromises = imagesArray.map(async (image: any) => {
|
408
409
|
try {
|
409
410
|
const filename = getFilenameFromUrl(image.url)
|
411
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${slugify(
|
412
|
+
packageInfo.title.us
|
413
|
+
)}/images/${filename}`
|
410
414
|
|
411
415
|
const imagePath = path.join(tutorialDir, ".learn", "assets", filename)
|
412
416
|
|
413
|
-
const res = await generateImage(rigoToken, {
|
417
|
+
const res = await generateImage(rigoToken, {
|
418
|
+
prompt: image.alt,
|
419
|
+
callbackUrl: webhookUrl,
|
420
|
+
})
|
414
421
|
await downloadImage(res.image_url, imagePath)
|
415
422
|
return true
|
416
423
|
} catch {
|
@@ -434,9 +441,12 @@ const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
|
|
434
441
|
"Generate a preview image for the tutorial. This is all the tutorial information: " +
|
435
442
|
packageContext +
|
436
443
|
"\n Generate only a basic preview image, add the tutorial Title as a text add the top middle, avoid adding any other text elements. Try to generate an image that related with the tutorial content.",
|
444
|
+
callbackUrl: `${process.env.HOST}/webhooks/${slugify(
|
445
|
+
packageInfo.title.us
|
446
|
+
)}/images/preview.png`,
|
437
447
|
})
|
438
448
|
|
439
|
-
await downloadImage(res.image_url, imagePath)
|
449
|
+
// await downloadImage(res.image_url, imagePath)
|
440
450
|
|
441
451
|
return true
|
442
452
|
}
|
package/src/commands/publish.ts
CHANGED
@@ -19,6 +19,7 @@ import api, { getConsumable, RIGOBOT_HOST, TAcademy } from "../utils/api"
|
|
19
19
|
import * as prompts from "prompts"
|
20
20
|
import { isValidRigoToken } from "../utils/rigoActions"
|
21
21
|
import { minutesToISO8601Duration } from "../utils/misc"
|
22
|
+
import { slugify } from "../utils/creatorUtilities"
|
22
23
|
|
23
24
|
const uploadZipEndpont = RIGOBOT_HOST + "/v1/learnpack/upload"
|
24
25
|
|
@@ -26,11 +27,13 @@ export const handleAssetCreation = async (
|
|
26
27
|
sessionPayload: { token: string; rigobotToken: string },
|
27
28
|
learnJson: any,
|
28
29
|
selectedLang: string,
|
29
|
-
learnpackDeployUrl: string
|
30
|
+
learnpackDeployUrl: string,
|
31
|
+
b64IndexReadme: string,
|
32
|
+
all_translations: string[] = []
|
30
33
|
) => {
|
31
34
|
const categories: Record<string, number> = {
|
32
|
-
us:
|
33
|
-
es:
|
35
|
+
us: 9,
|
36
|
+
es: 10,
|
34
37
|
}
|
35
38
|
|
36
39
|
let category = categories[selectedLang]
|
@@ -42,15 +45,13 @@ export const handleAssetCreation = async (
|
|
42
45
|
try {
|
43
46
|
const user = await api.validateToken(sessionPayload.token)
|
44
47
|
|
45
|
-
const
|
46
|
-
|
47
|
-
learnJson.slug
|
48
|
-
)
|
48
|
+
const slug = slugify(learnJson.title[selectedLang]).slice(0, 50)
|
49
|
+
const { exists } = await api.doesAssetExists(sessionPayload.token, slug)
|
49
50
|
|
50
51
|
if (!exists) {
|
51
52
|
Console.info("Asset does not exist in this academy, creating it")
|
52
53
|
const asset = await api.createAsset(sessionPayload.token, {
|
53
|
-
slug:
|
54
|
+
slug: slug,
|
54
55
|
title: learnJson.title[selectedLang],
|
55
56
|
lang: selectedLang,
|
56
57
|
description: learnJson.description[selectedLang],
|
@@ -61,6 +62,8 @@ export const handleAssetCreation = async (
|
|
61
62
|
owner: user.id,
|
62
63
|
author: user.id,
|
63
64
|
preview: learnJson.preview,
|
65
|
+
readme_raw: b64IndexReadme,
|
66
|
+
all_translations,
|
64
67
|
})
|
65
68
|
await api.updateRigoAssetID(
|
66
69
|
sessionPayload.token,
|
@@ -68,26 +71,26 @@ export const handleAssetCreation = async (
|
|
68
71
|
asset.id
|
69
72
|
)
|
70
73
|
Console.info("Asset created with id", asset.id)
|
71
|
-
|
72
|
-
Console.info("Asset exists, updating it")
|
73
|
-
const asset = await api.updateAsset(
|
74
|
-
sessionPayload.token,
|
75
|
-
learnJson.slug,
|
76
|
-
{
|
77
|
-
learnpack_deploy_url: learnpackDeployUrl,
|
78
|
-
title: learnJson.title[selectedLang],
|
79
|
-
description: learnJson.description[selectedLang],
|
80
|
-
}
|
81
|
-
)
|
82
|
-
await api.updateRigoAssetID(
|
83
|
-
sessionPayload.rigobotToken,
|
84
|
-
learnJson.slug,
|
85
|
-
asset.id
|
86
|
-
)
|
87
|
-
Console.info("Asset updated with id", asset.id)
|
74
|
+
return asset
|
88
75
|
}
|
76
|
+
|
77
|
+
Console.info("Asset exists, updating it")
|
78
|
+
const asset = await api.updateAsset(sessionPayload.token, slug, {
|
79
|
+
learnpack_deploy_url: learnpackDeployUrl,
|
80
|
+
title: learnJson.title[selectedLang],
|
81
|
+
description: learnJson.description[selectedLang],
|
82
|
+
all_translations,
|
83
|
+
})
|
84
|
+
await api.updateRigoAssetID(
|
85
|
+
sessionPayload.rigobotToken.trim(),
|
86
|
+
learnJson.slug,
|
87
|
+
asset.id
|
88
|
+
)
|
89
|
+
Console.info("Asset updated with id", asset.id)
|
90
|
+
return asset
|
89
91
|
} catch (error) {
|
90
92
|
Console.error("Error updating or creating asset:", error)
|
93
|
+
return null
|
91
94
|
}
|
92
95
|
}
|
93
96
|
|
@@ -435,7 +438,14 @@ class BuildCommand extends SessionCommand {
|
|
435
438
|
fs.unlinkSync(zipFilePath)
|
436
439
|
this.removeDirectory(buildDir)
|
437
440
|
|
438
|
-
await handleAssetCreation(
|
441
|
+
await handleAssetCreation(
|
442
|
+
sessionPayload,
|
443
|
+
learnJson,
|
444
|
+
"us",
|
445
|
+
res.data.url,
|
446
|
+
"",
|
447
|
+
[]
|
448
|
+
)
|
439
449
|
} catch (error) {
|
440
450
|
if (axios.isAxiosError(error)) {
|
441
451
|
if (error.response && error.response.status === 403) {
|