{"id":"7cd7d2bb-7695-4112-90eb-d9e35848adf7","entityType":"agent","slug":"clawhub-pandaltsgo-the-english-tutor","name":"The English Tutor","canonicalUrl":"https://www.xpersona.co/agent/clawhub-pandaltsgo-the-english-tutor","canonicalPath":"/agent/clawhub-pandaltsgo-the-english-tutor","generatedAt":"2026-10-13T05:58:00.554Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T00:19:58.817Z","emptyReason":null},"description":"英语口语陪练助手。触发词：「练习英语」「我要说英语」「英语陪练」。功能：上传生词表 → 每日定时情景对话 → 语音输入即时纠错 → 飞书语音推送 → 自动艾宾浩斯复习。","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 969 downloads reported by the source. Last updated 10/12/2026.","installCommand":"clawhub skill install s17761jw9y1e7ynw7f9xfz3a7585k0qb:the-english-tutor","sourceUrl":"https://clawhub.ai/pandaltsgo/the-english-tutor","homepage":"https://clawhub.ai/pandaltsgo/skills/the-english-tutor","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/pandaltsgo/the-english-tutor","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/pandaltsgo/skills/the-english-tutor","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"The English Tutor technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-12T00:19:58.817Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T00:19:58.817Z","emptyReason":null},"stars":null,"forks":null,"downloads":969,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"3.0.4","tractionLabel":"969 downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T00:19:58.803Z","emptyReason":null},"lastUpdatedAt":"2026-10-12T00:19:58.817Z","lastCrawledAt":"2026-10-12T00:19:58.803Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-13T00:19:58.803Z","lastVerifiedAt":null,"highlights":[{"version":"3.0.4","createdAt":"2026-05-10T15:13:53.498Z","changelog":"Security hardening: remove hardcoded API keys, add null guards, cross-platform paths, stop-word filtering, logging module, all-optional config check","fileCount":16,"zipByteSize":36516},{"version":"3.0.3","createdAt":"2026-05-07T15:26:31.895Z","changelog":"Version 3.0.3 of \"the-english-tutor\" skill - 最新版本，修复部分提示词","fileCount":15,"zipByteSize":34107},{"version":"3.0.2","createdAt":"2026-05-03T14:26:42.608Z","changelog":"3.0.2: 删除 morning-task-v2.js（内含硬编码密钥，已清理）；删除 local-tts.js/asr.js/feishu-voice.js（已由 scripts/ 纯 Python 版替代）；agent.js 重构为纯文本逻辑无 exec；config_manager.py 写入时脱敏；彻底清除所有 exposed_secret_literal 和 dangerous_exec 模式。","fileCount":15,"zipByteSize":33721},{"version":"3.0.1","createdAt":"2026-05-03T14:21:56.221Z","changelog":"3.0.1: feishu_voice.py 改为纯 Python 实现（无 Node.js subprocess）；config_manager.py 写入时自动脱敏敏感字段；删除 download_model.sh；修复 exposed_secret_literal 和 dangerous_exec 问题。","fileCount":19,"zipByteSize":46120},{"version":"3.0.0","createdAt":"2026-05-03T14:10:24.692Z","changelog":"3.0.0: 重构为基座 Skill，所有环境变量可选。模块化设计，缺失静默跳过。","fileCount":20,"zipByteSize":44543},{"version":"2.0.1","createdAt":"2026-05-02T05:40:47.574Z","changelog":"修复凭证处理合规问题：移除磁盘写.env，改为内存env参数传递；check_env.py全部使用subprocess列表形式无shell=True；Python代码块JSON.stringify防注入","fileCount":11,"zipByteSize":20786},{"version":"2.0.0","createdAt":"2026-04-28T00:30:52.248Z","changelog":"English Tutor 1.0.1 — major update with new features and architecture - Added essential scripts for configuration, Feishu voice integration, and wordlist parsing. - Refactored skill documentation for clarity: now details flow, modules, environment variables, and setup. - Added support for uploading custom wordlists and daily scenario-based practice sessions. - Introduced intelligent Ebbinghaus-based vocabulary review with multi-dimensional table tracking. - Enhanced voice interaction: text-to-speech outputs (via Feishu), local/offline TTS/ASR fallback logic. - Modularized the skill with clear APIs for main agent logic, Feishu messaging, local TTS, ASR, and memory.","fileCount":10,"zipByteSize":19734},{"version":"1.0.0","createdAt":"2026-04-26T23:46:40.942Z","changelog":"English Tutor 1.0.0 — Initial Release - Added local and online ASR (automatic speech recognition) setup guides, with model download and verification scripts. - Introduced TTS (text to speech) options including piper, espeak-ng, gTTS, and several online providers, with detailed environment variable instructions. - Provided spoken English practice and correction workflow, with Chinese explanations attached to each response. - Included Ebbinghaus-based vocabulary review system. - Added scripts for environment check, model download, and transcription.","fileCount":6,"zipByteSize":10092}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17761jw9y1e7ynw7f9xfz3a7585k0qb:the-english-tutor","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17761jw9y1e7ynw7f9xfz3a7585k0qb:the-english-tutor` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/pandaltsgo/the-english-tutor before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-13T05:58:00.552Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pandaltsgo-the-english-tutor/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T00:19:58.817Z","emptyReason":null},"readme":"Skill: The English Tutor\n\nOwner: pandaltsgo\n\nSummary: 英语口语陪练助手。触发词：「练习英语」「我要说英语」「英语陪练」。功能：上传生词表 → 每日定时情景对话 → 语音输入即时纠错 → 飞书语音推送 → 自动艾宾浩斯复习。\n\nTags: asr:3.0.4, english:3.0.4, latest:3.0.4, learning:3.0.4, spaced-repetition:3.0.4, tts:3.0.4\n\nVersion history:\n\nv3.0.4 | 2026-05-10T15:13:53.498Z | user\n\nSecurity hardening: remove hardcoded API keys, add null guards, cross-platform paths, stop-word filtering, logging module, all-optional config check\n\nv3.0.3 | 2026-05-07T15:26:31.895Z | user\n\nVersion 3.0.3 of \"the-english-tutor\" skill\n\n- 最新版本，修复部分提示词\n\nv3.0.2 | 2026-05-03T14:26:42.608Z | user\n\n3.0.2: 删除 morning-task-v2.js（内含硬编码密钥，已清理）；删除 local-tts.js/asr.js/feishu-voice.js（已由 scripts/ 纯 Python 版替代）；agent.js 重构为纯文本逻辑无 exec；config_manager.py 写入时脱敏；彻底清除所有 exposed_secret_literal 和 dangerous_exec 模式。\n\nv3.0.1 | 2026-05-03T14:21:56.221Z | user\n\n3.0.1: feishu_voice.py 改为纯 Python 实现（无 Node.js subprocess）；config_manager.py 写入时自动脱敏敏感字段；删除 download_model.sh；修复 exposed_secret_literal 和 dangerous_exec 问题。\n\nv3.0.0 | 2026-05-03T14:10:24.692Z | user\n\n3.0.0: 重构为基座 Skill，所有环境变量可选。模块化设计，缺失静默跳过。\n\nv2.0.1 | 2026-05-02T05:40:47.574Z | user\n\n修复凭证处理合规问题：移除磁盘写.env，改为内存env参数传递；check_env.py全部使用subprocess列表形式无shell=True；Python代码块JSON.stringify防注入\n\nv2.0.0 | 2026-04-28T00:30:52.248Z | user\n\nEnglish Tutor 1.0.1 — major update with new features and architecture\n\n- Added essential scripts for configuration, Feishu voice integration, and wordlist parsing.\n- Refactored skill documentation for clarity: now details flow, modules, environment variables, and setup.\n- Added support for uploading custom wordlists and daily scenario-based practice sessions.\n- Introduced intelligent Ebbinghaus-based vocabulary review with multi-dimensional table tracking.\n- Enhanced voice interaction: text-to-speech outputs (via Feishu), local/offline TTS/ASR fallback logic.\n- Modularized the skill with clear APIs for main agent logic, Feishu messaging, local TTS, ASR, and memory.\n\nv1.0.0 | 2026-04-26T23:46:40.942Z | user\n\nEnglish Tutor 1.0.0 — Initial Release\n\n- Added local and online ASR (automatic speech recognition) setup guides, with model download and verification scripts.\n- Introduced TTS (text to speech) options including piper, espeak-ng, gTTS, and several online providers, with detailed environment variable instructions.\n- Provided spoken English practice and correction workflow, with Chinese explanations attached to each response.\n- Included Ebbinghaus-based vocabulary review system.\n- Added scripts for environment check, model download, and transcription.\n\nArchive index:\n\nArchive v3.0.4: 16 files, 36516 bytes\n\nFiles: _meta.json (136b), agent/agent.js (11569b), agent/config.js (2964b), agent/memory.js (5946b), agent/minimax.js (6573b), assets/wordlist_example.csv (812b), metadata.json (5408b), references/config-schema.md (5438b), scripts/check_env.py (6407b), scripts/config_manager.py (5451b), scripts/download_model.py (1966b), scripts/feishu_voice.py (13420b), scripts/transcribe.py (6042b), scripts/wordlist_parser.py (4937b), skill-card.md (2906b), SKILL.md (7952b)\n\nFile v3.0.4:SKILL.md\n\n# 英语助教 · English Tutor Skill\n\n> **模块化基座 Skill** — 功能按需配置，所有环境变量均为**选填**。\n> 有配置就启用对应功能，无配置则跳过。完整功能需要飞书 + MiniMax + 多维表格。\n\n---\n\n## 功能模块（按需启用）\n\n| 模块 | 环境变量 | 说明 |\n|------|---------|------|\n| 飞书语音推送 | `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `FEISHU_USER_OPEN_ID` | 发 TTS 语音到飞书 |\n| MiniMax TTS | `MINIMAX_API_KEY` | 云端语音合成（主方案） |\n| Piper 本地 TTS | `PIPER_BIN`, `PIPER_MODEL` | 完全离线的语音兜底 |\n| SenseVoice 本地 ASR | `SENSE_VOICE_MODEL_DIR` | 完全离线的语音识别 |\n| 多维表格记忆 | `BITABLE_APP_TOKEN`, `BITABLE_WORDS_TABLE_ID`, `BITABLE_CHAT_TABLE_ID` | 单词记录 + 艾宾浩斯 |\n| 定时推送 | cron jobs | 08:00 / 12:00 / 20:00（可单独开启） |\n\n**原则**：填了变量 → 启用该模块；没填 → 该模块静默跳过，不报错。\n\n---\n\n## 文件结构\n\n```\nenglish-tutor/\n├── SKILL.md\n├── metadata.json\n├── _meta.json\n├── agent/                    ← 核心 Node.js 运行时\n│   ├── config.js             ← 配置（全部选填，env 注入）\n│   ├── minimax.js            ← MiniMax TTS + Chat API\n│   ├── memory.js             ← 多维表格记忆（可选）\n│   └── agent.js              ← 主流程入口\n├── scripts/                  ← Python 辅助脚本\n│   ├── check_env.py          ← 环境检测\n│   ├── config_manager.py     ← 配置管理\n│   ├── download_model.py     ← SenseVoice 模型下载\n│   ├── feishu_voice.py       ← 飞书语音发送（TTS→Opus→上传→发送）\n│   ├── transcribe.py         ← ASR 转录（本地/云端）\n│   └── wordlist_parser.py    ← 单词表解析器\n├── references/\n│   └── config-schema.md\n└── assets/\n    └── wordlist_example.csv\n```\n\n---\n\n## 环境变量（全部选填）\n\n### 飞书模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `FEISHU_APP_ID` | `\"\"` | 飞书应用 App ID（填了才发飞书语音） |\n| `FEISHU_APP_SECRET` | `\"\"` | 飞书应用 Secret |\n| `FEISHU_USER_OPEN_ID` | `\"\"` | 接收语音的飞书用户 Open ID |\n\n### TTS 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `MINIMAX_API_KEY` | `\"\"` | MiniMax API Key（不填则跳过云端 TTS） |\n| `MINIMAX_TTS_MODEL` | `speech-2.8-hd` | TTS 模型 |\n| `MINIMAX_TTS_SPEED` | `1.05` | 语速 |\n| `MINIMAX_TTS_VOICE_ID` | `male-qn-qingse` | 音色 ID |\n| `PIPER_BIN` | `\"\"` | Piper 主程序路径（不填则跳过本地 TTS） |\n| `PIPER_MODEL` | `\"\"` | Piper ONNX 模型路径 |\n| `TTS_PROVIDER` | `minimax` | 优先方案：`minimax` / `piper` |\n\n### ASR 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `SENSE_VOICE_MODEL_DIR` | `\"\"` | SenseVoice 模型目录（不填则跳过本地 ASR） |\n\n### 多维表格模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `BITABLE_APP_TOKEN` | `\"\"` | App Token（不填则无艾宾浩斯记忆） |\n| `BITABLE_WORDS_TABLE_ID` | `\"\"` | words 表 ID |\n| `BITABLE_CHAT_TABLE_ID` | `\"\"` | chat_log 表 ID |\n\n### 每日练习配置\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `DAILY_WORD_MAX` | `15` | 每日新词上限 |\n\n---\n\n## 凭据声明（metadata）\n\n本 skill 为 **Credential-Using Skill**，但**所有凭据均为选填**：\n\n```json\n{\n  \"credential_using\": true,\n  \"required_credentials\": [],\n  \"optional_credentials\": [\n    { \"name\": \"FEISHU_APP_ID\",      \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_APP_SECRET\",  \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_USER_OPEN_ID\",\"description\": \"飞书语音推送\" },\n    { \"name\": \"MINIMAX_API_KEY\",    \"description\": \"云端 TTS + LLM 对话\" },\n    { \"name\": \"BITABLE_APP_TOKEN\",  \"description\": \"艾宾浩斯记忆（可选）\" },\n    { \"name\": \"BITABLE_WORDS_TABLE_ID\", \"description\": \"单词记录表\" },\n    { \"name\": \"BITABLE_CHAT_TABLE_ID\",  \"description\": \"对话历史表\" }\n  ]\n}\n```\n\n---\n\n## 定时任务\n\n| 时间 | cron | 说明 |\n|------|------|------|\n| 晨间 | `0 8 * * *` | 通勤场景跟读 |\n| 午间 | `0 12 * * *` | 口语问答 |\n| 晚间 | `0 20 * * *` | 复盘 + 旧词复习 |\n\n**定时任务默认关闭**，用户在引导设置中自行选择开启哪些。\n\n---\n\n## 引导设置流程（用户可选配置）\n\n### 第 1 步：飞书配置（选填）\n- 提供 `FEISHU_APP_ID` / `FEISHU_APP_SECRET` / `FEISHU_USER_OPEN_ID`\n- 不填则无飞书语音推送功能\n\n### 第 2 步：TTS 配置（选填）\n- MiniMax：提供 `MINIMAX_API_KEY`\n- Piper 本地：提供 `PIPER_BIN` / `PIPER_MODEL`\n- 都不填则 TTS 功能不可用（仍有文字对话）\n\n### 第 3 步：ASR 配置（选填）\n- 提供 `SENSE_VOICE_MODEL_DIR`（或运行 `python3 scripts/download_model.py`）\n- 不填则无法处理语音输入（仅支持文字）\n\n### 第 4 步：多维表格（选填）\n- 提供 `BITABLE_APP_TOKEN` + 两个表 ID\n- 不填则无艾宾浩斯记忆功能（仍可练习，但不记录进度）\n\n### 第 5 步：每日定时（选填）\n- 选择开启哪些时段（08:00 / 12:00 / 20:00）\n- 不选择则不创建 cron 任务\n\n### 第 6 步：上传单词表（选填）\n- CSV 或纯文本格式\n- 不上传也可进行自由对话练习\n\n---\n\n## 核心模块说明\n\n### feishu_voice.py — 飞书语音发送\n- 优先 MiniMax TTS，配额耗尽自动切换 Piper\n- 无任何凭据配置时：静默跳过，不报错\n- 流程：TTS → ffmpeg 转 Opus → 上传飞书 → 发送 audio 消息\n\n### transcribe.py — ASR 转录\n- 本地 SenseVoice（默认），也支持 AssemblyAI/OpenAI Whisper\n- 无本地模型时：回退到文字输入模式\n- 使用列表形式 subprocess，无 shell 注入\n\n### memory.js — 多维表格\n- 无多维表格配置时：`_isReady()` 返回 false，所有方法静默跳过\n- 所有操作有 try/catch，不因单次失败中断流程\n\n### agent.js — 主流程\n- **课程模式**（定时触发，无用户输入）：自动生成跟读对话，逐条发飞书语音\n- **交互模式**（用户发消息）：实时对话 + 可选 TTS 回复\n- 所有模块都是**失败静默跳过**，不影响其他模块运行\n\n---\n\n## 安全设计原则\n\n1. **所有密钥通过环境变量注入**，不硬编码\n2. **feishu_voice.py**：配置通过 `env=` 参数传递给 Node.js 子进程（内存传递）\n3. **scripts/ 无 shell=True**：subprocess 使用列表形式\n4. **config.json 权限**：`~/.openclaw/english-tutor/config.json` 设为 `600`\n5. **全部源码纳入 skill 包**，审查者可查看全部代码（agent/ + scripts/）\n\n---\n\n## 模型下载命令\n\n### Piper TTS（本地语音合成）\n\n```bash\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/piper/voices\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\n```\n\n### SenseVoice ASR（本地语音识别）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\npython3 /vol1/@apphome/trim.openclaw/data/workspace/skills/english-tutor/scripts/download_model.py\n```\n\n---\n\n## 单词表格式\n\n**CSV（推荐）：**\n```csv\nword,pronunciation,meaning,example\ncommute,/kəˈmjuːt/,通勤,I commute by subway every day.\n```\n\n**纯文本（每行一个）：**\n```\ncommute,通勤\nsubway,地铁\ntransfer,换乘\n```\n\n---\n\n## 艾宾浩斯复习周期\n\n| 复习轮次 | 间隔 |\n|---------|------|\n| 第 1 次 | 次日 |\n| 第 2 次 | 3 天后 |\n| 第 3 次 | 7 天后 |\n| 第 4 次 | 15 天后 |\n| 第 5 次+ | 掌握（不再自动提醒）|\n\nFile v3.0.4:_meta.json\n\n{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"3.0.4\",\n  \"publishedAt\": 1778426033498\n}\n\nFile v3.0.4:references/config-schema.md\n\n# English Tutor · 完整配置参考\n\n## 配置存储\n\n用户配置统一保存在 `~/.openclaw/english-tutor/config.json`，由 `scripts/config_manager.py` 管理。\n\n**首次由陪练助手通过对话引导创建，无需手动编辑。**\n\n---\n\n## config.json 字段说明\n\n### 基础配置\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `setup_complete` | ✅ | `false` | 首次设置是否完成 |\n| `word_list_path` | ✅ | `\"\"` | 单词表 JSON 文件路径 |\n| `daily_words` | ✅ | `5` | 每日练习单词数量（建议 5-15）|\n| `schedule_times` | ✅ | `[\"08:00\"]` | 每日推送时间（上海时区）|\n\n### LLM 模型配置 🤖\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `llm_provider` | ✅ | `\"openclaw\"` | 模型提供商：`openclaw` / `minimax` / `openai` |\n| `llm_model` | 否 | `\"\"` | 指定模型 ID（留空用默认）|\n\n> 选择 `openclaw` 时使用系统默认 LLM，无需额外配置。\n\n### 飞书语音配置 📢\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `feishu_app_id` | ✅ | `\"\"` | 飞书应用 App ID |\n| `feishu_app_secret` | ✅ | `\"\"` | 飞书应用 App Secret |\n| `feishu_bot_token` | 否 | `\"\"` | 飞书 Bot Token（可选）|\n| `feishu_user_open_id` | ✅ | `\"\"` | 接收消息的用户 Open ID |\n\n### TTS 语音合成 🔊\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `tts_provider` | 否 | `\"minimax\"` | TTS 方案：`minimax` / `piper` / `espeak` |\n| `minimax_api_key` | minimax时 | `\"\"` | MiniMax API Key |\n\n> MiniMax TTS 有 API Key 时推荐音色：`male-qn-qingse`（男声）、`female-tianmei`（女声）；无 Key 时静默跳过，可配 Piper 本地兜底\n\n### 多维表格（可选）\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `bitable_app_token` | 否 | `\"\"` | 飞书多维表格 App Token |\n| `bitable_words_table_id` | 否 | `\"\"` | words 表 ID |\n| `bitable_chat_table_id` | 否 | `\"\"` | chat_log 表 ID |\n\n### Piper 本地 TTS（可选）\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `piper_bin` | piper时 | piper 二进制路径 |\n| `piper_model` | piper时 | .onnx 模型文件路径 |\n\n---\n\n## 飞书 audio 消息发送流程\n\n每日练习第一步，通过 `scripts/feishu_voice.py` 实现：\n\n```\n1. TTS 合成 mp3\n   - minimax: POST /v1/t2a_v2 → hex audio → 解码为 mp3\n   - piper:   piper CLI → WAV\n   \n2. ffmpeg 转 opus\n   ffmpeg -i input.mp3 -ar 16000 -ac 1 -acodec libopus -b:a 128k output.opus\n\n3. 上传获取 file_key\n   POST /open-apis/im/v1/files\n   Content-Type: multipart/form-data; boundary=...\n   body: file_type=opus, file=opus二进制\n\n4. 发送 audio 消息\n   POST /open-apis/im/v1/messages?receive_id_type=open_id\n   {\n     \"receive_id\": \"<user_open_id>\",\n     \"msg_type\": \"audio\",\n     \"content\": \"{\\\"file_key\\\": \\\"<file_key>\\\"}\"\n   }\n```\n\n**使用示例：**\n```bash\n# 使用配置发送语音\npython3 scripts/feishu_voice.py \"Good morning! Today's vocabulary: commute, subway, transfer.\"\n\n# 使用配置（指定路径）\npython3 scripts/feishu_voice.py \"Hello!\" --config /path/to/config.json\n\n# 仅合成，不发送（调试用）\npython3 scripts/feishu_voice.py \"Hello!\" --dry-run\n```\n\n---\n\n## TTS_PROVIDER 配置\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n### piper（本地，高质量，离线）\n\n**下载主程序（Linux x86_64）：**\n```bash\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n```\n\n**下载英语模型（Lessac Medium，音质好，速度快）：**\n```bash\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /tmp/en_US-lessac-medium.onnx\n```\n\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/tmp/piper/piper_phonemize\nPIPER_MODEL=/tmp/en_US-lessac-medium.onnx\n```\n\n**测试：**\n```bash\necho \"Hello world\" | /tmp/piper/piper_phonemize \\\n  --model /tmp/en_US-lessac-medium.onnx \\\n  --input-file /dev/stdin -w /tmp/test.wav\n```\n\n### espeak-ng（系统级，完全离线）\n\n```bash\nsudo apt-get install espeak-ng\n```\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n---\n\n## ASR_PROVIDER 配置\n\n### local（默认，推荐，完全离线）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\nbash scripts/download_model.sh\n```\n\n### assemblyai / openai（云端）\n\n```env\nASR_PROVIDER=assemblyai\nASR_API_KEY=your-key\n```\n\n---\n\n## 多维表格表结构（可选）\n\n**表 1：单词表（words）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| word | 文本 | 英文单词 |\n| pronunciation | 文本 | 音标 |\n| meaning | 文本 | 中文释义 |\n| example | 文本 | 例句 |\n| mastery | 数字 | 掌握程度 0-5 |\n| review_count | 数字 | 复习次数 |\n| last_review | 日期时间 | 最近复习时间 |\n| next_review | 日期时间 | 下次复习时间 |\n| user_id | 文本 | 用户 ID |\n\n**表 2：对话记录（chat_log）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| user_id | 文本 | 用户 ID |\n| role | 单选 | `ai` 或 `user` |\n| text | 文本 | 对话内容 |\n| voice_url | 文本 | 语音 URL（可选）|\n| created_at | 日期时间 | 创建时间 |\n\nFile v3.0.4:skill-card.md\n\n## Description:\n\nThe English Tutor helps learners practice spoken English with optional word-list review, timed scenario dialogs, speech transcription, text-to-speech, Feishu voice delivery, and Bitable memory.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[pandaltsgo](https://clawhub.ai/user/pandaltsgo)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nLearners use this agent to rehearse short American English conversations, upload vocabulary lists, receive optional scheduled practice prompts, and review words with spaced repetition. Developers or advanced users configure Feishu, MiniMax, Piper, SenseVoice, and Bitable integrations according to the deployment environment.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles private voice, chat, learning records, and service credentials.\n\nMitigation: Configure only trusted Feishu, MiniMax, and ASR providers; store secrets through environment variables or secured configuration; avoid passing secrets as command-line arguments.\n\nRisk: Optional Bitable memory stores chat and vocabulary records outside the local agent environment.\n\nMitigation: Enable Bitable memory only when external storage of practice data is acceptable, and limit stored content to learning records needed for review.\n\nRisk: Optional Piper and SenseVoice setup downloads external binaries or model artifacts.\n\nMitigation: Verify downloaded artifacts before use, prefer a virtual environment with pinned dependencies, and review downloaded files according to local security policy.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/pandaltsgo/skills/the-english-tutor)\n- [Configuration schema](references/config-schema.md)\n- [MiniMax TTS API reference](https://platform.minimaxi.com/docs/api-reference/speech-t2a-http)\n- [Piper TTS release v1.2.0](https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz)\n- [Piper English voice model](https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx)\n- [SenseVoice model files](https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/model.onnx)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown and plain text with optional JSON status from helper scripts]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Feishu audio-message results or skipped status when voice delivery is configured.]\n\n## Skill Version(s):\n\n3.0.4 (source: server release and artifact metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v3.0.4:metadata.json\n\n{\n  \"name\": \"english-tutor\",\n  \"version\": \"3.0.4\",\n  \"description\": \"英语口语陪练基座。飞书语音推送 + MiniMax/本地 TTS + SenseVoice ASR + 艾宾浩斯复习。全部模块选填，按需启用。\",\n  \"credential_using\": true,\n  \"all_optional\": true,\n  \"optional_credentials\": [\n    {\n      \"name\": \"FEISHU_APP_ID\",\n      \"type\": \"feishu_app_id\",\n      \"required\": false,\n      \"description\": \"飞书应用 App ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_APP_SECRET\",\n      \"type\": \"feishu_app_secret\",\n      \"required\": false,\n      \"description\": \"飞书应用 Secret（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_USER_OPEN_ID\",\n      \"type\": \"feishu_open_id\",\n      \"required\": false,\n      \"description\": \"接收语音的飞书用户 Open ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"MINIMAX_API_KEY\",\n      \"type\": \"api_key\",\n      \"required\": false,\n      \"description\": \"MiniMax API Key（填了启用云端 TTS，不填则跳过）\"\n    },\n    {\n      \"name\": \"PIPER_BIN\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper 主程序路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"PIPER_MODEL\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper ONNX 模型路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"SENSE_VOICE_MODEL_DIR\",\n      \"type\": \"directory_path\",\n      \"required\": false,\n      \"description\": \"SenseVoice 模型目录（填了启用本地 ASR，不填则跳过）\"\n    },\n    {\n      \"name\": \"BITABLE_APP_TOKEN\",\n      \"type\": \"feishu_bitable_token\",\n      \"required\": false,\n      \"description\": \"飞书多维表格 App Token（不填则无艾宾浩斯记忆）\"\n    },\n    {\n      \"name\": \"BITABLE_WORDS_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"words 表 ID（单词记录表）\"\n    },\n    {\n      \"name\": \"BITABLE_CHAT_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"chat_log 表 ID（对话历史表）\"\n    }\n  ],\n  \"module_design\": {\n    \"principle\": \"填了变量启用该模块，没填则静默跳过，不报错\",\n    \"modules\": [\n      {\n        \"name\": \"飞书语音推送\",\n        \"env\": [\"FEISHU_APP_ID\", \"FEISHU_APP_SECRET\", \"FEISHU_USER_OPEN_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不发飞书语音\"\n      },\n      {\n        \"name\": \"MiniMax TTS\",\n        \"env\": [\"MINIMAX_API_KEY\"],\n        \"behavior_when_empty\": \"静默跳过，尝试 Piper 本地 TTS\"\n      },\n      {\n        \"name\": \"Piper 本地 TTS\",\n        \"env\": [\"PIPER_BIN\", \"PIPER_MODEL\"],\n        \"behavior_when_empty\": \"静默跳过，无 TTS 功能\"\n      },\n      {\n        \"name\": \"SenseVoice 本地 ASR\",\n        \"env\": [\"SENSE_VOICE_MODEL_DIR\"],\n        \"behavior_when_empty\": \"静默跳过，仅支持文字输入\"\n      },\n      {\n        \"name\": \"多维表格记忆\",\n        \"env\": [\"BITABLE_APP_TOKEN\", \"BITABLE_WORDS_TABLE_ID\", \"BITABLE_CHAT_TABLE_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不记录学习进度\"\n      }\n    ]\n  },\n  \"scheduled_actions\": [\n    {\n      \"name\": \"每日晨间练习 08:00\",\n      \"cron\": \"0 8 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"用户选择开启后，自动生成跟读对话，发飞书语音，等待用户回复\"\n    },\n    {\n      \"name\": \"每日午间练习 12:00\",\n      \"cron\": \"0 12 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    },\n    {\n      \"name\": \"每日晚间练习 20:00\",\n      \"cron\": \"0 20 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    }\n  ],\n  \"data_storage\": {\n    \"conversation_history\": {\n      \"location\": \"飞书多维表格（BITABLE_APP_TOKEN 指向的多维表格）\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"user_id\", \"role\", \"text\", \"voice_url\", \"created_at\"],\n      \"note\": \"口语练习对话内容和语音 URL 会被存储用于艾宾浩斯复习\"\n    },\n    \"word_records\": {\n      \"location\": \"飞书多维表格\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"word\", \"user_id\", \"first_seen\", \"last_review\", \"next_review\", \"review_count\", \"mastery\", \"source\"]\n    },\n    \"config_file\": {\n      \"location\": \"~/.openclaw/english-tutor/config.json\",\n      \"sensitive\": true,\n      \"permission\": \"600\",\n      \"enabled\": \"always\"\n    }\n  },\n  \"external_downloads\": [\n    {\n      \"name\": \"Piper TTS\",\n      \"urls\": [\n        \"https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz\",\n        \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 TTS 兜底方案。下载后建议校验 SHA256：sha256sum piper_amd64.tar.gz en_US-lessac-medium.onnx\"\n    },\n    {\n      \"name\": \"SenseVoice ASR\",\n      \"urls\": [\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/model.onnx\",\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/tokens.txt\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 ASR，下载后建议校验 SHA256：sha256sum model.onnx tokens.txt\"\n    }\n  ]\n}\n\nArchive v3.0.3: 15 files, 34107 bytes\n\nFiles: agent/agent.js (11191b), agent/config.js (2739b), agent/memory.js (5655b), agent/minimax.js (6468b), assets/wordlist_example.csv (812b), metadata.json (5330b), references/config-schema.md (5438b), scripts/check_env.py (6407b), scripts/config_manager.py (4775b), scripts/download_model.py (1966b), scripts/feishu_voice.py (13287b), scripts/transcribe.py (5994b), scripts/wordlist_parser.py (4937b), SKILL.md (7523b), _meta.json (136b)\n\nFile v3.0.3:SKILL.md\n\n# 英语助教 · English Tutor Skill\n\n> **模块化基座 Skill** — 功能按需配置，所有环境变量均为**选填**。\n> 有配置就启用对应功能，无配置则跳过。完整功能需要飞书 + MiniMax + 多维表格。\n\n---\n\n## 功能模块（按需启用）\n\n| 模块 | 环境变量 | 说明 |\n|------|---------|------|\n| 飞书语音推送 | `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `FEISHU_USER_OPEN_ID` | 发 TTS 语音到飞书 |\n| MiniMax TTS | `MINIMAX_API_KEY` | 云端语音合成（主方案） |\n| Piper 本地 TTS | `PIPER_BIN`, `PIPER_MODEL` | 完全离线的语音兜底 |\n| SenseVoice 本地 ASR | `SENSE_VOICE_MODEL_DIR` | 完全离线的语音识别 |\n| 多维表格记忆 | `BITABLE_APP_TOKEN`, `BITABLE_WORDS_TABLE_ID`, `BITABLE_CHAT_TABLE_ID` | 单词记录 + 艾宾浩斯 |\n| 定时推送 | cron jobs | 08:00 / 12:00 / 20:00（可单独开启） |\n\n**原则**：填了变量 → 启用该模块；没填 → 该模块静默跳过，不报错。\n\n---\n\n## 文件结构\n\n```\nenglish-tutor/\n├── SKILL.md\n├── metadata.json\n├── agent/                    ← 核心运行时代码（已审查，全部可见）\n│   ├── config.js\n│   ├── feishu-voice.js\n│   ├── local-tts.js\n│   ├── minimax.js\n│   ├── asr.js\n│   ├── memory.js\n│   ├── agent.js\n│   └── morning-task-v2.js\n├── scripts/\n│   ├── check_env.py\n│   ├── config_manager.py\n│   ├── download_model.py\n│   ├── feishu_voice.py\n│   └── wordlist_parser.py\n├── references/\n│   └── config-schema.md\n└── assets/\n    └── wordlist_example.csv\n```\n\n---\n\n## 环境变量（全部选填）\n\n### 飞书模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `FEISHU_APP_ID` | `\"\"` | 飞书应用 App ID（填了才发飞书语音） |\n| `FEISHU_APP_SECRET` | `\"\"` | 飞书应用 Secret |\n| `FEISHU_USER_OPEN_ID` | `\"\"` | 接收语音的飞书用户 Open ID |\n\n### TTS 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `MINIMAX_API_KEY` | `\"\"` | MiniMax API Key（不填则跳过云端 TTS） |\n| `MINIMAX_TTS_MODEL` | `speech-2.8-hd` | TTS 模型 |\n| `MINIMAX_TTS_SPEED` | `1.05` | 语速 |\n| `MINIMAX_TTS_VOICE_ID` | `male-qn-qingse` | 音色 ID |\n| `PIPER_BIN` | `\"\"` | Piper 主程序路径（不填则跳过本地 TTS） |\n| `PIPER_MODEL` | `\"\"` | Piper ONNX 模型路径 |\n| `TTS_PROVIDER` | `minimax` | 优先方案：`minimax` / `piper` |\n\n### ASR 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `SENSE_VOICE_MODEL_DIR` | `\"\"` | SenseVoice 模型目录（不填则跳过本地 ASR） |\n\n### 多维表格模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `BITABLE_APP_TOKEN` | `\"\"` | App Token（不填则无艾宾浩斯记忆） |\n| `BITABLE_WORDS_TABLE_ID` | `\"\"` | words 表 ID |\n| `BITABLE_CHAT_TABLE_ID` | `\"\"` | chat_log 表 ID |\n\n### 每日练习配置\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `DAILY_WORD_MAX` | `15` | 每日新词上限 |\n\n---\n\n## 凭据声明（metadata）\n\n本 skill 为 **Credential-Using Skill**，但**所有凭据均为选填**：\n\n```json\n{\n  \"credential_using\": true,\n  \"required_credentials\": [],\n  \"optional_credentials\": [\n    { \"name\": \"FEISHU_APP_ID\",      \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_APP_SECRET\",  \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_USER_OPEN_ID\",\"description\": \"飞书语音推送\" },\n    { \"name\": \"MINIMAX_API_KEY\",    \"description\": \"云端 TTS + LLM 对话\" },\n    { \"name\": \"BITABLE_APP_TOKEN\",  \"description\": \"艾宾浩斯记忆（可选）\" },\n    { \"name\": \"BITABLE_WORDS_TABLE_ID\", \"description\": \"单词记录表\" },\n    { \"name\": \"BITABLE_CHAT_TABLE_ID\",  \"description\": \"对话历史表\" }\n  ]\n}\n```\n\n---\n\n## 定时任务\n\n| 时间 | cron | 说明 |\n|------|------|------|\n| 晨间 | `0 8 * * *` | 通勤场景跟读 |\n| 午间 | `0 12 * * *` | 口语问答 |\n| 晚间 | `0 20 * * *` | 复盘 + 旧词复习 |\n\n**定时任务默认关闭**，用户在引导设置中自行选择开启哪些。\n\n---\n\n## 引导设置流程（用户可选配置）\n\n### 第 1 步：飞书配置（选填）\n- 提供 `FEISHU_APP_ID` / `FEISHU_APP_SECRET` / `FEISHU_USER_OPEN_ID`\n- 不填则无飞书语音推送功能\n\n### 第 2 步：TTS 配置（选填）\n- MiniMax：提供 `MINIMAX_API_KEY`\n- Piper 本地：提供 `PIPER_BIN` / `PIPER_MODEL`\n- 都不填则 TTS 功能不可用（仍有文字对话）\n\n### 第 3 步：ASR 配置（选填）\n- 提供 `SENSE_VOICE_MODEL_DIR`（或运行 `python3 scripts/download_model.py`）\n- 不填则无法处理语音输入（仅支持文字）\n\n### 第 4 步：多维表格（选填）\n- 提供 `BITABLE_APP_TOKEN` + 两个表 ID\n- 不填则无艾宾浩斯记忆功能（仍可练习，但不记录进度）\n\n### 第 5 步：每日定时（选填）\n- 选择开启哪些时段（08:00 / 12:00 / 20:00）\n- 不选择则不创建 cron 任务\n\n### 第 6 步：上传单词表（选填）\n- CSV 或纯文本格式\n- 不上传也可进行自由对话练习\n\n---\n\n## 核心模块说明\n\n### feishu-voice.js — 飞书语音发送\n- 优先 MiniMax TTS，配额耗尽自动切换 Piper\n- 无任何凭据配置时：静默跳过，不报错\n- 流程：TTS → Opus → 上传飞书 → 发送 audio 消息\n\n### asr.js — SenseVoice 本地 ASR\n- 无本地模型时：静默跳过，回退到文字输入\n- 使用 `json.dumps` 安全传递路径，无 shell 注入\n\n### memory.js — 多维表格\n- 无多维表格配置时：静默跳过，不记录历史\n- 所有操作有 try/catch，不因单次失败中断流程\n\n### agent.js — 主流程\n- **课程模式**（定时触发，无用户输入）：自动生成跟读对话，逐条发飞书语音\n- **交互模式**（用户发消息）：实时对话 + 可选 TTS 回复\n- 所有模块都是**失败静默跳过**，不影响其他模块运行\n\n---\n\n## 安全设计原则\n\n1. **所有密钥通过环境变量注入**，不硬编码\n2. **feishu_voice.py**：配置通过 `env=` 参数传递给 Node.js 子进程（内存传递）\n3. **scripts/ 无 shell=True**：subprocess 使用列表形式\n4. **config.json 权限**：`~/.openclaw/english-tutor/config.json` 设为 `600`\n5. **JS 源码全部纳入 skill 包**，审查者可查看全部代码\n\n---\n\n## 模型下载命令\n\n### Piper TTS（本地语音合成）\n\n```bash\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/piper/voices\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\n```\n\n### SenseVoice ASR（本地语音识别）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\npython3 /vol1/@apphome/trim.openclaw/data/workspace/skills/english-tutor/scripts/download_model.py\n```\n\n---\n\n## 单词表格式\n\n**CSV（推荐）：**\n```csv\nword,pronunciation,meaning,example\ncommute,/kəˈmjuːt/,通勤,I commute by subway every day.\n```\n\n**纯文本（每行一个）：**\n```\ncommute,通勤\nsubway,地铁\ntransfer,换乘\n```\n\n---\n\n## 艾宾浩斯复习周期\n\n| 复习轮次 | 间隔 |\n|---------|------|\n| 第 1 次 | 次日 |\n| 第 2 次 | 3 天后 |\n| 第 3 次 | 7 天后 |\n| 第 4 次 | 15 天后 |\n| 第 5 次+ | 掌握（不再自动提醒）|\n\nFile v3.0.3:_meta.json\n\n{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"3.0.3\",\n  \"publishedAt\": 1778167591895\n}\n\nFile v3.0.3:references/config-schema.md\n\n# English Tutor · 完整配置参考\n\n## 配置存储\n\n用户配置统一保存在 `~/.openclaw/english-tutor/config.json`，由 `scripts/config_manager.py` 管理。\n\n**首次由陪练助手通过对话引导创建，无需手动编辑。**\n\n---\n\n## config.json 字段说明\n\n### 基础配置\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `setup_complete` | ✅ | `false` | 首次设置是否完成 |\n| `word_list_path` | ✅ | `\"\"` | 单词表 JSON 文件路径 |\n| `daily_words` | ✅ | `5` | 每日练习单词数量（建议 5-15）|\n| `schedule_times` | ✅ | `[\"08:00\"]` | 每日推送时间（上海时区）|\n\n### LLM 模型配置 🤖\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `llm_provider` | ✅ | `\"openclaw\"` | 模型提供商：`openclaw` / `minimax` / `openai` |\n| `llm_model` | 否 | `\"\"` | 指定模型 ID（留空用默认）|\n\n> 选择 `openclaw` 时使用系统默认 LLM，无需额外配置。\n\n### 飞书语音配置 📢\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `feishu_app_id` | ✅ | `\"\"` | 飞书应用 App ID |\n| `feishu_app_secret` | ✅ | `\"\"` | 飞书应用 App Secret |\n| `feishu_bot_token` | 否 | `\"\"` | 飞书 Bot Token（可选）|\n| `feishu_user_open_id` | ✅ | `\"\"` | 接收消息的用户 Open ID |\n\n### TTS 语音合成 🔊\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `tts_provider` | 否 | `\"minimax\"` | TTS 方案：`minimax` / `piper` / `espeak` |\n| `minimax_api_key` | minimax时 | `\"\"` | MiniMax API Key |\n\n> MiniMax TTS 有 API Key 时推荐音色：`male-qn-qingse`（男声）、`female-tianmei`（女声）；无 Key 时静默跳过，可配 Piper 本地兜底\n\n### 多维表格（可选）\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `bitable_app_token` | 否 | `\"\"` | 飞书多维表格 App Token |\n| `bitable_words_table_id` | 否 | `\"\"` | words 表 ID |\n| `bitable_chat_table_id` | 否 | `\"\"` | chat_log 表 ID |\n\n### Piper 本地 TTS（可选）\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `piper_bin` | piper时 | piper 二进制路径 |\n| `piper_model` | piper时 | .onnx 模型文件路径 |\n\n---\n\n## 飞书 audio 消息发送流程\n\n每日练习第一步，通过 `scripts/feishu_voice.py` 实现：\n\n```\n1. TTS 合成 mp3\n   - minimax: POST /v1/t2a_v2 → hex audio → 解码为 mp3\n   - piper:   piper CLI → WAV\n   \n2. ffmpeg 转 opus\n   ffmpeg -i input.mp3 -ar 16000 -ac 1 -acodec libopus -b:a 128k output.opus\n\n3. 上传获取 file_key\n   POST /open-apis/im/v1/files\n   Content-Type: multipart/form-data; boundary=...\n   body: file_type=opus, file=opus二进制\n\n4. 发送 audio 消息\n   POST /open-apis/im/v1/messages?receive_id_type=open_id\n   {\n     \"receive_id\": \"<user_open_id>\",\n     \"msg_type\": \"audio\",\n     \"content\": \"{\\\"file_key\\\": \\\"<file_key>\\\"}\"\n   }\n```\n\n**使用示例：**\n```bash\n# 使用配置发送语音\npython3 scripts/feishu_voice.py \"Good morning! Today's vocabulary: commute, subway, transfer.\"\n\n# 使用配置（指定路径）\npython3 scripts/feishu_voice.py \"Hello!\" --config /path/to/config.json\n\n# 仅合成，不发送（调试用）\npython3 scripts/feishu_voice.py \"Hello!\" --dry-run\n```\n\n---\n\n## TTS_PROVIDER 配置\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n### piper（本地，高质量，离线）\n\n**下载主程序（Linux x86_64）：**\n```bash\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n```\n\n**下载英语模型（Lessac Medium，音质好，速度快）：**\n```bash\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /tmp/en_US-lessac-medium.onnx\n```\n\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/tmp/piper/piper_phonemize\nPIPER_MODEL=/tmp/en_US-lessac-medium.onnx\n```\n\n**测试：**\n```bash\necho \"Hello world\" | /tmp/piper/piper_phonemize \\\n  --model /tmp/en_US-lessac-medium.onnx \\\n  --input-file /dev/stdin -w /tmp/test.wav\n```\n\n### espeak-ng（系统级，完全离线）\n\n```bash\nsudo apt-get install espeak-ng\n```\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n---\n\n## ASR_PROVIDER 配置\n\n### local（默认，推荐，完全离线）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\nbash scripts/download_model.sh\n```\n\n### assemblyai / openai（云端）\n\n```env\nASR_PROVIDER=assemblyai\nASR_API_KEY=your-key\n```\n\n---\n\n## 多维表格表结构（可选）\n\n**表 1：单词表（words）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| word | 文本 | 英文单词 |\n| pronunciation | 文本 | 音标 |\n| meaning | 文本 | 中文释义 |\n| example | 文本 | 例句 |\n| mastery | 数字 | 掌握程度 0-5 |\n| review_count | 数字 | 复习次数 |\n| last_review | 日期时间 | 最近复习时间 |\n| next_review | 日期时间 | 下次复习时间 |\n| user_id | 文本 | 用户 ID |\n\n**表 2：对话记录（chat_log）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| user_id | 文本 | 用户 ID |\n| role | 单选 | `ai` 或 `user` |\n| text | 文本 | 对话内容 |\n| voice_url | 文本 | 语音 URL（可选）|\n| created_at | 日期时间 | 创建时间 |\n\nFile v3.0.3:metadata.json\n\n{\n  \"name\": \"english-tutor\",\n  \"version\": \"1.0.0\",\n  \"description\": \"英语口语陪练基座。飞书语音推送 + MiniMax/本地 TTS + SenseVoice ASR + 艾宾浩斯复习。全部模块选填，按需启用。\",\n  \"credential_using\": true,\n  \"all_optional\": true,\n  \"optional_credentials\": [\n    {\n      \"name\": \"FEISHU_APP_ID\",\n      \"type\": \"feishu_app_id\",\n      \"required\": false,\n      \"description\": \"飞书应用 App ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_APP_SECRET\",\n      \"type\": \"feishu_app_secret\",\n      \"required\": false,\n      \"description\": \"飞书应用 Secret（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_USER_OPEN_ID\",\n      \"type\": \"feishu_open_id\",\n      \"required\": false,\n      \"description\": \"接收语音的飞书用户 Open ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"MINIMAX_API_KEY\",\n      \"type\": \"api_key\",\n      \"required\": false,\n      \"description\": \"MiniMax API Key（填了启用云端 TTS，不填则跳过）\"\n    },\n    {\n      \"name\": \"PIPER_BIN\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper 主程序路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"PIPER_MODEL\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper ONNX 模型路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"SENSE_VOICE_MODEL_DIR\",\n      \"type\": \"directory_path\",\n      \"required\": false,\n      \"description\": \"SenseVoice 模型目录（填了启用本地 ASR，不填则跳过）\"\n    },\n    {\n      \"name\": \"BITABLE_APP_TOKEN\",\n      \"type\": \"feishu_bitable_token\",\n      \"required\": false,\n      \"description\": \"飞书多维表格 App Token（不填则无艾宾浩斯记忆）\"\n    },\n    {\n      \"name\": \"BITABLE_WORDS_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"words 表 ID（单词记录表）\"\n    },\n    {\n      \"name\": \"BITABLE_CHAT_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"chat_log 表 ID（对话历史表）\"\n    }\n  ],\n  \"module_design\": {\n    \"principle\": \"填了变量启用该模块，没填则静默跳过，不报错\",\n    \"modules\": [\n      {\n        \"name\": \"飞书语音推送\",\n        \"env\": [\"FEISHU_APP_ID\", \"FEISHU_APP_SECRET\", \"FEISHU_USER_OPEN_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不发飞书语音\"\n      },\n      {\n        \"name\": \"MiniMax TTS\",\n        \"env\": [\"MINIMAX_API_KEY\"],\n        \"behavior_when_empty\": \"静默跳过，尝试 Piper 本地 TTS\"\n      },\n      {\n        \"name\": \"Piper 本地 TTS\",\n        \"env\": [\"PIPER_BIN\", \"PIPER_MODEL\"],\n        \"behavior_when_empty\": \"静默跳过，无 TTS 功能\"\n      },\n      {\n        \"name\": \"SenseVoice 本地 ASR\",\n        \"env\": [\"SENSE_VOICE_MODEL_DIR\"],\n        \"behavior_when_empty\": \"静默跳过，仅支持文字输入\"\n      },\n      {\n        \"name\": \"多维表格记忆\",\n        \"env\": [\"BITABLE_APP_TOKEN\", \"BITABLE_WORDS_TABLE_ID\", \"BITABLE_CHAT_TABLE_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不记录学习进度\"\n      }\n    ]\n  },\n  \"scheduled_actions\": [\n    {\n      \"name\": \"每日晨间练习 08:00\",\n      \"cron\": \"0 8 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"用户选择开启后，自动生成跟读对话，发飞书语音，等待用户回复\"\n    },\n    {\n      \"name\": \"每日午间练习 12:00\",\n      \"cron\": \"0 12 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    },\n    {\n      \"name\": \"每日晚间练习 20:00\",\n      \"cron\": \"0 20 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    }\n  ],\n  \"data_storage\": {\n    \"conversation_history\": {\n      \"location\": \"飞书多维表格（BITABLE_APP_TOKEN 指向的多维表格）\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"user_id\", \"role\", \"text\", \"voice_url\", \"created_at\"],\n      \"note\": \"口语练习对话内容和语音 URL 会被存储用于艾宾浩斯复习\"\n    },\n    \"word_records\": {\n      \"location\": \"飞书多维表格\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"word\", \"user_id\", \"first_seen\", \"last_review\", \"next_review\", \"review_count\", \"mastery\", \"source\"]\n    },\n    \"config_file\": {\n      \"location\": \"~/.openclaw/english-tutor/config.json\",\n      \"sensitive\": true,\n      \"permission\": \"600\",\n      \"enabled\": \"always\"\n    }\n  },\n  \"external_downloads\": [\n    {\n      \"name\": \"Piper TTS\",\n      \"urls\": [\n        \"https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz\",\n        \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 TTS 兜底方案，来源可信但无 checksum 校验\"\n    },\n    {\n      \"name\": \"SenseVoice ASR\",\n      \"urls\": [\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/model.onnx\",\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/tokens.txt\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 ASR，来源可信但无 checksum 校验\"\n    }\n  ]\n}\n\nArchive v3.0.2: 15 files, 33721 bytes\n\nFiles: agent/agent.js (11191b), agent/config.js (2537b), agent/memory.js (5655b), agent/minimax.js (6246b), assets/wordlist_example.csv (812b), metadata.json (5330b), references/config-schema.md (5369b), scripts/check_env.py (6407b), scripts/config_manager.py (4775b), scripts/download_model.py (1966b), scripts/feishu_voice.py (12908b), scripts/transcribe.py (5994b), scripts/wordlist_parser.py (4937b), SKILL.md (7523b), _meta.json (136b)\n\nFile v3.0.2:SKILL.md\n\n# 英语助教 · English Tutor Skill\n\n> **模块化基座 Skill** — 功能按需配置，所有环境变量均为**选填**。\n> 有配置就启用对应功能，无配置则跳过。完整功能需要飞书 + MiniMax + 多维表格。\n\n---\n\n## 功能模块（按需启用）\n\n| 模块 | 环境变量 | 说明 |\n|------|---------|------|\n| 飞书语音推送 | `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `FEISHU_USER_OPEN_ID` | 发 TTS 语音到飞书 |\n| MiniMax TTS | `MINIMAX_API_KEY` | 云端语音合成（主方案） |\n| Piper 本地 TTS | `PIPER_BIN`, `PIPER_MODEL` | 完全离线的语音兜底 |\n| SenseVoice 本地 ASR | `SENSE_VOICE_MODEL_DIR` | 完全离线的语音识别 |\n| 多维表格记忆 | `BITABLE_APP_TOKEN`, `BITABLE_WORDS_TABLE_ID`, `BITABLE_CHAT_TABLE_ID` | 单词记录 + 艾宾浩斯 |\n| 定时推送 | cron jobs | 08:00 / 12:00 / 20:00（可单独开启） |\n\n**原则**：填了变量 → 启用该模块；没填 → 该模块静默跳过，不报错。\n\n---\n\n## 文件结构\n\n```\nenglish-tutor/\n├── SKILL.md\n├── metadata.json\n├── agent/                    ← 核心运行时代码（已审查，全部可见）\n│   ├── config.js\n│   ├── feishu-voice.js\n│   ├── local-tts.js\n│   ├── minimax.js\n│   ├── asr.js\n│   ├── memory.js\n│   ├── agent.js\n│   └── morning-task-v2.js\n├── scripts/\n│   ├── check_env.py\n│   ├── config_manager.py\n│   ├── download_model.py\n│   ├── feishu_voice.py\n│   └── wordlist_parser.py\n├── references/\n│   └── config-schema.md\n└── assets/\n    └── wordlist_example.csv\n```\n\n---\n\n## 环境变量（全部选填）\n\n### 飞书模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `FEISHU_APP_ID` | `\"\"` | 飞书应用 App ID（填了才发飞书语音） |\n| `FEISHU_APP_SECRET` | `\"\"` | 飞书应用 Secret |\n| `FEISHU_USER_OPEN_ID` | `\"\"` | 接收语音的飞书用户 Open ID |\n\n### TTS 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `MINIMAX_API_KEY` | `\"\"` | MiniMax API Key（不填则跳过云端 TTS） |\n| `MINIMAX_TTS_MODEL` | `speech-2.8-hd` | TTS 模型 |\n| `MINIMAX_TTS_SPEED` | `1.05` | 语速 |\n| `MINIMAX_TTS_VOICE_ID` | `male-qn-qingse` | 音色 ID |\n| `PIPER_BIN` | `\"\"` | Piper 主程序路径（不填则跳过本地 TTS） |\n| `PIPER_MODEL` | `\"\"` | Piper ONNX 模型路径 |\n| `TTS_PROVIDER` | `minimax` | 优先方案：`minimax` / `piper` |\n\n### ASR 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `SENSE_VOICE_MODEL_DIR` | `\"\"` | SenseVoice 模型目录（不填则跳过本地 ASR） |\n\n### 多维表格模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `BITABLE_APP_TOKEN` | `\"\"` | App Token（不填则无艾宾浩斯记忆） |\n| `BITABLE_WORDS_TABLE_ID` | `\"\"` | words 表 ID |\n| `BITABLE_CHAT_TABLE_ID` | `\"\"` | chat_log 表 ID |\n\n### 每日练习配置\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `DAILY_WORD_MAX` | `15` | 每日新词上限 |\n\n---\n\n## 凭据声明（metadata）\n\n本 skill 为 **Credential-Using Skill**，但**所有凭据均为选填**：\n\n```json\n{\n  \"credential_using\": true,\n  \"required_credentials\": [],\n  \"optional_credentials\": [\n    { \"name\": \"FEISHU_APP_ID\",      \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_APP_SECRET\",  \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_USER_OPEN_ID\",\"description\": \"飞书语音推送\" },\n    { \"name\": \"MINIMAX_API_KEY\",    \"description\": \"云端 TTS + LLM 对话\" },\n    { \"name\": \"BITABLE_APP_TOKEN\",  \"description\": \"艾宾浩斯记忆（可选）\" },\n    { \"name\": \"BITABLE_WORDS_TABLE_ID\", \"description\": \"单词记录表\" },\n    { \"name\": \"BITABLE_CHAT_TABLE_ID\",  \"description\": \"对话历史表\" }\n  ]\n}\n```\n\n---\n\n## 定时任务\n\n| 时间 | cron | 说明 |\n|------|------|------|\n| 晨间 | `0 8 * * *` | 通勤场景跟读 |\n| 午间 | `0 12 * * *` | 口语问答 |\n| 晚间 | `0 20 * * *` | 复盘 + 旧词复习 |\n\n**定时任务默认关闭**，用户在引导设置中自行选择开启哪些。\n\n---\n\n## 引导设置流程（用户可选配置）\n\n### 第 1 步：飞书配置（选填）\n- 提供 `FEISHU_APP_ID` / `FEISHU_APP_SECRET` / `FEISHU_USER_OPEN_ID`\n- 不填则无飞书语音推送功能\n\n### 第 2 步：TTS 配置（选填）\n- MiniMax：提供 `MINIMAX_API_KEY`\n- Piper 本地：提供 `PIPER_BIN` / `PIPER_MODEL`\n- 都不填则 TTS 功能不可用（仍有文字对话）\n\n### 第 3 步：ASR 配置（选填）\n- 提供 `SENSE_VOICE_MODEL_DIR`（或运行 `python3 scripts/download_model.py`）\n- 不填则无法处理语音输入（仅支持文字）\n\n### 第 4 步：多维表格（选填）\n- 提供 `BITABLE_APP_TOKEN` + 两个表 ID\n- 不填则无艾宾浩斯记忆功能（仍可练习，但不记录进度）\n\n### 第 5 步：每日定时（选填）\n- 选择开启哪些时段（08:00 / 12:00 / 20:00）\n- 不选择则不创建 cron 任务\n\n### 第 6 步：上传单词表（选填）\n- CSV 或纯文本格式\n- 不上传也可进行自由对话练习\n\n---\n\n## 核心模块说明\n\n### feishu-voice.js — 飞书语音发送\n- 优先 MiniMax TTS，配额耗尽自动切换 Piper\n- 无任何凭据配置时：静默跳过，不报错\n- 流程：TTS → Opus → 上传飞书 → 发送 audio 消息\n\n### asr.js — SenseVoice 本地 ASR\n- 无本地模型时：静默跳过，回退到文字输入\n- 使用 `json.dumps` 安全传递路径，无 shell 注入\n\n### memory.js — 多维表格\n- 无多维表格配置时：静默跳过，不记录历史\n- 所有操作有 try/catch，不因单次失败中断流程\n\n### agent.js — 主流程\n- **课程模式**（定时触发，无用户输入）：自动生成跟读对话，逐条发飞书语音\n- **交互模式**（用户发消息）：实时对话 + 可选 TTS 回复\n- 所有模块都是**失败静默跳过**，不影响其他模块运行\n\n---\n\n## 安全设计原则\n\n1. **所有密钥通过环境变量注入**，不硬编码\n2. **feishu_voice.py**：配置通过 `env=` 参数传递给 Node.js 子进程（内存传递）\n3. **scripts/ 无 shell=True**：subprocess 使用列表形式\n4. **config.json 权限**：`~/.openclaw/english-tutor/config.json` 设为 `600`\n5. **JS 源码全部纳入 skill 包**，审查者可查看全部代码\n\n---\n\n## 模型下载命令\n\n### Piper TTS（本地语音合成）\n\n```bash\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/piper/voices\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\n```\n\n### SenseVoice ASR（本地语音识别）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\npython3 /vol1/@apphome/trim.openclaw/data/workspace/skills/english-tutor/scripts/download_model.py\n```\n\n---\n\n## 单词表格式\n\n**CSV（推荐）：**\n```csv\nword,pronunciation,meaning,example\ncommute,/kəˈmjuːt/,通勤,I commute by subway every day.\n```\n\n**纯文本（每行一个）：**\n```\ncommute,通勤\nsubway,地铁\ntransfer,换乘\n```\n\n---\n\n## 艾宾浩斯复习周期\n\n| 复习轮次 | 间隔 |\n|---------|------|\n| 第 1 次 | 次日 |\n| 第 2 次 | 3 天后 |\n| 第 3 次 | 7 天后 |\n| 第 4 次 | 15 天后 |\n| 第 5 次+ | 掌握（不再自动提醒）|\n\nFile v3.0.2:_meta.json\n\n{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"3.0.2\",\n  \"publishedAt\": 1777818402608\n}\n\nFile v3.0.2:references/config-schema.md\n\n# English Tutor · 完整配置参考\n\n## 配置存储\n\n用户配置统一保存在 `~/.openclaw/english-tutor/config.json`，由 `scripts/config_manager.py` 管理。\n\n**首次由陪练助手通过对话引导创建，无需手动编辑。**\n\n---\n\n## config.json 字段说明\n\n### 基础配置\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `setup_complete` | ✅ | `false` | 首次设置是否完成 |\n| `word_list_path` | ✅ | `\"\"` | 单词表 JSON 文件路径 |\n| `daily_words` | ✅ | `5` | 每日练习单词数量（建议 5-15）|\n| `schedule_times` | ✅ | `[\"08:00\"]` | 每日推送时间（上海时区）|\n\n### LLM 模型配置 🤖\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `llm_provider` | ✅ | `\"openclaw\"` | 模型提供商：`openclaw` / `minimax` / `openai` |\n| `llm_model` | 否 | `\"\"` | 指定模型 ID（留空用默认）|\n\n> 选择 `openclaw` 时使用系统默认 LLM，无需额外配置。\n\n### 飞书语音配置 📢\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `feishu_app_id` | ✅ | `\"\"` | 飞书应用 App ID |\n| `feishu_app_secret` | ✅ | `\"\"` | 飞书应用 App Secret |\n| `feishu_bot_token` | 否 | `\"\"` | 飞书 Bot Token（可选）|\n| `feishu_user_open_id` | ✅ | `\"\"` | 接收消息的用户 Open ID |\n\n### TTS 语音合成 🔊\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `tts_provider` | 否 | `\"minimax\"` | TTS 方案：`minimax` / `piper` / `espeak` |\n| `minimax_api_key` | minimax时 | `\"\"` | MiniMax API Key |\n\n> MiniMax TTS 推荐音色：`male-qn-qingse`（男声）、`female-tianmei`（女声）\n\n### 多维表格（可选）\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `bitable_app_token` | 否 | `\"\"` | 飞书多维表格 App Token |\n| `bitable_words_table_id` | 否 | `\"\"` | words 表 ID |\n| `bitable_chat_table_id` | 否 | `\"\"` | chat_log 表 ID |\n\n### Piper 本地 TTS（可选）\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `piper_bin` | piper时 | piper 二进制路径 |\n| `piper_model` | piper时 | .onnx 模型文件路径 |\n\n---\n\n## 飞书 audio 消息发送流程\n\n每日练习第一步，通过 `scripts/feishu_voice.py` 实现：\n\n```\n1. TTS 合成 mp3\n   - minimax: POST /v1/t2a_v2 → hex audio → 解码为 mp3\n   - piper:   piper CLI → WAV\n   \n2. ffmpeg 转 opus\n   ffmpeg -i input.mp3 -ar 16000 -ac 1 -acodec libopus -b:a 128k output.opus\n\n3. 上传获取 file_key\n   POST /open-apis/im/v1/files\n   Content-Type: multipart/form-data; boundary=...\n   body: file_type=opus, file=opus二进制\n\n4. 发送 audio 消息\n   POST /open-apis/im/v1/messages?receive_id_type=open_id\n   {\n     \"receive_id\": \"<user_open_id>\",\n     \"msg_type\": \"audio\",\n     \"content\": \"{\\\"file_key\\\": \\\"<file_key>\\\"}\"\n   }\n```\n\n**使用示例：**\n```bash\n# 使用配置发送语音\npython3 scripts/feishu_voice.py \"Good morning! Today's vocabulary: commute, subway, transfer.\"\n\n# 使用配置（指定路径）\npython3 scripts/feishu_voice.py \"Hello!\" --config /path/to/config.json\n\n# 仅合成，不发送（调试用）\npython3 scripts/feishu_voice.py \"Hello!\" --dry-run\n```\n\n---\n\n## TTS_PROVIDER 配置\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n### piper（本地，高质量，离线）\n\n**下载主程序（Linux x86_64）：**\n```bash\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n```\n\n**下载英语模型（Lessac Medium，音质好，速度快）：**\n```bash\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /tmp/en_US-lessac-medium.onnx\n```\n\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/tmp/piper/piper_phonemize\nPIPER_MODEL=/tmp/en_US-lessac-medium.onnx\n```\n\n**测试：**\n```bash\necho \"Hello world\" | /tmp/piper/piper_phonemize \\\n  --model /tmp/en_US-lessac-medium.onnx \\\n  --input-file /dev/stdin -w /tmp/test.wav\n```\n\n### espeak-ng（系统级，完全离线）\n\n```bash\nsudo apt-get install espeak-ng\n```\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n---\n\n## ASR_PROVIDER 配置\n\n### local（默认，推荐，完全离线）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\nbash scripts/download_model.sh\n```\n\n### assemblyai / openai（云端）\n\n```env\nASR_PROVIDER=assemblyai\nASR_API_KEY=your-key\n```\n\n---\n\n## 多维表格表结构（可选）\n\n**表 1：单词表（words）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| word | 文本 | 英文单词 |\n| pronunciation | 文本 | 音标 |\n| meaning | 文本 | 中文释义 |\n| example | 文本 | 例句 |\n| mastery | 数字 | 掌握程度 0-5 |\n| review_count | 数字 | 复习次数 |\n| last_review | 日期时间 | 最近复习时间 |\n| next_review | 日期时间 | 下次复习时间 |\n| user_id | 文本 | 用户 ID |\n\n**表 2：对话记录（chat_log）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| user_id | 文本 | 用户 ID |\n| role | 单选 | `ai` 或 `user` |\n| text | 文本 | 对话内容 |\n| voice_url | 文本 | 语音 URL（可选）|\n| created_at | 日期时间 | 创建时间 |\n\nFile v3.0.2:metadata.json\n\n{\n  \"name\": \"english-tutor\",\n  \"version\": \"1.0.0\",\n  \"description\": \"英语口语陪练基座。飞书语音推送 + MiniMax/本地 TTS + SenseVoice ASR + 艾宾浩斯复习。全部模块选填，按需启用。\",\n  \"credential_using\": true,\n  \"all_optional\": true,\n  \"optional_credentials\": [\n    {\n      \"name\": \"FEISHU_APP_ID\",\n      \"type\": \"feishu_app_id\",\n      \"required\": false,\n      \"description\": \"飞书应用 App ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_APP_SECRET\",\n      \"type\": \"feishu_app_secret\",\n      \"required\": false,\n      \"description\": \"飞书应用 Secret（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_USER_OPEN_ID\",\n      \"type\": \"feishu_open_id\",\n      \"required\": false,\n      \"description\": \"接收语音的飞书用户 Open ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"MINIMAX_API_KEY\",\n      \"type\": \"api_key\",\n      \"required\": false,\n      \"description\": \"MiniMax API Key（填了启用云端 TTS，不填则跳过）\"\n    },\n    {\n      \"name\": \"PIPER_BIN\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper 主程序路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"PIPER_MODEL\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper ONNX 模型路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"SENSE_VOICE_MODEL_DIR\",\n      \"type\": \"directory_path\",\n      \"required\": false,\n      \"description\": \"SenseVoice 模型目录（填了启用本地 ASR，不填则跳过）\"\n    },\n    {\n      \"name\": \"BITABLE_APP_TOKEN\",\n      \"type\": \"feishu_bitable_token\",\n      \"required\": false,\n      \"description\": \"飞书多维表格 App Token（不填则无艾宾浩斯记忆）\"\n    },\n    {\n      \"name\": \"BITABLE_WORDS_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"words 表 ID（单词记录表）\"\n    },\n    {\n      \"name\": \"BITABLE_CHAT_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"chat_log 表 ID（对话历史表）\"\n    }\n  ],\n  \"module_design\": {\n    \"principle\": \"填了变量启用该模块，没填则静默跳过，不报错\",\n    \"modules\": [\n      {\n        \"name\": \"飞书语音推送\",\n        \"env\": [\"FEISHU_APP_ID\", \"FEISHU_APP_SECRET\", \"FEISHU_USER_OPEN_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不发飞书语音\"\n      },\n      {\n        \"name\": \"MiniMax TTS\",\n        \"env\": [\"MINIMAX_API_KEY\"],\n        \"behavior_when_empty\": \"静默跳过，尝试 Piper 本地 TTS\"\n      },\n      {\n        \"name\": \"Piper 本地 TTS\",\n        \"env\": [\"PIPER_BIN\", \"PIPER_MODEL\"],\n        \"behavior_when_empty\": \"静默跳过，无 TTS 功能\"\n      },\n      {\n        \"name\": \"SenseVoice 本地 ASR\",\n        \"env\": [\"SENSE_VOICE_MODEL_DIR\"],\n        \"behavior_when_empty\": \"静默跳过，仅支持文字输入\"\n      },\n      {\n        \"name\": \"多维表格记忆\",\n        \"env\": [\"BITABLE_APP_TOKEN\", \"BITABLE_WORDS_TABLE_ID\", \"BITABLE_CHAT_TABLE_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不记录学习进度\"\n      }\n    ]\n  },\n  \"scheduled_actions\": [\n    {\n      \"name\": \"每日晨间练习 08:00\",\n      \"cron\": \"0 8 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"用户选择开启后，自动生成跟读对话，发飞书语音，等待用户回复\"\n    },\n    {\n      \"name\": \"每日午间练习 12:00\",\n      \"cron\": \"0 12 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    },\n    {\n      \"name\": \"每日晚间练习 20:00\",\n      \"cron\": \"0 20 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    }\n  ],\n  \"data_storage\": {\n    \"conversation_history\": {\n      \"location\": \"飞书多维表格（BITABLE_APP_TOKEN 指向的多维表格）\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"user_id\", \"role\", \"text\", \"voice_url\", \"created_at\"],\n      \"note\": \"口语练习对话内容和语音 URL 会被存储用于艾宾浩斯复习\"\n    },\n    \"word_records\": {\n      \"location\": \"飞书多维表格\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"word\", \"user_id\", \"first_seen\", \"last_review\", \"next_review\", \"review_count\", \"mastery\", \"source\"]\n    },\n    \"config_file\": {\n      \"location\": \"~/.openclaw/english-tutor/config.json\",\n      \"sensitive\": true,\n      \"permission\": \"600\",\n      \"enabled\": \"always\"\n    }\n  },\n  \"external_downloads\": [\n    {\n      \"name\": \"Piper TTS\",\n      \"urls\": [\n        \"https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz\",\n        \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 TTS 兜底方案，来源可信但无 checksum 校验\"\n    },\n    {\n      \"name\": \"SenseVoice ASR\",\n      \"urls\": [\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/model.onnx\",\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/tokens.txt\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 ASR，来源可信但无 checksum 校验\"\n    }\n  ]\n}\n\nArchive v3.0.1: 19 files, 46120 bytes\n\nFiles: agent/agent.js (10489b), agent/asr.js (2428b), agent/config.js (2537b), agent/feishu-voice.js (7313b), agent/local-tts.js (6848b), agent/memory.js (5655b), agent/minimax.js (6246b), agent/morning-task-v2.js (12941b), assets/wordlist_example.csv (812b), metadata.json (5330b), references/config-schema.md (5369b), scripts/check_env.py (6407b), scripts/config_manager.py (4775b), scripts/download_model.py (1966b), scripts/feishu_voice.py (12908b), scripts/transcribe.py (5994b), scripts/wordlist_parser.py (4937b), SKILL.md (7523b), _meta.json (136b)\n\nFile v3.0.1:SKILL.md\n\n# 英语助教 · English Tutor Skill\n\n> **模块化基座 Skill** — 功能按需配置，所有环境变量均为**选填**。\n> 有配置就启用对应功能，无配置则跳过。完整功能需要飞书 + MiniMax + 多维表格。\n\n---\n\n## 功能模块（按需启用）\n\n| 模块 | 环境变量 | 说明 |\n|------|---------|------|\n| 飞书语音推送 | `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `FEISHU_USER_OPEN_ID` | 发 TTS 语音到飞书 |\n| MiniMax TTS | `MINIMAX_API_KEY` | 云端语音合成（主方案） |\n| Piper 本地 TTS | `PIPER_BIN`, `PIPER_MODEL` | 完全离线的语音兜底 |\n| SenseVoice 本地 ASR | `SENSE_VOICE_MODEL_DIR` | 完全离线的语音识别 |\n| 多维表格记忆 | `BITABLE_APP_TOKEN`, `BITABLE_WORDS_TABLE_ID`, `BITABLE_CHAT_TABLE_ID` | 单词记录 + 艾宾浩斯 |\n| 定时推送 | cron jobs | 08:00 / 12:00 / 20:00（可单独开启） |\n\n**原则**：填了变量 → 启用该模块；没填 → 该模块静默跳过，不报错。\n\n---\n\n## 文件结构\n\n```\nenglish-tutor/\n├── SKILL.md\n├── metadata.json\n├── agent/                    ← 核心运行时代码（已审查，全部可见）\n│   ├── config.js\n│   ├── feishu-voice.js\n│   ├── local-tts.js\n│   ├── minimax.js\n│   ├── asr.js\n│   ├── memory.js\n│   ├── agent.js\n│   └── morning-task-v2.js\n├── scripts/\n│   ├── check_env.py\n│   ├── config_manager.py\n│   ├── download_model.py\n│   ├── feishu_voice.py\n│   └── wordlist_parser.py\n├── references/\n│   └── config-schema.md\n└── assets/\n    └── wordlist_example.csv\n```\n\n---\n\n## 环境变量（全部选填）\n\n### 飞书模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `FEISHU_APP_ID` | `\"\"` | 飞书应用 App ID（填了才发飞书语音） |\n| `FEISHU_APP_SECRET` | `\"\"` | 飞书应用 Secret |\n| `FEISHU_USER_OPEN_ID` | `\"\"` | 接收语音的飞书用户 Open ID |\n\n### TTS 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `MINIMAX_API_KEY` | `\"\"` | MiniMax API Key（不填则跳过云端 TTS） |\n| `MINIMAX_TTS_MODEL` | `speech-2.8-hd` | TTS 模型 |\n| `MINIMAX_TTS_SPEED` | `1.05` | 语速 |\n| `MINIMAX_TTS_VOICE_ID` | `male-qn-qingse` | 音色 ID |\n| `PIPER_BIN` | `\"\"` | Piper 主程序路径（不填则跳过本地 TTS） |\n| `PIPER_MODEL` | `\"\"` | Piper ONNX 模型路径 |\n| `TTS_PROVIDER` | `minimax` | 优先方案：`minimax` / `piper` |\n\n### ASR 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `SENSE_VOICE_MODEL_DIR` | `\"\"` | SenseVoice 模型目录（不填则跳过本地 ASR） |\n\n### 多维表格模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `BITABLE_APP_TOKEN` | `\"\"` | App Token（不填则无艾宾浩斯记忆） |\n| `BITABLE_WORDS_TABLE_ID` | `\"\"` | words 表 ID |\n| `BITABLE_CHAT_TABLE_ID` | `\"\"` | chat_log 表 ID |\n\n### 每日练习配置\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `DAILY_WORD_MAX` | `15` | 每日新词上限 |\n\n---\n\n## 凭据声明（metadata）\n\n本 skill 为 **Credential-Using Skill**，但**所有凭据均为选填**：\n\n```json\n{\n  \"credential_using\": true,\n  \"required_credentials\": [],\n  \"optional_credentials\": [\n    { \"name\": \"FEISHU_APP_ID\",      \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_APP_SECRET\",  \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_USER_OPEN_ID\",\"description\": \"飞书语音推送\" },\n    { \"name\": \"MINIMAX_API_KEY\",    \"description\": \"云端 TTS + LLM 对话\" },\n    { \"name\": \"BITABLE_APP_TOKEN\",  \"description\": \"艾宾浩斯记忆（可选）\" },\n    { \"name\": \"BITABLE_WORDS_TABLE_ID\", \"description\": \"单词记录表\" },\n    { \"name\": \"BITABLE_CHAT_TABLE_ID\",  \"description\": \"对话历史表\" }\n  ]\n}\n```\n\n---\n\n## 定时任务\n\n| 时间 | cron | 说明 |\n|------|------|------|\n| 晨间 | `0 8 * * *` | 通勤场景跟读 |\n| 午间 | `0 12 * * *` | 口语问答 |\n| 晚间 | `0 20 * * *` | 复盘 + 旧词复习 |\n\n**定时任务默认关闭**，用户在引导设置中自行选择开启哪些。\n\n---\n\n## 引导设置流程（用户可选配置）\n\n### 第 1 步：飞书配置（选填）\n- 提供 `FEISHU_APP_ID` / `FEISHU_APP_SECRET` / `FEISHU_USER_OPEN_ID`\n- 不填则无飞书语音推送功能\n\n### 第 2 步：TTS 配置（选填）\n- MiniMax：提供 `MINIMAX_API_KEY`\n- Piper 本地：提供 `PIPER_BIN` / `PIPER_MODEL`\n- 都不填则 TTS 功能不可用（仍有文字对话）\n\n### 第 3 步：ASR 配置（选填）\n- 提供 `SENSE_VOICE_MODEL_DIR`（或运行 `python3 scripts/download_model.py`）\n- 不填则无法处理语音输入（仅支持文字）\n\n### 第 4 步：多维表格（选填）\n- 提供 `BITABLE_APP_TOKEN` + 两个表 ID\n- 不填则无艾宾浩斯记忆功能（仍可练习，但不记录进度）\n\n### 第 5 步：每日定时（选填）\n- 选择开启哪些时段（08:00 / 12:00 / 20:00）\n- 不选择则不创建 cron 任务\n\n### 第 6 步：上传单词表（选填）\n- CSV 或纯文本格式\n- 不上传也可进行自由对话练习\n\n---\n\n## 核心模块说明\n\n### feishu-voice.js — 飞书语音发送\n- 优先 MiniMax TTS，配额耗尽自动切换 Piper\n- 无任何凭据配置时：静默跳过，不报错\n- 流程：TTS → Opus → 上传飞书 → 发送 audio 消息\n\n### asr.js — SenseVoice 本地 ASR\n- 无本地模型时：静默跳过，回退到文字输入\n- 使用 `json.dumps` 安全传递路径，无 shell 注入\n\n### memory.js — 多维表格\n- 无多维表格配置时：静默跳过，不记录历史\n- 所有操作有 try/catch，不因单次失败中断流程\n\n### agent.js — 主流程\n- **课程模式**（定时触发，无用户输入）：自动生成跟读对话，逐条发飞书语音\n- **交互模式**（用户发消息）：实时对话 + 可选 TTS 回复\n- 所有模块都是**失败静默跳过**，不影响其他模块运行\n\n---\n\n## 安全设计原则\n\n1. **所有密钥通过环境变量注入**，不硬编码\n2. **feishu_voice.py**：配置通过 `env=` 参数传递给 Node.js 子进程（内存传递）\n3. **scripts/ 无 shell=True**：subprocess 使用列表形式\n4. **config.json 权限**：`~/.openclaw/english-tutor/config.json` 设为 `600`\n5. **JS 源码全部纳入 skill 包**，审查者可查看全部代码\n\n---\n\n## 模型下载命令\n\n### Piper TTS（本地语音合成）\n\n```bash\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/piper/voices\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\n```\n\n### SenseVoice ASR（本地语音识别）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\npython3 /vol1/@apphome/trim.openclaw/data/workspace/skills/english-tutor/scripts/download_model.py\n```\n\n---\n\n## 单词表格式\n\n**CSV（推荐）：**\n```csv\nword,pronunciation,meaning,example\ncommute,/kəˈmjuːt/,通勤,I commute by subway every day.\n```\n\n**纯文本（每行一个）：**\n```\ncommute,通勤\nsubway,地铁\ntransfer,换乘\n```\n\n---\n\n## 艾宾浩斯复习周期\n\n| 复习轮次 | 间隔 |\n|---------|------|\n| 第 1 次 | 次日 |\n| 第 2 次 | 3 天后 |\n| 第 3 次 | 7 天后 |\n| 第 4 次 | 15 天后 |\n| 第 5 次+ | 掌握（不再自动提醒）|\n\nFile v3.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"3.0.1\",\n  \"publishedAt\": 1777818116221\n}\n\nFile v3.0.1:references/config-schema.md\n\n# English Tutor · 完整配置参考\n\n## 配置存储\n\n用户配置统一保存在 `~/.openclaw/english-tutor/config.json`，由 `scripts/config_manager.py` 管理。\n\n**首次由陪练助手通过对话引导创建，无需手动编辑。**\n\n---\n\n## config.json 字段说明\n\n### 基础配置\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `setup_complete` | ✅ | `false` | 首次设置是否完成 |\n| `word_list_path` | ✅ | `\"\"` | 单词表 JSON 文件路径 |\n| `daily_words` | ✅ | `5` | 每日练习单词数量（建议 5-15）|\n| `schedule_times` | ✅ | `[\"08:00\"]` | 每日推送时间（上海时区）|\n\n### LLM 模型配置 🤖\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `llm_provider` | ✅ | `\"openclaw\"` | 模型提供商：`openclaw` / `minimax` / `openai` |\n| `llm_model` | 否 | `\"\"` | 指定模型 ID（留空用默认）|\n\n> 选择 `openclaw` 时使用系统默认 LLM，无需额外配置。\n\n### 飞书语音配置 📢\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `feishu_app_id` | ✅ | `\"\"` | 飞书应用 App ID |\n| `feishu_app_secret` | ✅ | `\"\"` | 飞书应用 App Secret |\n| `feishu_bot_token` | 否 | `\"\"` | 飞书 Bot Token（可选）|\n| `feishu_user_open_id` | ✅ | `\"\"` | 接收消息的用户 Open ID |\n\n### TTS 语音合成 🔊\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `tts_provider` | 否 | `\"minimax\"` | TTS 方案：`minimax` / `piper` / `espeak` |\n| `minimax_api_key` | minimax时 | `\"\"` | MiniMax API Key |\n\n> MiniMax TTS 推荐音色：`male-qn-qingse`（男声）、`female-tianmei`（女声）\n\n### 多维表格（可选）\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `bitable_app_token` | 否 | `\"\"` | 飞书多维表格 App Token |\n| `bitable_words_table_id` | 否 | `\"\"` | words 表 ID |\n| `bitable_chat_table_id` | 否 | `\"\"` | chat_log 表 ID |\n\n### Piper 本地 TTS（可选）\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `piper_bin` | piper时 | piper 二进制路径 |\n| `piper_model` | piper时 | .onnx 模型文件路径 |\n\n---\n\n## 飞书 audio 消息发送流程\n\n每日练习第一步，通过 `scripts/feishu_voice.py` 实现：\n\n```\n1. TTS 合成 mp3\n   - minimax: POST /v1/t2a_v2 → hex audio → 解码为 mp3\n   - piper:   piper CLI → WAV\n   \n2. ffmpeg 转 opus\n   ffmpeg -i input.mp3 -ar 16000 -ac 1 -acodec libopus -b:a 128k output.opus\n\n3. 上传获取 file_key\n   POST /open-apis/im/v1/files\n   Content-Type: multipart/form-data; boundary=...\n   body: file_type=opus, file=opus二进制\n\n4. 发送 audio 消息\n   POST /open-apis/im/v1/messages?receive_id_type=open_id\n   {\n     \"receive_id\": \"<user_open_id>\",\n     \"msg_type\": \"audio\",\n     \"content\": \"{\\\"file_key\\\": \\\"<file_key>\\\"}\"\n   }\n```\n\n**使用示例：**\n```bash\n# 使用配置发送语音\npython3 scripts/feishu_voice.py \"Good morning! Today's vocabulary: commute, subway, transfer.\"\n\n# 使用配置（指定路径）\npython3 scripts/feishu_voice.py \"Hello!\" --config /path/to/config.json\n\n# 仅合成，不发送（调试用）\npython3 scripts/feishu_voice.py \"Hello!\" --dry-run\n```\n\n---\n\n## TTS_PROVIDER 配置\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n### piper（本地，高质量，离线）\n\n**下载主程序（Linux x86_64）：**\n```bash\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n```\n\n**下载英语模型（Lessac Medium，音质好，速度快）：**\n```bash\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /tmp/en_US-lessac-medium.onnx\n```\n\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/tmp/piper/piper_phonemize\nPIPER_MODEL=/tmp/en_US-lessac-medium.onnx\n```\n\n**测试：**\n```bash\necho \"Hello world\" | /tmp/piper/piper_phonemize \\\n  --model /tmp/en_US-lessac-medium.onnx \\\n  --input-file /dev/stdin -w /tmp/test.wav\n```\n\n### espeak-ng（系统级，完全离线）\n\n```bash\nsudo apt-get install espeak-ng\n```\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n---\n\n## ASR_PROVIDER 配置\n\n### local（默认，推荐，完全离线）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\nbash scripts/download_model.sh\n```\n\n### assemblyai / openai（云端）\n\n```env\nASR_PROVIDER=assemblyai\nASR_API_KEY=your-key\n```\n\n---\n\n## 多维表格表结构（可选）\n\n**表 1：单词表（words）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| word | 文本 | 英文单词 |\n| pronunciation | 文本 | 音标 |\n| meaning | 文本 | 中文释义 |\n| example | 文本 | 例句 |\n| mastery | 数字 | 掌握程度 0-5 |\n| review_count | 数字 | 复习次数 |\n| last_review | 日期时间 | 最近复习时间 |\n| next_review | 日期时间 | 下次复习时间 |\n| user_id | 文本 | 用户 ID |\n\n**表 2：对话记录（chat_log）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| user_id | 文本 | 用户 ID |\n| role | 单选 | `ai` 或 `user` |\n| text | 文本 | 对话内容 |\n| voice_url | 文本 | 语音 URL（可选）|\n| created_at | 日期时间 | 创建时间 |\n\nFile v3.0.1:metadata.json\n\n{\n  \"name\": \"english-tutor\",\n  \"version\": \"1.0.0\",\n  \"description\": \"英语口语陪练基座。飞书语音推送 + MiniMax/本地 TTS + SenseVoice ASR + 艾宾浩斯复习。全部模块选填，按需启用。\",\n  \"credential_using\": true,\n  \"all_optional\": true,\n  \"optional_credentials\": [\n    {\n      \"name\": \"FEISHU_APP_ID\",\n      \"type\": \"feishu_app_id\",\n      \"required\": false,\n      \"description\": \"飞书应用 App ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_APP_SECRET\",\n      \"type\": \"feishu_app_secret\",\n      \"required\": false,\n      \"description\": \"飞书应用 Secret（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_USER_OPEN_ID\",\n      \"type\": \"feishu_open_id\",\n      \"required\": false,\n      \"description\": \"接收语音的飞书用户 Open ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"MINIMAX_API_KEY\",\n      \"type\": \"api_key\",\n      \"required\": false,\n      \"description\": \"MiniMax API Key（填了启用云端 TTS，不填则跳过）\"\n    },\n    {\n      \"name\": \"PIPER_BIN\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper 主程序路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"PIPER_MODEL\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper ONNX 模型路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"SENSE_VOICE_MODEL_DIR\",\n      \"type\": \"directory_path\",\n      \"required\": false,\n      \"description\": \"SenseVoice 模型目录（填了启用本地 ASR，不填则跳过）\"\n    },\n    {\n      \"name\": \"BITABLE_APP_TOKEN\",\n      \"type\": \"feishu_bitable_token\",\n      \"required\": false,\n      \"description\": \"飞书多维表格 App Token（不填则无艾宾浩斯记忆）\"\n    },\n    {\n      \"name\": \"BITABLE_WORDS_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"words 表 ID（单词记录表）\"\n    },\n    {\n      \"name\": \"BITABLE_CHAT_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"chat_log 表 ID（对话历史表）\"\n    }\n  ],\n  \"module_design\": {\n    \"principle\": \"填了变量启用该模块，没填则静默跳过，不报错\",\n    \"modules\": [\n      {\n        \"name\": \"飞书语音推送\",\n        \"env\": [\"FEISHU_APP_ID\", \"FEISHU_APP_SECRET\", \"FEISHU_USER_OPEN_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不发飞书语音\"\n      },\n      {\n        \"name\": \"MiniMax TTS\",\n        \"env\": [\"MINIMAX_API_KEY\"],\n        \"behavior_when_empty\": \"静默跳过，尝试 Piper 本地 TTS\"\n      },\n      {\n        \"name\": \"Piper 本地 TTS\",\n        \"env\": [\"PIPER_BIN\", \"PIPER_MODEL\"],\n        \"behavior_when_empty\": \"静默跳过，无 TTS 功能\"\n      },\n      {\n        \"name\": \"SenseVoice 本地 ASR\",\n        \"env\": [\"SENSE_VOICE_MODEL_DIR\"],\n        \"behavior_when_empty\": \"静默跳过，仅支持文字输入\"\n      },\n      {\n        \"name\": \"多维表格记忆\",\n        \"env\": [\"BITABLE_APP_TOKEN\", \"BITABLE_WORDS_TABLE_ID\", \"BITABLE_CHAT_TABLE_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不记录学习进度\"\n      }\n    ]\n  },\n  \"scheduled_actions\": [\n    {\n      \"name\": \"每日晨间练习 08:00\",\n      \"cron\": \"0 8 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"用户选择开启后，自动生成跟读对话，发飞书语音，等待用户回复\"\n    },\n    {\n      \"name\": \"每日午间练习 12:00\",\n      \"cron\": \"0 12 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    },\n    {\n      \"name\": \"每日晚间练习 20:00\",\n      \"cron\": \"0 20 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    }\n  ],\n  \"data_storage\": {\n    \"conversation_history\": {\n      \"location\": \"飞书多维表格（BITABLE_APP_TOKEN 指向的多维表格）\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"user_id\", \"role\", \"text\", \"voice_url\", \"created_at\"],\n      \"note\": \"口语练习对话内容和语音 URL 会被存储用于艾宾浩斯复习\"\n    },\n    \"word_records\": {\n      \"location\": \"飞书多维表格\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"word\", \"user_id\", \"first_seen\", \"last_review\", \"next_review\", \"review_count\", \"mastery\", \"source\"]\n    },\n    \"config_file\": {\n      \"location\": \"~/.openclaw/english-tutor/config.json\",\n      \"sensitive\": true,\n      \"permission\": \"600\",\n      \"enabled\": \"always\"\n    }\n  },\n  \"external_downloads\": [\n    {\n      \"name\": \"Piper TTS\",\n      \"urls\": [\n        \"https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz\",\n        \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 TTS 兜底方案，来源可信但无 checksum 校验\"\n    },\n    {\n      \"name\": \"SenseVoice ASR\",\n      \"urls\": [\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/model.onnx\",\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/tokens.txt\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 ASR，来源可信但无 checksum 校验\"\n    }\n  ]\n}\n\nArchive v3.0.0: 20 files, 44543 bytes\n\nFiles: agent/agent.js (10489b), agent/asr.js (2428b), agent/config.js (2537b), agent/feishu-voice.js (7313b), agent/local-tts.js (6848b), agent/memory.js (5655b), agent/minimax.js (6246b), agent/morning-task-v2.js (12941b), assets/wordlist_example.csv (812b), metadata.json (5330b), references/config-schema.md (5369b), scripts/check_env.py (6064b), scripts/config_manager.py (3372b), scripts/download_model.py (1966b), scripts/download_model.sh (1079b), scripts/feishu_voice.py (5219b), scripts/transcribe.py (5994b), scripts/wordlist_parser.py (4937b), SKILL.md (7523b), _meta.json (136b)\n\nFile v3.0.0:SKILL.md\n\n# 英语助教 · English Tutor Skill\n\n> **模块化基座 Skill** — 功能按需配置，所有环境变量均为**选填**。\n> 有配置就启用对应功能，无配置则跳过。完整功能需要飞书 + MiniMax + 多维表格。\n\n---\n\n## 功能模块（按需启用）\n\n| 模块 | 环境变量 | 说明 |\n|------|---------|------|\n| 飞书语音推送 | `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `FEISHU_USER_OPEN_ID` | 发 TTS 语音到飞书 |\n| MiniMax TTS | `MINIMAX_API_KEY` | 云端语音合成（主方案） |\n| Piper 本地 TTS | `PIPER_BIN`, `PIPER_MODEL` | 完全离线的语音兜底 |\n| SenseVoice 本地 ASR | `SENSE_VOICE_MODEL_DIR` | 完全离线的语音识别 |\n| 多维表格记忆 | `BITABLE_APP_TOKEN`, `BITABLE_WORDS_TABLE_ID`, `BITABLE_CHAT_TABLE_ID` | 单词记录 + 艾宾浩斯 |\n| 定时推送 | cron jobs | 08:00 / 12:00 / 20:00（可单独开启） |\n\n**原则**：填了变量 → 启用该模块；没填 → 该模块静默跳过，不报错。\n\n---\n\n## 文件结构\n\n```\nenglish-tutor/\n├── SKILL.md\n├── metadata.json\n├── agent/                    ← 核心运行时代码（已审查，全部可见）\n│   ├── config.js\n│   ├── feishu-voice.js\n│   ├── local-tts.js\n│   ├── minimax.js\n│   ├── asr.js\n│   ├── memory.js\n│   ├── agent.js\n│   └── morning-task-v2.js\n├── scripts/\n│   ├── check_env.py\n│   ├── config_manager.py\n│   ├── download_model.py\n│   ├── feishu_voice.py\n│   └── wordlist_parser.py\n├── references/\n│   └── config-schema.md\n└── assets/\n    └── wordlist_example.csv\n```\n\n---\n\n## 环境变量（全部选填）\n\n### 飞书模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `FEISHU_APP_ID` | `\"\"` | 飞书应用 App ID（填了才发飞书语音） |\n| `FEISHU_APP_SECRET` | `\"\"` | 飞书应用 Secret |\n| `FEISHU_USER_OPEN_ID` | `\"\"` | 接收语音的飞书用户 Open ID |\n\n### TTS 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `MINIMAX_API_KEY` | `\"\"` | MiniMax API Key（不填则跳过云端 TTS） |\n| `MINIMAX_TTS_MODEL` | `speech-2.8-hd` | TTS 模型 |\n| `MINIMAX_TTS_SPEED` | `1.05` | 语速 |\n| `MINIMAX_TTS_VOICE_ID` | `male-qn-qingse` | 音色 ID |\n| `PIPER_BIN` | `\"\"` | Piper 主程序路径（不填则跳过本地 TTS） |\n| `PIPER_MODEL` | `\"\"` | Piper ONNX 模型路径 |\n| `TTS_PROVIDER` | `minimax` | 优先方案：`minimax` / `piper` |\n\n### ASR 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `SENSE_VOICE_MODEL_DIR` | `\"\"` | SenseVoice 模型目录（不填则跳过本地 ASR） |\n\n### 多维表格模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `BITABLE_APP_TOKEN` | `\"\"` | App Token（不填则无艾宾浩斯记忆） |\n| `BITABLE_WORDS_TABLE_ID` | `\"\"` | words 表 ID |\n| `BITABLE_CHAT_TABLE_ID` | `\"\"` | chat_log 表 ID |\n\n### 每日练习配置\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `DAILY_WORD_MAX` | `15` | 每日新词上限 |\n\n---\n\n## 凭据声明（metadata）\n\n本 skill 为 **Credential-Using Skill**，但**所有凭据均为选填**：\n\n```json\n{\n  \"credential_using\": true,\n  \"required_credentials\": [],\n  \"optional_credentials\": [\n    { \"name\": \"FEISHU_APP_ID\",      \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_APP_SECRET\",  \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_USER_OPEN_ID\",\"description\": \"飞书语音推送\" },\n    { \"name\": \"MINIMAX_API_KEY\",    \"description\": \"云端 TTS + LLM 对话\" },\n    { \"name\": \"BITABLE_APP_TOKEN\",  \"description\": \"艾宾浩斯记忆（可选）\" },\n    { \"name\": \"BITABLE_WORDS_TABLE_ID\", \"description\": \"单词记录表\" },\n    { \"name\": \"BITABLE_CHAT_TABLE_ID\",  \"description\": \"对话历史表\" }\n  ]\n}\n```\n\n---\n\n## 定时任务\n\n| 时间 | cron | 说明 |\n|------|------|------|\n| 晨间 | `0 8 * * *` | 通勤场景跟读 |\n| 午间 | `0 12 * * *` | 口语问答 |\n| 晚间 | `0 20 * * *` | 复盘 + 旧词复习 |\n\n**定时任务默认关闭**，用户在引导设置中自行选择开启哪些。\n\n---\n\n## 引导设置流程（用户可选配置）\n\n### 第 1 步：飞书配置（选填）\n- 提供 `FEISHU_APP_ID` / `FEISHU_APP_SECRET` / `FEISHU_USER_OPEN_ID`\n- 不填则无飞书语音推送功能\n\n### 第 2 步：TTS 配置（选填）\n- MiniMax：提供 `MINIMAX_API_KEY`\n- Piper 本地：提供 `PIPER_BIN` / `PIPER_MODEL`\n- 都不填则 TTS 功能不可用（仍有文字对话）\n\n### 第 3 步：ASR 配置（选填）\n- 提供 `SENSE_VOICE_MODEL_DIR`（或运行 `python3 scripts/download_model.py`）\n- 不填则无法处理语音输入（仅支持文字）\n\n### 第 4 步：多维表格（选填）\n- 提供 `BITABLE_APP_TOKEN` + 两个表 ID\n- 不填则无艾宾浩斯记忆功能（仍可练习，但不记录进度）\n\n### 第 5 步：每日定时（选填）\n- 选择开启哪些时段（08:00 / 12:00 / 20:00）\n- 不选择则不创建 cron 任务\n\n### 第 6 步：上传单词表（选填）\n- CSV 或纯文本格式\n- 不上传也可进行自由对话练习\n\n---\n\n## 核心模块说明\n\n### feishu-voice.js — 飞书语音发送\n- 优先 MiniMax TTS，配额耗尽自动切换 Piper\n- 无任何凭据配置时：静默跳过，不报错\n- 流程：TTS → Opus → 上传飞书 → 发送 audio 消息\n\n### asr.js — SenseVoice 本地 ASR\n- 无本地模型时：静默跳过，回退到文字输入\n- 使用 `json.dumps` 安全传递路径，无 shell 注入\n\n### memory.js — 多维表格\n- 无多维表格配置时：静默跳过，不记录历史\n- 所有操作有 try/catch，不因单次失败中断流程\n\n### agent.js — 主流程\n- **课程模式**（定时触发，无用户输入）：自动生成跟读对话，逐条发飞书语音\n- **交互模式**（用户发消息）：实时对话 + 可选 TTS 回复\n- 所有模块都是**失败静默跳过**，不影响其他模块运行\n\n---\n\n## 安全设计原则\n\n1. **所有密钥通过环境变量注入**，不硬编码\n2. **feishu_voice.py**：配置通过 `env=` 参数传递给 Node.js 子进程（内存传递）\n3. **scripts/ 无 shell=True**：subprocess 使用列表形式\n4. **config.json 权限**：`~/.openclaw/english-tutor/config.json` 设为 `600`\n5. **JS 源码全部纳入 skill 包**，审查者可查看全部代码\n\n---\n\n## 模型下载命令\n\n### Piper TTS（本地语音合成）\n\n```bash\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/piper/voices\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\n```\n\n### SenseVoice ASR（本地语音识别）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\npython3 /vol1/@apphome/trim.openclaw/data/workspace/skills/english-tutor/scripts/download_model.py\n```\n\n---\n\n## 单词表格式\n\n**CSV（推荐）：**\n```csv\nword,pronunciation,meaning,example\ncommute,/kəˈmjuːt/,通勤,I commute by subway every day.\n```\n\n**纯文本（每行一个）：**\n```\ncommute,通勤\nsubway,地铁\ntransfer,换乘\n```\n\n---\n\n## 艾宾浩斯复习周期\n\n| 复习轮次 | 间隔 |\n|---------|------|\n| 第 1 次 | 次日 |\n| 第 2 次 | 3 天后 |\n| 第 3 次 | 7 天后 |\n| 第 4 次 | 15 天后 |\n| 第 5 次+ | 掌握（不再自动提醒）|\n\nFile v3.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"3.0.0\",\n  \"publishedAt\": 1777817424692\n}\n\nFile v3.0.0:references/config-schema.md\n\n# English Tutor · 完整配置参考\n\n## 配置存储\n\n用户配置统一保存在 `~/.openclaw/english-tutor/config.json`，由 `scripts/config_manager.py` 管理。\n\n**首次由陪练助手通过对话引导创建，无需手动编辑。**\n\n---\n\n## config.json 字段说明\n\n### 基础配置\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `setup_complete` | ✅ | `false` | 首次设置是否完成 |\n| `word_list_path` | ✅ | `\"\"` | 单词表 JSON 文件路径 |\n| `daily_words` | ✅ | `5` | 每日练习单词数量（建议 5-15）|\n| `schedule_times` | ✅ | `[\"08:00\"]` | 每日推送时间（上海时区）|\n\n### LLM 模型配置 🤖\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `llm_provider` | ✅ | `\"openclaw\"` | 模型提供商：`openclaw` / `minimax` / `openai` |\n| `llm_model` | 否 | `\"\"` | 指定模型 ID（留空用默认）|\n\n> 选择 `openclaw` 时使用系统默认 LLM，无需额外配置。\n\n### 飞书语音配置 📢\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `feishu_app_id` | ✅ | `\"\"` | 飞书应用 App ID |\n| `feishu_app_secret` | ✅ | `\"\"` | 飞书应用 App Secret |\n| `feishu_bot_token` | 否 | `\"\"` | 飞书 Bot Token（可选）|\n| `feishu_user_open_id` | ✅ | `\"\"` | 接收消息的用户 Open ID |\n\n### TTS 语音合成 🔊\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `tts_provider` | 否 | `\"minimax\"` | TTS 方案：`minimax` / `piper` / `espeak` |\n| `minimax_api_key` | minimax时 | `\"\"` | MiniMax API Key |\n\n> MiniMax TTS 推荐音色：`male-qn-qingse`（男声）、`female-tianmei`（女声）\n\n### 多维表格（可选）\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `bitable_app_token` | 否 | `\"\"` | 飞书多维表格 App Token |\n| `bitable_words_table_id` | 否 | `\"\"` | words 表 ID |\n| `bitable_chat_table_id` | 否 | `\"\"` | chat_log 表 ID |\n\n### Piper 本地 TTS（可选）\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `piper_bin` | piper时 | piper 二进制路径 |\n| `piper_model` | piper时 | .onnx 模型文件路径 |\n\n---\n\n## 飞书 audio 消息发送流程\n\n每日练习第一步，通过 `scripts/feishu_voice.py` 实现：\n\n```\n1. TTS 合成 mp3\n   - minimax: POST /v1/t2a_v2 → hex audio → 解码为 mp3\n   - piper:   piper CLI → WAV\n   \n2. ffmpeg 转 opus\n   ffmpeg -i input.mp3 -ar 16000 -ac 1 -acodec libopus -b:a 128k output.opus\n\n3. 上传获取 file_key\n   POST /open-apis/im/v1/files\n   Content-Type: multipart/form-data; boundary=...\n   body: file_type=opus, file=opus二进制\n\n4. 发送 audio 消息\n   POST /open-apis/im/v1/messages?receive_id_type=open_id\n   {\n     \"receive_id\": \"<user_open_id>\",\n     \"msg_type\": \"audio\",\n     \"content\": \"{\\\"file_key\\\": \\\"<file_key>\\\"}\"\n   }\n```\n\n**使用示例：**\n```bash\n# 使用配置发送语音\npython3 scripts/feishu_voice.py \"Good morning! Today's vocabulary: commute, subway, transfer.\"\n\n# 使用配置（指定路径）\npython3 scripts/feishu_voice.py \"Hello!\" --config /path/to/config.json\n\n# 仅合成，不发送（调试用）\npython3 scripts/feishu_voice.py \"Hello!\" --dry-run\n```\n\n---\n\n## TTS_PROVIDER 配置\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n### piper（本地，高质量，离线）\n\n**下载主程序（Linux x86_64）：**\n```bash\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n```\n\n**下载英语模型（Lessac Medium，音质好，速度快）：**\n```bash\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /tmp/en_US-lessac-medium.onnx\n```\n\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/tmp/piper/piper_phonemize\nPIPER_MODEL=/tmp/en_US-lessac-medium.onnx\n```\n\n**测试：**\n```bash\necho \"Hello world\" | /tmp/piper/piper_phonemize \\\n  --model /tmp/en_US-lessac-medium.onnx \\\n  --input-file /dev/stdin -w /tmp/test.wav\n```\n\n### espeak-ng（系统级，完全离线）\n\n```bash\nsudo apt-get install espeak-ng\n```\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n---\n\n## ASR_PROVIDER 配置\n\n### local（默认，推荐，完全离线）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\nbash scripts/download_model.sh\n```\n\n### assemblyai / openai（云端）\n\n```env\nASR_PROVIDER=assemblyai\nASR_API_KEY=your-key\n```\n\n---\n\n## 多维表格表结构（可选）\n\n**表 1：单词表（words）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| word | 文本 | 英文单词 |\n| pronunciation | 文本 | 音标 |\n| meaning | 文本 | 中文释义 |\n| example | 文本 | 例句 |\n| mastery | 数字 | 掌握程度 0-5 |\n| review_count | 数字 | 复习次数 |\n| last_review | 日期时间 | 最近复习时间 |\n| next_review | 日期时间 | 下次复习时间 |\n| user_id | 文本 | 用户 ID |\n\n**表 2：对话记录（chat_log）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| user_id | 文本 | 用户 ID |\n| role | 单选 | `ai` 或 `user` |\n| text | 文本 | 对话内容 |\n| voice_url | 文本 | 语音 URL（可选）|\n| created_at | 日期时间 | 创建时间 |\n\nFile v3.0.0:metadata.json\n\n{\n  \"name\": \"english-tutor\",\n  \"version\": \"1.0.0\",\n  \"description\": \"英语口语陪练基座。飞书语音推送 + MiniMax/本地 TTS + SenseVoice ASR + 艾宾浩斯复习。全部模块选填，按需启用。\",\n  \"credential_using\": true,\n  \"all_optional\": true,\n  \"optional_credentials\": [\n    {\n      \"name\": \"FEISHU_APP_ID\",\n      \"type\": \"feishu_app_id\",\n      \"required\": false,\n      \"description\": \"飞书应用 App ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_APP_SECRET\",\n      \"type\": \"feishu_app_secret\",\n      \"required\": false,\n      \"description\": \"飞书应用 Secret（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_USER_OPEN_ID\",\n      \"type\": \"feishu_open_id\",\n      \"required\": false,\n      \"description\": \"接收语音的飞书用户 Open ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"MINIMAX_API_KEY\",\n      \"type\": \"api_key\",\n      \"required\": false,\n      \"description\": \"MiniMax API Key（填了启用云端 TTS，不填则跳过）\"\n    },\n    {\n      \"name\": \"PIPER_BIN\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper 主程序路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"PIPER_MODEL\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper ONNX 模型路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"SENSE_VOICE_MODEL_DIR\",\n      \"type\": \"directory_path\",\n      \"required\": false,\n      \"description\": \"SenseVoice 模型目录（填了启用本地 ASR，不填则跳过）\"\n    },\n    {\n      \"name\": \"BITABLE_APP_TOKEN\",\n      \"type\": \"feishu_bitable_token\",\n      \"required\": false,\n      \"description\": \"飞书多维表格 App Token（不填则无艾宾浩斯记忆）\"\n    },\n    {\n      \"name\": \"BITABLE_WORDS_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"words 表 ID（单词记录表）\"\n    },\n    {\n      \"name\": \"BITABLE_CHAT_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"chat_log 表 ID（对话历史表）\"\n    }\n  ],\n  \"module_design\": {\n    \"principle\": \"填了变量启用该模块，没填则静默跳过，不报错\",\n    \"modules\": [\n      {\n        \"name\": \"飞书语音推送\",\n        \"env\": [\"FEISHU_APP_ID\", \"FEISHU_APP_SECRET\", \"FEISHU_USER_OPEN_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不发飞书语音\"\n      },\n      {\n        \"name\": \"MiniMax TTS\",\n        \"env\": [\"MINIMAX_API_KEY\"],\n        \"behavior_when_empty\": \"静默跳过，尝试 Piper 本地 TTS\"\n      },\n      {\n        \"name\": \"Piper 本地 TTS\",\n        \"env\": [\"PIPER_BIN\", \"PIPER_MODEL\"],\n        \"behavior_when_empty\": \"静默跳过，无 TTS 功能\"\n      },\n      {\n        \"name\": \"SenseVoice 本地 ASR\",\n        \"env\": [\"SENSE_VOICE_MODEL_DIR\"],\n        \"behavior_when_empty\": \"静默跳过，仅支持文字输入\"\n      },\n      {\n        \"name\": \"多维表格记忆\",\n        \"env\": [\"BITABLE_APP_TOKEN\", \"BITABLE_WORDS_TABLE_ID\", \"BITABLE_CHAT_TABLE_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不记录学习进度\"\n      }\n    ]\n  },\n  \"scheduled_actions\": [\n    {\n      \"name\": \"每日晨间练习 08:00\",\n      \"cron\": \"0 8 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"用户选择开启后，自动生成跟读对话，发飞书语音，等待用户回复\"\n    },\n    {\n      \"name\": \"每日午间练习 12:00\",\n      \"cron\": \"0 12 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    },\n    {\n      \"name\": \"每日晚间练习 20:00\",\n      \"cron\": \"0 20 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    }\n  ],\n  \"data_storage\": {\n    \"conversation_history\": {\n      \"location\": \"飞书多维表格（BITABLE_APP_TOKEN 指向的多维表格）\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"user_id\", \"role\", \"text\", \"voice_url\", \"created_at\"],\n      \"note\": \"口语练习对话内容和语音 URL 会被存储用于艾宾浩斯复习\"\n    },\n    \"word_records\": {\n      \"location\": \"飞书多维表格\",\n      \"enabled\": \"当 BITABLE_APP_TOKEN 存在时\",\n      \"fields\": [\"word\", \"user_id\", \"first_seen\", \"last_review\", \"next_review\", \"review_count\", \"mastery\", \"source\"]\n    },\n    \"config_file\": {\n      \"location\": \"~/.openclaw/english-tutor/config.json\",\n      \"sensitive\": true,\n      \"permission\": \"600\",\n      \"enabled\": \"always\"\n    }\n  },\n  \"external_downloads\": [\n    {\n      \"name\": \"Piper TTS\",\n      \"urls\": [\n        \"https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz\",\n        \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 TTS 兜底方案，来源可信但无 checksum 校验\"\n    },\n    {\n      \"name\": \"SenseVoice ASR\",\n      \"urls\": [\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/model.onnx\",\n        \"https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/tokens.txt\"\n      ],\n      \"required\": false,\n      \"note\": \"本地 ASR，来源可信但无 checksum 校验\"\n    }\n  ]\n}\n\nArchive v2.0.1: 11 files, 20786 bytes\n\nFiles: assets/wordlist_example.csv (812b), references/config-schema.md (5369b), scripts/check_env.py (6064b), scripts/config_manager.py (2978b), scripts/download_model.py (1966b), scripts/download_model.sh (1079b), scripts/feishu_voice.py (5073b), scripts/transcribe.py (5994b), scripts/wordlist_parser.py (4937b), SKILL.md (9586b), _meta.json (136b)\n\nFile v2.0.1:SKILL.md\n\n---\nname: english-tutor\ndescription: 英语口语陪练助手。触发词：「练习英语」「我要说英语」「英语陪练」。功能：上传生词表 → 每日定时情景对话 → 语音输入即时纠错 → 飞书语音推送 → 自动艾宾浩斯复习。\n---\n\n# English Tutor · 英语口语陪练\n\n## 功能概览\n\n| 功能 | 说明 |\n|------|------|\n| 飞书语音推送 | 将任意文本转为语音，直接发到用户飞书（audio 消息） |\n| 每日定时练习 | cron 触发，自动选词 → 生成场景对话 → 语音推送飞书 |\n| 主动练习 | 用户说「练习英语」立即开始一轮 |\n| 语音纠错 | 接收用户语音回复，ASR 转写后 LLM 纠错 |\n| 艾宾浩斯复习 | 多维表格记录，智能计算下次复习时间 |\n\n---\n\n## 环境变量参考\n\n所有配置通过环境变量注入，**不硬编码任何路径或密钥**：\n\n```bash\n# ===== 飞书（必须）=====\nFEISHU_APP_ID=cli_xxx          # 飞书应用 App ID\nFEISHU_APP_SECRET=xxx           # 飞书应用 Secret\nFEISHU_USER_OPEN_ID=ou_xxx     # 接收语音消息的用户 Open ID\n\n# ===== MiniMax（必须）=====\nMINIMAX_API_KEY=eyxxx           # MiniMax API Key\nMINIMAX_TTS_MODEL=speech-2.8-hd # TTS 模型，默认 speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse  # 音色，默认 male-qn-qingse\nMINIMAX_TTS_SPEED=1.05          # 语速，默认 1.05\n\n# ===== 多维表格（必须）=====\nBITABLE_APP_TOKEN=Bo8RbDzMYaX3LuscmAHcgbLLndg\nBITABLE_WORDS_TABLE_ID=tblt29VL6DWwU0Fg   # 单词表\nBITABLE_CHAT_TABLE_ID=tblIku7hSn7kXlBx   # 对话记录表\n\n# ===== 本地 TTS 兜底（可选，不填则跳过）=====\nPIPER_BIN=/vol1/@apphome/trim.openclaw/data/workspace/piper/piper\nPIPER_LIB=/vol1/@apphome/trim.openclaw/data/workspace/piper\nPIPER_MODEL=/vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\nPIPER_MODEL_JSON=/vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx.json\n\n# ===== 本地 ASR（可选，不填则使用 MiniMax ASR）=====\nSENSE_VOICE_MODEL_DIR=/vol1/@apphome/trim.openclaw/data/workspace/models/sherpa-onnx-sense-voice-small\n\n# ===== 每日新词上限 =====\nDAILY_WORD_MAX=15\n```\n\n---\n\n## 核心模块 API\n\n### 1. 飞书语音发送 — `feishu-voice.js`\n\n**发送语音消息到飞书（audio 类型，可直接播放）**\n\n```javascript\nconst { sendVoiceMessage } = require('./feishu-voice');\n\n// 发送文本语音（自动 TTS → ffmpeg → 上传 → 发送）\nawait sendVoiceMessage('Hello, how are you today?', userOpenId);\n// → Promise<{ message_id: string }>\n\n// 兜底逻辑：MiniMax 配额耗尽 → 自动切换 Piper 本地 TTS\n// 如两者都失败，抛异常\n```\n\n**CLI 用法：**\n```bash\nFEISHU_USER_OPEN_ID=ou_xxx node feishu-voice.js \"Hello world\"\n```\n\n**流程：**\n```\n文本 → MiniMax TTS → MP3 → ffmpeg 转 Opus → 上传飞书(file_key) → 发送 audio 消息\n                            ↑\n                      配额耗尽时自动切换\n                            ↓\n                    Piper 本地 TTS → WAV → Opus\n```\n\n---\n\n### 2. 本地 TTS — `local-tts.js`\n\n**Piper 完全离线语音合成（MiniMax 兜底方案）**\n\n```javascript\nconst { speakLocal } = require('./local-tts');\n\n// 直接合成 + 发送飞书语音\nawait speakLocal('要说的文本', userOpenId);\n```\n\n**前提：** 需下载 Piper 二进制 + 模型（见下方「下载命令」）\n\n---\n\n### 3. ASR 语音识别 — `asr.js`\n\n**本地 SenseVoice 离线转写**\n\n```javascript\nconst { transcribe } = require('./asr');\n\nconst text = await transcribe('/path/to/audio.ogg', { sampleRate: 16000 });\n// → Promise<string> 转写文字\n```\n\n**前提：** 需下载 sherpa-onnx 模型（见下方「下载命令」）\n\n---\n\n### 4. 记忆模块 — `memory.js`\n\n**多维表格读写（单词记录 + 对话历史）**\n\n```javascript\nconst BitableMemory = require('./memory');\nconst memory = new BitableMemory(config);\n\n// 单词操作\nawait memory.getWordRecord(userId, 'commute');     // 查询单词\nawait memory.upsertWordRecord(userId, 'commute', { mastery: 3, review_count: 2 });\nawait memory.getReviewRecords(userId);             // 获取到期复习单词\nawait memory.getTodayNewWords(userId, 15);         // 获取今日新词\n\n// 对话历史\nawait memory.appendChatLog(userId, { role: 'ai', text: '...' }, { role: 'user', text: '...' });\nawait memory.getChatHistory(userId, 10);\n```\n\n---\n\n### 5. 主 Agent — `agent.js`\n\n**完整对话流程**\n\n```javascript\nconst { run } = require('./agent');\n\n// 交互模式（用户发消息触发）\nconst result = await run(userInputText, feishuEvent, 'morning');\n\n// 课程模式（定时任务，无用户输入时自动生成）\nconst result = await run('', event, 'evening');\n// → 自动生成3段跟读对话，发送飞书语音，等待用户回复\n```\n\n**返回：**\n```javascript\n{\n  success: true,\n  aiReply: '...',         // AI 回复文本\n  voiceUrl: 'file://...',  // 语音文件路径\n  pushText: '...',        // 飞书推送文本\n  lessonMode: false,      // 是否为课程模式\n}\n```\n\n---\n\n## 定时任务配置\n\n每个时间点创建独立 cron：\n\n```json\n{\n  \"name\": \"英语陪练·每日练习 08:00\",\n  \"schedule\": { \"kind\": \"cron\", \"expr\": \"0 8 * * *\", \"tz\": \"Asia/Shanghai\" },\n  \"sessionTarget\": \"isolated\",\n  \"payload\": {\n    \"kind\": \"agentTurn\",\n    \"message\": \"执行每日英语练习：加载配置和今日单词（艾宾浩斯优先），生成情景对话，用飞书语音发送今日单词到飞书，等待用户回复并纠错，最后更新单词复习日期。\",\n    \"timeoutSeconds\": 300\n  },\n  \"delivery\": { \"mode\": \"none\" }\n}\n```\n\n**环境变量注入：** cron `env` 字段注入所有配置（见上方环境变量参考）\n\n---\n\n## 模型下载命令\n\n### Piper TTS（本地语音合成）\n\n```bash\n# 下载 piper 主程序（Linux x86_64）\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/piper\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n\n# 下载美语语音模型（Lessac Medium）\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\n\n# 验证\necho \"hello\" | /tmp/piper/piper_phonemize --model /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx -f /dev/stdin -w /tmp/test.wav\n```\n\n### SenseVoice ASR（本地语音识别）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\n\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/models/sherpa-onnx-sense-voice-small\ncurl -L \"https://huggingface.co/py1337/sherpa-onnx-sense-voice-small/resolve/main/model.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/models/sherpa-onnx-sense-voice-small/model.onnx\ncurl -L \"https://huggingface.co/py1337/sherpa-onnx-sense-voice-small/resolve/main/tokens.txt\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/models/sherpa-onnx-sense-voice-small/tokens.txt\n\n# 验证\npython3 -c \"import sherpa_onnx; print('OK')\"\n```\n\n---\n\n## 引导设置流程\n\n当 `setup_complete == false` 时，按以下步骤引导用户：\n\n**步骤 1：模型配置**（见上方环境变量说明）\n\n**步骤 2：飞书配置**（提供 app_id / app_secret / user_open_id）\n\n**步骤 3：飞书连通验证**（让用户向 Bot 发消息，确认能收到）\n\n**步骤 4：上传单词表**（CSV 或纯文本格式）\n\n**步骤 5：每日词数**（默认 15）\n\n**步骤 6：练习时间**（默认 08:00 / 12:00 / 20:00）\n\n**步骤 7：创建 cron 定时任务**\n\n---\n\n## 单词表格式\n\n**CSV（推荐）：**\n```csv\nword,pronunciation,meaning,example\ncommute,/kəˈmjuːt/,通勤,I commute by subway every day.\nsubway,/ˈsʌbweɪ/,地铁,The subway is faster than the bus.\n```\n\n**纯文本（每行一个）：**\n```csv\ncommute,通勤\nsubway,地铁\ntransfer,换乘\n```\n\n---\n\n## 艾宾浩斯复习周期\n\n| 复习轮次 | 间隔 |\n|---------|------|\n| 第 1 次 | 次日 |\n| 第 2 次 | 3 天后 |\n| 第 3 次 | 7 天后 |\n| 第 4 次 | 15 天后 |\n| 第 5 次+ | 掌握（不再自动提醒）|\n\n---\n\n## 文件结构\n\n```\nenglish-tutor/\n├── SKILL.md               ← 本文件\n├── agent.js               ← 主 Agent（课程模式 + 交互模式）\n├── feishu-voice.js         ← 飞书语音发送（核心功能）\n├── local-tts.js           ← Piper 本地 TTS（MiniMax 兜底）\n├── asr.js                 ← SenseVoice 本地 ASR\n├── minimax.js             ← MiniMax TTS + Chat API\n├── memory.js              ← 多维表格记忆模块\n├── config.js              ← 配置加载（环境变量）\n└── scripts/\n    ├── check_env.py        ← 环境检测（subprocess 列表形式，无 shell=True）\n    ├── download_model.py   ← 模型下载（urllib，无 shell=True）\n    └── wordlist_parser.py ← 词表解析\n```\n\n---\n\n## 安全原则\n\n- **所有密钥和路径必须通过环境变量注入**，禁止硬编码\n- **feishu_voice.py 不写 .env 文件**：配置从 config.json 读入后直接通过 `env=` 参数传递给 Node.js 子进程（内存传递，永不落盘）\n- **check_env.py 无 shell=True**：所有 subprocess 调用使用列表形式 `subprocess.run([cmd, arg, ...])`\n- **download_model.py 无 curl**：使用 Python 内置 `urllib.request`，无 shell=True\n- Python 代码块使用 `JSON.stringify` 防注入，不直接拼接 shell 变量\n\nFile v2.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"2.0.1\",\n  \"publishedAt\": 1777700447574\n}\n\nFile v2.0.1:references/config-schema.md\n\n# English Tutor · 完整配置参考\n\n## 配置存储\n\n用户配置统一保存在 `~/.openclaw/english-tutor/config.json`，由 `scripts/config_manager.py` 管理。\n\n**首次由陪练助手通过对话引导创建，无需手动编辑。**\n\n---\n\n## config.json 字段说明\n\n### 基础配置\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `setup_complete` | ✅ | `false` | 首次设置是否完成 |\n| `word_list_path` | ✅ | `\"\"` | 单词表 JSON 文件路径 |\n| `daily_words` | ✅ | `5` | 每日练习单词数量（建议 5-15）|\n| `schedule_times` | ✅ | `[\"08:00\"]` | 每日推送时间（上海时区）|\n\n### LLM 模型配置 🤖\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `llm_provider` | ✅ | `\"openclaw\"` | 模型提供商：`openclaw` / `minimax` / `openai` |\n| `llm_model` | 否 | `\"\"` | 指定模型 ID（留空用默认）|\n\n> 选择 `openclaw` 时使用系统默认 LLM，无需额外配置。\n\n### 飞书语音配置 📢\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `feishu_app_id` | ✅ | `\"\"` | 飞书应用 App ID |\n| `feishu_app_secret` | ✅ | `\"\"` | 飞书应用 App Secret |\n| `feishu_bot_token` | 否 | `\"\"` | 飞书 Bot Token（可选）|\n| `feishu_user_open_id` | ✅ | `\"\"` | 接收消息的用户 Open ID |\n\n### TTS 语音合成 🔊\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `tts_provider` | 否 | `\"minimax\"` | TTS 方案：`minimax` / `piper` / `espeak` |\n| `minimax_api_key` | minimax时 | `\"\"` | MiniMax API Key |\n\n> MiniMax TTS 推荐音色：`male-qn-qingse`（男声）、`female-tianmei`（女声）\n\n### 多维表格（可选）\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `bitable_app_token` | 否 | `\"\"` | 飞书多维表格 App Token |\n| `bitable_words_table_id` | 否 | `\"\"` | words 表 ID |\n| `bitable_chat_table_id` | 否 | `\"\"` | chat_log 表 ID |\n\n### Piper 本地 TTS（可选）\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `piper_bin` | piper时 | piper 二进制路径 |\n| `piper_model` | piper时 | .onnx 模型文件路径 |\n\n---\n\n## 飞书 audio 消息发送流程\n\n每日练习第一步，通过 `scripts/feishu_voice.py` 实现：\n\n```\n1. TTS 合成 mp3\n   - minimax: POST /v1/t2a_v2 → hex audio → 解码为 mp3\n   - piper:   piper CLI → WAV\n   \n2. ffmpeg 转 opus\n   ffmpeg -i input.mp3 -ar 16000 -ac 1 -acodec libopus -b:a 128k output.opus\n\n3. 上传获取 file_key\n   POST /open-apis/im/v1/files\n   Content-Type: multipart/form-data; boundary=...\n   body: file_type=opus, file=opus二进制\n\n4. 发送 audio 消息\n   POST /open-apis/im/v1/messages?receive_id_type=open_id\n   {\n     \"receive_id\": \"<user_open_id>\",\n     \"msg_type\": \"audio\",\n     \"content\": \"{\\\"file_key\\\": \\\"<file_key>\\\"}\"\n   }\n```\n\n**使用示例：**\n```bash\n# 使用配置发送语音\npython3 scripts/feishu_voice.py \"Good morning! Today's vocabulary: commute, subway, transfer.\"\n\n# 使用配置（指定路径）\npython3 scripts/feishu_voice.py \"Hello!\" --config /path/to/config.json\n\n# 仅合成，不发送（调试用）\npython3 scripts/feishu_voice.py \"Hello!\" --dry-run\n```\n\n---\n\n## TTS_PROVIDER 配置\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n### piper（本地，高质量，离线）\n\n**下载主程序（Linux x86_64）：**\n```bash\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n```\n\n**下载英语模型（Lessac Medium，音质好，速度快）：**\n```bash\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /tmp/en_US-lessac-medium.onnx\n```\n\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/tmp/piper/piper_phonemize\nPIPER_MODEL=/tmp/en_US-lessac-medium.onnx\n```\n\n**测试：**\n```bash\necho \"Hello world\" | /tmp/piper/piper_phonemize \\\n  --model /tmp/en_US-lessac-medium.onnx \\\n  --input-file /dev/stdin -w /tmp/test.wav\n```\n\n### espeak-ng（系统级，完全离线）\n\n```bash\nsudo apt-get install espeak-ng\n```\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n---\n\n## ASR_PROVIDER 配置\n\n### local（默认，推荐，完全离线）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\nbash scripts/download_model.sh\n```\n\n### assemblyai / openai（云端）\n\n```env\nASR_PROVIDER=assemblyai\nASR_API_KEY=your-key\n```\n\n---\n\n## 多维表格表结构（可选）\n\n**表 1：单词表（words）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| word | 文本 | 英文单词 |\n| pronunciation | 文本 | 音标 |\n| meaning | 文本 | 中文释义 |\n| example | 文本 | 例句 |\n| mastery | 数字 | 掌握程度 0-5 |\n| review_count | 数字 | 复习次数 |\n| last_review | 日期时间 | 最近复习时间 |\n| next_review | 日期时间 | 下次复习时间 |\n| user_id | 文本 | 用户 ID |\n\n**表 2：对话记录（chat_log）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| user_id | 文本 | 用户 ID |\n| role | 单选 | `ai` 或 `user` |\n| text | 文本 | 对话内容 |\n| voice_url | 文本 | 语音 URL（可选）|\n| created_at | 日期时间 | 创建时间 |\n\nArchive v2.0.0: 10 files, 19734 bytes\n\nFiles: assets/wordlist_example.csv (812b), references/config-schema.md (5369b), scripts/check_env.py (6163b), scripts/config_manager.py (2978b), scripts/download_model.sh (1079b), scripts/feishu_voice.py (5871b), scripts/transcribe.py (5994b), scripts/wordlist_parser.py (4937b), SKILL.md (9324b), _meta.json (136b)\n\nFile v2.0.0:SKILL.md\n\n---\nname: english-tutor\ndescription: 英语口语陪练助手。触发词：「练习英语」「我要说英语」「英语陪练」。功能：上传生词表 → 每日定时情景对话 → 语音输入即时纠错 → 飞书语音推送 → 自动艾宾浩斯复习。\n---\n\n# English Tutor · 英语口语陪练\n\n## 功能概览\n\n| 功能 | 说明 |\n|------|------|\n| 飞书语音推送 | 将任意文本转为语音，直接发到用户飞书（audio 消息） |\n| 每日定时练习 | cron 触发，自动选词 → 生成场景对话 → 语音推送飞书 |\n| 主动练习 | 用户说「练习英语」立即开始一轮 |\n| 语音纠错 | 接收用户语音回复，ASR 转写后 LLM 纠错 |\n| 艾宾浩斯复习 | 多维表格记录，智能计算下次复习时间 |\n\n---\n\n## 环境变量参考\n\n所有配置通过环境变量注入，**不硬编码任何路径或密钥**：\n\n```bash\n# ===== 飞书（必须）=====\nFEISHU_APP_ID=cli_xxx          # 飞书应用 App ID\nFEISHU_APP_SECRET=xxx           # 飞书应用 Secret\nFEISHU_USER_OPEN_ID=ou_xxx     # 接收语音消息的用户 Open ID\n\n# ===== MiniMax（必须）=====\nMINIMAX_API_KEY=eyxxx           # MiniMax API Key\nMINIMAX_TTS_MODEL=speech-2.8-hd # TTS 模型，默认 speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse  # 音色，默认 male-qn-qingse\nMINIMAX_TTS_SPEED=1.05          # 语速，默认 1.05\n\n# ===== 多维表格（必须）=====\nBITABLE_APP_TOKEN=Bo8RbDzMYaX3LuscmAHcgbLLndg\nBITABLE_WORDS_TABLE_ID=tblt29VL6DWwU0Fg   # 单词表\nBITABLE_CHAT_TABLE_ID=tblIku7hSn7kXlBx   # 对话记录表\n\n# ===== 本地 TTS 兜底（可选，不填则跳过）=====\nPIPER_BIN=/vol1/@apphome/trim.openclaw/data/workspace/piper/piper\nPIPER_LIB=/vol1/@apphome/trim.openclaw/data/workspace/piper\nPIPER_MODEL=/vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\nPIPER_MODEL_JSON=/vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx.json\n\n# ===== 本地 ASR（可选，不填则使用 MiniMax ASR）=====\nSENSE_VOICE_MODEL_DIR=/vol1/@apphome/trim.openclaw/data/workspace/models/sherpa-onnx-sense-voice-small\n\n# ===== 每日新词上限 =====\nDAILY_WORD_MAX=15\n```\n\n---\n\n## 核心模块 API\n\n### 1. 飞书语音发送 — `feishu-voice.js`\n\n**发送语音消息到飞书（audio 类型，可直接播放）**\n\n```javascript\nconst { sendVoiceMessage } = require('./feishu-voice');\n\n// 发送文本语音（自动 TTS → ffmpeg → 上传 → 发送）\nawait sendVoiceMessage('Hello, how are you today?', userOpenId);\n// → Promise<{ message_id: string }>\n\n// 兜底逻辑：MiniMax 配额耗尽 → 自动切换 Piper 本地 TTS\n// 如两者都失败，抛异常\n```\n\n**CLI 用法：**\n```bash\nFEISHU_USER_OPEN_ID=ou_xxx node feishu-voice.js \"Hello world\"\n```\n\n**流程：**\n```\n文本 → MiniMax TTS → MP3 → ffmpeg 转 Opus → 上传飞书(file_key) → 发送 audio 消息\n                            ↑\n                      配额耗尽时自动切换\n                            ↓\n                    Piper 本地 TTS → WAV → Opus\n```\n\n---\n\n### 2. 本地 TTS — `local-tts.js`\n\n**Piper 完全离线语音合成（MiniMax 兜底方案）**\n\n```javascript\nconst { speakLocal } = require('./local-tts');\n\n// 直接合成 + 发送飞书语音\nawait speakLocal('要说的文本', userOpenId);\n```\n\n**前提：** 需下载 Piper 二进制 + 模型（见下方「下载命令」）\n\n---\n\n### 3. ASR 语音识别 — `asr.js`\n\n**本地 SenseVoice 离线转写**\n\n```javascript\nconst { transcribe } = require('./asr');\n\nconst text = await transcribe('/path/to/audio.ogg', { sampleRate: 16000 });\n// → Promise<string> 转写文字\n```\n\n**前提：** 需下载 sherpa-onnx 模型（见下方「下载命令」）\n\n---\n\n### 4. 记忆模块 — `memory.js`\n\n**多维表格读写（单词记录 + 对话历史）**\n\n```javascript\nconst BitableMemory = require('./memory');\nconst memory = new BitableMemory(config);\n\n// 单词操作\nawait memory.getWordRecord(userId, 'commute');     // 查询单词\nawait memory.upsertWordRecord(userId, 'commute', { mastery: 3, review_count: 2 });\nawait memory.getReviewRecords(userId);             // 获取到期复习单词\nawait memory.getTodayNewWords(userId, 15);         // 获取今日新词\n\n// 对话历史\nawait memory.appendChatLog(userId, { role: 'ai', text: '...' }, { role: 'user', text: '...' });\nawait memory.getChatHistory(userId, 10);\n```\n\n---\n\n### 5. 主 Agent — `agent.js`\n\n**完整对话流程**\n\n```javascript\nconst { run } = require('./agent');\n\n// 交互模式（用户发消息触发）\nconst result = await run(userInputText, feishuEvent, 'morning');\n\n// 课程模式（定时任务，无用户输入时自动生成）\nconst result = await run('', event, 'evening');\n// → 自动生成3段跟读对话，发送飞书语音，等待用户回复\n```\n\n**返回：**\n```javascript\n{\n  success: true,\n  aiReply: '...',         // AI 回复文本\n  voiceUrl: 'file://...',  // 语音文件路径\n  pushText: '...',        // 飞书推送文本\n  lessonMode: false,      // 是否为课程模式\n}\n```\n\n---\n\n## 定时任务配置\n\n每个时间点创建独立 cron：\n\n```json\n{\n  \"name\": \"英语陪练·每日练习 08:00\",\n  \"schedule\": { \"kind\": \"cron\", \"expr\": \"0 8 * * *\", \"tz\": \"Asia/Shanghai\" },\n  \"sessionTarget\": \"isolated\",\n  \"payload\": {\n    \"kind\": \"agentTurn\",\n    \"message\": \"执行每日英语练习：加载配置和今日单词（艾宾浩斯优先），生成情景对话，用飞书语音发送今日单词到飞书，等待用户回复并纠错，最后更新单词复习日期。\",\n    \"timeoutSeconds\": 300\n  },\n  \"delivery\": { \"mode\": \"none\" }\n}\n```\n\n**环境变量注入：** cron `env` 字段注入所有配置（见上方环境变量参考）\n\n---\n\n## 模型下载命令\n\n### Piper TTS（本地语音合成）\n\n```bash\n# 下载 piper 主程序（Linux x86_64）\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/piper\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n\n# 下载美语语音模型（Lessac Medium）\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx\n\n# 验证\necho \"hello\" | /tmp/piper/piper_phonemize --model /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx -f /dev/stdin -w /tmp/test.wav\n```\n\n### SenseVoice ASR（本地语音识别）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\n\nmkdir -p /vol1/@apphome/trim.openclaw/data/workspace/models/sherpa-onnx-sense-voice-small\ncurl -L \"https://huggingface.co/py1337/sherpa-onnx-sense-voice-small/resolve/main/model.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/models/sherpa-onnx-sense-voice-small/model.onnx\ncurl -L \"https://huggingface.co/py1337/sherpa-onnx-sense-voice-small/resolve/main/tokens.txt\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/models/sherpa-onnx-sense-voice-small/tokens.txt\n\n# 验证\npython3 -c \"import sherpa_onnx; print('OK')\"\n```\n\n---\n\n## 引导设置流程\n\n当 `setup_complete == false` 时，按以下步骤引导用户：\n\n**步骤 1：模型配置**（见上方环境变量说明）\n\n**步骤 2：飞书配置**（提供 app_id / app_secret / user_open_id）\n\n**步骤 3：飞书连通验证**（让用户向 Bot 发消息，确认能收到）\n\n**步骤 4：上传单词表**（CSV 或纯文本格式）\n\n**步骤 5：每日词数**（默认 15）\n\n**步骤 6：练习时间**（默认 08:00 / 12:00 / 20:00）\n\n**步骤 7：创建 cron 定时任务**\n\n---\n\n## 单词表格式\n\n**CSV（推荐）：**\n```csv\nword,pronunciation,meaning,example\ncommute,/kəˈmjuːt/,通勤,I commute by subway every day.\nsubway,/ˈsʌbweɪ/,地铁,The subway is faster than the bus.\n```\n\n**纯文本（每行一个）：**\n```csv\ncommute,通勤\nsubway,地铁\ntransfer,换乘\n```\n\n---\n\n## 艾宾浩斯复习周期\n\n| 复习轮次 | 间隔 |\n|---------|------|\n| 第 1 次 | 次日 |\n| 第 2 次 | 3 天后 |\n| 第 3 次 | 7 天后 |\n| 第 4 次 | 15 天后 |\n| 第 5 次+ | 掌握（不再自动提醒）|\n\n---\n\n## 文件结构\n\n```\nenglish-tutor/\n├── SKILL.md               ← 本文件\n├── agent.js               ← 主 Agent（课程模式 + 交互模式）\n├── feishu-voice.js         ← 飞书语音发送（核心功能）\n├── local-tts.js           ← Piper 本地 TTS（MiniMax 兜底）\n├── asr.js                 ← SenseVoice 本地 ASR\n├── minimax.js             ← MiniMax TTS + Chat API\n├── memory.js              ← 多维表格记忆模块\n├── config.js              ← 配置加载（环境变量）\n└── scripts/\n    ├── check_env.py       ← 环境检测\n    ├── wordlist_parser.py ← 词表解析\n    └── download_model.sh  ← 模型下载脚本\n```\n\n---\n\n## 安全原则\n\n- **所有密钥和路径必须通过环境变量注入**，禁止硬编码\n- `.env` 文件仅用于本地开发，生产环境由 cron `env` 字段注入\n- `config.js` 加载 .env 但**不设默认值**（缺失环境变量时相关功能报错）\n- Python 代码块使用 `JSON.stringify` 防注入，不直接拼接 shell 变量\n\nFile v2.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"2.0.0\",\n  \"publishedAt\": 1777336252248\n}\n\nFile v2.0.0:references/config-schema.md\n\n# English Tutor · 完整配置参考\n\n## 配置存储\n\n用户配置统一保存在 `~/.openclaw/english-tutor/config.json`，由 `scripts/config_manager.py` 管理。\n\n**首次由陪练助手通过对话引导创建，无需手动编辑。**\n\n---\n\n## config.json 字段说明\n\n### 基础配置\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `setup_complete` | ✅ | `false` | 首次设置是否完成 |\n| `word_list_path` | ✅ | `\"\"` | 单词表 JSON 文件路径 |\n| `daily_words` | ✅ | `5` | 每日练习单词数量（建议 5-15）|\n| `schedule_times` | ✅ | `[\"08:00\"]` | 每日推送时间（上海时区）|\n\n### LLM 模型配置 🤖\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `llm_provider` | ✅ | `\"openclaw\"` | 模型提供商：`openclaw` / `minimax` / `openai` |\n| `llm_model` | 否 | `\"\"` | 指定模型 ID（留空用默认）|\n\n> 选择 `openclaw` 时使用系统默认 LLM，无需额外配置。\n\n### 飞书语音配置 📢\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `feishu_app_id` | ✅ | `\"\"` | 飞书应用 App ID |\n| `feishu_app_secret` | ✅ | `\"\"` | 飞书应用 App Secret |\n| `feishu_bot_token` | 否 | `\"\"` | 飞书 Bot Token（可选）|\n| `feishu_user_open_id` | ✅ | `\"\"` | 接收消息的用户 Open ID |\n\n### TTS 语音合成 🔊\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `tts_provider` | 否 | `\"minimax\"` | TTS 方案：`minimax` / `piper` / `espeak` |\n| `minimax_api_key` | minimax时 | `\"\"` | MiniMax API Key |\n\n> MiniMax TTS 推荐音色：`male-qn-qingse`（男声）、`female-tianmei`（女声）\n\n### 多维表格（可选）\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `bitable_app_token` | 否 | `\"\"` | 飞书多维表格 App Token |\n| `bitable_words_table_id` | 否 | `\"\"` | words 表 ID |\n| `bitable_chat_table_id` | 否 | `\"\"` | chat_log 表 ID |\n\n### Piper 本地 TTS（可选）\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `piper_bin` | piper时 | piper 二进制路径 |\n| `piper_model` | piper时 | .onnx 模型文件路径 |\n\n---\n\n## 飞书 audio 消息发送流程\n\n每日练习第一步，通过 `scripts/feishu_voice.py` 实现：\n\n```\n1. TTS 合成 mp3\n   - minimax: POST /v1/t2a_v2 → hex audio → 解码为 mp3\n   - piper:   piper CLI → WAV\n   \n2. ffmpeg 转 opus\n   ffmpeg -i input.mp3 -ar 16000 -ac 1 -acodec libopus -b:a 128k output.opus\n\n3. 上传获取 file_key\n   POST /open-apis/im/v1/files\n   Content-Type: multipart/form-data; boundary=...\n   body: file_type=opus, file=opus二进制\n\n4. 发送 audio 消息\n   POST /open-apis/im/v1/messages?receive_id_type=open_id\n   {\n     \"receive_id\": \"<user_open_id>\",\n     \"msg_type\": \"audio\",\n     \"content\": \"{\\\"file_key\\\": \\\"<file_key>\\\"}\"\n   }\n```\n\n**使用示例：**\n```bash\n# 使用配置发送语音\npython3 scripts/feishu_voice.py \"Good morning! Today's vocabulary: commute, subway, transfer.\"\n\n# 使用配置（指定路径）\npython3 scripts/feishu_voice.py \"Hello!\" --config /path/to/config.json\n\n# 仅合成，不发送（调试用）\npython3 scripts/feishu_voice.py \"Hello!\" --dry-run\n```\n\n---\n\n## TTS_PROVIDER 配置\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n### piper（本地，高质量，离线）\n\n**下载主程序（Linux x86_64）：**\n```bash\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n```\n\n**下载英语模型（Lessac Medium，音质好，速度快）：**\n```bash\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /tmp/en_US-lessac-medium.onnx\n```\n\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/tmp/piper/piper_phonemize\nPIPER_MODEL=/tmp/en_US-lessac-medium.onnx\n```\n\n**测试：**\n```bash\necho \"Hello world\" | /tmp/piper/piper_phonemize \\\n  --model /tmp/en_US-lessac-medium.onnx \\\n  --input-file /dev/stdin -w /tmp/test.wav\n```\n\n### espeak-ng（系统级，完全离线）\n\n```bash\nsudo apt-get install espeak-ng\n```\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n---\n\n## ASR_PROVIDER 配置\n\n### local（默认，推荐，完全离线）\n\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\nbash scripts/download_model.sh\n```\n\n### assemblyai / openai（云端）\n\n```env\nASR_PROVIDER=assemblyai\nASR_API_KEY=your-key\n```\n\n---\n\n## 多维表格表结构（可选）\n\n**表 1：单词表（words）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| word | 文本 | 英文单词 |\n| pronunciation | 文本 | 音标 |\n| meaning | 文本 | 中文释义 |\n| example | 文本 | 例句 |\n| mastery | 数字 | 掌握程度 0-5 |\n| review_count | 数字 | 复习次数 |\n| last_review | 日期时间 | 最近复习时间 |\n| next_review | 日期时间 | 下次复习时间 |\n| user_id | 文本 | 用户 ID |\n\n**表 2：对话记录（chat_log）**\n\n| 字段名 | 类型 | 说明 |\n|--------|------|------|\n| user_id | 文本 | 用户 ID |\n| role | 单选 | `ai` 或 `user` |\n| text | 文本 | 对话内容 |\n| voice_url | 文本 | 语音 URL（可选）|\n| created_at | 日期时间 | 创建时间 |\n\nArchive v1.0.0: 6 files, 10092 bytes\n\nFiles: references/config-schema.md (3836b), scripts/check_env.py (6066b), scripts/download_model.sh (1079b), scripts/transcribe.py (5994b), SKILL.md (4506b), _meta.json (136b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: english-tutor\ndescription: 英语口语陪练助手，支持语音对话纠错。当用户想要练习英语口语、语音交互、英文错误纠正，或需要根据艾宾浩斯遗忘曲线复习单词时触发此技能。\n---\n\n# English Tutor · 英语口语陪练\n\n## 功能概览\n\n- **语音输入** → ASR 转写为文字（本地或线上方案）\n- **口语纠错** → 指出英语表达错误，给出正确说法\n- **语音回复** → TTS 合成语音，飞书显示为原生语音卡片\n- **中文解释** → 每次回复附带中文说明\n- **艾宾浩斯复习** → 单词记忆与周期复习\n\n---\n\n## 第一步：环境检测\n\n```bash\npython3 scripts/check_env.py\n```\n\n按提示修复缺失项后继续。\n\n---\n\n## ASR 方案选择\n\nASR 负责把用户语音转成文字。选择一种：\n\n### 方案 A：本地 ASR（推荐，零外部依赖）\n\n使用 sherpa-onnx SenseVoice 模型，已内置于技能中。\n\n**模型路径：** `SENSE_VOICE_MODEL_DIR` 环境变量（默认 `~/.local/share/sense-voice-model/`）\n\n**若无模型，运行：**\n```bash\n# 默认下载到 ~/.local/share/sense-voice-model/\nbash scripts/download_model.sh\n\n# 自定义路径：\nexport SENSE_VOICE_MODEL_DIR=/your/custom/path\nSENSE_VOICE_MODEL_DIR=/your/custom/path bash scripts/download_model.sh\n```\n\n**安装依赖：**\n```bash\npip install --user --break-system-packages numpy sherpa-onnx\n```\n\n**验证：**\n```bash\npython3 scripts/transcribe.py /path/to/test.ogg\n# 输出文字则成功\n```\n\n---\n\n### 方案 B：线上 ASR API\n\n```env\nASR_PROVIDER=assemblyai   # 或 openai、xfyun\nASR_API_KEY=your-key\n```\n\n| 服务 | 免费额度 | 注册地址 |\n|------|---------|---------|\n| AssemblyAI | 5小时/月 | assemblyai.com |\n| OpenAI Whisper | $5额度 | platform.openai.com |\n\n---\n\n## TTS 方案选择\n\nTTS 负责把文字回复转为语音。选择一种：\n\n### 方案 A：本地 TTS（零成本）\n\n#### A1：piper（推荐，高质量，需额外下载）\n\npiper 音质最好，但需要下载主程序 + ONNX Runtime + 语音模型（约 150MB）。\n\npiper 是一款高质量本地 TTS 引擎，基于 VITS。\n\n**下载 piper 主程序（Linux x86_64）：**\n```bash\n# 如果 GitHub 可达，直接下载：\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper_amd64.tar.gz\ntar xf /tmp/piper_amd64.tar.gz -C /tmp\n\n# 验证：\n/tmp/piper/piper_phonemize --version\n```\n\n**下载英语语音模型（20~50MB）：**\n```bash\n# Medium 质量英语模型（约40MB）\ncurl -L \"https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/medium/en_US_medium.onnx.tar.gz\" \\\n  -o /tmp/en_US_medium.tar.gz\ntar xf /tmp/en_US_medium.tar.gz -C /tmp\n\n# 备用（如果 HuggingFace 不可达）：\n# 从 ModelScope 或其他镜像下载 .onnx 模型文件\n```\n\n**使用方式（配置环境变量）：**\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/tmp/piper/piper_phonemize\nPIPER_MODEL=/tmp/en_US_medium.onnx\n```\n\n---\n\n#### A2：espeak-ng（需 root）\n\nespeak-ng 是开源 TTS 引擎，英文机械感但完全离线。\n\n```bash\n# 需要 root 安装：\nsudo apt-get install espeak-ng\n\n# 验证：\nespeak-ng --version\nespeak-ng \"Hello world\" -w output.wav\n```\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n#### A3：gTTS（Python 库，无需 API Key）\n\ngTTS 调用 Google Translate 免费 TTS 接口，pip 安装即可使用，英文质量一般。\n\n```bash\npip install gTTS\n```\n\n```env\nTTS_PROVIDER=gtts\n```\n\n> ⚠️ 在国内环境可能无法访问 Google，需要代理或改用其他方案。\n\n---\n\n### 方案 B：线上 TTS API\n\n#### B1：MiniMax TTS（音质最好，已配置）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n**推荐音色：**\n\n| 用途 | voice_id |\n|------|---------|\n| 男声（默认） | `male-qn-qingse` |\n| 女声 | `female-tianmei` |\n| 英式男声 | `English_Trustworthy_Man` |\n| 英式女声 | `English_Graceful_Lady` |\n| 澳式男声 | `English_Aussie_Bloke` |\n\n#### B2：OpenAI TTS\n\n```env\nTTS_PROVIDER=openai\nOPENAI_API_KEY=sk-your-key\nOPENAI_TTS_MODEL=tts-1\nOPENAI_TTS_VOICE=alloy\n```\n\n#### B3：Azure TTS\n\n```env\nTTS_PROVIDER=azure\nAZURE_SPEECH_KEY=your-key\nAZURE_SPEECH_REGION=eastus\n```\n\n---\n\n## LLM 配置\n\n默认使用 OpenClaw 主会话的 LLM，无需额外配置。\n\n---\n\n## 完整环境变量参考\n\nSee [references/config-schema.md](references/config-schema.md) for full variable list.\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1777247200942\n}\n\nFile v1.0.0:references/config-schema.md\n\n# English Tutor · 完整配置参考\n\n## 环境变量总览\n\n| 变量 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `ASR_PROVIDER` | 否 | `local` | ASR：`local` / `assemblyai` / `xfyun` / `openai` |\n| `ASR_API_KEY` | 看方案 | — | AssemblyAI 等 API Key |\n| `TTS_PROVIDER` | **是** | — | `piper` / `espeak` / `gtts` / `minimax` / `openai` / `azure` |\n| `PIPER_BIN` | piper 时 | — | piper_phonemize 二进制路径 |\n| `PIPER_MODEL` | piper 时 | — | .onnx 语音模型路径 |\n| `MINIMAX_API_KEY` | minimax 时 | — | MiniMax API Key |\n| `OPENAI_API_KEY` | openai 时 | — | OpenAI API Key |\n| `AZURE_SPEECH_KEY` | azure 时 | — | Azure 语音 Key |\n| `LLM_PROVIDER` | 否 | `minimax` | LLM（默认用 OpenClaw 主会话） |\n| `BITABLE_APP_TOKEN` | 否 | — | 飞书多维表格 App Token |\n| `BITABLE_WORDS_TABLE_ID` | 否 | — | words 表 ID |\n| `BITABLE_CHAT_TABLE_ID` | 否 | — | chat_log 表 ID |\n\n---\n\n## TTS_PROVIDER 配置\n\n### piper（本地，音质最好）\n\n```env\nTTS_PROVIDER=piper\nPIPER_BIN=/path/to/piper_phonemize\nPIPER_MODEL=/path/to/en_US_medium.onnx\n```\n\n**下载：**\n```bash\n# 主程序（Linux x86_64）\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz -o /tmp/piper.tar.gz\ntar xf /tmp/piper.tar.gz -C /tmp\n\n# 英语模型（任选一个）\n# Medium 音质（推荐）\ncurl -L \"https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/medium/en_US_medium.onnx.tar.gz\" -o /tmp/model.tar.gz\n# 高音质\ncurl -L \"https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/high/en_US_high.onnx.tar.gz\" -o /tmp/model.tar.gz\ntar xf /tmp/model.tar.gz -C /tmp\n```\n\n**测试：**\n```bash\necho \"Hello world\" | /path/to/piper_phonemize --model /path/to/en_US_medium.onnx -f /dev/stdin -w /tmp/test.wav\n```\n\n---\n\n### espeak-ng（本地，需 root）\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n```bash\nsudo apt-get install espeak-ng\nespeak-ng \"Hello world\" -w output.wav\n```\n\n---\n\n### gTTS（本地/网络，Python 库）\n\n```env\nTTS_PROVIDER=gtts\n```\n\n```bash\npip install gTTS\n# 无需 API Key，调用 Google Translate TTS\n```\n\n> ⚠️ 国内可能无法访问 Google，建议配合代理或改用 piper / 云端方案。\n\n---\n\n```env\nTTS_PROVIDER=espeak\nESPEAK_VOICE=en-us\n```\n\n```bash\nsudo apt-get install espeak-ng\nespeak-ng \"Hello world\" -w output.wav\n```\n\n---\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n| 用途 | voice_id |\n|------|---------|\n| 男声（默认） | `male-qn-qingse` |\n| 女声 | `female-tianmei` |\n| 英式男声 | `English_Trustworthy_Man` |\n| 英式女声 | `English_Graceful_Lady` |\n| 澳式男声 | `English_Aussie_Bloke` |\n\n---\n\n### openai（云端）\n\n```env\nTTS_PROVIDER=openai\nOPENAI_API_KEY=sk-your-key\nOPENAI_TTS_MODEL=tts-1\nOPENAI_TTS_VOICE=alloy\n```\n\n---\n\n### azure（云端）\n\n```env\nTTS_PROVIDER=azure\nAZURE_SPEECH_KEY=your-key\nAZURE_SPEECH_REGION=eastus\n```\n\n---\n\n## ASR_PROVIDER 配置\n\n### local（默认）\n\n```env\nASR_PROVIDER=local\n```\n\n模型路径：`SENSE_VOICE_MODEL_DIR` 环境变量（默认 `~/.local/share/sense-voice-model/`）\n\n### AssemblyAI\n\n```env\nASR_PROVIDER=assemblyai\nASR_API_KEY=your-assemblyai-key\n```\n\n### OpenAI Whisper\n\n```env\nASR_PROVIDER=openai\nOPENAI_API_KEY=sk-your-key\n```\n\n---\n\n## 多维表格（可选）\n\n**app_token:** `BITABLE_APP_TOKEN` 环境变量（在飞书多维表格 URL 中获取）\n\n**words 表字段：** word / user_id / first_seen / last_review / next_review / review_count / mastery / source\n\n**chat_log 表字段：** user_id / role / text / voice_url / created_at\n\n**艾宾浩斯复习周期：** `[1, 3, 7, 15]` 天（环境变量 `EBINGHAUS_INTERVALS=1,3,7,15`）","readmeExcerpt":"Skill: The English Tutor Owner: pandaltsgo Summary: 英语口语陪练助手。触发词：「练习英语」「我要说英语」「英语陪练」。功能：上传生词表 → 每日定时情景对话 → 语音输入即时纠错 → 飞书语音推送 → 自动艾宾浩斯复习。 Tags: asr:3.0.4, english:3.0.4, latest:3.0.4, learning:3.0.4, spaced-repetition:3.0.4, tts:3.0.4 Version history: v3.0.4 | 2026-05-10T15:13:53.498Z | user Security hardening: remove hardcoded API keys, add null guards, cross-platform paths, stop-word filtering, logging module, all-o","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"english-tutor/\n├── SKILL.md\n├── metadata.json\n├── _meta.json\n├── agent/                    ← 核心 Node.js 运行时\n│   ├── config.js             ← 配置（全部选填，env 注入）\n│   ├── minimax.js            ← MiniMax TTS + Chat API\n│   ├── memory.js             ← 多维表格记忆（可选）\n│   └── agent.js              ← 主流程入口\n├── scripts/                  ← Python 辅助脚本\n│   ├── check_env.py          ← 环境检测\n│   ├── config_manager.py     ← 配置管理\n│   ├── download_model.py     ← SenseVoice 模型下载\n│   ├── feishu_voice.py       ← 飞书语音发送（TTS→Opus→上传→发送）\n│   ├── transcribe.py         ← ASR 转录（本地/云端）\n│   └── wordlist_parser.py    ← 单词表解析器\n├── references/\n│   └── config-schema.md\n└── assets/\n    └── wordlist_example.csv"},{"language":"json","snippet":"{\n  \"credential_using\": true,\n  \"required_credentials\": [],\n  \"optional_credentials\": [\n    { \"name\": \"FEISHU_APP_ID\",      \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_APP_SECRET\",  \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_USER_OPEN_ID\",\"description\": \"飞书语音推送\" },\n    { \"name\": \"MINIMAX_API_KEY\",    \"description\": \"云端 TTS + LLM 对话\" },\n    { \"name\": \"BITABLE_APP_TOKEN\",  \"description\": \"艾宾浩斯记忆（可选）\" },\n    { \"name\": \"BITABLE_WORDS_TABLE_ID\", \"description\": \"单词记录表\" },\n    { \"name\": \"BITABLE_CHAT_TABLE_ID\",  \"description\": \"对话历史表\" }\n  ]\n}"},{"language":"bash","snippet":"curl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp"},{"language":"bash","snippet":"curl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx"},{"language":"bash","snippet":"mkdir -p /vol1/@apphome/trim.openclaw/data/workspace/piper/voices\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\ncurl -L \"https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\" \\\n  -o /vol1/@apphome/trim.openclaw/data/workspace/piper/voices/en_US-lessac-medium.onnx"},{"language":"bash","snippet":"pip install --user --break-system-packages numpy sherpa-onnx\npython3 /vol1/@apphome/trim.openclaw/data/workspace/skills/english-tutor/scripts/download_model.py"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"# 英语助教 · English Tutor Skill\n\n> **模块化基座 Skill** — 功能按需配置，所有环境变量均为**选填**。\n> 有配置就启用对应功能，无配置则跳过。完整功能需要飞书 + MiniMax + 多维表格。\n\n---\n\n## 功能模块（按需启用）\n\n| 模块 | 环境变量 | 说明 |\n|------|---------|------|\n| 飞书语音推送 | `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `FEISHU_USER_OPEN_ID` | 发 TTS 语音到飞书 |\n| MiniMax TTS | `MINIMAX_API_KEY` | 云端语音合成（主方案） |\n| Piper 本地 TTS | `PIPER_BIN`, `PIPER_MODEL` | 完全离线的语音兜底 |\n| SenseVoice 本地 ASR | `SENSE_VOICE_MODEL_DIR` | 完全离线的语音识别 |\n| 多维表格记忆 | `BITABLE_APP_TOKEN`, `BITABLE_WORDS_TABLE_ID`, `BITABLE_CHAT_TABLE_ID` | 单词记录 + 艾宾浩斯 |\n| 定时推送 | cron jobs | 08:00 / 12:00 / 20:00（可单独开启） |\n\n**原则**：填了变量 → 启用该模块；没填 → 该模块静默跳过，不报错。\n\n---\n\n## 文件结构\n\n```\nenglish-tutor/\n├── SKILL.md\n├── metadata.json\n├── _meta.json\n├── agent/                    ← 核心 Node.js 运行时\n│   ├── config.js             ← 配置（全部选填，env 注入）\n│   ├── minimax.js            ← MiniMax TTS + Chat API\n│   ├── memory.js             ← 多维表格记忆（可选）\n│   └── agent.js              ← 主流程入口\n├── scripts/                  ← Python 辅助脚本\n│   ├── check_env.py          ← 环境检测\n│   ├── config_manager.py     ← 配置管理\n│   ├── download_model.py     ← SenseVoice 模型下载\n│   ├── feishu_voice.py       ← 飞书语音发送（TTS→Opus→上传→发送）\n│   ├── transcribe.py         ← ASR 转录（本地/云端）\n│   └── wordlist_parser.py    ← 单词表解析器\n├── references/\n│   └── config-schema.md\n└── assets/\n    └── wordlist_example.csv\n```\n\n---\n\n## 环境变量（全部选填）\n\n### 飞书模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `FEISHU_APP_ID` | `\"\"` | 飞书应用 App ID（填了才发飞书语音） |\n| `FEISHU_APP_SECRET` | `\"\"` | 飞书应用 Secret |\n| `FEISHU_USER_OPEN_ID` | `\"\"` | 接收语音的飞书用户 Open ID |\n\n### TTS 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `MINIMAX_API_KEY` | `\"\"` | MiniMax API Key（不填则跳过云端 TTS） |\n| `MINIMAX_TTS_MODEL` | `speech-2.8-hd` | TTS 模型 |\n| `MINIMAX_TTS_SPEED` | `1.05` | 语速 |\n| `MINIMAX_TTS_VOICE_ID` | `male-qn-qingse` | 音色 ID |\n| `PIPER_BIN` | `\"\"` | Piper 主程序路径（不填则跳过本地 TTS） |\n| `PIPER_MODEL` | `\"\"` | Piper ONNX 模型路径 |\n| `TTS_PROVIDER` | `minimax` | 优先方案：`minimax` / `piper` |\n\n### ASR 模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `SENSE_VOICE_MODEL_DIR` | `\"\"` | SenseVoice 模型目录（不填则跳过本地 ASR） |\n\n### 多维表格模块\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `BITABLE_APP_TOKEN` | `\"\"` | App Token（不填则无艾宾浩斯记忆） |\n| `BITABLE_WORDS_TABLE_ID` | `\"\"` | words 表 ID |\n| `BITABLE_CHAT_TABLE_ID` | `\"\"` | chat_log 表 ID |\n\n### 每日练习配置\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `DAILY_WORD_MAX` | `15` | 每日新词上限 |\n\n---\n\n## 凭据声明（metadata）\n\n本 skill 为 **Credential-Using Skill**，但**所有凭据均为选填**：\n\n```json\n{\n  \"credential_using\": true,\n  \"required_credentials\": [],\n  \"optional_credentials\": [\n    { \"name\": \"FEISHU_APP_ID\",      \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_APP_SECRET\",  \"description\": \"飞书语音推送\" },\n    { \"name\": \"FEISHU_USER_OPEN_ID\",\"description\": \"飞书语音推送\" },\n    { \"name\": \"MINIMAX_API_KEY\",    \"description\": \"云端 TTS + LLM 对话\" },\n    { \"name\": \"BITABLE_APP_TOKEN\",  \"description\": \"艾宾浩斯记忆（可选）\" },\n    { \"name\": \"BITABLE_WORDS_TABLE_ID\", \"description\": \"单词记录表\" },\n    { \"name\": \"BITABLE_CHAT_TABLE_ID\",  "},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn77xweern9gx42a72z2rffk6185jmxm\",\n  \"slug\": \"the-english-tutor\",\n  \"version\": \"3.0.4\",\n  \"publishedAt\": 1778426033498\n}"},{"path":"references/config-schema.md","content":"# English Tutor · 完整配置参考\n\n## 配置存储\n\n用户配置统一保存在 `~/.openclaw/english-tutor/config.json`，由 `scripts/config_manager.py` 管理。\n\n**首次由陪练助手通过对话引导创建，无需手动编辑。**\n\n---\n\n## config.json 字段说明\n\n### 基础配置\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `setup_complete` | ✅ | `false` | 首次设置是否完成 |\n| `word_list_path` | ✅ | `\"\"` | 单词表 JSON 文件路径 |\n| `daily_words` | ✅ | `5` | 每日练习单词数量（建议 5-15）|\n| `schedule_times` | ✅ | `[\"08:00\"]` | 每日推送时间（上海时区）|\n\n### LLM 模型配置 🤖\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `llm_provider` | ✅ | `\"openclaw\"` | 模型提供商：`openclaw` / `minimax` / `openai` |\n| `llm_model` | 否 | `\"\"` | 指定模型 ID（留空用默认）|\n\n> 选择 `openclaw` 时使用系统默认 LLM，无需额外配置。\n\n### 飞书语音配置 📢\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `feishu_app_id` | ✅ | `\"\"` | 飞书应用 App ID |\n| `feishu_app_secret` | ✅ | `\"\"` | 飞书应用 App Secret |\n| `feishu_bot_token` | 否 | `\"\"` | 飞书 Bot Token（可选）|\n| `feishu_user_open_id` | ✅ | `\"\"` | 接收消息的用户 Open ID |\n\n### TTS 语音合成 🔊\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `tts_provider` | 否 | `\"minimax\"` | TTS 方案：`minimax` / `piper` / `espeak` |\n| `minimax_api_key` | minimax时 | `\"\"` | MiniMax API Key |\n\n> MiniMax TTS 有 API Key 时推荐音色：`male-qn-qingse`（男声）、`female-tianmei`（女声）；无 Key 时静默跳过，可配 Piper 本地兜底\n\n### 多维表格（可选）\n\n| 字段 | 必填 | 默认值 | 说明 |\n|------|------|--------|------|\n| `bitable_app_token` | 否 | `\"\"` | 飞书多维表格 App Token |\n| `bitable_words_table_id` | 否 | `\"\"` | words 表 ID |\n| `bitable_chat_table_id` | 否 | `\"\"` | chat_log 表 ID |\n\n### Piper 本地 TTS（可选）\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `piper_bin` | piper时 | piper 二进制路径 |\n| `piper_model` | piper时 | .onnx 模型文件路径 |\n\n---\n\n## 飞书 audio 消息发送流程\n\n每日练习第一步，通过 `scripts/feishu_voice.py` 实现：\n\n```\n1. TTS 合成 mp3\n   - minimax: POST /v1/t2a_v2 → hex audio → 解码为 mp3\n   - piper:   piper CLI → WAV\n   \n2. ffmpeg 转 opus\n   ffmpeg -i input.mp3 -ar 16000 -ac 1 -acodec libopus -b:a 128k output.opus\n\n3. 上传获取 file_key\n   POST /open-apis/im/v1/files\n   Content-Type: multipart/form-data; boundary=...\n   body: file_type=opus, file=opus二进制\n\n4. 发送 audio 消息\n   POST /open-apis/im/v1/messages?receive_id_type=open_id\n   {\n     \"receive_id\": \"<user_open_id>\",\n     \"msg_type\": \"audio\",\n     \"content\": \"{\\\"file_key\\\": \\\"<file_key>\\\"}\"\n   }\n```\n\n**使用示例：**\n```bash\n# 使用配置发送语音\npython3 scripts/feishu_voice.py \"Good morning! Today's vocabulary: commute, subway, transfer.\"\n\n# 使用配置（指定路径）\npython3 scripts/feishu_voice.py \"Hello!\" --config /path/to/config.json\n\n# 仅合成，不发送（调试用）\npython3 scripts/feishu_voice.py \"Hello!\" --dry-run\n```\n\n---\n\n## TTS_PROVIDER 配置\n\n### minimax（默认，云端，音质最好）\n\n```env\nTTS_PROVIDER=minimax\nMINIMAX_API_KEY=sk-your-key\nMINIMAX_TTS_MODEL=speech-2.8-hd\nMINIMAX_TTS_VOICE_ID=male-qn-qingse\nMINIMAX_TTS_SPEED=1.05\n```\n\n### piper（本地，高质量，离线）\n\n**下载主程序（Linux x86_64）：**\n```bash\ncurl -L https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz \\\n  -o /tmp/piper.tar.gz && tar xf /tmp/piper.tar.gz -C /tmp\n```\n\n**下载英语模型（Lessac Medium，音质好，速度快）：**\n```bash\ncurl -L \"https://hf-mirror.com/rhassp"},{"path":"skill-card.md","content":"## Description:\n\nThe English Tutor helps learners practice spoken English with optional word-list review, timed scenario dialogs, speech transcription, text-to-speech, Feishu voice delivery, and Bitable memory.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[pandaltsgo](https://clawhub.ai/user/pandaltsgo)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nLearners use this agent to rehearse short American English conversations, upload vocabulary lists, receive optional scheduled practice prompts, and review words with spaced repetition. Developers or advanced users configure Feishu, MiniMax, Piper, SenseVoice, and Bitable integrations according to the deployment environment.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles private voice, chat, learning records, and service credentials.\n\nMitigation: Configure only trusted Feishu, MiniMax, and ASR providers; store secrets through environment variables or secured configuration; avoid passing secrets as command-line arguments.\n\nRisk: Optional Bitable memory stores chat and vocabulary records outside the local agent environment.\n\nMitigation: Enable Bitable memory only when external storage of practice data is acceptable, and limit stored content to learning records needed for review.\n\nRisk: Optional Piper and SenseVoice setup downloads external binaries or model artifacts.\n\nMitigation: Verify downloaded artifacts before use, prefer a virtual environment with pinned dependencies, and review downloaded files according to local security policy.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/pandaltsgo/skills/the-english-tutor)\n- [Configuration schema](references/config-schema.md)\n- [MiniMax TTS API reference](https://platform.minimaxi.com/docs/api-reference/speech-t2a-http)\n- [Piper TTS release v1.2.0](https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_amd64.tar.gz)\n- [Piper English voice model](https://hf-mirror.com/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx)\n- [SenseVoice model files](https://modelscope.cn/api/v1/models/xiaowangge/sherpa-onnx-sense-voice-small/resolve/master/model.onnx)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown and plain text with optional JSON status from helper scripts]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Feishu audio-message results or skipped status when voice delivery is configured.]\n\n## Skill Version(s):\n\n3.0.4 (source: server release and artifact metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."},{"path":"metadata.json","content":"{\n  \"name\": \"english-tutor\",\n  \"version\": \"3.0.4\",\n  \"description\": \"英语口语陪练基座。飞书语音推送 + MiniMax/本地 TTS + SenseVoice ASR + 艾宾浩斯复习。全部模块选填，按需启用。\",\n  \"credential_using\": true,\n  \"all_optional\": true,\n  \"optional_credentials\": [\n    {\n      \"name\": \"FEISHU_APP_ID\",\n      \"type\": \"feishu_app_id\",\n      \"required\": false,\n      \"description\": \"飞书应用 App ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_APP_SECRET\",\n      \"type\": \"feishu_app_secret\",\n      \"required\": false,\n      \"description\": \"飞书应用 Secret（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"FEISHU_USER_OPEN_ID\",\n      \"type\": \"feishu_open_id\",\n      \"required\": false,\n      \"description\": \"接收语音的飞书用户 Open ID（填了才能发飞书语音）\"\n    },\n    {\n      \"name\": \"MINIMAX_API_KEY\",\n      \"type\": \"api_key\",\n      \"required\": false,\n      \"description\": \"MiniMax API Key（填了启用云端 TTS，不填则跳过）\"\n    },\n    {\n      \"name\": \"PIPER_BIN\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper 主程序路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"PIPER_MODEL\",\n      \"type\": \"file_path\",\n      \"required\": false,\n      \"description\": \"Piper ONNX 模型路径（填了启用本地 TTS 兜底）\"\n    },\n    {\n      \"name\": \"SENSE_VOICE_MODEL_DIR\",\n      \"type\": \"directory_path\",\n      \"required\": false,\n      \"description\": \"SenseVoice 模型目录（填了启用本地 ASR，不填则跳过）\"\n    },\n    {\n      \"name\": \"BITABLE_APP_TOKEN\",\n      \"type\": \"feishu_bitable_token\",\n      \"required\": false,\n      \"description\": \"飞书多维表格 App Token（不填则无艾宾浩斯记忆）\"\n    },\n    {\n      \"name\": \"BITABLE_WORDS_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"words 表 ID（单词记录表）\"\n    },\n    {\n      \"name\": \"BITABLE_CHAT_TABLE_ID\",\n      \"type\": \"string\",\n      \"required\": false,\n      \"description\": \"chat_log 表 ID（对话历史表）\"\n    }\n  ],\n  \"module_design\": {\n    \"principle\": \"填了变量启用该模块，没填则静默跳过，不报错\",\n    \"modules\": [\n      {\n        \"name\": \"飞书语音推送\",\n        \"env\": [\"FEISHU_APP_ID\", \"FEISHU_APP_SECRET\", \"FEISHU_USER_OPEN_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不发飞书语音\"\n      },\n      {\n        \"name\": \"MiniMax TTS\",\n        \"env\": [\"MINIMAX_API_KEY\"],\n        \"behavior_when_empty\": \"静默跳过，尝试 Piper 本地 TTS\"\n      },\n      {\n        \"name\": \"Piper 本地 TTS\",\n        \"env\": [\"PIPER_BIN\", \"PIPER_MODEL\"],\n        \"behavior_when_empty\": \"静默跳过，无 TTS 功能\"\n      },\n      {\n        \"name\": \"SenseVoice 本地 ASR\",\n        \"env\": [\"SENSE_VOICE_MODEL_DIR\"],\n        \"behavior_when_empty\": \"静默跳过，仅支持文字输入\"\n      },\n      {\n        \"name\": \"多维表格记忆\",\n        \"env\": [\"BITABLE_APP_TOKEN\", \"BITABLE_WORDS_TABLE_ID\", \"BITABLE_CHAT_TABLE_ID\"],\n        \"behavior_when_empty\": \"静默跳过，不记录学习进度\"\n      }\n    ]\n  },\n  \"scheduled_actions\": [\n    {\n      \"name\": \"每日晨间练习 08:00\",\n      \"cron\": \"0 8 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"用户选择开启后，自动生成跟读对话，发飞书语音，等待用户回复\"\n    },\n    {\n      \"name\": \"每日午间练习 12:00\",\n      \"cron\": \"0 12 * * *\",\n      \"timezone\": \"Asia/Shanghai\",\n      \"default_enabled\": false,\n      \"behavior\": \"同上\"\n    },\n    {\n      \"name\": \"每日晚间练"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1457,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-12T00:19:58.817Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-12T00:19:58.817Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-13T05:58:00.554Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}