@learnpack/learnpack 5.0.178 → 5.0.180

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 (32) hide show
  1. package/README.md +13 -13
  2. package/lib/commands/serve.js +32 -18
  3. package/lib/creatorDist/assets/{index-CrWESWmj.css → index-Bnq3eZ3T.css} +13 -3
  4. package/lib/creatorDist/assets/index-hhajeHFt.js +35366 -0
  5. package/lib/creatorDist/index.html +2 -2
  6. package/lib/utils/creatorSocket.d.ts +1 -0
  7. package/lib/utils/creatorSocket.js +24 -0
  8. package/oclif.manifest.json +1 -1
  9. package/package.json +1 -1
  10. package/src/commands/serve.ts +48 -26
  11. package/src/creator/package-lock.json +137 -0
  12. package/src/creator/package.json +1 -0
  13. package/src/creator/src/App.tsx +77 -50
  14. package/src/creator/src/components/ConsumablesManager.tsx +1 -3
  15. package/src/creator/src/components/FileUploader.tsx +136 -44
  16. package/src/creator/src/components/PurposeSelector.tsx +70 -0
  17. package/src/creator/src/components/SelectableCard.tsx +5 -3
  18. package/src/creator/src/components/Uploader.tsx +12 -1
  19. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +6 -12
  20. package/src/creator/src/utils/constants.ts +10 -4
  21. package/src/creator/src/utils/lib.ts +0 -2
  22. package/src/creator/src/utils/rigo.ts +9 -5
  23. package/src/creator/src/utils/socket.ts +61 -0
  24. package/src/creator/src/utils/store.ts +7 -1
  25. package/src/creatorDist/assets/{index-CrWESWmj.css → index-Bnq3eZ3T.css} +13 -3
  26. package/src/creatorDist/assets/index-hhajeHFt.js +35366 -0
  27. package/src/creatorDist/index.html +2 -2
  28. package/src/ui/_app/app.js +19 -8
  29. package/src/ui/app.tar.gz +0 -0
  30. package/src/utils/creatorSocket.ts +30 -0
  31. package/lib/creatorDist/assets/index-BvrB0WCf.js +0 -32991
  32. package/src/creatorDist/assets/index-BvrB0WCf.js +0 -32991
@@ -12,10 +12,11 @@ import { checkParams, loginWithToken, parseLesson } from "./utils/lib"
12
12
  import { Uploader } from "./components/Uploader"
13
13
  import toast from "react-hot-toast"
14
14
  import { ParamsChecker } from "./components/ParamsChecker"
15
- import { RIGO_FLOAT_GIT } from "./utils/constants"
15
+ import { RIGO_FLOAT_GIF } from "./utils/constants"
16
16
  import TurnstileChallenge from "./components/TurnstileChallenge"
17
17
  // import TurnstileChallenge from "./components/TurnstileChallenge"
18
18
  import ResumeCourseModal from "./components/ResumeCourseModal"
19
+ import { possiblePurposes, PurposeSelector } from "./components/PurposeSelector"
19
20
 
20
21
  function App() {
21
22
  const navigate = useNavigate()
@@ -72,10 +73,11 @@ function App() {
72
73
  }
73
74
 
74
75
  const checkDescription = () => {
75
- const { description, duration, plan } = checkParams([
76
+ const { description, duration, plan, purpose } = checkParams([
76
77
  "description",
77
78
  "duration",
78
79
  "plan",
80
+ "purpose",
79
81
  ])
80
82
  if (description) {
81
83
  console.log("description", description)
@@ -102,6 +104,13 @@ function App() {
102
104
  } else {
103
105
  console.debug("No plan received in params")
104
106
  }
107
+
108
+ if (purpose && purpose.length > 0 && possiblePurposes.includes(purpose)) {
109
+ setFormState({
110
+ purpose: purpose,
111
+ currentStep: "hasContentIndex",
112
+ })
113
+ }
105
114
  }
106
115
 
107
116
  const handleCreateTutorial = async () => {
@@ -110,22 +119,17 @@ function App() {
110
119
 
111
120
  const res = await publicInteractiveCreation(
112
121
  {
113
- courseInfo: `${JSON.stringify(formState)}
114
- ${
115
- uploadedFiles.length > 0
116
- ? `These files where uploaded by the user: \n\n${JSON.stringify(
117
- uploadedFiles
118
- )}`
119
- : ""
120
- }`,
122
+ courseInfo: `${JSON.stringify(formState)} `,
121
123
  prevInteractions: "",
122
124
  },
123
- auth.publicToken
125
+ auth.publicToken,
126
+ formState.purpose
124
127
  )
125
128
  const lessons = res.parsed.listOfSteps.map((lesson: any) => {
126
129
  return parseLesson(lesson, [])
127
130
  })
128
131
 
132
+ console.log("RES FROM RIGO", res)
129
133
  push({
130
134
  lessons,
131
135
  courseInfo: {
@@ -133,7 +137,13 @@ ${
133
137
  title: res.parsed.title,
134
138
  description: res.parsed.description,
135
139
  },
136
- sources: uploadedFiles,
140
+ messages: [
141
+ {
142
+ type: "assistant",
143
+ content: res.parsed.aiMessage,
144
+ },
145
+ ],
146
+ // sources: uploadedFiles,
137
147
  })
138
148
  navigate("/creator/syllabus")
139
149
  setFormState({
@@ -185,7 +195,7 @@ ${
185
195
  onClick={() => {
186
196
  setFormState({
187
197
  duration: 30,
188
- currentStep: "hasContentIndex",
198
+ currentStep: "purpose",
189
199
  })
190
200
  }}
191
201
  selected={formState.duration === 30}
@@ -196,7 +206,7 @@ ${
196
206
  onClick={() => {
197
207
  setFormState({
198
208
  duration: 60,
199
- currentStep: "hasContentIndex",
209
+ currentStep: "purpose",
200
210
  })
201
211
  }}
202
212
  selected={formState.duration === 60}
@@ -207,7 +217,7 @@ ${
207
217
  onClick={() => {
208
218
  setFormState({
209
219
  duration: 120,
210
- currentStep: "hasContentIndex",
220
+ currentStep: "purpose",
211
221
  })
212
222
  }}
213
223
  selected={formState.duration === 120}
@@ -215,6 +225,53 @@ ${
215
225
  </div>
216
226
  ),
217
227
  },
228
+ {
229
+ title: "How would you like to use learnpack?",
230
+ slug: "purpose",
231
+ isCompleted: formState?.purpose?.length > 0,
232
+ required: true,
233
+ content: (
234
+ <PurposeSelector
235
+ onFinish={(purpose) => {
236
+ setFormState({
237
+ purpose: purpose,
238
+ currentStep: "verifyHuman",
239
+ })
240
+ }}
241
+ />
242
+ ),
243
+ },
244
+ {
245
+ title: "Please verify you are a human",
246
+ slug: "verifyHuman",
247
+ isCompleted: false,
248
+ content: (
249
+ <TurnstileChallenge
250
+ // siteKey={"0x4AAAAAABeKMBYYinMU4Ib0"}
251
+ siteKey={"0x4AAAAAABeZ9tjEevGBsJFU"} // This is the learnpack one
252
+ onSuccess={async (token) => {
253
+ const { human, message, token: jwtToken } = await isHuman(token)
254
+ if (human) {
255
+ toast.success("You are a human! 👌🏻")
256
+
257
+ console.log("JWT TOKEN received", jwtToken)
258
+ setAuth({
259
+ ...auth,
260
+ publicToken: jwtToken,
261
+ })
262
+ setFormState({
263
+ currentStep: "hasContentIndex",
264
+ })
265
+ } else {
266
+ toast.error(message)
267
+ setFormState({
268
+ currentStep: "purpose",
269
+ })
270
+ }
271
+ }}
272
+ />
273
+ ),
274
+ },
218
275
  {
219
276
  title: "Any materials to get this course started?",
220
277
  slug: "hasContentIndex",
@@ -227,16 +284,15 @@ ${
227
284
  onClick={() => {
228
285
  setFormState({
229
286
  hasContentIndex: false,
230
- currentStep: "verifyHuman",
231
287
  variables: [
232
288
  ...formState.variables.filter(
233
289
  (v) => v !== "contentIndex"
234
290
  ),
235
291
  ],
236
- // isCompleted: true,
292
+ isCompleted: true,
237
293
  })
238
294
  }}
239
- selected={false}
295
+ selected={formState.hasContentIndex === false}
240
296
  />
241
297
  <SelectableCard
242
298
  title="✅ Yes"
@@ -247,7 +303,7 @@ ${
247
303
  variables: [...formState.variables, "contentIndex"],
248
304
  })
249
305
  }}
250
- selected={false}
306
+ selected={formState.hasContentIndex === true}
251
307
  />
252
308
  </div>
253
309
  </>
@@ -266,41 +322,12 @@ ${
266
322
  onFinish={(text) => {
267
323
  setFormState({
268
324
  contentIndex: text,
269
- currentStep: "verifyHuman",
270
- // isCompleted: true,
325
+ isCompleted: true,
271
326
  })
272
327
  }}
273
328
  />
274
329
  ),
275
330
  },
276
- {
277
- title: "Please verify you are a human",
278
- slug: "verifyHuman",
279
- isCompleted: false,
280
- content: (
281
- <TurnstileChallenge
282
- // siteKey={"0x4AAAAAABeKMBYYinMU4Ib0"}
283
- siteKey={"0x4AAAAAABeZ9tjEevGBsJFU"}
284
- onSuccess={async (token) => {
285
- const { human, message, token: jwtToken } = await isHuman(token)
286
- if (human) {
287
- toast.success("You are a human! 👌🏻")
288
-
289
- setAuth({
290
- ...auth,
291
- publicToken: jwtToken,
292
- })
293
- setFormState({ isCompleted: true })
294
- } else {
295
- toast.error(message)
296
- setFormState({
297
- currentStep: "hasContentIndex",
298
- })
299
- }
300
- }}
301
- />
302
- ),
303
- },
304
331
  ]
305
332
 
306
333
  return steps.filter(
@@ -316,7 +343,7 @@ ${
316
343
  {formState.isCompleted && history.length === 0 ? (
317
344
  <Loader
318
345
  text="Learnpack is setting up your tutorial. It may take a moment..."
319
- icon={<img src={RIGO_FLOAT_GIT} alt="rigo" className="w-20 h-20" />}
346
+ icon={<img src={RIGO_FLOAT_GIF} alt="rigo" className="w-20 h-20" />}
320
347
  />
321
348
  ) : (
322
349
  <>
@@ -20,11 +20,9 @@ export const ConsumablesManager = () => {
20
20
  setConsumables(parseConsumables(consumables.voids))
21
21
  } catch (error) {
22
22
  setAuth({
23
+ ...auth,
23
24
  bcToken: "",
24
25
  rigoToken: "",
25
- userId: "",
26
- user: null,
27
- publicToken: "",
28
26
  })
29
27
  }
30
28
  }
@@ -1,8 +1,11 @@
1
- import React, { useRef, useState } from "react"
1
+ import React, { useEffect, useRef, useState } from "react"
2
2
  import { SVGS } from "../assets/svgs"
3
3
  import { ContentCard } from "./ContentCard"
4
4
  import useStore from "../utils/store"
5
5
  import toast from "react-hot-toast"
6
+ import CreatorSocket from "../utils/socket"
7
+
8
+ const socketClient = new CreatorSocket("")
6
9
 
7
10
  const allowedTypes = [
8
11
  "application/pdf",
@@ -14,14 +17,100 @@ const allowedTypes = [
14
17
  export interface ParsedFile {
15
18
  name: string
16
19
  text: string
20
+ status: "PROCESSING" | "SUCCESS" | "ERROR"
21
+ notificationId: string
17
22
  }
18
23
 
19
24
  interface FileUploaderProps {
20
25
  styledAs?: "button" | "card"
26
+ onFinish?: (files: ParsedFile[]) => void
27
+ }
28
+
29
+ const UploadedFileCard = ({ idx, file }: { idx: number; file: ParsedFile }) => {
30
+ const setUploadedFiles = useStore((state) => state.setUploadedFiles)
31
+ const uploadedFiles = useStore((state) => state.uploadedFiles)
32
+
33
+ const handleUpdate = (data: any) => {
34
+ if (data.text) {
35
+ setUploadedFiles(
36
+ uploadedFiles.map((f, i) =>
37
+ i === idx ? { ...f, status: "SUCCESS", text: data.text } : f
38
+ )
39
+ )
40
+ } else {
41
+ setUploadedFiles(
42
+ uploadedFiles.map((f, i) => (i === idx ? { ...f, status: "ERROR" } : f))
43
+ )
44
+ }
45
+ }
46
+
47
+ useEffect(() => {
48
+ if (file.status === "SUCCESS") return
49
+
50
+ console.log("CONNECTING TO SOCKET", file.notificationId)
51
+ socketClient.connect()
52
+ socketClient.on(file.notificationId, handleUpdate)
53
+
54
+ socketClient.emit("registerNotification", {
55
+ notificationId: file.notificationId,
56
+ })
57
+
58
+ return () => {
59
+ socketClient.off(file.notificationId, handleUpdate)
60
+ socketClient.disconnect()
61
+ }
62
+ }, [])
63
+
64
+ return (
65
+ <div
66
+ className={
67
+ "p-3 rounded-md shadow-sm text-sm text-gray-800 text-left flex items-center gap-2" +
68
+ (file.status === "PROCESSING"
69
+ ? " bg-gray-100"
70
+ : file.status === "ERROR"
71
+ ? " bg-red-100"
72
+ : " bg-white")
73
+ }
74
+ title={file.name}
75
+ >
76
+ {file.status === "PROCESSING" && (
77
+ <div className="w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
78
+ )}
79
+ {file.status === "ERROR" && (
80
+ <span className="text-red-500 font-bold">Error!</span>
81
+ )}
82
+
83
+ <strong className="truncate">{file.name.slice(0, 20)}...</strong>
84
+
85
+ <button
86
+ className={
87
+ "ml-auto cursor-pointer transition-colors " +
88
+ (file.status === "PROCESSING"
89
+ ? "text-gray-400 cursor-not-allowed"
90
+ : "text-gray-600 hover:text-red-500")
91
+ }
92
+ onClick={
93
+ () => setUploadedFiles(uploadedFiles.filter((_, i) => i !== idx))
94
+ // Set the file as error
95
+ // setUploadedFiles(
96
+ // uploadedFiles.map((f, i) =>
97
+ // i === idx ? { ...f, status: "ERROR" } : f
98
+ // )
99
+ // )
100
+ }
101
+ >
102
+ {SVGS.trash}
103
+ </button>
104
+ </div>
105
+ )
21
106
  }
22
107
 
23
- const FileUploader: React.FC<FileUploaderProps> = ({ styledAs = "button" }) => {
24
- const rigoToken = useStore((state) => state.auth.rigoToken)
108
+ const FileUploader: React.FC<FileUploaderProps> = ({
109
+ styledAs = "button",
110
+ onFinish,
111
+ }) => {
112
+ // const rigoToken = useStore((state) => state.auth.rigoToken)
113
+ const publicToken = useStore((state) => state.auth.publicToken)
25
114
  const inputRef = useRef<HTMLInputElement>(null)
26
115
  const uploadedFiles = useStore((state) => state.uploadedFiles)
27
116
  const setUploadedFiles = useStore((state) => state.setUploadedFiles)
@@ -33,7 +122,7 @@ const FileUploader: React.FC<FileUploaderProps> = ({ styledAs = "button" }) => {
33
122
 
34
123
  if (type === "text/plain" || type === "text/markdown") {
35
124
  const text = await file.text()
36
- return { name, text }
125
+ return { name, text, status: "SUCCESS", notificationId: "" }
37
126
  }
38
127
 
39
128
  const formData = new FormData()
@@ -41,24 +130,28 @@ const FileUploader: React.FC<FileUploaderProps> = ({ styledAs = "button" }) => {
41
130
 
42
131
  const loadingToast = toast.loading(`Processing ${file.name}...`)
43
132
  try {
44
- const res = await fetch("http://localhost:3000/read-document", {
133
+ const res = await fetch("/read-document", {
45
134
  method: "POST",
46
135
  headers: {
47
- "x-rigo-token": rigoToken,
136
+ "x-public-token": publicToken,
48
137
  },
49
138
  body: formData,
50
139
  })
51
140
 
52
141
  if (!res.ok) throw new Error(`Failed to read ${file.name}`)
53
142
  const data = await res.json()
54
- console.log("DATA FROM BACKEND", data)
55
- toast.success(`✅ ${file.name} processed`, { id: loadingToast })
56
- return { name, text: data.content }
143
+ toast.success(`Processing ${file.name}`, { id: loadingToast })
144
+ return {
145
+ name,
146
+ text: "",
147
+ status: data.status,
148
+ notificationId: data.notificationId,
149
+ }
57
150
  } catch (err: any) {
58
151
  toast.error(`❌ ${file.name} failed: ${err.message}`, {
59
152
  id: loadingToast,
60
153
  })
61
- return { name, text: "" }
154
+ return { name, text: "", status: "ERROR", notificationId: "" }
62
155
  }
63
156
  }
64
157
 
@@ -73,7 +166,9 @@ const FileUploader: React.FC<FileUploaderProps> = ({ styledAs = "button" }) => {
73
166
 
74
167
  setIsLoading(true)
75
168
  const parsed = await Promise.all(validFiles.map(extractTextFromFile))
76
- setUploadedFiles([...uploadedFiles, ...parsed])
169
+ const newFiles = [...uploadedFiles, ...parsed]
170
+
171
+ setUploadedFiles(newFiles.filter((file) => file.status !== "ERROR"))
77
172
  setIsLoading(false)
78
173
  }
79
174
 
@@ -95,21 +190,7 @@ const FileUploader: React.FC<FileUploaderProps> = ({ styledAs = "button" }) => {
95
190
  {uploadedFiles.length > 0 && styledAs === "card" && (
96
191
  <div className="w-full flex flex-row gap-2 flex-wrap justify-center items-center">
97
192
  {uploadedFiles.map((file, idx) => (
98
- <div
99
- key={idx}
100
- className="p-3 rounded-md bg-white shadow-sm text-sm text-gray-800 text-left"
101
- title={file.name}
102
- >
103
- <strong>{file.name.slice(0, 20)}...</strong>
104
- <button
105
- className="text-gray-600 mt-1 float-right cursor-pointer"
106
- onClick={() =>
107
- setUploadedFiles(uploadedFiles.filter((_, i) => i !== idx))
108
- }
109
- >
110
- {SVGS.trash}
111
- </button>
112
- </div>
193
+ <UploadedFileCard key={idx} idx={idx} file={file} />
113
194
  ))}
114
195
  </div>
115
196
  )}
@@ -131,24 +212,35 @@ const FileUploader: React.FC<FileUploaderProps> = ({ styledAs = "button" }) => {
131
212
  )}
132
213
 
133
214
  {styledAs === "card" && (
134
- <ContentCard
135
- description={
136
- isDragging
137
- ? "Drop it here"
138
- : isLoading
139
- ? "Processing..."
140
- : "Upload a PDF or DOCX file or drag it here"
141
- }
142
- icon={isDragging ? SVGS.clip : SVGS.pdf}
143
- onClick={() => inputRef.current?.click()}
144
- onDragOver={(e) => {
145
- e.preventDefault()
146
- setIsDragging(true)
147
- }}
148
- onDragLeave={() => setIsDragging(false)}
149
- onDrop={handleDrop}
150
- className={isDragging ? "border-blue-600 bg-blue-50" : ""}
151
- />
215
+ <>
216
+ <ContentCard
217
+ description={
218
+ isDragging
219
+ ? "Drop it here"
220
+ : isLoading
221
+ ? "Processing..."
222
+ : "Upload a PDF or DOCX file or drag it here"
223
+ }
224
+ icon={isDragging ? SVGS.clip : SVGS.pdf}
225
+ onClick={() => inputRef.current?.click()}
226
+ onDragOver={(e) => {
227
+ e.preventDefault()
228
+ setIsDragging(true)
229
+ }}
230
+ onDragLeave={() => setIsDragging(false)}
231
+ onDrop={handleDrop}
232
+ className={isDragging ? "border-blue-600 bg-blue-50" : ""}
233
+ />
234
+ <button
235
+ disabled={uploadedFiles.some((file) => file.status !== "SUCCESS")}
236
+ className="bg-blue-500 text-white px-4 py-2 rounded-md cursor-pointer disabled:opacity-50"
237
+ onClick={() => {
238
+ onFinish?.(uploadedFiles)
239
+ }}
240
+ >
241
+ 🚀 Finish
242
+ </button>
243
+ </>
152
244
  )}
153
245
 
154
246
  <input
@@ -0,0 +1,70 @@
1
+ import React from "react"
2
+ import SelectableCard from "./SelectableCard"
3
+ import useStore from "../utils/store"
4
+
5
+ export const possiblePurposes = [
6
+ "learnpack-lesson-writer",
7
+ "homework-and-exam-preparation-aid",
8
+ "skill-building-facilitator",
9
+ "certification-preparation-specialist",
10
+ ]
11
+
12
+ type PurposeSlug =
13
+ | "learnpack-lesson-writer"
14
+ | "homework-and-exam-preparation-aid"
15
+ | "skill-building-facilitator"
16
+ | "certification-preparation-specialist"
17
+
18
+ const PURPOSES: { slug: PurposeSlug; label: string; description: string }[] = [
19
+ {
20
+ slug: "learnpack-lesson-writer",
21
+ label: "Understand a new topic",
22
+ description:
23
+ "Learn about a new concept (e.g., ISO 27001 or exponential decay).",
24
+ },
25
+ {
26
+ slug: "homework-and-exam-preparation-aid",
27
+ label: "Practice for an exam or homework",
28
+ description: "Solve math problems or certification questions.",
29
+ },
30
+ {
31
+ slug: "skill-building-facilitator",
32
+ label: "Build real-world skills",
33
+ description:
34
+ "Apply concepts to projects, data science, or security audits.",
35
+ },
36
+ {
37
+ slug: "certification-preparation-specialist",
38
+ label: "Prepare for a certification",
39
+ description: "Get ready for exams like ISO 27001 Lead Auditor.",
40
+ },
41
+ ]
42
+
43
+ interface PurposeSelectorProps {
44
+ onFinish: (purpose: PurposeSlug) => void
45
+ // Optionally allow passing an initial purpose, for testability or server-side rendering
46
+ initialPurpose?: PurposeSlug
47
+ }
48
+
49
+ export const PurposeSelector: React.FC<PurposeSelectorProps> = ({
50
+ onFinish,
51
+ }) => {
52
+ const formState = useStore((state) => state.formState)
53
+
54
+ return (
55
+ <div className="w-full">
56
+ <ul className="flex flex-row gap-4 flex-wrap">
57
+ {PURPOSES.map((p) => (
58
+ <SelectableCard
59
+ key={p.slug}
60
+ title={p.label}
61
+ selected={formState.purpose === p.slug}
62
+ subtitle={p.description}
63
+ onClick={() => onFinish(p.slug)}
64
+ className="w-full"
65
+ />
66
+ ))}
67
+ </ul>
68
+ </div>
69
+ )
70
+ }
@@ -5,6 +5,7 @@ interface SelectableCardProps {
5
5
  subtitle?: string
6
6
  selected?: boolean
7
7
  onClick: () => void
8
+ className?: string
8
9
  }
9
10
 
10
11
  const SelectableCard: React.FC<SelectableCardProps> = ({
@@ -12,13 +13,14 @@ const SelectableCard: React.FC<SelectableCardProps> = ({
12
13
  selected = false,
13
14
  subtitle = "",
14
15
  onClick,
16
+ className = "",
15
17
  }) => {
16
18
  return (
17
19
  <div
18
20
  className={`cursor-pointer bg-white rounded-lg shadow-md p-6 text-center transition-all
19
- hover:shadow-lg border-2 ${
20
- selected ? "border-blue-500" : "border-transparent"
21
- }`}
21
+ hover:shadow-lg border-2 ${className} ${
22
+ selected ? "border-blue-500" : "border-transparent"
23
+ }`}
22
24
  onClick={onClick}
23
25
  >
24
26
  <p className="text-md font-medium">{title}</p>
@@ -61,7 +61,18 @@ export const Uploader = ({
61
61
 
62
62
  {selectedOption === "text" && <TextUploader onFinish={onFinish} />}
63
63
 
64
- {selectedOption === "files" && <FileUploader styledAs="card" />}
64
+ {selectedOption === "files" && (
65
+ <FileUploader
66
+ styledAs="card"
67
+ onFinish={(files) => {
68
+ const allFilesText = files
69
+ .filter((f) => f.status === "SUCCESS")
70
+ .map((f) => `<FILE name="${f.name}">${f.text}</FILE>`)
71
+ .join("\n")
72
+ onFinish(allFilesText)
73
+ }}
74
+ />
75
+ )}
65
76
 
66
77
  {selectedOption === "youtube" && (
67
78
  <LinkUploader
@@ -24,7 +24,7 @@ import Login from "../Login"
24
24
  import { useNavigate } from "react-router"
25
25
  import { ParamsChecker } from "../ParamsChecker"
26
26
  import { slugify } from "../../utils/creatorUtils"
27
- import { RIGO_FLOAT_GIT } from "../../utils/constants"
27
+ import { RIGO_FLOAT_GIF } from "../../utils/constants"
28
28
 
29
29
  const SyllabusEditor: React.FC = () => {
30
30
  const navigate = useNavigate()
@@ -69,7 +69,6 @@ const SyllabusEditor: React.FC = () => {
69
69
  useEffect(() => {
70
70
  if (!syllabus) {
71
71
  navigate("/creator", { replace: true })
72
- } else {
73
72
  }
74
73
  }, [syllabus, navigate])
75
74
 
@@ -141,19 +140,14 @@ const SyllabusEditor: React.FC = () => {
141
140
 
142
141
  const res = await publicInteractiveCreation(
143
142
  {
144
- courseInfo: `${JSON.stringify(syllabus.courseInfo)}
145
- ${
146
- uploadedFiles.length > 0 &&
147
- "The user has uploaded files, take them in consideration while generating the course structure." +
148
- JSON.stringify(uploadedFiles)
149
- }
150
- `,
143
+ courseInfo: JSON.stringify(syllabus.courseInfo),
151
144
  prevInteractions:
152
145
  messages
153
146
  .map((message) => `${message.type}: ${message.content}`)
154
147
  .join("\n") + `\nUSER: ${prompt}`,
155
148
  },
156
- auth.publicToken
149
+ auth.publicToken,
150
+ syllabus.courseInfo.purpose
157
151
  )
158
152
 
159
153
  const lessons: Lesson[] = res.parsed.listOfSteps.map((step: any) =>
@@ -208,7 +202,7 @@ const SyllabusEditor: React.FC = () => {
208
202
  // toast.error("You don't have enough credits to generate a course!")
209
203
  // return
210
204
  // }
211
- syllabus.sources = uploadedFiles
205
+ // syllabus.sources = uploadedFiles
212
206
  console.log(syllabus)
213
207
 
214
208
  setIsGenerating(true)
@@ -229,7 +223,7 @@ const SyllabusEditor: React.FC = () => {
229
223
  <>
230
224
  <Loader
231
225
  listeningTo="course-generation"
232
- icon={<img src={RIGO_FLOAT_GIT} alt="rigo" className="w-20 h-20" />}
226
+ icon={<img src={RIGO_FLOAT_GIF} alt="rigo" className="w-20 h-20" />}
233
227
  initialBuffer="🚀 Starting course generation..."
234
228
  text="Learnpack is setting up your tutorial.
235
229
  It may take a moment..."
@@ -1,6 +1,12 @@
1
- export const RIGOBOT_HOST = "https://rigobot.herokuapp.com"
2
- // export const RIGOBOT_HOST = "https://rigobot-test-cca7d841c9d8.herokuapp.com"
3
- export const BREATHECODE_HOST = "https://breathecode.herokuapp.com"
1
+ export const DEV_MODE = false
4
2
 
5
- export const RIGO_FLOAT_GIT =
3
+ export const RIGOBOT_HOST = DEV_MODE
4
+ ? "https://rigobot-test-cca7d841c9d8.herokuapp.com"
5
+ : "https://rigobot.herokuapp.com"
6
+
7
+ export const BREATHECODE_HOST = DEV_MODE
8
+ ? "https://breathecode-test.herokuapp.com"
9
+ : "https://breathecode.herokuapp.com"
10
+
11
+ export const RIGO_FLOAT_GIF =
6
12
  "https://raw.githubusercontent.com/learnpack/ide/20ed3f4c3ead9b33d5d6acb20154dcd93a0ec4af/public/rigo-float.gif"