@thanh01.pmt/curriculum-kit 1.4.21 → 1.4.22
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 +78 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +78 -9
- package/dist/index.mjs.map +1 -1
- package/dist/workflow/index.cjs +15 -0
- package/dist/workflow/index.cjs.map +1 -1
- package/dist/workflow/index.mjs +15 -0
- package/dist/workflow/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -11519,6 +11519,21 @@ function normalizeHeading(str) {
|
|
|
11519
11519
|
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
11520
11520
|
}
|
|
11521
11521
|
function findCanonicalFuzzy(norm) {
|
|
11522
|
+
if (norm.includes("toolchain") || norm.includes("moi truong phat trien") || norm.includes("cong cu") || norm.includes("version") || norm.includes("phan mem") || norm.includes("development environment") || norm.includes("technical overview") || norm.includes("kien truc")) {
|
|
11523
|
+
return "Technical Overview & Architecture Blueprint";
|
|
11524
|
+
}
|
|
11525
|
+
if (norm.includes("pinout") || norm.includes("phan cung") || norm.includes("hardware") || norm.includes("wiring") || norm.includes("ket noi")) {
|
|
11526
|
+
return "Hardware Pinout & Wiring Configuration Matrix";
|
|
11527
|
+
}
|
|
11528
|
+
if (norm.includes("pedagog") || norm.includes("phuong phap") || norm.includes("day hoc") || norm.includes("su pham")) {
|
|
11529
|
+
return "Core Pedagogical Concept Anchor & Real-World Domain Bridge";
|
|
11530
|
+
}
|
|
11531
|
+
if (norm.includes("standard") || norm.includes("tieu chuan") || norm.includes("csta") || norm.includes("cs2023") || norm.includes("chuan academic")) {
|
|
11532
|
+
return "Standards Alignment";
|
|
11533
|
+
}
|
|
11534
|
+
if (norm.includes("roadmap") || norm.includes("lo trinh") || norm.includes("milestone") || norm.includes("giai doan")) {
|
|
11535
|
+
return void 0;
|
|
11536
|
+
}
|
|
11522
11537
|
if (norm.includes("symbol") || norm.includes("identifier ledger") || norm.includes("dinh danh")) {
|
|
11523
11538
|
return "Symbol & Identifier Ledger";
|
|
11524
11539
|
}
|
|
@@ -11655,7 +11670,7 @@ function buildSystemPrompt(targetLanguage = "vi", techStack, hardwarePlatform) {
|
|
|
11655
11670
|
langDirective
|
|
11656
11671
|
].join("\n");
|
|
11657
11672
|
}
|
|
11658
|
-
function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMarkdown) {
|
|
11673
|
+
function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMarkdown, refPack) {
|
|
11659
11674
|
const depthLines = session.depth_assignments.map((d) => "- " + d.node_id + " [" + d.depth.toUpperCase() + "]: " + DEPTH_RULES[d.depth]).join("\n");
|
|
11660
11675
|
const termLines = glossary.map((g) => "- " + g.term + (g.definition ? " \u2014 " + g.definition : "") + (g.example ? " (example: " + g.example + ")" : "")).join("\n");
|
|
11661
11676
|
const langCode = resolveTargetLanguageCode(targetLanguage);
|
|
@@ -11668,6 +11683,28 @@ function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMark
|
|
|
11668
11683
|
const hQuestions = headings["Self-Check Questions"] || (langCode === "vi" ? "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra" : "Self-Check Questions");
|
|
11669
11684
|
const skeleton = `## ${hScope} / ## ${hTerms} / ## ${hNarratives} / ## ${hExamples} / ## ${hMistakes} / ## ${hQuestions}`;
|
|
11670
11685
|
const headingDirective = buildHeadingDirective("KNOWLEDGE_EXPOSITION", slcMarkdown, targetLanguage);
|
|
11686
|
+
let refPackBlock = "";
|
|
11687
|
+
if (refPack && refPack.trim()) {
|
|
11688
|
+
const refExcerpt = buildSectionAwareExcerpt(refPack, {
|
|
11689
|
+
priorities: [
|
|
11690
|
+
"Technical Overview & Architecture Blueprint",
|
|
11691
|
+
"Hardware Pinout & Wiring Configuration Matrix",
|
|
11692
|
+
"Standards Alignment"
|
|
11693
|
+
],
|
|
11694
|
+
budget: 2500
|
|
11695
|
+
}).excerpt;
|
|
11696
|
+
if (refExcerpt) {
|
|
11697
|
+
refPackBlock = [
|
|
11698
|
+
"",
|
|
11699
|
+
"[GROUND TRUTH \u2014 BINDING, from REFERENCE_PACK.md]:",
|
|
11700
|
+
"Tool versions, APIs, and platform facts below are CANONICAL. Do NOT",
|
|
11701
|
+
"contradict them; do NOT substitute versions from memory. If a fact you",
|
|
11702
|
+
"need is not stated here, stay generic rather than inventing specifics.",
|
|
11703
|
+
"",
|
|
11704
|
+
refExcerpt
|
|
11705
|
+
].join("\n");
|
|
11706
|
+
}
|
|
11707
|
+
}
|
|
11671
11708
|
return [
|
|
11672
11709
|
"Session: " + session.id + " \u2014 " + session.title,
|
|
11673
11710
|
"Objective: " + session.prose_objective,
|
|
@@ -11680,6 +11717,7 @@ function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMark
|
|
|
11680
11717
|
"",
|
|
11681
11718
|
"Glossary terms (definitions are canonical):",
|
|
11682
11719
|
termLines || "(none provided \u2014 write definitions and mark them for glossary sync)",
|
|
11720
|
+
refPackBlock,
|
|
11683
11721
|
"",
|
|
11684
11722
|
"Section skeleton to fill (replace ONLY the {{placeholders}}):",
|
|
11685
11723
|
skeleton,
|
|
@@ -11688,7 +11726,7 @@ function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMark
|
|
|
11688
11726
|
].filter(Boolean).join("\n");
|
|
11689
11727
|
}
|
|
11690
11728
|
async function ensureKnowledgeExposition(options) {
|
|
11691
|
-
const { projectId, lessonCode, plan, glossary, llmFn, storage, techStack, hardwarePlatform } = options;
|
|
11729
|
+
const { projectId, lessonCode, plan, glossary, llmFn, storage, techStack, hardwarePlatform, refPack } = options;
|
|
11692
11730
|
const session = plan.sessions.find((s) => s.id === lessonCode);
|
|
11693
11731
|
if (!session) throw new Error("Session " + lessonCode + " not found in plan " + plan.plan_id);
|
|
11694
11732
|
const existing = await storage.readArtifact(projectId, EXPOSITION_REL(lessonCode));
|
|
@@ -11702,9 +11740,11 @@ async function ensureKnowledgeExposition(options) {
|
|
|
11702
11740
|
throw new ExpositionApprovalError("Approval hash " + plan.approval.plan_hash + " does not match current plan hash " + plan.plan_hash + " \u2014 re-approve after plan changes");
|
|
11703
11741
|
}
|
|
11704
11742
|
const targetLanguage = options.targetLanguage || plan.translation?.target_language || "vi";
|
|
11743
|
+
const originalSystemPrompt = buildSystemPrompt(targetLanguage, techStack, hardwarePlatform);
|
|
11744
|
+
const originalUserPrompt = buildUserPrompt(session, plan, glossary, targetLanguage, options.slcMarkdown, refPack);
|
|
11705
11745
|
const content = (await llmFn(
|
|
11706
|
-
|
|
11707
|
-
|
|
11746
|
+
originalSystemPrompt,
|
|
11747
|
+
originalUserPrompt
|
|
11708
11748
|
)).trim();
|
|
11709
11749
|
if (content.length < 200) {
|
|
11710
11750
|
throw new Error("EXPOSITION too short for " + lessonCode + " (" + content.length + " chars) \u2014 refusing to save");
|
|
@@ -11737,8 +11777,16 @@ async function ensureKnowledgeExposition(options) {
|
|
|
11737
11777
|
};
|
|
11738
11778
|
let verdict = await judgeOnce(finalContent);
|
|
11739
11779
|
if (verdict.verdict !== "APPROVED") {
|
|
11740
|
-
const repairPrompt =
|
|
11741
|
-
|
|
11780
|
+
const repairPrompt = [
|
|
11781
|
+
originalUserPrompt,
|
|
11782
|
+
"",
|
|
11783
|
+
"--- YOUR PREVIOUS DRAFT (REJECTED, fix ALL issues below) ---",
|
|
11784
|
+
finalContent,
|
|
11785
|
+
"",
|
|
11786
|
+
"--- JUDGE CRITIQUE (fix ALL issues, output the COMPLETE corrected document) ---",
|
|
11787
|
+
verdict.critique
|
|
11788
|
+
].join("\n");
|
|
11789
|
+
finalContent = (await llmFn(originalSystemPrompt, repairPrompt)).trim();
|
|
11742
11790
|
verdict = await judgeOnce(finalContent);
|
|
11743
11791
|
}
|
|
11744
11792
|
if (verdict.verdict !== "APPROVED") {
|
|
@@ -11779,12 +11827,27 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
11779
11827
|
try {
|
|
11780
11828
|
const lpRaw = await storage.readSotDocument(projectId, "LEARNER_PROFILE.md");
|
|
11781
11829
|
if (lpRaw) {
|
|
11782
|
-
const
|
|
11783
|
-
|
|
11830
|
+
const hwPatterns = [
|
|
11831
|
+
/(?:Student Equipment|Hardware|Platform|Thiết bị|Thiết bị học tập)\s*(?:\(|:|\*)*\s*([^\n\r]+?)(?:\s*\*\*|[.).]?\s*$)/i,
|
|
11832
|
+
/(?:máy|device|machine)\s+([^,.;\n]{4,60}(?:M\d|Intel|PC|computer|mini)[^,.;\n]{0,30})/i
|
|
11833
|
+
];
|
|
11834
|
+
for (const p of hwPatterns) {
|
|
11835
|
+
const m = lpRaw.match(p);
|
|
11836
|
+
if (m && !hw) {
|
|
11837
|
+
hw = m[1].trim();
|
|
11838
|
+
break;
|
|
11839
|
+
}
|
|
11840
|
+
}
|
|
11784
11841
|
}
|
|
11785
11842
|
} catch {
|
|
11786
11843
|
}
|
|
11787
11844
|
}
|
|
11845
|
+
let refPackContent;
|
|
11846
|
+
try {
|
|
11847
|
+
refPackContent = await storage.readSotDocument(projectId, "REFERENCE_PACK.md") || void 0;
|
|
11848
|
+
} catch {
|
|
11849
|
+
refPackContent = void 0;
|
|
11850
|
+
}
|
|
11788
11851
|
const { runCurriculumAIInference: runCurriculumAIInference2 } = await Promise.resolve().then(() => (init_streamRunner(), streamRunner_exports));
|
|
11789
11852
|
const targetLang = options.targetLanguage || plan.translation?.target_language || "vi";
|
|
11790
11853
|
const result = await ensureKnowledgeExposition({
|
|
@@ -11796,6 +11859,7 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
11796
11859
|
slcMarkdown: options.slcMarkdown,
|
|
11797
11860
|
techStack: tech,
|
|
11798
11861
|
hardwarePlatform: hw,
|
|
11862
|
+
refPack: refPackContent,
|
|
11799
11863
|
llmFn: async (systemPrompt, userPrompt) => {
|
|
11800
11864
|
const runnerOpts = options.customInference ? { customInference: options.customInference } : {};
|
|
11801
11865
|
const out = await runCurriculumAIInference2(
|
|
@@ -26094,11 +26158,16 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
26094
26158
|
}).excerpt : "";
|
|
26095
26159
|
let effectiveRefPack = refPack ? buildSectionAwareExcerpt(refPack, {
|
|
26096
26160
|
priorities: [
|
|
26161
|
+
// Toolchain/version matrix FIRST — the most-frequently-hallucinated
|
|
26162
|
+
// facts are tool versions ("Xcode 15" vs ground truth "Xcode 16").
|
|
26163
|
+
// The bilingual fuzzy matcher in contextBuilder resolves these keys
|
|
26164
|
+
// even when the generated RefPack headings are Vietnamese.
|
|
26097
26165
|
"Technical Overview & Architecture Blueprint",
|
|
26098
26166
|
"Hardware Pinout & Wiring Configuration Matrix",
|
|
26167
|
+
"Standards Alignment",
|
|
26099
26168
|
"Core Pedagogical Concept Anchor & Real-World Domain Bridge"
|
|
26100
26169
|
],
|
|
26101
|
-
budget:
|
|
26170
|
+
budget: 3500
|
|
26102
26171
|
}).excerpt : "";
|
|
26103
26172
|
const baseContextPrefix = `PROJECT & ACADEMIC CONTEXT:
|
|
26104
26173
|
- Project ID: ${projectId}
|