@learnpack/learnpack 5.0.270 → 5.0.274

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 (77) 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 +48 -20
  8. package/lib/creatorDist/assets/{index-CQXTTbaZ.js → index-BfLyIQVh.js} +11535 -11409
  9. package/lib/creatorDist/assets/{index-B4khtb0r.css → index-C39zeF3W.css} +3 -3
  10. package/lib/creatorDist/index.html +2 -2
  11. package/lib/managers/config/index.js +77 -77
  12. package/lib/models/creator.d.ts +1 -0
  13. package/lib/utils/api.js +1 -0
  14. package/lib/utils/creatorUtilities.js +14 -14
  15. package/package.json +1 -1
  16. package/src/commands/audit.ts +487 -487
  17. package/src/commands/breakToken.ts +67 -67
  18. package/src/commands/clean.ts +30 -30
  19. package/src/commands/init.ts +650 -650
  20. package/src/commands/logout.ts +38 -38
  21. package/src/commands/publish.ts +522 -522
  22. package/src/commands/serve.ts +64 -33
  23. package/src/commands/start.ts +333 -333
  24. package/src/commands/translate.ts +123 -123
  25. package/src/creator/README.md +54 -54
  26. package/src/creator/eslint.config.js +28 -28
  27. package/src/creator/src/components/syllabus/ContentIndex.tsx +1 -1
  28. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +3 -1
  29. package/src/creator/src/i18n.ts +28 -28
  30. package/src/creator/src/index.css +217 -217
  31. package/src/creator/src/locales/en.json +1 -0
  32. package/src/creator/src/locales/es.json +1 -0
  33. package/src/creator/src/utils/configTypes.ts +122 -122
  34. package/src/creator/src/utils/constants.ts +13 -13
  35. package/src/creator/src/utils/creatorUtils.ts +46 -46
  36. package/src/creator/src/utils/eventBus.ts +2 -2
  37. package/src/creator/src/utils/lib.ts +468 -468
  38. package/src/creator/src/utils/rigo.ts +26 -26
  39. package/src/creator/src/utils/socket.ts +61 -61
  40. package/src/creator/src/utils/store.ts +222 -222
  41. package/src/creator/src/vite-env.d.ts +1 -1
  42. package/src/creator/vite.config.ts +13 -13
  43. package/src/creatorDist/assets/{index-CQXTTbaZ.js → index-BfLyIQVh.js} +11535 -11409
  44. package/src/creatorDist/assets/{index-B4khtb0r.css → index-C39zeF3W.css} +3 -3
  45. package/src/creatorDist/index.html +2 -2
  46. package/src/managers/config/defaults.ts +49 -49
  47. package/src/managers/config/exercise.ts +364 -364
  48. package/src/managers/config/index.ts +775 -775
  49. package/src/managers/file.ts +236 -236
  50. package/src/managers/server/routes.ts +554 -554
  51. package/src/managers/session.ts +182 -182
  52. package/src/managers/telemetry.ts +188 -188
  53. package/src/models/action.ts +13 -13
  54. package/src/models/config-manager.ts +28 -28
  55. package/src/models/config.ts +106 -106
  56. package/src/models/creator.ts +40 -39
  57. package/src/models/exercise-obj.ts +30 -30
  58. package/src/models/session.ts +39 -39
  59. package/src/models/socket.ts +61 -61
  60. package/src/models/status.ts +16 -16
  61. package/src/ui/_app/app.css +1 -1
  62. package/src/ui/_app/app.js +435 -414
  63. package/src/ui/_app/learnpack.svg +7 -7
  64. package/src/ui/app.tar.gz +0 -0
  65. package/src/utils/BaseCommand.ts +56 -56
  66. package/src/utils/api.ts +31 -30
  67. package/src/utils/audit.ts +392 -392
  68. package/src/utils/checkNotInstalled.ts +267 -267
  69. package/src/utils/configBuilder.ts +82 -82
  70. package/src/utils/convertCreds.js +34 -34
  71. package/src/utils/creatorUtilities.ts +504 -504
  72. package/src/utils/incrementVersion.js +74 -74
  73. package/src/utils/misc.ts +58 -58
  74. package/src/utils/rigoActions.ts +500 -500
  75. package/src/utils/sidebarGenerator.ts +195 -195
  76. package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  77. package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
@@ -1,500 +1,500 @@
1
- import axios from "axios"
2
- import { writeFile } from "fs/promises"
3
- import Console from "../utils/console"
4
- import { PackageInfo } from "./creatorUtilities"
5
- import * as fs from "fs"
6
- import * as path from "path"
7
- import { RIGOBOT_HOST } from "./api"
8
-
9
- type TCreateReadmeInputs = {
10
- title: string
11
- output_lang: string
12
- list_of_exercises: string
13
- tutorial_description: string
14
- include_quiz: string
15
- lesson_description: string
16
- prev_lesson: string
17
- }
18
-
19
- export const createReadme = async (
20
- token: string,
21
- inputs: TCreateReadmeInputs,
22
- purpose: string,
23
- webhookUrl?: string
24
- ) => {
25
- try {
26
- const response = await axios.post(
27
- `${RIGOBOT_HOST}/v1/prompting/completion/create-sequencial-readme/`,
28
- {
29
- inputs,
30
- include_purpose_objective: true,
31
- execute_async: !!webhookUrl,
32
- purpose_slug: purpose,
33
- webhook_url: webhookUrl,
34
- },
35
- {
36
- headers: {
37
- "Content-Type": "application/json",
38
- Authorization: "Token " + token,
39
- },
40
- }
41
- )
42
- return response.data
43
- } catch (error) {
44
- console.error(error)
45
- return null
46
- }
47
- }
48
-
49
- export const hasCreatorPermission = async (token: string) => {
50
- Console.debug("Checking if user has creator permission")
51
- try {
52
- const response = await axios.get(
53
- `${RIGOBOT_HOST}/v1/learnpack/permissions/creator`,
54
- {
55
- headers: {
56
- "Content-Type": "application/json",
57
- Authorization: "Token " + token,
58
- },
59
- }
60
- )
61
-
62
- // If the status code is 403, it means no permission
63
- if (response.status === 403) return false
64
-
65
- Console.debug("The user is a creator! 🎉")
66
- return true
67
- } catch (error) {
68
- Console.error(error as string)
69
- return false
70
- }
71
- }
72
-
73
- type TGenerateImageParams = {
74
- prompt: string
75
- callbackUrl: string
76
- }
77
-
78
- export const generateImage = async (
79
- token: string,
80
- { prompt, callbackUrl }: TGenerateImageParams
81
- ) => {
82
- try {
83
- const response = await axios.post(
84
- `${RIGOBOT_HOST}/v1/learnpack/tools/images`,
85
- {
86
- prompt,
87
- webhook_callback_url: callbackUrl,
88
- provider: "bfl",
89
- model: "flux-pro-1.1",
90
- },
91
- {
92
- headers: {
93
- "Content-Type": "application/json",
94
- Authorization: "Token " + token,
95
- },
96
- }
97
- )
98
-
99
- return response.data
100
- } catch (error) {
101
- Console.debug(error)
102
- return null
103
- }
104
- }
105
-
106
- export async function downloadImage(
107
- imageUrl: string,
108
- savePath: string
109
- ): Promise<void> {
110
- const response = await axios.get(imageUrl, { responseType: "arraybuffer" })
111
-
112
- const buffer = Buffer.from(response.data, "binary")
113
-
114
- await writeFile(savePath, buffer)
115
- }
116
-
117
- type TTranslateInputs = {
118
- text_to_translate: string
119
- output_language: string
120
- }
121
- export const translateExercise = async (
122
- token: string,
123
- inputs: TTranslateInputs,
124
- webhookUrl: string
125
- ) => {
126
- const response = await axios.post(
127
- `${RIGOBOT_HOST}/v1/prompting/completion/translate-asset-markdown/`,
128
- {
129
- inputs: inputs,
130
- include_purpose_objective: false,
131
- execute_async: true,
132
- webhook_url: webhookUrl,
133
- },
134
- {
135
- headers: {
136
- "Content-Type": "application/json",
137
- Authorization: "Token " + token,
138
- },
139
- }
140
- )
141
-
142
- return response.data
143
- }
144
-
145
- type TGenerateCourseIntroductionInputs = {
146
- course_title: string
147
- lessons_context: string
148
- }
149
-
150
- export const generateCourseIntroduction = async (
151
- token: string,
152
- inputs: TGenerateCourseIntroductionInputs
153
- ) => {
154
- const response = await axios.post(
155
- `${RIGOBOT_HOST}/v1/prompting/completion/192/`,
156
- {
157
- inputs: inputs,
158
- include_purpose_objective: false,
159
- execute_async: false,
160
- },
161
- {
162
- headers: {
163
- "Content-Type": "application/json",
164
- Authorization: "Token " + token,
165
- },
166
- }
167
- )
168
-
169
- return response.data
170
- }
171
-
172
- type TInteractiveCreationInputs = {
173
- courseInfo: string
174
- prevInteractions: string
175
- }
176
- export const interactiveCreation = async (
177
- token: string,
178
- inputs: TInteractiveCreationInputs
179
- ) => {
180
- const response = await axios.post(
181
- `${RIGOBOT_HOST}/v1/prompting/completion/390/`,
182
- {
183
- inputs: inputs,
184
- include_purpose_objective: false,
185
- execute_async: false,
186
- },
187
- {
188
- headers: {
189
- "Content-Type": "application/json",
190
- Authorization: "Token " + token,
191
- },
192
- }
193
- )
194
-
195
- return response.data
196
- }
197
-
198
- type TCreateCodeFileInputs = {
199
- readme: string
200
- tutorial_info: string
201
- }
202
-
203
- export const createCodeFile = async (
204
- token: string,
205
- inputs: TCreateCodeFileInputs
206
- ) => {
207
- const response = await axios.post(
208
- `${RIGOBOT_HOST}/v1/prompting/completion/456/`,
209
- {
210
- inputs: inputs,
211
- include_purpose_objective: false,
212
- execute_async: false,
213
- },
214
- {
215
- headers: {
216
- "Content-Type": "application/json",
217
- Authorization: "Token " + token,
218
- },
219
- }
220
- )
221
-
222
- return response.data
223
- }
224
-
225
- type TCreateCodingReadmeInputs = {
226
- title: string
227
- output_lang: string
228
- prev_lesson: string
229
- tutorial_info: string
230
- list_of_exercises: string
231
- lesson_description: string
232
- }
233
- export const createCodingReadme = async (
234
- token: string,
235
- inputs: TCreateCodingReadmeInputs,
236
- purpose: string,
237
- webhookUrl?: string
238
- ) => {
239
- const response = await axios.post(
240
- `${RIGOBOT_HOST}/v1/prompting/completion/create-coding-exercise/`,
241
- {
242
- inputs,
243
- include_purpose_objective: true,
244
- purpose_slug: purpose,
245
- execute_async: !!webhookUrl,
246
- webhook_url: webhookUrl,
247
- },
248
- {
249
- headers: {
250
- "Content-Type": "application/json",
251
- Authorization: "Token " + token,
252
- },
253
- }
254
- )
255
-
256
- return response.data
257
- }
258
-
259
- type TReadmeCreatorInputs = {
260
- tutorial_description: string
261
- list_of_exercises: string
262
- output_lang: string
263
- title: string
264
- lesson_description: string
265
- kind: string
266
- last_lesson: string
267
- }
268
-
269
- export const readmeCreator = async (
270
- token: string,
271
- inputs: TReadmeCreatorInputs,
272
- purpose: string,
273
- webhookUrl?: string
274
- ) => {
275
- if (inputs.kind === "quiz" || inputs.kind === "read") {
276
- const createReadmeInputs: TCreateReadmeInputs = {
277
- title: inputs.title,
278
- output_lang: inputs.output_lang,
279
- list_of_exercises: inputs.list_of_exercises,
280
- tutorial_description: inputs.tutorial_description,
281
- include_quiz: inputs.kind === "quiz" ? "true" : "false",
282
- lesson_description: inputs.lesson_description,
283
- prev_lesson: inputs.last_lesson,
284
- }
285
- return createReadme(token, createReadmeInputs, purpose, webhookUrl)
286
- }
287
-
288
- if (inputs.kind === "code") {
289
- return createCodingReadme(
290
- token,
291
- {
292
- title: inputs.title,
293
- output_lang: inputs.output_lang,
294
- list_of_exercises: inputs.list_of_exercises,
295
- tutorial_info: inputs.tutorial_description,
296
- lesson_description: inputs.lesson_description,
297
- prev_lesson: inputs.last_lesson,
298
- },
299
- purpose,
300
- webhookUrl
301
- )
302
- }
303
-
304
- throw new Error("Invalid kind of lesson")
305
- }
306
-
307
- type TCreateStructuredPreviewReadmeInputs = {
308
- tutorial_info: string
309
- }
310
-
311
- export const createStructuredPreviewReadme = async (
312
- token: string,
313
- inputs: TCreateStructuredPreviewReadmeInputs,
314
- webhookUrl?: string
315
- ) => {
316
- const response = await axios.post(
317
- `${RIGOBOT_HOST}/v1/prompting/completion/write-course-introduction-readme/`,
318
- {
319
- inputs: inputs,
320
- include_purpose_objective: false,
321
- webhook_url: webhookUrl,
322
- },
323
- {
324
- headers: {
325
- "Content-Type": "application/json",
326
- Authorization: "Token " + token,
327
- },
328
- }
329
- )
330
-
331
- return response.data
332
- }
333
-
334
- export const translateCourseMetadata = async (
335
- token: string,
336
- inputs: {
337
- title: string
338
- description: string
339
- new_languages: string
340
- }
341
- ) => {
342
- const response = await axios.post(
343
- `${RIGOBOT_HOST}/v1/prompting/completion/translate-course-metadata/`,
344
- { inputs, include_purpose_objective: false, execute_async: false },
345
- {
346
- headers: {
347
- "Content-Type": "application/json",
348
- Authorization: "Token " + token,
349
- },
350
- }
351
- )
352
-
353
- return response.data
354
- }
355
-
356
- export async function createPreviewReadme(
357
- tutorialDir: string,
358
- packageInfo: PackageInfo,
359
- rigoToken: string,
360
- readmeContents: string[]
361
- ) {
362
- const readmeFilename = `README.md`
363
-
364
- const readmeContent = await generateCourseIntroduction(rigoToken, {
365
- course_title: packageInfo.title.us,
366
- lessons_context: readmeContents.join("\n"),
367
- })
368
- fs.writeFileSync(path.join(tutorialDir, readmeFilename), readmeContent.answer)
369
- }
370
-
371
- // {"lesson": "The text of the lesson", "number_of_words": "Words lenght of the lesson", "expected_number_words": "The expected number of words"}
372
-
373
- type TReduceReadmeInputs = {
374
- lesson: string
375
- number_of_words: string
376
- expected_number_words: string
377
- fkgl_results: string
378
- expected_grade_level: string
379
- }
380
- export async function makeReadmeReadable(
381
- rigoToken: string,
382
- inputs: TReduceReadmeInputs,
383
- purpose: string
384
- ) {
385
- try {
386
- const response = await axios.post(
387
- `${RIGOBOT_HOST}/v1/prompting/completion/588/`,
388
- { inputs, include_purpose_objective: false, execute_async: false },
389
- {
390
- headers: {
391
- "Content-Type": "application/json",
392
- Authorization: "Token " + rigoToken,
393
- },
394
- }
395
- )
396
-
397
- return response.data
398
- } catch (error) {
399
- Console.debug(error)
400
- return null
401
- }
402
- }
403
-
404
- export const isValidRigoToken = async (rigobotToken: string) => {
405
- const rigoUrl = `${RIGOBOT_HOST}/v1/auth/token/${rigobotToken}`
406
- const rigoResp = await fetch(rigoUrl)
407
- if (!rigoResp.ok) {
408
- Console.debug("Invalid Rigobot token", rigoResp.status)
409
- Console.debug(rigoResp.statusText)
410
- return false
411
- }
412
-
413
- return true
414
- }
415
-
416
- type TGenerateCourseShortNameInputs = {
417
- learnJSON: string
418
- }
419
-
420
- export const generateCourseShortName = async (
421
- token: string,
422
- inputs: TGenerateCourseShortNameInputs
423
- ) => {
424
- const response = await axios.post(
425
- `${RIGOBOT_HOST}/v1/prompting/completion/852/`,
426
- { inputs, include_purpose_objective: false, execute_async: false },
427
- {
428
- headers: {
429
- "Content-Type": "application/json",
430
- Authorization: "Token " + token,
431
- },
432
- }
433
- )
434
-
435
- return response.data
436
- }
437
-
438
- type TFillSidebarJSONInputs = {
439
- needed_translations: string
440
- sidebar_json: string
441
- }
442
-
443
- export const fillSidebarJSON = async (
444
- token: string,
445
- inputs: TFillSidebarJSONInputs
446
- ) => {
447
- const response = await axios.post(
448
- `${RIGOBOT_HOST}/v1/prompting/completion/951/`,
449
- { inputs, include_purpose_objective: false, execute_async: false },
450
- {
451
- headers: {
452
- "Content-Type": "application/json",
453
- Authorization: "Token " + token,
454
- },
455
- }
456
- )
457
-
458
- return response.data
459
- }
460
-
461
- export const isPackageAuthor = async (
462
- token: string,
463
- packageSlug: string
464
- ): Promise<{ isAuthor: boolean; status: number }> => {
465
- const url = `${RIGOBOT_HOST}/v1/learnpack/package/${packageSlug}/`
466
-
467
- const headers = {
468
- Authorization: `Token ${token}`,
469
- }
470
-
471
- try {
472
- const response = await axios.get(url, { headers })
473
- return { isAuthor: response.status === 200, status: response.status }
474
- } catch (error: any) {
475
- const status = error?.response?.status || 500
476
- console.error("Error fetching package:", error)
477
- return { isAuthor: false, status }
478
- }
479
- }
480
-
481
- type TGetLanguageCodesInputs = {
482
- raw_languages: string
483
- }
484
- export const getLanguageCodes = async (
485
- token: string,
486
- inputs: TGetLanguageCodesInputs
487
- ) => {
488
- const response = await axios.post(
489
- `${RIGOBOT_HOST}/v1/prompting/completion/get-language-codes/`,
490
- { inputs, include_purpose_objective: false, execute_async: false },
491
- {
492
- headers: {
493
- "Content-Type": "application/json",
494
- Authorization: "Token " + token,
495
- },
496
- }
497
- )
498
-
499
- return response.data
500
- }
1
+ import axios from "axios"
2
+ import { writeFile } from "fs/promises"
3
+ import Console from "../utils/console"
4
+ import { PackageInfo } from "./creatorUtilities"
5
+ import * as fs from "fs"
6
+ import * as path from "path"
7
+ import { RIGOBOT_HOST } from "./api"
8
+
9
+ type TCreateReadmeInputs = {
10
+ title: string
11
+ output_lang: string
12
+ list_of_exercises: string
13
+ tutorial_description: string
14
+ include_quiz: string
15
+ lesson_description: string
16
+ prev_lesson: string
17
+ }
18
+
19
+ export const createReadme = async (
20
+ token: string,
21
+ inputs: TCreateReadmeInputs,
22
+ purpose: string,
23
+ webhookUrl?: string
24
+ ) => {
25
+ try {
26
+ const response = await axios.post(
27
+ `${RIGOBOT_HOST}/v1/prompting/completion/create-sequencial-readme/`,
28
+ {
29
+ inputs,
30
+ include_purpose_objective: true,
31
+ execute_async: !!webhookUrl,
32
+ purpose_slug: purpose,
33
+ webhook_url: webhookUrl,
34
+ },
35
+ {
36
+ headers: {
37
+ "Content-Type": "application/json",
38
+ Authorization: "Token " + token,
39
+ },
40
+ }
41
+ )
42
+ return response.data
43
+ } catch (error) {
44
+ console.error(error)
45
+ return null
46
+ }
47
+ }
48
+
49
+ export const hasCreatorPermission = async (token: string) => {
50
+ Console.debug("Checking if user has creator permission")
51
+ try {
52
+ const response = await axios.get(
53
+ `${RIGOBOT_HOST}/v1/learnpack/permissions/creator`,
54
+ {
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ Authorization: "Token " + token,
58
+ },
59
+ }
60
+ )
61
+
62
+ // If the status code is 403, it means no permission
63
+ if (response.status === 403) return false
64
+
65
+ Console.debug("The user is a creator! 🎉")
66
+ return true
67
+ } catch (error) {
68
+ Console.error(error as string)
69
+ return false
70
+ }
71
+ }
72
+
73
+ type TGenerateImageParams = {
74
+ prompt: string
75
+ callbackUrl: string
76
+ }
77
+
78
+ export const generateImage = async (
79
+ token: string,
80
+ { prompt, callbackUrl }: TGenerateImageParams
81
+ ) => {
82
+ try {
83
+ const response = await axios.post(
84
+ `${RIGOBOT_HOST}/v1/learnpack/tools/images`,
85
+ {
86
+ prompt,
87
+ webhook_callback_url: callbackUrl,
88
+ provider: "bfl",
89
+ model: "flux-pro-1.1",
90
+ },
91
+ {
92
+ headers: {
93
+ "Content-Type": "application/json",
94
+ Authorization: "Token " + token,
95
+ },
96
+ }
97
+ )
98
+
99
+ return response.data
100
+ } catch (error) {
101
+ Console.debug(error)
102
+ return null
103
+ }
104
+ }
105
+
106
+ export async function downloadImage(
107
+ imageUrl: string,
108
+ savePath: string
109
+ ): Promise<void> {
110
+ const response = await axios.get(imageUrl, { responseType: "arraybuffer" })
111
+
112
+ const buffer = Buffer.from(response.data, "binary")
113
+
114
+ await writeFile(savePath, buffer)
115
+ }
116
+
117
+ type TTranslateInputs = {
118
+ text_to_translate: string
119
+ output_language: string
120
+ }
121
+ export const translateExercise = async (
122
+ token: string,
123
+ inputs: TTranslateInputs,
124
+ webhookUrl: string
125
+ ) => {
126
+ const response = await axios.post(
127
+ `${RIGOBOT_HOST}/v1/prompting/completion/translate-asset-markdown/`,
128
+ {
129
+ inputs: inputs,
130
+ include_purpose_objective: false,
131
+ execute_async: true,
132
+ webhook_url: webhookUrl,
133
+ },
134
+ {
135
+ headers: {
136
+ "Content-Type": "application/json",
137
+ Authorization: "Token " + token,
138
+ },
139
+ }
140
+ )
141
+
142
+ return response.data
143
+ }
144
+
145
+ type TGenerateCourseIntroductionInputs = {
146
+ course_title: string
147
+ lessons_context: string
148
+ }
149
+
150
+ export const generateCourseIntroduction = async (
151
+ token: string,
152
+ inputs: TGenerateCourseIntroductionInputs
153
+ ) => {
154
+ const response = await axios.post(
155
+ `${RIGOBOT_HOST}/v1/prompting/completion/192/`,
156
+ {
157
+ inputs: inputs,
158
+ include_purpose_objective: false,
159
+ execute_async: false,
160
+ },
161
+ {
162
+ headers: {
163
+ "Content-Type": "application/json",
164
+ Authorization: "Token " + token,
165
+ },
166
+ }
167
+ )
168
+
169
+ return response.data
170
+ }
171
+
172
+ type TInteractiveCreationInputs = {
173
+ courseInfo: string
174
+ prevInteractions: string
175
+ }
176
+ export const interactiveCreation = async (
177
+ token: string,
178
+ inputs: TInteractiveCreationInputs
179
+ ) => {
180
+ const response = await axios.post(
181
+ `${RIGOBOT_HOST}/v1/prompting/completion/390/`,
182
+ {
183
+ inputs: inputs,
184
+ include_purpose_objective: false,
185
+ execute_async: false,
186
+ },
187
+ {
188
+ headers: {
189
+ "Content-Type": "application/json",
190
+ Authorization: "Token " + token,
191
+ },
192
+ }
193
+ )
194
+
195
+ return response.data
196
+ }
197
+
198
+ type TCreateCodeFileInputs = {
199
+ readme: string
200
+ tutorial_info: string
201
+ }
202
+
203
+ export const createCodeFile = async (
204
+ token: string,
205
+ inputs: TCreateCodeFileInputs
206
+ ) => {
207
+ const response = await axios.post(
208
+ `${RIGOBOT_HOST}/v1/prompting/completion/456/`,
209
+ {
210
+ inputs: inputs,
211
+ include_purpose_objective: false,
212
+ execute_async: false,
213
+ },
214
+ {
215
+ headers: {
216
+ "Content-Type": "application/json",
217
+ Authorization: "Token " + token,
218
+ },
219
+ }
220
+ )
221
+
222
+ return response.data
223
+ }
224
+
225
+ type TCreateCodingReadmeInputs = {
226
+ title: string
227
+ output_lang: string
228
+ prev_lesson: string
229
+ tutorial_info: string
230
+ list_of_exercises: string
231
+ lesson_description: string
232
+ }
233
+ export const createCodingReadme = async (
234
+ token: string,
235
+ inputs: TCreateCodingReadmeInputs,
236
+ purpose: string,
237
+ webhookUrl?: string
238
+ ) => {
239
+ const response = await axios.post(
240
+ `${RIGOBOT_HOST}/v1/prompting/completion/create-coding-exercise/`,
241
+ {
242
+ inputs,
243
+ include_purpose_objective: true,
244
+ purpose_slug: purpose,
245
+ execute_async: !!webhookUrl,
246
+ webhook_url: webhookUrl,
247
+ },
248
+ {
249
+ headers: {
250
+ "Content-Type": "application/json",
251
+ Authorization: "Token " + token,
252
+ },
253
+ }
254
+ )
255
+
256
+ return response.data
257
+ }
258
+
259
+ type TReadmeCreatorInputs = {
260
+ tutorial_description: string
261
+ list_of_exercises: string
262
+ output_lang: string
263
+ title: string
264
+ lesson_description: string
265
+ kind: string
266
+ last_lesson: string
267
+ }
268
+
269
+ export const readmeCreator = async (
270
+ token: string,
271
+ inputs: TReadmeCreatorInputs,
272
+ purpose: string,
273
+ webhookUrl?: string
274
+ ) => {
275
+ if (inputs.kind === "quiz" || inputs.kind === "read") {
276
+ const createReadmeInputs: TCreateReadmeInputs = {
277
+ title: inputs.title,
278
+ output_lang: inputs.output_lang,
279
+ list_of_exercises: inputs.list_of_exercises,
280
+ tutorial_description: inputs.tutorial_description,
281
+ include_quiz: inputs.kind === "quiz" ? "true" : "false",
282
+ lesson_description: inputs.lesson_description,
283
+ prev_lesson: inputs.last_lesson,
284
+ }
285
+ return createReadme(token, createReadmeInputs, purpose, webhookUrl)
286
+ }
287
+
288
+ if (inputs.kind === "code") {
289
+ return createCodingReadme(
290
+ token,
291
+ {
292
+ title: inputs.title,
293
+ output_lang: inputs.output_lang,
294
+ list_of_exercises: inputs.list_of_exercises,
295
+ tutorial_info: inputs.tutorial_description,
296
+ lesson_description: inputs.lesson_description,
297
+ prev_lesson: inputs.last_lesson,
298
+ },
299
+ purpose,
300
+ webhookUrl
301
+ )
302
+ }
303
+
304
+ throw new Error("Invalid kind of lesson")
305
+ }
306
+
307
+ type TCreateStructuredPreviewReadmeInputs = {
308
+ tutorial_info: string
309
+ }
310
+
311
+ export const createStructuredPreviewReadme = async (
312
+ token: string,
313
+ inputs: TCreateStructuredPreviewReadmeInputs,
314
+ webhookUrl?: string
315
+ ) => {
316
+ const response = await axios.post(
317
+ `${RIGOBOT_HOST}/v1/prompting/completion/write-course-introduction-readme/`,
318
+ {
319
+ inputs: inputs,
320
+ include_purpose_objective: false,
321
+ webhook_url: webhookUrl,
322
+ },
323
+ {
324
+ headers: {
325
+ "Content-Type": "application/json",
326
+ Authorization: "Token " + token,
327
+ },
328
+ }
329
+ )
330
+
331
+ return response.data
332
+ }
333
+
334
+ export const translateCourseMetadata = async (
335
+ token: string,
336
+ inputs: {
337
+ title: string
338
+ description: string
339
+ new_languages: string
340
+ }
341
+ ) => {
342
+ const response = await axios.post(
343
+ `${RIGOBOT_HOST}/v1/prompting/completion/translate-course-metadata/`,
344
+ { inputs, include_purpose_objective: false, execute_async: false },
345
+ {
346
+ headers: {
347
+ "Content-Type": "application/json",
348
+ Authorization: "Token " + token,
349
+ },
350
+ }
351
+ )
352
+
353
+ return response.data
354
+ }
355
+
356
+ export async function createPreviewReadme(
357
+ tutorialDir: string,
358
+ packageInfo: PackageInfo,
359
+ rigoToken: string,
360
+ readmeContents: string[]
361
+ ) {
362
+ const readmeFilename = `README.md`
363
+
364
+ const readmeContent = await generateCourseIntroduction(rigoToken, {
365
+ course_title: packageInfo.title.us,
366
+ lessons_context: readmeContents.join("\n"),
367
+ })
368
+ fs.writeFileSync(path.join(tutorialDir, readmeFilename), readmeContent.answer)
369
+ }
370
+
371
+ // {"lesson": "The text of the lesson", "number_of_words": "Words lenght of the lesson", "expected_number_words": "The expected number of words"}
372
+
373
+ type TReduceReadmeInputs = {
374
+ lesson: string
375
+ number_of_words: string
376
+ expected_number_words: string
377
+ fkgl_results: string
378
+ expected_grade_level: string
379
+ }
380
+ export async function makeReadmeReadable(
381
+ rigoToken: string,
382
+ inputs: TReduceReadmeInputs,
383
+ purpose: string
384
+ ) {
385
+ try {
386
+ const response = await axios.post(
387
+ `${RIGOBOT_HOST}/v1/prompting/completion/588/`,
388
+ { inputs, include_purpose_objective: false, execute_async: false },
389
+ {
390
+ headers: {
391
+ "Content-Type": "application/json",
392
+ Authorization: "Token " + rigoToken,
393
+ },
394
+ }
395
+ )
396
+
397
+ return response.data
398
+ } catch (error) {
399
+ Console.debug(error)
400
+ return null
401
+ }
402
+ }
403
+
404
+ export const isValidRigoToken = async (rigobotToken: string) => {
405
+ const rigoUrl = `${RIGOBOT_HOST}/v1/auth/token/${rigobotToken}`
406
+ const rigoResp = await fetch(rigoUrl)
407
+ if (!rigoResp.ok) {
408
+ Console.debug("Invalid Rigobot token", rigoResp.status)
409
+ Console.debug(rigoResp.statusText)
410
+ return false
411
+ }
412
+
413
+ return true
414
+ }
415
+
416
+ type TGenerateCourseShortNameInputs = {
417
+ learnJSON: string
418
+ }
419
+
420
+ export const generateCourseShortName = async (
421
+ token: string,
422
+ inputs: TGenerateCourseShortNameInputs
423
+ ) => {
424
+ const response = await axios.post(
425
+ `${RIGOBOT_HOST}/v1/prompting/completion/852/`,
426
+ { inputs, include_purpose_objective: false, execute_async: false },
427
+ {
428
+ headers: {
429
+ "Content-Type": "application/json",
430
+ Authorization: "Token " + token,
431
+ },
432
+ }
433
+ )
434
+
435
+ return response.data
436
+ }
437
+
438
+ type TFillSidebarJSONInputs = {
439
+ needed_translations: string
440
+ sidebar_json: string
441
+ }
442
+
443
+ export const fillSidebarJSON = async (
444
+ token: string,
445
+ inputs: TFillSidebarJSONInputs
446
+ ) => {
447
+ const response = await axios.post(
448
+ `${RIGOBOT_HOST}/v1/prompting/completion/951/`,
449
+ { inputs, include_purpose_objective: false, execute_async: false },
450
+ {
451
+ headers: {
452
+ "Content-Type": "application/json",
453
+ Authorization: "Token " + token,
454
+ },
455
+ }
456
+ )
457
+
458
+ return response.data
459
+ }
460
+
461
+ export const isPackageAuthor = async (
462
+ token: string,
463
+ packageSlug: string
464
+ ): Promise<{ isAuthor: boolean; status: number }> => {
465
+ const url = `${RIGOBOT_HOST}/v1/learnpack/package/${packageSlug}/`
466
+
467
+ const headers = {
468
+ Authorization: `Token ${token}`,
469
+ }
470
+
471
+ try {
472
+ const response = await axios.get(url, { headers })
473
+ return { isAuthor: response.status === 200, status: response.status }
474
+ } catch (error: any) {
475
+ const status = error?.response?.status || 500
476
+ console.error("Error fetching package:", error)
477
+ return { isAuthor: false, status }
478
+ }
479
+ }
480
+
481
+ type TGetLanguageCodesInputs = {
482
+ raw_languages: string
483
+ }
484
+ export const getLanguageCodes = async (
485
+ token: string,
486
+ inputs: TGetLanguageCodesInputs
487
+ ) => {
488
+ const response = await axios.post(
489
+ `${RIGOBOT_HOST}/v1/prompting/completion/get-language-codes/`,
490
+ { inputs, include_purpose_objective: false, execute_async: false },
491
+ {
492
+ headers: {
493
+ "Content-Type": "application/json",
494
+ Authorization: "Token " + token,
495
+ },
496
+ }
497
+ )
498
+
499
+ return response.data
500
+ }