@rookiestar/eng-lang-tutor 1.2.4 → 1.2.5
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 +15 -0
- package/package.json +8 -6
- package/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/__pycache__/audio_composer.cpython-313.pyc +0 -0
- package/scripts/__pycache__/audio_converter.cpython-313.pyc +0 -0
- package/scripts/__pycache__/audio_enhancer.cpython-313.pyc +0 -0
- package/scripts/__pycache__/audio_utils.cpython-313.pyc +0 -0
- package/scripts/__pycache__/command_parser.cpython-313.pyc +0 -0
- package/scripts/__pycache__/constants.cpython-313.pyc +0 -0
- package/scripts/__pycache__/cron_push.cpython-313.pyc +0 -0
- package/scripts/__pycache__/dedup.cpython-313.pyc +0 -0
- package/scripts/__pycache__/error_notebook.cpython-313.pyc +0 -0
- package/scripts/__pycache__/feishu_voice.cpython-313.pyc +0 -0
- package/scripts/__pycache__/gamification.cpython-313.pyc +0 -0
- package/scripts/__pycache__/scorer.cpython-313.pyc +0 -0
- package/scripts/__pycache__/state_manager.cpython-313.pyc +0 -0
- package/scripts/__pycache__/utils.cpython-313.pyc +0 -0
- package/scripts/audio/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/audio/__pycache__/composer.cpython-313.pyc +0 -0
- package/scripts/audio/__pycache__/converter.cpython-313.pyc +0 -0
- package/scripts/audio/__pycache__/feishu_voice.cpython-313.pyc +0 -0
- package/scripts/audio/__pycache__/utils.cpython-313.pyc +0 -0
- package/scripts/audio/tts/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/audio/tts/__pycache__/base.cpython-313.pyc +0 -0
- package/scripts/audio/tts/__pycache__/manager.cpython-313.pyc +0 -0
- package/scripts/audio/tts/providers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/audio/tts/providers/__pycache__/edge.cpython-313.pyc +0 -0
- package/scripts/audio/tts/providers/__pycache__/xunfei.cpython-313.pyc +0 -0
- package/scripts/cli/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/cli/__pycache__/cli.cpython-313.pyc +0 -0
- package/scripts/cli/__pycache__/command_parser.cpython-313.pyc +0 -0
- package/scripts/core/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/core/__pycache__/constants.cpython-313.pyc +0 -0
- package/scripts/core/__pycache__/error_notebook.cpython-313.pyc +0 -0
- package/scripts/core/__pycache__/gamification.cpython-313.pyc +0 -0
- package/scripts/core/__pycache__/scorer.cpython-313.pyc +0 -0
- package/scripts/core/__pycache__/state_manager.cpython-313.pyc +0 -0
- package/scripts/release.py +255 -0
- package/scripts/scheduling/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/scheduling/__pycache__/cron_push.cpython-313.pyc +0 -0
- package/scripts/utils/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/utils/__pycache__/dedup.cpython-313.pyc +0 -0
- package/scripts/utils/__pycache__/helpers.cpython-313.pyc +0 -0
- package/.claude/settings.local.json +0 -22
- package/.gitignore +0 -32
- package/CHANGELOG.md +0 -88
- package/CLAUDE.md +0 -275
- package/backups/state_backup_20260227_063358.json +0 -47
- package/backups/state_backup_20260227_063405.json +0 -47
- package/backups/state_backup_20260227_064016.json +0 -47
- package/bin/eng-lang-tutor.js +0 -177
- package/docs/OPENCLAW_DEPLOYMENT.md +0 -241
package/README.md
CHANGED
|
@@ -84,6 +84,21 @@ openclaw skills list
|
|
|
84
84
|
openclaw skills info eng-lang-tutor
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
+
### 卸载
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# 卸载 npm 包并清除所有数据(包括状态和媒体文件)
|
|
91
|
+
npm uninstall -g @rookiestar/eng-lang-tutor && rm -rf ~/.openclaw/state/eng-lang-tutor ~/.openclaw/media/eng-lang-tutor
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**如需保留学习数据,仅卸载软件:**
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npm uninstall -g @rookiestar/eng-lang-tutor
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
> 注意:`~/.openclaw/state/eng-lang-tutor/` 存储学习进度、XP、连胜等数据;`~/.openclaw/media/eng-lang-tutor/` 存储生成的音频文件。
|
|
101
|
+
|
|
87
102
|
**重启 Gateway:**
|
|
88
103
|
|
|
89
104
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rookiestar/eng-lang-tutor",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "地道美式英语导师 - OpenClaw Skill for learning authentic American English",
|
|
5
5
|
"main": "scripts/cli/cli.py",
|
|
6
6
|
"bin": {
|
|
@@ -29,11 +29,13 @@
|
|
|
29
29
|
},
|
|
30
30
|
"homepage": "https://github.com/rookiestar/Skills/tree/main/eng-lang-tutor#readme",
|
|
31
31
|
"files": [
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
32
|
+
"scripts/",
|
|
33
|
+
"templates/",
|
|
34
|
+
"examples/",
|
|
35
|
+
"references/",
|
|
36
|
+
"SKILL.md",
|
|
37
|
+
"README.md",
|
|
38
|
+
"requirements.txt"
|
|
37
39
|
],
|
|
38
40
|
"engines": {
|
|
39
41
|
"node": ">=14.0.0"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Release Script - Manages file visibility across local repo, remote repo, and npm package.
|
|
4
|
+
|
|
5
|
+
This script handles three layers:
|
|
6
|
+
1. Local repo - All tracked files (managed by .gitignore)
|
|
7
|
+
2. Remote repo - Public files only
|
|
8
|
+
3. npm package - Minimal user-facing files
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
python3 scripts/release.py --check # Show file distribution
|
|
12
|
+
python3 scripts/release.py --sync-remote # Sync to remote (dry-run)
|
|
13
|
+
python3 scripts/release.py --npm-pack # Create npm tarball
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
import subprocess
|
|
18
|
+
import json
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Set
|
|
21
|
+
|
|
22
|
+
# Files/directories to EXCLUDE from remote repo (not publicly visible)
|
|
23
|
+
REMOTE_EXCLUDE = {
|
|
24
|
+
"tests/",
|
|
25
|
+
"package.json",
|
|
26
|
+
"package-lock.json",
|
|
27
|
+
"bin/",
|
|
28
|
+
"scripts/setup.py",
|
|
29
|
+
".gitignore",
|
|
30
|
+
".gitattributes",
|
|
31
|
+
".npmignore",
|
|
32
|
+
"*.egg-info/",
|
|
33
|
+
".pytest_cache/",
|
|
34
|
+
"__pycache__/",
|
|
35
|
+
".coverage",
|
|
36
|
+
"htmlcov/",
|
|
37
|
+
".tox/",
|
|
38
|
+
".nox/",
|
|
39
|
+
".claude/",
|
|
40
|
+
"*.pyc",
|
|
41
|
+
"*.pyo",
|
|
42
|
+
"*.tgz",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Files/directories to EXCLUDE from npm package (in addition to REMOTE_EXCLUDE)
|
|
46
|
+
# npm package should be minimal - only what users need to run
|
|
47
|
+
NPM_EXCLUDE = REMOTE_EXCLUDE | {
|
|
48
|
+
"CLAUDE.md", # Development guide for Claude AI
|
|
49
|
+
"docs/", # Internal documentation
|
|
50
|
+
"examples/", # Sample files (not needed for runtime)
|
|
51
|
+
"references/", # Reference materials
|
|
52
|
+
"*.md", # All markdown except README.md
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# Files that MUST be included in npm package
|
|
56
|
+
NPM_INCLUDE = {
|
|
57
|
+
"README.md", # Keep README for npm display
|
|
58
|
+
"package.json", # Required for npm
|
|
59
|
+
"requirements.txt", # Python dependencies
|
|
60
|
+
"scripts/", # All scripts (excluding setup.py)
|
|
61
|
+
"templates/", # Prompt templates
|
|
62
|
+
"SKILL.md", # Skill documentation
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_tracked_files() -> Set[str]:
|
|
67
|
+
"""Get all files tracked by git."""
|
|
68
|
+
result = subprocess.run(
|
|
69
|
+
["git", "ls-files"],
|
|
70
|
+
capture_output=True,
|
|
71
|
+
text=True,
|
|
72
|
+
cwd=Path(__file__).parent.parent
|
|
73
|
+
)
|
|
74
|
+
return set(result.stdout.strip().split("\n"))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def should_exclude(path: str, exclude_patterns: Set[str]) -> bool:
|
|
78
|
+
"""Check if a path should be excluded based on patterns."""
|
|
79
|
+
for pattern in exclude_patterns:
|
|
80
|
+
if pattern.endswith("/"):
|
|
81
|
+
if path.startswith(pattern) or "/" + pattern in path:
|
|
82
|
+
return True
|
|
83
|
+
elif pattern.startswith("*."):
|
|
84
|
+
if path.endswith(pattern[1:]):
|
|
85
|
+
return True
|
|
86
|
+
else:
|
|
87
|
+
if path == pattern or path.startswith(pattern + "/"):
|
|
88
|
+
return True
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def categorize_files():
|
|
93
|
+
"""Categorize files into local, remote, and npm groups."""
|
|
94
|
+
tracked = get_tracked_files()
|
|
95
|
+
|
|
96
|
+
local_only = set()
|
|
97
|
+
remote_files = set()
|
|
98
|
+
npm_files = set()
|
|
99
|
+
|
|
100
|
+
for file in tracked:
|
|
101
|
+
# Skip empty strings
|
|
102
|
+
if not file:
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
# Check if in remote exclude list
|
|
106
|
+
if should_exclude(file, REMOTE_EXCLUDE):
|
|
107
|
+
local_only.add(file)
|
|
108
|
+
else:
|
|
109
|
+
remote_files.add(file)
|
|
110
|
+
|
|
111
|
+
# Check if should be in npm package
|
|
112
|
+
if should_exclude(file, NPM_EXCLUDE):
|
|
113
|
+
# Check if explicitly included
|
|
114
|
+
included = False
|
|
115
|
+
for inc_pattern in NPM_INCLUDE:
|
|
116
|
+
if inc_pattern.endswith("/"):
|
|
117
|
+
if file.startswith(inc_pattern):
|
|
118
|
+
included = True
|
|
119
|
+
break
|
|
120
|
+
elif file == inc_pattern:
|
|
121
|
+
included = True
|
|
122
|
+
break
|
|
123
|
+
|
|
124
|
+
if included:
|
|
125
|
+
npm_files.add(file)
|
|
126
|
+
else:
|
|
127
|
+
npm_files.add(file)
|
|
128
|
+
|
|
129
|
+
return local_only, remote_files, npm_files
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def show_distribution():
|
|
133
|
+
"""Show file distribution across three layers."""
|
|
134
|
+
local_only, remote_files, npm_files = categorize_files()
|
|
135
|
+
|
|
136
|
+
print("=" * 60)
|
|
137
|
+
print("FILE DISTRIBUTION ACROSS THREE LAYERS")
|
|
138
|
+
print("=" * 60)
|
|
139
|
+
|
|
140
|
+
print(f"\n📦 LOCAL REPO ONLY ({len(local_only)} files)")
|
|
141
|
+
print("-" * 40)
|
|
142
|
+
for f in sorted(local_only):
|
|
143
|
+
print(f" {f}")
|
|
144
|
+
|
|
145
|
+
print(f"\n🌐 REMOTE REPO (public, {len(remote_files)} files)")
|
|
146
|
+
print("-" * 40)
|
|
147
|
+
for f in sorted(remote_files):
|
|
148
|
+
print(f" {f}")
|
|
149
|
+
|
|
150
|
+
print(f"\n📦 NPM PACKAGE ({len(npm_files)} files)")
|
|
151
|
+
print("-" * 40)
|
|
152
|
+
for f in sorted(npm_files):
|
|
153
|
+
print(f" {f}")
|
|
154
|
+
|
|
155
|
+
print("\n" + "=" * 60)
|
|
156
|
+
print(f"SUMMARY: Local={len(local_only) + len(remote_files)} | Remote={len(remote_files)} | npm={len(npm_files)}")
|
|
157
|
+
print("=" * 60)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def create_gitattributes():
|
|
161
|
+
"""Create .gitattributes with export-ignore for local-only files."""
|
|
162
|
+
eng_lang_tutor_dir = Path(__file__).parent.parent
|
|
163
|
+
gitattributes_path = eng_lang_tutor_dir / ".gitattributes"
|
|
164
|
+
|
|
165
|
+
# Patterns to exclude from git archive (remote export)
|
|
166
|
+
export_ignore_patterns = [
|
|
167
|
+
"tests/",
|
|
168
|
+
".pytest_cache/",
|
|
169
|
+
"*.pyc",
|
|
170
|
+
"*.pyo",
|
|
171
|
+
".coverage",
|
|
172
|
+
"htmlcov/",
|
|
173
|
+
".tox/",
|
|
174
|
+
".nox/",
|
|
175
|
+
".claude/",
|
|
176
|
+
"*.egg-info/",
|
|
177
|
+
"*.tgz",
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
content = "# Files to exclude from git archive export\n"
|
|
181
|
+
content += "# These files are tracked locally but not exported to remote archives\n\n"
|
|
182
|
+
|
|
183
|
+
for pattern in export_ignore_patterns:
|
|
184
|
+
content += f"{pattern} export-ignore\n"
|
|
185
|
+
|
|
186
|
+
gitattributes_path.write_text(content)
|
|
187
|
+
print(f"✓ Created {gitattributes_path}")
|
|
188
|
+
print("\nNote: This affects 'git archive' only.")
|
|
189
|
+
print("For selective push to remote, consider using a separate public branch.")
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def npm_pack():
|
|
193
|
+
"""Create npm tarball with proper file filtering."""
|
|
194
|
+
eng_lang_tutor_dir = Path(__file__).parent.parent
|
|
195
|
+
|
|
196
|
+
# Update package.json files field for npm
|
|
197
|
+
package_json_path = eng_lang_tutor_dir / "package.json"
|
|
198
|
+
|
|
199
|
+
with open(package_json_path) as f:
|
|
200
|
+
package = json.load(f)
|
|
201
|
+
|
|
202
|
+
# Set files field to include only what we want
|
|
203
|
+
package["files"] = [
|
|
204
|
+
"scripts/",
|
|
205
|
+
"templates/",
|
|
206
|
+
"SKILL.md",
|
|
207
|
+
"README.md",
|
|
208
|
+
"requirements.txt",
|
|
209
|
+
]
|
|
210
|
+
|
|
211
|
+
# Remove tests from npm package
|
|
212
|
+
if "!tests/**" in package.get("files", []):
|
|
213
|
+
pass # Already excluded
|
|
214
|
+
|
|
215
|
+
print("npm pack would include:")
|
|
216
|
+
print(json.dumps(package.get("files", []), indent=2))
|
|
217
|
+
|
|
218
|
+
print("\nRun the following to create npm package:")
|
|
219
|
+
print(f" cd {eng_lang_tutor_dir} && npm pack")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def main():
|
|
223
|
+
parser = argparse.ArgumentParser(
|
|
224
|
+
description="Manage file visibility across local repo, remote repo, and npm package"
|
|
225
|
+
)
|
|
226
|
+
parser.add_argument(
|
|
227
|
+
"--check",
|
|
228
|
+
action="store_true",
|
|
229
|
+
help="Show file distribution across three layers"
|
|
230
|
+
)
|
|
231
|
+
parser.add_argument(
|
|
232
|
+
"--create-gitattributes",
|
|
233
|
+
action="store_true",
|
|
234
|
+
help="Create .gitattributes with export-ignore rules"
|
|
235
|
+
)
|
|
236
|
+
parser.add_argument(
|
|
237
|
+
"--npm-pack",
|
|
238
|
+
action="store_true",
|
|
239
|
+
help="Show npm pack configuration"
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
args = parser.parse_args()
|
|
243
|
+
|
|
244
|
+
if args.check:
|
|
245
|
+
show_distribution()
|
|
246
|
+
elif args.create_gitattributes:
|
|
247
|
+
create_gitattributes()
|
|
248
|
+
elif args.npm_pack:
|
|
249
|
+
npm_pack()
|
|
250
|
+
else:
|
|
251
|
+
parser.print_help()
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
if __name__ == "__main__":
|
|
255
|
+
main()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(python3 -m pytest:*)",
|
|
5
|
-
"Bash(pytest:*)",
|
|
6
|
-
"Bash(find:*)",
|
|
7
|
-
"Bash(git add:*)",
|
|
8
|
-
"Bash(git commit:*)",
|
|
9
|
-
"Bash(git push)",
|
|
10
|
-
"mcp__brave-search__brave_web_search",
|
|
11
|
-
"mcp__web-search-prime__webSearchPrime",
|
|
12
|
-
"mcp__zread__get_repo_structure",
|
|
13
|
-
"mcp__zread__read_file",
|
|
14
|
-
"mcp__zread__search_doc",
|
|
15
|
-
"mcp__web-reader__webReader",
|
|
16
|
-
"WebSearch",
|
|
17
|
-
"mcp__fetch__fetch",
|
|
18
|
-
"Bash(wc:*)",
|
|
19
|
-
"Bash(python3 -m py_compile:*)"
|
|
20
|
-
]
|
|
21
|
-
}
|
|
22
|
-
}
|
package/.gitignore
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Python
|
|
2
|
-
__pycache__/
|
|
3
|
-
*.py[cod]
|
|
4
|
-
*$py.class
|
|
5
|
-
*.so
|
|
6
|
-
.Python
|
|
7
|
-
.venv/
|
|
8
|
-
venv/
|
|
9
|
-
ENV/
|
|
10
|
-
|
|
11
|
-
# IDE
|
|
12
|
-
.idea/
|
|
13
|
-
.vscode/
|
|
14
|
-
*.swp
|
|
15
|
-
*.swo
|
|
16
|
-
|
|
17
|
-
# OS
|
|
18
|
-
.DS_Store
|
|
19
|
-
Thumbs.db
|
|
20
|
-
|
|
21
|
-
# Backups
|
|
22
|
-
backups/
|
|
23
|
-
*.bak
|
|
24
|
-
|
|
25
|
-
# User data
|
|
26
|
-
data/state.json
|
|
27
|
-
data/logs/
|
|
28
|
-
data/daily/
|
|
29
|
-
|
|
30
|
-
# npm
|
|
31
|
-
node_modules/
|
|
32
|
-
*.tgz
|
package/CHANGELOG.md
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
## [1.2.4] - 2026-02-27
|
|
6
|
-
|
|
7
|
-
### Fixed
|
|
8
|
-
- **TTS voice selection**: Audio composer now automatically selects appropriate voices based on TTS provider
|
|
9
|
-
- Edge-TTS: `en-US-JennyNeural`, `en-US-EricNeural`
|
|
10
|
-
- XunFei: `catherine`, `henry`
|
|
11
|
-
- **CLI import paths**: Fixed broken imports in `state_manager.py` CLI module
|
|
12
|
-
|
|
13
|
-
### Changed
|
|
14
|
-
- **npm package**: Removed automatic `pip install` from postinstall script
|
|
15
|
-
- Added `eng-lang-tutor-setup` CLI tool for manual dependency installation
|
|
16
|
-
- Supports `--venv`, `--user`, and `--check` options
|
|
17
|
-
- **Test coverage**: Added 38 new tests covering:
|
|
18
|
-
- `scripts/audio/utils.py` (6 tests)
|
|
19
|
-
- `scripts/audio/converter.py` (16 tests)
|
|
20
|
-
- `scripts/utils/helpers.py` (16 tests)
|
|
21
|
-
- **Test fixes**: Fixed pre-existing test failures in CLI and TTS modules
|
|
22
|
-
|
|
23
|
-
## [1.2.3] - 2026-02-27
|
|
24
|
-
|
|
25
|
-
### Changed
|
|
26
|
-
- Version bump for npm publishing
|
|
27
|
-
|
|
28
|
-
## [1.2.0] - 2026-02-27
|
|
29
|
-
|
|
30
|
-
### Changed
|
|
31
|
-
- Initial npm package setup
|
|
32
|
-
|
|
33
|
-
## [1.0.1] - 2025-02-27
|
|
34
|
-
|
|
35
|
-
### Fixed
|
|
36
|
-
- **TTS voice selection**: Audio composer now automatically selects appropriate voices based on TTS provider
|
|
37
|
-
- Edge-TTS: `en-US-JennyNeural`, `en-US-EricNeural`
|
|
38
|
-
- XunFei: `catherine`, `henry`
|
|
39
|
-
- **CLI import paths**: Fixed broken imports in `state_manager.py` CLI module
|
|
40
|
-
|
|
41
|
-
### Changed
|
|
42
|
-
- **npm package**: Removed automatic `pip install` from postinstall script
|
|
43
|
-
- Added `eng-lang-tutor-setup` CLI tool for manual dependency installation
|
|
44
|
-
- Supports `--venv`, `--user`, and `--check` options
|
|
45
|
-
- **Test coverage**: Added 38 new tests covering:
|
|
46
|
-
- `scripts/audio/utils.py` (6 tests)
|
|
47
|
-
- `scripts/audio/converter.py` (16 tests)
|
|
48
|
-
- `scripts/utils/helpers.py` (16 tests)
|
|
49
|
-
- **Test fixes**: Fixed pre-existing test failures in CLI and TTS modules
|
|
50
|
-
|
|
51
|
-
## [1.0.1] - 2025-02-27
|
|
52
|
-
|
|
53
|
-
### Changed
|
|
54
|
-
- Version bump for npm publishing (1.0.0 was previously unpublished)
|
|
55
|
-
|
|
56
|
-
## [1.0.0] - 2025-02-26
|
|
57
|
-
|
|
58
|
-
Initial release.
|
|
59
|
-
|
|
60
|
-
### Added
|
|
61
|
-
|
|
62
|
-
**Core Features:**
|
|
63
|
-
- Daily knowledge points with authentic American English expressions
|
|
64
|
-
- Quiz system with 4 question types (multiple choice, Chinglish fix, fill blank, dialogue completion)
|
|
65
|
-
- Duolingo-style gamification (XP, levels 1-20, streaks, badges, gems)
|
|
66
|
-
- Error notebook for tracking and reviewing mistakes
|
|
67
|
-
- 14-day content deduplication
|
|
68
|
-
|
|
69
|
-
**CEFR Support:**
|
|
70
|
-
- Complete CEFR level definitions (A1-C2) with Can-Do Statements
|
|
71
|
-
- 12 sample JSON files covering all 6 CEFR levels
|
|
72
|
-
- Content difficulty adjusted by user's CEFR level
|
|
73
|
-
|
|
74
|
-
**Audio:**
|
|
75
|
-
- TTS audio generation (Edge-TTS default, XunFei optional)
|
|
76
|
-
- Async audio generation with background threading
|
|
77
|
-
- Context manager pattern for reliable temp file cleanup
|
|
78
|
-
|
|
79
|
-
**Configuration:**
|
|
80
|
-
- 7-step onboarding flow
|
|
81
|
-
- Initialization guard check before content generation
|
|
82
|
-
- Centralized configuration constants
|
|
83
|
-
- Prompt version control via `_meta.prompt_version` field
|
|
84
|
-
|
|
85
|
-
**Documentation:**
|
|
86
|
-
- SKILL.md, README.md, CLAUDE.md
|
|
87
|
-
- OpenClaw deployment guide
|
|
88
|
-
- Prompt templates (keypoint generation, quiz generation, etc.)
|