@thanh01.pmt/curriculum-kit 1.4.6 → 1.4.8
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/index.cjs +282 -100
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.mjs +282 -101
- package/dist/index.mjs.map +1 -1
- package/dist/workflow/index.cjs +218 -84
- package/dist/workflow/index.cjs.map +1 -1
- package/dist/workflow/index.mjs +218 -84
- package/dist/workflow/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -9819,6 +9819,224 @@ function gateModeFor(resolved, type) {
|
|
|
9819
9819
|
return resolved[type] ?? "OFF";
|
|
9820
9820
|
}
|
|
9821
9821
|
|
|
9822
|
+
// src/services/languageDirective.ts
|
|
9823
|
+
function resolveTargetLanguageCode(language) {
|
|
9824
|
+
const raw = String(language || "vi").trim().toLowerCase();
|
|
9825
|
+
if (raw.startsWith("vi")) return "vi";
|
|
9826
|
+
if (raw.startsWith("en")) return "en";
|
|
9827
|
+
return raw || "vi";
|
|
9828
|
+
}
|
|
9829
|
+
function targetLanguageDisplayName(code) {
|
|
9830
|
+
const map = {
|
|
9831
|
+
vi: "Vietnamese (Ti\u1EBFng Vi\u1EC7t)",
|
|
9832
|
+
en: "English (US)"
|
|
9833
|
+
};
|
|
9834
|
+
return map[code] || code;
|
|
9835
|
+
}
|
|
9836
|
+
function buildLanguageDirective(targetLanguage) {
|
|
9837
|
+
const code = resolveTargetLanguageCode(targetLanguage);
|
|
9838
|
+
const name = targetLanguageDisplayName(code);
|
|
9839
|
+
const perLanguageExamples = {
|
|
9840
|
+
vi: `- V\xED d\u1EE5 ti\xEAu \u0111\u1EC1 b\xE0i h\u1ECDc \u0111\xFAng chu\u1EA9n: "B\xE0i 1: Kh\xE1m ph\xE1 m\u1EA1ch \u0111i\u1EC7n c\u01A1 b\u1EA3n", "B\xE0i 2: \u0110i\u1EC1u khi\u1EC3n \u0111\xE8n LED nh\u1EA5p nh\xE1y" \u2014 KH\xD4NG d\xF9ng ti\xEAu \u0111\u1EC1 ti\u1EBFng Anh.`,
|
|
9841
|
+
en: `- Example compliant lesson title: "Lesson 1: Exploring Basic Circuits" \u2014 natural, idiomatic English throughout.`
|
|
9842
|
+
};
|
|
9843
|
+
const exampleLine = perLanguageExamples[code] || "";
|
|
9844
|
+
return `MANDATORY LANGUAGE DIRECTIVE (TARGET OUTPUT LANGUAGE: ${name}):
|
|
9845
|
+
- The TARGET OUTPUT LANGUAGE for this course is ${name}. You MUST author the ENTIRE document in ${name}.
|
|
9846
|
+
- All section titles, table headers, table cells, lesson names, learning objectives, pedagogical narratives, and cognitive analyses MUST be written in natural, fluent, academic ${name}.
|
|
9847
|
+
- Technical identifiers, code keywords (e.g. setup(), loop(), pinMode()), standard protocols (I2C, SPI, UART, GPIO), and component model numbers (ESP32, Arduino Uno) remain in standard technical notation, but all surrounding explanations MUST be in ${name}.
|
|
9848
|
+
- DO NOT mix in paragraphs, tables, or titles written in any other language. Strict adherence is required.${exampleLine ? `
|
|
9849
|
+
${exampleLine}` : ""}`;
|
|
9850
|
+
}
|
|
9851
|
+
function matchesArtifactType(candidate, target) {
|
|
9852
|
+
const c = candidate.trim().toUpperCase();
|
|
9853
|
+
const t = target.trim().toUpperCase();
|
|
9854
|
+
if (c === t) return true;
|
|
9855
|
+
if (c.startsWith("LESSON") && t.startsWith("LESSON")) return true;
|
|
9856
|
+
if ((c === "CODE" || c === "CODE_LAB") && (t === "CODE" || t === "CODE_LAB")) return true;
|
|
9857
|
+
if ((c === "EXPOSITION" || c === "KNOWLEDGE_EXPOSITION") && (t === "EXPOSITION" || t === "KNOWLEDGE_EXPOSITION")) return true;
|
|
9858
|
+
if ((c === "WKS" || c === "WORKSHEET") && (t === "WKS" || t === "WORKSHEET")) return true;
|
|
9859
|
+
if ((c === "EXT" || c === "EXTENSION") && (t === "EXT" || t === "EXTENSION")) return true;
|
|
9860
|
+
return false;
|
|
9861
|
+
}
|
|
9862
|
+
var DEFAULT_VIETNAMESE_SECTION_HEADINGS = {
|
|
9863
|
+
LEARNER_PROFILE: {
|
|
9864
|
+
"Foundational Info": "Th\xF4ng tin N\u1EC1n t\u1EA3ng",
|
|
9865
|
+
"Entry Level": "Tr\xECnh \u0111\u1ED9 \u0110\u1EA7u v\xE0o",
|
|
9866
|
+
"Learning Context": "B\u1ED1i c\u1EA3nh H\u1ECDc t\u1EADp",
|
|
9867
|
+
"Client Objectives": "M\u1EE5c ti\xEAu Kh\xE1ch h\xE0ng & Chu\u1EA9n \u0111\u1EA7u ra"
|
|
9868
|
+
},
|
|
9869
|
+
PROJECT_BRIEF: {
|
|
9870
|
+
"Project Overview": "T\u1ED5ng quan D\u1EF1 \xE1n",
|
|
9871
|
+
"Audience & Duration": "\u0110\u1ED1i t\u01B0\u1EE3ng & Th\u1EDDi l\u01B0\u1EE3ng",
|
|
9872
|
+
"Learning Roadmap": "L\u1ED9 tr\xECnh H\u1ECDc t\u1EADp & C\u1ED9t m\u1ED1c",
|
|
9873
|
+
"Artifact Scope": "Ph\u1EA1m vi S\u1EA3n ph\u1EA9m H\u1ECDc t\u1EADp"
|
|
9874
|
+
},
|
|
9875
|
+
CURRICULUM_FRAMEWORK: {
|
|
9876
|
+
"Course Overview": "T\u1ED5ng quan Kh\xF3a h\u1ECDc",
|
|
9877
|
+
"Global Learning Objectives": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp To\xE0n di\u1EC7n",
|
|
9878
|
+
"Structural Hierarchy (Unit & Module)": "C\u1EA5u tr\xFAc Kh\xF3a h\u1ECDc (Unit & Module)",
|
|
9879
|
+
"Scope & Sequence (Detailed Roadmap)": "Ph\u1EA1m vi & Tr\xECnh t\u1EF1 Chi ti\u1EBFt"
|
|
9880
|
+
},
|
|
9881
|
+
CONTENT_STYLE_GUIDE: {
|
|
9882
|
+
"Voice & Tone": "Gi\u1ECDng v\u0103n & Phong c\xE1ch",
|
|
9883
|
+
"Standard Terminology (Glossary)": "Thu\u1EADt ng\u1EEF Chu\u1EA9n (B\u1EA3ng thu\u1EADt ng\u1EEF)",
|
|
9884
|
+
"Examples & Context Rules": "Quy t\u1EAFc V\xED d\u1EE5 & Ng\u1EEF c\u1EA3nh",
|
|
9885
|
+
"Lesson Content Standards": "Ti\xEAu chu\u1EA9n N\u1ED9i dung B\xE0i h\u1ECDc"
|
|
9886
|
+
},
|
|
9887
|
+
SECTION_LANGUAGE_CONTRACT: {
|
|
9888
|
+
"Metadata & Scope": "Th\xF4ng tin & Ph\u1EA1m vi H\u1EE3p \u0111\u1ED3ng",
|
|
9889
|
+
"Section Translation Matrix": "Ma tr\u1EADn Ti\xEAu \u0111\u1EC1 \u0110a ng\xF4n ng\u1EEF",
|
|
9890
|
+
"Validation Rules": "Quy t\u1EAFc X\xE1c th\u1EF1c & Kh\xF3a Chu\u1EA9n"
|
|
9891
|
+
},
|
|
9892
|
+
KNOWLEDGE_EXPOSITION: {
|
|
9893
|
+
"Session Scope": "Ph\u1EA1m vi Bu\u1ED5i h\u1ECDc",
|
|
9894
|
+
"Key Terms": "Thu\u1EADt ng\u1EEF Then ch\u1ED1t",
|
|
9895
|
+
"Concept Narratives": "Di\u1EC5n gi\u1EA3i Kh\xE1i ni\u1EC7m",
|
|
9896
|
+
"Worked Micro-Examples": "V\xED d\u1EE5 M\u1EABu Chi ti\u1EBFt",
|
|
9897
|
+
"Common Mistakes": "L\u1ED7i Th\u01B0\u1EDDng g\u1EB7p & Kh\u1EAFc ph\u1EE5c",
|
|
9898
|
+
"Self-Check Questions": "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra"
|
|
9899
|
+
},
|
|
9900
|
+
LESSON: {
|
|
9901
|
+
"A. Lesson Design Plan": "A. K\u1EBF ho\u1EA1ch Thi\u1EBFt k\u1EBF B\xE0i h\u1ECDc",
|
|
9902
|
+
"Learning Objectives & Evidence": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp & B\u1EB1ng ch\u1EE9ng N\u0103ng l\u1EF1c",
|
|
9903
|
+
"Activity Sequence": "Chu\u1ED7i Ho\u1EA1t \u0111\u1ED9ng D\u1EA1y & H\u1ECDc",
|
|
9904
|
+
"Resource Map": "B\u1EA3n \u0111\u1ED3 T\xE0i nguy\xEAn & H\u1ECDc li\u1EC7u",
|
|
9905
|
+
"Assessment Map": "B\u1EA3n \u0111\u1ED3 \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c",
|
|
9906
|
+
"Artifact Contract": "H\u1EE3p \u0111\u1ED3ng S\u1EA3n ph\u1EA9m \u0110\u1EA7u ra",
|
|
9907
|
+
"B. Lesson Flow": "B. Ti\u1EBFn tr\xECnh Gi\u1EA3ng d\u1EA1y Chi ti\u1EBFt"
|
|
9908
|
+
},
|
|
9909
|
+
ACT: {
|
|
9910
|
+
"Computational Thinking Focus": "Tr\u1ECDng t\xE2m T\u01B0 duy M\xE1y t\xEDnh",
|
|
9911
|
+
"Materials & Setup": "V\u1EADt li\u1EC7u & Chu\u1EA9n b\u1ECB Thi\u1EBFt b\u1ECB",
|
|
9912
|
+
"Constraints & Safety": "R\xE0ng bu\u1ED9c & An to\xE0n Ph\xF2ng th\u1EF1c h\xE0nh",
|
|
9913
|
+
"Active Learning Workflow": "Quy tr\xECnh Ho\u1EA1t \u0111\u1ED9ng Tr\u1EA3i nghi\u1EC7m",
|
|
9914
|
+
"3-Tier Differentiation": "Ph\xE2n h\xF3a H\u1ECDc t\u1EADp 3 T\u1EA7ng",
|
|
9915
|
+
"Reflection": "T\u1ED5ng k\u1EBFt & \u0110\xFAc k\u1EBFt Tr\u1EA3i nghi\u1EC7m"
|
|
9916
|
+
},
|
|
9917
|
+
CODE: {
|
|
9918
|
+
"Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
|
|
9919
|
+
"Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
|
|
9920
|
+
"Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
|
|
9921
|
+
"Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
|
|
9922
|
+
"Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
|
|
9923
|
+
"Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
|
|
9924
|
+
},
|
|
9925
|
+
CODE_LAB: {
|
|
9926
|
+
"Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
|
|
9927
|
+
"Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
|
|
9928
|
+
"Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
|
|
9929
|
+
"Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
|
|
9930
|
+
"Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
|
|
9931
|
+
"Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
|
|
9932
|
+
},
|
|
9933
|
+
QUIZ: {
|
|
9934
|
+
"Assessment Objectives": "M\u1EE5c ti\xEAu \u0110\xE1nh gi\xE1",
|
|
9935
|
+
"Multiple-Choice Question Bank": "Ng\xE2n h\xE0ng C\xE2u h\u1ECFi Tr\u1EAFc nghi\u1EC7m",
|
|
9936
|
+
"Code Analysis / Debugging Question": "C\xE2u h\u1ECFi Ph\xE2n t\xEDch M\xE3 ngu\u1ED3n & S\u1EEDa l\u1ED7i",
|
|
9937
|
+
"Competency Rubric": "Thang \u0111o \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c (Rubric)"
|
|
9938
|
+
},
|
|
9939
|
+
GUIDE: {
|
|
9940
|
+
"Objectives & Preparation": "M\u1EE5c ti\xEAu & Chu\u1EA9n b\u1ECB Gi\u1EA3ng d\u1EA1y",
|
|
9941
|
+
"Preparation Checklist & Workstation Setup": "Danh m\u1EE5c Ki\u1EC3m tra Chu\u1EA9n b\u1ECB & Tr\u1EA1m Th\u1EF1c h\xE0nh",
|
|
9942
|
+
"Facilitation Script & Timeline": "K\u1ECBch b\u1EA3n \u0110i\u1EC1u ph\u1ED1i & Khung Th\u1EDDi gian",
|
|
9943
|
+
"Common Misconceptions & Diagnostic Remediation Matrix": "Quan ni\u1EC7m Sai l\u1EA7m Th\u01B0\u1EDDng g\u1EB7p & Ma tr\u1EADn Kh\u1EAFc ph\u1EE5c",
|
|
9944
|
+
"Differentiated Support Strategies": "Chi\u1EBFn l\u01B0\u1EE3c H\u1ED7 tr\u1EE3 Ph\xE2n h\xF3a"
|
|
9945
|
+
},
|
|
9946
|
+
HANDOUT: {
|
|
9947
|
+
"Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
|
|
9948
|
+
"Core Syntax & Mechanism Cheat Sheet": "B\u1EA3ng Tra c\u1EE9u C\xFA ph\xE1p & C\u01A1 ch\u1EBF Tr\u1ECDng t\xE2m",
|
|
9949
|
+
"Visual Mental Model / Architecture Diagram": "M\xF4 h\xECnh T\u01B0 duy Tr\u1EF1c quan / S\u01A1 \u0111\u1ED3 Ki\u1EBFn tr\xFAc",
|
|
9950
|
+
"Step-by-Step Practical Quick-Start Guide": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh T\u1EEBng b\u01B0\u1EDBc",
|
|
9951
|
+
"Self-Check Diagnostic Checklist": "B\u1EA3ng Ki\u1EC3m tra T\u1EF1 ch\u1EA9n \u0111o\xE1n"
|
|
9952
|
+
},
|
|
9953
|
+
WKS: {
|
|
9954
|
+
"Part 1: Knowledge Check": "Ph\u1EA7n 1: Ki\u1EC3m tra Ki\u1EBFn th\u1EE9c",
|
|
9955
|
+
"Part 2: Concept Tracing & Diagram Fill-in": "Ph\u1EA7n 2: L\u1EA7n v\u1EBFt Kh\xE1i ni\u1EC7m & \u0110i\u1EC1n S\u01A1 \u0111\u1ED3",
|
|
9956
|
+
"Part 3: Code Analysis & Bug Hunting Challenge": "Ph\u1EA7n 3: Ph\xE2n t\xEDch M\xE3 & Th\u1EED th\xE1ch S\u0103n l\u1ED7i",
|
|
9957
|
+
"Part 4: Synthesis & Problem-Solving Application": "Ph\u1EA7n 4: T\u1ED5ng h\u1EE3p & \u1EE8ng d\u1EE5ng Gi\u1EA3i quy\u1EBFt V\u1EA5n \u0111\u1EC1",
|
|
9958
|
+
"Part 5: Self-Reflection & Learning Log": "Ph\u1EA7n 5: T\u1EF1 suy ng\u1EABm & Nh\u1EADt k\xFD H\u1ECDc t\u1EADp"
|
|
9959
|
+
},
|
|
9960
|
+
EXT: {
|
|
9961
|
+
"For: Advanced Students / Extra Time": "D\xE0nh cho: H\u1ECDc sinh N\xE2ng cao / Ho\xE0n th\xE0nh S\u1EDBm",
|
|
9962
|
+
"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",
|
|
9963
|
+
"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",
|
|
9964
|
+
"Challenge 3: Extension Milestones": "Th\u1EED th\xE1ch 3: C\xE1c M\u1ED1c Nhi\u1EC7m v\u1EE5 N\xE2ng cao",
|
|
9965
|
+
"Metacognitive Deep Dive & Engineering Trade-offs": "Suy ng\u1EABm Si\xEAu nh\u1EADn th\u1EE9c & \u0110\xE1nh \u0111\u1ED5i K\u1EF9 thu\u1EADt"
|
|
9966
|
+
},
|
|
9967
|
+
SLIDE: {
|
|
9968
|
+
"Title & Agenda": "Ti\xEAu \u0111\u1EC1 & M\u1EE5c l\u1EE5c",
|
|
9969
|
+
"Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
|
|
9970
|
+
"Guided Demonstration": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh & Th\u1ECB ph\u1EA1m",
|
|
9971
|
+
"Hands-on Mission": "Nhi\u1EC7m v\u1EE5 Th\u1EF1c h\xE0nh Tr\u1EA3i nghi\u1EC7m",
|
|
9972
|
+
"Summary & Next Steps": "T\u1ED5ng k\u1EBFt & \u0110\u1ECBnh h\u01B0\u1EDBng Ti\u1EBFp theo"
|
|
9973
|
+
}
|
|
9974
|
+
};
|
|
9975
|
+
function extractSectionHeadingsFromSLC(slcInput, artifactType, targetLanguage = "vi") {
|
|
9976
|
+
const upperType = artifactType.trim().toUpperCase();
|
|
9977
|
+
const getFallback = () => {
|
|
9978
|
+
if (resolveTargetLanguageCode(targetLanguage) === "vi") {
|
|
9979
|
+
for (const [key, mapping] of Object.entries(DEFAULT_VIETNAMESE_SECTION_HEADINGS)) {
|
|
9980
|
+
if (matchesArtifactType(key, upperType)) {
|
|
9981
|
+
return mapping;
|
|
9982
|
+
}
|
|
9983
|
+
}
|
|
9984
|
+
}
|
|
9985
|
+
return {};
|
|
9986
|
+
};
|
|
9987
|
+
if (!slcInput) return getFallback();
|
|
9988
|
+
if (typeof slcInput === "object") {
|
|
9989
|
+
if (slcInput[upperType] && Object.keys(slcInput[upperType]).length > 0) return slcInput[upperType];
|
|
9990
|
+
for (const [key, mapping] of Object.entries(slcInput)) {
|
|
9991
|
+
if (matchesArtifactType(key, upperType) && Object.keys(mapping).length > 0) {
|
|
9992
|
+
return mapping;
|
|
9993
|
+
}
|
|
9994
|
+
}
|
|
9995
|
+
return getFallback();
|
|
9996
|
+
}
|
|
9997
|
+
const slcMarkdown = slcInput;
|
|
9998
|
+
const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
9999
|
+
for (const block of blocks) {
|
|
10000
|
+
const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
10001
|
+
if (!headerMatch) continue;
|
|
10002
|
+
const blockType = headerMatch[1].trim().toUpperCase();
|
|
10003
|
+
if (matchesArtifactType(blockType, upperType)) {
|
|
10004
|
+
const mapping = {};
|
|
10005
|
+
const lines = block.split("\n");
|
|
10006
|
+
for (const line of lines) {
|
|
10007
|
+
const trimmed = line.trim();
|
|
10008
|
+
if (trimmed.startsWith("|") && !trimmed.includes("---")) {
|
|
10009
|
+
const cells = trimmed.split("|").map((c) => c.trim()).filter((_, idx, arr) => idx > 0 && idx < arr.length - 1);
|
|
10010
|
+
if (cells.length >= 2 && !cells[0].toLowerCase().includes("canonical") && !cells[1].toLowerCase().includes("localized")) {
|
|
10011
|
+
mapping[cells[0]] = cells[1];
|
|
10012
|
+
}
|
|
10013
|
+
} else {
|
|
10014
|
+
const bullet = line.match(/^[-*]\s+([^:]+):\s+(.+)$/);
|
|
10015
|
+
if (bullet) {
|
|
10016
|
+
mapping[bullet[1].trim()] = bullet[2].trim();
|
|
10017
|
+
}
|
|
10018
|
+
}
|
|
10019
|
+
}
|
|
10020
|
+
if (Object.keys(mapping).length > 0) return mapping;
|
|
10021
|
+
}
|
|
10022
|
+
}
|
|
10023
|
+
return getFallback();
|
|
10024
|
+
}
|
|
10025
|
+
function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi") {
|
|
10026
|
+
const headings = extractSectionHeadingsFromSLC(slcMarkdown, artifactType, targetLanguage);
|
|
10027
|
+
if (Object.keys(headings).length === 0) {
|
|
10028
|
+
return "";
|
|
10029
|
+
}
|
|
10030
|
+
const lines = Object.entries(headings).map(
|
|
10031
|
+
([canonical, localized]) => ` - "${canonical}" -> Use Display Heading: "${localized}"`
|
|
10032
|
+
);
|
|
10033
|
+
return `MANDATORY SECTION HEADINGS FROM SECTION_LANGUAGE_CONTRACT:
|
|
10034
|
+
- The YAML frontmatter \`template_required_sections\` MUST preserve the exact English canonical keys.
|
|
10035
|
+
- In the markdown body, section headers MUST use the EXACT Localized Display Labels below (do NOT translate or paraphrase):
|
|
10036
|
+
${lines.join("\n")}
|
|
10037
|
+
- For example: if canonical section is "Computational Thinking Focus", your heading must be "## [REQUIRED] ${headings["Computational Thinking Focus"] || "Computational Thinking Focus"}".`;
|
|
10038
|
+
}
|
|
10039
|
+
|
|
9822
10040
|
// src/services/contextBuilder.ts
|
|
9823
10041
|
var DEFAULT_LESSON_PRIORITIES = [
|
|
9824
10042
|
"A. Lesson Design Plan",
|
|
@@ -10108,7 +10326,8 @@ var DEPTH_RULES = {
|
|
|
10108
10326
|
cio: "Write WHAT + WHY + HOW: include the mechanism, step by step, still technology-independent.",
|
|
10109
10327
|
sio: "Write WHAT + WHY + HOW + SPECIFIC: include concrete implementations and how the real project keywords are used."
|
|
10110
10328
|
};
|
|
10111
|
-
function buildSystemPrompt() {
|
|
10329
|
+
function buildSystemPrompt(targetLanguage = "vi") {
|
|
10330
|
+
const langDirective = buildLanguageDirective(targetLanguage);
|
|
10112
10331
|
return [
|
|
10113
10332
|
"You write KNOWLEDGE_EXPOSITION: self-study reading material for a student in a teacherless program.",
|
|
10114
10333
|
"Rules:",
|
|
@@ -10117,12 +10336,22 @@ function buildSystemPrompt() {
|
|
|
10117
10336
|
"3. Respect each concept depth target (ULO/CIO/SIO) \u2014 do not overshoot.",
|
|
10118
10337
|
"4. Student-facing only: no teacher instructions, no classroom management text.",
|
|
10119
10338
|
"5. Output the full markdown document following the provided section skeleton exactly (headers and placeholders preserved).",
|
|
10120
|
-
|
|
10339
|
+
langDirective
|
|
10121
10340
|
].join("\n");
|
|
10122
10341
|
}
|
|
10123
|
-
function buildUserPrompt(session, plan, glossary) {
|
|
10342
|
+
function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMarkdown) {
|
|
10124
10343
|
const depthLines = session.depth_assignments.map((d) => "- " + d.node_id + " [" + d.depth.toUpperCase() + "]: " + DEPTH_RULES[d.depth]).join("\n");
|
|
10125
10344
|
const termLines = glossary.map((g) => "- " + g.term + (g.definition ? " \u2014 " + g.definition : "") + (g.example ? " (example: " + g.example + ")" : "")).join("\n");
|
|
10345
|
+
const langCode = resolveTargetLanguageCode(targetLanguage);
|
|
10346
|
+
const headings = extractSectionHeadingsFromSLC(slcMarkdown, "KNOWLEDGE_EXPOSITION");
|
|
10347
|
+
const hScope = headings["Session Scope"] || (langCode === "vi" ? "Ph\u1EA1m vi Bu\u1ED5i h\u1ECDc" : "Session Scope");
|
|
10348
|
+
const hTerms = headings["Key Terms"] || (langCode === "vi" ? "Thu\u1EADt ng\u1EEF Then ch\u1ED1t" : "Key Terms");
|
|
10349
|
+
const hNarratives = headings["Concept Narratives"] || (langCode === "vi" ? "Di\u1EC5n gi\u1EA3i Kh\xE1i ni\u1EC7m" : "Concept Narratives");
|
|
10350
|
+
const hExamples = headings["Worked Micro-Examples"] || (langCode === "vi" ? "V\xED d\u1EE5 M\u1EABu Chi ti\u1EBFt" : "Worked Micro-Examples");
|
|
10351
|
+
const hMistakes = headings["Common Mistakes"] || (langCode === "vi" ? "L\u1ED7i Th\u01B0\u1EDDng g\u1EB7p & Kh\u1EAFc ph\u1EE5c" : "Common Mistakes");
|
|
10352
|
+
const hQuestions = headings["Self-Check Questions"] || (langCode === "vi" ? "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra" : "Self-Check Questions");
|
|
10353
|
+
const skeleton = `## ${hScope} / ## ${hTerms} / ## ${hNarratives} / ## ${hExamples} / ## ${hMistakes} / ## ${hQuestions}`;
|
|
10354
|
+
const headingDirective = buildHeadingDirective("KNOWLEDGE_EXPOSITION", slcMarkdown, targetLanguage);
|
|
10126
10355
|
return [
|
|
10127
10356
|
"Session: " + session.id + " \u2014 " + session.title,
|
|
10128
10357
|
"Objective: " + session.prose_objective,
|
|
@@ -10137,9 +10366,10 @@ function buildUserPrompt(session, plan, glossary) {
|
|
|
10137
10366
|
termLines || "(none provided \u2014 write definitions and mark them for glossary sync)",
|
|
10138
10367
|
"",
|
|
10139
10368
|
"Section skeleton to fill (replace ONLY the {{placeholders}}):",
|
|
10140
|
-
|
|
10369
|
+
skeleton,
|
|
10370
|
+
headingDirective ? "\n" + headingDirective : "",
|
|
10141
10371
|
"Plan hash: " + plan.plan_hash
|
|
10142
|
-
].join("\n");
|
|
10372
|
+
].filter(Boolean).join("\n");
|
|
10143
10373
|
}
|
|
10144
10374
|
async function ensureKnowledgeExposition(options) {
|
|
10145
10375
|
const { projectId, lessonCode, plan, glossary, llmFn, storage } = options;
|
|
@@ -10155,11 +10385,18 @@ async function ensureKnowledgeExposition(options) {
|
|
|
10155
10385
|
if (plan.approval.plan_hash !== plan.plan_hash) {
|
|
10156
10386
|
throw new ExpositionApprovalError("Approval hash " + plan.approval.plan_hash + " does not match current plan hash " + plan.plan_hash + " \u2014 re-approve after plan changes");
|
|
10157
10387
|
}
|
|
10158
|
-
const
|
|
10388
|
+
const targetLanguage = options.targetLanguage || plan.translation?.target_language || "vi";
|
|
10389
|
+
const content = (await llmFn(
|
|
10390
|
+
buildSystemPrompt(targetLanguage),
|
|
10391
|
+
buildUserPrompt(session, plan, glossary, targetLanguage, options.slcMarkdown)
|
|
10392
|
+
)).trim();
|
|
10159
10393
|
if (content.length < 200) {
|
|
10160
10394
|
throw new Error("EXPOSITION too short for " + lessonCode + " (" + content.length + " chars) \u2014 refusing to save");
|
|
10161
10395
|
}
|
|
10162
|
-
|
|
10396
|
+
const hasKeyTerms = content.includes("Key Terms") || content.includes("Thu\u1EADt ng\u1EEF");
|
|
10397
|
+
const hasNarratives = content.includes("Concept Narratives") || content.includes("Kh\xE1i ni\u1EC7m") || content.includes("Di\u1EC5n gi\u1EA3i");
|
|
10398
|
+
const hasSelfCheck = content.includes("Self-Check") || content.includes("T\u1EF1 ki\u1EC3m tra") || content.includes("C\xE2u h\u1ECFi");
|
|
10399
|
+
if (!hasKeyTerms || !hasNarratives || !hasSelfCheck) {
|
|
10163
10400
|
throw new Error("EXPOSITION missing required sections for " + lessonCode + " \u2014 refusing to save");
|
|
10164
10401
|
}
|
|
10165
10402
|
const gateMode = gateModeFor(options.gates ?? {}, "KNOWLEDGE_EXPOSITION");
|
|
@@ -10221,16 +10458,20 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
10221
10458
|
const scopedTerms = new Set(plan.glossary_scope.find((g) => g.session_id === lessonCode)?.terms ?? []);
|
|
10222
10459
|
glossary = glossary.filter((g) => scopedTerms.has(g.term));
|
|
10223
10460
|
const { runCurriculumAIInference: runCurriculumAIInference2 } = await Promise.resolve().then(() => (init_streamRunner(), streamRunner_exports));
|
|
10461
|
+
const targetLang = options.targetLanguage || plan.translation?.target_language || "vi";
|
|
10224
10462
|
const result = await ensureKnowledgeExposition({
|
|
10225
10463
|
projectId,
|
|
10226
10464
|
lessonCode,
|
|
10227
10465
|
plan,
|
|
10228
10466
|
glossary,
|
|
10467
|
+
targetLanguage: targetLang,
|
|
10468
|
+
slcMarkdown: options.slcMarkdown,
|
|
10229
10469
|
llmFn: async (systemPrompt, userPrompt) => {
|
|
10470
|
+
const runnerOpts = options.customInference ? { customInference: options.customInference } : {};
|
|
10230
10471
|
const out = await runCurriculumAIInference2(
|
|
10231
10472
|
[{ role: "user", content: userPrompt + "\n\n[SYSTEM RULES]:\n" + systemPrompt }],
|
|
10232
|
-
|
|
10233
|
-
|
|
10473
|
+
`You are generating KNOWLEDGE_EXPOSITION - canonical self-study knowledge for one session in ${targetLang === "vi" ? "VIETNAMESE" : targetLang}. Output the complete markdown document only.`,
|
|
10474
|
+
runnerOpts
|
|
10234
10475
|
);
|
|
10235
10476
|
return out;
|
|
10236
10477
|
},
|
|
@@ -23978,90 +24219,6 @@ function extractStandardRefs(text) {
|
|
|
23978
24219
|
return Array.from(new Set(matches));
|
|
23979
24220
|
}
|
|
23980
24221
|
|
|
23981
|
-
// src/services/languageDirective.ts
|
|
23982
|
-
function resolveTargetLanguageCode(language) {
|
|
23983
|
-
const raw = String(language || "vi").trim().toLowerCase();
|
|
23984
|
-
if (raw.startsWith("vi")) return "vi";
|
|
23985
|
-
if (raw.startsWith("en")) return "en";
|
|
23986
|
-
return raw || "vi";
|
|
23987
|
-
}
|
|
23988
|
-
function targetLanguageDisplayName(code) {
|
|
23989
|
-
const map = {
|
|
23990
|
-
vi: "Vietnamese (Ti\u1EBFng Vi\u1EC7t)",
|
|
23991
|
-
en: "English (US)"
|
|
23992
|
-
};
|
|
23993
|
-
return map[code] || code;
|
|
23994
|
-
}
|
|
23995
|
-
function buildLanguageDirective(targetLanguage) {
|
|
23996
|
-
const code = resolveTargetLanguageCode(targetLanguage);
|
|
23997
|
-
const name = targetLanguageDisplayName(code);
|
|
23998
|
-
const perLanguageExamples = {
|
|
23999
|
-
vi: `- V\xED d\u1EE5 ti\xEAu \u0111\u1EC1 b\xE0i h\u1ECDc \u0111\xFAng chu\u1EA9n: "B\xE0i 1: Kh\xE1m ph\xE1 m\u1EA1ch \u0111i\u1EC7n c\u01A1 b\u1EA3n", "B\xE0i 2: \u0110i\u1EC1u khi\u1EC3n \u0111\xE8n LED nh\u1EA5p nh\xE1y" \u2014 KH\xD4NG d\xF9ng ti\xEAu \u0111\u1EC1 ti\u1EBFng Anh.`,
|
|
24000
|
-
en: `- Example compliant lesson title: "Lesson 1: Exploring Basic Circuits" \u2014 natural, idiomatic English throughout.`
|
|
24001
|
-
};
|
|
24002
|
-
const exampleLine = perLanguageExamples[code] || "";
|
|
24003
|
-
return `MANDATORY LANGUAGE DIRECTIVE (TARGET OUTPUT LANGUAGE: ${name}):
|
|
24004
|
-
- The TARGET OUTPUT LANGUAGE for this course is ${name}. You MUST author the ENTIRE document in ${name}.
|
|
24005
|
-
- All section titles, table headers, table cells, lesson names, learning objectives, pedagogical narratives, and cognitive analyses MUST be written in natural, fluent, academic ${name}.
|
|
24006
|
-
- Technical identifiers, code keywords (e.g. setup(), loop(), pinMode()), standard protocols (I2C, SPI, UART, GPIO), and component model numbers (ESP32, Arduino Uno) remain in standard technical notation, but all surrounding explanations MUST be in ${name}.
|
|
24007
|
-
- DO NOT mix in paragraphs, tables, or titles written in any other language. Strict adherence is required.${exampleLine ? `
|
|
24008
|
-
${exampleLine}` : ""}`;
|
|
24009
|
-
}
|
|
24010
|
-
function extractSectionHeadingsFromSLC(slcInput, artifactType) {
|
|
24011
|
-
if (!slcInput) return {};
|
|
24012
|
-
const upperType = artifactType.trim().toUpperCase();
|
|
24013
|
-
if (typeof slcInput === "object") {
|
|
24014
|
-
if (slcInput[upperType]) return slcInput[upperType];
|
|
24015
|
-
for (const [key, mapping] of Object.entries(slcInput)) {
|
|
24016
|
-
if (key.toUpperCase() === upperType || upperType.startsWith("LESSON") && key.toUpperCase().startsWith("LESSON")) {
|
|
24017
|
-
return mapping;
|
|
24018
|
-
}
|
|
24019
|
-
}
|
|
24020
|
-
return {};
|
|
24021
|
-
}
|
|
24022
|
-
const slcMarkdown = slcInput;
|
|
24023
|
-
const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
24024
|
-
for (const block of blocks) {
|
|
24025
|
-
const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
24026
|
-
if (!headerMatch) continue;
|
|
24027
|
-
const blockType = headerMatch[1].trim().toUpperCase();
|
|
24028
|
-
if (blockType === upperType || upperType.startsWith("LESSON") && blockType.startsWith("LESSON")) {
|
|
24029
|
-
const mapping = {};
|
|
24030
|
-
const lines = block.split("\n");
|
|
24031
|
-
for (const line of lines) {
|
|
24032
|
-
const trimmed = line.trim();
|
|
24033
|
-
if (trimmed.startsWith("|") && !trimmed.includes("---")) {
|
|
24034
|
-
const cells = trimmed.split("|").map((c) => c.trim()).filter((_, idx, arr) => idx > 0 && idx < arr.length - 1);
|
|
24035
|
-
if (cells.length >= 2 && !cells[0].toLowerCase().includes("canonical") && !cells[1].toLowerCase().includes("localized")) {
|
|
24036
|
-
mapping[cells[0]] = cells[1];
|
|
24037
|
-
}
|
|
24038
|
-
} else {
|
|
24039
|
-
const bullet = line.match(/^[-*]\s+([^:]+):\s+(.+)$/);
|
|
24040
|
-
if (bullet) {
|
|
24041
|
-
mapping[bullet[1].trim()] = bullet[2].trim();
|
|
24042
|
-
}
|
|
24043
|
-
}
|
|
24044
|
-
}
|
|
24045
|
-
if (Object.keys(mapping).length > 0) return mapping;
|
|
24046
|
-
}
|
|
24047
|
-
}
|
|
24048
|
-
return {};
|
|
24049
|
-
}
|
|
24050
|
-
function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi") {
|
|
24051
|
-
const headings = extractSectionHeadingsFromSLC(slcMarkdown, artifactType);
|
|
24052
|
-
if (Object.keys(headings).length === 0) {
|
|
24053
|
-
return "";
|
|
24054
|
-
}
|
|
24055
|
-
const lines = Object.entries(headings).map(
|
|
24056
|
-
([canonical, localized]) => ` - "${canonical}" -> Use Display Heading: "${localized}"`
|
|
24057
|
-
);
|
|
24058
|
-
return `MANDATORY SECTION HEADINGS FROM SECTION_LANGUAGE_CONTRACT:
|
|
24059
|
-
- The YAML frontmatter \`template_required_sections\` MUST preserve the exact English canonical keys.
|
|
24060
|
-
- In the markdown body, section headers MUST use the EXACT Localized Display Labels below (do NOT translate or paraphrase):
|
|
24061
|
-
${lines.join("\n")}
|
|
24062
|
-
- For example: if canonical section is "Computational Thinking Focus", your heading must be "## [REQUIRED] ${headings["Computational Thinking Focus"] || "Computational Thinking Focus"}".`;
|
|
24063
|
-
}
|
|
24064
|
-
|
|
24065
24222
|
// src/services/lessonProductionService.ts
|
|
24066
24223
|
var __filename2 = typeof (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) === "string" && typeof url.fileURLToPath === "function" ? 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))) : "";
|
|
24067
24224
|
var _resolvedDir = __filename2 ? path3__default.default.dirname(__filename2) : typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
@@ -24475,7 +24632,10 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
24475
24632
|
try {
|
|
24476
24633
|
const exposition = await ensureExpositionForLesson(storage, projectId, lessonCode, {
|
|
24477
24634
|
gates: resolveGateSettings(options.gateSettings),
|
|
24478
|
-
force: options.force
|
|
24635
|
+
force: options.force,
|
|
24636
|
+
targetLanguage: targetLang,
|
|
24637
|
+
slcMarkdown,
|
|
24638
|
+
customInference: options.customInference
|
|
24479
24639
|
});
|
|
24480
24640
|
if (exposition) {
|
|
24481
24641
|
const expoExcerpt = buildExpositionExcerpt(exposition.rawContent || exposition.context, {
|
|
@@ -25525,6 +25685,22 @@ ${buildHeadingDirective("CODE", slcMarkdown, targetLang)}`;
|
|
|
25525
25685
|
if (artifactScope.includes("EXT") && (!await storage.readArtifact(projectId, extRelPath) || force)) {
|
|
25526
25686
|
onProgress?.("@activity", `Authoring Advanced Extension Challenge: \`EXT_${lessonCode}.md\`...`, { artifactType: "EXT" });
|
|
25527
25687
|
const extDateStr = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
25688
|
+
const isVi = targetLang === "vi";
|
|
25689
|
+
const extHeadings = isVi ? {
|
|
25690
|
+
main: "# NHI\u1EC6M V\u1EE4 N\xC2NG CAO: [TI\xCAU \u0110\u1EC0 B\xC0I H\u1ECCC]",
|
|
25691
|
+
sub: "## D\xE0nh cho: H\u1ECDc sinh N\xE2ng cao / Ho\xE0n th\xE0nh S\u1EDBm",
|
|
25692
|
+
c1: "### Th\u1EED th\xE1ch 1: [T\xEAn th\u1EED th\xE1ch] (\u0110\u1ED9 kh\xF3: \u2B50\u2B50\u2B50) \u2014 B\u1ED1i c\u1EA3nh Nhi\u1EC7m v\u1EE5 Th\u1EF1c t\u1EBF & K\u1ECBch b\u1EA3n \u1EE8ng d\u1EE5ng",
|
|
25693
|
+
c2: "### Th\u1EED th\xE1ch 2: [T\xEAn th\u1EED th\xE1ch] (\u0110\u1ED9 kh\xF3: \u2B50\u2B50\u2B50\u2B50) \u2014 R\xE0ng bu\u1ED9c Ki\u1EBFn tr\xFAc N\xE2ng cao & Tr\u01B0\u1EDDng h\u1EE3p Bi\xEAn",
|
|
25694
|
+
c3: "### Th\u1EED th\xE1ch 3: [T\xEAn th\u1EED th\xE1ch] (\u0110\u1ED9 kh\xF3: \u2B50\u2B50\u2B50\u2B50\u2B50) \u2014 C\xE1c M\u1ED1c Nhi\u1EC7m v\u1EE5 N\xE2ng cao (C\u1EA5p 1: Kh\u1EDFi \u0111\u1ED9ng \u2192 C\u1EA5p 2: N\xE2ng cao \u2192 C\u1EA5p 3: Chuy\xEAn gia)",
|
|
25695
|
+
meta: "## [REQUIRED] Suy ng\u1EABm Si\xEAu nh\u1EADn th\u1EE9c & \u0110\xE1nh \u0111\u1ED5i K\u1EF9 thu\u1EADt"
|
|
25696
|
+
} : {
|
|
25697
|
+
main: "# EXTENSION TASKS: [LESSON TITLE]",
|
|
25698
|
+
sub: "## For: Advanced Students / Extra Time",
|
|
25699
|
+
c1: "### Challenge 1: [Name] (Difficulty: \u2B50\u2B50\u2B50) \u2014 Mission Briefing & Real-World High-Stakes Scenario",
|
|
25700
|
+
c2: "### Challenge 2: [Name] (Difficulty: \u2B50\u2B50\u2B50\u2B50) \u2014 Advanced Architectural Constraints & Edge Cases",
|
|
25701
|
+
c3: "### Challenge 3: [Name] (Difficulty: \u2B50\u2B50\u2B50\u2B50\u2B50) \u2014 Extension Milestones (Level 1: Ninja \u2192 Level 2: Guru \u2192 Level 3: Master)",
|
|
25702
|
+
meta: "## [REQUIRED] Metacognitive Deep Dive & Engineering Trade-offs"
|
|
25703
|
+
};
|
|
25528
25704
|
const extPrompt = `You are @activity (Lead STEM Specialist & Differentiated Extension Designer).
|
|
25529
25705
|
Based on Master Lesson Plan \`LESSON_${lessonCode}.md\`, author the advanced extension challenge: \`EXT_${lessonCode}.md\`.
|
|
25530
25706
|
|
|
@@ -25540,16 +25716,21 @@ deliverable: "P3-T8"
|
|
|
25540
25716
|
version: "v1.0"
|
|
25541
25717
|
date: "${extDateStr}"
|
|
25542
25718
|
template_contract: "artifact-template-v1"
|
|
25719
|
+
template_required_sections:
|
|
25720
|
+
- "Challenge 1: Mission Briefing & Real-World High-Stakes Scenario"
|
|
25721
|
+
- "Challenge 2: Advanced Architectural Constraints & Edge Cases"
|
|
25722
|
+
- "Challenge 3: Extension Milestones"
|
|
25723
|
+
- "Metacognitive Deep Dive & Engineering Trade-offs"
|
|
25543
25724
|
---
|
|
25544
25725
|
|
|
25545
|
-
|
|
25546
|
-
|
|
25726
|
+
${extHeadings.main}
|
|
25727
|
+
${extHeadings.sub}
|
|
25547
25728
|
|
|
25548
25729
|
2. Mandatory sections (matching EXT_template.md):
|
|
25549
|
-
-
|
|
25550
|
-
-
|
|
25551
|
-
-
|
|
25552
|
-
-
|
|
25730
|
+
- ${extHeadings.c1}
|
|
25731
|
+
- ${extHeadings.c2}
|
|
25732
|
+
- ${extHeadings.c3}
|
|
25733
|
+
- ${extHeadings.meta}
|
|
25553
25734
|
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
25554
25735
|
|
|
25555
25736
|
${languageDirective}
|
|
@@ -30205,6 +30386,7 @@ exports.DEFAULT_KX_PRIORITIES = DEFAULT_KX_PRIORITIES;
|
|
|
30205
30386
|
exports.DEFAULT_LESSON_PRIORITIES = DEFAULT_LESSON_PRIORITIES;
|
|
30206
30387
|
exports.DEFAULT_STREAM_IDLE_MS = DEFAULT_STREAM_IDLE_MS;
|
|
30207
30388
|
exports.DEFAULT_STREAM_TOTAL_MS = DEFAULT_STREAM_TOTAL_MS;
|
|
30389
|
+
exports.DEFAULT_VIETNAMESE_SECTION_HEADINGS = DEFAULT_VIETNAMESE_SECTION_HEADINGS;
|
|
30208
30390
|
exports.DependencyEdgeSchema = DependencyEdgeSchema;
|
|
30209
30391
|
exports.DepthAssignmentSchema = DepthAssignmentSchema;
|
|
30210
30392
|
exports.DepthLevelSchema = DepthLevelSchema;
|