@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.
- package/.claude/settings.local.json +22 -0
- package/.gitignore +32 -0
- package/CHANGELOG.md +37 -0
- package/CLAUDE.md +275 -0
- package/README.md +369 -0
- package/SKILL.md +613 -0
- package/bin/eng-lang-tutor.js +177 -0
- package/docs/OPENCLAW_DEPLOYMENT.md +241 -0
- package/examples/sample_keypoint_a1.json +112 -0
- package/examples/sample_keypoint_a2.json +124 -0
- package/examples/sample_keypoint_b1.json +135 -0
- package/examples/sample_keypoint_b2.json +137 -0
- package/examples/sample_keypoint_c1.json +134 -0
- package/examples/sample_keypoint_c2.json +141 -0
- package/examples/sample_quiz_a1.json +94 -0
- package/examples/sample_quiz_a2.json +94 -0
- package/examples/sample_quiz_b1.json +92 -0
- package/examples/sample_quiz_b2.json +94 -0
- package/examples/sample_quiz_c1.json +94 -0
- package/examples/sample_quiz_c2.json +104 -0
- package/package.json +41 -0
- package/references/resources.md +292 -0
- package/requirements.txt +16 -0
- package/scripts/__init__.py +28 -0
- package/scripts/audio/__init__.py +23 -0
- package/scripts/audio/composer.py +367 -0
- package/scripts/audio/converter.py +331 -0
- package/scripts/audio/feishu_voice.py +404 -0
- package/scripts/audio/tts/__init__.py +30 -0
- package/scripts/audio/tts/base.py +166 -0
- package/scripts/audio/tts/manager.py +306 -0
- package/scripts/audio/tts/providers/__init__.py +12 -0
- package/scripts/audio/tts/providers/edge.py +111 -0
- package/scripts/audio/tts/providers/xunfei.py +205 -0
- package/scripts/audio/utils.py +63 -0
- package/scripts/cli/__init__.py +7 -0
- package/scripts/cli/cli.py +229 -0
- package/scripts/cli/command_parser.py +336 -0
- package/scripts/core/__init__.py +30 -0
- package/scripts/core/constants.py +125 -0
- package/scripts/core/error_notebook.py +308 -0
- package/scripts/core/gamification.py +405 -0
- package/scripts/core/scorer.py +295 -0
- package/scripts/core/state_manager.py +814 -0
- package/scripts/eng-lang-tutor +16 -0
- package/scripts/scheduling/__init__.py +6 -0
- package/scripts/scheduling/cron_push.py +229 -0
- package/scripts/utils/__init__.py +12 -0
- package/scripts/utils/dedup.py +331 -0
- package/scripts/utils/helpers.py +82 -0
- package/templates/keypoint_schema.json +420 -0
- package/templates/prompt_templates.md +73 -0
- package/templates/prompts/display_guide.md +106 -0
- package/templates/prompts/initialization.md +350 -0
- package/templates/prompts/keypoint_generation.md +272 -0
- package/templates/prompts/output_rules.md +106 -0
- package/templates/prompts/quiz_generation.md +190 -0
- package/templates/prompts/responses.md +339 -0
- package/templates/prompts/shared_enums.md +252 -0
- package/templates/quiz_schema.json +214 -0
- package/templates/state_schema.json +277 -0
package/SKILL.md
ADDED
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eng-lang-tutor
|
|
3
|
+
description: "地道美式英语导师 - 提供每日知识点、Quiz测验等学习内容。支持游戏化学习(XP/连胜/等级/徽章)。触发场景:学习英语、英语知识点、Quiz、错题本、学习进度。被 cron job 调用以实现定期内容推送。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# American English Tutor
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Teaches authentic American English expressions, avoiding Chinglish patterns.
|
|
11
|
+
Delivers personalized content via daily knowledge points and quizzes.
|
|
12
|
+
Includes Duolingo-style gamification (XP, streaks, levels, badges).
|
|
13
|
+
|
|
14
|
+
## Core Workflow
|
|
15
|
+
|
|
16
|
+
### 0. Initialization Guard Check
|
|
17
|
+
|
|
18
|
+
> **⛔ BEFORE generating any content (keypoint/quiz), check `initialized` status:**
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
If state.initialized == false:
|
|
22
|
+
1. Show friendly message: "看起来你还没有完成初始化配置,让我帮你快速设置一下吧!"
|
|
23
|
+
2. Automatically start onboarding from Step 1/7
|
|
24
|
+
3. DO NOT proceed with content generation until onboarding completes
|
|
25
|
+
|
|
26
|
+
If state.initialized == true:
|
|
27
|
+
Proceed with normal workflow below
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 1. Daily Knowledge Point Generation
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
Input: state.json (user preferences, CEFR level, recent topics)
|
|
34
|
+
Process:
|
|
35
|
+
1. Load user preferences from state.json
|
|
36
|
+
2. Load recent topic fingerprints (14 days) for deduplication
|
|
37
|
+
3. Select topic based on user preference weights
|
|
38
|
+
4. Generate knowledge point via LLM (pure JSON output)
|
|
39
|
+
5. Validate JSON schema
|
|
40
|
+
6. Save to daily/YYYY-MM-DD/keypoint.json
|
|
41
|
+
7. Update state.json recent_topics
|
|
42
|
+
8. Append event to logs/events_YYYY-MM.jsonl
|
|
43
|
+
Output: keypoint.json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. Quiz Generation
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Input: keypoint.json
|
|
50
|
+
Process:
|
|
51
|
+
1. Read today's keypoint.json
|
|
52
|
+
2. Generate 3 questions (fixed pattern):
|
|
53
|
+
- 1 multiple_choice (10 XP)
|
|
54
|
+
- 1 chinglish_fix (15 XP)
|
|
55
|
+
- 1 fill_blank OR dialogue_completion (12 XP, random)
|
|
56
|
+
3. Save to daily/YYYY-MM-DD/quiz.json (with answers)
|
|
57
|
+
Output: quiz.json (~37 XP total)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. Answer Evaluation
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
Input: quiz.json, user_answers.json
|
|
64
|
+
Process:
|
|
65
|
+
1. Compare user answers with correct answers
|
|
66
|
+
2. Calculate XP (base + streak multiplier + perfect bonus)
|
|
67
|
+
3. Update state.json (XP, streak, level, badges)
|
|
68
|
+
4. Record wrong answers to error_notebook
|
|
69
|
+
Output: results.json, updated state.json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Quiz Types
|
|
73
|
+
|
|
74
|
+
> See [templates/prompts/shared_enums.md](templates/prompts/shared_enums.md#quiz-question-types-题型) for full definitions.
|
|
75
|
+
|
|
76
|
+
| Type | XP | Daily |
|
|
77
|
+
|------|-----|-------|
|
|
78
|
+
| multiple_choice | 10 | 1 (required) |
|
|
79
|
+
| chinglish_fix | 15 | 1 (required) |
|
|
80
|
+
| fill_blank / dialogue_completion | 12 | 0-1 (random) |
|
|
81
|
+
|
|
82
|
+
**Daily Quiz:** 3 questions, ~37 XP, pass with 2/3 correct
|
|
83
|
+
|
|
84
|
+
## Gamification System
|
|
85
|
+
|
|
86
|
+
### XP & Levels
|
|
87
|
+
|
|
88
|
+
This system has two independent level systems:
|
|
89
|
+
- **Ability Level (CEFR)**: A1-C2, determines content difficulty
|
|
90
|
+
- **Activity Level (Level)**: 1-20, measures engagement depth
|
|
91
|
+
|
|
92
|
+
> See [templates/prompts/shared_enums.md](templates/prompts/shared_enums.md) for level stages and badge definitions.
|
|
93
|
+
|
|
94
|
+
### Streak System
|
|
95
|
+
- Consecutive days of study builds streak
|
|
96
|
+
- Streak multiplier: `1.0 + (streak * 0.05)`, max 2.0x
|
|
97
|
+
- Streak freeze costs 50 gems
|
|
98
|
+
|
|
99
|
+
## Key Scripts
|
|
100
|
+
|
|
101
|
+
| Script | Purpose |
|
|
102
|
+
|--------|---------|
|
|
103
|
+
| core/state_manager.py | State persistence, event logging, error notebook |
|
|
104
|
+
| core/error_notebook.py | Error notebook management |
|
|
105
|
+
| core/scorer.py | Answer evaluation, XP calculation |
|
|
106
|
+
| core/gamification.py | Streak/level/badge logic |
|
|
107
|
+
| core/constants.py | Shared constants (level thresholds, level names) |
|
|
108
|
+
| cli/cli.py | CLI entry point for state management |
|
|
109
|
+
| cli/command_parser.py | Natural language command parsing |
|
|
110
|
+
| scheduling/cron_push.py | Scheduled content push (keypoint/quiz placeholders) |
|
|
111
|
+
| utils/dedup.py | 14-day content deduplication |
|
|
112
|
+
| utils/helpers.py | Utility functions (safe divide, deep merge) |
|
|
113
|
+
| audio/ | Audio generation (TTS, composition, conversion, Feishu) |
|
|
114
|
+
|
|
115
|
+
## CLI Commands
|
|
116
|
+
|
|
117
|
+
> These bash commands are used by the Agent to execute operations. Data is stored in `~/.openclaw/state/eng-lang-tutor/` by default. Do NOT specify `--data-dir` unless using a custom location.
|
|
118
|
+
|
|
119
|
+
### Content Management
|
|
120
|
+
```bash
|
|
121
|
+
# Save daily content (keypoint/quiz)
|
|
122
|
+
python3 -m scripts.cli.cli save_daily --content-type keypoint --content '<JSON>'
|
|
123
|
+
|
|
124
|
+
# Record keypoint view
|
|
125
|
+
python3 -m scripts.cli.cli record_view [--date YYYY-MM-DD]
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Stats & Config
|
|
129
|
+
```bash
|
|
130
|
+
# Display learning progress
|
|
131
|
+
python3 -m scripts.cli.cli stats
|
|
132
|
+
|
|
133
|
+
# Display current configuration
|
|
134
|
+
python3 -m scripts.cli.cli config
|
|
135
|
+
|
|
136
|
+
# Update configuration
|
|
137
|
+
python3 -m scripts.cli.cli config --cefr B2
|
|
138
|
+
python3 -m scripts.cli.cli config --style professional
|
|
139
|
+
python3 -m scripts.cli.cli config --oral-ratio 80
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Error Notebook
|
|
143
|
+
```bash
|
|
144
|
+
# List errors (paginated)
|
|
145
|
+
python3 -m scripts.cli.cli errors [--page 1] [--per-page 5] [--month YYYY-MM]
|
|
146
|
+
|
|
147
|
+
# Get random errors for review
|
|
148
|
+
python3 -m scripts.cli.cli errors --random 5
|
|
149
|
+
|
|
150
|
+
# Get error statistics
|
|
151
|
+
python3 -m scripts.cli.cli errors --stats
|
|
152
|
+
|
|
153
|
+
# Get errors for review session
|
|
154
|
+
python3 -m scripts.cli.cli errors --review 5
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Schedule
|
|
158
|
+
```bash
|
|
159
|
+
# Display current schedule
|
|
160
|
+
python3 -m scripts.cli.cli schedule
|
|
161
|
+
|
|
162
|
+
# Update schedule (quiz_time must be later than keypoint_time)
|
|
163
|
+
python3 -m scripts.cli.cli schedule --keypoint-time 07:00 --quiz-time 21:00
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Core Principles
|
|
167
|
+
|
|
168
|
+
> See [templates/prompts/keypoint_generation.md](templates/prompts/keypoint_generation.md) for detailed generation rules.
|
|
169
|
+
|
|
170
|
+
1. **Always output valid JSON** - No markdown, no extra text
|
|
171
|
+
2. **Focus on "How Americans say it"** - NOT translation
|
|
172
|
+
3. **Every knowledge point must include**: Scene context, alternatives, Chinglish trap
|
|
173
|
+
4. **14-day deduplication** - No repeated topics or expressions
|
|
174
|
+
|
|
175
|
+
## File Structure
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
~/.openclaw/state/eng-lang-tutor/ # Default data location
|
|
179
|
+
state.json # Core state (streak/xp/preferences)
|
|
180
|
+
logs/
|
|
181
|
+
events_2026-02.jsonl # Monthly event log
|
|
182
|
+
daily/
|
|
183
|
+
2026-02-20/
|
|
184
|
+
keypoint.json # Today's knowledge point
|
|
185
|
+
quiz.json # Today's quiz
|
|
186
|
+
user_answers.json # User's answers
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Note:** Data location can be customized via `OPENCLAW_STATE_DIR` environment variable.
|
|
190
|
+
|
|
191
|
+
## JSON Schemas
|
|
192
|
+
|
|
193
|
+
See templates/ directory:
|
|
194
|
+
- state_schema.json
|
|
195
|
+
- keypoint_schema.json
|
|
196
|
+
- quiz_schema.json
|
|
197
|
+
|
|
198
|
+
## Resource References
|
|
199
|
+
|
|
200
|
+
**Prompt Templates** (templates/prompts/):
|
|
201
|
+
- [shared_enums.md](templates/prompts/shared_enums.md) - Topics, CEFR levels, styles, badges
|
|
202
|
+
- [output_rules.md](templates/prompts/output_rules.md) - JSON/markdown formatting rules
|
|
203
|
+
- [keypoint_generation.md](templates/prompts/keypoint_generation.md) - Knowledge point generation
|
|
204
|
+
- [quiz_generation.md](templates/prompts/quiz_generation.md) - Quiz generation
|
|
205
|
+
- [display_guide.md](templates/prompts/display_guide.md) - Emoji and formatting guide
|
|
206
|
+
- [initialization.md](templates/prompts/initialization.md) - Onboarding flow
|
|
207
|
+
- [responses.md](templates/prompts/responses.md) - Response templates
|
|
208
|
+
|
|
209
|
+
**Other Resources:**
|
|
210
|
+
- [references/resources.md](references/resources.md) - Themed English learning resources
|
|
211
|
+
- [templates/prompt_templates.md](templates/prompt_templates.md) - Prompt template index
|
|
212
|
+
|
|
213
|
+
## Examples
|
|
214
|
+
|
|
215
|
+
See `examples/` directory for sample outputs covering all CEFR levels:
|
|
216
|
+
|
|
217
|
+
| Level | Keypoint | Quiz |
|
|
218
|
+
|-------|----------|------|
|
|
219
|
+
| A1 (入门级) | sample_keypoint_a1.json | sample_quiz_a1.json |
|
|
220
|
+
| A2 (初级) | sample_keypoint_a2.json | sample_quiz_a2.json |
|
|
221
|
+
| B1 (中级) | sample_keypoint_b1.json | sample_quiz_b1.json |
|
|
222
|
+
| B2 (中高级) | sample_keypoint_b2.json | sample_quiz_b2.json |
|
|
223
|
+
| C1 (高级) | sample_keypoint_c1.json | sample_quiz_c1.json |
|
|
224
|
+
| C2 (精通级) | sample_keypoint_c2.json | sample_quiz_c2.json |
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## User Commands
|
|
229
|
+
|
|
230
|
+
The bot recognizes these natural language commands:
|
|
231
|
+
|
|
232
|
+
### Initialization
|
|
233
|
+
| Command | Aliases | Description |
|
|
234
|
+
|---------|---------|-------------|
|
|
235
|
+
| `start` | `begin`, `开始`, `初始化`, `你好` | Start the onboarding process |
|
|
236
|
+
|
|
237
|
+
### Learning Content
|
|
238
|
+
| Command | Aliases | Description |
|
|
239
|
+
|---------|---------|-------------|
|
|
240
|
+
| `keypoint` | `知识点`, `今天`, `today` | View today's knowledge point |
|
|
241
|
+
| `keypoint history` | `知识点 历史`, `昨天`, `yesterday` | View historical keypoints |
|
|
242
|
+
| `quiz` | `测验`, `test`, `测试` | Take today's quiz (once per day) |
|
|
243
|
+
|
|
244
|
+
### Progress & Stats
|
|
245
|
+
| Command | Aliases | Description |
|
|
246
|
+
|---------|---------|-------------|
|
|
247
|
+
| `stats` | `进度`, `统计`, `level`, `XP` | View learning progress |
|
|
248
|
+
| `errors` | `错题本`, `mistakes` | View error notebook (recent 5) |
|
|
249
|
+
| `errors more` | `错题本 更多` | Next 5 errors |
|
|
250
|
+
| `errors 2026-02` | `错题本 2026-02` | Filter by month |
|
|
251
|
+
| `errors random 5` | `错题本 随机5` | Random 5 for review |
|
|
252
|
+
| `errors stats` | `错题本 统计` | Show error statistics |
|
|
253
|
+
| `errors review` | `错题本 复习`, `错题复习` | Start error review session (5 questions) |
|
|
254
|
+
|
|
255
|
+
### Settings
|
|
256
|
+
| Command | Aliases | Description |
|
|
257
|
+
|---------|---------|-------------|
|
|
258
|
+
| `config` | `设置`, `preferences` | View current settings |
|
|
259
|
+
| `set level B2` | `设置等级 B2` | Change CEFR level |
|
|
260
|
+
| `set style professional` | `设置风格 专业` | Change tutor style |
|
|
261
|
+
| `schedule` | `时间表`, `推送时间` | View/change schedule |
|
|
262
|
+
|
|
263
|
+
### Help
|
|
264
|
+
| Command | Aliases | Description |
|
|
265
|
+
|---------|---------|-------------|
|
|
266
|
+
| `help` | `帮助`, `怎么用` | Show available commands |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Initialization Flow
|
|
271
|
+
|
|
272
|
+
The 7-step onboarding process:
|
|
273
|
+
1. CEFR Level
|
|
274
|
+
2. Topic Interests
|
|
275
|
+
3. Tutor Style
|
|
276
|
+
4. Oral/Written Ratio
|
|
277
|
+
5. Schedule
|
|
278
|
+
6. Voice Teaching
|
|
279
|
+
7. Confirm
|
|
280
|
+
|
|
281
|
+
Follow [templates/prompts/initialization.md](templates/prompts/initialization.md) exactly. Display ALL options with numbers (1, 2, 3...).
|
|
282
|
+
|
|
283
|
+
**Step 7 Completion:** Set `initialized=true` + Create cron jobs for keypoint/quiz push times.
|
|
284
|
+
|
|
285
|
+
**State Fields:**
|
|
286
|
+
- `initialized`: Boolean - Whether user completed onboarding
|
|
287
|
+
- `onboarding_step`: Integer (0-7) - Current step
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Response Scenarios
|
|
292
|
+
|
|
293
|
+
> **TIMEZONE AWARENESS:** All "today" date checks should use `state.json schedule.timezone` (default: Asia/Shanghai) to ensure consistent behavior across server locations. File paths like `daily/2026-02-21/` are timezone-specific.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## ⛔ MANDATORY BASH COMMANDS - READ THIS FIRST ⛔
|
|
298
|
+
|
|
299
|
+
**When generating content via LLM, you MUST execute bash commands to persist data to disk.**
|
|
300
|
+
|
|
301
|
+
### After Keypoint Generation (MANDATORY)
|
|
302
|
+
```
|
|
303
|
+
Step 1: LLM generates keypoint JSON
|
|
304
|
+
Step 2: ⛔ EXECUTE THIS BASH COMMAND (do NOT skip):
|
|
305
|
+
python3 -m scripts.cli.cli save_daily --content-type keypoint --content '<ESCAPED_JSON>'
|
|
306
|
+
(This auto-generates audio and saves to audio/YYYY-MM-DD/keypoint_full.mp3)
|
|
307
|
+
Step 3: ⛔ EXECUTE THIS BASH COMMAND (do NOT skip):
|
|
308
|
+
python3 -m scripts.cli.cli record_view
|
|
309
|
+
Step 4: Send audio file via message tool (if audio exists):
|
|
310
|
+
- Read keypoint.json and check if audio.composed field exists
|
|
311
|
+
- If exists, send audio file using message tool with media parameter
|
|
312
|
+
- Audio path: ~/.openclaw/state/eng-lang-tutor/{audio.composed}
|
|
313
|
+
Step 5: Display formatted content to user
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Audio File Sending (After Keypoint Save)
|
|
317
|
+
|
|
318
|
+
When keypoint is saved, audio is auto-generated. Send it to user with backward compatibility:
|
|
319
|
+
|
|
320
|
+
**Step 1: Check voice bubble capability**
|
|
321
|
+
```bash
|
|
322
|
+
echo $FEISHU_VOICE_BUBBLE_ENABLED
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Step 2a: If FEISHU_VOICE_BUBBLE_ENABLED=true (enhanced mode)**
|
|
326
|
+
|
|
327
|
+
Send BOTH voice bubble AND file attachment for best compatibility:
|
|
328
|
+
|
|
329
|
+
```json
|
|
330
|
+
// Voice bubble (handled by enhanced OpenClaw gateway)
|
|
331
|
+
{
|
|
332
|
+
"action": "send",
|
|
333
|
+
"media": "~/.openclaw/media/{audio.composed}",
|
|
334
|
+
"asVoice": true
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// File attachment (fallback for progress bar control)
|
|
338
|
+
{
|
|
339
|
+
"action": "send",
|
|
340
|
+
"media": "~/.openclaw/media/{audio.composed}",
|
|
341
|
+
"caption": "🔊 今日知识点语音版"
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Step 2b: If FEISHU_VOICE_BUBBLE_ENABLED not set or false (standard mode)**
|
|
346
|
+
|
|
347
|
+
Only send file attachment:
|
|
348
|
+
```json
|
|
349
|
+
{
|
|
350
|
+
"action": "send",
|
|
351
|
+
"media": "~/.openclaw/media/{audio.composed}",
|
|
352
|
+
"caption": "🔊 今日知识点语音版"
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Audio file info is stored in keypoint.json:**
|
|
357
|
+
```json
|
|
358
|
+
{
|
|
359
|
+
"audio": {
|
|
360
|
+
"composed": "eng-lang-tutor/2026-02-23/keypoint_full.mp3",
|
|
361
|
+
"duration_seconds": 37.7,
|
|
362
|
+
"generated_at": "2026-02-23T02:20:14"
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**IMPORTANT:**
|
|
368
|
+
- Audio is saved to `~/.openclaw/media/` (OpenClaw's allowed media directory)
|
|
369
|
+
- Always send audio file BEFORE displaying text content
|
|
370
|
+
- The `audio.composed` field contains the path relative to `~/.openclaw/media/`
|
|
371
|
+
- Enhanced mode (voice bubble) requires OpenClaw gateway patch for Feishu
|
|
372
|
+
|
|
373
|
+
### After Quiz Generation (MANDATORY)
|
|
374
|
+
```
|
|
375
|
+
Step 1: LLM generates quiz JSON
|
|
376
|
+
Step 2: ⛔ EXECUTE THIS BASH COMMAND (do NOT skip):
|
|
377
|
+
python3 -m scripts.cli.cli save_daily --content-type quiz --content '<ESCAPED_JSON>'
|
|
378
|
+
Step 3: Present quiz questions to user
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**JSON Escaping Rules:**
|
|
382
|
+
- Wrap content in single quotes: `'{"key": "value"}'`
|
|
383
|
+
- Escape internal single quotes: `'` → `'\''`
|
|
384
|
+
- Example: `'{"title": "It'\''s a test"}'`
|
|
385
|
+
|
|
386
|
+
**⛔ FAILURE TO EXECUTE BASH COMMANDS = DATA LOSS ⛔**
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
### Quiz Already Completed
|
|
391
|
+
```
|
|
392
|
+
User: "quiz"
|
|
393
|
+
Bot checks: completion_status.quiz_completed_date == today?
|
|
394
|
+
→ YES: "You've already completed today's quiz! 🎉 Score: X/Y"
|
|
395
|
+
→ NO: Check quiz.json exists (~/.openclaw/state/eng-lang-tutor/daily/YYYY-MM-DD/quiz.json) and quiz.generated == true?
|
|
396
|
+
→ YES: Load quiz and present questions
|
|
397
|
+
→ NO:
|
|
398
|
+
1. Check if keypoint.json exists for today
|
|
399
|
+
→ If NO: Generate keypoint via LLM first
|
|
400
|
+
→ ⛔ EXECUTE: python3 -m scripts.cli.cli save_daily --content-type keypoint --content '<ESCAPED_JSON>'
|
|
401
|
+
2. Generate quiz via LLM
|
|
402
|
+
3. Set generated=true in the JSON content
|
|
403
|
+
4. ⛔ EXECUTE: python3 -m scripts.cli.cli save_daily --content-type quiz --content '<ESCAPED_JSON>'
|
|
404
|
+
5. Present questions to user
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**⛔ CRITICAL: You MUST execute bash commands to save BEFORE presenting to user.**
|
|
408
|
+
|
|
409
|
+
### Manual Quiz Before Keypoint Push
|
|
410
|
+
```
|
|
411
|
+
User manually requests quiz before scheduled keypoint push time
|
|
412
|
+
Bot checks: Does keypoint.json exist for today?
|
|
413
|
+
→ NO:
|
|
414
|
+
1. IMMEDIATELY generate keypoint via LLM (do NOT say "will notify later")
|
|
415
|
+
2. ⛔ EXECUTE: python3 -m scripts.cli.cli save_daily --content-type keypoint --content '<ESCAPED_JSON>'
|
|
416
|
+
3. Generate quiz via LLM
|
|
417
|
+
4. ⛔ EXECUTE: python3 -m scripts.cli.cli save_daily --content-type quiz --content '<ESCAPED_JSON>'
|
|
418
|
+
5. Present quiz questions to user
|
|
419
|
+
→ All in ONE response - user should receive quiz immediately
|
|
420
|
+
→ YES: Proceed with quiz generation normally (see Quiz Already Completed section)
|
|
421
|
+
|
|
422
|
+
This ensures learning sequence is preserved even for early learners.
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**⛔ CRITICAL: NEVER tell user "will generate later and notify" - always generate immediately.**
|
|
426
|
+
**⛔ CRITICAL: You MUST execute the bash save commands BEFORE presenting content to user.**
|
|
427
|
+
|
|
428
|
+
### Keypoint Query
|
|
429
|
+
```
|
|
430
|
+
User: "keypoint" or "知识点" or Cron Push
|
|
431
|
+
Bot checks: Does keypoint.json exist for today (~/.openclaw/state/eng-lang-tutor/daily/YYYY-MM-DD/keypoint.json)?
|
|
432
|
+
→ NO:
|
|
433
|
+
1. Generate new keypoint via LLM
|
|
434
|
+
2. Set generated=true in the JSON content
|
|
435
|
+
3. ⛔ EXECUTE: python3 -m scripts.cli.cli save_daily --content-type keypoint --content '<ESCAPED_JSON>'
|
|
436
|
+
4. ⛔ EXECUTE: python3 -m scripts.cli.cli record_view
|
|
437
|
+
5. Send audio file via message tool (if audio.composed exists)
|
|
438
|
+
6. Display formatted content to user (REMOVE any [AUDIO:...] tags from text)
|
|
439
|
+
→ YES: Check keypoint.generated
|
|
440
|
+
→ TRUE: ⛔ EXECUTE: python3 -m scripts.cli.cli record_view, then send audio and display
|
|
441
|
+
→ FALSE: Follow steps 1-6 above
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
**⛔ CRITICAL:**
|
|
445
|
+
1. **You MUST execute bash commands to save BEFORE displaying to user**
|
|
446
|
+
2. **You MUST remove `[AUDIO:...]` tags from display text** - these are NOT supported and will show as plain text
|
|
447
|
+
3. **You SHOULD send audio via message tool** if `audio.composed` field exists
|
|
448
|
+
|
|
449
|
+
**Display Fields (from keypoint.json `display` object):**
|
|
450
|
+
|
|
451
|
+
| Field | Description |
|
|
452
|
+
|-------|-------------|
|
|
453
|
+
| `title` | Main title with emoji |
|
|
454
|
+
| `topic_tag` | Topic label |
|
|
455
|
+
| `formality_tag` | Formality level |
|
|
456
|
+
| `scene_text` | Scene description |
|
|
457
|
+
| `expressions_formatted` | Array of formatted expressions |
|
|
458
|
+
| `alternatives_formatted` | Bullet list of alternatives |
|
|
459
|
+
| `chinglish_formatted` | Wrong/Correct comparison |
|
|
460
|
+
| `examples_formatted` | Array of dialogue examples |
|
|
461
|
+
| `extended_formatted` | Extended learning content |
|
|
462
|
+
| `references_formatted` | Reference links |
|
|
463
|
+
| `footer` | Date and footer info |
|
|
464
|
+
|
|
465
|
+
> **IMPORTANT:**
|
|
466
|
+
> - Output assembled Markdown text directly, NOT JSON
|
|
467
|
+
> - **DO NOT display the `audio` field in text** - it's for message tool media sending only
|
|
468
|
+
> - See `templates/prompt_templates.md` Section 10.3 for full assembly template
|
|
469
|
+
|
|
470
|
+
### Keypoint History
|
|
471
|
+
```
|
|
472
|
+
User: "keypoint history" or "知识点 历史"
|
|
473
|
+
Bot scans: ~/.openclaw/state/eng-lang-tutor/daily/ directory for YYYY-MM-DD/keypoint.json files
|
|
474
|
+
→ NO files found: "📚 No history yet. Start learning with 'keypoint' today!"
|
|
475
|
+
→ YES: List keypoints (most recent first), max 10 entries:
|
|
476
|
+
- {date}: {title/topic} (e.g., "2026-02-20: Touch Base - 工作沟通")
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
**Display Format:**
|
|
480
|
+
```markdown
|
|
481
|
+
📚 **知识点历史记录**
|
|
482
|
+
|
|
483
|
+
| 日期 | 主题 | 查看 |
|
|
484
|
+
|------|------|------|
|
|
485
|
+
| 2026-02-20 | Touch Base - 工作沟通 | 输入 `keypoint 2026-02-20` |
|
|
486
|
+
| 2026-02-19 | Gonna/Wanna - 口语缩写 | 输入 `keypoint 2026-02-19` |
|
|
487
|
+
...
|
|
488
|
+
|
|
489
|
+
💡 输入 `keypoint 日期` 查看历史知识点详情
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### Historical Keypoint
|
|
493
|
+
```
|
|
494
|
+
User: "keypoint 昨天" or "keypoint 2026-02-19"
|
|
495
|
+
Bot checks: Does keypoint.json exist for that date?
|
|
496
|
+
→ YES: Display
|
|
497
|
+
→ NO: "No keypoint found for that date. Try 'keypoint today'."
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Config Display
|
|
501
|
+
```
|
|
502
|
+
User: "config" or "设置"
|
|
503
|
+
Bot reads: state.json preferences
|
|
504
|
+
Output: Card format with formatted text (see Output Format below)
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### Stats Display
|
|
508
|
+
```
|
|
509
|
+
User: "stats" or "进度"
|
|
510
|
+
Bot reads: state.json user + progress
|
|
511
|
+
Output: Card format with emoji and formatted text
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## Response Output Format
|
|
517
|
+
|
|
518
|
+
> IMPORTANT: All responses use platform-agnostic Markdown format. See `templates/prompt_templates.md` Section 10 for detailed formatting rules and `examples/` for sample outputs.
|
|
519
|
+
|
|
520
|
+
### Quick Reference
|
|
521
|
+
|
|
522
|
+
- **Format**: Standard Markdown (compatible with Feishu, Discord, Telegram, Slack)
|
|
523
|
+
- **Bold**: `**text**`
|
|
524
|
+
- **Links**: `[text](url)`
|
|
525
|
+
- **Emojis**: Use liberally for visual sections
|
|
526
|
+
- **Dividers**: `───────────────────`
|
|
527
|
+
|
|
528
|
+
### Response Templates
|
|
529
|
+
|
|
530
|
+
All response templates are documented in `templates/prompt_templates.md` Section 10:
|
|
531
|
+
|
|
532
|
+
| Template | Section | Description |
|
|
533
|
+
|----------|---------|-------------|
|
|
534
|
+
| Keypoint Display | 10.3 | Daily knowledge point output |
|
|
535
|
+
| Stats Display | 10.4 | Learning progress stats |
|
|
536
|
+
| Config Display | 10.5 | User settings display |
|
|
537
|
+
| Errors Display | 10.6 | Error notebook (paginated) |
|
|
538
|
+
| Error Review | 10.7 | Error review session flow |
|
|
539
|
+
| Quiz Result | 10.8 | Quiz completion results |
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
## Completion Tracking
|
|
544
|
+
|
|
545
|
+
### State Fields
|
|
546
|
+
|
|
547
|
+
```json
|
|
548
|
+
{
|
|
549
|
+
"completion_status": {
|
|
550
|
+
"quiz_completed_date": "2026-02-20",
|
|
551
|
+
"keypoint_view_history": [
|
|
552
|
+
{"date": "2026-02-20", "viewed_at": "2026-02-20T06:45:00"}
|
|
553
|
+
]
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Rules
|
|
559
|
+
|
|
560
|
+
1. **Quiz**: Can only take once per day (resets at midnight)
|
|
561
|
+
2. **Keypoint**: Can view multiple times (including historical pushed keypoints)
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## Cron Configuration
|
|
566
|
+
|
|
567
|
+
### Default Schedule (UTC+8 / Asia/Shanghai)
|
|
568
|
+
|
|
569
|
+
| Task | Default Time | Description |
|
|
570
|
+
|------|--------------|-------------|
|
|
571
|
+
| Keypoint Push | 06:45 | Daily knowledge point |
|
|
572
|
+
| Quiz Push | 22:45 | Daily quiz |
|
|
573
|
+
|
|
574
|
+
### Crontab Template
|
|
575
|
+
|
|
576
|
+
```bash
|
|
577
|
+
# /etc/cron.d/eng-lang-tutor
|
|
578
|
+
CRON_TZ=Asia/Shanghai
|
|
579
|
+
|
|
580
|
+
# 6:45 AM - Keypoint push
|
|
581
|
+
45 6 * * * openclaw agent --channel discord --message "☕ Good morning!" --agent eng-lang-tutor
|
|
582
|
+
|
|
583
|
+
# 10:45 PM - Quiz push
|
|
584
|
+
45 22 * * * openclaw agent --channel discord --message "🌙 Quiz time!" --agent eng-lang-tutor
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### User-Customizable Schedule
|
|
588
|
+
|
|
589
|
+
Users can customize their schedule via commands:
|
|
590
|
+
```
|
|
591
|
+
set schedule keypoint 7:00
|
|
592
|
+
set schedule quiz 21:00
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Stored in `state.json`:
|
|
596
|
+
```json
|
|
597
|
+
{
|
|
598
|
+
"schedule": {
|
|
599
|
+
"keypoint_time": "07:00",
|
|
600
|
+
"quiz_time": "21:00",
|
|
601
|
+
"timezone": "Asia/Shanghai"
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
## Additional Scripts
|
|
608
|
+
|
|
609
|
+
| Script | Purpose |
|
|
610
|
+
|--------|---------|
|
|
611
|
+
| cli/command_parser.py | Parse user messages to determine intent |
|
|
612
|
+
| scheduling/cron_push.py | Handle scheduled content generation |
|
|
613
|
+
|