@rookiestar/eng-lang-tutor 1.0.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.
Files changed (61) hide show
  1. package/.claude/settings.local.json +22 -0
  2. package/.gitignore +32 -0
  3. package/CHANGELOG.md +37 -0
  4. package/CLAUDE.md +275 -0
  5. package/README.md +369 -0
  6. package/SKILL.md +613 -0
  7. package/bin/eng-lang-tutor.js +177 -0
  8. package/docs/OPENCLAW_DEPLOYMENT.md +241 -0
  9. package/examples/sample_keypoint_a1.json +112 -0
  10. package/examples/sample_keypoint_a2.json +124 -0
  11. package/examples/sample_keypoint_b1.json +135 -0
  12. package/examples/sample_keypoint_b2.json +137 -0
  13. package/examples/sample_keypoint_c1.json +134 -0
  14. package/examples/sample_keypoint_c2.json +141 -0
  15. package/examples/sample_quiz_a1.json +94 -0
  16. package/examples/sample_quiz_a2.json +94 -0
  17. package/examples/sample_quiz_b1.json +92 -0
  18. package/examples/sample_quiz_b2.json +94 -0
  19. package/examples/sample_quiz_c1.json +94 -0
  20. package/examples/sample_quiz_c2.json +104 -0
  21. package/package.json +41 -0
  22. package/references/resources.md +292 -0
  23. package/requirements.txt +16 -0
  24. package/scripts/__init__.py +28 -0
  25. package/scripts/audio/__init__.py +23 -0
  26. package/scripts/audio/composer.py +367 -0
  27. package/scripts/audio/converter.py +331 -0
  28. package/scripts/audio/feishu_voice.py +404 -0
  29. package/scripts/audio/tts/__init__.py +30 -0
  30. package/scripts/audio/tts/base.py +166 -0
  31. package/scripts/audio/tts/manager.py +306 -0
  32. package/scripts/audio/tts/providers/__init__.py +12 -0
  33. package/scripts/audio/tts/providers/edge.py +111 -0
  34. package/scripts/audio/tts/providers/xunfei.py +205 -0
  35. package/scripts/audio/utils.py +63 -0
  36. package/scripts/cli/__init__.py +7 -0
  37. package/scripts/cli/cli.py +229 -0
  38. package/scripts/cli/command_parser.py +336 -0
  39. package/scripts/core/__init__.py +30 -0
  40. package/scripts/core/constants.py +125 -0
  41. package/scripts/core/error_notebook.py +308 -0
  42. package/scripts/core/gamification.py +405 -0
  43. package/scripts/core/scorer.py +295 -0
  44. package/scripts/core/state_manager.py +814 -0
  45. package/scripts/eng-lang-tutor +16 -0
  46. package/scripts/scheduling/__init__.py +6 -0
  47. package/scripts/scheduling/cron_push.py +229 -0
  48. package/scripts/utils/__init__.py +12 -0
  49. package/scripts/utils/dedup.py +331 -0
  50. package/scripts/utils/helpers.py +82 -0
  51. package/templates/keypoint_schema.json +420 -0
  52. package/templates/prompt_templates.md +73 -0
  53. package/templates/prompts/display_guide.md +106 -0
  54. package/templates/prompts/initialization.md +350 -0
  55. package/templates/prompts/keypoint_generation.md +272 -0
  56. package/templates/prompts/output_rules.md +106 -0
  57. package/templates/prompts/quiz_generation.md +190 -0
  58. package/templates/prompts/responses.md +339 -0
  59. package/templates/prompts/shared_enums.md +252 -0
  60. package/templates/quiz_schema.json +214 -0
  61. package/templates/state_schema.json +277 -0
@@ -0,0 +1,277 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "state_schema.json",
4
+ "title": "State",
5
+ "description": "Core state for eng-lang-tutor skill",
6
+ "type": "object",
7
+ "required": ["version", "initialized", "user", "preferences", "progress", "recent_topics", "error_notebook", "completion_status"],
8
+ "properties": {
9
+ "version": {
10
+ "type": "integer",
11
+ "const": 2,
12
+ "description": "Schema version"
13
+ },
14
+ "initialized": {
15
+ "type": "boolean",
16
+ "default": false,
17
+ "description": "Whether user has completed onboarding"
18
+ },
19
+ "onboarding_step": {
20
+ "type": "integer",
21
+ "minimum": 0,
22
+ "maximum": 7,
23
+ "default": 0,
24
+ "description": "Current onboarding step (0=not started, 7=complete)"
25
+ },
26
+ "completion_status": {
27
+ "type": "object",
28
+ "properties": {
29
+ "quiz_completed_date": {
30
+ "type": ["string", "null"],
31
+ "format": "date",
32
+ "description": "Date when quiz was last completed"
33
+ },
34
+ "keypoint_view_history": {
35
+ "type": "array",
36
+ "items": {
37
+ "type": "object",
38
+ "properties": {
39
+ "date": { "type": "string", "format": "date" },
40
+ "viewed_at": { "type": "string", "format": "date-time" }
41
+ }
42
+ },
43
+ "description": "History of viewed keypoints"
44
+ }
45
+ },
46
+ "description": "Tracks completion status for quizzes and exercises"
47
+ },
48
+ "schedule": {
49
+ "type": "object",
50
+ "properties": {
51
+ "keypoint_time": {
52
+ "type": "string",
53
+ "pattern": "^([01]?[0-9]|2[0-3]):[0-5][0-9]$",
54
+ "default": "06:45",
55
+ "description": "Daily keypoint push time (HH:MM)"
56
+ },
57
+ "quiz_time": {
58
+ "type": "string",
59
+ "pattern": "^([01]?[0-9]|2[0-3]):[0-5][0-9]$",
60
+ "default": "22:45",
61
+ "description": "Daily quiz push time (HH:MM)"
62
+ },
63
+ "timezone": {
64
+ "type": "string",
65
+ "default": "Asia/Shanghai",
66
+ "description": "Timezone for schedule"
67
+ }
68
+ },
69
+ "description": "User's preferred schedule for content delivery"
70
+ },
71
+ "user": {
72
+ "type": "object",
73
+ "required": ["xp", "level", "streak", "streak_freeze", "gems", "badges"],
74
+ "properties": {
75
+ "xp": {
76
+ "type": "integer",
77
+ "minimum": 0,
78
+ "description": "Total experience points"
79
+ },
80
+ "level": {
81
+ "type": "integer",
82
+ "minimum": 1,
83
+ "maximum": 20,
84
+ "description": "Activity Level (活跃等级): measures engagement depth, NOT language ability. Stages: Starter(1-5), Traveler(6-10), Explorer(11-15), Pioneer(16-20)"
85
+ },
86
+ "streak": {
87
+ "type": "integer",
88
+ "minimum": 0,
89
+ "description": "Consecutive study days"
90
+ },
91
+ "streak_freeze": {
92
+ "type": "integer",
93
+ "minimum": 0,
94
+ "description": "Number of streak freeze items available"
95
+ },
96
+ "gems": {
97
+ "type": "integer",
98
+ "minimum": 0,
99
+ "description": "Currency for streak freeze and hints"
100
+ },
101
+ "badges": {
102
+ "type": "array",
103
+ "items": {
104
+ "type": "string",
105
+ "enum": ["first_steps", "week_warrior", "month_master", "perfect_10", "vocab_hunter", "error_slayer"]
106
+ },
107
+ "description": "Earned badges"
108
+ }
109
+ }
110
+ },
111
+ "preferences": {
112
+ "type": "object",
113
+ "required": ["cefr_level", "oral_written_ratio", "topics", "tutor_style", "dedup_days"],
114
+ "properties": {
115
+ "cefr_level": {
116
+ "type": "string",
117
+ "enum": ["A1", "A2", "B1", "B2", "C1", "C2"],
118
+ "default": "B1",
119
+ "description": "Ability Level (能力等级): CEFR standard for content difficulty matching"
120
+ },
121
+ "oral_written_ratio": {
122
+ "type": "number",
123
+ "minimum": 0,
124
+ "maximum": 1,
125
+ "default": 0.7,
126
+ "description": "Ratio of oral to written expressions (0.7 = 70% oral)"
127
+ },
128
+ "topics": {
129
+ "type": "object",
130
+ "properties": {
131
+ "movies": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.2 },
132
+ "news": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.15 },
133
+ "gaming": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.15 },
134
+ "sports": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.1 },
135
+ "workplace": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.2 },
136
+ "social": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.1 },
137
+ "daily_life": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.1 }
138
+ },
139
+ "description": "Topic preference weights (should sum to 1.0)"
140
+ },
141
+ "tutor_style": {
142
+ "type": "string",
143
+ "enum": ["humorous", "rigorous", "casual", "professional"],
144
+ "default": "humorous",
145
+ "description": "Tutor personality style"
146
+ },
147
+ "dedup_days": {
148
+ "type": "integer",
149
+ "minimum": 7,
150
+ "maximum": 30,
151
+ "default": 14,
152
+ "description": "Days to look back for content deduplication"
153
+ }
154
+ }
155
+ },
156
+ "tts_settings": {
157
+ "type": "object",
158
+ "description": "TTS voice and speed configuration",
159
+ "properties": {
160
+ "enabled": {
161
+ "type": "boolean",
162
+ "default": true,
163
+ "description": "Whether voice teaching is enabled"
164
+ },
165
+ "provider": {
166
+ "type": "string",
167
+ "enum": ["edge-tts", "xunfei"],
168
+ "default": "edge-tts",
169
+ "description": "TTS provider to use"
170
+ },
171
+ "speed": {
172
+ "type": "number",
173
+ "enum": [0.5, 0.7, 0.9, 1.3, 1.7],
174
+ "default": 0.9,
175
+ "description": "Speech speed: 0.5=very slow, 0.7=slow, 0.9=normal(recommended), 1.3=fast, 1.7=very fast"
176
+ },
177
+ "voices": {
178
+ "type": "object",
179
+ "description": "Voice mappings for different roles",
180
+ "properties": {
181
+ "narrator": {
182
+ "type": "string",
183
+ "description": "Narrator voice (female by default)"
184
+ },
185
+ "dialogue_a": {
186
+ "type": "string",
187
+ "description": "Dialogue A voice (male by default)"
188
+ },
189
+ "dialogue_b": {
190
+ "type": "string",
191
+ "description": "Dialogue B voice (female by default)"
192
+ }
193
+ }
194
+ }
195
+ }
196
+ },
197
+ "progress": {
198
+ "type": "object",
199
+ "required": ["total_quizzes", "correct_rate", "last_study_date"],
200
+ "properties": {
201
+ "total_quizzes": {
202
+ "type": "integer",
203
+ "minimum": 0,
204
+ "description": "Total quizzes completed"
205
+ },
206
+ "correct_rate": {
207
+ "type": "number",
208
+ "minimum": 0,
209
+ "maximum": 100,
210
+ "description": "Overall correct answer rate (percentage)"
211
+ },
212
+ "last_study_date": {
213
+ "type": ["string", "null"],
214
+ "format": "date",
215
+ "description": "Last study date (YYYY-MM-DD)"
216
+ },
217
+ "perfect_quizzes": {
218
+ "type": "integer",
219
+ "minimum": 0,
220
+ "description": "Number of perfect quizzes (100% correct)"
221
+ },
222
+ "expressions_learned": {
223
+ "type": "integer",
224
+ "minimum": 0,
225
+ "description": "Total expressions learned"
226
+ }
227
+ }
228
+ },
229
+ "recent_topics": {
230
+ "type": "array",
231
+ "items": {
232
+ "type": "string"
233
+ },
234
+ "maxItems": 50,
235
+ "description": "Recent topic fingerprints for deduplication"
236
+ },
237
+ "error_notebook": {
238
+ "type": "array",
239
+ "items": {
240
+ "type": "object",
241
+ "required": ["date", "question", "user_answer", "correct_answer", "explanation"],
242
+ "properties": {
243
+ "date": { "type": "string", "format": "date" },
244
+ "question": { "type": "string" },
245
+ "user_answer": { "type": "string" },
246
+ "correct_answer": { "type": "string" },
247
+ "explanation": { "type": "string" },
248
+ "reviewed": { "type": "boolean", "default": false },
249
+ "wrong_count": { "type": "integer", "default": 1, "minimum": 1, "description": "Number of times this question was answered incorrectly" },
250
+ "keypoint_date": { "type": "string", "format": "date", "description": "Date of the associated knowledge point" },
251
+ "question_type": { "type": "string", "enum": ["multiple_choice", "fill_blank", "dialogue_completion", "chinglish_fix"], "description": "Type of quiz question" }
252
+ }
253
+ },
254
+ "description": "Wrong answers for review"
255
+ },
256
+ "error_archive": {
257
+ "type": "array",
258
+ "items": {
259
+ "type": "object",
260
+ "required": ["date", "question", "user_answer", "correct_answer", "explanation"],
261
+ "properties": {
262
+ "date": { "type": "string", "format": "date" },
263
+ "question": { "type": "string" },
264
+ "user_answer": { "type": "string" },
265
+ "correct_answer": { "type": "string" },
266
+ "explanation": { "type": "string" },
267
+ "reviewed": { "type": "boolean", "default": false },
268
+ "wrong_count": { "type": "integer", "default": 1, "minimum": 1 },
269
+ "keypoint_date": { "type": "string", "format": "date" },
270
+ "question_type": { "type": "string", "enum": ["multiple_choice", "fill_blank", "dialogue_completion", "chinglish_fix"] },
271
+ "archived_at": { "type": "string", "format": "date", "description": "Date when this error was archived" }
272
+ }
273
+ },
274
+ "description": "Archived stubborn errors (wrong_count >= 3 and over 30 days old)"
275
+ }
276
+ }
277
+ }