@thanh01.pmt/interactive-quiz-kit 1.0.31 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react-ui.mjs CHANGED
@@ -1,15 +1,13 @@
1
1
  import * as React162 from 'react';
2
2
  import React162__default, { createContext, forwardRef, createElement, useRef, useState, useImperativeHandle, useCallback, useEffect, useLayoutEffect, useContext, useMemo, cloneElement, isValidElement, Children, useTransition, PureComponent, Component as Component$1, memo, Suspense, useReducer } from 'react';
3
3
  import { z } from 'zod';
4
- import { genkit } from 'genkit';
5
- import { gemini20Flash, googleAI } from '@genkit-ai/googleai';
4
+ import { GoogleGenAI } from '@google/genai';
6
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
6
  import * as ReactDOM4 from 'react-dom';
8
7
  import ReactDOM4__default, { unstable_batchedUpdates, createPortal } from 'react-dom';
9
8
  import default2 from 'path';
10
9
  import default3 from 'process';
11
10
  import { fileURLToPath } from 'url';
12
- import { GoogleGenAI } from '@google/genai';
13
11
  import JSZip from 'jszip';
14
12
  import { useRouter } from 'next/navigation';
15
13
 
@@ -7836,10 +7834,7 @@ var EvaluateUserCodeOutputSchema = AIEvaluationOutputSchema;
7836
7834
  // src/ai/flows/evaluate-user-code.ts
7837
7835
  async function evaluateUserCode(clientInput, apiKey) {
7838
7836
  try {
7839
- const ai = genkit({
7840
- plugins: [googleAI({ apiKey })],
7841
- model: gemini20Flash
7842
- });
7837
+ const genAI = new GoogleGenAI({ apiKey });
7843
7838
  const { language: language3, problemPrompt, userCode, testCase } = clientInput;
7844
7839
  const promptText = `
7845
7840
  You are an expert Code Judge and Teaching Assistant for a ${language3} programming course.
@@ -7876,8 +7871,17 @@ Return ONLY the JSON object with this EXACT structure.
7876
7871
  \`\`\`
7877
7872
 
7878
7873
  Return only the JSON response.`;
7879
- const response = await ai.generate(promptText);
7880
- const rawText = response.text;
7874
+ const modelName = "gemini-1.5-flash";
7875
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
7876
+ const result = await genAI.models.generateContent({
7877
+ model: modelName,
7878
+ contents
7879
+ });
7880
+ const response = result;
7881
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
7882
+ if (!rawText) {
7883
+ throw new Error("AI returned an empty response.");
7884
+ }
7881
7885
  const jsonText = extractJsonFromMarkdown(rawText);
7882
7886
  const aiGeneratedContent = JSON.parse(jsonText);
7883
7887
  return EvaluateUserCodeOutputSchema.parse(aiGeneratedContent);
@@ -128421,109 +128425,6 @@ function QuestionFilters({
128421
128425
  }
128422
128426
  ), /* @__PURE__ */ React162__default.createElement(Select2, { value: subjectCode || ALL_ITEMS_VALUE, onValueChange: createSelectHandler(setSubjectCode) }, /* @__PURE__ */ React162__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React162__default.createElement(SelectValue2, { placeholder: "Subject" })), /* @__PURE__ */ React162__default.createElement(SelectContent2, null, /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: ALL_ITEMS_VALUE }, "All Subjects"), subjects.map((s4) => /* @__PURE__ */ React162__default.createElement(SelectItem2, { key: s4.code, value: s4.code }, s4.name)))), /* @__PURE__ */ React162__default.createElement(Select2, { value: topicCode || ALL_ITEMS_VALUE, onValueChange: createSelectHandler(setTopicCode), disabled: !subjectCode || filteredTopics.length === 0 }, /* @__PURE__ */ React162__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React162__default.createElement(SelectValue2, { placeholder: "Topic" })), /* @__PURE__ */ React162__default.createElement(SelectContent2, null, /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: ALL_ITEMS_VALUE }, "All Topics"), filteredTopics.map((t4) => /* @__PURE__ */ React162__default.createElement(SelectItem2, { key: t4.code, value: t4.code }, t4.name)))), /* @__PURE__ */ React162__default.createElement(Select2, { value: gradeLevelCode || ALL_ITEMS_VALUE, onValueChange: createSelectHandler(setGradeLevelCode) }, /* @__PURE__ */ React162__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React162__default.createElement(SelectValue2, { placeholder: "Grade Level" })), /* @__PURE__ */ React162__default.createElement(SelectContent2, null, /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: ALL_ITEMS_VALUE }, "All Grade Levels"), gradeLevels.map((gl) => /* @__PURE__ */ React162__default.createElement(SelectItem2, { key: gl.code, value: gl.code }, gl.name)))), /* @__PURE__ */ React162__default.createElement(Select2, { value: bloomLevelCode || ALL_ITEMS_VALUE, onValueChange: createSelectHandler(setBloomLevelCode) }, /* @__PURE__ */ React162__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React162__default.createElement(SelectValue2, { placeholder: "Bloom's Level" })), /* @__PURE__ */ React162__default.createElement(SelectContent2, null, /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: ALL_ITEMS_VALUE }, "All Levels"), bloomLevels.map((bl) => /* @__PURE__ */ React162__default.createElement(SelectItem2, { key: bl.code, value: bl.code }, bl.name)))), /* @__PURE__ */ React162__default.createElement(Select2, { value: questionTypeCode || ALL_ITEMS_VALUE, onValueChange: createSelectHandler(setQuestionTypeCode) }, /* @__PURE__ */ React162__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React162__default.createElement(SelectValue2, { placeholder: "Question Type" })), /* @__PURE__ */ React162__default.createElement(SelectContent2, null, /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: ALL_ITEMS_VALUE }, "All Types"), questionTypes.map((qt) => /* @__PURE__ */ React162__default.createElement(SelectItem2, { key: qt.code, value: qt.code }, qt.name)))), /* @__PURE__ */ React162__default.createElement(Select2, { value: difficulty || ALL_ITEMS_VALUE, onValueChange: createSelectHandler(setDifficulty) }, /* @__PURE__ */ React162__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React162__default.createElement(SelectValue2, { placeholder: "Difficulty" })), /* @__PURE__ */ React162__default.createElement(SelectContent2, null, /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: ALL_ITEMS_VALUE }, "All Difficulties"), /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: "easy" }, "Easy"), /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: "medium" }, "Medium"), /* @__PURE__ */ React162__default.createElement(SelectItem2, { value: "hard" }, "Hard"))), /* @__PURE__ */ React162__default.createElement("div", { className: "flex gap-2 col-span-full sm:col-span-1 xl:col-span-2 xl:col-start-6" }, /* @__PURE__ */ React162__default.createElement(Button, { onClick: handleApplyFilters, className: "w-full sm:w-auto flex-grow" }, /* @__PURE__ */ React162__default.createElement(Search, { className: "mr-2 h-4 w-4" }), " Apply"), /* @__PURE__ */ React162__default.createElement(Button, { onClick: handleClearFilters, variant: "outline", className: "w-full sm:w-auto flex-grow" }, /* @__PURE__ */ React162__default.createElement(CircleX, { className: "mr-2 h-4 w-4" }), " Clear"))));
128423
128427
  }
128424
-
128425
- // src/services/questionBankService.ts
128426
- var LocalStorageManager2 = class {
128427
- constructor(key) {
128428
- this.key = key;
128429
- }
128430
- getAll() {
128431
- if (typeof window === "undefined") return [];
128432
- try {
128433
- const stored = localStorage.getItem(this.key);
128434
- return stored ? JSON.parse(stored) : [];
128435
- } catch (e3) {
128436
- console.error(`Error reading from localStorage key ${this.key}:`, e3);
128437
- return [];
128438
- }
128439
- }
128440
- saveAll(items) {
128441
- if (typeof window === "undefined") return;
128442
- try {
128443
- localStorage.setItem(this.key, JSON.stringify(items));
128444
- } catch (e3) {
128445
- console.error(`Error writing to localStorage key ${this.key}:`, e3);
128446
- }
128447
- }
128448
- };
128449
- var questionBankManager = new LocalStorageManager2("iqk_question_bank");
128450
- var QuestionBankService = class {
128451
- static getQuestions(filters) {
128452
- let questions = questionBankManager.getAll();
128453
- if (filters) {
128454
- if (filters.subjectCode) {
128455
- questions = questions.filter((q2) => q2.subjectCode === filters.subjectCode);
128456
- }
128457
- if (filters.topicCode) {
128458
- questions = questions.filter((q2) => q2.topicCode === filters.topicCode);
128459
- }
128460
- if (filters.gradeLevelCode) {
128461
- questions = questions.filter((q2) => q2.gradeLevelCode === filters.gradeLevelCode);
128462
- }
128463
- if (filters.bloomLevelCode) {
128464
- questions = questions.filter((q2) => q2.bloomLevelCode === filters.bloomLevelCode);
128465
- }
128466
- if (filters.questionTypeCode) {
128467
- questions = questions.filter((q2) => q2.questionTypeCode === filters.questionTypeCode);
128468
- }
128469
- if (filters.difficulty) {
128470
- questions = questions.filter((q2) => q2.difficulty === filters.difficulty);
128471
- }
128472
- if (filters.searchTerm) {
128473
- const lowercasedTerm = filters.searchTerm.toLowerCase();
128474
- questions = questions.filter(
128475
- (q2) => q2.text.toLowerCase().includes(lowercasedTerm) || q2.code.toLowerCase().includes(lowercasedTerm)
128476
- );
128477
- }
128478
- }
128479
- return questions.sort((a4, b2) => new Date(b2.lastModified).getTime() - new Date(a4.lastModified).getTime());
128480
- }
128481
- static getQuestionByCode(code4) {
128482
- return questionBankManager.getAll().find((q2) => q2.code === code4);
128483
- }
128484
- // CHANGE 2: Simplified function signature. It now takes the full object to be added.
128485
- static addQuestion(questionData) {
128486
- const allQuestions = questionBankManager.getAll();
128487
- if (allQuestions.some((q2) => q2.code === questionData.code)) {
128488
- throw new Error(`A question with code "${questionData.code}" already exists.`);
128489
- }
128490
- const newQuestion = {
128491
- ...questionData,
128492
- id: generateUniqueId("qb_"),
128493
- lastModified: (/* @__PURE__ */ new Date()).toISOString()
128494
- };
128495
- questionBankManager.saveAll([...allQuestions, newQuestion]);
128496
- return newQuestion;
128497
- }
128498
- // CHANGE 2: Simplified function signature.
128499
- static updateQuestion(id3, updates) {
128500
- const allQuestions = questionBankManager.getAll();
128501
- const index3 = allQuestions.findIndex((q2) => q2.id === id3);
128502
- if (index3 === -1) {
128503
- console.warn(`Question with id "${id3}" not found for update.`);
128504
- return null;
128505
- }
128506
- const updatedQuestion = {
128507
- ...allQuestions[index3],
128508
- ...updates,
128509
- lastModified: (/* @__PURE__ */ new Date()).toISOString()
128510
- };
128511
- allQuestions[index3] = updatedQuestion;
128512
- questionBankManager.saveAll(allQuestions);
128513
- return updatedQuestion;
128514
- }
128515
- static deleteQuestionByCode(code4) {
128516
- const allQuestions = questionBankManager.getAll();
128517
- const newQuestions = allQuestions.filter((q2) => q2.code !== code4);
128518
- if (allQuestions.length === newQuestions.length) {
128519
- return false;
128520
- }
128521
- questionBankManager.saveAll(newQuestions);
128522
- return true;
128523
- }
128524
- };
128525
-
128526
- // src/react-ui/components/authoring/QuestionFormDialog.tsx
128527
128428
  function QuestionFormDialog({
128528
128429
  isOpen,
128529
128430
  onOpenChange,
@@ -128608,9 +128509,11 @@ function QuestionFormDialog({
128608
128509
  toast2({ title: "Validation Error", description: "Question content is missing. Please create or edit the question details.", variant: "destructive" });
128609
128510
  return;
128610
128511
  }
128611
- startTransition(() => {
128512
+ startTransition(async () => {
128612
128513
  try {
128613
128514
  const finalDataPayload = {
128515
+ id: questionToEdit?.id || "",
128516
+ // Will be ignored for new items, used for updates
128614
128517
  code: code4,
128615
128518
  text: questionConfig.prompt.replace(/<[^>]*>?/gm, "").substring(0, 200),
128616
128519
  subjectCode,
@@ -128619,6 +128522,8 @@ function QuestionFormDialog({
128619
128522
  bloomLevelCode,
128620
128523
  questionTypeCode: questionConfig.questionType,
128621
128524
  difficulty: questionConfig.difficulty,
128525
+ lastModified: (/* @__PURE__ */ new Date()).toISOString(),
128526
+ // This will be set by the saving service
128622
128527
  questionConfig: {
128623
128528
  ...questionConfig,
128624
128529
  subject: subjectCode,
@@ -128627,14 +128532,7 @@ function QuestionFormDialog({
128627
128532
  bloomLevel: bloomLevelCode
128628
128533
  }
128629
128534
  };
128630
- if (questionToEdit) {
128631
- QuestionBankService.updateQuestion(questionToEdit.id, finalDataPayload);
128632
- toast2({ title: "Success", description: "Question updated." });
128633
- } else {
128634
- QuestionBankService.addQuestion(finalDataPayload);
128635
- toast2({ title: "Success", description: "Question added." });
128636
- }
128637
- onSave();
128535
+ await onSave(finalDataPayload);
128638
128536
  onOpenChange(false);
128639
128537
  } catch (error) {
128640
128538
  toast2({ title: "Error", description: error.message || "Failed to save question.", variant: "destructive" });
@@ -133475,10 +133373,7 @@ var AIQuizReviewOutputSchema = z.object({
133475
133373
  // src/ai/flows/generate-quiz-review.ts
133476
133374
  async function generateQuizReview(clientInput, apiKey) {
133477
133375
  try {
133478
- const ai = genkit({
133479
- plugins: [googleAI({ apiKey })],
133480
- model: gemini20Flash
133481
- });
133376
+ const genAI = new GoogleGenAI({ apiKey });
133482
133377
  const resultsString = JSON.stringify(clientInput.questionResults, null, 2);
133483
133378
  const promptText = `
133484
133379
  You are an expert educational tutor. Your task is to analyze a student's quiz results and provide a detailed, helpful review in ${clientInput.language}.
@@ -133515,8 +133410,17 @@ Return a single, valid JSON object with this EXACT format.
133515
133410
  \`\`\`
133516
133411
 
133517
133412
  Return only the valid JSON response.`;
133518
- const response = await ai.generate(promptText);
133519
- const rawText = response.text;
133413
+ const modelName = "gemini-1.5-flash";
133414
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
133415
+ const result = await genAI.models.generateContent({
133416
+ model: modelName,
133417
+ contents
133418
+ });
133419
+ const response = result;
133420
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
133421
+ if (!rawText) {
133422
+ throw new Error("AI returned an empty response.");
133423
+ }
133520
133424
  const jsonText = extractJsonFromMarkdown(rawText);
133521
133425
  const aiGeneratedContent = JSON.parse(jsonText);
133522
133426
  const validatedOutput = AIQuizReviewOutputSchema.parse(aiGeneratedContent);
@@ -133581,10 +133485,7 @@ var LearningAnalysisOutputSchema = z.object({
133581
133485
  // src/ai/flows/generate-learning-analysis.ts
133582
133486
  async function generateLearningAnalysis(clientInput, apiKey) {
133583
133487
  try {
133584
- const ai = genkit({
133585
- plugins: [googleAI({ apiKey })],
133586
- model: gemini20Flash
133587
- });
133488
+ const genAI = new GoogleGenAI({ apiKey });
133588
133489
  const {
133589
133490
  language: language3,
133590
133491
  userName = "learner",
@@ -133672,8 +133573,17 @@ The 'suggestedDifficulty' field MUST ALWAYS be one of these exact English string
133672
133573
  }
133673
133574
  \`\`\`
133674
133575
  `;
133675
- const response = await ai.generate(promptText);
133676
- const rawText = response.text;
133576
+ const modelName = "gemini-1.5-flash";
133577
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
133578
+ const result = await genAI.models.generateContent({
133579
+ model: modelName,
133580
+ contents
133581
+ });
133582
+ const response = result;
133583
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
133584
+ if (!rawText) {
133585
+ throw new Error("AI returned an empty response.");
133586
+ }
133677
133587
  const jsonText = extractJsonFromMarkdown(rawText);
133678
133588
  const aiGeneratedContent = JSON.parse(jsonText);
133679
133589
  const validatedOutput = LearningAnalysisOutputSchema.parse(aiGeneratedContent);
@@ -133704,10 +133614,7 @@ var GenerateMotivationalQuoteOutputSchema = z.object({
133704
133614
  // src/ai/flows/generate-motivational-quote.ts
133705
133615
  async function generateMotivationalQuote(clientInput, apiKey) {
133706
133616
  try {
133707
- const ai = genkit({
133708
- plugins: [googleAI({ apiKey })],
133709
- model: gemini20Flash
133710
- });
133617
+ const genAI = new GoogleGenAI({ apiKey });
133711
133618
  const { language: language3, userName, currentStreak, weakestTopic } = clientInput;
133712
133619
  let contextPrompt = "";
133713
133620
  if (userName) {
@@ -133740,8 +133647,17 @@ Return the response as a single, valid JSON object with this EXACT format:
133740
133647
 
133741
133648
  Return only the JSON response.`;
133742
133649
  try {
133743
- const response = await ai.generate(promptText);
133744
- const rawText = response.text;
133650
+ const modelName = "gemini-1.5-flash";
133651
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
133652
+ const result = await genAI.models.generateContent({
133653
+ model: modelName,
133654
+ contents
133655
+ });
133656
+ const response = result;
133657
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
133658
+ if (!rawText) {
133659
+ throw new Error("AI returned an empty response.");
133660
+ }
133745
133661
  const jsonText = extractJsonFromMarkdown(rawText);
133746
133662
  const aiGeneratedContent = JSON.parse(jsonText);
133747
133663
  const validatedOutput = GenerateMotivationalQuoteOutputSchema.parse(aiGeneratedContent);
@@ -133767,10 +133683,7 @@ var PlanKnowledgeCardsOutputSchema = z.object({
133767
133683
  // src/ai/flows/plan-knowledge-cards.ts
133768
133684
  async function planKnowledgeCards(clientInput, apiKey) {
133769
133685
  try {
133770
- const ai = genkit({
133771
- plugins: [googleAI({ apiKey })],
133772
- model: gemini20Flash
133773
- });
133686
+ const genAI = new GoogleGenAI({ apiKey });
133774
133687
  const { language: language3, learningObjectivesContent, overallSubject } = clientInput;
133775
133688
  const promptText = `
133776
133689
  You are an expert curriculum designer specializing in the subject of "${overallSubject}".
@@ -133790,18 +133703,28 @@ ${learningObjectivesContent}
133790
133703
 
133791
133704
  **JSON OUTPUT FORMAT:**
133792
133705
  Return a single, valid JSON object with this EXACT format:
133706
+ \`\`\`json
133793
133707
  {
133794
133708
  "concepts": [
133795
133709
  "First Concept",
133796
133710
  "Second Concept",
133797
- "Third Concept",
133798
- ...
133711
+ "Third Concept"
133799
133712
  ]
133800
133713
  }
133714
+ \`\`\`
133801
133715
 
133802
133716
  Return only the JSON response.`;
133803
- const response = await ai.generate(promptText);
133804
- const rawText = response.text;
133717
+ const modelName = "gemini-1.5-flash";
133718
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
133719
+ const result = await genAI.models.generateContent({
133720
+ model: modelName,
133721
+ contents
133722
+ });
133723
+ const response = result;
133724
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
133725
+ if (!rawText) {
133726
+ throw new Error("AI returned an empty response.");
133727
+ }
133805
133728
  const jsonText = extractJsonFromMarkdown(rawText);
133806
133729
  const aiGeneratedContent = JSON.parse(jsonText);
133807
133730
  const validatedOutput = PlanKnowledgeCardsOutputSchema.parse(aiGeneratedContent);
@@ -133828,30 +133751,48 @@ var GenerateSingleKnowledgeCardOutputSchema = z.object({
133828
133751
 
133829
133752
  // src/ai/flows/generate-single-knowledge-card.ts
133830
133753
  async function generateSingleKnowledgeCard(clientInput, apiKey) {
133831
- const ai = genkit({
133832
- plugins: [googleAI({ apiKey })],
133833
- model: gemini20Flash
133834
- });
133835
133754
  try {
133836
- const { language: language3, concept, overallSubject, fullContext } = clientInput;
133755
+ const genAI = new GoogleGenAI({ apiKey });
133756
+ const { language: language3, concept, overallSubject } = clientInput;
133837
133757
  const promptText = `
133838
- You are an expert educator for "${overallSubject}". Create content for a single knowledge card.
133839
- Target Concept: ${concept}
133840
- Instructions:
133841
- 1. Write a concise "definition" (under 40 words).
133842
- 2. Provide a practical "example" (code or real-world scenario) relevant to "${overallSubject}".
133843
- 3. All content must be in ${language3}.
133844
- 4. The 'concept' field in your output must exactly match the Target Concept.`;
133845
- const response = await ai.generate({
133846
- prompt: promptText,
133847
- output: {
133848
- schema: GenerateSingleKnowledgeCardOutputSchema
133849
- }
133758
+ You are an expert educator for "${overallSubject}". Your task is to create content for a single knowledge card based on the provided concept.
133759
+
133760
+ **Target Concept:**
133761
+ ${concept}
133762
+
133763
+ **Instructions:**
133764
+ 1. **Definition:** Write a concise definition for the concept (under 40 words).
133765
+ 2. **Example:** Provide a practical example (code or real-world scenario) relevant to "${overallSubject}".
133766
+ 3. **Language:** All content must be in ${language3}.
133767
+ 4. **Format:** You MUST return ONLY a single, valid JSON object that strictly follows the provided schema. Do not include any extra text, comments, or markdown formatting.
133768
+
133769
+ **Required JSON Output Format:**
133770
+ Your response must be ONLY the JSON object, matching this exact structure. The 'concept' field must exactly match the Target Concept provided above.
133771
+
133772
+ {
133773
+ "concept": "${concept}",
133774
+ "definition": "A concise explanation of the concept goes here, in ${language3}.",
133775
+ "example": "A practical code snippet or real-world example goes here, in ${language3}."
133776
+ }
133777
+
133778
+ Now, generate the JSON for the requested knowledge card.`;
133779
+ const modelName = "gemini-1.5-flash";
133780
+ const config3 = {
133781
+ responseMimeType: "application/json"
133782
+ };
133783
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
133784
+ const result = await genAI.models.generateContent({
133785
+ model: modelName,
133786
+ contents,
133787
+ config: config3
133850
133788
  });
133851
- const validatedOutput = response.output;
133852
- if (!validatedOutput) {
133789
+ const response = result;
133790
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
133791
+ if (!rawText) {
133853
133792
  throw new Error("AI did not return a valid structured output.");
133854
133793
  }
133794
+ const aiGeneratedContent = JSON.parse(rawText);
133795
+ const validatedOutput = GenerateSingleKnowledgeCardOutputSchema.parse(aiGeneratedContent);
133855
133796
  return validatedOutput;
133856
133797
  } catch (error) {
133857
133798
  console.error(`Error generating knowledge card for concept "${clientInput.concept}":`, error);
@@ -133887,10 +133828,7 @@ var AssessAndMapDocumentOutputSchema = z.object({
133887
133828
  // src/ai/flows/assess-and-map-document.ts
133888
133829
  async function assessAndMapDocument(clientInput, apiKey) {
133889
133830
  try {
133890
- const ai = genkit({
133891
- plugins: [googleAI({ apiKey })],
133892
- model: gemini20Flash
133893
- });
133831
+ const genAI = new GoogleGenAI({ apiKey });
133894
133832
  const { language: language3, documentContent, learningObjectives } = clientInput;
133895
133833
  const relevanceThreshold = 40;
133896
133834
  const promptText = `
@@ -133938,8 +133876,17 @@ Return a single, valid JSON object in this EXACT format. Do not include any othe
133938
133876
 
133939
133877
  If the document is not relevant at all, the "mappedLOs" array should be empty, and the "relevanceScore" should be low.
133940
133878
  `;
133941
- const response = await ai.generate(promptText);
133942
- const rawText = response.text;
133879
+ const modelName = "gemini-1.5-flash";
133880
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
133881
+ const result = await genAI.models.generateContent({
133882
+ model: modelName,
133883
+ contents
133884
+ });
133885
+ const response = result;
133886
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
133887
+ if (!rawText) {
133888
+ throw new Error("AI returned an empty response.");
133889
+ }
133943
133890
  const jsonText = extractJsonFromMarkdown(rawText);
133944
133891
  const aiGeneratedContent = JSON.parse(jsonText);
133945
133892
  const validatedOutput = AssessAndMapDocumentOutputSchema.parse(aiGeneratedContent);
@@ -133971,10 +133918,7 @@ var GenerateQuizFromTextOutputSchema = z.object({
133971
133918
  var AnyGeneratedQuestionSchema2 = GenerateQuizFromTextOutputSchema.shape.generatedQuestions.element;
133972
133919
  async function generateQuizFromText(clientInput, apiKey) {
133973
133920
  try {
133974
- const ai = genkit({
133975
- plugins: [googleAI({ apiKey })],
133976
- model: gemini20Flash
133977
- });
133921
+ const genAI = new GoogleGenAI({ apiKey });
133978
133922
  const { language: language3, documentContent, numQuestions, questionTypes } = clientInput;
133979
133923
  const allowedTypes = questionTypes || ["multiple_choice", "true_false"];
133980
133924
  const promptText = `
@@ -134028,8 +133972,17 @@ Return the response as a single JSON object with a key "generatedQuestions" cont
134028
133972
  \`\`\`
134029
133973
 
134030
133974
  Now, generate the JSON response.`;
134031
- const response = await ai.generate(promptText);
134032
- const rawText = response.text;
133975
+ const modelName = "gemini-1.5-flash";
133976
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
133977
+ const result = await genAI.models.generateContent({
133978
+ model: modelName,
133979
+ contents
133980
+ });
133981
+ const response = result;
133982
+ const rawText = response.candidates?.[0]?.content?.parts?.[0]?.text || "";
133983
+ if (!rawText) {
133984
+ throw new Error("AI returned an empty response.");
133985
+ }
134033
133986
  const jsonText = extractJsonFromMarkdown(rawText);
134034
133987
  const aiGeneratedContent = JSON.parse(jsonText);
134035
133988
  if (!aiGeneratedContent.generatedQuestions || !Array.isArray(aiGeneratedContent.generatedQuestions)) {
@@ -162947,10 +162900,7 @@ var AskTutorChatOutputSchema = z.object({
162947
162900
  // src/ai/flows/ask-tutor-chat.ts
162948
162901
  async function askTutorChat(clientInput, apiKey) {
162949
162902
  try {
162950
- const ai = genkit({
162951
- plugins: [googleAI({ apiKey })],
162952
- model: gemini20Flash
162953
- });
162903
+ const genAI = new GoogleGenAI({ apiKey });
162954
162904
  const { language: language3, currentQuestion, chatHistory, knowledgeContext } = clientInput;
162955
162905
  const historyString = chatHistory.map((msg) => `${msg.role}: ${msg.content}`).join("\n");
162956
162906
  const contextString = knowledgeContext && knowledgeContext.length > 0 ? `--- KNOWLEDGE CONTEXT ---
@@ -162977,8 +162927,14 @@ user: ${currentQuestion}
162977
162927
 
162978
162928
  **Your Response (as 'assistant'):**
162979
162929
  `;
162980
- const response = await ai.generate(promptText);
162981
- const aiResponseText = response.text.trim();
162930
+ const modelName = "gemini-1.5-flash";
162931
+ const contents = [{ role: "user", parts: [{ text: promptText }] }];
162932
+ const result = await genAI.models.generateContent({
162933
+ model: modelName,
162934
+ contents
162935
+ });
162936
+ const response = result;
162937
+ const aiResponseText = response.candidates?.[0]?.content?.parts?.[0]?.text?.trim() || "";
162982
162938
  if (!aiResponseText) {
162983
162939
  throw new Error("AI returned an empty response.");
162984
162940
  }
@@ -71,7 +71,7 @@ declare function QuestionFilters({ onFilterChange, initialFilters, }: QuestionFi
71
71
  interface QuestionFormDialogProps {
72
72
  isOpen: boolean;
73
73
  onOpenChange: (isOpen: boolean) => void;
74
- onSave: () => void;
74
+ onSave: (question: QuestionInBank) => Promise<void> | void;
75
75
  questionToEdit?: QuestionInBank | null;
76
76
  }
77
77
  declare function QuestionFormDialog({ isOpen, onOpenChange, onSave, questionToEdit, }: QuestionFormDialogProps): React__default.JSX.Element;
@@ -71,7 +71,7 @@ declare function QuestionFilters({ onFilterChange, initialFilters, }: QuestionFi
71
71
  interface QuestionFormDialogProps {
72
72
  isOpen: boolean;
73
73
  onOpenChange: (isOpen: boolean) => void;
74
- onSave: () => void;
74
+ onSave: (question: QuestionInBank) => Promise<void> | void;
75
75
  questionToEdit?: QuestionInBank | null;
76
76
  }
77
77
  declare function QuestionFormDialog({ isOpen, onOpenChange, onSave, questionToEdit, }: QuestionFormDialogProps): React__default.JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thanh01.pmt/interactive-quiz-kit",
3
- "version": "1.0.31",
3
+ "version": "1.0.33",
4
4
  "description": "A comprehensive library for creating, managing, and playing interactive quizzes, with AI generation and SCORM support.",
5
5
  "keywords": [
6
6
  "react",