@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/workflow/index.cjs
CHANGED
|
@@ -5,9 +5,9 @@ var path = require('path');
|
|
|
5
5
|
var google = require('@ai-sdk/google');
|
|
6
6
|
var openai = require('@ai-sdk/openai');
|
|
7
7
|
var deepseek = require('@ai-sdk/deepseek');
|
|
8
|
+
var url = require('url');
|
|
8
9
|
var ai = require('ai');
|
|
9
10
|
var zod = require('zod');
|
|
10
|
-
var url = require('url');
|
|
11
11
|
var workflow = require('workflow');
|
|
12
12
|
var fs3 = require('fs/promises');
|
|
13
13
|
var rest = require('@octokit/rest');
|
|
@@ -1136,10 +1136,138 @@ var init_provider_factory = __esm({
|
|
|
1136
1136
|
};
|
|
1137
1137
|
}
|
|
1138
1138
|
});
|
|
1139
|
+
function stripTemplateFrontmatter(raw) {
|
|
1140
|
+
let body = raw;
|
|
1141
|
+
if (body.startsWith("---")) {
|
|
1142
|
+
const end = body.indexOf("\n---", 3);
|
|
1143
|
+
if (end !== -1) body = body.slice(end + 4);
|
|
1144
|
+
}
|
|
1145
|
+
return body.split("\n").filter((l) => l.trim() !== "<!-- INJECT_BODY -->").join("\n").replace(/^\s*\n/, "").trimEnd();
|
|
1146
|
+
}
|
|
1147
|
+
function stripHeadingKey(h) {
|
|
1148
|
+
return h.replace(/\[(REQUIRED|OPTIONAL|CONDITIONAL)\]\s*/gi, "").replace(/^\s*\d+[.)]\s+/, "").replace(/\s+/g, " ").trim();
|
|
1149
|
+
}
|
|
1150
|
+
function isVariableHeading(text) {
|
|
1151
|
+
return /\{\{[^}]*\}\}/.test(text) || /\[[^\]]+\]/.test(text);
|
|
1152
|
+
}
|
|
1153
|
+
function collectHeadings(body) {
|
|
1154
|
+
const out = [];
|
|
1155
|
+
let inFence = false;
|
|
1156
|
+
for (const line of body.split("\n")) {
|
|
1157
|
+
if (/^(```|~~~)/.test(line.trim())) {
|
|
1158
|
+
inFence = !inFence;
|
|
1159
|
+
continue;
|
|
1160
|
+
}
|
|
1161
|
+
if (inFence) continue;
|
|
1162
|
+
const m = line.match(/^(#{2,3})\s+(.*)$/);
|
|
1163
|
+
if (!m) continue;
|
|
1164
|
+
const text = m[2].trim();
|
|
1165
|
+
const optional = /^\[OPTIONAL\]/i.test(text);
|
|
1166
|
+
const name = stripHeadingKey(text);
|
|
1167
|
+
if (!name || isVariableHeading(name)) continue;
|
|
1168
|
+
out.push({ level: m[1].length, name, optional });
|
|
1169
|
+
}
|
|
1170
|
+
return out;
|
|
1171
|
+
}
|
|
1172
|
+
function extractEchoSections(raw) {
|
|
1173
|
+
const hs = collectHeadings(stripTemplateFrontmatter(raw));
|
|
1174
|
+
return {
|
|
1175
|
+
required: hs.filter((h) => !h.optional).map((h) => h.name),
|
|
1176
|
+
optional: hs.filter((h) => h.optional).map((h) => h.name)
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
function extractConditionalSections(raw) {
|
|
1180
|
+
const body = stripTemplateFrontmatter(raw);
|
|
1181
|
+
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));
|
|
1182
|
+
}
|
|
1183
|
+
function extractDeclaredLanguage(raw) {
|
|
1184
|
+
const m = raw.match(/^template_language:\s*["']?([a-zA-Z-]+)["']?\s*$/m);
|
|
1185
|
+
return m?.[1]?.toLowerCase() || "en";
|
|
1186
|
+
}
|
|
1187
|
+
function candidateDirs(explicitDir) {
|
|
1188
|
+
const dirs = [];
|
|
1189
|
+
if (process.env.CURRICULUM_TEMPLATES_DIR) dirs.push(process.env.CURRICULUM_TEMPLATES_DIR);
|
|
1190
|
+
dirs.push(path__default.default.resolve(process.cwd(), "_templates"));
|
|
1191
|
+
for (const rel of KIT_TEMPLATE_FALLBACK_DIRS) {
|
|
1192
|
+
dirs.push(path__default.default.resolve(_moduleDir, rel));
|
|
1193
|
+
dirs.push(path__default.default.resolve(process.cwd(), rel));
|
|
1194
|
+
dirs.push(path__default.default.resolve(process.cwd(), "packages/curriculum-kit", rel));
|
|
1195
|
+
}
|
|
1196
|
+
return dirs;
|
|
1197
|
+
}
|
|
1198
|
+
function findTemplatePath(templateName, explicitDir) {
|
|
1199
|
+
for (const dir of candidateDirs()) {
|
|
1200
|
+
const p = path__default.default.join(dir, templateName);
|
|
1201
|
+
if (!fs2__default.default.existsSync(p)) continue;
|
|
1202
|
+
try {
|
|
1203
|
+
fs2__default.default.accessSync(p, fs2__default.default.constants.R_OK);
|
|
1204
|
+
return p;
|
|
1205
|
+
} catch {
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
return null;
|
|
1209
|
+
}
|
|
1210
|
+
function resolveArtifactTemplate(templateName, opts) {
|
|
1211
|
+
const p = findTemplatePath(templateName);
|
|
1212
|
+
if (!p) return null;
|
|
1213
|
+
try {
|
|
1214
|
+
const raw = fs2__default.default.readFileSync(p, "utf-8");
|
|
1215
|
+
const echo = extractEchoSections(raw);
|
|
1216
|
+
return {
|
|
1217
|
+
content: stripTemplateFrontmatter(raw),
|
|
1218
|
+
sections: echo.required,
|
|
1219
|
+
optionalSections: echo.optional,
|
|
1220
|
+
sourcePath: p,
|
|
1221
|
+
conditionals: extractConditionalSections(raw),
|
|
1222
|
+
declaredLang: extractDeclaredLanguage(raw)
|
|
1223
|
+
};
|
|
1224
|
+
} catch {
|
|
1225
|
+
return null;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
function loadCurriculumTemplate(templateName, templatesDir) {
|
|
1229
|
+
const p = findTemplatePath(templateName);
|
|
1230
|
+
if (!p) return "";
|
|
1231
|
+
try {
|
|
1232
|
+
return fs2__default.default.readFileSync(p, "utf-8");
|
|
1233
|
+
} catch {
|
|
1234
|
+
return "";
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
function loadAuthoringTemplate(templateName, templatesDir) {
|
|
1238
|
+
const p = findTemplatePath(templateName);
|
|
1239
|
+
if (!p) return "";
|
|
1240
|
+
try {
|
|
1241
|
+
return stripTemplateFrontmatter(fs2__default.default.readFileSync(p, "utf-8"));
|
|
1242
|
+
} catch {
|
|
1243
|
+
return "";
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
var KIT_TEMPLATE_FALLBACK_DIRS, _moduleDir;
|
|
1247
|
+
var init_templateLoader = __esm({
|
|
1248
|
+
"src/services/templateLoader.ts"() {
|
|
1249
|
+
KIT_TEMPLATE_FALLBACK_DIRS = [
|
|
1250
|
+
// Packaged with the npm bundle (dist/templates) — resolves from node_modules.
|
|
1251
|
+
"templates",
|
|
1252
|
+
// Repo checkout layouts.
|
|
1253
|
+
"docs/refs/templates"
|
|
1254
|
+
];
|
|
1255
|
+
_moduleDir = (() => {
|
|
1256
|
+
try {
|
|
1257
|
+
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && typeof (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) === "string") {
|
|
1258
|
+
return path__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
|
|
1259
|
+
}
|
|
1260
|
+
} catch {
|
|
1261
|
+
}
|
|
1262
|
+
return typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
1263
|
+
})();
|
|
1264
|
+
}
|
|
1265
|
+
});
|
|
1139
1266
|
|
|
1140
1267
|
// src/parsers/lessonFlowParser.ts
|
|
1141
1268
|
var init_lessonFlowParser = __esm({
|
|
1142
1269
|
"src/parsers/lessonFlowParser.ts"() {
|
|
1270
|
+
init_templateLoader();
|
|
1143
1271
|
}
|
|
1144
1272
|
});
|
|
1145
1273
|
|
|
@@ -2753,72 +2881,9 @@ zod.z.object({
|
|
|
2753
2881
|
}),
|
|
2754
2882
|
phases: zod.z.array(PhaseInputSchema).default([])
|
|
2755
2883
|
});
|
|
2756
|
-
function stripTemplateFrontmatter(raw) {
|
|
2757
|
-
let body = raw;
|
|
2758
|
-
if (body.startsWith("---")) {
|
|
2759
|
-
const end = body.indexOf("\n---", 3);
|
|
2760
|
-
if (end !== -1) body = body.slice(end + 4);
|
|
2761
|
-
}
|
|
2762
|
-
return body.split("\n").filter((l) => l.trim() !== "<!-- INJECT_BODY -->").join("\n").replace(/^\s*\n/, "").trimEnd();
|
|
2763
|
-
}
|
|
2764
|
-
var KIT_TEMPLATE_FALLBACK_DIRS = [
|
|
2765
|
-
// Packaged with the npm bundle (dist/templates) — resolves from node_modules.
|
|
2766
|
-
"templates",
|
|
2767
|
-
// Repo checkout layouts.
|
|
2768
|
-
"docs/refs/templates"
|
|
2769
|
-
];
|
|
2770
|
-
var _moduleDir = (() => {
|
|
2771
|
-
try {
|
|
2772
|
-
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && typeof (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) === "string") {
|
|
2773
|
-
return path__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
|
|
2774
|
-
}
|
|
2775
|
-
} catch {
|
|
2776
|
-
}
|
|
2777
|
-
return typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
2778
|
-
})();
|
|
2779
|
-
function candidateDirs(explicitDir) {
|
|
2780
|
-
const dirs = [];
|
|
2781
|
-
if (process.env.CURRICULUM_TEMPLATES_DIR) dirs.push(process.env.CURRICULUM_TEMPLATES_DIR);
|
|
2782
|
-
dirs.push(path__default.default.resolve(process.cwd(), "_templates"));
|
|
2783
|
-
for (const rel of KIT_TEMPLATE_FALLBACK_DIRS) {
|
|
2784
|
-
dirs.push(path__default.default.resolve(_moduleDir, rel));
|
|
2785
|
-
dirs.push(path__default.default.resolve(process.cwd(), rel));
|
|
2786
|
-
dirs.push(path__default.default.resolve(process.cwd(), "packages/curriculum-kit", rel));
|
|
2787
|
-
}
|
|
2788
|
-
return dirs;
|
|
2789
|
-
}
|
|
2790
|
-
function findTemplatePath(templateName, explicitDir) {
|
|
2791
|
-
for (const dir of candidateDirs()) {
|
|
2792
|
-
const p = path__default.default.join(dir, templateName);
|
|
2793
|
-
if (!fs2__default.default.existsSync(p)) continue;
|
|
2794
|
-
try {
|
|
2795
|
-
fs2__default.default.accessSync(p, fs2__default.default.constants.R_OK);
|
|
2796
|
-
return p;
|
|
2797
|
-
} catch {
|
|
2798
|
-
}
|
|
2799
|
-
}
|
|
2800
|
-
return null;
|
|
2801
|
-
}
|
|
2802
|
-
function loadCurriculumTemplate(templateName, templatesDir) {
|
|
2803
|
-
const p = findTemplatePath(templateName);
|
|
2804
|
-
if (!p) return "";
|
|
2805
|
-
try {
|
|
2806
|
-
return fs2__default.default.readFileSync(p, "utf-8");
|
|
2807
|
-
} catch {
|
|
2808
|
-
return "";
|
|
2809
|
-
}
|
|
2810
|
-
}
|
|
2811
|
-
function loadAuthoringTemplate(templateName, templatesDir) {
|
|
2812
|
-
const p = findTemplatePath(templateName);
|
|
2813
|
-
if (!p) return "";
|
|
2814
|
-
try {
|
|
2815
|
-
return stripTemplateFrontmatter(fs2__default.default.readFileSync(p, "utf-8"));
|
|
2816
|
-
} catch {
|
|
2817
|
-
return "";
|
|
2818
|
-
}
|
|
2819
|
-
}
|
|
2820
2884
|
|
|
2821
2885
|
// src/ai/prompts/lessonMasterPrompt.ts
|
|
2886
|
+
init_templateLoader();
|
|
2822
2887
|
function buildLessonMasterPrompt(input) {
|
|
2823
2888
|
const { milestone, language, topic, targetAudience, contextContinuity, standardsContext } = input;
|
|
2824
2889
|
const learningObjectives = milestone.learning_objectives || [];
|
|
@@ -2920,6 +2985,7 @@ Return a single valid JSON object matching the LessonPlanSchema with these exact
|
|
|
2920
2985
|
}
|
|
2921
2986
|
|
|
2922
2987
|
// src/ai/prompts/activityPrompt.ts
|
|
2988
|
+
init_templateLoader();
|
|
2923
2989
|
function buildActivityPrompt(input) {
|
|
2924
2990
|
const { lesson, language, hardwareBOM, softwareTools } = input;
|
|
2925
2991
|
const loList = lesson.learningObjectives.map((lo) => `- [${lo.bloomLevel}] ${lo.code}: ${lo.name || ""} \u2014 ${lo.description}${lo.successCriteria ? ` (Evidence: ${lo.successCriteria})` : ""}`).join("\n");
|
|
@@ -3019,6 +3085,7 @@ Return a single JSON object matching ActivityLabSchema with these exact keys:
|
|
|
3019
3085
|
}
|
|
3020
3086
|
|
|
3021
3087
|
// src/ai/prompts/codeLabPrompt.ts
|
|
3088
|
+
init_templateLoader();
|
|
3022
3089
|
function buildCodeLabPrompt(input) {
|
|
3023
3090
|
const { lesson, activity, language, targetTechStack } = input;
|
|
3024
3091
|
const techStackList = targetTechStack && targetTechStack.length > 0 ? targetTechStack : ["General Programming & Engineering"];
|
|
@@ -3425,6 +3492,7 @@ Please return a single JSON object matching these exact keys:
|
|
|
3425
3492
|
}
|
|
3426
3493
|
|
|
3427
3494
|
// src/ai/prompts/selfLabPrompt.ts
|
|
3495
|
+
init_templateLoader();
|
|
3428
3496
|
function buildSelfLabPrompt(input) {
|
|
3429
3497
|
const { milestone, projectGraph, language, targetTechStack, contextContinuity } = input;
|
|
3430
3498
|
const techStackList = targetTechStack && targetTechStack.length > 0 ? targetTechStack : milestone.tech_keywords && milestone.tech_keywords.length > 0 ? milestone.tech_keywords : ["General Engineering"];
|
|
@@ -3533,6 +3601,7 @@ Return a single valid JSON object matching SelfLabSchema with these exact keys:
|
|
|
3533
3601
|
}
|
|
3534
3602
|
|
|
3535
3603
|
// src/ai/prompts/diagnosticQuizPrompt.ts
|
|
3604
|
+
init_templateLoader();
|
|
3536
3605
|
function buildDiagnosticQuizPrompt(input) {
|
|
3537
3606
|
const { milestone, language, questionCount = 4, passingScorePct = 80 } = input;
|
|
3538
3607
|
const learningObjectives = milestone.learning_objectives || [];
|
|
@@ -4082,7 +4151,7 @@ ${cc.technicalDepth}`;
|
|
|
4082
4151
|
const dataRows = cc.comparisonTable.rows.map((r) => `| ${r.join(" | ")} |`).join("\n");
|
|
4083
4152
|
str += `
|
|
4084
4153
|
|
|
4085
|
-
|
|
4154
|
+
**Comparison & Trade-off Analysis**
|
|
4086
4155
|
${headerRow}
|
|
4087
4156
|
${dividerRow}
|
|
4088
4157
|
${dataRows}`;
|
|
@@ -4126,7 +4195,8 @@ ${learningObjectivesStr}
|
|
|
4126
4195
|
|
|
4127
4196
|
---
|
|
4128
4197
|
|
|
4129
|
-
## 1. ENGAGE (Hook & High-Stakes Scenario)
|
|
4198
|
+
## 1. ENGAGE (Hook & High-Stakes Scenario)
|
|
4199
|
+
> **Duration:** 10-15 mins
|
|
4130
4200
|
|
|
4131
4201
|
### Real-World Context: "${lesson.hookTitle || "The Incident"}"
|
|
4132
4202
|
${lesson.hookScenario}
|
|
@@ -4135,13 +4205,15 @@ ${lesson.hookQuestions && lesson.hookQuestions.length > 0 ? lesson.hookQuestions
|
|
|
4135
4205
|
|
|
4136
4206
|
---
|
|
4137
4207
|
|
|
4138
|
-
## 2. EXPLORE & EXPLAIN (Core Technical Concepts & Principles)
|
|
4208
|
+
## 2. EXPLORE & EXPLAIN (Core Technical Concepts & Principles)
|
|
4209
|
+
> **Duration:** 30-40 mins
|
|
4139
4210
|
|
|
4140
4211
|
${coreConceptsStr}
|
|
4141
4212
|
|
|
4142
4213
|
---
|
|
4143
4214
|
|
|
4144
|
-
## 3. GUIDED PRACTICE (Visual Architecture & Annotated Code)
|
|
4215
|
+
## 3. GUIDED PRACTICE (Visual Architecture & Annotated Code)
|
|
4216
|
+
> **Duration:** 20-25 mins
|
|
4145
4217
|
|
|
4146
4218
|
### System Architecture & Data Flow (Mermaid Diagram)
|
|
4147
4219
|
${mermaidBlock}
|
|
@@ -4155,7 +4227,8 @@ ${guidedPractice.codeSnippet}
|
|
|
4155
4227
|
|
|
4156
4228
|
---
|
|
4157
4229
|
|
|
4158
|
-
## 4. ELABORATE & INDEPENDENT PRACTICE (Technical Challenge & Scaffolding)
|
|
4230
|
+
## 4. ELABORATE & INDEPENDENT PRACTICE (Technical Challenge & Scaffolding)
|
|
4231
|
+
> **Duration:** 15-20 mins
|
|
4159
4232
|
|
|
4160
4233
|
### Engineering Challenge: "${lesson.independentPractice?.title || "System Optimization Challenge"}"
|
|
4161
4234
|
${lesson.independentPractice?.description || "Implement the core logic and test against simulated edge cases."}
|
|
@@ -4166,7 +4239,8 @@ ${lesson.independentPractice?.description || "Implement the core logic and test
|
|
|
4166
4239
|
|
|
4167
4240
|
---
|
|
4168
4241
|
|
|
4169
|
-
## 5. EVALUATE (Summary, Assessment & Metacognition)
|
|
4242
|
+
## 5. EVALUATE (Summary, Assessment & Metacognition)
|
|
4243
|
+
> **Duration:** 5-10 mins
|
|
4170
4244
|
|
|
4171
4245
|
### Exit Ticket (Bloom: Apply / Analyze)
|
|
4172
4246
|
> **Scenario Question:** ${lesson.exitTicket.questionStem}
|
|
@@ -4259,12 +4333,16 @@ ${hardwareItems}
|
|
|
4259
4333
|
|
|
4260
4334
|
## [REQUIRED] Active Learning Workflow
|
|
4261
4335
|
|
|
4262
|
-
### Phase 1: Planning & Design
|
|
4336
|
+
### Phase 1: Planning & Design
|
|
4337
|
+
> **Duration:** ${phase1.durationMinutes} mins
|
|
4338
|
+
|
|
4263
4339
|
- **Student Task:** ${phase1.studentTask}
|
|
4264
4340
|
- **Teacher Action:** ${phase1.teacherAction}
|
|
4265
4341
|
${phase1.inquiryQuestions.map((q) => ` - *Inquiry Question:* ${q}`).join("\n")}
|
|
4266
4342
|
|
|
4267
|
-
### Phase 2: Implementation & Discovery
|
|
4343
|
+
### Phase 2: Implementation & Discovery
|
|
4344
|
+
> **Duration:** ${phase2.durationMinutes} mins
|
|
4345
|
+
|
|
4268
4346
|
- **Student Task:** ${phase2.studentTask}
|
|
4269
4347
|
- **Teacher Action:** ${phase2.teacherAction}
|
|
4270
4348
|
|
|
@@ -4272,7 +4350,9 @@ ${phase2.codeOrCommands.map((c) => `\`\`\`text
|
|
|
4272
4350
|
${c}
|
|
4273
4351
|
\`\`\``).join("\n\n")}
|
|
4274
4352
|
|
|
4275
|
-
### Phase 3: Debugging & Testing
|
|
4353
|
+
### Phase 3: Debugging & Testing
|
|
4354
|
+
> **Duration:** ${phase3.durationMinutes} mins
|
|
4355
|
+
|
|
4276
4356
|
- **Testing:** ${phase3.testingSteps}
|
|
4277
4357
|
- **Error Analysis:** ${phase3.errorAnalysis}
|
|
4278
4358
|
|
|
@@ -4327,22 +4407,28 @@ This lab focuses on the practical implementation of core technical concepts, bri
|
|
|
4327
4407
|
|
|
4328
4408
|
## \u{1F4DD} Lab Tasks (3-Tier Differentiation)
|
|
4329
4409
|
|
|
4330
|
-
### \u{1F949} Bronze (Foundational)
|
|
4410
|
+
### \u{1F949} Bronze (Foundational)
|
|
4411
|
+
> **Duration:** ${tasks.bronze.mins} mins
|
|
4412
|
+
|
|
4331
4413
|
**Objective:** ${tasks.bronze.objective}
|
|
4332
4414
|
- **Task:** ${tasks.bronze.task}
|
|
4333
4415
|
- **Requirement:** ${tasks.bronze.requirement}
|
|
4334
4416
|
|
|
4335
|
-
### \u{1F948} Silver (Application)
|
|
4417
|
+
### \u{1F948} Silver (Application)
|
|
4418
|
+
> **Duration:** ${tasks.silver.mins} mins
|
|
4419
|
+
|
|
4336
4420
|
**Objective:** ${tasks.silver.objective}
|
|
4337
4421
|
- **Task:** ${tasks.silver.task}
|
|
4338
4422
|
- **Requirement:** ${tasks.silver.requirement}
|
|
4339
4423
|
|
|
4340
|
-
### \u{1F947} Gold (Enrichment/Creative)
|
|
4424
|
+
### \u{1F947} Gold (Enrichment/Creative)
|
|
4425
|
+
> **Duration:** ${tasks.gold.mins} mins
|
|
4426
|
+
|
|
4341
4427
|
**Objective:** ${tasks.gold.objective}
|
|
4342
4428
|
- **Task:** ${tasks.gold.task}
|
|
4343
4429
|
- **Requirement:** ${tasks.gold.requirement}
|
|
4344
4430
|
|
|
4345
|
-
## \u{1F4BB} Technical Reference
|
|
4431
|
+
## \u{1F4BB} Technical Reference
|
|
4346
4432
|
<!-- [SME_MANDATE] -->
|
|
4347
4433
|
> Any code provided in this section is verified for syntax accuracy and runtime execution.
|
|
4348
4434
|
|
|
@@ -4417,7 +4503,9 @@ ${proTipsStr}
|
|
|
4417
4503
|
function serializeSelfLabToMarkdown(lab) {
|
|
4418
4504
|
const renderChallenge = (c, label) => {
|
|
4419
4505
|
const tasksList = c.tasks.map((t) => `- ${t}`).join("\n");
|
|
4420
|
-
return `### ${label}: ${c.title}
|
|
4506
|
+
return `### ${label}: ${c.title}
|
|
4507
|
+
> **Duration:** ~${c.estimatedMinutes} mins
|
|
4508
|
+
|
|
4421
4509
|
**Objective:** ${c.objective}
|
|
4422
4510
|
|
|
4423
4511
|
#### Tasks & Implementation Details:
|
|
@@ -18527,6 +18615,7 @@ var LLMJudgeEngine = class {
|
|
|
18527
18615
|
init_errors();
|
|
18528
18616
|
|
|
18529
18617
|
// src/services/languageDirective.ts
|
|
18618
|
+
init_templateLoader();
|
|
18530
18619
|
function resolveTargetLanguageCode(language) {
|
|
18531
18620
|
const raw = String(language || "vi").trim().toLowerCase();
|
|
18532
18621
|
if (raw.startsWith("vi")) return "vi";
|
|
@@ -18556,193 +18645,46 @@ function buildLanguageDirective(targetLanguage) {
|
|
|
18556
18645
|
${exampleLine}` : ""}
|
|
18557
18646
|
- 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.`;
|
|
18558
18647
|
}
|
|
18559
|
-
|
|
18560
|
-
|
|
18561
|
-
|
|
18562
|
-
|
|
18563
|
-
|
|
18564
|
-
|
|
18565
|
-
|
|
18566
|
-
|
|
18567
|
-
|
|
18568
|
-
|
|
18569
|
-
|
|
18570
|
-
|
|
18571
|
-
|
|
18572
|
-
|
|
18573
|
-
|
|
18574
|
-
|
|
18575
|
-
|
|
18576
|
-
|
|
18577
|
-
PROJECT_BRIEF:
|
|
18578
|
-
|
|
18579
|
-
|
|
18580
|
-
"Learning Roadmap": "L\u1ED9 tr\xECnh H\u1ECDc t\u1EADp & C\u1ED9t m\u1ED1c",
|
|
18581
|
-
"Artifact Scope": "Ph\u1EA1m vi S\u1EA3n ph\u1EA9m H\u1ECDc t\u1EADp"
|
|
18582
|
-
},
|
|
18583
|
-
CURRICULUM_FRAMEWORK: {
|
|
18584
|
-
"Course Overview": "T\u1ED5ng quan Kh\xF3a h\u1ECDc",
|
|
18585
|
-
"Global Learning Objectives": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp To\xE0n di\u1EC7n",
|
|
18586
|
-
"Structural Hierarchy (Unit & Module)": "C\u1EA5u tr\xFAc Kh\xF3a h\u1ECDc (Unit & Module)",
|
|
18587
|
-
"Scope & Sequence (Detailed Roadmap)": "Ph\u1EA1m vi & Tr\xECnh t\u1EF1 Chi ti\u1EBFt"
|
|
18588
|
-
},
|
|
18589
|
-
CONTENT_STYLE_GUIDE: {
|
|
18590
|
-
"Voice & Tone": "Gi\u1ECDng v\u0103n & Phong c\xE1ch",
|
|
18591
|
-
"Standard Terminology (Glossary)": "Thu\u1EADt ng\u1EEF Chu\u1EA9n (B\u1EA3ng thu\u1EADt ng\u1EEF)",
|
|
18592
|
-
"Examples & Context Rules": "Quy t\u1EAFc V\xED d\u1EE5 & Ng\u1EEF c\u1EA3nh",
|
|
18593
|
-
"Lesson Content Standards": "Ti\xEAu chu\u1EA9n N\u1ED9i dung B\xE0i h\u1ECDc"
|
|
18594
|
-
},
|
|
18595
|
-
SECTION_LANGUAGE_CONTRACT: {
|
|
18596
|
-
"Metadata & Scope": "Th\xF4ng tin & Ph\u1EA1m vi H\u1EE3p \u0111\u1ED3ng",
|
|
18597
|
-
"Section Translation Matrix": "Ma tr\u1EADn Ti\xEAu \u0111\u1EC1 \u0110a ng\xF4n ng\u1EEF",
|
|
18598
|
-
"Validation Rules": "Quy t\u1EAFc X\xE1c th\u1EF1c & Kh\xF3a Chu\u1EA9n"
|
|
18599
|
-
},
|
|
18600
|
-
KNOWLEDGE_EXPOSITION: {
|
|
18601
|
-
"Session Scope": "Ph\u1EA1m vi Bu\u1ED5i h\u1ECDc",
|
|
18602
|
-
"Key Terms": "Thu\u1EADt ng\u1EEF Then ch\u1ED1t",
|
|
18603
|
-
"Concept Narratives": "Di\u1EC5n gi\u1EA3i Kh\xE1i ni\u1EC7m",
|
|
18604
|
-
"Worked Micro-Examples": "V\xED d\u1EE5 M\u1EABu Chi ti\u1EBFt",
|
|
18605
|
-
"Common Mistakes": "L\u1ED7i Th\u01B0\u1EDDng g\u1EB7p & Kh\u1EAFc ph\u1EE5c",
|
|
18606
|
-
"Self-Check Questions": "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra"
|
|
18607
|
-
},
|
|
18608
|
-
LESSON: {
|
|
18609
|
-
"A. Lesson Design Plan": "A. K\u1EBF ho\u1EA1ch Thi\u1EBFt k\u1EBF B\xE0i h\u1ECDc",
|
|
18610
|
-
"Learning Objectives & Evidence": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp & B\u1EB1ng ch\u1EE9ng N\u0103ng l\u1EF1c",
|
|
18611
|
-
"Activity Sequence": "Chu\u1ED7i Ho\u1EA1t \u0111\u1ED9ng D\u1EA1y & H\u1ECDc",
|
|
18612
|
-
"Resource Map": "B\u1EA3n \u0111\u1ED3 T\xE0i nguy\xEAn & H\u1ECDc li\u1EC7u",
|
|
18613
|
-
"Assessment Map": "B\u1EA3n \u0111\u1ED3 \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c",
|
|
18614
|
-
"Artifact Contract": "H\u1EE3p \u0111\u1ED3ng S\u1EA3n ph\u1EA9m \u0110\u1EA7u ra",
|
|
18615
|
-
"B. Lesson Flow": "B. Ti\u1EBFn tr\xECnh Gi\u1EA3ng d\u1EA1y Chi ti\u1EBFt"
|
|
18616
|
-
},
|
|
18617
|
-
ACT: {
|
|
18618
|
-
"Computational Thinking Focus": "Tr\u1ECDng t\xE2m T\u01B0 duy M\xE1y t\xEDnh",
|
|
18619
|
-
"Materials & Setup": "V\u1EADt li\u1EC7u & Chu\u1EA9n b\u1ECB Thi\u1EBFt b\u1ECB",
|
|
18620
|
-
"Constraints & Safety": "R\xE0ng bu\u1ED9c & An to\xE0n Ph\xF2ng th\u1EF1c h\xE0nh",
|
|
18621
|
-
"Active Learning Workflow": "Quy tr\xECnh Ho\u1EA1t \u0111\u1ED9ng Tr\u1EA3i nghi\u1EC7m",
|
|
18622
|
-
"3-Tier Differentiation": "Ph\xE2n h\xF3a H\u1ECDc t\u1EADp 3 T\u1EA7ng",
|
|
18623
|
-
"Reflection": "T\u1ED5ng k\u1EBFt & \u0110\xFAc k\u1EBFt Tr\u1EA3i nghi\u1EC7m"
|
|
18624
|
-
},
|
|
18625
|
-
CODE: {
|
|
18626
|
-
"Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
|
|
18627
|
-
"Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
|
|
18628
|
-
"Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
|
|
18629
|
-
"Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
|
|
18630
|
-
"Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
|
|
18631
|
-
"Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
|
|
18632
|
-
},
|
|
18633
|
-
CODE_LAB: {
|
|
18634
|
-
"Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
|
|
18635
|
-
"Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
|
|
18636
|
-
"Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
|
|
18637
|
-
"Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
|
|
18638
|
-
"Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
|
|
18639
|
-
"Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
|
|
18640
|
-
},
|
|
18641
|
-
QUIZ: {
|
|
18642
|
-
"Assessment Objectives": "M\u1EE5c ti\xEAu \u0110\xE1nh gi\xE1",
|
|
18643
|
-
"Multiple-Choice Question Bank": "Ng\xE2n h\xE0ng C\xE2u h\u1ECFi Tr\u1EAFc nghi\u1EC7m",
|
|
18644
|
-
"Code Analysis / Debugging Question": "C\xE2u h\u1ECFi Ph\xE2n t\xEDch M\xE3 ngu\u1ED3n & S\u1EEDa l\u1ED7i",
|
|
18645
|
-
"Competency Rubric": "Thang \u0111o \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c (Rubric)"
|
|
18646
|
-
},
|
|
18647
|
-
GUIDE: {
|
|
18648
|
-
"Objectives & Preparation": "M\u1EE5c ti\xEAu & Chu\u1EA9n b\u1ECB Gi\u1EA3ng d\u1EA1y",
|
|
18649
|
-
"Preparation Checklist & Workstation Setup": "Danh m\u1EE5c Ki\u1EC3m tra Chu\u1EA9n b\u1ECB & Tr\u1EA1m Th\u1EF1c h\xE0nh",
|
|
18650
|
-
"Facilitation Script & Timeline": "K\u1ECBch b\u1EA3n \u0110i\u1EC1u ph\u1ED1i & Khung Th\u1EDDi gian",
|
|
18651
|
-
"Common Misconceptions & Diagnostic Remediation Matrix": "Quan ni\u1EC7m Sai l\u1EA7m Th\u01B0\u1EDDng g\u1EB7p & Ma tr\u1EADn Kh\u1EAFc ph\u1EE5c",
|
|
18652
|
-
"Differentiated Support Strategies": "Chi\u1EBFn l\u01B0\u1EE3c H\u1ED7 tr\u1EE3 Ph\xE2n h\xF3a"
|
|
18653
|
-
},
|
|
18654
|
-
HANDOUT: {
|
|
18655
|
-
"Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
|
|
18656
|
-
"Core Syntax & Mechanism Cheat Sheet": "B\u1EA3ng Tra c\u1EE9u C\xFA ph\xE1p & C\u01A1 ch\u1EBF Tr\u1ECDng t\xE2m",
|
|
18657
|
-
"Visual Mental Model / Architecture Diagram": "M\xF4 h\xECnh T\u01B0 duy Tr\u1EF1c quan / S\u01A1 \u0111\u1ED3 Ki\u1EBFn tr\xFAc",
|
|
18658
|
-
"Step-by-Step Practical Quick-Start Guide": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh T\u1EEBng b\u01B0\u1EDBc",
|
|
18659
|
-
"Self-Check Diagnostic Checklist": "B\u1EA3ng Ki\u1EC3m tra T\u1EF1 ch\u1EA9n \u0111o\xE1n"
|
|
18660
|
-
},
|
|
18661
|
-
WKS: {
|
|
18662
|
-
"Part 1: Knowledge Check": "Ph\u1EA7n 1: Ki\u1EC3m tra Ki\u1EBFn th\u1EE9c",
|
|
18663
|
-
"Part 2: Concept Tracing & Diagram Fill-in": "Ph\u1EA7n 2: L\u1EA7n v\u1EBFt Kh\xE1i ni\u1EC7m & \u0110i\u1EC1n S\u01A1 \u0111\u1ED3",
|
|
18664
|
-
"Part 3: Code Analysis & Bug Hunting Challenge": "Ph\u1EA7n 3: Ph\xE2n t\xEDch M\xE3 & Th\u1EED th\xE1ch S\u0103n l\u1ED7i",
|
|
18665
|
-
"Part 4: Synthesis & Problem-Solving Application": "Ph\u1EA7n 4: T\u1ED5ng h\u1EE3p & \u1EE8ng d\u1EE5ng Gi\u1EA3i quy\u1EBFt V\u1EA5n \u0111\u1EC1",
|
|
18666
|
-
"Part 5: Self-Reflection & Learning Log": "Ph\u1EA7n 5: T\u1EF1 suy ng\u1EABm & Nh\u1EADt k\xFD H\u1ECDc t\u1EADp"
|
|
18667
|
-
},
|
|
18668
|
-
EXT: {
|
|
18669
|
-
"For: Advanced Students / Extra Time": "D\xE0nh cho: H\u1ECDc sinh N\xE2ng cao / Ho\xE0n th\xE0nh S\u1EDBm",
|
|
18670
|
-
"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",
|
|
18671
|
-
"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",
|
|
18672
|
-
"Challenge 3: Extension Milestones": "Th\u1EED th\xE1ch 3: C\xE1c M\u1ED1c Nhi\u1EC7m v\u1EE5 N\xE2ng cao",
|
|
18673
|
-
"Metacognitive Deep Dive & Engineering Trade-offs": "Suy ng\u1EABm Si\xEAu nh\u1EADn th\u1EE9c & \u0110\xE1nh \u0111\u1ED5i K\u1EF9 thu\u1EADt"
|
|
18674
|
-
},
|
|
18675
|
-
SLIDE: {
|
|
18676
|
-
"Title & Agenda": "Ti\xEAu \u0111\u1EC1 & M\u1EE5c l\u1EE5c",
|
|
18677
|
-
"Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
|
|
18678
|
-
"Guided Demonstration": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh & Th\u1ECB ph\u1EA1m",
|
|
18679
|
-
"Hands-on Mission": "Nhi\u1EC7m v\u1EE5 Th\u1EF1c h\xE0nh Tr\u1EA3i nghi\u1EC7m",
|
|
18680
|
-
"Summary & Next Steps": "T\u1ED5ng k\u1EBFt & \u0110\u1ECBnh h\u01B0\u1EDBng Ti\u1EBFp theo"
|
|
18681
|
-
}
|
|
18648
|
+
var TEMPLATE_BY_TYPE = {
|
|
18649
|
+
LESSON: "LESSON_5E_template.md",
|
|
18650
|
+
LESSON_5E: "LESSON_5E_template.md",
|
|
18651
|
+
LESSON_EDP: "LESSON_EDP_template.md",
|
|
18652
|
+
LESSON_GENERAL: "LESSON_GENERAL_template.md",
|
|
18653
|
+
ACT: "ACT_template.md",
|
|
18654
|
+
CODE: "CODE_template.md",
|
|
18655
|
+
// JSON-first code lab shares the CODE label set (the serializer renders its
|
|
18656
|
+
// own headings; this lookup only feeds the directive fallback path).
|
|
18657
|
+
CODE_LAB: "CODE_template.md",
|
|
18658
|
+
QUIZ: "QUIZ_v4.6_template.md",
|
|
18659
|
+
GUIDE: "GUIDE_template.md",
|
|
18660
|
+
HANDOUT: "HANDOUT_template.md",
|
|
18661
|
+
WKS: "WKS_template.md",
|
|
18662
|
+
EXT: "EXT_template.md",
|
|
18663
|
+
SLIDE: "SLIDE_template.md",
|
|
18664
|
+
KNOWLEDGE_EXPOSITION: "KNOWLEDGE_EXPOSITION_template.md",
|
|
18665
|
+
LEARNER_PROFILE: "LEARNER_PROFILE_template.md",
|
|
18666
|
+
PROJECT_BRIEF: "PROJECT_BRIEF_template.md",
|
|
18667
|
+
CURRICULUM_FRAMEWORK: "CURRICULUM_FRAMEWORK_template.md",
|
|
18668
|
+
CONTENT_STYLE_GUIDE: "CONTENT_STYLE_GUIDE_template.md"
|
|
18682
18669
|
};
|
|
18683
|
-
function
|
|
18684
|
-
const
|
|
18685
|
-
|
|
18686
|
-
|
|
18687
|
-
|
|
18688
|
-
|
|
18689
|
-
return mapping;
|
|
18690
|
-
}
|
|
18691
|
-
}
|
|
18692
|
-
}
|
|
18693
|
-
return {};
|
|
18694
|
-
};
|
|
18695
|
-
if (!slcInput) return getFallback();
|
|
18696
|
-
if (typeof slcInput === "object") {
|
|
18697
|
-
if (slcInput[upperType] && Object.keys(slcInput[upperType]).length > 0) return slcInput[upperType];
|
|
18698
|
-
for (const [key, mapping] of Object.entries(slcInput)) {
|
|
18699
|
-
if (matchesArtifactType(key, upperType) && Object.keys(mapping).length > 0) {
|
|
18700
|
-
return mapping;
|
|
18701
|
-
}
|
|
18702
|
-
}
|
|
18703
|
-
return getFallback();
|
|
18704
|
-
}
|
|
18705
|
-
const slcMarkdown = slcInput;
|
|
18706
|
-
const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
18707
|
-
for (const block of blocks) {
|
|
18708
|
-
const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
18709
|
-
if (!headerMatch) continue;
|
|
18710
|
-
const blockType = headerMatch[1].trim().toUpperCase();
|
|
18711
|
-
if (matchesArtifactType(blockType, upperType)) {
|
|
18712
|
-
const mapping = {};
|
|
18713
|
-
const lines = block.split("\n");
|
|
18714
|
-
for (const line of lines) {
|
|
18715
|
-
const trimmed = line.trim();
|
|
18716
|
-
if (trimmed.startsWith("|") && !trimmed.includes("---")) {
|
|
18717
|
-
const cells = trimmed.split("|").map((c) => c.trim()).filter((_, idx, arr) => idx > 0 && idx < arr.length - 1);
|
|
18718
|
-
if (cells.length >= 2 && !cells[0].toLowerCase().includes("canonical") && !cells[1].toLowerCase().includes("localized")) {
|
|
18719
|
-
mapping[cells[0]] = cells[1];
|
|
18720
|
-
}
|
|
18721
|
-
} else {
|
|
18722
|
-
const bullet = line.match(/^[-*]\s+([^:]+):\s+(.+)$/);
|
|
18723
|
-
if (bullet) {
|
|
18724
|
-
mapping[bullet[1].trim()] = bullet[2].trim();
|
|
18725
|
-
}
|
|
18726
|
-
}
|
|
18727
|
-
}
|
|
18728
|
-
if (Object.keys(mapping).length > 0) return mapping;
|
|
18729
|
-
}
|
|
18730
|
-
}
|
|
18731
|
-
return getFallback();
|
|
18670
|
+
function extractSectionHeadings(artifactType, opts) {
|
|
18671
|
+
const templateFile = TEMPLATE_BY_TYPE[artifactType.trim().toUpperCase()];
|
|
18672
|
+
if (!templateFile) return {};
|
|
18673
|
+
const resolved = resolveArtifactTemplate(templateFile);
|
|
18674
|
+
if (!resolved) return {};
|
|
18675
|
+
return Object.fromEntries(resolved.sections.map((s) => [s, s]));
|
|
18732
18676
|
}
|
|
18733
|
-
function buildHeadingDirective(artifactType,
|
|
18734
|
-
const headings =
|
|
18677
|
+
function buildHeadingDirective(artifactType, opts) {
|
|
18678
|
+
const headings = extractSectionHeadings(artifactType);
|
|
18735
18679
|
if (Object.keys(headings).length === 0) {
|
|
18736
18680
|
return "";
|
|
18737
18681
|
}
|
|
18738
|
-
const lines = Object.
|
|
18739
|
-
|
|
18740
|
-
|
|
18741
|
-
|
|
18742
|
-
- The YAML frontmatter \`template_required_sections\` MUST preserve the exact English canonical keys.
|
|
18743
|
-
- In the markdown body, section headers MUST use the EXACT Localized Display Labels below (do NOT translate or paraphrase):
|
|
18682
|
+
const lines = Object.keys(headings).map((heading) => ` - "${heading}"`);
|
|
18683
|
+
return `MANDATORY SECTION HEADINGS (SOURCE: RESOLVED ARTIFACT TEMPLATE):
|
|
18684
|
+
- Copy the template's YAML frontmatter \`template_required_sections\` list VERBATIM into the artifact frontmatter \u2014 never translate, reorder, or invent entries.
|
|
18685
|
+
- In the markdown body, section headers MUST be exactly the Display Headings below (do NOT translate, paraphrase, or re-marker them):
|
|
18744
18686
|
${lines.join("\n")}
|
|
18745
|
-
-
|
|
18687
|
+
- Example: if the resolved template's heading is "${Object.values(headings)[0]}", your body heading must be exactly "## ${Object.values(headings)[0]}".`;
|
|
18746
18688
|
}
|
|
18747
18689
|
|
|
18748
18690
|
// src/services/curriculumHorizon.ts
|
|
@@ -19056,9 +18998,8 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
|
|
|
19056
18998
|
};
|
|
19057
18999
|
}
|
|
19058
19000
|
const minContentChars = opts.minContentChars !== void 0 ? opts.minContentChars : Math.min(400, source.length);
|
|
19059
|
-
const slcMap = normalizeSlcContract(opts.sectionLanguageContract);
|
|
19060
19001
|
const effectiveArtifactType = opts.artifactType || deriveArtifactTypeFromFileName(opts.fileName);
|
|
19061
|
-
const sections = parseMarkdownSections(source
|
|
19002
|
+
const sections = parseMarkdownSections(source);
|
|
19062
19003
|
const metaBlock = buildMetaBlock(source, effectiveArtifactType);
|
|
19063
19004
|
if (sections.length === 0) {
|
|
19064
19005
|
issues.push("parse:no-sections");
|
|
@@ -19181,48 +19122,16 @@ function buildLessonExcerpt(markdown, opts = {}) {
|
|
|
19181
19122
|
priorities: DEFAULT_LESSON_PRIORITIES
|
|
19182
19123
|
});
|
|
19183
19124
|
}
|
|
19184
|
-
function
|
|
19185
|
-
if (!slc) return void 0;
|
|
19186
|
-
if (typeof slc !== "string") return slc;
|
|
19187
|
-
const out = {};
|
|
19188
|
-
const blocks = slc.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
19189
|
-
for (const block of blocks) {
|
|
19190
|
-
const header = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
19191
|
-
if (!header?.[1]) continue;
|
|
19192
|
-
const mapping = {};
|
|
19193
|
-
for (const line of block.split("\n")) {
|
|
19194
|
-
const t = line.trim();
|
|
19195
|
-
if (!t.startsWith("|") || t.includes("---")) continue;
|
|
19196
|
-
const cells = t.split("|").map((c) => c.trim()).filter((_, i, a) => i > 0 && i < a.length - 1);
|
|
19197
|
-
const [c0, c1] = cells;
|
|
19198
|
-
if (c0 && c1 && !c0.toLowerCase().includes("canonical") && !c1.toLowerCase().includes("localized")) {
|
|
19199
|
-
mapping[c0] = c1;
|
|
19200
|
-
}
|
|
19201
|
-
}
|
|
19202
|
-
if (Object.keys(mapping).length > 0) out[header[1]] = mapping;
|
|
19203
|
-
}
|
|
19204
|
-
return Object.keys(out).length > 0 ? out : void 0;
|
|
19205
|
-
}
|
|
19206
|
-
function parseMarkdownSections(markdown, slcMap, artifactType) {
|
|
19125
|
+
function parseMarkdownSections(markdown) {
|
|
19207
19126
|
const sections = [];
|
|
19208
19127
|
const lines = markdown.split("\n");
|
|
19209
19128
|
let currentHeading = "";
|
|
19210
19129
|
let currentBody = [];
|
|
19211
|
-
const reverseMap = /* @__PURE__ */ new Map();
|
|
19212
|
-
if (slcMap) {
|
|
19213
|
-
const maps = artifactType && slcMap[artifactType] ? [slcMap[artifactType]] : Object.values(slcMap);
|
|
19214
|
-
for (const m of maps) {
|
|
19215
|
-
for (const [canonical, localized] of Object.entries(m)) {
|
|
19216
|
-
reverseMap.set(normalizeHeading(localized), canonical);
|
|
19217
|
-
reverseMap.set(normalizeHeading(canonical), canonical);
|
|
19218
|
-
}
|
|
19219
|
-
}
|
|
19220
|
-
}
|
|
19221
19130
|
const flush = () => {
|
|
19222
19131
|
if (!currentHeading) return;
|
|
19223
19132
|
const cleanTitle = currentHeading.replace(/^#{1,4}\s+/, "").trim();
|
|
19224
19133
|
const norm = normalizeHeading(cleanTitle);
|
|
19225
|
-
const canonicalKey =
|
|
19134
|
+
const canonicalKey = findCanonicalFuzzy(norm);
|
|
19226
19135
|
sections.push({
|
|
19227
19136
|
rawHeading: currentHeading,
|
|
19228
19137
|
cleanTitle,
|
|
@@ -19321,7 +19230,7 @@ function buildMetaBlock(source, artifactType) {
|
|
|
19321
19230
|
function deriveArtifactTypeFromFileName(fileName) {
|
|
19322
19231
|
if (!fileName) return void 0;
|
|
19323
19232
|
const base = fileName.replace(/\.md$/i, "");
|
|
19324
|
-
const multiWord = base.match(/^(KNOWLEDGE_EXPOSITION|
|
|
19233
|
+
const multiWord = base.match(/^(KNOWLEDGE_EXPOSITION|CONTENT_STYLE_GUIDE|CURRICULUM_FRAMEWORK|LEARNER_PROFILE|PROJECT_BRIEF|REFERENCE_PACK|CURRICULUM_PLAN)/i);
|
|
19325
19234
|
if (multiWord) return multiWord[1].toUpperCase();
|
|
19326
19235
|
const token = base.match(/^([A-Z][A-Z0-9_]*?)(?=_|$)/);
|
|
19327
19236
|
return token ? token[1] : void 0;
|
|
@@ -19390,6 +19299,9 @@ zod.z.object({
|
|
|
19390
19299
|
tieredScaffolding: zod.z.object({ bronze: zod.z.string().default(""), silver: zod.z.string().default(""), gold: zod.z.string().default("") }).default({ bronze: "", silver: "", gold: "" })
|
|
19391
19300
|
});
|
|
19392
19301
|
|
|
19302
|
+
// src/services/lessonProductionService.ts
|
|
19303
|
+
init_templateLoader();
|
|
19304
|
+
|
|
19393
19305
|
// src/services/singleArtifactService.ts
|
|
19394
19306
|
init_errors();
|
|
19395
19307
|
|
|
@@ -19555,11 +19467,7 @@ async function generateSingleArtifact(req) {
|
|
|
19555
19467
|
language.toLowerCase().includes("bilingual") || language.toLowerCase().includes("song");
|
|
19556
19468
|
const targetLang = resolveTargetLanguageCode(language);
|
|
19557
19469
|
const langDirective = buildLanguageDirective(language);
|
|
19558
|
-
const headingDirective = buildHeadingDirective(
|
|
19559
|
-
artifactType.toUpperCase(),
|
|
19560
|
-
req.sectionLanguageContract,
|
|
19561
|
-
targetLang
|
|
19562
|
-
);
|
|
19470
|
+
const headingDirective = buildHeadingDirective(artifactType.toUpperCase());
|
|
19563
19471
|
const availableSources = {
|
|
19564
19472
|
KNOWLEDGE_EXPOSITION: contextSot.exposition || researchContext,
|
|
19565
19473
|
CANONICAL_LESSON: contextSot.lessonPlan,
|
|
@@ -19626,11 +19534,10 @@ ${symbolLedgerPrompt}
|
|
|
19626
19534
|
|
|
19627
19535
|
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).
|
|
19628
19536
|
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.` : ""}`;
|
|
19629
|
-
const
|
|
19630
|
-
const
|
|
19631
|
-
const
|
|
19632
|
-
const
|
|
19633
|
-
const expositionExcerpt = contextSot.exposition ? buildExpositionExcerpt(contextSot.exposition, { budget: 6e3, sectionLanguageContract: slcContract }).excerpt : "";
|
|
19537
|
+
const frameworkExcerpt = contextSot.framework ? buildSectionAwareExcerpt(contextSot.framework, { budget: 2500 }).excerpt : "";
|
|
19538
|
+
const lessonPlanExcerpt = contextSot.lessonPlan ? buildLessonExcerpt(contextSot.lessonPlan, { budget: 8e3, artifactType: "LESSON" }).excerpt : "";
|
|
19539
|
+
const handoutExcerpt = contextSot.handout ? buildSectionAwareExcerpt(contextSot.handout, { budget: 2e3 }).excerpt : "";
|
|
19540
|
+
const expositionExcerpt = contextSot.exposition ? buildExpositionExcerpt(contextSot.exposition, { budget: 6e3 }).excerpt : "";
|
|
19634
19541
|
const userPrompt = `### CONTEXT GROUND TRUTH:
|
|
19635
19542
|
- Topic / Concept Domain: "${topic}"
|
|
19636
19543
|
- Lesson ID: "${lessonId || "ON_DEMAND"}"
|