learn-anything-cli 0.4.0-beta.1 → 0.4.1

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/README.md CHANGED
@@ -23,6 +23,12 @@ npm install -g learn-anything-cli
23
23
  learn-anything init
24
24
  ```
25
25
 
26
+ ### Context7 Integration (Optional)
27
+
28
+ When running `init` or `update`, you'll be prompted to enable **Context7** for documentation verification. When enabled, the AI will fetch official documentation and verify its explanations against authoritative sources — improving teaching accuracy.
29
+
30
+ If you haven't set up Context7 yet, run `npx ctx7 setup` or visit the [Context7 docs](https://context7.com/docs/resources/all-clients) for your specific AI tool.
31
+
26
32
  After init, your AI assistant gains five learning commands:
27
33
 
28
34
  | Command | What it does |
@@ -37,7 +43,7 @@ After init, your AI assistant gains five learning commands:
37
43
 
38
44
  ### `/learn:topic <topic-name>` — Initialize a Topic
39
45
 
40
- The AI generates a hierarchical knowledge map (`.learn/topics/<topic>/knowledge-map.md`), creates a learning state tracker (`state.yaml`), and presents the landscape for you to choose your own path.
46
+ The AI creates a learning state file (`state.json`) and generates a knowledge map (`knowledge-map.md`) via `render.mjs`, then presents the landscape for you to choose your own path.
41
47
 
42
48
  ### `/learn:explain <concept-name>` — Recursive Deep Dive
43
49
 
@@ -75,8 +81,8 @@ Your Project/
75
81
  ├── .learn/ # Your learning data (knowledge maps, progress)
76
82
  │ └── topics/
77
83
  │ └── javascript/
78
- │ ├── knowledge-map.md
79
- │ ├── state.yaml
84
+ │ ├── state.json # Learning data (single source of truth)
85
+ │ ├── knowledge-map.md # Auto-generated by render.mjs from state.json
80
86
  │ └── sessions/
81
87
  └── ...
82
88
  ```
package/README.zh-CN.md CHANGED
@@ -21,6 +21,12 @@ npm install -g learn-anything-cli
21
21
  learn-anything init
22
22
  ```
23
23
 
24
+ ### Context7 集成(可选)
25
+
26
+ 在执行 `init` 或 `update` 时,会提示是否启用 **Context7** 文档验证。启用后,AI 会获取官方文档并对照权威来源验证其教学内容——提高教学准确性。
27
+
28
+ 如果你还没有配置 Context7,运行 `npx ctx7 setup` 或访问 [Context7 文档](https://context7.com/docs/resources/all-clients) 查看你使用的 AI 工具的配置方式。
29
+
24
30
  初始化后,你的 AI 助手获得五个学习命令:
25
31
 
26
32
  | 命令 | 功能 |
@@ -35,7 +41,7 @@ learn-anything init
35
41
 
36
42
  ### `/learn:topic <topic-name>` — 初始化主题
37
43
 
38
- AI 生成层次化知识图谱(`.learn/topics/<topic>/knowledge-map.md`),创建学习状态跟踪文件(`state.yaml`),展示知识全景让你自主选择学习路径。
44
+ AI 创建学习状态文件(`state.json`),并通过 `render.mjs` 生成知识图谱(`knowledge-map.md`),展示知识全景让你自主选择学习路径。
39
45
 
40
46
  ### `/learn:explain <concept-name>` — 递归式深度学习
41
47
 
@@ -73,8 +79,8 @@ npx learn-anything-cli update
73
79
  ├── .learn/ # 你的学习数据(知识图谱、进度)
74
80
  │ └── topics/
75
81
  │ └── javascript/
76
- │ ├── knowledge-map.md
77
- │ ├── state.yaml
82
+ │ ├── state.json # 学习数据(唯一数据源)
83
+ │ ├── knowledge-map.md # 由 render.mjs 从 state.json 自动生成
78
84
  │ └── sessions/
79
85
  └── ...
80
86
  ```
package/dist/cli/index.js CHANGED
@@ -24,6 +24,8 @@ program
24
24
  .option('--tools <tools>', m.cli.toolsOptionDescription(availableToolIds.join(', ')))
25
25
  .option('--force', m.cli.forceOption)
26
26
  .option('--lang <locale>', m.cli.langOption)
27
+ .option('--context7', 'Enable Context7 documentation verification')
28
+ .option('--no-context7', 'Disable Context7 documentation verification')
27
29
  .action(async (targetPath = '.', options) => {
28
30
  const cliLocale = resolveLocale(options?.lang);
29
31
  const mc = cliLocale !== earlyLocale ? getMessages(cliLocale).cli : m.cli;
@@ -51,6 +53,7 @@ program
51
53
  tools: options?.tools,
52
54
  force: options?.force,
53
55
  locale: cliLocale,
56
+ context7: options?.context7,
54
57
  });
55
58
  await initCommand.execute(targetPath);
56
59
  }
@@ -4,14 +4,18 @@ type InitCommandOptions = {
4
4
  force?: boolean;
5
5
  locale?: SupportedLocale;
6
6
  update?: boolean;
7
+ context7?: boolean;
7
8
  };
8
9
  export declare class InitCommand {
9
10
  private readonly toolsArg?;
10
11
  private readonly force;
11
12
  private readonly locale;
12
13
  private readonly isUpdate;
14
+ private readonly context7Arg?;
15
+ private context7Enabled;
13
16
  constructor(options?: InitCommandOptions);
14
17
  execute(targetPath?: string): Promise<void>;
18
+ private promptContext7;
15
19
  private detectTools;
16
20
  private hasToolDir;
17
21
  private interactiveSelect;
package/dist/core/init.js CHANGED
@@ -9,6 +9,7 @@ import { isInteractive } from '../utils/interactive.js';
9
9
  import { generateCommands, CommandAdapterRegistry } from './command-generation/index.js';
10
10
  import { getSkillTemplates, getCommandContents, generateSkillContent } from './shared/index.js';
11
11
  import { getMessages } from '../i18n/index.js';
12
+ import { CONTEXT7_GUIDANCE } from './templates/context7-guidance.js';
12
13
  const require = createRequire(import.meta.url);
13
14
  const { version: VERSION } = require('../../package.json');
14
15
  export class InitCommand {
@@ -16,11 +17,14 @@ export class InitCommand {
16
17
  force;
17
18
  locale;
18
19
  isUpdate;
20
+ context7Arg;
21
+ context7Enabled = false;
19
22
  constructor(options = {}) {
20
23
  this.toolsArg = options.tools;
21
24
  this.force = options.force ?? false;
22
25
  this.locale = options.locale ?? 'en';
23
26
  this.isUpdate = options.update ?? false;
27
+ this.context7Arg = options.context7;
24
28
  }
25
29
  async execute(targetPath = '.') {
26
30
  const resolvedPath = path.resolve(targetPath);
@@ -67,6 +71,12 @@ export class InitCommand {
67
71
  .join(', '))));
68
72
  return;
69
73
  }
74
+ // Context7 setup
75
+ this.context7Enabled = await this.promptContext7();
76
+ if (this.context7Enabled) {
77
+ console.log(chalk.dim(m.init.context7Enabled));
78
+ }
79
+ console.log('');
70
80
  // Generate skill files for each tool
71
81
  for (const tool of selectedTools) {
72
82
  if (!tool.skillsDir)
@@ -87,6 +97,21 @@ export class InitCommand {
87
97
  console.log(cmd(chalk.cyan('/learn:review [topic-name]'), chalk.dim(' — Review progress, spaced repetition recommendations')));
88
98
  console.log(cmd(chalk.cyan('/learn:status [topic-name]'), chalk.dim(' — Visualize learning state as knowledge map heatmap')));
89
99
  console.log('');
100
+ if (this.context7Enabled) {
101
+ console.log(chalk.dim(m.init.context7SetupHint));
102
+ console.log('');
103
+ }
104
+ }
105
+ async promptContext7() {
106
+ const m = getMessages(this.locale);
107
+ if (this.context7Arg === true)
108
+ return true;
109
+ if (this.context7Arg === false)
110
+ return false;
111
+ if (!isInteractive())
112
+ return true;
113
+ const { confirm } = await import('@inquirer/prompts');
114
+ return confirm({ message: m.init.context7Prompt, default: true });
90
115
  }
91
116
  async detectTools(_resolvedPath) {
92
117
  return AI_TOOLS;
@@ -125,7 +150,9 @@ export class InitCommand {
125
150
  for (const entry of skillTemplates) {
126
151
  const skillDir = path.join(resolvedPath, tool.skillsDir, 'skills', entry.dirName);
127
152
  const skillFile = path.join(skillDir, 'SKILL.md');
128
- const content = generateSkillContent(entry.template, VERSION);
153
+ const content = generateSkillContent(entry.template, VERSION, this.context7Enabled && isDocVerificationTemplate(entry.workflowId)
154
+ ? injectContext7Guidance
155
+ : undefined);
129
156
  await FileSystemUtils.writeFile(skillFile, content);
130
157
  const scriptsDir = path.join(skillDir, 'scripts');
131
158
  // topic / explain / practice → utils.mjs + render.mjs
@@ -135,6 +162,10 @@ export class InitCommand {
135
162
  await FileSystemUtils.writeFile(path.join(scriptsDir, 'utils.mjs'), this.readCompiledScript('utils.mjs'));
136
163
  await FileSystemUtils.writeFile(path.join(scriptsDir, 'render.mjs'), this.readCompiledScript('render.mjs'));
137
164
  }
165
+ // topic -> init-sessions.mjs
166
+ if (entry.dirName === 'learn-anything-topic') {
167
+ await FileSystemUtils.writeFile(path.join(scriptsDir, 'init-sessions.mjs'), this.readCompiledScript('init-sessions.mjs'));
168
+ }
138
169
  // status → utils.mjs + status.mjs
139
170
  if (entry.dirName === 'learn-anything-status') {
140
171
  await FileSystemUtils.writeFile(path.join(scriptsDir, 'utils.mjs'), this.readCompiledScript('utils.mjs'));
@@ -160,4 +191,15 @@ export class InitCommand {
160
191
  }
161
192
  }
162
193
  }
194
+ const DOC_VERIFICATION_WORKFLOWS = new Set(['topic', 'explain', 'practice']);
195
+ function isDocVerificationTemplate(workflowId) {
196
+ return DOC_VERIFICATION_WORKFLOWS.has(workflowId);
197
+ }
198
+ function injectContext7Guidance(instructions) {
199
+ const marker = '\n## Command:';
200
+ const index = instructions.indexOf(marker);
201
+ if (index === -1)
202
+ return instructions + CONTEXT7_GUIDANCE;
203
+ return instructions.slice(0, index) + CONTEXT7_GUIDANCE + instructions.slice(index);
204
+ }
163
205
  //# sourceMappingURL=init.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Context7 documentation verification guidance.
3
+ * Injected into topic/explain/practice skill templates when Context7 is enabled.
4
+ *
5
+ * Instructs the AI to use Context7 MCP tools at runtime:
6
+ * - resolve-library-id: resolves library name to Context7 ID
7
+ * - query-docs: fetches docs by library ID + query
8
+ *
9
+ * NOT injected into review/status templates (those are about progress review
10
+ * and visualization, not teaching content).
11
+ */
12
+ export declare const CONTEXT7_GUIDANCE = "\n## Documentation Verification (Context7)\n\nWhen teaching about a specific library or framework, verify your explanations against official documentation using Context7 MCP tools:\n\n1. **Resolve the library**: Call `resolve-library-id` with the library name (e.g., \"React\", \"TypeScript\")\n2. **Fetch relevant docs**: Call `query-docs` with the resolved library ID and the concept you are teaching as the query\n3. **Cross-reference**: Ensure your explanations, code examples, and API usage match the official documentation\n4. **Defer to docs**: If your explanation conflicts with official documentation, use the official documentation as the authoritative source\n\nIf Context7 MCP tools are not available in your environment, proceed with your built-in knowledge.\n";
13
+ //# sourceMappingURL=context7-guidance.d.ts.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Context7 documentation verification guidance.
3
+ * Injected into topic/explain/practice skill templates when Context7 is enabled.
4
+ *
5
+ * Instructs the AI to use Context7 MCP tools at runtime:
6
+ * - resolve-library-id: resolves library name to Context7 ID
7
+ * - query-docs: fetches docs by library ID + query
8
+ *
9
+ * NOT injected into review/status templates (those are about progress review
10
+ * and visualization, not teaching content).
11
+ */
12
+ export const CONTEXT7_GUIDANCE = `
13
+ ## Documentation Verification (Context7)
14
+
15
+ When teaching about a specific library or framework, verify your explanations against official documentation using Context7 MCP tools:
16
+
17
+ 1. **Resolve the library**: Call \`resolve-library-id\` with the library name (e.g., "React", "TypeScript")
18
+ 2. **Fetch relevant docs**: Call \`query-docs\` with the resolved library ID and the concept you are teaching as the query
19
+ 3. **Cross-reference**: Ensure your explanations, code examples, and API usage match the official documentation
20
+ 4. **Defer to docs**: If your explanation conflicts with official documentation, use the official documentation as the authoritative source
21
+
22
+ If Context7 MCP tools are not available in your environment, proceed with your built-in knowledge.
23
+ `;
24
+ //# sourceMappingURL=context7-guidance.js.map
@@ -51,17 +51,21 @@ Structure your explanation:
51
51
 
52
52
  **A) Determine the filename:**
53
53
 
54
- Use the concept name exactly as it appears in state.json, in the same language. Convert to kebab-case and append the date:
54
+ Use the concept name exactly as it appears in state.json, in the same language. Convert to kebab-case and append the date. Place the file in the subdirectory matching the domain's \`slug\` field from state.json:
55
55
 
56
- > \`./.learn/topics/<topic-name>/sessions/<concept-name-as-is>-YYYY-MM-DD.md\`
56
+ > \`./.learn/topics/<topic-name>/sessions/<domain-slug>/<concept-name-as-is>-YYYY-MM-DD.md\`
57
+
58
+ Where \`<domain-slug>\` is the \`slug\` field of the domain that contains this concept.
57
59
 
58
60
  Examples:
59
- - state.json has \`变量声明与数据类型\` → \`变量声明与数据类型-2026-05-24.md\`
60
- - state.json has \`Scope & Closures\` → \`Scope-Closures-2026-05-24.md\`
61
- - state.json has \`Event Loop\` → \`Event-Loop-2026-05-24.md\`
61
+ - concept \`变量声明与数据类型\` in domain with slug \`语言基础\` \`sessions/语言基础/变量声明与数据类型-2026-05-24.md\`
62
+ - concept \`Scope & Closures\` in domain with slug \`函数与作用域\` → \`sessions/函数与作用域/Scope-Closures-2026-05-24.md\`
63
+ - concept \`Event Loop\` in domain with slug \`async-programming\` → \`sessions/async-programming/Event-Loop-2026-05-24.md\`
62
64
 
63
65
  Match the language the user is learning in — don't force-translate.
64
66
 
67
+ ⚠️ If the domain subdirectory does not exist, create it first: \`mkdir -p ./.learn/topics/<topic-name>/sessions/<domain-slug>\`
68
+
65
69
  **B) Write the session file** containing: positioning, analogy, core mechanism, code example with walkthrough, misconceptions, Socratic check, and quick summary. The file should be self-contained — re-readable without the chat.
66
70
 
67
71
  Session file format:
@@ -153,7 +157,7 @@ Follow the workflow defined in the skill:
153
157
  1. Load context: match topic → read state.json (single source of truth, do NOT read knowledge-map.md)
154
158
  2. Assess user level (beginner/intermediate/advanced) and adjust teaching strategy
155
159
  3. Compose the full explanation: positioning → analogy → core mechanism → code example → common misconceptions → Socratic check
156
- 4. CRITICAL — Write the session file FIRST (./.learn/topics/<topic>/sessions/<concept-name>-YYYY-MM-DD.md, matching the user's language), then echo the file content verbatim to the conversation. Also update state.json with Edit (last_explained, explain_count, status, confidence). Then run render.mjs to regenerate knowledge-map.md.
160
+ 4. CRITICAL — Write the session file FIRST (./.learn/topics/<topic>/sessions/<domain-slug>/<concept-name>-YYYY-MM-DD.md, where <domain-slug> comes from state.json, matching the user's language), then echo the file content verbatim to the conversation. Also update state.json with Edit (last_explained, explain_count, status, confidence). Then run render.mjs to regenerate knowledge-map.md.
157
161
  5. Identify sub-topics as recursive entry points (only AFTER saving the session and echoing to conversation)`;
158
162
  export function getLearnExplainSkillTemplate() {
159
163
  return {
@@ -77,7 +77,7 @@ Based on your expert understanding of "<topic-name>", generate a hierarchical kn
77
77
  - **Slug format**: lowercase kebab-case ("Scope & Closures" → "scope-closures").
78
78
  - All initial concepts: status "unexplored", confidence 0, counts 0, dates null.
79
79
 
80
- ### Step 4: Run render.mjs to generate knowledge-map.md
80
+ ### Step 4: Run render.mjs and init-sessions.mjs
81
81
 
82
82
  \`\`\`bash
83
83
  SCRIPT=$(find . -path '*/learn-anything-topic/scripts/render.mjs' -print -quit 2>/dev/null)
@@ -86,6 +86,13 @@ node "$SCRIPT" ./.learn/topics/<topic-name>
86
86
 
87
87
  render.mjs validates state.json against the v1 schema and generates knowledge-map.md. If validation fails, fix state.json and re-run render.mjs. Do NOT manually write knowledge-map.md.
88
88
 
89
+ \`\`\`bash
90
+ SCRIPT=$(find . -path '*/learn-anything-topic/scripts/init-sessions.mjs' -print -quit 2>/dev/null)
91
+ node "$SCRIPT" ./.learn/topics/<topic-name>
92
+ \`\`\`
93
+
94
+ init-sessions.mjs reads state.json and creates domain subdirectories under \`sessions/\` (based on each domain's \`slug\`). This organizes future learning session files by domain. Safe to re-run — existing directories are skipped.
95
+
89
96
  ### Step 5: Present the knowledge map
90
97
 
91
98
  Display the knowledge map as an ASCII tree:
@@ -124,6 +131,15 @@ Then guide the user:
124
131
 
125
132
  Read \`./.learn/topics/<topic-name>/state.json\` — state.json is the single source of truth, do NOT read knowledge-map.md or state.yaml.
126
133
 
134
+ ### Step 2.5: Run init-sessions.mjs to ensure domain directories exist
135
+
136
+ \`\`\`bash
137
+ SCRIPT=$(find . -path '*/learn-anything-topic/scripts/init-sessions.mjs' -print -quit 2>/dev/null)
138
+ node "$SCRIPT" ./.learn/topics/<topic-name>
139
+ \`\`\`
140
+
141
+ This ensures domain subdirectories under \`sessions/\` are created (in case they were not created before or new domains were added). Safe to re-run.
142
+
127
143
  ### Step 3: Calculate and display progress
128
144
 
129
145
  From the domains/concepts structure, calculate: 🟢 mastered, 🔵 in progress, 🟠 needs practice, ⚪ unexplored.
@@ -158,8 +174,8 @@ const COMMAND_DESCRIPTION = 'Initialize or load a learning topic — view knowle
158
174
  const COMMAND_CONTENT = `Use the learn-anything-topic skill to handle the user's /learn <topic-name> request.
159
175
  Follow the workflow defined in the skill:
160
176
  1. Determine if the topic exists
161
- 2. New topic: create directory structure → generate state.json (v1 with domains/concepts hierarchy) → run render.mjs to generate knowledge-map.md → present knowledge map and guide the user
162
- 3. Existing topic: read state.json → calculate progress → give personalized recommendations`;
177
+ 2. New topic: create directory structure → generate state.json (v1 with domains/concepts hierarchy) → run render.mjs run init-sessions.mjs → present knowledge map and guide the user
178
+ 3. Existing topic: read state.json → run init-sessions.mjs → calculate progress → give personalized recommendations`;
163
179
  export function getLearnTopicSkillTemplate() {
164
180
  return {
165
181
  name: SKILL_NAME,
@@ -24,6 +24,9 @@ export const en = {
24
24
  cmdLine: (cmd, desc) => ` ${cmd}${desc}`,
25
25
  interactiveSelectPrompt: 'Select AI tools to generate skills for (space to select, enter to confirm):',
26
26
  migrationComplete: (count) => `Migrated ${count} topic(s) from v0 to v1 format (backups created).`,
27
+ context7Prompt: 'Enable Context7 for documentation verification? (Provides on-demand access to official library docs)',
28
+ context7Enabled: ' 📚 Context7 guidance enabled.',
29
+ context7SetupHint: ' 💡 To set up Context7 MCP, run `npx ctx7 setup` or visit https://context7.com/docs/resources/all-clients',
27
30
  },
28
31
  };
29
32
  //# sourceMappingURL=en.js.map
@@ -24,6 +24,9 @@ export const zhCN = {
24
24
  cmdLine: (cmd, desc) => ` ${cmd}${desc}`,
25
25
  interactiveSelectPrompt: '选择要生成技能的 AI 工具(空格选择,回车确认):',
26
26
  migrationComplete: (count) => `已迁移 ${count} 个主题从 v0 到 v1 格式(已创建备份)。`,
27
+ context7Prompt: '是否启用 Context7 进行文档验证?(提供按需访问官方库文档的能力)',
28
+ context7Enabled: ' 📚 已启用 Context7 文档验证引导。',
29
+ context7SetupHint: ' 💡 配置 Context7 MCP:运行 `npx ctx7 setup` 或访问 https://context7.com/docs/resources/all-clients',
27
30
  },
28
31
  };
29
32
  //# sourceMappingURL=zh-CN.js.map
@@ -24,6 +24,9 @@ export interface InitMessages {
24
24
  cmdLine: (cmd: string, desc: string) => string;
25
25
  interactiveSelectPrompt: string;
26
26
  migrationComplete: (count: number) => string;
27
+ context7Prompt: string;
28
+ context7Enabled: string;
29
+ context7SetupHint: string;
27
30
  }
28
31
  export interface LocaleMessages {
29
32
  cli: CLIMessages;
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * init-sessions.mjs — standalone script
4
+ * Reads state.json (v1) and creates domain subdirectories under sessions/.
5
+ *
6
+ * Usage: node init-sessions.mjs <topic-dir>
7
+ *
8
+ * This file is compiled from src/scripts/init-sessions.mts via tsc and
9
+ * copied into each skill's scripts/ directory by init/update.
10
+ */
11
+ import type { StateV1 } from './utils.mjs';
12
+ export declare function initSessions(topicDir: string, state: StateV1): number;
13
+ //# sourceMappingURL=init-sessions.d.mts.map
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * init-sessions.mjs — standalone script
4
+ * Reads state.json (v1) and creates domain subdirectories under sessions/.
5
+ *
6
+ * Usage: node init-sessions.mjs <topic-dir>
7
+ *
8
+ * This file is compiled from src/scripts/init-sessions.mts via tsc and
9
+ * copied into each skill's scripts/ directory by init/update.
10
+ */
11
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
12
+ import { join, resolve } from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+ import { validateStateV1 } from './utils.mjs';
15
+ /* ------------------------------------------------------------------ */
16
+ /* Init Sessions */
17
+ /* ------------------------------------------------------------------ */
18
+ export function initSessions(topicDir, state) {
19
+ const sessionsDir = join(topicDir, 'sessions');
20
+ // Ensure the top-level sessions/ directory exists
21
+ if (!existsSync(sessionsDir)) {
22
+ mkdirSync(sessionsDir, { recursive: true });
23
+ }
24
+ let created = 0;
25
+ for (const domain of state.domains) {
26
+ const domainDir = join(sessionsDir, domain.slug);
27
+ if (!existsSync(domainDir)) {
28
+ mkdirSync(domainDir, { recursive: true });
29
+ created++;
30
+ }
31
+ }
32
+ return created;
33
+ }
34
+ /* ------------------------------------------------------------------ */
35
+ /* CLI */
36
+ /* ------------------------------------------------------------------ */
37
+ function usage() {
38
+ const script = process.argv[1]?.split('/').pop() || 'init-sessions.mjs';
39
+ console.error(`Usage: node ${script} <topic-dir>`);
40
+ process.exit(1);
41
+ }
42
+ function main() {
43
+ const args = process.argv.slice(2);
44
+ if (args.length === 0) {
45
+ usage();
46
+ }
47
+ const topicDir = resolve(args[0]);
48
+ const statePath = join(topicDir, 'state.json');
49
+ // 1. Read state.json
50
+ let raw;
51
+ try {
52
+ raw = readFileSync(statePath, 'utf-8');
53
+ }
54
+ catch (error) {
55
+ console.error(`Error: state.json not found at ${statePath}`, error);
56
+ process.exit(1);
57
+ }
58
+ // 2. Parse JSON
59
+ let data;
60
+ try {
61
+ data = JSON.parse(raw);
62
+ }
63
+ catch (err) {
64
+ const msg = err instanceof Error ? err.message : String(err);
65
+ console.error(`Error: Failed to parse state.json: ${msg}`);
66
+ process.exit(1);
67
+ }
68
+ // 3. Validate v1 format
69
+ const errors = validateStateV1(data);
70
+ if (errors.length > 0) {
71
+ console.error('Error: state.json validation failed:');
72
+ for (const e of errors) {
73
+ console.error(` .${e.path}: ${e.message}`);
74
+ }
75
+ console.error('Fix the above issues in state.json and re-run init-sessions.mjs.');
76
+ process.exit(1);
77
+ }
78
+ const state = data;
79
+ // 4. Create domain subdirectories
80
+ const created = initSessions(topicDir, state);
81
+ // Summary to stdout
82
+ console.log(`Initialized ${state.domains.length} domain directories under sessions/ (${created} new) for "${state.topic}"`);
83
+ }
84
+ const isMain = process.argv[1] != null &&
85
+ fileURLToPath(import.meta.url) === resolve(process.argv[1]);
86
+ if (isMain) {
87
+ main();
88
+ }
89
+ //# sourceMappingURL=init-sessions.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "learn-anything-cli",
3
- "version": "0.4.0-beta.1",
3
+ "version": "0.4.1",
4
4
  "description": "AI-powered recursive learning system with Socratic method and TDD practice",
5
5
  "keywords": [
6
6
  "learn-anything-cli",