learn-loops 0.4.0 → 0.4.2
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/diagram.js +7 -1
- package/dist/prompts.js +13 -1
- package/package.json +1 -1
package/dist/diagram.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { renderMermaidASCII } from "beautiful-mermaid";
|
|
2
2
|
const color = !!process.stdout.isTTY && !process.env.NO_COLOR;
|
|
3
|
+
// beautiful-mermaid hardcodes near-black label text, unreadable on dark terminals. Render labels in a
|
|
4
|
+
// sentinel colour and swap it for the terminal's default foreground; lines use a mid-grey legible on both.
|
|
5
|
+
const SENTINEL = "\x1b[38;5;201m";
|
|
6
|
+
const GREY = "#8a8a8a";
|
|
7
|
+
const theme = { fg: "#ff00ff", border: GREY, line: GREY, arrow: GREY, corner: GREY, junction: GREY };
|
|
3
8
|
const widest = (s) => Math.max(...s.split("\n").map((l) => l.replace(/\x1b\[[0-9;]*m/g, "").length));
|
|
4
9
|
/** mindmap isn't supported by beautiful-mermaid, so draw it as an indented tree. */
|
|
5
10
|
function mindmapTree(src) {
|
|
@@ -34,7 +39,8 @@ export function renderDiagram(src, cols = process.stdout.columns ?? 100) {
|
|
|
34
39
|
return mindmapTree(text);
|
|
35
40
|
const attempt = (s) => {
|
|
36
41
|
try {
|
|
37
|
-
|
|
42
|
+
const out = renderMermaidASCII(s, { colorMode: color ? "ansi256" : "none", paddingY: 2, paddingX: 4, theme });
|
|
43
|
+
return color ? out.split(SENTINEL).join("\x1b[39m") : out;
|
|
38
44
|
}
|
|
39
45
|
catch {
|
|
40
46
|
return null;
|
package/dist/prompts.js
CHANGED
|
@@ -20,6 +20,12 @@ const STEM_RULES = `Math and science content:
|
|
|
20
20
|
- Physical or geometric setups (free-body diagrams, circuits, ray/optics diagrams, fields, waves, geometry) go in a fenced svg block holding one complete <svg viewBox='0 0 640 360'>. Use SINGLE quotes for every attribute, include a <title>, dark strokes on a transparent background, labelled parts via <text>, arrowheads via <marker>, and no scripts, images or external references. Keep it uncluttered and physically correct.
|
|
21
21
|
- Graphs of functions (waveforms, potentials, distributions, trade-off curves) go in a fenced plot block holding JSON: {"title":"...","xlabel":"...","ylabel":"...","xmin":0,"xmax":10,"series":[{"label":"...","expr":"exp(-0.3*x)*cos(3*x)"}]}. The expr is a mathjs expression in x (use *, ^, sin, cos, exp, sqrt, pi), never LaTeX.
|
|
22
22
|
- Use mermaid only for processes, hierarchies and state/flow structure. Add equations or figures only where they genuinely clarify; never decorate.`;
|
|
23
|
+
const QUESTION_RULES = `Question precision (every question you write, including multiple-choice checks, flashcard fronts, predictions and follow-ups):
|
|
24
|
+
- Each question must have exactly one defensible reading. Name the specific thing being asked about; never use bare "it", "this" or "the system" without a clear referent, and never lean on context the learner cannot see.
|
|
25
|
+
- State any assumptions, conditions or scope the answer depends on inside the question itself (e.g. "assuming a single thread", "in the ideal case").
|
|
26
|
+
- Ask for one thing at a time, and say what form the answer takes (which, why, how many, what happens next).
|
|
27
|
+
- For multiple-choice: exactly one option is correct, the others are clearly wrong on a strict reading, and no option is a matter of opinion or "it depends". Avoid "all/none of the above" and vague words like "usually", "best" or "better" unless the question defines the criterion.
|
|
28
|
+
- Open-ended questions may have many good answers, but the task must still be unambiguous about what to address.`;
|
|
23
29
|
const diagramRule = (p) => p.diagrams === "lots" ? "Include 1-2 mermaid diagrams." : p.diagrams === "some" ? "Include one mermaid diagram if it genuinely helps." : "Only include a diagram if essential.";
|
|
24
30
|
export function mapPrompt(p, topic, prior) {
|
|
25
31
|
return `${learnerBlurb(p)}
|
|
@@ -47,6 +53,7 @@ Concepts to touch: ${area.concepts.map((c) => c.name).join(", ")}.
|
|
|
47
53
|
Rules: max ~250 words in markdown. ${p.order === "examples-first" ? "Open with a concrete example, then name the idea." : p.order === "theory-first" ? "State the core principle first, then illustrate." : "Open with where it fits in the whole field, then the idea, then an example."}
|
|
48
54
|
Use the learner's preferred styles (${p.styles.join(", ") || "any"}). ${diagramRule(p)} ${MERMAID_RULES}
|
|
49
55
|
${STEM_RULES}
|
|
56
|
+
${QUESTION_RULES}
|
|
50
57
|
Exactly 2 multiple-choice checks (4 options each, "answer" is the 0-based index, plausible distractors based on real misconceptions; vary the position of the right answer). 2-3 flashcards.
|
|
51
58
|
Return ONLY JSON of this shape:
|
|
52
59
|
${lessonShape}`;
|
|
@@ -64,6 +71,7 @@ Already covered in this area: ${doneTitles.join("; ") || "nothing yet"}. Build o
|
|
|
64
71
|
Rules: 400-650 words of markdown with ## subheadings. ${p.order === "examples-first" ? "Start from a worked example, then abstract." : p.order === "theory-first" ? "Start from first principles, then apply." : "Start from the big picture, zoom in, then work an example."}
|
|
65
72
|
Include a worked example, one common misconception to avoid, and ${p.diagrams === "minimal" ? "at least one" : "1-2"} figure(s) (mermaid, svg or plot as fits the subject) showing the real mechanism/structure (not decoration). ${MERMAID_RULES}
|
|
66
73
|
${STEM_RULES}
|
|
74
|
+
${QUESTION_RULES}
|
|
67
75
|
Challenge level: ${p.challenge}. Exactly ${p.challenge === "tough" ? 4 : 3} multiple-choice checks that test understanding/application, not trivia (4 options, "answer" is 0-based). 3-4 flashcards phrased as recall questions.
|
|
68
76
|
${p.socratic ? "The learner prefers a SOCRATIC style: the markdown is the consolidation shown AFTER they work through your leading questions, so it should name and tie together the ideas those questions lead to." : ""}
|
|
69
77
|
Also include the "prediction" (a situation where a wrong intuition is likely, so they learn from guessing wrong), the "deeper" trade-off question${p.socratic ? ", and exactly 3 \"socratic\" questions" : ""}.
|
|
@@ -102,13 +110,14 @@ export const PERSONAS = [
|
|
|
102
110
|
export function personaPrompt(p, persona, title, keyPoints, answer) {
|
|
103
111
|
return `Role-play ${persona.label} (${persona.voice}) who just heard the learner explain "${title}". Their explanation: """${answer}"""
|
|
104
112
|
A complete explanation would cover: ${keyPoints.join("; ")}.
|
|
105
|
-
React in character in 1-2 sentences (say honestly what confused you or what clicked), then ask ONE follow-up question aimed at the biggest gap or shaky claim in what they said. Stay in character; never reveal the answer.
|
|
113
|
+
React in character in 1-2 sentences (say honestly what confused you or what clicked), then ask ONE follow-up question aimed at the biggest gap or shaky claim in what they said. Stay in character; never reveal the answer. The question must still be unambiguous: one specific thing asked, with any needed context stated.
|
|
106
114
|
Return ONLY JSON: {"reaction":"...","question":"..."}`;
|
|
107
115
|
}
|
|
108
116
|
export function diagnoseQuestionsPrompt(p, title, missed, explanation) {
|
|
109
117
|
return `${learnerBlurb(p)}
|
|
110
118
|
The learner struggled with "${title}". They missed: ${missed.map((m) => `"${m}"`).join("; ") || "none (their own-words explanation was weak)"}. ${explanation ? `Feedback on their explanation: ${explanation}` : ""}
|
|
111
119
|
Write exactly 2 short diagnostic questions (not quiz questions) that reveal WHAT mental model they hold, e.g. "what do you picture happens when ...?". Do not teach yet.
|
|
120
|
+
${QUESTION_RULES}
|
|
112
121
|
Return ONLY JSON: {"questions":["...","..."]}`;
|
|
113
122
|
}
|
|
114
123
|
export function diagnoseResultPrompt(p, title, qa, missed) {
|
|
@@ -117,6 +126,7 @@ Lesson "${title}". Missed questions: ${missed.join("; ") || "n/a"}.
|
|
|
117
126
|
Diagnostic Q&A:
|
|
118
127
|
${qa.map((x) => `Q: ${x.q}\nA: ${x.a || "(no answer)"}`).join("\n")}
|
|
119
128
|
Identify the single most likely misconception or gap, re-teach exactly that with a NEW angle (max 150 words, markdown, optional tiny mermaid), and write one fresh multiple-choice check that would fail if the misconception persists (4 options, "answer" 0-based index).
|
|
129
|
+
${QUESTION_RULES}
|
|
120
130
|
Return ONLY JSON: {"misconception":"one sentence","reteach":"markdown","retest":{"q":"...","options":["","","",""],"answer":0,"explain":"..."}}`;
|
|
121
131
|
}
|
|
122
132
|
export const LENSES = [
|
|
@@ -131,6 +141,7 @@ export function deeperPrompt(p, s, title, lens, earlier) {
|
|
|
131
141
|
return `${learnerBlurb(p)} ${useBlurb(s)}
|
|
132
142
|
Topic "${s.title}", lesson "${title}". Pose ONE open-ended "think deeper" question through the lens "${lens.label}": ${lens.ask}
|
|
133
143
|
Make it concrete (a specific situation, not abstract). Do not repeat earlier questions: ${earlier.join(" | ") || "none"}.
|
|
144
|
+
${QUESTION_RULES}
|
|
134
145
|
Return ONLY JSON: {"question":"...","considerations":["4-5 things a thoughtful answer would raise"]}`;
|
|
135
146
|
}
|
|
136
147
|
export function critiquePrompt(p, title, question, considerations, answer) {
|
|
@@ -145,5 +156,6 @@ export function challengePrompt(p, s, area, covered) {
|
|
|
145
156
|
return `${learnerBlurb(p)} ${useBlurb(s)}
|
|
146
157
|
The learner just finished a deep dive into "${area.title}" (topic "${s.title}"), covering: ${covered.join("; ")}.
|
|
147
158
|
Write ONE realistic application challenge: a specific scenario with constraints and a decision to make, where there is no single right answer and the learner must weigh trade-offs and anticipate what could go wrong. Make it ${p.challenge === "tough" ? "hard and ambiguous" : p.challenge === "gentle" ? "approachable" : "moderately demanding"}.
|
|
159
|
+
${QUESTION_RULES}
|
|
148
160
|
Return ONLY JSON: {"scenario":"3-5 sentences","task":"what they must decide or design, and justify","considerations":["5-6 things a strong answer weighs"]}`;
|
|
149
161
|
}
|