@thanh01.pmt/curriculum-kit 1.4.43 → 1.4.45
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/ai/index.cjs +66 -470
- package/dist/ai/index.cjs.map +1 -1
- package/dist/ai/index.d.cts +77 -77
- package/dist/ai/index.d.ts +77 -77
- package/dist/ai/index.mjs +64 -469
- package/dist/ai/index.mjs.map +1 -1
- package/dist/index.cjs +478 -837
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +124 -58
- package/dist/index.d.ts +124 -58
- package/dist/index.mjs +470 -829
- package/dist/index.mjs.map +1 -1
- package/dist/pipeline/index.cjs +99 -484
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.mjs +97 -483
- package/dist/pipeline/index.mjs.map +1 -1
- package/dist/schemas/index.d.cts +1064 -1064
- package/dist/schemas/index.d.ts +1064 -1064
- package/dist/standards/index.d.cts +2 -2
- package/dist/standards/index.d.ts +2 -2
- package/dist/{standardsCoverageGate-49pJq5t8.d.cts → standardsCoverageGate-CLnq0d0s.d.cts} +12 -12
- package/dist/{standardsCoverageGate-49pJq5t8.d.ts → standardsCoverageGate-CLnq0d0s.d.ts} +12 -12
- package/dist/templates/ACT_template.md +18 -9
- package/dist/templates/ALIGNMENT_MATRIX_template.md +5 -0
- package/dist/templates/ART_DIRECTION_template.md +7 -0
- package/dist/templates/ASSET_MANIFEST_template.md +5 -0
- package/dist/templates/BASELINE_STANDARD.md +5 -0
- package/dist/templates/BELL_RINGER_template.md +13 -13
- package/dist/templates/CHANGELOG_template.md +3 -0
- package/dist/templates/CHOICE_BOARD_template.md +8 -5
- package/dist/templates/CODE_template.md +5 -6
- package/dist/templates/CONTENT_CONTINUITY_template.md +6 -0
- package/dist/templates/CONTENT_STYLE_GUIDE_template.md +4 -5
- package/dist/templates/CURRICULUM_FRAMEWORK_template.md +5 -6
- package/dist/templates/DEPENDENCY_MAP_template.md +3 -4
- package/dist/templates/EXIT_TICKET_template.md +8 -8
- package/dist/templates/EXT_template.md +3 -0
- package/dist/templates/GLOSSARY_template.md +1 -2
- package/dist/templates/GRAPHIC_ORGANIZER_template.md +8 -8
- package/dist/templates/GUIDE_template.md +5 -6
- package/dist/templates/HANDOUT_template.md +5 -6
- package/dist/templates/HANDOVER_DOCUMENT_template.md +8 -0
- package/dist/templates/KNOWLEDGE_EXPOSITION_template.md +16 -6
- package/dist/templates/LAB_TEMPLATE.md +78 -0
- package/dist/templates/LEARNER_PROFILE_template.md +4 -5
- package/dist/templates/LESSONS_LEARNED_template.md +8 -0
- package/dist/templates/LESSON_5E_template.md +24 -9
- package/dist/templates/LESSON_EDP_template.md +26 -10
- package/dist/templates/LESSON_GENERAL_template.md +22 -8
- package/dist/templates/OUTPUT_CONSTRAINTS_template.md +7 -0
- package/dist/templates/PACKAGING_SPEC_template.md +8 -0
- package/dist/templates/PILOT_FEEDBACK_template.md +6 -0
- package/dist/templates/PROJECT_BRIEF_template.md +8 -0
- package/dist/templates/PROJECT_STATUS_template.md +9 -0
- package/dist/templates/QUIZ_template.md +7 -0
- package/dist/templates/QUIZ_v4.6_template.md +4 -5
- package/dist/templates/REFERENCE_PACK_template.md +4 -0
- package/dist/templates/REVIEW_GAME_template.md +11 -8
- package/dist/templates/RUBRIC_template.md +2 -3
- package/dist/templates/SCIENCE_LAB_template.md +11 -5
- package/dist/templates/SECTION_LANGUAGE_CONTRACT_template.md +44 -0
- package/dist/templates/SELF_LAB_template.md +174 -0
- package/dist/templates/SLIDE_template.md +23 -0
- package/dist/templates/STATION_ROTATION_template.md +11 -11
- package/dist/templates/TASK_CARDS_template.md +8 -8
- package/dist/templates/TIERED_PRACTICE_template.md +14 -10
- package/dist/templates/UPDATE_ROADMAP_template.md +7 -0
- package/dist/templates/WKS_template.md +5 -6
- package/dist/workflow/index.cjs +250 -672
- package/dist/workflow/index.cjs.map +1 -1
- package/dist/workflow/index.d.cts +1 -1
- package/dist/workflow/index.d.ts +1 -1
- package/dist/workflow/index.mjs +248 -670
- package/dist/workflow/index.mjs.map +1 -1
- package/docs/refs/templates/ACT_template.md +18 -9
- package/docs/refs/templates/ALIGNMENT_MATRIX_template.md +5 -0
- package/docs/refs/templates/ART_DIRECTION_template.md +7 -0
- package/docs/refs/templates/ASSET_MANIFEST_template.md +5 -0
- package/docs/refs/templates/BASELINE_STANDARD.md +5 -0
- package/docs/refs/templates/BELL_RINGER_template.md +13 -13
- package/docs/refs/templates/CHANGELOG_template.md +3 -0
- package/docs/refs/templates/CHOICE_BOARD_template.md +8 -5
- package/docs/refs/templates/CODE_template.md +5 -6
- package/docs/refs/templates/CONTENT_CONTINUITY_template.md +6 -0
- package/docs/refs/templates/CONTENT_STYLE_GUIDE_template.md +4 -5
- package/docs/refs/templates/CURRICULUM_FRAMEWORK_template.md +5 -6
- package/docs/refs/templates/DEPENDENCY_MAP_template.md +3 -4
- package/docs/refs/templates/EXIT_TICKET_template.md +8 -8
- package/docs/refs/templates/EXT_template.md +3 -0
- package/docs/refs/templates/GLOSSARY_template.md +1 -2
- package/docs/refs/templates/GRAPHIC_ORGANIZER_template.md +8 -8
- package/docs/refs/templates/GUIDE_template.md +5 -6
- package/docs/refs/templates/HANDOUT_template.md +5 -6
- package/docs/refs/templates/HANDOVER_DOCUMENT_template.md +8 -0
- package/docs/refs/templates/KNOWLEDGE_EXPOSITION_template.md +16 -6
- package/docs/refs/templates/LAB_TEMPLATE.md +78 -0
- package/docs/refs/templates/LEARNER_PROFILE_template.md +4 -5
- package/docs/refs/templates/LESSONS_LEARNED_template.md +8 -0
- package/docs/refs/templates/LESSON_5E_template.md +24 -9
- package/docs/refs/templates/LESSON_EDP_template.md +26 -10
- package/docs/refs/templates/LESSON_GENERAL_template.md +22 -8
- package/docs/refs/templates/OUTPUT_CONSTRAINTS_template.md +7 -0
- package/docs/refs/templates/PACKAGING_SPEC_template.md +8 -0
- package/docs/refs/templates/PILOT_FEEDBACK_template.md +6 -0
- package/docs/refs/templates/PROJECT_BRIEF_template.md +8 -0
- package/docs/refs/templates/PROJECT_STATUS_template.md +9 -0
- package/docs/refs/templates/QUIZ_template.md +7 -0
- package/docs/refs/templates/QUIZ_v4.6_template.md +4 -5
- package/docs/refs/templates/REFERENCE_PACK_template.md +4 -0
- package/docs/refs/templates/REVIEW_GAME_template.md +11 -8
- package/docs/refs/templates/RUBRIC_template.md +2 -3
- package/docs/refs/templates/SCIENCE_LAB_template.md +11 -5
- package/docs/refs/templates/SECTION_LANGUAGE_CONTRACT_template.md +44 -0
- package/docs/refs/templates/SELF_LAB_template.md +174 -0
- package/docs/refs/templates/SLIDE_template.md +23 -0
- package/docs/refs/templates/STATION_ROTATION_template.md +11 -11
- package/docs/refs/templates/TASK_CARDS_template.md +8 -8
- package/docs/refs/templates/TIERED_PRACTICE_template.md +14 -10
- package/docs/refs/templates/UPDATE_ROADMAP_template.md +7 -0
- package/docs/refs/templates/WKS_template.md +5 -6
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import fs3 from 'fs';
|
|
2
|
+
import path4 from 'path';
|
|
3
3
|
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
4
4
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
5
5
|
import { createDeepSeek } from '@ai-sdk/deepseek';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
6
7
|
import { z } from 'zod';
|
|
7
8
|
import { generateObject, streamObject, streamText, generateText } from 'ai';
|
|
8
9
|
import pRetry from 'p-retry';
|
|
@@ -11,7 +12,6 @@ import pLimit from 'p-limit';
|
|
|
11
12
|
import fsPromises from 'fs/promises';
|
|
12
13
|
import crypto, { createHash } from 'crypto';
|
|
13
14
|
import { createClient } from '@supabase/supabase-js';
|
|
14
|
-
import { fileURLToPath } from 'url';
|
|
15
15
|
import { Octokit } from '@octokit/rest';
|
|
16
16
|
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
@@ -165,18 +165,18 @@ function resolveApiKey(keyName, explicitKey) {
|
|
|
165
165
|
try {
|
|
166
166
|
const currentDir = process.cwd();
|
|
167
167
|
const envPaths = [
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
168
|
+
path4.resolve(currentDir, ".env.local"),
|
|
169
|
+
path4.resolve(currentDir, ".env"),
|
|
170
|
+
path4.resolve(currentDir, "apps/web/.env.local"),
|
|
171
|
+
path4.resolve(currentDir, "packages/learnwell-platform/.env"),
|
|
172
|
+
path4.resolve(currentDir, "..", ".env.local"),
|
|
173
|
+
path4.resolve(currentDir, "..", ".env"),
|
|
174
|
+
path4.resolve(currentDir, "../..", ".env.local"),
|
|
175
|
+
path4.resolve(currentDir, "../..", ".env")
|
|
176
176
|
];
|
|
177
177
|
for (const envPath of envPaths) {
|
|
178
|
-
if (
|
|
179
|
-
const content =
|
|
178
|
+
if (fs3.existsSync(envPath)) {
|
|
179
|
+
const content = fs3.readFileSync(envPath, "utf-8");
|
|
180
180
|
for (const line of content.split("\n")) {
|
|
181
181
|
const trimmed = line.trim();
|
|
182
182
|
if (trimmed && !trimmed.startsWith("#") && trimmed.startsWith(keyName + "=")) {
|
|
@@ -1166,6 +1166,229 @@ var init_provider_factory = __esm({
|
|
|
1166
1166
|
};
|
|
1167
1167
|
}
|
|
1168
1168
|
});
|
|
1169
|
+
function stripTemplateFrontmatter(raw) {
|
|
1170
|
+
let body = raw;
|
|
1171
|
+
if (body.startsWith("---")) {
|
|
1172
|
+
const end = body.indexOf("\n---", 3);
|
|
1173
|
+
if (end !== -1) body = body.slice(end + 4);
|
|
1174
|
+
}
|
|
1175
|
+
return body.split("\n").filter((l) => l.trim() !== "<!-- INJECT_BODY -->").join("\n").replace(/^\s*\n/, "").trimEnd();
|
|
1176
|
+
}
|
|
1177
|
+
function extractRequiredSections(raw) {
|
|
1178
|
+
const lines = raw.split("\n");
|
|
1179
|
+
const start = lines.findIndex((l) => /^template_required_sections:\s*$/.test(l.trim()));
|
|
1180
|
+
if (start === -1) return null;
|
|
1181
|
+
const items = [];
|
|
1182
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
1183
|
+
const line = lines[i] ?? "";
|
|
1184
|
+
if (line.trim() === "") continue;
|
|
1185
|
+
if (!/^\s+-\s/.test(line)) break;
|
|
1186
|
+
items.push(line.trim().replace(/^-\s+/, "").replace(/^["']|["']$/g, ""));
|
|
1187
|
+
}
|
|
1188
|
+
return items.length > 0 ? items : null;
|
|
1189
|
+
}
|
|
1190
|
+
function stripHeadingKey(h) {
|
|
1191
|
+
return h.replace(/\[(REQUIRED|OPTIONAL|CONDITIONAL)\]\s*/gi, "").replace(/^\s*\d+[.)]\s+/, "").replace(/\s+/g, " ").trim();
|
|
1192
|
+
}
|
|
1193
|
+
function isVariableHeading(text) {
|
|
1194
|
+
return /\{\{[^}]*\}\}/.test(text) || /\[[^\]]+\]/.test(text);
|
|
1195
|
+
}
|
|
1196
|
+
function collectHeadings(body) {
|
|
1197
|
+
const out = [];
|
|
1198
|
+
let inFence = false;
|
|
1199
|
+
for (const line of body.split("\n")) {
|
|
1200
|
+
if (/^(```|~~~)/.test(line.trim())) {
|
|
1201
|
+
inFence = !inFence;
|
|
1202
|
+
continue;
|
|
1203
|
+
}
|
|
1204
|
+
if (inFence) continue;
|
|
1205
|
+
const m = line.match(/^(#{2,3})\s+(.*)$/);
|
|
1206
|
+
if (!m) continue;
|
|
1207
|
+
const text = m[2].trim();
|
|
1208
|
+
const optional = /^\[OPTIONAL\]/i.test(text);
|
|
1209
|
+
const name = stripHeadingKey(text);
|
|
1210
|
+
if (!name || isVariableHeading(name)) continue;
|
|
1211
|
+
out.push({ level: m[1].length, name, optional });
|
|
1212
|
+
}
|
|
1213
|
+
return out;
|
|
1214
|
+
}
|
|
1215
|
+
function extractEchoSections(raw) {
|
|
1216
|
+
const hs = collectHeadings(stripTemplateFrontmatter(raw));
|
|
1217
|
+
return {
|
|
1218
|
+
required: hs.filter((h) => !h.optional).map((h) => h.name),
|
|
1219
|
+
optional: hs.filter((h) => h.optional).map((h) => h.name)
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
function extractConditionalSections(raw) {
|
|
1223
|
+
const body = stripTemplateFrontmatter(raw);
|
|
1224
|
+
return body.split("\n").filter((l) => /^#{2,3} .*\[CONDITIONAL\]/i.test(l)).map((l) => stripHeadingKey(l.replace(/^#{2,3}\s*/, "").trim())).filter((s) => s.length > 0 && !isVariableHeading(s));
|
|
1225
|
+
}
|
|
1226
|
+
function extractDeclaredLanguage(raw) {
|
|
1227
|
+
const m = raw.match(/^template_language:\s*["']?([a-zA-Z-]+)["']?\s*$/m);
|
|
1228
|
+
return m?.[1]?.toLowerCase() || "en";
|
|
1229
|
+
}
|
|
1230
|
+
function candidateDirs(explicitDir) {
|
|
1231
|
+
const dirs = [];
|
|
1232
|
+
if (explicitDir) dirs.push(explicitDir);
|
|
1233
|
+
if (process.env.CURRICULUM_TEMPLATES_DIR) dirs.push(process.env.CURRICULUM_TEMPLATES_DIR);
|
|
1234
|
+
dirs.push(path4.resolve(process.cwd(), "_templates"));
|
|
1235
|
+
for (const rel of KIT_TEMPLATE_FALLBACK_DIRS) {
|
|
1236
|
+
dirs.push(path4.resolve(_moduleDir, rel));
|
|
1237
|
+
dirs.push(path4.resolve(process.cwd(), rel));
|
|
1238
|
+
dirs.push(path4.resolve(process.cwd(), "packages/curriculum-kit", rel));
|
|
1239
|
+
}
|
|
1240
|
+
return dirs;
|
|
1241
|
+
}
|
|
1242
|
+
function findTemplatePath(templateName, explicitDir) {
|
|
1243
|
+
for (const dir of candidateDirs(explicitDir)) {
|
|
1244
|
+
const p = path4.join(dir, templateName);
|
|
1245
|
+
if (!fs3.existsSync(p)) continue;
|
|
1246
|
+
try {
|
|
1247
|
+
fs3.accessSync(p, fs3.constants.R_OK);
|
|
1248
|
+
return p;
|
|
1249
|
+
} catch {
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
return null;
|
|
1253
|
+
}
|
|
1254
|
+
function resolveArtifactTemplate(templateName, opts) {
|
|
1255
|
+
const p = findTemplatePath(templateName, opts?.templatesDir);
|
|
1256
|
+
if (!p) return null;
|
|
1257
|
+
try {
|
|
1258
|
+
const raw = fs3.readFileSync(p, "utf-8");
|
|
1259
|
+
const echo = extractEchoSections(raw);
|
|
1260
|
+
return {
|
|
1261
|
+
content: stripTemplateFrontmatter(raw),
|
|
1262
|
+
sections: echo.required,
|
|
1263
|
+
optionalSections: echo.optional,
|
|
1264
|
+
sourcePath: p,
|
|
1265
|
+
conditionals: extractConditionalSections(raw),
|
|
1266
|
+
declaredLang: extractDeclaredLanguage(raw)
|
|
1267
|
+
};
|
|
1268
|
+
} catch {
|
|
1269
|
+
return null;
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
function assembleTranslatedTemplate(templateName, translatedBody, targetLanguage, opts) {
|
|
1273
|
+
const raw = loadCurriculumTemplate(templateName, opts?.templatesDir);
|
|
1274
|
+
if (!raw || !translatedBody?.trim()) return null;
|
|
1275
|
+
const base = collectHeadings(stripTemplateFrontmatter(raw));
|
|
1276
|
+
const out = collectHeadings(translatedBody);
|
|
1277
|
+
if (base.length !== out.length) return null;
|
|
1278
|
+
for (let i = 0; i < base.length; i++) {
|
|
1279
|
+
if (base[i].level !== out[i].level || base[i].optional !== out[i].optional) return null;
|
|
1280
|
+
}
|
|
1281
|
+
const srcBody = stripTemplateFrontmatter(raw);
|
|
1282
|
+
for (const ph of new Set(srcBody.match(/\{\{[^}]+\}\}/g) ?? [])) {
|
|
1283
|
+
if (!translatedBody.includes(ph)) return null;
|
|
1284
|
+
}
|
|
1285
|
+
for (const mk of new Set(srcBody.match(/<!--\s*\[\/?[^\]]+\]\s*-->/g) ?? [])) {
|
|
1286
|
+
if (!translatedBody.includes(mk)) return null;
|
|
1287
|
+
}
|
|
1288
|
+
const lang = targetLanguage.trim().toLowerCase() || "en";
|
|
1289
|
+
const req = out.filter((h) => !h.optional).map((h) => h.name);
|
|
1290
|
+
let fmRaw = "";
|
|
1291
|
+
if (raw.startsWith("---")) {
|
|
1292
|
+
const end = raw.indexOf("\n---", 3);
|
|
1293
|
+
if (end !== -1) fmRaw = raw.slice(0, end + 4);
|
|
1294
|
+
}
|
|
1295
|
+
const fm = stampEchoOnFrontmatter(fmRaw || "---\n---", lang, req);
|
|
1296
|
+
return { raw: `${fm}
|
|
1297
|
+
${translatedBody.trimStart()}`, sections: req, templateLanguage: lang };
|
|
1298
|
+
}
|
|
1299
|
+
function stampEchoOnFrontmatter(rawDoc, lang, sections) {
|
|
1300
|
+
const echoLines = ['template_language: "' + lang + '"', "template_required_sections:", ...sections.map((n) => ` - "${n.replace(/"/g, '\\"')}"`)];
|
|
1301
|
+
if (rawDoc.startsWith("---")) {
|
|
1302
|
+
const lines = rawDoc.split("\n");
|
|
1303
|
+
const closeIdx = lines.findIndex((l, i) => i > 0 && l.trim() === "---");
|
|
1304
|
+
if (closeIdx === -1) {
|
|
1305
|
+
return ["---", ...echoLines, "---", "", stripTemplateFrontmatter(rawDoc)].join("\n");
|
|
1306
|
+
}
|
|
1307
|
+
const kept = [];
|
|
1308
|
+
let skippingList = false;
|
|
1309
|
+
for (const l of lines.slice(0, closeIdx)) {
|
|
1310
|
+
const t = l.trim();
|
|
1311
|
+
if (/^template_required_sections:$/.test(t)) {
|
|
1312
|
+
skippingList = true;
|
|
1313
|
+
continue;
|
|
1314
|
+
}
|
|
1315
|
+
if (/^template_language:/.test(t)) continue;
|
|
1316
|
+
if (skippingList) {
|
|
1317
|
+
if (/^\s+-\s/.test(l)) continue;
|
|
1318
|
+
skippingList = false;
|
|
1319
|
+
}
|
|
1320
|
+
kept.push(l);
|
|
1321
|
+
}
|
|
1322
|
+
return [...kept, ...echoLines, "---", ...lines.slice(closeIdx + 1)].join("\n");
|
|
1323
|
+
}
|
|
1324
|
+
return ["---", ...echoLines, "---", "", rawDoc].join("\n");
|
|
1325
|
+
}
|
|
1326
|
+
async function translateTemplate(templateName, targetLanguage, runner, opts) {
|
|
1327
|
+
const raw = loadCurriculumTemplate(templateName, opts?.templatesDir);
|
|
1328
|
+
if (!raw) return null;
|
|
1329
|
+
const body = stripTemplateFrontmatter(raw);
|
|
1330
|
+
const placeholders = Array.from(new Set(body.match(/\{\{[^}]+\}\}/g) ?? []));
|
|
1331
|
+
const markers = Array.from(new Set(body.match(/<!--\s*\[\/?[^\]]+\]\s*-->/g) ?? []));
|
|
1332
|
+
const prompt = `Translate the following Markdown artifact TEMPLATE body into ${targetLanguage}.
|
|
1333
|
+
STRICT PRESERVATION RULES (violating any of these invalidates the output):
|
|
1334
|
+
1. Keep the document structure EXACTLY: same number of headings, same order, same heading levels (## / ###).
|
|
1335
|
+
2. Translate heading TEXT naturally, but a heading must remain a single static line: move nothing into or out of it. Headings never contain durations or placeholders \u2014 if a source heading carries "[X mins]"-style timing, the timing belongs on the line below the heading, not inside it.
|
|
1336
|
+
3. Keep every placeholder token VERBATIM (do not translate or alter), including {{ XX }}-style duration tokens: ${placeholders.join(" ") || "(none)"}
|
|
1337
|
+
4. Keep every HTML comment marker VERBATIM: ${markers.join(" ") || "(none)"}
|
|
1338
|
+
5. Keep code blocks, file paths, technical identifiers (API names, protocols, component models) untranslated.
|
|
1339
|
+
6. Translate ONLY natural-language prose, headings, and table headers into natural ${targetLanguage}.
|
|
1340
|
+
7. Output ONLY the translated markdown \u2014 no explanations, no code fences around the whole document.
|
|
1341
|
+
|
|
1342
|
+
TEMPLATE BODY:
|
|
1343
|
+
${body}`;
|
|
1344
|
+
let translatedBody;
|
|
1345
|
+
try {
|
|
1346
|
+
translatedBody = await runner(prompt);
|
|
1347
|
+
} catch {
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
if (!translatedBody || translatedBody.length < body.length * 0.4) return null;
|
|
1351
|
+
translatedBody = translatedBody.trim().replace(/^```(?:markdown)?\n/, "").replace(/\n```$/, "");
|
|
1352
|
+
return assembleTranslatedTemplate(templateName, translatedBody, targetLanguage, opts);
|
|
1353
|
+
}
|
|
1354
|
+
function loadCurriculumTemplate(templateName, templatesDir) {
|
|
1355
|
+
const p = findTemplatePath(templateName, templatesDir);
|
|
1356
|
+
if (!p) return "";
|
|
1357
|
+
try {
|
|
1358
|
+
return fs3.readFileSync(p, "utf-8");
|
|
1359
|
+
} catch {
|
|
1360
|
+
return "";
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
function loadAuthoringTemplate(templateName, templatesDir) {
|
|
1364
|
+
const p = findTemplatePath(templateName, templatesDir);
|
|
1365
|
+
if (!p) return "";
|
|
1366
|
+
try {
|
|
1367
|
+
return stripTemplateFrontmatter(fs3.readFileSync(p, "utf-8"));
|
|
1368
|
+
} catch {
|
|
1369
|
+
return "";
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
var KIT_TEMPLATE_FALLBACK_DIRS, _moduleDir;
|
|
1373
|
+
var init_templateLoader = __esm({
|
|
1374
|
+
"src/services/templateLoader.ts"() {
|
|
1375
|
+
KIT_TEMPLATE_FALLBACK_DIRS = [
|
|
1376
|
+
// Packaged with the npm bundle (dist/templates) — resolves from node_modules.
|
|
1377
|
+
"templates",
|
|
1378
|
+
// Repo checkout layouts.
|
|
1379
|
+
"docs/refs/templates"
|
|
1380
|
+
];
|
|
1381
|
+
_moduleDir = (() => {
|
|
1382
|
+
try {
|
|
1383
|
+
if (typeof import.meta !== "undefined" && typeof import.meta.url === "string") {
|
|
1384
|
+
return path4.dirname(fileURLToPath(import.meta.url));
|
|
1385
|
+
}
|
|
1386
|
+
} catch {
|
|
1387
|
+
}
|
|
1388
|
+
return typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
1389
|
+
})();
|
|
1390
|
+
}
|
|
1391
|
+
});
|
|
1169
1392
|
|
|
1170
1393
|
// src/pipeline/artifactLinter.ts
|
|
1171
1394
|
var artifactLinter_exports = {};
|
|
@@ -1532,14 +1755,26 @@ function parseLessonFlow(lessonMarkdown) {
|
|
|
1532
1755
|
}
|
|
1533
1756
|
}
|
|
1534
1757
|
}
|
|
1535
|
-
const flowMatch = lessonMarkdown.match(/##\s
|
|
1758
|
+
const flowMatch = lessonMarkdown.match(/##\s*(?:\[?REQUIRED\]?\s*)?B\.\s*Lesson Flow([\s\S]*?)$/i);
|
|
1536
1759
|
const flowSection = flowMatch ? flowMatch[1] : lessonMarkdown;
|
|
1537
|
-
const phaseRegex = /###\s*(?:(\d+)\.\s*)?([^\n
|
|
1760
|
+
const phaseRegex = /###\s*(?:(\d+)\.\s*)?([^\n]+)\n([\s\S]*?)(?=(?:###\s*(?:\d+\.)?|$))/gi;
|
|
1538
1761
|
let pMatch;
|
|
1539
1762
|
while ((pMatch = phaseRegex.exec(flowSection)) !== null) {
|
|
1540
|
-
const
|
|
1541
|
-
const
|
|
1542
|
-
const
|
|
1763
|
+
const headingText = pMatch[2].trim();
|
|
1764
|
+
const tailMatch = headingText.match(/[—–-]\s*\[?([^\]—–]+)\]?\s*$/);
|
|
1765
|
+
const tail = tailMatch?.[1]?.trim() ?? "";
|
|
1766
|
+
const rawPhaseName = stripHeadingKey(
|
|
1767
|
+
tailMatch && /mins?/i.test(tail) ? headingText.slice(0, tailMatch.index).trim() : headingText
|
|
1768
|
+
);
|
|
1769
|
+
let content = pMatch[3].trim();
|
|
1770
|
+
let timing;
|
|
1771
|
+
const durMatch2 = content.match(/^>?\s*\**Duration:?\**\s*([~0-9][^\n]*)/i);
|
|
1772
|
+
if (durMatch2) {
|
|
1773
|
+
timing = durMatch2[1].trim();
|
|
1774
|
+
content = content.replace(/^>?\s*\**Duration:?\**\s*[^\n]*\n?/i, "").trim();
|
|
1775
|
+
} else if (tail && /mins?/i.test(tail)) {
|
|
1776
|
+
timing = tail;
|
|
1777
|
+
}
|
|
1543
1778
|
const codeSnippets = [];
|
|
1544
1779
|
const codeRegex = /```(?:[a-zA-Z0-9_\-]+)?\s*\n([\s\S]*?)```/g;
|
|
1545
1780
|
let cMatch;
|
|
@@ -1567,6 +1802,7 @@ function parseLessonFlow(lessonMarkdown) {
|
|
|
1567
1802
|
}
|
|
1568
1803
|
var init_lessonFlowParser = __esm({
|
|
1569
1804
|
"src/parsers/lessonFlowParser.ts"() {
|
|
1805
|
+
init_templateLoader();
|
|
1570
1806
|
}
|
|
1571
1807
|
});
|
|
1572
1808
|
|
|
@@ -3933,468 +4169,8 @@ var RoadmapInputSchema = z.object({
|
|
|
3933
4169
|
// src/ai/index.ts
|
|
3934
4170
|
init_provider_factory();
|
|
3935
4171
|
|
|
3936
|
-
// src/templates/lessonTemplate.ts
|
|
3937
|
-
var LESSON_PLAN_TEMPLATE = `
|
|
3938
|
-
---
|
|
3939
|
-
id: "{{ID}}"
|
|
3940
|
-
title: "{{TITLE}}"
|
|
3941
|
-
type: "LESSON_5E"
|
|
3942
|
-
created_by: "Curriculum OS Builder"
|
|
3943
|
-
phase: "{{PHASE}}"
|
|
3944
|
-
deliverable: "P3-T1"
|
|
3945
|
-
version: "{{VERSION}}"
|
|
3946
|
-
date: "{{DATE}}"
|
|
3947
|
-
prerequisite: []
|
|
3948
|
-
template_contract: "lesson-plan-v2"
|
|
3949
|
-
template_required_sections:
|
|
3950
|
-
- "A. Lesson Design Plan"
|
|
3951
|
-
- "Learning Objectives & Evidence"
|
|
3952
|
-
- "Activity Sequence"
|
|
3953
|
-
- "Resource Map"
|
|
3954
|
-
- "Assessment Map"
|
|
3955
|
-
- "Artifact Contract"
|
|
3956
|
-
- "B. Lesson Flow"
|
|
3957
|
-
---
|
|
3958
|
-
<!-- INJECT_BODY -->
|
|
3959
|
-
|
|
3960
|
-
# LESSON [{{LESSON_ID}}]: {{TITLE}} (5E Model)
|
|
3961
|
-
|
|
3962
|
-
## [REQUIRED] A. Lesson Design Plan
|
|
3963
|
-
|
|
3964
|
-
### 1. Learning Objectives & Evidence
|
|
3965
|
-
- **Estimated Duration:** {{DURATION}}
|
|
3966
|
-
- **Materials & Equipment:** {{MATERIALS_SUMMARY}}
|
|
3967
|
-
- **Keywords / Core Concepts:** {{KEYWORDS}}
|
|
3968
|
-
|
|
3969
|
-
| LO | Objective (Bloom's) | Student Evidence | Success Criteria |
|
|
3970
|
-
|---|---|---|---|
|
|
3971
|
-
{{LEARNING_OBJECTIVES_TABLE_ROWS}}
|
|
3972
|
-
|
|
3973
|
-
### 2. Activity Sequence
|
|
3974
|
-
> This is the canonical activity contract. Satellite artifacts must expand this sequence and must not invent a different one.
|
|
3975
|
-
|
|
3976
|
-
| Seq | 5E Phase | Activity Type | Actor | Purpose | Student Action | Teacher Move | Output/Evidence | LO | Time | Artifact Contract |
|
|
3977
|
-
|---|---|---|---|---|---|---|---|---|---|---|
|
|
3978
|
-
{{ACTIVITY_SEQUENCE_TABLE_ROWS}}
|
|
3979
|
-
|
|
3980
|
-
### 3. Resource Map
|
|
3981
|
-
| Resource | Used In Activity | Purpose | Owner Artifact |
|
|
3982
|
-
|---|---|---|---|
|
|
3983
|
-
{{RESOURCE_MAP_TABLE_ROWS}}
|
|
3984
|
-
|
|
3985
|
-
### 4. Assessment Map
|
|
3986
|
-
| Evidence | Assessed By | Criteria | Follow-up If Missing |
|
|
3987
|
-
|---|---|---|---|
|
|
3988
|
-
{{ASSESSMENT_MAP_TABLE_ROWS}}
|
|
3989
|
-
|
|
3990
|
-
### 5. Artifact Contract
|
|
3991
|
-
- **ACT must expand:** {{ACT_CONTRACT}}
|
|
3992
|
-
- **GUIDE must support:** {{GUIDE_CONTRACT}}
|
|
3993
|
-
- **SLIDE must visualize:** {{SLIDE_CONTRACT}}
|
|
3994
|
-
- **HANDOUT must provide:** {{HANDOUT_CONTRACT}}
|
|
3995
|
-
- **WKS must practice:** {{WKS_CONTRACT}}
|
|
3996
|
-
- **QUIZ must assess:** {{QUIZ_CONTRACT}}
|
|
3997
|
-
- **EXT must extend:** {{EXT_CONTRACT}}
|
|
3998
|
-
|
|
3999
|
-
---
|
|
4000
|
-
|
|
4001
|
-
## [REQUIRED] B. Lesson Flow
|
|
4002
|
-
|
|
4003
|
-
### 1. ENGAGE \u2014 {{ENGAGE_DURATION}} mins
|
|
4004
|
-
- **Hook Scenario:** {{HOOK_SCENARIO}}
|
|
4005
|
-
- **Open Question:** {{HOOK_OPEN_QUESTION}}
|
|
4006
|
-
- **Transition:** {{HOOK_TRANSITION}}
|
|
4007
|
-
|
|
4008
|
-
### 2. EXPLORE \u2014 {{EXPLORE_DURATION}} mins
|
|
4009
|
-
- **Activity Reference:** {{EXPLORE_ACTIVITY_REF}}
|
|
4010
|
-
- **Student Discovery:** {{EXPLORE_STUDENT_DISCOVERY}}
|
|
4011
|
-
|
|
4012
|
-
### 3. EXPLAIN \u2014 {{EXPLAIN_DURATION}} mins
|
|
4013
|
-
- **Definitions:**
|
|
4014
|
-
{{EXPLAIN_DEFINITIONS}}
|
|
4015
|
-
- **Visual Illustration (REQUIRED):**
|
|
4016
|
-
{{EXPLAIN_VISUAL_ILLUSTRATION}}
|
|
4017
|
-
|
|
4018
|
-
### 4. ELABORATE \u2014 {{ELABORATE_DURATION}} mins
|
|
4019
|
-
- **Tiered Scaffolding:**
|
|
4020
|
-
- \u{1F949} **Bronze:** {{DIFFERENTIATION_BRONZE}}
|
|
4021
|
-
- \u{1F948} **Silver:** {{DIFFERENTIATION_SILVER}}
|
|
4022
|
-
- \u{1F947} **Gold:** {{DIFFERENTIATION_GOLD}}
|
|
4023
|
-
|
|
4024
|
-
> **ACT Contract**: Detailed operational instructions must expand the Activity Sequence above and must not change the planned evidence target.
|
|
4025
|
-
|
|
4026
|
-
### 5. EVALUATE \u2014 {{EVALUATE_DURATION}} mins
|
|
4027
|
-
- **Exit Ticket:** {{EXIT_TICKET_CONTENT}}
|
|
4028
|
-
- **Closing:** {{CLOSING_REMARKS}}
|
|
4029
|
-
|
|
4030
|
-
> **QUIZ Contract**: Detailed assessment criteria and rubrics must assess the evidence and success criteria defined in the Lesson Design Plan.
|
|
4031
|
-
|
|
4032
|
-
---
|
|
4033
|
-
|
|
4034
|
-
## [OPTIONAL] Teacher Notes
|
|
4035
|
-
- **Common Pitfalls:**
|
|
4036
|
-
{{COMMON_PITFALLS}}
|
|
4037
|
-
- **Troubleshooting:**
|
|
4038
|
-
{{TROUBLESHOOTING_ROWS}}
|
|
4039
|
-
|
|
4040
|
-
---
|
|
4041
|
-
|
|
4042
|
-
## [REQUIRED] Artifact Linkage (Master Index)
|
|
4043
|
-
> List all satellite files used in this lesson.
|
|
4044
|
-
|
|
4045
|
-
| Artifact File | Role in the Classroom | When to Use |
|
|
4046
|
-
|---|---|---|
|
|
4047
|
-
| \`GUIDE_{{LESSON_ID}}.md\` | Detailed Teaching Script | Teacher preparation |
|
|
4048
|
-
| \`SLIDE_{{LESSON_ID}}.md\` | Presentation Content | Throughout the session |
|
|
4049
|
-
| \`HANDOUT_{{LESSON_ID}}.md\` | Theory Summary for Students | During EXPLAIN phase |
|
|
4050
|
-
| \`ACT_{{LESSON_ID}}.md\` | Detailed Learning Activity Operations | During EXPLORE / ELABORATE / checkpoint phases |
|
|
4051
|
-
| \`WKS_{{LESSON_ID}}.md\` | Individual Worksheet | Wrap-up or Homework |
|
|
4052
|
-
| \`QUIZ_{{LESSON_ID}}.md\` | Assessment Rubric | During EVALUATE phase |
|
|
4053
|
-
| \`EXT_{{LESSON_ID}}.md\` | Enrichment Materials | For "Gold" students |
|
|
4054
|
-
`.trim();
|
|
4055
|
-
|
|
4056
|
-
// src/templates/actTemplate.ts
|
|
4057
|
-
var ACT_TEMPLATE = `
|
|
4058
|
-
---
|
|
4059
|
-
id: "{{ID}}"
|
|
4060
|
-
title: "{{TITLE}}"
|
|
4061
|
-
type: "ACT"
|
|
4062
|
-
created_by: "Curriculum OS Builder"
|
|
4063
|
-
phase: "{{PHASE}}"
|
|
4064
|
-
deliverable: "P3-T2"
|
|
4065
|
-
version: "{{VERSION}}"
|
|
4066
|
-
date: "{{DATE}}"
|
|
4067
|
-
template_contract: "artifact-template-v1"
|
|
4068
|
-
template_required_sections:
|
|
4069
|
-
- "Computational Thinking Focus"
|
|
4070
|
-
- "Materials & Setup"
|
|
4071
|
-
- "Constraints & Safety"
|
|
4072
|
-
- "Active Learning Workflow"
|
|
4073
|
-
- "3-Tier Differentiation"
|
|
4074
|
-
- "Reflection"
|
|
4075
|
-
---
|
|
4076
|
-
<!-- INJECT_BODY -->
|
|
4077
|
-
|
|
4078
|
-
# INQUIRY-BASED ACTIVITY: {{TITLE}}
|
|
4079
|
-
_Milestone: {{MILESTONE_ID}} | Module: {{MODULE_NAME}} | Lesson: {{LESSON_ID}}_
|
|
4080
|
-
|
|
4081
|
-
## [REQUIRED] Computational Thinking Focus
|
|
4082
|
-
- **Problem Statement (Real-world Scenario):** {{PROBLEM_STATEMENT}}
|
|
4083
|
-
- **Decomposition:**
|
|
4084
|
-
{{DECOMPOSITION_STEPS}}
|
|
4085
|
-
- **Algorithm Design:** {{ALGORITHM_DESIGN}}
|
|
4086
|
-
|
|
4087
|
-
## [REQUIRED] Materials & Setup
|
|
4088
|
-
- **Reference Material:** Students should use the **HANDOUT** for this lesson as their primary technical reference (lifeline).
|
|
4089
|
-
- **Hardware/Software:**
|
|
4090
|
-
<!-- [HARDWARE_BOM] -->
|
|
4091
|
-
{{HARDWARE_ITEMS}}
|
|
4092
|
-
<!-- [/HARDWARE_BOM] -->
|
|
4093
|
-
- **Software:** {{SOFTWARE_ITEMS}}
|
|
4094
|
-
- **Consumables:** {{CONSUMABLES}}
|
|
4095
|
-
- **Other Resources:** {{OTHER_RESOURCES}}
|
|
4096
|
-
|
|
4097
|
-
## [REQUIRED] Constraints & Safety
|
|
4098
|
-
- \u26A0\uFE0F **Technical/Safety:** {{SAFETY_WARNING}}
|
|
4099
|
-
- \u{1F4A1} **Design Constraint:** {{DESIGN_CONSTRAINT}}
|
|
4100
|
-
|
|
4101
|
-
## [REQUIRED] Active Learning Workflow
|
|
4102
|
-
|
|
4103
|
-
### Phase 1: Planning & Design \u2014 {{PHASE1_DURATION}} mins
|
|
4104
|
-
- **Student Task:** Hand-draw (or draft in words) the algorithm flowchart or connection architecture before touching the computer/devices.
|
|
4105
|
-
- **Teacher Action:** Walk around to check the logic of each group. Ask inquiry questions:
|
|
4106
|
-
{{PHASE1_INQUIRY_QUESTIONS}}
|
|
4107
|
-
|
|
4108
|
-
### Phase 2: Implementation & Discovery \u2014 {{PHASE2_DURATION}} mins
|
|
4109
|
-
- **Student Task:** Apply the knowledge from the **HANDOUT** to realize the plan designed in Phase 1. Encourage self-inquiry and documentation lookup.
|
|
4110
|
-
- **Teacher Action:** Avoid "hand-holding." Only intervene if a group has been stuck for more than 5 minutes.
|
|
4111
|
-
{{PHASE2_GUIDANCE_BLOCK}}
|
|
4112
|
-
|
|
4113
|
-
### Phase 3: Debugging & Testing \u2014 {{PHASE3_DURATION}} mins
|
|
4114
|
-
- **Testing:** Students run their system.
|
|
4115
|
-
- **Error Analysis:** Ask students to record any error codes or unexpected behaviors and compare them with the Troubleshooting table in the Handout.
|
|
4116
|
-
{{PHASE3_TESTING_STEPS}}
|
|
4117
|
-
|
|
4118
|
-
## [REQUIRED] 3-Tier Differentiation
|
|
4119
|
-
> MUST design tasks in 3 tiers to support diverse learner groups. Bronze is the minimum requirement for all students.
|
|
4120
|
-
- \u{1F949} **Bronze (Foundational):** {{DIFFERENTIATION_BRONZE}}
|
|
4121
|
-
- \u{1F948} **Silver (Application):** {{DIFFERENTIATION_SILVER}}
|
|
4122
|
-
- \u{1F947} **Gold (Enrichment/Creative):** {{DIFFERENTIATION_GOLD}}
|
|
4123
|
-
|
|
4124
|
-
## [REQUIRED] Reflection
|
|
4125
|
-
- **Discussion Question:** {{REFLECTION_QUESTION}}
|
|
4126
|
-
`.trim();
|
|
4127
|
-
|
|
4128
|
-
// src/templates/codeLabTemplate.ts
|
|
4129
|
-
var CODE_LAB_TEMPLATE = `
|
|
4130
|
-
---
|
|
4131
|
-
id: "{{ID}}"
|
|
4132
|
-
title: "{{TITLE}}"
|
|
4133
|
-
type: "LAB"
|
|
4134
|
-
created_by: "Curriculum OS Builder"
|
|
4135
|
-
phase: "{{PHASE}}"
|
|
4136
|
-
deliverable: "P3-T2"
|
|
4137
|
-
version: "{{VERSION}}"
|
|
4138
|
-
date: "{{DATE}}"
|
|
4139
|
-
---
|
|
4140
|
-
<!-- INJECT_BODY -->
|
|
4141
|
-
|
|
4142
|
-
# \u{1F468}\u200D\u{1F4BB} CODE LAB: {{TITLE}}
|
|
4143
|
-
_Milestone: {{MILESTONE_ID}} | Tech Stack: {{TECH_STACK}}_
|
|
4144
|
-
|
|
4145
|
-
## \u{1F3AF} Overview
|
|
4146
|
-
This lab focuses on the practical implementation of core technical concepts, bridging theory into working, robust, and testable code.
|
|
4147
|
-
|
|
4148
|
-
## \u{1F6E0}\uFE0F Environment & Setup
|
|
4149
|
-
- **Language / Framework:** {{LANGUAGE_FRAMEWORK}}
|
|
4150
|
-
- **IDE / Editor:** {{IDE_EDITOR}}
|
|
4151
|
-
- **Required Libraries:** {{REQUIRED_LIBRARIES}}
|
|
4152
|
-
- **Hardware / Connection Setup:** {{HARDWARE_ENV_CONNECTION}}
|
|
4153
|
-
|
|
4154
|
-
## \u{1F4DD} Lab Tasks (3-Tier Differentiation)
|
|
4155
|
-
|
|
4156
|
-
### \u{1F949} Bronze (Foundational) \u2014 {{BRONZE_MINS}} mins
|
|
4157
|
-
**Objective:** {{BRONZE_OBJECTIVE}}
|
|
4158
|
-
- **Task:** {{BRONZE_TASK}}
|
|
4159
|
-
- **Requirement:** {{BRONZE_REQUIREMENT}}
|
|
4160
|
-
|
|
4161
|
-
### \u{1F948} Silver (Application) \u2014 {{SILVER_MINS}} mins
|
|
4162
|
-
**Objective:** {{SILVER_OBJECTIVE}}
|
|
4163
|
-
- **Task:** {{SILVER_TASK}}
|
|
4164
|
-
- **Requirement:** {{SILVER_REQUIREMENT}}
|
|
4165
|
-
|
|
4166
|
-
### \u{1F947} Gold (Enrichment/Creative) \u2014 {{GOLD_MINS}} mins
|
|
4167
|
-
**Objective:** {{GOLD_OBJECTIVE}}
|
|
4168
|
-
- **Task:** {{GOLD_TASK}}
|
|
4169
|
-
- **Requirement:** {{GOLD_REQUIREMENT}}
|
|
4170
|
-
|
|
4171
|
-
## \u{1F4BB} Technical Reference ([SME_MANDATE])
|
|
4172
|
-
<!-- [SME_MANDATE] -->
|
|
4173
|
-
> Any code provided in this section is verified for syntax accuracy and runtime execution.
|
|
4174
|
-
|
|
4175
|
-
### Starter Code Template
|
|
4176
|
-
\`\`\`{{CODE_LANGUAGE}}
|
|
4177
|
-
{{STARTER_CODE}}
|
|
4178
|
-
\`\`\`
|
|
4179
|
-
|
|
4180
|
-
### Solution Code
|
|
4181
|
-
\`\`\`{{CODE_LANGUAGE}}
|
|
4182
|
-
{{SOLUTION_CODE}}
|
|
4183
|
-
\`\`\`
|
|
4184
|
-
<!-- [/SME_MANDATE] -->
|
|
4185
|
-
|
|
4186
|
-
## \u{1F50D} Troubleshooting & Debugging Matrix
|
|
4187
|
-
| Issue | Potential Cause | Solution |
|
|
4188
|
-
| :--- | :--- | :--- |
|
|
4189
|
-
{{TROUBLESHOOTING_ROWS}}
|
|
4190
|
-
|
|
4191
|
-
## \u{1F3C1} Submission & Verification Checklist
|
|
4192
|
-
{{CHECKLIST_ITEMS}}
|
|
4193
|
-
`.trim();
|
|
4194
|
-
|
|
4195
|
-
// src/templates/quizTemplate.ts
|
|
4196
|
-
var QUIZ_TEMPLATE = `
|
|
4197
|
-
---
|
|
4198
|
-
id: "{{ID}}"
|
|
4199
|
-
title: "{{TITLE}}"
|
|
4200
|
-
type: "QUIZ"
|
|
4201
|
-
language: "{{LANGUAGE}}"
|
|
4202
|
-
total_questions: {{TOTAL_QUESTIONS}}
|
|
4203
|
-
passing_score_pct: {{PASSING_SCORE_PCT}}
|
|
4204
|
-
---
|
|
4205
|
-
|
|
4206
|
-
# \u{1F9E0} Diagnostic & Active Recall Quiz: {{TITLE}}
|
|
4207
|
-
|
|
4208
|
-
> \u23F1\uFE0F **Recommended Time:** ~10-15 mins
|
|
4209
|
-
> \u{1F3AF} **Passing Score:** {{PASSING_SCORE_PCT}}%
|
|
4210
|
-
> \u{1F4A1} **Purpose:** Test your conceptual understanding, catch hidden misconceptions, and evaluate architectural trade-offs.
|
|
4211
|
-
|
|
4212
|
-
---
|
|
4213
|
-
|
|
4214
|
-
{{QUESTIONS_SECTION}}
|
|
4215
|
-
|
|
4216
|
-
---
|
|
4217
|
-
|
|
4218
|
-
## \u{1F511} Comprehensive Answer Key & Deep Explanation (Expand after completing)
|
|
4219
|
-
<details>
|
|
4220
|
-
<summary><b>\u{1F449} Click to View Full Explanations & Common Pitfall Analysis</b></summary>
|
|
4221
|
-
|
|
4222
|
-
{{ANSWER_KEY_SECTION}}
|
|
4223
|
-
</details>
|
|
4224
|
-
`.trim();
|
|
4225
|
-
|
|
4226
|
-
// src/templates/selfLabTemplate.ts
|
|
4227
|
-
var SELF_LAB_TEMPLATE = `
|
|
4228
|
-
---
|
|
4229
|
-
id: "{{ID}}"
|
|
4230
|
-
title: "{{TITLE}}"
|
|
4231
|
-
type: "SELF_LAB"
|
|
4232
|
-
language: "{{LANGUAGE}}"
|
|
4233
|
-
difficulty: "{{DIFFICULTY}}"
|
|
4234
|
-
estimated_minutes: {{ESTIMATED_MINUTES}}
|
|
4235
|
-
tech_stack: {{TECH_STACK}}
|
|
4236
|
-
---
|
|
4237
|
-
|
|
4238
|
-
# \u{1F680} Self-Paced Hands-On Lab: {{TITLE}}
|
|
4239
|
-
|
|
4240
|
-
> \u23F1\uFE0F **Estimated Duration:** ~{{ESTIMATED_MINUTES}} mins
|
|
4241
|
-
> \u{1F3AF} **Difficulty Level:** {{DIFFICULTY_UPPER}}
|
|
4242
|
-
> \u{1F9F0} **Tech Stack:** {{TECH_STACK_STR}}
|
|
4243
|
-
> \u{1F4A1} **Self-Learner Notice:** You are in full control of this lab. Follow the progressive challenges below. If you get stuck at any point, use the **Progressive Hints System** to get unstuck without ruining the learning experience!
|
|
4244
|
-
|
|
4245
|
-
---
|
|
4246
|
-
|
|
4247
|
-
## \u{1F4CB} Mission Briefing & Environment Setup
|
|
4248
|
-
{{MISSION_BRIEFING}}
|
|
4249
|
-
|
|
4250
|
-
### \u{1F6EB} Preflight Checklist
|
|
4251
|
-
{{PREFLIGHT_CHECKLIST}}
|
|
4252
|
-
|
|
4253
|
-
---
|
|
4254
|
-
|
|
4255
|
-
## \u{1F3AF} Progressive Challenges (3-Tier Differentiation)
|
|
4256
|
-
|
|
4257
|
-
### \u{1F949} Challenge 1: Foundational Core (Bronze) \u2014 ~{{BRONZE_MINS}} mins
|
|
4258
|
-
**Objective:** {{BRONZE_OBJECTIVE}}
|
|
4259
|
-
|
|
4260
|
-
#### Tasks & Implementation Details:
|
|
4261
|
-
{{BRONZE_TASKS}}
|
|
4262
|
-
|
|
4263
|
-
#### \u{1F9EA} Self-Verification Command:
|
|
4264
|
-
\`\`\`bash
|
|
4265
|
-
{{BRONZE_VERIFY_COMMAND}}
|
|
4266
|
-
\`\`\`
|
|
4267
|
-
*Expected Terminal Output:*
|
|
4268
|
-
\`\`\`text
|
|
4269
|
-
{{BRONZE_EXPECTED_OUTPUT}}
|
|
4270
|
-
\`\`\`
|
|
4271
|
-
|
|
4272
|
-
#### \u{1F4A1} Progressive Hints (Expand only if stuck):
|
|
4273
|
-
<details>
|
|
4274
|
-
<summary><b>\u{1F4A1} Hint Level 1: Conceptual Clue (H\u01B0\u1EDBng t\u01B0 duy)</b></summary>
|
|
4275
|
-
|
|
4276
|
-
{{BRONZE_HINT_1}}
|
|
4277
|
-
</details>
|
|
4278
|
-
|
|
4279
|
-
<details>
|
|
4280
|
-
<summary><b>\u{1F50D} Hint Level 2: Structural Skeleton (Khung code m\u1EABu)</b></summary>
|
|
4281
|
-
|
|
4282
|
-
\`\`\`{{CODE_LANGUAGE}}
|
|
4283
|
-
{{BRONZE_HINT_2}}
|
|
4284
|
-
\`\`\`
|
|
4285
|
-
</details>
|
|
4286
|
-
|
|
4287
|
-
<details>
|
|
4288
|
-
<summary><b>\u{1F6A8} Hint Level 3: Full Solution & Explanation (L\u1EDDi gi\u1EA3i tr\u1ECDn v\u1EB9n)</b></summary>
|
|
4289
|
-
|
|
4290
|
-
\`\`\`{{CODE_LANGUAGE}}
|
|
4291
|
-
{{BRONZE_HINT_3_CODE}}
|
|
4292
|
-
\`\`\`
|
|
4293
|
-
|
|
4294
|
-
**Why this solution works:**
|
|
4295
|
-
{{BRONZE_HINT_3_EXPLANATION}}
|
|
4296
|
-
</details>
|
|
4297
|
-
|
|
4298
|
-
---
|
|
4299
|
-
|
|
4300
|
-
### \u{1F948} Challenge 2: Logic & Error Handling (Silver) \u2014 ~{{SILVER_MINS}} mins
|
|
4301
|
-
**Objective:** {{SILVER_OBJECTIVE}}
|
|
4302
|
-
|
|
4303
|
-
#### Tasks & Implementation Details:
|
|
4304
|
-
{{SILVER_TASKS}}
|
|
4305
|
-
|
|
4306
|
-
#### \u{1F9EA} Self-Verification Command:
|
|
4307
|
-
\`\`\`bash
|
|
4308
|
-
{{SILVER_VERIFY_COMMAND}}
|
|
4309
|
-
\`\`\`
|
|
4310
|
-
*Expected Terminal Output:*
|
|
4311
|
-
\`\`\`text
|
|
4312
|
-
{{SILVER_EXPECTED_OUTPUT}}
|
|
4313
|
-
\`\`\`
|
|
4314
|
-
|
|
4315
|
-
#### \u{1F4A1} Progressive Hints (Expand only if stuck):
|
|
4316
|
-
<details>
|
|
4317
|
-
<summary><b>\u{1F4A1} Hint Level 1: Conceptual Clue (H\u01B0\u1EDBng t\u01B0 duy)</b></summary>
|
|
4318
|
-
|
|
4319
|
-
{{SILVER_HINT_1}}
|
|
4320
|
-
</details>
|
|
4321
|
-
|
|
4322
|
-
<details>
|
|
4323
|
-
<summary><b>\u{1F50D} Hint Level 2: Structural Skeleton (Khung code m\u1EABu)</b></summary>
|
|
4324
|
-
|
|
4325
|
-
\`\`\`{{CODE_LANGUAGE}}
|
|
4326
|
-
{{SILVER_HINT_2}}
|
|
4327
|
-
\`\`\`
|
|
4328
|
-
</details>
|
|
4329
|
-
|
|
4330
|
-
<details>
|
|
4331
|
-
<summary><b>\u{1F6A8} Hint Level 3: Full Solution & Explanation (L\u1EDDi gi\u1EA3i tr\u1ECDn v\u1EB9n)</b></summary>
|
|
4332
|
-
|
|
4333
|
-
\`\`\`{{CODE_LANGUAGE}}
|
|
4334
|
-
{{SILVER_HINT_3_CODE}}
|
|
4335
|
-
\`\`\`
|
|
4336
|
-
|
|
4337
|
-
**Why this solution works:**
|
|
4338
|
-
{{SILVER_HINT_3_EXPLANATION}}
|
|
4339
|
-
</details>
|
|
4340
|
-
|
|
4341
|
-
---
|
|
4342
|
-
|
|
4343
|
-
### \u{1F947} Challenge 3: Edge Cases & Optimization (Gold) \u2014 ~{{GOLD_MINS}} mins
|
|
4344
|
-
**Objective:** {{GOLD_OBJECTIVE}}
|
|
4345
|
-
|
|
4346
|
-
#### Tasks & Implementation Details:
|
|
4347
|
-
{{GOLD_TASKS}}
|
|
4348
|
-
|
|
4349
|
-
#### \u{1F9EA} Self-Verification Command:
|
|
4350
|
-
\`\`\`bash
|
|
4351
|
-
{{GOLD_VERIFY_COMMAND}}
|
|
4352
|
-
\`\`\`
|
|
4353
|
-
*Expected Terminal Output:*
|
|
4354
|
-
\`\`\`text
|
|
4355
|
-
{{GOLD_EXPECTED_OUTPUT}}
|
|
4356
|
-
\`\`\`
|
|
4357
|
-
|
|
4358
|
-
#### \u{1F4A1} Progressive Hints (Expand only if stuck):
|
|
4359
|
-
<details>
|
|
4360
|
-
<summary><b>\u{1F4A1} Hint Level 1: Conceptual Clue (H\u01B0\u1EDBng t\u01B0 duy)</b></summary>
|
|
4361
|
-
|
|
4362
|
-
{{GOLD_HINT_1}}
|
|
4363
|
-
</details>
|
|
4364
|
-
|
|
4365
|
-
<details>
|
|
4366
|
-
<summary><b>\u{1F50D} Hint Level 2: Structural Skeleton (Khung code m\u1EABu)</b></summary>
|
|
4367
|
-
|
|
4368
|
-
\`\`\`{{CODE_LANGUAGE}}
|
|
4369
|
-
{{GOLD_HINT_2}}
|
|
4370
|
-
\`\`\`
|
|
4371
|
-
</details>
|
|
4372
|
-
|
|
4373
|
-
<details>
|
|
4374
|
-
<summary><b>\u{1F6A8} Hint Level 3: Full Solution & Explanation (L\u1EDDi gi\u1EA3i tr\u1ECDn v\u1EB9n)</b></summary>
|
|
4375
|
-
|
|
4376
|
-
\`\`\`{{CODE_LANGUAGE}}
|
|
4377
|
-
{{GOLD_HINT_3_CODE}}
|
|
4378
|
-
\`\`\`
|
|
4379
|
-
|
|
4380
|
-
**Why this solution works:**
|
|
4381
|
-
{{GOLD_HINT_3_EXPLANATION}}
|
|
4382
|
-
</details>
|
|
4383
|
-
|
|
4384
|
-
---
|
|
4385
|
-
|
|
4386
|
-
## \u{1F50D} Self-Learner Troubleshooting Matrix
|
|
4387
|
-
| Symptom / Error Message | Root Cause | Exact Fix |
|
|
4388
|
-
| :--- | :--- | :--- |
|
|
4389
|
-
{{TROUBLESHOOTING_ROWS}}
|
|
4390
|
-
|
|
4391
|
-
---
|
|
4392
|
-
|
|
4393
|
-
## \u{1F3C1} Final Lab Submission & Mastery Checklist
|
|
4394
|
-
{{FINAL_CHECKLIST}}
|
|
4395
|
-
`.trim();
|
|
4396
|
-
|
|
4397
4172
|
// src/ai/prompts/lessonMasterPrompt.ts
|
|
4173
|
+
init_templateLoader();
|
|
4398
4174
|
function buildLessonMasterPrompt(input) {
|
|
4399
4175
|
const { milestone, language, topic, targetAudience, contextContinuity, standardsContext } = input;
|
|
4400
4176
|
const learningObjectives = milestone.learning_objectives || [];
|
|
@@ -4446,7 +4222,7 @@ Build a deep, rigorous, and highly pedagogical Master Lesson Plan (LESSON) that
|
|
|
4446
4222
|
# MANDATORY TEMPLATE STRUCTURE
|
|
4447
4223
|
You MUST generate structured data that will render directly into this exact Markdown template:
|
|
4448
4224
|
---
|
|
4449
|
-
${
|
|
4225
|
+
${loadAuthoringTemplate("LESSON_5E_template.md") ?? "[TEMPLATE FILE NOT FOUND: LESSON_5E_template.md]"}
|
|
4450
4226
|
---
|
|
4451
4227
|
|
|
4452
4228
|
# INPUT PARAMETERS
|
|
@@ -4496,6 +4272,7 @@ Return a single valid JSON object matching the LessonPlanSchema with these exact
|
|
|
4496
4272
|
}
|
|
4497
4273
|
|
|
4498
4274
|
// src/ai/prompts/activityPrompt.ts
|
|
4275
|
+
init_templateLoader();
|
|
4499
4276
|
function buildActivityPrompt(input) {
|
|
4500
4277
|
const { lesson, language, hardwareBOM, softwareTools } = input;
|
|
4501
4278
|
const loList = lesson.learningObjectives.map((lo) => `- [${lo.bloomLevel}] ${lo.code}: ${lo.name || ""} \u2014 ${lo.description}${lo.successCriteria ? ` (Evidence: ${lo.successCriteria})` : ""}`).join("\n");
|
|
@@ -4524,7 +4301,7 @@ Transform the exact pedagogical flow and activities from the Master Lesson Plan
|
|
|
4524
4301
|
# MANDATORY TEMPLATE STRUCTURE
|
|
4525
4302
|
You MUST generate data aligned with this Markdown template:
|
|
4526
4303
|
---
|
|
4527
|
-
${
|
|
4304
|
+
${loadAuthoringTemplate("ACT_template.md") ?? "[TEMPLATE FILE NOT FOUND: ACT_template.md]"}
|
|
4528
4305
|
---
|
|
4529
4306
|
|
|
4530
4307
|
# CANONICAL MASTER LESSON CONTEXT (SOURCE OF TRUTH)
|
|
@@ -4595,6 +4372,7 @@ Return a single JSON object matching ActivityLabSchema with these exact keys:
|
|
|
4595
4372
|
}
|
|
4596
4373
|
|
|
4597
4374
|
// src/ai/prompts/codeLabPrompt.ts
|
|
4375
|
+
init_templateLoader();
|
|
4598
4376
|
function buildCodeLabPrompt(input) {
|
|
4599
4377
|
const { lesson, activity, language, targetTechStack } = input;
|
|
4600
4378
|
const techStackList = targetTechStack && targetTechStack.length > 0 ? targetTechStack : ["General Programming & Engineering"];
|
|
@@ -4619,7 +4397,7 @@ Generate complete, verified source code that satisfies the lesson objectives and
|
|
|
4619
4397
|
# MANDATORY TEMPLATE STRUCTURE
|
|
4620
4398
|
You MUST generate data aligned with this Markdown template:
|
|
4621
4399
|
---
|
|
4622
|
-
${
|
|
4400
|
+
${loadAuthoringTemplate("LAB_TEMPLATE.md") ?? "[TEMPLATE FILE NOT FOUND: LAB_TEMPLATE.md]"}
|
|
4623
4401
|
---
|
|
4624
4402
|
|
|
4625
4403
|
# CANONICAL LESSON CONTEXT (SOURCE OF TRUTH)
|
|
@@ -5284,6 +5062,7 @@ Please return a single JSON object matching these exact keys:
|
|
|
5284
5062
|
}
|
|
5285
5063
|
|
|
5286
5064
|
// src/ai/prompts/selfLabPrompt.ts
|
|
5065
|
+
init_templateLoader();
|
|
5287
5066
|
function buildSelfLabPrompt(input) {
|
|
5288
5067
|
const { milestone, projectGraph, language, targetTechStack, contextContinuity } = input;
|
|
5289
5068
|
const techStackList = targetTechStack && targetTechStack.length > 0 ? targetTechStack : milestone.tech_keywords && milestone.tech_keywords.length > 0 ? milestone.tech_keywords : ["General Engineering"];
|
|
@@ -5314,7 +5093,7 @@ Build a complete, engaging Self-Paced Hands-On Lab (SELF_LAB) for autonomous lea
|
|
|
5314
5093
|
# MANDATORY TEMPLATE STRUCTURE
|
|
5315
5094
|
You MUST generate data aligned with this Markdown template:
|
|
5316
5095
|
---
|
|
5317
|
-
${
|
|
5096
|
+
${loadAuthoringTemplate("SELF_LAB_template.md") ?? "[TEMPLATE FILE NOT FOUND: SELF_LAB_template.md]"}
|
|
5318
5097
|
---
|
|
5319
5098
|
|
|
5320
5099
|
# INPUT PARAMETERS
|
|
@@ -5392,6 +5171,7 @@ Return a single valid JSON object matching SelfLabSchema with these exact keys:
|
|
|
5392
5171
|
}
|
|
5393
5172
|
|
|
5394
5173
|
// src/ai/prompts/diagnosticQuizPrompt.ts
|
|
5174
|
+
init_templateLoader();
|
|
5395
5175
|
function buildDiagnosticQuizPrompt(input) {
|
|
5396
5176
|
const { milestone, language, questionCount = 4, passingScorePct = 80 } = input;
|
|
5397
5177
|
const learningObjectives = milestone.learning_objectives || [];
|
|
@@ -5451,7 +5231,7 @@ Use this mapping to determine which Bloom level each question truly targets. Mat
|
|
|
5451
5231
|
# MANDATORY TEMPLATE STRUCTURE
|
|
5452
5232
|
You MUST generate data aligned with this Markdown template:
|
|
5453
5233
|
---
|
|
5454
|
-
${
|
|
5234
|
+
${loadAuthoringTemplate("QUIZ_v4.6_template.md") ?? "[TEMPLATE FILE NOT FOUND: QUIZ_v4.6_template.md]"}
|
|
5455
5235
|
---
|
|
5456
5236
|
|
|
5457
5237
|
# INPUT PARAMETERS
|
|
@@ -6856,7 +6636,7 @@ ${cc.technicalDepth}`;
|
|
|
6856
6636
|
const dataRows = cc.comparisonTable.rows.map((r) => `| ${r.join(" | ")} |`).join("\n");
|
|
6857
6637
|
str += `
|
|
6858
6638
|
|
|
6859
|
-
|
|
6639
|
+
**Comparison & Trade-off Analysis**
|
|
6860
6640
|
${headerRow}
|
|
6861
6641
|
${dividerRow}
|
|
6862
6642
|
${dataRows}`;
|
|
@@ -6900,7 +6680,8 @@ ${learningObjectivesStr}
|
|
|
6900
6680
|
|
|
6901
6681
|
---
|
|
6902
6682
|
|
|
6903
|
-
## 1. ENGAGE (Hook & High-Stakes Scenario)
|
|
6683
|
+
## 1. ENGAGE (Hook & High-Stakes Scenario)
|
|
6684
|
+
> **Duration:** 10-15 mins
|
|
6904
6685
|
|
|
6905
6686
|
### Real-World Context: "${lesson.hookTitle || "The Incident"}"
|
|
6906
6687
|
${lesson.hookScenario}
|
|
@@ -6909,13 +6690,15 @@ ${lesson.hookQuestions && lesson.hookQuestions.length > 0 ? lesson.hookQuestions
|
|
|
6909
6690
|
|
|
6910
6691
|
---
|
|
6911
6692
|
|
|
6912
|
-
## 2. EXPLORE & EXPLAIN (Core Technical Concepts & Principles)
|
|
6693
|
+
## 2. EXPLORE & EXPLAIN (Core Technical Concepts & Principles)
|
|
6694
|
+
> **Duration:** 30-40 mins
|
|
6913
6695
|
|
|
6914
6696
|
${coreConceptsStr}
|
|
6915
6697
|
|
|
6916
6698
|
---
|
|
6917
6699
|
|
|
6918
|
-
## 3. GUIDED PRACTICE (Visual Architecture & Annotated Code)
|
|
6700
|
+
## 3. GUIDED PRACTICE (Visual Architecture & Annotated Code)
|
|
6701
|
+
> **Duration:** 20-25 mins
|
|
6919
6702
|
|
|
6920
6703
|
### System Architecture & Data Flow (Mermaid Diagram)
|
|
6921
6704
|
${mermaidBlock}
|
|
@@ -6929,7 +6712,8 @@ ${guidedPractice.codeSnippet}
|
|
|
6929
6712
|
|
|
6930
6713
|
---
|
|
6931
6714
|
|
|
6932
|
-
## 4. ELABORATE & INDEPENDENT PRACTICE (Technical Challenge & Scaffolding)
|
|
6715
|
+
## 4. ELABORATE & INDEPENDENT PRACTICE (Technical Challenge & Scaffolding)
|
|
6716
|
+
> **Duration:** 15-20 mins
|
|
6933
6717
|
|
|
6934
6718
|
### Engineering Challenge: "${lesson.independentPractice?.title || "System Optimization Challenge"}"
|
|
6935
6719
|
${lesson.independentPractice?.description || "Implement the core logic and test against simulated edge cases."}
|
|
@@ -6940,7 +6724,8 @@ ${lesson.independentPractice?.description || "Implement the core logic and test
|
|
|
6940
6724
|
|
|
6941
6725
|
---
|
|
6942
6726
|
|
|
6943
|
-
## 5. EVALUATE (Summary, Assessment & Metacognition)
|
|
6727
|
+
## 5. EVALUATE (Summary, Assessment & Metacognition)
|
|
6728
|
+
> **Duration:** 5-10 mins
|
|
6944
6729
|
|
|
6945
6730
|
### Exit Ticket (Bloom: Apply / Analyze)
|
|
6946
6731
|
> **Scenario Question:** ${lesson.exitTicket.questionStem}
|
|
@@ -7033,12 +6818,16 @@ ${hardwareItems}
|
|
|
7033
6818
|
|
|
7034
6819
|
## [REQUIRED] Active Learning Workflow
|
|
7035
6820
|
|
|
7036
|
-
### Phase 1: Planning & Design
|
|
6821
|
+
### Phase 1: Planning & Design
|
|
6822
|
+
> **Duration:** ${phase1.durationMinutes} mins
|
|
6823
|
+
|
|
7037
6824
|
- **Student Task:** ${phase1.studentTask}
|
|
7038
6825
|
- **Teacher Action:** ${phase1.teacherAction}
|
|
7039
6826
|
${phase1.inquiryQuestions.map((q) => ` - *Inquiry Question:* ${q}`).join("\n")}
|
|
7040
6827
|
|
|
7041
|
-
### Phase 2: Implementation & Discovery
|
|
6828
|
+
### Phase 2: Implementation & Discovery
|
|
6829
|
+
> **Duration:** ${phase2.durationMinutes} mins
|
|
6830
|
+
|
|
7042
6831
|
- **Student Task:** ${phase2.studentTask}
|
|
7043
6832
|
- **Teacher Action:** ${phase2.teacherAction}
|
|
7044
6833
|
|
|
@@ -7046,7 +6835,9 @@ ${phase2.codeOrCommands.map((c) => `\`\`\`text
|
|
|
7046
6835
|
${c}
|
|
7047
6836
|
\`\`\``).join("\n\n")}
|
|
7048
6837
|
|
|
7049
|
-
### Phase 3: Debugging & Testing
|
|
6838
|
+
### Phase 3: Debugging & Testing
|
|
6839
|
+
> **Duration:** ${phase3.durationMinutes} mins
|
|
6840
|
+
|
|
7050
6841
|
- **Testing:** ${phase3.testingSteps}
|
|
7051
6842
|
- **Error Analysis:** ${phase3.errorAnalysis}
|
|
7052
6843
|
|
|
@@ -7101,22 +6892,28 @@ This lab focuses on the practical implementation of core technical concepts, bri
|
|
|
7101
6892
|
|
|
7102
6893
|
## \u{1F4DD} Lab Tasks (3-Tier Differentiation)
|
|
7103
6894
|
|
|
7104
|
-
### \u{1F949} Bronze (Foundational)
|
|
6895
|
+
### \u{1F949} Bronze (Foundational)
|
|
6896
|
+
> **Duration:** ${tasks.bronze.mins} mins
|
|
6897
|
+
|
|
7105
6898
|
**Objective:** ${tasks.bronze.objective}
|
|
7106
6899
|
- **Task:** ${tasks.bronze.task}
|
|
7107
6900
|
- **Requirement:** ${tasks.bronze.requirement}
|
|
7108
6901
|
|
|
7109
|
-
### \u{1F948} Silver (Application)
|
|
6902
|
+
### \u{1F948} Silver (Application)
|
|
6903
|
+
> **Duration:** ${tasks.silver.mins} mins
|
|
6904
|
+
|
|
7110
6905
|
**Objective:** ${tasks.silver.objective}
|
|
7111
6906
|
- **Task:** ${tasks.silver.task}
|
|
7112
6907
|
- **Requirement:** ${tasks.silver.requirement}
|
|
7113
6908
|
|
|
7114
|
-
### \u{1F947} Gold (Enrichment/Creative)
|
|
6909
|
+
### \u{1F947} Gold (Enrichment/Creative)
|
|
6910
|
+
> **Duration:** ${tasks.gold.mins} mins
|
|
6911
|
+
|
|
7115
6912
|
**Objective:** ${tasks.gold.objective}
|
|
7116
6913
|
- **Task:** ${tasks.gold.task}
|
|
7117
6914
|
- **Requirement:** ${tasks.gold.requirement}
|
|
7118
6915
|
|
|
7119
|
-
## \u{1F4BB} Technical Reference
|
|
6916
|
+
## \u{1F4BB} Technical Reference
|
|
7120
6917
|
<!-- [SME_MANDATE] -->
|
|
7121
6918
|
> Any code provided in this section is verified for syntax accuracy and runtime execution.
|
|
7122
6919
|
|
|
@@ -7254,7 +7051,9 @@ ${instruction.verificationChecklist.map((c) => `- [ ] ${c}`).join("\n")}
|
|
|
7254
7051
|
function serializeSelfLabToMarkdown(lab) {
|
|
7255
7052
|
const renderChallenge = (c, label) => {
|
|
7256
7053
|
const tasksList = c.tasks.map((t) => `- ${t}`).join("\n");
|
|
7257
|
-
return `### ${label}: ${c.title}
|
|
7054
|
+
return `### ${label}: ${c.title}
|
|
7055
|
+
> **Duration:** ~${c.estimatedMinutes} mins
|
|
7056
|
+
|
|
7258
7057
|
**Objective:** ${c.objective}
|
|
7259
7058
|
|
|
7260
7059
|
#### Tasks & Implementation Details:
|
|
@@ -7748,13 +7547,13 @@ async function generateSelfPacedBundle(input) {
|
|
|
7748
7547
|
if (input.outputDirectory) {
|
|
7749
7548
|
await fsPromises.mkdir(input.outputDirectory, { recursive: true });
|
|
7750
7549
|
await Promise.all([
|
|
7751
|
-
fsPromises.writeFile(
|
|
7752
|
-
fsPromises.writeFile(
|
|
7753
|
-
fsPromises.writeFile(
|
|
7754
|
-
fsPromises.writeFile(
|
|
7755
|
-
fsPromises.writeFile(
|
|
7756
|
-
fsPromises.writeFile(
|
|
7757
|
-
fsPromises.writeFile(
|
|
7550
|
+
fsPromises.writeFile(path4.join(input.outputDirectory, "INSTRUCTION.md"), instructionMd, "utf-8"),
|
|
7551
|
+
fsPromises.writeFile(path4.join(input.outputDirectory, "SELF_LAB.md"), selfLabMd, "utf-8"),
|
|
7552
|
+
fsPromises.writeFile(path4.join(input.outputDirectory, "QUIZ.md"), quizMd, "utf-8"),
|
|
7553
|
+
fsPromises.writeFile(path4.join(input.outputDirectory, "QUIZ.json"), JSON.stringify(quiz, null, 2), "utf-8"),
|
|
7554
|
+
fsPromises.writeFile(path4.join(input.outputDirectory, "CHEAT_SHEET.md"), cheatSheetMd, "utf-8"),
|
|
7555
|
+
fsPromises.writeFile(path4.join(input.outputDirectory, "LAB.md"), codeLabMd, "utf-8"),
|
|
7556
|
+
fsPromises.writeFile(path4.join(input.outputDirectory, "bundle.json"), JSON.stringify(bundle, null, 2), "utf-8")
|
|
7758
7557
|
]);
|
|
7759
7558
|
}
|
|
7760
7559
|
return {
|
|
@@ -8155,15 +7954,15 @@ var STANDARD_SOT_FILES = [
|
|
|
8155
7954
|
"ALIGNMENT_MATRIX.md"
|
|
8156
7955
|
];
|
|
8157
7956
|
function atomicWriteFileSync(targetPath, content) {
|
|
8158
|
-
const dir =
|
|
8159
|
-
if (!
|
|
8160
|
-
const tmpPath =
|
|
7957
|
+
const dir = path4.dirname(targetPath);
|
|
7958
|
+
if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
|
|
7959
|
+
const tmpPath = path4.join(dir, `.${path4.basename(targetPath)}.${process.pid}.${Date.now()}.${crypto.randomBytes(4).toString("hex")}.tmp`);
|
|
8161
7960
|
try {
|
|
8162
|
-
|
|
8163
|
-
|
|
7961
|
+
fs3.writeFileSync(tmpPath, content, "utf-8");
|
|
7962
|
+
fs3.renameSync(tmpPath, targetPath);
|
|
8164
7963
|
} catch (err) {
|
|
8165
7964
|
try {
|
|
8166
|
-
if (
|
|
7965
|
+
if (fs3.existsSync(tmpPath)) fs3.unlinkSync(tmpPath);
|
|
8167
7966
|
} catch {
|
|
8168
7967
|
}
|
|
8169
7968
|
throw err;
|
|
@@ -8172,51 +7971,51 @@ function atomicWriteFileSync(targetPath, content) {
|
|
|
8172
7971
|
var FileSystemCurriculumAdapter = class {
|
|
8173
7972
|
baseDir;
|
|
8174
7973
|
constructor(options = {}) {
|
|
8175
|
-
this.baseDir = options.baseDir ||
|
|
7974
|
+
this.baseDir = options.baseDir || path4.resolve(process.cwd(), "output", "projects");
|
|
8176
7975
|
}
|
|
8177
7976
|
getProjectDir(projectId) {
|
|
8178
7977
|
const raw = (projectId || "").replace("proj_", "");
|
|
8179
|
-
const directPath =
|
|
8180
|
-
if (
|
|
8181
|
-
const fullIdPath =
|
|
8182
|
-
if (
|
|
7978
|
+
const directPath = path4.join(this.baseDir, raw);
|
|
7979
|
+
if (fs3.existsSync(directPath)) return directPath;
|
|
7980
|
+
const fullIdPath = path4.join(this.baseDir, projectId);
|
|
7981
|
+
if (fs3.existsSync(fullIdPath)) return fullIdPath;
|
|
8183
7982
|
return directPath;
|
|
8184
7983
|
}
|
|
8185
7984
|
/** Ensures the resolved path stays within the project directory (prevents path traversal). */
|
|
8186
7985
|
assertInsideProject(projectDir, targetPath) {
|
|
8187
|
-
const resolvedProject =
|
|
8188
|
-
const resolvedTarget =
|
|
8189
|
-
if (!resolvedTarget.startsWith(resolvedProject +
|
|
7986
|
+
const resolvedProject = path4.resolve(projectDir);
|
|
7987
|
+
const resolvedTarget = path4.resolve(targetPath);
|
|
7988
|
+
if (!resolvedTarget.startsWith(resolvedProject + path4.sep) && resolvedTarget !== resolvedProject) {
|
|
8190
7989
|
throw new Error(`[FileSystemCurriculumAdapter] Path traversal blocked: ${targetPath} is outside project directory ${projectDir}`);
|
|
8191
7990
|
}
|
|
8192
7991
|
}
|
|
8193
7992
|
async projectExists(projectId) {
|
|
8194
|
-
return
|
|
7993
|
+
return fs3.existsSync(this.getProjectDir(projectId));
|
|
8195
7994
|
}
|
|
8196
7995
|
async readSotDocument(projectId, filename) {
|
|
8197
7996
|
const projectDir = this.getProjectDir(projectId);
|
|
8198
7997
|
const possiblePaths = [
|
|
8199
|
-
|
|
8200
|
-
|
|
7998
|
+
path4.join(projectDir, "_sot", filename),
|
|
7999
|
+
path4.join(projectDir, filename)
|
|
8201
8000
|
];
|
|
8202
8001
|
for (const p of possiblePaths) {
|
|
8203
|
-
if (
|
|
8204
|
-
return
|
|
8002
|
+
if (fs3.existsSync(p) && fs3.statSync(p).isFile()) {
|
|
8003
|
+
return fs3.readFileSync(p, "utf-8");
|
|
8205
8004
|
}
|
|
8206
8005
|
}
|
|
8207
8006
|
return null;
|
|
8208
8007
|
}
|
|
8209
8008
|
async listSotDocuments(projectId) {
|
|
8210
8009
|
const projectDir = this.getProjectDir(projectId);
|
|
8211
|
-
const sotDir =
|
|
8010
|
+
const sotDir = path4.join(projectDir, "_sot");
|
|
8212
8011
|
const discoveredFiles = new Set(STANDARD_SOT_FILES);
|
|
8213
|
-
if (
|
|
8012
|
+
if (fs3.existsSync(sotDir)) {
|
|
8214
8013
|
try {
|
|
8215
|
-
const diskFiles =
|
|
8014
|
+
const diskFiles = fs3.readdirSync(sotDir);
|
|
8216
8015
|
for (const f of diskFiles) {
|
|
8217
8016
|
if (f.startsWith(".") || f.endsWith(".review.json")) continue;
|
|
8218
|
-
const fullPath =
|
|
8219
|
-
if (
|
|
8017
|
+
const fullPath = path4.join(sotDir, f);
|
|
8018
|
+
if (fs3.statSync(fullPath).isFile()) {
|
|
8220
8019
|
discoveredFiles.add(f);
|
|
8221
8020
|
}
|
|
8222
8021
|
}
|
|
@@ -8224,9 +8023,9 @@ var FileSystemCurriculumAdapter = class {
|
|
|
8224
8023
|
}
|
|
8225
8024
|
}
|
|
8226
8025
|
return Array.from(discoveredFiles).map((filename) => {
|
|
8227
|
-
const p =
|
|
8228
|
-
if (p &&
|
|
8229
|
-
const stats =
|
|
8026
|
+
const p = fs3.existsSync(path4.join(sotDir, filename)) ? path4.join(sotDir, filename) : fs3.existsSync(path4.join(projectDir, filename)) ? path4.join(projectDir, filename) : null;
|
|
8027
|
+
if (p && fs3.existsSync(p)) {
|
|
8028
|
+
const stats = fs3.statSync(p);
|
|
8230
8029
|
return {
|
|
8231
8030
|
name: filename.replace(/\.(md|json)$/i, "").replace(/_/g, " "),
|
|
8232
8031
|
filename,
|
|
@@ -8244,18 +8043,18 @@ var FileSystemCurriculumAdapter = class {
|
|
|
8244
8043
|
}
|
|
8245
8044
|
async readArtifact(projectId, relPathOrIdentifier) {
|
|
8246
8045
|
const projectDir = this.getProjectDir(projectId);
|
|
8247
|
-
const directCandidate =
|
|
8046
|
+
const directCandidate = path4.join(projectDir, relPathOrIdentifier);
|
|
8248
8047
|
this.assertInsideProject(projectDir, directCandidate);
|
|
8249
8048
|
const possiblePaths = [
|
|
8250
8049
|
directCandidate,
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8050
|
+
path4.join(projectDir, "_sot", relPathOrIdentifier),
|
|
8051
|
+
path4.join(projectDir, "lessons", relPathOrIdentifier),
|
|
8052
|
+
path4.join(projectDir, "_sot", path4.basename(relPathOrIdentifier)),
|
|
8053
|
+
path4.join(projectDir, "lessons", path4.basename(relPathOrIdentifier))
|
|
8255
8054
|
];
|
|
8256
8055
|
for (const p of possiblePaths) {
|
|
8257
|
-
if (
|
|
8258
|
-
return
|
|
8056
|
+
if (fs3.existsSync(p) && fs3.statSync(p).isFile()) {
|
|
8057
|
+
return fs3.readFileSync(p, "utf-8");
|
|
8259
8058
|
}
|
|
8260
8059
|
}
|
|
8261
8060
|
if (relPathOrIdentifier.includes(".md") || relPathOrIdentifier.includes("/")) {
|
|
@@ -8264,8 +8063,8 @@ var FileSystemCurriculumAdapter = class {
|
|
|
8264
8063
|
const lessonMatch = relPathOrIdentifier.match(/U\d+_M\d+_L\d+/i);
|
|
8265
8064
|
if (lessonMatch) {
|
|
8266
8065
|
const lessonId = lessonMatch[0].toUpperCase();
|
|
8267
|
-
const lessonDir =
|
|
8268
|
-
if (
|
|
8066
|
+
const lessonDir = path4.join(projectDir, "lessons", lessonId);
|
|
8067
|
+
if (fs3.existsSync(lessonDir) && fs3.statSync(lessonDir).isDirectory()) {
|
|
8269
8068
|
const lower = relPathOrIdentifier.toLowerCase();
|
|
8270
8069
|
let artifactPrefix = "LESSON";
|
|
8271
8070
|
if (lower.includes("act") || lower.includes("lab") || lower.includes("th\u1EF1c h\xE0nh")) {
|
|
@@ -8285,9 +8084,9 @@ var FileSystemCurriculumAdapter = class {
|
|
|
8285
8084
|
} else if (lower.includes("ext") || lower.includes("extension")) {
|
|
8286
8085
|
artifactPrefix = "EXT";
|
|
8287
8086
|
}
|
|
8288
|
-
const candidateFile =
|
|
8289
|
-
if (
|
|
8290
|
-
return
|
|
8087
|
+
const candidateFile = path4.join(lessonDir, `${artifactPrefix}_${lessonId}.md`);
|
|
8088
|
+
if (fs3.existsSync(candidateFile)) {
|
|
8089
|
+
return fs3.readFileSync(candidateFile, "utf-8");
|
|
8291
8090
|
}
|
|
8292
8091
|
}
|
|
8293
8092
|
}
|
|
@@ -8295,22 +8094,22 @@ var FileSystemCurriculumAdapter = class {
|
|
|
8295
8094
|
}
|
|
8296
8095
|
async saveArtifact(projectId, relPath, content) {
|
|
8297
8096
|
const projectDir = this.getProjectDir(projectId);
|
|
8298
|
-
const targetPath =
|
|
8097
|
+
const targetPath = path4.join(projectDir, relPath);
|
|
8299
8098
|
this.assertInsideProject(projectDir, targetPath);
|
|
8300
|
-
const targetDir =
|
|
8301
|
-
if (!
|
|
8302
|
-
|
|
8099
|
+
const targetDir = path4.dirname(targetPath);
|
|
8100
|
+
if (!fs3.existsSync(targetDir)) {
|
|
8101
|
+
fs3.mkdirSync(targetDir, { recursive: true });
|
|
8303
8102
|
}
|
|
8304
|
-
if (
|
|
8103
|
+
if (fs3.existsSync(targetPath)) {
|
|
8305
8104
|
try {
|
|
8306
|
-
const oldContent =
|
|
8105
|
+
const oldContent = fs3.readFileSync(targetPath, "utf-8");
|
|
8307
8106
|
if (oldContent !== content) {
|
|
8308
|
-
const historyDir =
|
|
8309
|
-
|
|
8310
|
-
atomicWriteFileSync(
|
|
8311
|
-
const versions =
|
|
8107
|
+
const historyDir = path4.join(projectDir, ".history", relPath);
|
|
8108
|
+
fs3.mkdirSync(historyDir, { recursive: true });
|
|
8109
|
+
atomicWriteFileSync(path4.join(historyDir, `${Date.now()}.md`), oldContent);
|
|
8110
|
+
const versions = fs3.readdirSync(historyDir).filter((f) => f.endsWith(".md")).sort();
|
|
8312
8111
|
while (versions.length > 10) {
|
|
8313
|
-
|
|
8112
|
+
fs3.unlinkSync(path4.join(historyDir, versions.shift()));
|
|
8314
8113
|
}
|
|
8315
8114
|
}
|
|
8316
8115
|
} catch (histErr) {
|
|
@@ -8318,24 +8117,24 @@ var FileSystemCurriculumAdapter = class {
|
|
|
8318
8117
|
}
|
|
8319
8118
|
}
|
|
8320
8119
|
atomicWriteFileSync(targetPath, content);
|
|
8321
|
-
const filename =
|
|
8120
|
+
const filename = path4.basename(relPath);
|
|
8322
8121
|
const match = filename.match(/(LESSON|ACT|QUIZ|SLIDE|GUIDE|HANDOUT|WKS|EXT)_(U\d+_M\d+_L\d+)\.md/i);
|
|
8323
8122
|
if (match) {
|
|
8324
8123
|
const lessonId = match[2].toUpperCase();
|
|
8325
|
-
atomicWriteFileSync(
|
|
8326
|
-
const legacyContentDir =
|
|
8327
|
-
if (
|
|
8328
|
-
atomicWriteFileSync(
|
|
8124
|
+
atomicWriteFileSync(path4.join(projectDir, "lessons", lessonId, filename), content);
|
|
8125
|
+
const legacyContentDir = path4.join(projectDir, "_content", lessonId);
|
|
8126
|
+
if (fs3.existsSync(legacyContentDir)) {
|
|
8127
|
+
atomicWriteFileSync(path4.join(legacyContentDir, filename), content);
|
|
8329
8128
|
}
|
|
8330
8129
|
}
|
|
8331
8130
|
}
|
|
8332
8131
|
async listLessons(projectId) {
|
|
8333
|
-
const lessonsDir =
|
|
8334
|
-
if (!
|
|
8335
|
-
const lessonFolders =
|
|
8132
|
+
const lessonsDir = path4.join(this.getProjectDir(projectId), "lessons");
|
|
8133
|
+
if (!fs3.existsSync(lessonsDir)) return [];
|
|
8134
|
+
const lessonFolders = fs3.readdirSync(lessonsDir).filter((f) => !f.startsWith("."));
|
|
8336
8135
|
return lessonFolders.map((folder) => {
|
|
8337
|
-
const lDir =
|
|
8338
|
-
const isDir =
|
|
8136
|
+
const lDir = path4.join(lessonsDir, folder);
|
|
8137
|
+
const isDir = fs3.statSync(lDir).isDirectory();
|
|
8339
8138
|
if (!isDir) {
|
|
8340
8139
|
return {
|
|
8341
8140
|
lessonId: folder,
|
|
@@ -8344,7 +8143,7 @@ var FileSystemCurriculumAdapter = class {
|
|
|
8344
8143
|
artifacts: []
|
|
8345
8144
|
};
|
|
8346
8145
|
}
|
|
8347
|
-
const artifacts =
|
|
8146
|
+
const artifacts = fs3.readdirSync(lDir).filter((f) => !f.startsWith("."));
|
|
8348
8147
|
return {
|
|
8349
8148
|
lessonId: folder,
|
|
8350
8149
|
artifactsCount: artifacts.length,
|
|
@@ -8390,10 +8189,10 @@ ${lessonTable}
|
|
|
8390
8189
|
}
|
|
8391
8190
|
async getPipelineState(projectId) {
|
|
8392
8191
|
const projectDir = this.getProjectDir(projectId);
|
|
8393
|
-
const stateFile =
|
|
8394
|
-
if (
|
|
8192
|
+
const stateFile = path4.join(projectDir, "_pipeline", "state.json");
|
|
8193
|
+
if (fs3.existsSync(stateFile)) {
|
|
8395
8194
|
try {
|
|
8396
|
-
const raw =
|
|
8195
|
+
const raw = fs3.readFileSync(stateFile, "utf-8");
|
|
8397
8196
|
const parsed = JSON.parse(raw);
|
|
8398
8197
|
if (parsed && typeof parsed === "object" && parsed.tasks) {
|
|
8399
8198
|
return parsed;
|
|
@@ -8410,11 +8209,11 @@ ${lessonTable}
|
|
|
8410
8209
|
}
|
|
8411
8210
|
async savePipelineState(projectId, state) {
|
|
8412
8211
|
const projectDir = this.getProjectDir(projectId);
|
|
8413
|
-
const pipelineDir =
|
|
8414
|
-
if (!
|
|
8415
|
-
|
|
8212
|
+
const pipelineDir = path4.join(projectDir, "_pipeline");
|
|
8213
|
+
if (!fs3.existsSync(pipelineDir)) {
|
|
8214
|
+
fs3.mkdirSync(pipelineDir, { recursive: true });
|
|
8416
8215
|
}
|
|
8417
|
-
const stateFile =
|
|
8216
|
+
const stateFile = path4.join(pipelineDir, "state.json");
|
|
8418
8217
|
state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8419
8218
|
atomicWriteFileSync(stateFile, JSON.stringify(state, null, 2));
|
|
8420
8219
|
}
|
|
@@ -8437,9 +8236,9 @@ ${lessonTable}
|
|
|
8437
8236
|
async deleteArtifact(projectId, relPath) {
|
|
8438
8237
|
try {
|
|
8439
8238
|
const projectDir = this.getProjectDir(projectId);
|
|
8440
|
-
const targetPath =
|
|
8239
|
+
const targetPath = path4.join(projectDir, relPath);
|
|
8441
8240
|
this.assertInsideProject(projectDir, targetPath);
|
|
8442
|
-
if (
|
|
8241
|
+
if (fs3.existsSync(targetPath)) fs3.rmSync(targetPath, { force: true });
|
|
8443
8242
|
} catch {
|
|
8444
8243
|
}
|
|
8445
8244
|
}
|
|
@@ -9189,19 +8988,19 @@ function buildStandardStackMarkdown(opts) {
|
|
|
9189
8988
|
|
|
9190
8989
|
// src/services/sotGeneratorService.ts
|
|
9191
8990
|
var __filename$1 = typeof import.meta?.url === "string" && typeof fileURLToPath === "function" ? fileURLToPath(import.meta.url) : "";
|
|
9192
|
-
var __dirname2 = __filename$1 ?
|
|
8991
|
+
var __dirname2 = __filename$1 ? path4.dirname(__filename$1) : process.cwd();
|
|
9193
8992
|
function loadSotTemplate(templateFileName) {
|
|
9194
8993
|
const possiblePaths = [
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
8994
|
+
path4.resolve(__dirname2, "../../docs/refs/templates", templateFileName),
|
|
8995
|
+
path4.resolve(process.cwd(), "packages/curriculum-kit/docs/refs/templates", templateFileName),
|
|
8996
|
+
path4.resolve(process.cwd(), "../learnwell-platform/packages/curriculum-kit/docs/refs/templates", templateFileName),
|
|
8997
|
+
path4.resolve("/Users/tonypham/MEGA/WebApp/WIP/learnwell-platform/packages/curriculum-kit/docs/refs/templates", templateFileName),
|
|
8998
|
+
path4.resolve("/Users/tonypham/MEGA/ai-platform/learning-artifact-gen-ui/_templates", templateFileName)
|
|
9200
8999
|
];
|
|
9201
9000
|
for (const p of possiblePaths) {
|
|
9202
|
-
if (
|
|
9001
|
+
if (fs3.existsSync(p)) {
|
|
9203
9002
|
try {
|
|
9204
|
-
return
|
|
9003
|
+
return fs3.readFileSync(p, "utf-8");
|
|
9205
9004
|
} catch {
|
|
9206
9005
|
}
|
|
9207
9006
|
}
|
|
@@ -9617,6 +9416,7 @@ function gateModeFor(resolved, type) {
|
|
|
9617
9416
|
}
|
|
9618
9417
|
|
|
9619
9418
|
// src/services/languageDirective.ts
|
|
9419
|
+
init_templateLoader();
|
|
9620
9420
|
function resolveTargetLanguageCode(language) {
|
|
9621
9421
|
const raw = String(language || "vi").trim().toLowerCase();
|
|
9622
9422
|
if (raw.startsWith("vi")) return "vi";
|
|
@@ -9657,137 +9457,58 @@ function matchesArtifactType(candidate, target) {
|
|
|
9657
9457
|
if ((c === "EXT" || c === "EXTENSION") && (t === "EXT" || t === "EXTENSION")) return true;
|
|
9658
9458
|
return false;
|
|
9659
9459
|
}
|
|
9660
|
-
var
|
|
9661
|
-
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
"Examples & Context Rules": "Quy t\u1EAFc V\xED d\u1EE5 & Ng\u1EEF c\u1EA3nh",
|
|
9683
|
-
"Lesson Content Standards": "Ti\xEAu chu\u1EA9n N\u1ED9i dung B\xE0i h\u1ECDc"
|
|
9684
|
-
},
|
|
9685
|
-
SECTION_LANGUAGE_CONTRACT: {
|
|
9686
|
-
"Metadata & Scope": "Th\xF4ng tin & Ph\u1EA1m vi H\u1EE3p \u0111\u1ED3ng",
|
|
9687
|
-
"Section Translation Matrix": "Ma tr\u1EADn Ti\xEAu \u0111\u1EC1 \u0110a ng\xF4n ng\u1EEF",
|
|
9688
|
-
"Validation Rules": "Quy t\u1EAFc X\xE1c th\u1EF1c & Kh\xF3a Chu\u1EA9n"
|
|
9689
|
-
},
|
|
9690
|
-
KNOWLEDGE_EXPOSITION: {
|
|
9691
|
-
"Session Scope": "Ph\u1EA1m vi Bu\u1ED5i h\u1ECDc",
|
|
9692
|
-
"Key Terms": "Thu\u1EADt ng\u1EEF Then ch\u1ED1t",
|
|
9693
|
-
"Concept Narratives": "Di\u1EC5n gi\u1EA3i Kh\xE1i ni\u1EC7m",
|
|
9694
|
-
"Worked Micro-Examples": "V\xED d\u1EE5 M\u1EABu Chi ti\u1EBFt",
|
|
9695
|
-
"Common Mistakes": "L\u1ED7i Th\u01B0\u1EDDng g\u1EB7p & Kh\u1EAFc ph\u1EE5c",
|
|
9696
|
-
"Self-Check Questions": "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra"
|
|
9697
|
-
},
|
|
9698
|
-
LESSON: {
|
|
9699
|
-
"A. Lesson Design Plan": "A. K\u1EBF ho\u1EA1ch Thi\u1EBFt k\u1EBF B\xE0i h\u1ECDc",
|
|
9700
|
-
"Learning Objectives & Evidence": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp & B\u1EB1ng ch\u1EE9ng N\u0103ng l\u1EF1c",
|
|
9701
|
-
"Activity Sequence": "Chu\u1ED7i Ho\u1EA1t \u0111\u1ED9ng D\u1EA1y & H\u1ECDc",
|
|
9702
|
-
"Resource Map": "B\u1EA3n \u0111\u1ED3 T\xE0i nguy\xEAn & H\u1ECDc li\u1EC7u",
|
|
9703
|
-
"Assessment Map": "B\u1EA3n \u0111\u1ED3 \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c",
|
|
9704
|
-
"Artifact Contract": "H\u1EE3p \u0111\u1ED3ng S\u1EA3n ph\u1EA9m \u0110\u1EA7u ra",
|
|
9705
|
-
"B. Lesson Flow": "B. Ti\u1EBFn tr\xECnh Gi\u1EA3ng d\u1EA1y Chi ti\u1EBFt"
|
|
9706
|
-
},
|
|
9707
|
-
ACT: {
|
|
9708
|
-
"Computational Thinking Focus": "Tr\u1ECDng t\xE2m T\u01B0 duy M\xE1y t\xEDnh",
|
|
9709
|
-
"Materials & Setup": "V\u1EADt li\u1EC7u & Chu\u1EA9n b\u1ECB Thi\u1EBFt b\u1ECB",
|
|
9710
|
-
"Constraints & Safety": "R\xE0ng bu\u1ED9c & An to\xE0n Ph\xF2ng th\u1EF1c h\xE0nh",
|
|
9711
|
-
"Active Learning Workflow": "Quy tr\xECnh Ho\u1EA1t \u0111\u1ED9ng Tr\u1EA3i nghi\u1EC7m",
|
|
9712
|
-
"3-Tier Differentiation": "Ph\xE2n h\xF3a H\u1ECDc t\u1EADp 3 T\u1EA7ng",
|
|
9713
|
-
"Reflection": "T\u1ED5ng k\u1EBFt & \u0110\xFAc k\u1EBFt Tr\u1EA3i nghi\u1EC7m"
|
|
9714
|
-
},
|
|
9715
|
-
CODE: {
|
|
9716
|
-
"Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
|
|
9717
|
-
"Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
|
|
9718
|
-
"Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
|
|
9719
|
-
"Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
|
|
9720
|
-
"Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
|
|
9721
|
-
"Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
|
|
9722
|
-
},
|
|
9723
|
-
CODE_LAB: {
|
|
9724
|
-
"Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
|
|
9725
|
-
"Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
|
|
9726
|
-
"Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
|
|
9727
|
-
"Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
|
|
9728
|
-
"Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
|
|
9729
|
-
"Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
|
|
9730
|
-
},
|
|
9731
|
-
QUIZ: {
|
|
9732
|
-
"Assessment Objectives": "M\u1EE5c ti\xEAu \u0110\xE1nh gi\xE1",
|
|
9733
|
-
"Multiple-Choice Question Bank": "Ng\xE2n h\xE0ng C\xE2u h\u1ECFi Tr\u1EAFc nghi\u1EC7m",
|
|
9734
|
-
"Code Analysis / Debugging Question": "C\xE2u h\u1ECFi Ph\xE2n t\xEDch M\xE3 ngu\u1ED3n & S\u1EEDa l\u1ED7i",
|
|
9735
|
-
"Competency Rubric": "Thang \u0111o \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c (Rubric)"
|
|
9736
|
-
},
|
|
9737
|
-
GUIDE: {
|
|
9738
|
-
"Objectives & Preparation": "M\u1EE5c ti\xEAu & Chu\u1EA9n b\u1ECB Gi\u1EA3ng d\u1EA1y",
|
|
9739
|
-
"Preparation Checklist & Workstation Setup": "Danh m\u1EE5c Ki\u1EC3m tra Chu\u1EA9n b\u1ECB & Tr\u1EA1m Th\u1EF1c h\xE0nh",
|
|
9740
|
-
"Facilitation Script & Timeline": "K\u1ECBch b\u1EA3n \u0110i\u1EC1u ph\u1ED1i & Khung Th\u1EDDi gian",
|
|
9741
|
-
"Common Misconceptions & Diagnostic Remediation Matrix": "Quan ni\u1EC7m Sai l\u1EA7m Th\u01B0\u1EDDng g\u1EB7p & Ma tr\u1EADn Kh\u1EAFc ph\u1EE5c",
|
|
9742
|
-
"Differentiated Support Strategies": "Chi\u1EBFn l\u01B0\u1EE3c H\u1ED7 tr\u1EE3 Ph\xE2n h\xF3a"
|
|
9743
|
-
},
|
|
9744
|
-
HANDOUT: {
|
|
9745
|
-
"Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
|
|
9746
|
-
"Core Syntax & Mechanism Cheat Sheet": "B\u1EA3ng Tra c\u1EE9u C\xFA ph\xE1p & C\u01A1 ch\u1EBF Tr\u1ECDng t\xE2m",
|
|
9747
|
-
"Visual Mental Model / Architecture Diagram": "M\xF4 h\xECnh T\u01B0 duy Tr\u1EF1c quan / S\u01A1 \u0111\u1ED3 Ki\u1EBFn tr\xFAc",
|
|
9748
|
-
"Step-by-Step Practical Quick-Start Guide": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh T\u1EEBng b\u01B0\u1EDBc",
|
|
9749
|
-
"Self-Check Diagnostic Checklist": "B\u1EA3ng Ki\u1EC3m tra T\u1EF1 ch\u1EA9n \u0111o\xE1n"
|
|
9750
|
-
},
|
|
9751
|
-
WKS: {
|
|
9752
|
-
"Part 1: Knowledge Check": "Ph\u1EA7n 1: Ki\u1EC3m tra Ki\u1EBFn th\u1EE9c",
|
|
9753
|
-
"Part 2: Concept Tracing & Diagram Fill-in": "Ph\u1EA7n 2: L\u1EA7n v\u1EBFt Kh\xE1i ni\u1EC7m & \u0110i\u1EC1n S\u01A1 \u0111\u1ED3",
|
|
9754
|
-
"Part 3: Code Analysis & Bug Hunting Challenge": "Ph\u1EA7n 3: Ph\xE2n t\xEDch M\xE3 & Th\u1EED th\xE1ch S\u0103n l\u1ED7i",
|
|
9755
|
-
"Part 4: Synthesis & Problem-Solving Application": "Ph\u1EA7n 4: T\u1ED5ng h\u1EE3p & \u1EE8ng d\u1EE5ng Gi\u1EA3i quy\u1EBFt V\u1EA5n \u0111\u1EC1",
|
|
9756
|
-
"Part 5: Self-Reflection & Learning Log": "Ph\u1EA7n 5: T\u1EF1 suy ng\u1EABm & Nh\u1EADt k\xFD H\u1ECDc t\u1EADp"
|
|
9757
|
-
},
|
|
9758
|
-
EXT: {
|
|
9759
|
-
"For: Advanced Students / Extra Time": "D\xE0nh cho: H\u1ECDc sinh N\xE2ng cao / Ho\xE0n th\xE0nh S\u1EDBm",
|
|
9760
|
-
"Challenge 1: Mission Briefing & Real-World High-Stakes Scenario": "Th\u1EED th\xE1ch 1: B\u1ED1i c\u1EA3nh Nhi\u1EC7m v\u1EE5 Th\u1EF1c t\u1EBF & K\u1ECBch b\u1EA3n \u1EE8ng d\u1EE5ng",
|
|
9761
|
-
"Challenge 2: Advanced Architectural Constraints & Edge Cases": "Th\u1EED th\xE1ch 2: R\xE0ng bu\u1ED9c Ki\u1EBFn tr\xFAc N\xE2ng cao & Tr\u01B0\u1EDDng h\u1EE3p Bi\xEAn",
|
|
9762
|
-
"Challenge 3: Extension Milestones": "Th\u1EED th\xE1ch 3: C\xE1c M\u1ED1c Nhi\u1EC7m v\u1EE5 N\xE2ng cao",
|
|
9763
|
-
"Metacognitive Deep Dive & Engineering Trade-offs": "Suy ng\u1EABm Si\xEAu nh\u1EADn th\u1EE9c & \u0110\xE1nh \u0111\u1ED5i K\u1EF9 thu\u1EADt"
|
|
9764
|
-
},
|
|
9765
|
-
SLIDE: {
|
|
9766
|
-
"Title & Agenda": "Ti\xEAu \u0111\u1EC1 & M\u1EE5c l\u1EE5c",
|
|
9767
|
-
"Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
|
|
9768
|
-
"Guided Demonstration": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh & Th\u1ECB ph\u1EA1m",
|
|
9769
|
-
"Hands-on Mission": "Nhi\u1EC7m v\u1EE5 Th\u1EF1c h\xE0nh Tr\u1EA3i nghi\u1EC7m",
|
|
9770
|
-
"Summary & Next Steps": "T\u1ED5ng k\u1EBFt & \u0110\u1ECBnh h\u01B0\u1EDBng Ti\u1EBFp theo"
|
|
9771
|
-
}
|
|
9460
|
+
var TEMPLATE_BY_TYPE = {
|
|
9461
|
+
LESSON: "LESSON_5E_template.md",
|
|
9462
|
+
LESSON_5E: "LESSON_5E_template.md",
|
|
9463
|
+
LESSON_EDP: "LESSON_EDP_template.md",
|
|
9464
|
+
LESSON_GENERAL: "LESSON_GENERAL_template.md",
|
|
9465
|
+
ACT: "ACT_template.md",
|
|
9466
|
+
CODE: "CODE_template.md",
|
|
9467
|
+
// JSON-first code lab shares the CODE label set (the serializer renders its
|
|
9468
|
+
// own headings; this lookup only feeds the SLC/directive fallback path).
|
|
9469
|
+
CODE_LAB: "CODE_template.md",
|
|
9470
|
+
QUIZ: "QUIZ_v4.6_template.md",
|
|
9471
|
+
GUIDE: "GUIDE_template.md",
|
|
9472
|
+
HANDOUT: "HANDOUT_template.md",
|
|
9473
|
+
WKS: "WKS_template.md",
|
|
9474
|
+
EXT: "EXT_template.md",
|
|
9475
|
+
SLIDE: "SLIDE_template.md",
|
|
9476
|
+
KNOWLEDGE_EXPOSITION: "KNOWLEDGE_EXPOSITION_template.md",
|
|
9477
|
+
LEARNER_PROFILE: "LEARNER_PROFILE_template.md",
|
|
9478
|
+
PROJECT_BRIEF: "PROJECT_BRIEF_template.md",
|
|
9479
|
+
CURRICULUM_FRAMEWORK: "CURRICULUM_FRAMEWORK_template.md",
|
|
9480
|
+
CONTENT_STYLE_GUIDE: "CONTENT_STYLE_GUIDE_template.md",
|
|
9481
|
+
SECTION_LANGUAGE_CONTRACT: "SECTION_LANGUAGE_CONTRACT_template.md"
|
|
9772
9482
|
};
|
|
9483
|
+
function keepContractEntries(artifactType, mapping) {
|
|
9484
|
+
const templateFile = TEMPLATE_BY_TYPE[artifactType.trim().toUpperCase()];
|
|
9485
|
+
if (!templateFile) return mapping;
|
|
9486
|
+
const resolved = resolveArtifactTemplate(templateFile);
|
|
9487
|
+
if (!resolved) return mapping;
|
|
9488
|
+
const contract = new Set(resolved.sections.map(stripHeadingKey));
|
|
9489
|
+
const kept = {};
|
|
9490
|
+
for (const [k, v] of Object.entries(mapping)) {
|
|
9491
|
+
if (contract.has(stripHeadingKey(k))) kept[k] = v;
|
|
9492
|
+
}
|
|
9493
|
+
return kept;
|
|
9494
|
+
}
|
|
9773
9495
|
function extractSectionHeadingsFromSLC(slcInput, artifactType, targetLanguage = "vi") {
|
|
9774
9496
|
const upperType = artifactType.trim().toUpperCase();
|
|
9775
9497
|
const getFallback = () => {
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
}
|
|
9782
|
-
}
|
|
9783
|
-
return {};
|
|
9498
|
+
const templateFile = TEMPLATE_BY_TYPE[upperType];
|
|
9499
|
+
if (!templateFile) return {};
|
|
9500
|
+
const resolved = resolveArtifactTemplate(templateFile);
|
|
9501
|
+
if (!resolved) return {};
|
|
9502
|
+
return Object.fromEntries(resolved.sections.map((s) => [s, s]));
|
|
9784
9503
|
};
|
|
9785
9504
|
if (!slcInput) return getFallback();
|
|
9786
9505
|
if (typeof slcInput === "object") {
|
|
9787
|
-
if (slcInput[upperType] && Object.keys(slcInput[upperType]).length > 0)
|
|
9506
|
+
if (slcInput[upperType] && Object.keys(slcInput[upperType]).length > 0) {
|
|
9507
|
+
return keepContractEntries(upperType, slcInput[upperType]);
|
|
9508
|
+
}
|
|
9788
9509
|
for (const [key, mapping] of Object.entries(slcInput)) {
|
|
9789
9510
|
if (matchesArtifactType(key, upperType) && Object.keys(mapping).length > 0) {
|
|
9790
|
-
return mapping;
|
|
9511
|
+
return keepContractEntries(upperType, mapping);
|
|
9791
9512
|
}
|
|
9792
9513
|
}
|
|
9793
9514
|
return getFallback();
|
|
@@ -9815,24 +9536,33 @@ function extractSectionHeadingsFromSLC(slcInput, artifactType, targetLanguage =
|
|
|
9815
9536
|
}
|
|
9816
9537
|
}
|
|
9817
9538
|
}
|
|
9818
|
-
if (Object.keys(mapping).length > 0) return mapping;
|
|
9539
|
+
if (Object.keys(mapping).length > 0) return keepContractEntries(upperType, mapping);
|
|
9819
9540
|
}
|
|
9820
9541
|
}
|
|
9821
9542
|
return getFallback();
|
|
9822
9543
|
}
|
|
9823
|
-
function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi") {
|
|
9824
|
-
const
|
|
9544
|
+
function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi", opts) {
|
|
9545
|
+
const upperType = artifactType.trim().toUpperCase();
|
|
9546
|
+
const templateFile = TEMPLATE_BY_TYPE[upperType];
|
|
9547
|
+
const resolved = templateFile ? resolveArtifactTemplate(templateFile, opts) : null;
|
|
9548
|
+
const baked = !!resolved && resolved.declaredLang !== "en";
|
|
9549
|
+
const headings = resolved ? Object.fromEntries(
|
|
9550
|
+
resolved.sections.map((s) => [
|
|
9551
|
+
s,
|
|
9552
|
+
baked ? s : extractSectionHeadingsFromSLC(slcMarkdown, upperType, targetLanguage)[s] || s
|
|
9553
|
+
])
|
|
9554
|
+
) : extractSectionHeadingsFromSLC(baked ? null : slcMarkdown, upperType, targetLanguage);
|
|
9825
9555
|
if (Object.keys(headings).length === 0) {
|
|
9826
9556
|
return "";
|
|
9827
9557
|
}
|
|
9828
9558
|
const lines = Object.entries(headings).map(
|
|
9829
|
-
([
|
|
9559
|
+
([heading, display]) => heading === display ? ` - "${display}"` : ` - "${heading}" -> Use Display Heading: "${display}"`
|
|
9830
9560
|
);
|
|
9831
|
-
return `MANDATORY SECTION HEADINGS
|
|
9832
|
-
-
|
|
9833
|
-
- In the markdown body, section headers MUST
|
|
9561
|
+
return `MANDATORY SECTION HEADINGS (SOURCE: RESOLVED ARTIFACT TEMPLATE):
|
|
9562
|
+
- Copy the template's YAML frontmatter \`template_required_sections\` list VERBATIM into the artifact frontmatter \u2014 never translate, reorder, or invent entries.
|
|
9563
|
+
- In the markdown body, section headers MUST be exactly the Display Headings below (do NOT translate, paraphrase, or re-marker them):
|
|
9834
9564
|
${lines.join("\n")}
|
|
9835
|
-
-
|
|
9565
|
+
- Example: if the resolved template's heading is "${Object.values(headings)[0]}", your body heading must be exactly "## ${Object.values(headings)[0]}".`;
|
|
9836
9566
|
}
|
|
9837
9567
|
|
|
9838
9568
|
// src/services/curriculumHorizon.ts
|
|
@@ -10686,14 +10416,13 @@ function buildSystemPrompt(targetLanguage = "vi", techStack, hardwarePlatform) {
|
|
|
10686
10416
|
function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMarkdown, refPack) {
|
|
10687
10417
|
const depthLines = session.depth_assignments.map((d) => "- " + d.node_id + " [" + d.depth.toUpperCase() + "]: " + DEPTH_RULES[d.depth]).join("\n");
|
|
10688
10418
|
const termLines = glossary.map((g) => "- " + g.term + (g.definition ? " \u2014 " + g.definition : "") + (g.example ? " (example: " + g.example + ")" : "")).join("\n");
|
|
10689
|
-
const
|
|
10690
|
-
const
|
|
10691
|
-
const
|
|
10692
|
-
const
|
|
10693
|
-
const
|
|
10694
|
-
const
|
|
10695
|
-
const
|
|
10696
|
-
const hQuestions = headings["Self-Check Questions"] || (langCode === "vi" ? "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra" : "Self-Check Questions");
|
|
10419
|
+
const headings = extractSectionHeadingsFromSLC(slcMarkdown, "KNOWLEDGE_EXPOSITION", targetLanguage);
|
|
10420
|
+
const hScope = headings["Session Scope"] || "Session Scope";
|
|
10421
|
+
const hTerms = headings["Key Terms"] || "Key Terms";
|
|
10422
|
+
const hNarratives = headings["Concept Narratives"] || "Concept Narratives";
|
|
10423
|
+
const hExamples = headings["Worked Micro-Examples"] || "Worked Micro-Examples";
|
|
10424
|
+
const hMistakes = headings["Common Mistakes"] || "Common Mistakes";
|
|
10425
|
+
const hQuestions = headings["Self-Check Questions"] || "Self-Check Questions";
|
|
10697
10426
|
const skeleton = `## ${hScope} / ## ${hTerms} / ## ${hNarratives} / ## ${hExamples} / ## ${hMistakes} / ## ${hQuestions}`;
|
|
10698
10427
|
const headingDirective = buildHeadingDirective("KNOWLEDGE_EXPOSITION", slcMarkdown, targetLanguage);
|
|
10699
10428
|
let refPackBlock = "";
|
|
@@ -25449,98 +25178,9 @@ function evaluateActivityAlignment(canonicalExcerpt, generatedContent, now = /*
|
|
|
25449
25178
|
const passed = matchedTokens.length > 0;
|
|
25450
25179
|
return { checked: true, passed, matchedTokens: matchedTokens.slice(0, 10), missingTokens: missingTokens.slice(0, 10), mode };
|
|
25451
25180
|
}
|
|
25452
|
-
function stripTemplateFrontmatter(raw) {
|
|
25453
|
-
let body = raw;
|
|
25454
|
-
if (body.startsWith("---")) {
|
|
25455
|
-
const end = body.indexOf("\n---", 3);
|
|
25456
|
-
if (end !== -1) body = body.slice(end + 4);
|
|
25457
|
-
}
|
|
25458
|
-
return body.split("\n").filter((l) => l.trim() !== "<!-- INJECT_BODY -->").join("\n").replace(/^\s*\n/, "").trimEnd();
|
|
25459
|
-
}
|
|
25460
|
-
function extractRequiredSections(raw) {
|
|
25461
|
-
const lines = raw.split("\n");
|
|
25462
|
-
const start = lines.findIndex((l) => /^template_required_sections:\s*$/.test(l.trim()));
|
|
25463
|
-
if (start === -1) return null;
|
|
25464
|
-
const items = [];
|
|
25465
|
-
for (let i = start + 1; i < lines.length; i++) {
|
|
25466
|
-
const line = lines[i] ?? "";
|
|
25467
|
-
if (line.trim() === "") continue;
|
|
25468
|
-
if (!/^\s+-\s/.test(line)) break;
|
|
25469
|
-
items.push(line.trim().replace(/^-\s+/, "").replace(/^["']|["']$/g, ""));
|
|
25470
|
-
}
|
|
25471
|
-
return items.length > 0 ? items : null;
|
|
25472
|
-
}
|
|
25473
|
-
function normalizeHeading2(h) {
|
|
25474
|
-
return h.replace(/\[(REQUIRED|OPTIONAL|CONDITIONAL)\]\s*/gi, "").replace(/\s+/g, " ").trim();
|
|
25475
|
-
}
|
|
25476
|
-
function extractBodySections(raw) {
|
|
25477
|
-
const body = stripTemplateFrontmatter(raw);
|
|
25478
|
-
return body.split("\n").filter((l) => l.startsWith("## ")).map((l) => normalizeHeading2(l.slice(3).trim())).filter((s) => s.length > 0);
|
|
25479
|
-
}
|
|
25480
|
-
var KIT_TEMPLATE_FALLBACK_DIRS = [
|
|
25481
|
-
// Packaged with the npm bundle (dist/templates) — resolves from node_modules.
|
|
25482
|
-
"templates",
|
|
25483
|
-
// Repo checkout layouts.
|
|
25484
|
-
"docs/refs/templates"
|
|
25485
|
-
];
|
|
25486
|
-
var _moduleDir = (() => {
|
|
25487
|
-
try {
|
|
25488
|
-
if (typeof import.meta !== "undefined" && typeof import.meta.url === "string") {
|
|
25489
|
-
return path3.dirname(fileURLToPath(import.meta.url));
|
|
25490
|
-
}
|
|
25491
|
-
} catch {
|
|
25492
|
-
}
|
|
25493
|
-
return typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
25494
|
-
})();
|
|
25495
|
-
function candidateDirs(explicitDir) {
|
|
25496
|
-
const dirs = [];
|
|
25497
|
-
if (explicitDir) dirs.push(explicitDir);
|
|
25498
|
-
if (process.env.CURRICULUM_TEMPLATES_DIR) dirs.push(process.env.CURRICULUM_TEMPLATES_DIR);
|
|
25499
|
-
dirs.push(path3.resolve(process.cwd(), "_templates"));
|
|
25500
|
-
for (const rel of KIT_TEMPLATE_FALLBACK_DIRS) {
|
|
25501
|
-
dirs.push(path3.resolve(_moduleDir, rel));
|
|
25502
|
-
dirs.push(path3.resolve(process.cwd(), rel));
|
|
25503
|
-
dirs.push(path3.resolve(process.cwd(), "packages/curriculum-kit", rel));
|
|
25504
|
-
}
|
|
25505
|
-
return dirs;
|
|
25506
|
-
}
|
|
25507
|
-
function findTemplatePath(templateName, explicitDir) {
|
|
25508
|
-
for (const dir of candidateDirs(explicitDir)) {
|
|
25509
|
-
const p = path3.join(dir, templateName);
|
|
25510
|
-
if (!fs2.existsSync(p)) continue;
|
|
25511
|
-
try {
|
|
25512
|
-
fs2.accessSync(p, fs2.constants.R_OK);
|
|
25513
|
-
return p;
|
|
25514
|
-
} catch {
|
|
25515
|
-
}
|
|
25516
|
-
}
|
|
25517
|
-
return null;
|
|
25518
|
-
}
|
|
25519
|
-
function resolveArtifactTemplate(templateName, opts) {
|
|
25520
|
-
const p = findTemplatePath(templateName, opts?.templatesDir);
|
|
25521
|
-
if (!p) return null;
|
|
25522
|
-
try {
|
|
25523
|
-
const raw = fs2.readFileSync(p, "utf-8");
|
|
25524
|
-
return {
|
|
25525
|
-
content: stripTemplateFrontmatter(raw),
|
|
25526
|
-
sections: extractRequiredSections(raw) ?? extractBodySections(raw),
|
|
25527
|
-
sourcePath: p
|
|
25528
|
-
};
|
|
25529
|
-
} catch {
|
|
25530
|
-
return null;
|
|
25531
|
-
}
|
|
25532
|
-
}
|
|
25533
|
-
function loadCurriculumTemplate(templateName, templatesDir) {
|
|
25534
|
-
const p = findTemplatePath(templateName, templatesDir);
|
|
25535
|
-
if (!p) return "";
|
|
25536
|
-
try {
|
|
25537
|
-
return fs2.readFileSync(p, "utf-8");
|
|
25538
|
-
} catch {
|
|
25539
|
-
return "";
|
|
25540
|
-
}
|
|
25541
|
-
}
|
|
25542
25181
|
|
|
25543
25182
|
// src/services/lessonProductionService.ts
|
|
25183
|
+
init_templateLoader();
|
|
25544
25184
|
var LESSON_TEMPLATE_BY_PEDAGOGY = {
|
|
25545
25185
|
edp: "LESSON_EDP_template.md",
|
|
25546
25186
|
general: "LESSON_GENERAL_template.md",
|
|
@@ -29476,14 +29116,15 @@ function isTranslationDue(target, context) {
|
|
|
29476
29116
|
}
|
|
29477
29117
|
|
|
29478
29118
|
// src/services/index.ts
|
|
29119
|
+
init_templateLoader();
|
|
29479
29120
|
init_slideProductionWorkflow();
|
|
29480
29121
|
var LocalWorkspaceManager = class {
|
|
29481
29122
|
baseDir;
|
|
29482
29123
|
constructor(baseDir) {
|
|
29483
|
-
this.baseDir = baseDir ||
|
|
29124
|
+
this.baseDir = baseDir || path4.resolve(process.cwd(), "output", "workspace-jobs");
|
|
29484
29125
|
}
|
|
29485
29126
|
getJobDirectory(jobId) {
|
|
29486
|
-
return
|
|
29127
|
+
return path4.join(this.baseDir, jobId);
|
|
29487
29128
|
}
|
|
29488
29129
|
async initJobWorkspace(jobId, initialInfo) {
|
|
29489
29130
|
const jobDir = this.getJobDirectory(jobId);
|
|
@@ -29506,9 +29147,9 @@ var LocalWorkspaceManager = class {
|
|
|
29506
29147
|
}
|
|
29507
29148
|
async saveArtifact(jobId, milestoneSlug, filename, content, artifactType) {
|
|
29508
29149
|
const jobDir = this.getJobDirectory(jobId);
|
|
29509
|
-
const targetDir =
|
|
29150
|
+
const targetDir = path4.join(jobDir, milestoneSlug);
|
|
29510
29151
|
await fsPromises.mkdir(targetDir, { recursive: true });
|
|
29511
|
-
const filePath =
|
|
29152
|
+
const filePath = path4.join(targetDir, filename);
|
|
29512
29153
|
await fsPromises.writeFile(filePath, content, "utf-8");
|
|
29513
29154
|
const stat = await fsPromises.stat(filePath);
|
|
29514
29155
|
const manifest = await this.getManifest(jobId);
|
|
@@ -29516,7 +29157,7 @@ var LocalWorkspaceManager = class {
|
|
|
29516
29157
|
manifest.artifacts.push({
|
|
29517
29158
|
milestoneId: milestoneSlug,
|
|
29518
29159
|
artifactType,
|
|
29519
|
-
filePath:
|
|
29160
|
+
filePath: path4.relative(jobDir, filePath),
|
|
29520
29161
|
sizeBytes: stat.size,
|
|
29521
29162
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
29522
29163
|
});
|
|
@@ -29526,7 +29167,7 @@ var LocalWorkspaceManager = class {
|
|
|
29526
29167
|
return filePath;
|
|
29527
29168
|
}
|
|
29528
29169
|
async getManifest(jobId) {
|
|
29529
|
-
const manifestPath =
|
|
29170
|
+
const manifestPath = path4.join(this.getJobDirectory(jobId), "manifest.json");
|
|
29530
29171
|
try {
|
|
29531
29172
|
const data = await fsPromises.readFile(manifestPath, "utf-8");
|
|
29532
29173
|
return JSON.parse(data);
|
|
@@ -29535,7 +29176,7 @@ var LocalWorkspaceManager = class {
|
|
|
29535
29176
|
}
|
|
29536
29177
|
}
|
|
29537
29178
|
async saveManifest(jobId, manifest) {
|
|
29538
|
-
const manifestPath =
|
|
29179
|
+
const manifestPath = path4.join(this.getJobDirectory(jobId), "manifest.json");
|
|
29539
29180
|
manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
29540
29181
|
await fsPromises.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
29541
29182
|
}
|
|
@@ -29576,12 +29217,12 @@ async function publishToGitHub(options) {
|
|
|
29576
29217
|
async function scanDir(currentDir) {
|
|
29577
29218
|
const entries = await fsPromises.readdir(currentDir, { withFileTypes: true });
|
|
29578
29219
|
for (const entry of entries) {
|
|
29579
|
-
const fullPath =
|
|
29220
|
+
const fullPath = path4.join(currentDir, entry.name);
|
|
29580
29221
|
if (entry.isDirectory()) {
|
|
29581
29222
|
await scanDir(fullPath);
|
|
29582
29223
|
} else if (entry.isFile() && !entry.name.startsWith(".")) {
|
|
29583
29224
|
const content = await fsPromises.readFile(fullPath, "utf-8");
|
|
29584
|
-
const relPath =
|
|
29225
|
+
const relPath = path4.relative(options.localJobDir, fullPath);
|
|
29585
29226
|
filesToUpload.push({ path: relPath, content });
|
|
29586
29227
|
}
|
|
29587
29228
|
}
|
|
@@ -31687,13 +31328,13 @@ var MediaLedger = class {
|
|
|
31687
31328
|
filePath;
|
|
31688
31329
|
entries = /* @__PURE__ */ new Map();
|
|
31689
31330
|
constructor(projectDir, lessonId) {
|
|
31690
|
-
this.filePath =
|
|
31331
|
+
this.filePath = path4.join(projectDir, "_media", `ledger-${lessonId.toUpperCase()}.jsonl`);
|
|
31691
31332
|
this.load();
|
|
31692
31333
|
}
|
|
31693
31334
|
load() {
|
|
31694
31335
|
this.entries.clear();
|
|
31695
|
-
if (!
|
|
31696
|
-
const lines =
|
|
31336
|
+
if (!fs3.existsSync(this.filePath)) return;
|
|
31337
|
+
const lines = fs3.readFileSync(this.filePath, "utf-8").split("\n");
|
|
31697
31338
|
for (const line of lines) {
|
|
31698
31339
|
const trimmed = line.trim();
|
|
31699
31340
|
if (!trimmed) continue;
|
|
@@ -31705,8 +31346,8 @@ var MediaLedger = class {
|
|
|
31705
31346
|
}
|
|
31706
31347
|
}
|
|
31707
31348
|
persist() {
|
|
31708
|
-
|
|
31709
|
-
|
|
31349
|
+
fs3.mkdirSync(path4.dirname(this.filePath), { recursive: true });
|
|
31350
|
+
fs3.writeFileSync(this.filePath, Array.from(this.entries.values()).map((e) => JSON.stringify(e)).join("\n") + "\n", "utf-8");
|
|
31710
31351
|
}
|
|
31711
31352
|
/** Agent tạo artifact ghi entry mới (hoặc cập nhật nếu slug đã có và chưa done) */
|
|
31712
31353
|
upsert(input) {
|
|
@@ -31888,8 +31529,8 @@ async function fulfillMediaLedger(options) {
|
|
|
31888
31529
|
const maxRetries = options.maxRetries ?? 2;
|
|
31889
31530
|
const approved = ledger.listByStatus("approved");
|
|
31890
31531
|
const result = { done: [], failed: [], skipped: [] };
|
|
31891
|
-
const mediaDir =
|
|
31892
|
-
|
|
31532
|
+
const mediaDir = path4.join(projectDir, "_media");
|
|
31533
|
+
fs3.mkdirSync(mediaDir, { recursive: true });
|
|
31893
31534
|
const mode = policy.mode ?? "auto";
|
|
31894
31535
|
const canSearch = mode === "search_only" || mode === "auto";
|
|
31895
31536
|
const canGen = mode === "gen_only" || mode === "auto";
|
|
@@ -31971,7 +31612,7 @@ async function fulfillMediaLedger(options) {
|
|
|
31971
31612
|
});
|
|
31972
31613
|
const ext = image.mimeType === "image/jpeg" ? "jpg" : "png";
|
|
31973
31614
|
const filename = `${entry.slug}-${Date.now()}.${ext}`;
|
|
31974
|
-
|
|
31615
|
+
fs3.writeFileSync(path4.join(mediaDir, filename), Buffer.from(image.base64, "base64"));
|
|
31975
31616
|
ledger.setStatus(entry.slug, "done", { relPath: `_media/${filename}`, provider: image.provider });
|
|
31976
31617
|
result.done.push(entry.slug);
|
|
31977
31618
|
options.onProgress?.(entry.slug, "done", `source: ${image.provider}`);
|
|
@@ -32002,6 +31643,6 @@ function renderMediaPlaceholder(entry) {
|
|
|
32002
31643
|
return `> \u{1F5BC}\uFE0F [\u1EA2nh \u0111ang ch\u1EDD: ${entry.name} \u2014 s\u1EBD \u0111\u01B0\u1EE3c t\u1EA1o sau khi duy\u1EC7t media]`;
|
|
32003
31644
|
}
|
|
32004
31645
|
|
|
32005
|
-
export {
|
|
31646
|
+
export { ARTIFACT_DEPENDENCY_ROUTING, ARTIFACT_EXECUTION_ORDER, AcademicAuditor, ActionableRepairActionSchema, ActionableRepairPromptSchema, ActiveLearningWorkflowSchema, ActivityLabSchema, ActivitySeqRowSchema, ActivityStepSchema, ArtifactContractRowSchema, AssessmentMapRowSchema, AssessmentObjectiveSchema, BLOOM_ACTION_VERBS, BUNDLED_STANDARDS_PACK_IDS, BellRingerDaySchema, BellRingerSchema, BloomHintSchema, BloomLevelSchema, BloomTaxonomyEvaluator, BronzeTierSchema, CERConclusionSchema, CURRICULUM_SLASH_COMMANDS, CardTierEnum, ChoiceBoardRubricRowSchema, ChoiceBoardSchema, ChoiceRuleSchema, ChoiceSquareSchema, ClassificationSchema, CodeHardwareFeasibilityEvaluator, CodeLabSchema, CodeSnippetSchema, CompetencyRubricRowSchema, ComputationalThinkingSchema, ConceptPrerequisiteEdgeSchema, ConceptSpiralEncounterSchema, ConstructiveAlignmentEvaluator, CoreConceptSchema, CourseObjectiveSchema, CoverageReportSchema, CrossArtifactDriftEvaluator, CurriculumArtifactSchema, CurriculumError, CurriculumPlanSchema, CurriculumQualityReportSchema, DEFAULT_ARTIFACT_STREAM_IDLE_MS, DEFAULT_ARTIFACT_STREAM_TOTAL_MS, DEFAULT_ENABLED_PROVIDERS, DEFAULT_GATE_SETTINGS, DEFAULT_KX_PRIORITIES, DEFAULT_LESSON_PRIORITIES, DEFAULT_OVERHEAD_RATIO, DEFAULT_STREAM_IDLE_MS, DEFAULT_STREAM_TOTAL_MS, DependencyEdgeSchema, DepthAssignmentSchema, DepthLevelSchema, DeterministicPipelineRunner, DeterministicStructuralLinter, DiagnosticQuestionSchema, DiagnosticQuizSchema, EDPPhaseEnum, ENVIRONMENT_PROVISIONING_MODELS, EXPOSITION_REL, EntryLevelSchema, ExitTicketBugHuntSchema, ExitTicketMetacognitionSchema, ExitTicketQuickItemSchema, ExitTicketRecallPromptSchema, ExitTicketSchema, ExperimentalDesignSchema, ExpositionApprovalError, ExtensionChallengeSchema, ExtensionSchema, FileSystemCurriculumAdapter, FiveEFlowPhaseSchema, FiveEInstructionalEvaluator, FiveEPhaseEnum, FrameworkMappingSchema, FrameworkPackManifestSchema, FrameworkPackSchema, FrameworkStatementSchema, GeneratedSlideArraySchema, GeneratedSlideSchema, GlossaryQuickRefRowSchema, GlossarySchema, GlossaryTermSchema, GoldTierSchema, GradeBandSchema, GraphicOrganizerItemSchema, GraphicOrganizerSchema, HandoutSchema, HandoutSectionSchema, HybridBlueprintArraySchema, HybridBlueprintItemSchema, HybridDeckSlideArraySchema, HybridDeckSlideSchema, HybridPipelineError, InstructionSectionSchema, InstructionStepSchema, JUDGE_AUTO_APPROVE_THRESHOLD, JUDGE_ESCALATE_THRESHOLD, JudgeCriterionSchema, LAYER_IDLE_BUDGET_MS, LAYER_TOTAL_BUDGET_MS, LLMJudgeEngine, LabTierTaskSchema, LearningObjectiveInputSchema, LearningObjectiveRowSchema, LessonEntitySchema, LessonFlowPhaseSchema, LessonPlan5ESchema, LessonPlanEDPSchema, LessonPlanSchema, LessonSectionSchema, LocalWorkspaceManager, MAX_AUTONOMOUS_REPAIR_TURNS, MAX_IN_SESSION_SETUP_MINUTES, MAX_NEW_CONCEPTS_PER_SESSION_ADULT, MAX_NEW_CONCEPTS_PER_SESSION_K12, MacroPedagogyPlanAuditSchema, MappingKindSchema, MarpSlideSchema, MasteryGateSchema, MediaError, MediaLedger, MentorCheatsheetSchema, MilestoneInputSchema, MisconceptionEvaluator, MisconceptionSchema, ModelPolicyResolver, NVIDIA_MODELS, NodeKindSchema, OrganizerTypeEnum, PhaseInputSchema, PlanConstraintsSchema, PlannerInputSchema, PlanningGraphSchema, PlanningNodeSchema, PrerequisiteDecisionEntrySchema, PrerequisiteDecisionSchema, ProductGoalSchema, ProgressiveHintsSchema, ProjectGraphAuditSchema, ProjectGraphSchema, ProjectInstructionSchema, ProjectProfileSchema, QualityAuditVerdictSchema, QuizOptionSchema, RecordProvenanceSchema, ResourceMapRowSchema, ReviewGameExportRowSchema, ReviewGameQuestionSchema, ReviewGameSchema, RoadmapInputSchema, RotationStationSchema, RubricCriteriaSchema, RubricSchema, SATELLITE_LESSON_PRIORITIES, SLIDE_CANONICAL_METHODOLOGY, STANDARD_REF_REGEX, STANDARD_SOT_FILES, STUDENT_FRICTION_MULTIPLIER, ScaffoldDecisionEntrySchema, ScaffoldDecisionSchema, ScienceLabSchema, ScoringRubricRowSchema, SelfLabSchema, SelfPacedBundleSchema, SelfPacedChallengeSchema, SessionPlanSchema, SessionZpdStatusSchema, SilverTierSchema, SlideBlueprintArraySchema, SlideBlueprintItemSchema, SlideDeckSchema, StandardizedTermRowSchema, StandardsRegistryAdapter, StationRecordRowSchema, StationRotationSchema, StationTypeEnum, SupabaseCurriculumAdapter, TaskCardSchema, TaskCardsSchema, TeacherGuideSchema, TeachingScriptPhaseSchema, TierLevelEnum, TierObjectiveSchema, TieredPracticeSchema, TranslationPolicySchema, TroubleshootingEntrySchema, TroubleshootingRowSchema, UnitPlanSchema, UserJourneySchema, WalkingSkeletonSchema, WorksheetItemSchema, WorksheetItemTypeEnum, WorksheetPartSchema, WorksheetSchema, ZpdVerdictSchema, activityTools, analystTools, analyzeProjectCreationIntent, assembleTranslatedTemplate, assertAcyclic, assessorTools, assignDepths, atomicWriteFileSync, auditCurriculumPlanFlow, auditCurriculumQualityFlow, auditProjectGraphFlow, auditQualityReport, buildActivityPrompt, buildArtifactPrompt, buildCodeLabPrompt, buildConceptPrerequisites, buildCurriculumContext, buildCurriculumPlan, buildCurriculumPlanJudgePrompt, buildDeliveryPackages, buildDiagnosticQuizPrompt, buildDomainLexiconGuardrail, buildExpositionContext, buildExpositionExcerpt, buildExtensionPrompt, buildHandoutPrompt, buildHeadingDirective, buildHtmlDeckSlidePrompt, buildImagePrompt, buildJudgePrompt, buildLanguageDirective, buildLessonEntityJson, buildLessonExcerpt, buildLessonMasterPrompt, buildMarpMarkdownSlidePrompt, buildMasteryGates, buildProjectGraphJudgePrompt, buildProjectInstructionPrompt, buildSatelliteContext, buildSectionAwareExcerpt, buildSelfLabPrompt, buildSessionSliceContext, buildSlidesPrompt, buildStandardStackMarkdown, buildStandardsContext, buildStandardsContextBlock, buildTeacherGuidePrompt, buildWalkingSkeleton, buildWorksheetPrompt, checkSessionZpd, closeTruncatedJson, computeConceptSpiralProgression, computeContentHash, computePackingSpec, conductPreliminaryResearch, contentTools, convertRoadmapToFoundationSot, createAiInferenceError, createContextMissingError, createCurriculumStorage, createIdleAbortController, createStreamAbortController, createStreamAbortSignal, createStreamChunkExtractor, curateMediaLedger, designerTools, detectProjectPedagogy, dropCyclicConceptEdges, emitUsage, ensureExpositionForLesson, ensureKnowledgeExposition, entityRowAssignedTo, evaluateActivityAlignment, evaluateStandardsCoverage, executeCurriculumCommand, executeSlideProductionWorkflow, exportAllProjectQuizzes, expositionCacheKey, extractActivityContractRows, extractAssessmentMap, extractConditionalSections, extractCurriculumHorizon, extractDeclaredLanguage, extractEchoSections, extractJsonArray, extractRequiredSections, extractScopeSequenceRows, extractSectionHeadingsFromSLC, extractSessionSlice, extractStandardRefs, extractStreamChunk, extractSymbolLedger, extractThoughtAndContent, extractTieredScaffoldingBlock, findStandardStatement, formatQuizzesToCsv, fulfillMediaLedger, gateModeFor, generateActivityFlow, generateCodeLabFlow, generateDiagnosticQuizFlow, generateEducationalImage, generateExtensionFlow, generateHandoutFlow, generateLessonMasterFlow, generateMilestoneCurriculumBundle, generatePhase1SotArtifacts, generatePhase2SotArtifacts, generateProjectInstruction, generateProjectInstructionFlow, generateRoadmapCurriculum, generateSelfLabFlow, generateSelfPacedBundle, generateSingleArtifact, generateSlidesFlow, generateTeacherGuideFlow, generateWorksheetFlow, getAIModel, getArtifactMetadata, getDesignatedFallbackChain, getDesignatedFallbackConfig, getLessonMetadata, getProjectArtifactScope, getProjectStatusReport, getSmartResumeContext, glossaryTermsForSession, illustratorTools, importRoadmapToProject, ingestProjectGraphIntoProject, initializeProjectInStorage, injectMediaIntoMarkdown, isActivityAlignmentLogOnly, isExpositionFresh, isModelAllowed, isProviderEnabled, isTranslationDue, lintAndSanitizeArtifact, lintCurriculumFramework, lintFrameworkPack, loadAuthoringTemplate, loadCurriculumTemplate, loadSotTemplate, normalizePlanningGraph, normalizeSlcContract, packagerTools, parseAllSessions, parseGateSettings, parseQuizMarkdown, parseRoadmapJsonToProjectPayload, produceBatchLessons, produceSingleLesson, publishToGitHub, publishToSupabase, rankGenCandidates, renderAssignedRowsTable, renderEntitySlotsForType, renderFrameworkFromPlan, renderHorizonPromptBlock, renderMediaPlaceholder, researcherTools, resolveApiKey, resolveArtifactTemplate, resolveGateSettings, resolveStandardsPacks, resolveStreamBudget, resolveTargetLanguageCode, resolveTranslationTargets, reviewerTools, runCurriculumAIInference, safeParseJson, searchEducationalImages, searchEducationalVideos, selectStatementsForLesson, serializeActivityToMarkdown, serializeCodeLabToMarkdown, serializeDiagnosticQuizToMarkdown, serializeHandoutToMarkdown, serializeLessonToMarkdown, serializeProjectInstructionToMarkdown, serializeSelfLabToMarkdown, slugifyProjectName, streamCurriculumAIInference, streamCurriculumAIInferenceWithTools, streamDiagnosticQuizFlow, streamLLMWithFallback, streamLayerPrefillWithFallback, streamLessonMasterFlow, streamSelfLabFlow, stripHeadingKey, stripLlmJsonWrappers, stripTemplateFrontmatter, targetLanguageDisplayName, techSmeTools, topoSort, translateTemplate, uploadAssetToBucket, validateArtifactDependencies, validateCurriculumPlan, validateFrameworkPack, validateHorizonCompliance, validateHybridDeckSlides, validateMarkdownTables, validateMermaidSyntax, withAutoRepair };
|
|
32006
31647
|
//# sourceMappingURL=index.mjs.map
|
|
32007
31648
|
//# sourceMappingURL=index.mjs.map
|