@thanh01.pmt/interactive-quiz-kit 1.0.24 → 1.0.27

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.
@@ -3,37 +3,7 @@ import { z } from 'zod';
3
3
  import { genkit } from 'genkit';
4
4
  import { gemini20Flash, googleAI } from '@genkit-ai/googleai';
5
5
 
6
- var __defProp = Object.defineProperty;
7
- var __defProps = Object.defineProperties;
8
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
9
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
10
- var __hasOwnProp = Object.prototype.hasOwnProperty;
11
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
- var __spreadValues = (a, b) => {
14
- for (var prop in b || (b = {}))
15
- if (__hasOwnProp.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- if (__getOwnPropSymbols)
18
- for (var prop of __getOwnPropSymbols(b)) {
19
- if (__propIsEnum.call(b, prop))
20
- __defNormalProp(a, prop, b[prop]);
21
- }
22
- return a;
23
- };
24
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
- var __objRest = (source, exclude) => {
26
- var target = {};
27
- for (var prop in source)
28
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
29
- target[prop] = source[prop];
30
- if (source != null && __getOwnPropSymbols)
31
- for (var prop of __getOwnPropSymbols(source)) {
32
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
33
- target[prop] = source[prop];
34
- }
35
- return target;
36
- };
6
+ // src/ai/flows/question-gen/generate-fitb-question.ts
37
7
 
38
8
  // src/utils/idGenerators.ts
39
9
  function generateUniqueId(prefix = "id_") {
@@ -252,7 +222,7 @@ var MAX_RETRY_ATTEMPTS = 3;
252
222
  var RETRY_DELAY_MS = 3e3;
253
223
  function buildEnhancedPrompt(clientInput, attemptNumber) {
254
224
  const { quizContext, language, difficulty, numberOfBlanks, imageUrl } = clientInput;
255
- const category = (quizContext == null ? void 0 : quizContext.originalCategory) || "the specified technical category";
225
+ const category = quizContext?.originalCategory || "the specified technical category";
256
226
  const attemptInfo = attemptNumber > 1 ? `
257
227
  ## DEBUG INFO - This is attempt #${attemptNumber}
258
228
  Previous attempts failed. Pay strict attention to the JSON schema, especially the 'segments' array structure. Ensure 'blank' segments have 'acceptedAnswers' and 'text' segments have 'content'.
@@ -261,10 +231,10 @@ Previous attempts failed. Pay strict attention to the JSON schema, especially th
261
231
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The question and blanks must be directly related to the content of this image.` : "";
262
232
  const contextStrings = [
263
233
  `**Required Category:** ${category}`,
264
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
234
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
265
235
  imageContextInstruction,
266
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
267
- (quizContext == null ? void 0 : quizContext.targetMisconception) && `**Target Misconception:** Design the blank to test this specific point: "${quizContext.targetMisconception}"`
236
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
237
+ quizContext?.targetMisconception && `**Target Misconception:** Design the blank to test this specific point: "${quizContext.targetMisconception}"`
268
238
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
269
239
  const exampleJson = JSON.stringify({
270
240
  prompt: "Complete the following Swift code snippet.",
@@ -294,7 +264,7 @@ ${contextStrings}
294
264
  Based on all the rules and context above, generate a single Fill-in-the-Blanks Question.
295
265
 
296
266
  ### Input Parameters
297
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
267
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
298
268
  - **Language for Text:** ${language}
299
269
  - **Difficulty Level:** ${difficulty}
300
270
  - **Number of Blanks:** Generate exactly ${numberOfBlanks} segment(s) with type 'blank'.
@@ -307,7 +277,6 @@ ${exampleJson}
307
277
  Now, generate the JSON for the requested question.`;
308
278
  }
309
279
  async function generateFillInTheBlanksQuestion(clientInput, apiKey) {
310
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
311
280
  const ai = new GoogleGenAI({ apiKey });
312
281
  const model = "gemini-2.5-flash";
313
282
  const config = {
@@ -324,7 +293,7 @@ async function generateFillInTheBlanksQuestion(clientInput, apiKey) {
324
293
  const promptText = buildEnhancedPrompt(clientInput, attempt);
325
294
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
326
295
  try {
327
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
296
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
328
297
  const parts = [{ text: promptText }];
329
298
  if (clientInput.imageUrl) {
330
299
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -334,7 +303,7 @@ async function generateFillInTheBlanksQuestion(clientInput, apiKey) {
334
303
  const contents = [{ role: "user", parts }];
335
304
  const aiResult = await ai.models.generateContent({ model, config, contents });
336
305
  const response = aiResult;
337
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
306
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
338
307
  const duration = Date.now() - startTime;
339
308
  DebugLogger.logResponse(attempt, rawText);
340
309
  if (!rawText) throw new Error("AI returned an empty response.");
@@ -354,8 +323,8 @@ async function generateFillInTheBlanksQuestion(clientInput, apiKey) {
354
323
  throw new Error(`Segment ${index} is 'text' but is missing 'content'.`);
355
324
  }
356
325
  });
357
- if ((_f = clientInput.quizContext) == null ? void 0 : _f.originalCategory) {
358
- const verifiedCategory = (_g = aiGeneratedContent.verifiedCategory) == null ? void 0 : _g.toLowerCase();
326
+ if (clientInput.quizContext?.originalCategory) {
327
+ const verifiedCategory = aiGeneratedContent.verifiedCategory?.toLowerCase();
359
328
  const requiredCategory = clientInput.quizContext.originalCategory.toLowerCase();
360
329
  if (verifiedCategory && verifiedCategory !== requiredCategory) {
361
330
  throw new Error(`Category mismatch: Required ${requiredCategory}, got ${verifiedCategory}`);
@@ -381,13 +350,13 @@ async function generateFillInTheBlanksQuestion(clientInput, apiKey) {
381
350
  isCaseSensitive: clientInput.isCaseSensitive,
382
351
  explanation: aiGeneratedContent.explanation,
383
352
  points: aiGeneratedContent.points,
384
- topic: aiGeneratedContent.topic || ((_h = clientInput.quizContext) == null ? void 0 : _h.originalTopic),
353
+ topic: aiGeneratedContent.topic || clientInput.quizContext?.originalTopic,
385
354
  difficulty: clientInput.difficulty,
386
- contextCode: (_i = clientInput.quizContext) == null ? void 0 : _i.plannedContextId,
387
- bloomLevel: (_j = clientInput.quizContext) == null ? void 0 : _j.plannedBloomLevel,
388
- learningObjective: (_k = clientInput.quizContext) == null ? void 0 : _k.originalLoId,
389
- subject: (_l = clientInput.quizContext) == null ? void 0 : _l.originalSubject,
390
- category: (_m = clientInput.quizContext) == null ? void 0 : _m.originalCategory,
355
+ contextCode: clientInput.quizContext?.plannedContextId,
356
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
357
+ learningObjective: clientInput.quizContext?.originalLoId,
358
+ subject: clientInput.quizContext?.originalSubject,
359
+ category: clientInput.quizContext?.originalCategory,
391
360
  imageUrl: clientInput.imageUrl
392
361
  };
393
362
  const validatedQuestion = FillInTheBlanksQuestionZodSchema.parse(completeQuestion);
@@ -409,7 +378,7 @@ async function generateFillInTheBlanksQuestion(clientInput, apiKey) {
409
378
  }
410
379
  }
411
380
  DebugLogger.logAttemptSummary(attemptResults);
412
- const errorMessage = `Failed to generate FITB question after ${MAX_RETRY_ATTEMPTS} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
381
+ const errorMessage = `Failed to generate FITB question after ${MAX_RETRY_ATTEMPTS} attempts. Last error: ${lastError?.message}`;
413
382
  console.error("\n\u274C Final Result: FAILED");
414
383
  console.error(errorMessage);
415
384
  return { error: errorMessage };
@@ -437,7 +406,7 @@ var MAX_RETRY_ATTEMPTS2 = 3;
437
406
  var RETRY_DELAY_MS2 = 3e3;
438
407
  function buildEnhancedPrompt2(clientInput, attemptNumber) {
439
408
  const { quizContext, language, difficulty, numberOfPairs, imageUrl } = clientInput;
440
- const category = (quizContext == null ? void 0 : quizContext.originalCategory) || "the specified technical category";
409
+ const category = quizContext?.originalCategory || "the specified technical category";
441
410
  const attemptInfo = attemptNumber > 1 ? `
442
411
  ## DEBUG INFO - This is attempt #${attemptNumber}
443
412
  Previous attempts failed. Please ensure the 'correctPairs' array has exactly the required number of items and the JSON is valid.
@@ -446,10 +415,10 @@ Previous attempts failed. Please ensure the 'correctPairs' array has exactly the
446
415
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The matching pairs must be directly related to the content of this image.` : "";
447
416
  const contextStrings = [
448
417
  `**Required Category:** ${category}`,
449
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
418
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
450
419
  imageContextInstruction,
451
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
452
- (quizContext == null ? void 0 : quizContext.targetMisconception) && `**Target Misconception:** Design a pair that specifically tests this confusion: "${quizContext.targetMisconception}"`
420
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
421
+ quizContext?.targetMisconception && `**Target Misconception:** Design a pair that specifically tests this confusion: "${quizContext.targetMisconception}"`
453
422
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
454
423
  const exampleJson = JSON.stringify({
455
424
  prompt: "Match each Swift collection type to its primary characteristic.",
@@ -479,7 +448,7 @@ ${contextStrings}
479
448
  Based on all the rules and context above, generate a single Matching Question.
480
449
 
481
450
  ### Input Parameters
482
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
451
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
483
452
  - **Language for Text:** ${language}
484
453
  - **Difficulty Level:** ${difficulty}
485
454
  - **Number of Pairs:** Generate exactly ${numberOfPairs} correct pairs in the 'correctPairs' array.
@@ -492,7 +461,6 @@ ${exampleJson}
492
461
  Now, generate the JSON for the requested question.`;
493
462
  }
494
463
  async function generateMatchingQuestion(clientInput, apiKey) {
495
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
496
464
  const ai = new GoogleGenAI({ apiKey });
497
465
  const model = "gemini-2.5-flash";
498
466
  const config = {
@@ -509,7 +477,7 @@ async function generateMatchingQuestion(clientInput, apiKey) {
509
477
  const promptText = buildEnhancedPrompt2(clientInput, attempt);
510
478
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
511
479
  try {
512
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
480
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
513
481
  const parts = [{ text: promptText }];
514
482
  if (clientInput.imageUrl) {
515
483
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -519,7 +487,7 @@ async function generateMatchingQuestion(clientInput, apiKey) {
519
487
  const contents = [{ role: "user", parts }];
520
488
  const aiResult = await ai.models.generateContent({ model, config, contents });
521
489
  const response = aiResult;
522
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
490
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
523
491
  const duration = Date.now() - startTime;
524
492
  DebugLogger.logResponse(attempt, rawText);
525
493
  if (!rawText) throw new Error("AI returned an empty response.");
@@ -530,8 +498,8 @@ async function generateMatchingQuestion(clientInput, apiKey) {
530
498
  if (aiGeneratedContent.correctPairs.length !== clientInput.numberOfPairs) {
531
499
  throw new Error(`AI generated ${aiGeneratedContent.correctPairs.length} pairs, but ${clientInput.numberOfPairs} were required.`);
532
500
  }
533
- if ((_f = clientInput.quizContext) == null ? void 0 : _f.originalCategory) {
534
- const verifiedCategory = (_g = aiGeneratedContent.verifiedCategory) == null ? void 0 : _g.toLowerCase();
501
+ if (clientInput.quizContext?.originalCategory) {
502
+ const verifiedCategory = aiGeneratedContent.verifiedCategory?.toLowerCase();
535
503
  const requiredCategory = clientInput.quizContext.originalCategory.toLowerCase();
536
504
  if (verifiedCategory && verifiedCategory !== requiredCategory) {
537
505
  throw new Error(`Category mismatch: Required ${requiredCategory}, got ${verifiedCategory}`);
@@ -557,13 +525,13 @@ async function generateMatchingQuestion(clientInput, apiKey) {
557
525
  shuffleOptions: clientInput.shuffleOptions,
558
526
  explanation: aiGeneratedContent.explanation,
559
527
  points: aiGeneratedContent.points,
560
- topic: aiGeneratedContent.topic || ((_h = clientInput.quizContext) == null ? void 0 : _h.originalTopic),
528
+ topic: aiGeneratedContent.topic || clientInput.quizContext?.originalTopic,
561
529
  difficulty: clientInput.difficulty,
562
- contextCode: (_i = clientInput.quizContext) == null ? void 0 : _i.plannedContextId,
563
- bloomLevel: (_j = clientInput.quizContext) == null ? void 0 : _j.plannedBloomLevel,
564
- learningObjective: (_k = clientInput.quizContext) == null ? void 0 : _k.originalLoId,
565
- subject: (_l = clientInput.quizContext) == null ? void 0 : _l.originalSubject,
566
- category: (_m = clientInput.quizContext) == null ? void 0 : _m.originalCategory,
530
+ contextCode: clientInput.quizContext?.plannedContextId,
531
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
532
+ learningObjective: clientInput.quizContext?.originalLoId,
533
+ subject: clientInput.quizContext?.originalSubject,
534
+ category: clientInput.quizContext?.originalCategory,
567
535
  imageUrl: clientInput.imageUrl
568
536
  };
569
537
  const validatedQuestion = MatchingQuestionZodSchema.parse(completeQuestion);
@@ -585,7 +553,7 @@ async function generateMatchingQuestion(clientInput, apiKey) {
585
553
  }
586
554
  }
587
555
  DebugLogger.logAttemptSummary(attemptResults);
588
- const errorMessage = `Failed to generate Matching question after ${MAX_RETRY_ATTEMPTS2} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
556
+ const errorMessage = `Failed to generate Matching question after ${MAX_RETRY_ATTEMPTS2} attempts. Last error: ${lastError?.message}`;
589
557
  console.error("\n\u274C Final Result: FAILED");
590
558
  console.error(errorMessage);
591
559
  return { error: errorMessage };
@@ -614,7 +582,7 @@ var MAX_RETRY_ATTEMPTS3 = 3;
614
582
  var RETRY_DELAY_MS3 = 3e3;
615
583
  function buildEnhancedPrompt3(clientInput, attemptNumber) {
616
584
  const { quizContext, language, difficulty, numberOfOptions, imageUrl } = clientInput;
617
- const category = (quizContext == null ? void 0 : quizContext.originalCategory) || "the specified technical category";
585
+ const category = quizContext?.originalCategory || "the specified technical category";
618
586
  const attemptInfo = attemptNumber > 1 ? `
619
587
  ## DEBUG INFO - This is attempt #${attemptNumber}
620
588
  Previous attempts failed...
@@ -623,11 +591,11 @@ Previous attempts failed...
623
591
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The question and options must be directly related to the content of this image.` : "";
624
592
  const contextStrings = [
625
593
  `**Required Category:** ${category}`,
626
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
594
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
627
595
  imageContextInstruction,
628
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
629
- (quizContext == null ? void 0 : quizContext.targetMisconception) && `**Target Misconception:** Use this to create plausible incorrect answers: "${quizContext.targetMisconception}"`,
630
- (quizContext == null ? void 0 : quizContext.difficultyReason) && `**Pedagogical Reason:** ${quizContext.difficultyReason}`
596
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
597
+ quizContext?.targetMisconception && `**Target Misconception:** Use this to create plausible incorrect answers: "${quizContext.targetMisconception}"`,
598
+ quizContext?.difficultyReason && `**Pedagogical Reason:** ${quizContext.difficultyReason}`
631
599
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
632
600
  const exampleJson = JSON.stringify({
633
601
  prompt: `In ${category}, what is the primary purpose of the 'guard' statement?`,
@@ -659,7 +627,7 @@ ${contextStrings}
659
627
  Based on all the rules and context above, generate a single Multiple Choice Question.
660
628
 
661
629
  ### Input Parameters
662
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
630
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
663
631
  - **Language for Text:** ${language}
664
632
  - **Difficulty Level:** ${difficulty}
665
633
  - **Number of Options:** ${numberOfOptions}
@@ -672,7 +640,6 @@ ${exampleJson}
672
640
  Now, generate the JSON for the requested question.`;
673
641
  }
674
642
  async function generateMCQQuestion(clientInput, apiKey) {
675
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
676
643
  const ai = new GoogleGenAI({ apiKey });
677
644
  const model = "gemini-2.5-flash";
678
645
  const config = {
@@ -689,7 +656,7 @@ async function generateMCQQuestion(clientInput, apiKey) {
689
656
  const promptText = buildEnhancedPrompt3(clientInput, attempt);
690
657
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
691
658
  try {
692
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
659
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
693
660
  const parts = [{ text: promptText }];
694
661
  if (clientInput.imageUrl) {
695
662
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -703,7 +670,7 @@ async function generateMCQQuestion(clientInput, apiKey) {
703
670
  contents
704
671
  });
705
672
  const response = aiResult;
706
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
673
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
707
674
  const duration = Date.now() - startTime;
708
675
  DebugLogger.logResponse(attempt, rawText);
709
676
  if (!rawText) {
@@ -713,8 +680,8 @@ async function generateMCQQuestion(clientInput, apiKey) {
713
680
  DebugLogger.logValidation(attempt, "JSON Parsed Successfully", parsedJson);
714
681
  const aiGeneratedContent = AIMCQOutputFieldsSchema.parse(parsedJson);
715
682
  DebugLogger.logValidation(attempt, "Zod Schema Validated", aiGeneratedContent);
716
- if ((_f = clientInput.quizContext) == null ? void 0 : _f.originalCategory) {
717
- const verifiedCategory = (_g = aiGeneratedContent.verifiedCategory) == null ? void 0 : _g.toLowerCase();
683
+ if (clientInput.quizContext?.originalCategory) {
684
+ const verifiedCategory = aiGeneratedContent.verifiedCategory?.toLowerCase();
718
685
  const requiredCategory = clientInput.quizContext.originalCategory.toLowerCase();
719
686
  if (verifiedCategory && verifiedCategory !== requiredCategory) {
720
687
  throw new Error(`Category mismatch: Required ${requiredCategory}, got ${verifiedCategory}`);
@@ -739,13 +706,13 @@ async function generateMCQQuestion(clientInput, apiKey) {
739
706
  correctAnswerId: finalCorrectAnswerId,
740
707
  explanation: aiGeneratedContent.explanation,
741
708
  points: aiGeneratedContent.points,
742
- topic: aiGeneratedContent.topic || ((_h = clientInput.quizContext) == null ? void 0 : _h.originalTopic),
709
+ topic: aiGeneratedContent.topic || clientInput.quizContext?.originalTopic,
743
710
  difficulty: clientInput.difficulty,
744
- contextCode: (_i = clientInput.quizContext) == null ? void 0 : _i.plannedContextId,
745
- bloomLevel: (_j = clientInput.quizContext) == null ? void 0 : _j.plannedBloomLevel,
746
- learningObjective: (_k = clientInput.quizContext) == null ? void 0 : _k.originalLoId,
747
- subject: (_l = clientInput.quizContext) == null ? void 0 : _l.originalSubject,
748
- category: (_m = clientInput.quizContext) == null ? void 0 : _m.originalCategory,
711
+ contextCode: clientInput.quizContext?.plannedContextId,
712
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
713
+ learningObjective: clientInput.quizContext?.originalLoId,
714
+ subject: clientInput.quizContext?.originalSubject,
715
+ category: clientInput.quizContext?.originalCategory,
749
716
  imageUrl: clientInput.imageUrl
750
717
  };
751
718
  const validatedQuestion = MultipleChoiceQuestionZodSchema.parse(completeQuestion);
@@ -767,7 +734,7 @@ async function generateMCQQuestion(clientInput, apiKey) {
767
734
  }
768
735
  }
769
736
  DebugLogger.logAttemptSummary(attemptResults);
770
- const errorMessage = `Failed to generate MCQ question after ${MAX_RETRY_ATTEMPTS3} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
737
+ const errorMessage = `Failed to generate MCQ question after ${MAX_RETRY_ATTEMPTS3} attempts. Last error: ${lastError?.message}`;
771
738
  console.error("\n\u274C Final Result: FAILED");
772
739
  console.error(errorMessage);
773
740
  return { error: errorMessage };
@@ -793,7 +760,7 @@ var MAX_RETRY_ATTEMPTS4 = 3;
793
760
  var RETRY_DELAY_MS4 = 3e3;
794
761
  function buildEnhancedPrompt4(clientInput, attemptNumber) {
795
762
  const { quizContext, language, difficulty, numberOfOptions, minCorrectAnswers, maxCorrectAnswers, imageUrl } = clientInput;
796
- const category = (quizContext == null ? void 0 : quizContext.originalCategory) || "the specified technical category";
763
+ const category = quizContext?.originalCategory || "the specified technical category";
797
764
  const attemptInfo = attemptNumber > 1 ? `
798
765
  ## DEBUG INFO - This is attempt #${attemptNumber}
799
766
  Previous attempts failed due to validation errors. Pay close attention to the number of correct answers and the JSON schema.
@@ -802,11 +769,11 @@ Previous attempts failed due to validation errors. Pay close attention to the nu
802
769
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The question and options must be directly related to the content of this image.` : "";
803
770
  const contextStrings = [
804
771
  `**Required Category:** ${category} (This is the ONLY language to be used)`,
805
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
772
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
806
773
  imageContextInstruction,
807
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
808
- (quizContext == null ? void 0 : quizContext.targetMisconception) && `**Target Misconception:** Use this to create plausible incorrect answers (distractors). The misconception is: "${quizContext.targetMisconception}"`,
809
- (quizContext == null ? void 0 : quizContext.difficultyReason) && `**Pedagogical Reason:** ${quizContext.difficultyReason}`
774
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
775
+ quizContext?.targetMisconception && `**Target Misconception:** Use this to create plausible incorrect answers (distractors). The misconception is: "${quizContext.targetMisconception}"`,
776
+ quizContext?.difficultyReason && `**Pedagogical Reason:** ${quizContext.difficultyReason}`
810
777
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
811
778
  const exampleJson = JSON.stringify({
812
779
  prompt: "Which of the following are considered programming paradigms?",
@@ -839,7 +806,7 @@ ${contextStrings}
839
806
  Based on all the rules and context above, generate a single Multiple Response Question.
840
807
 
841
808
  ### Input Parameters
842
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
809
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
843
810
  - **Language for Text:** ${language}
844
811
  - **Difficulty Level:** ${difficulty}
845
812
  - **Number of Options:** Generate exactly ${numberOfOptions} options.
@@ -853,7 +820,6 @@ ${exampleJson}
853
820
  Now, generate the JSON for the requested question.`;
854
821
  }
855
822
  async function generateMRQQuestion(clientInput, apiKey) {
856
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
857
823
  if (clientInput.minCorrectAnswers > clientInput.maxCorrectAnswers) {
858
824
  return { error: `Invalid input: minCorrectAnswers (${clientInput.minCorrectAnswers}) cannot be greater than maxCorrectAnswers (${clientInput.maxCorrectAnswers}).` };
859
825
  }
@@ -876,7 +842,7 @@ async function generateMRQQuestion(clientInput, apiKey) {
876
842
  const promptText = buildEnhancedPrompt4(clientInput, attempt);
877
843
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
878
844
  try {
879
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
845
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
880
846
  const parts = [{ text: promptText }];
881
847
  if (clientInput.imageUrl) {
882
848
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -890,7 +856,7 @@ async function generateMRQQuestion(clientInput, apiKey) {
890
856
  contents
891
857
  });
892
858
  const response = aiResult;
893
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
859
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
894
860
  const duration = Date.now() - startTime;
895
861
  DebugLogger.logResponse(attempt, rawText);
896
862
  if (!rawText) {
@@ -907,8 +873,8 @@ async function generateMRQQuestion(clientInput, apiKey) {
907
873
  if (correctCount < clientInput.minCorrectAnswers || correctCount > clientInput.maxCorrectAnswers) {
908
874
  throw new Error(`AI provided ${correctCount} correct answers, which is outside the required range of ${clientInput.minCorrectAnswers}-${clientInput.maxCorrectAnswers}.`);
909
875
  }
910
- if ((_f = clientInput.quizContext) == null ? void 0 : _f.originalCategory) {
911
- const verifiedCategory = (_g = aiGeneratedContent.verifiedCategory) == null ? void 0 : _g.toLowerCase();
876
+ if (clientInput.quizContext?.originalCategory) {
877
+ const verifiedCategory = aiGeneratedContent.verifiedCategory?.toLowerCase();
912
878
  const requiredCategory = clientInput.quizContext.originalCategory.toLowerCase();
913
879
  if (verifiedCategory && verifiedCategory !== requiredCategory) {
914
880
  throw new Error(`Category mismatch: Required ${requiredCategory}, got ${verifiedCategory}`);
@@ -937,13 +903,13 @@ async function generateMRQQuestion(clientInput, apiKey) {
937
903
  correctAnswerIds: finalCorrectAnswerIds,
938
904
  explanation: aiGeneratedContent.explanation,
939
905
  points: aiGeneratedContent.points,
940
- topic: aiGeneratedContent.topic || ((_h = clientInput.quizContext) == null ? void 0 : _h.originalTopic),
906
+ topic: aiGeneratedContent.topic || clientInput.quizContext?.originalTopic,
941
907
  difficulty: aiGeneratedContent.difficulty || clientInput.difficulty,
942
- contextCode: (_i = clientInput.quizContext) == null ? void 0 : _i.plannedContextId,
943
- bloomLevel: (_j = clientInput.quizContext) == null ? void 0 : _j.plannedBloomLevel,
944
- learningObjective: (_k = clientInput.quizContext) == null ? void 0 : _k.originalLoId,
945
- subject: (_l = clientInput.quizContext) == null ? void 0 : _l.originalSubject,
946
- category: (_m = clientInput.quizContext) == null ? void 0 : _m.originalCategory,
908
+ contextCode: clientInput.quizContext?.plannedContextId,
909
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
910
+ learningObjective: clientInput.quizContext?.originalLoId,
911
+ subject: clientInput.quizContext?.originalSubject,
912
+ category: clientInput.quizContext?.originalCategory,
947
913
  imageUrl: clientInput.imageUrl
948
914
  };
949
915
  const validatedQuestion = MultipleResponseQuestionZodSchema.parse(completeQuestion);
@@ -965,7 +931,7 @@ async function generateMRQQuestion(clientInput, apiKey) {
965
931
  }
966
932
  }
967
933
  DebugLogger.logAttemptSummary(attemptResults);
968
- const errorMessage = `Failed to generate MRQ question after ${MAX_RETRY_ATTEMPTS4} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
934
+ const errorMessage = `Failed to generate MRQ question after ${MAX_RETRY_ATTEMPTS4} attempts. Last error: ${lastError?.message}`;
969
935
  console.error("\n\u274C Final Result: FAILED");
970
936
  console.error(errorMessage);
971
937
  return { error: errorMessage };
@@ -995,7 +961,7 @@ var MAX_RETRY_ATTEMPTS5 = 3;
995
961
  var RETRY_DELAY_MS5 = 3e3;
996
962
  function buildEnhancedPrompt5(clientInput, attemptNumber) {
997
963
  const { quizContext, language, difficulty, minRange, maxRange, allowDecimals, imageUrl } = clientInput;
998
- const category = (quizContext == null ? void 0 : quizContext.originalCategory) || "the specified technical category";
964
+ const category = quizContext?.originalCategory || "the specified technical category";
999
965
  const attemptInfo = attemptNumber > 1 ? `
1000
966
  ## DEBUG INFO - This is attempt #${attemptNumber}
1001
967
  Previous attempts failed. Ensure the 'answer' is a valid number and fits within the specified constraints.
@@ -1004,10 +970,10 @@ Previous attempts failed. Ensure the 'answer' is a valid number and fits within
1004
970
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The question and its numerical answer must be directly related to the content of this image.` : "";
1005
971
  const contextStrings = [
1006
972
  `**Required Category:** ${category}`,
1007
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
973
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
1008
974
  imageContextInstruction,
1009
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
1010
- (quizContext == null ? void 0 : quizContext.targetMisconception) && `**Target Misconception:** The question should clarify this numerical error: "${quizContext.targetMisconception}"`
975
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
976
+ quizContext?.targetMisconception && `**Target Misconception:** The question should clarify this numerical error: "${quizContext.targetMisconception}"`
1011
977
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
1012
978
  const constraintStrings = [
1013
979
  minRange !== void 0 && `The final 'answer' MUST be greater than or equal to ${minRange}.`,
@@ -1039,7 +1005,7 @@ ${contextStrings}
1039
1005
  Based on all the rules and context above, generate a single Numeric Question.
1040
1006
 
1041
1007
  ### Input Parameters & Constraints
1042
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
1008
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
1043
1009
  - **Language for Text:** ${language}
1044
1010
  - **Difficulty Level:** ${difficulty}
1045
1011
  ${constraintStrings ? `
@@ -1054,7 +1020,6 @@ ${exampleJson}
1054
1020
  Now, generate the JSON for the requested question.`;
1055
1021
  }
1056
1022
  async function generateNumericQuestion(clientInput, apiKey) {
1057
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
1058
1023
  if (clientInput.minRange !== void 0 && clientInput.maxRange !== void 0 && clientInput.minRange > clientInput.maxRange) {
1059
1024
  return { error: `Invalid input: minRange (${clientInput.minRange}) cannot be greater than maxRange (${clientInput.maxRange}).` };
1060
1025
  }
@@ -1075,7 +1040,7 @@ async function generateNumericQuestion(clientInput, apiKey) {
1075
1040
  const promptText = buildEnhancedPrompt5(clientInput, attempt);
1076
1041
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
1077
1042
  try {
1078
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
1043
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
1079
1044
  const parts = [{ text: promptText }];
1080
1045
  if (clientInput.imageUrl) {
1081
1046
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -1085,7 +1050,7 @@ async function generateNumericQuestion(clientInput, apiKey) {
1085
1050
  const contents = [{ role: "user", parts }];
1086
1051
  const aiResult = await ai.models.generateContent({ model, config, contents });
1087
1052
  const response = aiResult;
1088
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
1053
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
1089
1054
  const duration = Date.now() - startTime;
1090
1055
  DebugLogger.logResponse(attempt, rawText);
1091
1056
  if (!rawText) throw new Error("AI returned an empty response.");
@@ -1103,8 +1068,8 @@ async function generateNumericQuestion(clientInput, apiKey) {
1103
1068
  if (!clientInput.allowDecimals && !Number.isInteger(answer)) {
1104
1069
  throw new Error(`AI answer ${answer} is not an integer, but decimals are not allowed.`);
1105
1070
  }
1106
- if ((_f = clientInput.quizContext) == null ? void 0 : _f.originalCategory) {
1107
- const verifiedCategory = (_g = aiGeneratedContent.verifiedCategory) == null ? void 0 : _g.toLowerCase();
1071
+ if (clientInput.quizContext?.originalCategory) {
1072
+ const verifiedCategory = aiGeneratedContent.verifiedCategory?.toLowerCase();
1108
1073
  const requiredCategory = clientInput.quizContext.originalCategory.toLowerCase();
1109
1074
  if (verifiedCategory && verifiedCategory !== requiredCategory) {
1110
1075
  throw new Error(`Category mismatch: Required ${requiredCategory}, got ${verifiedCategory}`);
@@ -1115,16 +1080,16 @@ async function generateNumericQuestion(clientInput, apiKey) {
1115
1080
  questionType: "numeric",
1116
1081
  prompt: aiGeneratedContent.prompt,
1117
1082
  answer: aiGeneratedContent.answer,
1118
- tolerance: (_i = (_h = clientInput.tolerance) != null ? _h : aiGeneratedContent.tolerance) != null ? _i : 0,
1083
+ tolerance: clientInput.tolerance ?? aiGeneratedContent.tolerance ?? 0,
1119
1084
  explanation: aiGeneratedContent.explanation,
1120
1085
  points: aiGeneratedContent.points,
1121
- topic: aiGeneratedContent.topic || ((_j = clientInput.quizContext) == null ? void 0 : _j.originalTopic),
1086
+ topic: aiGeneratedContent.topic || clientInput.quizContext?.originalTopic,
1122
1087
  difficulty: clientInput.difficulty,
1123
- contextCode: (_k = clientInput.quizContext) == null ? void 0 : _k.plannedContextId,
1124
- bloomLevel: (_l = clientInput.quizContext) == null ? void 0 : _l.plannedBloomLevel,
1125
- learningObjective: (_m = clientInput.quizContext) == null ? void 0 : _m.originalLoId,
1126
- subject: (_n = clientInput.quizContext) == null ? void 0 : _n.originalSubject,
1127
- category: (_o = clientInput.quizContext) == null ? void 0 : _o.originalCategory,
1088
+ contextCode: clientInput.quizContext?.plannedContextId,
1089
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
1090
+ learningObjective: clientInput.quizContext?.originalLoId,
1091
+ subject: clientInput.quizContext?.originalSubject,
1092
+ category: clientInput.quizContext?.originalCategory,
1128
1093
  imageUrl: clientInput.imageUrl
1129
1094
  };
1130
1095
  const validatedQuestion = NumericQuestionZodSchema.parse(completeQuestion);
@@ -1146,7 +1111,7 @@ async function generateNumericQuestion(clientInput, apiKey) {
1146
1111
  }
1147
1112
  }
1148
1113
  DebugLogger.logAttemptSummary(attemptResults);
1149
- const errorMessage = `Failed to generate Numeric question after ${MAX_RETRY_ATTEMPTS5} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
1114
+ const errorMessage = `Failed to generate Numeric question after ${MAX_RETRY_ATTEMPTS5} attempts. Last error: ${lastError?.message}`;
1150
1115
  console.error("\n\u274C Final Result: FAILED");
1151
1116
  console.error(errorMessage);
1152
1117
  return { error: errorMessage };
@@ -1172,7 +1137,7 @@ var MAX_RETRY_ATTEMPTS6 = 3;
1172
1137
  var RETRY_DELAY_MS6 = 3e3;
1173
1138
  function buildEnhancedPrompt6(clientInput, attemptNumber) {
1174
1139
  const { quizContext, language, difficulty, numberOfItems, imageUrl } = clientInput;
1175
- const category = (quizContext == null ? void 0 : quizContext.originalCategory) || "the specified technical category";
1140
+ const category = quizContext?.originalCategory || "the specified technical category";
1176
1141
  const attemptInfo = attemptNumber > 1 ? `
1177
1142
  ## DEBUG INFO - This is attempt #${attemptNumber}
1178
1143
  Previous attempts failed. Ensure the 'itemsInCorrectOrder' array has exactly the required number of items and the JSON is valid.
@@ -1181,10 +1146,10 @@ Previous attempts failed. Ensure the 'itemsInCorrectOrder' array has exactly the
1181
1146
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The sequence of items must be directly related to the process or content shown in this image.` : "";
1182
1147
  const contextStrings = [
1183
1148
  `**Required Category:** ${category}`,
1184
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
1149
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
1185
1150
  imageContextInstruction,
1186
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
1187
- (quizContext == null ? void 0 : quizContext.targetMisconception) && `**Target Misconception:** The sequence should clarify this specific process error: "${quizContext.targetMisconception}"`
1151
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
1152
+ quizContext?.targetMisconception && `**Target Misconception:** The sequence should clarify this specific process error: "${quizContext.targetMisconception}"`
1188
1153
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
1189
1154
  const exampleJson = JSON.stringify({
1190
1155
  prompt: "Arrange the steps to make a network request in Swift using URLSession.",
@@ -1215,7 +1180,7 @@ ${contextStrings}
1215
1180
  Based on all the rules and context above, generate a single Sequence Question.
1216
1181
 
1217
1182
  ### Input Parameters
1218
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
1183
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
1219
1184
  - **Language for Text:** ${language}
1220
1185
  - **Difficulty Level:** ${difficulty}
1221
1186
  - **Number of Items:** Generate an array 'itemsInCorrectOrder' containing exactly ${numberOfItems} items. The array itself MUST be in the correct final sequence.
@@ -1228,7 +1193,6 @@ ${exampleJson}
1228
1193
  Now, generate the JSON for the requested question.`;
1229
1194
  }
1230
1195
  async function generateSequenceQuestion(clientInput, apiKey) {
1231
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
1232
1196
  const ai = new GoogleGenAI({ apiKey });
1233
1197
  const model = "gemini-2.5-flash";
1234
1198
  const config = {
@@ -1245,7 +1209,7 @@ async function generateSequenceQuestion(clientInput, apiKey) {
1245
1209
  const promptText = buildEnhancedPrompt6(clientInput, attempt);
1246
1210
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
1247
1211
  try {
1248
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
1212
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
1249
1213
  const parts = [{ text: promptText }];
1250
1214
  if (clientInput.imageUrl) {
1251
1215
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -1255,7 +1219,7 @@ async function generateSequenceQuestion(clientInput, apiKey) {
1255
1219
  const contents = [{ role: "user", parts }];
1256
1220
  const aiResult = await ai.models.generateContent({ model, config, contents });
1257
1221
  const response = aiResult;
1258
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
1222
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
1259
1223
  const duration = Date.now() - startTime;
1260
1224
  DebugLogger.logResponse(attempt, rawText);
1261
1225
  if (!rawText) throw new Error("AI returned an empty response.");
@@ -1266,8 +1230,8 @@ async function generateSequenceQuestion(clientInput, apiKey) {
1266
1230
  if (aiGeneratedContent.itemsInCorrectOrder.length !== clientInput.numberOfItems) {
1267
1231
  throw new Error(`AI generated ${aiGeneratedContent.itemsInCorrectOrder.length} items, but ${clientInput.numberOfItems} were required.`);
1268
1232
  }
1269
- if ((_f = clientInput.quizContext) == null ? void 0 : _f.originalCategory) {
1270
- const verifiedCategory = (_g = aiGeneratedContent.verifiedCategory) == null ? void 0 : _g.toLowerCase();
1233
+ if (clientInput.quizContext?.originalCategory) {
1234
+ const verifiedCategory = aiGeneratedContent.verifiedCategory?.toLowerCase();
1271
1235
  const requiredCategory = clientInput.quizContext.originalCategory.toLowerCase();
1272
1236
  if (verifiedCategory && verifiedCategory !== requiredCategory) {
1273
1237
  throw new Error(`Category mismatch: Required ${requiredCategory}, got ${verifiedCategory}`);
@@ -1288,13 +1252,13 @@ async function generateSequenceQuestion(clientInput, apiKey) {
1288
1252
  correctOrder: finalCorrectOrder,
1289
1253
  explanation: aiGeneratedContent.explanation,
1290
1254
  points: aiGeneratedContent.points,
1291
- topic: aiGeneratedContent.topic || ((_h = clientInput.quizContext) == null ? void 0 : _h.originalTopic),
1255
+ topic: aiGeneratedContent.topic || clientInput.quizContext?.originalTopic,
1292
1256
  difficulty: clientInput.difficulty,
1293
- contextCode: (_i = clientInput.quizContext) == null ? void 0 : _i.plannedContextId,
1294
- bloomLevel: (_j = clientInput.quizContext) == null ? void 0 : _j.plannedBloomLevel,
1295
- learningObjective: (_k = clientInput.quizContext) == null ? void 0 : _k.originalLoId,
1296
- subject: (_l = clientInput.quizContext) == null ? void 0 : _l.originalSubject,
1297
- category: (_m = clientInput.quizContext) == null ? void 0 : _m.originalCategory,
1257
+ contextCode: clientInput.quizContext?.plannedContextId,
1258
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
1259
+ learningObjective: clientInput.quizContext?.originalLoId,
1260
+ subject: clientInput.quizContext?.originalSubject,
1261
+ category: clientInput.quizContext?.originalCategory,
1298
1262
  imageUrl: clientInput.imageUrl
1299
1263
  };
1300
1264
  const validatedQuestion = SequenceQuestionZodSchema.parse(completeQuestion);
@@ -1316,7 +1280,7 @@ async function generateSequenceQuestion(clientInput, apiKey) {
1316
1280
  }
1317
1281
  }
1318
1282
  DebugLogger.logAttemptSummary(attemptResults);
1319
- const errorMessage = `Failed to generate Sequence question after ${MAX_RETRY_ATTEMPTS6} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
1283
+ const errorMessage = `Failed to generate Sequence question after ${MAX_RETRY_ATTEMPTS6} attempts. Last error: ${lastError?.message}`;
1320
1284
  console.error("\n\u274C Final Result: FAILED");
1321
1285
  console.error(errorMessage);
1322
1286
  return { error: errorMessage };
@@ -1341,7 +1305,7 @@ var MAX_RETRY_ATTEMPTS7 = 3;
1341
1305
  var RETRY_DELAY_MS7 = 3e3;
1342
1306
  function buildEnhancedPrompt7(clientInput, attemptNumber) {
1343
1307
  const { quizContext, language, difficulty, imageUrl } = clientInput;
1344
- const category = (quizContext == null ? void 0 : quizContext.originalCategory) || "the specified technical category";
1308
+ const category = quizContext?.originalCategory || "the specified technical category";
1345
1309
  const attemptInfo = attemptNumber > 1 ? `
1346
1310
  ## DEBUG INFO - This is attempt #${attemptNumber}
1347
1311
  Previous attempts failed. Ensure 'acceptedAnswers' is a non-empty array of strings and the JSON is valid.
@@ -1350,10 +1314,10 @@ Previous attempts failed. Ensure 'acceptedAnswers' is a non-empty array of strin
1350
1314
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The question and its short answer must be directly related to the content of this image.` : "";
1351
1315
  const contextStrings = [
1352
1316
  `**Required Category:** ${category}`,
1353
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
1317
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
1354
1318
  imageContextInstruction,
1355
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
1356
- (quizContext == null ? void 0 : quizContext.targetMisconception) && `**Target Misconception:** The question should require an answer that corrects this specific misconception: "${quizContext.targetMisconception}"`
1319
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
1320
+ quizContext?.targetMisconception && `**Target Misconception:** The question should require an answer that corrects this specific misconception: "${quizContext.targetMisconception}"`
1357
1321
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
1358
1322
  const exampleJson = JSON.stringify({
1359
1323
  prompt: "In Swift, what keyword is used to declare a constant?",
@@ -1379,7 +1343,7 @@ ${contextStrings}
1379
1343
  Based on all the rules and context above, generate a single Short Answer Question.
1380
1344
 
1381
1345
  ### Input Parameters
1382
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
1346
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
1383
1347
  - **Language for Text:** ${language}
1384
1348
  - **Difficulty Level:** ${difficulty}
1385
1349
 
@@ -1391,7 +1355,6 @@ ${exampleJson}
1391
1355
  Now, generate the JSON for the requested question.`;
1392
1356
  }
1393
1357
  async function generateShortAnswerQuestion(clientInput, apiKey) {
1394
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
1395
1358
  const ai = new GoogleGenAI({ apiKey });
1396
1359
  const model = "gemini-2.5-flash";
1397
1360
  const config = {
@@ -1408,7 +1371,7 @@ async function generateShortAnswerQuestion(clientInput, apiKey) {
1408
1371
  const promptText = buildEnhancedPrompt7(clientInput, attempt);
1409
1372
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
1410
1373
  try {
1411
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
1374
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
1412
1375
  const parts = [{ text: promptText }];
1413
1376
  if (clientInput.imageUrl) {
1414
1377
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -1418,7 +1381,7 @@ async function generateShortAnswerQuestion(clientInput, apiKey) {
1418
1381
  const contents = [{ role: "user", parts }];
1419
1382
  const aiResult = await ai.models.generateContent({ model, config, contents });
1420
1383
  const response = aiResult;
1421
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
1384
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
1422
1385
  const duration = Date.now() - startTime;
1423
1386
  DebugLogger.logResponse(attempt, rawText);
1424
1387
  if (!rawText) throw new Error("AI returned an empty response.");
@@ -1426,8 +1389,8 @@ async function generateShortAnswerQuestion(clientInput, apiKey) {
1426
1389
  DebugLogger.logValidation(attempt, "JSON Parsed Successfully", parsedJson);
1427
1390
  const aiGeneratedContent = AIShortAnswerOutputFieldsSchema.parse(parsedJson);
1428
1391
  DebugLogger.logValidation(attempt, "Zod Schema Validated", aiGeneratedContent);
1429
- if ((_f = clientInput.quizContext) == null ? void 0 : _f.originalCategory) {
1430
- const verifiedCategory = (_g = aiGeneratedContent.verifiedCategory) == null ? void 0 : _g.toLowerCase();
1392
+ if (clientInput.quizContext?.originalCategory) {
1393
+ const verifiedCategory = aiGeneratedContent.verifiedCategory?.toLowerCase();
1431
1394
  const requiredCategory = clientInput.quizContext.originalCategory.toLowerCase();
1432
1395
  if (verifiedCategory && verifiedCategory !== requiredCategory) {
1433
1396
  throw new Error(`Category mismatch: Required ${requiredCategory}, got ${verifiedCategory}`);
@@ -1441,13 +1404,13 @@ async function generateShortAnswerQuestion(clientInput, apiKey) {
1441
1404
  isCaseSensitive: clientInput.isCaseSensitive,
1442
1405
  explanation: aiGeneratedContent.explanation,
1443
1406
  points: aiGeneratedContent.points,
1444
- topic: aiGeneratedContent.topic || ((_h = clientInput.quizContext) == null ? void 0 : _h.originalTopic),
1407
+ topic: aiGeneratedContent.topic || clientInput.quizContext?.originalTopic,
1445
1408
  difficulty: clientInput.difficulty,
1446
- contextCode: (_i = clientInput.quizContext) == null ? void 0 : _i.plannedContextId,
1447
- bloomLevel: (_j = clientInput.quizContext) == null ? void 0 : _j.plannedBloomLevel,
1448
- learningObjective: (_k = clientInput.quizContext) == null ? void 0 : _k.originalLoId,
1449
- subject: (_l = clientInput.quizContext) == null ? void 0 : _l.originalSubject,
1450
- category: (_m = clientInput.quizContext) == null ? void 0 : _m.originalCategory,
1409
+ contextCode: clientInput.quizContext?.plannedContextId,
1410
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
1411
+ learningObjective: clientInput.quizContext?.originalLoId,
1412
+ subject: clientInput.quizContext?.originalSubject,
1413
+ category: clientInput.quizContext?.originalCategory,
1451
1414
  imageUrl: clientInput.imageUrl
1452
1415
  };
1453
1416
  const validatedQuestion = ShortAnswerQuestionZodSchema.parse(completeQuestion);
@@ -1469,7 +1432,7 @@ async function generateShortAnswerQuestion(clientInput, apiKey) {
1469
1432
  }
1470
1433
  }
1471
1434
  DebugLogger.logAttemptSummary(attemptResults);
1472
- const errorMessage = `Failed to generate Short Answer question after ${MAX_RETRY_ATTEMPTS7} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
1435
+ const errorMessage = `Failed to generate Short Answer question after ${MAX_RETRY_ATTEMPTS7} attempts. Last error: ${lastError?.message}`;
1473
1436
  console.error("\n\u274C Final Result: FAILED");
1474
1437
  console.error(errorMessage);
1475
1438
  return { error: errorMessage };
@@ -1491,21 +1454,21 @@ var MAX_RETRY_ATTEMPTS8 = 3;
1491
1454
  var RETRY_DELAY_MS8 = 3e3;
1492
1455
  function buildEnhancedPrompt8(clientInput, attemptNumber) {
1493
1456
  const { quizContext, language, difficulty, imageUrl } = clientInput;
1494
- const category = (quizContext == null ? void 0 : quizContext.originalCategory) || "the specified technical category";
1457
+ const category = quizContext?.originalCategory || "the specified technical category";
1495
1458
  const attemptInfo = attemptNumber > 1 ? `
1496
1459
  ## DEBUG INFO - This is attempt #${attemptNumber}
1497
1460
  Previous attempts failed. Ensure the JSON is valid and 'correctAnswer' is a boolean.
1498
1461
 
1499
1462
  ` : "";
1500
1463
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The True/False statement must be directly related to the content of this image.` : "";
1501
- const misconceptionGuidance = (quizContext == null ? void 0 : quizContext.targetMisconception) ? `**Target Misconception:** The statement you create MUST be FALSE and based on this common mistake: "${quizContext.targetMisconception}"` : "";
1464
+ const misconceptionGuidance = quizContext?.targetMisconception ? `**Target Misconception:** The statement you create MUST be FALSE and based on this common mistake: "${quizContext.targetMisconception}"` : "";
1502
1465
  const contextStrings = [
1503
1466
  `**Required Category:** ${category}`,
1504
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
1467
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
1505
1468
  imageContextInstruction,
1506
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
1469
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
1507
1470
  misconceptionGuidance,
1508
- (quizContext == null ? void 0 : quizContext.difficultyReason) && `**Pedagogical Reason:** ${quizContext.difficultyReason}`
1471
+ quizContext?.difficultyReason && `**Pedagogical Reason:** ${quizContext.difficultyReason}`
1509
1472
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
1510
1473
  const exampleJson = JSON.stringify({
1511
1474
  prompt: "In Swift, you must explicitly unwrap an Optional value before you can use its stored value.",
@@ -1532,7 +1495,7 @@ ${contextStrings}
1532
1495
  Based on all the rules and context above, generate a single True/False Question.
1533
1496
 
1534
1497
  ### Input Parameters
1535
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
1498
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
1536
1499
  - **Language for Text:** ${language}
1537
1500
  - **Difficulty Level:** ${difficulty}
1538
1501
 
@@ -1544,7 +1507,6 @@ ${exampleJson}
1544
1507
  Now, generate the JSON for the requested question.`;
1545
1508
  }
1546
1509
  async function generateTrueFalseQuestion(clientInput, apiKey) {
1547
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
1548
1510
  const ai = new GoogleGenAI({ apiKey });
1549
1511
  const model = "gemini-2.5-flash";
1550
1512
  const config = {
@@ -1561,7 +1523,7 @@ async function generateTrueFalseQuestion(clientInput, apiKey) {
1561
1523
  const promptText = buildEnhancedPrompt8(clientInput, attempt);
1562
1524
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
1563
1525
  try {
1564
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
1526
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
1565
1527
  const parts = [{ text: promptText }];
1566
1528
  if (clientInput.imageUrl) {
1567
1529
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -1571,7 +1533,7 @@ async function generateTrueFalseQuestion(clientInput, apiKey) {
1571
1533
  const contents = [{ role: "user", parts }];
1572
1534
  const aiResult = await ai.models.generateContent({ model, config, contents });
1573
1535
  const response = aiResult;
1574
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
1536
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
1575
1537
  const duration = Date.now() - startTime;
1576
1538
  DebugLogger.logResponse(attempt, rawText);
1577
1539
  if (!rawText) throw new Error("AI returned an empty response.");
@@ -1579,11 +1541,11 @@ async function generateTrueFalseQuestion(clientInput, apiKey) {
1579
1541
  DebugLogger.logValidation(attempt, "JSON Parsed Successfully", parsedJson);
1580
1542
  const aiGeneratedContent = AITrueFalseOutputFieldsSchema.parse(parsedJson);
1581
1543
  DebugLogger.logValidation(attempt, "Zod Schema Validated", aiGeneratedContent);
1582
- if (((_f = clientInput.quizContext) == null ? void 0 : _f.targetMisconception) && aiGeneratedContent.correctAnswer === true) {
1544
+ if (clientInput.quizContext?.targetMisconception && aiGeneratedContent.correctAnswer === true) {
1583
1545
  throw new Error("AI failed to follow the Misconception Priority rule. The answer should have been false.");
1584
1546
  }
1585
- if ((_g = clientInput.quizContext) == null ? void 0 : _g.originalCategory) {
1586
- const verifiedCategory = (_h = aiGeneratedContent.verifiedCategory) == null ? void 0 : _h.toLowerCase();
1547
+ if (clientInput.quizContext?.originalCategory) {
1548
+ const verifiedCategory = aiGeneratedContent.verifiedCategory?.toLowerCase();
1587
1549
  const requiredCategory = clientInput.quizContext.originalCategory.toLowerCase();
1588
1550
  if (verifiedCategory && verifiedCategory !== requiredCategory) {
1589
1551
  throw new Error(`Category mismatch: Required ${requiredCategory}, got ${verifiedCategory}`);
@@ -1596,13 +1558,13 @@ async function generateTrueFalseQuestion(clientInput, apiKey) {
1596
1558
  correctAnswer: aiGeneratedContent.correctAnswer,
1597
1559
  explanation: aiGeneratedContent.explanation,
1598
1560
  points: aiGeneratedContent.points,
1599
- topic: aiGeneratedContent.topic || ((_i = clientInput.quizContext) == null ? void 0 : _i.originalTopic),
1561
+ topic: aiGeneratedContent.topic || clientInput.quizContext?.originalTopic,
1600
1562
  difficulty: clientInput.difficulty,
1601
- contextCode: (_j = clientInput.quizContext) == null ? void 0 : _j.plannedContextId,
1602
- bloomLevel: (_k = clientInput.quizContext) == null ? void 0 : _k.plannedBloomLevel,
1603
- learningObjective: (_l = clientInput.quizContext) == null ? void 0 : _l.originalLoId,
1604
- subject: (_m = clientInput.quizContext) == null ? void 0 : _m.originalSubject,
1605
- category: (_n = clientInput.quizContext) == null ? void 0 : _n.originalCategory,
1563
+ contextCode: clientInput.quizContext?.plannedContextId,
1564
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
1565
+ learningObjective: clientInput.quizContext?.originalLoId,
1566
+ subject: clientInput.quizContext?.originalSubject,
1567
+ category: clientInput.quizContext?.originalCategory,
1606
1568
  imageUrl: clientInput.imageUrl
1607
1569
  };
1608
1570
  const validatedQuestion = TrueFalseQuestionZodSchema.parse(completeQuestion);
@@ -1624,7 +1586,7 @@ async function generateTrueFalseQuestion(clientInput, apiKey) {
1624
1586
  }
1625
1587
  }
1626
1588
  DebugLogger.logAttemptSummary(attemptResults);
1627
- const errorMessage = `Failed to generate True/False question after ${MAX_RETRY_ATTEMPTS8} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
1589
+ const errorMessage = `Failed to generate True/False question after ${MAX_RETRY_ATTEMPTS8} attempts. Last error: ${lastError?.message}`;
1628
1590
  console.error("\n\u274C Final Result: FAILED");
1629
1591
  console.error(errorMessage);
1630
1592
  return { error: errorMessage };
@@ -1672,10 +1634,10 @@ var JsonRepairEngine = class {
1672
1634
  if (breakIndex !== -1) {
1673
1635
  const stringContent = afterUnterminated.substring(0, breakIndex);
1674
1636
  const remainder = afterUnterminated.substring(breakIndex);
1675
- const escapedContent = stringContent.replace(new RegExp('(?<!\\\\)"', "g"), '\\"');
1637
+ const escapedContent = stringContent.replace(/(?<!\\)"/g, '\\"');
1676
1638
  repaired = beforeUnterminated + escapedContent + '"' + remainder;
1677
1639
  } else {
1678
- const escapedContent = afterUnterminated.replace(new RegExp('(?<!\\\\)"', "g"), '\\"');
1640
+ const escapedContent = afterUnterminated.replace(/(?<!\\)"/g, '\\"');
1679
1641
  repaired = beforeUnterminated + escapedContent + '"';
1680
1642
  }
1681
1643
  }
@@ -1751,7 +1713,6 @@ var JsonRepairEngine = class {
1751
1713
  * Main repair function that attempts multiple strategies.
1752
1714
  */
1753
1715
  static repairJson(jsonStr) {
1754
- var _a;
1755
1716
  let current = jsonStr.trim();
1756
1717
  const maxAttempts = 5;
1757
1718
  let lastError = "";
@@ -1781,7 +1742,7 @@ var JsonRepairEngine = class {
1781
1742
  }
1782
1743
  lastError = validation.error || "";
1783
1744
  lastPosition = validation.position;
1784
- if ((_a = validation.error) == null ? void 0 : _a.includes("Unterminated string")) {
1745
+ if (validation.error?.includes("Unterminated string")) {
1785
1746
  current = this.repairUnterminatedStrings(current);
1786
1747
  } else {
1787
1748
  current = this.applyCommonFixes(current);
@@ -2113,7 +2074,6 @@ ENHANCED DIVERSITY & QUALITY ASSURANCE RULES:
2113
2074
  `;
2114
2075
  }
2115
2076
  async function generateQuizPlan(clientInput, apiKey, imageContexts = []) {
2116
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2117
2077
  const logger = new QuizPlanLogger();
2118
2078
  try {
2119
2079
  logger.log("VALIDATION_START", {
@@ -2249,10 +2209,7 @@ Execute this plan with pedagogical precision. The quiz should feel like a carefu
2249
2209
  logger.log("PROMPT_PREPARATION", {
2250
2210
  promptLength: enhancedPromptText.length,
2251
2211
  topicCount: clientInput.topics.length,
2252
- misconceptionCount: clientInput.topics.reduce((sum, t) => {
2253
- var _a2;
2254
- return sum + (((_a2 = t.commonMisconceptions) == null ? void 0 : _a2.length) || 0);
2255
- }, 0)
2212
+ misconceptionCount: clientInput.topics.reduce((sum, t) => sum + (t.commonMisconceptions?.length || 0), 0)
2256
2213
  }, Date.now() - promptStartTime);
2257
2214
  const generationStartTime = Date.now();
2258
2215
  const contents = [
@@ -2273,11 +2230,11 @@ Execute this plan with pedagogical precision. The quiz should feel like a carefu
2273
2230
  const response = aiResult;
2274
2231
  const generationDuration = Date.now() - generationStartTime;
2275
2232
  logger.log("AI_GENERATION", {
2276
- responseLength: ((_f = (_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) == null ? void 0 : _f.length) || 0,
2233
+ responseLength: response.candidates?.[0]?.content?.parts?.[0]?.text?.length || 0,
2277
2234
  duration: generationDuration
2278
2235
  }, generationDuration);
2279
2236
  const processingStartTime = Date.now();
2280
- const rawText = ((_k = (_j = (_i = (_h = (_g = response.candidates) == null ? void 0 : _g[0]) == null ? void 0 : _h.content) == null ? void 0 : _i.parts) == null ? void 0 : _j[0]) == null ? void 0 : _k.text) || "";
2237
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
2281
2238
  let jsonText = rawText;
2282
2239
  if (!rawText.trim().startsWith("{") && !rawText.trim().startsWith("[")) {
2283
2240
  jsonText = extractJsonFromMarkdown(rawText);
@@ -2310,11 +2267,12 @@ Execute this plan with pedagogical precision. The quiz should feel like a carefu
2310
2267
  questionCount: aiGeneratedContent.quizPlan.length,
2311
2268
  codingQuestionCount: codingQuestions.length,
2312
2269
  maxConsecutiveType: diversityAnalysis.maxConsecutive,
2313
- questionTypeDistribution: ((_l = aiGeneratedContent.diversityMetrics) == null ? void 0 : _l.questionTypeDistribution) || {}
2270
+ questionTypeDistribution: aiGeneratedContent.diversityMetrics?.questionTypeDistribution || {}
2314
2271
  }, Date.now() - validationStartTime);
2315
- const finalResult = __spreadProps(__spreadValues({}, aiGeneratedContent), {
2272
+ const finalResult = {
2273
+ ...aiGeneratedContent,
2316
2274
  logs: logger.getLogs()
2317
- });
2275
+ };
2318
2276
  logger.log("GENERATION_COMPLETE", {
2319
2277
  totalDuration: logger.getTotalDuration(),
2320
2278
  success: true,
@@ -2323,8 +2281,8 @@ Execute this plan with pedagogical precision. The quiz should feel like a carefu
2323
2281
  console.log("\n=== QUIZ PLAN GENERATION SUMMARY ===");
2324
2282
  console.log(`\u2705 Successfully generated ${finalResult.quizPlan.length} questions`);
2325
2283
  console.log(`\u23F1\uFE0F Total generation time: ${logger.getTotalDuration()}ms`);
2326
- console.log(`\u{1F3AF} Question types: ${Object.keys(((_m = finalResult.diversityMetrics) == null ? void 0 : _m.questionTypeDistribution) || {}).join(", ")}`);
2327
- console.log(`\u{1F9E0} Bloom levels: ${Object.keys(((_n = finalResult.diversityMetrics) == null ? void 0 : _n.bloomLevelDistribution) || {}).join(", ")}`);
2284
+ console.log(`\u{1F3AF} Question types: ${Object.keys(finalResult.diversityMetrics?.questionTypeDistribution || {}).join(", ")}`);
2285
+ console.log(`\u{1F9E0} Bloom levels: ${Object.keys(finalResult.diversityMetrics?.bloomLevelDistribution || {}).join(", ")}`);
2328
2286
  if (numCodingQuestions > 0) {
2329
2287
  console.log(`\u{1F4BB} Coding questions: ${codingQuestions.length}/${numCodingQuestions} required`);
2330
2288
  }
@@ -2343,12 +2301,11 @@ Execute this plan with pedagogical precision. The quiz should feel like a carefu
2343
2301
  }
2344
2302
  }
2345
2303
  function validateConsecutiveTypes(quizPlan) {
2346
- var _a, _b;
2347
2304
  let maxConsecutive = 1;
2348
- let maxType = ((_a = quizPlan[0]) == null ? void 0 : _a.plannedQuestionType) || "";
2305
+ let maxType = quizPlan[0]?.plannedQuestionType || "";
2349
2306
  let maxStartIndex = 0;
2350
2307
  let currentConsecutive = 1;
2351
- let currentType = ((_b = quizPlan[0]) == null ? void 0 : _b.plannedQuestionType) || "";
2308
+ let currentType = quizPlan[0]?.plannedQuestionType || "";
2352
2309
  let currentStartIndex = 0;
2353
2310
  for (let i = 1; i < quizPlan.length; i++) {
2354
2311
  if (quizPlan[i].plannedQuestionType === currentType) {
@@ -2546,7 +2503,10 @@ var AICodingQuestionOutputSchema = z.object({
2546
2503
  solutionCode: z.string().describe("A complete, correct model solution in the specified language."),
2547
2504
  testCases: z.array(z.object({
2548
2505
  input: z.array(z.any()),
2549
- expectedOutput: z.any().describe("The expected output for this test case - REQUIRED"),
2506
+ // FIX: Use .refine to make it explicitly non-optional for TypeScript's inference
2507
+ expectedOutput: z.any().refine((val) => val !== void 0, {
2508
+ message: "expectedOutput is required and cannot be undefined."
2509
+ }),
2550
2510
  isPublic: z.boolean()
2551
2511
  })).min(3, { message: "Must provide at least 3 test cases." }),
2552
2512
  verifiedCodingLanguage: z.enum(["cpp", "javascript", "python", "swift", "csharp"]).optional().describe("The programming language this question actually addresses.")
@@ -2557,19 +2517,19 @@ var MAX_RETRY_ATTEMPTS9 = 3;
2557
2517
  var RETRY_DELAY_MS9 = 3e3;
2558
2518
  function buildEnhancedPrompt9(clientInput, attemptNumber) {
2559
2519
  const { quizContext, difficulty, codingLanguage, language, imageUrl } = clientInput;
2560
- const subject = (quizContext == null ? void 0 : quizContext.originalSubject) || codingLanguage;
2520
+ const subject = quizContext?.originalSubject || codingLanguage;
2561
2521
  const attemptInfo = attemptNumber > 1 ? `
2562
2522
  ## DEBUG INFO - This is attempt #${attemptNumber}
2563
- Previous attempts failed. Pay strict attention to the JSON schema and all rules.
2523
+ Previous attempts failed. Pay strict attention to the JSON schema and all rules. Ensure every object in the 'testCases' array has a non-null 'expectedOutput' field.
2564
2524
 
2565
2525
  ` : "";
2566
2526
  const imageContextInstruction = imageUrl ? `**Image Context:** You MUST analyze the provided image. The coding problem must be directly related to processing or interpreting the content of this image.` : "";
2567
2527
  const contextStrings = [
2568
2528
  `**Subject:** ${subject}`,
2569
- (quizContext == null ? void 0 : quizContext.loDescription) && `**Learning Objective:** ${quizContext.loDescription}`,
2529
+ quizContext?.loDescription && `**Learning Objective:** ${quizContext.loDescription}`,
2570
2530
  imageContextInstruction,
2571
- (quizContext == null ? void 0 : quizContext.plannedBloomLevel) && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
2572
- (quizContext == null ? void 0 : quizContext.targetMisconception) && `**Target Misconception:** The problem should test against this common error: "${quizContext.targetMisconception}"`
2531
+ quizContext?.plannedBloomLevel && `**Cognitive Level (Bloom's):** ${quizContext.plannedBloomLevel}`,
2532
+ quizContext?.targetMisconception && `**Target Misconception:** The problem should test against this common error: "${quizContext.targetMisconception}"`
2573
2533
  ].filter(Boolean).map((s) => `- ${s}`).join("\n");
2574
2534
  const exampleJson = JSON.stringify({
2575
2535
  prompt: "Write a function named 'add' that takes two integers and returns their sum.",
@@ -2589,13 +2549,14 @@ Generate a single, high-quality Coding question.
2589
2549
  1. **Language Purity:** All code ('functionSignature', 'solutionCode') MUST be in **${codingLanguage}**.
2590
2550
  2. **Context Adherence:** The problem MUST be directly related to the provided context.
2591
2551
  3. **Format Integrity:** You MUST return ONLY a single, valid JSON object.
2552
+ 4. **Test Case Integrity:** Every test case object in the 'testCases' array MUST have a non-null and defined 'expectedOutput' field. This is a critical rule.
2592
2553
 
2593
2554
  ## CRITICAL CONTEXT FOR THIS QUESTION
2594
2555
  ${contextStrings}
2595
2556
 
2596
2557
  ## Task: Generate the Question
2597
2558
  ### Input Parameters
2598
- - **Topic for Question:** ${(quizContext == null ? void 0 : quizContext.plannedTopic) || "General"}
2559
+ - **Topic for Question:** ${quizContext?.plannedTopic || "General"}
2599
2560
  - **Natural Language for Text:** ${language}
2600
2561
  - **Coding Language:** ${codingLanguage}
2601
2562
  - **Difficulty Level:** ${difficulty}
@@ -2608,7 +2569,6 @@ ${exampleJson}
2608
2569
  Now, generate the JSON for the requested question.`;
2609
2570
  }
2610
2571
  async function generateCodingQuestion(clientInput, apiKey) {
2611
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2612
2572
  const ai = new GoogleGenAI({ apiKey });
2613
2573
  const model = "gemini-2.5-flash";
2614
2574
  const config = {
@@ -2625,7 +2585,7 @@ async function generateCodingQuestion(clientInput, apiKey) {
2625
2585
  const promptText = buildEnhancedPrompt9(clientInput, attempt);
2626
2586
  const promptHash = Buffer.from(promptText).toString("base64").slice(0, 10);
2627
2587
  try {
2628
- DebugLogger.logPrompt(attempt, promptText, __spreadProps(__spreadValues({}, clientInput), { attemptNumber: attempt, promptHash }));
2588
+ DebugLogger.logPrompt(attempt, promptText, { ...clientInput, attemptNumber: attempt, promptHash });
2629
2589
  const parts = [{ text: promptText }];
2630
2590
  if (clientInput.imageUrl) {
2631
2591
  const mimeType = clientInput.imageUrl.endsWith(".png") ? "image/png" : "image/jpeg";
@@ -2635,7 +2595,7 @@ async function generateCodingQuestion(clientInput, apiKey) {
2635
2595
  const contents = [{ role: "user", parts }];
2636
2596
  const aiResult = await ai.models.generateContent({ model, config, contents });
2637
2597
  const response = aiResult;
2638
- const rawText = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
2598
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
2639
2599
  const duration = Date.now() - startTime;
2640
2600
  DebugLogger.logResponse(attempt, rawText);
2641
2601
  if (!rawText) throw new Error("AI returned an empty response.");
@@ -2646,42 +2606,36 @@ async function generateCodingQuestion(clientInput, apiKey) {
2646
2606
  if (aiGeneratedContent.verifiedCodingLanguage && aiGeneratedContent.verifiedCodingLanguage !== clientInput.codingLanguage) {
2647
2607
  throw new Error(`Language mismatch: Required ${clientInput.codingLanguage}, but AI generated for ${aiGeneratedContent.verifiedCodingLanguage}.`);
2648
2608
  }
2649
- const testCases = aiGeneratedContent.testCases.map((tc) => {
2650
- if (tc.expectedOutput === void 0) {
2651
- throw new Error("A test case from AI is missing the required 'expectedOutput' field.");
2652
- }
2653
- return {
2654
- id: generateUniqueId("tc_"),
2655
- input: tc.input,
2656
- expectedOutput: tc.expectedOutput,
2657
- isPublic: tc.isPublic
2658
- };
2659
- });
2609
+ const testCases = aiGeneratedContent.testCases.map((tc) => ({
2610
+ id: generateUniqueId("tc_"),
2611
+ input: tc.input,
2612
+ expectedOutput: tc.expectedOutput,
2613
+ isPublic: tc.isPublic
2614
+ }));
2660
2615
  const completeQuestion = {
2661
2616
  id: generateUniqueId("coding_"),
2662
2617
  questionType: "coding",
2663
2618
  prompt: aiGeneratedContent.prompt,
2664
2619
  codingLanguage: clientInput.codingLanguage,
2665
- // FIXED: Correct field name
2666
2620
  functionSignature: aiGeneratedContent.functionSignature,
2667
2621
  solutionCode: aiGeneratedContent.solutionCode,
2668
2622
  testCases,
2669
2623
  points: 25,
2670
- topic: (_f = clientInput.quizContext) == null ? void 0 : _f.originalTopic,
2624
+ topic: clientInput.quizContext?.originalTopic,
2671
2625
  difficulty: clientInput.difficulty,
2672
- contextCode: (_g = clientInput.quizContext) == null ? void 0 : _g.plannedContextId,
2673
- bloomLevel: (_h = clientInput.quizContext) == null ? void 0 : _h.plannedBloomLevel,
2674
- learningObjective: (_i = clientInput.quizContext) == null ? void 0 : _i.originalLoId,
2675
- subject: (_j = clientInput.quizContext) == null ? void 0 : _j.originalSubject,
2676
- category: (_k = clientInput.quizContext) == null ? void 0 : _k.originalCategory,
2626
+ contextCode: clientInput.quizContext?.plannedContextId,
2627
+ bloomLevel: clientInput.quizContext?.plannedBloomLevel,
2628
+ learningObjective: clientInput.quizContext?.originalLoId,
2629
+ subject: clientInput.quizContext?.originalSubject,
2630
+ category: clientInput.quizContext?.originalCategory,
2677
2631
  imageUrl: clientInput.imageUrl
2678
2632
  };
2679
- const validatedQuestion = CodingQuestionZodSchema.parse(completeQuestion);
2633
+ CodingQuestionZodSchema.parse(completeQuestion);
2680
2634
  attemptResults.push({ success: true, duration, promptLength: promptText.length, responseLength: rawText.length, promptHash });
2681
2635
  console.log(`
2682
2636
  \u2705 Coding question generation successful on attempt ${attempt} (${duration}ms)`);
2683
2637
  if (attempt > 1) DebugLogger.logAttemptSummary(attemptResults);
2684
- return { question: validatedQuestion };
2638
+ return { question: completeQuestion };
2685
2639
  } catch (error) {
2686
2640
  lastError = error;
2687
2641
  const duration = Date.now() - startTime;
@@ -2695,7 +2649,7 @@ async function generateCodingQuestion(clientInput, apiKey) {
2695
2649
  }
2696
2650
  }
2697
2651
  DebugLogger.logAttemptSummary(attemptResults);
2698
- const errorMessage = `Failed to generate Coding question after ${MAX_RETRY_ATTEMPTS9} attempts. Last error: ${lastError == null ? void 0 : lastError.message}`;
2652
+ const errorMessage = `Failed to generate Coding question after ${MAX_RETRY_ATTEMPTS9} attempts. Last error: ${lastError?.message}`;
2699
2653
  console.error("\n\u274C Final Result: FAILED");
2700
2654
  console.error(errorMessage);
2701
2655
  return { error: errorMessage };
@@ -2734,7 +2688,6 @@ var calculateCombinedDifficulty = (plannedQ) => {
2734
2688
  return "hard";
2735
2689
  };
2736
2690
  async function generateQuestionsFromQuizPlan(clientInput, apiKey) {
2737
- var _a, _b;
2738
2691
  const { quizPlan, language, imageContexts } = clientInput;
2739
2692
  const generatedQuestions = [];
2740
2693
  const errors = [];
@@ -2758,9 +2711,9 @@ async function generateQuestionsFromQuizPlan(clientInput, apiKey) {
2758
2711
  originalSubject: plannedQ.originalSubject,
2759
2712
  originalCategory: plannedQ.originalCategory,
2760
2713
  originalTopic: plannedQ.originalTopic,
2761
- loDescription: (fullLO == null ? void 0 : fullLO.loDescription) || plannedQ.plannedTopic
2714
+ loDescription: fullLO?.loDescription || plannedQ.plannedTopic
2762
2715
  };
2763
- const imageUrl = plannedQ.imageId && imageContexts ? (_a = imageContexts.find((ctx) => ctx.id === plannedQ.imageId)) == null ? void 0 : _a.imageUrl : void 0;
2716
+ const imageUrl = plannedQ.imageId && imageContexts ? imageContexts.find((ctx) => ctx.id === plannedQ.imageId)?.imageUrl : void 0;
2764
2717
  const baseClientInput = {
2765
2718
  language,
2766
2719
  difficulty: calculateCombinedDifficulty(plannedQ),
@@ -2773,35 +2726,36 @@ async function generateQuestionsFromQuizPlan(clientInput, apiKey) {
2773
2726
  result = await generateTrueFalseQuestion(baseClientInput, apiKey);
2774
2727
  break;
2775
2728
  case "multiple_choice":
2776
- result = await generateMCQQuestion(__spreadProps(__spreadValues({}, baseClientInput), { numberOfOptions: 4 }), apiKey);
2729
+ result = await generateMCQQuestion({ ...baseClientInput, numberOfOptions: 4 }, apiKey);
2777
2730
  break;
2778
2731
  case "multiple_response":
2779
- result = await generateMRQQuestion(__spreadProps(__spreadValues({}, baseClientInput), { numberOfOptions: 5, minCorrectAnswers: 2, maxCorrectAnswers: 3 }), apiKey);
2732
+ result = await generateMRQQuestion({ ...baseClientInput, numberOfOptions: 5, minCorrectAnswers: 2, maxCorrectAnswers: 3 }, apiKey);
2780
2733
  break;
2781
2734
  case "short_answer":
2782
- result = await generateShortAnswerQuestion(__spreadProps(__spreadValues({}, baseClientInput), { isCaseSensitive: false }), apiKey);
2735
+ result = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive: false }, apiKey);
2783
2736
  break;
2784
2737
  case "numeric":
2785
- result = await generateNumericQuestion(__spreadProps(__spreadValues({}, baseClientInput), { allowDecimals: true, tolerance: 0 }), apiKey);
2738
+ result = await generateNumericQuestion({ ...baseClientInput, allowDecimals: true, tolerance: 0 }, apiKey);
2786
2739
  break;
2787
2740
  case "fill_in_the_blanks":
2788
- result = await generateFillInTheBlanksQuestion(__spreadProps(__spreadValues({}, baseClientInput), { numberOfBlanks: 2, isCaseSensitive: false }), apiKey);
2741
+ result = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks: 2, isCaseSensitive: false }, apiKey);
2789
2742
  break;
2790
2743
  case "sequence":
2791
- result = await generateSequenceQuestion(__spreadProps(__spreadValues({}, baseClientInput), { numberOfItems: 4 }), apiKey);
2744
+ result = await generateSequenceQuestion({ ...baseClientInput, numberOfItems: 4 }, apiKey);
2792
2745
  break;
2793
2746
  case "matching":
2794
- result = await generateMatchingQuestion(__spreadProps(__spreadValues({}, baseClientInput), { numberOfPairs: 4, shuffleOptions: true }), apiKey);
2747
+ result = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs: 4, shuffleOptions: true }, apiKey);
2795
2748
  break;
2796
2749
  case "coding": {
2797
- const subject = ((_b = plannedQ.originalSubject) == null ? void 0 : _b.toLowerCase()) || "";
2750
+ const subject = plannedQ.originalSubject?.toLowerCase() || "";
2798
2751
  let codingLanguage = "javascript";
2799
2752
  if (subject.includes("swift")) codingLanguage = "swift";
2800
2753
  else if (subject.includes("python")) codingLanguage = "python";
2801
- result = await generateCodingQuestion(__spreadProps(__spreadValues({}, baseClientInput), {
2754
+ result = await generateCodingQuestion({
2755
+ ...baseClientInput,
2802
2756
  codingLanguage,
2803
- displayLanguage: language || "English"
2804
- }), apiKey);
2757
+ language: language || "English"
2758
+ }, apiKey);
2805
2759
  break;
2806
2760
  }
2807
2761
  default:
@@ -3538,19 +3492,17 @@ Now, generate the JSON response.`;
3538
3492
  console.warn(`Skipping MCQ due to invalid correctTempOptionId: ${correctTempId}`);
3539
3493
  continue;
3540
3494
  }
3541
- finalQuestion = __spreadProps(__spreadValues({}, rawQuestion), {
3495
+ finalQuestion = {
3496
+ ...rawQuestion,
3542
3497
  id: questionId,
3543
- options: finalOptions.map((_a) => {
3544
- var _b = _a, { tempId } = _b, rest = __objRest(_b, ["tempId"]);
3545
- return rest;
3546
- }),
3498
+ options: finalOptions.map(({ tempId, ...rest }) => rest),
3547
3499
  correctAnswerId: correctFinalOption.id
3548
- });
3500
+ };
3549
3501
  break;
3550
3502
  }
3551
3503
  case "true_false":
3552
3504
  case "short_answer": {
3553
- finalQuestion = __spreadProps(__spreadValues({}, rawQuestion), { id: questionId });
3505
+ finalQuestion = { ...rawQuestion, id: questionId };
3554
3506
  break;
3555
3507
  }
3556
3508
  default: