learngraph 0.1.1 → 0.3.0
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/LICENSE +190 -21
- package/README.md +165 -3
- package/dist/cjs/llm/adapters/anthropic.js +124 -0
- package/dist/cjs/llm/adapters/anthropic.js.map +1 -0
- package/dist/cjs/llm/adapters/base.js +100 -0
- package/dist/cjs/llm/adapters/base.js.map +1 -0
- package/dist/cjs/llm/adapters/index.js +22 -0
- package/dist/cjs/llm/adapters/index.js.map +1 -0
- package/dist/cjs/llm/adapters/ollama.js +149 -0
- package/dist/cjs/llm/adapters/ollama.js.map +1 -0
- package/dist/cjs/llm/adapters/openai.js +126 -0
- package/dist/cjs/llm/adapters/openai.js.map +1 -0
- package/dist/cjs/llm/index.js +34 -5
- package/dist/cjs/llm/index.js.map +1 -1
- package/dist/cjs/llm/orchestrator.js +219 -0
- package/dist/cjs/llm/orchestrator.js.map +1 -0
- package/dist/cjs/llm/prompts.js +367 -0
- package/dist/cjs/llm/prompts.js.map +1 -0
- package/dist/cjs/parsers/base.js +189 -0
- package/dist/cjs/parsers/base.js.map +1 -0
- package/dist/cjs/parsers/demo.js +159 -0
- package/dist/cjs/parsers/demo.js.map +1 -0
- package/dist/cjs/parsers/extractor.js +191 -0
- package/dist/cjs/parsers/extractor.js.map +1 -0
- package/dist/cjs/parsers/index.js +43 -4
- package/dist/cjs/parsers/index.js.map +1 -1
- package/dist/cjs/parsers/json.js +157 -0
- package/dist/cjs/parsers/json.js.map +1 -0
- package/dist/cjs/parsers/markdown.js +168 -0
- package/dist/cjs/parsers/markdown.js.map +1 -0
- package/dist/cjs/parsers/samples.js +139 -0
- package/dist/cjs/parsers/samples.js.map +1 -0
- package/dist/cjs/storage/base.js +231 -0
- package/dist/cjs/storage/base.js.map +1 -0
- package/dist/cjs/storage/errors.js +128 -0
- package/dist/cjs/storage/errors.js.map +1 -0
- package/dist/cjs/storage/index.js +92 -5
- package/dist/cjs/storage/index.js.map +1 -1
- package/dist/cjs/storage/levelgraph.js +855 -0
- package/dist/cjs/storage/levelgraph.js.map +1 -0
- package/dist/cjs/storage/memory.js +447 -0
- package/dist/cjs/storage/memory.js.map +1 -0
- package/dist/cjs/storage/neo4j.js +866 -0
- package/dist/cjs/storage/neo4j.js.map +1 -0
- package/dist/cjs/storage/seeds.js +565 -0
- package/dist/cjs/storage/seeds.js.map +1 -0
- package/dist/cjs/types/llm.js +8 -0
- package/dist/cjs/types/llm.js.map +1 -0
- package/dist/cjs/types/parser.js +8 -0
- package/dist/cjs/types/parser.js.map +1 -0
- package/dist/esm/llm/adapters/anthropic.js +119 -0
- package/dist/esm/llm/adapters/anthropic.js.map +1 -0
- package/dist/esm/llm/adapters/base.js +95 -0
- package/dist/esm/llm/adapters/base.js.map +1 -0
- package/dist/esm/llm/adapters/index.js +10 -0
- package/dist/esm/llm/adapters/index.js.map +1 -0
- package/dist/esm/llm/adapters/ollama.js +144 -0
- package/dist/esm/llm/adapters/ollama.js.map +1 -0
- package/dist/esm/llm/adapters/openai.js +121 -0
- package/dist/esm/llm/adapters/openai.js.map +1 -0
- package/dist/esm/llm/index.js +12 -6
- package/dist/esm/llm/index.js.map +1 -1
- package/dist/esm/llm/orchestrator.js +214 -0
- package/dist/esm/llm/orchestrator.js.map +1 -0
- package/dist/esm/llm/prompts.js +360 -0
- package/dist/esm/llm/prompts.js.map +1 -0
- package/dist/esm/parsers/base.js +179 -0
- package/dist/esm/parsers/base.js.map +1 -0
- package/dist/esm/parsers/demo.js +154 -0
- package/dist/esm/parsers/demo.js.map +1 -0
- package/dist/esm/parsers/extractor.js +187 -0
- package/dist/esm/parsers/extractor.js.map +1 -0
- package/dist/esm/parsers/index.js +24 -5
- package/dist/esm/parsers/index.js.map +1 -1
- package/dist/esm/parsers/json.js +153 -0
- package/dist/esm/parsers/json.js.map +1 -0
- package/dist/esm/parsers/markdown.js +164 -0
- package/dist/esm/parsers/markdown.js.map +1 -0
- package/dist/esm/parsers/samples.js +136 -0
- package/dist/esm/parsers/samples.js.map +1 -0
- package/dist/esm/storage/base.js +221 -0
- package/dist/esm/storage/base.js.map +1 -0
- package/dist/esm/storage/errors.js +116 -0
- package/dist/esm/storage/errors.js.map +1 -0
- package/dist/esm/storage/index.js +71 -6
- package/dist/esm/storage/index.js.map +1 -1
- package/dist/esm/storage/levelgraph.js +818 -0
- package/dist/esm/storage/levelgraph.js.map +1 -0
- package/dist/esm/storage/memory.js +443 -0
- package/dist/esm/storage/memory.js.map +1 -0
- package/dist/esm/storage/neo4j.js +829 -0
- package/dist/esm/storage/neo4j.js.map +1 -0
- package/dist/esm/storage/seeds.js +561 -0
- package/dist/esm/storage/seeds.js.map +1 -0
- package/dist/esm/types/llm.js +7 -0
- package/dist/esm/types/llm.js.map +1 -0
- package/dist/esm/types/parser.js +7 -0
- package/dist/esm/types/parser.js.map +1 -0
- package/dist/types/llm/adapters/anthropic.d.ts +21 -0
- package/dist/types/llm/adapters/anthropic.d.ts.map +1 -0
- package/dist/types/llm/adapters/base.d.ts +46 -0
- package/dist/types/llm/adapters/base.d.ts.map +1 -0
- package/dist/types/llm/adapters/index.d.ts +11 -0
- package/dist/types/llm/adapters/index.d.ts.map +1 -0
- package/dist/types/llm/adapters/ollama.d.ts +30 -0
- package/dist/types/llm/adapters/ollama.d.ts.map +1 -0
- package/dist/types/llm/adapters/openai.d.ts +22 -0
- package/dist/types/llm/adapters/openai.d.ts.map +1 -0
- package/dist/types/llm/index.d.ts +5 -0
- package/dist/types/llm/index.d.ts.map +1 -1
- package/dist/types/llm/orchestrator.d.ts +35 -0
- package/dist/types/llm/orchestrator.d.ts.map +1 -0
- package/dist/types/llm/prompts.d.ts +269 -0
- package/dist/types/llm/prompts.d.ts.map +1 -0
- package/dist/types/parsers/base.d.ts +39 -0
- package/dist/types/parsers/base.d.ts.map +1 -0
- package/dist/types/parsers/demo.d.ts +87 -0
- package/dist/types/parsers/demo.d.ts.map +1 -0
- package/dist/types/parsers/extractor.d.ts +43 -0
- package/dist/types/parsers/extractor.d.ts.map +1 -0
- package/dist/types/parsers/index.d.ts +10 -0
- package/dist/types/parsers/index.d.ts.map +1 -1
- package/dist/types/parsers/json.d.ts +71 -0
- package/dist/types/parsers/json.d.ts.map +1 -0
- package/dist/types/parsers/markdown.d.ts +43 -0
- package/dist/types/parsers/markdown.d.ts.map +1 -0
- package/dist/types/parsers/samples.d.ts +27 -0
- package/dist/types/parsers/samples.d.ts.map +1 -0
- package/dist/types/storage/base.d.ts +39 -0
- package/dist/types/storage/base.d.ts.map +1 -0
- package/dist/types/storage/errors.d.ts +74 -0
- package/dist/types/storage/errors.d.ts.map +1 -0
- package/dist/types/storage/index.d.ts +50 -2
- package/dist/types/storage/index.d.ts.map +1 -1
- package/dist/types/storage/levelgraph.d.ts +92 -0
- package/dist/types/storage/levelgraph.d.ts.map +1 -0
- package/dist/types/storage/memory.d.ts +70 -0
- package/dist/types/storage/memory.d.ts.map +1 -0
- package/dist/types/storage/neo4j.d.ts +88 -0
- package/dist/types/storage/neo4j.d.ts.map +1 -0
- package/dist/types/storage/seeds.d.ts +27 -0
- package/dist/types/storage/seeds.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +2 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/types/llm.d.ts +298 -0
- package/dist/types/types/llm.d.ts.map +1 -0
- package/dist/types/types/parser.d.ts +208 -0
- package/dist/types/types/parser.d.ts.map +1 -0
- package/package.json +4 -2
- package/scripts/postinstall.js +68 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base parser utilities
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import { detectBloomLevel } from '../types/bloom.js';
|
|
7
|
+
/**
|
|
8
|
+
* Default parse options
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_PARSE_OPTIONS = {
|
|
11
|
+
detectBloom: true,
|
|
12
|
+
extractTime: true,
|
|
13
|
+
suggestNames: true,
|
|
14
|
+
includeRaw: false,
|
|
15
|
+
sectionHeaders: [
|
|
16
|
+
'module',
|
|
17
|
+
'chapter',
|
|
18
|
+
'unit',
|
|
19
|
+
'week',
|
|
20
|
+
'section',
|
|
21
|
+
'part',
|
|
22
|
+
'lesson',
|
|
23
|
+
'topic',
|
|
24
|
+
],
|
|
25
|
+
objectiveMarkers: [
|
|
26
|
+
'students will be able to',
|
|
27
|
+
'learners will',
|
|
28
|
+
'by the end of this',
|
|
29
|
+
'learning objectives',
|
|
30
|
+
'objectives:',
|
|
31
|
+
'learning outcomes',
|
|
32
|
+
'outcomes:',
|
|
33
|
+
'lo:',
|
|
34
|
+
'swbat',
|
|
35
|
+
'•',
|
|
36
|
+
'-',
|
|
37
|
+
'*',
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Common time patterns in syllabi
|
|
42
|
+
* Note: Decimal hours pattern must come before integer hours pattern
|
|
43
|
+
*/
|
|
44
|
+
const TIME_PATTERNS = [
|
|
45
|
+
/(\d+)\s*(?:min(?:ute)?s?|mins?)/i,
|
|
46
|
+
/(\d+\.\d+)\s*(?:hour?s?|hrs?)/i,
|
|
47
|
+
/(\d+)\s*(?:hour?s?|hrs?)/i,
|
|
48
|
+
];
|
|
49
|
+
/**
|
|
50
|
+
* Extract estimated time from text
|
|
51
|
+
*/
|
|
52
|
+
export function extractTime(text) {
|
|
53
|
+
for (const pattern of TIME_PATTERNS) {
|
|
54
|
+
const match = text.match(pattern);
|
|
55
|
+
if (match && match[1]) {
|
|
56
|
+
const value = parseFloat(match[1]);
|
|
57
|
+
if (pattern.source.includes('hour')) {
|
|
58
|
+
return Math.round(value * 60);
|
|
59
|
+
}
|
|
60
|
+
return Math.round(value);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Detect if a line is a learning objective
|
|
67
|
+
*/
|
|
68
|
+
export function isObjectiveLine(line, markers) {
|
|
69
|
+
const lower = line.toLowerCase().trim();
|
|
70
|
+
return markers.some((marker) => lower.includes(marker.toLowerCase()));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Clean and normalize text
|
|
74
|
+
*/
|
|
75
|
+
export function cleanText(text) {
|
|
76
|
+
return text
|
|
77
|
+
.replace(/\s+/g, ' ')
|
|
78
|
+
.replace(/^\s*[-•*]\s*/, '')
|
|
79
|
+
.replace(/^\d+\.\s*/, '')
|
|
80
|
+
.trim();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Generate a skill name from an objective
|
|
84
|
+
*/
|
|
85
|
+
export function objectiveToSkillName(objective) {
|
|
86
|
+
const cleaned = cleanText(objective);
|
|
87
|
+
// Remove common prefixes
|
|
88
|
+
const prefixes = [
|
|
89
|
+
/^students will be able to\s+/i,
|
|
90
|
+
/^learners will\s+/i,
|
|
91
|
+
/^by the end of this [\w\s]+,?\s*/i,
|
|
92
|
+
/^the student will\s+/i,
|
|
93
|
+
/^understand\s+/i,
|
|
94
|
+
/^learn\s+/i,
|
|
95
|
+
];
|
|
96
|
+
let result = cleaned;
|
|
97
|
+
for (const prefix of prefixes) {
|
|
98
|
+
result = result.replace(prefix, '');
|
|
99
|
+
}
|
|
100
|
+
// Capitalize first letter
|
|
101
|
+
result = result.charAt(0).toUpperCase() + result.slice(1);
|
|
102
|
+
// Truncate if too long
|
|
103
|
+
if (result.length > 80) {
|
|
104
|
+
result = result.substring(0, 77) + '...';
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Create a learning objective from text
|
|
110
|
+
*/
|
|
111
|
+
export function createObjective(text, section, week) {
|
|
112
|
+
const cleaned = cleanText(text);
|
|
113
|
+
const bloomLevel = detectBloomLevel(cleaned);
|
|
114
|
+
const objective = {
|
|
115
|
+
text: cleaned,
|
|
116
|
+
bloomLevel,
|
|
117
|
+
bloomConfidence: bloomLevel ? 0.8 : 0,
|
|
118
|
+
suggestedName: objectiveToSkillName(cleaned),
|
|
119
|
+
};
|
|
120
|
+
if (section !== undefined) {
|
|
121
|
+
objective.section = section;
|
|
122
|
+
}
|
|
123
|
+
if (week !== undefined) {
|
|
124
|
+
objective.week = week;
|
|
125
|
+
}
|
|
126
|
+
return objective;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Create empty parse result
|
|
130
|
+
*/
|
|
131
|
+
export function createEmptyResult(source, format) {
|
|
132
|
+
return {
|
|
133
|
+
metadata: {
|
|
134
|
+
source,
|
|
135
|
+
format,
|
|
136
|
+
parsedAt: new Date().toISOString(),
|
|
137
|
+
},
|
|
138
|
+
modules: [],
|
|
139
|
+
topics: [],
|
|
140
|
+
objectives: [],
|
|
141
|
+
warnings: [],
|
|
142
|
+
stats: {
|
|
143
|
+
moduleCount: 0,
|
|
144
|
+
topicCount: 0,
|
|
145
|
+
objectiveCount: 0,
|
|
146
|
+
bloomDetectedCount: 0,
|
|
147
|
+
durationMs: 0,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Calculate parse statistics
|
|
153
|
+
*/
|
|
154
|
+
export function calculateStats(result, startTime) {
|
|
155
|
+
let objectiveCount = result.objectives.length;
|
|
156
|
+
let bloomDetectedCount = result.objectives.filter((o) => o.bloomLevel).length;
|
|
157
|
+
for (const topic of result.topics) {
|
|
158
|
+
objectiveCount += topic.objectives.length;
|
|
159
|
+
bloomDetectedCount += topic.objectives.filter((o) => o.bloomLevel).length;
|
|
160
|
+
}
|
|
161
|
+
for (const mod of result.modules) {
|
|
162
|
+
objectiveCount += mod.objectives.length;
|
|
163
|
+
bloomDetectedCount += mod.objectives.filter((o) => o.bloomLevel).length;
|
|
164
|
+
for (const topic of mod.topics) {
|
|
165
|
+
objectiveCount += topic.objectives.length;
|
|
166
|
+
bloomDetectedCount += topic.objectives.filter((o) => o.bloomLevel).length;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const topicCount = result.topics.length +
|
|
170
|
+
result.modules.reduce((sum, m) => sum + m.topics.length, 0);
|
|
171
|
+
return {
|
|
172
|
+
moduleCount: result.modules.length,
|
|
173
|
+
topicCount,
|
|
174
|
+
objectiveCount,
|
|
175
|
+
bloomDetectedCount,
|
|
176
|
+
durationMs: Date.now() - startTime,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/parsers/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo utilities for quick testing and exploration
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import { MarkdownParser } from './markdown.js';
|
|
7
|
+
import { BasicExtractor } from './extractor.js';
|
|
8
|
+
import { MemoryStorage } from '../storage/memory.js';
|
|
9
|
+
import { SAMPLE_SYLLABI } from './samples.js';
|
|
10
|
+
/**
|
|
11
|
+
* Try LearnGraph with a sample syllabus
|
|
12
|
+
*
|
|
13
|
+
* This is the easiest way to see LearnGraph in action.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { tryWithSample } from 'learngraph/parsers';
|
|
18
|
+
*
|
|
19
|
+
* // Try with physics syllabus
|
|
20
|
+
* const result = await tryWithSample('physics');
|
|
21
|
+
* console.log(`Created ${result.skills.length} skills!`);
|
|
22
|
+
* console.log('Skills:', result.skills.map(s => s.name));
|
|
23
|
+
*
|
|
24
|
+
* // Try with kindergarten math
|
|
25
|
+
* const kResult = await tryWithSample('kindergarten');
|
|
26
|
+
* console.log(`Kindergarten: ${kResult.skills.length} skills`);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export async function tryWithSample(sample = 'physics') {
|
|
30
|
+
const syllabus = SAMPLE_SYLLABI[sample];
|
|
31
|
+
return tryWithSyllabus(syllabus);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Try LearnGraph with your own syllabus
|
|
35
|
+
*
|
|
36
|
+
* Paste your syllabus as markdown and see the magic happen!
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* import { tryWithSyllabus } from 'learngraph/parsers';
|
|
41
|
+
*
|
|
42
|
+
* const mySyllabus = `
|
|
43
|
+
* # My Course
|
|
44
|
+
*
|
|
45
|
+
* ## Week 1: Introduction
|
|
46
|
+
*
|
|
47
|
+
* ### Learning Objectives
|
|
48
|
+
* - Understand the course structure
|
|
49
|
+
* - Identify key topics
|
|
50
|
+
* - Apply basic concepts
|
|
51
|
+
* `;
|
|
52
|
+
*
|
|
53
|
+
* const result = await tryWithSyllabus(mySyllabus);
|
|
54
|
+
* console.log('Found', result.parseResult.stats.objectiveCount, 'objectives');
|
|
55
|
+
* console.log('Created', result.skills.length, 'skills');
|
|
56
|
+
*
|
|
57
|
+
* // See the skills
|
|
58
|
+
* for (const skill of result.skills) {
|
|
59
|
+
* console.log(`- ${skill.name} (${skill.bloomLevel}, difficulty: ${skill.difficulty})`);
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export async function tryWithSyllabus(syllabus, options) {
|
|
64
|
+
// Parse the syllabus
|
|
65
|
+
const parser = new MarkdownParser();
|
|
66
|
+
const parseResult = await parser.parse(syllabus);
|
|
67
|
+
// Extract skills
|
|
68
|
+
const extractor = new BasicExtractor();
|
|
69
|
+
const extraction = await extractor.extract(parseResult, options);
|
|
70
|
+
// Create storage and populate
|
|
71
|
+
const storage = new MemoryStorage();
|
|
72
|
+
await storage.connect({ backend: 'memory' });
|
|
73
|
+
// Create skills
|
|
74
|
+
const skills = [];
|
|
75
|
+
const skillMap = new Map();
|
|
76
|
+
for (const { skill: input } of extraction.skills) {
|
|
77
|
+
const skill = await storage.createSkill(input);
|
|
78
|
+
skills.push(skill);
|
|
79
|
+
skillMap.set(skill.name, skill);
|
|
80
|
+
}
|
|
81
|
+
// Create edges
|
|
82
|
+
const edges = [];
|
|
83
|
+
for (const suggested of extraction.suggestedEdges) {
|
|
84
|
+
const source = skillMap.get(suggested.sourceName);
|
|
85
|
+
const target = skillMap.get(suggested.targetName);
|
|
86
|
+
if (source && target) {
|
|
87
|
+
const edgeInput = {
|
|
88
|
+
sourceId: source.id,
|
|
89
|
+
targetId: target.id,
|
|
90
|
+
strength: suggested.strength,
|
|
91
|
+
type: suggested.strength >= 0.8 ? 'hard' : 'soft',
|
|
92
|
+
metadata: {},
|
|
93
|
+
};
|
|
94
|
+
if (suggested.reasoning) {
|
|
95
|
+
edgeInput.reasoning = suggested.reasoning;
|
|
96
|
+
}
|
|
97
|
+
const edge = await storage.createPrerequisite(edgeInput);
|
|
98
|
+
edges.push(edge);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Get stats
|
|
102
|
+
const stats = await storage.getStats();
|
|
103
|
+
await storage.disconnect();
|
|
104
|
+
return {
|
|
105
|
+
parseResult,
|
|
106
|
+
extraction,
|
|
107
|
+
skills,
|
|
108
|
+
edges,
|
|
109
|
+
stats,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Quick console output of demo results
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* import { tryWithSample, printDemoResults } from 'learngraph/parsers';
|
|
118
|
+
*
|
|
119
|
+
* const result = await tryWithSample('physics');
|
|
120
|
+
* printDemoResults(result);
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export function printDemoResults(result) {
|
|
124
|
+
console.log('\n' + '='.repeat(60));
|
|
125
|
+
console.log('LearnGraph Demo Results');
|
|
126
|
+
console.log('='.repeat(60));
|
|
127
|
+
console.log(`\nCourse: ${result.parseResult.metadata.title || 'Untitled'}`);
|
|
128
|
+
console.log(`Format: ${result.parseResult.metadata.format}`);
|
|
129
|
+
console.log('\n--- Parse Statistics ---');
|
|
130
|
+
console.log(`Modules: ${result.parseResult.stats.moduleCount}`);
|
|
131
|
+
console.log(`Topics: ${result.parseResult.stats.topicCount}`);
|
|
132
|
+
console.log(`Objectives: ${result.parseResult.stats.objectiveCount}`);
|
|
133
|
+
console.log(`Bloom's Detected: ${result.parseResult.stats.bloomDetectedCount}`);
|
|
134
|
+
console.log('\n--- Skills Created ---');
|
|
135
|
+
for (const skill of result.skills) {
|
|
136
|
+
console.log(` - ${skill.name} [${skill.bloomLevel}] (difficulty: ${skill.difficulty.toFixed(2)})`);
|
|
137
|
+
}
|
|
138
|
+
console.log('\n--- Prerequisites ---');
|
|
139
|
+
for (const edge of result.edges) {
|
|
140
|
+
const source = result.skills.find((s) => s.id === edge.sourceId);
|
|
141
|
+
const target = result.skills.find((s) => s.id === edge.targetId);
|
|
142
|
+
if (source && target) {
|
|
143
|
+
console.log(` ${source.name} → ${target.name} (${edge.type})`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
console.log('\n--- Graph Statistics ---');
|
|
147
|
+
console.log(`Total Skills: ${result.stats.nodeCount}`);
|
|
148
|
+
console.log(`Total Edges: ${result.stats.edgeCount}`);
|
|
149
|
+
console.log(`Root Skills: ${result.stats.rootNodeCount}`);
|
|
150
|
+
console.log(`Max Depth: ${result.stats.maxDepth}`);
|
|
151
|
+
console.log(`Bloom Distribution:`, result.stats.bloomDistribution);
|
|
152
|
+
console.log('\n' + '='.repeat(60) + '\n');
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=demo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../../../src/parsers/demo.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAA2B,MAAM,cAAc,CAAC;AAkBvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,SAA6B,SAAS;IAEtC,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,OAA2B;IAE3B,qBAAqB;IACrB,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;IACpC,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEjD,iBAAiB;IACjB,MAAM,SAAS,GAAG,IAAI,cAAc,EAAE,CAAC;IACvC,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAEjE,8BAA8B;IAC9B,MAAM,OAAO,GAAG,IAAI,aAAa,EAAE,CAAC;IACpC,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IAE7C,gBAAgB;IAChB,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAC;IAE9C,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,eAAe;IACf,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAElD,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;YACrB,MAAM,SAAS,GAAqD;gBAClE,QAAQ,EAAE,MAAM,CAAC,EAAE;gBACnB,QAAQ,EAAE,MAAM,CAAC,EAAE;gBACnB,QAAQ,EAAE,SAAS,CAAC,QAAQ;gBAC5B,IAAI,EAAE,SAAS,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;gBACjD,QAAQ,EAAE,EAAE;aACb,CAAC;YAEF,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;gBACxB,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;YAC5C,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;YACzD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,YAAY;IACZ,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;IAEvC,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;IAE3B,OAAO;QACL,WAAW;QACX,UAAU;QACV,MAAM;QACN,KAAK;QACL,KAAK;KACN,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAkB;IACjD,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7D,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAEhF,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CACT,OAAO,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,UAAU,kBAAkB,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACvF,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjE,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAEnE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill extractor - converts parsed syllabi into graph-ready skills
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import { objectiveToSkillName } from './base.js';
|
|
7
|
+
/**
|
|
8
|
+
* Default extraction options
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_EXTRACTION_OPTIONS = {
|
|
11
|
+
detectBloom: true,
|
|
12
|
+
extractTime: true,
|
|
13
|
+
suggestNames: true,
|
|
14
|
+
includeRaw: false,
|
|
15
|
+
sectionHeaders: [],
|
|
16
|
+
objectiveMarkers: [],
|
|
17
|
+
defaultDifficulty: 0.5,
|
|
18
|
+
defaultMasteryThreshold: 0.8,
|
|
19
|
+
defaultEstimatedMinutes: 30,
|
|
20
|
+
tags: [],
|
|
21
|
+
domain: '',
|
|
22
|
+
gradeLevel: '',
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Map Bloom's level to difficulty estimate
|
|
26
|
+
*/
|
|
27
|
+
function bloomToDifficulty(level) {
|
|
28
|
+
switch (level) {
|
|
29
|
+
case 'remember':
|
|
30
|
+
return 0.2;
|
|
31
|
+
case 'understand':
|
|
32
|
+
return 0.35;
|
|
33
|
+
case 'apply':
|
|
34
|
+
return 0.5;
|
|
35
|
+
case 'analyze':
|
|
36
|
+
return 0.65;
|
|
37
|
+
case 'evaluate':
|
|
38
|
+
return 0.8;
|
|
39
|
+
case 'create':
|
|
40
|
+
return 0.9;
|
|
41
|
+
default:
|
|
42
|
+
return 0.5;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Basic skill extractor
|
|
47
|
+
*
|
|
48
|
+
* Converts parsed syllabus content into skills ready for graph storage.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { MarkdownParser, BasicExtractor } from 'learngraph/parsers';
|
|
53
|
+
*
|
|
54
|
+
* const parser = new MarkdownParser();
|
|
55
|
+
* const extractor = new BasicExtractor();
|
|
56
|
+
*
|
|
57
|
+
* const parseResult = await parser.parse(syllabusMarkdown);
|
|
58
|
+
* const extraction = await extractor.extract(parseResult, {
|
|
59
|
+
* tags: ['physics', 'intro'],
|
|
60
|
+
* domain: 'Physics',
|
|
61
|
+
* gradeLevel: 'Undergraduate'
|
|
62
|
+
* });
|
|
63
|
+
*
|
|
64
|
+
* // Now create skills in storage
|
|
65
|
+
* for (const { skill } of extraction.skills) {
|
|
66
|
+
* await storage.createSkill(skill);
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export class BasicExtractor {
|
|
71
|
+
async extract(parseResult, options) {
|
|
72
|
+
const opts = { ...DEFAULT_EXTRACTION_OPTIONS, ...options };
|
|
73
|
+
const skills = [];
|
|
74
|
+
const warnings = [];
|
|
75
|
+
const skillNames = new Set();
|
|
76
|
+
// Helper to create skill from objective
|
|
77
|
+
const createSkillFromObjective = (objective, topic, moduleTitle) => {
|
|
78
|
+
const name = objective.suggestedName || objectiveToSkillName(objective.text);
|
|
79
|
+
// Skip duplicates
|
|
80
|
+
if (skillNames.has(name.toLowerCase())) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
skillNames.add(name.toLowerCase());
|
|
84
|
+
const difficulty = objective.bloomLevel
|
|
85
|
+
? bloomToDifficulty(objective.bloomLevel)
|
|
86
|
+
: opts.defaultDifficulty;
|
|
87
|
+
const skill = {
|
|
88
|
+
name,
|
|
89
|
+
description: objective.text,
|
|
90
|
+
bloomLevel: objective.bloomLevel || 'understand',
|
|
91
|
+
difficulty,
|
|
92
|
+
isThresholdConcept: objective.bloomLevel === 'analyze' || objective.bloomLevel === 'evaluate',
|
|
93
|
+
masteryThreshold: opts.defaultMasteryThreshold,
|
|
94
|
+
estimatedMinutes: topic?.estimatedMinutes || opts.defaultEstimatedMinutes,
|
|
95
|
+
tags: [
|
|
96
|
+
...opts.tags,
|
|
97
|
+
...(moduleTitle ? [moduleTitle.toLowerCase().replace(/[^a-z0-9]+/g, '-')] : []),
|
|
98
|
+
],
|
|
99
|
+
metadata: {
|
|
100
|
+
source: parseResult.metadata.source,
|
|
101
|
+
section: objective.section,
|
|
102
|
+
week: objective.week,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
// Add optional fields
|
|
106
|
+
if (opts.domain) {
|
|
107
|
+
skill.domain = opts.domain;
|
|
108
|
+
}
|
|
109
|
+
if (opts.gradeLevel) {
|
|
110
|
+
skill.gradeLevel = opts.gradeLevel;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
skill,
|
|
114
|
+
source: objective,
|
|
115
|
+
confidence: objective.bloomConfidence || 0.7,
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
// Extract from standalone objectives
|
|
119
|
+
for (const objective of parseResult.objectives) {
|
|
120
|
+
const extracted = createSkillFromObjective(objective);
|
|
121
|
+
if (extracted)
|
|
122
|
+
skills.push(extracted);
|
|
123
|
+
}
|
|
124
|
+
// Extract from standalone topics
|
|
125
|
+
for (const topic of parseResult.topics) {
|
|
126
|
+
for (const objective of topic.objectives) {
|
|
127
|
+
const extracted = createSkillFromObjective(objective, topic);
|
|
128
|
+
if (extracted)
|
|
129
|
+
skills.push(extracted);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Extract from modules
|
|
133
|
+
for (const mod of parseResult.modules) {
|
|
134
|
+
// Module-level objectives
|
|
135
|
+
for (const objective of mod.objectives) {
|
|
136
|
+
const extracted = createSkillFromObjective(objective, undefined, mod.title);
|
|
137
|
+
if (extracted)
|
|
138
|
+
skills.push(extracted);
|
|
139
|
+
}
|
|
140
|
+
// Topic objectives within modules
|
|
141
|
+
for (const topic of mod.topics) {
|
|
142
|
+
for (const objective of topic.objectives) {
|
|
143
|
+
const extracted = createSkillFromObjective(objective, topic, mod.title);
|
|
144
|
+
if (extracted)
|
|
145
|
+
skills.push(extracted);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Suggest prerequisite edges based on order and Bloom's levels
|
|
150
|
+
const suggestedEdges = this.suggestEdges(skills);
|
|
151
|
+
return {
|
|
152
|
+
skills,
|
|
153
|
+
suggestedEdges,
|
|
154
|
+
warnings,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Suggest prerequisite relationships based on skill order and Bloom's levels
|
|
159
|
+
*/
|
|
160
|
+
suggestEdges(skills) {
|
|
161
|
+
const edges = [];
|
|
162
|
+
for (let i = 1; i < skills.length; i++) {
|
|
163
|
+
const current = skills[i];
|
|
164
|
+
const previous = skills[i - 1];
|
|
165
|
+
if (!current || !previous)
|
|
166
|
+
continue;
|
|
167
|
+
// Skills in the same module/section are likely related
|
|
168
|
+
const sameSection = current.skill.metadata?.section === previous.skill.metadata?.section;
|
|
169
|
+
const sameWeek = current.skill.metadata?.week === previous.skill.metadata?.week;
|
|
170
|
+
if (sameSection || sameWeek) {
|
|
171
|
+
// Higher Bloom's level likely depends on lower
|
|
172
|
+
const currentDiff = current.skill.difficulty;
|
|
173
|
+
const prevDiff = previous.skill.difficulty;
|
|
174
|
+
if (currentDiff > prevDiff) {
|
|
175
|
+
edges.push({
|
|
176
|
+
sourceName: previous.skill.name,
|
|
177
|
+
targetName: current.skill.name,
|
|
178
|
+
strength: 0.7,
|
|
179
|
+
reasoning: 'Sequential in syllabus, increasing complexity',
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return edges;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../../src/parsers/extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,30 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Content parsers for educational materials
|
|
4
3
|
*
|
|
4
|
+
* Parse syllabi, course outlines, and learning objectives into
|
|
5
|
+
* structured skill graphs.
|
|
6
|
+
*
|
|
5
7
|
* @packageDocumentation
|
|
6
8
|
*/
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
|
|
9
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
10
|
+
// Parsers
|
|
11
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
12
|
+
export { MarkdownParser } from './markdown.js';
|
|
13
|
+
export { JSONParser } from './json.js';
|
|
14
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
// Skill Extraction
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
export { BasicExtractor, DEFAULT_EXTRACTION_OPTIONS } from './extractor.js';
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
// Utilities
|
|
20
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
+
export { DEFAULT_PARSE_OPTIONS, extractTime, isObjectiveLine, cleanText, objectiveToSkillName, createObjective, } from './base.js';
|
|
22
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
23
|
+
// Sample Syllabi
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
+
export { PHYSICS_101_SYLLABUS, KINDERGARTEN_MATH_SYLLABUS, PROGRAMMING_101_SYLLABUS, SAMPLE_SYLLABI, } from './samples.js';
|
|
26
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
+
// Demo Functions
|
|
28
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
29
|
+
export { tryWithSample, tryWithSyllabus, printDemoResults, } from './demo.js';
|
|
11
30
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/parsers/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/parsers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsBH,gFAAgF;AAChF,UAAU;AACV,gFAAgF;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAqB,MAAM,WAAW,CAAC;AAE1D,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAChF,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5E,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAChF,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,eAAe,EACf,SAAS,EACT,oBAAoB,EACpB,eAAe,GAChB,MAAM,WAAW,CAAC;AAEnB,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAChF,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,EACxB,cAAc,GAEf,MAAM,cAAc,CAAC;AAEtB,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAChF,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,GAEjB,MAAM,WAAW,CAAC"}
|