@thanh01.pmt/curriculum-kit 1.4.44 → 1.4.46
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.map +1 -1
- package/dist/ai/index.mjs.map +1 -1
- package/dist/{gateSettings-oo5tCUS_.d.cts → gateSettings-JoqERuS1.d.cts} +0 -1
- package/dist/{gateSettings-oo5tCUS_.d.ts → gateSettings-JoqERuS1.d.ts} +0 -1
- package/dist/index.cjs +362 -395
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -33
- package/dist/index.d.ts +111 -33
- package/dist/index.mjs +356 -392
- package/dist/index.mjs.map +1 -1
- package/dist/pipeline/index.cjs +33 -14
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.mjs +33 -14
- package/dist/pipeline/index.mjs.map +1 -1
- package/dist/storage/index.cjs +0 -1
- package/dist/storage/index.cjs.map +1 -1
- package/dist/storage/index.mjs +0 -1
- package/dist/storage/index.mjs.map +1 -1
- 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 +20 -3
- 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/SELF_LAB_template.md +7 -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 +214 -307
- package/dist/workflow/index.cjs.map +1 -1
- package/dist/workflow/index.d.cts +2 -2
- package/dist/workflow/index.d.ts +2 -2
- package/dist/workflow/index.mjs +214 -307
- 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 +20 -3
- 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/SELF_LAB_template.md +7 -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
|
@@ -3,11 +3,11 @@ 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';
|
|
9
10
|
import { jsonrepair } from 'jsonrepair';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
11
|
import pLimit from 'p-limit';
|
|
12
12
|
import fsPromises from 'fs/promises';
|
|
13
13
|
import crypto, { createHash } from 'crypto';
|
|
@@ -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
|
|
|
@@ -3932,107 +4168,9 @@ var RoadmapInputSchema = z.object({
|
|
|
3932
4168
|
|
|
3933
4169
|
// src/ai/index.ts
|
|
3934
4170
|
init_provider_factory();
|
|
3935
|
-
function stripTemplateFrontmatter(raw) {
|
|
3936
|
-
let body = raw;
|
|
3937
|
-
if (body.startsWith("---")) {
|
|
3938
|
-
const end = body.indexOf("\n---", 3);
|
|
3939
|
-
if (end !== -1) body = body.slice(end + 4);
|
|
3940
|
-
}
|
|
3941
|
-
return body.split("\n").filter((l) => l.trim() !== "<!-- INJECT_BODY -->").join("\n").replace(/^\s*\n/, "").trimEnd();
|
|
3942
|
-
}
|
|
3943
|
-
function extractRequiredSections(raw) {
|
|
3944
|
-
const lines = raw.split("\n");
|
|
3945
|
-
const start = lines.findIndex((l) => /^template_required_sections:\s*$/.test(l.trim()));
|
|
3946
|
-
if (start === -1) return null;
|
|
3947
|
-
const items = [];
|
|
3948
|
-
for (let i = start + 1; i < lines.length; i++) {
|
|
3949
|
-
const line = lines[i] ?? "";
|
|
3950
|
-
if (line.trim() === "") continue;
|
|
3951
|
-
if (!/^\s+-\s/.test(line)) break;
|
|
3952
|
-
items.push(line.trim().replace(/^-\s+/, "").replace(/^["']|["']$/g, ""));
|
|
3953
|
-
}
|
|
3954
|
-
return items.length > 0 ? items : null;
|
|
3955
|
-
}
|
|
3956
|
-
function normalizeHeading(h) {
|
|
3957
|
-
return h.replace(/\[(REQUIRED|OPTIONAL|CONDITIONAL)\]\s*/gi, "").replace(/\s+/g, " ").trim();
|
|
3958
|
-
}
|
|
3959
|
-
function extractBodySections(raw) {
|
|
3960
|
-
const body = stripTemplateFrontmatter(raw);
|
|
3961
|
-
return body.split("\n").filter((l) => l.startsWith("## ")).map((l) => normalizeHeading(l.slice(3).trim())).filter((s) => s.length > 0);
|
|
3962
|
-
}
|
|
3963
|
-
var KIT_TEMPLATE_FALLBACK_DIRS = [
|
|
3964
|
-
// Packaged with the npm bundle (dist/templates) — resolves from node_modules.
|
|
3965
|
-
"templates",
|
|
3966
|
-
// Repo checkout layouts.
|
|
3967
|
-
"docs/refs/templates"
|
|
3968
|
-
];
|
|
3969
|
-
var _moduleDir = (() => {
|
|
3970
|
-
try {
|
|
3971
|
-
if (typeof import.meta !== "undefined" && typeof import.meta.url === "string") {
|
|
3972
|
-
return path4.dirname(fileURLToPath(import.meta.url));
|
|
3973
|
-
}
|
|
3974
|
-
} catch {
|
|
3975
|
-
}
|
|
3976
|
-
return typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
3977
|
-
})();
|
|
3978
|
-
function candidateDirs(explicitDir) {
|
|
3979
|
-
const dirs = [];
|
|
3980
|
-
if (explicitDir) dirs.push(explicitDir);
|
|
3981
|
-
if (process.env.CURRICULUM_TEMPLATES_DIR) dirs.push(process.env.CURRICULUM_TEMPLATES_DIR);
|
|
3982
|
-
dirs.push(path4.resolve(process.cwd(), "_templates"));
|
|
3983
|
-
for (const rel of KIT_TEMPLATE_FALLBACK_DIRS) {
|
|
3984
|
-
dirs.push(path4.resolve(_moduleDir, rel));
|
|
3985
|
-
dirs.push(path4.resolve(process.cwd(), rel));
|
|
3986
|
-
dirs.push(path4.resolve(process.cwd(), "packages/curriculum-kit", rel));
|
|
3987
|
-
}
|
|
3988
|
-
return dirs;
|
|
3989
|
-
}
|
|
3990
|
-
function findTemplatePath(templateName, explicitDir) {
|
|
3991
|
-
for (const dir of candidateDirs(explicitDir)) {
|
|
3992
|
-
const p = path4.join(dir, templateName);
|
|
3993
|
-
if (!fs3.existsSync(p)) continue;
|
|
3994
|
-
try {
|
|
3995
|
-
fs3.accessSync(p, fs3.constants.R_OK);
|
|
3996
|
-
return p;
|
|
3997
|
-
} catch {
|
|
3998
|
-
}
|
|
3999
|
-
}
|
|
4000
|
-
return null;
|
|
4001
|
-
}
|
|
4002
|
-
function resolveArtifactTemplate(templateName, opts) {
|
|
4003
|
-
const p = findTemplatePath(templateName, opts?.templatesDir);
|
|
4004
|
-
if (!p) return null;
|
|
4005
|
-
try {
|
|
4006
|
-
const raw = fs3.readFileSync(p, "utf-8");
|
|
4007
|
-
return {
|
|
4008
|
-
content: stripTemplateFrontmatter(raw),
|
|
4009
|
-
sections: extractRequiredSections(raw) ?? extractBodySections(raw),
|
|
4010
|
-
sourcePath: p
|
|
4011
|
-
};
|
|
4012
|
-
} catch {
|
|
4013
|
-
return null;
|
|
4014
|
-
}
|
|
4015
|
-
}
|
|
4016
|
-
function loadCurriculumTemplate(templateName, templatesDir) {
|
|
4017
|
-
const p = findTemplatePath(templateName, templatesDir);
|
|
4018
|
-
if (!p) return "";
|
|
4019
|
-
try {
|
|
4020
|
-
return fs3.readFileSync(p, "utf-8");
|
|
4021
|
-
} catch {
|
|
4022
|
-
return "";
|
|
4023
|
-
}
|
|
4024
|
-
}
|
|
4025
|
-
function loadAuthoringTemplate(templateName, templatesDir) {
|
|
4026
|
-
const p = findTemplatePath(templateName, templatesDir);
|
|
4027
|
-
if (!p) return "";
|
|
4028
|
-
try {
|
|
4029
|
-
return stripTemplateFrontmatter(fs3.readFileSync(p, "utf-8"));
|
|
4030
|
-
} catch {
|
|
4031
|
-
return "";
|
|
4032
|
-
}
|
|
4033
|
-
}
|
|
4034
4171
|
|
|
4035
4172
|
// src/ai/prompts/lessonMasterPrompt.ts
|
|
4173
|
+
init_templateLoader();
|
|
4036
4174
|
function buildLessonMasterPrompt(input) {
|
|
4037
4175
|
const { milestone, language, topic, targetAudience, contextContinuity, standardsContext } = input;
|
|
4038
4176
|
const learningObjectives = milestone.learning_objectives || [];
|
|
@@ -4134,6 +4272,7 @@ Return a single valid JSON object matching the LessonPlanSchema with these exact
|
|
|
4134
4272
|
}
|
|
4135
4273
|
|
|
4136
4274
|
// src/ai/prompts/activityPrompt.ts
|
|
4275
|
+
init_templateLoader();
|
|
4137
4276
|
function buildActivityPrompt(input) {
|
|
4138
4277
|
const { lesson, language, hardwareBOM, softwareTools } = input;
|
|
4139
4278
|
const loList = lesson.learningObjectives.map((lo) => `- [${lo.bloomLevel}] ${lo.code}: ${lo.name || ""} \u2014 ${lo.description}${lo.successCriteria ? ` (Evidence: ${lo.successCriteria})` : ""}`).join("\n");
|
|
@@ -4233,6 +4372,7 @@ Return a single JSON object matching ActivityLabSchema with these exact keys:
|
|
|
4233
4372
|
}
|
|
4234
4373
|
|
|
4235
4374
|
// src/ai/prompts/codeLabPrompt.ts
|
|
4375
|
+
init_templateLoader();
|
|
4236
4376
|
function buildCodeLabPrompt(input) {
|
|
4237
4377
|
const { lesson, activity, language, targetTechStack } = input;
|
|
4238
4378
|
const techStackList = targetTechStack && targetTechStack.length > 0 ? targetTechStack : ["General Programming & Engineering"];
|
|
@@ -4922,6 +5062,7 @@ Please return a single JSON object matching these exact keys:
|
|
|
4922
5062
|
}
|
|
4923
5063
|
|
|
4924
5064
|
// src/ai/prompts/selfLabPrompt.ts
|
|
5065
|
+
init_templateLoader();
|
|
4925
5066
|
function buildSelfLabPrompt(input) {
|
|
4926
5067
|
const { milestone, projectGraph, language, targetTechStack, contextContinuity } = input;
|
|
4927
5068
|
const techStackList = targetTechStack && targetTechStack.length > 0 ? targetTechStack : milestone.tech_keywords && milestone.tech_keywords.length > 0 ? milestone.tech_keywords : ["General Engineering"];
|
|
@@ -5030,6 +5171,7 @@ Return a single valid JSON object matching SelfLabSchema with these exact keys:
|
|
|
5030
5171
|
}
|
|
5031
5172
|
|
|
5032
5173
|
// src/ai/prompts/diagnosticQuizPrompt.ts
|
|
5174
|
+
init_templateLoader();
|
|
5033
5175
|
function buildDiagnosticQuizPrompt(input) {
|
|
5034
5176
|
const { milestone, language, questionCount = 4, passingScorePct = 80 } = input;
|
|
5035
5177
|
const learningObjectives = milestone.learning_objectives || [];
|
|
@@ -6494,7 +6636,7 @@ ${cc.technicalDepth}`;
|
|
|
6494
6636
|
const dataRows = cc.comparisonTable.rows.map((r) => `| ${r.join(" | ")} |`).join("\n");
|
|
6495
6637
|
str += `
|
|
6496
6638
|
|
|
6497
|
-
|
|
6639
|
+
**Comparison & Trade-off Analysis**
|
|
6498
6640
|
${headerRow}
|
|
6499
6641
|
${dividerRow}
|
|
6500
6642
|
${dataRows}`;
|
|
@@ -6538,7 +6680,8 @@ ${learningObjectivesStr}
|
|
|
6538
6680
|
|
|
6539
6681
|
---
|
|
6540
6682
|
|
|
6541
|
-
## 1. ENGAGE (Hook & High-Stakes Scenario)
|
|
6683
|
+
## 1. ENGAGE (Hook & High-Stakes Scenario)
|
|
6684
|
+
> **Duration:** 10-15 mins
|
|
6542
6685
|
|
|
6543
6686
|
### Real-World Context: "${lesson.hookTitle || "The Incident"}"
|
|
6544
6687
|
${lesson.hookScenario}
|
|
@@ -6547,13 +6690,15 @@ ${lesson.hookQuestions && lesson.hookQuestions.length > 0 ? lesson.hookQuestions
|
|
|
6547
6690
|
|
|
6548
6691
|
---
|
|
6549
6692
|
|
|
6550
|
-
## 2. EXPLORE & EXPLAIN (Core Technical Concepts & Principles)
|
|
6693
|
+
## 2. EXPLORE & EXPLAIN (Core Technical Concepts & Principles)
|
|
6694
|
+
> **Duration:** 30-40 mins
|
|
6551
6695
|
|
|
6552
6696
|
${coreConceptsStr}
|
|
6553
6697
|
|
|
6554
6698
|
---
|
|
6555
6699
|
|
|
6556
|
-
## 3. GUIDED PRACTICE (Visual Architecture & Annotated Code)
|
|
6700
|
+
## 3. GUIDED PRACTICE (Visual Architecture & Annotated Code)
|
|
6701
|
+
> **Duration:** 20-25 mins
|
|
6557
6702
|
|
|
6558
6703
|
### System Architecture & Data Flow (Mermaid Diagram)
|
|
6559
6704
|
${mermaidBlock}
|
|
@@ -6567,7 +6712,8 @@ ${guidedPractice.codeSnippet}
|
|
|
6567
6712
|
|
|
6568
6713
|
---
|
|
6569
6714
|
|
|
6570
|
-
## 4. ELABORATE & INDEPENDENT PRACTICE (Technical Challenge & Scaffolding)
|
|
6715
|
+
## 4. ELABORATE & INDEPENDENT PRACTICE (Technical Challenge & Scaffolding)
|
|
6716
|
+
> **Duration:** 15-20 mins
|
|
6571
6717
|
|
|
6572
6718
|
### Engineering Challenge: "${lesson.independentPractice?.title || "System Optimization Challenge"}"
|
|
6573
6719
|
${lesson.independentPractice?.description || "Implement the core logic and test against simulated edge cases."}
|
|
@@ -6578,7 +6724,8 @@ ${lesson.independentPractice?.description || "Implement the core logic and test
|
|
|
6578
6724
|
|
|
6579
6725
|
---
|
|
6580
6726
|
|
|
6581
|
-
## 5. EVALUATE (Summary, Assessment & Metacognition)
|
|
6727
|
+
## 5. EVALUATE (Summary, Assessment & Metacognition)
|
|
6728
|
+
> **Duration:** 5-10 mins
|
|
6582
6729
|
|
|
6583
6730
|
### Exit Ticket (Bloom: Apply / Analyze)
|
|
6584
6731
|
> **Scenario Question:** ${lesson.exitTicket.questionStem}
|
|
@@ -6671,12 +6818,16 @@ ${hardwareItems}
|
|
|
6671
6818
|
|
|
6672
6819
|
## [REQUIRED] Active Learning Workflow
|
|
6673
6820
|
|
|
6674
|
-
### Phase 1: Planning & Design
|
|
6821
|
+
### Phase 1: Planning & Design
|
|
6822
|
+
> **Duration:** ${phase1.durationMinutes} mins
|
|
6823
|
+
|
|
6675
6824
|
- **Student Task:** ${phase1.studentTask}
|
|
6676
6825
|
- **Teacher Action:** ${phase1.teacherAction}
|
|
6677
6826
|
${phase1.inquiryQuestions.map((q) => ` - *Inquiry Question:* ${q}`).join("\n")}
|
|
6678
6827
|
|
|
6679
|
-
### Phase 2: Implementation & Discovery
|
|
6828
|
+
### Phase 2: Implementation & Discovery
|
|
6829
|
+
> **Duration:** ${phase2.durationMinutes} mins
|
|
6830
|
+
|
|
6680
6831
|
- **Student Task:** ${phase2.studentTask}
|
|
6681
6832
|
- **Teacher Action:** ${phase2.teacherAction}
|
|
6682
6833
|
|
|
@@ -6684,7 +6835,9 @@ ${phase2.codeOrCommands.map((c) => `\`\`\`text
|
|
|
6684
6835
|
${c}
|
|
6685
6836
|
\`\`\``).join("\n\n")}
|
|
6686
6837
|
|
|
6687
|
-
### Phase 3: Debugging & Testing
|
|
6838
|
+
### Phase 3: Debugging & Testing
|
|
6839
|
+
> **Duration:** ${phase3.durationMinutes} mins
|
|
6840
|
+
|
|
6688
6841
|
- **Testing:** ${phase3.testingSteps}
|
|
6689
6842
|
- **Error Analysis:** ${phase3.errorAnalysis}
|
|
6690
6843
|
|
|
@@ -6739,22 +6892,28 @@ This lab focuses on the practical implementation of core technical concepts, bri
|
|
|
6739
6892
|
|
|
6740
6893
|
## \u{1F4DD} Lab Tasks (3-Tier Differentiation)
|
|
6741
6894
|
|
|
6742
|
-
### \u{1F949} Bronze (Foundational)
|
|
6895
|
+
### \u{1F949} Bronze (Foundational)
|
|
6896
|
+
> **Duration:** ${tasks.bronze.mins} mins
|
|
6897
|
+
|
|
6743
6898
|
**Objective:** ${tasks.bronze.objective}
|
|
6744
6899
|
- **Task:** ${tasks.bronze.task}
|
|
6745
6900
|
- **Requirement:** ${tasks.bronze.requirement}
|
|
6746
6901
|
|
|
6747
|
-
### \u{1F948} Silver (Application)
|
|
6902
|
+
### \u{1F948} Silver (Application)
|
|
6903
|
+
> **Duration:** ${tasks.silver.mins} mins
|
|
6904
|
+
|
|
6748
6905
|
**Objective:** ${tasks.silver.objective}
|
|
6749
6906
|
- **Task:** ${tasks.silver.task}
|
|
6750
6907
|
- **Requirement:** ${tasks.silver.requirement}
|
|
6751
6908
|
|
|
6752
|
-
### \u{1F947} Gold (Enrichment/Creative)
|
|
6909
|
+
### \u{1F947} Gold (Enrichment/Creative)
|
|
6910
|
+
> **Duration:** ${tasks.gold.mins} mins
|
|
6911
|
+
|
|
6753
6912
|
**Objective:** ${tasks.gold.objective}
|
|
6754
6913
|
- **Task:** ${tasks.gold.task}
|
|
6755
6914
|
- **Requirement:** ${tasks.gold.requirement}
|
|
6756
6915
|
|
|
6757
|
-
## \u{1F4BB} Technical Reference
|
|
6916
|
+
## \u{1F4BB} Technical Reference
|
|
6758
6917
|
<!-- [SME_MANDATE] -->
|
|
6759
6918
|
> Any code provided in this section is verified for syntax accuracy and runtime execution.
|
|
6760
6919
|
|
|
@@ -6892,7 +7051,9 @@ ${instruction.verificationChecklist.map((c) => `- [ ] ${c}`).join("\n")}
|
|
|
6892
7051
|
function serializeSelfLabToMarkdown(lab) {
|
|
6893
7052
|
const renderChallenge = (c, label) => {
|
|
6894
7053
|
const tasksList = c.tasks.map((t) => `- ${t}`).join("\n");
|
|
6895
|
-
return `### ${label}: ${c.title}
|
|
7054
|
+
return `### ${label}: ${c.title}
|
|
7055
|
+
> **Duration:** ~${c.estimatedMinutes} mins
|
|
7056
|
+
|
|
6896
7057
|
**Objective:** ${c.objective}
|
|
6897
7058
|
|
|
6898
7059
|
#### Tasks & Implementation Details:
|
|
@@ -7786,7 +7947,6 @@ var STANDARD_SOT_FILES = [
|
|
|
7786
7947
|
"REFERENCE_PACK.md",
|
|
7787
7948
|
"PROJECT_GRAPH.json",
|
|
7788
7949
|
"HYBRID_GRAPH.json",
|
|
7789
|
-
"SECTION_LANGUAGE_CONTRACT.md",
|
|
7790
7950
|
"CURRICULUM_FRAMEWORK.md",
|
|
7791
7951
|
"CONTENT_STYLE_GUIDE.md",
|
|
7792
7952
|
"ART_DIRECTION.md",
|
|
@@ -9255,6 +9415,7 @@ function gateModeFor(resolved, type) {
|
|
|
9255
9415
|
}
|
|
9256
9416
|
|
|
9257
9417
|
// src/services/languageDirective.ts
|
|
9418
|
+
init_templateLoader();
|
|
9258
9419
|
function resolveTargetLanguageCode(language) {
|
|
9259
9420
|
const raw = String(language || "vi").trim().toLowerCase();
|
|
9260
9421
|
if (raw.startsWith("vi")) return "vi";
|
|
@@ -9284,193 +9445,46 @@ function buildLanguageDirective(targetLanguage) {
|
|
|
9284
9445
|
${exampleLine}` : ""}
|
|
9285
9446
|
- CJK / NON-LATIN SCRIPT BAN (ABSOLUTE): NEVER output characters from Chinese (\u6C49\u5B57), Japanese (\u304B\u306A/\u6F22\u5B57), or Korean (\uD55C\uAE00) scripts ANYWHERE in the document \u2014 not even a single glyph spliced inside a ${name} sentence. Observed past violations that are STRICTLY forbidden: \u6392\u67E5, \u5305\u542B, \u5BFC\u81F4, \u662F\u591A\u5C11, \u6280\u672F, \u771F\u673A, \u4F11\u606F, \u7EB8\u8D28. To express such meaning write it fully in ${name} or keep the ENGLISH technical term (e.g. write "t\u1EF1 ki\u1EC3m tra l\u1ED7i" / "self-debugging", "bao g\u1ED3m" / "includes"). A mechanical scanner rejects any document containing even one CJK character.`;
|
|
9286
9447
|
}
|
|
9287
|
-
|
|
9288
|
-
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
PROJECT_BRIEF:
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
"Learning Roadmap": "L\u1ED9 tr\xECnh H\u1ECDc t\u1EADp & C\u1ED9t m\u1ED1c",
|
|
9309
|
-
"Artifact Scope": "Ph\u1EA1m vi S\u1EA3n ph\u1EA9m H\u1ECDc t\u1EADp"
|
|
9310
|
-
},
|
|
9311
|
-
CURRICULUM_FRAMEWORK: {
|
|
9312
|
-
"Course Overview": "T\u1ED5ng quan Kh\xF3a h\u1ECDc",
|
|
9313
|
-
"Global Learning Objectives": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp To\xE0n di\u1EC7n",
|
|
9314
|
-
"Structural Hierarchy (Unit & Module)": "C\u1EA5u tr\xFAc Kh\xF3a h\u1ECDc (Unit & Module)",
|
|
9315
|
-
"Scope & Sequence (Detailed Roadmap)": "Ph\u1EA1m vi & Tr\xECnh t\u1EF1 Chi ti\u1EBFt"
|
|
9316
|
-
},
|
|
9317
|
-
CONTENT_STYLE_GUIDE: {
|
|
9318
|
-
"Voice & Tone": "Gi\u1ECDng v\u0103n & Phong c\xE1ch",
|
|
9319
|
-
"Standard Terminology (Glossary)": "Thu\u1EADt ng\u1EEF Chu\u1EA9n (B\u1EA3ng thu\u1EADt ng\u1EEF)",
|
|
9320
|
-
"Examples & Context Rules": "Quy t\u1EAFc V\xED d\u1EE5 & Ng\u1EEF c\u1EA3nh",
|
|
9321
|
-
"Lesson Content Standards": "Ti\xEAu chu\u1EA9n N\u1ED9i dung B\xE0i h\u1ECDc"
|
|
9322
|
-
},
|
|
9323
|
-
SECTION_LANGUAGE_CONTRACT: {
|
|
9324
|
-
"Metadata & Scope": "Th\xF4ng tin & Ph\u1EA1m vi H\u1EE3p \u0111\u1ED3ng",
|
|
9325
|
-
"Section Translation Matrix": "Ma tr\u1EADn Ti\xEAu \u0111\u1EC1 \u0110a ng\xF4n ng\u1EEF",
|
|
9326
|
-
"Validation Rules": "Quy t\u1EAFc X\xE1c th\u1EF1c & Kh\xF3a Chu\u1EA9n"
|
|
9327
|
-
},
|
|
9328
|
-
KNOWLEDGE_EXPOSITION: {
|
|
9329
|
-
"Session Scope": "Ph\u1EA1m vi Bu\u1ED5i h\u1ECDc",
|
|
9330
|
-
"Key Terms": "Thu\u1EADt ng\u1EEF Then ch\u1ED1t",
|
|
9331
|
-
"Concept Narratives": "Di\u1EC5n gi\u1EA3i Kh\xE1i ni\u1EC7m",
|
|
9332
|
-
"Worked Micro-Examples": "V\xED d\u1EE5 M\u1EABu Chi ti\u1EBFt",
|
|
9333
|
-
"Common Mistakes": "L\u1ED7i Th\u01B0\u1EDDng g\u1EB7p & Kh\u1EAFc ph\u1EE5c",
|
|
9334
|
-
"Self-Check Questions": "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra"
|
|
9335
|
-
},
|
|
9336
|
-
LESSON: {
|
|
9337
|
-
"A. Lesson Design Plan": "A. K\u1EBF ho\u1EA1ch Thi\u1EBFt k\u1EBF B\xE0i h\u1ECDc",
|
|
9338
|
-
"Learning Objectives & Evidence": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp & B\u1EB1ng ch\u1EE9ng N\u0103ng l\u1EF1c",
|
|
9339
|
-
"Activity Sequence": "Chu\u1ED7i Ho\u1EA1t \u0111\u1ED9ng D\u1EA1y & H\u1ECDc",
|
|
9340
|
-
"Resource Map": "B\u1EA3n \u0111\u1ED3 T\xE0i nguy\xEAn & H\u1ECDc li\u1EC7u",
|
|
9341
|
-
"Assessment Map": "B\u1EA3n \u0111\u1ED3 \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c",
|
|
9342
|
-
"Artifact Contract": "H\u1EE3p \u0111\u1ED3ng S\u1EA3n ph\u1EA9m \u0110\u1EA7u ra",
|
|
9343
|
-
"B. Lesson Flow": "B. Ti\u1EBFn tr\xECnh Gi\u1EA3ng d\u1EA1y Chi ti\u1EBFt"
|
|
9344
|
-
},
|
|
9345
|
-
ACT: {
|
|
9346
|
-
"Computational Thinking Focus": "Tr\u1ECDng t\xE2m T\u01B0 duy M\xE1y t\xEDnh",
|
|
9347
|
-
"Materials & Setup": "V\u1EADt li\u1EC7u & Chu\u1EA9n b\u1ECB Thi\u1EBFt b\u1ECB",
|
|
9348
|
-
"Constraints & Safety": "R\xE0ng bu\u1ED9c & An to\xE0n Ph\xF2ng th\u1EF1c h\xE0nh",
|
|
9349
|
-
"Active Learning Workflow": "Quy tr\xECnh Ho\u1EA1t \u0111\u1ED9ng Tr\u1EA3i nghi\u1EC7m",
|
|
9350
|
-
"3-Tier Differentiation": "Ph\xE2n h\xF3a H\u1ECDc t\u1EADp 3 T\u1EA7ng",
|
|
9351
|
-
"Reflection": "T\u1ED5ng k\u1EBFt & \u0110\xFAc k\u1EBFt Tr\u1EA3i nghi\u1EC7m"
|
|
9352
|
-
},
|
|
9353
|
-
CODE: {
|
|
9354
|
-
"Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
|
|
9355
|
-
"Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
|
|
9356
|
-
"Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
|
|
9357
|
-
"Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
|
|
9358
|
-
"Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
|
|
9359
|
-
"Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
|
|
9360
|
-
},
|
|
9361
|
-
CODE_LAB: {
|
|
9362
|
-
"Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
|
|
9363
|
-
"Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
|
|
9364
|
-
"Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
|
|
9365
|
-
"Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
|
|
9366
|
-
"Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
|
|
9367
|
-
"Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
|
|
9368
|
-
},
|
|
9369
|
-
QUIZ: {
|
|
9370
|
-
"Assessment Objectives": "M\u1EE5c ti\xEAu \u0110\xE1nh gi\xE1",
|
|
9371
|
-
"Multiple-Choice Question Bank": "Ng\xE2n h\xE0ng C\xE2u h\u1ECFi Tr\u1EAFc nghi\u1EC7m",
|
|
9372
|
-
"Code Analysis / Debugging Question": "C\xE2u h\u1ECFi Ph\xE2n t\xEDch M\xE3 ngu\u1ED3n & S\u1EEDa l\u1ED7i",
|
|
9373
|
-
"Competency Rubric": "Thang \u0111o \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c (Rubric)"
|
|
9374
|
-
},
|
|
9375
|
-
GUIDE: {
|
|
9376
|
-
"Objectives & Preparation": "M\u1EE5c ti\xEAu & Chu\u1EA9n b\u1ECB Gi\u1EA3ng d\u1EA1y",
|
|
9377
|
-
"Preparation Checklist & Workstation Setup": "Danh m\u1EE5c Ki\u1EC3m tra Chu\u1EA9n b\u1ECB & Tr\u1EA1m Th\u1EF1c h\xE0nh",
|
|
9378
|
-
"Facilitation Script & Timeline": "K\u1ECBch b\u1EA3n \u0110i\u1EC1u ph\u1ED1i & Khung Th\u1EDDi gian",
|
|
9379
|
-
"Common Misconceptions & Diagnostic Remediation Matrix": "Quan ni\u1EC7m Sai l\u1EA7m Th\u01B0\u1EDDng g\u1EB7p & Ma tr\u1EADn Kh\u1EAFc ph\u1EE5c",
|
|
9380
|
-
"Differentiated Support Strategies": "Chi\u1EBFn l\u01B0\u1EE3c H\u1ED7 tr\u1EE3 Ph\xE2n h\xF3a"
|
|
9381
|
-
},
|
|
9382
|
-
HANDOUT: {
|
|
9383
|
-
"Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
|
|
9384
|
-
"Core Syntax & Mechanism Cheat Sheet": "B\u1EA3ng Tra c\u1EE9u C\xFA ph\xE1p & C\u01A1 ch\u1EBF Tr\u1ECDng t\xE2m",
|
|
9385
|
-
"Visual Mental Model / Architecture Diagram": "M\xF4 h\xECnh T\u01B0 duy Tr\u1EF1c quan / S\u01A1 \u0111\u1ED3 Ki\u1EBFn tr\xFAc",
|
|
9386
|
-
"Step-by-Step Practical Quick-Start Guide": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh T\u1EEBng b\u01B0\u1EDBc",
|
|
9387
|
-
"Self-Check Diagnostic Checklist": "B\u1EA3ng Ki\u1EC3m tra T\u1EF1 ch\u1EA9n \u0111o\xE1n"
|
|
9388
|
-
},
|
|
9389
|
-
WKS: {
|
|
9390
|
-
"Part 1: Knowledge Check": "Ph\u1EA7n 1: Ki\u1EC3m tra Ki\u1EBFn th\u1EE9c",
|
|
9391
|
-
"Part 2: Concept Tracing & Diagram Fill-in": "Ph\u1EA7n 2: L\u1EA7n v\u1EBFt Kh\xE1i ni\u1EC7m & \u0110i\u1EC1n S\u01A1 \u0111\u1ED3",
|
|
9392
|
-
"Part 3: Code Analysis & Bug Hunting Challenge": "Ph\u1EA7n 3: Ph\xE2n t\xEDch M\xE3 & Th\u1EED th\xE1ch S\u0103n l\u1ED7i",
|
|
9393
|
-
"Part 4: Synthesis & Problem-Solving Application": "Ph\u1EA7n 4: T\u1ED5ng h\u1EE3p & \u1EE8ng d\u1EE5ng Gi\u1EA3i quy\u1EBFt V\u1EA5n \u0111\u1EC1",
|
|
9394
|
-
"Part 5: Self-Reflection & Learning Log": "Ph\u1EA7n 5: T\u1EF1 suy ng\u1EABm & Nh\u1EADt k\xFD H\u1ECDc t\u1EADp"
|
|
9395
|
-
},
|
|
9396
|
-
EXT: {
|
|
9397
|
-
"For: Advanced Students / Extra Time": "D\xE0nh cho: H\u1ECDc sinh N\xE2ng cao / Ho\xE0n th\xE0nh S\u1EDBm",
|
|
9398
|
-
"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",
|
|
9399
|
-
"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",
|
|
9400
|
-
"Challenge 3: Extension Milestones": "Th\u1EED th\xE1ch 3: C\xE1c M\u1ED1c Nhi\u1EC7m v\u1EE5 N\xE2ng cao",
|
|
9401
|
-
"Metacognitive Deep Dive & Engineering Trade-offs": "Suy ng\u1EABm Si\xEAu nh\u1EADn th\u1EE9c & \u0110\xE1nh \u0111\u1ED5i K\u1EF9 thu\u1EADt"
|
|
9402
|
-
},
|
|
9403
|
-
SLIDE: {
|
|
9404
|
-
"Title & Agenda": "Ti\xEAu \u0111\u1EC1 & M\u1EE5c l\u1EE5c",
|
|
9405
|
-
"Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
|
|
9406
|
-
"Guided Demonstration": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh & Th\u1ECB ph\u1EA1m",
|
|
9407
|
-
"Hands-on Mission": "Nhi\u1EC7m v\u1EE5 Th\u1EF1c h\xE0nh Tr\u1EA3i nghi\u1EC7m",
|
|
9408
|
-
"Summary & Next Steps": "T\u1ED5ng k\u1EBFt & \u0110\u1ECBnh h\u01B0\u1EDBng Ti\u1EBFp theo"
|
|
9409
|
-
}
|
|
9448
|
+
var TEMPLATE_BY_TYPE = {
|
|
9449
|
+
LESSON: "LESSON_5E_template.md",
|
|
9450
|
+
LESSON_5E: "LESSON_5E_template.md",
|
|
9451
|
+
LESSON_EDP: "LESSON_EDP_template.md",
|
|
9452
|
+
LESSON_GENERAL: "LESSON_GENERAL_template.md",
|
|
9453
|
+
ACT: "ACT_template.md",
|
|
9454
|
+
CODE: "CODE_template.md",
|
|
9455
|
+
// JSON-first code lab shares the CODE label set (the serializer renders its
|
|
9456
|
+
// own headings; this lookup only feeds the directive fallback path).
|
|
9457
|
+
CODE_LAB: "CODE_template.md",
|
|
9458
|
+
QUIZ: "QUIZ_v4.6_template.md",
|
|
9459
|
+
GUIDE: "GUIDE_template.md",
|
|
9460
|
+
HANDOUT: "HANDOUT_template.md",
|
|
9461
|
+
WKS: "WKS_template.md",
|
|
9462
|
+
EXT: "EXT_template.md",
|
|
9463
|
+
SLIDE: "SLIDE_template.md",
|
|
9464
|
+
KNOWLEDGE_EXPOSITION: "KNOWLEDGE_EXPOSITION_template.md",
|
|
9465
|
+
LEARNER_PROFILE: "LEARNER_PROFILE_template.md",
|
|
9466
|
+
PROJECT_BRIEF: "PROJECT_BRIEF_template.md",
|
|
9467
|
+
CURRICULUM_FRAMEWORK: "CURRICULUM_FRAMEWORK_template.md",
|
|
9468
|
+
CONTENT_STYLE_GUIDE: "CONTENT_STYLE_GUIDE_template.md"
|
|
9410
9469
|
};
|
|
9411
|
-
function
|
|
9412
|
-
const
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
}
|
|
9421
|
-
return {};
|
|
9422
|
-
};
|
|
9423
|
-
if (!slcInput) return getFallback();
|
|
9424
|
-
if (typeof slcInput === "object") {
|
|
9425
|
-
if (slcInput[upperType] && Object.keys(slcInput[upperType]).length > 0) return slcInput[upperType];
|
|
9426
|
-
for (const [key, mapping] of Object.entries(slcInput)) {
|
|
9427
|
-
if (matchesArtifactType(key, upperType) && Object.keys(mapping).length > 0) {
|
|
9428
|
-
return mapping;
|
|
9429
|
-
}
|
|
9430
|
-
}
|
|
9431
|
-
return getFallback();
|
|
9432
|
-
}
|
|
9433
|
-
const slcMarkdown = slcInput;
|
|
9434
|
-
const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
9435
|
-
for (const block of blocks) {
|
|
9436
|
-
const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
9437
|
-
if (!headerMatch) continue;
|
|
9438
|
-
const blockType = headerMatch[1].trim().toUpperCase();
|
|
9439
|
-
if (matchesArtifactType(blockType, upperType)) {
|
|
9440
|
-
const mapping = {};
|
|
9441
|
-
const lines = block.split("\n");
|
|
9442
|
-
for (const line of lines) {
|
|
9443
|
-
const trimmed = line.trim();
|
|
9444
|
-
if (trimmed.startsWith("|") && !trimmed.includes("---")) {
|
|
9445
|
-
const cells = trimmed.split("|").map((c) => c.trim()).filter((_, idx, arr) => idx > 0 && idx < arr.length - 1);
|
|
9446
|
-
if (cells.length >= 2 && !cells[0].toLowerCase().includes("canonical") && !cells[1].toLowerCase().includes("localized")) {
|
|
9447
|
-
mapping[cells[0]] = cells[1];
|
|
9448
|
-
}
|
|
9449
|
-
} else {
|
|
9450
|
-
const bullet = line.match(/^[-*]\s+([^:]+):\s+(.+)$/);
|
|
9451
|
-
if (bullet) {
|
|
9452
|
-
mapping[bullet[1].trim()] = bullet[2].trim();
|
|
9453
|
-
}
|
|
9454
|
-
}
|
|
9455
|
-
}
|
|
9456
|
-
if (Object.keys(mapping).length > 0) return mapping;
|
|
9457
|
-
}
|
|
9458
|
-
}
|
|
9459
|
-
return getFallback();
|
|
9460
|
-
}
|
|
9461
|
-
function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi") {
|
|
9462
|
-
const headings = extractSectionHeadingsFromSLC(slcMarkdown, artifactType, targetLanguage);
|
|
9470
|
+
function extractSectionHeadings(artifactType, opts) {
|
|
9471
|
+
const templateFile = TEMPLATE_BY_TYPE[artifactType.trim().toUpperCase()];
|
|
9472
|
+
if (!templateFile) return {};
|
|
9473
|
+
const resolved = resolveArtifactTemplate(templateFile, opts);
|
|
9474
|
+
if (!resolved) return {};
|
|
9475
|
+
return Object.fromEntries(resolved.sections.map((s) => [s, s]));
|
|
9476
|
+
}
|
|
9477
|
+
function buildHeadingDirective(artifactType, opts) {
|
|
9478
|
+
const headings = extractSectionHeadings(artifactType, opts);
|
|
9463
9479
|
if (Object.keys(headings).length === 0) {
|
|
9464
9480
|
return "";
|
|
9465
9481
|
}
|
|
9466
|
-
const lines = Object.
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
- The YAML frontmatter \`template_required_sections\` MUST preserve the exact English canonical keys.
|
|
9471
|
-
- In the markdown body, section headers MUST use the EXACT Localized Display Labels below (do NOT translate or paraphrase):
|
|
9482
|
+
const lines = Object.keys(headings).map((heading) => ` - "${heading}"`);
|
|
9483
|
+
return `MANDATORY SECTION HEADINGS (SOURCE: RESOLVED ARTIFACT TEMPLATE):
|
|
9484
|
+
- Copy the template's YAML frontmatter \`template_required_sections\` list VERBATIM into the artifact frontmatter \u2014 never translate, reorder, or invent entries.
|
|
9485
|
+
- In the markdown body, section headers MUST be exactly the Display Headings below (do NOT translate, paraphrase, or re-marker them):
|
|
9472
9486
|
${lines.join("\n")}
|
|
9473
|
-
-
|
|
9487
|
+
- Example: if the resolved template's heading is "${Object.values(headings)[0]}", your body heading must be exactly "## ${Object.values(headings)[0]}".`;
|
|
9474
9488
|
}
|
|
9475
9489
|
|
|
9476
9490
|
// src/services/curriculumHorizon.ts
|
|
@@ -9829,9 +9843,8 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
|
|
|
9829
9843
|
};
|
|
9830
9844
|
}
|
|
9831
9845
|
const minContentChars = opts.minContentChars !== void 0 ? opts.minContentChars : Math.min(400, source.length);
|
|
9832
|
-
const slcMap = normalizeSlcContract(opts.sectionLanguageContract);
|
|
9833
9846
|
const effectiveArtifactType = opts.artifactType || deriveArtifactTypeFromFileName(opts.fileName);
|
|
9834
|
-
const sections = parseMarkdownSections(source
|
|
9847
|
+
const sections = parseMarkdownSections(source);
|
|
9835
9848
|
const metaBlock = buildMetaBlock(source, effectiveArtifactType);
|
|
9836
9849
|
if (sections.length === 0) {
|
|
9837
9850
|
issues.push("parse:no-sections");
|
|
@@ -9854,7 +9867,7 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
|
|
|
9854
9867
|
if (s.canonicalKey && !byCanonical.has(s.canonicalKey)) {
|
|
9855
9868
|
byCanonical.set(s.canonicalKey, s);
|
|
9856
9869
|
}
|
|
9857
|
-
const norm2 =
|
|
9870
|
+
const norm2 = normalizeHeading(s.cleanTitle);
|
|
9858
9871
|
if (!byCleanTitle.has(norm2)) {
|
|
9859
9872
|
byCleanTitle.set(norm2, s);
|
|
9860
9873
|
}
|
|
@@ -9904,7 +9917,7 @@ ${truncated}`;
|
|
|
9904
9917
|
blocks.push(metaBlock);
|
|
9905
9918
|
let sectionAware = false;
|
|
9906
9919
|
for (const key of priorities) {
|
|
9907
|
-
const sec = byCanonical.get(key) || byCleanTitle.get(
|
|
9920
|
+
const sec = byCanonical.get(key) || byCleanTitle.get(normalizeHeading(key));
|
|
9908
9921
|
if (!sec) continue;
|
|
9909
9922
|
sectionAware = true;
|
|
9910
9923
|
if (!tryAdd(sec.cleanTitle, sec.body, key)) break;
|
|
@@ -9954,48 +9967,16 @@ function buildLessonExcerpt(markdown, opts = {}) {
|
|
|
9954
9967
|
priorities: DEFAULT_LESSON_PRIORITIES
|
|
9955
9968
|
});
|
|
9956
9969
|
}
|
|
9957
|
-
function
|
|
9958
|
-
if (!slc) return void 0;
|
|
9959
|
-
if (typeof slc !== "string") return slc;
|
|
9960
|
-
const out = {};
|
|
9961
|
-
const blocks = slc.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
9962
|
-
for (const block of blocks) {
|
|
9963
|
-
const header = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
9964
|
-
if (!header?.[1]) continue;
|
|
9965
|
-
const mapping = {};
|
|
9966
|
-
for (const line of block.split("\n")) {
|
|
9967
|
-
const t = line.trim();
|
|
9968
|
-
if (!t.startsWith("|") || t.includes("---")) continue;
|
|
9969
|
-
const cells = t.split("|").map((c) => c.trim()).filter((_, i, a) => i > 0 && i < a.length - 1);
|
|
9970
|
-
const [c0, c1] = cells;
|
|
9971
|
-
if (c0 && c1 && !c0.toLowerCase().includes("canonical") && !c1.toLowerCase().includes("localized")) {
|
|
9972
|
-
mapping[c0] = c1;
|
|
9973
|
-
}
|
|
9974
|
-
}
|
|
9975
|
-
if (Object.keys(mapping).length > 0) out[header[1]] = mapping;
|
|
9976
|
-
}
|
|
9977
|
-
return Object.keys(out).length > 0 ? out : void 0;
|
|
9978
|
-
}
|
|
9979
|
-
function parseMarkdownSections(markdown, slcMap, artifactType) {
|
|
9970
|
+
function parseMarkdownSections(markdown) {
|
|
9980
9971
|
const sections = [];
|
|
9981
9972
|
const lines = markdown.split("\n");
|
|
9982
9973
|
let currentHeading = "";
|
|
9983
9974
|
let currentBody = [];
|
|
9984
|
-
const reverseMap = /* @__PURE__ */ new Map();
|
|
9985
|
-
if (slcMap) {
|
|
9986
|
-
const maps = artifactType && slcMap[artifactType] ? [slcMap[artifactType]] : Object.values(slcMap);
|
|
9987
|
-
for (const m of maps) {
|
|
9988
|
-
for (const [canonical, localized] of Object.entries(m)) {
|
|
9989
|
-
reverseMap.set(normalizeHeading2(localized), canonical);
|
|
9990
|
-
reverseMap.set(normalizeHeading2(canonical), canonical);
|
|
9991
|
-
}
|
|
9992
|
-
}
|
|
9993
|
-
}
|
|
9994
9975
|
const flush = () => {
|
|
9995
9976
|
if (!currentHeading) return;
|
|
9996
9977
|
const cleanTitle = currentHeading.replace(/^#{1,4}\s+/, "").trim();
|
|
9997
|
-
const norm2 =
|
|
9998
|
-
const canonicalKey =
|
|
9978
|
+
const norm2 = normalizeHeading(cleanTitle);
|
|
9979
|
+
const canonicalKey = findCanonicalFuzzy(norm2);
|
|
9999
9980
|
sections.push({
|
|
10000
9981
|
rawHeading: currentHeading,
|
|
10001
9982
|
cleanTitle,
|
|
@@ -10018,7 +9999,7 @@ function parseMarkdownSections(markdown, slcMap, artifactType) {
|
|
|
10018
9999
|
flush();
|
|
10019
10000
|
return sections;
|
|
10020
10001
|
}
|
|
10021
|
-
function
|
|
10002
|
+
function normalizeHeading(str) {
|
|
10022
10003
|
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
10023
10004
|
}
|
|
10024
10005
|
function findCanonicalFuzzy(norm2) {
|
|
@@ -10094,7 +10075,7 @@ function buildMetaBlock(source, artifactType) {
|
|
|
10094
10075
|
function deriveArtifactTypeFromFileName(fileName) {
|
|
10095
10076
|
if (!fileName) return void 0;
|
|
10096
10077
|
const base = fileName.replace(/\.md$/i, "");
|
|
10097
|
-
const multiWord = base.match(/^(KNOWLEDGE_EXPOSITION|
|
|
10078
|
+
const multiWord = base.match(/^(KNOWLEDGE_EXPOSITION|CONTENT_STYLE_GUIDE|CURRICULUM_FRAMEWORK|LEARNER_PROFILE|PROJECT_BRIEF|REFERENCE_PACK|CURRICULUM_PLAN)/i);
|
|
10098
10079
|
if (multiWord) return multiWord[1].toUpperCase();
|
|
10099
10080
|
const token = base.match(/^([A-Z][A-Z0-9_]*?)(?=_|$)/);
|
|
10100
10081
|
return token ? token[1] : void 0;
|
|
@@ -10321,19 +10302,18 @@ function buildSystemPrompt(targetLanguage = "vi", techStack, hardwarePlatform) {
|
|
|
10321
10302
|
langDirective
|
|
10322
10303
|
].join("\n");
|
|
10323
10304
|
}
|
|
10324
|
-
function buildUserPrompt(session, plan, glossary, targetLanguage = "vi",
|
|
10305
|
+
function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", refPack) {
|
|
10325
10306
|
const depthLines = session.depth_assignments.map((d) => "- " + d.node_id + " [" + d.depth.toUpperCase() + "]: " + DEPTH_RULES[d.depth]).join("\n");
|
|
10326
10307
|
const termLines = glossary.map((g) => "- " + g.term + (g.definition ? " \u2014 " + g.definition : "") + (g.example ? " (example: " + g.example + ")" : "")).join("\n");
|
|
10327
|
-
const
|
|
10328
|
-
const
|
|
10329
|
-
const
|
|
10330
|
-
const
|
|
10331
|
-
const
|
|
10332
|
-
const
|
|
10333
|
-
const
|
|
10334
|
-
const hQuestions = headings["Self-Check Questions"] || (langCode === "vi" ? "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra" : "Self-Check Questions");
|
|
10308
|
+
const headings = extractSectionHeadings("KNOWLEDGE_EXPOSITION");
|
|
10309
|
+
const hScope = headings["Session Scope"] || "Session Scope";
|
|
10310
|
+
const hTerms = headings["Key Terms"] || "Key Terms";
|
|
10311
|
+
const hNarratives = headings["Concept Narratives"] || "Concept Narratives";
|
|
10312
|
+
const hExamples = headings["Worked Micro-Examples"] || "Worked Micro-Examples";
|
|
10313
|
+
const hMistakes = headings["Common Mistakes"] || "Common Mistakes";
|
|
10314
|
+
const hQuestions = headings["Self-Check Questions"] || "Self-Check Questions";
|
|
10335
10315
|
const skeleton = `## ${hScope} / ## ${hTerms} / ## ${hNarratives} / ## ${hExamples} / ## ${hMistakes} / ## ${hQuestions}`;
|
|
10336
|
-
const headingDirective = buildHeadingDirective("KNOWLEDGE_EXPOSITION"
|
|
10316
|
+
const headingDirective = buildHeadingDirective("KNOWLEDGE_EXPOSITION");
|
|
10337
10317
|
let refPackBlock = "";
|
|
10338
10318
|
if (refPack && refPack.trim()) {
|
|
10339
10319
|
const refExcerpt = buildSectionAwareExcerpt(refPack, {
|
|
@@ -10399,7 +10379,7 @@ async function ensureKnowledgeExposition(options) {
|
|
|
10399
10379
|
skipToolchainList: true
|
|
10400
10380
|
// same RefPack excerpt already in [GROUND TRUTH]
|
|
10401
10381
|
});
|
|
10402
|
-
const originalUserPrompt = buildUserPrompt(session, plan, glossary, targetLanguage,
|
|
10382
|
+
const originalUserPrompt = buildUserPrompt(session, plan, glossary, targetLanguage, refPack) + (productSpecBlock ? "\n\n" + productSpecBlock : "");
|
|
10403
10383
|
const content = (await llmFn(
|
|
10404
10384
|
originalSystemPrompt,
|
|
10405
10385
|
originalUserPrompt
|
|
@@ -10537,7 +10517,6 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
10537
10517
|
plan,
|
|
10538
10518
|
glossary,
|
|
10539
10519
|
targetLanguage: targetLang,
|
|
10540
|
-
slcMarkdown: options.slcMarkdown,
|
|
10541
10520
|
techStack: tech,
|
|
10542
10521
|
hardwarePlatform: hw,
|
|
10543
10522
|
refPack: refPackContent,
|
|
@@ -24906,7 +24885,6 @@ function buildSatelliteContext(input) {
|
|
|
24906
24885
|
lessonContent,
|
|
24907
24886
|
lessonExcerpt,
|
|
24908
24887
|
expositionContent,
|
|
24909
|
-
slcMarkdown,
|
|
24910
24888
|
symbolLedgerBlock,
|
|
24911
24889
|
pedagogyLabel,
|
|
24912
24890
|
lessonEntity,
|
|
@@ -24942,7 +24920,6 @@ ${lessonExcerpt.excerpt}${symbolLedgerBlock}`;
|
|
|
24942
24920
|
const kxExcerpt = buildSectionAwareExcerpt(expositionContent, {
|
|
24943
24921
|
priorities: KX_SLOT_PRIORITIES[type] ?? ["Key Terms", "Concept Narratives", "Worked Micro-Examples"],
|
|
24944
24922
|
budget: 4500,
|
|
24945
|
-
sectionLanguageContract: slcMarkdown,
|
|
24946
24923
|
artifactType: "KNOWLEDGE_EXPOSITION"
|
|
24947
24924
|
});
|
|
24948
24925
|
parts.push(`
|
|
@@ -24974,7 +24951,6 @@ ${slots}`;
|
|
|
24974
24951
|
const excerpt = buildSectionAwareExcerpt(lessonContent, {
|
|
24975
24952
|
priorities: spec.priorities ?? ["Artifact Contract", "A. Lesson Design Plan", "B. Lesson Flow", "Learning Objectives & Evidence", "Activity Sequence"],
|
|
24976
24953
|
budget: spec.budget,
|
|
24977
|
-
sectionLanguageContract: slcMarkdown,
|
|
24978
24954
|
artifactType: "LESSON"
|
|
24979
24955
|
});
|
|
24980
24956
|
const excerptBlock = `
|
|
@@ -25089,6 +25065,7 @@ function evaluateActivityAlignment(canonicalExcerpt, generatedContent, now = /*
|
|
|
25089
25065
|
}
|
|
25090
25066
|
|
|
25091
25067
|
// src/services/lessonProductionService.ts
|
|
25068
|
+
init_templateLoader();
|
|
25092
25069
|
var LESSON_TEMPLATE_BY_PEDAGOGY = {
|
|
25093
25070
|
edp: "LESSON_EDP_template.md",
|
|
25094
25071
|
general: "LESSON_GENERAL_template.md",
|
|
@@ -25268,7 +25245,7 @@ ${nextRow}`
|
|
|
25268
25245
|
].filter(Boolean);
|
|
25269
25246
|
return parts.join("\n\n") || framework.slice(0, 1500);
|
|
25270
25247
|
}
|
|
25271
|
-
function buildLessonPrompt(pedagogy, lessonCode, unitCode, lessonTitle, concept, bloomLevel, dateStr, targetLanguage = "vi"
|
|
25248
|
+
function buildLessonPrompt(pedagogy, lessonCode, unitCode, lessonTitle, concept, bloomLevel, dateStr, targetLanguage = "vi") {
|
|
25272
25249
|
const templateFile = LESSON_TEMPLATE_BY_PEDAGOGY[pedagogy] ?? "LESSON_5E_template.md";
|
|
25273
25250
|
const artifactType = templateFile.replace("_template.md", "");
|
|
25274
25251
|
const contract = resolveArtifactTemplate(templateFile)?.sections ?? [];
|
|
@@ -25311,9 +25288,7 @@ type: "${artifactType}"
|
|
|
25311
25288
|
${NO_VERBATIM_COPYING}`;
|
|
25312
25289
|
const langDirective = buildLanguageDirective(targetLanguage);
|
|
25313
25290
|
const headingDirective = buildHeadingDirective(
|
|
25314
|
-
pedagogy === "edp" ? "LESSON_EDP" : pedagogy === "general" || pedagogy === "pbl" ? "LESSON_GENERAL" : "LESSON_5E"
|
|
25315
|
-
sectionLanguageContract,
|
|
25316
|
-
targetLanguage
|
|
25291
|
+
pedagogy === "edp" ? "LESSON_EDP" : pedagogy === "general" || pedagogy === "pbl" ? "LESSON_GENERAL" : "LESSON_5E"
|
|
25317
25292
|
);
|
|
25318
25293
|
const body = buildArtifactPrompt({ directive, templateFile });
|
|
25319
25294
|
return `${body}
|
|
@@ -25366,7 +25341,6 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
25366
25341
|
if (!currentPlanHash || content.includes('plan_hash: "' + currentPlanHash + '"')) return content;
|
|
25367
25342
|
return content + '\n---\nplan_hash: "' + currentPlanHash + '"\n- **Plan reference:** ' + currentPlanHash + "\n";
|
|
25368
25343
|
};
|
|
25369
|
-
const slcMarkdown = options.sectionLanguageContract || await storage.readSotDocument(projectId, "SECTION_LANGUAGE_CONTRACT.md") || "";
|
|
25370
25344
|
let targetLang = options.targetLanguage;
|
|
25371
25345
|
if (!targetLang) {
|
|
25372
25346
|
try {
|
|
@@ -25389,13 +25363,11 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
25389
25363
|
gates: resolveGateSettings(options.gateSettings),
|
|
25390
25364
|
force: options.force,
|
|
25391
25365
|
targetLanguage: targetLang,
|
|
25392
|
-
slcMarkdown,
|
|
25393
25366
|
customInference: options.customInference
|
|
25394
25367
|
});
|
|
25395
25368
|
if (exposition) {
|
|
25396
25369
|
const expoExcerpt = buildExpositionExcerpt(exposition.rawContent || exposition.context, {
|
|
25397
25370
|
budget: 6e3,
|
|
25398
|
-
sectionLanguageContract: slcMarkdown,
|
|
25399
25371
|
artifactType: "KNOWLEDGE_EXPOSITION"
|
|
25400
25372
|
});
|
|
25401
25373
|
expositionContext = expoExcerpt.excerpt || exposition.context;
|
|
@@ -25604,8 +25576,7 @@ Khi n\u1ED9i dung c\u1EA7n minh h\u1ECDa (diagram quy tr\xECnh, s\u01A1 \u0111\u
|
|
|
25604
25576
|
concept,
|
|
25605
25577
|
bloomLevel,
|
|
25606
25578
|
dateStr,
|
|
25607
|
-
targetLang
|
|
25608
|
-
slcMarkdown
|
|
25579
|
+
targetLang
|
|
25609
25580
|
) + mediaDirective;
|
|
25610
25581
|
const rawLesson = await runCurriculumAIInference(
|
|
25611
25582
|
[{ role: "user", content: lessonPrompt }],
|
|
@@ -25723,7 +25694,7 @@ ${yamlBlock.trim()}
|
|
|
25723
25694
|
});
|
|
25724
25695
|
}
|
|
25725
25696
|
const judgeObjectives = parseLessonObjectives(lessonContent, concept, bloomLevel);
|
|
25726
|
-
const judgeExpositionExcerpt = expositionContext ? buildExpositionExcerpt(expositionContext, { budget: 3e3,
|
|
25697
|
+
const judgeExpositionExcerpt = expositionContext ? buildExpositionExcerpt(expositionContext, { budget: 3e3, artifactType: "KNOWLEDGE_EXPOSITION" }).excerpt : void 0;
|
|
25727
25698
|
const judgeResult = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
25728
25699
|
targetArtifactType: "LESSON",
|
|
25729
25700
|
lessonId: lessonCode,
|
|
@@ -25793,7 +25764,6 @@ ${currentContent}` }],
|
|
|
25793
25764
|
const repairedExcerptCheck = buildSectionAwareExcerpt(repairedRaw, {
|
|
25794
25765
|
priorities: DEFAULT_LESSON_PRIORITIES,
|
|
25795
25766
|
budget: 12e3,
|
|
25796
|
-
sectionLanguageContract: slcMarkdown,
|
|
25797
25767
|
artifactType: "LESSON"
|
|
25798
25768
|
});
|
|
25799
25769
|
if (repairedExcerptCheck.issues.includes("parse:no-priority-resolution")) {
|
|
@@ -25824,7 +25794,7 @@ ${currentContent}` }],
|
|
|
25824
25794
|
title: lessonTitle,
|
|
25825
25795
|
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
25826
25796
|
styleGuideExcerpt: effectiveStyleGuide || void 0,
|
|
25827
|
-
canonicalExposition: expositionContext ? buildExpositionExcerpt(expositionContext, { budget: 3e3,
|
|
25797
|
+
canonicalExposition: expositionContext ? buildExpositionExcerpt(expositionContext, { budget: 3e3, artifactType: "KNOWLEDGE_EXPOSITION" }).excerpt : void 0
|
|
25828
25798
|
}),
|
|
25829
25799
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
25830
25800
|
});
|
|
@@ -25954,7 +25924,6 @@ ${currentContent}` }],
|
|
|
25954
25924
|
const lessonExcerptResult = buildSectionAwareExcerpt(lessonContent, {
|
|
25955
25925
|
priorities: SATELLITE_LESSON_PRIORITIES,
|
|
25956
25926
|
budget: 12e3,
|
|
25957
|
-
sectionLanguageContract: slcMarkdown,
|
|
25958
25927
|
artifactType: "LESSON"
|
|
25959
25928
|
});
|
|
25960
25929
|
const lessonExcerpt = lessonExcerptResult.excerpt;
|
|
@@ -25984,7 +25953,6 @@ ${currentContent}` }],
|
|
|
25984
25953
|
lessonContent,
|
|
25985
25954
|
lessonExcerpt: lessonExcerptResult,
|
|
25986
25955
|
expositionContent: expositionContext,
|
|
25987
|
-
slcMarkdown,
|
|
25988
25956
|
symbolLedgerBlock,
|
|
25989
25957
|
pedagogyLabel,
|
|
25990
25958
|
lessonEntity,
|
|
@@ -26098,7 +26066,7 @@ ${NO_VERBATIM_COPYING}`;
|
|
|
26098
26066
|
|
|
26099
26067
|
${languageDirective}
|
|
26100
26068
|
|
|
26101
|
-
${buildHeadingDirective("ACT"
|
|
26069
|
+
${buildHeadingDirective("ACT")}`;
|
|
26102
26070
|
const rawAct = await runCurriculumAIInference(
|
|
26103
26071
|
[{ role: "user", content: actPrompt }],
|
|
26104
26072
|
satelliteContextFor("ACT"),
|
|
@@ -26169,7 +26137,7 @@ ${NO_VERBATIM_COPYING}`;
|
|
|
26169
26137
|
|
|
26170
26138
|
${languageDirective}
|
|
26171
26139
|
|
|
26172
|
-
${buildHeadingDirective("QUIZ"
|
|
26140
|
+
${buildHeadingDirective("QUIZ")}`;
|
|
26173
26141
|
const rawQuiz = await runCurriculumAIInference(
|
|
26174
26142
|
[{ role: "user", content: quizPrompt }],
|
|
26175
26143
|
satelliteContextFor("QUIZ"),
|
|
@@ -26222,7 +26190,7 @@ ${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
|
|
|
26222
26190
|
stylePresetId: "blue-professional",
|
|
26223
26191
|
language: targetLang || "Vietnamese",
|
|
26224
26192
|
languageDirective,
|
|
26225
|
-
headingDirective: buildHeadingDirective("SLIDE"
|
|
26193
|
+
headingDirective: buildHeadingDirective("SLIDE"),
|
|
26226
26194
|
groundContext: slideGroundContext,
|
|
26227
26195
|
productSpecBlock: productSpecBlock || void 0,
|
|
26228
26196
|
satelliteContext: satelliteContextFor("SLIDE"),
|
|
@@ -26305,7 +26273,7 @@ footer: "Curriculum OS \u2022 ${lessonCode} (${pedagogyLabel})"
|
|
|
26305
26273
|
lessonCode,
|
|
26306
26274
|
templateScaffold,
|
|
26307
26275
|
languageDirective,
|
|
26308
|
-
headingDirective: buildHeadingDirective("SLIDE"
|
|
26276
|
+
headingDirective: buildHeadingDirective("SLIDE")
|
|
26309
26277
|
});
|
|
26310
26278
|
const rawSlide = await runCurriculumAIInference(
|
|
26311
26279
|
[{ role: "user", content: slidePrompt }],
|
|
@@ -26374,7 +26342,7 @@ ${NO_VERBATIM_COPYING}`;
|
|
|
26374
26342
|
|
|
26375
26343
|
${languageDirective}
|
|
26376
26344
|
|
|
26377
|
-
${buildHeadingDirective("GUIDE"
|
|
26345
|
+
${buildHeadingDirective("GUIDE")}`;
|
|
26378
26346
|
const rawGuide = await runCurriculumAIInference(
|
|
26379
26347
|
[{ role: "user", content: guidePrompt }],
|
|
26380
26348
|
satelliteContextFor("GUIDE"),
|
|
@@ -26430,7 +26398,7 @@ ${NO_VERBATIM_COPYING}`;
|
|
|
26430
26398
|
|
|
26431
26399
|
${languageDirective}
|
|
26432
26400
|
|
|
26433
|
-
${buildHeadingDirective("HANDOUT"
|
|
26401
|
+
${buildHeadingDirective("HANDOUT")}`;
|
|
26434
26402
|
const rawHandout = await runCurriculumAIInference(
|
|
26435
26403
|
[{ role: "user", content: handoutPrompt }],
|
|
26436
26404
|
satelliteContextFor("HANDOUT"),
|
|
@@ -26486,7 +26454,7 @@ ${NO_VERBATIM_COPYING}`;
|
|
|
26486
26454
|
|
|
26487
26455
|
${languageDirective}
|
|
26488
26456
|
|
|
26489
|
-
${buildHeadingDirective("WKS"
|
|
26457
|
+
${buildHeadingDirective("WKS")}`;
|
|
26490
26458
|
const rawWks = await runCurriculumAIInference(
|
|
26491
26459
|
[{ role: "user", content: wksPrompt }],
|
|
26492
26460
|
satelliteContextFor("WKS"),
|
|
@@ -26549,7 +26517,7 @@ ${NO_VERBATIM_COPYING}`;
|
|
|
26549
26517
|
|
|
26550
26518
|
${languageDirective}
|
|
26551
26519
|
|
|
26552
|
-
${buildHeadingDirective("CODE"
|
|
26520
|
+
${buildHeadingDirective("CODE")}`;
|
|
26553
26521
|
const rawCode = await runCurriculumAIInference(
|
|
26554
26522
|
[{ role: "user", content: codePrompt }],
|
|
26555
26523
|
satelliteContextFor("CODE"),
|
|
@@ -26636,7 +26604,7 @@ ${zpdCeilingPrompt}
|
|
|
26636
26604
|
|
|
26637
26605
|
${languageDirective}
|
|
26638
26606
|
|
|
26639
|
-
${buildHeadingDirective("EXT"
|
|
26607
|
+
${buildHeadingDirective("EXT")}`;
|
|
26640
26608
|
const rawExt = await runCurriculumAIInference(
|
|
26641
26609
|
[{ role: "user", content: extPrompt }],
|
|
26642
26610
|
satelliteContextFor("EXT"),
|
|
@@ -27132,11 +27100,7 @@ async function generateSingleArtifact(req) {
|
|
|
27132
27100
|
language.toLowerCase().includes("bilingual") || language.toLowerCase().includes("song");
|
|
27133
27101
|
const targetLang = resolveTargetLanguageCode(language);
|
|
27134
27102
|
const langDirective = buildLanguageDirective(language);
|
|
27135
|
-
const headingDirective = buildHeadingDirective(
|
|
27136
|
-
artifactType.toUpperCase(),
|
|
27137
|
-
req.sectionLanguageContract,
|
|
27138
|
-
targetLang
|
|
27139
|
-
);
|
|
27103
|
+
const headingDirective = buildHeadingDirective(artifactType.toUpperCase());
|
|
27140
27104
|
const availableSources = {
|
|
27141
27105
|
KNOWLEDGE_EXPOSITION: contextSot.exposition || researchContext,
|
|
27142
27106
|
CANONICAL_LESSON: contextSot.lessonPlan,
|
|
@@ -27203,11 +27167,10 @@ ${symbolLedgerPrompt}
|
|
|
27203
27167
|
|
|
27204
27168
|
IMAGE PLANNING (media ledger) \u2014 QUOTA GEN: t\u1ED1i \u0111a ${mediaPolicy.maxGenImagesPerArtifact} \u1EA3nh AI cho artifact n\xE0y (\u1EA3nh search kho kh\xF4ng gi\u1EDBi h\u1EA1n).
|
|
27205
27169
|
Khi n\u1ED9i dung c\u1EA7n minh h\u1ECDa (diagram quy tr\xECnh, s\u01A1 \u0111\u1ED3 kh\xE1i ni\u1EC7m, step-by-step visual), ch\xE8n placeholder \u0111\xFAng format [IMAGE: slug] (slug ch\u1EEF th\u01B0\u1EDDng-g\u1EA1ch ngang, unique trong b\xE0i, vd img-for-loop-diagram) T\u1EA0I \u0110\xDANG CH\u1ED6 c\u1EA7n \u1EA3nh, tr\xEAn d\xF2ng ri\xEAng. KH\xD4NG t\u1EF1 sinh \u1EA3nh, KH\xD4NG d\xF9ng markdown image \u2014 placeholder s\u1EBD \u0111\u01B0\u1EE3c thay b\u1EB1ng \u1EA3nh th\u1EADt sau khi Media Curator duy\u1EC7t. Ch\u1EC9 \u0111\u1EB7t cho \u1EA3nh TH\u1EF0C S\u1EF0 c\u1EA7n thi\u1EBFt.` : ""}`;
|
|
27206
|
-
const
|
|
27207
|
-
const
|
|
27208
|
-
const
|
|
27209
|
-
const
|
|
27210
|
-
const expositionExcerpt = contextSot.exposition ? buildExpositionExcerpt(contextSot.exposition, { budget: 6e3, sectionLanguageContract: slcContract }).excerpt : "";
|
|
27170
|
+
const frameworkExcerpt = contextSot.framework ? buildSectionAwareExcerpt(contextSot.framework, { budget: 2500 }).excerpt : "";
|
|
27171
|
+
const lessonPlanExcerpt = contextSot.lessonPlan ? buildLessonExcerpt(contextSot.lessonPlan, { budget: 8e3, artifactType: "LESSON" }).excerpt : "";
|
|
27172
|
+
const handoutExcerpt = contextSot.handout ? buildSectionAwareExcerpt(contextSot.handout, { budget: 2e3 }).excerpt : "";
|
|
27173
|
+
const expositionExcerpt = contextSot.exposition ? buildExpositionExcerpt(contextSot.exposition, { budget: 6e3 }).excerpt : "";
|
|
27211
27174
|
const userPrompt = `### CONTEXT GROUND TRUTH:
|
|
27212
27175
|
- Topic / Concept Domain: "${topic}"
|
|
27213
27176
|
- Lesson ID: "${lessonId || "ON_DEMAND"}"
|
|
@@ -29024,6 +28987,7 @@ function isTranslationDue(target, context) {
|
|
|
29024
28987
|
}
|
|
29025
28988
|
|
|
29026
28989
|
// src/services/index.ts
|
|
28990
|
+
init_templateLoader();
|
|
29027
28991
|
init_slideProductionWorkflow();
|
|
29028
28992
|
var LocalWorkspaceManager = class {
|
|
29029
28993
|
baseDir;
|
|
@@ -31550,6 +31514,6 @@ function renderMediaPlaceholder(entry) {
|
|
|
31550
31514
|
return `> \u{1F5BC}\uFE0F [\u1EA2nh \u0111ang ch\u1EDD: ${entry.name} \u2014 s\u1EBD \u0111\u01B0\u1EE3c t\u1EA1o sau khi duy\u1EC7t media]`;
|
|
31551
31515
|
}
|
|
31552
31516
|
|
|
31553
|
-
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,
|
|
31517
|
+
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, extractSectionHeadings, 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, 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 };
|
|
31554
31518
|
//# sourceMappingURL=index.mjs.map
|
|
31555
31519
|
//# sourceMappingURL=index.mjs.map
|