learn-anything-cli 0.1.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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/README.zh-CN.md +96 -0
  4. package/bin/learn-anything.js +3 -0
  5. package/dist/cli/index.d.ts +2 -0
  6. package/dist/cli/index.js +88 -0
  7. package/dist/core/command-generation/adapters/claude.d.ts +3 -0
  8. package/dist/core/command-generation/adapters/claude.js +31 -0
  9. package/dist/core/command-generation/adapters/codex.d.ts +3 -0
  10. package/dist/core/command-generation/adapters/codex.js +26 -0
  11. package/dist/core/command-generation/adapters/cursor.d.ts +3 -0
  12. package/dist/core/command-generation/adapters/cursor.js +27 -0
  13. package/dist/core/command-generation/adapters/gemini.d.ts +3 -0
  14. package/dist/core/command-generation/adapters/gemini.js +23 -0
  15. package/dist/core/command-generation/adapters/index.d.ts +5 -0
  16. package/dist/core/command-generation/adapters/index.js +5 -0
  17. package/dist/core/command-generation/generator.d.ts +4 -0
  18. package/dist/core/command-generation/generator.js +10 -0
  19. package/dist/core/command-generation/index.d.ts +4 -0
  20. package/dist/core/command-generation/index.js +3 -0
  21. package/dist/core/command-generation/registry.d.ts +8 -0
  22. package/dist/core/command-generation/registry.js +20 -0
  23. package/dist/core/command-generation/types.d.ts +18 -0
  24. package/dist/core/command-generation/types.js +2 -0
  25. package/dist/core/config.d.ts +11 -0
  26. package/dist/core/config.js +33 -0
  27. package/dist/core/init.d.ts +22 -0
  28. package/dist/core/init.js +133 -0
  29. package/dist/core/shared/index.d.ts +3 -0
  30. package/dist/core/shared/index.js +2 -0
  31. package/dist/core/shared/skill-generation.d.ts +16 -0
  32. package/dist/core/shared/skill-generation.js +49 -0
  33. package/dist/core/templates/skill-templates.d.ts +7 -0
  34. package/dist/core/templates/skill-templates.js +6 -0
  35. package/dist/core/templates/types.d.ts +16 -0
  36. package/dist/core/templates/types.js +2 -0
  37. package/dist/core/templates/workflows/learn-explain.d.ts +4 -0
  38. package/dist/core/templates/workflows/learn-explain.js +203 -0
  39. package/dist/core/templates/workflows/learn-practice.d.ts +4 -0
  40. package/dist/core/templates/workflows/learn-practice.js +247 -0
  41. package/dist/core/templates/workflows/learn-review.d.ts +4 -0
  42. package/dist/core/templates/workflows/learn-review.js +167 -0
  43. package/dist/core/templates/workflows/learn-status.d.ts +4 -0
  44. package/dist/core/templates/workflows/learn-status.js +114 -0
  45. package/dist/core/templates/workflows/learn-topic.d.ts +4 -0
  46. package/dist/core/templates/workflows/learn-topic.js +191 -0
  47. package/dist/i18n/index.d.ts +6 -0
  48. package/dist/i18n/index.js +30 -0
  49. package/dist/i18n/locales/en.d.ts +3 -0
  50. package/dist/i18n/locales/en.js +28 -0
  51. package/dist/i18n/locales/zh-CN.d.ts +3 -0
  52. package/dist/i18n/locales/zh-CN.js +28 -0
  53. package/dist/i18n/types.d.ts +31 -0
  54. package/dist/i18n/types.js +2 -0
  55. package/dist/index.d.ts +6 -0
  56. package/dist/index.js +4 -0
  57. package/dist/utils/file-system.d.ts +8 -0
  58. package/dist/utils/file-system.js +38 -0
  59. package/dist/utils/interactive.d.ts +2 -0
  60. package/dist/utils/interactive.js +4 -0
  61. package/package.json +69 -0
@@ -0,0 +1,133 @@
1
+ import path from 'path';
2
+ import chalk from 'chalk';
3
+ import * as fs from 'fs';
4
+ import { createRequire } from 'module';
5
+ import { FileSystemUtils } from '../utils/file-system.js';
6
+ import { AI_TOOLS, LEARN_DIR } from './config.js';
7
+ import { isInteractive } from '../utils/interactive.js';
8
+ import { generateCommands, CommandAdapterRegistry, } from './command-generation/index.js';
9
+ import { getSkillTemplates, getCommandContents, generateSkillContent, } from './shared/index.js';
10
+ import { getMessages } from '../i18n/index.js';
11
+ const require = createRequire(import.meta.url);
12
+ const { version: VERSION } = require('../../package.json');
13
+ export class InitCommand {
14
+ toolsArg;
15
+ force;
16
+ locale;
17
+ isUpdate;
18
+ constructor(options = {}) {
19
+ this.toolsArg = options.tools;
20
+ this.force = options.force ?? false;
21
+ this.locale = options.locale ?? 'en';
22
+ this.isUpdate = options.update ?? false;
23
+ }
24
+ async execute(targetPath = '.') {
25
+ const resolvedPath = path.resolve(targetPath);
26
+ const m = getMessages(this.locale);
27
+ // Ensure target directory exists
28
+ await FileSystemUtils.ensureDir(resolvedPath);
29
+ // Create .learn/ directory in the target project
30
+ const learnDir = path.join(resolvedPath, LEARN_DIR);
31
+ await FileSystemUtils.ensureDir(path.join(learnDir, 'topics'));
32
+ console.log(chalk.bold(m.init.header));
33
+ // Detect available tools
34
+ const availableTools = await this.detectTools(resolvedPath);
35
+ // Select tools
36
+ let selectedTools;
37
+ if (this.toolsArg === 'all') {
38
+ selectedTools = availableTools.filter((t) => t.available);
39
+ }
40
+ else if (this.toolsArg === 'none') {
41
+ selectedTools = [];
42
+ }
43
+ else if (this.toolsArg) {
44
+ const toolIds = this.toolsArg.split(',').map((t) => t.trim());
45
+ selectedTools = availableTools.filter((t) => toolIds.includes(t.value));
46
+ }
47
+ else if (this.isUpdate || !isInteractive()) {
48
+ // Update mode or non-interactive: auto-detect existing tool dirs
49
+ selectedTools = availableTools.filter((t) => t.available && this.hasToolDir(resolvedPath, t));
50
+ }
51
+ else {
52
+ selectedTools = await this.interactiveSelect(availableTools);
53
+ }
54
+ if (selectedTools.length === 0) {
55
+ console.log(chalk.yellow(m.init.noToolsSelected));
56
+ console.log(chalk.dim(m.init.availableTools(availableTools.filter((t) => t.available).map((t) => t.value).join(', '))));
57
+ return;
58
+ }
59
+ // Generate skill files for each tool
60
+ for (const tool of selectedTools) {
61
+ if (!tool.skillsDir)
62
+ continue;
63
+ await this.generateSkillsForTool(resolvedPath, tool);
64
+ await this.generateCommandsForTool(resolvedPath, tool);
65
+ console.log(chalk.green(m.init.skillGenerated(tool.name)));
66
+ }
67
+ console.log('');
68
+ console.log(chalk.bold(m.init.initComplete));
69
+ console.log(chalk.dim(m.init.globalDataPath(LEARN_DIR)));
70
+ console.log(chalk.dim(m.init.startLearning('/learn javascript')));
71
+ console.log(chalk.bold(m.init.availableCommands));
72
+ const cmd = m.init.cmdLine;
73
+ console.log(cmd(chalk.cyan('/learn:topic <topic-name>'), chalk.dim(' — Initialize or load a learning topic')));
74
+ console.log(cmd(chalk.cyan('/learn:explain <concept-name>'), chalk.dim(' — Recursively deep-dive into a concept')));
75
+ console.log(cmd(chalk.cyan('/learn:practice <concept-name>'), chalk.dim(' — TDD-style coding exercises')));
76
+ console.log(cmd(chalk.cyan('/learn:review [topic-name]'), chalk.dim(' — Review progress, spaced repetition recommendations')));
77
+ console.log(cmd(chalk.cyan('/learn:status [topic-name]'), chalk.dim(' — Visualize learning state as knowledge map heatmap')));
78
+ console.log('');
79
+ }
80
+ async detectTools(resolvedPath) {
81
+ return AI_TOOLS;
82
+ }
83
+ hasToolDir(resolvedPath, tool) {
84
+ if (!tool.skillsDir)
85
+ return false;
86
+ const dirPath = path.join(resolvedPath, tool.skillsDir);
87
+ try {
88
+ return fs.statSync(dirPath).isDirectory();
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ }
94
+ async interactiveSelect(tools) {
95
+ const availableTools = tools.filter((t) => t.available && t.skillsDir);
96
+ const { search, checkbox } = await import('@inquirer/prompts');
97
+ // Auto-detect existing tool dirs and pre-select them
98
+ const detected = availableTools.filter((t) => this.hasToolDir(process.cwd(), t));
99
+ const detectedValues = new Set(detected.map((t) => t.value));
100
+ const choices = availableTools.map((t) => ({
101
+ name: t.name,
102
+ value: t.value,
103
+ checked: detectedValues.has(t.value),
104
+ }));
105
+ const selected = await checkbox({
106
+ message: getMessages(this.locale).init.interactiveSelectPrompt,
107
+ choices,
108
+ pageSize: 15,
109
+ });
110
+ return availableTools.filter((t) => selected.includes(t.value));
111
+ }
112
+ async generateSkillsForTool(resolvedPath, tool) {
113
+ const skillTemplates = getSkillTemplates();
114
+ for (const entry of skillTemplates) {
115
+ const skillDir = path.join(resolvedPath, tool.skillsDir, 'skills', entry.dirName);
116
+ const skillFile = path.join(skillDir, 'SKILL.md');
117
+ const content = generateSkillContent(entry.template, VERSION);
118
+ await FileSystemUtils.writeFile(skillFile, content);
119
+ }
120
+ }
121
+ async generateCommandsForTool(resolvedPath, tool) {
122
+ const adapter = CommandAdapterRegistry.get(tool.value);
123
+ if (!adapter)
124
+ return;
125
+ const commandContents = getCommandContents();
126
+ const generatedCommands = generateCommands(commandContents, adapter);
127
+ for (const cmd of generatedCommands) {
128
+ const filePath = path.resolve(resolvedPath, cmd.path);
129
+ await FileSystemUtils.writeFile(filePath, cmd.fileContent);
130
+ }
131
+ }
132
+ }
133
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1,3 @@
1
+ export { getSkillTemplates, getCommandTemplates, getCommandContents, generateSkillContent, } from './skill-generation.js';
2
+ export type { SkillTemplateEntry, CommandTemplateEntry } from './skill-generation.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { getSkillTemplates, getCommandTemplates, getCommandContents, generateSkillContent, } from './skill-generation.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,16 @@
1
+ import { getLearnTopicCommandTemplate, type SkillTemplate } from '../templates/skill-templates.js';
2
+ import type { CommandContent } from '../command-generation/index.js';
3
+ export interface SkillTemplateEntry {
4
+ template: SkillTemplate;
5
+ dirName: string;
6
+ workflowId: string;
7
+ }
8
+ export interface CommandTemplateEntry {
9
+ template: ReturnType<typeof getLearnTopicCommandTemplate>;
10
+ id: string;
11
+ }
12
+ export declare function getSkillTemplates(): SkillTemplateEntry[];
13
+ export declare function getCommandTemplates(): CommandTemplateEntry[];
14
+ export declare function getCommandContents(): CommandContent[];
15
+ export declare function generateSkillContent(template: SkillTemplate, generatedByVersion: string, transformInstructions?: (instructions: string) => string): string;
16
+ //# sourceMappingURL=skill-generation.d.ts.map
@@ -0,0 +1,49 @@
1
+ import { getLearnTopicSkillTemplate, getLearnExplainSkillTemplate, getLearnPracticeSkillTemplate, getLearnReviewSkillTemplate, getLearnStatusSkillTemplate, getLearnTopicCommandTemplate, getLearnExplainCommandTemplate, getLearnPracticeCommandTemplate, getLearnReviewCommandTemplate, getLearnStatusCommandTemplate, } from '../templates/skill-templates.js';
2
+ export function getSkillTemplates() {
3
+ return [
4
+ { template: getLearnTopicSkillTemplate(), dirName: 'learn-anything-topic', workflowId: 'topic' },
5
+ { template: getLearnExplainSkillTemplate(), dirName: 'learn-anything-explain', workflowId: 'explain' },
6
+ { template: getLearnPracticeSkillTemplate(), dirName: 'learn-anything-practice', workflowId: 'practice' },
7
+ { template: getLearnReviewSkillTemplate(), dirName: 'learn-anything-review', workflowId: 'review' },
8
+ { template: getLearnStatusSkillTemplate(), dirName: 'learn-anything-status', workflowId: 'status' },
9
+ ];
10
+ }
11
+ export function getCommandTemplates() {
12
+ return [
13
+ { template: getLearnTopicCommandTemplate(), id: 'topic' },
14
+ { template: getLearnExplainCommandTemplate(), id: 'explain' },
15
+ { template: getLearnPracticeCommandTemplate(), id: 'practice' },
16
+ { template: getLearnReviewCommandTemplate(), id: 'review' },
17
+ { template: getLearnStatusCommandTemplate(), id: 'status' },
18
+ ];
19
+ }
20
+ export function getCommandContents() {
21
+ const commandTemplates = getCommandTemplates();
22
+ return commandTemplates.map(({ template, id }) => ({
23
+ id,
24
+ name: template.name,
25
+ description: template.description,
26
+ category: template.category,
27
+ tags: template.tags,
28
+ body: template.content,
29
+ }));
30
+ }
31
+ export function generateSkillContent(template, generatedByVersion, transformInstructions) {
32
+ const instructions = transformInstructions
33
+ ? transformInstructions(template.instructions)
34
+ : template.instructions;
35
+ return `---
36
+ name: ${template.name}
37
+ description: ${template.description}
38
+ license: ${template.license || 'MIT'}
39
+ compatibility: ${template.compatibility || 'Requires learn-anything CLI.'}
40
+ metadata:
41
+ author: ${template.metadata?.author || 'learn-anything'}
42
+ version: "${template.metadata?.version || '1.0'}"
43
+ generatedBy: "${generatedByVersion}"
44
+ ---
45
+
46
+ ${instructions}
47
+ `;
48
+ }
49
+ //# sourceMappingURL=skill-generation.js.map
@@ -0,0 +1,7 @@
1
+ export type { SkillTemplate, CommandTemplate } from './types.js';
2
+ export { getLearnTopicSkillTemplate, getLearnTopicCommandTemplate } from './workflows/learn-topic.js';
3
+ export { getLearnExplainSkillTemplate, getLearnExplainCommandTemplate } from './workflows/learn-explain.js';
4
+ export { getLearnPracticeSkillTemplate, getLearnPracticeCommandTemplate } from './workflows/learn-practice.js';
5
+ export { getLearnReviewSkillTemplate, getLearnReviewCommandTemplate } from './workflows/learn-review.js';
6
+ export { getLearnStatusSkillTemplate, getLearnStatusCommandTemplate } from './workflows/learn-status.js';
7
+ //# sourceMappingURL=skill-templates.d.ts.map
@@ -0,0 +1,6 @@
1
+ export { getLearnTopicSkillTemplate, getLearnTopicCommandTemplate } from './workflows/learn-topic.js';
2
+ export { getLearnExplainSkillTemplate, getLearnExplainCommandTemplate } from './workflows/learn-explain.js';
3
+ export { getLearnPracticeSkillTemplate, getLearnPracticeCommandTemplate } from './workflows/learn-practice.js';
4
+ export { getLearnReviewSkillTemplate, getLearnReviewCommandTemplate } from './workflows/learn-review.js';
5
+ export { getLearnStatusSkillTemplate, getLearnStatusCommandTemplate } from './workflows/learn-status.js';
6
+ //# sourceMappingURL=skill-templates.js.map
@@ -0,0 +1,16 @@
1
+ export interface SkillTemplate {
2
+ name: string;
3
+ description: string;
4
+ instructions: string;
5
+ license?: string;
6
+ compatibility?: string;
7
+ metadata?: Record<string, string>;
8
+ }
9
+ export interface CommandTemplate {
10
+ name: string;
11
+ description: string;
12
+ category: string;
13
+ tags: string[];
14
+ content: string;
15
+ }
16
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,4 @@
1
+ import type { SkillTemplate, CommandTemplate } from '../types.js';
2
+ export declare function getLearnExplainSkillTemplate(): SkillTemplate;
3
+ export declare function getLearnExplainCommandTemplate(): CommandTemplate;
4
+ //# sourceMappingURL=learn-explain.d.ts.map
@@ -0,0 +1,203 @@
1
+ const SKILL_NAME = 'learn-anything-explain';
2
+ const SKILL_DESCRIPTION = 'Recursively deep-dive into a concept. AI explains, identifies deeper sub-topics, and lets you choose your own depth direction.';
3
+ const INSTRUCTIONS = `Always respond in the same language the user uses.
4
+ If the user speaks Chinese, explain all concepts, examples, and guidance in Chinese.
5
+
6
+ ---
7
+
8
+ You are Learn Anything's Explanation Mentor. You excel at explaining complex concepts in simple, clear language.
9
+ Your explanations follow the "Recursive Learning Method": first establish a foundation of understanding, then identify deeper sub-topics, letting the user choose whether to go deeper.
10
+
11
+ ## Your Teaching Philosophy
12
+
13
+ 1. **Understanding over Information** — Explaining one concept thoroughly matters more than covering ten superficially
14
+ 2. **Analogies Build Intuition** — Every abstract concept should have a real-world analogy
15
+ 3. **Socratic Guidance, Not Interrogation** — Questions help users discover answers themselves, not test them
16
+ 4. **Know When to Stop** — When the user signals understanding, offer depth options without pushing
17
+ 5. **Connect to the Knowledge Map** — Always show where the current concept fits in the broader knowledge system
18
+
19
+ ---
20
+
21
+ ## Command: /learn-explain <concept-name>
22
+
23
+ ### Step 1: Load Context
24
+
25
+ 1. **Match topic**: Infer the parent topic from the concept name.
26
+ - Look at all directories under \`./.learn/topics/\`
27
+ - If there's only one topic, use it directly
28
+ - If there are multiple topics, search knowledge maps for the concept name
29
+ - If no matching topic is found, ask the user "Which topic would you like to learn this concept under? Available topics: [list]"
30
+
31
+ 2. **Read knowledge map**: Use the Read tool to read \`./.learn/topics/<topic-name>/knowledge-map.md\`, locating the concept's position in the knowledge tree.
32
+
33
+ 3. **Read learning state**: Use the Read tool to read \`./.learn/topics/<topic-name>/state.yaml\`, finding the concept's current status.
34
+
35
+ ### Step 2: Assess User Level
36
+
37
+ Synthesize these signals to judge whether the user is beginner, intermediate, or advanced:
38
+
39
+ **Beginner signals:**
40
+ - Short, vague questions (e.g., "What is a closure?")
41
+ - Uses general descriptors ("I don't really get it", "completely lost")
42
+ - Concept status is \`unexplored\`
43
+ - Related concept confidence in state.yaml < 0.3
44
+
45
+ **Intermediate signals:**
46
+ - Uses some technical terms, though not always precise
47
+ - Questions are targeted ("How do closures cause memory leaks?")
48
+ - Concept status is \`in_progress\`
49
+ - Related concept confidence in state.yaml 0.3-0.7
50
+
51
+ **Advanced signals:**
52
+ - Uses precise technical terminology
53
+ - Questions go deep ("How does V8 optimize scope chain lookups for closures?")
54
+ - Concept status is \`mastered\` but seeking deeper discussion
55
+ - Related concept confidence in state.yaml > 0.7
56
+
57
+ **Level-adaptive strategy:**
58
+ - Beginners: Explanation-heavy (70% explanation + 30% guided questions), heavy use of analogies
59
+ - Intermediate: Balanced (50% explanation + 50% guidance), encourage self-derivation
60
+ - Advanced: Guidance and challenge-heavy (30% supplement + 70% deep discussion), quickly skip basics
61
+
62
+ ### Step 3: Explain the Concept
63
+
64
+ **Explanation structure (for beginner/intermediate):**
65
+
66
+ 1. **Positioning** — Where is this concept in the knowledge map? (One sentence)
67
+ > "Closures sit in the **Functions → Scope & Closures** branch of the JavaScript knowledge tree. To understand closures, you first need to know what scope is."
68
+
69
+ 2. **Analogy** — Build intuition with a real-world metaphor
70
+ > "Think of a function as a backpack. Every time you create a function, it packs up all the variables visible around it at that moment..."
71
+
72
+ 3. **Core Mechanism** — Explain "what" and "why" in clear language
73
+ > "A closure is the combination of a function and its lexical environment. When a function 'remembers' the scope it was created in..."
74
+
75
+ 4. **Code Example** — A minimal but complete example
76
+ > \`\`\`javascript
77
+ > function createCounter() {
78
+ > let count = 0;
79
+ > return function() { count++; return count; };
80
+ > }
81
+ > const counter = createCounter();
82
+ > counter(); // 1
83
+ > counter(); // 2 — it "remembers" count
84
+ > \`\`\`
85
+
86
+ 5. **Common Misconceptions** — Point out the most common beginner mistakes
87
+ > "Many people think a closure is just a function defined inside another function. The key is actually 'capturing external variables'..."
88
+
89
+ 6. **Socratic Check** — Use 1-2 natural questions to confirm understanding (NOT a quiz!)
90
+ > "If I create 5 closures inside a loop using var versus let, what would be different? Take a guess?"
91
+
92
+ Note: This is a thinking-guiding question, tone should be curious and exploratory, not exam-like. If the user is unsure, give the answer immediately — don't wait.
93
+
94
+ ### Step 4: Identify Sub-topics (Recursive Entry Points)
95
+
96
+ After the explanation, identify deeper sub-topics under this concept. These aren't a bullet list of facts — they flow naturally into the closing:
97
+
98
+ > Now you understand the basics of closures. If you'd like to go deeper, we can explore:
99
+ >
100
+ > 🔍 **Classic Closure Patterns**
101
+ > - Module Pattern — Using closures for private variables
102
+ > - Currying — One of the most elegant uses of closures
103
+ > - Debounce & Throttle — Closures in real-world frontend
104
+ >
105
+ > 🔍 **Closure Performance**
106
+ > - Memory leaks — When do closures cause problems?
107
+ > - V8 hidden classes and closure optimization
108
+ >
109
+ > Which direction interests you? Or would you rather do some practice exercises to solidify?
110
+
111
+ **Sub-topic identification rules:**
112
+ - Sub-topics should be organic extensions, not random tangents
113
+ - List 2-4 sub-directions, each with 1-2 sentences explaining why it's worth learning
114
+ - Always offer the "practice" option alongside
115
+ - For advanced users, sub-topics should be deeper
116
+ - For beginners, sub-topics should lean practical and applied
117
+ - **Never rush**, let the user decide their next step
118
+
119
+ ### Step 5: Record Learning Session
120
+
121
+ After each explanation, append a session record to \`./.learn/topics/<topic-name>/sessions/YYYY-MM-DD.md\`:
122
+
123
+ \`\`\`markdown
124
+ # Learning Session - <date>
125
+
126
+ ## Content
127
+ - Concept: [concept name]
128
+ - Path: [path in knowledge map, e.g., "Functions/Closures"]
129
+ - Depth: beginner/intermediate/advanced explanation
130
+
131
+ ## Key Points Covered
132
+ - [point 1]
133
+ - [point 2]
134
+
135
+ ## Sub-topics Explored by User
136
+ (If the user chose to go deeper, record which direction)
137
+
138
+ ## Follow-ups
139
+ (If the user expressed confusion that wasn't fully resolved, record it here)
140
+ \`\`\`
141
+
142
+ **Also update state.yaml:**
143
+ - If concept status is \`unexplored\`, update to \`in_progress\`
144
+ - Update \`last_session\` to current date
145
+ - If the user showed good understanding (asked questions, answered correctly), slightly increase \`confidence\` (+0.05 to +0.1)
146
+
147
+ ---
148
+
149
+ ## Edge Cases
150
+
151
+ - **Concept name mismatch**: Fuzzy search the concept name in the knowledge map.
152
+ E.g., user enters "closure principles", matches to "Functions/Closures". "Did you mean **Closures** (under the Functions branch)?"
153
+
154
+ - **Multiple matches**: List all matching concepts for the user to choose.
155
+ "I found several possible matches in the knowledge map:
156
+ 1. Functions/Closures — A function combined with its lexical environment
157
+ 2. Rust/Ownership & Borrowing — Ownership rules similar to closures
158
+ Which would you like to learn?"
159
+
160
+ - **Concept not in knowledge map**:
161
+ "'Micro-frontends' isn't in the current JavaScript knowledge map. This might be a more advanced or cross-domain concept.
162
+ I can:
163
+ - Add this concept to the JavaScript knowledge map
164
+ - Or create a separate 'Micro-frontends' learning topic
165
+ Which do you prefer?"
166
+
167
+ - **Topic doesn't exist**: Prompt user to create a topic first with \`/learn <topic-name>\`.
168
+ "You haven't created a related topic yet. Run \`/learn <topic-name>\` first to start learning!"
169
+
170
+ - **User is clearly a beginner**: Adjust explanation style:
171
+ - More analogies, fewer technical terms
172
+ - More comprehension checks ("Does that make sense?")
173
+ - Prioritize "why we need this concept" over "how it works internally"
174
+ - Provide simpler code examples`;
175
+ const COMMAND_NAME = 'Learn: Explain';
176
+ const COMMAND_DESCRIPTION = 'Recursively deep-dive into a concept — AI explains, guides thinking, you choose the depth';
177
+ const COMMAND_CONTENT = `Use the learn-anything-explain skill to handle the user's /learn-explain <concept-name> request.
178
+ Follow the workflow defined in the skill:
179
+ 1. Load context: match topic → read knowledge map → read learning state
180
+ 2. Assess user level (beginner/intermediate/advanced) and adjust teaching strategy
181
+ 3. Follow the explanation structure: positioning → analogy → core mechanism → code example → common misconceptions → Socratic check
182
+ 4. Identify sub-topics as recursive entry points
183
+ 5. Record learning session and update state.yaml`;
184
+ export function getLearnExplainSkillTemplate() {
185
+ return {
186
+ name: SKILL_NAME,
187
+ description: SKILL_DESCRIPTION,
188
+ instructions: INSTRUCTIONS,
189
+ license: 'MIT',
190
+ compatibility: 'Requires learn-anything CLI.',
191
+ metadata: { author: 'learn-anything', version: '1.0' },
192
+ };
193
+ }
194
+ export function getLearnExplainCommandTemplate() {
195
+ return {
196
+ name: COMMAND_NAME,
197
+ description: COMMAND_DESCRIPTION,
198
+ category: 'Learning',
199
+ tags: ['learning', 'explain', 'socratic', 'recursive'],
200
+ content: COMMAND_CONTENT,
201
+ };
202
+ }
203
+ //# sourceMappingURL=learn-explain.js.map
@@ -0,0 +1,4 @@
1
+ import type { SkillTemplate, CommandTemplate } from '../types.js';
2
+ export declare function getLearnPracticeSkillTemplate(): SkillTemplate;
3
+ export declare function getLearnPracticeCommandTemplate(): CommandTemplate;
4
+ //# sourceMappingURL=learn-practice.d.ts.map