@thanh01.pmt/curriculum-kit 1.0.22 → 1.1.0
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/LICENSE +21 -0
- package/dist/ai/index.cjs +13 -2
- package/dist/ai/index.cjs.map +1 -1
- package/dist/ai/index.mjs +13 -2
- package/dist/ai/index.mjs.map +1 -1
- package/dist/index.cjs +230 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -2
- package/dist/index.d.ts +20 -2
- package/dist/index.mjs +226 -30
- package/dist/index.mjs.map +1 -1
- package/dist/media/index.cjs.map +1 -1
- package/dist/media/index.mjs.map +1 -1
- package/dist/pipeline/index.cjs +13 -2
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.mjs +13 -2
- package/dist/pipeline/index.mjs.map +1 -1
- package/dist/schemas/index.cjs +13 -2
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.cts +34 -16
- package/dist/schemas/index.d.ts +34 -16
- package/dist/schemas/index.mjs +13 -2
- package/dist/schemas/index.mjs.map +1 -1
- package/dist/workflow/index.cjs +14 -2
- package/dist/workflow/index.cjs.map +1 -1
- package/dist/workflow/index.mjs +14 -2
- package/dist/workflow/index.mjs.map +1 -1
- package/package.json +21 -22
package/dist/index.cjs
CHANGED
|
@@ -2432,9 +2432,20 @@ var SessionPlanSchema = zod.z.object({
|
|
|
2432
2432
|
differentiation: zod.z.object({ bronze: zod.z.string(), silver: zod.z.string(), gold: zod.z.string() })
|
|
2433
2433
|
});
|
|
2434
2434
|
var TranslationPolicySchema = zod.z.object({
|
|
2435
|
-
policy: zod.z.enum(["after_artifact", "end_of_unit", "at_publish"]).default("
|
|
2435
|
+
policy: zod.z.enum(["after_artifact", "end_of_unit", "at_publish", "native"]).default("native"),
|
|
2436
2436
|
target_language: zod.z.string().nullable().default(null)
|
|
2437
|
-
})
|
|
2437
|
+
}).refine(
|
|
2438
|
+
(data) => {
|
|
2439
|
+
if (data.policy === "native") {
|
|
2440
|
+
return typeof data.target_language === "string" && data.target_language.trim().length > 0;
|
|
2441
|
+
}
|
|
2442
|
+
return true;
|
|
2443
|
+
},
|
|
2444
|
+
{
|
|
2445
|
+
message: "When translation policy is 'native', target_language must be a non-empty string",
|
|
2446
|
+
path: ["target_language"]
|
|
2447
|
+
}
|
|
2448
|
+
);
|
|
2438
2449
|
var CoverageReportSchema = zod.z.object({
|
|
2439
2450
|
assigned_node_ids: zod.z.array(zod.z.string()),
|
|
2440
2451
|
unassigned_node_ids: zod.z.array(zod.z.string()),
|
|
@@ -9855,6 +9866,7 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
9855
9866
|
});
|
|
9856
9867
|
return { relPath: result.relPath, context: buildExpositionContext(result.content), reused: result.reused };
|
|
9857
9868
|
}
|
|
9869
|
+
init_errors();
|
|
9858
9870
|
var asArr = (v) => Array.isArray(v) ? v : [];
|
|
9859
9871
|
var asStr = (v, dflt = "") => typeof v === "string" ? v : dflt;
|
|
9860
9872
|
var asNum = (v, dflt) => typeof v === "number" && Number.isFinite(v) ? v : dflt;
|
|
@@ -10497,7 +10509,15 @@ function extractSessionSlice(plan, lessonCode) {
|
|
|
10497
10509
|
}
|
|
10498
10510
|
function buildSessionSliceContext(plan, lessonCode) {
|
|
10499
10511
|
const s = plan.sessions.find((x) => x.id === lessonCode);
|
|
10500
|
-
if (!s)
|
|
10512
|
+
if (!s) {
|
|
10513
|
+
throw new exports.CurriculumError({
|
|
10514
|
+
errorCode: "ERR_LESSON_NOT_IN_SOT",
|
|
10515
|
+
message: `Session "${lessonCode}" not found in CURRICULUM_PLAN.json (${plan.plan_hash})`,
|
|
10516
|
+
suggestedAction: "\u0110\u1ED3ng b\u1ED9 CURRICULUM_PLAN r\u1ED3i ch\u1EA1y l\u1EA1i",
|
|
10517
|
+
retryable: false,
|
|
10518
|
+
lessonId: lessonCode
|
|
10519
|
+
});
|
|
10520
|
+
}
|
|
10501
10521
|
const lines = [];
|
|
10502
10522
|
lines.push("[SESSION SLICE (from CURRICULUM_PLAN " + plan.plan_hash + ")]");
|
|
10503
10523
|
lines.push("- Objective: " + s.prose_objective);
|
|
@@ -11064,6 +11084,80 @@ function resolveStandardsPacks(packIds) {
|
|
|
11064
11084
|
return packs;
|
|
11065
11085
|
}
|
|
11066
11086
|
|
|
11087
|
+
// src/services/languageDirective.ts
|
|
11088
|
+
function resolveTargetLanguageCode(language) {
|
|
11089
|
+
const raw = String(language || "vi").trim().toLowerCase();
|
|
11090
|
+
if (raw.startsWith("vi")) return "vi";
|
|
11091
|
+
if (raw.startsWith("en")) return "en";
|
|
11092
|
+
return raw || "vi";
|
|
11093
|
+
}
|
|
11094
|
+
function targetLanguageDisplayName(code) {
|
|
11095
|
+
const map = {
|
|
11096
|
+
vi: "Vietnamese (Ti\u1EBFng Vi\u1EC7t)",
|
|
11097
|
+
en: "English (US)"
|
|
11098
|
+
};
|
|
11099
|
+
return map[code] || code;
|
|
11100
|
+
}
|
|
11101
|
+
function buildLanguageDirective(targetLanguage) {
|
|
11102
|
+
const code = resolveTargetLanguageCode(targetLanguage);
|
|
11103
|
+
const name = targetLanguageDisplayName(code);
|
|
11104
|
+
const perLanguageExamples = {
|
|
11105
|
+
vi: `- V\xED d\u1EE5 ti\xEAu \u0111\u1EC1 b\xE0i h\u1ECDc \u0111\xFAng chu\u1EA9n: "B\xE0i 1: Kh\xE1m ph\xE1 m\u1EA1ch \u0111i\u1EC7n c\u01A1 b\u1EA3n", "B\xE0i 2: \u0110i\u1EC1u khi\u1EC3n \u0111\xE8n LED nh\u1EA5p nh\xE1y" \u2014 KH\xD4NG d\xF9ng ti\xEAu \u0111\u1EC1 ti\u1EBFng Anh.`,
|
|
11106
|
+
en: `- Example compliant lesson title: "Lesson 1: Exploring Basic Circuits" \u2014 natural, idiomatic English throughout.`
|
|
11107
|
+
};
|
|
11108
|
+
const exampleLine = perLanguageExamples[code] || "";
|
|
11109
|
+
return `MANDATORY LANGUAGE DIRECTIVE (TARGET OUTPUT LANGUAGE: ${name}):
|
|
11110
|
+
- The TARGET OUTPUT LANGUAGE for this course is ${name}. You MUST author the ENTIRE document in ${name}.
|
|
11111
|
+
- All section titles, table headers, table cells, lesson names, learning objectives, pedagogical narratives, and cognitive analyses MUST be written in natural, fluent, academic ${name}.
|
|
11112
|
+
- Technical identifiers, code keywords (e.g. setup(), loop(), pinMode()), standard protocols (I2C, SPI, UART, GPIO), and component model numbers (ESP32, Arduino Uno) remain in standard technical notation, but all surrounding explanations MUST be in ${name}.
|
|
11113
|
+
- DO NOT mix in paragraphs, tables, or titles written in any other language. Strict adherence is required.${exampleLine ? `
|
|
11114
|
+
${exampleLine}` : ""}`;
|
|
11115
|
+
}
|
|
11116
|
+
function extractSectionHeadingsFromSLC(slcMarkdown, artifactType) {
|
|
11117
|
+
if (!slcMarkdown) return {};
|
|
11118
|
+
const upperType = artifactType.trim().toUpperCase();
|
|
11119
|
+
const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
11120
|
+
for (const block of blocks) {
|
|
11121
|
+
const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
11122
|
+
if (!headerMatch) continue;
|
|
11123
|
+
const blockType = headerMatch[1].trim().toUpperCase();
|
|
11124
|
+
if (blockType === upperType || upperType.startsWith("LESSON") && blockType.startsWith("LESSON")) {
|
|
11125
|
+
const mapping = {};
|
|
11126
|
+
const lines = block.split("\n");
|
|
11127
|
+
for (const line of lines) {
|
|
11128
|
+
const trimmed = line.trim();
|
|
11129
|
+
if (trimmed.startsWith("|") && !trimmed.includes("---")) {
|
|
11130
|
+
const cells = trimmed.split("|").map((c) => c.trim()).filter((_, idx, arr) => idx > 0 && idx < arr.length - 1);
|
|
11131
|
+
if (cells.length >= 2 && !cells[0].toLowerCase().includes("canonical") && !cells[1].toLowerCase().includes("localized")) {
|
|
11132
|
+
mapping[cells[0]] = cells[1];
|
|
11133
|
+
}
|
|
11134
|
+
} else {
|
|
11135
|
+
const bullet = line.match(/^[-*]\s+([^:]+):\s+(.+)$/);
|
|
11136
|
+
if (bullet) {
|
|
11137
|
+
mapping[bullet[1].trim()] = bullet[2].trim();
|
|
11138
|
+
}
|
|
11139
|
+
}
|
|
11140
|
+
}
|
|
11141
|
+
if (Object.keys(mapping).length > 0) return mapping;
|
|
11142
|
+
}
|
|
11143
|
+
}
|
|
11144
|
+
return {};
|
|
11145
|
+
}
|
|
11146
|
+
function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi") {
|
|
11147
|
+
const headings = extractSectionHeadingsFromSLC(slcMarkdown, artifactType);
|
|
11148
|
+
if (Object.keys(headings).length === 0) {
|
|
11149
|
+
return "";
|
|
11150
|
+
}
|
|
11151
|
+
const lines = Object.entries(headings).map(
|
|
11152
|
+
([canonical, localized]) => ` - "${canonical}" -> Use Display Heading: "${localized}"`
|
|
11153
|
+
);
|
|
11154
|
+
return `MANDATORY SECTION HEADINGS FROM SECTION_LANGUAGE_CONTRACT:
|
|
11155
|
+
- The YAML frontmatter \`template_required_sections\` MUST preserve the exact English canonical keys.
|
|
11156
|
+
- In the markdown body, section headers MUST use the EXACT Localized Display Labels below (do NOT translate or paraphrase):
|
|
11157
|
+
${lines.join("\n")}
|
|
11158
|
+
- For example: if canonical section is "Computational Thinking Focus", your heading must be "## [REQUIRED] ${headings["Computational Thinking Focus"] || "Computational Thinking Focus"}".`;
|
|
11159
|
+
}
|
|
11160
|
+
|
|
11067
11161
|
// src/services/lessonProductionService.ts
|
|
11068
11162
|
var __filename2 = typeof (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) === "string" ? url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))) : "";
|
|
11069
11163
|
var _resolvedDir = __filename2 ? path3__default.default.dirname(__filename2) : typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
@@ -11105,11 +11199,44 @@ function detectProjectPedagogy(frameworkText, styleGuideText, explicitPedagogy)
|
|
|
11105
11199
|
return "5e";
|
|
11106
11200
|
}
|
|
11107
11201
|
async function getLessonMetadata(storage, projectId, lessonId) {
|
|
11108
|
-
const framework = await storage.readSotDocument(projectId, "CURRICULUM_FRAMEWORK.md") || "";
|
|
11109
11202
|
const parts = lessonId.split("_");
|
|
11110
11203
|
const unitCode = parts[0] || "U01";
|
|
11111
11204
|
const moduleCode = parts.length >= 2 ? `${parts[0]}_${parts[1]}` : `${unitCode}_M01`;
|
|
11112
11205
|
const lessonCode = lessonId;
|
|
11206
|
+
let planStr = null;
|
|
11207
|
+
try {
|
|
11208
|
+
planStr = await storage.readSotDocument(projectId, "CURRICULUM_PLAN.json") || await storage.readArtifact(projectId, "_sot/CURRICULUM_PLAN.json") || await storage.readArtifact(projectId, "CURRICULUM_PLAN.json");
|
|
11209
|
+
} catch {
|
|
11210
|
+
}
|
|
11211
|
+
if (planStr) {
|
|
11212
|
+
try {
|
|
11213
|
+
const plan = JSON.parse(planStr);
|
|
11214
|
+
if (Array.isArray(plan.sessions)) {
|
|
11215
|
+
const session = plan.sessions.find((s) => s.id === lessonId);
|
|
11216
|
+
if (session) {
|
|
11217
|
+
const lessonTitle2 = session.title || `Lesson ${lessonId}`;
|
|
11218
|
+
const keywords = Array.isArray(session.new_keywords) && session.new_keywords.length > 0 ? ` T\u1EEB kh\xF3a: ${session.new_keywords.join(", ")}` : "";
|
|
11219
|
+
const objective2 = session.prose_objective || session.title || "";
|
|
11220
|
+
const concept2 = objective2 ? `${objective2}.${keywords}` : session.title || "Core Technical Competency";
|
|
11221
|
+
const prerequisites2 = session.anchor_type ? `Anchor: ${session.anchor_type}` : "None";
|
|
11222
|
+
const depth = Array.isArray(session.depth_assignments) ? session.depth_assignments[0]?.depth : session.depth_assignments?.knowledge_depth;
|
|
11223
|
+
const bloomLevel2 = depth === "sio" ? "Create" : depth === "cio" ? "Apply" : "Understand";
|
|
11224
|
+
return {
|
|
11225
|
+
unitCode: session.unit_id || unitCode,
|
|
11226
|
+
moduleCode,
|
|
11227
|
+
lessonCode,
|
|
11228
|
+
lessonTitle: lessonTitle2,
|
|
11229
|
+
concept: `M\u1EE5c ti\xEAu bu\u1ED5i h\u1ECDc: ${concept2}`,
|
|
11230
|
+
prerequisites: prerequisites2,
|
|
11231
|
+
bloomLevel: bloomLevel2
|
|
11232
|
+
};
|
|
11233
|
+
}
|
|
11234
|
+
}
|
|
11235
|
+
} catch (planErr) {
|
|
11236
|
+
console.warn(`[getLessonMetadata] Error parsing CURRICULUM_PLAN.json for ${projectId}:`, planErr);
|
|
11237
|
+
}
|
|
11238
|
+
}
|
|
11239
|
+
const framework = await storage.readSotDocument(projectId, "CURRICULUM_FRAMEWORK.md") || "";
|
|
11113
11240
|
let lessonTitle = `Lesson ${lessonId}`;
|
|
11114
11241
|
let concept = "Core Technical Competency";
|
|
11115
11242
|
let prerequisites = "None";
|
|
@@ -11154,15 +11281,24 @@ async function getLessonMetadata(storage, projectId, lessonId) {
|
|
|
11154
11281
|
}
|
|
11155
11282
|
if (found) break;
|
|
11156
11283
|
}
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11284
|
+
if (found) {
|
|
11285
|
+
return {
|
|
11286
|
+
unitCode,
|
|
11287
|
+
moduleCode,
|
|
11288
|
+
lessonCode,
|
|
11289
|
+
lessonTitle,
|
|
11290
|
+
concept: objective ? `${concept}. M\u1EE5c ti\xEAu bu\u1ED5i h\u1ECDc: ${objective}` : concept,
|
|
11291
|
+
prerequisites: deliverable ? `${prerequisites}. S\u1EA3n ph\u1EA9m hands-on c\u1EE7a bu\u1ED5i: ${deliverable}` : prerequisites,
|
|
11292
|
+
bloomLevel
|
|
11293
|
+
};
|
|
11294
|
+
}
|
|
11295
|
+
throw new exports.CurriculumError({
|
|
11296
|
+
errorCode: "ERR_LESSON_NOT_IN_SOT",
|
|
11297
|
+
lessonId,
|
|
11298
|
+
message: `ERR_LESSON_NOT_IN_SOT: B\xE0i h\u1ECDc "${lessonId}" kh\xF4ng t\u1ED3n t\u1EA1i trong CURRICULUM_PLAN.json ho\u1EB7c CURRICULUM_FRAMEWORK.md c\u1EE7a d\u1EF1 \xE1n "${projectId}".`,
|
|
11299
|
+
suggestedAction: "\u0110\u1ED3ng b\u1ED9 CURRICULUM_PLAN r\u1ED3i ch\u1EA1y l\u1EA1i",
|
|
11300
|
+
retryable: false
|
|
11301
|
+
});
|
|
11166
11302
|
}
|
|
11167
11303
|
function buildFrameworkExcerptForLesson(framework, lessonId) {
|
|
11168
11304
|
if (!framework) return "";
|
|
@@ -11204,7 +11340,7 @@ ${nextRow}`
|
|
|
11204
11340
|
].filter(Boolean);
|
|
11205
11341
|
return parts.join("\n\n") || framework.slice(0, 1500);
|
|
11206
11342
|
}
|
|
11207
|
-
function buildLessonPrompt(pedagogy, lessonCode, unitCode, lessonTitle, concept, bloomLevel, dateStr) {
|
|
11343
|
+
function buildLessonPrompt(pedagogy, lessonCode, unitCode, lessonTitle, concept, bloomLevel, dateStr, targetLanguage = "vi", sectionLanguageContract) {
|
|
11208
11344
|
const commonFrontmatter = `id: "LESSON_${lessonCode}"
|
|
11209
11345
|
title: "${lessonTitle}"
|
|
11210
11346
|
created_by: "Curriculum OS Builder"
|
|
@@ -11224,8 +11360,9 @@ template_required_sections:
|
|
|
11224
11360
|
- "Artifact Contract"
|
|
11225
11361
|
- "B. Lesson Flow"
|
|
11226
11362
|
- "Artifact Linkage"`;
|
|
11363
|
+
let prompt = "";
|
|
11227
11364
|
if (pedagogy === "edp") {
|
|
11228
|
-
|
|
11365
|
+
prompt = `You are @content (Educational Content Editor & EDP Engineering Design Process Specialist).
|
|
11229
11366
|
Author the comprehensive Master Lesson Plan adhering strictly to \`LESSON_EDP_template.md\` standards for:
|
|
11230
11367
|
- Lesson Code: ${lessonCode}
|
|
11231
11368
|
- Title: ${lessonTitle}
|
|
@@ -11274,9 +11411,8 @@ Linkage ledger mapping all satellite artifacts (\`ACT_...\`, \`QUIZ_...\`, \`SLI
|
|
|
11274
11411
|
|
|
11275
11412
|
3. Ensure all sample code and schemas are 100% syntax-valid and executable.
|
|
11276
11413
|
4. Output 100% clean Markdown directly.`;
|
|
11277
|
-
}
|
|
11278
|
-
|
|
11279
|
-
return `You are @content (Educational Content Editor & PBL/General Pedagogy Specialist).
|
|
11414
|
+
} else if (pedagogy === "pbl" || pedagogy === "general") {
|
|
11415
|
+
prompt = `You are @content (Educational Content Editor & PBL/General Pedagogy Specialist).
|
|
11280
11416
|
Author the comprehensive Master Lesson Plan adhering strictly to \`LESSON_GENERAL_template.md\` standards for:
|
|
11281
11417
|
- Lesson Code: ${lessonCode}
|
|
11282
11418
|
- Title: ${lessonTitle}
|
|
@@ -11323,8 +11459,8 @@ type: "LESSON_GENERAL"
|
|
|
11323
11459
|
Linkage ledger mapping all satellite artifacts (\`ACT_...\`, \`QUIZ_...\`, \`SLIDE_...\`).
|
|
11324
11460
|
|
|
11325
11461
|
3. Output 100% clean Markdown directly.`;
|
|
11326
|
-
}
|
|
11327
|
-
|
|
11462
|
+
} else {
|
|
11463
|
+
prompt = `You are @content (Educational Content Editor & 5E Instructional Model Specialist).
|
|
11328
11464
|
Author the comprehensive Master Lesson Plan adhering strictly to \`LESSON_5E_template.md\` standards for:
|
|
11329
11465
|
- Lesson Code: ${lessonCode}
|
|
11330
11466
|
- Title: ${lessonTitle}
|
|
@@ -11372,6 +11508,18 @@ Linkage ledger mapping all satellite artifacts (\`GUIDE_...\`, \`SLIDE_...\`, \`
|
|
|
11372
11508
|
|
|
11373
11509
|
3. Ensure all sample code and syntax are 100% verified and runnable.
|
|
11374
11510
|
4. Output 100% clean Markdown directly.`;
|
|
11511
|
+
}
|
|
11512
|
+
const langDirective = buildLanguageDirective(targetLanguage);
|
|
11513
|
+
const headingDirective = buildHeadingDirective(
|
|
11514
|
+
pedagogy === "edp" ? "LESSON_EDP" : pedagogy === "general" || pedagogy === "pbl" ? "LESSON_GENERAL" : "LESSON_5E",
|
|
11515
|
+
sectionLanguageContract,
|
|
11516
|
+
targetLanguage
|
|
11517
|
+
);
|
|
11518
|
+
return `${prompt}
|
|
11519
|
+
|
|
11520
|
+
${langDirective}${headingDirective ? `
|
|
11521
|
+
|
|
11522
|
+
${headingDirective}` : ""}`;
|
|
11375
11523
|
}
|
|
11376
11524
|
async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
11377
11525
|
const {
|
|
@@ -11402,6 +11550,20 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11402
11550
|
const styleGuide = await storage.readSotDocument(projectId, "CONTENT_STYLE_GUIDE.md") || "";
|
|
11403
11551
|
const refPack = await storage.readSotDocument(projectId, "REFERENCE_PACK.md") || "";
|
|
11404
11552
|
await storage.readSotDocument(projectId, "LEARNER_PROFILE.md") || "";
|
|
11553
|
+
const slcMarkdown = options.sectionLanguageContract || await storage.readSotDocument(projectId, "SECTION_LANGUAGE_CONTRACT.md") || "";
|
|
11554
|
+
let targetLang = options.targetLanguage;
|
|
11555
|
+
if (!targetLang) {
|
|
11556
|
+
try {
|
|
11557
|
+
const planRaw = await storage.readArtifact(projectId, "_sot/CURRICULUM_PLAN.json");
|
|
11558
|
+
if (planRaw) {
|
|
11559
|
+
const p = JSON.parse(planRaw);
|
|
11560
|
+
targetLang = p?.translation?.target_language;
|
|
11561
|
+
}
|
|
11562
|
+
} catch {
|
|
11563
|
+
}
|
|
11564
|
+
}
|
|
11565
|
+
targetLang = targetLang || "vi";
|
|
11566
|
+
const languageDirective = buildLanguageDirective(targetLang);
|
|
11405
11567
|
let expositionContext = "";
|
|
11406
11568
|
let sessionSliceContext = "";
|
|
11407
11569
|
try {
|
|
@@ -11471,7 +11633,9 @@ Khi n\u1ED9i dung c\u1EA7n minh h\u1ECDa (diagram quy tr\xECnh, s\u01A1 \u0111\u
|
|
|
11471
11633
|
lessonTitle,
|
|
11472
11634
|
concept,
|
|
11473
11635
|
bloomLevel,
|
|
11474
|
-
dateStr
|
|
11636
|
+
dateStr,
|
|
11637
|
+
targetLang,
|
|
11638
|
+
slcMarkdown
|
|
11475
11639
|
) + mediaDirective;
|
|
11476
11640
|
const rawLesson = await runCurriculumAIInference(
|
|
11477
11641
|
[{ role: "user", content: lessonPrompt }],
|
|
@@ -11812,7 +11976,11 @@ template_required_sections:
|
|
|
11812
11976
|
- ### Phase 3: Debugging & Testing
|
|
11813
11977
|
- ## [REQUIRED] 3-Tier Differentiation (Bronze/Silver/Gold tasks)
|
|
11814
11978
|
- ## [REQUIRED] Reflection (Discussion question)
|
|
11815
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
11979
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
11980
|
+
|
|
11981
|
+
${languageDirective}
|
|
11982
|
+
|
|
11983
|
+
${buildHeadingDirective("ACT", slcMarkdown, targetLang)}`;
|
|
11816
11984
|
const rawAct = await runCurriculumAIInference(
|
|
11817
11985
|
[{ role: "user", content: actPrompt }],
|
|
11818
11986
|
satelliteContext,
|
|
@@ -11884,7 +12052,11 @@ template_required_sections:
|
|
|
11884
12052
|
- ## [REQUIRED] Multiple-Choice Question Bank (\u22655 scenario-based 4-option questions with: Question text, A/B/C/D options, Correct answer, Bloom level, Detailed distractor rationale)
|
|
11885
12053
|
- ## [REQUIRED] Code Analysis / Debugging Question (1 deep code tracing question requiring students to predict output or identify bugs)
|
|
11886
12054
|
- ## [REQUIRED] Competency Rubric (4-tier matrix: Developing \u2192 Proficient \u2192 Advanced \u2192 Exemplary)
|
|
11887
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12055
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12056
|
+
|
|
12057
|
+
${languageDirective}
|
|
12058
|
+
|
|
12059
|
+
${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
|
|
11888
12060
|
const rawQuiz = await runCurriculumAIInference(
|
|
11889
12061
|
[{ role: "user", content: quizPrompt }],
|
|
11890
12062
|
satelliteContext,
|
|
@@ -11963,7 +12135,11 @@ Mandatory Canvas & Presentation Invariants:
|
|
|
11963
12135
|
* COLD CALL / CHECK: Specific diagnostic question to ask students.
|
|
11964
12136
|
* SCAFFOLDING / GOTCHA: Guidance for students who get stuck.
|
|
11965
12137
|
* PACING: Recommended minutes for the slide.
|
|
11966
|
-
- Output 100% valid Marp Markdown
|
|
12138
|
+
- Output 100% valid Marp Markdown.
|
|
12139
|
+
|
|
12140
|
+
${languageDirective}
|
|
12141
|
+
|
|
12142
|
+
${buildHeadingDirective("SLIDE", slcMarkdown, targetLang)}`;
|
|
11967
12143
|
const rawSlide = await runCurriculumAIInference(
|
|
11968
12144
|
[{ role: "user", content: slidePrompt }],
|
|
11969
12145
|
satelliteContext,
|
|
@@ -12030,7 +12206,11 @@ template_contract: "artifact-template-v1"
|
|
|
12030
12206
|
- ## [REQUIRED] Facilitation Script & Timeline (Phase-by-phase teacher moves, inquiry questions, transitions)
|
|
12031
12207
|
- ## [REQUIRED] Common Misconceptions & Diagnostic Remediation Matrix
|
|
12032
12208
|
- ## [REQUIRED] Differentiated Support Strategies (Support scaffolds vs Extension challenges)
|
|
12033
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12209
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12210
|
+
|
|
12211
|
+
${languageDirective}
|
|
12212
|
+
|
|
12213
|
+
${buildHeadingDirective("GUIDE", slcMarkdown, targetLang)}`;
|
|
12034
12214
|
const rawGuide = await runCurriculumAIInference(
|
|
12035
12215
|
[{ role: "user", content: guidePrompt }],
|
|
12036
12216
|
satelliteContext,
|
|
@@ -12089,7 +12269,11 @@ template_contract: "artifact-template-v1"
|
|
|
12089
12269
|
- ## [REQUIRED] Visual Mental Model / Architecture Diagram (Mermaid or ASCII diagram)
|
|
12090
12270
|
- ## [REQUIRED] Step-by-Step Practical Quick-Start Guide
|
|
12091
12271
|
- ## [REQUIRED] Self-Check Diagnostic Checklist (Can-do statements for student self-assessment)
|
|
12092
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12272
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12273
|
+
|
|
12274
|
+
${languageDirective}
|
|
12275
|
+
|
|
12276
|
+
${buildHeadingDirective("HANDOUT", slcMarkdown, targetLang)}`;
|
|
12093
12277
|
const rawHandout = await runCurriculumAIInference(
|
|
12094
12278
|
[{ role: "user", content: handoutPrompt }],
|
|
12095
12279
|
satelliteContext,
|
|
@@ -12152,7 +12336,11 @@ template_contract: "artifact-template-v1"
|
|
|
12152
12336
|
- ## [REQUIRED] Part 3: Code Analysis & Bug Hunting Challenge
|
|
12153
12337
|
- ## [REQUIRED] Part 4: Synthesis & Problem-Solving Application
|
|
12154
12338
|
- ## [REQUIRED] Part 5: Self-Reflection & Learning Log
|
|
12155
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12339
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12340
|
+
|
|
12341
|
+
${languageDirective}
|
|
12342
|
+
|
|
12343
|
+
${buildHeadingDirective("WKS", slcMarkdown, targetLang)}`;
|
|
12156
12344
|
const rawWks = await runCurriculumAIInference(
|
|
12157
12345
|
[{ role: "user", content: wksPrompt }],
|
|
12158
12346
|
satelliteContext,
|
|
@@ -12219,7 +12407,11 @@ template_required_sections:
|
|
|
12219
12407
|
- ## [REQUIRED] Verified Reference Solution Code (100% syntactically valid, production-ready, fully commented)
|
|
12220
12408
|
- ## [REQUIRED] Automated Test / Verification Script (How to compile, flash, or unit test)
|
|
12221
12409
|
- ## [REQUIRED] Common Syntax & Runtime Pitfalls Matrix
|
|
12222
|
-
3. Output 100% clean Markdown directly with runnable code snippets \u2014 NO outer code fences around the document
|
|
12410
|
+
3. Output 100% clean Markdown directly with runnable code snippets \u2014 NO outer code fences around the document.
|
|
12411
|
+
|
|
12412
|
+
${languageDirective}
|
|
12413
|
+
|
|
12414
|
+
${buildHeadingDirective("CODE", slcMarkdown, targetLang)}`;
|
|
12223
12415
|
const rawCode = await runCurriculumAIInference(
|
|
12224
12416
|
[{ role: "user", content: codePrompt }],
|
|
12225
12417
|
satelliteContext,
|
|
@@ -12285,7 +12477,11 @@ template_contract: "artifact-template-v1"
|
|
|
12285
12477
|
- ### Challenge 2: [Name] (Difficulty: \u2B50\u2B50\u2B50\u2B50) \u2014 Advanced Architectural Constraints & Edge Cases
|
|
12286
12478
|
- ### Challenge 3: [Name] (Difficulty: \u2B50\u2B50\u2B50\u2B50\u2B50) \u2014 Extension Milestones (Level 1: Ninja \u2192 Level 2: Guru \u2192 Level 3: Master)
|
|
12287
12479
|
- ## [REQUIRED] Metacognitive Deep Dive & Engineering Trade-offs
|
|
12288
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12480
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12481
|
+
|
|
12482
|
+
${languageDirective}
|
|
12483
|
+
|
|
12484
|
+
${buildHeadingDirective("EXT", slcMarkdown, targetLang)}`;
|
|
12289
12485
|
const rawExt = await runCurriculumAIInference(
|
|
12290
12486
|
[{ role: "user", content: extPrompt }],
|
|
12291
12487
|
satelliteContext,
|
|
@@ -16929,8 +17125,10 @@ exports.buildDiagnosticQuizPrompt = buildDiagnosticQuizPrompt;
|
|
|
16929
17125
|
exports.buildExpositionContext = buildExpositionContext;
|
|
16930
17126
|
exports.buildExtensionPrompt = buildExtensionPrompt;
|
|
16931
17127
|
exports.buildHandoutPrompt = buildHandoutPrompt;
|
|
17128
|
+
exports.buildHeadingDirective = buildHeadingDirective;
|
|
16932
17129
|
exports.buildImagePrompt = buildImagePrompt;
|
|
16933
17130
|
exports.buildJudgePrompt = buildJudgePrompt;
|
|
17131
|
+
exports.buildLanguageDirective = buildLanguageDirective;
|
|
16934
17132
|
exports.buildLessonMasterPrompt = buildLessonMasterPrompt;
|
|
16935
17133
|
exports.buildProjectInstructionPrompt = buildProjectInstructionPrompt;
|
|
16936
17134
|
exports.buildSelfLabPrompt = buildSelfLabPrompt;
|
|
@@ -16963,6 +17161,7 @@ exports.executeCurriculumCommand = executeCurriculumCommand;
|
|
|
16963
17161
|
exports.exportAllProjectQuizzes = exportAllProjectQuizzes;
|
|
16964
17162
|
exports.expositionCacheKey = expositionCacheKey;
|
|
16965
17163
|
exports.extractScopeSequenceRows = extractScopeSequenceRows;
|
|
17164
|
+
exports.extractSectionHeadingsFromSLC = extractSectionHeadingsFromSLC;
|
|
16966
17165
|
exports.extractSessionSlice = extractSessionSlice;
|
|
16967
17166
|
exports.extractStreamChunk = extractStreamChunk;
|
|
16968
17167
|
exports.extractThoughtAndContent = extractThoughtAndContent;
|
|
@@ -17029,6 +17228,7 @@ exports.researcherTools = researcherTools;
|
|
|
17029
17228
|
exports.resolveGateSettings = resolveGateSettings;
|
|
17030
17229
|
exports.resolveStandardsPacks = resolveStandardsPacks;
|
|
17031
17230
|
exports.resolveStreamBudget = resolveStreamBudget;
|
|
17231
|
+
exports.resolveTargetLanguageCode = resolveTargetLanguageCode;
|
|
17032
17232
|
exports.resolveTranslationTargets = resolveTranslationTargets;
|
|
17033
17233
|
exports.reviewerTools = reviewerTools;
|
|
17034
17234
|
exports.runCurriculumAIInference = runCurriculumAIInference;
|
|
@@ -17052,6 +17252,7 @@ exports.streamLayerPrefillWithFallback = streamLayerPrefillWithFallback;
|
|
|
17052
17252
|
exports.streamLessonMasterFlow = streamLessonMasterFlow;
|
|
17053
17253
|
exports.streamSelfLabFlow = streamSelfLabFlow;
|
|
17054
17254
|
exports.stripLlmJsonWrappers = stripLlmJsonWrappers;
|
|
17255
|
+
exports.targetLanguageDisplayName = targetLanguageDisplayName;
|
|
17055
17256
|
exports.techSmeTools = techSmeTools;
|
|
17056
17257
|
exports.topoSort = topoSort;
|
|
17057
17258
|
exports.uploadAssetToBucket = uploadAssetToBucket;
|